@human-kit/svelte-components 1.0.0-alpha.2 → 1.0.0-alpha.20
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 +362 -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/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-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 +277 -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.svelte +8 -7
- package/dist/popover/trigger/popover-trigger.svelte +14 -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 +26 -0
- package/dist/table/body/table-body.svelte +24 -0
- package/dist/table/body/table-body.svelte.d.ts +4 -0
- package/dist/table/cell/README.md +27 -0
- package/dist/table/cell/table-cell.svelte +265 -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 +128 -0
- package/dist/table/checkbox/table-checkbox-test.svelte.d.ts +18 -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 +228 -0
- package/dist/table/root/context.js +2111 -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 +553 -0
- package/dist/table/root/table-root.svelte.d.ts +4 -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 +95 -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 +31 -1
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
4
|
import { useListBoxContext } from '../root/context';
|
|
5
5
|
import { onMount, onDestroy } from 'svelte';
|
|
6
|
+
import {
|
|
7
|
+
focusWithModality,
|
|
8
|
+
shouldShowFocusVisible,
|
|
9
|
+
trackInteractionModality
|
|
10
|
+
} from '../../primitives/input-modality';
|
|
6
11
|
|
|
7
12
|
/**
|
|
8
13
|
* Props for the ListBox.Item component.
|
|
@@ -26,14 +31,20 @@
|
|
|
26
31
|
disableFocusHandling?: boolean;
|
|
27
32
|
/** Override the focused state. When provided, this value is used instead of internal focus tracking. */
|
|
28
33
|
isFocusedOverride?: boolean;
|
|
34
|
+
/** Override the focus-visible presentation state. */
|
|
35
|
+
isFocusVisibleOverride?: boolean;
|
|
29
36
|
/** Override the select behavior. When provided, called instead of default listbox selection. */
|
|
30
37
|
onItemSelect?: (id: string | number, label: string) => void;
|
|
31
38
|
/** Callback with resolved text value when mounted (from prop or rendered content). */
|
|
32
39
|
onResolvedTextValue?: (label: string) => void;
|
|
40
|
+
/** Callback when pointer hover should move logical focus to this item. */
|
|
41
|
+
onItemHoverStart?: (id: string | number, label: string) => void;
|
|
33
42
|
/** Whether to scroll this item into view when focused. Useful for virtual focus patterns. */
|
|
34
43
|
scrollOnFocus?: boolean;
|
|
35
44
|
/** Additional disabled state from parent. */
|
|
36
45
|
isParentDisabled?: boolean;
|
|
46
|
+
/** Override the visual pressed state. When provided, this value is used instead of internal press tracking. */
|
|
47
|
+
pressed?: boolean;
|
|
37
48
|
};
|
|
38
49
|
|
|
39
50
|
let {
|
|
@@ -46,10 +57,13 @@
|
|
|
46
57
|
customId,
|
|
47
58
|
disableFocusHandling = false,
|
|
48
59
|
isFocusedOverride,
|
|
60
|
+
isFocusVisibleOverride,
|
|
49
61
|
onItemSelect,
|
|
50
62
|
onResolvedTextValue,
|
|
63
|
+
onItemHoverStart,
|
|
51
64
|
scrollOnFocus = false,
|
|
52
65
|
isParentDisabled = false,
|
|
66
|
+
pressed: pressedOverride,
|
|
53
67
|
...restProps
|
|
54
68
|
}: ListBoxItemProps = $props();
|
|
55
69
|
|
|
@@ -58,7 +72,12 @@
|
|
|
58
72
|
let elementRef: HTMLElement;
|
|
59
73
|
let isSelected = $state(false);
|
|
60
74
|
let isFocused = $state(false);
|
|
75
|
+
let isFocusVisible = $state(false);
|
|
76
|
+
let listFocusVisible = $state(false);
|
|
61
77
|
let isHovered = $state(false);
|
|
78
|
+
let isPressed = $state(false);
|
|
79
|
+
let pressedKey: 'Enter' | 'Space' | null = $state(null);
|
|
80
|
+
let suppressNextFocusVisible = $state(false);
|
|
62
81
|
|
|
63
82
|
// Focus: use override if provided, otherwise use internal state
|
|
64
83
|
const isFocusedComputed = $derived(
|
|
@@ -67,12 +86,28 @@
|
|
|
67
86
|
const isDisabledComputed = $derived(
|
|
68
87
|
disabled || listboxCtx.disabledIds.has(id) || isParentDisabled
|
|
69
88
|
);
|
|
89
|
+
const isPressedComputed = $derived(
|
|
90
|
+
pressedOverride !== undefined
|
|
91
|
+
? Boolean(pressedOverride) && !isDisabledComputed
|
|
92
|
+
: isPressed && !isDisabledComputed
|
|
93
|
+
);
|
|
94
|
+
const isFocusVisibleComputed = $derived(
|
|
95
|
+
isFocusVisibleOverride !== undefined ? isFocusVisibleOverride : isFocusVisible
|
|
96
|
+
);
|
|
97
|
+
const isActiveFocusVisible = $derived(
|
|
98
|
+
isFocusVisibleOverride !== undefined
|
|
99
|
+
? isFocusVisibleComputed
|
|
100
|
+
: isFocusedComputed && listFocusVisible
|
|
101
|
+
);
|
|
102
|
+
const showFocusVisible = $derived(isActiveFocusVisible && !isHovered);
|
|
103
|
+
const showHovered = $derived(isHovered && !isActiveFocusVisible);
|
|
70
104
|
|
|
71
105
|
// ID: use custom if provided, otherwise generate
|
|
72
106
|
const uniqueId = $derived(customId ?? `listbox-item-${id}`);
|
|
73
107
|
|
|
74
108
|
let unsubscribeSelection: (() => void) | null = null;
|
|
75
109
|
let unsubscribeFocus: (() => void) | null = null;
|
|
110
|
+
let unsubscribeFocusVisible: (() => void) | null = null;
|
|
76
111
|
|
|
77
112
|
function getResolvedTextValue() {
|
|
78
113
|
return textValue || elementRef?.textContent?.trim() || String(id);
|
|
@@ -94,6 +129,9 @@
|
|
|
94
129
|
unsubscribeFocus = listboxCtx.subscribeToFocus(id, (focused) => {
|
|
95
130
|
isFocused = focused;
|
|
96
131
|
});
|
|
132
|
+
unsubscribeFocusVisible = listboxCtx.subscribeToFocusVisible((visible) => {
|
|
133
|
+
listFocusVisible = visible;
|
|
134
|
+
});
|
|
97
135
|
listboxCtx.keyboardNav.updateItems();
|
|
98
136
|
}
|
|
99
137
|
});
|
|
@@ -102,58 +140,265 @@
|
|
|
102
140
|
listboxCtx.unregisterItem(id);
|
|
103
141
|
unsubscribeSelection?.();
|
|
104
142
|
unsubscribeFocus?.();
|
|
143
|
+
unsubscribeFocusVisible?.();
|
|
105
144
|
});
|
|
106
145
|
|
|
107
146
|
// Scroll into view when focused (if enabled)
|
|
108
147
|
$effect(() => {
|
|
109
|
-
if (scrollOnFocus && isFocusedComputed && elementRef) {
|
|
148
|
+
if (scrollOnFocus && isFocusedComputed && isFocusVisibleComputed && elementRef) {
|
|
110
149
|
requestAnimationFrame(() => {
|
|
111
150
|
elementRef?.scrollIntoView({ block: 'nearest' });
|
|
112
151
|
});
|
|
113
152
|
}
|
|
114
153
|
});
|
|
115
154
|
|
|
155
|
+
$effect(() => {
|
|
156
|
+
if (!isDisabledComputed) return;
|
|
157
|
+
clearPressedState();
|
|
158
|
+
isHovered = false;
|
|
159
|
+
isFocusVisible = false;
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
$effect(() => {
|
|
163
|
+
if (!isFocusedComputed) {
|
|
164
|
+
if (pressedKey !== null) {
|
|
165
|
+
clearPressedState();
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (listFocusVisible || isFocusVisibleComputed) {
|
|
171
|
+
isHovered = false;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
function clearPressedState() {
|
|
176
|
+
isPressed = false;
|
|
177
|
+
pressedKey = null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function applyPointerFocusState() {
|
|
181
|
+
suppressNextFocusVisible = true;
|
|
182
|
+
listboxCtx.setFocusVisible(false);
|
|
183
|
+
listboxCtx.setFocusedId(id);
|
|
184
|
+
listboxCtx.keyboardNav.setCurrentId(id);
|
|
185
|
+
if (elementRef) {
|
|
186
|
+
focusWithModality(elementRef, 'pointer');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function transferHoverFocus() {
|
|
191
|
+
const label = getResolvedTextValue();
|
|
192
|
+
if (onItemHoverStart) {
|
|
193
|
+
onItemHoverStart(id, label);
|
|
194
|
+
} else if (!disableFocusHandling) {
|
|
195
|
+
applyPointerFocusState();
|
|
196
|
+
requestAnimationFrame(() => {
|
|
197
|
+
if (isHovered && !isDisabledComputed) {
|
|
198
|
+
applyPointerFocusState();
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
116
204
|
function handleClick() {
|
|
117
205
|
if (isDisabledComputed) return;
|
|
118
206
|
|
|
119
207
|
const label = getResolvedTextValue();
|
|
120
208
|
|
|
209
|
+
if (!disableFocusHandling && elementRef) {
|
|
210
|
+
suppressNextFocusVisible = true;
|
|
211
|
+
isFocusVisible = false;
|
|
212
|
+
listboxCtx.setFocusVisible(false);
|
|
213
|
+
listboxCtx.setFocusedId(id);
|
|
214
|
+
listboxCtx.keyboardNav.setCurrentId(id);
|
|
215
|
+
focusWithModality(elementRef, 'pointer');
|
|
216
|
+
}
|
|
217
|
+
|
|
121
218
|
// Use custom select handler if provided, otherwise use listbox default
|
|
122
219
|
if (onItemSelect) {
|
|
123
220
|
onItemSelect(id, label);
|
|
124
221
|
} else {
|
|
125
222
|
listboxCtx.select(id);
|
|
126
|
-
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!disableFocusHandling) {
|
|
226
|
+
listboxCtx.keyboardNav.setCurrentId(id);
|
|
127
227
|
}
|
|
128
228
|
}
|
|
129
229
|
|
|
130
230
|
function handleFocus() {
|
|
231
|
+
if (isDisabledComputed) return;
|
|
232
|
+
isFocusVisible = suppressNextFocusVisible ? false : shouldShowFocusVisible(elementRef);
|
|
233
|
+
suppressNextFocusVisible = false;
|
|
234
|
+
if (isFocusVisible) {
|
|
235
|
+
isHovered = false;
|
|
236
|
+
}
|
|
131
237
|
if (!disableFocusHandling) {
|
|
238
|
+
listboxCtx.setFocusVisible(isFocusVisible);
|
|
132
239
|
listboxCtx.setFocusedId(id);
|
|
133
240
|
}
|
|
134
241
|
}
|
|
135
242
|
|
|
136
|
-
function handleBlur() {
|
|
243
|
+
function handleBlur() {
|
|
244
|
+
isFocusVisible = false;
|
|
245
|
+
if (!disableFocusHandling && listboxCtx.isFocused(id)) {
|
|
246
|
+
listboxCtx.setFocusVisible(false);
|
|
247
|
+
listboxCtx.setFocusedId(null);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function handlePointerDown(event: PointerEvent) {
|
|
252
|
+
trackInteractionModality(event, elementRef);
|
|
253
|
+
isFocusVisible = false;
|
|
254
|
+
if (!disableFocusHandling) {
|
|
255
|
+
listboxCtx.setFocusVisible(false);
|
|
256
|
+
}
|
|
137
257
|
|
|
138
|
-
|
|
258
|
+
if (isDisabledComputed) {
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
clearPressedState();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (event.button !== 0) return;
|
|
265
|
+
isPressed = true;
|
|
266
|
+
pressedKey = null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function handlePointerUp(event: PointerEvent) {
|
|
270
|
+
if (event.button !== 0) return;
|
|
271
|
+
isPressed = false;
|
|
272
|
+
pressedKey = null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function handlePointerCancel() {
|
|
276
|
+
clearPressedState();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function handlePointerEnter(event: PointerEvent) {
|
|
280
|
+
if (isDisabledComputed) return;
|
|
281
|
+
|
|
282
|
+
trackInteractionModality(event, elementRef);
|
|
283
|
+
if (!disableFocusHandling) {
|
|
284
|
+
listboxCtx.setFocusVisible(false);
|
|
285
|
+
}
|
|
286
|
+
transferHoverFocus();
|
|
287
|
+
|
|
288
|
+
if ((event.buttons & 1) === 1 && pressedKey === null) {
|
|
289
|
+
isPressed = true;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function handlePointerLeave() {
|
|
294
|
+
if (pressedKey === null) {
|
|
295
|
+
isPressed = false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function handleMouseEnter(event: MouseEvent) {
|
|
139
300
|
if (!isDisabledComputed) {
|
|
301
|
+
trackInteractionModality(event, elementRef);
|
|
140
302
|
isHovered = true;
|
|
303
|
+
isFocusVisible = false;
|
|
304
|
+
if (!disableFocusHandling) {
|
|
305
|
+
listboxCtx.setFocusVisible(false);
|
|
306
|
+
transferHoverFocus();
|
|
307
|
+
}
|
|
141
308
|
}
|
|
142
309
|
}
|
|
143
310
|
|
|
144
311
|
function handleMouseLeave() {
|
|
145
312
|
isHovered = false;
|
|
313
|
+
if (pressedKey === null) {
|
|
314
|
+
isPressed = false;
|
|
315
|
+
}
|
|
146
316
|
}
|
|
147
317
|
|
|
148
318
|
// Keyboard is handled by parent container
|
|
149
|
-
function handleKeydown() {
|
|
319
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
320
|
+
trackInteractionModality(event, elementRef);
|
|
321
|
+
if (isFocusedComputed) {
|
|
322
|
+
isHovered = false;
|
|
323
|
+
isFocusVisible = true;
|
|
324
|
+
if (!disableFocusHandling) {
|
|
325
|
+
listboxCtx.setFocusVisible(true);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const key =
|
|
330
|
+
event.key === 'Enter'
|
|
331
|
+
? 'Enter'
|
|
332
|
+
: event.key === ' ' || event.key === 'Spacebar'
|
|
333
|
+
? 'Space'
|
|
334
|
+
: null;
|
|
335
|
+
|
|
336
|
+
if (!key) return;
|
|
337
|
+
|
|
338
|
+
if (isDisabledComputed) {
|
|
339
|
+
event.preventDefault();
|
|
340
|
+
clearPressedState();
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (event.repeat && isPressed && pressedKey === key) return;
|
|
345
|
+
|
|
346
|
+
isPressed = true;
|
|
347
|
+
pressedKey = key;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function handleKeyup(event: KeyboardEvent) {
|
|
351
|
+
const key =
|
|
352
|
+
event.key === 'Enter'
|
|
353
|
+
? 'Enter'
|
|
354
|
+
: event.key === ' ' || event.key === 'Spacebar'
|
|
355
|
+
? 'Space'
|
|
356
|
+
: null;
|
|
357
|
+
|
|
358
|
+
if (!key) return;
|
|
359
|
+
|
|
360
|
+
if (isDisabledComputed) {
|
|
361
|
+
event.preventDefault();
|
|
362
|
+
clearPressedState();
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (pressedKey === key) {
|
|
367
|
+
clearPressedState();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
150
371
|
function handleMouseDown(event: MouseEvent) {
|
|
372
|
+
trackInteractionModality(event, elementRef);
|
|
373
|
+
isFocusVisible = false;
|
|
374
|
+
if (!disableFocusHandling) {
|
|
375
|
+
listboxCtx.setFocusVisible(false);
|
|
376
|
+
}
|
|
377
|
+
|
|
151
378
|
// Prevent focus stealing when used in ComboBox (disableFocusHandling=true)
|
|
152
379
|
// This keeps the focus on the input while allowing click selection
|
|
380
|
+
if (isDisabledComputed) {
|
|
381
|
+
event.preventDefault();
|
|
382
|
+
clearPressedState();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (event.button === 0) {
|
|
387
|
+
isPressed = true;
|
|
388
|
+
pressedKey = null;
|
|
389
|
+
}
|
|
390
|
+
|
|
153
391
|
if (disableFocusHandling) {
|
|
154
392
|
event.preventDefault();
|
|
155
393
|
}
|
|
156
394
|
}
|
|
395
|
+
|
|
396
|
+
function handleMouseUp(event: MouseEvent) {
|
|
397
|
+
if (event.button !== 0) return;
|
|
398
|
+
if (pressedKey === null) {
|
|
399
|
+
clearPressedState();
|
|
400
|
+
}
|
|
401
|
+
}
|
|
157
402
|
</script>
|
|
158
403
|
|
|
159
404
|
<div
|
|
@@ -170,10 +415,19 @@
|
|
|
170
415
|
data-selected={isSelected || undefined}
|
|
171
416
|
data-disabled={isDisabledComputed || undefined}
|
|
172
417
|
data-focused={isFocusedComputed || undefined}
|
|
173
|
-
data-
|
|
418
|
+
data-focus-visible={showFocusVisible || undefined}
|
|
419
|
+
data-hovered={showHovered || undefined}
|
|
420
|
+
data-pressed={isPressedComputed || undefined}
|
|
421
|
+
onpointerdown={handlePointerDown}
|
|
422
|
+
onpointerup={handlePointerUp}
|
|
423
|
+
onpointercancel={handlePointerCancel}
|
|
424
|
+
onpointerenter={handlePointerEnter}
|
|
425
|
+
onpointerleave={handlePointerLeave}
|
|
174
426
|
onmousedown={handleMouseDown}
|
|
427
|
+
onmouseup={handleMouseUp}
|
|
175
428
|
onclick={handleClick}
|
|
176
429
|
onkeydown={handleKeydown}
|
|
430
|
+
onkeyup={handleKeyup}
|
|
177
431
|
onfocus={handleFocus}
|
|
178
432
|
onblur={handleBlur}
|
|
179
433
|
onmouseenter={handleMouseEnter}
|
|
@@ -20,14 +20,20 @@ type ListBoxItemProps = Omit<HTMLAttributes<HTMLDivElement>, 'id' | 'children'>
|
|
|
20
20
|
disableFocusHandling?: boolean;
|
|
21
21
|
/** Override the focused state. When provided, this value is used instead of internal focus tracking. */
|
|
22
22
|
isFocusedOverride?: boolean;
|
|
23
|
+
/** Override the focus-visible presentation state. */
|
|
24
|
+
isFocusVisibleOverride?: boolean;
|
|
23
25
|
/** Override the select behavior. When provided, called instead of default listbox selection. */
|
|
24
26
|
onItemSelect?: (id: string | number, label: string) => void;
|
|
25
27
|
/** Callback with resolved text value when mounted (from prop or rendered content). */
|
|
26
28
|
onResolvedTextValue?: (label: string) => void;
|
|
29
|
+
/** Callback when pointer hover should move logical focus to this item. */
|
|
30
|
+
onItemHoverStart?: (id: string | number, label: string) => void;
|
|
27
31
|
/** Whether to scroll this item into view when focused. Useful for virtual focus patterns. */
|
|
28
32
|
scrollOnFocus?: boolean;
|
|
29
33
|
/** Additional disabled state from parent. */
|
|
30
34
|
isParentDisabled?: boolean;
|
|
35
|
+
/** Override the visual pressed state. When provided, this value is used instead of internal press tracking. */
|
|
36
|
+
pressed?: boolean;
|
|
31
37
|
};
|
|
32
38
|
declare const ListboxItem: import("svelte").Component<ListBoxItemProps, {}, "">;
|
|
33
39
|
type ListboxItem = ReturnType<typeof ListboxItem>;
|
|
@@ -20,6 +20,8 @@ export type ListBoxContext = {
|
|
|
20
20
|
isDisabled: (id: string | number) => boolean;
|
|
21
21
|
/** Checks if an item is focused. */
|
|
22
22
|
isFocused: (id: string | number) => boolean;
|
|
23
|
+
/** Whether keyboard focus-visible should be shown for the currently focused item. */
|
|
24
|
+
getFocusVisible: () => boolean;
|
|
23
25
|
/** Keyboard navigation controller from the shared primitive. */
|
|
24
26
|
keyboardNav: KeyboardNavigationReturn;
|
|
25
27
|
/** Map of registered items with their metadata. */
|
|
@@ -45,10 +47,14 @@ export type ListBoxContext = {
|
|
|
45
47
|
setSelection: (selection: Set<string | number>) => void;
|
|
46
48
|
/** Sets the focused item ID. */
|
|
47
49
|
setFocusedId: (id: string | number | null) => void;
|
|
50
|
+
/** Sets whether the focused item should render keyboard focus-visible. */
|
|
51
|
+
setFocusVisible: (visible: boolean) => void;
|
|
48
52
|
/** Subscribes to selection changes for a specific item. Returns unsubscribe function. */
|
|
49
53
|
subscribeToItem: (id: string | number, callback: (selected: boolean) => void) => () => void;
|
|
50
54
|
/** Subscribes to focus changes for a specific item. Returns unsubscribe function. */
|
|
51
55
|
subscribeToFocus: (id: string | number, callback: (focused: boolean) => void) => () => void;
|
|
56
|
+
/** Subscribes to focus-visible state changes. Returns unsubscribe function. */
|
|
57
|
+
subscribeToFocusVisible: (callback: (visible: boolean) => void) => () => void;
|
|
52
58
|
/** Returns the next item ID respecting loop setting, or null if at end. */
|
|
53
59
|
getNextItemId: (currentId: string | number | null) => string | number | null;
|
|
54
60
|
/** Returns the previous item ID respecting loop setting, or null if at start. */
|
|
@@ -53,30 +53,30 @@ export function createListBoxContext(options = {}) {
|
|
|
53
53
|
}
|
|
54
54
|
let focusedId = null;
|
|
55
55
|
const focusCallbacks = new Map();
|
|
56
|
+
let focusVisible = false;
|
|
57
|
+
const focusVisibleCallbacks = new Set();
|
|
56
58
|
function getFocusedId() {
|
|
57
59
|
return focusedId;
|
|
58
60
|
}
|
|
59
61
|
function isFocused(id) {
|
|
60
62
|
return focusedId === id || String(focusedId) === String(id);
|
|
61
63
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
if (callbacks) {
|
|
65
|
-
callbacks.forEach((cb) => cb(focused));
|
|
66
|
-
}
|
|
64
|
+
function getFocusVisible() {
|
|
65
|
+
return focusVisible;
|
|
67
66
|
}
|
|
68
67
|
function setFocusedId(newId) {
|
|
69
|
-
if (focusedId === newId)
|
|
70
|
-
return;
|
|
71
|
-
const previousId = focusedId;
|
|
72
68
|
focusedId = newId;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (newId !== null) {
|
|
77
|
-
notifyFocus(newId, true);
|
|
69
|
+
for (const [id, callbacks] of focusCallbacks) {
|
|
70
|
+
const focused = newId !== null && (id === newId || String(id) === String(newId));
|
|
71
|
+
callbacks.forEach((callback) => callback(focused));
|
|
78
72
|
}
|
|
79
73
|
}
|
|
74
|
+
function setFocusVisible(visible) {
|
|
75
|
+
if (focusVisible === visible)
|
|
76
|
+
return;
|
|
77
|
+
focusVisible = visible;
|
|
78
|
+
focusVisibleCallbacks.forEach((callback) => callback(visible));
|
|
79
|
+
}
|
|
80
80
|
function subscribeToFocus(id, callback) {
|
|
81
81
|
if (!focusCallbacks.has(id)) {
|
|
82
82
|
focusCallbacks.set(id, new Set());
|
|
@@ -93,6 +93,13 @@ export function createListBoxContext(options = {}) {
|
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
|
+
function subscribeToFocusVisible(callback) {
|
|
97
|
+
focusVisibleCallbacks.add(callback);
|
|
98
|
+
callback(focusVisible);
|
|
99
|
+
return () => {
|
|
100
|
+
focusVisibleCallbacks.delete(callback);
|
|
101
|
+
};
|
|
102
|
+
}
|
|
96
103
|
function subscribeToItem(id, callback) {
|
|
97
104
|
if (!itemCallbacks.has(id)) {
|
|
98
105
|
itemCallbacks.set(id, new Set());
|
|
@@ -221,6 +228,7 @@ export function createListBoxContext(options = {}) {
|
|
|
221
228
|
isSelected,
|
|
222
229
|
isDisabled,
|
|
223
230
|
isFocused,
|
|
231
|
+
getFocusVisible,
|
|
224
232
|
keyboardNav,
|
|
225
233
|
items,
|
|
226
234
|
registerItem,
|
|
@@ -232,8 +240,10 @@ export function createListBoxContext(options = {}) {
|
|
|
232
240
|
selectAll,
|
|
233
241
|
setSelection,
|
|
234
242
|
setFocusedId,
|
|
243
|
+
setFocusVisible,
|
|
235
244
|
subscribeToItem,
|
|
236
245
|
subscribeToFocus,
|
|
246
|
+
subscribeToFocusVisible,
|
|
237
247
|
getNextItemId,
|
|
238
248
|
getPreviousItemId
|
|
239
249
|
};
|
|
@@ -5,9 +5,17 @@
|
|
|
5
5
|
selectionMode?: 'single' | 'multiple';
|
|
6
6
|
selectionBehavior?: 'toggle' | 'replace';
|
|
7
7
|
disabledIds?: Iterable<string | number>;
|
|
8
|
+
pressedIds?: Iterable<string | number>;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
|
-
let {
|
|
11
|
+
let {
|
|
12
|
+
selectionMode = 'single',
|
|
13
|
+
selectionBehavior = 'toggle',
|
|
14
|
+
disabledIds,
|
|
15
|
+
pressedIds
|
|
16
|
+
}: Props = $props();
|
|
17
|
+
|
|
18
|
+
const pressedIdSet = $derived(new Set(pressedIds ?? []));
|
|
11
19
|
|
|
12
20
|
const fruits = [
|
|
13
21
|
{ id: 'apple', name: 'Apple' },
|
|
@@ -20,7 +28,11 @@
|
|
|
20
28
|
|
|
21
29
|
<ListBox.Root {selectionMode} {selectionBehavior} {disabledIds} aria-label="Fruits list">
|
|
22
30
|
{#each fruits as fruit (fruit.id)}
|
|
23
|
-
<ListBox.Item
|
|
31
|
+
<ListBox.Item
|
|
32
|
+
id={fruit.id}
|
|
33
|
+
textValue={fruit.name}
|
|
34
|
+
pressed={pressedIdSet.has(fruit.id) ? true : undefined}
|
|
35
|
+
>
|
|
24
36
|
{fruit.name}
|
|
25
37
|
</ListBox.Item>
|
|
26
38
|
{/each}
|
|
@@ -2,6 +2,7 @@ type Props = {
|
|
|
2
2
|
selectionMode?: 'single' | 'multiple';
|
|
3
3
|
selectionBehavior?: 'toggle' | 'replace';
|
|
4
4
|
disabledIds?: Iterable<string | number>;
|
|
5
|
+
pressedIds?: Iterable<string | number>;
|
|
5
6
|
};
|
|
6
7
|
declare const ListboxTest: import("svelte").Component<Props, {}, "">;
|
|
7
8
|
type ListboxTest = ReturnType<typeof ListboxTest>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script lang="ts" generics="T extends object = object">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import { onMount } from 'svelte';
|
|
3
4
|
import { createListBoxContext, type ListBoxContext } from './context';
|
|
5
|
+
import { trackInteractionModality } from '../../primitives/input-modality';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Props for the ListBox component.
|
|
@@ -31,6 +33,8 @@
|
|
|
31
33
|
'aria-label'?: string;
|
|
32
34
|
/** Callback fired when the selection changes. */
|
|
33
35
|
onChange?: (value: Set<string | number>) => void;
|
|
36
|
+
/** Disable DOM focus handling on the root container for virtual-focus compositions. */
|
|
37
|
+
disableFocusHandling?: boolean;
|
|
34
38
|
};
|
|
35
39
|
|
|
36
40
|
let {
|
|
@@ -46,6 +50,7 @@
|
|
|
46
50
|
id,
|
|
47
51
|
'aria-label': ariaLabel,
|
|
48
52
|
onChange,
|
|
53
|
+
disableFocusHandling = false,
|
|
49
54
|
context = $bindable(),
|
|
50
55
|
element = $bindable()
|
|
51
56
|
}: ListBoxProps & { context?: ListBoxContext; element?: HTMLElement } = $props();
|
|
@@ -114,6 +119,43 @@
|
|
|
114
119
|
|
|
115
120
|
const itemsArray = $derived(items ? Array.from(items) : []);
|
|
116
121
|
const hasItems = $derived(itemsArray.length > 0 || itemCount > 0);
|
|
122
|
+
let hasMounted = $state(false);
|
|
123
|
+
|
|
124
|
+
let focusWithin = $state(false);
|
|
125
|
+
|
|
126
|
+
onMount(() => {
|
|
127
|
+
hasMounted = true;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
function syncFocusWithin() {
|
|
131
|
+
focusWithin =
|
|
132
|
+
!!listboxElement &&
|
|
133
|
+
!!document.activeElement &&
|
|
134
|
+
listboxElement.contains(document.activeElement);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function handleFocusIn() {
|
|
138
|
+
focusWithin = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function handleFocusOut() {
|
|
142
|
+
queueMicrotask(syncFocusWithin);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function handleMouseDown(event: MouseEvent) {
|
|
146
|
+
trackInteractionModality(event, event.target as HTMLElement | null);
|
|
147
|
+
ctx.setFocusVisible(false);
|
|
148
|
+
if (disableFocusHandling) {
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
154
|
+
trackInteractionModality(event, event.target as HTMLElement | null);
|
|
155
|
+
if (focusWithin) {
|
|
156
|
+
ctx.setFocusVisible(true);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
117
159
|
</script>
|
|
118
160
|
|
|
119
161
|
<div
|
|
@@ -123,8 +165,13 @@
|
|
|
123
165
|
aria-multiselectable={selectionMode === 'multiple'}
|
|
124
166
|
aria-label={ariaLabel}
|
|
125
167
|
class={className}
|
|
126
|
-
tabindex=
|
|
168
|
+
tabindex={disableFocusHandling ? undefined : 0}
|
|
169
|
+
data-focus-within={focusWithin || undefined}
|
|
127
170
|
use:keyboardAction
|
|
171
|
+
onfocusin={handleFocusIn}
|
|
172
|
+
onfocusout={handleFocusOut}
|
|
173
|
+
onmousedown={handleMouseDown}
|
|
174
|
+
onkeydown={handleKeyDown}
|
|
128
175
|
>
|
|
129
176
|
{#if items && children}
|
|
130
177
|
{#each itemsArray as item (item)}
|
|
@@ -134,7 +181,7 @@
|
|
|
134
181
|
{@render (children as Snippet)()}
|
|
135
182
|
{/if}
|
|
136
183
|
|
|
137
|
-
{#if !hasItems && itemCount === 0}
|
|
184
|
+
{#if hasMounted && !hasItems && itemCount === 0}
|
|
138
185
|
{#if typeof emptyPlaceholder === 'string'}
|
|
139
186
|
<div role="option" aria-selected="false" aria-disabled="true" data-empty-placeholder>
|
|
140
187
|
{emptyPlaceholder}
|
|
@@ -26,12 +26,14 @@ declare function $$render<T extends object = object>(): {
|
|
|
26
26
|
'aria-label'?: string;
|
|
27
27
|
/** Callback fired when the selection changes. */
|
|
28
28
|
onChange?: (value: Set<string | number>) => void;
|
|
29
|
+
/** Disable DOM focus handling on the root container for virtual-focus compositions. */
|
|
30
|
+
disableFocusHandling?: boolean;
|
|
29
31
|
} & {
|
|
30
32
|
context?: ListBoxContext;
|
|
31
33
|
element?: HTMLElement;
|
|
32
34
|
};
|
|
33
35
|
exports: {};
|
|
34
|
-
bindings: "value" | "
|
|
36
|
+
bindings: "value" | "element" | "context";
|
|
35
37
|
slots: {};
|
|
36
38
|
events: {};
|
|
37
39
|
};
|
|
@@ -39,7 +41,7 @@ declare class __sveltets_Render<T extends object = object> {
|
|
|
39
41
|
props(): ReturnType<typeof $$render<T>>['props'];
|
|
40
42
|
events(): ReturnType<typeof $$render<T>>['events'];
|
|
41
43
|
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
42
|
-
bindings(): "value" | "
|
|
44
|
+
bindings(): "value" | "element" | "context";
|
|
43
45
|
exports(): {};
|
|
44
46
|
}
|
|
45
47
|
interface $$IsomorphicComponent {
|
package/dist/popover/README.md
CHANGED
|
@@ -12,6 +12,16 @@
|
|
|
12
12
|
- Use `Popover.Content` inside `Popover.Root`, or in standalone mode with `open`, `triggerRef`, and `onOpenChange`.
|
|
13
13
|
- Configure `isNonModal`, `shouldCloseOnInteractOutside`, and `shouldCloseOnBlur` to match your interaction model.
|
|
14
14
|
|
|
15
|
+
## onOpenChange details
|
|
16
|
+
|
|
17
|
+
`Popover.Root` and standalone `Popover.Content` use:
|
|
18
|
+
|
|
19
|
+
- `onOpenChange(open, details)`
|
|
20
|
+
- `details.reason`: `trigger-press | imperative-action | none | escape-key | outside-press | focus-out | close-press`
|
|
21
|
+
- `details.event?`: native event that triggered the change when available
|
|
22
|
+
- `details.cancel()`: prevents the open-state transition
|
|
23
|
+
- `details.isCanceled`: reflects cancellation state inside the callback
|
|
24
|
+
|
|
15
25
|
## Anatomy
|
|
16
26
|
|
|
17
27
|
Import the component and compose its parts:
|