2025-10-28 07:59:26 +00:00
|
|
|
|
'use client';
|
|
|
|
|
|
|
|
|
|
|
|
import { cn } from '@/lib';
|
|
|
|
|
|
import { useControllableValue } from 'ahooks';
|
|
|
|
|
|
import { InputLeft } from '.';
|
2025-11-03 10:03:34 +00:00
|
|
|
|
import { Switch as SwitchPrimitive } from 'radix-ui';
|
|
|
|
|
|
|
2025-10-28 07:59:26 +00:00
|
|
|
|
const { Root, Thumb } = SwitchPrimitive;
|
|
|
|
|
|
type SwitchProps = {
|
|
|
|
|
|
value?: boolean;
|
|
|
|
|
|
onChange?: (value: boolean) => void;
|
|
|
|
|
|
icon?: any;
|
|
|
|
|
|
text?: string;
|
|
|
|
|
|
} & React.HTMLAttributes<HTMLDivElement>;
|
|
|
|
|
|
|
|
|
|
|
|
export default function Switch(props: SwitchProps) {
|
|
|
|
|
|
const { icon, text, ...rest } = props;
|
|
|
|
|
|
const [value, onChange] = useControllableValue(props);
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div {...rest} className={cn('input-view justify-between', rest.className)}>
|
|
|
|
|
|
<InputLeft icon={icon} text={text} />
|
|
|
|
|
|
<Root
|
|
|
|
|
|
checked={value}
|
|
|
|
|
|
onCheckedChange={onChange}
|
|
|
|
|
|
className={cn(
|
|
|
|
|
|
'relative inline-flex h-[28px] w-[52px] shrink-0 items-center',
|
|
|
|
|
|
'cursor-pointer rounded-full',
|
|
|
|
|
|
'transition-colors duration-200 ease-in-out',
|
|
|
|
|
|
'focus-visible:ring-2 focus-visible:ring-white/20 focus-visible:outline-none',
|
|
|
|
|
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
|
|
|
|
// 未选中状态 - 灰色背景
|
|
|
|
|
|
'bg-white/20',
|
|
|
|
|
|
// 选中状态 - 绿色背景
|
|
|
|
|
|
'data-[state=checked]:bg-[rgb(0,110,74)]' // 注意:RGB 值之间不能有空格
|
|
|
|
|
|
)}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Thumb
|
|
|
|
|
|
className={cn(
|
|
|
|
|
|
'pointer-events-none block h-[24px] w-[24px] rounded-full',
|
|
|
|
|
|
'bg-white shadow-lg',
|
|
|
|
|
|
'transition-transform duration-200 ease-in-out',
|
|
|
|
|
|
// 未选中时在左侧(2px 偏移)
|
|
|
|
|
|
'translate-x-[2px]',
|
|
|
|
|
|
// 选中时移到右侧(52px - 24px - 2px = 26px)
|
|
|
|
|
|
'data-[state=checked]:translate-x-[26px]'
|
|
|
|
|
|
)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</Root>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|