react-native-varia 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +35 -18
- package/lib/components/Badge.tsx +31 -32
- package/lib/components/Button.tsx +20 -20
- package/lib/components/Checkbox.tsx +95 -0
- package/lib/components/CircleProgress.tsx +56 -66
- package/lib/components/Field.tsx +137 -0
- package/lib/components/GradientBackground.tsx +17 -18
- package/lib/components/GradientText.tsx +25 -64
- package/lib/components/IconWrapper.tsx +32 -25
- package/lib/components/Input.tsx +66 -68
- package/lib/components/Link.tsx +14 -28
- package/lib/components/Modal.tsx +197 -97
- package/lib/components/NewSelect.tsx +202 -0
- package/lib/components/NumberInput.tsx +226 -0
- package/lib/components/RadioGroup.tsx +195 -0
- package/lib/components/ReText.tsx +53 -87
- package/lib/components/Select.tsx +272 -0
- package/lib/components/SelectOld.tsx +153 -0
- package/lib/components/Slider.tsx +32 -40
- package/lib/components/Slideshow.tsx +174 -261
- package/lib/components/SlidingDrawer.tsx +216 -265
- package/lib/components/Spinner.tsx +21 -12
- package/lib/components/Switch.tsx +133 -180
- package/lib/components/Switchold.tsx +174 -0
- package/lib/components/Text.tsx +36 -83
- package/lib/components/layoutTest.tsx +74 -0
- package/lib/patterns/index.tsx +143 -202
- package/lib/theme/Badge.recipe.tsx +44 -39
- package/lib/theme/Button.recipe.tsx +139 -48
- package/lib/theme/Checkbox.recipe.tsx +121 -0
- package/lib/theme/CircleProgress.recipe.tsx +16 -22
- package/lib/theme/Field.recipe.tsx +66 -0
- package/lib/theme/GradientBackground.recipe.tsx +7 -20
- package/lib/theme/GradientText.recipe.tsx +42 -28
- package/lib/theme/IconWrapper.recipe.tsx +10 -85
- package/lib/theme/Input.recipe.tsx +76 -83
- package/lib/theme/Link.recipe.tsx +16 -43
- package/lib/theme/Modal.recipe.tsx +59 -21
- package/lib/theme/NumberInput.recipe.tsx +191 -0
- package/lib/theme/RadioGroup.recipe.tsx +163 -0
- package/lib/theme/ReText.recipe.tsx +4 -7
- package/lib/theme/Select.recipe.tsx +121 -0
- package/lib/theme/Slider.recipe.tsx +97 -181
- package/lib/theme/Slideshow.recipe.tsx +24 -102
- package/lib/theme/SlidingDrawer.recipe.tsx +21 -59
- package/lib/theme/Spinner.recipe.tsx +28 -3
- package/lib/theme/Switch.recipe.tsx +75 -54
- package/lib/theme/Text.recipe.tsx +66 -8
- package/lib/theme/animations.tsx +13 -0
- package/lib/varia/colorPalettes/amber.ts +54 -0
- package/lib/varia/colorPalettes/blue.ts +54 -0
- package/lib/varia/colorPalettes/bronze.ts +54 -0
- package/lib/varia/colorPalettes/brown.ts +54 -0
- package/lib/varia/colorPalettes/crimson.ts +55 -0
- package/lib/varia/colorPalettes/cyan.ts +54 -0
- package/lib/varia/colorPalettes/gold.ts +54 -0
- package/lib/varia/colorPalettes/grass.ts +54 -0
- package/lib/varia/colorPalettes/green.ts +54 -0
- package/lib/varia/colorPalettes/indigo.ts +54 -0
- package/lib/varia/colorPalettes/iris.ts +54 -0
- package/lib/varia/colorPalettes/jade.ts +54 -0
- package/lib/varia/colorPalettes/lime.ts +55 -0
- package/lib/varia/colorPalettes/mauve.ts +54 -0
- package/lib/varia/colorPalettes/mint.ts +54 -0
- package/lib/varia/colorPalettes/neutral.ts +54 -0
- package/lib/varia/colorPalettes/olive.ts +54 -0
- package/lib/varia/colorPalettes/orange.ts +54 -0
- package/lib/varia/colorPalettes/pink.ts +54 -0
- package/lib/varia/colorPalettes/plum.ts +54 -0
- package/lib/varia/colorPalettes/purple.ts +56 -0
- package/lib/varia/colorPalettes/red.ts +55 -0
- package/lib/varia/colorPalettes/ruby.ts +56 -0
- package/lib/varia/colorPalettes/sage.ts +56 -0
- package/lib/varia/colorPalettes/sand.ts +56 -0
- package/lib/varia/colorPalettes/sky.ts +56 -0
- package/lib/varia/colorPalettes/slate.ts +56 -0
- package/lib/varia/colorPalettes/teal.ts +56 -0
- package/lib/varia/colorPalettes/tomato.ts +56 -0
- package/lib/varia/colorPalettes/violet.ts +56 -0
- package/lib/varia/colorPalettes/yellow.ts +56 -0
- package/lib/varia/defaultTheme.ts +174 -0
- package/lib/varia/mixins.ts +223 -0
- package/lib/varia/textStyles.ts +48 -0
- package/lib/varia/types.ts +277 -0
- package/lib/varia/utils.ts +283 -0
- package/package.json +1 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
ReactNode,
|
|
6
|
+
ReactElement,
|
|
7
|
+
} from 'react'
|
|
8
|
+
import {
|
|
9
|
+
View,
|
|
10
|
+
TouchableOpacity,
|
|
11
|
+
ScrollView,
|
|
12
|
+
TouchableWithoutFeedback,
|
|
13
|
+
StyleSheet,
|
|
14
|
+
} from 'react-native'
|
|
15
|
+
import {Portal} from '@gorhom/portal'
|
|
16
|
+
import Text from './Text'
|
|
17
|
+
import {StyleSheet as UniStyleSheet} from 'react-native-unistyles'
|
|
18
|
+
import {SelectStyles, SelectDefaultVariants} from '../theme/Select.recipe'
|
|
19
|
+
import {PalettesWithNestedKeys} from '../style/varia/types'
|
|
20
|
+
import {UnistylesVariants} from 'react-native-unistyles'
|
|
21
|
+
|
|
22
|
+
type SelectVariants = UnistylesVariants<typeof SelectStyles>
|
|
23
|
+
|
|
24
|
+
interface Option {
|
|
25
|
+
label: string
|
|
26
|
+
value: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface SelectContextType {
|
|
30
|
+
value: string
|
|
31
|
+
setValue: (val: string) => void
|
|
32
|
+
isOpen: boolean
|
|
33
|
+
setIsOpen: (open: boolean) => void
|
|
34
|
+
options: Option[]
|
|
35
|
+
colorPalette: PalettesWithNestedKeys
|
|
36
|
+
variant: SelectVariants['variant']
|
|
37
|
+
size: SelectVariants['size']
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const SelectContext = createContext<SelectContextType | undefined>(undefined)
|
|
41
|
+
|
|
42
|
+
const useSelect = () => {
|
|
43
|
+
const context = useContext(SelectContext)
|
|
44
|
+
if (!context)
|
|
45
|
+
throw new Error('Select subcomponent must be used within Select.Provider')
|
|
46
|
+
return context
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type RootProps = SelectVariants & {
|
|
50
|
+
options: Option[]
|
|
51
|
+
value?: string
|
|
52
|
+
onChange?: (val: string) => void
|
|
53
|
+
defaultValue?: string
|
|
54
|
+
placeholder?: string
|
|
55
|
+
colorPalette?: PalettesWithNestedKeys
|
|
56
|
+
flex?: number
|
|
57
|
+
portalHostName?: string
|
|
58
|
+
children: ReactNode
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const SelectRoot = ({
|
|
62
|
+
options,
|
|
63
|
+
value: propValue,
|
|
64
|
+
onChange: propOnChange,
|
|
65
|
+
defaultValue = '',
|
|
66
|
+
variant = SelectDefaultVariants.variant,
|
|
67
|
+
size = SelectDefaultVariants.size,
|
|
68
|
+
colorPalette = 'accent',
|
|
69
|
+
flex = 1,
|
|
70
|
+
portalHostName = 'select',
|
|
71
|
+
children,
|
|
72
|
+
}: RootProps) => {
|
|
73
|
+
SelectStyles.useVariants({variant, size})
|
|
74
|
+
const [internalValue, setInternalValue] = useState(defaultValue)
|
|
75
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
76
|
+
|
|
77
|
+
const isControlled = propValue !== undefined && propOnChange !== undefined
|
|
78
|
+
const value = isControlled ? propValue! : internalValue
|
|
79
|
+
|
|
80
|
+
const setValue = (val: string) => {
|
|
81
|
+
if (isControlled) propOnChange!(val)
|
|
82
|
+
else setInternalValue(val)
|
|
83
|
+
setIsOpen(false)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const trigger = React.Children.toArray(children).find(
|
|
87
|
+
(child: any) =>
|
|
88
|
+
React.isValidElement(child) &&
|
|
89
|
+
(child.type as any).displayName === 'SelectTrigger',
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const portalChildren = React.Children.toArray(children).filter(
|
|
93
|
+
(child: any) =>
|
|
94
|
+
!(
|
|
95
|
+
React.isValidElement(child) &&
|
|
96
|
+
(child.type as any).displayName === 'SelectTrigger'
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<View style={[styles.container(flex)]}>
|
|
102
|
+
{trigger &&
|
|
103
|
+
React.cloneElement(trigger as ReactElement<TriggerProps>, {
|
|
104
|
+
isOpen,
|
|
105
|
+
setIsOpen,
|
|
106
|
+
value,
|
|
107
|
+
options,
|
|
108
|
+
variant:
|
|
109
|
+
(trigger as ReactElement<TriggerProps>).props.variant ?? variant,
|
|
110
|
+
size: (trigger as ReactElement<TriggerProps>).props.size ?? size,
|
|
111
|
+
colorPalette:
|
|
112
|
+
(trigger as ReactElement<TriggerProps>).props.colorPalette ??
|
|
113
|
+
colorPalette,
|
|
114
|
+
})}
|
|
115
|
+
|
|
116
|
+
{isOpen && (
|
|
117
|
+
<Portal hostName={portalHostName}>
|
|
118
|
+
<SelectContext.Provider
|
|
119
|
+
value={{
|
|
120
|
+
value,
|
|
121
|
+
setValue,
|
|
122
|
+
isOpen,
|
|
123
|
+
setIsOpen,
|
|
124
|
+
options,
|
|
125
|
+
colorPalette,
|
|
126
|
+
variant,
|
|
127
|
+
size,
|
|
128
|
+
}}>
|
|
129
|
+
<View style={styles.portalContainer}>{portalChildren}</View>
|
|
130
|
+
</SelectContext.Provider>
|
|
131
|
+
</Portal>
|
|
132
|
+
)}
|
|
133
|
+
</View>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface TriggerProps {
|
|
138
|
+
placeholder?: string
|
|
139
|
+
isOpen?: boolean
|
|
140
|
+
setIsOpen?: (v: boolean) => void
|
|
141
|
+
variant?: SelectVariants['variant']
|
|
142
|
+
size?: SelectVariants['size']
|
|
143
|
+
colorPalette?: PalettesWithNestedKeys
|
|
144
|
+
value?: string
|
|
145
|
+
options?: Option[]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const SelectTrigger = ({
|
|
149
|
+
placeholder = 'Selecciona una opción',
|
|
150
|
+
isOpen,
|
|
151
|
+
setIsOpen,
|
|
152
|
+
variant,
|
|
153
|
+
size,
|
|
154
|
+
colorPalette = 'accent',
|
|
155
|
+
value,
|
|
156
|
+
options = [],
|
|
157
|
+
}: TriggerProps) => {
|
|
158
|
+
SelectStyles.useVariants({variant, size})
|
|
159
|
+
const selected = options.find(opt => opt.value === value)
|
|
160
|
+
return (
|
|
161
|
+
<TouchableWithoutFeedback onPress={() => setIsOpen?.(!isOpen)}>
|
|
162
|
+
<View style={[styles.input, SelectStyles.trigger(colorPalette)]}>
|
|
163
|
+
<Text>{selected ? selected.label : placeholder}</Text>
|
|
164
|
+
</View>
|
|
165
|
+
</TouchableWithoutFeedback>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
SelectTrigger.displayName = 'SelectTrigger'
|
|
169
|
+
|
|
170
|
+
const SelectOverlay = ({
|
|
171
|
+
variant,
|
|
172
|
+
size,
|
|
173
|
+
colorPalette = 'accent',
|
|
174
|
+
}: {
|
|
175
|
+
variant?: SelectVariants['variant']
|
|
176
|
+
size?: SelectVariants['size']
|
|
177
|
+
colorPalette?: PalettesWithNestedKeys
|
|
178
|
+
}) => {
|
|
179
|
+
SelectStyles.useVariants({variant, size})
|
|
180
|
+
const {setIsOpen} = useSelect()
|
|
181
|
+
return (
|
|
182
|
+
<TouchableWithoutFeedback onPress={() => setIsOpen(false)}>
|
|
183
|
+
<View style={[styles.backdrop, SelectStyles.overlay(colorPalette)]} />
|
|
184
|
+
</TouchableWithoutFeedback>
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
SelectOverlay.displayName = 'SelectOverlay'
|
|
188
|
+
|
|
189
|
+
const SelectContent = ({
|
|
190
|
+
children,
|
|
191
|
+
...props
|
|
192
|
+
}: {
|
|
193
|
+
children: ReactNode
|
|
194
|
+
variant?: SelectVariants['variant']
|
|
195
|
+
size?: SelectVariants['size']
|
|
196
|
+
}) => {
|
|
197
|
+
const {variant, size, colorPalette} = {...useSelect(), ...props}
|
|
198
|
+
SelectStyles.useVariants({variant, size})
|
|
199
|
+
return (
|
|
200
|
+
<View style={[styles.modalContent, SelectStyles.content(colorPalette)]}>
|
|
201
|
+
<ScrollView>{children}</ScrollView>
|
|
202
|
+
</View>
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
SelectContent.displayName = 'SelectContent'
|
|
206
|
+
|
|
207
|
+
const SelectItem = ({value, label, ...props}: Option) => {
|
|
208
|
+
const {
|
|
209
|
+
variant,
|
|
210
|
+
size,
|
|
211
|
+
setValue,
|
|
212
|
+
value: selected,
|
|
213
|
+
colorPalette,
|
|
214
|
+
} = {...useSelect(), ...props}
|
|
215
|
+
const isSelected = selected === value
|
|
216
|
+
SelectStyles.useVariants({variant, size})
|
|
217
|
+
return (
|
|
218
|
+
<TouchableOpacity onPress={() => setValue(value)}>
|
|
219
|
+
<View style={[styles.item, SelectStyles.item(colorPalette, isSelected)]}>
|
|
220
|
+
<Text style={SelectStyles.itemText(colorPalette, isSelected)}>
|
|
221
|
+
{label}
|
|
222
|
+
</Text>
|
|
223
|
+
</View>
|
|
224
|
+
</TouchableOpacity>
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
SelectItem.displayName = 'SelectItem'
|
|
228
|
+
|
|
229
|
+
const Select = {
|
|
230
|
+
Root: SelectRoot,
|
|
231
|
+
Trigger: SelectTrigger,
|
|
232
|
+
Overlay: SelectOverlay,
|
|
233
|
+
Content: SelectContent,
|
|
234
|
+
Item: SelectItem,
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export default Select
|
|
238
|
+
|
|
239
|
+
const styles = UniStyleSheet.create({
|
|
240
|
+
container: (flex: number) => ({
|
|
241
|
+
flexGrow: flex,
|
|
242
|
+
flexDirection: 'row',
|
|
243
|
+
justifyContent: 'center',
|
|
244
|
+
}),
|
|
245
|
+
input: {
|
|
246
|
+
flex: 1,
|
|
247
|
+
flexDirection: 'row',
|
|
248
|
+
alignItems: 'center',
|
|
249
|
+
justifyContent: 'center',
|
|
250
|
+
},
|
|
251
|
+
item: {
|
|
252
|
+
alignItems: 'center',
|
|
253
|
+
flexDirection: 'row',
|
|
254
|
+
},
|
|
255
|
+
backdrop: {
|
|
256
|
+
...StyleSheet.absoluteFillObject,
|
|
257
|
+
backgroundColor: 'rgba(0,0,0,0.3)',
|
|
258
|
+
},
|
|
259
|
+
modalContent: {
|
|
260
|
+
overflow: 'hidden',
|
|
261
|
+
alignSelf: 'stretch',
|
|
262
|
+
},
|
|
263
|
+
portalContainer: {
|
|
264
|
+
position: 'absolute',
|
|
265
|
+
top: 0,
|
|
266
|
+
left: 0,
|
|
267
|
+
right: 0,
|
|
268
|
+
bottom: 0,
|
|
269
|
+
justifyContent: 'center',
|
|
270
|
+
alignItems: 'center',
|
|
271
|
+
},
|
|
272
|
+
})
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React, {useState} from 'react'
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
Text,
|
|
5
|
+
TouchableOpacity,
|
|
6
|
+
ScrollView,
|
|
7
|
+
TouchableWithoutFeedback,
|
|
8
|
+
} from 'react-native'
|
|
9
|
+
import {StyleSheet} from 'react-native-unistyles'
|
|
10
|
+
import {SelectStyles, SelectDefaultVariants} from '../theme/Select.recipe'
|
|
11
|
+
import {PalettesWithNestedKeys} from '../style/varia/types'
|
|
12
|
+
import {UnistylesVariants} from 'react-native-unistyles'
|
|
13
|
+
import {Modal} from './Modal'
|
|
14
|
+
|
|
15
|
+
type SelectVariants = UnistylesVariants<typeof SelectStyles>
|
|
16
|
+
|
|
17
|
+
interface Option {
|
|
18
|
+
label: string
|
|
19
|
+
value: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type SelectProps = SelectVariants & {
|
|
23
|
+
options: Option[]
|
|
24
|
+
value?: string
|
|
25
|
+
onChange?: (value: string) => void
|
|
26
|
+
onBlur?: () => void
|
|
27
|
+
defaultValue?: string
|
|
28
|
+
placeholder?: string
|
|
29
|
+
colorPalette?: PalettesWithNestedKeys
|
|
30
|
+
flex?: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const Select = ({
|
|
34
|
+
options,
|
|
35
|
+
value: propValue,
|
|
36
|
+
onChange: propOnChange,
|
|
37
|
+
onBlur: propOnBlur,
|
|
38
|
+
defaultValue = '',
|
|
39
|
+
placeholder = 'Selecciona una opción',
|
|
40
|
+
variant = SelectDefaultVariants.variant,
|
|
41
|
+
size = SelectDefaultVariants.size,
|
|
42
|
+
colorPalette = 'accent',
|
|
43
|
+
flex = 1,
|
|
44
|
+
}: SelectProps) => {
|
|
45
|
+
SelectStyles.useVariants({
|
|
46
|
+
variant,
|
|
47
|
+
size,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
51
|
+
const [internalValue, setInternalValue] = useState<string>(defaultValue)
|
|
52
|
+
|
|
53
|
+
const isControlled = propValue !== undefined && propOnChange !== undefined
|
|
54
|
+
|
|
55
|
+
const value = isControlled ? propValue! : internalValue
|
|
56
|
+
|
|
57
|
+
const handleSelect = (val: string) => {
|
|
58
|
+
if (isControlled) {
|
|
59
|
+
propOnChange!(val)
|
|
60
|
+
} else {
|
|
61
|
+
setInternalValue(val)
|
|
62
|
+
}
|
|
63
|
+
setIsOpen(false)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const selectedOption = options.find(opt => opt.value === value)
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<>
|
|
70
|
+
<TouchableWithoutFeedback
|
|
71
|
+
onPress={() => {
|
|
72
|
+
setIsOpen(true)
|
|
73
|
+
propOnBlur?.()
|
|
74
|
+
}}>
|
|
75
|
+
<View
|
|
76
|
+
style={[
|
|
77
|
+
styles.container(flex),
|
|
78
|
+
SelectStyles.container(colorPalette),
|
|
79
|
+
]}>
|
|
80
|
+
<View style={[styles.input, SelectStyles.input(colorPalette)]}>
|
|
81
|
+
<Text
|
|
82
|
+
style={[SelectStyles.valueText(colorPalette, !!selectedOption)]}>
|
|
83
|
+
{selectedOption ? selectedOption.label : placeholder}
|
|
84
|
+
</Text>
|
|
85
|
+
</View>
|
|
86
|
+
</View>
|
|
87
|
+
</TouchableWithoutFeedback>
|
|
88
|
+
|
|
89
|
+
{/* Modal con lista de opciones */}
|
|
90
|
+
<Modal.Root
|
|
91
|
+
isOpen={isOpen}
|
|
92
|
+
setIsOpen={setIsOpen}
|
|
93
|
+
colorPalette={colorPalette}
|
|
94
|
+
variant="outline"
|
|
95
|
+
portalHostName="select">
|
|
96
|
+
<Modal.Overlay variant={'outline'} customStyle={SelectStyles}>
|
|
97
|
+
<Modal.Content>
|
|
98
|
+
<Modal.Body>
|
|
99
|
+
<ScrollView
|
|
100
|
+
style={[SelectStyles.ModalContainer(colorPalette)]}
|
|
101
|
+
contentContainerStyle={[
|
|
102
|
+
SelectStyles.itemsContainer(colorPalette),
|
|
103
|
+
]}>
|
|
104
|
+
{options.map(item => (
|
|
105
|
+
<TouchableOpacity
|
|
106
|
+
key={item.value}
|
|
107
|
+
onPress={() => handleSelect(item.value)}>
|
|
108
|
+
<View
|
|
109
|
+
style={[
|
|
110
|
+
styles.item,
|
|
111
|
+
SelectStyles.item(
|
|
112
|
+
colorPalette,
|
|
113
|
+
selectedOption?.value === item.value,
|
|
114
|
+
),
|
|
115
|
+
]}>
|
|
116
|
+
<Text
|
|
117
|
+
style={SelectStyles.itemText(
|
|
118
|
+
colorPalette,
|
|
119
|
+
selectedOption?.value === item.value,
|
|
120
|
+
)}>
|
|
121
|
+
{item.label}
|
|
122
|
+
</Text>
|
|
123
|
+
</View>
|
|
124
|
+
</TouchableOpacity>
|
|
125
|
+
))}
|
|
126
|
+
</ScrollView>
|
|
127
|
+
</Modal.Body>
|
|
128
|
+
</Modal.Content>
|
|
129
|
+
</Modal.Overlay>
|
|
130
|
+
</Modal.Root>
|
|
131
|
+
</>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const styles = StyleSheet.create({
|
|
136
|
+
container: (flex: number) => ({
|
|
137
|
+
flexGrow: flex,
|
|
138
|
+
flexDirection: 'row',
|
|
139
|
+
justifyContent: 'center',
|
|
140
|
+
}),
|
|
141
|
+
input: {
|
|
142
|
+
flex: 1,
|
|
143
|
+
flexDirection: 'row',
|
|
144
|
+
alignItems: 'center',
|
|
145
|
+
justifyContent: 'center',
|
|
146
|
+
},
|
|
147
|
+
item: {
|
|
148
|
+
paddingVertical: 2,
|
|
149
|
+
paddingHorizontal: 8,
|
|
150
|
+
alignItems: 'center',
|
|
151
|
+
flexDirection: 'row',
|
|
152
|
+
},
|
|
153
|
+
})
|
|
@@ -7,12 +7,13 @@ import Animated, {
|
|
|
7
7
|
useSharedValue,
|
|
8
8
|
} from 'react-native-reanimated'
|
|
9
9
|
import {runOnJS} from 'react-native-worklets'
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import {SliderStyles, SliderDefaultVariants} from '../theme/Slider.recipe'
|
|
11
|
+
import {PalettesWithNestedKeys} from '../style/varia/types'
|
|
12
12
|
|
|
13
13
|
type SliderVariants = UnistylesVariants<typeof SliderStyles>
|
|
14
14
|
|
|
15
15
|
type SliderProps = SliderVariants & {
|
|
16
|
+
colorPalette?: PalettesWithNestedKeys
|
|
16
17
|
thickness?: number
|
|
17
18
|
minimumTrackThickness?: number
|
|
18
19
|
minimumTrackColor?: string
|
|
@@ -30,10 +31,9 @@ type SliderProps = SliderVariants & {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
const Slider = ({
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
minimumTrackColor = '#FFF',
|
|
34
|
+
colorPalette = 'accent',
|
|
35
|
+
variant = SliderDefaultVariants.variant,
|
|
36
|
+
size = SliderDefaultVariants.size,
|
|
37
37
|
displayStepsOnMinimumTrack = false,
|
|
38
38
|
thumbChildren: ThumbChildren,
|
|
39
39
|
axis = 'x',
|
|
@@ -50,17 +50,21 @@ const Slider = ({
|
|
|
50
50
|
}
|
|
51
51
|
SliderStyles.useVariants({
|
|
52
52
|
size,
|
|
53
|
-
|
|
53
|
+
variant,
|
|
54
54
|
})
|
|
55
|
-
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
const halfSize = (SliderStyles.thumb(colorPalette).width ?? 0) / 2
|
|
56
57
|
const thumbSize = {
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
width: SliderStyles.thumb(colorPalette).width,
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
height: SliderStyles.thumb(colorPalette).height,
|
|
59
62
|
}
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
const maximumTrackWidth = SliderStyles.maximumTrack(colorPalette).height ?? 0
|
|
62
65
|
const minimumTrackWidth =
|
|
63
|
-
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
SliderStyles.minimumTrack(colorPalette, false).height ?? 0
|
|
64
68
|
const context = useSharedValue({x: 0})
|
|
65
69
|
const translate = useSharedValue(value)
|
|
66
70
|
const trackLength = useSharedValue(0)
|
|
@@ -73,7 +77,6 @@ const Slider = ({
|
|
|
73
77
|
|
|
74
78
|
const slideGesture = Gesture.Pan()
|
|
75
79
|
.onTouchesDown(() => {
|
|
76
|
-
// Mark the child gesture as active when touching the child zone
|
|
77
80
|
isInsideChild.value = true
|
|
78
81
|
})
|
|
79
82
|
.onBegin(() => {
|
|
@@ -116,25 +119,22 @@ const Slider = ({
|
|
|
116
119
|
.onFinalize(() => {
|
|
117
120
|
isInsideChild.value = false
|
|
118
121
|
})
|
|
119
|
-
// New Tap Gesture
|
|
120
122
|
const tapGesture = Gesture.Tap()
|
|
121
123
|
.onBegin(e => {
|
|
122
124
|
if (isInsideChild.value) {
|
|
123
|
-
return
|
|
125
|
+
return
|
|
124
126
|
}
|
|
125
127
|
const tapPosition = axis === 'x' ? e.x : e.y
|
|
126
128
|
const stepLength = steps ? trackLength.value / steps : 1
|
|
127
129
|
|
|
128
|
-
// Calculate the raw position
|
|
129
130
|
const rawValue =
|
|
130
131
|
axis === 'y'
|
|
131
132
|
? Math.max(
|
|
132
133
|
0,
|
|
133
134
|
Math.min(trackLength.value - tapPosition, trackLength.value),
|
|
134
|
-
)
|
|
135
|
+
)
|
|
135
136
|
: Math.max(0, Math.min(tapPosition, trackLength.value))
|
|
136
137
|
|
|
137
|
-
// Snap to step if needed
|
|
138
138
|
const snappedValue = steps
|
|
139
139
|
? Math.round(rawValue / stepLength) * stepLength
|
|
140
140
|
: rawValue
|
|
@@ -159,27 +159,19 @@ const Slider = ({
|
|
|
159
159
|
}))
|
|
160
160
|
|
|
161
161
|
const opacityTrack = steps !== undefined && displayStepsOnMinimumTrack
|
|
162
|
-
console.log('🚀 ~ opacityTrack:', opacityTrack)
|
|
163
|
-
|
|
164
|
-
// const minimumTrackBackgroundColor =
|
|
165
|
-
// SliderTokens.minimumTrack.variants.colorPalette[colorPalette]
|
|
166
|
-
// ?.backgroundColor;
|
|
167
|
-
const minimumTrackBackgroundColor = hexToRgba('#ff0000', 0.5)
|
|
168
|
-
console.log('🚀 ~ minimumTrackBackgroundColor:', minimumTrackBackgroundColor)
|
|
169
162
|
|
|
170
163
|
return (
|
|
171
|
-
// <View style={{flexDirection: 'row', flex: 1}}>
|
|
172
164
|
<View
|
|
173
165
|
style={[
|
|
174
166
|
styles.container(maximumTrackWidth, halfSize),
|
|
175
|
-
SliderStyles.container,
|
|
167
|
+
SliderStyles.container(colorPalette),
|
|
176
168
|
]}>
|
|
177
169
|
{axis === 'x' && <View style={{width: halfSize}} />}
|
|
178
170
|
<GestureDetector gesture={tapGesture}>
|
|
179
171
|
<View
|
|
180
172
|
style={[
|
|
181
173
|
styles.maximumTrack(maximumTrackWidth),
|
|
182
|
-
SliderStyles.maximumTrack,
|
|
174
|
+
SliderStyles.maximumTrack(colorPalette),
|
|
183
175
|
]}
|
|
184
176
|
onLayout={handleTrackLayout}>
|
|
185
177
|
{steps && (
|
|
@@ -188,7 +180,10 @@ const Slider = ({
|
|
|
188
180
|
(_, i) => (
|
|
189
181
|
<View
|
|
190
182
|
key={i}
|
|
191
|
-
style={[
|
|
183
|
+
style={[
|
|
184
|
+
styles.step(i, steps),
|
|
185
|
+
SliderStyles.step(colorPalette),
|
|
186
|
+
]}
|
|
192
187
|
/>
|
|
193
188
|
),
|
|
194
189
|
)}
|
|
@@ -197,12 +192,15 @@ const Slider = ({
|
|
|
197
192
|
<Animated.View
|
|
198
193
|
style={[
|
|
199
194
|
styles.minimumTrack(halfSize, minimumTrackWidth),
|
|
200
|
-
SliderStyles.minimumTrack(opacityTrack),
|
|
195
|
+
SliderStyles.minimumTrack(colorPalette, opacityTrack),
|
|
201
196
|
animatedTrack,
|
|
202
197
|
]}>
|
|
203
198
|
<GestureDetector gesture={slideGesture}>
|
|
204
199
|
<View
|
|
205
|
-
style={[
|
|
200
|
+
style={[
|
|
201
|
+
SliderStyles.thumb(colorPalette),
|
|
202
|
+
styles.thumb(halfSize, thumbSize),
|
|
203
|
+
]}>
|
|
206
204
|
{ThumbChildren || null}
|
|
207
205
|
</View>
|
|
208
206
|
</GestureDetector>
|
|
@@ -265,13 +263,11 @@ const stylesX = StyleSheet.create(theme => ({
|
|
|
265
263
|
width: 1,
|
|
266
264
|
height: '100%',
|
|
267
265
|
backgroundColor:
|
|
268
|
-
index === 0 || index === length ? 'transparent' : theme.colors.
|
|
266
|
+
index === 0 || index === length ? 'transparent' : theme.colors.fg.default,
|
|
269
267
|
}),
|
|
270
268
|
}))
|
|
271
269
|
const stylesY = StyleSheet.create(theme => ({
|
|
272
270
|
container: (maximumTrackWidth, halfSize) => ({
|
|
273
|
-
// borderWidth: 1,
|
|
274
|
-
// borderColor: theme.colors.foreground,
|
|
275
271
|
flex: 1,
|
|
276
272
|
maxWidth: maximumTrackWidth,
|
|
277
273
|
maxHeight: 'auto',
|
|
@@ -280,13 +276,10 @@ const stylesY = StyleSheet.create(theme => ({
|
|
|
280
276
|
height: '100%',
|
|
281
277
|
paddingTop: halfSize,
|
|
282
278
|
paddingRight: 0,
|
|
283
|
-
backgroundColor: theme.colors.background,
|
|
284
279
|
flexDirection: 'column',
|
|
285
280
|
}),
|
|
286
281
|
maximumTrack: maximumTrackWidth => ({
|
|
287
282
|
flex: 1,
|
|
288
|
-
borderRadius: 22,
|
|
289
|
-
backgroundColor: theme.colors.background,
|
|
290
283
|
justifyContent: 'center',
|
|
291
284
|
alignItems: 'center',
|
|
292
285
|
position: 'relative',
|
|
@@ -307,7 +300,6 @@ const stylesY = StyleSheet.create(theme => ({
|
|
|
307
300
|
}),
|
|
308
301
|
thumb: (halfSize, thumbSize) => ({
|
|
309
302
|
borderRadius: 25,
|
|
310
|
-
backgroundColor: theme.colors.foreground,
|
|
311
303
|
position: 'absolute',
|
|
312
304
|
top: 0,
|
|
313
305
|
zIndex: 2,
|
|
@@ -327,7 +319,7 @@ const stylesY = StyleSheet.create(theme => ({
|
|
|
327
319
|
width: '100%',
|
|
328
320
|
height: 1,
|
|
329
321
|
backgroundColor:
|
|
330
|
-
index === 0 || index === length ? 'transparent' : theme.colors.
|
|
322
|
+
index === 0 || index === length ? 'transparent' : theme.colors.fg.default,
|
|
331
323
|
}),
|
|
332
324
|
}))
|
|
333
325
|
|