feat(size-slider): improve size-slider component
This commit is contained in:
1 parent
aa06c7e058
commit
780be9d868
3 files changed
+74
-47
No files matched your search
@@ -38,38 +38,40 @@ export const ColorPicker = React.forwardRef((props: ColorPickerProps, ref) => {
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{/* <SizeSlider
|
||||
step={4}
|
||||
defaultValue={100}
|
||||
onChange={(value) => {}}
|
||||
></SizeSlider> */}
|
||||
<Stack.Col gap={2}>
|
||||
{ROWS_CLASSIC_COLORS.map((colors, index) => (
|
||||
<Stack.Row key={index} gap={2}>
|
||||
{colors.map((color) => {
|
||||
return (
|
||||
<button
|
||||
key={color.value}
|
||||
className={`color-select-item ${
|
||||
selectedColor === color.value ? 'active' : ''
|
||||
} ${color.value === 'transparent' ? 'transparent' : ''}`}
|
||||
style={{
|
||||
backgroundColor: color.value,
|
||||
color: color.value === '#000000' ? '#FFFFFF' : '#000000',
|
||||
}}
|
||||
onClick={() => {
|
||||
setSelectedColor(color.value);
|
||||
onSelect(color.value);
|
||||
}}
|
||||
title={color.name}
|
||||
>
|
||||
{color.value === 'transparent' && TransparentIcon}
|
||||
{selectedColor === color.value && Check}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</Stack.Row>
|
||||
))}
|
||||
<Stack.Col gap={3}>
|
||||
<SizeSlider
|
||||
step={5}
|
||||
defaultValue={100}
|
||||
onChange={(value) => {}}
|
||||
></SizeSlider>
|
||||
<Stack.Col gap={2}>
|
||||
{ROWS_CLASSIC_COLORS.map((colors, index) => (
|
||||
<Stack.Row key={index} gap={2}>
|
||||
{colors.map((color) => {
|
||||
return (
|
||||
<button
|
||||
key={color.value}
|
||||
className={`color-select-item ${
|
||||
selectedColor === color.value ? 'active' : ''
|
||||
} ${color.value === 'transparent' ? 'transparent' : ''}`}
|
||||
style={{
|
||||
backgroundColor: color.value,
|
||||
color: color.value === '#000000' ? '#FFFFFF' : '#000000',
|
||||
}}
|
||||
onClick={() => {
|
||||
setSelectedColor(color.value);
|
||||
onSelect(color.value);
|
||||
}}
|
||||
title={color.name}
|
||||
>
|
||||
{color.value === 'transparent' && TransparentIcon}
|
||||
{selectedColor === color.value && Check}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</Stack.Row>
|
||||
))}
|
||||
</Stack.Col>
|
||||
</Stack.Col>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
background-color: var(--color-gray-20);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
margin: 0 8px;
|
||||
}
|
||||
.slider-range {
|
||||
position: absolute;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useCallback } from 'react';
|
||||
|
||||
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
||||
import { toFixed } from '@plait/core';
|
||||
import './size-slider.scss';
|
||||
|
||||
interface SliderProps {
|
||||
@@ -13,19 +13,35 @@ interface SliderProps {
|
||||
export const SizeSlider: React.FC<SliderProps> = ({
|
||||
min = 0,
|
||||
max = 100,
|
||||
step = 2,
|
||||
step = 1,
|
||||
defaultValue = 100,
|
||||
onChange,
|
||||
}) => {
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
const [thumbPercentage, setThumbPercentage] = useState(defaultValue);
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
const thumbRef = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
if (sliderRef.current && thumbRef.current) {
|
||||
const sliderRect = sliderRef.current.getBoundingClientRect();
|
||||
const thumbRect = thumbRef.current.getBoundingClientRect();
|
||||
setThumbPercentage(
|
||||
toFixed((thumbRect.width / 2 / sliderRect.width) * 100)
|
||||
);
|
||||
}
|
||||
}, [thumbRef.current, sliderRef.current]);
|
||||
|
||||
const handleSliderChange = useCallback(
|
||||
(event: React.MouseEvent<HTMLDivElement> | MouseEvent) => {
|
||||
if (sliderRef.current) {
|
||||
const rect = sliderRef.current.getBoundingClientRect();
|
||||
const x = event.clientX - rect.left;
|
||||
const percentage = Math.min(Math.max(x / rect.width, 0), 1);
|
||||
if (sliderRef.current && thumbRef.current) {
|
||||
const sliderRect = sliderRef.current.getBoundingClientRect();
|
||||
const x = event.clientX - sliderRect.left;
|
||||
let percentage = Math.min(Math.max(x / sliderRect.width, 0), 1);
|
||||
if (percentage >= (100 - thumbPercentage) / 100) {
|
||||
percentage = 1;
|
||||
} else if (percentage <= thumbPercentage / 100) {
|
||||
percentage = 0;
|
||||
}
|
||||
const newValue =
|
||||
Math.round((percentage * (max - min)) / step) * step + min;
|
||||
setValue(newValue);
|
||||
@@ -35,18 +51,24 @@ export const SizeSlider: React.FC<SliderProps> = ({
|
||||
[min, max, step, onChange]
|
||||
);
|
||||
|
||||
const handleMouseDown = useCallback(() => {
|
||||
const handlePointerDown = useCallback(() => {
|
||||
const handleMouseMove = (e: MouseEvent) => handleSliderChange(e);
|
||||
const handleMouseUp = () => {
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
document.removeEventListener('mouseup', handleMouseUp);
|
||||
document.removeEventListener('pointermove', handleMouseMove);
|
||||
document.removeEventListener('pointerup', handleMouseUp);
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
document.addEventListener('mouseup', handleMouseUp);
|
||||
document.addEventListener('pointermove', handleMouseMove);
|
||||
document.addEventListener('pointerup', handleMouseUp);
|
||||
}, [handleSliderChange]);
|
||||
|
||||
const percentage = ((value - min) / (max - min)) * 100;
|
||||
let percentage = ((value - min) / (max - min)) * 100;
|
||||
if (percentage >= 100 - thumbPercentage) {
|
||||
percentage = 100 - thumbPercentage;
|
||||
}
|
||||
if (percentage <= thumbPercentage) {
|
||||
percentage = thumbPercentage;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="slider-container">
|
||||
@@ -54,7 +76,10 @@ export const SizeSlider: React.FC<SliderProps> = ({
|
||||
ref={sliderRef}
|
||||
className="slider-track"
|
||||
onClick={handleSliderChange}
|
||||
onMouseDown={handleMouseDown}
|
||||
onPointerDown={(event) => {
|
||||
event.preventDefault();
|
||||
handlePointerDown();
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="slider-range"
|
||||
@@ -63,6 +88,7 @@ export const SizeSlider: React.FC<SliderProps> = ({
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
ref={thumbRef}
|
||||
className="slider-thumb"
|
||||
style={{
|
||||
left: `${percentage}%`,
|
||||
|
||||
Reference in new issue
Block a user