feat(size-slider): improve size-slider component

This commit is contained in:
pubuzhixing8 committed 2024-10-18 19:12:02 +08:00
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;
+40 -14
View File
@@ -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}%`,