react-native-molecules 0.5.0-beta.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.
Files changed (355) hide show
  1. package/components/Accordion/Accordion.tsx +89 -0
  2. package/components/Accordion/AccordionItem.tsx +94 -0
  3. package/components/Accordion/AccordionItemContent.tsx +17 -0
  4. package/components/Accordion/AccordionItemHeader.tsx +122 -0
  5. package/components/Accordion/index.tsx +36 -0
  6. package/components/Accordion/utils.ts +62 -0
  7. package/components/ActivityIndicator/ActivityIndicator.ios.tsx +1 -0
  8. package/components/ActivityIndicator/ActivityIndicator.tsx +200 -0
  9. package/components/ActivityIndicator/AnimatedSpinner.tsx +121 -0
  10. package/components/ActivityIndicator/index.tsx +17 -0
  11. package/components/Appbar/AppbarActions.tsx +13 -0
  12. package/components/Appbar/AppbarBase.tsx +60 -0
  13. package/components/Appbar/AppbarCenterAligned.tsx +13 -0
  14. package/components/Appbar/AppbarLarge.tsx +13 -0
  15. package/components/Appbar/AppbarLeft.tsx +26 -0
  16. package/components/Appbar/AppbarMedium.tsx +13 -0
  17. package/components/Appbar/AppbarRight.tsx +40 -0
  18. package/components/Appbar/AppbarSmall.tsx +13 -0
  19. package/components/Appbar/AppbarTitle.tsx +49 -0
  20. package/components/Appbar/index.tsx +46 -0
  21. package/components/Appbar/types.ts +19 -0
  22. package/components/Appbar/utils.ts +127 -0
  23. package/components/Avatar/Avatar.tsx +189 -0
  24. package/components/Avatar/index.tsx +11 -0
  25. package/components/Avatar/utils.ts +35 -0
  26. package/components/Backdrop/Backdrop.tsx +18 -0
  27. package/components/Backdrop/index.tsx +11 -0
  28. package/components/Backdrop/types.ts +3 -0
  29. package/components/Backdrop/utils.ts +21 -0
  30. package/components/Badge/Badge.tsx +29 -0
  31. package/components/Badge/index.tsx +11 -0
  32. package/components/Badge/utils.ts +38 -0
  33. package/components/Button/Button.tsx +349 -0
  34. package/components/Button/index.tsx +11 -0
  35. package/components/Button/types.ts +5 -0
  36. package/components/Button/utils.ts +416 -0
  37. package/components/Card/Card.tsx +160 -0
  38. package/components/Card/CardActions.tsx +18 -0
  39. package/components/Card/CardContent.tsx +29 -0
  40. package/components/Card/CardHeader.tsx +31 -0
  41. package/components/Card/CardHeadline.tsx +15 -0
  42. package/components/Card/CardMedia.tsx +36 -0
  43. package/components/Card/CardSubhead.tsx +15 -0
  44. package/components/Card/CardText.tsx +13 -0
  45. package/components/Card/CardTypography.tsx +113 -0
  46. package/components/Card/index.tsx +38 -0
  47. package/components/Card/types.ts +1 -0
  48. package/components/Card/utils.ts +23 -0
  49. package/components/Checkbox/Checkbox.tsx +123 -0
  50. package/components/Checkbox/CheckboxBase.ios.tsx +86 -0
  51. package/components/Checkbox/CheckboxBase.tsx +216 -0
  52. package/components/Checkbox/index.tsx +11 -0
  53. package/components/Checkbox/types.ts +72 -0
  54. package/components/Checkbox/utils.ts +210 -0
  55. package/components/Chip/Chip.tsx +416 -0
  56. package/components/Chip/index.tsx +51 -0
  57. package/components/Chip/utils.ts +100 -0
  58. package/components/DatePickerDocked/DatePickerDocked.tsx +30 -0
  59. package/components/DatePickerDocked/DatePickerDockedHeader.tsx +129 -0
  60. package/components/DatePickerDocked/index.tsx +21 -0
  61. package/components/DatePickerDocked/types.ts +11 -0
  62. package/components/DatePickerDocked/utils.ts +155 -0
  63. package/components/DatePickerInline/AutoSizer.tsx +46 -0
  64. package/components/DatePickerInline/DatePickerContext.tsx +21 -0
  65. package/components/DatePickerInline/DatePickerInline.tsx +82 -0
  66. package/components/DatePickerInline/DatePickerInlineBase.tsx +181 -0
  67. package/components/DatePickerInline/DatePickerInlineHeader.tsx +108 -0
  68. package/components/DatePickerInline/Day.tsx +88 -0
  69. package/components/DatePickerInline/DayName.tsx +17 -0
  70. package/components/DatePickerInline/DayNames.tsx +32 -0
  71. package/components/DatePickerInline/DayRange.tsx +48 -0
  72. package/components/DatePickerInline/HeaderItem.tsx +111 -0
  73. package/components/DatePickerInline/Month.tsx +233 -0
  74. package/components/DatePickerInline/MonthPicker.tsx +174 -0
  75. package/components/DatePickerInline/Swiper.native.tsx +172 -0
  76. package/components/DatePickerInline/Swiper.tsx +172 -0
  77. package/components/DatePickerInline/SwiperUtils.ts +40 -0
  78. package/components/DatePickerInline/Week.tsx +67 -0
  79. package/components/DatePickerInline/YearPicker.tsx +139 -0
  80. package/components/DatePickerInline/dateUtils.tsx +334 -0
  81. package/components/DatePickerInline/index.tsx +41 -0
  82. package/components/DatePickerInline/types.ts +104 -0
  83. package/components/DatePickerInline/utils.ts +367 -0
  84. package/components/DatePickerInput/DatePickerInput.tsx +139 -0
  85. package/components/DatePickerInput/DatePickerInputModal.tsx +48 -0
  86. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +77 -0
  87. package/components/DatePickerInput/DateRangeInput.tsx +88 -0
  88. package/components/DatePickerInput/index.tsx +14 -0
  89. package/components/DatePickerInput/inputUtils.ts +138 -0
  90. package/components/DatePickerInput/types.ts +28 -0
  91. package/components/DatePickerInput/utils.ts +16 -0
  92. package/components/DatePickerModal/AnimatedCrossView.tsx +94 -0
  93. package/components/DatePickerModal/CalendarEdit.tsx +139 -0
  94. package/components/DatePickerModal/DatePickerModal.tsx +85 -0
  95. package/components/DatePickerModal/DatePickerModalContent.tsx +155 -0
  96. package/components/DatePickerModal/DatePickerModalContentHeader.tsx +213 -0
  97. package/components/DatePickerModal/DatePickerModalHeader.tsx +74 -0
  98. package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +13 -0
  99. package/components/DatePickerModal/index.tsx +20 -0
  100. package/components/DatePickerModal/types.ts +92 -0
  101. package/components/DatePickerModal/utils.ts +121 -0
  102. package/components/DateTimePicker/DateTimePicker.tsx +172 -0
  103. package/components/DateTimePicker/index.tsx +14 -0
  104. package/components/DateTimePicker/utils.ts +13 -0
  105. package/components/Dialog/Dialog.tsx +66 -0
  106. package/components/Dialog/DialogActions.tsx +89 -0
  107. package/components/Dialog/DialogContent.tsx +37 -0
  108. package/components/Dialog/DialogIcon.tsx +69 -0
  109. package/components/Dialog/DialogTitle.tsx +68 -0
  110. package/components/Dialog/index.tsx +37 -0
  111. package/components/Dialog/utils.ts +80 -0
  112. package/components/Drawer/Collapsible/DrawerCollapsible.tsx +22 -0
  113. package/components/Drawer/Collapsible/DrawerCollapsibleItem.tsx +38 -0
  114. package/components/Drawer/Collapsible/DrawerCollapsibleItemContent.tsx +16 -0
  115. package/components/Drawer/Collapsible/DrawerCollapsibleItemHeader.tsx +48 -0
  116. package/components/Drawer/Collapsible/index.tsx +23 -0
  117. package/components/Drawer/Collapsible/utils.ts +49 -0
  118. package/components/Drawer/Drawer.tsx +43 -0
  119. package/components/Drawer/DrawerContent.tsx +35 -0
  120. package/components/Drawer/DrawerFooter.tsx +27 -0
  121. package/components/Drawer/DrawerHeader.tsx +27 -0
  122. package/components/Drawer/DrawerItem.tsx +206 -0
  123. package/components/Drawer/DrawerItemGroup.tsx +82 -0
  124. package/components/Drawer/index.tsx +47 -0
  125. package/components/Drawer/types.ts +3 -0
  126. package/components/Drawer/utils.ts +8 -0
  127. package/components/ElementGroup/ElementGroup.tsx +139 -0
  128. package/components/ElementGroup/index.tsx +11 -0
  129. package/components/ElementGroup/utils.ts +25 -0
  130. package/components/FAB/FAB.tsx +176 -0
  131. package/components/FAB/index.tsx +12 -0
  132. package/components/FAB/types.ts +1 -0
  133. package/components/FAB/utils.ts +221 -0
  134. package/components/FilePicker/FilePicker.tsx +133 -0
  135. package/components/FilePicker/index.tsx +11 -0
  136. package/components/FilePicker/utils.ts +13 -0
  137. package/components/HelperText/HelperText.tsx +139 -0
  138. package/components/HelperText/index.tsx +11 -0
  139. package/components/HelperText/utils.ts +29 -0
  140. package/components/HorizontalDivider/HorizontalDivider.tsx +101 -0
  141. package/components/HorizontalDivider/index.tsx +13 -0
  142. package/components/Icon/CrossFadeIcon.tsx +116 -0
  143. package/components/Icon/Icon.tsx +41 -0
  144. package/components/Icon/iconFactory.tsx +23 -0
  145. package/components/Icon/index.tsx +11 -0
  146. package/components/Icon/types.ts +35 -0
  147. package/components/IconButton/IconButton.tsx +218 -0
  148. package/components/IconButton/index.tsx +11 -0
  149. package/components/IconButton/types.ts +1 -0
  150. package/components/IconButton/utils.ts +325 -0
  151. package/components/If/index.tsx +13 -0
  152. package/components/InputAddon/InputAddon.tsx +27 -0
  153. package/components/InputAddon/index.tsx +11 -0
  154. package/components/InputAddon/utils.ts +33 -0
  155. package/components/Link/Link.tsx +48 -0
  156. package/components/Link/index.tsx +11 -0
  157. package/components/Link/utils.ts +37 -0
  158. package/components/ListItem/ListItem.tsx +136 -0
  159. package/components/ListItem/ListItemDescription.tsx +25 -0
  160. package/components/ListItem/ListItemTitle.tsx +25 -0
  161. package/components/ListItem/index.tsx +18 -0
  162. package/components/ListItem/utils.ts +113 -0
  163. package/components/Menu/Menu.tsx +69 -0
  164. package/components/Menu/MenuDivider.tsx +13 -0
  165. package/components/Menu/MenuItem.tsx +128 -0
  166. package/components/Menu/index.tsx +19 -0
  167. package/components/Menu/utils.ts +92 -0
  168. package/components/Modal/Modal.tsx +261 -0
  169. package/components/Modal/index.tsx +11 -0
  170. package/components/Modal/utils.ts +45 -0
  171. package/components/NavigationRail/NavigationRail.tsx +32 -0
  172. package/components/NavigationRail/NavigationRailContent.tsx +25 -0
  173. package/components/NavigationRail/NavigationRailFooter.tsx +18 -0
  174. package/components/NavigationRail/NavigationRailHeader.tsx +18 -0
  175. package/components/NavigationRail/NavigationRailItem.tsx +226 -0
  176. package/components/NavigationRail/index.tsx +35 -0
  177. package/components/NavigationRail/utils.ts +170 -0
  178. package/components/NavigationStack/NavigationStack.tsx +85 -0
  179. package/components/NavigationStack/NavigationStackItem.tsx +60 -0
  180. package/components/NavigationStack/index.tsx +20 -0
  181. package/components/NavigationStack/utils.tsx +16 -0
  182. package/components/Popover/Popover.native.tsx +185 -0
  183. package/components/Popover/Popover.tsx +198 -0
  184. package/components/Popover/common.ts +459 -0
  185. package/components/Popover/index.ts +2 -0
  186. package/components/Portal/Portal.tsx +13 -0
  187. package/components/Portal/index.tsx +12 -0
  188. package/components/RadioButton/RadioButton.tsx +138 -0
  189. package/components/RadioButton/RadioButtonAndroid.tsx +188 -0
  190. package/components/RadioButton/RadioButtonGroup.tsx +98 -0
  191. package/components/RadioButton/RadioButtonIOS.tsx +106 -0
  192. package/components/RadioButton/RadioButtonItem.tsx +232 -0
  193. package/components/RadioButton/index.ts +27 -0
  194. package/components/RadioButton/utils.ts +164 -0
  195. package/components/Rating/Rating.tsx +149 -0
  196. package/components/Rating/RatingItem.tsx +125 -0
  197. package/components/Rating/index.tsx +13 -0
  198. package/components/Rating/utils.ts +38 -0
  199. package/components/Select/Select.tsx +1038 -0
  200. package/components/Select/index.ts +14 -0
  201. package/components/Select/types.ts +115 -0
  202. package/components/StateLayer/StateLayer.tsx +12 -0
  203. package/components/StateLayer/index.tsx +11 -0
  204. package/components/StateLayer/utils.ts +17 -0
  205. package/components/Surface/BackgroundContextWrapper.tsx +27 -0
  206. package/components/Surface/Surface.android.tsx +62 -0
  207. package/components/Surface/Surface.ios.tsx +123 -0
  208. package/components/Surface/Surface.tsx +48 -0
  209. package/components/Surface/index.tsx +12 -0
  210. package/components/Surface/utils.ts +106 -0
  211. package/components/Switch/Switch.ios.tsx +67 -0
  212. package/components/Switch/Switch.tsx +278 -0
  213. package/components/Switch/index.tsx +11 -0
  214. package/components/Switch/utils.ts +283 -0
  215. package/components/Tabs/TabItem.tsx +150 -0
  216. package/components/Tabs/TabLabel.tsx +84 -0
  217. package/components/Tabs/Tabs.tsx +398 -0
  218. package/components/Tabs/index.tsx +21 -0
  219. package/components/Tabs/utils.ts +126 -0
  220. package/components/Text/Text.tsx +23 -0
  221. package/components/Text/index.tsx +2 -0
  222. package/components/Text/textFactory.tsx +33 -0
  223. package/components/TextInput/InputLabel.tsx +181 -0
  224. package/components/TextInput/TextInput.tsx +693 -0
  225. package/components/TextInput/index.tsx +16 -0
  226. package/components/TextInput/types.ts +96 -0
  227. package/components/TextInput/utils.ts +544 -0
  228. package/components/TextInputWithMask/TextInputMask.tsx +57 -0
  229. package/components/TextInputWithMask/index.tsx +11 -0
  230. package/components/TextInputWithMask/utils.ts +56 -0
  231. package/components/TimePicker/AmPmSwitcher.tsx +99 -0
  232. package/components/TimePicker/AnalogClock.tsx +165 -0
  233. package/components/TimePicker/AnalogClockHours.tsx +163 -0
  234. package/components/TimePicker/AnalogClockMinutes.tsx +68 -0
  235. package/components/TimePicker/AnimatedClockSwitcher.tsx +72 -0
  236. package/components/TimePicker/DisplayModeContext.tsx +6 -0
  237. package/components/TimePicker/TimeInput.tsx +112 -0
  238. package/components/TimePicker/TimeInputs.tsx +148 -0
  239. package/components/TimePicker/TimePicker.tsx +130 -0
  240. package/components/TimePicker/index.tsx +19 -0
  241. package/components/TimePicker/timeUtils.ts +159 -0
  242. package/components/TimePicker/utils.ts +285 -0
  243. package/components/TimePickerField/TimePickerField.tsx +152 -0
  244. package/components/TimePickerField/index.tsx +14 -0
  245. package/components/TimePickerField/sanitizeTime.ts +85 -0
  246. package/components/TimePickerField/utils.ts +95 -0
  247. package/components/TimePickerModal/TimePickerModal.tsx +115 -0
  248. package/components/TimePickerModal/index.tsx +14 -0
  249. package/components/TimePickerModal/utils.ts +48 -0
  250. package/components/Tooltip/Tooltip.tsx +137 -0
  251. package/components/Tooltip/TooltipContent.tsx +12 -0
  252. package/components/Tooltip/TooltipTrigger.tsx +94 -0
  253. package/components/Tooltip/index.tsx +20 -0
  254. package/components/Tooltip/utils.ts +21 -0
  255. package/components/TouchableRipple/TouchableRipple.native.tsx +105 -0
  256. package/components/TouchableRipple/TouchableRipple.tsx +286 -0
  257. package/components/TouchableRipple/index.tsx +14 -0
  258. package/components/TouchableRipple/utils.ts +15 -0
  259. package/components/VerticalDivider/VerticalDivider.tsx +99 -0
  260. package/components/VerticalDivider/index.tsx +13 -0
  261. package/context-bridge/index.tsx +87 -0
  262. package/core/componentsRegistry.ts +164 -0
  263. package/core/index.tsx +2 -0
  264. package/fast-context/index.tsx +190 -0
  265. package/hocs/index.tsx +5 -0
  266. package/hocs/typedMemo.tsx +5 -0
  267. package/hocs/withKeyboardAccessibility.tsx +231 -0
  268. package/hocs/withPortal.tsx +16 -0
  269. package/hooks/createPsuedoHook.tsx +50 -0
  270. package/hooks/index.tsx +29 -0
  271. package/hooks/useActionState.native.tsx +22 -0
  272. package/hooks/useActionState.tsx +34 -0
  273. package/hooks/useActive.tsx +5 -0
  274. package/hooks/useBreakpoints.tsx +7 -0
  275. package/hooks/useColorMode.tsx +17 -0
  276. package/hooks/useContrastColor.ts +15 -0
  277. package/hooks/useControlledValue.tsx +68 -0
  278. package/hooks/useFilePicker.tsx +48 -0
  279. package/hooks/useFocus.tsx +5 -0
  280. package/hooks/useHandleNumberFormat.tsx +106 -0
  281. package/hooks/useHover.tsx +5 -0
  282. package/hooks/useKeyboardDismissable.ts +66 -0
  283. package/hooks/useLatest.tsx +9 -0
  284. package/hooks/useMediaQuery.tsx +64 -0
  285. package/hooks/useMergedRefs.ts +14 -0
  286. package/hooks/usePrevious.ts +13 -0
  287. package/hooks/useQueryFilter.tsx +35 -0
  288. package/hooks/useSearchable.tsx +74 -0
  289. package/hooks/useSubcomponents.tsx +59 -0
  290. package/hooks/useTheme.ts +3 -0
  291. package/hooks/useToggle.tsx +24 -0
  292. package/package.json +114 -0
  293. package/shortcuts-manager/EventsManager.tsx +121 -0
  294. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.native.tsx +9 -0
  295. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +58 -0
  296. package/shortcuts-manager/ShortcutsManager/index.tsx +2 -0
  297. package/shortcuts-manager/ShortcutsManager/utils.tsx +30 -0
  298. package/shortcuts-manager/index.tsx +6 -0
  299. package/shortcuts-manager/types.ts +24 -0
  300. package/shortcuts-manager/useIsKeyPressed/index.tsx +1 -0
  301. package/shortcuts-manager/useIsKeyPressed/useIsKeyPress.tsx +9 -0
  302. package/shortcuts-manager/useSetScopes/index.tsx +1 -0
  303. package/shortcuts-manager/useSetScopes/useSetScopes.native.tsx +9 -0
  304. package/shortcuts-manager/useSetScopes/useSetScopes.tsx +25 -0
  305. package/shortcuts-manager/useShortcut/index.tsx +2 -0
  306. package/shortcuts-manager/useShortcut/types.ts +3 -0
  307. package/shortcuts-manager/useShortcut/useShortcut.native.tsx +9 -0
  308. package/shortcuts-manager/useShortcut/useShortcut.tsx +61 -0
  309. package/shortcuts-manager/utils.ts +105 -0
  310. package/styles/index.ts +4 -0
  311. package/styles/overlay.ts +69 -0
  312. package/styles/shadow.ts +21 -0
  313. package/styles/themes/DarkTheme.tsx +98 -0
  314. package/styles/themes/LightTheme.tsx +212 -0
  315. package/styles/themes/tokens.ts +248 -0
  316. package/styles/utils.ts +11 -0
  317. package/types/index.ts +129 -0
  318. package/types/theme.ts +159 -0
  319. package/utils/DocumentPicker/documentPicker.native.ts +10 -0
  320. package/utils/DocumentPicker/documentPicker.ts +76 -0
  321. package/utils/DocumentPicker/index.ts +2 -0
  322. package/utils/DocumentPicker/types.ts +28 -0
  323. package/utils/addEventListener.tsx +51 -0
  324. package/utils/backgroundContext.ts +9 -0
  325. package/utils/color.ts +22 -0
  326. package/utils/compare/index.ts +54 -0
  327. package/utils/composeEventHandlers.ts +9 -0
  328. package/utils/createNumberMask/createNumberMask.ts +98 -0
  329. package/utils/createNumberMask/index.ts +5 -0
  330. package/utils/createSyntheticEvent.ts +31 -0
  331. package/utils/date-fns.ts +7 -0
  332. package/utils/dateTimePicker.ts +5 -0
  333. package/utils/escapeRegex.ts +9 -0
  334. package/utils/extractTextStyles.ts +52 -0
  335. package/utils/formatNumberWithMask/formatNumberWithMask.ts +26 -0
  336. package/utils/formatNumberWithMask/formatWithMask.ts +119 -0
  337. package/utils/formatNumberWithMask/index.ts +6 -0
  338. package/utils/getCursorStyle/getCursorStyle.native.ts +1 -0
  339. package/utils/getCursorStyle/getCursorStyle.ts +1 -0
  340. package/utils/getCursorStyle/index.ts +1 -0
  341. package/utils/getOS/getOS.native.ts +7 -0
  342. package/utils/getOS/getOS.ts +24 -0
  343. package/utils/getOS/index.ts +1 -0
  344. package/utils/getyearRange.ts +5 -0
  345. package/utils/index.ts +20 -0
  346. package/utils/lodash.ts +50 -0
  347. package/utils/mergeRefs.ts +13 -0
  348. package/utils/normalizeBorderRadiuses.ts +24 -0
  349. package/utils/normalizeSpacings.ts +110 -0
  350. package/utils/normalizeToNumberString/index.ts +4 -0
  351. package/utils/normalizeToNumberString/normalizeToNumberString.ts +48 -0
  352. package/utils/repository.ts +103 -0
  353. package/utils/resolveColorMode.ts +9 -0
  354. package/utils/resolveStateVariant.ts +26 -0
  355. package/utils/tokenStylesParser.ts +7 -0
@@ -0,0 +1,68 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+
3
+ type ReturnType<T> = [T, (value: T, ...args: any[]) => void];
4
+
5
+ type Args<T> = {
6
+ value?: T;
7
+ defaultValue?: T;
8
+ onChange?: (value: T, ...args: any[]) => any;
9
+ disabled?: boolean;
10
+ manipulateValue?: (value: T | undefined, prevValue: T | undefined) => T;
11
+ };
12
+
13
+ const defaultManipulateValue = (val: any) => val;
14
+
15
+ const useControlledValue = <T,>({
16
+ value: valueProp,
17
+ defaultValue,
18
+ disabled = false,
19
+ onChange,
20
+ manipulateValue = defaultManipulateValue,
21
+ }: Args<T>): ReturnType<T> => {
22
+ const value = useMemo(
23
+ () =>
24
+ valueProp !== undefined
25
+ ? manipulateValue(valueProp, undefined)
26
+ : manipulateValue(defaultValue, undefined),
27
+ [defaultValue, manipulateValue, valueProp],
28
+ );
29
+
30
+ const hasWarnedRef = useRef(false);
31
+
32
+ const isUncontrolled = useRef(valueProp).current === undefined;
33
+ const [uncontrolledValue, setValue] = useState(value);
34
+
35
+ const updateValue = useCallback(
36
+ (val: T, ...rest: any[]) => {
37
+ if (disabled) return;
38
+
39
+ if (isUncontrolled) {
40
+ setValue(manipulateValue(val, uncontrolledValue));
41
+ }
42
+
43
+ onChange?.(
44
+ manipulateValue(val, isUncontrolled ? uncontrolledValue : valueProp),
45
+ ...rest,
46
+ );
47
+ },
48
+ [disabled, isUncontrolled, manipulateValue, onChange, uncontrolledValue, valueProp],
49
+ );
50
+
51
+ useEffect(() => {
52
+ if (hasWarnedRef.current) return;
53
+ hasWarnedRef.current = true;
54
+
55
+ if (valueProp !== undefined && isUncontrolled) {
56
+ console.warn(
57
+ 'Trying to change the value from uncontrolled to controlled can lead to inconsistencies',
58
+ );
59
+ }
60
+ }, [isUncontrolled, valueProp]);
61
+
62
+ return useMemo(
63
+ () => [isUncontrolled ? uncontrolledValue : value, updateValue],
64
+ [isUncontrolled, uncontrolledValue, updateValue, value],
65
+ );
66
+ };
67
+
68
+ export default useControlledValue;
@@ -0,0 +1,48 @@
1
+ import { useCallback } from 'react';
2
+
3
+ import {
4
+ DocumentPicker,
5
+ type DocumentPickerOptions,
6
+ type DocumentResult,
7
+ } from '../utils/DocumentPicker';
8
+ import { isNil, omitBy } from '../utils/lodash';
9
+
10
+ export const useFilePicker = ({
11
+ multiple,
12
+ onCancel,
13
+ onError,
14
+ ...options
15
+ }: DocumentPickerOptions) => {
16
+ const openFilePicker = useCallback(
17
+ async (callback: (response: DocumentResult | DocumentResult[]) => void): Promise<void> => {
18
+ const omittedOptions = omitBy(options, isNil);
19
+
20
+ try {
21
+ let response;
22
+
23
+ if (multiple) {
24
+ response = await DocumentPicker.pickMultiple(omittedOptions);
25
+ } else {
26
+ response = await DocumentPicker.pickSingle(omittedOptions);
27
+ }
28
+
29
+ callback?.(response);
30
+ } catch (e: any) {
31
+ // eslint-disable-next-line no-console
32
+ console.log('FilePicker Error', e, e?.code);
33
+
34
+ if (e?.code === 'DOCUMENT_PICKER_CANCELED.') {
35
+ onCancel?.();
36
+ return;
37
+ }
38
+ // It might result in an error.
39
+ onError?.(e);
40
+ }
41
+ },
42
+ [multiple, onCancel, onError, options],
43
+ );
44
+
45
+ return { openFilePicker };
46
+ };
47
+
48
+ export default useFilePicker;
@@ -0,0 +1,5 @@
1
+ import createPseudoHook from './createPsuedoHook';
2
+
3
+ export const useFocus = createPseudoHook({
4
+ events: ['focus', 'blur'],
5
+ });
@@ -0,0 +1,106 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import type { NativeSyntheticEvent, TextInputFocusEventData } from 'react-native';
3
+
4
+ import { formatNumberWithMask, normalizeToNumberString } from '../utils';
5
+ import { isNil } from '../utils/lodash';
6
+ import usePrevious from './usePrevious';
7
+
8
+ export type NumberMaskConfig = {
9
+ prefix?: string;
10
+ suffix?: string;
11
+ delimiter?: string;
12
+ separator?: string;
13
+ precision?: number;
14
+ allowNegative?: boolean;
15
+ };
16
+
17
+ type DefaultPropsT = { [key: string]: any };
18
+
19
+ export type UseHandleNumberFormatProps<T extends DefaultPropsT = DefaultPropsT> = T & {
20
+ value: number | null;
21
+ onChangeText: (newValue: number | null) => void;
22
+ config?: NumberMaskConfig;
23
+ onBlur?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void;
24
+ onFocus?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void;
25
+ formatInitialValue?: boolean;
26
+ };
27
+
28
+ const useHandleNumberFormat = <T extends DefaultPropsT = DefaultPropsT>({
29
+ value: valueProp,
30
+ onChangeText: onChangeTextProp,
31
+ config,
32
+ onFocus: onFocusProp,
33
+ onBlur: onBlurProp,
34
+ formatInitialValue = true,
35
+ ...rest
36
+ }: UseHandleNumberFormatProps<T>) => {
37
+ const [displayValue, setDisplayValue] = useState(() =>
38
+ !isNil(valueProp)
39
+ ? formatInitialValue
40
+ ? `${formatNumberWithMask({ number: valueProp, ...config })}`
41
+ : `${valueProp}`
42
+ : '',
43
+ );
44
+
45
+ const [isBlur, setIsBlur] = useState(true);
46
+
47
+ const firstRenderRef = useRef(true);
48
+
49
+ const isFirstRender = usePrevious(firstRenderRef.current);
50
+
51
+ const onChangeText = useCallback(
52
+ (text: string) => {
53
+ const normalizedNumberString = normalizeToNumberString({ text, ...config });
54
+
55
+ onChangeTextProp(
56
+ normalizedNumberString === ''
57
+ ? null
58
+ : +normalizeToNumberString({ text, ...config }),
59
+ );
60
+ setDisplayValue(text);
61
+ },
62
+ [config, onChangeTextProp],
63
+ );
64
+
65
+ const onBlur = useCallback(
66
+ (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
67
+ onBlurProp?.(e);
68
+
69
+ setDisplayValue(`${formatNumberWithMask({ number: valueProp, ...config })}`);
70
+ setIsBlur(true);
71
+ },
72
+ [config, onBlurProp, valueProp],
73
+ );
74
+
75
+ const onFocus = useCallback(
76
+ (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
77
+ onFocusProp?.(e);
78
+
79
+ setIsBlur(false);
80
+ },
81
+ [onFocusProp],
82
+ );
83
+
84
+ useEffect(() => {
85
+ firstRenderRef.current = false;
86
+ });
87
+
88
+ useEffect(() => {
89
+ if (!isBlur || isFirstRender.current) return;
90
+
91
+ setDisplayValue(`${formatNumberWithMask({ number: valueProp, ...config })}`);
92
+ }, [config, formatInitialValue, isBlur, isFirstRender, valueProp]);
93
+
94
+ return useMemo(
95
+ () => ({
96
+ value: displayValue,
97
+ onChangeText: onChangeText,
98
+ onFocus,
99
+ onBlur,
100
+ ...rest,
101
+ }),
102
+ [displayValue, onBlur, onChangeText, onFocus, rest],
103
+ );
104
+ };
105
+
106
+ export default useHandleNumberFormat;
@@ -0,0 +1,5 @@
1
+ import createPseudoHook from './createPsuedoHook';
2
+
3
+ export const useHover = createPseudoHook({
4
+ events: ['mouseenter', 'mouseleave'],
5
+ });
@@ -0,0 +1,66 @@
1
+ import React, { useEffect } from 'react';
2
+ import { BackHandler, Platform } from 'react-native';
3
+
4
+ type TKeyboardDismissableParams = {
5
+ enabled?: boolean;
6
+ callback: Function;
7
+ };
8
+
9
+ type TBackHandler = TKeyboardDismissableParams;
10
+
11
+ let keyboardDismissHandlers: Array<Function> = [];
12
+ export const keyboardDismissHandlerManager = {
13
+ push: (handler: Function) => {
14
+ keyboardDismissHandlers.push(handler);
15
+ return () => {
16
+ keyboardDismissHandlers = keyboardDismissHandlers.filter(h => h !== handler);
17
+ };
18
+ },
19
+
20
+ length: () => keyboardDismissHandlers.length,
21
+
22
+ pop: () => {
23
+ return keyboardDismissHandlers.pop();
24
+ },
25
+ };
26
+
27
+ /**
28
+ * Handles attaching callback for Escape key listener on web and Back button listener on Android
29
+ */
30
+ export const useKeyboardDismissable = ({ enabled, callback }: TKeyboardDismissableParams) => {
31
+ React.useEffect(() => {
32
+ let cleanupFn = () => {};
33
+ if (enabled) {
34
+ cleanupFn = keyboardDismissHandlerManager.push(callback);
35
+ } else {
36
+ cleanupFn();
37
+ }
38
+ return () => {
39
+ cleanupFn();
40
+ };
41
+ }, [enabled, callback]);
42
+
43
+ useBackHandler({ enabled, callback });
44
+ };
45
+
46
+ /**
47
+ * Handles attaching callback for Escape key listener on web and Back button listener on Android
48
+ */
49
+ export function useBackHandler({ enabled, callback }: TBackHandler) {
50
+ useEffect(() => {
51
+ if (Platform.OS === 'web') return;
52
+
53
+ const backHandler = () => {
54
+ callback();
55
+ return true;
56
+ };
57
+
58
+ if (enabled) {
59
+ BackHandler.addEventListener('hardwareBackPress', backHandler);
60
+ } else {
61
+ // BackHandler.removeEventListener('hardwareBackPress', backHandler);
62
+ }
63
+
64
+ // return () => BackHandler.removeEventListener('hardwareBackPress', backHandler);
65
+ }, [enabled, callback]);
66
+ }
@@ -0,0 +1,9 @@
1
+ import { useRef } from 'react';
2
+
3
+ const useLatest = <T,>(value: T) => {
4
+ const ref = useRef(value);
5
+ ref.current = value;
6
+ return ref;
7
+ };
8
+
9
+ export default useLatest;
@@ -0,0 +1,64 @@
1
+ import { useMemo } from 'react';
2
+ import { useWindowDimensions } from 'react-native';
3
+
4
+ import { isNil } from '../utils/lodash';
5
+
6
+ type Query = {
7
+ maxWidth?: number;
8
+ minWidth?: number;
9
+ maxHeight?: number;
10
+ minHeight?: number;
11
+ orientation?: 'portrait' | 'landscape';
12
+ };
13
+
14
+ export function useMediaQuery(query: Query) {
15
+ const dims = useWindowDimensions();
16
+ const height = dims?.height;
17
+ const width = dims?.width;
18
+
19
+ return useMemo(() => queryResolver(query, width, height), [height, query, width]);
20
+ }
21
+
22
+ function queryResolver(query: Query, width?: number, height?: number) {
23
+ for (const queryKey in query) {
24
+ // if the func returns false, stop the loop and return false
25
+ if (!calculateQuery(queryKey, query[queryKey as keyof Query], height, width)) {
26
+ return false;
27
+ }
28
+ }
29
+ return true;
30
+ }
31
+
32
+ function calculateQuery(key: string, val?: number | string, height?: number, width?: number) {
33
+ let returnVal: boolean;
34
+ if (isNil(width) || isNil(height) || isNil(val)) {
35
+ return false;
36
+ }
37
+
38
+ switch (key) {
39
+ case 'maxWidth':
40
+ returnVal = width <= +val;
41
+ break;
42
+ case 'minWidth':
43
+ returnVal = width >= +val;
44
+ break;
45
+ case 'maxHeight':
46
+ returnVal = height <= +val;
47
+ break;
48
+ case 'minHeight':
49
+ returnVal = height >= +val;
50
+ break;
51
+ case 'orientation':
52
+ if (width > height) {
53
+ returnVal = val === 'landscape';
54
+ } else {
55
+ returnVal = val === 'portrait';
56
+ }
57
+ break;
58
+ default:
59
+ returnVal = false;
60
+ break;
61
+ }
62
+
63
+ return returnVal;
64
+ }
@@ -0,0 +1,14 @@
1
+ import { useCallback } from 'react';
2
+
3
+ import { mergeRefs } from '../utils';
4
+ import useLatest from './useLatest';
5
+
6
+ export const useMergedRefs: typeof mergeRefs = refs => {
7
+ const latestRefs = useLatest(refs);
8
+ return useCallback(
9
+ value => {
10
+ mergeRefs(latestRefs.current)(value);
11
+ },
12
+ [latestRefs],
13
+ );
14
+ };
@@ -0,0 +1,13 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ const usePrevious = <T>(value: T) => {
4
+ const ref = useRef<T>(value);
5
+
6
+ useEffect(() => {
7
+ ref.current = value;
8
+ }, [value]);
9
+
10
+ return ref;
11
+ };
12
+
13
+ export default usePrevious;
@@ -0,0 +1,35 @@
1
+ import { useMemo, useState } from 'react';
2
+
3
+ type DefaultItem = { id: string | number; [key: string]: any };
4
+
5
+ export type UseQueryFilterProps<TItem extends DefaultItem = DefaultItem> = {
6
+ records: TItem[];
7
+ filterKey?: string;
8
+ };
9
+
10
+ type ReturnType<TItem extends DefaultItem = DefaultItem> = [
11
+ records: TItem[],
12
+ query: string,
13
+ onChange: (value: string) => void,
14
+ ];
15
+
16
+ export const useQueryFilter = <TItem extends DefaultItem = DefaultItem>({
17
+ records: _records,
18
+ filterKey = 'label',
19
+ }: UseQueryFilterProps<TItem>): ReturnType<TItem> => {
20
+ const [query, setQuery] = useState('');
21
+
22
+ const records = useMemo(
23
+ // TODO: match all unicode character with regex
24
+ () =>
25
+ _records.filter(item => {
26
+ const value = item[filterKey];
27
+ if (typeof value !== 'string') return !query;
28
+
29
+ return value.toLowerCase().includes(query.toLowerCase());
30
+ }),
31
+ [_records, filterKey, query],
32
+ );
33
+
34
+ return useMemo(() => [records, query, setQuery], [records, query, setQuery]);
35
+ };
@@ -0,0 +1,74 @@
1
+ import { type ReactElement, useCallback, useMemo } from 'react';
2
+
3
+ import { IconButton } from '../components/IconButton';
4
+ import {
5
+ TextInput,
6
+ type TextInputElementProps,
7
+ type TextInputProps,
8
+ } from '../components/TextInput';
9
+ import useControlledValue from './useControlledValue';
10
+
11
+ export interface UseSearchableProps {
12
+ searchable?: boolean;
13
+ onQueryChange?: (search: string) => void;
14
+ query?: string;
15
+ searchInputProps?: Omit<TextInputProps, 'value' | 'onChangeText'>;
16
+ }
17
+
18
+ const useSearchInputProps = (props?: Partial<TextInputProps>) => {
19
+ const onChange = props?.onChangeText;
20
+ const onPressClear = useCallback(() => {
21
+ onChange?.('');
22
+ }, [onChange]);
23
+
24
+ const right = useCallback(
25
+ ({ color, forceFocus }: TextInputElementProps) => (
26
+ <IconButton
27
+ name={props?.value ? 'close-circle-outline' : 'magnify'}
28
+ onPress={props?.value ? onPressClear : forceFocus}
29
+ color={color}
30
+ />
31
+ ),
32
+ [onPressClear, props?.value],
33
+ );
34
+
35
+ return useMemo(
36
+ () => (props?.right === undefined ? props : { right, ...props }),
37
+ [props, right],
38
+ );
39
+ };
40
+
41
+ const useSearchable = ({
42
+ searchable,
43
+ onQueryChange,
44
+ query,
45
+ searchInputProps,
46
+ }: UseSearchableProps = {}): ReactElement<TextInputProps> | null => {
47
+ const [value, onValueChange] = useControlledValue({
48
+ value: query || '',
49
+ defaultValue: '', // to disable the useControlledValue inside TextInput
50
+ onChange: onQueryChange,
51
+ disabled: !searchable,
52
+ });
53
+
54
+ const props = useSearchInputProps(
55
+ useMemo(
56
+ () => ({
57
+ ...searchInputProps,
58
+ value,
59
+ onChangeText: onValueChange,
60
+ }),
61
+ [onValueChange, searchInputProps, value],
62
+ ),
63
+ );
64
+
65
+ return useMemo(() => {
66
+ if (!searchable || !onQueryChange) return null;
67
+
68
+ return <TextInput {...props} />;
69
+ }, [onQueryChange, props, searchable]);
70
+ };
71
+
72
+ export { useSearchInputProps };
73
+
74
+ export default useSearchable;
@@ -0,0 +1,59 @@
1
+ import type { ReactElement } from 'react';
2
+ import { Children, type FC, isValidElement, useMemo } from 'react';
3
+
4
+ export type UseSubcomponentsProps<T extends string> = {
5
+ children: ReactElement | ReactElement[];
6
+ /**
7
+ * array of displayName as string
8
+ * */
9
+ allowedChildren: T[];
10
+ };
11
+
12
+ /**
13
+ * This will return an object with the displayNames as the property names
14
+ * eg. allowedChildren: ['Drawer_Header', 'Drawer_Content', 'Drawer_Footer', 'DrawerItem'];
15
+ *
16
+ * return value -> {
17
+ * Drawer_Header: [],
18
+ * Drawer_Content: [],
19
+ * Drawer_Footer: [],
20
+ * DrawerItem: [],
21
+ * }
22
+ * */
23
+ const useSubcomponents = <T extends string = string>({
24
+ children,
25
+ allowedChildren,
26
+ }: UseSubcomponentsProps<T>) => {
27
+ return useMemo(() => {
28
+ // this will create properties with default empty array values even if they don't exist in the children
29
+ const defaultContext = allowedChildren.reduce((context, childName) => {
30
+ return {
31
+ ...context,
32
+ [childName]: [],
33
+ };
34
+ }, {}) as {
35
+ [key in T]: ReactElement[];
36
+ };
37
+
38
+ return Children.map(children, child => child).reduce((context, child) => {
39
+ if (!isValidElement(child)) return context;
40
+
41
+ if (
42
+ !allowedChildren.find(name => name === ((child.type as FC).displayName as string))
43
+ ) {
44
+ return context;
45
+ }
46
+
47
+ const name = (child.type as FC).displayName as T;
48
+
49
+ if (!name) return context;
50
+
51
+ return {
52
+ ...context,
53
+ [name]: [...context[name], child],
54
+ };
55
+ }, defaultContext);
56
+ }, [allowedChildren, children]);
57
+ };
58
+
59
+ export default useSubcomponents;
@@ -0,0 +1,3 @@
1
+ import { useUnistyles } from 'react-native-unistyles';
2
+
3
+ export const useTheme = () => useUnistyles().theme;
@@ -0,0 +1,24 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+
3
+ const useToggle = (initialState = false) => {
4
+ const [state, setState] = useState<boolean>(initialState);
5
+
6
+ const toggle = useCallback(() => setState(prevState => !prevState), []);
7
+
8
+ const handleClose = useCallback(() => setState(false), [setState]);
9
+
10
+ const handleOpen = useCallback(() => setState(true), [setState]);
11
+
12
+ return useMemo(
13
+ () => ({
14
+ state,
15
+ onToggle: toggle,
16
+ setState,
17
+ handleOpen,
18
+ handleClose,
19
+ }),
20
+ [state, toggle, setState, handleOpen, handleClose],
21
+ );
22
+ };
23
+
24
+ export default useToggle;