@utilitywarehouse/hearth-react-native 0.36.1 → 0.36.3

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 (226) hide show
  1. package/SKILL.md +27 -16
  2. package/build/components/Accordion/Accordion.d.ts +4 -0
  3. package/build/components/Accordion/Accordion.js +4 -0
  4. package/build/components/Accordion/Accordion.props.d.ts +2 -0
  5. package/build/components/Alert/Alert.d.ts +4 -0
  6. package/build/components/Alert/Alert.js +4 -0
  7. package/build/components/Avatar/Avatar.d.ts +4 -0
  8. package/build/components/Avatar/Avatar.js +4 -0
  9. package/build/components/Badge/Badge.d.ts +4 -0
  10. package/build/components/Badge/Badge.js +4 -0
  11. package/build/components/Badge/Badge.props.d.ts +19 -0
  12. package/build/components/Banner/Banner.d.ts +5 -0
  13. package/build/components/Banner/Banner.js +5 -0
  14. package/build/components/Banner/BannerIllustration.d.ts +4 -0
  15. package/build/components/Banner/BannerIllustration.js +4 -0
  16. package/build/components/Banner/BannerImage.d.ts +4 -0
  17. package/build/components/Banner/BannerImage.js +4 -0
  18. package/build/components/BodyText/BodyText.d.ts +4 -0
  19. package/build/components/BodyText/BodyText.js +4 -0
  20. package/build/components/BottomSheet/BottomSheet.d.ts +6 -0
  21. package/build/components/BottomSheet/BottomSheet.js +6 -0
  22. package/build/components/BottomSheet/BottomSheet.props.d.ts +2 -0
  23. package/build/components/Box/Box.d.ts +4 -0
  24. package/build/components/Box/Box.js +4 -0
  25. package/build/components/Box/Box.props.d.ts +2 -0
  26. package/build/components/Button/Button.d.ts +4 -0
  27. package/build/components/Button/Button.js +4 -0
  28. package/build/components/Button/Button.props.d.ts +129 -0
  29. package/build/components/Card/Card.d.ts +4 -0
  30. package/build/components/Card/Card.js +4 -0
  31. package/build/components/Card/Card.props.d.ts +19 -1
  32. package/build/components/Card/CardAction/CardAction.d.ts +4 -0
  33. package/build/components/Card/CardAction/CardAction.js +4 -0
  34. package/build/components/Card/CardAction/CardAction.props.d.ts +23 -0
  35. package/build/components/Card/CardPressHandler.d.ts +8 -3
  36. package/build/components/Card/CardPressHandler.js +3 -0
  37. package/build/components/Carousel/Carousel.d.ts +3 -0
  38. package/build/components/Carousel/Carousel.js +3 -0
  39. package/build/components/Carousel/Carousel.props.d.ts +37 -0
  40. package/build/components/Center/Center.d.ts +3 -0
  41. package/build/components/Center/Center.js +3 -0
  42. package/build/components/Checkbox/Checkbox.d.ts +3 -0
  43. package/build/components/Checkbox/Checkbox.js +3 -0
  44. package/build/components/Checkbox/Checkbox.props.d.ts +20 -0
  45. package/build/components/Checkbox/CheckboxGroup.d.ts +3 -0
  46. package/build/components/Checkbox/CheckboxGroup.js +3 -0
  47. package/build/components/Checkbox/CheckboxGroup.props.d.ts +24 -0
  48. package/build/components/Combobox/Combobox.d.ts +3 -0
  49. package/build/components/Combobox/Combobox.js +3 -0
  50. package/build/components/Container/Container.d.ts +3 -0
  51. package/build/components/Container/Container.js +3 -0
  52. package/build/components/CurrencyInput/CurrencyInput.d.ts +3 -0
  53. package/build/components/CurrencyInput/CurrencyInput.js +3 -0
  54. package/build/components/CurrencyInput/CurrencyInput.props.d.ts +25 -0
  55. package/build/components/DateInput/DateInput.d.ts +4 -0
  56. package/build/components/DateInput/DateInput.js +4 -0
  57. package/build/components/DateInput/DateInput.props.d.ts +3 -0
  58. package/build/components/DatePicker/DatePicker.context.d.ts +1 -0
  59. package/build/components/DatePicker/DatePicker.d.ts +14 -0
  60. package/build/components/DatePicker/DatePicker.js +31 -0
  61. package/build/components/DatePicker/DatePicker.props.d.ts +78 -0
  62. package/build/components/DatePicker/DatePickerFooter.js +6 -2
  63. package/build/components/DatePickerInput/DatePickerInput.d.ts +5 -1
  64. package/build/components/DatePickerInput/DatePickerInput.js +15 -5
  65. package/build/components/DatePickerInput/DatePickerInput.props.d.ts +28 -0
  66. package/build/components/DescriptionList/DescriptionList.d.ts +4 -0
  67. package/build/components/DescriptionList/DescriptionList.js +4 -0
  68. package/build/components/DescriptionList/DescriptionList.props.d.ts +4 -0
  69. package/build/components/DetailText/DetailText.d.ts +4 -0
  70. package/build/components/DetailText/DetailText.js +4 -0
  71. package/build/components/Divider/Divider.d.ts +4 -0
  72. package/build/components/Divider/Divider.js +4 -0
  73. package/build/components/Divider/Divider.props.d.ts +10 -0
  74. package/build/components/Expandable/Expandable.d.ts +5 -0
  75. package/build/components/Expandable/Expandable.js +5 -0
  76. package/build/components/ExpandableCard/ExpandableCard.d.ts +4 -0
  77. package/build/components/ExpandableCard/ExpandableCard.js +4 -0
  78. package/build/components/Flex/Flex.d.ts +4 -0
  79. package/build/components/Flex/Flex.js +4 -0
  80. package/build/components/Flex/Flex.props.d.ts +20 -0
  81. package/build/components/FormField/FormField.d.ts +5 -0
  82. package/build/components/FormField/FormField.js +5 -0
  83. package/build/components/FormField/FormField.props.d.ts +24 -0
  84. package/build/components/Grid/Grid.d.ts +4 -0
  85. package/build/components/Grid/Grid.js +4 -0
  86. package/build/components/HTMLElements/ListItem.d.ts +5 -0
  87. package/build/components/HTMLElements/OrderedList.d.ts +10 -0
  88. package/build/components/HTMLElements/OrderedList.js +4 -0
  89. package/build/components/HTMLElements/UnorderedList.d.ts +10 -0
  90. package/build/components/HTMLElements/UnorderedList.js +4 -0
  91. package/build/components/Heading/Heading.d.ts +4 -0
  92. package/build/components/Heading/Heading.js +4 -0
  93. package/build/components/HighlightBanner/HighlightBanner.d.ts +5 -0
  94. package/build/components/HighlightBanner/HighlightBanner.js +5 -0
  95. package/build/components/HighlightBanner/HighlightBanner.props.d.ts +14 -0
  96. package/build/components/HighlightBanner/HighlightBannerImage.d.ts +4 -0
  97. package/build/components/HighlightBanner/HighlightBannerImage.js +4 -0
  98. package/build/components/Icon/Icon.d.ts +4 -0
  99. package/build/components/Icon/Icon.js +4 -0
  100. package/build/components/Icon/Icon.props.d.ts +8 -0
  101. package/build/components/IconButton/IconButton.d.ts +5 -0
  102. package/build/components/IconButton/IconButton.js +5 -0
  103. package/build/components/IconButton/IconButton.props.d.ts +9 -0
  104. package/build/components/IconContainer/IconContainer.d.ts +4 -0
  105. package/build/components/IconContainer/IconContainer.js +4 -0
  106. package/build/components/IndicatorIconButton/IndicatorIconButton.d.ts +6 -0
  107. package/build/components/IndicatorIconButton/IndicatorIconButton.js +6 -0
  108. package/build/components/InlineLink/InlineLink.d.ts +1 -0
  109. package/build/components/InlineLink/InlineLink.js +1 -0
  110. package/build/components/InlineLink/InlineLink.props.d.ts +4 -0
  111. package/build/components/Input/Input.d.ts +5 -0
  112. package/build/components/Input/Input.js +5 -0
  113. package/build/components/Input/Input.props.d.ts +54 -0
  114. package/build/components/Link/Link.d.ts +5 -0
  115. package/build/components/Link/Link.js +5 -0
  116. package/build/components/Link/Link.props.d.ts +15 -0
  117. package/build/components/List/List.d.ts +1 -0
  118. package/build/components/List/List.js +1 -0
  119. package/build/components/List/List.props.d.ts +8 -0
  120. package/build/components/Menu/Menu.d.ts +1 -0
  121. package/build/components/Menu/Menu.js +1 -0
  122. package/build/components/Modal/Modal.d.ts +5 -0
  123. package/build/components/Modal/Modal.js +5 -0
  124. package/build/components/Modal/Modal.props.d.ts +6 -0
  125. package/build/components/Modal/Modal.shared.types.d.ts +32 -0
  126. package/build/components/Modal/ModalImage.d.ts +1 -0
  127. package/build/components/Modal/ModalImage.js +1 -0
  128. package/build/components/NavModal/NavModal.d.ts +8 -0
  129. package/build/components/NavModal/NavModal.js +8 -0
  130. package/build/components/NavModal/NavModal.props.d.ts +10 -0
  131. package/build/components/Pagination/Pagination.d.ts +5 -0
  132. package/build/components/Pagination/Pagination.js +5 -0
  133. package/build/components/PillGroup/Pill.d.ts +1 -0
  134. package/build/components/PillGroup/Pill.js +1 -0
  135. package/build/components/PillGroup/PillGroup.d.ts +5 -0
  136. package/build/components/PillGroup/PillGroup.js +5 -0
  137. package/build/components/ProgressBar/ProgressBar.d.ts +5 -0
  138. package/build/components/ProgressBar/ProgressBar.js +5 -0
  139. package/build/components/ProgressBar/ProgressBar.props.d.ts +4 -0
  140. package/build/components/ProgressStepper/ProgressStep.d.ts +13 -0
  141. package/build/components/ProgressStepper/ProgressStep.js +5 -0
  142. package/build/components/ProgressStepper/ProgressStepper.d.ts +5 -0
  143. package/build/components/ProgressStepper/ProgressStepper.js +5 -0
  144. package/build/components/Radio/Radio.d.ts +5 -0
  145. package/build/components/Radio/Radio.js +5 -0
  146. package/build/components/Radio/Radio.props.d.ts +17 -0
  147. package/build/components/Radio/RadioGroup.d.ts +5 -0
  148. package/build/components/Radio/RadioGroup.js +5 -0
  149. package/build/components/Radio/RadioGroup.props.d.ts +25 -0
  150. package/build/components/RadioCard/RadioCard.d.ts +10 -0
  151. package/build/components/RadioCard/RadioCard.js +10 -0
  152. package/build/components/RadioCard/RadioCard.props.d.ts +14 -0
  153. package/build/components/RadioCard/RadioCardGroup.d.ts +4 -0
  154. package/build/components/RadioCard/RadioCardGroup.js +4 -0
  155. package/build/components/RadioCard/RadioCardGroup.props.d.ts +17 -0
  156. package/build/components/Rating/Rating.d.ts +5 -0
  157. package/build/components/Rating/Rating.js +5 -0
  158. package/build/components/Roundel/Roundel.d.ts +1 -0
  159. package/build/components/Roundel/Roundel.js +1 -0
  160. package/build/components/SectionHeader/SectionHeader.d.ts +1 -0
  161. package/build/components/SectionHeader/SectionHeader.js +1 -0
  162. package/build/components/SectionHeader/SectionHeader.props.d.ts +7 -0
  163. package/build/components/SegmentedControl/SegmentedControl.d.ts +5 -0
  164. package/build/components/SegmentedControl/SegmentedControl.js +5 -0
  165. package/build/components/Select/Select.d.ts +5 -0
  166. package/build/components/Select/Select.js +5 -0
  167. package/build/components/Skeleton/Skeleton.d.ts +1 -0
  168. package/build/components/Skeleton/Skeleton.js +1 -0
  169. package/build/components/Skeleton/Skeleton.props.d.ts +4 -0
  170. package/build/components/Spinner/Spinner.d.ts +4 -0
  171. package/build/components/Spinner/Spinner.js +8 -0
  172. package/build/components/Spinner/Spinner.props.d.ts +5 -0
  173. package/build/components/Spinner/Spinner.web.d.ts +4 -0
  174. package/build/components/Spinner/Spinner.web.js +8 -0
  175. package/build/components/StepperInput/StepperInput.d.ts +4 -0
  176. package/build/components/StepperInput/StepperInput.js +4 -0
  177. package/build/components/StepperInput/StepperInput.props.d.ts +44 -0
  178. package/build/components/Switch/Switch.d.ts +4 -0
  179. package/build/components/Switch/Switch.js +4 -0
  180. package/build/components/Switch/Switch.props.d.ts +5 -0
  181. package/build/components/Table/Table.d.ts +4 -0
  182. package/build/components/Table/Table.js +4 -0
  183. package/build/components/Table/Table.props.d.ts +6 -0
  184. package/build/components/Table/TableHeader.d.ts +3 -0
  185. package/build/components/Table/TableHeader.js +3 -0
  186. package/build/components/Table/TableHeaderCell.d.ts +6 -0
  187. package/build/components/Table/TableHeaderCell.js +3 -0
  188. package/build/components/Tabs/Tabs.d.ts +5 -0
  189. package/build/components/Tabs/Tabs.js +5 -0
  190. package/build/components/Textarea/Textarea.d.ts +6 -0
  191. package/build/components/Textarea/Textarea.js +6 -0
  192. package/build/components/Textarea/Textarea.props.d.ts +14 -0
  193. package/build/components/TimePicker/TimePicker.d.ts +5 -0
  194. package/build/components/TimePicker/TimePicker.js +14 -1
  195. package/build/components/TimePicker/TimePickerView.js +5 -19
  196. package/build/components/TimePicker/TimePickerWheel.web.js +11 -2
  197. package/build/components/TimePicker/utils.d.ts +9 -0
  198. package/build/components/TimePicker/utils.js +30 -0
  199. package/build/components/TimePicker/utils.test.d.ts +1 -0
  200. package/build/components/TimePicker/utils.test.js +31 -0
  201. package/build/components/TimePickerInput/TimePickerInput.d.ts +6 -1
  202. package/build/components/TimePickerInput/TimePickerInput.js +16 -5
  203. package/build/components/TimePickerInput/TimePickerInput.props.d.ts +35 -0
  204. package/build/components/Timeline/Timeline.d.ts +5 -0
  205. package/build/components/Timeline/Timeline.js +5 -0
  206. package/build/components/Timeline/TimelineItem.d.ts +4 -0
  207. package/build/components/Timeline/TimelineItem.js +4 -0
  208. package/build/components/Toast/Toast.context.d.ts +4 -0
  209. package/build/components/Toast/Toast.context.js +4 -0
  210. package/build/components/Toast/Toast.props.d.ts +7 -0
  211. package/build/components/ToggleButton/ToggleButton.d.ts +4 -0
  212. package/build/components/ToggleButton/ToggleButton.js +4 -0
  213. package/build/components/ToggleButton/ToggleButton.props.d.ts +6 -0
  214. package/build/components/ToggleButtonCard/ToggleButtonCard.d.ts +8 -0
  215. package/build/components/ToggleButtonCard/ToggleButtonCard.js +8 -0
  216. package/build/components/ToggleButtonCard/ToggleButtonCard.props.d.ts +9 -0
  217. package/build/components/ToggleButtonCard/ToggleButtonCardGroup.props.d.ts +15 -0
  218. package/build/components/UnstyledIconButton/UnstyledIconButton.d.ts +5 -0
  219. package/build/components/UnstyledIconButton/UnstyledIconButton.js +5 -0
  220. package/build/components/UnstyledIconButton/UnstyledIconButton.props.d.ts +17 -0
  221. package/build/components/VerificationInput/VerificationInput.d.ts +4 -0
  222. package/build/components/VerificationInput/VerificationInput.js +4 -0
  223. package/package.json +8 -5
  224. package/public/llms/components/date-picker.md +7 -1
  225. package/public/llms/components/time-picker.md +1 -0
  226. package/public/llms/docs/introduction.md +1 -1
@@ -34,7 +34,14 @@ const TimePickerWheel = ({ value, setValue = () => { }, items }) => {
34
34
  const height = 140;
35
35
  const radius = height / 2;
36
36
  const valueIndex = useMemo(() => {
37
- return Math.max(0, items.findIndex(item => item.value === value));
37
+ const rawIndex = items.findIndex(item => item.value === value);
38
+ if (rawIndex === -1) {
39
+ if (__DEV__) {
40
+ console.warn(`TimePickerWheel: value "${value}" not found in items [${items.map(item => item.value).join(', ')}]; falling back to index 0.`);
41
+ }
42
+ return 0;
43
+ }
44
+ return rawIndex;
38
45
  }, [items, value]);
39
46
  const handlePanEnd = useCallback((deltaY) => {
40
47
  let newValueIndex = valueIndex - Math.round(deltaY / ((radius * 2) / displayCount));
@@ -81,7 +88,9 @@ const TimePickerWheel = ({ value, setValue = () => { }, items }) => {
81
88
  return items[targetIndex] || items[0];
82
89
  });
83
90
  }, [renderCount, valueIndex, items, circular]);
84
- const currentIndex = Math.max(0, displayValues.findIndex(item => item?.value === value));
91
+ // displayValues is centered on valueIndex by construction, so the current item always
92
+ // sits at the middle index rather than needing a second findIndex/fallback lookup.
93
+ const currentIndex = Math.floor(renderCount / 2);
85
94
  return (_jsx(GestureDetector, { gesture: panGesture, children: _jsxs(View, { style: styles.container, children: [_jsx(View, { style: [
86
95
  styles.selectedIndicator,
87
96
  {
@@ -0,0 +1,9 @@
1
+ import type { PickerOption } from './TimePicker.props';
2
+ /**
3
+ * Snaps a value to the closest matching option's value. Used to guarantee the value
4
+ * handed to a wheel picker always exists in its own options list — an exact match is
5
+ * returned as-is, a numeric mismatch snaps to the nearest option by distance, and a
6
+ * non-numeric or unmatched value falls back to the first option, since a mismatched
7
+ * value has nothing for the wheel to scroll to.
8
+ */
9
+ export declare const getClosestOption: <T extends number | string>(value: T, options: PickerOption[]) => T;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Snaps a value to the closest matching option's value. Used to guarantee the value
3
+ * handed to a wheel picker always exists in its own options list — an exact match is
4
+ * returned as-is, a numeric mismatch snaps to the nearest option by distance, and a
5
+ * non-numeric or unmatched value falls back to the first option, since a mismatched
6
+ * value has nothing for the wheel to scroll to.
7
+ */
8
+ export const getClosestOption = (value, options) => {
9
+ if (!options.length)
10
+ return value;
11
+ const values = options.map(option => option.value);
12
+ if (values.includes(value))
13
+ return value;
14
+ const numericValues = values.filter((optionValue) => {
15
+ return typeof optionValue === 'number';
16
+ });
17
+ if (typeof value !== 'number' || Number.isNaN(value) || !numericValues.length) {
18
+ return (options[0]?.value ?? value);
19
+ }
20
+ let closest = numericValues[0];
21
+ let closestDiff = Math.abs(value - closest);
22
+ numericValues.forEach(optionValue => {
23
+ const diff = Math.abs(value - optionValue);
24
+ if (diff < closestDiff) {
25
+ closestDiff = diff;
26
+ closest = optionValue;
27
+ }
28
+ });
29
+ return closest;
30
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getClosestOption } from './utils';
3
+ const minuteOptions = [0, 15, 30, 45].map(value => ({
4
+ value,
5
+ text: String(value),
6
+ }));
7
+ const periodOptions = [
8
+ { value: 'AM', text: 'AM' },
9
+ { value: 'PM', text: 'PM' },
10
+ ];
11
+ describe('getClosestOption', () => {
12
+ it('returns the value unchanged when it matches an option exactly', () => {
13
+ expect(getClosestOption(30, minuteOptions)).toBe(30);
14
+ });
15
+ it('snaps a mismatched numeric value to the nearest option', () => {
16
+ expect(getClosestOption(20, minuteOptions)).toBe(15);
17
+ expect(getClosestOption(23, minuteOptions)).toBe(30);
18
+ });
19
+ it('returns the value unchanged when options is empty', () => {
20
+ expect(getClosestOption(37, [])).toBe(37);
21
+ });
22
+ it('falls back to the first option for a NaN value', () => {
23
+ expect(getClosestOption(NaN, minuteOptions)).toBe(0);
24
+ });
25
+ it('matches a non-numeric value against string options', () => {
26
+ expect(getClosestOption('PM', periodOptions)).toBe('PM');
27
+ });
28
+ it('falls back to the first option for an unmatched non-numeric value', () => {
29
+ expect(getClosestOption('unknown', periodOptions)).toBe('AM');
30
+ });
31
+ });
@@ -1,6 +1,11 @@
1
1
  import type TimePickerInputProps from './TimePickerInput.props';
2
+ /**
3
+ * A text input for entering a time directly, paired with a trigger button that opens a
4
+ * TimePicker for selecting the same value. Formats and parses input using Day.js.
5
+ * @summary A text input with a time picker trigger.
6
+ */
2
7
  declare const TimePickerInput: {
3
- ({ validationStatus, disabled, focused, readonly, placeholder, inBottomSheet, format, openButtonLabel, autoCloseOnSelect, label, labelVariant, helperText, helperIcon, validText, invalidText, required, onChange, onChangeText, onBlur, onFocus, value, timePickerProps, onClear, ...rest }: TimePickerInputProps): import("react").JSX.Element;
8
+ ({ validationStatus, disabled, focused, readonly, placeholder, inBottomSheet, format, openButtonLabel, autoCloseOnSelect, disableManualEntry, label, labelVariant, helperText, helperIcon, validText, invalidText, required, onChange, onChangeText, onBlur, onFocus, value, timePickerProps, onClear, ...rest }: TimePickerInputProps): import("react").JSX.Element;
4
9
  displayName: string;
5
10
  };
6
11
  export default TimePickerInput;
@@ -3,7 +3,7 @@ import { CloseSmallIcon, TimeSmallIcon } from '@utilitywarehouse/hearth-react-na
3
3
  import dayjs from 'dayjs';
4
4
  import customParseFormat from 'dayjs/plugin/customParseFormat';
5
5
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
- import { Keyboard, Platform } from 'react-native';
6
+ import { Keyboard, Platform, Pressable } from 'react-native';
7
7
  import { StyleSheet } from 'react-native-unistyles';
8
8
  import { useFormFieldContext } from '../FormField';
9
9
  import { Input, InputField, InputSlot } from '../Input';
@@ -12,7 +12,12 @@ import { UnstyledIconButton } from '../UnstyledIconButton';
12
12
  import { DEFAULT_FORMAT_12, DEFAULT_FORMAT_24, maskDefaultFormat } from './TimePickerInput.utils';
13
13
  import TimePickerInputDoneButton from './TimePickerInputDoneButton';
14
14
  dayjs.extend(customParseFormat);
15
- const TimePickerInput = ({ validationStatus = 'initial', disabled, focused, readonly, placeholder = '--:--', inBottomSheet = false, format, openButtonLabel = 'Open time picker', autoCloseOnSelect = true, label, labelVariant, helperText, helperIcon, validText, invalidText, required = true, onChange, onChangeText, onBlur, onFocus, value, timePickerProps, onClear, ...rest }) => {
15
+ /**
16
+ * A text input for entering a time directly, paired with a trigger button that opens a
17
+ * TimePicker for selecting the same value. Formats and parses input using Day.js.
18
+ * @summary A text input with a time picker trigger.
19
+ */
20
+ const TimePickerInput = ({ validationStatus = 'initial', disabled, focused, readonly, placeholder = '--:--', inBottomSheet = false, format, openButtonLabel = 'Open time picker', autoCloseOnSelect = true, disableManualEntry = false, label, labelVariant, helperText, helperIcon, validText, invalidText, required = true, onChange, onChangeText, onBlur, onFocus, value, timePickerProps, onClear, ...rest }) => {
16
21
  const formFieldContext = useFormFieldContext();
17
22
  const isDisabled = formFieldContext?.disabled ?? disabled;
18
23
  const isReadonly = formFieldContext?.readonly ?? readonly;
@@ -103,18 +108,24 @@ const TimePickerInput = ({ validationStatus = 'initial', disabled, focused, read
103
108
  pickerRef.current?.close?.();
104
109
  }, [pickerOnCancel]);
105
110
  const placeholderValue = placeholder;
106
- return (_jsxs(_Fragment, { children: [_jsxs(Input, { validationStatus: validationStatus, disabled: disabled, readonly: readonly, focused: focused, label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validText: validText, invalidText: invalidText, required: required, style: styles.wrap, accessible: false, children: [_jsx(InputField, { editable: !isReadonly && !isDisabled, value: inputValue, placeholder: placeholderValue, onChangeText: handleTextChange, onBlur: handleBlur, onFocus: handleFocus, inBottomSheet: inBottomSheet, keyboardType: resolvedKeyboardType, inputMode: resolvedInputMode, accessibilityHint: resolvedAccessibilityHint, "aria-label": "Time input", accessibilityLabel: resolvedAccessibilityLabel, accessible: resolvedAccessible, accessibilityState: {
107
- disabled: isDisabled || isReadonly,
108
- }, importantForAccessibility: resolvedImportantForAccessibility, inputAccessoryViewID: Platform.OS === 'ios' ? accessoryViewID : undefined, ...textInputProps, style: [styles.input, inputStyle] }), !!inputValue && onClear && !isReadonly && !isDisabled && (_jsx(InputSlot, { accessibilityElementsHidden: false, children: _jsx(UnstyledIconButton, { accessibilityLabel: "Clear time", accessibilityHint: "Removes the current time", icon: CloseSmallIcon, onPress: handleClear }) })), _jsx(InputSlot, { accessibilityElementsHidden: false, children: _jsx(UnstyledIconButton, { accessibilityLabel: openButtonLabel, accessibilityHint: "Opens the time picker", icon: TimeSmallIcon, onPress: openPicker, disabled: isDisabled || isReadonly }) })] }), _jsx(TimePicker, { ref: pickerRef, date: selectedDate, onChange: handlePickerChange, onCancel: handleCancel, ...restTimePickerProps }), Platform.OS === 'ios' && accessoryViewID && (_jsx(TimePickerInputDoneButton, { accessoryViewID: accessoryViewID, closeKeyboard: closeKeyboard }))] }));
111
+ return (_jsxs(_Fragment, { children: [_jsxs(Input, { validationStatus: validationStatus, disabled: disabled, readonly: readonly, focused: focused, label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validText: validText, invalidText: invalidText, required: required, style: styles.wrap, accessible: false, children: [_jsx(Pressable, { style: styles.fieldPressable, disabled: !disableManualEntry || isDisabled || isReadonly, onPress: openPicker, children: _jsx(InputField, { value: inputValue, placeholder: placeholderValue, onChangeText: handleTextChange, onBlur: handleBlur, onFocus: handleFocus, inBottomSheet: inBottomSheet, keyboardType: resolvedKeyboardType, inputMode: resolvedInputMode, accessibilityHint: resolvedAccessibilityHint, "aria-label": "Time input", accessibilityLabel: resolvedAccessibilityLabel, accessible: resolvedAccessible, accessibilityState: {
112
+ disabled: isDisabled || isReadonly,
113
+ }, importantForAccessibility: resolvedImportantForAccessibility, inputAccessoryViewID: Platform.OS === 'ios' ? accessoryViewID : undefined, ...textInputProps, editable: !isReadonly && !isDisabled && !disableManualEntry, style: [styles.input, inputStyle, disableManualEntry && styles.noPointerEvents] }) }), !!inputValue && onClear && !isReadonly && !isDisabled && (_jsx(InputSlot, { accessibilityElementsHidden: false, children: _jsx(UnstyledIconButton, { accessibilityLabel: "Clear time", accessibilityHint: "Removes the current time", icon: CloseSmallIcon, onPress: handleClear }) })), _jsx(InputSlot, { accessibilityElementsHidden: false, children: _jsx(UnstyledIconButton, { accessibilityLabel: openButtonLabel, accessibilityHint: "Opens the time picker", icon: TimeSmallIcon, onPress: openPicker, disabled: isDisabled || isReadonly }) })] }), _jsx(TimePicker, { ref: pickerRef, date: selectedDate, onChange: handlePickerChange, onCancel: handleCancel, ...restTimePickerProps }), Platform.OS === 'ios' && accessoryViewID && (_jsx(TimePickerInputDoneButton, { accessoryViewID: accessoryViewID, closeKeyboard: closeKeyboard }))] }));
109
114
  };
110
115
  TimePickerInput.displayName = 'TimePickerInput';
111
116
  const styles = StyleSheet.create(theme => ({
112
117
  wrap: {
113
118
  gap: theme.components.input.date.gap,
114
119
  },
120
+ fieldPressable: {
121
+ flex: 1,
122
+ },
115
123
  input: {
116
124
  paddingLeft: 0,
117
125
  paddingRight: 0,
118
126
  },
127
+ noPointerEvents: {
128
+ pointerEvents: 'none',
129
+ },
119
130
  }));
120
131
  export default TimePickerInput;
@@ -2,18 +2,46 @@ import type { TextInputProps, ViewProps } from 'react-native';
2
2
  import type { DateType } from '../DatePicker/DatePicker.props';
3
3
  import type { TimePickerProps } from '../TimePicker/TimePicker.props';
4
4
  export interface TimePickerInputBaseProps {
5
+ /** Disables both typing and the time picker trigger button. */
5
6
  disabled?: boolean;
7
+ /**
8
+ * Renders the corresponding validation style. Inherited from FormField when nested.
9
+ * @default 'initial'
10
+ */
6
11
  validationStatus?: 'initial' | 'valid' | 'invalid';
12
+ /** Prevents manual typing while keeping the picker trigger available. */
7
13
  readonly?: boolean;
14
+ /** Forces the focused state styling. */
8
15
  focused?: boolean;
16
+ /** Label for the input. Inherited from FormField context when nested. */
9
17
  label?: string;
18
+ /**
19
+ * Visual variant of the label text.
20
+ * @default 'body'
21
+ */
10
22
  labelVariant?: 'heading' | 'body';
23
+ /** Helper text shown below the input. Inherited from FormField context when nested. */
11
24
  helperText?: string;
25
+ /** Icon shown alongside the helper text. */
12
26
  helperIcon?: React.ComponentType;
27
+ /** Text shown when `validationStatus` is `'valid'`. Inherited from FormField context when nested. */
13
28
  validText?: string;
29
+ /** Text shown when `validationStatus` is `'invalid'`. Inherited from FormField context when nested. */
14
30
  invalidText?: string;
31
+ /**
32
+ * Placeholder text shown when the input is empty.
33
+ * @default '--:--'
34
+ */
15
35
  placeholder?: string;
36
+ /**
37
+ * Uses BottomSheetTextInput when rendering inside a bottom sheet.
38
+ * @default false
39
+ */
16
40
  inBottomSheet?: boolean;
41
+ /**
42
+ * Whether the input is required.
43
+ * @default true
44
+ */
17
45
  required?: boolean;
18
46
  /**
19
47
  * Controls how the selected time is formatted when displayed inside the input.
@@ -28,6 +56,13 @@ export interface TimePickerInputBaseProps {
28
56
  * When true (default), the picker sheet is dismissed as soon as a time is picked.
29
57
  */
30
58
  autoCloseOnSelect?: boolean;
59
+ /**
60
+ * Blocks manual keyboard entry and makes tapping anywhere on the field open the
61
+ * time picker, instead of only the trailing trigger button. Independent of
62
+ * `disabled`/`readonly`, which still disable the whole field regardless of this prop.
63
+ * @default false
64
+ */
65
+ disableManualEntry?: boolean;
31
66
  /**
32
67
  * Additional props forwarded to the underlying TimePicker instance.
33
68
  */
@@ -1,5 +1,10 @@
1
1
  import React from 'react';
2
2
  import type { TimelineProps } from './Timeline.props';
3
+ /**
4
+ * Renders a vertical sequence of TimelineItem components, connecting them with a line and
5
+ * passing each its position so start, middle, and end connectors draw correctly.
6
+ * @summary A vertical timeline of connected steps.
7
+ */
3
8
  declare const Timeline: {
4
9
  ({ children, variant, style, ...rest }: TimelineProps): React.JSX.Element;
5
10
  displayName: string;
@@ -14,6 +14,11 @@ const getItemPosition = (index, count) => {
14
14
  }
15
15
  return 'middle';
16
16
  };
17
+ /**
18
+ * Renders a vertical sequence of TimelineItem components, connecting them with a line and
19
+ * passing each its position so start, middle, and end connectors draw correctly.
20
+ * @summary A vertical timeline of connected steps.
21
+ */
17
22
  const Timeline = ({ children, variant = 'static', style, ...rest }) => {
18
23
  const childElements = React.Children.toArray(children).filter(React.isValidElement);
19
24
  return (_jsx(View, { accessibilityRole: "list", style: [styles.root, style], ...rest, children: childElements.map((child, index) => {
@@ -1,4 +1,8 @@
1
1
  import type { TimelineItemProps } from './Timeline.props';
2
+ /**
3
+ * A single step within a Timeline, showing a label, optional helper text, and a connector
4
+ * indicator. Can also be used standalone outside of Timeline.
5
+ */
2
6
  declare const TimelineItem: {
3
7
  ({ children, helperText, label, position, state, style, variant, accessibilityLabel: accessibilityLabelProp, accessible: accessibleProp, ...rest }: TimelineItemProps): import("react").JSX.Element;
4
8
  displayName: string;
@@ -4,6 +4,10 @@ import { View } from 'react-native';
4
4
  import { StyleSheet } from 'react-native-unistyles';
5
5
  import { BodyText } from '../BodyText';
6
6
  import { Icon } from '../Icon';
7
+ /**
8
+ * A single step within a Timeline, showing a label, optional helper text, and a connector
9
+ * indicator. Can also be used standalone outside of Timeline.
10
+ */
7
11
  const TimelineItem = ({ children, helperText, label, position = 'single', state = 'incomplete', style, variant = 'static', accessibilityLabel: accessibilityLabelProp, accessible: accessibleProp, ...rest }) => {
8
12
  styles.useVariants({ position, state, variant });
9
13
  const hasCustomContent = Boolean(children);
@@ -2,6 +2,10 @@ import React from 'react';
2
2
  import type { ToastContextValue, ToastProviderProps } from './Toast.props';
3
3
  declare const ToastContext: React.Context<ToastContextValue | undefined>;
4
4
  export declare const useToastContext: () => ToastContextValue;
5
+ /**
6
+ * Renders and manages toast notifications for its subtree. Mount once near the
7
+ * app root, then trigger toasts anywhere below it via `useToast()`.
8
+ */
5
9
  export declare const ToastProvider: React.FC<ToastProviderProps>;
6
10
  export declare const useToast: () => ToastContextValue;
7
11
  export default ToastContext;
@@ -10,6 +10,10 @@ export const useToastContext = () => {
10
10
  throw new Error('useToastContext must be used within ToastProvider');
11
11
  return ctx;
12
12
  };
13
+ /**
14
+ * Renders and manages toast notifications for its subtree. Mount once near the
15
+ * app root, then trigger toasts anywhere below it via `useToast()`.
16
+ */
13
17
  export const ToastProvider = ({ children, safeAreaPadding = true, }) => {
14
18
  const [toasts, setToasts] = useState([]);
15
19
  const timers = useRef({});
@@ -1,6 +1,8 @@
1
1
  import type { ReactNode } from 'react';
2
2
  export interface ToastOptions {
3
+ /** Custom ID for the toast; auto-generated when omitted. */
3
4
  id?: string;
5
+ /** The main message to display. */
4
6
  text: string | ReactNode;
5
7
  /** Optional action text to display as a link */
6
8
  actionText?: string;
@@ -23,7 +25,12 @@ export interface ToastInstance extends ToastOptions {
23
25
  duration: number;
24
26
  }
25
27
  export interface ToastProviderProps {
28
+ /** App content to render below the toast stack. */
26
29
  children: ReactNode;
30
+ /**
31
+ * Whether to pad the toast stack for the device's safe area insets.
32
+ * @default true
33
+ */
27
34
  safeAreaPadding?: boolean;
28
35
  }
29
36
  export interface ToastContextValue {
@@ -9,6 +9,10 @@ export declare const ToggleButtonIcon: import("react").ForwardRefExoticComponent
9
9
  }> & import("..").IconProps & {
10
10
  toggled: boolean;
11
11
  }>;
12
+ /**
13
+ * A pressable button that switches between an on and off state, such as for a single
14
+ * standalone setting.
15
+ */
12
16
  declare const ToggleButton: {
13
17
  ({ text, toggled, onToggle, ...props }: ToggleButtonProps): import("react").JSX.Element;
14
18
  displayName: string;
@@ -14,6 +14,10 @@ export const ToggleButtonText = ToggleButtonComponent.Text;
14
14
  export const ToggleButtonIcon = ToggleButtonComponent.Icon;
15
15
  ToggleButtonText.displayName = 'ToggleButtonText';
16
16
  ToggleButtonIcon.displayName = 'ToggleButtonIcon';
17
+ /**
18
+ * A pressable button that switches between an on and off state, such as for a single
19
+ * standalone setting.
20
+ */
17
21
  const ToggleButton = ({ text, toggled = false, onToggle, ...props }) => {
18
22
  return (_jsxs(ToggleButtonComponent, { toggled: toggled, onToggle: onToggle, ...props, children: [toggled && _jsx(ToggleButtonIcon, { toggled: toggled }), _jsx(ToggleButtonText, { toggled: toggled, children: text })] }));
19
23
  };
@@ -1,6 +1,12 @@
1
1
  import type { PressableProps } from 'react-native';
2
2
  export interface ToggleButtonProps extends PressableProps {
3
+ /** The text label of the button. */
3
4
  text?: string;
5
+ /**
6
+ * Whether the button is in the toggled (pressed/selected) state.
7
+ * @default false
8
+ */
4
9
  toggled?: boolean;
10
+ /** Called with the new toggled state whenever the button is pressed. */
5
11
  onToggle?: (toggled: boolean) => void;
6
12
  }
@@ -1,9 +1,17 @@
1
1
  import ToggleButtonCardProps from './ToggleButtonCard.props';
2
2
  import ToggleButtonCardGroupProps from './ToggleButtonCardGroup.props';
3
+ /**
4
+ * Groups a set of `ToggleButtonCard`s so only one can be selected at a time, laid out as a
5
+ * flexbox row or a grid. Use it for forms or surveys that present multiple selectable options.
6
+ */
3
7
  declare const ToggleButtonCardGroup: {
4
8
  ({ onChange, onValueChange, ...props }: ToggleButtonCardGroupProps): import("react").JSX.Element;
5
9
  displayName: string;
6
10
  };
11
+ /**
12
+ * A selectable card used as a single option within a `ToggleButtonCardGroup`. Use it to let
13
+ * users pick one option from a set of predefined choices in forms or surveys.
14
+ */
7
15
  declare const ToggleButtonCard: {
8
16
  ({ children, contentStyle, ...props }: ToggleButtonCardProps): import("react").JSX.Element;
9
17
  displayName: string;
@@ -12,11 +12,19 @@ const ToggleButtonCardComponent = createRadio({
12
12
  Label: () => null,
13
13
  });
14
14
  const ToggleButtonCardGroupComponent = ToggleButtonCardComponent.Group;
15
+ /**
16
+ * Groups a set of `ToggleButtonCard`s so only one can be selected at a time, laid out as a
17
+ * flexbox row or a grid. Use it for forms or surveys that present multiple selectable options.
18
+ */
15
19
  const ToggleButtonCardGroup = ({ onChange, onValueChange, ...props }) => (_jsx(ToggleButtonCardGroupComponent, { ...props, onChange: (value) => {
16
20
  onChange?.(value);
17
21
  onValueChange?.(value);
18
22
  } }));
19
23
  ToggleButtonCardGroup.displayName = 'ToggleButtonCardGroup';
24
+ /**
25
+ * A selectable card used as a single option within a `ToggleButtonCardGroup`. Use it to let
26
+ * users pick one option from a set of predefined choices in forms or surveys.
27
+ */
20
28
  const ToggleButtonCard = ({ children, contentStyle, ...props }) => {
21
29
  const { computedStyles } = useStyleProps(props);
22
30
  return (_jsx(ToggleButtonCardComponent, { ...props, children: !!children && _jsx(View, { style: [computedStyles, contentStyle], children: children }) }));
@@ -1,15 +1,24 @@
1
1
  import type { PressableProps, ViewProps, ViewStyle } from 'react-native';
2
2
  import { SpaceValue } from '../../types';
3
3
  interface ToggleButtonCardProps extends Omit<PressableProps, 'children'> {
4
+ /** The value used for the toggle button, returned on form submission. */
4
5
  value: string;
6
+ /** Called when the state of the toggle button changes. */
5
7
  onChange?: (isSelected: boolean) => void;
6
8
  children?: ViewProps['children'];
9
+ /** The label to be displayed next to the toggle button. */
7
10
  label?: string;
11
+ /** Flex direction. */
8
12
  flexDirection?: ViewStyle['flexDirection'];
13
+ /** Flex wrap. */
9
14
  flexWrap?: ViewStyle['flexWrap'];
15
+ /** Align items. */
10
16
  alignItems?: ViewStyle['alignItems'];
17
+ /** Justify content. */
11
18
  justifyContent?: ViewStyle['justifyContent'];
19
+ /** Style applied to the content wrapper around `children`. */
12
20
  contentStyle?: ViewStyle;
21
+ /** Gap between child elements. */
13
22
  gap?: SpaceValue;
14
23
  }
15
24
  export default ToggleButtonCardProps;
@@ -2,22 +2,37 @@ import { ViewProps, ViewStyle } from 'react-native';
2
2
  import { space } from '../../tokens';
3
3
  import { GridProps } from '../Grid';
4
4
  type ToggleButtonCardGroupBaseProps = {
5
+ /** The value of the currently selected toggle button card. */
5
6
  value?: string;
7
+ /** Called when the selected toggle button card changes. */
6
8
  onValueChange?: (value: string) => void;
7
9
  /**
10
+ * Called when any child ToggleButtonCard is checked or unchecked.
8
11
  * @deprecated Use `onValueChange` instead.
9
12
  */
10
13
  onChange?: (value: string) => void;
14
+ /**
15
+ * Gap between child elements.
16
+ * @default '200'
17
+ */
11
18
  gap?: keyof typeof space;
12
19
  } & ViewProps;
13
20
  type ToggleButtonCardGroupFlexProps = {
14
21
  columns?: never;
22
+ /**
23
+ * Flex direction.
24
+ * @default 'row'
25
+ */
15
26
  flexDirection?: ViewStyle['flexDirection'];
27
+ /** Flex wrap. */
16
28
  flexWrap?: ViewStyle['flexWrap'];
29
+ /** Align items. */
17
30
  alignItems?: ViewStyle['alignItems'];
31
+ /** Justify content. */
18
32
  justifyContent?: ViewStyle['justifyContent'];
19
33
  };
20
34
  type ToggleButtonCardGroupGridProps = {
35
+ /** Number of grid columns. When set, the group uses a grid layout instead of flexbox. */
21
36
  columns: GridProps['columns'];
22
37
  flexDirection?: never;
23
38
  flexWrap?: never;
@@ -1,4 +1,9 @@
1
1
  import { UnstyledIconButtonProps } from './UnstyledIconButton.props';
2
+ /**
3
+ * A pressable icon with no default visual styling, used as a building block for buttons that
4
+ * need bespoke appearance (such as input adornments) while keeping button accessibility and
5
+ * loading behaviour.
6
+ */
2
7
  declare const UnstyledIconButton: {
3
8
  ({ icon, disabled, pressed, size, inverted, iconStyle, ...props }: UnstyledIconButtonProps): import("react").JSX.Element;
4
9
  displayName: string;
@@ -15,6 +15,11 @@ const UnstyledIconButtonSpinner = UnstyledIconButtonComponent.Spinner;
15
15
  const UnstyledIconButtonIcon = UnstyledIconButtonComponent.Icon;
16
16
  UnstyledIconButtonSpinner.displayName = 'UnstyledIconButtonSpinner';
17
17
  UnstyledIconButtonIcon.displayName = 'UnstyledIconButtonIcon';
18
+ /**
19
+ * A pressable icon with no default visual styling, used as a building block for buttons that
20
+ * need bespoke appearance (such as input adornments) while keeping button accessibility and
21
+ * loading behaviour.
22
+ */
18
23
  const UnstyledIconButton = ({ icon, disabled = false, pressed, size = 'md', inverted = false, iconStyle, ...props }) => {
19
24
  const { disabled: groupDisabled, loading: groupLoading } = useButtonGroupContext();
20
25
  const { loading, accessibilityRole = 'button', accessible = true, focusable = true, importantForAccessibility = 'yes', ...restProps } = props;
@@ -3,12 +3,29 @@ import type { PressableProps, ViewProps } from 'react-native';
3
3
  import { ColorValue } from '../../types';
4
4
  export type UnstyledIconButtonProps = {
5
5
  disabled?: boolean;
6
+ /** Whether the button is currently pressed. */
6
7
  pressed?: boolean;
8
+ /**
9
+ * The icon component displayed on the button.
10
+ */
7
11
  icon: ComponentType;
12
+ /**
13
+ * If `true`, the button will show a spinner.
14
+ * @default false
15
+ */
8
16
  loading?: boolean;
17
+ /**
18
+ * The size of the button.
19
+ * @default 'md'
20
+ */
9
21
  size?: 'sm' | 'md';
22
+ /**
23
+ * If `true`, the button colours will be inverted.
24
+ * @default false
25
+ */
10
26
  inverted?: boolean;
11
27
  children?: React.ReactNode;
28
+ /** Style applied to the icon. */
12
29
  iconStyle?: ViewProps['style'] & {
13
30
  color?: ColorValue;
14
31
  };
@@ -1,3 +1,7 @@
1
1
  import type { VerificationInputHandle, VerificationInputProps } from './VerificationInput.props';
2
+ /**
3
+ * Captures a one-time password or other verification code as a sequence of single-character slots.
4
+ * Use it for OTP and SMS/email verification flows.
5
+ */
2
6
  declare const VerificationInput: import("react").ForwardRefExoticComponent<VerificationInputProps & import("react").RefAttributes<VerificationInputHandle>>;
3
7
  export default VerificationInput;
@@ -6,6 +6,10 @@ import { useFormFieldAccessibility } from '../../hooks';
6
6
  import { FormField } from '../FormField';
7
7
  import { getNextIndexFromValueChange } from './VerificationInput.utils';
8
8
  import { VerificationInputSlot } from './VerificationInputSlot';
9
+ /**
10
+ * Captures a one-time password or other verification code as a sequence of single-character slots.
11
+ * Use it for OTP and SMS/email verification flows.
12
+ */
9
13
  const VerificationInput = forwardRef(({ value = '', onChangeText, label, labelVariant = 'body', helperText, helperIcon, validationStatus = 'initial', validText, invalidText, disabled = false, readonly = false, secureTextEntry = false, autoFocus = false, style, testID, ...props }, ref) => {
10
14
  const length = 6;
11
15
  const inputRef = useRef(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.36.1",
3
+ "version": "0.36.3",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -59,6 +59,7 @@
59
59
  "@vitest/browser": "^3.2.4",
60
60
  "@vitest/coverage-v8": "^3.2.4",
61
61
  "globals": "^15.15.0",
62
+ "oversight-lint": "^0.7.0",
62
63
  "playwright": "^1.59.1",
63
64
  "prismjs": "^1.30.0",
64
65
  "react": "19.2.3",
@@ -75,15 +76,16 @@
75
76
  "react-native-worklets": "0.10.1",
76
77
  "remark-gfm": "^4.0.1",
77
78
  "storybook": "^10.5.6",
79
+ "storybook-addon-oversight": "^0.7.0",
78
80
  "vite": "^7.1.3",
79
81
  "vite-plugin-svgr": "^4.5.0",
80
82
  "vitest": "^4.1.7",
81
- "@utilitywarehouse/hearth-react-icons": "^0.9.2",
82
83
  "@utilitywarehouse/hearth-fonts": "^0.1.1",
83
- "@utilitywarehouse/hearth-svg-assets": "^0.6.6",
84
+ "@utilitywarehouse/hearth-react-icons": "^0.9.2",
84
85
  "@utilitywarehouse/hearth-react-native-icons": "^0.9.2",
85
86
  "@utilitywarehouse/hearth-storybook-utils": "0.0.0",
86
- "@utilitywarehouse/hearth-tokens": "^0.4.6"
87
+ "@utilitywarehouse/hearth-svg-assets": "^0.6.6",
88
+ "@utilitywarehouse/hearth-tokens": "^0.4.7"
87
89
  },
88
90
  "peerDependencies": {
89
91
  "@gorhom/bottom-sheet": ">=5.0.0",
@@ -115,6 +117,7 @@
115
117
  "dev": "storybook dev -p 6006",
116
118
  "dev:docs": "storybook dev -p 6002 --no-open",
117
119
  "build:storybook": "storybook build",
118
- "build:storybook:docs": "storybook build --docs"
120
+ "build:storybook:docs": "storybook build --docs",
121
+ "lint:oversight": "oversight"
119
122
  }
120
123
  }
@@ -24,11 +24,17 @@ The `DatePicker` component presents a calendar experience in a bottom sheet so p
24
24
  <View style={Platform.OS === 'web' ? { width: 400, height: 400 } : {}}>
25
25
  <ViewWrap>
26
26
  <Button onPress={() => modalRef.current?.present()}>Show Date Picker</Button>
27
+ <BodyText>
28
+ {confirmedDate ? `Confirmed: ${dayjs(confirmedDate).format('YYYY-MM-DD')}` : 'Not confirmed'}
29
+ </BodyText>
27
30
  <DatePicker
28
31
  ref={modalRef}
29
32
  mode="single"
30
33
  date={selected}
31
- onChange={({ date }) => setSelected(date)}
34
+ onChange={({ date }) => {
35
+ setSelected(date);
36
+ setConfirmedDate(date);
37
+ }}
32
38
  onCancel={() => setSelected(undefined)}
33
39
  />
34
40
  </ViewWrap>
@@ -14,6 +14,7 @@
14
14
  <View style={Platform.OS === 'web' ? { width: 400, height: 400 } : {}}>
15
15
  <ViewWrap>
16
16
  <Button onPress={() => modalRef.current?.present()}>Show Time Picker</Button>
17
+ <BodyText>{selected ? 'Confirmed' : 'Not confirmed'}</BodyText>
17
18
  <TimePicker
18
19
  ref={modalRef}
19
20
  date={selected}
@@ -1,7 +1,7 @@
1
1
  # Hearth React Native
2
2
 
3
3
  React Native component library for building UIs at Utility Warehouse.<br/>
4
- Current version: v0.36.1
4
+ Current version: v0.36.3
5
5
 
6
6
  Hearth React Native is a comprehensive design system library for React Native, providing reusable components, consistent styling, and tools to streamline UI development. It is built to enhance productivity and maintain design consistency across projects.
7
7