@utilitywarehouse/hearth-react-native 0.3.1 → 0.4.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 (274) hide show
  1. package/.storybook/preview.tsx +3 -0
  2. package/.turbo/turbo-build.log +1 -1
  3. package/.turbo/turbo-lint.log +1 -1
  4. package/CHANGELOG.md +16 -0
  5. package/build/components/CurrencyInput/CurrencyInput.js +1 -1
  6. package/build/components/DatePicker/DatePicker.context.d.ts +19 -0
  7. package/build/components/DatePicker/DatePicker.context.js +3 -0
  8. package/build/components/DatePicker/DatePicker.d.ts +19 -0
  9. package/build/components/DatePicker/DatePicker.js +479 -0
  10. package/build/components/DatePicker/DatePicker.props.d.ts +125 -0
  11. package/build/components/DatePicker/DatePicker.props.js +1 -0
  12. package/build/components/DatePicker/DatePickerCalendar.d.ts +2 -0
  13. package/build/components/DatePicker/DatePickerCalendar.js +28 -0
  14. package/build/components/DatePicker/DatePickerDay.d.ts +11 -0
  15. package/build/components/DatePicker/DatePickerDay.js +242 -0
  16. package/build/components/DatePicker/DatePickerDays.d.ts +2 -0
  17. package/build/components/DatePicker/DatePickerDays.js +157 -0
  18. package/build/components/DatePicker/DatePickerFooter.d.ts +2 -0
  19. package/build/components/DatePicker/DatePickerFooter.js +23 -0
  20. package/build/components/DatePicker/DatePickerHeader/DatePickerHeader.props.d.ts +8 -0
  21. package/build/components/DatePicker/DatePickerHeader/DatePickerHeader.props.js +1 -0
  22. package/build/components/DatePicker/DatePickerHeader/DatePickerMonthButton.d.ts +2 -0
  23. package/build/components/DatePicker/DatePickerHeader/DatePickerMonthButton.js +14 -0
  24. package/build/components/DatePicker/DatePickerHeader/DatePickerNextButton.d.ts +2 -0
  25. package/build/components/DatePicker/DatePickerHeader/DatePickerNextButton.js +32 -0
  26. package/build/components/DatePicker/DatePickerHeader/DatePickerPrevButton.d.ts +2 -0
  27. package/build/components/DatePicker/DatePickerHeader/DatePickerPrevButton.js +32 -0
  28. package/build/components/DatePicker/DatePickerHeader/DatePickerSelectors.d.ts +6 -0
  29. package/build/components/DatePicker/DatePickerHeader/DatePickerSelectors.js +64 -0
  30. package/build/components/DatePicker/DatePickerHeader/DatePickerTimeButton.d.ts +1 -0
  31. package/build/components/DatePicker/DatePickerHeader/DatePickerTimeButton.js +22 -0
  32. package/build/components/DatePicker/DatePickerHeader/DatePickerYearButton.d.ts +2 -0
  33. package/build/components/DatePicker/DatePickerHeader/DatePickerYearButton.js +25 -0
  34. package/build/components/DatePicker/DatePickerHeader/index.d.ts +3 -0
  35. package/build/components/DatePicker/DatePickerHeader/index.js +30 -0
  36. package/build/components/DatePicker/DatePickerMonths.d.ts +2 -0
  37. package/build/components/DatePicker/DatePickerMonths.js +69 -0
  38. package/build/components/DatePicker/DatePickerWeekdays.d.ts +8 -0
  39. package/build/components/DatePicker/DatePickerWeekdays.js +26 -0
  40. package/build/components/DatePicker/DatePickerYears.d.ts +2 -0
  41. package/build/components/DatePicker/DatePickerYears.js +83 -0
  42. package/build/components/DatePicker/TimePicker.d.ts +3 -0
  43. package/build/components/DatePicker/TimePicker.js +84 -0
  44. package/build/components/DatePicker/enums.d.ts +12 -0
  45. package/build/components/DatePicker/enums.js +12 -0
  46. package/build/components/DatePicker/index.d.ts +4 -0
  47. package/build/components/DatePicker/index.js +3 -0
  48. package/build/components/DatePicker/polyfill.d.ts +0 -0
  49. package/build/components/DatePicker/polyfill.js +22 -0
  50. package/build/components/DatePicker/time-picker/animated-math.d.ts +4 -0
  51. package/build/components/DatePicker/time-picker/animated-math.js +19 -0
  52. package/build/components/DatePicker/time-picker/period-native.d.ts +6 -0
  53. package/build/components/DatePicker/time-picker/period-native.js +17 -0
  54. package/build/components/DatePicker/time-picker/period-picker.d.ts +6 -0
  55. package/build/components/DatePicker/time-picker/period-picker.js +10 -0
  56. package/build/components/DatePicker/time-picker/period-web.d.ts +6 -0
  57. package/build/components/DatePicker/time-picker/period-web.js +21 -0
  58. package/build/components/DatePicker/time-picker/wheel-native.d.ts +8 -0
  59. package/build/components/DatePicker/time-picker/wheel-native.js +19 -0
  60. package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +2 -0
  61. package/build/components/DatePicker/time-picker/wheel-picker/index.js +2 -0
  62. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +16 -0
  63. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +97 -0
  64. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +21 -0
  65. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +88 -0
  66. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +23 -0
  67. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +21 -0
  68. package/build/components/DatePicker/time-picker/wheel-web.d.ts +8 -0
  69. package/build/components/DatePicker/time-picker/wheel-web.js +148 -0
  70. package/build/components/DatePicker/time-picker/wheel.d.ts +8 -0
  71. package/build/components/DatePicker/time-picker/wheel.js +10 -0
  72. package/build/components/DatePicker/utils.d.ts +212 -0
  73. package/build/components/DatePicker/utils.js +391 -0
  74. package/build/components/DatePickerInput/DatePickerInput.d.ts +6 -0
  75. package/build/components/DatePickerInput/DatePickerInput.js +126 -0
  76. package/build/components/DatePickerInput/DatePickerInput.props.d.ts +47 -0
  77. package/build/components/DatePickerInput/DatePickerInput.props.js +1 -0
  78. package/build/components/DatePickerInput/DatePickerInputDoneButton.d.ts +8 -0
  79. package/build/components/DatePickerInput/DatePickerInputDoneButton.js +19 -0
  80. package/build/components/DatePickerInput/DatePickerInputDoneButton.web.d.ts +5 -0
  81. package/build/components/DatePickerInput/DatePickerInputDoneButton.web.js +5 -0
  82. package/build/components/DatePickerInput/index.d.ts +2 -0
  83. package/build/components/DatePickerInput/index.js +1 -0
  84. package/build/components/Input/InputField.d.ts +1 -1
  85. package/build/components/Input/InputField.js +1 -1
  86. package/build/components/Input/InputSlot.d.ts +1 -1
  87. package/build/components/Input/InputSlot.js +3 -3
  88. package/build/components/UnstyledIconButton/UnstyledIconButton.js +2 -2
  89. package/build/components/UnstyledIconButton/UnstyledIconButtonRoot.js +1 -1
  90. package/build/components/index.d.ts +2 -0
  91. package/build/components/index.js +2 -0
  92. package/build/core/themes.d.ts +482 -0
  93. package/build/core/themes.js +31 -0
  94. package/build/hooks/index.d.ts +4 -3
  95. package/build/hooks/index.js +4 -3
  96. package/build/hooks/usePrevious.d.ts +1 -0
  97. package/build/hooks/usePrevious.js +8 -0
  98. package/build/hooks/useTheme.d.ts +2 -1
  99. package/build/hooks/useTheme.js +2 -2
  100. package/build/legacyTokens/common/brand.d.ts +16 -0
  101. package/build/legacyTokens/common/brand.js +17 -0
  102. package/build/legacyTokens/common/index.d.ts +8 -0
  103. package/build/legacyTokens/common/index.js +9 -0
  104. package/build/legacyTokens/common/service.d.ts +20 -0
  105. package/build/legacyTokens/common/service.js +21 -0
  106. package/build/legacyTokens/dark/apple.d.ts +28 -0
  107. package/build/legacyTokens/dark/apple.js +29 -0
  108. package/build/legacyTokens/dark/cyan.d.ts +48 -0
  109. package/build/legacyTokens/dark/cyan.js +49 -0
  110. package/build/legacyTokens/dark/gold.d.ts +44 -0
  111. package/build/legacyTokens/dark/gold.js +45 -0
  112. package/build/legacyTokens/dark/grape.d.ts +28 -0
  113. package/build/legacyTokens/dark/grape.js +29 -0
  114. package/build/legacyTokens/dark/green.d.ts +40 -0
  115. package/build/legacyTokens/dark/green.js +41 -0
  116. package/build/legacyTokens/dark/grey.d.ts +60 -0
  117. package/build/legacyTokens/dark/grey.js +61 -0
  118. package/build/legacyTokens/dark/index.d.ts +40 -0
  119. package/build/legacyTokens/dark/index.js +41 -0
  120. package/build/legacyTokens/dark/pink.d.ts +28 -0
  121. package/build/legacyTokens/dark/pink.js +29 -0
  122. package/build/legacyTokens/dark/purple.d.ts +48 -0
  123. package/build/legacyTokens/dark/purple.js +49 -0
  124. package/build/legacyTokens/dark/red.d.ts +40 -0
  125. package/build/legacyTokens/dark/red.js +41 -0
  126. package/build/legacyTokens/dark/rose.d.ts +28 -0
  127. package/build/legacyTokens/dark/rose.js +29 -0
  128. package/build/legacyTokens/index.d.ts +12 -0
  129. package/build/legacyTokens/index.js +13 -0
  130. package/build/legacyTokens/light/apple.d.ts +28 -0
  131. package/build/legacyTokens/light/apple.js +29 -0
  132. package/build/legacyTokens/light/cyan.d.ts +48 -0
  133. package/build/legacyTokens/light/cyan.js +49 -0
  134. package/build/legacyTokens/light/gold.d.ts +44 -0
  135. package/build/legacyTokens/light/gold.js +45 -0
  136. package/build/legacyTokens/light/grape.d.ts +28 -0
  137. package/build/legacyTokens/light/grape.js +29 -0
  138. package/build/legacyTokens/light/green.d.ts +40 -0
  139. package/build/legacyTokens/light/green.js +41 -0
  140. package/build/legacyTokens/light/grey.d.ts +60 -0
  141. package/build/legacyTokens/light/grey.js +61 -0
  142. package/build/legacyTokens/light/index.d.ts +40 -0
  143. package/build/legacyTokens/light/index.js +41 -0
  144. package/build/legacyTokens/light/pink.d.ts +28 -0
  145. package/build/legacyTokens/light/pink.js +29 -0
  146. package/build/legacyTokens/light/purple.d.ts +48 -0
  147. package/build/legacyTokens/light/purple.js +49 -0
  148. package/build/legacyTokens/light/red.d.ts +40 -0
  149. package/build/legacyTokens/light/red.js +41 -0
  150. package/build/legacyTokens/light/rose.d.ts +32 -0
  151. package/build/legacyTokens/light/rose.js +33 -0
  152. package/build/tokens/components/dark/date-picker.d.ts +1 -0
  153. package/build/tokens/components/dark/date-picker.js +1 -0
  154. package/build/tokens/components/dark/illustrations.d.ts +7 -0
  155. package/build/tokens/components/dark/illustrations.js +6 -0
  156. package/build/tokens/components/dark/index.d.ts +1 -0
  157. package/build/tokens/components/dark/index.js +1 -0
  158. package/build/tokens/components/dark/segmented-control.d.ts +2 -2
  159. package/build/tokens/components/dark/segmented-control.js +2 -2
  160. package/build/tokens/components/dark/table.d.ts +3 -0
  161. package/build/tokens/components/dark/table.js +3 -0
  162. package/build/tokens/components/light/date-picker.d.ts +1 -0
  163. package/build/tokens/components/light/date-picker.js +1 -0
  164. package/build/tokens/components/light/illustrations.d.ts +7 -0
  165. package/build/tokens/components/light/illustrations.js +6 -0
  166. package/build/tokens/components/light/index.d.ts +1 -0
  167. package/build/tokens/components/light/index.js +1 -0
  168. package/build/tokens/components/light/segmented-control.d.ts +2 -2
  169. package/build/tokens/components/light/segmented-control.js +2 -2
  170. package/build/tokens/components/light/table.d.ts +3 -0
  171. package/build/tokens/components/light/table.js +3 -0
  172. package/build/utils/index.d.ts +1 -0
  173. package/build/utils/index.js +1 -0
  174. package/build/utils/isEqual.d.ts +2 -0
  175. package/build/utils/isEqual.js +29 -0
  176. package/chromatic.config.json +6 -0
  177. package/docs/components/AllComponents.web.tsx +43 -1
  178. package/docs/components/ViewWrap.tsx +32 -0
  179. package/docs/components/index.ts +1 -0
  180. package/docs/getting-started.mdx +6 -6
  181. package/package.json +11 -8
  182. package/src/components/CurrencyInput/CurrencyInput.tsx +2 -1
  183. package/src/components/DatePicker/DatePicker.context.ts +23 -0
  184. package/src/components/DatePicker/DatePicker.docs.mdx +239 -0
  185. package/src/components/DatePicker/DatePicker.props.ts +139 -0
  186. package/src/components/DatePicker/DatePicker.stories.tsx +98 -0
  187. package/src/components/DatePicker/DatePicker.tsx +669 -0
  188. package/src/components/DatePicker/DatePickerCalendar.tsx +41 -0
  189. package/src/components/DatePicker/DatePickerDay.tsx +302 -0
  190. package/src/components/DatePicker/DatePickerDays.tsx +241 -0
  191. package/src/components/DatePicker/DatePickerFooter.tsx +35 -0
  192. package/src/components/DatePicker/DatePickerHeader/DatePickerHeader.props.ts +10 -0
  193. package/src/components/DatePicker/DatePickerHeader/DatePickerMonthButton.tsx +29 -0
  194. package/src/components/DatePicker/DatePickerHeader/DatePickerNextButton.tsx +46 -0
  195. package/src/components/DatePicker/DatePickerHeader/DatePickerPrevButton.tsx +46 -0
  196. package/src/components/DatePicker/DatePickerHeader/DatePickerSelectors.tsx +96 -0
  197. package/src/components/DatePicker/DatePickerHeader/DatePickerTimeButton.tsx +48 -0
  198. package/src/components/DatePicker/DatePickerHeader/DatePickerYearButton.tsx +50 -0
  199. package/src/components/DatePicker/DatePickerHeader/index.tsx +64 -0
  200. package/src/components/DatePicker/DatePickerMonths.tsx +101 -0
  201. package/src/components/DatePicker/DatePickerWeekdays.tsx +49 -0
  202. package/src/components/DatePicker/DatePickerYears.tsx +119 -0
  203. package/src/components/DatePicker/TimePicker.tsx +141 -0
  204. package/src/components/DatePicker/enums.ts +14 -0
  205. package/src/components/DatePicker/index.ts +13 -0
  206. package/src/components/DatePicker/polyfill.ts +21 -0
  207. package/src/components/DatePicker/time-picker/animated-math.ts +33 -0
  208. package/src/components/DatePicker/time-picker/period-native.tsx +34 -0
  209. package/src/components/DatePicker/time-picker/period-picker.tsx +16 -0
  210. package/src/components/DatePicker/time-picker/period-web.tsx +36 -0
  211. package/src/components/DatePicker/time-picker/wheel-native.tsx +37 -0
  212. package/src/components/DatePicker/time-picker/wheel-picker/index.ts +3 -0
  213. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.tsx +132 -0
  214. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.ts +22 -0
  215. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.tsx +200 -0
  216. package/src/components/DatePicker/time-picker/wheel-web.tsx +181 -0
  217. package/src/components/DatePicker/time-picker/wheel.tsx +18 -0
  218. package/src/components/DatePicker/utils.ts +549 -0
  219. package/src/components/DatePickerInput/DatePickerInput.docs.mdx +237 -0
  220. package/src/components/DatePickerInput/DatePickerInput.props.ts +50 -0
  221. package/src/components/DatePickerInput/DatePickerInput.stories.tsx +178 -0
  222. package/src/components/DatePickerInput/DatePickerInput.tsx +265 -0
  223. package/src/components/DatePickerInput/DatePickerInputDoneButton.tsx +42 -0
  224. package/src/components/DatePickerInput/DatePickerInputDoneButton.web.tsx +7 -0
  225. package/src/components/DatePickerInput/index.ts +2 -0
  226. package/src/components/Icon/Icon.stories.tsx +4 -3
  227. package/src/components/Input/InputField.tsx +0 -2
  228. package/src/components/Input/InputSlot.tsx +14 -3
  229. package/src/components/Modal/Modal.stories.tsx +2 -30
  230. package/src/components/UnstyledIconButton/UnstyledIconButton.tsx +14 -2
  231. package/src/components/UnstyledIconButton/UnstyledIconButtonRoot.tsx +7 -3
  232. package/src/components/index.ts +2 -0
  233. package/src/core/themes.ts +31 -0
  234. package/src/hooks/index.ts +4 -3
  235. package/src/hooks/usePrevious.ts +9 -0
  236. package/src/hooks/useTheme.ts +4 -3
  237. package/src/legacyTokens/common/brand.ts +18 -0
  238. package/src/legacyTokens/common/index.ts +10 -0
  239. package/src/legacyTokens/common/service.ts +22 -0
  240. package/src/legacyTokens/dark/apple.ts +30 -0
  241. package/src/legacyTokens/dark/cyan.ts +50 -0
  242. package/src/legacyTokens/dark/gold.ts +46 -0
  243. package/src/legacyTokens/dark/grape.ts +30 -0
  244. package/src/legacyTokens/dark/green.ts +42 -0
  245. package/src/legacyTokens/dark/grey.ts +62 -0
  246. package/src/legacyTokens/dark/index.ts +42 -0
  247. package/src/legacyTokens/dark/pink.ts +30 -0
  248. package/src/legacyTokens/dark/purple.ts +50 -0
  249. package/src/legacyTokens/dark/red.ts +42 -0
  250. package/src/legacyTokens/dark/rose.ts +30 -0
  251. package/src/legacyTokens/index.ts +14 -0
  252. package/src/legacyTokens/light/apple.ts +30 -0
  253. package/src/legacyTokens/light/cyan.ts +50 -0
  254. package/src/legacyTokens/light/gold.ts +46 -0
  255. package/src/legacyTokens/light/grape.ts +30 -0
  256. package/src/legacyTokens/light/green.ts +42 -0
  257. package/src/legacyTokens/light/grey.ts +62 -0
  258. package/src/legacyTokens/light/index.ts +42 -0
  259. package/src/legacyTokens/light/pink.ts +30 -0
  260. package/src/legacyTokens/light/purple.ts +50 -0
  261. package/src/legacyTokens/light/red.ts +42 -0
  262. package/src/legacyTokens/light/rose.ts +34 -0
  263. package/src/tokens/components/dark/date-picker.ts +1 -0
  264. package/src/tokens/components/dark/illustrations.ts +7 -0
  265. package/src/tokens/components/dark/index.ts +1 -0
  266. package/src/tokens/components/dark/segmented-control.ts +2 -2
  267. package/src/tokens/components/dark/table.ts +3 -0
  268. package/src/tokens/components/light/date-picker.ts +1 -0
  269. package/src/tokens/components/light/illustrations.ts +7 -0
  270. package/src/tokens/components/light/index.ts +1 -0
  271. package/src/tokens/components/light/segmented-control.ts +2 -2
  272. package/src/tokens/components/light/table.ts +3 -0
  273. package/src/utils/index.ts +1 -0
  274. package/src/utils/isEqual.ts +30 -0
@@ -0,0 +1,265 @@
1
+ import type { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
2
+ import { CalendarSmallIcon, CloseSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
3
+ import dayjs from 'dayjs';
4
+ import customParseFormat from 'dayjs/plugin/customParseFormat';
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
+ import { Keyboard, Platform, TextInputFocusEvent } from 'react-native';
7
+ import { StyleSheet } from 'react-native-unistyles';
8
+ import { DatePicker } from '../DatePicker';
9
+ import type { DateType } from '../DatePicker/DatePicker.props';
10
+ import { useFormFieldContext } from '../FormField';
11
+ import { Input, InputField, InputSlot } from '../Input';
12
+ import { UnstyledIconButton } from '../UnstyledIconButton';
13
+ import type DatePickerInputProps from './DatePickerInput.props';
14
+ import DatePickerInputDoneButton from './DatePickerInputDoneButton';
15
+
16
+ dayjs.extend(customParseFormat);
17
+
18
+ const DEFAULT_FORMAT = 'DD/MM/YYYY';
19
+
20
+ const maskDefaultFormat = (value: string) => {
21
+ const digitsOnly = value.replace(/\D/g, '').slice(0, 8);
22
+ const day = digitsOnly.slice(0, 2);
23
+ const month = digitsOnly.slice(2, 4);
24
+ const year = digitsOnly.slice(4, 8);
25
+
26
+ return [day, month, year].filter(Boolean).join('/');
27
+ };
28
+
29
+ const DatePickerInput = ({
30
+ validationStatus = 'initial',
31
+ disabled,
32
+ focused,
33
+ readonly,
34
+ placeholder,
35
+ inBottomSheet = false,
36
+ format = DEFAULT_FORMAT,
37
+ openButtonLabel = 'Open date picker',
38
+ autoCloseOnSelect = true,
39
+ onChange,
40
+ onChangeText,
41
+ onBlur,
42
+ onFocus,
43
+ value,
44
+ datePickerProps,
45
+ onClear,
46
+ ...rest
47
+ }: DatePickerInputProps) => {
48
+ const formFieldContext = useFormFieldContext();
49
+ const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
50
+ const isDisabled = formFieldContext?.disabled ?? disabled;
51
+ const isReadonly = formFieldContext?.readonly ?? readonly;
52
+
53
+ const pickerRef = useRef<BottomSheetModalMethods | null>(null);
54
+ const accessoryViewID = useMemo(() => {
55
+ if (Platform.OS !== 'ios') return undefined;
56
+ return `datepicker-input-${Math.random().toString(36).slice(2)}`;
57
+ }, []);
58
+
59
+ const formatDate = useCallback(
60
+ (dateValue?: DateType) => {
61
+ if (!dateValue) return '';
62
+ const parsed = dayjs(dateValue);
63
+ return parsed.isValid() ? parsed.format(format) : '';
64
+ },
65
+ [format]
66
+ );
67
+
68
+ const isDefaultFormat = format === DEFAULT_FORMAT;
69
+
70
+ const [inputValue, setInputValue] = useState(() => formatDate(value));
71
+
72
+ useEffect(() => {
73
+ setInputValue(formatDate(value));
74
+ }, [value, formatDate]);
75
+
76
+ const handleTextChange = useCallback(
77
+ (text: string) => {
78
+ const nextValue = isDefaultFormat ? maskDefaultFormat(text) : text;
79
+
80
+ setInputValue(nextValue);
81
+ onChangeText?.(nextValue);
82
+
83
+ if (!nextValue) {
84
+ onChange?.({ date: undefined });
85
+ return;
86
+ }
87
+
88
+ const parsed = dayjs(nextValue, format, true);
89
+
90
+ if (parsed.isValid()) {
91
+ onChange?.({ date: parsed.toDate() });
92
+ } else {
93
+ onChange?.({ date: undefined });
94
+ }
95
+ },
96
+ [format, isDefaultFormat, onChange, onChangeText]
97
+ );
98
+
99
+ const handleClear = useCallback(() => {
100
+ setInputValue('');
101
+ onChange?.({ date: undefined });
102
+ onClear?.();
103
+ }, [onChange, onClear]);
104
+
105
+ const closeKeyboard = useCallback(() => {
106
+ Keyboard.dismiss();
107
+ }, []);
108
+
109
+ const openPicker = useCallback(() => {
110
+ if (isDisabled || isReadonly) return;
111
+ closeKeyboard();
112
+ pickerRef.current?.present();
113
+ }, [closeKeyboard, isDisabled, isReadonly]);
114
+
115
+ const selectedDate = useMemo(() => {
116
+ if (value) {
117
+ return value;
118
+ }
119
+
120
+ const parsed = dayjs(inputValue, format, true);
121
+ return parsed.isValid() ? parsed.toDate() : undefined;
122
+ }, [value, inputValue, format]);
123
+
124
+ const handlePickerChange = useCallback(
125
+ ({ date }: { date: DateType }) => {
126
+ if (!date) {
127
+ handleClear();
128
+ return;
129
+ }
130
+
131
+ const formatted = formatDate(date);
132
+ setInputValue(formatted);
133
+ onChange?.({ date });
134
+
135
+ if (autoCloseOnSelect) {
136
+ pickerRef.current?.close?.();
137
+ }
138
+ },
139
+ [autoCloseOnSelect, formatDate, handleClear, onChange]
140
+ );
141
+
142
+ const handleBlur = useCallback(
143
+ (event: TextInputFocusEvent) => {
144
+ onBlur?.(event);
145
+ },
146
+ [onBlur]
147
+ );
148
+
149
+ const handleFocus = useCallback(
150
+ (event: TextInputFocusEvent) => {
151
+ onFocus?.(event);
152
+ },
153
+ [onFocus]
154
+ );
155
+
156
+ const { onCancel: pickerOnCancel, ...restDatePickerProps } = datePickerProps ?? {};
157
+ const {
158
+ style: inputStyle,
159
+ keyboardType: keyboardTypeProp,
160
+ inputMode: inputModeProp,
161
+ accessibilityHint: accessibilityHintProp,
162
+ accessibilityLabel: accessibilityLabelProp,
163
+ accessible: accessibleProp,
164
+ accessibilityRole: accessibilityRoleProp,
165
+ importantForAccessibility: importantForAccessibilityProp,
166
+ ...textInputProps
167
+ } = rest;
168
+
169
+ const resolvedKeyboardType = keyboardTypeProp ?? (isDefaultFormat ? 'number-pad' : undefined);
170
+ const resolvedInputMode = inputModeProp ?? (isDefaultFormat ? 'numeric' : undefined);
171
+ const resolvedAccessibilityHint = accessibilityHintProp ?? `Enter the date in ${format} format`;
172
+ const resolvedAccessibilityLabel = accessibilityLabelProp ?? 'Date input';
173
+ const resolvedAccessible = accessibleProp ?? true;
174
+ const resolvedImportantForAccessibility = importantForAccessibilityProp ?? 'yes';
175
+
176
+ const handleCancel = useCallback(() => {
177
+ pickerOnCancel?.();
178
+ pickerRef.current?.close?.();
179
+ }, [pickerOnCancel]);
180
+
181
+ const placeholderValue = placeholder ?? format;
182
+
183
+ return (
184
+ <>
185
+ <Input
186
+ validationStatus={validationStatusFromContext}
187
+ disabled={isDisabled}
188
+ readonly={isReadonly}
189
+ focused={focused}
190
+ style={styles.wrap}
191
+ accessible={false}
192
+ >
193
+ <InputField
194
+ editable={!isReadonly && !isDisabled}
195
+ value={inputValue}
196
+ placeholder={placeholderValue}
197
+ onChangeText={handleTextChange}
198
+ onBlur={handleBlur}
199
+ onFocus={handleFocus}
200
+ inBottomSheet={inBottomSheet}
201
+ keyboardType={resolvedKeyboardType}
202
+ inputMode={resolvedInputMode}
203
+ accessibilityHint={resolvedAccessibilityHint}
204
+ aria-label="Date input"
205
+ accessibilityLabel={resolvedAccessibilityLabel}
206
+ accessible={resolvedAccessible}
207
+ accessibilityState={{
208
+ disabled: isDisabled || isReadonly,
209
+ }}
210
+ importantForAccessibility={resolvedImportantForAccessibility}
211
+ inputAccessoryViewID={Platform.OS === 'ios' ? accessoryViewID : undefined}
212
+ {...textInputProps}
213
+ style={[styles.input, inputStyle]}
214
+ />
215
+ {!!inputValue && onClear && !isReadonly && !isDisabled && (
216
+ <InputSlot accessibilityElementsHidden={false}>
217
+ <UnstyledIconButton
218
+ accessibilityLabel="Clear date"
219
+ accessibilityHint="Removes the current date"
220
+ icon={CloseSmallIcon}
221
+ onPress={handleClear}
222
+ />
223
+ </InputSlot>
224
+ )}
225
+ <InputSlot accessibilityElementsHidden={false}>
226
+ <UnstyledIconButton
227
+ accessibilityLabel={openButtonLabel}
228
+ accessibilityHint="Opens the date picker calendar"
229
+ icon={CalendarSmallIcon}
230
+ onPress={openPicker}
231
+ disabled={isDisabled || isReadonly}
232
+ />
233
+ </InputSlot>
234
+ </Input>
235
+ <DatePicker
236
+ ref={pickerRef}
237
+ mode="single"
238
+ date={selectedDate}
239
+ onChange={handlePickerChange}
240
+ onCancel={handleCancel}
241
+ {...restDatePickerProps}
242
+ />
243
+ {Platform.OS === 'ios' && accessoryViewID && (
244
+ <DatePickerInputDoneButton
245
+ accessoryViewID={accessoryViewID}
246
+ closeKeyboard={closeKeyboard}
247
+ />
248
+ )}
249
+ </>
250
+ );
251
+ };
252
+
253
+ DatePickerInput.displayName = 'DatePickerInput';
254
+
255
+ const styles = StyleSheet.create(theme => ({
256
+ wrap: {
257
+ gap: theme.components.input.date.gap,
258
+ },
259
+ input: {
260
+ paddingLeft: 0,
261
+ paddingRight: 0,
262
+ },
263
+ }));
264
+
265
+ export default DatePickerInput;
@@ -0,0 +1,42 @@
1
+ import { InputAccessoryView, View } from 'react-native';
2
+ import { StyleSheet } from 'react-native-unistyles';
3
+ import { Button } from '../Button';
4
+
5
+ const DatePickerInputDoneButton = ({
6
+ accessoryViewID,
7
+ closeKeyboard,
8
+ }: {
9
+ accessoryViewID: string;
10
+ closeKeyboard: () => void;
11
+ }) => {
12
+ return (
13
+ <InputAccessoryView nativeID={accessoryViewID}>
14
+ <View style={styles.accessory}>
15
+ <Button
16
+ accessibilityRole="button"
17
+ accessibilityLabel="Done"
18
+ onPress={closeKeyboard}
19
+ variant="ghost"
20
+ colorScheme="functional"
21
+ >
22
+ Done
23
+ </Button>
24
+ </View>
25
+ </InputAccessoryView>
26
+ );
27
+ };
28
+
29
+ const styles = StyleSheet.create(theme => ({
30
+ accessory: {
31
+ paddingHorizontal: 16,
32
+ paddingVertical: 2,
33
+ alignItems: 'flex-end',
34
+ backgroundColor: theme.color.surface.neutral.strong,
35
+ borderTopWidth: theme.borderWidth[1],
36
+ borderTopColor: theme.color.border.subtle,
37
+ },
38
+ }));
39
+
40
+ DatePickerInputDoneButton.DisplayName = 'DatePickerInputDoneButton';
41
+
42
+ export default DatePickerInputDoneButton;
@@ -0,0 +1,7 @@
1
+ const DatePickerInputDoneButton = () => {
2
+ return null;
3
+ };
4
+
5
+ DatePickerInputDoneButton.DisplayName = 'DatePickerInputDoneButton';
6
+
7
+ export default DatePickerInputDoneButton;
@@ -0,0 +1,2 @@
1
+ export { default as DatePickerInput } from './DatePickerInput';
2
+ export type { default as DatePickerInputProps } from './DatePickerInput.props';
@@ -1,6 +1,5 @@
1
1
  import { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import * as Icons from '@utilitywarehouse/hearth-react-native-icons';
3
- import { ComponentType } from 'react';
4
3
  import { Icon } from '.';
5
4
  import { ColorValue } from '../../types';
6
5
  import { coloursAsArray } from '../../utils';
@@ -25,7 +24,8 @@ const meta = {
25
24
  },
26
25
  },
27
26
  args: {
28
- as: Object.keys(Icons)[0] as ComponentType,
27
+ // @ts-expect-error - This is a playground
28
+ as: Object.keys(Icons)[0],
29
29
  color: 'grey1000' as ColorValue,
30
30
  },
31
31
  } satisfies Meta<typeof Icon>;
@@ -37,7 +37,8 @@ type Story = StoryObj<typeof meta>;
37
37
  export const Playground: Story = {
38
38
  // @ts-expect-error - This is a playground
39
39
  render: ({ as: icon, color }) => {
40
+ // @ts-expect-error - This is a playground
40
41
  const as = icon === 'none' ? undefined : Icons[icon];
41
- return <Icon as={as} color={colors[color]} />;
42
+ return <Icon as={as} color={color} />;
42
43
  },
43
44
  };
@@ -6,8 +6,6 @@ import { useInputContext } from './Input.context';
6
6
 
7
7
  const InputField = ({
8
8
  style,
9
- onFocus,
10
- onBlur,
11
9
  inBottomSheet = false,
12
10
  ...props
13
11
  }: TextInputProps & { inBottomSheet?: boolean }) => {
@@ -1,9 +1,20 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
1
  import { View, ViewProps } from 'react-native';
2
+ import { StyleSheet } from 'react-native-unistyles';
3
3
 
4
- const InputSlot = ({ children, style, ...props }: ViewProps) => {
4
+ const InputSlot = ({
5
+ children,
6
+ style,
7
+ accessible,
8
+ importantForAccessibility,
9
+ ...props
10
+ }: ViewProps) => {
5
11
  return (
6
- <View {...props} style={[styles.container, style]}>
12
+ <View
13
+ {...props}
14
+ accessible={accessible ?? false}
15
+ importantForAccessibility={importantForAccessibility ?? 'auto'}
16
+ style={[styles.container, style]}
17
+ >
7
18
  {children}
8
19
  </View>
9
20
  );
@@ -1,9 +1,9 @@
1
1
  import { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import { useRef } from 'react';
3
- import { Dimensions, ImageSourcePropType, Platform, View, ViewProps } from 'react-native';
4
- import { UnistylesRuntime } from 'react-native-unistyles';
3
+ import { ImageSourcePropType, Platform, View } from 'react-native';
5
4
  import { Modal } from '.';
6
5
  import pigs from '../../../docs/assets/pigs.png';
6
+ import { ViewWrap } from '../../../docs/components';
7
7
  import { BodyText } from '../BodyText';
8
8
  import { BottomSheetModal } from '../BottomSheet';
9
9
  import { Box } from '../Box';
@@ -61,34 +61,6 @@ const meta = {
61
61
  export default meta;
62
62
  type Story = StoryObj<typeof meta>;
63
63
 
64
- const ViewWrap = ({ children }: { children: ViewProps['children'] }) => (
65
- <View
66
- style={{
67
- width: Platform.OS === 'web' ? '100%' : Dimensions.get('window').width,
68
- height:
69
- Platform.OS === 'web'
70
- ? '100%'
71
- : Dimensions.get('window').height -
72
- UnistylesRuntime.insets.top -
73
- UnistylesRuntime.insets.bottom -
74
- 33,
75
-
76
- position: 'absolute',
77
- top: 0,
78
- left: 0,
79
- right: 0,
80
- bottom: 0,
81
- flex: 1,
82
- marginVertical: Platform.OS === 'web' ? 0 : -8,
83
- justifyContent: 'center',
84
- alignItems: 'center',
85
- padding: 16,
86
- }}
87
- >
88
- {children}
89
- </View>
90
- );
91
-
92
64
  export const Playground: Story = {
93
65
  args: {
94
66
  children: [],
@@ -30,17 +30,29 @@ const UnstyledIconButton = ({
30
30
  ...props
31
31
  }: UnstyledIconButtonProps) => {
32
32
  const { disabled: groupDisabled, loading: groupLoading } = useButtonGroupContext();
33
- const { loading } = props;
33
+ const {
34
+ loading,
35
+ accessibilityRole = 'button',
36
+ accessible = true,
37
+ focusable = true,
38
+ importantForAccessibility = 'yes',
39
+ ...restProps
40
+ } = props;
41
+
34
42
  const isLoading = loading ?? groupLoading;
35
43
  const buttonDisabled = isLoading || (disabled ?? groupDisabled);
36
44
 
37
45
  return (
38
46
  <UnstyledIconButtonComponent
39
- {...props}
47
+ {...restProps}
40
48
  size={size}
41
49
  inverted={inverted}
42
50
  isDisabled={buttonDisabled}
43
51
  isPressed={pressed}
52
+ accessibilityRole={accessibilityRole}
53
+ accessible={accessible}
54
+ focusable={focusable}
55
+ importantForAccessibility={importantForAccessibility}
44
56
  icon={icon}
45
57
  >
46
58
  {loading ? (
@@ -1,8 +1,8 @@
1
- import React, { useMemo } from 'react';
2
- import type { UnstyledIconButtonProps } from './UnstyledIconButton.props';
1
+ import { useMemo } from 'react';
3
2
  import { Pressable, ViewStyle } from 'react-native';
4
3
  import { StyleSheet } from 'react-native-unistyles';
5
4
  import { UnstyledIconButtonContext } from './UnstyledIconButton.context';
5
+ import type { UnstyledIconButtonProps } from './UnstyledIconButton.props';
6
6
 
7
7
  const UnstyledIconButtonRoot = ({
8
8
  size,
@@ -18,7 +18,11 @@ const UnstyledIconButtonRoot = ({
18
18
  );
19
19
  return (
20
20
  <UnstyledIconButtonContext.Provider value={value}>
21
- <Pressable {...props} style={[styles.container, props.style as ViewStyle]} />
21
+ <Pressable
22
+ {...props}
23
+ accessibilityState={{ disabled: !!disabled, ...props.accessibilityState }}
24
+ style={[styles.container, props.style as ViewStyle]}
25
+ />
22
26
  </UnstyledIconButtonContext.Provider>
23
27
  );
24
28
  };
@@ -10,6 +10,8 @@ export * from './Card';
10
10
  export * from './Center';
11
11
  export * from './Checkbox';
12
12
  export * from './CurrencyInput';
13
+ export * from './DatePicker';
14
+ export * from './DatePickerInput';
13
15
  export * from './DescriptionList';
14
16
  export * from './DetailText';
15
17
  export * from './Divider';
@@ -1,4 +1,5 @@
1
1
  import { DimensionValue, Platform } from 'react-native';
2
+ import { colors, colorsCommon, colorsDark } from '../legacyTokens';
2
3
  import {
3
4
  borderRadius,
4
5
  borderWidth,
@@ -280,6 +281,15 @@ export const lightTheme = {
280
281
  colorMode: 'light',
281
282
  isLight: true,
282
283
  isDark: false,
284
+ /**
285
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility
286
+ */
287
+ colors: {
288
+ ...colors,
289
+ ...colorsCommon,
290
+ white: '#ffffff',
291
+ black: '#000000',
292
+ },
283
293
  color: {
284
294
  ...restOfColors,
285
295
  ...light,
@@ -305,10 +315,31 @@ export const darkTheme = {
305
315
  colorMode: 'dark',
306
316
  isLight: false,
307
317
  isDark: true,
318
+ /**
319
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
320
+ */
321
+ colors: {
322
+ ...colorsDark,
323
+ ...colorsCommon,
324
+ /**
325
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
326
+ */
327
+ white: '#ffffff',
328
+ /**
329
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
330
+ */
331
+ black: '#000000',
332
+ },
308
333
  color: {
309
334
  ...restOfColors,
310
335
  ...dark,
336
+ /**
337
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
338
+ */
311
339
  white: '#ffffff',
340
+ /**
341
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
342
+ */
312
343
  black: '#000000',
313
344
  },
314
345
  components: components.dark,
@@ -1,6 +1,7 @@
1
- export { default as useColorMode } from './useColorMode';
2
1
  export { default as useBreakpointValue } from './useBreakpointValue';
3
- export { default as useTheme } from './useTheme';
2
+ export { default as useColorMode } from './useColorMode';
4
3
  export { default as useMedia } from './useMedia';
5
- export { default as useToken } from './useToken';
4
+ export { usePrevious } from './usePrevious';
6
5
  export { useStyleProps } from './useStyleProps';
6
+ export { default as useTheme } from './useTheme';
7
+ export { default as useToken } from './useToken';
@@ -0,0 +1,9 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ export const usePrevious = (value: any) => {
4
+ const ref = useRef(null);
5
+ useEffect(() => {
6
+ ref.current = value;
7
+ });
8
+ return ref.current;
9
+ };
@@ -1,8 +1,9 @@
1
- import { UnistylesRuntime } from 'react-native-unistyles';
1
+ import { useUnistyles } from 'react-native-unistyles';
2
+ import { AppThemes } from '../types';
2
3
 
3
4
  const useTheme = () => {
4
- const theme = UnistylesRuntime.getTheme();
5
- return theme;
5
+ const { theme } = useUnistyles();
6
+ return theme as AppThemes['light'] | AppThemes['dark'];
6
7
  };
7
8
 
8
9
  export default useTheme;
@@ -0,0 +1,18 @@
1
+ // HEY, DON'T EDIT THIS FILE DIRECTLY, IT'S BEEN MAGICALLY GENERATED.
2
+
3
+ /**
4
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
5
+ */
6
+ export const brandMidnight = '#1e0a46';
7
+ /**
8
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
9
+ */
10
+ export const brandWhite = '#ffffff';
11
+ /**
12
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
13
+ */
14
+ export const brandPink = '#f495f9';
15
+ /**
16
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
17
+ */
18
+ export const brandPrimaryPurple = '#550091';
@@ -0,0 +1,10 @@
1
+ // HEY, DON'T EDIT THIS FILE DIRECTLY, IT'S BEEN MAGICALLY GENERATED.
2
+
3
+ /**
4
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
5
+ */
6
+ export * from './brand';
7
+ /**
8
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
9
+ */
10
+ export * from './service';
@@ -0,0 +1,22 @@
1
+ // HEY, DON'T EDIT THIS FILE DIRECTLY, IT'S BEEN MAGICALLY GENERATED.
2
+
3
+ /**
4
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
5
+ */
6
+ export const serviceGas = '#75A7FD';
7
+ /**
8
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
9
+ */
10
+ export const serviceElectricity = '#62DD99';
11
+ /**
12
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
13
+ */
14
+ export const serviceInsurance = '#F25192';
15
+ /**
16
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
17
+ */
18
+ export const serviceMobile = '#FFD76F';
19
+ /**
20
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
21
+ */
22
+ export const serviceLandline = '#A66DE8';
@@ -0,0 +1,30 @@
1
+ // HEY, DON'T EDIT THIS FILE DIRECTLY, IT'S BEEN MAGICALLY GENERATED.
2
+
3
+ /**
4
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
5
+ */
6
+ export const apple100 = '#03361b';
7
+ /**
8
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
9
+ */
10
+ export const apple200 = '#087a3c';
11
+ /**
12
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
13
+ */
14
+ export const apple300 = '#10b259';
15
+ /**
16
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
17
+ */
18
+ export const apple600 = '#62dd99';
19
+ /**
20
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
21
+ */
22
+ export const apple700 = '#96e6b7';
23
+ /**
24
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
25
+ */
26
+ export const apple800 = '#c1f0d3';
27
+ /**
28
+ * @deprecated This will be removed in the next major version. This is kept for backward compatibility.
29
+ */
30
+ export const apple950 = '#e5f9ed';