@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
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Focus trap primitive.
|
|
3
3
|
* Traps keyboard focus within a container element.
|
|
4
4
|
*/
|
|
5
|
+
import { focusWithModality, getInteractionModality } from './input-modality';
|
|
5
6
|
const FOCUSABLE_SELECTOR = [
|
|
6
7
|
'a[href]',
|
|
7
8
|
'button:not([disabled])',
|
|
@@ -11,8 +12,29 @@ const FOCUSABLE_SELECTOR = [
|
|
|
11
12
|
'[tabindex]:not([tabindex="-1"])',
|
|
12
13
|
'[contenteditable="true"]'
|
|
13
14
|
].join(', ');
|
|
15
|
+
function resolveEnabled(options) {
|
|
16
|
+
if (typeof options === 'boolean')
|
|
17
|
+
return options;
|
|
18
|
+
return options.enabled ?? true;
|
|
19
|
+
}
|
|
20
|
+
function resolveRestoreFocus(options) {
|
|
21
|
+
if (typeof options === 'boolean')
|
|
22
|
+
return true;
|
|
23
|
+
return options.restoreFocus ?? true;
|
|
24
|
+
}
|
|
25
|
+
function resolveInitialFocus(container, initialFocus) {
|
|
26
|
+
if (!initialFocus)
|
|
27
|
+
return null;
|
|
28
|
+
if (typeof initialFocus === 'function') {
|
|
29
|
+
return initialFocus() ?? null;
|
|
30
|
+
}
|
|
31
|
+
if (typeof initialFocus === 'string') {
|
|
32
|
+
return container.querySelector(initialFocus);
|
|
33
|
+
}
|
|
34
|
+
return initialFocus;
|
|
35
|
+
}
|
|
14
36
|
function getFocusableElements(container) {
|
|
15
|
-
return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter((
|
|
37
|
+
return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter((element) => element.offsetParent !== null);
|
|
16
38
|
}
|
|
17
39
|
/**
|
|
18
40
|
* Svelte action that traps focus within an element.
|
|
@@ -25,8 +47,11 @@ function getFocusableElements(container) {
|
|
|
25
47
|
* </div>
|
|
26
48
|
* ```
|
|
27
49
|
*/
|
|
28
|
-
export function focusTrap(node,
|
|
50
|
+
export function focusTrap(node, options = true) {
|
|
29
51
|
let previousActiveElement = null;
|
|
52
|
+
let enabled = resolveEnabled(options);
|
|
53
|
+
let restoreFocus = resolveRestoreFocus(options);
|
|
54
|
+
let initialFocus = typeof options === 'boolean' ? undefined : options.initialFocus;
|
|
30
55
|
function handleKeydown(event) {
|
|
31
56
|
if (event.key !== 'Tab')
|
|
32
57
|
return;
|
|
@@ -49,12 +74,11 @@ export function focusTrap(node, enabled = true) {
|
|
|
49
74
|
event.preventDefault();
|
|
50
75
|
lastElement.focus();
|
|
51
76
|
}
|
|
77
|
+
return;
|
|
52
78
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
firstElement.focus();
|
|
57
|
-
}
|
|
79
|
+
if (document.activeElement === lastElement || document.activeElement === node) {
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
firstElement.focus();
|
|
58
82
|
}
|
|
59
83
|
}
|
|
60
84
|
function activate() {
|
|
@@ -62,21 +86,25 @@ export function focusTrap(node, enabled = true) {
|
|
|
62
86
|
if (!node.hasAttribute('tabindex')) {
|
|
63
87
|
node.setAttribute('tabindex', '-1');
|
|
64
88
|
}
|
|
65
|
-
// Focus first focusable element, or the container if none
|
|
66
89
|
requestAnimationFrame(() => {
|
|
90
|
+
const initialFocusTarget = resolveInitialFocus(node, initialFocus);
|
|
91
|
+
const modality = getInteractionModality();
|
|
92
|
+
if (initialFocusTarget && initialFocusTarget.isConnected) {
|
|
93
|
+
focusWithModality(initialFocusTarget, modality);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
67
96
|
const focusableElements = getFocusableElements(node);
|
|
68
97
|
if (focusableElements.length > 0) {
|
|
69
|
-
focusableElements[0]
|
|
70
|
-
|
|
71
|
-
else {
|
|
72
|
-
node.focus();
|
|
98
|
+
focusWithModality(focusableElements[0], modality);
|
|
99
|
+
return;
|
|
73
100
|
}
|
|
101
|
+
focusWithModality(node, modality);
|
|
74
102
|
});
|
|
75
103
|
document.addEventListener('keydown', handleKeydown, true);
|
|
76
104
|
}
|
|
77
105
|
function deactivate() {
|
|
78
106
|
document.removeEventListener('keydown', handleKeydown, true);
|
|
79
|
-
if (previousActiveElement && previousActiveElement.focus) {
|
|
107
|
+
if (restoreFocus && previousActiveElement && previousActiveElement.focus) {
|
|
80
108
|
previousActiveElement.focus();
|
|
81
109
|
}
|
|
82
110
|
}
|
|
@@ -84,14 +112,19 @@ export function focusTrap(node, enabled = true) {
|
|
|
84
112
|
activate();
|
|
85
113
|
}
|
|
86
114
|
return {
|
|
87
|
-
update(
|
|
88
|
-
|
|
115
|
+
update(newOptions) {
|
|
116
|
+
const nextEnabled = resolveEnabled(newOptions);
|
|
117
|
+
const nextRestoreFocus = resolveRestoreFocus(newOptions);
|
|
118
|
+
if (nextEnabled && !enabled) {
|
|
89
119
|
activate();
|
|
90
120
|
}
|
|
91
|
-
else if (!
|
|
121
|
+
else if (!nextEnabled && enabled) {
|
|
92
122
|
deactivate();
|
|
93
123
|
}
|
|
94
|
-
|
|
124
|
+
options = newOptions;
|
|
125
|
+
enabled = nextEnabled;
|
|
126
|
+
restoreFocus = nextRestoreFocus;
|
|
127
|
+
initialFocus = typeof newOptions === 'boolean' ? undefined : newOptions.initialFocus;
|
|
95
128
|
},
|
|
96
129
|
destroy() {
|
|
97
130
|
if (enabled) {
|
package/dist/primitives/index.js
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type InputModality = 'keyboard' | 'pointer' | 'virtual';
|
|
2
|
+
export declare function initInputModality(target?: HTMLElement | null): void;
|
|
3
|
+
export declare function trackInteractionModality(event?: Event, target?: HTMLElement | null): void;
|
|
4
|
+
export declare function getInteractionModality(): InputModality;
|
|
5
|
+
export declare function shouldShowFocusVisible(target: HTMLElement | null): boolean;
|
|
6
|
+
export declare function focusWithModality(target: HTMLElement, modality: InputModality, options?: FocusOptions): void;
|
|
7
|
+
export declare function resolveCloseInteractionModality(reason: string, event?: Event): InputModality;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
let currentModality = 'virtual';
|
|
2
|
+
const listenedWindows = new WeakSet();
|
|
3
|
+
let forcedFocusTarget = null;
|
|
4
|
+
let forcedFocusModality = null;
|
|
5
|
+
function isModifierOnlyKey(event) {
|
|
6
|
+
return (event.key === 'Shift' || event.key === 'Control' || event.key === 'Alt' || event.key === 'Meta');
|
|
7
|
+
}
|
|
8
|
+
function isKeyboardModalityKey(event) {
|
|
9
|
+
if (event.ctrlKey || event.metaKey || event.altKey)
|
|
10
|
+
return false;
|
|
11
|
+
if (isModifierOnlyKey(event))
|
|
12
|
+
return false;
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
function ensureWindowListeners(win) {
|
|
16
|
+
if (!win)
|
|
17
|
+
return;
|
|
18
|
+
if (listenedWindows.has(win))
|
|
19
|
+
return;
|
|
20
|
+
const onKeyDown = (event) => {
|
|
21
|
+
if (!isKeyboardModalityKey(event))
|
|
22
|
+
return;
|
|
23
|
+
currentModality = 'keyboard';
|
|
24
|
+
};
|
|
25
|
+
const onPointerDown = () => {
|
|
26
|
+
currentModality = 'pointer';
|
|
27
|
+
};
|
|
28
|
+
const onFocusIn = () => {
|
|
29
|
+
if (currentModality === 'pointer' || currentModality === 'keyboard')
|
|
30
|
+
return;
|
|
31
|
+
currentModality = 'virtual';
|
|
32
|
+
};
|
|
33
|
+
win.addEventListener('keydown', onKeyDown, true);
|
|
34
|
+
win.addEventListener('pointerdown', onPointerDown, true);
|
|
35
|
+
win.addEventListener('mousedown', onPointerDown, true);
|
|
36
|
+
win.addEventListener('focusin', onFocusIn, true);
|
|
37
|
+
listenedWindows.add(win);
|
|
38
|
+
}
|
|
39
|
+
export function initInputModality(target) {
|
|
40
|
+
const ownerWindow = target?.ownerDocument?.defaultView;
|
|
41
|
+
if (ownerWindow) {
|
|
42
|
+
ensureWindowListeners(ownerWindow);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (typeof window !== 'undefined') {
|
|
46
|
+
ensureWindowListeners(window);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function inferModalityFromEvent(event) {
|
|
50
|
+
if (!event)
|
|
51
|
+
return undefined;
|
|
52
|
+
if (event instanceof KeyboardEvent) {
|
|
53
|
+
return isKeyboardModalityKey(event) ? 'keyboard' : undefined;
|
|
54
|
+
}
|
|
55
|
+
if (event instanceof MouseEvent && event.type === 'click' && event.detail === 0) {
|
|
56
|
+
return 'keyboard';
|
|
57
|
+
}
|
|
58
|
+
if (event instanceof PointerEvent || event instanceof MouseEvent) {
|
|
59
|
+
return 'pointer';
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
function resolveModalityForTarget(target) {
|
|
64
|
+
if (target && forcedFocusTarget === target && forcedFocusModality) {
|
|
65
|
+
const modality = forcedFocusModality;
|
|
66
|
+
forcedFocusTarget = null;
|
|
67
|
+
forcedFocusModality = null;
|
|
68
|
+
return modality;
|
|
69
|
+
}
|
|
70
|
+
return currentModality;
|
|
71
|
+
}
|
|
72
|
+
export function trackInteractionModality(event, target) {
|
|
73
|
+
initInputModality(target);
|
|
74
|
+
const inferred = inferModalityFromEvent(event);
|
|
75
|
+
if (inferred) {
|
|
76
|
+
currentModality = inferred;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function getInteractionModality() {
|
|
80
|
+
return currentModality;
|
|
81
|
+
}
|
|
82
|
+
export function shouldShowFocusVisible(target) {
|
|
83
|
+
if (!target)
|
|
84
|
+
return false;
|
|
85
|
+
const modality = resolveModalityForTarget(target);
|
|
86
|
+
if (modality === 'pointer')
|
|
87
|
+
return false;
|
|
88
|
+
return target.matches(':focus-visible');
|
|
89
|
+
}
|
|
90
|
+
export function focusWithModality(target, modality, options) {
|
|
91
|
+
initInputModality(target);
|
|
92
|
+
// The forced target/modality pair is a synchronous safety net so a focus handler that runs
|
|
93
|
+
// immediately after target.focus() can resolve the intended modality without racing async timing.
|
|
94
|
+
// If it is consumed later, currentModality still preserves the same modality as fallback.
|
|
95
|
+
forcedFocusTarget = target;
|
|
96
|
+
forcedFocusModality = modality;
|
|
97
|
+
currentModality = modality;
|
|
98
|
+
if (modality === 'pointer') {
|
|
99
|
+
const pointerFocusOptions = {
|
|
100
|
+
...(options ?? {}),
|
|
101
|
+
focusVisible: false
|
|
102
|
+
};
|
|
103
|
+
target.focus(pointerFocusOptions);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
target.focus(options);
|
|
107
|
+
}
|
|
108
|
+
queueMicrotask(() => {
|
|
109
|
+
if (forcedFocusTarget !== target)
|
|
110
|
+
return;
|
|
111
|
+
forcedFocusTarget = null;
|
|
112
|
+
forcedFocusModality = null;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
export function resolveCloseInteractionModality(reason, event) {
|
|
116
|
+
if (reason === 'escape-key')
|
|
117
|
+
return 'keyboard';
|
|
118
|
+
if (event instanceof KeyboardEvent)
|
|
119
|
+
return 'keyboard';
|
|
120
|
+
if (event instanceof PointerEvent || event instanceof MouseEvent)
|
|
121
|
+
return 'pointer';
|
|
122
|
+
if (reason === 'outside-press')
|
|
123
|
+
return 'pointer';
|
|
124
|
+
return 'virtual';
|
|
125
|
+
}
|
|
@@ -53,6 +53,7 @@ export type KeyboardNavigationReturn = {
|
|
|
53
53
|
focusFirst: () => void;
|
|
54
54
|
focusLast: () => void;
|
|
55
55
|
focusById: (id: string | number) => void;
|
|
56
|
+
setCurrentId: (id: string | number | null) => void;
|
|
56
57
|
/** Update items (call after DOM changes) */
|
|
57
58
|
updateItems: () => void;
|
|
58
59
|
};
|
|
@@ -130,6 +130,22 @@ export function createKeyboardNavigation(options = {}) {
|
|
|
130
130
|
focusItem(element);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
+
function setCurrentId(id) {
|
|
134
|
+
if (id === null) {
|
|
135
|
+
focusedId.set(null);
|
|
136
|
+
focusedElement.set(null);
|
|
137
|
+
onFocusChange?.(null, null);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
items = getItems();
|
|
141
|
+
const element = items.find((el) => {
|
|
142
|
+
const itemId = getItemId(el);
|
|
143
|
+
return itemId === id || String(itemId) === String(id);
|
|
144
|
+
});
|
|
145
|
+
focusedId.set(id);
|
|
146
|
+
focusedElement.set(element ?? null);
|
|
147
|
+
onFocusChange?.(id, element ?? null);
|
|
148
|
+
}
|
|
133
149
|
function handleTypeahead(char) {
|
|
134
150
|
if (!typeahead)
|
|
135
151
|
return;
|
|
@@ -254,6 +270,7 @@ export function createKeyboardNavigation(options = {}) {
|
|
|
254
270
|
focusFirst,
|
|
255
271
|
focusLast,
|
|
256
272
|
focusById,
|
|
273
|
+
setCurrentId,
|
|
257
274
|
updateItems
|
|
258
275
|
};
|
|
259
276
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Table Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Open questions
|
|
4
|
+
|
|
5
|
+
- Disabled body rows are currently rendered and treated with an all-or-nothing disabled model. The planned `disabledBehavior` API (`'selection' | 'all'`) will require splitting focus/action disabling from selection disabling.
|
|
6
|
+
- `Table.Column` is implemented as a logical wrapper and currently assumes the intended child is a single `Table.ColumnHeaderCell`.
|
|
7
|
+
- `Table.Footer` renders semantic table cells but is intentionally excluded from the roving-focus model in v1.
|
|
8
|
+
- Interactive controls nested inside `Table.Cell` are still intentionally out of scope for v1.
|
|
9
|
+
- `pressRow()` is currently selection-oriented. The planned `onRowAction` feature will require a clearer interaction pipeline so pointer click, double click, `Enter`, and `Space` can route to action and selection independently.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Plan: `hiddenColumns` prop for Table.Root
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
|
|
5
|
+
Add a `hiddenColumns` prop to `Table.Root` that accepts an array of column IDs and hides those columns automatically across header, body, and footer — without breaking the positional column↔cell mapping.
|
|
6
|
+
|
|
7
|
+
## Reviewed decisions
|
|
8
|
+
|
|
9
|
+
- Keep **physical column order** for cell-to-column mapping in body/footer rows.
|
|
10
|
+
- Add a separate **visible column model** for aria counts, keyboard navigation, and visible `data-column-index` values.
|
|
11
|
+
- Preserve hidden column widths in state so re-showing a column restores its prior size.
|
|
12
|
+
|
|
13
|
+
## API Design
|
|
14
|
+
|
|
15
|
+
### New props on `Table.Root`
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
hiddenColumns?: string[]; // controlled (bindable)
|
|
19
|
+
defaultHiddenColumns?: string[]; // uncontrolled initial state
|
|
20
|
+
onHiddenColumnsChange?: (ids: string[]) => void;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- `hiddenColumns` is **bindable** (`bind:hiddenColumns`) so consumers can sync external state (e.g. a column-visibility dropdown).
|
|
24
|
+
- Follows the same controlled/uncontrolled pattern as `selectedKeys`, `sortDescriptor`, and `columnWidths`.
|
|
25
|
+
|
|
26
|
+
### Internal context method
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
isColumnHidden(columnId: string): boolean;
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Hiding strategy: `display: none` — not DOM removal
|
|
33
|
+
|
|
34
|
+
Body cells map their column by DOM position (`columnIndex`). Removing a `<Table.Column>` from the DOM with `{#if}` causes body cells to misalign because the index shifts.
|
|
35
|
+
|
|
36
|
+
Using `display: none`:
|
|
37
|
+
|
|
38
|
+
- DOM order is preserved → index mapping never breaks.
|
|
39
|
+
- Users don't need paired `{#if}` guards in both header and every body row.
|
|
40
|
+
- `display: none` on native `<th>`/`<td>` is valid — the table reflows correctly.
|
|
41
|
+
|
|
42
|
+
## Implementation tasks
|
|
43
|
+
|
|
44
|
+
### 1. Context (`table/root/context.ts`)
|
|
45
|
+
|
|
46
|
+
- Add `hiddenColumnsSet: Set<string>` as reactive internal state (derived from the array prop).
|
|
47
|
+
- Expose `isColumnHidden(columnId: string): boolean`.
|
|
48
|
+
- Add `hiddenColumnsVersion` store for efficient reactive invalidation.
|
|
49
|
+
- Update `getColumnCount()` to exclude hidden columns from the navigable count.
|
|
50
|
+
- Update navigable-cells cache (`navigableCellsCache`) to skip cells belonging to hidden columns.
|
|
51
|
+
- Update `getRowsWithCells()` so keyboard navigation sees only visible cells.
|
|
52
|
+
|
|
53
|
+
### 2. Root component (`table/root/table-root.svelte`)
|
|
54
|
+
|
|
55
|
+
- Add props: `hiddenColumns` (bindable), `defaultHiddenColumns`, `onHiddenColumnsChange`.
|
|
56
|
+
- Implement controlled/uncontrolled pattern (identical to `selectedKeys`).
|
|
57
|
+
- Pass `hiddenColumnsSet` into the context.
|
|
58
|
+
|
|
59
|
+
### 3. Column (`table/column/table-column.svelte`)
|
|
60
|
+
|
|
61
|
+
- Read `isColumnHidden(id)` from context.
|
|
62
|
+
- If hidden → propagate hidden state to column context so children can react.
|
|
63
|
+
|
|
64
|
+
### 4. ColumnHeaderCell (`table/column-header-cell/`)
|
|
65
|
+
|
|
66
|
+
- Apply `display: none` when column is hidden.
|
|
67
|
+
- Set `aria-hidden="true"` when hidden.
|
|
68
|
+
- Exclude from tab order.
|
|
69
|
+
|
|
70
|
+
### 5. Cell (`table/cell/table-cell.svelte`)
|
|
71
|
+
|
|
72
|
+
- Resolve column from `columnIndex` (existing behavior).
|
|
73
|
+
- If column is hidden → apply `display: none` and `aria-hidden="true"`.
|
|
74
|
+
- Exclude from tab order and focus navigation.
|
|
75
|
+
|
|
76
|
+
### 6. ColumnResizer (`table/column-resizer/`)
|
|
77
|
+
|
|
78
|
+
- Not navigable or interactive while its column is hidden.
|
|
79
|
+
|
|
80
|
+
### 7. Keyboard navigation
|
|
81
|
+
|
|
82
|
+
- Arrow left/right must skip cells of hidden columns.
|
|
83
|
+
- Home/End must target the first/last **visible** cell.
|
|
84
|
+
- If the currently focused cell becomes hidden, move focus to the nearest visible cell.
|
|
85
|
+
- Ctrl+A is unaffected (operates on rows, not columns).
|
|
86
|
+
|
|
87
|
+
### 8. Sorting and column widths
|
|
88
|
+
|
|
89
|
+
- Sorting a hidden column: keep the descriptor but do not render a visual indicator.
|
|
90
|
+
- Column widths: hidden columns retain their width in the Map but do not affect layout.
|
|
91
|
+
|
|
92
|
+
## Tests
|
|
93
|
+
|
|
94
|
+
### Rendering
|
|
95
|
+
|
|
96
|
+
- Hidden column is not visible in the DOM (`display: none` on header, body, and footer cells).
|
|
97
|
+
- Columns not listed in `hiddenColumns` render normally.
|
|
98
|
+
- Dynamically changing `hiddenColumns` shows/hides columns reactively.
|
|
99
|
+
|
|
100
|
+
### Bindable / controlled
|
|
101
|
+
|
|
102
|
+
- `bind:hiddenColumns` reflects bidirectional changes.
|
|
103
|
+
- `defaultHiddenColumns` applies only on initial mount.
|
|
104
|
+
- `onHiddenColumnsChange` fires when the set changes internally.
|
|
105
|
+
|
|
106
|
+
### Keyboard navigation
|
|
107
|
+
|
|
108
|
+
- Arrow left/right skip cells of hidden columns.
|
|
109
|
+
- Home/End target the first/last visible cell.
|
|
110
|
+
- Tab enters the grid on a visible cell (never a hidden one).
|
|
111
|
+
- Hiding the column of the currently focused cell moves focus to the nearest visible neighbor.
|
|
112
|
+
|
|
113
|
+
### Feature interactions
|
|
114
|
+
|
|
115
|
+
- Selection checkboxes in a hidden column: row selection still works.
|
|
116
|
+
- Sorting by a hidden column does not crash; descriptor is preserved.
|
|
117
|
+
- Column resize: hidden column is not resizable while hidden.
|
|
118
|
+
- `getColumnCount()` returns only visible columns.
|
|
119
|
+
- Empty `hiddenColumns` array has no effect.
|
|
120
|
+
|
|
121
|
+
### Accessibility
|
|
122
|
+
|
|
123
|
+
- Hidden cells carry `aria-hidden="true"` in header, body, and footer.
|
|
124
|
+
- `aria-colcount` on the `<table>` reflects only **visible** columns.
|
|
125
|
+
- `aria-colindex` on visible cells is recalculated excluding hidden columns.
|
|
126
|
+
- Screen readers do not announce hidden columns during navigation.
|
|
127
|
+
|
|
128
|
+
## Files affected
|
|
129
|
+
|
|
130
|
+
| File | Change |
|
|
131
|
+
| ---------------------------------------------------------- | ------------------------------------------ |
|
|
132
|
+
| `table/root/context.ts` | State, methods, caches |
|
|
133
|
+
| `table/root/table-root.svelte` | Props, binding, controlled pattern |
|
|
134
|
+
| `table/column/table-column.svelte` | Propagate hidden state |
|
|
135
|
+
| `table/column-header-cell/table-column-header-cell.svelte` | `display: none`, `aria-hidden` |
|
|
136
|
+
| `table/cell/table-cell.svelte` | `display: none`, `aria-hidden`, skip focus |
|
|
137
|
+
| `table/column-resizer/table-column-resizer.svelte` | Skip interaction when hidden |
|
|
138
|
+
| `table/index.parts.ts` | Type exports if needed |
|
|
139
|
+
| `table/index.ts` | Type exports if needed |
|
|
140
|
+
| `table/root/*.test.ts` | New test cases |
|
|
141
|
+
|
|
142
|
+
## Execution order
|
|
143
|
+
|
|
144
|
+
1. Context — state + methods (foundation)
|
|
145
|
+
2. Root — props + binding (public API → context)
|
|
146
|
+
3. Column + ColumnHeaderCell — hide header
|
|
147
|
+
4. Cell — hide body/footer cells
|
|
148
|
+
5. ColumnResizer — disable interaction
|
|
149
|
+
6. Navigation — update keyboard nav to skip hidden cells
|
|
150
|
+
7. Tests — validate all above
|
|
151
|
+
8. Accessibility — audit aria attributes
|
|
152
|
+
9. Demo page — add visibility toggle to the playground
|