abstract range
This commit is contained in:
81
src/design-system/base/range.tsx
Normal file
81
src/design-system/base/range.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* Range - 范围滑块组件
|
||||
*
|
||||
* 支持自定义进度条颜色、禁用状态和样式覆盖的滑块输入组件。
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* import { Range } from '@/design-system/base/range';
|
||||
*
|
||||
* <Range value={50} min={0} max={100} onChange={setValue} />
|
||||
* <Range value={75} min={0} max={100} disabled />
|
||||
* ```
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import { cn } from "@/design-system/lib/utils";
|
||||
|
||||
export interface RangeProps extends Omit<React.ComponentPropsWithoutRef<"input">, "onChange"> {
|
||||
/** 当前值 */
|
||||
value: number;
|
||||
/** 值变化回调 */
|
||||
onChange: (value: number) => void;
|
||||
/** 最小值 (默认: 0) */
|
||||
min?: number;
|
||||
/** 最大值 */
|
||||
max: number;
|
||||
}
|
||||
|
||||
export const Range = React.forwardRef<HTMLInputElement, RangeProps>(
|
||||
(
|
||||
{
|
||||
value,
|
||||
min = 0,
|
||||
max,
|
||||
onChange,
|
||||
disabled = false,
|
||||
className,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const handleChange = React.useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newValue = parseInt(event.target.value);
|
||||
onChange(newValue);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const progressPercentage = ((value - min) / (max - min)) * 100;
|
||||
|
||||
return (
|
||||
<input
|
||||
ref={ref}
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
"w-full h-2 rounded-lg appearance-none cursor-pointer",
|
||||
"focus:outline-none focus:ring-2 focus:ring-primary-500",
|
||||
disabled && "opacity-50 cursor-not-allowed",
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
background: `linear-gradient(to right, #374151 0%, #374151 ${progressPercentage}%, #e5e7eb ${progressPercentage}%, #e5e7eb 100%)`
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Range.displayName = "Range";
|
||||
|
||||
// 向后兼容别名
|
||||
export const RangeInput = Range;
|
||||
Reference in New Issue
Block a user