react-native-varia 0.0.1 → 0.2.1

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 (86) hide show
  1. package/bin/cli.js +35 -18
  2. package/lib/components/Badge.tsx +31 -32
  3. package/lib/components/Button.tsx +20 -20
  4. package/lib/components/Checkbox.tsx +95 -0
  5. package/lib/components/CircleProgress.tsx +56 -66
  6. package/lib/components/Field.tsx +137 -0
  7. package/lib/components/GradientBackground.tsx +17 -18
  8. package/lib/components/GradientText.tsx +25 -64
  9. package/lib/components/IconWrapper.tsx +32 -25
  10. package/lib/components/Input.tsx +66 -68
  11. package/lib/components/Link.tsx +14 -28
  12. package/lib/components/Modal.tsx +197 -97
  13. package/lib/components/NewSelect.tsx +202 -0
  14. package/lib/components/NumberInput.tsx +226 -0
  15. package/lib/components/RadioGroup.tsx +195 -0
  16. package/lib/components/ReText.tsx +53 -87
  17. package/lib/components/Select.tsx +272 -0
  18. package/lib/components/SelectOld.tsx +153 -0
  19. package/lib/components/Slider.tsx +32 -40
  20. package/lib/components/Slideshow.tsx +174 -261
  21. package/lib/components/SlidingDrawer.tsx +216 -265
  22. package/lib/components/Spinner.tsx +21 -12
  23. package/lib/components/Switch.tsx +133 -180
  24. package/lib/components/Switchold.tsx +174 -0
  25. package/lib/components/Text.tsx +36 -83
  26. package/lib/components/layoutTest.tsx +74 -0
  27. package/lib/patterns/index.tsx +143 -202
  28. package/lib/theme/Badge.recipe.tsx +44 -39
  29. package/lib/theme/Button.recipe.tsx +139 -48
  30. package/lib/theme/Checkbox.recipe.tsx +121 -0
  31. package/lib/theme/CircleProgress.recipe.tsx +16 -22
  32. package/lib/theme/Field.recipe.tsx +66 -0
  33. package/lib/theme/GradientBackground.recipe.tsx +7 -20
  34. package/lib/theme/GradientText.recipe.tsx +42 -28
  35. package/lib/theme/IconWrapper.recipe.tsx +10 -85
  36. package/lib/theme/Input.recipe.tsx +76 -83
  37. package/lib/theme/Link.recipe.tsx +16 -43
  38. package/lib/theme/Modal.recipe.tsx +59 -21
  39. package/lib/theme/NumberInput.recipe.tsx +191 -0
  40. package/lib/theme/RadioGroup.recipe.tsx +163 -0
  41. package/lib/theme/ReText.recipe.tsx +4 -7
  42. package/lib/theme/Select.recipe.tsx +121 -0
  43. package/lib/theme/Slider.recipe.tsx +97 -181
  44. package/lib/theme/Slideshow.recipe.tsx +24 -102
  45. package/lib/theme/SlidingDrawer.recipe.tsx +21 -59
  46. package/lib/theme/Spinner.recipe.tsx +28 -3
  47. package/lib/theme/Switch.recipe.tsx +75 -54
  48. package/lib/theme/Text.recipe.tsx +66 -8
  49. package/lib/theme/animations.tsx +13 -0
  50. package/lib/varia/colorPalettes/amber.ts +54 -0
  51. package/lib/varia/colorPalettes/blue.ts +54 -0
  52. package/lib/varia/colorPalettes/bronze.ts +54 -0
  53. package/lib/varia/colorPalettes/brown.ts +54 -0
  54. package/lib/varia/colorPalettes/crimson.ts +55 -0
  55. package/lib/varia/colorPalettes/cyan.ts +54 -0
  56. package/lib/varia/colorPalettes/gold.ts +54 -0
  57. package/lib/varia/colorPalettes/grass.ts +54 -0
  58. package/lib/varia/colorPalettes/green.ts +54 -0
  59. package/lib/varia/colorPalettes/indigo.ts +54 -0
  60. package/lib/varia/colorPalettes/iris.ts +54 -0
  61. package/lib/varia/colorPalettes/jade.ts +54 -0
  62. package/lib/varia/colorPalettes/lime.ts +55 -0
  63. package/lib/varia/colorPalettes/mauve.ts +54 -0
  64. package/lib/varia/colorPalettes/mint.ts +54 -0
  65. package/lib/varia/colorPalettes/neutral.ts +54 -0
  66. package/lib/varia/colorPalettes/olive.ts +54 -0
  67. package/lib/varia/colorPalettes/orange.ts +54 -0
  68. package/lib/varia/colorPalettes/pink.ts +54 -0
  69. package/lib/varia/colorPalettes/plum.ts +54 -0
  70. package/lib/varia/colorPalettes/purple.ts +56 -0
  71. package/lib/varia/colorPalettes/red.ts +55 -0
  72. package/lib/varia/colorPalettes/ruby.ts +56 -0
  73. package/lib/varia/colorPalettes/sage.ts +56 -0
  74. package/lib/varia/colorPalettes/sand.ts +56 -0
  75. package/lib/varia/colorPalettes/sky.ts +56 -0
  76. package/lib/varia/colorPalettes/slate.ts +56 -0
  77. package/lib/varia/colorPalettes/teal.ts +56 -0
  78. package/lib/varia/colorPalettes/tomato.ts +56 -0
  79. package/lib/varia/colorPalettes/violet.ts +56 -0
  80. package/lib/varia/colorPalettes/yellow.ts +56 -0
  81. package/lib/varia/defaultTheme.ts +174 -0
  82. package/lib/varia/mixins.ts +223 -0
  83. package/lib/varia/textStyles.ts +48 -0
  84. package/lib/varia/types.ts +277 -0
  85. package/lib/varia/utils.ts +283 -0
  86. package/package.json +1 -1
@@ -8,17 +8,16 @@ import {
8
8
  } from 'react-native'
9
9
  import Text from './Text'
10
10
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
11
- import LinkStyles from '../theme/Link.recipe'
12
- import {TextSemanticSizes} from '../style/types'
13
- type LinkVariants = UnistylesVariants<typeof LinkStyles>
14
-
15
- type LinkProps = LinkVariants & {
11
+ import {PalettesWithNestedKeys, ThemeColors} from '../style/varia/types'
12
+ import {DefaultTextVariants, TextStyles} from '../theme/Text.recipe'
13
+ type TextVariants = UnistylesVariants<typeof TextStyles>
14
+ type LinkProps = TextVariants & {
15
+ colorPalette?: PalettesWithNestedKeys
16
16
  text: string
17
17
  url: string
18
18
  underline?: boolean
19
- as?: TextSemanticSizes
20
19
  fontSize?: number
21
- color?: string
20
+ color?: ThemeColors
22
21
  style?: StyleProp<ViewStyle>
23
22
  mixins?:
24
23
  | StyleProp<ViewStyle>
@@ -28,21 +27,16 @@ type LinkProps = LinkVariants & {
28
27
  }
29
28
 
30
29
  const Link = ({
31
- colorPalette,
32
- size,
30
+ colorPalette = 'accent',
31
+ variant,
32
+ size = DefaultTextVariants.size,
33
33
  text,
34
34
  url,
35
35
  underline,
36
- as,
37
36
  fontSize,
38
37
  color,
39
38
  mixins,
40
39
  }: LinkProps) => {
41
- LinkStyles.useVariants({
42
- colorPalette,
43
- size,
44
- })
45
-
46
40
  return (
47
41
  <TouchableOpacity
48
42
  onPress={async () => {
@@ -53,19 +47,14 @@ const Link = ({
53
47
  }
54
48
  }}>
55
49
  <Text
56
- as={as}
50
+ size={size}
51
+ variant={variant}
57
52
  fontSize={fontSize}
58
- // color={color}
53
+ color={color}
54
+ colorPalette={colorPalette}
59
55
  style={
60
56
  [
61
- styles.link(
62
- underline ? 'underline' : 'none',
63
- // linkTokens.variants,
64
- // linkTokens.customVariants
65
- ),
66
- LinkStyles.link,
67
- // style && styles.customStyle(style),
68
- color && {color},
57
+ styles.link(underline ? 'underline' : 'none'),
69
58
  mixins && mixins,
70
59
  ] as any
71
60
  }>
@@ -79,9 +68,6 @@ const styles = StyleSheet.create({
79
68
  link: (underline): any => ({
80
69
  textDecorationLine: underline,
81
70
  }),
82
- // customStyle: style => ({
83
- // ...style,
84
- // }),
85
71
  })
86
72
 
87
73
  export default Link
@@ -1,134 +1,173 @@
1
- import {TouchableOpacity, TouchableWithoutFeedback, View} from 'react-native'
2
- import Animated, {FadeIn, FadeOut, Keyframe} from 'react-native-reanimated'
1
+ import React, {createContext, useContext} from 'react'
2
+ import {
3
+ TouchableOpacity,
4
+ TouchableWithoutFeedback,
5
+ View,
6
+ StyleSheet as RNStyleSheet,
7
+ } from 'react-native'
8
+ import Animated from 'react-native-reanimated'
3
9
  import {StyleSheet, UnistylesVariants} from 'react-native-unistyles'
4
10
  import Text from './Text'
5
11
  import Svg, {Path} from 'react-native-svg'
6
12
  import {ModalStyles, ModalTokens} from '../theme/Modal.recipe'
13
+ import {PalettesWithNestedKeys} from '../style/varia/types'
14
+ import {Portal} from '@gorhom/portal'
7
15
 
8
16
  type ModalVariants = UnistylesVariants<typeof ModalStyles>
17
+ type AnimationKey = keyof typeof ModalTokens.animations.variants
18
+ type ColorPaletteKey = PalettesWithNestedKeys
9
19
 
10
- type ModalProps = ModalVariants & {
20
+ type ModalRootProps = ModalVariants & {
21
+ colorPalette?: ColorPaletteKey
22
+ animation: AnimationKey
23
+ portalHostName?: string
11
24
  isOpen: boolean
12
25
  setIsOpen: (isOpen: boolean) => void
13
26
  children: React.ReactNode
14
- heading?: string
15
27
  }
16
28
 
17
- // Define animations outside of the component to avoid re-creation on each render
18
- const enteringModalContent = new Keyframe({
19
- 0: {opacity: 0, transform: [{scale: 0.8}]},
20
- 20: {opacity: 0.5, transform: [{scale: 0.9}]},
21
- 100: {opacity: 1, transform: [{scale: 1}]},
22
- }).duration(300)
29
+ type ModalContextProps = Omit<ModalRootProps, 'children' | 'isOpen'>
23
30
 
24
- const exitingModalContent = new Keyframe({
25
- 0: {opacity: 1, transform: [{scale: 1}]},
26
- 100: {opacity: 0, transform: [{scale: 0.8}]},
27
- }).duration(200)
31
+ const ModalContext = createContext<ModalContextProps | undefined>(undefined)
28
32
 
29
- const Modal = ({
33
+ const useModalContext = () => {
34
+ const context = useContext(ModalContext)
35
+ if (context === undefined) {
36
+ throw new Error('Modal components must be rendered within Modal.Root')
37
+ }
38
+ return context
39
+ }
40
+
41
+ const ModalRoot = ({
42
+ colorPalette = 'accent',
43
+ variant = ModalTokens.defaultProps.variant,
44
+ animation,
45
+ portalHostName = 'modal',
30
46
  isOpen,
31
47
  setIsOpen,
32
- heading,
33
48
  children,
34
- colorPalette = ModalTokens.defaultProps.colorPalette,
35
- }: ModalProps) => {
36
- // const tokens = useTokens('modal')();
37
- if (!isOpen) return null
49
+ }: ModalRootProps) => {
50
+ ModalStyles.useVariants({
51
+ variant,
52
+ })
38
53
 
39
- // const resolvedColorScheme =
40
- // colorScheme ??
41
- // (tokens.defaultProps.colorScheme as keyof ModalColorSchemeVariants);
54
+ if (!isOpen) return null
42
55
 
43
- ModalStyles.useVariants({
56
+ const contextValue: ModalContextProps = {
44
57
  colorPalette,
45
- })
58
+ variant,
59
+ animation,
60
+ setIsOpen,
61
+ }
62
+
63
+ return (
64
+ <Portal hostName={portalHostName}>
65
+ <ModalContext.Provider value={contextValue}>
66
+ {children}
67
+ </ModalContext.Provider>
68
+ </Portal>
69
+ )
70
+ }
71
+
72
+ type ModalOverlayProps = {
73
+ children: React.ReactNode
74
+ variant?: ModalVariants['variant']
75
+ animation?: keyof typeof ModalTokens.animations.variants
76
+ colorPalette?: PalettesWithNestedKeys
77
+ customStyle?: any
78
+ }
79
+
80
+ const ModalOverlay = ({children, ...props}: ModalOverlayProps) => {
81
+ const context = useModalContext()
82
+ const {
83
+ colorPalette = 'accent',
84
+ variant,
85
+ animation,
86
+ setIsOpen,
87
+ } = {...context, ...props}
88
+
89
+ ModalStyles.useVariants({variant})
46
90
 
47
91
  return (
48
92
  <Animated.View
49
- style={styles.overlay}
50
- entering={FadeIn.duration(200)}
51
- exiting={FadeOut.duration(250)}>
93
+ style={[styles.overlay, ModalStyles.overlay(colorPalette)]}
94
+ entering={ModalTokens.animations.variants[animation]?.enteringOverlay}
95
+ exiting={ModalTokens.animations.variants[animation]?.exitingOverlay}>
52
96
  <TouchableWithoutFeedback onPress={() => setIsOpen(false)}>
53
- <View style={StyleSheet.absoluteFillObject} />
97
+ <View style={RNStyleSheet.absoluteFillObject} />
54
98
  </TouchableWithoutFeedback>
55
- <Animated.View
56
- // @ts-ignore
57
- style={[styles.modalBox(), ModalStyles.container]}
58
- entering={enteringModalContent}
59
- exiting={exitingModalContent}>
60
- <View style={styles.header(!heading)}>
61
- <Text style={styles.headerTitle}>{!!heading && heading}</Text>
62
- <View
63
- style={{
64
- position: 'absolute',
65
- right: 0,
66
- top: 0,
67
- }}>
68
- <CloseButton onClose={() => setIsOpen(false)} />
69
- </View>
70
- </View>
71
- <View style={styles.content}>{children}</View>
72
- </Animated.View>
99
+ {children}
73
100
  </Animated.View>
74
101
  )
75
102
  }
76
103
 
77
- // type ModalTokenType = ReturnType<Tokens['modal']>;
78
- // type VariantsType = ModalTokenType['variants'];
104
+ type ModalContentProps = Omit<ModalVariants, 'variant'> & {
105
+ children: React.ReactNode
106
+ variant?: ModalVariants['variant']
107
+ animation?: keyof typeof ModalTokens.animations.variants
108
+ colorPalette?: PalettesWithNestedKeys
109
+ customStyle?: any
110
+ }
79
111
 
80
- const styles = StyleSheet.create(theme => {
81
- return {
82
- overlay: {
83
- ...StyleSheet.absoluteFillObject,
84
- backgroundColor: 'black',
85
- zIndex: 1000,
86
- justifyContent: 'center',
87
- alignItems: 'center',
88
- },
89
- modalBox: () => ({
90
- width: '80%',
91
- justifyContent: 'center',
92
- alignItems: 'center',
93
- padding: 20,
94
- borderRadius: 10,
95
- // backgroundColor: theme.colors.background,
96
- // boxShadow: '0px 0px 50px rgba(250, 250, 250, 0.6)',
97
- // variants: {
98
- // colorScheme: variants.colorScheme as any,
99
- // },
100
- }),
101
- header: padding => ({
102
- flexDirection: 'row',
103
- justifyContent: 'space-between',
104
- alignItems: 'center',
105
- width: '100%',
106
- marginBottom: 10,
107
- padding: padding && 10,
108
- }),
109
- headerTitle: {
110
- textAlign: 'center',
111
- flex: 1,
112
- },
113
- closeButton: {
114
- color: 'white',
115
- },
116
- content: {
117
- width: '100%',
118
- },
112
+ const ModalContent = ({children, ...props}: ModalContentProps) => {
113
+ const context = useModalContext()
114
+ const {
115
+ colorPalette = 'accent',
116
+ variant,
117
+ animation,
118
+ } = {
119
+ ...context,
120
+ ...props,
119
121
  }
120
- })
121
122
 
122
- export default Modal
123
+ ModalStyles.useVariants({variant})
123
124
 
124
- export interface CloseButtonProps {
125
+ return (
126
+ <Animated.View
127
+ style={[styles.content(), ModalStyles.content(colorPalette)]}
128
+ entering={ModalTokens.animations.variants[animation]?.enteringContent}
129
+ exiting={ModalTokens.animations.variants[animation]?.exitingContent}>
130
+ {children}
131
+ </Animated.View>
132
+ )
133
+ }
134
+
135
+ const ModalHeader = ({children}: {children: React.ReactNode}) => {
136
+ return <View style={styles.header}>{children}</View>
137
+ }
138
+
139
+ const ModalTitle = ({children, ...props}: {children: React.ReactNode}) => {
140
+ const context = useModalContext()
141
+ const {variant, colorPalette = 'accent'} = {...context, ...props}
142
+
143
+ ModalStyles.useVariants({variant})
144
+ return <Text style={ModalStyles.title(colorPalette)}>{children}</Text>
145
+ }
146
+
147
+ type ModalBodyProps = Omit<ModalVariants, 'variant'> & {
148
+ children: React.ReactNode
149
+ variant?: ModalVariants['variant']
150
+ colorPalette?: PalettesWithNestedKeys
151
+ customStyle?: any
152
+ }
153
+
154
+ const ModalBody = ({children, ...props}: ModalBodyProps) => {
155
+ const context = useModalContext()
156
+ const {colorPalette = 'accent', variant} = {
157
+ ...context,
158
+ ...props,
159
+ }
160
+
161
+ ModalStyles.useVariants({variant})
162
+ return <View>{children}</View>
163
+ }
164
+
165
+ type CloseButtonProps = {
125
166
  scale?: number
126
- color?: undefined
167
+ color?: string
127
168
  onClose: () => void
128
169
  }
129
170
 
130
- const defaultColor = 'white'
131
-
132
171
  const CloseButton = ({
133
172
  onClose,
134
173
  scale = 1,
@@ -137,8 +176,7 @@ const CloseButton = ({
137
176
  }: CloseButtonProps) => (
138
177
  <TouchableOpacity onPress={onClose}>
139
178
  <Svg
140
- // TODO: fix types
141
- //@ts-ignore
179
+ // @ts-ignore
142
180
  xmlns="http://www.w3.org/2000/svg"
143
181
  width={scale * 24}
144
182
  height={scale * 24}
@@ -146,7 +184,7 @@ const CloseButton = ({
146
184
  fill="none"
147
185
  {...rest}>
148
186
  <Path
149
- stroke={color || defaultColor}
187
+ stroke={color}
150
188
  strokeLinecap="round"
151
189
  strokeLinejoin="round"
152
190
  strokeWidth={1.5}
@@ -155,3 +193,65 @@ const CloseButton = ({
155
193
  </Svg>
156
194
  </TouchableOpacity>
157
195
  )
196
+
197
+ type ModalCloseTriggerProps = {
198
+ children: (params: {onClose: () => void}) => React.ReactNode
199
+ style?: any
200
+ }
201
+
202
+ const ModalCloseTrigger = ({children, style}: ModalCloseTriggerProps) => {
203
+ const {setIsOpen} = useModalContext()
204
+
205
+ const onClose = () => setIsOpen(false)
206
+
207
+ return (
208
+ <View
209
+ style={[
210
+ {
211
+ position: 'absolute',
212
+ right: 0,
213
+ top: 0,
214
+ },
215
+ style,
216
+ ]}>
217
+ {children({onClose})}
218
+ </View>
219
+ )
220
+ }
221
+
222
+ const styles = StyleSheet.create(theme => {
223
+ return {
224
+ overlay: {
225
+ ...RNStyleSheet.absoluteFillObject,
226
+ zIndex: 1000,
227
+ justifyContent: 'center',
228
+ alignItems: 'center',
229
+ },
230
+ content: () => ({
231
+ justifyContent: 'center',
232
+ alignItems: 'center',
233
+ alignSelf: 'stretch',
234
+ }),
235
+ header: {
236
+ flexDirection: 'row',
237
+ justifyContent: 'space-between',
238
+ alignItems: 'center',
239
+ width: '100%',
240
+ marginBottom: 10,
241
+ },
242
+ closeButton: {
243
+ color: 'white',
244
+ },
245
+ }
246
+ })
247
+
248
+ export const Modal = Object.assign(ModalRoot, {
249
+ Root: ModalRoot,
250
+ Overlay: ModalOverlay,
251
+ Content: ModalContent,
252
+ Header: ModalHeader,
253
+ Title: ModalTitle,
254
+ Body: ModalBody,
255
+ CloseTrigger: ModalCloseTrigger,
256
+ CloseButton: CloseButton,
257
+ })
@@ -0,0 +1,202 @@
1
+ import React, {createContext, useContext, useState, ReactNode} from 'react'
2
+ import {
3
+ View,
4
+ // Text,
5
+ TouchableOpacity,
6
+ ScrollView,
7
+ TouchableWithoutFeedback,
8
+ StyleSheet,
9
+ } from 'react-native'
10
+ import Text from './Text'
11
+ import {StyleSheet as UniStyleSheet} from 'react-native-unistyles'
12
+ import {SelectStyles, SelectDefaultVariants} from '../theme/Select.recipe'
13
+ import {PalettesWithNestedKeys} from '../style/varia/types'
14
+ import {UnistylesVariants} from 'react-native-unistyles'
15
+ import {Portal} from '@gorhom/portal'
16
+
17
+ type SelectVariants = UnistylesVariants<typeof SelectStyles>
18
+
19
+ interface Option {
20
+ label: string
21
+ value: string
22
+ }
23
+
24
+ interface SelectContextType {
25
+ value: string
26
+ setValue: (val: string) => void
27
+ isOpen: boolean
28
+ setIsOpen: (open: boolean) => void
29
+ options: Option[]
30
+ colorPalette: PalettesWithNestedKeys
31
+ variant: SelectVariants['variant']
32
+ size: SelectVariants['size']
33
+ }
34
+
35
+ const SelectContext = createContext<SelectContextType | undefined>(undefined)
36
+
37
+ const useSelect = () => {
38
+ const context = useContext(SelectContext)
39
+ if (!context)
40
+ throw new Error('Select subcomponent must be used within Select.Root')
41
+ return context
42
+ }
43
+
44
+ type RootProps = SelectVariants & {
45
+ options: Option[]
46
+ value?: string
47
+ onChange?: (val: string) => void
48
+ defaultValue?: string
49
+ placeholder?: string
50
+ colorPalette?: PalettesWithNestedKeys
51
+ flex?: number
52
+ children: ReactNode
53
+ portalHostName?: string
54
+ }
55
+
56
+ export const Select = {
57
+ Root: ({
58
+ options,
59
+ value: propValue,
60
+ onChange: propOnChange,
61
+ defaultValue = '',
62
+ placeholder = 'Selecciona una opción',
63
+ variant = SelectDefaultVariants.variant,
64
+ size = SelectDefaultVariants.size,
65
+ colorPalette = 'accent',
66
+ flex = 1,
67
+ children,
68
+ portalHostName = 'select',
69
+ }: RootProps) => {
70
+ SelectStyles.useVariants({variant, size})
71
+
72
+ const [internalValue, setInternalValue] = useState<string>(defaultValue)
73
+ const [isOpen, setIsOpen] = useState(false)
74
+ const isControlled = propValue !== undefined && propOnChange !== undefined
75
+ const value = isControlled ? propValue! : internalValue
76
+
77
+ const setValue = (val: string) => {
78
+ if (isControlled) propOnChange!(val)
79
+ else setInternalValue(val)
80
+ setIsOpen(false)
81
+ }
82
+
83
+ return (
84
+ <SelectContext.Provider
85
+ value={{
86
+ value,
87
+ setValue,
88
+ isOpen,
89
+ setIsOpen,
90
+ options,
91
+ colorPalette,
92
+ variant,
93
+ size,
94
+ }}>
95
+ <View style={[styles.container(flex)]}>{children}</View>
96
+
97
+ {isOpen && (
98
+ <Portal hostName={portalHostName}>
99
+ <View style={styles.modalOverlay}>
100
+ <TouchableWithoutFeedback onPress={() => setIsOpen(false)}>
101
+ <View style={styles.backdrop} />
102
+ </TouchableWithoutFeedback>
103
+ <View
104
+ style={[
105
+ styles.modalContent,
106
+ SelectStyles.ModalContainer(colorPalette),
107
+ ]}>
108
+ <ScrollView
109
+ contentContainerStyle={SelectStyles.itemsContainer(
110
+ colorPalette,
111
+ )}>
112
+ {options.map(opt => (
113
+ <TouchableOpacity
114
+ key={opt.value}
115
+ onPress={() => setValue(opt.value)}>
116
+ <View
117
+ style={[
118
+ styles.item,
119
+ SelectStyles.item(colorPalette, value === opt.value),
120
+ ]}>
121
+ <Text
122
+ style={SelectStyles.itemText(
123
+ colorPalette,
124
+ value === opt.value,
125
+ )}>
126
+ {opt.label}
127
+ </Text>
128
+ </View>
129
+ </TouchableOpacity>
130
+ ))}
131
+ </ScrollView>
132
+ </View>
133
+ </View>
134
+ </Portal>
135
+ )}
136
+ </SelectContext.Provider>
137
+ )
138
+ },
139
+
140
+ Trigger: ({placeholder = 'Selecciona una opción'}) => {
141
+ const {
142
+ variant,
143
+ size,
144
+ value,
145
+ setIsOpen,
146
+ options,
147
+ colorPalette = 'accent',
148
+ } = useSelect()
149
+ SelectStyles.useVariants({variant, size})
150
+ const selectedOption = options.find(opt => opt.value === value)
151
+
152
+ return (
153
+ <TouchableWithoutFeedback onPress={() => setIsOpen(true)}>
154
+ <View style={[styles.input, SelectStyles.input(colorPalette)]}>
155
+ <Text style={SelectStyles.valueText(colorPalette, !!selectedOption)}>
156
+ {selectedOption ? selectedOption.label : placeholder}
157
+ </Text>
158
+ </View>
159
+ </TouchableWithoutFeedback>
160
+ )
161
+ },
162
+ }
163
+
164
+ const styles = UniStyleSheet.create({
165
+ container: (flex: number) => ({
166
+ flexGrow: flex,
167
+ flexDirection: 'row',
168
+ justifyContent: 'center',
169
+ }),
170
+ input: {
171
+ flex: 1,
172
+ flexDirection: 'row',
173
+ alignItems: 'center',
174
+ justifyContent: 'center',
175
+ },
176
+ item: {
177
+ paddingVertical: 2,
178
+ paddingHorizontal: 8,
179
+ alignItems: 'center',
180
+ flexDirection: 'row',
181
+ },
182
+ modalOverlay: {
183
+ position: 'absolute',
184
+ top: 0,
185
+ left: 0,
186
+ right: 0,
187
+ bottom: 0,
188
+ justifyContent: 'center',
189
+ alignItems: 'center',
190
+ },
191
+ backdrop: {
192
+ ...StyleSheet.absoluteFillObject,
193
+ backgroundColor: 'rgba(0,0,0,0.3)',
194
+ },
195
+ modalContent: {
196
+ maxHeight: '50%',
197
+ width: '80%',
198
+ backgroundColor: 'white',
199
+ borderRadius: 8,
200
+ overflow: 'hidden',
201
+ },
202
+ })