@utilitywarehouse/hearth-react-native 0.3.0 → 0.4.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.
- package/.storybook/preview.tsx +3 -0
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +3 -1
- package/CHANGELOG.md +22 -0
- package/build/components/Alert/AlertCloseButton.js +25 -3
- package/build/components/Alert/AlertIcon.js +17 -1
- package/build/components/Alert/AlertIconButton.js +27 -1
- package/build/components/Alert/AlertLink.js +47 -1
- package/build/components/Alert/AlertText.d.ts +1 -1
- package/build/components/Alert/AlertText.js +26 -2
- package/build/components/Alert/AlertTitle.d.ts +1 -1
- package/build/components/Alert/AlertTitle.js +26 -2
- package/build/components/Badge/BadgeIcon.js +72 -0
- package/build/components/Badge/BadgeText.js +72 -0
- package/build/components/Button/ButtonRoot.js +1 -0
- package/build/components/Checkbox/Checkbox.d.ts +2 -2
- package/build/components/Checkbox/Checkbox.js +11 -10
- package/build/components/Checkbox/Checkbox.props.d.ts +3 -1
- package/build/components/Checkbox/CheckboxIcon.js +1 -1
- package/build/components/Checkbox/CheckboxImage.d.ts +6 -0
- package/build/components/Checkbox/CheckboxImage.js +5 -0
- package/build/components/Checkbox/CheckboxTileRoot.js +1 -1
- package/build/components/Checkbox/index.d.ts +3 -2
- package/build/components/Checkbox/index.js +2 -1
- package/build/components/CurrencyInput/CurrencyInput.js +1 -1
- package/build/components/DatePicker/DatePicker.context.d.ts +19 -0
- package/build/components/DatePicker/DatePicker.context.js +3 -0
- package/build/components/DatePicker/DatePicker.d.ts +19 -0
- package/build/components/DatePicker/DatePicker.js +479 -0
- package/build/components/DatePicker/DatePicker.props.d.ts +125 -0
- package/build/components/DatePicker/DatePicker.props.js +1 -0
- package/build/components/DatePicker/DatePickerCalendar.d.ts +2 -0
- package/build/components/DatePicker/DatePickerCalendar.js +28 -0
- package/build/components/DatePicker/DatePickerDay.d.ts +11 -0
- package/build/components/DatePicker/DatePickerDay.js +242 -0
- package/build/components/DatePicker/DatePickerDays.d.ts +2 -0
- package/build/components/DatePicker/DatePickerDays.js +157 -0
- package/build/components/DatePicker/DatePickerFooter.d.ts +2 -0
- package/build/components/DatePicker/DatePickerFooter.js +23 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerHeader.props.d.ts +8 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerHeader.props.js +1 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerMonthButton.d.ts +2 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerMonthButton.js +14 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerNextButton.d.ts +2 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerNextButton.js +32 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerPrevButton.d.ts +2 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerPrevButton.js +32 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerSelectors.d.ts +6 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerSelectors.js +64 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerTimeButton.d.ts +1 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerTimeButton.js +22 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerYearButton.d.ts +2 -0
- package/build/components/DatePicker/DatePickerHeader/DatePickerYearButton.js +25 -0
- package/build/components/DatePicker/DatePickerHeader/index.d.ts +3 -0
- package/build/components/DatePicker/DatePickerHeader/index.js +30 -0
- package/build/components/DatePicker/DatePickerMonths.d.ts +2 -0
- package/build/components/DatePicker/DatePickerMonths.js +69 -0
- package/build/components/DatePicker/DatePickerWeekdays.d.ts +8 -0
- package/build/components/DatePicker/DatePickerWeekdays.js +26 -0
- package/build/components/DatePicker/DatePickerYears.d.ts +2 -0
- package/build/components/DatePicker/DatePickerYears.js +83 -0
- package/build/components/DatePicker/TimePicker.d.ts +3 -0
- package/build/components/DatePicker/TimePicker.js +84 -0
- package/build/components/DatePicker/enums.d.ts +12 -0
- package/build/components/DatePicker/enums.js +12 -0
- package/build/components/DatePicker/index.d.ts +4 -0
- package/build/components/DatePicker/index.js +3 -0
- package/build/components/DatePicker/polyfill.d.ts +0 -0
- package/build/components/DatePicker/polyfill.js +22 -0
- package/build/components/DatePicker/time-picker/animated-math.d.ts +4 -0
- package/build/components/DatePicker/time-picker/animated-math.js +19 -0
- package/build/components/DatePicker/time-picker/period-native.d.ts +6 -0
- package/build/components/DatePicker/time-picker/period-native.js +17 -0
- package/build/components/DatePicker/time-picker/period-picker.d.ts +6 -0
- package/build/components/DatePicker/time-picker/period-picker.js +10 -0
- package/build/components/DatePicker/time-picker/period-web.d.ts +6 -0
- package/build/components/DatePicker/time-picker/period-web.js +21 -0
- package/build/components/DatePicker/time-picker/wheel-native.d.ts +8 -0
- package/build/components/DatePicker/time-picker/wheel-native.js +19 -0
- package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +2 -0
- package/build/components/DatePicker/time-picker/wheel-picker/index.js +2 -0
- package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +16 -0
- package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +97 -0
- package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +21 -0
- package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +88 -0
- package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +23 -0
- package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +21 -0
- package/build/components/DatePicker/time-picker/wheel-web.d.ts +8 -0
- package/build/components/DatePicker/time-picker/wheel-web.js +148 -0
- package/build/components/DatePicker/time-picker/wheel.d.ts +8 -0
- package/build/components/DatePicker/time-picker/wheel.js +10 -0
- package/build/components/DatePicker/utils.d.ts +212 -0
- package/build/components/DatePicker/utils.js +391 -0
- package/build/components/DatePickerInput/DatePickerInput.d.ts +6 -0
- package/build/components/DatePickerInput/DatePickerInput.js +126 -0
- package/build/components/DatePickerInput/DatePickerInput.props.d.ts +47 -0
- package/build/components/DatePickerInput/DatePickerInput.props.js +1 -0
- package/build/components/DatePickerInput/DatePickerInputDoneButton.d.ts +8 -0
- package/build/components/DatePickerInput/DatePickerInputDoneButton.js +19 -0
- package/build/components/DatePickerInput/DatePickerInputDoneButton.web.d.ts +5 -0
- package/build/components/DatePickerInput/DatePickerInputDoneButton.web.js +5 -0
- package/build/components/DatePickerInput/index.d.ts +2 -0
- package/build/components/DatePickerInput/index.js +1 -0
- package/build/components/Input/InputField.d.ts +1 -1
- package/build/components/Input/InputField.js +1 -1
- package/build/components/Input/InputSlot.d.ts +1 -1
- package/build/components/Input/InputSlot.js +3 -3
- package/build/components/Link/Link.d.ts +1 -1
- package/build/components/Link/Link.js +4 -4
- package/build/components/Link/Link.props.d.ts +3 -0
- package/build/components/Radio/Radio.d.ts +2 -2
- package/build/components/Radio/Radio.js +9 -8
- package/build/components/Radio/Radio.props.d.ts +3 -1
- package/build/components/Radio/RadioImage.d.ts +6 -0
- package/build/components/Radio/RadioImage.js +5 -0
- package/build/components/Radio/RadioTileRoot.js +1 -1
- package/build/components/Radio/index.d.ts +3 -2
- package/build/components/Radio/index.js +2 -1
- package/build/components/Select/SelectOption.js +1 -7
- package/build/components/UnstyledIconButton/UnstyledIconButton.d.ts +1 -1
- package/build/components/UnstyledIconButton/UnstyledIconButton.js +5 -5
- package/build/components/UnstyledIconButton/UnstyledIconButton.props.d.ts +2 -1
- package/build/components/UnstyledIconButton/UnstyledIconButtonRoot.js +1 -1
- package/build/components/index.d.ts +2 -0
- package/build/components/index.js +2 -0
- package/build/core/themes.d.ts +12 -12
- package/build/hooks/index.d.ts +4 -3
- package/build/hooks/index.js +4 -3
- package/build/hooks/usePrevious.d.ts +1 -0
- package/build/hooks/usePrevious.js +8 -0
- package/build/hooks/useTheme.d.ts +2 -1
- package/build/hooks/useTheme.js +2 -2
- package/build/tokens/color.d.ts +12 -12
- package/build/tokens/color.js +6 -6
- package/build/tokens/components/dark/alert.d.ts +13 -0
- package/build/tokens/components/dark/alert.js +13 -0
- package/build/tokens/components/dark/checkbox.d.ts +3 -0
- package/build/tokens/components/dark/checkbox.js +3 -0
- package/build/tokens/components/dark/date-picker.d.ts +1 -0
- package/build/tokens/components/dark/date-picker.js +1 -0
- package/build/tokens/components/dark/icon-button.d.ts +7 -0
- package/build/tokens/components/dark/icon-button.js +7 -0
- package/build/tokens/components/dark/illustrations.d.ts +7 -0
- package/build/tokens/components/dark/illustrations.js +6 -0
- package/build/tokens/components/dark/index.d.ts +2 -0
- package/build/tokens/components/dark/index.js +2 -0
- package/build/tokens/components/dark/link.d.ts +5 -0
- package/build/tokens/components/dark/link.js +5 -0
- package/build/tokens/components/dark/progress-bar.d.ts +41 -0
- package/build/tokens/components/dark/progress-bar.js +40 -0
- package/build/tokens/components/dark/segmented-control.d.ts +2 -2
- package/build/tokens/components/dark/segmented-control.js +2 -2
- package/build/tokens/components/dark/table.d.ts +3 -0
- package/build/tokens/components/dark/table.js +3 -0
- package/build/tokens/components/light/alert.d.ts +13 -0
- package/build/tokens/components/light/alert.js +13 -0
- package/build/tokens/components/light/checkbox.d.ts +3 -0
- package/build/tokens/components/light/checkbox.js +3 -0
- package/build/tokens/components/light/date-picker.d.ts +1 -0
- package/build/tokens/components/light/date-picker.js +1 -0
- package/build/tokens/components/light/icon-button.d.ts +7 -0
- package/build/tokens/components/light/icon-button.js +7 -0
- package/build/tokens/components/light/illustrations.d.ts +7 -0
- package/build/tokens/components/light/illustrations.js +6 -0
- package/build/tokens/components/light/index.d.ts +2 -0
- package/build/tokens/components/light/index.js +2 -0
- package/build/tokens/components/light/link.d.ts +5 -0
- package/build/tokens/components/light/link.js +5 -0
- package/build/tokens/components/light/progress-bar.d.ts +41 -0
- package/build/tokens/components/light/progress-bar.js +40 -0
- package/build/tokens/components/light/segmented-control.d.ts +2 -2
- package/build/tokens/components/light/segmented-control.js +2 -2
- package/build/tokens/components/light/table.d.ts +3 -0
- package/build/tokens/components/light/table.js +3 -0
- package/build/tokens/index.d.ts +1 -0
- package/build/tokens/index.js +1 -0
- package/build/tokens/motion.d.ts +23 -0
- package/build/tokens/motion.js +22 -0
- package/build/tokens/primitive.d.ts +19 -0
- package/build/tokens/primitive.js +19 -0
- package/build/tokens/semantic-dark.d.ts +5 -5
- package/build/tokens/semantic-dark.js +5 -5
- package/build/tokens/semantic-light.d.ts +1 -1
- package/build/tokens/semantic-light.js +1 -1
- package/build/utils/index.d.ts +1 -0
- package/build/utils/index.js +1 -0
- package/build/utils/isEqual.d.ts +2 -0
- package/build/utils/isEqual.js +29 -0
- package/chromatic.config.json +6 -0
- package/docs/assets/bank-logo.png +0 -0
- package/docs/assets/bank-logo1.png +0 -0
- package/docs/components/AllComponents.web.tsx +43 -1
- package/docs/components/ViewWrap.tsx +32 -0
- package/docs/components/index.ts +7 -7
- package/docs/getting-started.mdx +6 -6
- package/docs/introduction.mdx +3 -3
- package/package.json +16 -12
- package/src/components/Alert/AlertCloseButton.tsx +33 -5
- package/src/components/Alert/AlertIcon.tsx +17 -1
- package/src/components/Alert/AlertIconButton.tsx +37 -4
- package/src/components/Alert/AlertLink.tsx +52 -1
- package/src/components/Alert/AlertText.tsx +28 -3
- package/src/components/Alert/AlertTitle.tsx +28 -3
- package/src/components/Badge/BadgeIcon.tsx +72 -0
- package/src/components/Badge/BadgeText.tsx +72 -0
- package/src/components/Button/ButtonRoot.tsx +1 -0
- package/src/components/Checkbox/Checkbox.docs.mdx +45 -7
- package/src/components/Checkbox/Checkbox.props.ts +3 -1
- package/src/components/Checkbox/Checkbox.stories.tsx +37 -1
- package/src/components/Checkbox/Checkbox.tsx +12 -9
- package/src/components/Checkbox/CheckboxIcon.tsx +1 -1
- package/src/components/Checkbox/CheckboxImage.tsx +9 -0
- package/src/components/Checkbox/CheckboxTileRoot.tsx +1 -1
- package/src/components/Checkbox/index.ts +3 -2
- package/src/components/CurrencyInput/CurrencyInput.tsx +2 -1
- package/src/components/DatePicker/DatePicker.context.ts +23 -0
- package/src/components/DatePicker/DatePicker.docs.mdx +239 -0
- package/src/components/DatePicker/DatePicker.props.ts +139 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +98 -0
- package/src/components/DatePicker/DatePicker.tsx +669 -0
- package/src/components/DatePicker/DatePickerCalendar.tsx +41 -0
- package/src/components/DatePicker/DatePickerDay.tsx +302 -0
- package/src/components/DatePicker/DatePickerDays.tsx +241 -0
- package/src/components/DatePicker/DatePickerFooter.tsx +35 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerHeader.props.ts +10 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerMonthButton.tsx +29 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerNextButton.tsx +46 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerPrevButton.tsx +46 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerSelectors.tsx +96 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerTimeButton.tsx +48 -0
- package/src/components/DatePicker/DatePickerHeader/DatePickerYearButton.tsx +50 -0
- package/src/components/DatePicker/DatePickerHeader/index.tsx +64 -0
- package/src/components/DatePicker/DatePickerMonths.tsx +101 -0
- package/src/components/DatePicker/DatePickerWeekdays.tsx +49 -0
- package/src/components/DatePicker/DatePickerYears.tsx +119 -0
- package/src/components/DatePicker/TimePicker.tsx +141 -0
- package/src/components/DatePicker/enums.ts +14 -0
- package/src/components/DatePicker/index.ts +13 -0
- package/src/components/DatePicker/polyfill.ts +21 -0
- package/src/components/DatePicker/time-picker/animated-math.ts +33 -0
- package/src/components/DatePicker/time-picker/period-native.tsx +34 -0
- package/src/components/DatePicker/time-picker/period-picker.tsx +16 -0
- package/src/components/DatePicker/time-picker/period-web.tsx +36 -0
- package/src/components/DatePicker/time-picker/wheel-native.tsx +37 -0
- package/src/components/DatePicker/time-picker/wheel-picker/index.ts +3 -0
- package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.tsx +132 -0
- package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.ts +22 -0
- package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.tsx +200 -0
- package/src/components/DatePicker/time-picker/wheel-web.tsx +181 -0
- package/src/components/DatePicker/time-picker/wheel.tsx +18 -0
- package/src/components/DatePicker/utils.ts +549 -0
- package/src/components/DatePickerInput/DatePickerInput.docs.mdx +237 -0
- package/src/components/DatePickerInput/DatePickerInput.props.ts +50 -0
- package/src/components/DatePickerInput/DatePickerInput.stories.tsx +178 -0
- package/src/components/DatePickerInput/DatePickerInput.tsx +265 -0
- package/src/components/DatePickerInput/DatePickerInputDoneButton.tsx +42 -0
- package/src/components/DatePickerInput/DatePickerInputDoneButton.web.tsx +7 -0
- package/src/components/DatePickerInput/index.ts +2 -0
- package/src/components/Icon/Icon.stories.tsx +4 -3
- package/src/components/IconContainer/IconContainer.docs.mdx +4 -4
- package/src/components/Input/InputField.tsx +0 -2
- package/src/components/Input/InputSlot.tsx +14 -3
- package/src/components/Link/Link.props.ts +3 -0
- package/src/components/Link/Link.tsx +12 -6
- package/src/components/List/List.docs.mdx +24 -23
- package/src/components/Modal/Modal.stories.tsx +2 -30
- package/src/components/Radio/Radio.docs.mdx +96 -124
- package/src/components/Radio/Radio.props.ts +3 -1
- package/src/components/Radio/Radio.stories.tsx +47 -0
- package/src/components/Radio/Radio.tsx +10 -7
- package/src/components/Radio/RadioImage.tsx +9 -0
- package/src/components/Radio/RadioTileRoot.tsx +1 -1
- package/src/components/Radio/index.ts +3 -2
- package/src/components/Select/Select.docs.mdx +6 -6
- package/src/components/Select/Select.stories.tsx +7 -7
- package/src/components/Select/SelectOption.tsx +4 -10
- package/src/components/UnstyledIconButton/UnstyledIconButton.props.ts +2 -1
- package/src/components/UnstyledIconButton/UnstyledIconButton.tsx +23 -5
- package/src/components/UnstyledIconButton/UnstyledIconButtonRoot.tsx +7 -3
- package/src/components/index.ts +2 -0
- package/src/hooks/index.ts +4 -3
- package/src/hooks/usePrevious.ts +9 -0
- package/src/hooks/useTheme.ts +4 -3
- package/src/tokens/color.ts +6 -6
- package/src/tokens/components/dark/alert.ts +13 -0
- package/src/tokens/components/dark/checkbox.ts +3 -0
- package/src/tokens/components/dark/date-picker.ts +1 -0
- package/src/tokens/components/dark/icon-button.ts +7 -0
- package/src/tokens/components/dark/illustrations.ts +7 -0
- package/src/tokens/components/dark/index.ts +2 -0
- package/src/tokens/components/dark/link.ts +5 -0
- package/src/tokens/components/dark/progress-bar.ts +41 -0
- package/src/tokens/components/dark/segmented-control.ts +2 -2
- package/src/tokens/components/dark/table.ts +3 -0
- package/src/tokens/components/light/alert.ts +13 -0
- package/src/tokens/components/light/checkbox.ts +3 -0
- package/src/tokens/components/light/date-picker.ts +1 -0
- package/src/tokens/components/light/icon-button.ts +7 -0
- package/src/tokens/components/light/illustrations.ts +7 -0
- package/src/tokens/components/light/index.ts +2 -0
- package/src/tokens/components/light/link.ts +5 -0
- package/src/tokens/components/light/progress-bar.ts +41 -0
- package/src/tokens/components/light/segmented-control.ts +2 -2
- package/src/tokens/components/light/table.ts +3 -0
- package/src/tokens/index.ts +1 -0
- package/src/tokens/motion.ts +23 -0
- package/src/tokens/primitive.ts +19 -0
- package/src/tokens/semantic-dark.ts +5 -5
- package/src/tokens/semantic-light.ts +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/isEqual.ts +30 -0
- package/docs/assets/react-native-pig.png +0 -0
- package/docs/components/AdvancedRadioExample.tsx +0 -126
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { Canvas, Controls, Meta } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { Button, Center } from '../../';
|
|
3
|
+
import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
|
|
4
|
+
import * as Stories from './DatePicker.stories';
|
|
5
|
+
|
|
6
|
+
<ViewFigmaButton url="https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=3725-357" />
|
|
7
|
+
|
|
8
|
+
<Meta title="Components / Date Picker" />
|
|
9
|
+
|
|
10
|
+
<BackToTopButton />
|
|
11
|
+
|
|
12
|
+
# Date Picker
|
|
13
|
+
|
|
14
|
+
The `DatePicker` component presents a calendar experience in a bottom sheet so people can choose one or more dates without leaving the current screen. It supports single-day, ranged, and multi-date selection while respecting locale, calendar, and availability rules.
|
|
15
|
+
|
|
16
|
+
- [Playground](#playground)
|
|
17
|
+
- [Usage](#usage)
|
|
18
|
+
- [Props](#props)
|
|
19
|
+
- [`DatePicker`](#datepicker)
|
|
20
|
+
- [Change handlers](#change-handlers)
|
|
21
|
+
- [Imperative API](#imperative-api)
|
|
22
|
+
- [Examples](#examples)
|
|
23
|
+
- [Range selection](#range-selection)
|
|
24
|
+
- [Multiple selection](#multiple-selection)
|
|
25
|
+
- [Integration notes](#integration-notes)
|
|
26
|
+
- [Accessibility](#accessibility)
|
|
27
|
+
- [Screen reader support](#screen-reader-support)
|
|
28
|
+
- [Keyboard navigation](#keyboard-navigation)
|
|
29
|
+
- [Best practices](#best-practices)
|
|
30
|
+
|
|
31
|
+
## Playground
|
|
32
|
+
|
|
33
|
+
<Canvas of={Stories.Playground} />
|
|
34
|
+
|
|
35
|
+
<Controls of={Stories.Playground} />
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Use the `DatePicker` with a ref so you can present and dismiss the bottom sheet when people tap a trigger like a button or form field. The picker respects the locale and calendar you provide and can be configured to limit which dates are selectable.
|
|
40
|
+
|
|
41
|
+
<UsageWrap>
|
|
42
|
+
<Center>
|
|
43
|
+
<Button onPress={() => {}}>Pick a date</Button>
|
|
44
|
+
</Center>
|
|
45
|
+
</UsageWrap>
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import { useRef, useState } from 'react';
|
|
49
|
+
import {
|
|
50
|
+
BottomSheetModalProvider,
|
|
51
|
+
Button,
|
|
52
|
+
DatePicker,
|
|
53
|
+
type DateType,
|
|
54
|
+
} from '@utilitywarehouse/hearth-react-native';
|
|
55
|
+
|
|
56
|
+
const BookingDates = () => {
|
|
57
|
+
const pickerRef = useRef(null);
|
|
58
|
+
const [selected, setSelected] = useState<DateType>();
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<BottomSheetModalProvider>
|
|
62
|
+
<Button onPress={() => pickerRef.current?.present()}>Choose booking date</Button>
|
|
63
|
+
|
|
64
|
+
<DatePicker
|
|
65
|
+
ref={pickerRef}
|
|
66
|
+
mode="single"
|
|
67
|
+
date={selected}
|
|
68
|
+
onChange={({ date }) => setSelected(date)}
|
|
69
|
+
onCancel={() => setSelected(undefined)}
|
|
70
|
+
minDate={new Date()}
|
|
71
|
+
/>
|
|
72
|
+
</BottomSheetModalProvider>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Props
|
|
78
|
+
|
|
79
|
+
### `DatePicker`
|
|
80
|
+
|
|
81
|
+
The `DatePicker` extends the `BottomSheetModal` component. The table below highlights the most frequently used props.
|
|
82
|
+
|
|
83
|
+
| Prop | Type | Default | Description |
|
|
84
|
+
| -------------------- | --------------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------- |
|
|
85
|
+
| `mode` | `'single' \| 'range' \| 'multiple'` | `'single'` | Controls whether the picker returns one date, a start/end range, or multiple discrete dates. |
|
|
86
|
+
| `timeZone` | `string` | `-` | IANA time zone identifier applied when normalising and comparing dates. |
|
|
87
|
+
| `date` | `DateType` | `-` | Selected date in single mode. |
|
|
88
|
+
| `startDate` | `DateType` | `-` | Range start value in range mode. |
|
|
89
|
+
| `endDate` | `DateType` | `-` | Range end value in range mode. |
|
|
90
|
+
| `dates` | `DateType[]` | `-` | Selected dates in multiple mode. |
|
|
91
|
+
| `min` | `number` | `-` | Minimum length of a selected range (in days) when using range mode. |
|
|
92
|
+
| `max` | `number` | `-` | Maximum length of a selected range (in days) or the maximum number of selected dates in multiple mode. |
|
|
93
|
+
| `onChange` | `SingleChange \| RangeChange \| MultiChange` | `-` | Callback fired after a selection changes. |
|
|
94
|
+
| `minDate` | `DateType` | `-` | Earliest selectable date. Values before this are disabled. |
|
|
95
|
+
| `maxDate` | `DateType` | `-` | Latest selectable date. Values after this are disabled. |
|
|
96
|
+
| `enabledDates` | `DateType[] \| ((date: DateType) => boolean)` | `-` | List or predicate that marks which dates can be chosen. |
|
|
97
|
+
| `disabledDates` | `DateType[] \| ((date: DateType) => boolean)` | `-` | List or predicate that marks dates that cannot be chosen. |
|
|
98
|
+
| `firstDayOfWeek` | `number` | `1` | Index of the first weekday (0 = Sunday, 6 = Saturday). |
|
|
99
|
+
| `showOutsideDays` | `boolean` | `true` | Shows the trailing and leading days from adjacent months. |
|
|
100
|
+
| `initialView` | `'day' \| 'month' \| 'year'` | `'day'` | Determines the first calendar view when the sheet opens. |
|
|
101
|
+
| `containerHeight` | `number` | `CONTAINER_HEIGHT` | Height of the calendar container. |
|
|
102
|
+
| `weekdaysHeight` | `number` | `WEEKDAYS_HEIGHT` | Height of the weekday header row. |
|
|
103
|
+
| `navigationPosition` | `'around' \| 'right' \| 'left'` | `'right'` | Placement of the navigation controls. |
|
|
104
|
+
| `weekdaysFormat` | `'min' \| 'short' \| 'full'` | `'min'` | Formatting used for weekday labels. |
|
|
105
|
+
| `monthsFormat` | `'short' \| 'full'` | `'short'` | Formatting used for month names. |
|
|
106
|
+
| `monthCaptionFormat` | `'short' \| 'full'` | `'full'` | Formatting used for the heading above the calendar grid. |
|
|
107
|
+
| `multiRangeMode` | `boolean` | `-` | Enables an experimental range selection where users can keep choosing additional spans before confirming. |
|
|
108
|
+
| `hideHeader` | `boolean` | `-` | Hides the calendar header controls. |
|
|
109
|
+
| `hideFooter` | `boolean` | `-` | Hides the footer actions. |
|
|
110
|
+
| `hideWeekdays` | `boolean` | `-` | Removes the weekday labels row. |
|
|
111
|
+
| `disableMonthPicker` | `boolean` | `-` | Prevents switching to the month selection view. |
|
|
112
|
+
| `disableYearPicker` | `boolean` | `-` | Prevents switching to the year selection view. |
|
|
113
|
+
| `month` | `number` | `-` | Forces the calendar to display a specific month (0-11). |
|
|
114
|
+
| `year` | `number` | `-` | Forces the calendar to display a specific year. |
|
|
115
|
+
| `onMonthChange` | `(month: number) => void` | `() => {}` | Fired when the displayed month changes. |
|
|
116
|
+
| `onYearChange` | `(year: number) => void` | `() => {}` | Fired when the displayed year changes. |
|
|
117
|
+
| `onCancel` | `() => void` | `() => {}` | Fired when the cancel action is triggered from the footer. |
|
|
118
|
+
| `ref` | `Ref<BottomSheetModalMethods>` | `-` | Gives imperative access to the underlying bottom sheet for presenting or dismissing the picker. |
|
|
119
|
+
|
|
120
|
+
### Change handlers
|
|
121
|
+
|
|
122
|
+
Each selection mode provides specialised payloads when `onChange` fires:
|
|
123
|
+
|
|
124
|
+
- **Single**: `{ date: DateType }`
|
|
125
|
+
- **Range**: `{ startDate: DateType; endDate: DateType }`
|
|
126
|
+
- **Multiple**: `{ dates: DateType[]; datePressed?: DateType; change: 'added' | 'removed' | 'updated' }`
|
|
127
|
+
|
|
128
|
+
### Imperative API
|
|
129
|
+
|
|
130
|
+
Attach a ref that conforms to `BottomSheetModalMethods` so you can call `present()`, `close()`, or `dismiss()` as needed. This matches the API surface of `BottomSheetModal`.
|
|
131
|
+
|
|
132
|
+
## Examples
|
|
133
|
+
|
|
134
|
+
### Range selection
|
|
135
|
+
|
|
136
|
+
<Canvas of={Stories.Range} />
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { useRef, useState } from 'react';
|
|
140
|
+
import {
|
|
141
|
+
BottomSheetModalProvider,
|
|
142
|
+
Button,
|
|
143
|
+
DatePicker,
|
|
144
|
+
type DateType,
|
|
145
|
+
} from '@utilitywarehouse/hearth-react-native';
|
|
146
|
+
|
|
147
|
+
const Example = () => {
|
|
148
|
+
const pickerRef = useRef(null);
|
|
149
|
+
const [range, setRange] = useState<{ startDate?: DateType; endDate?: DateType }>({});
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<BottomSheetModalProvider>
|
|
153
|
+
<Button onPress={() => pickerRef.current?.present()}>Choose booking dates</Button>
|
|
154
|
+
|
|
155
|
+
<DatePicker
|
|
156
|
+
ref={pickerRef}
|
|
157
|
+
mode="range"
|
|
158
|
+
startDate={range.startDate}
|
|
159
|
+
endDate={range.endDate}
|
|
160
|
+
onChange={({ startDate, endDate }) => setRange({ startDate, endDate })}
|
|
161
|
+
onCancel={() => setRange({})}
|
|
162
|
+
minDate={new Date()}
|
|
163
|
+
min={2}
|
|
164
|
+
max={14}
|
|
165
|
+
/>
|
|
166
|
+
</BottomSheetModalProvider>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Multiple selection
|
|
172
|
+
|
|
173
|
+
<Canvas of={Stories.Multi} />
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { useRef, useState } from 'react';
|
|
177
|
+
import {
|
|
178
|
+
BottomSheetModalProvider,
|
|
179
|
+
Button,
|
|
180
|
+
DatePicker,
|
|
181
|
+
} from '@utilitywarehouse/hearth-react-native';
|
|
182
|
+
|
|
183
|
+
const Example = () => {
|
|
184
|
+
const pickerRef = useRef(null);
|
|
185
|
+
const [dates, setDates] = useState<DateType[]>([]);
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<BottomSheetModalProvider>
|
|
189
|
+
<Button onPress={() => pickerRef.current?.present()}>Choose booking dates</Button>
|
|
190
|
+
|
|
191
|
+
<DatePicker
|
|
192
|
+
ref={pickerRef}
|
|
193
|
+
mode="multiple"
|
|
194
|
+
dates={dates}
|
|
195
|
+
onChange={({ dates, datePressed, change }) => setDates(dates)}
|
|
196
|
+
onCancel={() => setDates([])}
|
|
197
|
+
minDate={new Date()}
|
|
198
|
+
min={2}
|
|
199
|
+
max={14}
|
|
200
|
+
/>
|
|
201
|
+
</BottomSheetModalProvider>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Integration notes
|
|
207
|
+
|
|
208
|
+
- Wrap your application (or the portion that renders the picker) with `BottomSheetModalProvider` so the sheet can mount correctly, especially when combining with other bottom-sheet components.
|
|
209
|
+
- Because the picker respects locale and time zone information, ensure you pass consistent values throughout your app when working with server-sourced dates.
|
|
210
|
+
- When pairing the picker with inputs like `FormField`, surface the chosen dates in the trigger control so people can review their selection after the sheet closes.
|
|
211
|
+
|
|
212
|
+
## Accessibility
|
|
213
|
+
|
|
214
|
+
The `DatePicker` is designed to be fully accessible for VoiceOver (iOS) and TalkBack (Android) users:
|
|
215
|
+
|
|
216
|
+
### Screen reader support
|
|
217
|
+
|
|
218
|
+
- **Automatic focus**: When the picker opens, screen readers automatically announce "Date picker opened" and focus on the calendar content.
|
|
219
|
+
- **Platform-optimized navigation**:
|
|
220
|
+
- On iOS, VoiceOver can freely navigate through all calendar elements.
|
|
221
|
+
- On Android, TalkBack announces "Date picker calendar" when opened, then allows navigation through child elements.
|
|
222
|
+
- **Descriptive labels**: Each interactive element has clear accessibility labels:
|
|
223
|
+
- Day buttons announce the full date: "Monday, October 8" (with "selected" appended for chosen dates).
|
|
224
|
+
- Month/year buttons announce the current month and year.
|
|
225
|
+
- Navigation buttons specify direction: "Next month", "Prev month", etc.
|
|
226
|
+
- View switcher announces: "Change to day view" or "Change to month view".
|
|
227
|
+
|
|
228
|
+
### Keyboard navigation
|
|
229
|
+
|
|
230
|
+
- All interactive controls (days, months, years, navigation) expose `accessibilityRole="button"` for proper identification.
|
|
231
|
+
- Buttons respond to standard tap/activate gestures with screen readers.
|
|
232
|
+
- The footer cancel button is fully accessible and announced properly.
|
|
233
|
+
|
|
234
|
+
### Best practices
|
|
235
|
+
|
|
236
|
+
- The picker works seamlessly within forms when triggered by accessible inputs like `DatePickerInput`.
|
|
237
|
+
- Disabled dates are marked as disabled in the accessibility tree, preventing selection attempts.
|
|
238
|
+
- The bottom sheet modal itself is marked as not accessible (`accessible={false}`) to prevent it from blocking navigation to child elements.
|
|
239
|
+
- All date announcements respect the English locale for consistency with the current implementation.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
2
|
+
import type { Dayjs } from 'dayjs';
|
|
3
|
+
import { Ref } from 'react';
|
|
4
|
+
import type { ImageStyle, TextStyle, ViewStyle } from 'react-native';
|
|
5
|
+
import type { CalendarActionKind, CalendarViews } from './enums';
|
|
6
|
+
|
|
7
|
+
export type DateType = string | number | Dayjs | Date | null | undefined;
|
|
8
|
+
|
|
9
|
+
export type CalendarType = 'gregory';
|
|
10
|
+
|
|
11
|
+
export type CalendarMode = 'single' | 'range' | 'multiple';
|
|
12
|
+
|
|
13
|
+
export type NavigationPosition = 'around' | 'right' | 'left';
|
|
14
|
+
|
|
15
|
+
export type WeekdayFormat = 'min' | 'short' | 'full';
|
|
16
|
+
|
|
17
|
+
export type MonthFormat = 'short' | 'full';
|
|
18
|
+
|
|
19
|
+
export type LocalState = {
|
|
20
|
+
date: DateType;
|
|
21
|
+
startDate: DateType;
|
|
22
|
+
endDate: DateType;
|
|
23
|
+
dates?: DateType[];
|
|
24
|
+
calendarView: CalendarViews;
|
|
25
|
+
currentDate: DateType; // used for latest state of calendar based on Month and Year
|
|
26
|
+
currentYear: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type CalendarAction = {
|
|
30
|
+
type: CalendarActionKind;
|
|
31
|
+
payload: any;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type CalendarDay = {
|
|
35
|
+
number: number;
|
|
36
|
+
text: string;
|
|
37
|
+
date: string;
|
|
38
|
+
isDisabled: boolean;
|
|
39
|
+
isCurrentMonth: boolean;
|
|
40
|
+
dayOfMonth?: number;
|
|
41
|
+
isToday: boolean;
|
|
42
|
+
isSelected: boolean;
|
|
43
|
+
inRange: boolean;
|
|
44
|
+
leftCrop: boolean;
|
|
45
|
+
rightCrop: boolean;
|
|
46
|
+
isStartOfWeek: boolean;
|
|
47
|
+
isEndOfWeek: boolean;
|
|
48
|
+
isCrop: boolean;
|
|
49
|
+
inMiddle: boolean;
|
|
50
|
+
rangeStart: boolean;
|
|
51
|
+
rangeEnd: boolean;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type CalendarWeek = {
|
|
55
|
+
index: number;
|
|
56
|
+
name: {
|
|
57
|
+
full: string;
|
|
58
|
+
short: string;
|
|
59
|
+
min: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type CalendarMonth = {
|
|
64
|
+
index: number;
|
|
65
|
+
name: {
|
|
66
|
+
full: string;
|
|
67
|
+
short: string;
|
|
68
|
+
};
|
|
69
|
+
isSelected: boolean;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type CalendarYear = {
|
|
73
|
+
number: number;
|
|
74
|
+
text: string;
|
|
75
|
+
isSelected: boolean;
|
|
76
|
+
isActivated: boolean;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type SingleChange = (params: { date: DateType }) => void;
|
|
80
|
+
|
|
81
|
+
export type RangeChange = (params: { startDate: DateType; endDate: DateType }) => void;
|
|
82
|
+
|
|
83
|
+
export type MultiChange = (params: {
|
|
84
|
+
dates: DateType[];
|
|
85
|
+
datePressed?: DateType;
|
|
86
|
+
change: 'added' | 'removed' | 'updated';
|
|
87
|
+
}) => void;
|
|
88
|
+
|
|
89
|
+
export type Styles = Partial<ViewStyle | TextStyle | ImageStyle>;
|
|
90
|
+
|
|
91
|
+
export interface DatePickerBaseProps {
|
|
92
|
+
mode?: CalendarMode;
|
|
93
|
+
timeZone?: string;
|
|
94
|
+
date?: DateType;
|
|
95
|
+
startDate?: DateType;
|
|
96
|
+
endDate?: DateType;
|
|
97
|
+
dates?: DateType[];
|
|
98
|
+
min?: number;
|
|
99
|
+
max?: number;
|
|
100
|
+
onChange?: SingleChange | RangeChange | MultiChange;
|
|
101
|
+
startYear?: number;
|
|
102
|
+
endYear?: number;
|
|
103
|
+
minDate?: DateType;
|
|
104
|
+
maxDate?: DateType;
|
|
105
|
+
enabledDates?: DateType[] | ((date: DateType) => boolean);
|
|
106
|
+
disabledDates?: DateType[] | ((date: DateType) => boolean);
|
|
107
|
+
firstDayOfWeek?: number;
|
|
108
|
+
showOutsideDays?: boolean;
|
|
109
|
+
timePicker?: boolean;
|
|
110
|
+
use12Hours?: boolean;
|
|
111
|
+
initialView?: CalendarViews;
|
|
112
|
+
containerHeight?: number;
|
|
113
|
+
weekdaysHeight?: number;
|
|
114
|
+
style?: ViewStyle;
|
|
115
|
+
navigationPosition?: NavigationPosition;
|
|
116
|
+
weekdaysFormat?: WeekdayFormat;
|
|
117
|
+
monthsFormat?: MonthFormat;
|
|
118
|
+
monthCaptionFormat?: MonthFormat;
|
|
119
|
+
multiRangeMode?: boolean;
|
|
120
|
+
hideHeader?: boolean;
|
|
121
|
+
hideFooter?: boolean;
|
|
122
|
+
hideWeekdays?: boolean;
|
|
123
|
+
disableMonthPicker?: boolean;
|
|
124
|
+
disableYearPicker?: boolean;
|
|
125
|
+
/** use to handle month and year selectors */
|
|
126
|
+
month?: number;
|
|
127
|
+
year?: number;
|
|
128
|
+
onMonthChange?: (month: number) => void;
|
|
129
|
+
onYearChange?: (year: number) => void;
|
|
130
|
+
ref?: Ref<BottomSheetModalMethods<any>>;
|
|
131
|
+
onCancel?: () => void;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type Numerals = 'latn';
|
|
135
|
+
|
|
136
|
+
export type PickerOption = {
|
|
137
|
+
value: number | string;
|
|
138
|
+
text: string;
|
|
139
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
4
|
+
import { DatePicker, DateType } from '.';
|
|
5
|
+
import { ViewWrap } from '../../../docs/components';
|
|
6
|
+
import { BottomSheetModal } from '../BottomSheet';
|
|
7
|
+
import { Button } from '../Button';
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Stories / DatePicker',
|
|
11
|
+
component: DatePicker,
|
|
12
|
+
parameters: {
|
|
13
|
+
layout: 'centered',
|
|
14
|
+
},
|
|
15
|
+
argTypes: {},
|
|
16
|
+
args: {},
|
|
17
|
+
} satisfies Meta<typeof DatePicker>;
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
|
|
21
|
+
type Story = StoryObj<typeof meta>;
|
|
22
|
+
|
|
23
|
+
export const Playground: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
mode: 'single',
|
|
26
|
+
},
|
|
27
|
+
render: () => {
|
|
28
|
+
const [selected, setSelected] = useState<DateType>();
|
|
29
|
+
const modalRef = useRef<BottomSheetModal>(null);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<View style={Platform.OS === 'web' ? { width: 400, height: 400 } : {}}>
|
|
33
|
+
<ViewWrap>
|
|
34
|
+
<Button onPress={() => modalRef.current?.present()}>Show Date Picker</Button>
|
|
35
|
+
<DatePicker
|
|
36
|
+
ref={modalRef}
|
|
37
|
+
mode="single"
|
|
38
|
+
date={selected}
|
|
39
|
+
onChange={({ date }) => setSelected(date)}
|
|
40
|
+
onCancel={() => setSelected(undefined)}
|
|
41
|
+
/>
|
|
42
|
+
</ViewWrap>
|
|
43
|
+
</View>
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Range: Story = {
|
|
49
|
+
args: {
|
|
50
|
+
mode: 'range',
|
|
51
|
+
},
|
|
52
|
+
render: () => {
|
|
53
|
+
const [range, setRange] = useState<{
|
|
54
|
+
startDate: DateType;
|
|
55
|
+
endDate: DateType;
|
|
56
|
+
}>({ startDate: undefined, endDate: undefined });
|
|
57
|
+
const modalRef = useRef<BottomSheetModal>(null);
|
|
58
|
+
return (
|
|
59
|
+
<View style={Platform.OS === 'web' ? { width: 400, height: 400 } : {}}>
|
|
60
|
+
<ViewWrap>
|
|
61
|
+
<Button onPress={() => modalRef.current?.present()}>Show Range Date Picker</Button>
|
|
62
|
+
<DatePicker
|
|
63
|
+
mode="range"
|
|
64
|
+
ref={modalRef}
|
|
65
|
+
startDate={range.startDate}
|
|
66
|
+
endDate={range.endDate}
|
|
67
|
+
onChange={params => setRange(params)}
|
|
68
|
+
onCancel={() => setRange({ startDate: undefined, endDate: undefined })}
|
|
69
|
+
/>
|
|
70
|
+
</ViewWrap>
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const Multi: Story = {
|
|
77
|
+
args: {
|
|
78
|
+
mode: 'multiple',
|
|
79
|
+
},
|
|
80
|
+
render: () => {
|
|
81
|
+
const [dates, setDates] = useState<DateType[]>([]);
|
|
82
|
+
const modalRef = useRef<BottomSheetModal>(null);
|
|
83
|
+
return (
|
|
84
|
+
<View style={Platform.OS === 'web' ? { width: 400, height: 400 } : {}}>
|
|
85
|
+
<ViewWrap>
|
|
86
|
+
<Button onPress={() => modalRef.current?.present()}>Show Multi Date Picker</Button>
|
|
87
|
+
<DatePicker
|
|
88
|
+
mode="multiple"
|
|
89
|
+
ref={modalRef}
|
|
90
|
+
dates={dates}
|
|
91
|
+
onChange={({ dates }) => setDates(dates)}
|
|
92
|
+
onCancel={() => setDates([])}
|
|
93
|
+
/>
|
|
94
|
+
</ViewWrap>
|
|
95
|
+
</View>
|
|
96
|
+
);
|
|
97
|
+
},
|
|
98
|
+
};
|