mirror of
https://github.com/DocNR/POWR.git
synced 2025-04-19 19:01:18 +00:00
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import * as SwitchPrimitives from '@rn-primitives/switch';
|
|
import * as React from 'react';
|
|
import { Platform } from 'react-native';
|
|
import Animated, {
|
|
interpolateColor,
|
|
useAnimatedStyle,
|
|
useDerivedValue,
|
|
withTiming,
|
|
} from 'react-native-reanimated';
|
|
import { useColorScheme } from '@/lib/theme/useColorScheme';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
const SwitchWeb = React.forwardRef<SwitchPrimitives.RootRef, SwitchPrimitives.RootProps>(
|
|
({ className, ...props }, ref) => (
|
|
<SwitchPrimitives.Root
|
|
className={cn(
|
|
'peer flex-row h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed',
|
|
props.checked ? 'bg-primary' : 'bg-input',
|
|
props.disabled && 'opacity-50',
|
|
className
|
|
)}
|
|
{...props}
|
|
ref={ref}
|
|
>
|
|
<SwitchPrimitives.Thumb
|
|
className={cn(
|
|
'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-md shadow-foreground/5 ring-0 transition-transform',
|
|
props.checked ? 'translate-x-5' : 'translate-x-0'
|
|
)}
|
|
/>
|
|
</SwitchPrimitives.Root>
|
|
)
|
|
);
|
|
|
|
SwitchWeb.displayName = 'SwitchWeb';
|
|
|
|
const RGB_COLORS = {
|
|
light: {
|
|
primary: 'rgb(24, 24, 27)',
|
|
input: 'rgb(228, 228, 231)',
|
|
},
|
|
dark: {
|
|
primary: 'rgb(250, 250, 250)',
|
|
input: 'rgb(39, 39, 42)',
|
|
},
|
|
} as const;
|
|
|
|
const SwitchNative = React.forwardRef<SwitchPrimitives.RootRef, SwitchPrimitives.RootProps>(
|
|
({ className, ...props }, ref) => {
|
|
const { colorScheme } = useColorScheme();
|
|
const translateX = useDerivedValue(() => (props.checked ? 18 : 0));
|
|
const animatedRootStyle = useAnimatedStyle(() => {
|
|
return {
|
|
backgroundColor: interpolateColor(
|
|
translateX.value,
|
|
[0, 18],
|
|
[RGB_COLORS[colorScheme].input, RGB_COLORS[colorScheme].primary]
|
|
),
|
|
};
|
|
});
|
|
const animatedThumbStyle = useAnimatedStyle(() => ({
|
|
transform: [{ translateX: withTiming(translateX.value, { duration: 200 }) }],
|
|
}));
|
|
return (
|
|
<Animated.View
|
|
style={animatedRootStyle}
|
|
className={cn('h-8 w-[46px] rounded-full', props.disabled && 'opacity-50')}
|
|
>
|
|
<SwitchPrimitives.Root
|
|
className={cn(
|
|
'flex-row h-8 w-[46px] shrink-0 items-center rounded-full border-2 border-transparent',
|
|
props.checked ? 'bg-primary' : 'bg-input',
|
|
className
|
|
)}
|
|
{...props}
|
|
ref={ref}
|
|
>
|
|
<Animated.View style={animatedThumbStyle}>
|
|
<SwitchPrimitives.Thumb
|
|
className={'h-7 w-7 rounded-full bg-background shadow-md shadow-foreground/25 ring-0'}
|
|
/>
|
|
</Animated.View>
|
|
</SwitchPrimitives.Root>
|
|
</Animated.View>
|
|
);
|
|
}
|
|
);
|
|
SwitchNative.displayName = 'SwitchNative';
|
|
|
|
const Switch = Platform.select({
|
|
web: SwitchWeb,
|
|
default: SwitchNative,
|
|
});
|
|
|
|
export { Switch };
|