forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useEffect, useState} from 'react'
2import {type ViewStyle} from 'react-native'
3import {Slider as RNSlider} from '@miblanchard/react-native-slider'
4
5import {changeHue, useTheme} from '#/alf'
6
7interface SliderProps {
8 value: number
9 onValueChange: (value: number) => void
10 minimumValue?: number
11 maximumValue?: number
12 step?: number
13 trackStyle?: ViewStyle
14 minimumTrackStyle?: ViewStyle
15 thumbStyle?: ViewStyle
16 thumbTouchSize?: {width: number; height: number}
17 debounceFull?: boolean
18}
19
20export function Slider({
21 value,
22 onValueChange,
23 minimumValue = 0,
24 maximumValue = 1,
25 step = 1,
26 trackStyle,
27 minimumTrackStyle,
28 thumbStyle,
29 thumbTouchSize = {width: 40, height: 40},
30 debounceFull,
31}: SliderProps) {
32 const t = useTheme()
33 // We need local state to handle visual updates while dragging if debounceFull is true
34 const [localValue, setLocalValue] = useState(value)
35
36 // Sync local state if the parent updates the value prop externally
37 useEffect(() => {
38 setLocalValue(value)
39 }, [value])
40
41 return (
42 <RNSlider
43 value={[localValue]} // Read from local state
44 onValueChange={values => {
45 const nextVal = values[0]
46 setLocalValue(nextVal)
47
48 // If NOT debouncing, update parent immediately while dragging
49 if (!debounceFull) {
50 onValueChange(nextVal)
51 }
52 }}
53 onSlidingComplete={values => {
54 // If debouncing, update parent only when done dragging
55 if (debounceFull) {
56 onValueChange(values[0])
57 }
58 }}
59 minimumValue={minimumValue}
60 maximumValue={maximumValue}
61 step={step}
62 trackStyle={{
63 height: 4,
64 borderRadius: 2,
65 backgroundColor: t.atoms.bg_contrast_50.backgroundColor,
66 ...trackStyle,
67 }}
68 minimumTrackStyle={{
69 height: 4,
70 borderRadius: 2,
71 backgroundColor: changeHue(t.palette.primary_500, localValue - value),
72 ...minimumTrackStyle,
73 }}
74 thumbStyle={{
75 width: 24,
76 height: 24,
77 borderRadius: 12,
78 borderWidth: 1,
79 borderColor: t.atoms.border_contrast_low.borderColor,
80 backgroundColor: t.atoms.bg.backgroundColor,
81 shadowColor: '#000',
82 shadowOffset: {width: 0, height: 2},
83 shadowOpacity: 0.15,
84 shadowRadius: 4,
85 elevation: 3,
86 ...thumbStyle,
87 }}
88 thumbTouchSize={thumbTouchSize}
89 />
90 )
91}