@hero-design/rn 8.94.0 → 8.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/.turbo/turbo-build.log +7 -2
  2. package/CHANGELOG.md +18 -0
  3. package/es/index.js +1744 -1322
  4. package/lib/index.js +1747 -1324
  5. package/locales/en_AU.js +10 -0
  6. package/locales/en_AU.mjs +8 -0
  7. package/locales/en_CA.js +10 -0
  8. package/locales/en_CA.mjs +8 -0
  9. package/locales/index.js +11 -0
  10. package/locales/index.mjs +9 -0
  11. package/locales/types.js +2 -0
  12. package/locales/types.mjs +1 -0
  13. package/package.json +4 -3
  14. package/rollup.config.mjs +97 -58
  15. package/src/components/DatePicker/DatePickerAndroid.tsx +34 -40
  16. package/src/components/DatePicker/DatePickerCalendar.tsx +23 -4
  17. package/src/components/DatePicker/DatePickerIOS.tsx +36 -67
  18. package/src/components/DatePicker/Dialog/AndroidDialog.tsx +68 -0
  19. package/src/components/DatePicker/Dialog/IOSDialog.tsx +91 -0
  20. package/src/components/DatePicker/Dialog/__tests__/AndroidDialog.spec.tsx +70 -0
  21. package/src/components/DatePicker/Dialog/__tests__/IOSDialog.spec.tsx +114 -0
  22. package/src/components/DatePicker/Dialog/type.ts +50 -0
  23. package/src/components/DatePicker/__tests__/DatePicker.spec.tsx +30 -1
  24. package/src/components/DatePicker/__tests__/DatePickerAndroid.spec.tsx +27 -0
  25. package/src/components/DatePicker/__tests__/DatePickerCalendar.spec.tsx +27 -0
  26. package/src/components/DatePicker/__tests__/DatePickerIOS.spec.tsx +28 -1
  27. package/src/components/DatePicker/__tests__/__snapshots__/DatePickerAndroid.spec.tsx.snap +18 -9
  28. package/src/components/DatePicker/__tests__/__snapshots__/DatePickerIOS.spec.tsx.snap +1 -0
  29. package/src/components/DatePicker/hooks/__tests__/useFormatDate.spec.ts +61 -0
  30. package/src/components/DatePicker/{useCalculateDate.tsx → hooks/useCalculateDate.tsx} +1 -1
  31. package/src/components/DatePicker/hooks/useFormatDate.ts +25 -0
  32. package/src/components/DatePicker/hooks/utils.ts +30 -0
  33. package/src/components/DatePicker/index.tsx +12 -1
  34. package/src/components/DatePicker/types.ts +15 -1
  35. package/src/components/HeroDesignProvider/index.tsx +19 -6
  36. package/src/components/LocaleProvider/__tests__/utils.specs.ts +12 -0
  37. package/src/components/LocaleProvider/context.ts +7 -0
  38. package/src/components/LocaleProvider/hooks.ts +19 -0
  39. package/src/components/LocaleProvider/index.tsx +27 -0
  40. package/src/components/LocaleProvider/utils.ts +14 -0
  41. package/src/index.ts +2 -0
  42. package/src/locales/en_AU.ts +10 -0
  43. package/src/locales/en_CA.ts +10 -0
  44. package/src/locales/index.ts +7 -0
  45. package/src/locales/types.ts +12 -0
  46. package/src/testHelpers/renderWithTheme.tsx +7 -1
  47. package/src/types.ts +4 -0
  48. package/stats/8.95.0/rn-stats.html +4842 -0
  49. package/stats/8.96.0/rn-stats.html +4842 -0
  50. package/stats/8.97.0/rn-stats.html +4842 -0
  51. package/types/components/DatePicker/DatePickerAndroid.d.ts +1 -1
  52. package/types/components/DatePicker/DatePickerCalendar.d.ts +1 -1
  53. package/types/components/DatePicker/DatePickerIOS.d.ts +1 -1
  54. package/types/components/DatePicker/Dialog/AndroidDialog.d.ts +5 -0
  55. package/types/components/DatePicker/Dialog/IOSDialog.d.ts +4 -0
  56. package/types/components/DatePicker/Dialog/type.d.ts +50 -0
  57. package/types/components/DatePicker/{useCalculateDate.d.ts → hooks/useCalculateDate.d.ts} +1 -1
  58. package/types/components/DatePicker/hooks/useFormatDate.d.ts +10 -0
  59. package/types/components/DatePicker/hooks/utils.d.ts +6 -0
  60. package/types/components/DatePicker/index.d.ts +5 -2
  61. package/types/components/DatePicker/types.d.ts +8 -1
  62. package/types/components/HeroDesignProvider/index.d.ts +5 -1
  63. package/types/components/LocaleProvider/__tests__/utils.specs.d.ts +1 -0
  64. package/types/components/LocaleProvider/context.d.ts +3 -0
  65. package/types/components/LocaleProvider/hooks.d.ts +5 -0
  66. package/types/components/LocaleProvider/index.d.ts +7 -0
  67. package/types/components/LocaleProvider/utils.d.ts +3 -0
  68. package/types/index.d.ts +2 -1
  69. package/types/locales/en_AU.d.ts +3 -0
  70. package/types/locales/en_CA.d.ts +3 -0
  71. package/types/locales/index.d.ts +5 -0
  72. package/types/locales/types.d.ts +10 -0
  73. package/types/types.d.ts +2 -1
@@ -0,0 +1,91 @@
1
+ import { MonthYearPickerViewIOS } from '@hero-design/react-native-month-year-picker';
2
+ import DateTimePicker, {
3
+ DateTimePickerEvent,
4
+ } from '@react-native-community/datetimepicker';
5
+ import React, { useState } from 'react';
6
+ import BottomSheet from '../../BottomSheet';
7
+ import Button from '../../Button';
8
+ import { useTheme } from '../../../theme';
9
+ import { StyledPickerWrapper } from '../StyledDatePicker';
10
+ import { DatePickerDialogProps } from './type';
11
+ import { getDateValue } from '../hooks/useCalculateDate';
12
+
13
+ const IOSDatePickerDialog = ({
14
+ label,
15
+ open,
16
+ onClose,
17
+ confirmLabel,
18
+ locale,
19
+ value,
20
+ minDate,
21
+ maxDate,
22
+ onChange,
23
+ testID,
24
+ variant = 'default',
25
+ supportedOrientations = ['portrait'],
26
+ }: DatePickerDialogProps) => {
27
+ const theme = useTheme();
28
+ const [selectingDate, setSelectingDate] = useState<Date>(
29
+ getDateValue(value || new Date(), minDate, maxDate)
30
+ );
31
+
32
+ return (
33
+ <BottomSheet
34
+ testID={testID}
35
+ open={open}
36
+ onRequestClose={onClose}
37
+ header={label}
38
+ footer={
39
+ <Button
40
+ variant="text"
41
+ text={confirmLabel}
42
+ onPress={() => {
43
+ if (selectingDate) {
44
+ onChange(selectingDate);
45
+ }
46
+ onClose();
47
+ }}
48
+ />
49
+ }
50
+ supportedOrientations={supportedOrientations}
51
+ >
52
+ <StyledPickerWrapper>
53
+ {variant === 'month-year' ? (
54
+ <MonthYearPickerViewIOS
55
+ value={selectingDate}
56
+ locale={locale}
57
+ minimumDate={minDate}
58
+ textColor={theme.colors.onDefaultGlobalSurface}
59
+ maximumDate={maxDate}
60
+ onChange={(date: Date | undefined) => {
61
+ if (date) {
62
+ setSelectingDate(date);
63
+ }
64
+ }}
65
+ style={{ flex: 1 }}
66
+ />
67
+ ) : null}
68
+ {variant === 'default' ? (
69
+ <DateTimePicker
70
+ locale={locale}
71
+ testID="datePickerIOS"
72
+ value={selectingDate}
73
+ minimumDate={minDate}
74
+ maximumDate={maxDate}
75
+ mode="date"
76
+ onChange={(_: DateTimePickerEvent, date: Date | undefined) => {
77
+ if (date) {
78
+ setSelectingDate(date);
79
+ }
80
+ }}
81
+ display="spinner"
82
+ style={{ flex: 1 }}
83
+ textColor={theme.colors.onDefaultGlobalSurface}
84
+ />
85
+ ) : null}
86
+ </StyledPickerWrapper>
87
+ </BottomSheet>
88
+ );
89
+ };
90
+
91
+ export default IOSDatePickerDialog;
@@ -0,0 +1,70 @@
1
+ import { fireEvent } from '@testing-library/react-native';
2
+ import React, { useState } from 'react';
3
+ import { Button } from '../../../..';
4
+ import renderWithTheme from '../../../../testHelpers/renderWithTheme';
5
+ import AndroidDialog, { AndroidDatePickerDialogProps } from '../AndroidDialog';
6
+
7
+ const AndroidDialogExample = (
8
+ props: Omit<AndroidDatePickerDialogProps, 'open' | 'onClose'>
9
+ ) => {
10
+ const [open, setOpen] = useState(false);
11
+
12
+ return (
13
+ <>
14
+ <Button onPress={() => setOpen(true)} text="Open" />
15
+ <AndroidDialog open={open} onClose={() => setOpen(false)} {...props} />
16
+ </>
17
+ );
18
+ };
19
+
20
+ describe('AndroidDialog', () => {
21
+ it('renders correctly', () => {
22
+ const onChange = jest.fn();
23
+
24
+ const { getByText, queryByTestId } = renderWithTheme(
25
+ <AndroidDialogExample
26
+ value={new Date('December 21, 1995')}
27
+ minDate={new Date('December 17, 1994')}
28
+ maxDate={new Date('December 17, 1996')}
29
+ onChange={onChange}
30
+ testID="android-dialog"
31
+ />
32
+ );
33
+
34
+ expect(queryByTestId('android-dialog')).toBeNull();
35
+
36
+ // Open date picker
37
+ fireEvent.press(getByText('Open'));
38
+ expect(queryByTestId('datePickerAndroid')).toBeVisible();
39
+
40
+ // Change date
41
+ fireEvent(
42
+ queryByTestId('datePickerAndroid'),
43
+ 'onChange',
44
+ null,
45
+ new Date('December 17, 1995')
46
+ );
47
+
48
+ expect(onChange).toBeCalledWith(new Date('December 17, 1995'));
49
+ });
50
+
51
+ it('renders month-year picker', () => {
52
+ const onChangeSpy = jest.fn();
53
+ const { queryByText, getByText } = renderWithTheme(
54
+ <AndroidDialogExample
55
+ value={new Date('December 21, 1995')}
56
+ variant="month-year"
57
+ onChange={onChangeSpy}
58
+ testID="android-dialog"
59
+ />
60
+ );
61
+
62
+ fireEvent.press(getByText('Open'));
63
+ expect(queryByText('Android month year picker')).toBeDefined();
64
+
65
+ // mock change date
66
+ fireEvent.press(getByText('Android month year picker'));
67
+ expect(queryByText('Android month year picker')).toBeNull();
68
+ expect(onChangeSpy).toBeCalledWith(new Date('2019-09-01'));
69
+ });
70
+ });
@@ -0,0 +1,114 @@
1
+ import { fireEvent } from '@testing-library/react-native';
2
+ import React, { useState } from 'react';
3
+ import type { ModalProps } from 'react-native';
4
+ import renderWithTheme from '../../../../testHelpers/renderWithTheme';
5
+ import IOSDialog from '../IOSDialog';
6
+ import { setOrientation } from '../../../../testHelpers/utils';
7
+ import { Button } from '../../../..';
8
+ import { DatePickerDialogProps } from '../type';
9
+
10
+ jest.mock('react-native/Libraries/Modal/Modal', () => {
11
+ const Modal = jest.requireActual('react-native/Libraries/Modal/Modal');
12
+ return (props: ModalProps) => <Modal {...props} />;
13
+ });
14
+
15
+ const IOSDialogExample = (
16
+ props: Omit<DatePickerDialogProps, 'open' | 'onClose'>
17
+ ) => {
18
+ const [open, setOpen] = useState(false);
19
+
20
+ return (
21
+ <>
22
+ <Button onPress={() => setOpen(true)} text="Open" />
23
+ <IOSDialog open={open} onClose={() => setOpen(false)} {...props} />
24
+ </>
25
+ );
26
+ };
27
+
28
+ describe('IOSDialog', () => {
29
+ it('renders correctly', () => {
30
+ const onChange = jest.fn();
31
+ const { getByText, queryByTestId } = renderWithTheme(
32
+ <IOSDialogExample
33
+ value={new Date('December 21, 1995')}
34
+ label="Start date"
35
+ confirmLabel="Confirm"
36
+ onChange={onChange}
37
+ testID="ios-dialog"
38
+ />
39
+ );
40
+
41
+ expect(queryByTestId('ios-dialog')).toBeNull();
42
+
43
+ // Open date picker
44
+ fireEvent.press(getByText('Open'));
45
+ expect(queryByTestId('datePickerIOS')).toBeTruthy();
46
+
47
+ // Change date
48
+ fireEvent(
49
+ queryByTestId('datePickerIOS'),
50
+ 'onChange',
51
+ null,
52
+ new Date('December 17, 1995')
53
+ );
54
+ fireEvent.press(getByText('Confirm'));
55
+
56
+ expect(onChange).toBeCalledWith(new Date('December 17, 1995'));
57
+ });
58
+
59
+ it('renders correctly in landscape mode', () => {
60
+ const onChange = jest.fn();
61
+ setOrientation('landscape');
62
+ const { getByText, queryByTestId } = renderWithTheme(
63
+ <IOSDialogExample
64
+ value={new Date('December 21, 1995')}
65
+ label="Start date"
66
+ confirmLabel="Confirm"
67
+ onChange={onChange}
68
+ supportedOrientations={['landscape']}
69
+ testID="ios-dialog"
70
+ />
71
+ );
72
+
73
+ expect(queryByTestId('ios-dialog')).toBeNull();
74
+
75
+ // Open date picker
76
+ fireEvent.press(getByText('Open'));
77
+ expect(queryByTestId('datePickerIOS')).toBeTruthy();
78
+
79
+ // Change date
80
+ fireEvent(
81
+ queryByTestId('datePickerIOS'),
82
+ 'onChange',
83
+ null,
84
+ new Date('December 17, 1995')
85
+ );
86
+ fireEvent.press(getByText('Confirm'));
87
+
88
+ expect(onChange).toBeCalledWith(new Date('December 17, 1995'));
89
+ });
90
+
91
+ it('renders month-year picker', () => {
92
+ const onChangeSpy = jest.fn();
93
+ const { queryByText, getByText } = renderWithTheme(
94
+ <IOSDialogExample
95
+ value={new Date('December 21, 1995')}
96
+ variant="month-year"
97
+ label="Start date"
98
+ confirmLabel="Confirm"
99
+ onChange={onChangeSpy}
100
+ testID="ios-dialog"
101
+ />
102
+ );
103
+
104
+ fireEvent.press(getByText('Open'));
105
+ expect(getByText('Confirm')).toBeDefined();
106
+ expect(getByText('IOS month year picker')).toBeDefined();
107
+
108
+ // mock change date
109
+ fireEvent.press(getByText('IOS month year picker'));
110
+ fireEvent.press(getByText('Confirm'));
111
+ expect(queryByText('iOS month year picker')).toBeNull();
112
+ expect(onChangeSpy).toBeCalledWith(new Date('2019-09-01'));
113
+ });
114
+ });
@@ -0,0 +1,50 @@
1
+ export interface DatePickerDialogProps {
2
+ /**
3
+ * The value of the date picker.
4
+ */
5
+ value?: Date;
6
+ /**
7
+ * The minimum date of the date picker.
8
+ */
9
+ minDate?: Date;
10
+ /**
11
+ * The maximum date of the date picker.
12
+ */
13
+ maxDate?: Date;
14
+ /**
15
+ * The function to call when the date is changed.
16
+ */
17
+ onChange: (date: Date) => void;
18
+ /**
19
+ * The test ID of the date picker.
20
+ */
21
+ testID?: string;
22
+ /**
23
+ * Whether the dialog is open
24
+ */
25
+ open: boolean;
26
+ /**
27
+ * The function to call when the dialog is closed.
28
+ */
29
+ onClose: () => void;
30
+ /**
31
+ * The variant of the date picker.
32
+ */
33
+ variant?: 'default' | 'month-year';
34
+ /**
35
+ * [iOS only] The label of the DatePicker bottom sheet.
36
+ */
37
+ label: string;
38
+ /**
39
+ * [iOS only] The confirm label of the date picker bottom sheet.
40
+ */
41
+ confirmLabel: string;
42
+ /**
43
+ * [iOS only] The supported orientations of the date picker.
44
+ */
45
+ supportedOrientations?: ('portrait' | 'landscape')[];
46
+ /**
47
+ * [iOS only] The locale of the date picker.
48
+ */
49
+ locale?: string;
50
+ }
@@ -3,7 +3,7 @@ import { Platform } from 'react-native';
3
3
  import { fireEvent } from '@testing-library/react-native';
4
4
  import DatePicker from '..';
5
5
  import renderWithTheme from '../../../testHelpers/renderWithTheme';
6
- import { Button } from '../../..';
6
+ import { Button, Typography } from '../../..';
7
7
 
8
8
  describe('DatePicker', () => {
9
9
  it('renders DatePickerIOS when OS is iOS', () => {
@@ -146,4 +146,33 @@ describe('DatePicker', () => {
146
146
  fireEvent.press(getByText('Change max date'));
147
147
  expect(queryByDisplayValue('21/12/1994')).toBeTruthy();
148
148
  });
149
+
150
+ it.each`
151
+ OS | variant
152
+ ${'ios'} | ${'default'}
153
+ ${'android'} | ${'default'}
154
+ ${'ios'} | ${'calendar'}
155
+ ${'android'} | ${'calendar'}
156
+ `(
157
+ 'renders correct with custom value with OS=$OS and variant=$variant',
158
+ ({ OS, variant }) => {
159
+ Platform.OS = OS;
160
+ const { getByTestId } = renderWithTheme(
161
+ <DatePicker
162
+ value={new Date('1995-12-17')}
163
+ label="Start date"
164
+ confirmLabel="Confirm"
165
+ onChange={jest.fn()}
166
+ variant={variant}
167
+ renderSelectedValue={({ date }) => (
168
+ <Typography.Body testID="custom-value">
169
+ {date.toLocaleDateString()}
170
+ </Typography.Body>
171
+ )}
172
+ />
173
+ );
174
+
175
+ expect(getByTestId('custom-value')).toBeVisible();
176
+ }
177
+ );
149
178
  });
@@ -2,6 +2,11 @@ import { fireEvent } from '@testing-library/react-native';
2
2
  import React from 'react';
3
3
  import renderWithTheme from '../../../testHelpers/renderWithTheme';
4
4
  import DatePickerAndroid from '../DatePickerAndroid';
5
+ import HeroDesignProvider from '../../HeroDesignProvider';
6
+ import { theme } from '../../..';
7
+
8
+ import enAU from '../../../locales/en_AU';
9
+ import enCA from '../../../locales/en_CA';
5
10
 
6
11
  describe('DatePickerAndroid', () => {
7
12
  it('renders correctly', () => {
@@ -79,4 +84,26 @@ describe('DatePickerAndroid', () => {
79
84
  expect(queryByText('Android month year picker')).toBeNull();
80
85
  expect(onChangeSpy).toBeCalledWith(new Date('2019-09-01'));
81
86
  });
87
+
88
+ it.each`
89
+ locale | expected
90
+ ${enAU} | ${'21/12/1995'}
91
+ ${enCA} | ${'Dec 21, 1995'}
92
+ `(
93
+ 'renders correct format for $locale.lang locale',
94
+ ({ locale, expected }) => {
95
+ const { getByDisplayValue } = renderWithTheme(
96
+ <HeroDesignProvider theme={theme} locale={locale}>
97
+ <DatePickerAndroid
98
+ value={new Date('December 21, 1995')}
99
+ label="Start date"
100
+ confirmLabel="Confirm"
101
+ onChange={jest.fn()}
102
+ />
103
+ </HeroDesignProvider>
104
+ );
105
+
106
+ expect(getByDisplayValue(expected)).toBeVisible();
107
+ }
108
+ );
82
109
  });
@@ -4,6 +4,11 @@ import type { ModalProps } from 'react-native';
4
4
  import renderWithTheme from '../../../testHelpers/renderWithTheme';
5
5
  import DatePickerCalendar from '../DatePickerCalendar';
6
6
  import { setOrientation } from '../../../testHelpers/utils';
7
+ import HeroDesignProvider from '../../HeroDesignProvider';
8
+ import { theme } from '../../..';
9
+
10
+ import enAU from '../../../locales/en_AU';
11
+ import enCA from '../../../locales/en_CA';
7
12
 
8
13
  jest.mock('react-native/Libraries/Modal/Modal', () => {
9
14
  const Modal = jest.requireActual('react-native/Libraries/Modal/Modal');
@@ -137,4 +142,26 @@ describe('DatePickerCalendar', () => {
137
142
  expect(queryByText('January 1993')).toBeDefined();
138
143
  }
139
144
  );
145
+
146
+ it.each`
147
+ locale | expected
148
+ ${enAU} | ${'21/12/1995'}
149
+ ${enCA} | ${'Dec 21, 1995'}
150
+ `(
151
+ 'renders correct format for $locale.lang locale',
152
+ ({ locale, expected }) => {
153
+ const { getByDisplayValue } = renderWithTheme(
154
+ <HeroDesignProvider theme={theme} locale={locale}>
155
+ <DatePickerCalendar
156
+ value={new Date('December 21, 1995')}
157
+ label="Start date"
158
+ confirmLabel="Confirm"
159
+ onChange={jest.fn()}
160
+ />
161
+ </HeroDesignProvider>
162
+ );
163
+
164
+ expect(getByDisplayValue(expected)).toBeVisible();
165
+ }
166
+ );
140
167
  });
@@ -3,8 +3,13 @@ import React from 'react';
3
3
  import type { ModalProps } from 'react-native';
4
4
  import renderWithTheme from '../../../testHelpers/renderWithTheme';
5
5
  import DatePickerIOS from '../DatePickerIOS';
6
- import { getDateValue } from '../useCalculateDate';
6
+ import { getDateValue } from '../hooks/useCalculateDate';
7
7
  import { setOrientation } from '../../../testHelpers/utils';
8
+ import HeroDesignProvider from '../../HeroDesignProvider';
9
+ import { theme } from '../../..';
10
+
11
+ import enAU from '../../../locales/en_AU';
12
+ import enCA from '../../../locales/en_CA';
8
13
 
9
14
  jest.mock('react-native/Libraries/Modal/Modal', () => {
10
15
  const Modal = jest.requireActual('react-native/Libraries/Modal/Modal');
@@ -178,4 +183,26 @@ describe('DatePickerIOS', () => {
178
183
  expect(queryByText('iOS month year picker')).toBeNull();
179
184
  expect(onChangeSpy).toBeCalledWith(new Date('2019-09-01'));
180
185
  });
186
+
187
+ it.each`
188
+ locale | expected
189
+ ${enAU} | ${'21/12/1995'}
190
+ ${enCA} | ${'Dec 21, 1995'}
191
+ `(
192
+ 'renders correct format for $locale.lang locale',
193
+ ({ locale, expected }) => {
194
+ const { getByDisplayValue } = renderWithTheme(
195
+ <HeroDesignProvider theme={theme} locale={locale}>
196
+ <DatePickerIOS
197
+ value={new Date('December 21, 1995')}
198
+ label="Start date"
199
+ confirmLabel="Confirm"
200
+ onChange={jest.fn()}
201
+ />
202
+ </HeroDesignProvider>
203
+ );
204
+
205
+ expect(getByDisplayValue(expected)).toBeVisible();
206
+ }
207
+ );
181
208
  });
@@ -278,15 +278,24 @@ exports[`DatePickerAndroid renders correctly 1`] = `
278
278
  </View>
279
279
  </View>
280
280
  </View>
281
- <Picker
282
- display="default"
283
- maximumDate={1996-12-17T00:00:00.000Z}
284
- minimumDate={1994-12-17T00:00:00.000Z}
285
- mode="date"
286
- onChange={[Function]}
287
- testID="datePickerAndroid"
288
- value={1995-12-21T00:00:00.000Z}
289
- />
281
+ <View
282
+ style={
283
+ [
284
+ {},
285
+ undefined,
286
+ ]
287
+ }
288
+ >
289
+ <Picker
290
+ display="default"
291
+ maximumDate={1996-12-17T00:00:00.000Z}
292
+ minimumDate={1994-12-17T00:00:00.000Z}
293
+ mode="date"
294
+ onChange={[Function]}
295
+ testID="datePickerAndroid"
296
+ value={1995-12-21T00:00:00.000Z}
297
+ />
298
+ </View>
290
299
  </View>
291
300
  <View
292
301
  pointerEvents="box-none"
@@ -548,6 +548,7 @@ exports[`DatePickerIOS renders correctly 1`] = `
548
548
  >
549
549
  <Picker
550
550
  display="spinner"
551
+ locale="en-AU"
551
552
  mode="date"
552
553
  onChange={[Function]}
553
554
  style={
@@ -0,0 +1,61 @@
1
+ import { renderHook } from '@testing-library/react-hooks';
2
+ import formatDate from 'date-fns/fp/format';
3
+ import useFormatDate from '../useFormatDate';
4
+ import { useDateTimeFormat } from '../../../LocaleProvider/hooks';
5
+
6
+ // Mock dependencies
7
+ jest.mock('../../../LocaleProvider/hooks', () => ({
8
+ useDateTimeFormat: jest.fn(),
9
+ }));
10
+
11
+ jest.mock('date-fns/fp/format', () => {
12
+ return jest.fn((format, date) => {
13
+ return `Formatted: ${format}, Date: ${date.toISOString()}`;
14
+ });
15
+ });
16
+
17
+ describe('useFormatDate', () => {
18
+ const testDate = new Date('2023-04-15');
19
+
20
+ beforeEach(() => {
21
+ jest.clearAllMocks();
22
+ (useDateTimeFormat as jest.Mock).mockReturnValue({
23
+ localizeDateTime: () => 'MM/dd/yyyy',
24
+ });
25
+ });
26
+
27
+ it('should return empty string when no date is provided', () => {
28
+ const { result } = renderHook(() => useFormatDate({}));
29
+ expect(result.current.displayValue).toBe('');
30
+ });
31
+
32
+ it('should format date with provided format', () => {
33
+ const { result } = renderHook(() =>
34
+ useFormatDate({
35
+ value: testDate,
36
+ displayFormat: 'yyyy-MM-dd',
37
+ })
38
+ );
39
+
40
+ expect(formatDate).toHaveBeenCalledWith('yyyy-MM-dd', testDate);
41
+ expect(result.current.format).toBe('yyyy-MM-dd');
42
+ });
43
+
44
+ it('should use locale format when no displayFormat provided', () => {
45
+ const { result } = renderHook(() =>
46
+ useFormatDate({
47
+ value: testDate,
48
+ locale: 'en-US',
49
+ })
50
+ );
51
+
52
+ expect(formatDate).toHaveBeenCalledWith('MM/dd/yyyy', testDate);
53
+ expect(result.current.format).toBe('MM/dd/yyyy');
54
+ });
55
+
56
+ it('should use default format when no displayFormat or locale provided', () => {
57
+ const { result } = renderHook(() => useFormatDate({ value: testDate }));
58
+ expect(formatDate).toHaveBeenCalledWith('MM/dd/yyyy', testDate);
59
+ expect(result.current.format).toBe('MM/dd/yyyy');
60
+ });
61
+ });
@@ -1,5 +1,5 @@
1
1
  import { useEffect } from 'react';
2
- import { DatePickerProps } from './types';
2
+ import { DatePickerProps } from '../types';
3
3
 
4
4
  export const getDateValue = (
5
5
  value: Date,
@@ -0,0 +1,25 @@
1
+ import formatDate from 'date-fns/fp/format';
2
+ import { useDateTimeFormat } from '../../LocaleProvider/hooks';
3
+ import { getDateFormat } from './utils';
4
+
5
+ type UseFormatDateProps = {
6
+ displayFormat?: string;
7
+ locale?: string;
8
+ value?: Date;
9
+ };
10
+
11
+ const useFormatDate = ({
12
+ displayFormat,
13
+ locale,
14
+ value,
15
+ }: UseFormatDateProps) => {
16
+ const { localizeDateTime } = useDateTimeFormat();
17
+
18
+ const format = getDateFormat({ displayFormat, locale, localizeDateTime });
19
+
20
+ const displayValue = value ? formatDate(format, value) : '';
21
+
22
+ return { displayValue, format };
23
+ };
24
+
25
+ export default useFormatDate;
@@ -0,0 +1,30 @@
1
+ import { DateTimeFormats, LocaleCode } from '../../../types';
2
+ import locales from '../../../locales';
3
+
4
+ // Function to get the date format based on the displayFormat and locale,
5
+ // if no displayFormat or locale is provided, use the default fullDate format
6
+ export const getDateFormat = ({
7
+ displayFormat,
8
+ locale,
9
+ localizeDateTime,
10
+ }: {
11
+ displayFormat?: string;
12
+ locale?: string;
13
+ localizeDateTime: (key: keyof DateTimeFormats) => string;
14
+ }) => {
15
+ // Prioritise displayFormat
16
+ if (displayFormat) {
17
+ return displayFormat;
18
+ }
19
+
20
+ // If locale is provided, find the corresponding locale in the locales object
21
+ if (locale && locales[locale as LocaleCode]) {
22
+ const localeObject = locales[locale as LocaleCode];
23
+ if (localeObject) {
24
+ return localeObject.dateTimeFormats.fullDate;
25
+ }
26
+ }
27
+
28
+ // If no displayFormat or locale is provided, use the default fullDate format
29
+ return localizeDateTime('fullDate');
30
+ };
@@ -4,6 +4,9 @@ import DatePickerAndroid from './DatePickerAndroid';
4
4
  import DatePickerCalendar from './DatePickerCalendar';
5
5
  import DatePickerIOS from './DatePickerIOS';
6
6
  import type { DatePickerProps } from './types';
7
+ import IOSDatePickerDialog from './Dialog/IOSDialog';
8
+ import AndroidDatePickerDialog from './Dialog/AndroidDialog';
9
+ import { DatePickerDialogProps } from './Dialog/type';
7
10
 
8
11
  const DatePicker = ({ variant = 'default', ...props }: DatePickerProps) => {
9
12
  if (variant === 'calendar') {
@@ -16,4 +19,12 @@ const DatePicker = ({ variant = 'default', ...props }: DatePickerProps) => {
16
19
  return <DatePickerAndroid {...props} variant={variant} />;
17
20
  };
18
21
 
19
- export default DatePicker;
22
+ const Dialog = ({ ...props }: DatePickerDialogProps) => {
23
+ if (Platform.OS === 'ios') {
24
+ return <IOSDatePickerDialog {...props} />;
25
+ }
26
+
27
+ return <AndroidDatePickerDialog {...props} />;
28
+ };
29
+
30
+ export default Object.assign(DatePicker, { Dialog });