@arbor-education/design-system.components 0.14.0 → 0.16.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/.gather/skills/write-stories/SKILL.md +207 -271
- package/.storybook/preview.ts +5 -0
- package/CHANGELOG.md +27 -0
- package/README.md +8 -0
- package/component-library.md +144 -13
- package/dist/components/articleCard/ArticleCard.stories.d.ts +137 -11
- package/dist/components/articleCard/ArticleCard.stories.d.ts.map +1 -1
- package/dist/components/articleCard/ArticleCard.stories.js +358 -91
- package/dist/components/articleCard/ArticleCard.stories.js.map +1 -1
- package/dist/components/avatar/Avatar.stories.d.ts +6 -6
- package/dist/components/avatar/Avatar.stories.d.ts.map +1 -1
- package/dist/components/avatar/Avatar.stories.js +393 -49
- package/dist/components/avatar/Avatar.stories.js.map +1 -1
- package/dist/components/avatarGroup/AvatarGroup.stories.d.ts +9 -7
- package/dist/components/avatarGroup/AvatarGroup.stories.d.ts.map +1 -1
- package/dist/components/avatarGroup/AvatarGroup.stories.js +688 -65
- package/dist/components/avatarGroup/AvatarGroup.stories.js.map +1 -1
- package/dist/components/banner/Banner.stories.d.ts.map +1 -1
- package/dist/components/banner/Banner.stories.js +7 -3
- package/dist/components/banner/Banner.stories.js.map +1 -1
- package/dist/components/card/Card.stories.d.ts +105 -4
- package/dist/components/card/Card.stories.d.ts.map +1 -1
- package/dist/components/card/Card.stories.js +336 -18
- package/dist/components/card/Card.stories.js.map +1 -1
- package/dist/components/combobox/Combobox.stories.d.ts +134 -21
- package/dist/components/combobox/Combobox.stories.d.ts.map +1 -1
- package/dist/components/combobox/Combobox.stories.js +676 -175
- package/dist/components/combobox/Combobox.stories.js.map +1 -1
- package/dist/components/datePicker/DatePicker.stories.d.ts +119 -27
- package/dist/components/datePicker/DatePicker.stories.d.ts.map +1 -1
- package/dist/components/datePicker/DatePicker.stories.js +575 -47
- package/dist/components/datePicker/DatePicker.stories.js.map +1 -1
- package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts +155 -39
- package/dist/components/dateTimePicker/DateTimePicker.stories.d.ts.map +1 -1
- package/dist/components/dateTimePicker/DateTimePicker.stories.js +674 -103
- package/dist/components/dateTimePicker/DateTimePicker.stories.js.map +1 -1
- package/dist/components/editableText/EditableText.stories.d.ts +53 -12
- package/dist/components/editableText/EditableText.stories.d.ts.map +1 -1
- package/dist/components/editableText/EditableText.stories.js +401 -64
- package/dist/components/editableText/EditableText.stories.js.map +1 -1
- package/dist/components/formField/FormField.d.ts +4 -0
- package/dist/components/formField/FormField.d.ts.map +1 -1
- package/dist/components/formField/FormField.js +2 -1
- package/dist/components/formField/FormField.js.map +1 -1
- package/dist/components/formField/FormField.test.js +5 -0
- package/dist/components/formField/FormField.test.js.map +1 -1
- package/dist/components/formField/fieldset/Fieldset.stories.d.ts +56 -4
- package/dist/components/formField/fieldset/Fieldset.stories.d.ts.map +1 -1
- package/dist/components/formField/fieldset/Fieldset.stories.js +534 -28
- package/dist/components/formField/fieldset/Fieldset.stories.js.map +1 -1
- package/dist/components/formField/inputs/checkbox/CheckboxGroup.d.ts +3 -1
- package/dist/components/formField/inputs/checkbox/CheckboxGroup.d.ts.map +1 -1
- package/dist/components/formField/inputs/checkbox/CheckboxInput.js +1 -1
- package/dist/components/formField/inputs/checkbox/CheckboxInput.js.map +1 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts +95 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js +386 -9
- package/dist/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.js.map +1 -1
- package/dist/components/formField/inputs/number/NumberInput.d.ts.map +1 -1
- package/dist/components/formField/inputs/number/NumberInput.js +14 -2
- package/dist/components/formField/inputs/number/NumberInput.js.map +1 -1
- package/dist/components/formField/inputs/number/NumberInput.test.js +21 -0
- package/dist/components/formField/inputs/number/NumberInput.test.js.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonGroup.d.ts +6 -2
- package/dist/components/formField/inputs/radio/RadioButtonGroup.d.ts.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonGroup.js.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js +61 -49
- package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js.map +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts +188 -166
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js +821 -160
- package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js.map +1 -1
- package/dist/components/formField/inputs/time/TimeInput.stories.d.ts +176 -22
- package/dist/components/formField/inputs/time/TimeInput.stories.d.ts.map +1 -1
- package/dist/components/formField/inputs/time/TimeInput.stories.js +851 -92
- package/dist/components/formField/inputs/time/TimeInput.stories.js.map +1 -1
- package/dist/components/formField/label/Label.stories.d.ts +54 -5
- package/dist/components/formField/label/Label.stories.d.ts.map +1 -1
- package/dist/components/formField/label/Label.stories.js +238 -4
- package/dist/components/formField/label/Label.stories.js.map +1 -1
- package/dist/components/icoText/IcoText.stories.d.ts +32 -6
- package/dist/components/icoText/IcoText.stories.d.ts.map +1 -1
- package/dist/components/icoText/IcoText.stories.js +309 -14
- package/dist/components/icoText/IcoText.stories.js.map +1 -1
- package/dist/components/kpiCard/KPICard.stories.d.ts +100 -2
- package/dist/components/kpiCard/KPICard.stories.d.ts.map +1 -1
- package/dist/components/kpiCard/KPICard.stories.js +354 -10
- package/dist/components/kpiCard/KPICard.stories.js.map +1 -1
- package/dist/components/kvpList/KVPList.stories.d.ts +57 -4
- package/dist/components/kvpList/KVPList.stories.d.ts.map +1 -1
- package/dist/components/kvpList/KVPList.stories.js +403 -10
- package/dist/components/kvpList/KVPList.stories.js.map +1 -1
- package/dist/components/modal/Modal.stories.d.ts +113 -9
- package/dist/components/modal/Modal.stories.d.ts.map +1 -1
- package/dist/components/modal/Modal.stories.js +633 -13
- package/dist/components/modal/Modal.stories.js.map +1 -1
- package/dist/components/modal/modalManager/ModalManager.stories.d.ts +34 -10
- package/dist/components/modal/modalManager/ModalManager.stories.d.ts.map +1 -1
- package/dist/components/modal/modalManager/ModalManager.stories.js +463 -85
- package/dist/components/modal/modalManager/ModalManager.stories.js.map +1 -1
- package/dist/components/pill/Pill.d.ts.map +1 -1
- package/dist/components/pill/Pill.js +1 -1
- package/dist/components/pill/Pill.js.map +1 -1
- package/dist/components/pill/Pill.stories.d.ts.map +1 -1
- package/dist/components/pill/Pill.stories.js +11 -13
- package/dist/components/pill/Pill.stories.js.map +1 -1
- package/dist/components/row/Row.stories.d.ts +1 -2
- package/dist/components/row/Row.stories.d.ts.map +1 -1
- package/dist/components/row/Row.stories.js +360 -50
- package/dist/components/row/Row.stories.js.map +1 -1
- package/dist/components/searchBar/SearchBar.stories.d.ts +52 -4
- package/dist/components/searchBar/SearchBar.stories.d.ts.map +1 -1
- package/dist/components/searchBar/SearchBar.stories.js +428 -36
- package/dist/components/searchBar/SearchBar.stories.js.map +1 -1
- package/dist/components/section/Section.stories.d.ts +11 -41
- package/dist/components/section/Section.stories.d.ts.map +1 -1
- package/dist/components/section/Section.stories.js +494 -56
- package/dist/components/section/Section.stories.js.map +1 -1
- package/dist/components/singleUser/SingleUser.stories.d.ts +5 -4
- package/dist/components/singleUser/SingleUser.stories.d.ts.map +1 -1
- package/dist/components/singleUser/SingleUser.stories.js +303 -31
- package/dist/components/singleUser/SingleUser.stories.js.map +1 -1
- package/dist/components/slideoverManager/SlideoverManager.stories.d.ts +32 -11
- package/dist/components/slideoverManager/SlideoverManager.stories.d.ts.map +1 -1
- package/dist/components/slideoverManager/SlideoverManager.stories.js +380 -84
- package/dist/components/slideoverManager/SlideoverManager.stories.js.map +1 -1
- package/dist/components/table/DSDefaultColDef.d.ts.map +1 -1
- package/dist/components/table/DSDefaultColDef.js +4 -3
- package/dist/components/table/DSDefaultColDef.js.map +1 -1
- package/dist/components/table/Table.d.ts +7 -1
- package/dist/components/table/Table.d.ts.map +1 -1
- package/dist/components/table/Table.js +12 -5
- package/dist/components/table/Table.js.map +1 -1
- package/dist/components/table/Table.stories.d.ts +3 -0
- package/dist/components/table/Table.stories.d.ts.map +1 -1
- package/dist/components/table/Table.stories.js +445 -3
- package/dist/components/table/Table.stories.js.map +1 -1
- package/dist/components/table/Table.test.js +184 -0
- package/dist/components/table/Table.test.js.map +1 -1
- package/dist/components/table/TableFooter.stories.d.ts +49 -0
- package/dist/components/table/TableFooter.stories.d.ts.map +1 -0
- package/dist/components/table/TableFooter.stories.js +137 -0
- package/dist/components/table/TableFooter.stories.js.map +1 -0
- package/dist/components/table/TableHeader.stories.d.ts +93 -0
- package/dist/components/table/TableHeader.stories.d.ts.map +1 -0
- package/dist/components/table/TableHeader.stories.js +176 -0
- package/dist/components/table/TableHeader.stories.js.map +1 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts +44 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.d.ts.map +1 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.js +186 -0
- package/dist/components/table/cellEditors/DateCellEditor.stories.js.map +1 -0
- package/dist/components/table/cellEditors/NumberCellEditor.d.ts +13 -0
- package/dist/components/table/cellEditors/NumberCellEditor.d.ts.map +1 -0
- package/dist/components/table/cellEditors/NumberCellEditor.js +35 -0
- package/dist/components/table/cellEditors/NumberCellEditor.js.map +1 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts +40 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js +209 -0
- package/dist/components/table/cellRenderers/BooleanCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts +48 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js +244 -0
- package/dist/components/table/cellRenderers/ButtonCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.d.ts.map +1 -1
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.js +3 -1
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.js.map +1 -1
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts +64 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js +241 -0
- package/dist/components/table/cellRenderers/CheckboxCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts +55 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js +245 -0
- package/dist/components/table/cellRenderers/DefaultCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts +67 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js +221 -0
- package/dist/components/table/cellRenderers/InlineTextCellRenderer.stories.js.map +1 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts +75 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.d.ts.map +1 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js +270 -0
- package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.stories.js.map +1 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts +57 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.d.ts.map +1 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.js +198 -0
- package/dist/components/table/columnFilters/BooleanFilter.stories.js.map +1 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.d.ts +58 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.d.ts.map +1 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.js +207 -0
- package/dist/components/table/columnFilters/TimeFilter.stories.js.map +1 -0
- package/dist/components/table/pagination/PaginationPanel.stories.d.ts +113 -0
- package/dist/components/table/pagination/PaginationPanel.stories.d.ts.map +1 -0
- package/dist/components/table/pagination/PaginationPanel.stories.js +272 -0
- package/dist/components/table/pagination/PaginationPanel.stories.js.map +1 -0
- package/dist/components/table/tableControls/TableControls.stories.d.ts +151 -0
- package/dist/components/table/tableControls/TableControls.stories.d.ts.map +1 -0
- package/dist/components/table/tableControls/TableControls.stories.js +356 -0
- package/dist/components/table/tableControls/TableControls.stories.js.map +1 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.d.ts +27 -1
- package/dist/components/table/tableControls/TableSettingsDropdown.d.ts.map +1 -1
- package/dist/components/table/tableControls/TableSettingsDropdown.js +53 -26
- package/dist/components/table/tableControls/TableSettingsDropdown.js.map +1 -1
- package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts +2 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.test.d.ts.map +1 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.test.js +178 -0
- package/dist/components/table/tableControls/TableSettingsDropdown.test.js.map +1 -0
- package/dist/components/tabs/Tabs.stories.d.ts +22 -4
- package/dist/components/tabs/Tabs.stories.d.ts.map +1 -1
- package/dist/components/tabs/Tabs.stories.js +398 -22
- package/dist/components/tabs/Tabs.stories.js.map +1 -1
- package/dist/components/tabs/TabsItem.stories.d.ts +54 -1
- package/dist/components/tabs/TabsItem.stories.d.ts.map +1 -1
- package/dist/components/tabs/TabsItem.stories.js +61 -9
- package/dist/components/tabs/TabsItem.stories.js.map +1 -1
- package/dist/components/toast/Toast.stories.d.ts +103 -10
- package/dist/components/toast/Toast.stories.d.ts.map +1 -1
- package/dist/components/toast/Toast.stories.js +409 -47
- package/dist/components/toast/Toast.stories.js.map +1 -1
- package/dist/components/toggle/Toggle.stories.d.ts +61 -46
- package/dist/components/toggle/Toggle.stories.d.ts.map +1 -1
- package/dist/components/toggle/Toggle.stories.js +311 -122
- package/dist/components/toggle/Toggle.stories.js.map +1 -1
- package/dist/components/tooltip/Tooltip.stories.d.ts +78 -6
- package/dist/components/tooltip/Tooltip.stories.d.ts.map +1 -1
- package/dist/components/tooltip/Tooltip.stories.js +413 -7
- package/dist/components/tooltip/Tooltip.stories.js.map +1 -1
- package/dist/components/tooltip/TooltipWrapper.stories.d.ts +71 -7
- package/dist/components/tooltip/TooltipWrapper.stories.d.ts.map +1 -1
- package/dist/components/tooltip/TooltipWrapper.stories.js +238 -10
- package/dist/components/tooltip/TooltipWrapper.stories.js.map +1 -1
- package/dist/index.css +27 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/PopupParentContext.stories.d.ts +17 -0
- package/dist/utils/PopupParentContext.stories.d.ts.map +1 -0
- package/dist/utils/PopupParentContext.stories.js +266 -0
- package/dist/utils/PopupParentContext.stories.js.map +1 -0
- package/dist/utils/getDefaultPopupParent.d.ts.map +1 -1
- package/dist/utils/getDefaultPopupParent.js +6 -0
- package/dist/utils/getDefaultPopupParent.js.map +1 -1
- package/package.json +1 -1
- package/src/components/articleCard/ArticleCard.stories.tsx +524 -111
- package/src/components/avatar/Avatar.stories.tsx +504 -59
- package/src/components/avatarGroup/AvatarGroup.stories.tsx +977 -175
- package/src/components/banner/Banner.stories.tsx +7 -3
- package/src/components/card/Card.stories.tsx +466 -36
- package/src/components/combobox/Combobox.stories.tsx +867 -260
- package/src/components/datePicker/DatePicker.stories.tsx +777 -60
- package/src/components/dateTimePicker/DateTimePicker.stories.tsx +910 -132
- package/src/components/editableText/EditableText.stories.tsx +567 -91
- package/src/components/formField/FormField.test.tsx +6 -0
- package/src/components/formField/FormField.tsx +5 -0
- package/src/components/formField/fieldset/Fieldset.stories.tsx +761 -51
- package/src/components/formField/inputs/checkbox/CheckboxGroup.tsx +1 -1
- package/src/components/formField/inputs/checkbox/CheckboxInput.tsx +1 -1
- package/src/components/formField/inputs/colourPickerDropdown/ColourPickerDropdown.stories.tsx +504 -11
- package/src/components/formField/inputs/number/NumberInput.test.tsx +28 -0
- package/src/components/formField/inputs/number/NumberInput.tsx +15 -0
- package/src/components/formField/inputs/radio/RadioButtonGroup.tsx +17 -4
- package/src/components/formField/inputs/radio/RadioButtonInput.stories.tsx +71 -59
- package/src/components/formField/inputs/selectDropdown/SelectDropdown.stories.tsx +1079 -168
- package/src/components/formField/inputs/time/TimeInput.stories.tsx +1140 -104
- package/src/components/formField/label/Label.stories.tsx +317 -8
- package/src/components/icoText/IcoText.stories.tsx +442 -31
- package/src/components/kpiCard/KPICard.stories.tsx +475 -30
- package/src/components/kvpList/KVPList.stories.tsx +593 -26
- package/src/components/modal/Modal.stories.tsx +963 -26
- package/src/components/modal/modalManager/ModalManager.stories.tsx +612 -454
- package/src/components/pill/Pill.stories.tsx +11 -13
- package/src/components/pill/Pill.tsx +1 -0
- package/src/components/row/Row.stories.tsx +474 -58
- package/src/components/searchBar/SearchBar.stories.tsx +570 -38
- package/src/components/section/Section.stories.tsx +723 -70
- package/src/components/singleUser/SingleUser.stories.tsx +393 -34
- package/src/components/slideoverManager/SlideoverManager.stories.tsx +572 -342
- package/src/components/table/DSDefaultColDef.ts +25 -5
- package/src/components/table/Table.stories.tsx +504 -3
- package/src/components/table/Table.test.tsx +255 -0
- package/src/components/table/Table.tsx +15 -2
- package/src/components/table/TableFooter.stories.tsx +196 -0
- package/src/components/table/TableHeader.stories.tsx +251 -0
- package/src/components/table/cellEditors/DateCellEditor.stories.tsx +245 -0
- package/src/components/table/cellEditors/NumberCellEditor.tsx +83 -0
- package/src/components/table/cellEditors/numberCellEditor.scss +11 -0
- package/src/components/table/cellRenderers/BooleanCellRenderer.stories.tsx +278 -0
- package/src/components/table/cellRenderers/ButtonCellRenderer.stories.tsx +333 -0
- package/src/components/table/cellRenderers/CheckboxCellRenderer.stories.tsx +337 -0
- package/src/components/table/cellRenderers/CheckboxCellRenderer.tsx +5 -1
- package/src/components/table/cellRenderers/DefaultCellRenderer.stories.tsx +342 -0
- package/src/components/table/cellRenderers/InlineTextCellRenderer.stories.tsx +292 -0
- package/src/components/table/cellRenderers/SelectDropdownCellRenderer.stories.tsx +369 -0
- package/src/components/table/columnFilters/BooleanFilter.stories.tsx +268 -0
- package/src/components/table/columnFilters/TimeFilter.stories.tsx +281 -0
- package/src/components/table/pagination/PaginationPanel.stories.tsx +327 -0
- package/src/components/table/table.scss +11 -0
- package/src/components/table/tableControls/TableControls.stories.tsx +415 -0
- package/src/components/table/tableControls/TableSettingsDropdown.test.tsx +207 -0
- package/src/components/table/tableControls/TableSettingsDropdown.tsx +103 -39
- package/src/components/tabs/Tabs.stories.tsx +540 -60
- package/src/components/tabs/TabsItem.stories.tsx +82 -8
- package/src/components/toast/Toast.stories.tsx +539 -77
- package/src/components/toggle/Toggle.stories.tsx +371 -135
- package/src/components/tooltip/Tooltip.stories.tsx +606 -15
- package/src/components/tooltip/TooltipWrapper.stories.tsx +348 -12
- package/src/docs/Contributing.mdx +241 -0
- package/src/docs/UsingComponents.mdx +93 -0
- package/src/docs/Welcome.mdx +68 -0
- package/src/global.scss +7 -0
- package/src/index.scss +1 -0
- package/src/index.ts +3 -2
- package/src/utils/PopupParentContext.stories.tsx +367 -0
- package/src/utils/getDefaultPopupParent.ts +6 -0
- package/.ralph/storybook-upgrade/knowledge.md +0 -308
- package/.ralph/storybook-upgrade/prd.json +0 -777
- package/.ralph/storybook-upgrade/progress.md +0 -342
- package/src/components/table/TableWIP.mdx +0 -3
|
@@ -1,163 +1,734 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Controls, Heading as DocHeading, Markdown, Primary as DocPrimary, Stories, Subtitle, Title, } from '@storybook/addon-docs/blocks';
|
|
4
|
+
import { FormField } from '../formField/FormField';
|
|
5
5
|
import { DateTimePicker } from './DateTimePicker';
|
|
6
|
-
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Docs page content
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const DESCRIPTION_INTRO = [
|
|
10
|
+
'DateTimePicker combines a date input with an embedded time input, keeping a single unified `Date`',
|
|
11
|
+
'value. Built on [Radix UI Popover](https://www.radix-ui.com/primitives/docs/components/popover)',
|
|
12
|
+
'and [react-day-picker](https://daypicker.dev/).',
|
|
13
|
+
'',
|
|
14
|
+
'The calendar popup contains both the date picker and the time input, keeping date and time',
|
|
15
|
+
'selection in a single interaction flow. When a date is picked from the calendar, the existing',
|
|
16
|
+
'time is preserved. When a time is changed, the existing date is preserved.',
|
|
17
|
+
].join('\n');
|
|
18
|
+
const USAGE_GUIDANCE = [
|
|
19
|
+
'### When to use',
|
|
20
|
+
'',
|
|
21
|
+
'- **Event scheduling** — lesson start times, parent evening appointments, report deadlines',
|
|
22
|
+
'- **Booking flows** — any scenario where both a date AND a specific time are required',
|
|
23
|
+
'- **Audit timestamps** — log entries, registration opens/closes with precise time',
|
|
24
|
+
'',
|
|
25
|
+
'---',
|
|
26
|
+
'',
|
|
27
|
+
'### When NOT to use',
|
|
28
|
+
'',
|
|
29
|
+
'| Situation | Use instead |',
|
|
30
|
+
'|---|---|',
|
|
31
|
+
'| Date only (no time needed) | `DatePicker` |',
|
|
32
|
+
'| Time only (no date needed) | `TimeInput` |',
|
|
33
|
+
'| Date range selection | Two `DatePicker` fields |',
|
|
34
|
+
'| Fixed time slots from a list | `DateTimePicker` with `timeOptions` |',
|
|
35
|
+
].join('\n');
|
|
36
|
+
const DEVELOPER_NOTES = [
|
|
37
|
+
'### Critical usage patterns',
|
|
38
|
+
'',
|
|
39
|
+
'> **Portal rendering.** The calendar panel renders via a Radix portal — do **not** place inside',
|
|
40
|
+
'> a container with `overflow: hidden` or the calendar will be clipped.',
|
|
41
|
+
'',
|
|
42
|
+
'**`onChange` receives a `Date` object — never a string.** Format for display with',
|
|
43
|
+
'`date?.toLocaleDateString(\'en-GB\')` + time as needed. Do not assume ISO string format.',
|
|
44
|
+
'',
|
|
45
|
+
'**`value` and `defaultValue` are `Date` objects — not strings.** Month is zero-indexed:',
|
|
46
|
+
'`new Date(2026, 3, 14, 9, 0)` = 14 April 2026, 09:00. Passing a string is a type error.',
|
|
47
|
+
'',
|
|
48
|
+
'```tsx',
|
|
49
|
+
'// ✅ Correct',
|
|
50
|
+
'value={new Date(2026, 3, 14, 9, 0)}',
|
|
51
|
+
'',
|
|
52
|
+
'// ❌ Wrong — type error',
|
|
53
|
+
'value="2026-04-14T09:00"',
|
|
54
|
+
'```',
|
|
55
|
+
'',
|
|
56
|
+
'**Three display formats — choose based on your context:**',
|
|
57
|
+
'',
|
|
58
|
+
'| `displayFormat` | Input type | Placeholder hint | Example value |',
|
|
59
|
+
'|---|---|---|---|',
|
|
60
|
+
'| `"native"` (default) | `datetime-local` | `YYYY-MM-DDTHH:mm` | `2026-04-14T14:27` |',
|
|
61
|
+
'| `"default"` | `text` | `DD/MM/YYYY HH:mm` | `14/04/2026 14:27` |',
|
|
62
|
+
'| `"friendly"` | `text` | `Pick a date, HH:mm` | `April 14th, 2026 14:27` |',
|
|
63
|
+
'',
|
|
64
|
+
'**`timeOptions` switches the embedded time input to combobox mode.** Instead of a free-form',
|
|
65
|
+
'time input, the user picks from a predefined list. Use for fixed appointment slots.',
|
|
66
|
+
'',
|
|
67
|
+
'**`hasError` is visual-only when used standalone.** It applies the red border but does NOT',
|
|
68
|
+
'set `aria-invalid`. Always pair both when outside `<FormField>`:',
|
|
69
|
+
'',
|
|
70
|
+
'```tsx',
|
|
71
|
+
'<DateTimePicker hasError aria-invalid={true} aria-describedby="error-id" />',
|
|
72
|
+
'```',
|
|
73
|
+
'',
|
|
74
|
+
'**`granularity="second"` enables seconds** in both the `datetime-local` step attribute',
|
|
75
|
+
'(native mode) and the embedded time input.',
|
|
76
|
+
'',
|
|
77
|
+
'---',
|
|
78
|
+
'',
|
|
79
|
+
'### Accessibility',
|
|
80
|
+
'',
|
|
81
|
+
'- Always label via `<FormField>` or `aria-label` / `aria-labelledby`',
|
|
82
|
+
'- Pair `hasError` with `aria-invalid={true}` when used standalone — `<FormField>` handles both',
|
|
83
|
+
'- The calendar icon button has built-in screen reader text ("Open date and time picker")',
|
|
84
|
+
'- The embedded time input has `aria-label="Select time"`',
|
|
85
|
+
'- The calendar closes and returns focus to the date input on date selection or Escape',
|
|
86
|
+
'',
|
|
87
|
+
'---',
|
|
88
|
+
'',
|
|
89
|
+
'### TypeScript types',
|
|
90
|
+
'',
|
|
91
|
+
'```ts',
|
|
92
|
+
"import { DateTimePicker } from '@arbor-education/design-system.components';",
|
|
93
|
+
'',
|
|
94
|
+
'// Access via namespace:',
|
|
95
|
+
'function MyField(props: DateTimePicker.Props) { ... }',
|
|
96
|
+
'',
|
|
97
|
+
'// Display format type:',
|
|
98
|
+
'const format: DateTimePicker.DisplayFormat = "native"; // "native" | "default" | "friendly"',
|
|
99
|
+
'```',
|
|
100
|
+
'',
|
|
101
|
+
'| Type | Description |',
|
|
102
|
+
'|---|---|',
|
|
103
|
+
'| `DateTimePicker.Props` | Full props interface |',
|
|
104
|
+
'| `DateTimePicker.DisplayFormat` | `"native" \\| "default" \\| "friendly"` |',
|
|
105
|
+
].join('\n');
|
|
106
|
+
const RELATED_COMPONENTS = [
|
|
107
|
+
'## Related components',
|
|
108
|
+
'',
|
|
109
|
+
'[DatePicker](?path=/docs/components-datepicker--docs) · [TimeInput](?path=/docs/components-formfield-inputs-timeinput--docs) · [FormField](?path=/docs/components-formfield--docs)',
|
|
110
|
+
].join('\n');
|
|
111
|
+
const PROPS_INTRO = 'The preview below is wired to the **Controls** panel — tweak any prop to see the story update in real time.';
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Docs page component
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
function DateTimePickerDocsPage() {
|
|
116
|
+
return (_jsxs(_Fragment, { children: [_jsx(Title, {}), _jsx(Subtitle, {}), _jsx(Markdown, { children: DESCRIPTION_INTRO }), _jsx(DocHeading, { children: "Interactive example" }), _jsx(Markdown, { children: PROPS_INTRO }), _jsx(DocPrimary, {}), _jsx(Controls, {}), _jsx(DocHeading, { children: "Usage guidance" }), _jsx(Markdown, { children: USAGE_GUIDANCE }), _jsx(DocHeading, { children: "Developer notes" }), _jsx(Markdown, { children: DEVELOPER_NOTES }), _jsx(DocHeading, { children: "Examples" }), _jsx(Stories, { title: "" }), _jsx(Markdown, { children: RELATED_COMPONENTS })] }));
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Meta
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
7
121
|
const meta = {
|
|
8
122
|
title: 'Components/DateTimePicker',
|
|
9
123
|
component: DateTimePicker,
|
|
10
|
-
|
|
11
|
-
Story => (_jsx("div", { style: { maxWidth: '280px', width: '100%' }, children: _jsx(Story, {}) })),
|
|
12
|
-
],
|
|
124
|
+
tags: ['autodocs'],
|
|
13
125
|
parameters: {
|
|
14
|
-
layout: '
|
|
126
|
+
layout: 'padded',
|
|
15
127
|
docs: {
|
|
16
|
-
|
|
17
|
-
component: '`DateTimePicker` combines a date field with the existing `TimeInput`, keeping a single combined `Date` value. `displayFormat="native"` (default) uses a `datetime-local` input with a decorative empty-state hint span (browsers do not reliably show placeholders on native date/time fields). `"default"` and `"friendly"` use a plain text input with locale-style formatting and a real HTML placeholder.',
|
|
18
|
-
},
|
|
128
|
+
page: DateTimePickerDocsPage,
|
|
19
129
|
},
|
|
20
130
|
},
|
|
21
|
-
tags: ['autodocs'],
|
|
22
|
-
args: {
|
|
23
|
-
onChange: fn(),
|
|
24
|
-
},
|
|
25
131
|
argTypes: {
|
|
26
|
-
displayFormat: {
|
|
27
|
-
control: 'inline-radio',
|
|
132
|
+
'displayFormat': {
|
|
133
|
+
control: { type: 'inline-radio' },
|
|
28
134
|
options: ['native', 'default', 'friendly'],
|
|
29
|
-
description:
|
|
135
|
+
description: [
|
|
136
|
+
'Controls input type and value format.',
|
|
137
|
+
'`"native"` (default): `datetime-local` input with `YYYY-MM-DDTHH:mm` hint.',
|
|
138
|
+
'`"default"`: text input with `DD/MM/YYYY HH:mm` format.',
|
|
139
|
+
'`"friendly"`: text input with `April 14th, 2026 14:27` format.',
|
|
140
|
+
].join(' '),
|
|
141
|
+
table: {
|
|
142
|
+
type: { summary: '"native" | "default" | "friendly"' },
|
|
143
|
+
defaultValue: { summary: '"native"' },
|
|
144
|
+
},
|
|
30
145
|
},
|
|
31
|
-
granularity: {
|
|
32
|
-
control: 'inline-radio',
|
|
146
|
+
'granularity': {
|
|
147
|
+
control: { type: 'inline-radio' },
|
|
33
148
|
options: ['minute', 'second'],
|
|
34
|
-
description:
|
|
149
|
+
description: [
|
|
150
|
+
'Controls time precision.',
|
|
151
|
+
'`"minute"` (default): HH:mm.',
|
|
152
|
+
'`"second"`: HH:mm:ss — sets `step={1}` on the datetime-local input and shows seconds in the embedded time input.',
|
|
153
|
+
].join(' '),
|
|
154
|
+
table: {
|
|
155
|
+
type: { summary: '"minute" | "second"' },
|
|
156
|
+
defaultValue: { summary: '"minute"' },
|
|
157
|
+
},
|
|
35
158
|
},
|
|
36
|
-
|
|
37
|
-
control: '
|
|
38
|
-
description:
|
|
159
|
+
'placeholder': {
|
|
160
|
+
control: 'text',
|
|
161
|
+
description: [
|
|
162
|
+
'Custom text for the empty-state hint overlay (native mode only).',
|
|
163
|
+
'When set and the field is empty, the input becomes read-only — the calendar opens on click only, not Tab focus.',
|
|
164
|
+
].join(' '),
|
|
165
|
+
table: {
|
|
166
|
+
type: { summary: 'string' },
|
|
167
|
+
defaultValue: { summary: 'undefined' },
|
|
168
|
+
},
|
|
39
169
|
},
|
|
40
|
-
|
|
170
|
+
'onChange': {
|
|
41
171
|
control: false,
|
|
42
|
-
|
|
172
|
+
action: 'onChange',
|
|
173
|
+
description: [
|
|
174
|
+
'Callback fired when the combined date+time changes.',
|
|
175
|
+
'Receives a `Date` object, or `undefined` when cleared.',
|
|
176
|
+
'Never receives a string.',
|
|
177
|
+
].join(' '),
|
|
178
|
+
table: {
|
|
179
|
+
type: { summary: '(newDate?: Date) => void' },
|
|
180
|
+
},
|
|
43
181
|
},
|
|
44
|
-
|
|
182
|
+
'hasError': {
|
|
183
|
+
control: 'boolean',
|
|
184
|
+
description: [
|
|
185
|
+
'Applies error-state visual styling (red border).',
|
|
186
|
+
'Does **not** set `aria-invalid` automatically when used standalone.',
|
|
187
|
+
'Always pair with `aria-invalid={true}`. `<FormField>` handles both automatically.',
|
|
188
|
+
].join(' '),
|
|
189
|
+
table: {
|
|
190
|
+
type: { summary: 'boolean' },
|
|
191
|
+
defaultValue: { summary: 'false' },
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
'value': {
|
|
195
|
+
control: false,
|
|
196
|
+
description: [
|
|
197
|
+
'Controlled combined date+time value.',
|
|
198
|
+
'Must be a `Date` object — not a string.',
|
|
199
|
+
'Pair with `onChange` to keep state in sync.',
|
|
200
|
+
].join(' '),
|
|
201
|
+
table: {
|
|
202
|
+
type: { summary: 'Date' },
|
|
203
|
+
defaultValue: { summary: 'undefined' },
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
'defaultValue': {
|
|
45
207
|
control: false,
|
|
46
|
-
description:
|
|
208
|
+
description: [
|
|
209
|
+
'Uncontrolled initial date+time.',
|
|
210
|
+
'Must be a `Date` object (month is zero-indexed: `new Date(2026, 3, 14, 9, 0)` = 14 Apr 2026 09:00).',
|
|
211
|
+
'Use when you only need the value on form submit.',
|
|
212
|
+
].join(' '),
|
|
213
|
+
table: {
|
|
214
|
+
type: { summary: 'Date' },
|
|
215
|
+
defaultValue: { summary: 'undefined' },
|
|
216
|
+
},
|
|
47
217
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
description:
|
|
218
|
+
'timeOptions': {
|
|
219
|
+
control: false,
|
|
220
|
+
description: [
|
|
221
|
+
'Array of `TimeValue` strings to use as preset time slots.',
|
|
222
|
+
'When provided, the embedded time input switches to **combobox mode** — the user picks from the list instead of typing freely.',
|
|
223
|
+
'Ideal for fixed appointment slots like "09:00", "09:30", "10:00".',
|
|
224
|
+
].join(' '),
|
|
225
|
+
table: {
|
|
226
|
+
type: { summary: 'TimeValue[]' },
|
|
227
|
+
defaultValue: { summary: 'undefined' },
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
'searchType': {
|
|
231
|
+
control: { type: 'select' },
|
|
232
|
+
options: ['prefix', 'substring'],
|
|
233
|
+
description: [
|
|
234
|
+
'**Only used when `timeOptions` is provided.**',
|
|
235
|
+
'Controls how the time combobox filters options as the user types.',
|
|
236
|
+
'`"prefix"` (default) matches from the start; `"substring"` matches anywhere.',
|
|
237
|
+
].join(' '),
|
|
238
|
+
table: {
|
|
239
|
+
type: { summary: '"prefix" | "substring"' },
|
|
240
|
+
defaultValue: { summary: '"prefix"' },
|
|
241
|
+
},
|
|
51
242
|
},
|
|
52
|
-
|
|
243
|
+
'highlightStringMatches': {
|
|
244
|
+
control: 'boolean',
|
|
245
|
+
description: '**Only used when `timeOptions` is provided.** Bolds matched characters in the time dropdown.',
|
|
246
|
+
table: {
|
|
247
|
+
type: { summary: 'boolean' },
|
|
248
|
+
defaultValue: { summary: 'false' },
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
'id': {
|
|
252
|
+
control: 'text',
|
|
253
|
+
description: 'HTML `id` for the date input element. Required when inside `<FormField>` so the label `htmlFor` can be linked.',
|
|
254
|
+
table: {
|
|
255
|
+
type: { summary: 'string' },
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
'className': {
|
|
259
|
+
control: 'text',
|
|
260
|
+
description: 'Additional CSS class names on the root wrapper element.',
|
|
261
|
+
table: {
|
|
262
|
+
type: { summary: 'string' },
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
'aria-invalid': {
|
|
266
|
+
control: 'boolean',
|
|
267
|
+
description: [
|
|
268
|
+
'Marks the date input as invalid for screen readers.',
|
|
269
|
+
'Must be set manually when used standalone — `<FormField>` sets this automatically when `errorText` is provided.',
|
|
270
|
+
].join(' '),
|
|
271
|
+
table: {
|
|
272
|
+
type: { summary: 'boolean | "true" | "false"' },
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
'aria-describedby': {
|
|
53
276
|
control: 'text',
|
|
54
|
-
description: '
|
|
277
|
+
description: 'ID of the element describing the field (e.g. an error message).',
|
|
278
|
+
table: {
|
|
279
|
+
type: { summary: 'string' },
|
|
280
|
+
},
|
|
55
281
|
},
|
|
56
282
|
},
|
|
57
283
|
};
|
|
58
284
|
export default meta;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
granularity: 'minute',
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
// Helper: attach a per-story description
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
const withDescription = (story, description) => ({
|
|
289
|
+
...story,
|
|
290
|
+
parameters: {
|
|
291
|
+
...story.parameters,
|
|
292
|
+
docs: {
|
|
293
|
+
...story.parameters?.docs,
|
|
294
|
+
description: {
|
|
295
|
+
story: description,
|
|
296
|
+
},
|
|
297
|
+
},
|
|
73
298
|
},
|
|
74
|
-
|
|
299
|
+
});
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
// Named template components for stateful stories
|
|
302
|
+
// ---------------------------------------------------------------------------
|
|
303
|
+
const APPOINTMENT_SLOTS = [
|
|
304
|
+
'09:00',
|
|
305
|
+
'09:30',
|
|
306
|
+
'10:00',
|
|
307
|
+
'10:30',
|
|
308
|
+
'11:00',
|
|
309
|
+
'11:30',
|
|
310
|
+
'14:00',
|
|
311
|
+
'14:30',
|
|
312
|
+
'15:00',
|
|
313
|
+
'15:30',
|
|
314
|
+
];
|
|
315
|
+
const DisplayFormatDefaultTemplate = () => {
|
|
316
|
+
const [value, setValue] = useState(new Date(2026, 3, 14, 14, 27));
|
|
317
|
+
return (_jsxs("div", { style: { maxWidth: '320px' }, children: [_jsx(DateTimePicker, { displayFormat: "default", value: value, onChange: setValue, id: "format-default" }), _jsxs("p", { style: { margin: 'var(--spacing-small) 0 0', color: 'var(--color-grey-600)' }, children: ["Value:", ' ', _jsx("code", { children: value
|
|
318
|
+
? `${value.toLocaleDateString('en-GB')} ${value.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}`
|
|
319
|
+
: '(none)' })] })] }));
|
|
75
320
|
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
render: args => _jsx(ControlledDateTimePicker, { ...args }),
|
|
321
|
+
const DisplayFormatFriendlyTemplate = () => {
|
|
322
|
+
const [value, setValue] = useState(new Date(2026, 3, 14, 14, 27));
|
|
323
|
+
return (_jsxs("div", { style: { maxWidth: '320px' }, children: [_jsx(DateTimePicker, { displayFormat: "friendly", value: value, onChange: setValue, id: "format-friendly" }), _jsxs("p", { style: { margin: 'var(--spacing-small) 0 0', color: 'var(--color-grey-600)' }, children: ["Value:", ' ', _jsx("code", { children: value
|
|
324
|
+
? `${value.toLocaleDateString('en-GB')} ${value.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}`
|
|
325
|
+
: '(none)' })] })] }));
|
|
82
326
|
};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
327
|
+
const WithTimeOptionsTemplate = () => {
|
|
328
|
+
const [value, setValue] = useState(new Date(2026, 3, 14, 9, 0));
|
|
329
|
+
return (_jsxs("div", { style: { maxWidth: '280px' }, children: [_jsx(DateTimePicker, { timeOptions: APPOINTMENT_SLOTS, value: value, onChange: setValue, id: "time-options" }), _jsxs("p", { style: { margin: 'var(--spacing-small) 0 0', color: 'var(--color-grey-600)' }, children: ["Appointment:", ' ', _jsx("code", { children: value
|
|
330
|
+
? `${value.toLocaleDateString('en-GB')} ${value.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}`
|
|
331
|
+
: '(none)' })] })] }));
|
|
332
|
+
};
|
|
333
|
+
const GranularitySecondTemplate = () => {
|
|
334
|
+
const [value, setValue] = useState(undefined);
|
|
335
|
+
return (_jsxs("div", { style: { maxWidth: '280px' }, children: [_jsx(DateTimePicker, { granularity: "second", value: value, onChange: setValue, id: "granularity-second" }), _jsxs("p", { style: { margin: 'var(--spacing-small) 0 0', color: 'var(--color-grey-600)' }, children: ["Value (with seconds):", ' ', _jsx("code", { children: value
|
|
336
|
+
? `${value.toLocaleDateString('en-GB')} ${value.toLocaleTimeString('en-GB')}`
|
|
337
|
+
: '(none)' })] })] }));
|
|
89
338
|
};
|
|
90
|
-
|
|
91
|
-
|
|
339
|
+
const ControlledWithDisplayTemplate = () => {
|
|
340
|
+
const [value, setValue] = useState(undefined);
|
|
341
|
+
return (_jsxs("div", { style: { maxWidth: '280px' }, children: [_jsx(DateTimePicker, { id: "controlled-display", onChange: setValue }), _jsxs("p", { style: { margin: 'var(--spacing-small) 0 0', color: 'var(--color-grey-600)' }, children: ["Selected:", ' ', _jsx("code", { children: value
|
|
342
|
+
? `${value.toLocaleDateString('en-GB')} ${value.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}`
|
|
343
|
+
: '(none)' })] })] }));
|
|
344
|
+
};
|
|
345
|
+
const WithFormFieldTemplate = () => (_jsx("div", { style: { maxWidth: '320px' }, children: _jsx(FormField, { label: "Event start date and time", id: "ff-event-start", inputType: "dateTimePicker", fieldDescription: "Select the date and time the event will begin.", inputProps: {} }) }));
|
|
346
|
+
const WithFormFieldAndErrorTemplate = () => {
|
|
347
|
+
const [submitted, setSubmitted] = useState(false);
|
|
348
|
+
const [selectedDate, setSelectedDate] = useState(undefined);
|
|
349
|
+
const hasError = submitted && !selectedDate;
|
|
350
|
+
return (_jsxs("div", { style: { maxWidth: '320px', display: 'flex', flexDirection: 'column', gap: 'var(--spacing-large)' }, children: [_jsx(FormField, { label: "Lesson start date and time", id: "ff-lesson-start", inputType: "dateTimePicker", errorText: hasError ? 'Please select a date and time for the lesson.' : undefined, inputProps: {
|
|
351
|
+
'onChange': setSelectedDate,
|
|
352
|
+
hasError,
|
|
353
|
+
'aria-invalid': hasError ? true : undefined,
|
|
354
|
+
} }), _jsx("div", { children: _jsx("button", { type: "button", onClick: () => setSubmitted(true), style: { padding: 'var(--spacing-small) var(--spacing-medium)' }, children: "Submit" }) }), submitted && selectedDate && (_jsxs("p", { style: { margin: 0, color: 'var(--color-semantic-success-600)', fontSize: '0.875rem' }, children: ["Lesson scheduled for", ' ', selectedDate.toLocaleDateString('en-GB'), ' at ', selectedDate.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' }), "."] }))] }));
|
|
355
|
+
};
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
// Stories
|
|
358
|
+
// ---------------------------------------------------------------------------
|
|
359
|
+
export const Default = withDescription({
|
|
92
360
|
args: {
|
|
93
|
-
|
|
361
|
+
id: 'default-datetime',
|
|
94
362
|
},
|
|
363
|
+
render: args => (_jsx("div", { style: { maxWidth: '280px' }, children: _jsx(DateTimePicker, { ...args }) })),
|
|
364
|
+
}, [
|
|
365
|
+
'The interactive canvas — every prop is wired to the Controls panel.',
|
|
366
|
+
'Default `displayFormat="native"` shows the `YYYY-MM-DDTHH:mm` hint overlay (a decorative span,',
|
|
367
|
+
'because browsers do not reliably show `placeholder` on `datetime-local` inputs).',
|
|
368
|
+
'Click the calendar icon to open the combined date+time picker.',
|
|
369
|
+
].join(' '));
|
|
370
|
+
export const WithDefaultValue = withDescription({
|
|
371
|
+
render: () => (_jsx("div", { style: { maxWidth: '280px' }, children: _jsx(DateTimePicker, { id: "default-value-datetime", defaultValue: new Date(2026, 3, 14, 14, 27) }) })),
|
|
95
372
|
parameters: {
|
|
373
|
+
controls: { disable: true },
|
|
96
374
|
docs: {
|
|
97
|
-
|
|
98
|
-
|
|
375
|
+
source: {
|
|
376
|
+
language: 'tsx',
|
|
377
|
+
code: `
|
|
378
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
379
|
+
|
|
380
|
+
function EditEventStart() {
|
|
381
|
+
// 14 April 2026, 14:27 — month is zero-indexed (Apr = 3)
|
|
382
|
+
const eventStart = new Date(2026, 3, 14, 14, 27);
|
|
383
|
+
|
|
384
|
+
return (
|
|
385
|
+
<DateTimePicker
|
|
386
|
+
id="event-start"
|
|
387
|
+
defaultValue={eventStart}
|
|
388
|
+
onChange={(date) => {
|
|
389
|
+
// date is Date | undefined — not a string
|
|
390
|
+
console.log('Updated to:', date?.toLocaleString('en-GB'));
|
|
391
|
+
}}
|
|
392
|
+
/>
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
export default EditEventStart;
|
|
396
|
+
`.trim(),
|
|
99
397
|
},
|
|
100
398
|
},
|
|
101
399
|
},
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
400
|
+
}, [
|
|
401
|
+
'Use `defaultValue` to pre-populate an uncontrolled DateTimePicker — for example when editing',
|
|
402
|
+
'an existing event. The prop must be a `Date` object (month is zero-indexed: April = 3).',
|
|
403
|
+
].join(' '));
|
|
404
|
+
export const GranularitySecond = withDescription({
|
|
405
|
+
render: () => _jsx(GranularitySecondTemplate, {}),
|
|
406
|
+
parameters: {
|
|
407
|
+
controls: { disable: true },
|
|
408
|
+
docs: {
|
|
409
|
+
source: {
|
|
410
|
+
language: 'tsx',
|
|
411
|
+
code: `
|
|
412
|
+
import { useState } from 'react';
|
|
413
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
414
|
+
|
|
415
|
+
function PreciseDateTimePickerExample() {
|
|
416
|
+
const [value, setValue] = useState<Date | undefined>(undefined);
|
|
417
|
+
|
|
418
|
+
return (
|
|
419
|
+
<DateTimePicker
|
|
420
|
+
granularity="second"
|
|
421
|
+
value={value}
|
|
422
|
+
onChange={setValue}
|
|
423
|
+
id="precise-datetime"
|
|
424
|
+
/>
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
export default PreciseDateTimePickerExample;
|
|
428
|
+
`.trim(),
|
|
429
|
+
},
|
|
430
|
+
},
|
|
107
431
|
},
|
|
432
|
+
}, [
|
|
433
|
+
'`granularity="second"` enables seconds in both the `datetime-local` native input (sets `step={1}`)',
|
|
434
|
+
'and the embedded time input inside the calendar popup.',
|
|
435
|
+
'Use for precise event logging, stopwatch-style entry, or when sub-minute accuracy matters.',
|
|
436
|
+
].join(' '));
|
|
437
|
+
export const DisplayFormatDefault = withDescription({
|
|
438
|
+
render: () => _jsx(DisplayFormatDefaultTemplate, {}),
|
|
108
439
|
parameters: {
|
|
440
|
+
controls: { disable: true },
|
|
109
441
|
docs: {
|
|
110
|
-
|
|
111
|
-
|
|
442
|
+
source: {
|
|
443
|
+
language: 'tsx',
|
|
444
|
+
code: `
|
|
445
|
+
import { useState } from 'react';
|
|
446
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
447
|
+
|
|
448
|
+
function FormattedDateTimePickerExample() {
|
|
449
|
+
const [value, setValue] = useState<Date | undefined>(new Date(2026, 3, 14, 14, 27));
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
<DateTimePicker
|
|
453
|
+
displayFormat="default"
|
|
454
|
+
value={value}
|
|
455
|
+
onChange={setValue}
|
|
456
|
+
id="event-datetime"
|
|
457
|
+
/>
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
export default FormattedDateTimePickerExample;
|
|
461
|
+
`.trim(),
|
|
112
462
|
},
|
|
113
463
|
},
|
|
114
464
|
},
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
465
|
+
}, [
|
|
466
|
+
'`displayFormat="default"` uses a plain text input showing the value as `DD/MM/YYYY HH:mm`',
|
|
467
|
+
'(e.g. `14/04/2026 14:27`). The appearance is consistent across all browsers — unlike `"native"`,',
|
|
468
|
+
'which uses the OS date/time widget and varies by platform.',
|
|
469
|
+
].join(' '));
|
|
470
|
+
export const DisplayFormatFriendly = withDescription({
|
|
471
|
+
render: () => _jsx(DisplayFormatFriendlyTemplate, {}),
|
|
472
|
+
parameters: {
|
|
473
|
+
controls: { disable: true },
|
|
474
|
+
docs: {
|
|
475
|
+
source: {
|
|
476
|
+
language: 'tsx',
|
|
477
|
+
code: `
|
|
478
|
+
import { useState } from 'react';
|
|
479
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
480
|
+
|
|
481
|
+
function FriendlyDateTimePickerExample() {
|
|
482
|
+
const [value, setValue] = useState<Date | undefined>(new Date(2026, 3, 14, 14, 27));
|
|
483
|
+
|
|
484
|
+
return (
|
|
485
|
+
<DateTimePicker
|
|
486
|
+
displayFormat="friendly"
|
|
487
|
+
value={value}
|
|
488
|
+
onChange={setValue}
|
|
489
|
+
id="event-datetime"
|
|
490
|
+
/>
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
export default FriendlyDateTimePickerExample;
|
|
494
|
+
`.trim(),
|
|
495
|
+
},
|
|
496
|
+
},
|
|
122
497
|
},
|
|
123
|
-
|
|
498
|
+
}, [
|
|
499
|
+
'`displayFormat="friendly"` shows the value as `April 14th, 2026 14:27` — human-readable and',
|
|
500
|
+
'locale-style. Best for consumer-facing or less technical contexts where ISO-adjacent formats feel unfriendly.',
|
|
501
|
+
].join(' '));
|
|
502
|
+
export const WithTimeOptions = withDescription({
|
|
503
|
+
render: () => _jsx(WithTimeOptionsTemplate, {}),
|
|
124
504
|
parameters: {
|
|
505
|
+
controls: { disable: true },
|
|
125
506
|
docs: {
|
|
126
|
-
|
|
127
|
-
|
|
507
|
+
source: {
|
|
508
|
+
language: 'tsx',
|
|
509
|
+
code: `
|
|
510
|
+
import { useState } from 'react';
|
|
511
|
+
import { DateTimePicker, type TimeValue } from '@arbor-education/design-system.components';
|
|
512
|
+
|
|
513
|
+
const APPOINTMENT_SLOTS: TimeValue[] = [
|
|
514
|
+
'09:00', '09:30', '10:00', '10:30', '11:00', '11:30',
|
|
515
|
+
'14:00', '14:30', '15:00', '15:30',
|
|
516
|
+
];
|
|
517
|
+
|
|
518
|
+
function AppointmentBookingExample() {
|
|
519
|
+
const [value, setValue] = useState<Date | undefined>(new Date(2026, 3, 14, 9, 0));
|
|
520
|
+
|
|
521
|
+
return (
|
|
522
|
+
<DateTimePicker
|
|
523
|
+
timeOptions={APPOINTMENT_SLOTS}
|
|
524
|
+
value={value}
|
|
525
|
+
onChange={setValue}
|
|
526
|
+
id="appointment-datetime"
|
|
527
|
+
/>
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
export default AppointmentBookingExample;
|
|
531
|
+
`.trim(),
|
|
128
532
|
},
|
|
129
533
|
},
|
|
130
534
|
},
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
535
|
+
}, [
|
|
536
|
+
'`timeOptions` switches the embedded time input from free-form entry to a combobox list.',
|
|
537
|
+
'Ideal for appointment booking where only specific slots are valid — the user picks a date',
|
|
538
|
+
'from the calendar, then picks a slot from the dropdown. Both stay in a single `Date` value.',
|
|
539
|
+
].join(' '));
|
|
540
|
+
export const WithPlaceholder = withDescription({
|
|
541
|
+
render: () => (_jsx("div", { style: { maxWidth: '280px' }, children: _jsx(DateTimePicker, { id: "placeholder-datetime", placeholder: "Choose event start" }) })),
|
|
542
|
+
parameters: {
|
|
543
|
+
controls: { disable: true },
|
|
544
|
+
docs: {
|
|
545
|
+
source: {
|
|
546
|
+
language: 'tsx',
|
|
547
|
+
code: `
|
|
548
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
549
|
+
|
|
550
|
+
function GuidedDateTimePickerExample() {
|
|
551
|
+
return (
|
|
552
|
+
<DateTimePicker
|
|
553
|
+
id="event-start"
|
|
554
|
+
placeholder="Choose event start"
|
|
555
|
+
onChange={(date) => {
|
|
556
|
+
console.log('Event start:', date?.toLocaleString('en-GB'));
|
|
557
|
+
}}
|
|
558
|
+
/>
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
export default GuidedDateTimePickerExample;
|
|
562
|
+
`.trim(),
|
|
563
|
+
},
|
|
564
|
+
},
|
|
138
565
|
},
|
|
139
|
-
|
|
566
|
+
}, [
|
|
567
|
+
'`placeholder` (native mode only) replaces the `YYYY-MM-DDTHH:mm` hint with custom copy.',
|
|
568
|
+
'When set and the field is empty, the input becomes **read-only** and the calendar opens on',
|
|
569
|
+
'**click only** — Tab focus does not trigger it. Prevents accidental popup during keyboard navigation.',
|
|
570
|
+
].join(' '));
|
|
571
|
+
export const ErrorState = withDescription({
|
|
572
|
+
render: () => (_jsxs("div", { style: { maxWidth: '280px' }, children: [_jsx(DateTimePicker, { id: "error-state-datetime", hasError: true, "aria-invalid": true, "aria-describedby": "error-state-datetime-msg" }), _jsx("p", { id: "error-state-datetime-msg", role: "alert", style: { margin: 'var(--spacing-xsmall) 0 0', color: 'var(--color-semantic-destructive-600)', fontSize: '0.875rem' }, children: "Please select a valid date and time." })] })),
|
|
140
573
|
parameters: {
|
|
574
|
+
controls: { disable: true },
|
|
141
575
|
docs: {
|
|
142
|
-
|
|
143
|
-
|
|
576
|
+
source: {
|
|
577
|
+
language: 'tsx',
|
|
578
|
+
code: `
|
|
579
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
580
|
+
|
|
581
|
+
// Standalone — set both hasError (visual) and aria-invalid (screen reader) yourself.
|
|
582
|
+
// Inside <FormField> both are handled automatically when errorText is set.
|
|
583
|
+
function DateTimePickerWithError() {
|
|
584
|
+
return (
|
|
585
|
+
<>
|
|
586
|
+
<DateTimePicker
|
|
587
|
+
id="event-start"
|
|
588
|
+
hasError
|
|
589
|
+
aria-invalid={true}
|
|
590
|
+
aria-describedby="event-start-error"
|
|
591
|
+
/>
|
|
592
|
+
<p id="event-start-error" role="alert">
|
|
593
|
+
Please select a valid date and time.
|
|
594
|
+
</p>
|
|
595
|
+
</>
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
export default DateTimePickerWithError;
|
|
599
|
+
`.trim(),
|
|
144
600
|
},
|
|
145
601
|
},
|
|
146
602
|
},
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
603
|
+
}, [
|
|
604
|
+
'The error state requires **both** `hasError` (visual red border) and `aria-invalid={true}`',
|
|
605
|
+
'(screen-reader signal). Use `aria-describedby` to link the input to the error message.',
|
|
606
|
+
'When using `<FormField>`, set `errorText` and the component handles all three automatically.',
|
|
607
|
+
].join(' '));
|
|
608
|
+
export const ControlledWithDisplay = withDescription({
|
|
609
|
+
render: () => _jsx(ControlledWithDisplayTemplate, {}),
|
|
610
|
+
parameters: {
|
|
611
|
+
controls: { disable: true },
|
|
612
|
+
docs: {
|
|
613
|
+
source: {
|
|
614
|
+
language: 'tsx',
|
|
615
|
+
code: `
|
|
616
|
+
import { useState } from 'react';
|
|
617
|
+
import { DateTimePicker } from '@arbor-education/design-system.components';
|
|
618
|
+
|
|
619
|
+
function ControlledDateTimePickerExample() {
|
|
620
|
+
const [value, setValue] = useState<Date | undefined>(undefined);
|
|
621
|
+
|
|
622
|
+
return (
|
|
623
|
+
<div>
|
|
624
|
+
<DateTimePicker
|
|
625
|
+
id="event-datetime"
|
|
626
|
+
onChange={setValue}
|
|
627
|
+
/>
|
|
628
|
+
<p>
|
|
629
|
+
Selected:{' '}
|
|
630
|
+
<code>
|
|
631
|
+
{value
|
|
632
|
+
? \`\${value.toLocaleDateString('en-GB')} \${value.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}\`
|
|
633
|
+
: '(none)'}
|
|
634
|
+
</code>
|
|
635
|
+
</p>
|
|
636
|
+
</div>
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
export default ControlledDateTimePickerExample;
|
|
640
|
+
`.trim(),
|
|
641
|
+
},
|
|
642
|
+
},
|
|
153
643
|
},
|
|
644
|
+
}, [
|
|
645
|
+
'`onChange` receives a `Date` object (or `undefined`) — never a string.',
|
|
646
|
+
'This controlled example stores the combined date+time in state and renders it below the field.',
|
|
647
|
+
'Use `toLocaleDateString` + `toLocaleTimeString` (or `date-fns format`) for display.',
|
|
648
|
+
].join(' '));
|
|
649
|
+
export const WithFormField = withDescription({
|
|
650
|
+
render: () => _jsx(WithFormFieldTemplate, {}),
|
|
154
651
|
parameters: {
|
|
652
|
+
controls: { disable: true },
|
|
155
653
|
docs: {
|
|
156
|
-
|
|
157
|
-
|
|
654
|
+
source: {
|
|
655
|
+
language: 'tsx',
|
|
656
|
+
code: `
|
|
657
|
+
import { FormField } from '@arbor-education/design-system.components';
|
|
658
|
+
|
|
659
|
+
function EventStartField() {
|
|
660
|
+
return (
|
|
661
|
+
<FormField
|
|
662
|
+
label="Event start date and time"
|
|
663
|
+
id="event-start"
|
|
664
|
+
inputType="dateTimePicker"
|
|
665
|
+
fieldDescription="Select the date and time the event will begin."
|
|
666
|
+
inputProps={{
|
|
667
|
+
onChange: (date) => {
|
|
668
|
+
// date is Date | undefined
|
|
669
|
+
console.log('Event start:', date?.toLocaleString('en-GB'));
|
|
670
|
+
},
|
|
671
|
+
}}
|
|
672
|
+
/>
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
export default EventStartField;
|
|
676
|
+
`.trim(),
|
|
158
677
|
},
|
|
159
678
|
},
|
|
160
679
|
},
|
|
161
|
-
|
|
162
|
-
|
|
680
|
+
}, [
|
|
681
|
+
'The recommended form usage: `<FormField inputType="dateTimePicker">` provides the accessible',
|
|
682
|
+
'label, description, and error layout. DateTimePicker props go in `inputProps`.',
|
|
683
|
+
'The `label`, `fieldDescription`, and `errorText` props belong on `<FormField>` itself.',
|
|
684
|
+
].join(' '));
|
|
685
|
+
export const WithFormFieldAndError = withDescription({
|
|
686
|
+
render: () => _jsx(WithFormFieldAndErrorTemplate, {}),
|
|
687
|
+
parameters: {
|
|
688
|
+
controls: { disable: true },
|
|
689
|
+
docs: {
|
|
690
|
+
source: {
|
|
691
|
+
language: 'tsx',
|
|
692
|
+
code: `
|
|
693
|
+
import { useState } from 'react';
|
|
694
|
+
import { FormField } from '@arbor-education/design-system.components';
|
|
695
|
+
|
|
696
|
+
function LessonSchedulerForm() {
|
|
697
|
+
const [submitted, setSubmitted] = useState(false);
|
|
698
|
+
const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
|
|
699
|
+
const hasError = submitted && !selectedDate;
|
|
700
|
+
|
|
701
|
+
return (
|
|
702
|
+
<div>
|
|
703
|
+
<FormField
|
|
704
|
+
label="Lesson start date and time"
|
|
705
|
+
id="lesson-start"
|
|
706
|
+
inputType="dateTimePicker"
|
|
707
|
+
errorText={
|
|
708
|
+
hasError
|
|
709
|
+
? 'Please select a date and time for the lesson.'
|
|
710
|
+
: undefined
|
|
711
|
+
}
|
|
712
|
+
inputProps={{
|
|
713
|
+
onChange: setSelectedDate,
|
|
714
|
+
hasError,
|
|
715
|
+
'aria-invalid': hasError ? true : undefined,
|
|
716
|
+
}}
|
|
717
|
+
/>
|
|
718
|
+
<button type="button" onClick={() => setSubmitted(true)}>
|
|
719
|
+
Submit
|
|
720
|
+
</button>
|
|
721
|
+
</div>
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
export default LessonSchedulerForm;
|
|
725
|
+
`.trim(),
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
},
|
|
729
|
+
}, [
|
|
730
|
+
'A submit-gated form: clicking Submit without a selection triggers the full error pattern.',
|
|
731
|
+
'`errorText` on `<FormField>` renders the message in the correct accessible layout,',
|
|
732
|
+
'linked via `aria-describedby` automatically. Once a date+time is chosen, the error clears.',
|
|
733
|
+
].join(' '));
|
|
163
734
|
//# sourceMappingURL=DateTimePicker.stories.js.map
|