@arbor-education/design-system.components 0.4.2 → 0.5.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 (44) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/components/datePicker/DatePicker.d.ts +12 -0
  3. package/dist/components/datePicker/DatePicker.d.ts.map +1 -0
  4. package/dist/components/datePicker/DatePicker.js +60 -0
  5. package/dist/components/datePicker/DatePicker.js.map +1 -0
  6. package/dist/components/datePicker/DatePicker.stories.d.ts +31 -0
  7. package/dist/components/datePicker/DatePicker.stories.d.ts.map +1 -0
  8. package/dist/components/datePicker/DatePicker.stories.js +41 -0
  9. package/dist/components/datePicker/DatePicker.stories.js.map +1 -0
  10. package/dist/components/datePicker/DatePicker.test.d.ts +2 -0
  11. package/dist/components/datePicker/DatePicker.test.d.ts.map +1 -0
  12. package/dist/components/datePicker/DatePicker.test.js +158 -0
  13. package/dist/components/datePicker/DatePicker.test.js.map +1 -0
  14. package/dist/components/formField/FormField.d.ts +4 -0
  15. package/dist/components/formField/FormField.d.ts.map +1 -1
  16. package/dist/components/formField/FormField.js +2 -1
  17. package/dist/components/formField/FormField.js.map +1 -1
  18. package/dist/components/formField/FormField.stories.d.ts.map +1 -1
  19. package/dist/components/formField/FormField.stories.js +2 -2
  20. package/dist/components/formField/FormField.stories.js.map +1 -1
  21. package/dist/components/formField/FormField.test.js +5 -0
  22. package/dist/components/formField/FormField.test.js.map +1 -1
  23. package/dist/components/slideover/Slideover.d.ts +1 -1
  24. package/dist/components/slideover/Slideover.d.ts.map +1 -1
  25. package/dist/components/slideover/Slideover.js +10 -2
  26. package/dist/components/slideover/Slideover.js.map +1 -1
  27. package/dist/index.css +454 -0
  28. package/dist/index.css.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/dist/index.js.map +1 -1
  33. package/package.json +3 -1
  34. package/src/components/datePicker/DatePicker.stories.tsx +47 -0
  35. package/src/components/datePicker/DatePicker.test.tsx +189 -0
  36. package/src/components/datePicker/DatePicker.tsx +144 -0
  37. package/src/components/datePicker/datePicker.scss +37 -0
  38. package/src/components/formField/FormField.stories.tsx +7 -1
  39. package/src/components/formField/FormField.test.tsx +6 -0
  40. package/src/components/formField/FormField.tsx +5 -0
  41. package/src/components/slideover/Slideover.tsx +22 -3
  42. package/src/components/slideover/slideover.scss +5 -0
  43. package/src/index.scss +2 -0
  44. package/src/index.ts +1 -0
@@ -0,0 +1,189 @@
1
+ import { describe, expect, test, vi } from 'vitest';
2
+ import { render, screen, within, fireEvent } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import '@testing-library/jest-dom/vitest';
5
+ import { format } from 'date-fns';
6
+ import { DatePicker } from './DatePicker';
7
+
8
+ describe('DatePicker', () => {
9
+ test('renders a text input', () => {
10
+ render(<DatePicker />);
11
+ expect(screen.getByRole('textbox')).toBeInTheDocument();
12
+ });
13
+
14
+ test('renders a calendar toggle button', () => {
15
+ render(<DatePicker />);
16
+ // Button has an icon with screenReaderText="date" (from iconLeftName fallback in Button/Icon)
17
+ expect(screen.getByRole('button', { name: 'Open date picker' })).toBeInTheDocument();
18
+ });
19
+
20
+ test('day picker is hidden by default', () => {
21
+ render(<DatePicker />);
22
+ expect(screen.queryByRole('application')).not.toBeInTheDocument();
23
+ });
24
+
25
+ describe('calendar toggle', () => {
26
+ test('clicking the button opens the day picker', async () => {
27
+ render(<DatePicker />);
28
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
29
+ expect(screen.getByRole('application')).toBeInTheDocument();
30
+ });
31
+
32
+ test('clicking the button again closes the day picker', async () => {
33
+ render(<DatePicker />);
34
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
35
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
36
+ expect(screen.queryByRole('application')).not.toBeInTheDocument();
37
+ });
38
+ });
39
+
40
+ describe('text input', () => {
41
+ // Use fireEvent.change rather than userEvent.type — the component's useEffect overwrites
42
+ // inputValue state between individual keystrokes, which conflicts with userEvent's tracking.
43
+
44
+ test('entering a valid date updates the input value', () => {
45
+ render(<DatePicker />);
46
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '15/06/2024' } });
47
+ expect(screen.getByRole('textbox')).toHaveValue('15/06/2024');
48
+ });
49
+
50
+ test('entering a valid date calls onChange with the parsed Date', () => {
51
+ const onChange = vi.fn();
52
+ render(<DatePicker onChange={onChange} />);
53
+ onChange.mockClear(); // ignore the initial mount call with undefined
54
+
55
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '15/06/2024' } });
56
+
57
+ expect(onChange).toHaveBeenLastCalledWith(expect.any(Date));
58
+ const lastDate: Date = onChange.mock.lastCall![0];
59
+ expect(lastDate.getFullYear()).toBe(2024);
60
+ expect(lastDate.getMonth()).toBe(5); // June is month index 5
61
+ expect(lastDate.getDate()).toBe(15);
62
+ });
63
+
64
+ test('entering an invalid string after a valid date calls onChange with undefined', () => {
65
+ // onChange is only fired by the useEffect when selectedDate actually changes.
66
+ // So we first need a valid date to put selectedDate into a non-undefined state.
67
+ const onChange = vi.fn();
68
+ render(<DatePicker onChange={onChange} />);
69
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '15/06/2024' } });
70
+ onChange.mockClear();
71
+
72
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: 'not-a-date' } });
73
+
74
+ expect(onChange).toHaveBeenLastCalledWith(undefined);
75
+ });
76
+ });
77
+
78
+ describe('day picker selection', () => {
79
+ // Avoid fake timers (incompatible with userEvent) by navigating the picker to a
80
+ // known month via the text input before opening the calendar.
81
+
82
+ test('selecting a date from the picker updates the input', async () => {
83
+ render(<DatePicker />);
84
+ // Navigate to June 2024 by entering a different day in that month
85
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '01/06/2024' } });
86
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
87
+ // Day aria-labels use date-fns PPPP format e.g. "Thursday, June 20, 2024"
88
+ await userEvent.click(within(screen.getByRole('application')).getByRole('button', { name: /June 20/ }));
89
+ expect(screen.getByRole('textbox')).toHaveValue('20/06/2024');
90
+ });
91
+
92
+ test('selecting a date from the picker closes the picker', async () => {
93
+ render(<DatePicker />);
94
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '01/06/2024' } });
95
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
96
+ await userEvent.click(within(screen.getByRole('application')).getByRole('button', { name: /June 20/ }));
97
+ expect(screen.queryByRole('application')).not.toBeInTheDocument();
98
+ });
99
+
100
+ test('selecting a date from the picker calls onChange with the selected date', async () => {
101
+ const onChange = vi.fn();
102
+ render(<DatePicker onChange={onChange} />);
103
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '01/06/2024' } });
104
+ onChange.mockClear();
105
+
106
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
107
+ await userEvent.click(within(screen.getByRole('application')).getByRole('button', { name: /June 20/ }));
108
+
109
+ expect(onChange).toHaveBeenCalledWith(expect.any(Date));
110
+ const lastDate: Date = onChange.mock.lastCall![0];
111
+ expect(lastDate.getFullYear()).toBe(2024);
112
+ expect(lastDate.getMonth()).toBe(5); // June is month index 5
113
+ expect(lastDate.getDate()).toBe(20);
114
+ });
115
+
116
+ test('clicking the Today button selects today\'s date', async () => {
117
+ render(<DatePicker />);
118
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
119
+ await userEvent.click(screen.getByRole('button', { name: 'Today' }));
120
+ expect(screen.getByRole('textbox')).toHaveValue(format(new Date(), 'dd/MM/yyyy'));
121
+ });
122
+
123
+ test('clicking the Today button closes the picker', async () => {
124
+ render(<DatePicker />);
125
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
126
+ await userEvent.click(screen.getByRole('button', { name: 'Today' }));
127
+ expect(screen.queryByRole('application')).not.toBeInTheDocument();
128
+ });
129
+ });
130
+
131
+ describe('controlled value prop', () => {
132
+ test('renders with the initial value', () => {
133
+ render(<DatePicker value={new Date(2024, 5, 15)} />);
134
+ expect(screen.getByRole('textbox')).toHaveValue('15/06/2024');
135
+ });
136
+
137
+ test('updates the input when value prop changes', () => {
138
+ const { rerender } = render(<DatePicker value={new Date(2024, 5, 15)} />);
139
+ rerender(<DatePicker value={new Date(2024, 11, 25)} />);
140
+ expect(screen.getByRole('textbox')).toHaveValue('25/12/2024');
141
+ });
142
+
143
+ test('does not call onChange when value prop changes externally', () => {
144
+ const onChange = vi.fn();
145
+ const { rerender } = render(<DatePicker value={new Date(2024, 5, 15)} onChange={onChange} />);
146
+ onChange.mockClear();
147
+
148
+ rerender(<DatePicker value={new Date(2024, 11, 25)} onChange={onChange} />);
149
+
150
+ expect(onChange).not.toHaveBeenCalled();
151
+ });
152
+
153
+ test('still calls onChange when user interacts after a controlled value is set', async () => {
154
+ const onChange = vi.fn();
155
+ render(<DatePicker value={new Date(2024, 5, 15)} onChange={onChange} />);
156
+ onChange.mockClear();
157
+
158
+ // Navigate to June 2024 (already set via value) and pick a different day
159
+ await userEvent.click(screen.getByRole('button', { name: 'Open date picker' }));
160
+ await userEvent.click(within(screen.getByRole('application')).getByRole('button', { name: /June 20/ }));
161
+
162
+ expect(onChange).toHaveBeenCalledWith(expect.any(Date));
163
+ const lastDate: Date = onChange.mock.lastCall![0];
164
+ expect(lastDate.getDate()).toBe(20);
165
+ });
166
+ });
167
+
168
+ describe('custom dateFormat prop', () => {
169
+ test('formats the value according to the custom format', () => {
170
+ render(<DatePicker dateFormat="yyyy-MM-dd" />);
171
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '2024-06-15' } });
172
+ expect(screen.getByRole('textbox')).toHaveValue('2024-06-15');
173
+ });
174
+
175
+ test('calls onChange with the correctly parsed date for a custom format', () => {
176
+ const onChange = vi.fn();
177
+ render(<DatePicker dateFormat="MM/dd/yyyy" onChange={onChange} />);
178
+ onChange.mockClear();
179
+
180
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: '06/15/2024' } });
181
+
182
+ expect(onChange).toHaveBeenLastCalledWith(expect.any(Date));
183
+ const lastDate: Date = onChange.mock.lastCall![0];
184
+ expect(lastDate.getFullYear()).toBe(2024);
185
+ expect(lastDate.getMonth()).toBe(5); // June
186
+ expect(lastDate.getDate()).toBe(15);
187
+ });
188
+ });
189
+ });
@@ -0,0 +1,144 @@
1
+ import classNames from 'classnames';
2
+ import { Button } from 'Components/button/Button';
3
+ import { TextInput } from 'Components/formField/inputs/text/TextInput';
4
+ import { format, isValid, parse } from 'date-fns';
5
+ import { Popover } from 'radix-ui';
6
+ import { useContext, useRef, useState, type ChangeEvent } from 'react';
7
+ import { DayPicker } from 'react-day-picker';
8
+ import { useComponentDidUpdate } from 'Utils/hooks/useComponentDidUpdate';
9
+ import { PopupParentContext } from 'Utils/PopupParentContext';
10
+
11
+ export type DatePickerProps = {
12
+ 'className'?: string;
13
+ 'dateFormat'?: string;
14
+ 'onChange'?: (newDate?: Date) => void;
15
+ 'id'?: string;
16
+ 'hasError'?: boolean;
17
+ 'aria-describedby'?: string;
18
+ 'aria-invalid'?: boolean;
19
+ 'value'?: Date;
20
+ };
21
+
22
+ export const DatePicker = (props: DatePickerProps) => {
23
+ const {
24
+ className,
25
+ dateFormat = 'dd/MM/yyyy',
26
+ onChange,
27
+ id,
28
+ hasError,
29
+ 'aria-describedby': ariaDescribedBy,
30
+ 'aria-invalid': ariaInvalid,
31
+ value,
32
+ } = props;
33
+
34
+ const [month, setMonth] = useState(value ?? new Date());
35
+
36
+ const [selectedDate, setSelectedDate] = useState<Date | undefined>(value);
37
+
38
+ const [inputValue, setInputValue] = useState(value ? format(value, dateFormat) : '');
39
+
40
+ const isExternalSyncRef = useRef(false);
41
+
42
+ useComponentDidUpdate(() => {
43
+ if (value && value.getTime() !== selectedDate?.getTime()) {
44
+ isExternalSyncRef.current = true;
45
+ setSelectedDate(value);
46
+ setMonth(value);
47
+ }
48
+ }, [value]);
49
+
50
+ const [isPickerOpen, setIsPickerOpen] = useState(false);
51
+
52
+ const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
53
+ setInputValue(e.target.value);
54
+
55
+ const parsedDate = parse(e.target.value, dateFormat, new Date());
56
+
57
+ if (isValid(parsedDate)) {
58
+ setSelectedDate(parsedDate);
59
+ setMonth(parsedDate);
60
+ }
61
+ else {
62
+ setSelectedDate(undefined);
63
+ }
64
+ };
65
+
66
+ const onDayPickerSelect = (date?: Date) => {
67
+ setSelectedDate(date);
68
+ setIsPickerOpen(false);
69
+ };
70
+
71
+ useComponentDidUpdate(() => {
72
+ if (selectedDate) {
73
+ setInputValue(format(selectedDate, dateFormat));
74
+ }
75
+ else {
76
+ setInputValue('');
77
+ }
78
+
79
+ if (!isExternalSyncRef.current && onChange) {
80
+ onChange(selectedDate);
81
+ }
82
+ isExternalSyncRef.current = false;
83
+ }, [selectedDate, dateFormat, onChange]);
84
+
85
+ const popupParentRef = useContext(PopupParentContext);
86
+
87
+ return (
88
+ <div
89
+ className={classNames(
90
+ 'ds-date-picker',
91
+ className,
92
+ )}
93
+ >
94
+ <TextInput
95
+ value={inputValue}
96
+ onChange={onInputChange}
97
+ id={id}
98
+ hasError={hasError}
99
+ aria-describedby={ariaDescribedBy}
100
+ aria-invalid={ariaInvalid}
101
+ />
102
+ <Popover.Root open={isPickerOpen} onOpenChange={open => setIsPickerOpen(open)}>
103
+ <Popover.Trigger asChild>
104
+ <Button
105
+ onClick={() => {
106
+ setIsPickerOpen(!isPickerOpen);
107
+ }}
108
+ className="ds-date-picker__button"
109
+ variant="text-link"
110
+ iconLeftName="date"
111
+ iconLeftScreenReaderText="Open date picker"
112
+ />
113
+ </Popover.Trigger>
114
+ <Popover.Portal container={popupParentRef.current}>
115
+ <Popover.Content align="end" sideOffset={5}>
116
+ <DayPicker
117
+ className="ds-date-picker__popup"
118
+ month={month}
119
+ onMonthChange={setMonth}
120
+ autoFocus
121
+ role="application"
122
+ mode="single"
123
+ selected={selectedDate}
124
+ onSelect={onDayPickerSelect}
125
+ captionLayout="dropdown"
126
+ footer={(
127
+ <Button
128
+ variant="text-link"
129
+ onClick={() => {
130
+ setSelectedDate(new Date());
131
+ setIsPickerOpen(false);
132
+ }}
133
+ className="ds-date-picker__today-button"
134
+ >
135
+ Today
136
+ </Button>
137
+ )}
138
+ />
139
+ </Popover.Content>
140
+ </Popover.Portal>
141
+ </Popover.Root>
142
+ </div>
143
+ );
144
+ };
@@ -0,0 +1,37 @@
1
+ .ds-date-picker {
2
+ position: relative;
3
+
4
+ .ds-date-picker__button {
5
+ position: absolute;
6
+ right: 0;
7
+ top: 0;
8
+
9
+ svg {
10
+ stroke: var(--form-field-icon-default-color-icon);
11
+ }
12
+ }
13
+ }
14
+
15
+ .ds-date-picker__popup {
16
+ box-shadow: var(--shadow-small);
17
+ padding: var(--date-picker-spacing-vertical) var(--date-picker-spacing-horizontal);
18
+ border-radius: var(--date-picker-radius);
19
+ background-color: var(--date-picker-color-background);
20
+
21
+ --rdp-accent-color: var(--date-picker-date-cell-today-default-color-text);
22
+ --rdp-accent-background-color: var(--date-picker-date-cell-today-default-color-background);
23
+
24
+ .rdp-selected {
25
+ font-size: unset;
26
+
27
+ .rdp-day_button{
28
+ background-color: var(--rdp-accent-background-color);
29
+ }
30
+ }
31
+
32
+ .rdp-footer {
33
+ display: flex;
34
+ justify-content: flex-end;
35
+ }
36
+ }
37
+
@@ -41,7 +41,7 @@ export const Default = {
41
41
  },
42
42
  'inputType': {
43
43
  control: 'select',
44
- options: ['text', 'textarea', 'number'],
44
+ options: ['text', 'textarea', 'number', 'datePicker'],
45
45
  description: 'Input type',
46
46
  },
47
47
  'inputProps.size': {
@@ -130,6 +130,12 @@ export const FormExample: Story = {
130
130
  onSelectionChange: fn(),
131
131
  }}
132
132
  />
133
+ <FormField
134
+ id="date-of-birth"
135
+ label="Date of Birth"
136
+ inputType="datePicker"
137
+ inputProps={{ onChange: fn() }}
138
+ />
133
139
  </div>
134
140
  ),
135
141
  };
@@ -56,4 +56,10 @@ describe('FormField component', () => {
56
56
  const input = screen.getByRole('button');
57
57
  expect(input.textContent).toContain('Select');
58
58
  });
59
+
60
+ test('renders a date picker when inputType is datePicker', () => {
61
+ render(<FormField id="niceid" inputType="datePicker" />);
62
+ expect(screen.getByRole('textbox')).toBeInTheDocument();
63
+ expect(screen.getByRole('button', { name: 'Open date picker' })).toBeInTheDocument();
64
+ });
59
65
  });
@@ -6,6 +6,7 @@ import { TextArea, type TextAreaProps } from './inputs/textArea/TextArea';
6
6
  import { NumberInput, type NumberInputProps } from './inputs/number/NumberInput';
7
7
  import { ColourPickerDropdown, type ColourPickerDropdownProps } from './inputs/colourPickerDropdown/ColourPickerDropdown';
8
8
  import { SelectDropdown, type SelectDropdownInputProps } from './inputs/selectDropdown/SelectDropdown';
9
+ import { DatePicker, type DatePickerProps } from 'Components/datePicker/DatePicker';
9
10
 
10
11
  type FormFieldProps = {
11
12
  className?: string;
@@ -21,6 +22,7 @@ type FormFieldProps = {
21
22
  | { inputType?: 'number'; inputProps?: NumberInputProps }
22
23
  | { inputType?: 'colourPicker'; inputProps?: ColourPickerDropdownProps }
23
24
  | { inputType?: 'selectDropdown'; inputProps?: SelectDropdownInputProps }
25
+ | { inputType?: 'datePicker'; inputProps?: DatePickerProps }
24
26
  );
25
27
 
26
28
  export const FormField = (props: FormFieldProps) => {
@@ -66,6 +68,9 @@ export const FormField = (props: FormFieldProps) => {
66
68
  {inputType === 'selectDropdown' && (
67
69
  <SelectDropdown {...sharedProps} {...(inputProps as SelectDropdownInputProps)} />
68
70
  )}
71
+ {inputType === 'datePicker' && (
72
+ <DatePicker {...sharedProps} {...(inputProps as DatePickerProps)} />
73
+ )}
69
74
  {((helperLinkText && helperLinkUrl) || errorText) && (
70
75
  <div className="ds-form-field__message">
71
76
  {errorText && (
@@ -3,7 +3,8 @@ import { Button } from 'Components/button/Button';
3
3
  import { Heading } from 'Components/heading/Heading';
4
4
  import type { IconName } from 'Components/icon/allowedIcons';
5
5
  import { Icon } from 'Components/icon/Icon';
6
- import type { ReactNode } from 'react';
6
+ import { useState, type ReactNode } from 'react';
7
+ import { useComponentDidMount } from 'Utils/hooks/useComponentDidMount';
7
8
  import { SlideoverUtils } from 'Utils/SlideoverUtils';
8
9
 
9
10
  export type SlideoverProps = {
@@ -16,10 +17,28 @@ export type SlideoverProps = {
16
17
  };
17
18
 
18
19
  export const Slideover = (props: SlideoverProps) => {
19
- const { title, children, footerContents, headerIcon, centerHeaderText = true, hideBackButton } = props;
20
+ const {
21
+ title,
22
+ children,
23
+ footerContents,
24
+ headerIcon,
25
+ centerHeaderText = true,
26
+ hideBackButton,
27
+ } = props;
28
+
29
+ const [isFirstRender, setIsFirstRender] = useState(true);
30
+
31
+ useComponentDidMount(() => {
32
+ setIsFirstRender(false);
33
+ });
20
34
 
21
35
  return (
22
- <aside className="ds-slideover">
36
+ <aside className={classNames('ds-slideover',
37
+ {
38
+ 'ds-slideover--initial': isFirstRender,
39
+ },
40
+ )}
41
+ >
23
42
  <div className={classNames('ds-slideover__header', { 'ds-slideover__header--center': centerHeaderText })}>
24
43
  {
25
44
  !hideBackButton && (
@@ -7,6 +7,11 @@
7
7
  display: flex;
8
8
  flex-direction: column;
9
9
  align-items: stretch;
10
+ transition: right 300ms ease;
11
+
12
+ &--initial {
13
+ right: -580px;
14
+ }
10
15
 
11
16
  &__header {
12
17
  background-color: var(--slideover-header-color-background);
package/src/index.scss CHANGED
@@ -1,3 +1,4 @@
1
+ @use "../node_modules/react-day-picker/src/style.css";
1
2
  @use "./tokens.scss";
2
3
  @use "./global.scss";
3
4
  @use "components/button/button.scss";
@@ -32,6 +33,7 @@
32
33
  @use "components/editableText/editableText.scss";
33
34
  @use "components/progress/progress.scss";
34
35
  @use "components/toast/toast.scss";
36
+ @use "components/datePicker/datePicker.scss";
35
37
  @use "components/avatar/avatar.scss";
36
38
  @use "components/userDropdown/userDropdown.scss";
37
39
  @import "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap";
package/src/index.ts CHANGED
@@ -30,6 +30,7 @@ export { Banner, type BannerProps, BANNER_LEVEL } from 'Components/banner/Banner
30
30
  export { EditableText } from 'Components/editableText/EditableText';
31
31
  export { Progress } from 'Components/progress/Progress';
32
32
  export { Toast } from 'Components/toast/Toast';
33
+ export { DatePicker } from 'Components/datePicker/DatePicker';
33
34
  export { Avatar } from 'Components/avatar/Avatar';
34
35
  export { UserDropdown } from 'Components/userDropdown/UserDropdown';
35
36
  export type { UserDropdownUserInfoAction } from 'Components/userDropdown/UserDropdown';