react-native-molecules 0.5.0-beta.3 → 0.5.0-beta.31

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 (227) hide show
  1. package/components/Accordion/Accordion.tsx +2 -6
  2. package/components/Accordion/AccordionItem.tsx +16 -12
  3. package/components/Accordion/AccordionItemContent.tsx +6 -1
  4. package/components/Accordion/AccordionItemHeader.tsx +1 -1
  5. package/components/Accordion/utils.ts +6 -0
  6. package/components/ActivityIndicator/ActivityIndicator.tsx +6 -15
  7. package/components/Appbar/AppbarBase.tsx +18 -13
  8. package/components/Button/Button.tsx +211 -264
  9. package/components/Button/index.tsx +9 -3
  10. package/components/Button/types.ts +16 -2
  11. package/components/Button/utils.ts +230 -208
  12. package/components/Card/Card.tsx +1 -1
  13. package/components/Checkbox/Checkbox.tsx +125 -88
  14. package/components/Checkbox/CheckboxBase.ios.tsx +14 -23
  15. package/components/Checkbox/CheckboxBase.tsx +21 -137
  16. package/components/Checkbox/context.tsx +14 -0
  17. package/components/Checkbox/index.tsx +11 -4
  18. package/components/Checkbox/types.ts +63 -29
  19. package/components/Checkbox/utils.ts +25 -108
  20. package/components/Chip/Chip.tsx +41 -52
  21. package/components/Chip/utils.ts +3 -7
  22. package/components/DateField/DateField.tsx +111 -0
  23. package/components/DateField/index.tsx +6 -0
  24. package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +19 -51
  25. package/components/DatePicker/DateCalendar.tsx +83 -0
  26. package/components/DatePicker/DatePickerActions.tsx +73 -0
  27. package/components/DatePicker/DatePickerModal.tsx +246 -0
  28. package/components/DatePicker/DatePickerPopover.tsx +79 -0
  29. package/components/DatePicker/DatePickerProvider.tsx +158 -0
  30. package/components/DatePicker/DatePickerTrigger.tsx +23 -0
  31. package/components/DatePicker/context.tsx +83 -0
  32. package/components/DatePicker/index.tsx +45 -0
  33. package/components/DatePicker/utils.ts +295 -0
  34. package/components/DatePickerInline/DatePickerDockedHeader.tsx +117 -0
  35. package/components/DatePickerInline/DatePickerInline.tsx +17 -16
  36. package/components/DatePickerInline/DatePickerInlineBase.tsx +11 -5
  37. package/components/DatePickerInline/DatePickerInlineHeader.tsx +50 -20
  38. package/components/DatePickerInline/Day.tsx +25 -1
  39. package/components/DatePickerInline/DayNames.tsx +13 -10
  40. package/components/DatePickerInline/DayRange.tsx +2 -4
  41. package/components/DatePickerInline/HeaderItem.tsx +44 -29
  42. package/components/DatePickerInline/Month.tsx +48 -67
  43. package/components/DatePickerInline/MonthPicker.tsx +80 -92
  44. package/components/DatePickerInline/Swiper.native.tsx +21 -4
  45. package/components/DatePickerInline/Swiper.tsx +169 -14
  46. package/components/DatePickerInline/SwiperUtils.ts +1 -1
  47. package/components/DatePickerInline/Week.tsx +6 -1
  48. package/components/DatePickerInline/YearPicker.tsx +220 -78
  49. package/components/DatePickerInline/dateUtils.tsx +18 -13
  50. package/components/DatePickerInline/store.tsx +27 -0
  51. package/components/DatePickerInline/types.ts +6 -2
  52. package/components/DatePickerInline/utils.ts +66 -29
  53. package/components/Divider/Divider.tsx +192 -0
  54. package/components/Divider/index.tsx +10 -0
  55. package/components/Drawer/Drawer.tsx +17 -6
  56. package/components/Drawer/DrawerItemGroup.tsx +3 -7
  57. package/components/ElementGroup/ElementGroup.tsx +1 -1
  58. package/components/FilePicker/FilePicker.tsx +48 -78
  59. package/components/FilePicker/index.tsx +2 -1
  60. package/components/FilePicker/utils.ts +9 -0
  61. package/components/HelperText/HelperText.tsx +0 -35
  62. package/components/Icon/iconFactory.tsx +5 -4
  63. package/components/Icon/index.tsx +1 -1
  64. package/components/Icon/types.ts +17 -6
  65. package/components/IconButton/IconButton.tsx +84 -84
  66. package/components/IconButton/index.tsx +1 -0
  67. package/components/IconButton/types.ts +10 -0
  68. package/components/IconButton/utils.ts +167 -33
  69. package/components/List/List.tsx +276 -0
  70. package/components/List/context.tsx +27 -0
  71. package/components/List/index.ts +8 -0
  72. package/components/List/types.ts +117 -0
  73. package/components/List/utils.ts +79 -0
  74. package/components/LoadingIndicator/LoadingIndicator.tsx +253 -0
  75. package/components/LoadingIndicator/LoadingIndicator.web.tsx +136 -0
  76. package/components/LoadingIndicator/index.tsx +13 -0
  77. package/components/LoadingIndicator/utils.ts +117 -0
  78. package/components/Menu/Menu.tsx +162 -39
  79. package/components/Menu/index.tsx +10 -7
  80. package/components/Menu/utils.ts +21 -70
  81. package/components/NavigationRail/NavigationRail.tsx +15 -9
  82. package/components/Popover/Popover.tsx +119 -145
  83. package/components/Popover/PopoverRoot.tsx +60 -0
  84. package/components/Popover/common.ts +54 -34
  85. package/components/Popover/index.ts +12 -1
  86. package/components/Popover/usePlatformMeasure.native.ts +90 -0
  87. package/components/Popover/usePlatformMeasure.ts +120 -0
  88. package/components/Popover/utils.ts +34 -0
  89. package/components/Portal/Portal.tsx +1 -2
  90. package/components/Radio/Radio.tsx +188 -0
  91. package/components/Radio/RadioBase.ios.tsx +69 -0
  92. package/components/Radio/RadioBase.tsx +136 -0
  93. package/components/Radio/context.tsx +23 -0
  94. package/components/Radio/index.tsx +20 -0
  95. package/components/Radio/types.ts +101 -0
  96. package/components/Radio/utils.ts +115 -0
  97. package/components/Rating/Rating.tsx +1 -1
  98. package/components/Select/Select.tsx +521 -785
  99. package/components/Select/context.tsx +81 -0
  100. package/components/Select/index.ts +26 -14
  101. package/components/Select/types.ts +65 -58
  102. package/components/Select/utils.ts +126 -0
  103. package/components/Slot/Slot.tsx +224 -0
  104. package/components/Slot/compose-refs.tsx +62 -0
  105. package/components/Slot/index.tsx +8 -0
  106. package/components/Surface/Surface.android.tsx +32 -7
  107. package/components/Surface/Surface.ios.tsx +34 -29
  108. package/components/Surface/Surface.tsx +31 -4
  109. package/components/Surface/utils.ts +44 -6
  110. package/components/Switch/Switch.ios.tsx +1 -1
  111. package/components/Switch/Switch.tsx +10 -3
  112. package/components/Tabs/TabItem.tsx +35 -58
  113. package/components/Tabs/TabLabel.tsx +5 -9
  114. package/components/Tabs/Tabs.tsx +156 -150
  115. package/components/Tabs/utils.ts +15 -2
  116. package/components/Text/textFactory.tsx +17 -5
  117. package/components/TextInput/TextInput.tsx +663 -579
  118. package/components/TextInput/index.tsx +19 -3
  119. package/components/TextInput/types.ts +77 -28
  120. package/components/TextInput/utils.ts +235 -145
  121. package/components/TimeField/TimeField.tsx +75 -0
  122. package/components/TimeField/index.tsx +6 -0
  123. package/components/TimeField/useTimeFieldState.ts +70 -0
  124. package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
  125. package/components/TimePicker/AnalogClock.tsx +1 -1
  126. package/components/TimePicker/TimeInput.tsx +87 -42
  127. package/components/TimePicker/TimeInputs.tsx +138 -50
  128. package/components/TimePicker/TimePicker.tsx +74 -11
  129. package/components/TimePicker/TimePickerModal.tsx +186 -0
  130. package/components/TimePicker/context.tsx +17 -0
  131. package/components/TimePicker/index.tsx +15 -3
  132. package/components/TimePicker/utils.ts +93 -4
  133. package/components/Tooltip/Tooltip.tsx +42 -67
  134. package/components/Tooltip/TooltipContent.tsx +32 -5
  135. package/components/Tooltip/TooltipTrigger.tsx +21 -24
  136. package/components/Tooltip/index.tsx +1 -1
  137. package/components/TouchableRipple/TouchableRipple.native.tsx +83 -16
  138. package/components/TouchableRipple/TouchableRipple.tsx +150 -102
  139. package/components/TouchableRipple/rippleFromForegroundColor.ts +21 -0
  140. package/hocs/index.tsx +1 -1
  141. package/hocs/withKeyboardAccessibility.tsx +2 -3
  142. package/hocs/withPortal.tsx +1 -1
  143. package/hooks/index.tsx +2 -12
  144. package/hooks/useActionState.tsx +19 -8
  145. package/hooks/useContrastColor.ts +1 -2
  146. package/hooks/useFilePicker.tsx +7 -17
  147. package/hooks/useHandleNumberFormat.tsx +2 -2
  148. package/hooks/useMediaQuery.tsx +1 -2
  149. package/package.json +95 -111
  150. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +6 -3
  151. package/shortcuts-manager/ShortcutsManager/utils.tsx +1 -1
  152. package/shortcuts-manager/useSetScopes/useSetScopes.tsx +1 -1
  153. package/shortcuts-manager/useShortcut/useShortcut.tsx +1 -1
  154. package/styles/shadow.ts +2 -1
  155. package/styles/themes/LightTheme.tsx +1 -1
  156. package/utils/DocumentPicker/documentPicker.ts +78 -27
  157. package/utils/DocumentPicker/types.ts +0 -1
  158. package/utils/extractSubcomponents.ts +89 -0
  159. package/utils/extractTextStyles.ts +1 -2
  160. package/utils/formatNumberWithMask/formatNumberWithMask.ts +2 -1
  161. package/utils/index.ts +0 -3
  162. package/utils/normalizeToNumberString/normalizeToNumberString.ts +1 -1
  163. package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
  164. package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
  165. package/components/DatePickerDocked/index.tsx +0 -17
  166. package/components/DatePickerDocked/types.ts +0 -11
  167. package/components/DatePickerDocked/utils.ts +0 -157
  168. package/components/DatePickerInline/DatePickerContext.tsx +0 -21
  169. package/components/DatePickerInput/DatePickerInput.tsx +0 -139
  170. package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
  171. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -77
  172. package/components/DatePickerInput/DateRangeInput.tsx +0 -88
  173. package/components/DatePickerInput/index.tsx +0 -10
  174. package/components/DatePickerInput/types.ts +0 -28
  175. package/components/DatePickerInput/utils.ts +0 -15
  176. package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
  177. package/components/DatePickerModal/CalendarEdit.tsx +0 -139
  178. package/components/DatePickerModal/DatePickerModal.tsx +0 -85
  179. package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
  180. package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
  181. package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
  182. package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
  183. package/components/DatePickerModal/index.tsx +0 -16
  184. package/components/DatePickerModal/types.ts +0 -92
  185. package/components/DatePickerModal/utils.ts +0 -122
  186. package/components/DateTimePicker/DateTimePicker.tsx +0 -172
  187. package/components/DateTimePicker/index.tsx +0 -10
  188. package/components/DateTimePicker/utils.ts +0 -12
  189. package/components/HorizontalDivider/HorizontalDivider.tsx +0 -103
  190. package/components/HorizontalDivider/index.tsx +0 -9
  191. package/components/ListItem/ListItem.tsx +0 -136
  192. package/components/ListItem/ListItemDescription.tsx +0 -25
  193. package/components/ListItem/ListItemTitle.tsx +0 -25
  194. package/components/ListItem/index.tsx +0 -14
  195. package/components/ListItem/utils.ts +0 -115
  196. package/components/Menu/MenuDivider.tsx +0 -13
  197. package/components/Menu/MenuItem.tsx +0 -128
  198. package/components/Popover/Popover.native.tsx +0 -185
  199. package/components/RadioButton/RadioButton.tsx +0 -138
  200. package/components/RadioButton/RadioButtonAndroid.tsx +0 -188
  201. package/components/RadioButton/RadioButtonGroup.tsx +0 -98
  202. package/components/RadioButton/RadioButtonIOS.tsx +0 -106
  203. package/components/RadioButton/RadioButtonItem.tsx +0 -232
  204. package/components/RadioButton/index.ts +0 -22
  205. package/components/RadioButton/utils.ts +0 -165
  206. package/components/TimePickerField/TimePickerField.tsx +0 -152
  207. package/components/TimePickerField/index.tsx +0 -10
  208. package/components/TimePickerField/utils.ts +0 -94
  209. package/components/TimePickerModal/TimePickerModal.tsx +0 -115
  210. package/components/TimePickerModal/index.tsx +0 -10
  211. package/components/TimePickerModal/utils.ts +0 -47
  212. package/components/VerticalDivider/VerticalDivider.tsx +0 -100
  213. package/components/VerticalDivider/index.tsx +0 -9
  214. package/context-bridge/index.tsx +0 -87
  215. package/fast-context/index.tsx +0 -190
  216. package/hocs/typedMemo.tsx +0 -5
  217. package/hooks/useControlledValue.tsx +0 -68
  218. package/hooks/useLatest.tsx +0 -9
  219. package/hooks/useMergedRefs.ts +0 -14
  220. package/hooks/usePrevious.ts +0 -13
  221. package/hooks/useSearchable.tsx +0 -74
  222. package/hooks/useSubcomponents.tsx +0 -59
  223. package/hooks/useToggle.tsx +0 -24
  224. package/utils/color.ts +0 -22
  225. package/utils/compare/index.ts +0 -54
  226. package/utils/lodash.ts +0 -49
  227. package/utils/repository.ts +0 -53
@@ -4,6 +4,7 @@ import {
4
4
  getRegisteredComponentStylesWithFallback,
5
5
  getRegisteredComponentUtilsWithFallback,
6
6
  } from './../../core/componentsRegistry';
7
+ import type { IconButtonDefaultProps } from './types';
7
8
 
8
9
  export type States =
9
10
  | 'selectedAndDisabled'
@@ -19,14 +20,31 @@ const iconButtonSizeToIconSizeMapDefault = {
19
20
  lg: 26,
20
21
  };
21
22
 
23
+ const iconButtonConstantsDefault = {
24
+ minContainerSize: 32,
25
+ containerPadding: 16,
26
+ narrowWidthAdjustment: -8,
27
+ wideWidthAdjustment: 12,
28
+ squareCornerRadius: 12,
29
+ };
30
+
31
+ const iconButtonDefaultPropsDefault: IconButtonDefaultProps = {
32
+ size: 24,
33
+ variant: 'default',
34
+ shape: 'round',
35
+ width: 'default',
36
+ animated: false,
37
+ };
38
+
22
39
  const iconButtonStylesDefault = StyleSheet.create(theme => ({
23
40
  root: {
24
41
  borderColor: theme.colors.outline,
25
- color: theme.colors.onSurfaceVariant,
26
42
  borderRadius: theme.shapes.corner.full,
27
43
  overflow: 'hidden',
28
44
  borderWidth: 0,
29
45
  backgroundColor: 'transparent',
46
+ justifyContent: 'center',
47
+ alignItems: 'center',
30
48
 
31
49
  variants: {
32
50
  size: {
@@ -71,16 +89,13 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
71
89
 
72
90
  contained: {
73
91
  backgroundColor: theme.colors.surfaceVariant,
74
- color: theme.colors.primary,
75
92
  },
76
93
 
77
94
  'contained-tonal': {
78
95
  backgroundColor: theme.colors.surfaceVariant,
79
- color: theme.colors.onSurfaceVariant,
80
96
  },
81
97
 
82
98
  outlined: {
83
- color: theme.colors.onSurfaceVariant,
84
99
  borderWidth: 1,
85
100
  },
86
101
  },
@@ -90,30 +105,23 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
90
105
  {
91
106
  variant: 'default',
92
107
  state: 'selectedAndDisabled',
93
- styles: {
94
- color: theme.colors.primary,
95
- },
108
+ styles: {},
96
109
  },
97
110
  {
98
111
  variant: 'default',
99
112
  state: 'selected',
100
- styles: {
101
- color: theme.colors.primary,
102
- },
113
+ styles: {},
103
114
  },
104
115
  {
105
116
  variant: 'default',
106
117
  state: 'selectedAndHovered',
107
- styles: {
108
- color: theme.colors.primary,
109
- },
118
+ styles: {},
110
119
  },
111
120
  {
112
121
  variant: 'contained',
113
122
  state: 'selectedAndDisabled',
114
123
  styles: {
115
124
  backgroundColor: theme.colors.primary,
116
- color: theme.colors.onPrimary,
117
125
  },
118
126
  },
119
127
  {
@@ -128,14 +136,13 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
128
136
  state: 'selected',
129
137
  styles: {
130
138
  backgroundColor: theme.colors.primary,
131
- color: theme.colors.onPrimary,
132
139
  },
133
140
  },
134
141
  {
135
142
  variant: 'contained',
136
143
  state: 'selectedAndHovered',
137
144
  styles: {
138
- color: theme.colors.primary,
145
+ backgroundColor: theme.colors.primary,
139
146
  },
140
147
  },
141
148
  {
@@ -143,7 +150,6 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
143
150
  state: 'hovered',
144
151
  styles: {
145
152
  backgroundColor: theme.colors.primary,
146
- color: theme.colors.onPrimary,
147
153
  },
148
154
  },
149
155
  {
@@ -151,7 +157,6 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
151
157
  state: 'selectedAndDisabled',
152
158
  styles: {
153
159
  backgroundColor: theme.colors.secondaryContainer,
154
- color: theme.colors.onSecondaryContainer,
155
160
  },
156
161
  },
157
162
  {
@@ -166,7 +171,6 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
166
171
  state: 'selected',
167
172
  styles: {
168
173
  backgroundColor: theme.colors.secondaryContainer,
169
- color: theme.colors.onSecondaryContainer,
170
174
  },
171
175
  },
172
176
  {
@@ -174,7 +178,6 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
174
178
  state: 'selectedAndHovered',
175
179
  styles: {
176
180
  backgroundColor: theme.colors.secondaryContainer,
177
- color: theme.colors.onSecondaryContainer,
178
181
  },
179
182
  },
180
183
  {
@@ -182,7 +185,6 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
182
185
  state: 'selectedAndDisabled',
183
186
  styles: {
184
187
  backgroundColor: theme.colors.inverseSurface,
185
- color: theme.colors.inverseOnSurface,
186
188
  borderWidth: 0,
187
189
  },
188
190
  },
@@ -198,7 +200,6 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
198
200
  state: 'selected',
199
201
  styles: {
200
202
  backgroundColor: theme.colors.inverseSurface,
201
- color: theme.colors.inverseOnSurface,
202
203
  borderWidth: 0,
203
204
  },
204
205
  },
@@ -207,17 +208,12 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
207
208
  state: 'selectedAndHovered',
208
209
  styles: {
209
210
  backgroundColor: theme.colors.secondaryContainer,
210
- color: theme.colors.onSecondaryContainer,
211
211
  },
212
212
  },
213
213
  {
214
214
  variant: 'outlined',
215
215
  state: 'hovered',
216
- styles: {
217
- backgroundColor: theme.colors.inverseSurface,
218
- color: theme.colors.inverseOnSurface,
219
- borderWidth: 0,
220
- },
216
+ styles: {},
221
217
  },
222
218
  ],
223
219
  },
@@ -296,16 +292,146 @@ const iconButtonStylesDefault = StyleSheet.create(theme => ({
296
292
  variant: 'outlined',
297
293
  state: 'hovered',
298
294
  styles: {
299
- backgroundColor: theme.colors.stateLayer.hover.inverseOnSurface,
295
+ backgroundColor: theme.colors.stateLayer.hover.onSurfaceVariant,
300
296
  },
301
297
  },
302
298
  ],
303
299
  },
304
300
 
305
- innerContainer: {
306
- flexGrow: 1,
307
- justifyContent: 'center',
308
- alignItems: 'center',
301
+ icon: {
302
+ color: theme.colors.onSurfaceVariant,
303
+
304
+ variants: {
305
+ variant: {
306
+ default: {},
307
+
308
+ contained: {
309
+ color: theme.colors.primary,
310
+ },
311
+
312
+ 'contained-tonal': {
313
+ color: theme.colors.onSurfaceVariant,
314
+ },
315
+
316
+ outlined: {
317
+ color: theme.colors.onSurfaceVariant,
318
+ },
319
+ },
320
+ },
321
+
322
+ compoundVariants: [
323
+ {
324
+ variant: 'default',
325
+ state: 'selectedAndDisabled',
326
+ styles: {
327
+ color: theme.colors.primary,
328
+ },
329
+ },
330
+ {
331
+ variant: 'default',
332
+ state: 'selected',
333
+ styles: {
334
+ color: theme.colors.primary,
335
+ },
336
+ },
337
+ {
338
+ variant: 'default',
339
+ state: 'selectedAndHovered',
340
+ styles: {
341
+ color: theme.colors.primary,
342
+ },
343
+ },
344
+ {
345
+ variant: 'contained',
346
+ state: 'selectedAndDisabled',
347
+ styles: {
348
+ color: theme.colors.onPrimary,
349
+ },
350
+ },
351
+ {
352
+ variant: 'contained',
353
+ state: 'disabled',
354
+ styles: {},
355
+ },
356
+ {
357
+ variant: 'contained',
358
+ state: 'selected',
359
+ styles: {
360
+ color: theme.colors.onPrimary,
361
+ },
362
+ },
363
+ {
364
+ variant: 'contained',
365
+ state: 'selectedAndHovered',
366
+ styles: {
367
+ color: theme.colors.onPrimary,
368
+ },
369
+ },
370
+ {
371
+ variant: 'contained',
372
+ state: 'hovered',
373
+ styles: {
374
+ color: theme.colors.onPrimary,
375
+ },
376
+ },
377
+ {
378
+ variant: 'contained-tonal',
379
+ state: 'selectedAndDisabled',
380
+ styles: {
381
+ color: theme.colors.onSecondaryContainer,
382
+ },
383
+ },
384
+ {
385
+ variant: 'contained-tonal',
386
+ state: 'disabled',
387
+ styles: {},
388
+ },
389
+ {
390
+ variant: 'contained-tonal',
391
+ state: 'selected',
392
+ styles: {
393
+ color: theme.colors.onSecondaryContainer,
394
+ },
395
+ },
396
+ {
397
+ variant: 'contained-tonal',
398
+ state: 'selectedAndHovered',
399
+ styles: {
400
+ color: theme.colors.onSecondaryContainer,
401
+ },
402
+ },
403
+ {
404
+ variant: 'outlined',
405
+ state: 'selectedAndDisabled',
406
+ styles: {
407
+ color: theme.colors.inverseOnSurface,
408
+ },
409
+ },
410
+ {
411
+ variant: 'outlined',
412
+ state: 'disabled',
413
+ styles: {},
414
+ },
415
+ {
416
+ variant: 'outlined',
417
+ state: 'selected',
418
+ styles: {
419
+ color: theme.colors.inverseOnSurface,
420
+ },
421
+ },
422
+ {
423
+ variant: 'outlined',
424
+ state: 'selectedAndHovered',
425
+ styles: {
426
+ color: theme.colors.onSecondaryContainer,
427
+ },
428
+ },
429
+ {
430
+ variant: 'outlined',
431
+ state: 'hovered',
432
+ styles: {},
433
+ },
434
+ ],
309
435
  },
310
436
  }));
311
437
 
@@ -318,3 +444,11 @@ export const iconButtonSizeToIconSizeMap = getRegisteredComponentUtilsWithFallba
318
444
  iconButtonSizeToIconSizeMapDefault,
319
445
  'iconButtonSizeToIconSizeMap',
320
446
  );
447
+ export const iconButtonConstants = {
448
+ ...iconButtonConstantsDefault,
449
+ ...getRegisteredComponentUtilsWithFallback('IconButton', {}, 'iconButtonConstants'),
450
+ };
451
+ export const iconButtonDefaultProps: IconButtonDefaultProps = {
452
+ ...iconButtonDefaultPropsDefault,
453
+ ...getRegisteredComponentUtilsWithFallback('IconButton', {}, 'iconButtonDefaultProps'),
454
+ };
@@ -0,0 +1,276 @@
1
+ import { useControlledValue, useLatest } from '@react-native-molecules/utils/hooks';
2
+ import { memo, useCallback, useMemo } from 'react';
3
+ import { ScrollView, type StyleProp, type ViewStyle } from 'react-native';
4
+
5
+ import { typedMemo } from '../../hocs';
6
+ import { useActionState } from '../../hooks';
7
+ import { resolveStateVariant } from '../../utils';
8
+ import { StateLayer } from '../StateLayer';
9
+ import { TouchableRipple } from '../TouchableRipple';
10
+ import { ListContextProvider, useListContextValue } from './context';
11
+ import type {
12
+ DefaultListItemT,
13
+ ListContentProps,
14
+ ListContextValue,
15
+ ListItemId,
16
+ ListItemProps,
17
+ ListProps,
18
+ } from './types';
19
+ import { listItemStyles } from './utils';
20
+
21
+ const _ListItemBase = ({
22
+ ref,
23
+ children,
24
+ style: styleProp,
25
+ disabled = false,
26
+ variant = 'menuItem',
27
+ selected = false,
28
+ onPress,
29
+ hoverable: hoverableProp = false,
30
+ hovered: hoveredProp = false,
31
+ ...props
32
+ }: ListItemProps) => {
33
+ const {
34
+ hovered: _hovered,
35
+ focused,
36
+ actionsRef,
37
+ } = useActionState({ ref, actionsToListen: ['hover', 'focus'] });
38
+ const hoverable = hoverableProp || !!onPress;
39
+ const hovered = hoveredProp || _hovered;
40
+
41
+ const state = resolveStateVariant({
42
+ selectedAndFocused: selected && focused,
43
+ selected,
44
+ disabled,
45
+ hovered: hoverable && hovered,
46
+ focused,
47
+ });
48
+
49
+ listItemStyles.useVariants({
50
+ state: state as never,
51
+ variant: variant as never,
52
+ });
53
+
54
+ const containerStyles = useMemo(
55
+ () => [listItemStyles.root, styleProp],
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ [styleProp, state, variant],
58
+ );
59
+
60
+ return (
61
+ <TouchableRipple
62
+ {...props}
63
+ style={containerStyles as StyleProp<ViewStyle>}
64
+ disabled={disabled}
65
+ onPress={onPress}
66
+ ref={actionsRef}>
67
+ <>
68
+ {children}
69
+ <StateLayer style={listItemStyles.stateLayer} />
70
+ </>
71
+ </TouchableRipple>
72
+ );
73
+ };
74
+
75
+ const ListItemBase = memo(_ListItemBase);
76
+
77
+ const _ListItemSelectable = <Option extends object = DefaultListItemT>({
78
+ value,
79
+ children,
80
+ onPress,
81
+ onBeforeToggle,
82
+ disabled: itemDisabledProp = false,
83
+ shouldToggleOnPress = true,
84
+ accessibilityRole,
85
+ accessibilityState,
86
+ variant,
87
+ ...rest
88
+ }: ListItemProps<Option> & { value: ListItemId }) => {
89
+ const {
90
+ onAdd,
91
+ onRemove,
92
+ disabled: listDisabled,
93
+ allowDeselect,
94
+ isSelectedId,
95
+ } = useListContextValue(state => ({
96
+ onAdd: state.onAdd as (item: Option) => void,
97
+ onRemove: state.onRemove as (item: Option) => void,
98
+ disabled: state.disabled,
99
+ allowDeselect: state.allowDeselect,
100
+ isSelectedId: state.isSelectedId,
101
+ }));
102
+
103
+ const option = useMemo(
104
+ () =>
105
+ ({
106
+ id: value,
107
+ ...(itemDisabledProp ? { selectable: false } : {}),
108
+ } as Option),
109
+ [itemDisabledProp, value],
110
+ );
111
+
112
+ const isSelected = isSelectedId(value);
113
+
114
+ const isSelectable = (option as Record<string, unknown>).selectable;
115
+ const isOptionDisabled = Boolean(listDisabled || itemDisabledProp || isSelectable === false);
116
+
117
+ const handlePress = useCallback(
118
+ (
119
+ event: NonNullable<ListItemProps<Option>['onPress']> extends (event: infer E) => void
120
+ ? E
121
+ : never,
122
+ ) => {
123
+ if (isOptionDisabled) return;
124
+ onPress?.(event);
125
+
126
+ if (!shouldToggleOnPress) return;
127
+ onBeforeToggle?.(event);
128
+
129
+ if (isSelected) {
130
+ if (allowDeselect) onRemove(option);
131
+ return;
132
+ }
133
+ onAdd(option);
134
+ },
135
+ [
136
+ allowDeselect,
137
+ isOptionDisabled,
138
+ isSelected,
139
+ onAdd,
140
+ onBeforeToggle,
141
+ onPress,
142
+ onRemove,
143
+ option,
144
+ shouldToggleOnPress,
145
+ ],
146
+ );
147
+
148
+ return (
149
+ <ListItemBase
150
+ {...(rest as ListItemProps)}
151
+ selected={isSelected}
152
+ disabled={isOptionDisabled}
153
+ onPress={handlePress}
154
+ variant={variant ?? 'menuItem'}
155
+ accessibilityRole={accessibilityRole}
156
+ accessibilityState={
157
+ accessibilityState ?? { selected: isSelected, disabled: isOptionDisabled }
158
+ }>
159
+ {children}
160
+ </ListItemBase>
161
+ );
162
+ };
163
+
164
+ const ListItemSelectable = typedMemo(_ListItemSelectable);
165
+
166
+ const _ListItem = <Option extends object = DefaultListItemT>(props: ListItemProps<Option>) => {
167
+ if (props.value !== undefined) {
168
+ return <ListItemSelectable {...(props as ListItemProps<Option> & { value: ListItemId })} />;
169
+ }
170
+ return <ListItemBase {...(props as ListItemProps)} />;
171
+ };
172
+
173
+ const ListItem = typedMemo(_ListItem);
174
+
175
+ type ControlledListValue = ListItemId | ListItemId[] | null;
176
+
177
+ const emptyArr: ListItemId[] = [];
178
+
179
+ const ListProvider = typedMemo(
180
+ <Option extends object = DefaultListItemT>({
181
+ children,
182
+ value: valueProp,
183
+ defaultValue,
184
+ onChange,
185
+ multiple = false,
186
+ disabled = false,
187
+ error = false,
188
+ allowDeselect: allowDeselectProp,
189
+ }: ListProps<Option>) => {
190
+ const [value, onValueChange] = useControlledValue<ControlledListValue>({
191
+ value: valueProp,
192
+ defaultValue: defaultValue ?? (multiple ? (emptyArr as ListItemId[]) : null),
193
+ onChange: onChange as
194
+ | ((value: ControlledListValue, item: Option, event?: unknown) => void)
195
+ | undefined,
196
+ });
197
+ const valueRef = useLatest(value);
198
+
199
+ const allowDeselect = allowDeselectProp !== undefined ? allowDeselectProp : multiple;
200
+ const isSelectedId = useCallback(
201
+ (id: ListItemId) => {
202
+ if (multiple) {
203
+ const values = (value as ListItemId[] | null | undefined) ?? [];
204
+ return values.some(v => v === id);
205
+ }
206
+ return (value as ListItemId | null) === id;
207
+ },
208
+ [multiple, value],
209
+ );
210
+
211
+ const onAdd = useCallback(
212
+ (item: Option) => {
213
+ const id = (item as { id?: ListItemId }).id as ListItemId;
214
+ if (multiple) {
215
+ const currentValue = (valueRef.current as ListItemId[]) || [];
216
+ if (!currentValue.find(v => v === id)) {
217
+ onValueChange([...currentValue, id], item);
218
+ }
219
+ return;
220
+ }
221
+
222
+ onValueChange(id, item);
223
+ },
224
+ [multiple, onValueChange, valueRef],
225
+ );
226
+
227
+ const onRemove = useCallback(
228
+ (item: Option) => {
229
+ const id = (item as { id?: ListItemId }).id as ListItemId;
230
+ if (multiple) {
231
+ const currentValue = (valueRef.current as ListItemId[]) || [];
232
+ onValueChange(
233
+ currentValue.filter(v => v !== id),
234
+ item,
235
+ );
236
+ return;
237
+ }
238
+
239
+ onValueChange(null, item);
240
+ },
241
+ [multiple, onValueChange, valueRef],
242
+ );
243
+
244
+ const contextValue = {
245
+ value,
246
+ multiple,
247
+ onAdd: onAdd as (item: DefaultListItemT) => void,
248
+ onRemove: onRemove as (item: DefaultListItemT) => void,
249
+ isSelectedId,
250
+ disabled,
251
+ error,
252
+ allowDeselect,
253
+ } as ListContextValue<DefaultListItemT>;
254
+
255
+ return <ListContextProvider value={contextValue}>{children}</ListContextProvider>;
256
+ },
257
+ );
258
+
259
+ const ListContent = typedMemo(
260
+ ({ ref, children, style, ...rest }: ListContentProps & { ref?: React.ForwardedRef<any> }) => {
261
+ return (
262
+ <ScrollView style={style} {...rest} ref={ref}>
263
+ {children}
264
+ </ScrollView>
265
+ );
266
+ },
267
+ );
268
+
269
+ const List = Object.assign(ListProvider, {
270
+ Content: ListContent,
271
+ Item: ListItem,
272
+ });
273
+
274
+ export default List;
275
+
276
+ export { ListContent, ListItem, ListProvider };
@@ -0,0 +1,27 @@
1
+ import { createFastContext } from '@react-native-molecules/utils/fast-context';
2
+
3
+ import { registerPortalContext } from '../Portal';
4
+ import type { DefaultListItemT, ListContextValue } from './types';
5
+
6
+ const listContextDefaultValue: ListContextValue<DefaultListItemT> = {
7
+ value: null,
8
+ multiple: false,
9
+ onAdd: () => {},
10
+ onRemove: () => {},
11
+ isSelectedId: () => false,
12
+ disabled: false,
13
+ error: false,
14
+ allowDeselect: false,
15
+ };
16
+
17
+ const {
18
+ useStoreRef: useListStoreRef,
19
+ Provider: ListContextProvider,
20
+ useContext: useListContext,
21
+ useContextValue: useListContextValue,
22
+ Context: ListContext,
23
+ } = createFastContext<ListContextValue<DefaultListItemT>>(listContextDefaultValue, true);
24
+
25
+ export { ListContext, ListContextProvider, useListContext, useListContextValue, useListStoreRef };
26
+
27
+ registerPortalContext([ListContext]);
@@ -0,0 +1,8 @@
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
+ import ListDefault from './List';
3
+
4
+ export const List = getRegisteredComponentWithFallback('List', ListDefault);
5
+
6
+ export * from './context';
7
+ export type * from './types';
8
+ export * from './utils';