From 87767df0fdf7790306cf1dbbad55ab3a12248039 Mon Sep 17 00:00:00 2001 From: Jimmfly Date: Thu, 15 Aug 2024 14:18:36 +0800 Subject: [PATCH] refactor(component): impl with @radix-ui/react-slider --- packages/frontend/component/package.json | 1 + .../src/ui/slider/slider.stories.tsx | 13 +- .../component/src/ui/slider/slider.tsx | 127 ++++++------------ yarn.lock | 1 + 4 files changed, 52 insertions(+), 90 deletions(-) diff --git a/packages/frontend/component/package.json b/packages/frontend/component/package.json index 9ff1793d18..309d2d1a24 100644 --- a/packages/frontend/component/package.json +++ b/packages/frontend/component/package.json @@ -43,6 +43,7 @@ "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-radio-group": "^1.1.3", "@radix-ui/react-scroll-area": "^1.0.5", + "@radix-ui/react-slider": "^1.2.0", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toolbar": "^1.0.4", diff --git a/packages/frontend/component/src/ui/slider/slider.stories.tsx b/packages/frontend/component/src/ui/slider/slider.stories.tsx index e7cbd0ed09..dffdda38c1 100644 --- a/packages/frontend/component/src/ui/slider/slider.stories.tsx +++ b/packages/frontend/component/src/ui/slider/slider.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryFn } from '@storybook/react'; +import { useState } from 'react'; import type { SliderProps } from './index'; import { Slider } from './index'; @@ -8,7 +9,15 @@ export default { component: Slider, } satisfies Meta; -const Template: StoryFn = args => ; +const Template: StoryFn = args => { + const [value, setValue] = useState([0]); + return ; +}; export const Default: StoryFn = Template.bind(undefined); -Default.args = {}; +Default.args = { + min: 0, + max: 100, + step: 1, + nodes: [0, 50, 100], +}; diff --git a/packages/frontend/component/src/ui/slider/slider.tsx b/packages/frontend/component/src/ui/slider/slider.tsx index be12a7278c..85ec71334e 100644 --- a/packages/frontend/component/src/ui/slider/slider.tsx +++ b/packages/frontend/component/src/ui/slider/slider.tsx @@ -1,101 +1,52 @@ -import type { KeyboardEvent, MouseEvent } from 'react'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import * as Sliders from '@radix-ui/react-slider'; +import { useRef } from 'react'; import * as styles from './index.css'; -export interface SliderProps { - value?: number; - onChange?: (value: number) => void; - min?: number; - max?: number; - step?: number; +export interface SliderProps extends Sliders.SliderProps { nodes?: number[]; // The values where the nodes should be placed } export const Slider = ({ - value: propValue = 50, - onChange, - min = 0, - max = 100, - step = 1, - nodes = [20, 40, 60, 80], + value, + min, + max, + step, + nodes, + ...props }: SliderProps) => { - const [value, setValue] = useState(propValue); const sliderRef = useRef(null); - useEffect(() => { - setValue(propValue); - }, [propValue]); - - const handleThumbMove = useCallback( - (e: MouseEvent) => { - if (!sliderRef.current) return; - - const sliderRect = sliderRef.current.getBoundingClientRect(); - const newValue = - ((e.clientX - sliderRect.left) / sliderRect.width) * (max - min) + min; - const clampedValue = Math.min( - max, - Math.max(min, Math.round(newValue / step) * step) - ); - - setValue(clampedValue); - if (onChange) { - onChange(clampedValue); - } - }, - [max, min, onChange, step] - ); - - const handleThumbKeyDown = useCallback( - (e: KeyboardEvent) => { - let newValue = value; - if (e.key === 'ArrowLeft') { - newValue = Math.max(min, value - step); - } else if (e.key === 'ArrowRight') { - newValue = Math.min(max, value + step); - } - setValue(newValue); - if (onChange) { - onChange(newValue); - } - }, - [max, min, onChange, step, value] - ); - const thumbPosition = useMemo( - () => ((value - min) / (max - min)) * 100, - [max, min, value] - ); return ( -
-
-
- {nodes.map((nodeValue, index) => ( -
= nodeValue} - style={{ - left: `${((nodeValue - min) / (max - min)) * 100}%`, - }} - /> - ))} -
e.stopPropagation()} - onMouseMove={handleThumbMove} - onKeyDown={handleThumbKeyDown} - tabIndex={0} - /> -
-
+ + + + {!!nodes && + nodes.map((nodeValue, index) => ( +
= nodeValue} + style={{ + left: `${((nodeValue - (min !== undefined ? min : 0)) / (max !== undefined ? max - (min !== undefined ? min : 0) : 1)) * 100}%`, + transform: + index === 0 + ? 'translateY(-50%)' + : index === nodes.length - 1 + ? 'translateY(-50%) translateX(-100%)' + : undefined, + }} + /> + ))} + + + ); }; diff --git a/yarn.lock b/yarn.lock index 5d848ce4b9..f70d5a639c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -310,6 +310,7 @@ __metadata: "@radix-ui/react-popover": "npm:^1.0.7" "@radix-ui/react-radio-group": "npm:^1.1.3" "@radix-ui/react-scroll-area": "npm:^1.0.5" + "@radix-ui/react-slider": "npm:^1.2.0" "@radix-ui/react-tabs": "npm:^1.1.0" "@radix-ui/react-toast": "npm:^1.1.5" "@radix-ui/react-toolbar": "npm:^1.0.4"