@human-kit/svelte-components 1.0.0-alpha.2 → 1.0.0-alpha.21
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/dist/FOCUS_STATE_CONTRACT.md +63 -0
- package/dist/FOCUS_STATE_REVIEW_TEMPLATE.md +70 -0
- package/dist/button/README.md +48 -0
- package/dist/button/TODO.md +13 -0
- package/dist/button/index.d.ts +5 -0
- package/dist/button/index.js +4 -0
- package/dist/button/index.parts.d.ts +1 -0
- package/dist/button/index.parts.js +1 -0
- package/dist/button/root/README.md +43 -0
- package/dist/button/root/button-root.svelte +393 -0
- package/dist/button/root/button-root.svelte.d.ts +21 -0
- package/dist/button/root/button-test.svelte +76 -0
- package/dist/button/root/button-test.svelte.d.ts +11 -0
- package/dist/calendar/README.md +2 -1
- package/dist/calendar/TODO.md +21 -107
- package/dist/calendar/body-cell/README.md +15 -0
- package/dist/calendar/body-cell/calendar-body-cell.svelte +116 -41
- package/dist/calendar/grid/README.md +13 -0
- package/dist/calendar/grid-body/README.md +13 -0
- package/dist/calendar/grid-header/README.md +13 -0
- package/dist/calendar/header-cell/README.md +14 -0
- package/dist/calendar/heading/README.md +13 -0
- package/dist/calendar/index.d.ts +3 -3
- package/dist/calendar/index.js +3 -3
- package/dist/calendar/root/README.md +24 -0
- package/dist/calendar/root/calendar-root-test.svelte +4 -0
- package/dist/calendar/root/calendar-root-test.svelte.d.ts +1 -0
- package/dist/calendar/root/calendar-root.svelte +3 -0
- package/dist/calendar/root/calendar-root.svelte.d.ts +1 -0
- package/dist/calendar/root/context.d.ts +4 -0
- package/dist/calendar/root/context.js +28 -25
- package/dist/calendar/root/date-utils.d.ts +1 -1
- package/dist/calendar/root/date-utils.js +16 -26
- package/dist/calendar/trigger-next/README.md +14 -0
- package/dist/calendar/trigger-next/calendar-trigger-next.svelte +9 -4
- package/dist/calendar/trigger-next/calendar-trigger-next.svelte.d.ts +2 -1
- package/dist/calendar/trigger-previous/README.md +14 -0
- package/dist/calendar/trigger-previous/calendar-trigger-previous.svelte +9 -4
- package/dist/calendar/trigger-previous/calendar-trigger-previous.svelte.d.ts +2 -1
- package/dist/checkbox/README.md +53 -0
- package/dist/checkbox/TODO.md +16 -0
- package/dist/checkbox/index.d.ts +6 -0
- package/dist/checkbox/index.js +6 -0
- package/dist/checkbox/index.parts.d.ts +2 -0
- package/dist/checkbox/index.parts.js +2 -0
- package/dist/checkbox/indicator/README.md +23 -0
- package/dist/checkbox/indicator/checkbox-indicator.svelte +43 -0
- package/dist/checkbox/indicator/checkbox-indicator.svelte.d.ts +10 -0
- package/dist/checkbox/root/README.md +47 -0
- package/dist/checkbox/root/checkbox-label-test.svelte +10 -0
- package/dist/checkbox/root/checkbox-label-test.svelte.d.ts +18 -0
- package/dist/checkbox/root/checkbox-root.svelte +386 -0
- package/dist/checkbox/root/checkbox-root.svelte.d.ts +29 -0
- package/dist/checkbox/root/checkbox-test.svelte +59 -0
- package/dist/checkbox/root/checkbox-test.svelte.d.ts +18 -0
- package/dist/checkbox/root/context.d.ts +21 -0
- package/dist/checkbox/root/context.js +15 -0
- package/dist/clock/README.md +75 -0
- package/dist/clock/axis/README.md +24 -0
- package/dist/clock/axis/clock-axis.svelte +37 -0
- package/dist/clock/axis/clock-axis.svelte.d.ts +8 -0
- package/dist/clock/hooks/use-wheel-scroll.svelte.d.ts +16 -0
- package/dist/clock/hooks/use-wheel-scroll.svelte.js +336 -0
- package/dist/clock/index.d.ts +10 -0
- package/dist/clock/index.js +10 -0
- package/dist/clock/index.parts.d.ts +4 -0
- package/dist/clock/index.parts.js +4 -0
- package/dist/clock/root/README.md +38 -0
- package/dist/clock/root/clock-root-test.svelte +62 -0
- package/dist/clock/root/clock-root-test.svelte.d.ts +14 -0
- package/dist/clock/root/clock-root.svelte +329 -0
- package/dist/clock/root/clock-root.svelte.d.ts +25 -0
- package/dist/clock/root/context.d.ts +22 -0
- package/dist/clock/root/context.js +15 -0
- package/dist/clock/root/resolve-visible-columns.d.ts +7 -0
- package/dist/clock/root/resolve-visible-columns.js +16 -0
- package/dist/clock/root/time-utils.d.ts +48 -0
- package/dist/clock/root/time-utils.js +314 -0
- package/dist/clock/root/wheel-options.d.ts +17 -0
- package/dist/clock/root/wheel-options.js +63 -0
- package/dist/clock/wheel-column/README.md +25 -0
- package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte +16 -0
- package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte.d.ts +3 -0
- package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte +29 -0
- package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte.d.ts +6 -0
- package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte +11 -0
- package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte.d.ts +3 -0
- package/dist/clock/wheel-column/clock-wheel-column-test.svelte +38 -0
- package/dist/clock/wheel-column/clock-wheel-column-test.svelte.d.ts +12 -0
- package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte +38 -0
- package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte.d.ts +12 -0
- package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte +29 -0
- package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte.d.ts +6 -0
- package/dist/clock/wheel-column/clock-wheel-column.svelte +499 -0
- package/dist/clock/wheel-column/clock-wheel-column.svelte.d.ts +17 -0
- package/dist/clock/wheel-item/README.md +17 -0
- package/dist/clock/wheel-item/clock-wheel-item.svelte +49 -0
- package/dist/clock/wheel-item/clock-wheel-item.svelte.d.ts +17 -0
- package/dist/combobox/README.md +8 -2
- package/dist/combobox/TODO.md +28 -175
- package/dist/combobox/button/README.md +8 -3
- package/dist/combobox/button/combobox-button-test.svelte +27 -0
- package/dist/combobox/button/combobox-button-test.svelte.d.ts +6 -0
- package/dist/combobox/button/combobox-button.svelte +10 -11
- package/dist/combobox/clear/README.md +21 -0
- package/dist/combobox/clear/combobox-clear-test.svelte +34 -0
- package/dist/combobox/clear/combobox-clear-test.svelte.d.ts +3 -0
- package/dist/combobox/clear/combobox-clear.svelte +61 -0
- package/dist/combobox/clear/combobox-clear.svelte.d.ts +9 -0
- package/dist/combobox/index.d.ts +5 -3
- package/dist/combobox/index.js +5 -3
- package/dist/combobox/index.parts.d.ts +2 -0
- package/dist/combobox/index.parts.js +2 -0
- package/dist/combobox/input/combobox-input.svelte +44 -12
- package/dist/combobox/item/combobox-item-implicit-text-test.svelte +1 -1
- package/dist/combobox/item/combobox-listboxitem.svelte +14 -11
- package/dist/combobox/item-indicator/combobox-item-indicator.svelte +4 -15
- package/dist/combobox/list/combobox-listbox.svelte +1 -0
- package/dist/combobox/list/combobox-listbox.svelte.d.ts +2 -1
- package/dist/combobox/popover/README.md +18 -4
- package/dist/combobox/popover/combobox-popover-props-test.svelte +38 -0
- package/dist/combobox/popover/combobox-popover-props-test.svelte.d.ts +11 -0
- package/dist/combobox/popover/combobox-popover.svelte +166 -23
- package/dist/combobox/popover/combobox-popover.svelte.d.ts +3 -3
- package/dist/combobox/popover/combobox-scrollable-list-test.svelte +23 -0
- package/dist/combobox/popover/combobox-scrollable-list-test.svelte.d.ts +18 -0
- package/dist/combobox/root/README.md +1 -0
- package/dist/combobox/root/combobox-multiselect-test.svelte +5 -3
- package/dist/combobox/root/combobox-multiselect-test.svelte.d.ts +1 -0
- package/dist/combobox/root/combobox-numeric-string-id-test.svelte +1 -1
- package/dist/combobox/root/combobox-test.svelte +23 -4
- package/dist/combobox/root/combobox-test.svelte.d.ts +2 -0
- package/dist/combobox/root/combobox.svelte +119 -13
- package/dist/combobox/root/combobox.svelte.d.ts +1 -0
- package/dist/combobox/root/context.d.ts +19 -1
- package/dist/combobox/tag-remove/combobox-tag-remove.svelte +3 -2
- package/dist/combobox/trigger/README.md +21 -0
- package/dist/combobox/trigger/combobox-trigger.svelte +56 -0
- package/dist/combobox/trigger/combobox-trigger.svelte.d.ts +9 -0
- package/dist/datepicker/README.md +100 -0
- package/dist/datepicker/TODO.md +28 -0
- package/dist/datepicker/calendar/README.md +19 -0
- package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte +60 -0
- package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte.d.ts +3 -0
- package/dist/datepicker/calendar/date-picker-calendar.svelte +65 -0
- package/dist/datepicker/calendar/date-picker-calendar.svelte.d.ts +10 -0
- package/dist/datepicker/index.d.ts +18 -0
- package/dist/datepicker/index.js +18 -0
- package/dist/datepicker/index.parts.d.ts +14 -0
- package/dist/datepicker/index.parts.js +14 -0
- package/dist/datepicker/input/README.md +15 -0
- package/dist/datepicker/input/date-picker-input.svelte +108 -0
- package/dist/datepicker/input/date-picker-input.svelte.d.ts +11 -0
- package/dist/datepicker/internal/strict-props.d.ts +2 -0
- package/dist/datepicker/internal/strict-props.js +28 -0
- package/dist/datepicker/popover/README.md +20 -0
- package/dist/datepicker/popover/date-picker-popover-handler-test.svelte +57 -0
- package/dist/datepicker/popover/date-picker-popover-handler-test.svelte.d.ts +3 -0
- package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte +45 -0
- package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte.d.ts +18 -0
- package/dist/datepicker/popover/date-picker-popover.svelte +87 -0
- package/dist/datepicker/popover/date-picker-popover.svelte.d.ts +7 -0
- package/dist/datepicker/root/README.md +38 -0
- package/dist/datepicker/root/context.d.ts +43 -0
- package/dist/datepicker/root/context.js +15 -0
- package/dist/datepicker/root/date-picker-bindable-empty-test.svelte +24 -0
- package/dist/datepicker/root/date-picker-bindable-empty-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-bindable-test.svelte +41 -0
- package/dist/datepicker/root/date-picker-bindable-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-empty-test.svelte +47 -0
- package/dist/datepicker/root/date-picker-empty-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-locale-typing-test.svelte +47 -0
- package/dist/datepicker/root/date-picker-locale-typing-test.svelte.d.ts +3 -0
- package/dist/datepicker/root/date-picker-open-cancel-test.svelte +54 -0
- package/dist/datepicker/root/date-picker-open-cancel-test.svelte.d.ts +8 -0
- package/dist/datepicker/root/date-picker-root.svelte +495 -0
- package/dist/datepicker/root/date-picker-root.svelte.d.ts +24 -0
- package/dist/datepicker/root/date-picker-test.svelte +86 -0
- package/dist/datepicker/root/date-picker-test.svelte.d.ts +13 -0
- package/dist/datepicker/root/date-utils.d.ts +17 -0
- package/dist/datepicker/root/date-utils.js +138 -0
- package/dist/datepicker/root/draft-evaluation.d.ts +13 -0
- package/dist/datepicker/root/draft-evaluation.js +56 -0
- package/dist/datepicker/root/focus-controller.d.ts +3 -0
- package/dist/datepicker/root/focus-controller.js +15 -0
- package/dist/datepicker/root/open-change.d.ts +5 -0
- package/dist/datepicker/root/open-change.js +13 -0
- package/dist/datepicker/root/open-controller.d.ts +7 -0
- package/dist/datepicker/root/open-controller.js +15 -0
- package/dist/datepicker/root/segment-controller.d.ts +8 -0
- package/dist/datepicker/root/segment-controller.js +53 -0
- package/dist/datepicker/root/segment-state.d.ts +18 -0
- package/dist/datepicker/root/segment-state.js +134 -0
- package/dist/datepicker/root/value-commit.d.ts +4 -0
- package/dist/datepicker/root/value-commit.js +8 -0
- package/dist/datepicker/segment/README.md +14 -0
- package/dist/datepicker/segment/date-picker-segment.svelte +319 -0
- package/dist/datepicker/segment/date-picker-segment.svelte.d.ts +9 -0
- package/dist/datepicker/trigger/README.md +14 -0
- package/dist/datepicker/trigger/date-picker-trigger.svelte +110 -0
- package/dist/datepicker/trigger/date-picker-trigger.svelte.d.ts +9 -0
- package/dist/dialog/content/dialog-content.svelte +6 -6
- package/dist/dialog/index.d.ts +3 -3
- package/dist/dialog/index.js +2 -2
- package/dist/dialog/root/context.d.ts +2 -1
- package/dist/dialog/root/dialog-root.svelte +9 -2
- package/dist/dialog/trigger/dialog-trigger.svelte +3 -0
- package/dist/hooks/use-virtual-focus.svelte.js +3 -1
- package/dist/index.d.ts +31 -17
- package/dist/index.js +31 -17
- package/dist/input/README.md +38 -0
- package/dist/input/TODO.md +12 -0
- package/dist/input/input-test.svelte +43 -0
- package/dist/input/input-test.svelte.d.ts +12 -0
- package/dist/input/input.svelte +151 -7
- package/dist/input/input.svelte.d.ts +8 -2
- package/dist/listbox/index.d.ts +3 -3
- package/dist/listbox/index.js +3 -3
- package/dist/listbox/item/README.md +2 -1
- package/dist/listbox/item/listbox-item.svelte +260 -6
- package/dist/listbox/item/listbox-item.svelte.d.ts +6 -0
- package/dist/listbox/root/context.d.ts +6 -0
- package/dist/listbox/root/context.js +23 -13
- package/dist/listbox/root/listbox-test.svelte +14 -2
- package/dist/listbox/root/listbox-test.svelte.d.ts +1 -0
- package/dist/listbox/root/listbox.svelte +49 -2
- package/dist/listbox/root/listbox.svelte.d.ts +4 -2
- package/dist/popover/README.md +10 -0
- package/dist/popover/content/README.md +11 -0
- package/dist/popover/content/popover-content-controlled-close-test.svelte +30 -0
- package/dist/popover/content/popover-content-controlled-close-test.svelte.d.ts +3 -0
- package/dist/popover/content/popover-content-standalone-test.svelte +28 -0
- package/dist/popover/content/popover-content-standalone-test.svelte.d.ts +6 -0
- package/dist/popover/content/popover-content-test.svelte +32 -2
- package/dist/popover/content/popover-content-test.svelte.d.ts +3 -1
- package/dist/popover/content/popover-content.svelte +315 -24
- package/dist/popover/content/popover-content.svelte.d.ts +5 -1
- package/dist/popover/index.d.ts +3 -3
- package/dist/popover/index.js +3 -5
- package/dist/popover/root/README.md +10 -15
- package/dist/popover/root/context.d.ts +16 -7
- package/dist/popover/root/context.js +0 -2
- package/dist/popover/root/focus-state.d.ts +4 -0
- package/dist/popover/root/focus-state.js +33 -0
- package/dist/popover/root/popover-root.svelte +90 -17
- package/dist/popover/root/popover-root.svelte.d.ts +2 -1
- package/dist/popover/root/popover-test.svelte +2 -1
- package/dist/popover/root/popover-test.svelte.d.ts +2 -1
- package/dist/popover/trigger/popover-trigger-button-root-test.svelte +17 -0
- package/dist/popover/trigger/popover-trigger-button-root-test.svelte.d.ts +18 -0
- package/dist/popover/trigger/popover-trigger-button.svelte +9 -7
- package/dist/popover/trigger/popover-trigger.svelte +17 -5
- package/dist/portal/portal.svelte +3 -1
- package/dist/primitives/click-outside.d.ts +1 -1
- package/dist/primitives/click-outside.js +1 -1
- package/dist/primitives/floating.js +12 -4
- package/dist/primitives/focus-trap.d.ts +7 -2
- package/dist/primitives/focus-trap.js +50 -17
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.js +1 -0
- package/dist/primitives/input-modality.d.ts +7 -0
- package/dist/primitives/input-modality.js +125 -0
- package/dist/primitives/keyboard-navigation.d.ts +1 -0
- package/dist/primitives/keyboard-navigation.js +17 -0
- package/dist/table/IMPLEMENTATION_NOTES.md +9 -0
- package/dist/table/PLAN-HIDDEN-COLUMNS.md +152 -0
- package/dist/table/PLAN.md +1336 -0
- package/dist/table/README.md +143 -0
- package/dist/table/SELECTION_CHECKBOX_PLAN.md +234 -0
- package/dist/table/TODO.md +138 -0
- package/dist/table/body/README.md +39 -0
- package/dist/table/body/table-body-items-test.svelte +45 -0
- package/dist/table/body/table-body-items-test.svelte.d.ts +18 -0
- package/dist/table/body/table-body.svelte +171 -0
- package/dist/table/body/table-body.svelte.d.ts +45 -0
- package/dist/table/cell/README.md +27 -0
- package/dist/table/cell/table-cell.svelte +253 -0
- package/dist/table/cell/table-cell.svelte.d.ts +4 -0
- package/dist/table/checkbox/README.md +40 -0
- package/dist/table/checkbox/table-checkbox-test.svelte +170 -0
- package/dist/table/checkbox/table-checkbox-test.svelte.d.ts +22 -0
- package/dist/table/checkbox/table-checkbox.svelte +235 -0
- package/dist/table/checkbox/table-checkbox.svelte.d.ts +4 -0
- package/dist/table/checkbox-indicator/README.md +31 -0
- package/dist/table/checkbox-indicator/table-checkbox-indicator.svelte +15 -0
- package/dist/table/checkbox-indicator/table-checkbox-indicator.svelte.d.ts +4 -0
- package/dist/table/column/README.md +36 -0
- package/dist/table/column/table-column.svelte +79 -0
- package/dist/table/column/table-column.svelte.d.ts +4 -0
- package/dist/table/column-header-cell/README.md +30 -0
- package/dist/table/column-header-cell/table-column-header-cell.svelte +271 -0
- package/dist/table/column-header-cell/table-column-header-cell.svelte.d.ts +4 -0
- package/dist/table/column-resizer/README.md +33 -0
- package/dist/table/column-resizer/table-column-resizer-fixed-width-test.svelte +57 -0
- package/dist/table/column-resizer/table-column-resizer-fixed-width-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-freeze-layout-test.svelte +52 -0
- package/dist/table/column-resizer/table-column-resizer-freeze-layout-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-narrow-min-width-test.svelte +76 -0
- package/dist/table/column-resizer/table-column-resizer-narrow-min-width-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-overflow-test.svelte +64 -0
- package/dist/table/column-resizer/table-column-resizer-overflow-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-padded-container-test.svelte +67 -0
- package/dist/table/column-resizer/table-column-resizer-padded-container-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-sandbox-overflow-test.svelte +87 -0
- package/dist/table/column-resizer/table-column-resizer-sandbox-overflow-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-selection-column-test.svelte +84 -0
- package/dist/table/column-resizer/table-column-resizer-selection-column-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-test.svelte +77 -0
- package/dist/table/column-resizer/table-column-resizer-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer-three-column-relative-test.svelte +64 -0
- package/dist/table/column-resizer/table-column-resizer-three-column-relative-test.svelte.d.ts +3 -0
- package/dist/table/column-resizer/table-column-resizer.svelte +610 -0
- package/dist/table/column-resizer/table-column-resizer.svelte.d.ts +4 -0
- package/dist/table/empty-state/README.md +27 -0
- package/dist/table/empty-state/table-empty-state.svelte +33 -0
- package/dist/table/empty-state/table-empty-state.svelte.d.ts +4 -0
- package/dist/table/footer/README.md +26 -0
- package/dist/table/footer/table-footer.svelte +13 -0
- package/dist/table/footer/table-footer.svelte.d.ts +4 -0
- package/dist/table/header/README.md +26 -0
- package/dist/table/header/table-header.svelte +13 -0
- package/dist/table/header/table-header.svelte.d.ts +4 -0
- package/dist/table/index.d.ts +18 -0
- package/dist/table/index.js +17 -0
- package/dist/table/index.parts.d.ts +13 -0
- package/dist/table/index.parts.js +13 -0
- package/dist/table/root/README.md +66 -0
- package/dist/table/root/context.d.ts +233 -0
- package/dist/table/root/context.js +2153 -0
- package/dist/table/root/table-reorder-test.svelte +64 -0
- package/dist/table/root/table-reorder-test.svelte.d.ts +3 -0
- package/dist/table/root/table-root.svelte +561 -0
- package/dist/table/root/table-root.svelte.d.ts +4 -0
- package/dist/table/root/table-ssr-wrapper-column.svelte +48 -0
- package/dist/table/root/table-ssr-wrapper-column.svelte.d.ts +4 -0
- package/dist/table/root/table-ssr-wrapper-context.d.ts +11 -0
- package/dist/table/root/table-ssr-wrapper-context.js +13 -0
- package/dist/table/root/table-ssr-wrapper-test.svelte +57 -0
- package/dist/table/root/table-ssr-wrapper-test.svelte.d.ts +3 -0
- package/dist/table/root/table-test.svelte +206 -0
- package/dist/table/root/table-test.svelte.d.ts +29 -0
- package/dist/table/row/README.md +29 -0
- package/dist/table/row/table-row.svelte +244 -0
- package/dist/table/row/table-row.svelte.d.ts +4 -0
- package/dist/table/sort-trigger/README.md +45 -0
- package/dist/table/sort-trigger/table-sort-trigger.svelte +183 -0
- package/dist/table/sort-trigger/table-sort-trigger.svelte.d.ts +4 -0
- package/dist/table/types.d.ts +112 -0
- package/dist/table/types.js +1 -0
- package/dist/table/utils/handle-body-keydown.d.ts +13 -0
- package/dist/table/utils/handle-body-keydown.js +67 -0
- package/dist/table/utils/visually-hidden-style.d.ts +1 -0
- package/dist/table/utils/visually-hidden-style.js +1 -0
- package/dist/test-utils/focus-contract.d.ts +3 -0
- package/dist/test-utils/focus-contract.js +26 -0
- package/dist/timepicker/IMPLEMENTATION_PLAN.md +254 -0
- package/dist/timepicker/README.md +97 -0
- package/dist/timepicker/TODO.md +86 -0
- package/dist/timepicker/clock/README.md +14 -0
- package/dist/timepicker/clock/time-picker-clock-test.svelte +45 -0
- package/dist/timepicker/clock/time-picker-clock-test.svelte.d.ts +11 -0
- package/dist/timepicker/clock/time-picker-clock.svelte +65 -0
- package/dist/timepicker/clock/time-picker-clock.svelte.d.ts +10 -0
- package/dist/timepicker/index.d.ts +14 -0
- package/dist/timepicker/index.js +14 -0
- package/dist/timepicker/index.parts.d.ts +8 -0
- package/dist/timepicker/index.parts.js +8 -0
- package/dist/timepicker/input/README.md +15 -0
- package/dist/timepicker/input/time-picker-input-forwarding-test.svelte +40 -0
- package/dist/timepicker/input/time-picker-input-forwarding-test.svelte.d.ts +3 -0
- package/dist/timepicker/input/time-picker-input.svelte +109 -0
- package/dist/timepicker/input/time-picker-input.svelte.d.ts +11 -0
- package/dist/timepicker/internal/strict-props.d.ts +4 -0
- package/dist/timepicker/internal/strict-props.js +51 -0
- package/dist/timepicker/popover/README.md +20 -0
- package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte +22 -0
- package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte.d.ts +3 -0
- package/dist/timepicker/popover/time-picker-popover.svelte +89 -0
- package/dist/timepicker/popover/time-picker-popover.svelte.d.ts +7 -0
- package/dist/timepicker/root/README.md +42 -0
- package/dist/timepicker/root/context.d.ts +51 -0
- package/dist/timepicker/root/context.js +15 -0
- package/dist/timepicker/root/time-picker-12h-test.svelte +22 -0
- package/dist/timepicker/root/time-picker-12h-test.svelte.d.ts +3 -0
- package/dist/timepicker/root/time-picker-bindable-test.svelte +25 -0
- package/dist/timepicker/root/time-picker-bindable-test.svelte.d.ts +3 -0
- package/dist/timepicker/root/time-picker-empty-test.svelte +20 -0
- package/dist/timepicker/root/time-picker-empty-test.svelte.d.ts +3 -0
- package/dist/timepicker/root/time-picker-root.svelte +625 -0
- package/dist/timepicker/root/time-picker-root.svelte.d.ts +28 -0
- package/dist/timepicker/root/time-picker-test.svelte +72 -0
- package/dist/timepicker/root/time-picker-test.svelte.d.ts +15 -0
- package/dist/timepicker/root/time-utils.d.ts +1 -0
- package/dist/timepicker/root/time-utils.js +3 -0
- package/dist/timepicker/segment/README.md +14 -0
- package/dist/timepicker/segment/time-picker-segment.svelte +365 -0
- package/dist/timepicker/segment/time-picker-segment.svelte.d.ts +9 -0
- package/dist/timepicker/trigger/README.md +14 -0
- package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte +35 -0
- package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte.d.ts +3 -0
- package/dist/timepicker/trigger/time-picker-trigger.svelte +122 -0
- package/dist/timepicker/trigger/time-picker-trigger.svelte.d.ts +9 -0
- package/dist/utils/date-only.d.ts +11 -0
- package/dist/utils/date-only.js +53 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +33 -2
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
import { setComboBoxContext, type ComboBoxContext } from './context';
|
|
4
4
|
import type { ListBoxContext } from '../../listbox/root/context';
|
|
5
5
|
import { useVirtualFocus } from '../../hooks/use-virtual-focus.svelte';
|
|
6
|
+
import {
|
|
7
|
+
shouldShowFocusVisible,
|
|
8
|
+
trackInteractionModality
|
|
9
|
+
} from '../../primitives/input-modality';
|
|
6
10
|
|
|
7
11
|
type ComboBoxProps<T> = {
|
|
8
12
|
/** Stable ID used to generate internal ARIA IDs (recommended for SSR). */
|
|
9
13
|
id?: string;
|
|
10
14
|
isDisabled?: boolean;
|
|
15
|
+
isPending?: boolean;
|
|
11
16
|
isReadOnly?: boolean;
|
|
12
17
|
/** Selected value(s). Single value for single mode, array for multiple mode. Can be bound with bind:value */
|
|
13
18
|
value?: string | number | (string | number)[];
|
|
@@ -43,6 +48,7 @@
|
|
|
43
48
|
let {
|
|
44
49
|
id: rootId,
|
|
45
50
|
isDisabled = false,
|
|
51
|
+
isPending = false,
|
|
46
52
|
isReadOnly = false,
|
|
47
53
|
value = $bindable(),
|
|
48
54
|
defaultValue,
|
|
@@ -98,6 +104,11 @@
|
|
|
98
104
|
|
|
99
105
|
// Virtual focus for tag navigation in multiple mode
|
|
100
106
|
let focusedTagId: string | number | null = $state(null);
|
|
107
|
+
let focusWithin = $state(false);
|
|
108
|
+
let focusVisible = $state(false);
|
|
109
|
+
let popoverPointerDownPending = $state(false);
|
|
110
|
+
let shouldCloseOnEscapeState = $state(true);
|
|
111
|
+
let shouldCloseOnBlurState = $state(true);
|
|
101
112
|
|
|
102
113
|
// Flag to control whether inputValue should be used for filtering
|
|
103
114
|
// When false, all items are shown regardless of inputValue
|
|
@@ -188,6 +199,7 @@
|
|
|
188
199
|
// In multiple mode, selections are managed via tags, not input
|
|
189
200
|
if (selectionMode === 'single' && val.trim() === '' && currentSelection.size > 0) {
|
|
190
201
|
const emptySelection = new Set<string | number>();
|
|
202
|
+
selectedInternal = emptySelection;
|
|
191
203
|
if (isSelectionControlled) {
|
|
192
204
|
onChange?.(toExternalValue(emptySelection));
|
|
193
205
|
} else {
|
|
@@ -199,17 +211,26 @@
|
|
|
199
211
|
}
|
|
200
212
|
}
|
|
201
213
|
|
|
214
|
+
function syncInputValue(val: string, options?: { notifyInputChange?: boolean }) {
|
|
215
|
+
inputValueInternal = val;
|
|
216
|
+
inputValue = val;
|
|
217
|
+
|
|
218
|
+
if (options?.notifyInputChange ?? true) {
|
|
219
|
+
onInputChange?.(val);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
202
223
|
function selectItem(id: string | number, label: string) {
|
|
203
224
|
let newSelection: Set<string | number>;
|
|
204
225
|
|
|
205
226
|
if (selectionMode === 'single') {
|
|
206
227
|
newSelection = new Set([id]);
|
|
228
|
+
shouldFilter = false;
|
|
207
229
|
// Save the label persistently for restore on blur/escape
|
|
208
230
|
selectedLabel = label;
|
|
209
|
-
//
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
onInputChange?.(label);
|
|
231
|
+
// Keep the selected label visible in the input without re-triggering
|
|
232
|
+
// external filtering during the popover close animation.
|
|
233
|
+
syncInputValue(label, { notifyInputChange: false });
|
|
213
234
|
if (effectiveCloseOnSelect) {
|
|
214
235
|
closePopover(true); // Close and keep focus on input
|
|
215
236
|
}
|
|
@@ -236,6 +257,7 @@
|
|
|
236
257
|
}
|
|
237
258
|
}
|
|
238
259
|
|
|
260
|
+
selectedInternal = newSelection;
|
|
239
261
|
if (isSelectionControlled) {
|
|
240
262
|
onChange?.(toExternalValue(newSelection));
|
|
241
263
|
} else {
|
|
@@ -257,6 +279,7 @@
|
|
|
257
279
|
// Remove from persistent labels
|
|
258
280
|
selectedLabels.delete(id);
|
|
259
281
|
|
|
282
|
+
selectedInternal = newSelection;
|
|
260
283
|
if (isSelectionControlled) {
|
|
261
284
|
onChange?.(toExternalValue(newSelection));
|
|
262
285
|
} else {
|
|
@@ -274,6 +297,7 @@
|
|
|
274
297
|
function clearSelection() {
|
|
275
298
|
const emptySelection = new Set<string | number>();
|
|
276
299
|
|
|
300
|
+
selectedInternal = emptySelection;
|
|
277
301
|
if (isSelectionControlled) {
|
|
278
302
|
onChange?.(toExternalValue(emptySelection));
|
|
279
303
|
} else {
|
|
@@ -303,6 +327,8 @@
|
|
|
303
327
|
onInputChange?.('');
|
|
304
328
|
}
|
|
305
329
|
// Otherwise user typed, keep their filter
|
|
330
|
+
} else {
|
|
331
|
+
shouldFilter = true;
|
|
306
332
|
}
|
|
307
333
|
setIsOpen(true);
|
|
308
334
|
// Auto-focus the selected item when opening with a selection
|
|
@@ -318,8 +344,6 @@
|
|
|
318
344
|
setIsOpen(false);
|
|
319
345
|
// Reset navigation state
|
|
320
346
|
navigation.reset();
|
|
321
|
-
// Re-enable filtering for next open
|
|
322
|
-
shouldFilter = true;
|
|
323
347
|
// Only refocus input when explicitly requested (e.g., after selection)
|
|
324
348
|
// Never refocus in focus mode to prevent re-opening
|
|
325
349
|
if (refocusInput && trigger !== 'focus') {
|
|
@@ -335,9 +359,40 @@
|
|
|
335
359
|
}
|
|
336
360
|
}
|
|
337
361
|
|
|
362
|
+
function syncFocusWithin() {
|
|
363
|
+
focusWithin =
|
|
364
|
+
!!wrapperRef && !!document.activeElement && wrapperRef.contains(document.activeElement);
|
|
365
|
+
if (!focusWithin) {
|
|
366
|
+
focusVisible = false;
|
|
367
|
+
// Clean up stale data-focused/data-focus-visible that Popover.Root's
|
|
368
|
+
// focus-state module may have set imperatively on the wrapper (the
|
|
369
|
+
// wrapper is briefly used as triggerRef before the input overrides it).
|
|
370
|
+
if (wrapperRef) {
|
|
371
|
+
delete wrapperRef.dataset.focused;
|
|
372
|
+
delete wrapperRef.dataset.focusVisible;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function handleFocusIn(event: FocusEvent) {
|
|
378
|
+
focusWithin = true;
|
|
379
|
+
focusVisible = shouldShowFocusVisible(event.target as HTMLElement | null);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function handleFocusOut() {
|
|
383
|
+
queueMicrotask(syncFocusWithin);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function setFocusVisibleState(visible: boolean) {
|
|
387
|
+
focusVisible = visible && focusWithin;
|
|
388
|
+
}
|
|
389
|
+
|
|
338
390
|
// Use navigation hook methods for keyboard navigation
|
|
339
391
|
function selectFocusedItem() {
|
|
340
392
|
if (navigation.focusedId !== null) {
|
|
393
|
+
if (listboxCtxRef?.isDisabled(navigation.focusedId)) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
341
396
|
const label = navigation.itemLabels.get(navigation.focusedId) ?? String(navigation.focusedId);
|
|
342
397
|
selectItem(navigation.focusedId, label);
|
|
343
398
|
}
|
|
@@ -346,9 +401,29 @@
|
|
|
346
401
|
/**
|
|
347
402
|
* Handle input blur or escape - restore selection label or clear if no selection
|
|
348
403
|
*/
|
|
349
|
-
function
|
|
404
|
+
function consumePopoverPointerDown() {
|
|
405
|
+
if (!popoverPointerDownPending) return false;
|
|
406
|
+
popoverPointerDownPending = false;
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function handleInputBlur(event?: FocusEvent) {
|
|
350
411
|
// Clear tag virtual focus
|
|
351
412
|
focusedTagId = null;
|
|
413
|
+
|
|
414
|
+
const nextFocusedElement = event?.relatedTarget;
|
|
415
|
+
const isMovingFocusWithinCombobox =
|
|
416
|
+
nextFocusedElement instanceof Node &&
|
|
417
|
+
((wrapperRef?.contains(nextFocusedElement) ?? false) ||
|
|
418
|
+
(listboxRef?.contains(nextFocusedElement) ?? false));
|
|
419
|
+
|
|
420
|
+
if (isMovingFocusWithinCombobox || consumePopoverPointerDown()) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (!shouldCloseOnBlurState) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
352
427
|
// Close popover first to prevent flash of options when clearing input
|
|
353
428
|
closePopover();
|
|
354
429
|
|
|
@@ -376,15 +451,14 @@
|
|
|
376
451
|
if (currentSelection.size > 0 && selectedLabel) {
|
|
377
452
|
if (selectedLabel !== currentInputValue) {
|
|
378
453
|
// Restore the selected label
|
|
379
|
-
|
|
380
|
-
inputValue = selectedLabel;
|
|
381
|
-
onInputChange?.(selectedLabel);
|
|
454
|
+
syncInputValue(selectedLabel, { notifyInputChange: false });
|
|
382
455
|
}
|
|
383
456
|
}
|
|
384
457
|
}
|
|
385
458
|
|
|
386
459
|
function handleKeydown(event: KeyboardEvent) {
|
|
387
460
|
if (isDisabled) return;
|
|
461
|
+
trackInteractionModality(event, event.target as HTMLElement | null);
|
|
388
462
|
|
|
389
463
|
// Handle tag virtual focus navigation in multiple mode
|
|
390
464
|
if (focusedTagId !== null && selectionMode === 'multiple') {
|
|
@@ -552,14 +626,16 @@
|
|
|
552
626
|
}
|
|
553
627
|
break;
|
|
554
628
|
case 'Escape':
|
|
555
|
-
if (currentIsOpen) {
|
|
629
|
+
if (currentIsOpen && shouldCloseOnEscapeState) {
|
|
556
630
|
closePopover(true); // Keep focus on input after Escape
|
|
557
631
|
// Stop propagation so parent dialogs don't also close
|
|
558
632
|
event.stopPropagation();
|
|
559
633
|
event.stopImmediatePropagation();
|
|
634
|
+
handleInputBlur();
|
|
635
|
+
// Escape is a keyboard-only path, so focus-visible remains enabled for the input.
|
|
636
|
+
focusVisible = true;
|
|
637
|
+
event.preventDefault();
|
|
560
638
|
}
|
|
561
|
-
handleInputBlur();
|
|
562
|
-
event.preventDefault();
|
|
563
639
|
break;
|
|
564
640
|
case 'Backspace':
|
|
565
641
|
// In multiple mode, remove last tag when input is empty
|
|
@@ -604,6 +680,18 @@
|
|
|
604
680
|
get isDisabled() {
|
|
605
681
|
return isDisabled;
|
|
606
682
|
},
|
|
683
|
+
get isPending() {
|
|
684
|
+
return isPending;
|
|
685
|
+
},
|
|
686
|
+
get isFocusVisible() {
|
|
687
|
+
return focusVisible;
|
|
688
|
+
},
|
|
689
|
+
get shouldCloseOnEscape() {
|
|
690
|
+
return shouldCloseOnEscapeState;
|
|
691
|
+
},
|
|
692
|
+
get shouldCloseOnBlur() {
|
|
693
|
+
return shouldCloseOnBlurState;
|
|
694
|
+
},
|
|
607
695
|
get isReadOnly() {
|
|
608
696
|
return isReadOnly;
|
|
609
697
|
},
|
|
@@ -668,11 +756,22 @@
|
|
|
668
756
|
unregisterItem: navigation.unregister,
|
|
669
757
|
handleKeydown,
|
|
670
758
|
handleInputBlur,
|
|
759
|
+
setFocusVisible: setFocusVisibleState,
|
|
671
760
|
get focusedTagId() {
|
|
672
761
|
return focusedTagId;
|
|
673
762
|
},
|
|
674
763
|
setFocusedTagId: (id: string | number | null) => {
|
|
675
764
|
focusedTagId = id;
|
|
765
|
+
},
|
|
766
|
+
markPopoverPointerDown: () => {
|
|
767
|
+
popoverPointerDownPending = true;
|
|
768
|
+
},
|
|
769
|
+
consumePopoverPointerDown,
|
|
770
|
+
setShouldCloseOnEscape: (value: boolean) => {
|
|
771
|
+
shouldCloseOnEscapeState = value;
|
|
772
|
+
},
|
|
773
|
+
setShouldCloseOnBlur: (value: boolean) => {
|
|
774
|
+
shouldCloseOnBlurState = value;
|
|
676
775
|
}
|
|
677
776
|
};
|
|
678
777
|
|
|
@@ -684,11 +783,18 @@
|
|
|
684
783
|
role="group"
|
|
685
784
|
aria-label={ariaLabel}
|
|
686
785
|
aria-labelledby={ariaLabelledby}
|
|
786
|
+
aria-busy={isPending ? 'true' : undefined}
|
|
687
787
|
class={className}
|
|
688
788
|
data-combobox
|
|
789
|
+
data-focused={focusWithin || undefined}
|
|
689
790
|
data-disabled={isDisabled || undefined}
|
|
791
|
+
data-pending={isPending || undefined}
|
|
690
792
|
data-readonly={isReadOnly || undefined}
|
|
793
|
+
data-focus-within={focusWithin || undefined}
|
|
794
|
+
data-focus-visible={focusVisible || undefined}
|
|
691
795
|
use:setWrapperAsTrigger
|
|
796
|
+
onfocusin={handleFocusIn}
|
|
797
|
+
onfocusout={handleFocusOut}
|
|
692
798
|
>
|
|
693
799
|
{#if children}
|
|
694
800
|
{@render children()}
|
|
@@ -3,6 +3,7 @@ type ComboBoxProps<T> = {
|
|
|
3
3
|
/** Stable ID used to generate internal ARIA IDs (recommended for SSR). */
|
|
4
4
|
id?: string;
|
|
5
5
|
isDisabled?: boolean;
|
|
6
|
+
isPending?: boolean;
|
|
6
7
|
isReadOnly?: boolean;
|
|
7
8
|
/** Selected value(s). Single value for single mode, array for multiple mode. Can be bound with bind:value */
|
|
8
9
|
value?: string | number | (string | number)[];
|
|
@@ -20,6 +20,10 @@ export type ComboBoxContext<T extends object = object> = {
|
|
|
20
20
|
selectedValue: Set<string | number>;
|
|
21
21
|
/** Whether the combobox is disabled */
|
|
22
22
|
isDisabled: boolean;
|
|
23
|
+
/** Whether the combobox is pending async work */
|
|
24
|
+
isPending: boolean;
|
|
25
|
+
/** Whether focus should currently be presented as keyboard-visible */
|
|
26
|
+
isFocusVisible: boolean;
|
|
23
27
|
/** Whether the combobox is read-only */
|
|
24
28
|
isReadOnly: boolean;
|
|
25
29
|
/** Selection mode */
|
|
@@ -79,11 +83,25 @@ export type ComboBoxContext<T extends object = object> = {
|
|
|
79
83
|
/** Handle keyboard events (arrow navigation, enter, escape) */
|
|
80
84
|
handleKeydown: (event: KeyboardEvent) => void;
|
|
81
85
|
/** Handle input blur - restore selection or deselect if empty */
|
|
82
|
-
handleInputBlur: () => void;
|
|
86
|
+
handleInputBlur: (event?: FocusEvent) => void;
|
|
87
|
+
/** Update root-level focus-visible state based on current modality. */
|
|
88
|
+
setFocusVisible: (visible: boolean) => void;
|
|
83
89
|
/** Currently focused tag ID (virtual focus for tag navigation) */
|
|
84
90
|
focusedTagId: string | number | null;
|
|
85
91
|
/** Set focused tag ID (virtual focus for tag navigation) */
|
|
86
92
|
setFocusedTagId: (id: string | number | null) => void;
|
|
93
|
+
/** Mark that the next input blur was caused by pointer interaction inside the popover. */
|
|
94
|
+
markPopoverPointerDown: () => void;
|
|
95
|
+
/** Consume the pending popover-pointer marker. */
|
|
96
|
+
consumePopoverPointerDown: () => boolean;
|
|
97
|
+
/** Whether Escape should close the popover. */
|
|
98
|
+
shouldCloseOnEscape: boolean;
|
|
99
|
+
/** Whether blur should close the popover. */
|
|
100
|
+
shouldCloseOnBlur: boolean;
|
|
101
|
+
/** Update whether Escape should close the popover. */
|
|
102
|
+
setShouldCloseOnEscape: (value: boolean) => void;
|
|
103
|
+
/** Update whether blur should close the popover. */
|
|
104
|
+
setShouldCloseOnBlur: (value: boolean) => void;
|
|
87
105
|
};
|
|
88
106
|
export declare function setComboBoxContext<T extends object = object>(ctx: ComboBoxContext<T>): void;
|
|
89
107
|
export declare function getComboBoxContext<T extends object = object>(): ComboBoxContext<T> | undefined;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
4
|
import { getContext } from 'svelte';
|
|
5
|
+
import { ButtonRoot } from '../../button/index.js';
|
|
5
6
|
import { cn } from '../../utils/cn';
|
|
6
7
|
import { TAG_CONTEXT_KEY, type TagContext } from '../tag/combobox-tag.svelte';
|
|
7
8
|
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
</script>
|
|
28
29
|
|
|
29
30
|
{#if !tagCtx.disabled}
|
|
30
|
-
<
|
|
31
|
+
<ButtonRoot
|
|
31
32
|
type="button"
|
|
32
33
|
onclick={handleClick}
|
|
33
34
|
aria-label={`Remove ${tagCtx.label}`}
|
|
@@ -49,5 +50,5 @@
|
|
|
49
50
|
/>
|
|
50
51
|
</svg>
|
|
51
52
|
{/if}
|
|
52
|
-
</
|
|
53
|
+
</ButtonRoot>
|
|
53
54
|
{/if}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ComboBox Trigger
|
|
2
|
+
|
|
3
|
+
## API reference
|
|
4
|
+
|
|
5
|
+
### ComboBox.Trigger
|
|
6
|
+
|
|
7
|
+
Name: `ComboBox.Trigger`
|
|
8
|
+
Description: Optional trigger button that toggles the combobox popover without stealing focus from the input.
|
|
9
|
+
|
|
10
|
+
| Prop | Type | Default | Description |
|
|
11
|
+
| -------------- | ---------------------- | ----------- | --------------------------------------------------------------- |
|
|
12
|
+
| `class` | `string` | `undefined` | CSS class names for the trigger element. |
|
|
13
|
+
| `children` | `Snippet` | `undefined` | Custom trigger content. If omitted, a chevron icon is rendered. |
|
|
14
|
+
| `tabindex` | `number` | `-1` | Tab index applied to the trigger button. |
|
|
15
|
+
| `...restProps` | `HTMLButtonAttributes` | `-` | Additional native button attributes. |
|
|
16
|
+
|
|
17
|
+
## Notes
|
|
18
|
+
|
|
19
|
+
- `ComboBox.Trigger` reflects the root pending state through `data-pending`.
|
|
20
|
+
- While the combobox is disabled, read-only, or pending, the trigger becomes non-interactive.
|
|
21
|
+
- `ComboBox.Button` remains available as a compatibility alias.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
import { ButtonRoot } from '../../button/index.js';
|
|
5
|
+
import { useComboBoxContext } from '../root/context';
|
|
6
|
+
|
|
7
|
+
type ComboBoxTriggerProps = HTMLButtonAttributes & {
|
|
8
|
+
class?: string;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let { class: className, children, tabindex = -1, ...restProps }: ComboBoxTriggerProps = $props();
|
|
13
|
+
|
|
14
|
+
const ctx = useComboBoxContext();
|
|
15
|
+
const isTriggerDisabled = $derived(ctx.isDisabled || ctx.isReadOnly || ctx.isPending);
|
|
16
|
+
|
|
17
|
+
function handleMouseDown(event: MouseEvent) {
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
if (!isTriggerDisabled) {
|
|
20
|
+
ctx.toggle();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<ButtonRoot
|
|
26
|
+
type="button"
|
|
27
|
+
{tabindex}
|
|
28
|
+
aria-label={ctx.isOpen ? 'Close menu' : 'Open menu'}
|
|
29
|
+
aria-expanded={ctx.isOpen}
|
|
30
|
+
aria-controls={`combobox-listbox-${ctx.instanceId}`}
|
|
31
|
+
isDisabled={ctx.isDisabled || ctx.isReadOnly}
|
|
32
|
+
isPending={ctx.isPending}
|
|
33
|
+
pressed={ctx.isOpen}
|
|
34
|
+
onmousedown={handleMouseDown}
|
|
35
|
+
class={className}
|
|
36
|
+
{...restProps}
|
|
37
|
+
>
|
|
38
|
+
{#if children}
|
|
39
|
+
{@render children()}
|
|
40
|
+
{:else}
|
|
41
|
+
<svg
|
|
42
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
43
|
+
width="16"
|
|
44
|
+
height="16"
|
|
45
|
+
viewBox="0 0 24 24"
|
|
46
|
+
fill="none"
|
|
47
|
+
stroke="currentColor"
|
|
48
|
+
stroke-width="2"
|
|
49
|
+
stroke-linecap="round"
|
|
50
|
+
stroke-linejoin="round"
|
|
51
|
+
class="transition-transform {ctx.isOpen ? 'rotate-180' : ''}"
|
|
52
|
+
>
|
|
53
|
+
<path d="m6 9 6 6 6-6" />
|
|
54
|
+
</svg>
|
|
55
|
+
{/if}
|
|
56
|
+
</ButtonRoot>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
type ComboBoxTriggerProps = HTMLButtonAttributes & {
|
|
4
|
+
class?: string;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
};
|
|
7
|
+
declare const ComboboxTrigger: import("svelte").Component<ComboBoxTriggerProps, {}, "">;
|
|
8
|
+
type ComboboxTrigger = ReturnType<typeof ComboboxTrigger>;
|
|
9
|
+
export default ComboboxTrigger;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# DatePicker
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
`DatePicker` composes a segmented date input with a calendar popover for selecting dates.
|
|
6
|
+
|
|
7
|
+
## Anatomy
|
|
8
|
+
|
|
9
|
+
- `DatePicker.Root`
|
|
10
|
+
- `DatePicker.Input`
|
|
11
|
+
- `DatePicker.Segment`
|
|
12
|
+
- `DatePicker.Trigger`
|
|
13
|
+
- `DatePicker.Popover`
|
|
14
|
+
- `DatePicker.Calendar`
|
|
15
|
+
- `DatePicker.TriggerPrevious`
|
|
16
|
+
- `DatePicker.Heading`
|
|
17
|
+
- `DatePicker.TriggerNext`
|
|
18
|
+
- `DatePicker.Grid`
|
|
19
|
+
- `DatePicker.GridHeader`
|
|
20
|
+
- `DatePicker.HeaderCell`
|
|
21
|
+
- `DatePicker.GridBody`
|
|
22
|
+
- `DatePicker.BodyCell`
|
|
23
|
+
|
|
24
|
+
```svelte
|
|
25
|
+
<DatePicker.Root>
|
|
26
|
+
<DatePicker.Input aria-label="Date input">
|
|
27
|
+
{#snippet children(segment)}
|
|
28
|
+
<DatePicker.Segment {segment} />
|
|
29
|
+
{/snippet}
|
|
30
|
+
</DatePicker.Input>
|
|
31
|
+
<DatePicker.Trigger />
|
|
32
|
+
|
|
33
|
+
<DatePicker.Popover>
|
|
34
|
+
<DatePicker.Calendar>
|
|
35
|
+
<div>
|
|
36
|
+
<DatePicker.TriggerPrevious />
|
|
37
|
+
<DatePicker.Heading />
|
|
38
|
+
<DatePicker.TriggerNext />
|
|
39
|
+
</div>
|
|
40
|
+
<DatePicker.Grid>
|
|
41
|
+
<DatePicker.GridHeader />
|
|
42
|
+
<DatePicker.GridBody />
|
|
43
|
+
</DatePicker.Grid>
|
|
44
|
+
</DatePicker.Calendar>
|
|
45
|
+
</DatePicker.Popover>
|
|
46
|
+
</DatePicker.Root>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Root API
|
|
50
|
+
|
|
51
|
+
- `value?: string | null` (`YYYY-MM-DD`)
|
|
52
|
+
- `defaultValue?: string | null` (`YYYY-MM-DD`)
|
|
53
|
+
- `onChange?: (value: string | null) => void`
|
|
54
|
+
- `isDisabled?: boolean`
|
|
55
|
+
- `isReadOnly?: boolean`
|
|
56
|
+
- `minValue?: string` (`YYYY-MM-DD`)
|
|
57
|
+
- `maxValue?: string` (`YYYY-MM-DD`)
|
|
58
|
+
- `isDateUnavailable?: (date: string) => boolean`
|
|
59
|
+
- `open?: boolean`
|
|
60
|
+
- `defaultOpen?: boolean`
|
|
61
|
+
- `onOpenChange?: (open: boolean, details: { reason, event?, cancel(), isCanceled }) => void`
|
|
62
|
+
- `closeOnSelect?: boolean`
|
|
63
|
+
- Null-first empty contract: when `value` and `defaultValue` are omitted, the empty state is `null`.
|
|
64
|
+
- `DatePicker.Input` exposes `aria-invalid` and `data-invalid` when the current segment draft is not committeable.
|
|
65
|
+
|
|
66
|
+
## Popover API
|
|
67
|
+
|
|
68
|
+
- `DatePicker.Popover` forwards `Popover.Content` props (for example `placement`, `offset`, `shouldFlip`, `boundaryElement`, `isNonModal`, and close behavior props).
|
|
69
|
+
- The following are controlled internally by `DatePicker` and are not accepted on `DatePicker.Popover`: `open`, `triggerRef`, `onOpenChange`, `id`.
|
|
70
|
+
- Defaults:
|
|
71
|
+
- `placement` defaults to `bottom-start`.
|
|
72
|
+
- `aria-label` defaults to `Calendar`.
|
|
73
|
+
- `initialFocus` defaults to focusing the current active day cell in the calendar grid.
|
|
74
|
+
|
|
75
|
+
## Calendar API
|
|
76
|
+
|
|
77
|
+
- `DatePicker.Calendar` forwards `Calendar.Root` props except those controlled by `DatePicker.Root`.
|
|
78
|
+
- The following are controlled internally by `DatePicker` and are not accepted on `DatePicker.Calendar`: `selectionMode`, `value`, `defaultValue`, `onChange`, `isDisabled`, `isReadOnly`, `isDateUnavailable`.
|
|
79
|
+
|
|
80
|
+
## Notes
|
|
81
|
+
|
|
82
|
+
- Locale is read from `LocaleProvider` when available.
|
|
83
|
+
- Segment accessible names are resolved automatically from the active locale.
|
|
84
|
+
- During segment editing, the committed value is set to `null` when the draft is incomplete, invalid, out-of-range, or unavailable.
|
|
85
|
+
- Current MVP focuses on date-only values.
|
|
86
|
+
|
|
87
|
+
## UX Decisions
|
|
88
|
+
|
|
89
|
+
- **No Date Auto-Correction:** When users manually type dates out of the configured bounds (`minValue`/`maxValue`) or dates that are unavailable, the DatePicker **does not auto-correct** the typed value. Instead, it exposes `aria-invalid="true"` and `data-invalid` on the input, allowing the user to see what they typed incorrectly. The underlying committed value is kept as `null` until a valid date is completed. Auto-correcting input without explicit user consent is an inaccessible anti-pattern.
|
|
90
|
+
- **Navigable Disabled Dates:** When using the Calendar, disabled dates remain focusable via keyboard navigation. This ensures ARIA Grid spatial navigation parity so that screen readers can consistently announce all calendar cells and report them as "disabled", rather than skipping over them and disorienting the user.
|
|
91
|
+
|
|
92
|
+
## Focus behavior decisions
|
|
93
|
+
|
|
94
|
+
- DatePicker aligns with the shared modality primitive (`primitives/input-modality.ts`) for `keyboard`, `pointer`, and `virtual` interactions.
|
|
95
|
+
- `data-focus-visible` is modality-driven; `data-focused` and `data-focus-within` continue to represent real DOM focus state.
|
|
96
|
+
- Trigger focus restore after calendar close is modality-aware:
|
|
97
|
+
- keyboard close paths keep visible focus,
|
|
98
|
+
- pointer outside close restores focus without visible focus.
|
|
99
|
+
- The component keeps explicit `trackInteractionModality(...)` calls in local handlers to ensure deterministic modality updates before local focus-state logic runs.
|
|
100
|
+
- Cross-component focus contract and invariants are documented in `FOCUS_STATE_CONTRACT.md`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# DatePicker TODO
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Track DatePicker work with a single mandatory TODO format.
|
|
6
|
+
|
|
7
|
+
## Backlog
|
|
8
|
+
|
|
9
|
+
- [x] [M][P0][Area: Context][Owner: Unassigned][Target: Done] Complete core context wiring.
|
|
10
|
+
- [x] [M][P0][Area: State][Owner: Unassigned][Target: Done] Implement root state and value handling.
|
|
11
|
+
- [x] [M][P0][Area: Parsing][Owner: Unassigned][Target: Done] Integrate segment parser and formatter.
|
|
12
|
+
- [x] [M][P0][Area: Input][Owner: Unassigned][Target: Done] Deliver baseline segmented input rendering.
|
|
13
|
+
- [x] [M][P0][Area: Composition][Owner: Unassigned][Target: Done] Integrate calendar popover behavior.
|
|
14
|
+
- [x] [M][P0][Area: Accessibility][Owner: Unassigned][Target: Done] Implement keyboard navigation baseline.
|
|
15
|
+
- [x] [M][P0][Area: Validation][Owner: Unassigned][Target: Done] Implement min/max and unavailable date validation baseline.
|
|
16
|
+
- [x] [M][P0][Area: API][Owner: Unassigned][Target: Done] Ship public exports and baseline docs/tests.
|
|
17
|
+
- [x] [M][P0][Area: Forms][Owner: Unassigned][Target: Done] Support rich object values and hidden input synchronization.
|
|
18
|
+
- [x] [M][P0][Area: Focus][Owner: Unassigned][Target: Done] Unify focus-visible behavior with shared modality semantics.
|
|
19
|
+
- [x] [S][P1][Area: Focus][Owner: Unassigned][Target: Done] Remove DatePicker-local modality tracking in favor of shared primitive.
|
|
20
|
+
- [x] [S][P1][Area: Documentation][Owner: Unassigned][Target: Done] Document focus contract updates and DatePicker rationale.
|
|
21
|
+
- [ ] [S][P1][Area: Calendar][Owner: Unassigned][Target: TBD] Add multi-month calendar display.
|
|
22
|
+
- [ ] [S][P1][Area: Accessibility][Owner: Unassigned][Target: TBD] Run deep accessibility audit (SR + keyboard edge cases).
|
|
23
|
+
- [ ] [C][P2][Area: Time][Owner: Unassigned][Target: TBD] Add time selection integration.
|
|
24
|
+
- [ ] [C][P2][Area: API][Owner: Unassigned][Target: TBD] Decide and implement date-range mode strategy.
|
|
25
|
+
- [ ] [C][P2][Area: Input][Owner: Unassigned][Target: TBD] Add input mask helper utilities.
|
|
26
|
+
- [ ] [C][P2][Area: Mobile][Owner: Unassigned][Target: TBD] Add mobile-optimized interaction pass.
|
|
27
|
+
- [ ] [C][P2][Area: UX][Owner: Unassigned][Target: TBD] Add preset shortcuts (today, next week, custom).
|
|
28
|
+
- [ ] [C][P2][Area: Performance][Owner: Unassigned][Target: TBD] Add segment update micro-benchmarks and optimizations.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# DatePicker Calendar
|
|
2
|
+
|
|
3
|
+
## API reference
|
|
4
|
+
|
|
5
|
+
### DatePicker.Calendar
|
|
6
|
+
|
|
7
|
+
Name: `DatePicker.Calendar`
|
|
8
|
+
Description: Calendar composition part connected to `DatePicker.Root` selected date and navigation state.
|
|
9
|
+
|
|
10
|
+
| Prop | Type | Default | Description |
|
|
11
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------ |
|
|
12
|
+
| `children` | `Snippet` | `undefined` | Optional custom calendar content. |
|
|
13
|
+
| `class` | `string` | `''` | CSS class names for the calendar wrapper. |
|
|
14
|
+
| `...restProps` | `Omit<ComponentProps<typeof Calendar.Root>, 'selectionMode' \| 'value' \| 'defaultValue' \| 'onChange' \| 'isDisabled' \| 'isReadOnly' \| 'isDateUnavailable'>` | `-` | Additional calendar root props forwarded by this part. |
|
|
15
|
+
|
|
16
|
+
### Notes
|
|
17
|
+
|
|
18
|
+
Name: Root-controlled calendar props
|
|
19
|
+
Description: `selectionMode`, `value`, `defaultValue`, `onChange`, `isDisabled`, `isReadOnly`, and `isDateUnavailable` are controlled by `DatePicker.Root` and ignored when passed to this part.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import DatePicker from '../index';
|
|
3
|
+
|
|
4
|
+
let unsafeOnChangeCalls = $state(0);
|
|
5
|
+
let selectedValue = $state<string | null>('');
|
|
6
|
+
|
|
7
|
+
const unsafeCalendarProps: Record<string, unknown> = {
|
|
8
|
+
selectionMode: 'range',
|
|
9
|
+
value: { start: '2026-02-01', end: '2026-02-05' },
|
|
10
|
+
defaultValue: '2026-02-20',
|
|
11
|
+
onChange: () => {
|
|
12
|
+
unsafeOnChangeCalls += 1;
|
|
13
|
+
},
|
|
14
|
+
isDisabled: true,
|
|
15
|
+
isReadOnly: true,
|
|
16
|
+
isDateUnavailable: () => true
|
|
17
|
+
};
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<DatePicker.Root
|
|
21
|
+
defaultValue="2026-02-10"
|
|
22
|
+
defaultOpen={true}
|
|
23
|
+
onChange={(nextValue) => {
|
|
24
|
+
selectedValue = nextValue;
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
<DatePicker.Input class="date-picker-input" aria-label="Date input">
|
|
28
|
+
{#snippet children(segment)}
|
|
29
|
+
<DatePicker.Segment class="date-picker-segment" {segment} />
|
|
30
|
+
{/snippet}
|
|
31
|
+
</DatePicker.Input>
|
|
32
|
+
<DatePicker.Trigger class="date-picker-trigger">Open calendar</DatePicker.Trigger>
|
|
33
|
+
|
|
34
|
+
<DatePicker.Popover class="date-picker-popover">
|
|
35
|
+
<DatePicker.Calendar class="date-picker-calendar" {...unsafeCalendarProps}>
|
|
36
|
+
<div class="flex items-center justify-between gap-2 p-2">
|
|
37
|
+
<DatePicker.TriggerPrevious />
|
|
38
|
+
<DatePicker.Heading />
|
|
39
|
+
<DatePicker.TriggerNext />
|
|
40
|
+
</div>
|
|
41
|
+
<DatePicker.Grid>
|
|
42
|
+
<DatePicker.GridHeader>
|
|
43
|
+
{#snippet children(dayLabel: string)}
|
|
44
|
+
<DatePicker.HeaderCell>
|
|
45
|
+
{dayLabel}
|
|
46
|
+
</DatePicker.HeaderCell>
|
|
47
|
+
{/snippet}
|
|
48
|
+
</DatePicker.GridHeader>
|
|
49
|
+
<DatePicker.GridBody>
|
|
50
|
+
{#snippet children(date: string)}
|
|
51
|
+
<DatePicker.BodyCell {date} />
|
|
52
|
+
{/snippet}
|
|
53
|
+
</DatePicker.GridBody>
|
|
54
|
+
</DatePicker.Grid>
|
|
55
|
+
</DatePicker.Calendar>
|
|
56
|
+
</DatePicker.Popover>
|
|
57
|
+
</DatePicker.Root>
|
|
58
|
+
|
|
59
|
+
<p data-testid="unsafe-on-change-calls">{unsafeOnChangeCalls}</p>
|
|
60
|
+
<p data-testid="selected-value">{selectedValue}</p>
|