react-native-varia 0.2.2 → 0.2.4

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.
Files changed (40) hide show
  1. package/bin/cli.js +316 -139
  2. package/lib/components/Accordion.tsx +113 -0
  3. package/lib/components/Button.tsx +19 -8
  4. package/lib/components/CircleProgress.tsx +46 -28
  5. package/lib/components/Divider.tsx +18 -15
  6. package/lib/components/Drawer.tsx +496 -0
  7. package/lib/components/Field.tsx +24 -39
  8. package/lib/components/GradientBackground.tsx +25 -7
  9. package/lib/components/GradientText.tsx +38 -11
  10. package/lib/components/IconWrapper.tsx +20 -14
  11. package/lib/components/Input.tsx +106 -25
  12. package/lib/components/NumberInput.tsx +88 -19
  13. package/lib/components/OldSlider.tsx +327 -0
  14. package/lib/components/RadioGroup.tsx +55 -17
  15. package/lib/components/ReText.tsx +1 -1
  16. package/lib/components/Select.tsx +58 -22
  17. package/lib/components/Slider.tsx +176 -115
  18. package/lib/components/Slideshow.tsx +68 -69
  19. package/lib/components/SlidingDrawer.tsx +72 -29
  20. package/lib/components/Spinner.tsx +6 -2
  21. package/lib/components/Toast.tsx +89 -0
  22. package/lib/components/context/Field.tsx +27 -0
  23. package/lib/icons/Minus.tsx +24 -0
  24. package/lib/icons/Plus.tsx +23 -0
  25. package/lib/theme/Button.recipe.tsx +11 -1
  26. package/lib/theme/CircleProgress.recipe.tsx +3 -3
  27. package/lib/theme/Field.recipe.tsx +17 -2
  28. package/lib/theme/Input.recipe.tsx +12 -3
  29. package/lib/theme/NumberInput.recipe.tsx +9 -4
  30. package/lib/theme/RadioGroup.recipe.tsx +7 -1
  31. package/lib/theme/Select.recipe.tsx +7 -7
  32. package/lib/theme/Slider.recipe.tsx +366 -22
  33. package/lib/theme/Slideshow.recipe.tsx +1 -1
  34. package/lib/theme/SlidingDrawer.recipe.tsx +58 -4
  35. package/lib/theme/Toast.recipe.tsx +71 -0
  36. package/package.json +3 -2
  37. package/lib/components/NewSelect.tsx +0 -202
  38. package/lib/components/index.tsx +0 -83
  39. package/lib/components/layoutTest.tsx +0 -74
  40. package/lib/theme/Button.recipe-old.tsx +0 -67
@@ -0,0 +1,327 @@
1
+ import React from 'react'
2
+ import {type LayoutChangeEvent, View} from 'react-native'
3
+ import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
4
+ import {Gesture, GestureDetector} from 'react-native-gesture-handler'
5
+ import Animated, {
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ } from 'react-native-reanimated'
9
+ import {runOnJS} from 'react-native-worklets'
10
+ import {SliderStyles, SliderDefaultVariants} from '../theme/OldSlider.recipe'
11
+ import {PalettesWithNestedKeys} from '../style/varia/types'
12
+
13
+ type SliderVariants = UnistylesVariants<typeof SliderStyles>
14
+
15
+ type SliderProps = SliderVariants & {
16
+ colorPalette?: PalettesWithNestedKeys
17
+ thickness?: number
18
+ minimumTrackThickness?: number
19
+ minimumTrackColor?: string
20
+ displayStepsOnMinimumTrack?: boolean
21
+ thumbSize?: {
22
+ width: number
23
+ height: number
24
+ }
25
+ thumbChildren?: React.ReactNode
26
+ axis: 'x' | 'y'
27
+ steps?: number
28
+ value?: number
29
+ onValueChange?: (value: number) => void
30
+ onSlidingComplete?: (value: number) => void
31
+ }
32
+
33
+ const OldSlider = ({
34
+ colorPalette = 'accent',
35
+ variant = SliderDefaultVariants.variant,
36
+ size = SliderDefaultVariants.size,
37
+ displayStepsOnMinimumTrack = false,
38
+ thumbChildren: ThumbChildren,
39
+ axis = 'x',
40
+ value = 0,
41
+ steps,
42
+ onValueChange,
43
+ onSlidingComplete,
44
+ }: SliderProps) => {
45
+ let styles
46
+ if (axis === 'x') {
47
+ styles = stylesX
48
+ } else {
49
+ styles = stylesY
50
+ }
51
+ SliderStyles.useVariants({
52
+ size,
53
+ variant,
54
+ })
55
+ const thumbStyle = SliderStyles.thumb(colorPalette)
56
+ const maximumTrackStyle = SliderStyles.maximumTrack(colorPalette)
57
+ const minimumTrackStyle = SliderStyles.minimumTrack(colorPalette, false)
58
+
59
+ const halfSize = (thumbStyle.width ?? 0) / 2
60
+ const thumbSize = {
61
+ width: thumbStyle.width,
62
+ height: thumbStyle.height,
63
+ }
64
+ const maximumTrackWidth = maximumTrackStyle.height ?? 30
65
+ const minimumTrackWidth = minimumTrackStyle.height ?? 30
66
+ const context = useSharedValue({x: 0})
67
+ const translate = useSharedValue(value)
68
+ const trackLength = useSharedValue(0)
69
+ const isInsideChild = useSharedValue(false)
70
+
71
+ const handleTrackLayout = (event: LayoutChangeEvent) => {
72
+ const {width, height} = event.nativeEvent.layout
73
+ trackLength.value = axis === 'x' ? width : height
74
+ }
75
+
76
+ const slideGesture = Gesture.Pan()
77
+ .onTouchesDown(() => {
78
+ isInsideChild.value = true
79
+ })
80
+ .onBegin(() => {
81
+ context.value.x = translate.value
82
+ })
83
+ .onUpdate(e => {
84
+ const stepLength = steps ? trackLength.value / steps : 1
85
+ const delta = axis === 'y' ? -e.translationY : e.translationX
86
+
87
+ const rawValue = Math.max(
88
+ 0,
89
+ Math.min(context.value.x + delta, trackLength.value),
90
+ )
91
+
92
+ const snappedValue = steps
93
+ ? Math.round(rawValue / stepLength) * stepLength
94
+ : rawValue
95
+
96
+ translate.value = snappedValue
97
+
98
+ if (steps) {
99
+ const stepIndex = Math.round(snappedValue / stepLength)
100
+ onValueChange && runOnJS(onValueChange)(stepIndex)
101
+ } else {
102
+ onValueChange &&
103
+ runOnJS(onValueChange)(
104
+ Math.round((snappedValue / trackLength.value) * 100) / 100,
105
+ )
106
+ }
107
+ })
108
+ .onEnd(() => {
109
+ const stepLength = steps ? trackLength.value / steps : 1
110
+
111
+ const snappedValue = steps
112
+ ? Math.round(translate.value / stepLength)
113
+ : translate.value / trackLength.value
114
+
115
+ onSlidingComplete && runOnJS(onSlidingComplete)(snappedValue)
116
+ })
117
+ .onFinalize(() => {
118
+ isInsideChild.value = false
119
+ })
120
+ const tapGesture = Gesture.Tap()
121
+ .onBegin(e => {
122
+ if (isInsideChild.value) {
123
+ return
124
+ }
125
+ const tapPosition = axis === 'x' ? e.x : e.y
126
+ const stepLength = steps ? trackLength.value / steps : 1
127
+
128
+ const rawValue =
129
+ axis === 'y'
130
+ ? Math.max(
131
+ 0,
132
+ Math.min(trackLength.value - tapPosition, trackLength.value),
133
+ )
134
+ : Math.max(0, Math.min(tapPosition, trackLength.value))
135
+
136
+ const snappedValue = steps
137
+ ? Math.round(rawValue / stepLength) * stepLength
138
+ : rawValue
139
+
140
+ translate.value = snappedValue
141
+
142
+ if (steps) {
143
+ const stepIndex = Math.round(snappedValue / stepLength)
144
+ onValueChange && runOnJS(onValueChange)(stepIndex)
145
+ onSlidingComplete && runOnJS(onSlidingComplete)(stepIndex)
146
+ } else {
147
+ const normalizedValue =
148
+ Math.round((snappedValue / trackLength.value) * 100) / 100
149
+ onValueChange && runOnJS(onValueChange)(normalizedValue)
150
+ onSlidingComplete && runOnJS(onSlidingComplete)(normalizedValue)
151
+ }
152
+ })
153
+ .simultaneousWithExternalGesture(slideGesture)
154
+
155
+ const animatedTrack = useAnimatedStyle(() => ({
156
+ [axis === 'y' ? 'height' : 'width']: translate.value + halfSize,
157
+ }))
158
+
159
+ const opacityTrack = steps !== undefined && displayStepsOnMinimumTrack
160
+
161
+ return (
162
+ <View
163
+ style={[
164
+ styles.container(maximumTrackWidth, halfSize),
165
+ SliderStyles.container(colorPalette),
166
+ ]}>
167
+ {axis === 'x' && <View style={{width: halfSize}} />}
168
+ <GestureDetector gesture={tapGesture}>
169
+ <View
170
+ style={[
171
+ styles.maximumTrack(maximumTrackWidth),
172
+ SliderStyles.maximumTrack(colorPalette),
173
+ ]}
174
+ onLayout={handleTrackLayout}>
175
+ {steps && (
176
+ <View style={styles.steps}>
177
+ {Array.from({length: steps + 1}, (_, index) => index).map(
178
+ (_, i) => (
179
+ <View
180
+ key={i}
181
+ style={[
182
+ styles.step(i, steps),
183
+ SliderStyles.step(colorPalette),
184
+ ]}
185
+ />
186
+ ),
187
+ )}
188
+ </View>
189
+ )}
190
+ <Animated.View
191
+ style={[
192
+ styles.minimumTrack(halfSize, minimumTrackWidth),
193
+ SliderStyles.minimumTrack(colorPalette, opacityTrack),
194
+ animatedTrack,
195
+ ]}>
196
+ <GestureDetector gesture={slideGesture}>
197
+ <View
198
+ style={[
199
+ SliderStyles.thumb(colorPalette),
200
+ styles.thumb(halfSize, thumbSize),
201
+ ]}>
202
+ {ThumbChildren || null}
203
+ </View>
204
+ </GestureDetector>
205
+ </Animated.View>
206
+ </View>
207
+ </GestureDetector>
208
+ {axis === 'y' && <View style={{height: halfSize}} />}
209
+ </View>
210
+ )
211
+ }
212
+
213
+ const stylesX = StyleSheet.create(theme => ({
214
+ container: (thickness, halfSize) => ({
215
+ flex: thickness ? 1 : 1,
216
+ maxWidth: 'auto',
217
+ borderRadius: 22,
218
+ width: '100%',
219
+ height: '100%',
220
+ paddingTop: 0,
221
+ paddingRight: halfSize,
222
+ flexDirection: 'row',
223
+ }),
224
+ maximumTrack: thickness => ({
225
+ flex: thickness ? 1 : 1,
226
+ justifyContent: 'center',
227
+ position: 'relative',
228
+ borderRadius: 22,
229
+ }),
230
+ minimumTrack: (halfSize, minimumTrackThickness) => ({
231
+ height: minimumTrackThickness,
232
+ width: '100%',
233
+ left: halfSize * -1,
234
+ bottom: 'auto',
235
+ paddingBottom: 0,
236
+ paddingLeft: halfSize,
237
+ borderBottomLeftRadius: 20,
238
+ borderBottomRightRadius: 0,
239
+ borderTopLeftRadius: 20,
240
+ justifyContent: 'center',
241
+ }),
242
+ thumb: (halfSize, thumbSize) => ({
243
+ width: halfSize ? thumbSize.width : thumbSize.width,
244
+ height: thumbSize.height,
245
+ borderRadius: 25,
246
+ position: 'absolute',
247
+ right: 0,
248
+ zIndex: 2,
249
+ transform: [{translateX: '50%'}],
250
+ }),
251
+ steps: {
252
+ width: '100%',
253
+ height: '100%',
254
+ flexDirection: 'row',
255
+ justifyContent: 'space-between',
256
+ alignItems: 'center',
257
+ zIndex: 0,
258
+ position: 'absolute',
259
+ },
260
+ step: (index, length) => ({
261
+ width: 1,
262
+ height: '100%',
263
+ backgroundColor:
264
+ index === 0 || index === length ? 'transparent' : theme.colors.fg.default,
265
+ }),
266
+ }))
267
+ const stylesY = StyleSheet.create(theme => ({
268
+ container: (maximumTrackWidth, halfSize) => ({
269
+ flex: 1,
270
+ maxWidth: maximumTrackWidth,
271
+ maxHeight: 'auto',
272
+ borderRadius: 22,
273
+ width: '100%',
274
+ height: '100%',
275
+ paddingTop: halfSize,
276
+ paddingRight: 0,
277
+ flexDirection: 'column',
278
+ borderWidth: 1,
279
+ borderColor: 'yellow',
280
+ // minWidth: 30,
281
+ }),
282
+ maximumTrack: maximumTrackWidth => ({
283
+ flex: 1,
284
+ justifyContent: 'center',
285
+ alignItems: 'center',
286
+ position: 'relative',
287
+ maxWidth: maximumTrackWidth,
288
+ }),
289
+ minimumTrack: (halfSize, minimumTrackWidth) => ({
290
+ position: 'absolute',
291
+ height: '100%',
292
+ width: minimumTrackWidth,
293
+ left: 'auto',
294
+ bottom: halfSize * -1,
295
+ paddingBottom: halfSize,
296
+ paddingLeft: 0,
297
+ borderBottomLeftRadius: 20,
298
+ borderBottomRightRadius: 20,
299
+ borderTopLeftRadius: 0,
300
+ alignItems: 'center',
301
+ }),
302
+ thumb: (halfSize, thumbSize) => ({
303
+ borderRadius: 25,
304
+ position: 'absolute',
305
+ top: 0,
306
+ zIndex: 2,
307
+ transform: [{translateY: halfSize * -1}],
308
+ width: thumbSize.height,
309
+ height: thumbSize.width,
310
+ }),
311
+ steps: {
312
+ width: '100%',
313
+ height: '100%',
314
+ flexDirection: 'column',
315
+ justifyContent: 'space-between',
316
+ alignItems: 'center',
317
+ zIndex: 0,
318
+ },
319
+ step: (index, length) => ({
320
+ width: '100%',
321
+ height: 1,
322
+ backgroundColor:
323
+ index === 0 || index === length ? 'transparent' : theme.colors.fg.default,
324
+ }),
325
+ }))
326
+
327
+ export default OldSlider
@@ -1,11 +1,15 @@
1
1
  import React, {createContext, useContext, useState, useCallback} from 'react'
2
- import {View, Text, Pressable} from 'react-native'
2
+ import {View, Text, Pressable, ViewStyle} from 'react-native'
3
3
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
4
4
  import {
5
5
  RadioGroupStyles,
6
6
  RadioGroupDefaultVariants,
7
7
  } from '../theme/RadioGroup.recipe'
8
- import {PalettesWithNestedKeys} from '../style/varia/types'
8
+ import {
9
+ AlignSelf,
10
+ PalettesWithNestedKeys,
11
+ StackDirection,
12
+ } from '../style/varia/types'
9
13
 
10
14
  type RadioGroupVariants = UnistylesVariants<typeof RadioGroupStyles>
11
15
 
@@ -14,7 +18,12 @@ type RadioGroupRootProps = RadioGroupVariants & {
14
18
  colorPalette?: PalettesWithNestedKeys
15
19
  defaultValue?: string
16
20
  onValueChange?: (value: string) => void
17
- direction?: 'horizontal' | 'vertical'
21
+ direction?: StackDirection
22
+ flex?: number
23
+ alignSelf?: AlignSelf
24
+ justifyContent?: string
25
+ alignItems?: string
26
+ gap?: number
18
27
  }
19
28
 
20
29
  type RadioGroupContextProps = {
@@ -23,6 +32,8 @@ type RadioGroupContextProps = {
23
32
  colorPalette: PalettesWithNestedKeys
24
33
  variant: RadioGroupVariants['variant']
25
34
  size: RadioGroupVariants['size']
35
+ flex: number
36
+ alignSelf?: AlignSelf
26
37
  }
27
38
 
28
39
  const RadioGroupContext = createContext<RadioGroupContextProps | null>(null)
@@ -44,7 +55,12 @@ function Root({
44
55
  variant = RadioGroupDefaultVariants.variant,
45
56
  size = RadioGroupDefaultVariants.size,
46
57
  onValueChange,
47
- direction = 'vertical',
58
+ flex = 0,
59
+ alignSelf = 'auto',
60
+ direction = 'column',
61
+ justifyContent,
62
+ alignItems,
63
+ gap,
48
64
  }: RadioGroupRootProps) {
49
65
  RadioGroupStyles.useVariants({variant, size})
50
66
  const [value, setValue] = useState(defaultValue)
@@ -65,15 +81,22 @@ function Root({
65
81
  colorPalette,
66
82
  variant,
67
83
  size,
84
+ flex,
68
85
  }
69
86
 
70
87
  return (
71
88
  <RadioGroupContext.Provider value={contextValue}>
72
89
  <View
73
90
  style={[
74
- styles.root,
91
+ styles.root(
92
+ flex,
93
+ direction,
94
+ alignSelf,
95
+ justifyContent as ViewStyle['justifyContent'],
96
+ alignItems as ViewStyle['alignItems'],
97
+ gap,
98
+ ),
75
99
  RadioGroupStyles.container(colorPalette),
76
- direction === 'horizontal' && styles.rootHorizontal,
77
100
  ]}>
78
101
  {children}
79
102
  </View>
@@ -99,17 +122,23 @@ function Item({children, value: itemValue}: PublicItemProps) {
99
122
 
100
123
  const childrenWithValue = React.Children.map(children, child => {
101
124
  if (React.isValidElement(child)) {
102
- return React.cloneElement(child as React.ReactElement<any>, {
103
- itemValue,
104
- isSelected,
105
- })
125
+ return React.cloneElement(
126
+ child as React.ReactElement<{itemValue: string; isSelected: boolean}>,
127
+ {
128
+ itemValue,
129
+ isSelected,
130
+ },
131
+ )
106
132
  }
107
133
  return child
108
134
  })
109
135
 
110
136
  return (
111
137
  <Pressable
112
- style={[styles.item, RadioGroupStyles.item(colorPalette)]}
138
+ style={({pressed}) => [
139
+ styles.item,
140
+ RadioGroupStyles.item(colorPalette, pressed),
141
+ ]}
113
142
  onPress={() => onValueChange(itemValue)}
114
143
  accessibilityRole="radio"
115
144
  accessibilityState={{checked: isSelected}}>
@@ -175,12 +204,21 @@ function ItemText({
175
204
  }
176
205
 
177
206
  const styles = StyleSheet.create({
178
- root: {
179
- flexDirection: 'column',
180
- },
181
- rootHorizontal: {
182
- flexDirection: 'row',
183
- },
207
+ root: (
208
+ flex: number,
209
+ direction: StackDirection,
210
+ alignSelf?: AlignSelf,
211
+ justifyContent?: ViewStyle['justifyContent'],
212
+ alignItems?: ViewStyle['alignItems'],
213
+ gap?: number,
214
+ ) => ({
215
+ flex,
216
+ flexDirection: direction,
217
+ alignSelf,
218
+ alignItems,
219
+ gap,
220
+ justifyContent,
221
+ }),
184
222
  item: {
185
223
  flexDirection: 'row',
186
224
  alignItems: 'center',
@@ -51,7 +51,7 @@ const ReText = ({
51
51
  const animatedProps = useAnimatedProps(() => {
52
52
  return {
53
53
  text: text.value,
54
- } as any
54
+ } as TextInputProps
55
55
  })
56
56
  return (
57
57
  <AnimatedTextInput
@@ -4,24 +4,35 @@ import React, {
4
4
  useState,
5
5
  ReactNode,
6
6
  ReactElement,
7
+ useMemo,
7
8
  } from 'react'
8
9
  import {
9
10
  View,
10
11
  TouchableOpacity,
11
12
  ScrollView,
12
13
  TouchableWithoutFeedback,
13
- StyleSheet,
14
+ Pressable,
14
15
  } from 'react-native'
15
16
  import {UnistylesVariants} from 'react-native-unistyles'
16
17
  import {Portal} from '@gorhom/portal'
17
18
  import Text from './Text'
18
- import {StyleSheet as UniStyleSheet} from 'react-native-unistyles'
19
+ import {StyleSheet} from 'react-native-unistyles'
19
20
  import {SelectStyles, SelectDefaultVariants} from '../theme/Select.recipe'
20
- import {PalettesWithNestedKeys} from '../style/varia/types'
21
+ import {
22
+ AlignSelf,
23
+ Flex,
24
+ PalettesWithNestedKeys,
25
+ StackDirection,
26
+ } from '../style/varia/types'
27
+ import {computeFlexSync} from '../style/varia/utils'
21
28
 
22
29
  type SelectVariants = UnistylesVariants<typeof SelectStyles>
23
30
 
24
- interface Option {
31
+ function hasDisplayName(type: any): type is {displayName: string} {
32
+ return typeof type === 'function' && 'displayName' in type
33
+ }
34
+
35
+ type Option = SelectVariants & {
25
36
  label: string
26
37
  value: string
27
38
  }
@@ -35,6 +46,7 @@ interface SelectContextType {
35
46
  colorPalette: PalettesWithNestedKeys
36
47
  variant: SelectVariants['variant']
37
48
  size: SelectVariants['size']
49
+ flex: Flex
38
50
  }
39
51
 
40
52
  const SelectContext = createContext<SelectContextType | undefined>(undefined)
@@ -53,9 +65,11 @@ type RootProps = SelectVariants & {
53
65
  defaultValue?: string
54
66
  placeholder?: string
55
67
  colorPalette?: PalettesWithNestedKeys
56
- flex?: number
57
68
  portalHostName?: string
58
69
  children: ReactNode
70
+ flex?: Flex
71
+ stretch?: AlignSelf
72
+ direction?: 'row' | 'column'
59
73
  }
60
74
 
61
75
  const SelectRoot = ({
@@ -66,9 +80,11 @@ const SelectRoot = ({
66
80
  variant = SelectDefaultVariants.variant,
67
81
  size = SelectDefaultVariants.size,
68
82
  colorPalette = 'accent',
69
- flex = 1,
70
83
  portalHostName = 'select',
71
84
  children,
85
+ flex = 0,
86
+ stretch,
87
+ direction = 'column',
72
88
  }: RootProps) => {
73
89
  SelectStyles.useVariants({variant, size})
74
90
  const [internalValue, setInternalValue] = useState(defaultValue)
@@ -84,27 +100,32 @@ const SelectRoot = ({
84
100
  }
85
101
 
86
102
  const trigger = React.Children.toArray(children).find(
87
- (child: any) =>
103
+ (child): child is ReactElement<TriggerProps> =>
88
104
  React.isValidElement(child) &&
89
- (child.type as any).displayName === 'SelectTrigger',
105
+ hasDisplayName(child.type) &&
106
+ child.type.displayName === 'SelectTrigger',
90
107
  )
91
108
 
92
109
  const portalChildren = React.Children.toArray(children).filter(
93
- (child: any) =>
110
+ (child): child is ReactElement<TriggerProps> =>
94
111
  !(
95
112
  React.isValidElement(child) &&
96
- (child.type as any).displayName === 'SelectTrigger'
113
+ hasDisplayName(child.type) &&
114
+ child.type.displayName === 'SelectTrigger'
97
115
  ),
98
116
  )
99
117
 
100
118
  return (
101
- <View style={[styles.container(flex)]}>
119
+ <View style={[styles.container(flex, stretch)]}>
102
120
  {trigger &&
103
121
  React.cloneElement(trigger as ReactElement<TriggerProps>, {
104
122
  isOpen,
105
123
  setIsOpen,
106
124
  value,
107
125
  options,
126
+ flex,
127
+ stretch,
128
+ direction,
108
129
  variant:
109
130
  (trigger as ReactElement<TriggerProps>).props.variant ?? variant,
110
131
  size: (trigger as ReactElement<TriggerProps>).props.size ?? size,
@@ -125,6 +146,7 @@ const SelectRoot = ({
125
146
  colorPalette,
126
147
  variant,
127
148
  size,
149
+ flex,
128
150
  }}>
129
151
  <View style={styles.portalContainer}>{portalChildren}</View>
130
152
  </SelectContext.Provider>
@@ -143,6 +165,9 @@ interface TriggerProps {
143
165
  colorPalette?: PalettesWithNestedKeys
144
166
  value?: string
145
167
  options?: Option[]
168
+ flex?: Flex
169
+ stretch?: AlignSelf
170
+ direction?: 'row' | 'column'
146
171
  }
147
172
 
148
173
  const SelectTrigger = ({
@@ -153,16 +178,25 @@ const SelectTrigger = ({
153
178
  size,
154
179
  colorPalette = 'accent',
155
180
  value,
181
+ flex = 0,
182
+ stretch,
183
+ direction,
156
184
  options = [],
157
185
  }: TriggerProps) => {
158
186
  SelectStyles.useVariants({variant, size})
187
+ const {flex: childFlex} = useMemo(() => {
188
+ return computeFlexSync(flex as number, stretch, direction as StackDirection)
189
+ }, [flex, stretch, direction])
159
190
  const selected = options.find(opt => opt.value === value)
160
191
  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>
192
+ <Pressable
193
+ onPress={() => setIsOpen?.(!isOpen)}
194
+ style={({pressed}) => [
195
+ styles.input(childFlex),
196
+ SelectStyles.trigger(colorPalette, pressed),
197
+ ]}>
198
+ <Text>{selected ? selected.label : placeholder}</Text>
199
+ </Pressable>
166
200
  )
167
201
  }
168
202
  SelectTrigger.displayName = 'SelectTrigger'
@@ -236,18 +270,20 @@ const Select = {
236
270
 
237
271
  export default Select
238
272
 
239
- const styles = UniStyleSheet.create({
240
- container: (flex: number) => ({
241
- flexGrow: flex,
273
+ const styles = StyleSheet.create({
274
+ container: (flex: Flex, stretch: AlignSelf) => ({
275
+ flex,
242
276
  flexDirection: 'row',
243
277
  justifyContent: 'center',
278
+ ...(stretch ? {alignSelf: stretch} : {}),
279
+ alignItems: 'stretch',
244
280
  }),
245
- input: {
246
- flex: 1,
281
+ input: (flex: Flex) => ({
282
+ flex,
247
283
  flexDirection: 'row',
248
284
  alignItems: 'center',
249
285
  justifyContent: 'center',
250
- },
286
+ }),
251
287
  item: {
252
288
  alignItems: 'center',
253
289
  flexDirection: 'row',