@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
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD010 -->
|
|
2
|
+
|
|
3
|
+
# Table
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
`Table` is a headless interactive table primitive with grid-style keyboard navigation, row selection, explicit sortable header triggers, and a composable part-based API.
|
|
8
|
+
|
|
9
|
+
All public Table part prop types are exported from the table barrel, including `TableRootProps`, `TableColumnProps`, `TableHeaderProps`, `TableBodyProps`, `TableFooterProps`, `TableRowProps`, `TableColumnHeaderCellProps`, `TableSortTriggerProps`, `TableColumnResizerProps`, `TableCellProps`, `TableEmptyStateProps`, `TableCheckboxProps`, and `TableCheckboxIndicatorProps`.
|
|
10
|
+
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
```svelte
|
|
14
|
+
<Table.Root aria-label="Users table">
|
|
15
|
+
<Table.Header>
|
|
16
|
+
<Table.Row>
|
|
17
|
+
<Table.Column id="selection">
|
|
18
|
+
<Table.ColumnHeaderCell>
|
|
19
|
+
<Table.Checkbox>
|
|
20
|
+
<Table.CheckboxIndicator>
|
|
21
|
+
<CheckIcon />
|
|
22
|
+
</Table.CheckboxIndicator>
|
|
23
|
+
</Table.Checkbox>
|
|
24
|
+
</Table.ColumnHeaderCell>
|
|
25
|
+
</Table.Column>
|
|
26
|
+
<Table.Column id="email" isRowHeader>
|
|
27
|
+
<Table.ColumnHeaderCell>Email</Table.ColumnHeaderCell>
|
|
28
|
+
</Table.Column>
|
|
29
|
+
<Table.Column id="group">
|
|
30
|
+
<Table.ColumnHeaderCell>
|
|
31
|
+
<Table.SortTrigger>
|
|
32
|
+
{#snippet children({ sortDirection })}
|
|
33
|
+
<button
|
|
34
|
+
type="button"
|
|
35
|
+
aria-label={`Group sort button. ${sortDirection ?? 'not sorted'}.`}
|
|
36
|
+
>
|
|
37
|
+
Sort group
|
|
38
|
+
</button>
|
|
39
|
+
{/snippet}
|
|
40
|
+
</Table.SortTrigger>
|
|
41
|
+
</Table.ColumnHeaderCell>
|
|
42
|
+
</Table.Column>
|
|
43
|
+
<Table.Column id="size" minWidth={120}>
|
|
44
|
+
<Table.ColumnHeaderCell>
|
|
45
|
+
Size
|
|
46
|
+
<Table.ColumnResizer />
|
|
47
|
+
</Table.ColumnHeaderCell>
|
|
48
|
+
</Table.Column>
|
|
49
|
+
</Table.Row>
|
|
50
|
+
</Table.Header>
|
|
51
|
+
|
|
52
|
+
<Table.Body>
|
|
53
|
+
<Table.Row id="danilo">
|
|
54
|
+
<Table.Cell>
|
|
55
|
+
<Table.Checkbox>
|
|
56
|
+
<Table.CheckboxIndicator>
|
|
57
|
+
<CheckIcon />
|
|
58
|
+
</Table.CheckboxIndicator>
|
|
59
|
+
</Table.Checkbox>
|
|
60
|
+
</Table.Cell>
|
|
61
|
+
<Table.Cell>danilo@example.com</Table.Cell>
|
|
62
|
+
<Table.Cell>Developer</Table.Cell>
|
|
63
|
+
</Table.Row>
|
|
64
|
+
<Table.EmptyState>No users found.</Table.EmptyState>
|
|
65
|
+
</Table.Body>
|
|
66
|
+
|
|
67
|
+
<Table.Footer>
|
|
68
|
+
<Table.Row>
|
|
69
|
+
<Table.Cell />
|
|
70
|
+
<Table.Cell>Total</Table.Cell>
|
|
71
|
+
<Table.Cell>1 user</Table.Cell>
|
|
72
|
+
</Table.Row>
|
|
73
|
+
</Table.Footer>
|
|
74
|
+
</Table.Root>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- `Table.Root`
|
|
78
|
+
- `Table.Column`
|
|
79
|
+
- `Table.Header`
|
|
80
|
+
- `Table.Body`
|
|
81
|
+
- `Table.EmptyState`
|
|
82
|
+
- `Table.Footer`
|
|
83
|
+
- `Table.Row`
|
|
84
|
+
- `Table.ColumnHeaderCell`
|
|
85
|
+
- `Table.SortTrigger`
|
|
86
|
+
- `Table.ColumnResizer`
|
|
87
|
+
- `Table.Checkbox`
|
|
88
|
+
- `Table.CheckboxIndicator`
|
|
89
|
+
- `Table.Cell`
|
|
90
|
+
|
|
91
|
+
## Usage guidelines
|
|
92
|
+
|
|
93
|
+
- Use `Table.Root` as the stateful container for focus, selection, and sorting state.
|
|
94
|
+
- Use `selectionBehavior="toggle"` to allow deselecting an already selected row, or `selectionBehavior="replace"` to keep selected rows selected when pressed again.
|
|
95
|
+
- `Table.Column` is a logical-only wrapper for column metadata; it does not render DOM by itself and should wrap a single `Table.ColumnHeaderCell`.
|
|
96
|
+
- Wrap each header cell in `Table.Column` so the table can register stable column metadata.
|
|
97
|
+
- Add `Table.ColumnResizer` inside `Table.ColumnHeaderCell` to make the owning `Table.Column` resizable.
|
|
98
|
+
- Provide `aria-label` or `aria-labelledby` on `Table.Root`.
|
|
99
|
+
- Use `selectedKeys` / `onSelectionChange` for controlled row selection.
|
|
100
|
+
- Use `defaultSelectedKeys` for uncontrolled initial row selection.
|
|
101
|
+
- Use `sortDescriptor` / `onSortChange` for controlled sorting state.
|
|
102
|
+
- Use `defaultSortDescriptor` for uncontrolled initial sort state.
|
|
103
|
+
- Use `hiddenColumns` for controlled column visibility when consumers need to show or hide columns without changing the table markup.
|
|
104
|
+
- Use `defaultHiddenColumns` for uncontrolled initial column visibility.
|
|
105
|
+
- Use `columnWidths` / `onColumnWidthsChange` for controlled column width state. Width specs can be px, `%`, or `fr`.
|
|
106
|
+
- Use `defaultColumnWidths` and `Table.Column.defaultWidth` to seed uncontrolled initial widths that can still be resized by the user.
|
|
107
|
+
- Use `Table.Column.width` when a column should stay fixed at an explicit width. Fixed-width columns ignore resize attempts even if a `Table.ColumnResizer` is composed.
|
|
108
|
+
- In resizable tables, unspecified columns behave like an implicit `1fr` width before interaction. On the first real resize, visible columns are materialized to px; the trailing column absorbs the delta until its minimum width, and further growth overflows the table horizontally.
|
|
109
|
+
- Setting `sortDescriptor` back to `undefined` clears the controlled sort state, matching React Aria Table semantics.
|
|
110
|
+
- Set `Table.Column.textValue` when the spoken column label should differ from the column id; `Table.Root` uses it for polite sort announcements.
|
|
111
|
+
- Use `Table.EmptyState` inside `Table.Body` instead of conditionally rendering freeform body content.
|
|
112
|
+
- Use `Table.Checkbox` when you need explicit selection UI inside cells instead of relying only on row or cell presses.
|
|
113
|
+
- Use `Table.CheckboxIndicator` to compose your own visual affordance for checked and indeterminate states.
|
|
114
|
+
- `Table.Checkbox` auto-hides in header cells unless `selectionMode="multiple"`, and auto-hides everywhere when `selectionMode="none"`.
|
|
115
|
+
- Hidden columns are excluded from grid navigation, visible column counts, and active resize behavior, but their registered widths are preserved so they can be restored when shown again.
|
|
116
|
+
- Dedicated utility columns like selection checkboxes should usually set an explicit `width`, `minWidth`, and `maxWidth` on `Table.Column` so sibling resizes do not redistribute their space.
|
|
117
|
+
- When `selectionMode` changes to `none`, the component clears any existing row selection internally.
|
|
118
|
+
- v1 leaves text selection and `Ctrl+C` behavior browser-native; the table does not implement custom copy handling or force a text-selection policy.
|
|
119
|
+
- In `replace` mode, clicking outside the table clears focus but does not clear selection.
|
|
120
|
+
- In body rows, pressing `ArrowLeft` before the first cell or `ArrowRight` after the last cell moves focus to the row itself. Repeating that same horizontal arrow loops back into the opposite edge cell of the same row.
|
|
121
|
+
- `Table.Checkbox` is the supported interactive control inside table cells for explicit row selection in v1.
|
|
122
|
+
|
|
123
|
+
## Composition contract
|
|
124
|
+
|
|
125
|
+
- DOM-rendering parts: `Table.Root`, `Table.Header`, `Table.Body`, `Table.Footer`, `Table.Row`, `Table.Cell`, `Table.ColumnHeaderCell`, `Table.ColumnResizer`, `Table.Checkbox`, `Table.CheckboxIndicator`, and `Table.EmptyState` all render DOM.
|
|
126
|
+
- Metadata-only part: `Table.Column` does not render its own element. It only registers the public column input for the surrounding header composition.
|
|
127
|
+
- Sorting: `Table.SortTrigger` is the public opt-in for sortable columns. Rendering it inside `Table.ColumnHeaderCell` makes the owning `Table.Column` sortable and toggles `Table.Root.sortDescriptor`.
|
|
128
|
+
- `Table.SortTrigger.children` can consume a `sortDirection` render state so the nested button can expose stateful labels or visuals without reading the root descriptor directly.
|
|
129
|
+
- Resizing: `Table.ColumnResizer` is the only public opt-in for resizing. Rendering it inside a `Table.ColumnHeaderCell` enables resizing for the owning `Table.Column`.
|
|
130
|
+
- Public input types: import the `Table*Props` types you need from `@human-kit/svelte-components/table` or the main package barrel instead of deriving contracts from component internals.
|
|
131
|
+
- Internal normalized state: table context stores normalized column metadata internally as `TableColumnMetadata`. That metadata is not the public input contract for wrappers or consumers.
|
|
132
|
+
|
|
133
|
+
## Accessibility
|
|
134
|
+
|
|
135
|
+
- `Table.Root` renders an interactive `grid` over native table markup.
|
|
136
|
+
- Keyboard navigation uses roving `tabindex` across header and body cells.
|
|
137
|
+
- Body rows can also become the active focus target when horizontal navigation moves past the start or end of a row, and repeated left/right navigation loops back into the opposite edge cell.
|
|
138
|
+
- `Table.Checkbox` can receive DOM focus directly while still participating in the table's roving-focus grid.
|
|
139
|
+
- First-column body cells become `rowheader` when their associated column has `isRowHeader`.
|
|
140
|
+
- Disabled rows remain rendered and non-selectable, but are skipped by focus navigation.
|
|
141
|
+
- `Table.SortTrigger` wires a nested trigger button, while the header cell remains the roving-focus target for arrow-key grid navigation.
|
|
142
|
+
- Sort changes are mirrored into a polite live region so screen readers announce direction changes more reliably than `aria-sort` alone.
|
|
143
|
+
- Column resize handles are keyboard accessible separators. Press `Enter` to enter resize mode, use the horizontal arrow keys to resize, `Home` to jump to the minimum width, `End` to auto-fit to content width, and press `Enter` again to exit resize mode while keeping focus on the handle.
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD013 MD033 MD056 MD060 -->
|
|
2
|
+
|
|
3
|
+
# Table Selection Checkbox Plan
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Document the intended design for `Table.Checkbox` and `Table.CheckboxIndicator` parts that integrate with the existing table selection model without adding a separate high-level selection API.
|
|
8
|
+
|
|
9
|
+
The component should be composable, predictable, and aligned with the current `Table` architecture:
|
|
10
|
+
|
|
11
|
+
- part-based composition
|
|
12
|
+
- centralized state in `Table.Root`
|
|
13
|
+
- typed context contracts
|
|
14
|
+
- Svelte 5 runes
|
|
15
|
+
- keyboard navigation consistent with the current grid model
|
|
16
|
+
|
|
17
|
+
## Confirmed Decisions
|
|
18
|
+
|
|
19
|
+
- Public names: `Table.Checkbox` and `Table.CheckboxIndicator`
|
|
20
|
+
- Composition model: the consumer places it manually inside `Table.Cell` and `Table.ColumnHeaderCell`
|
|
21
|
+
- Focus target: the checkbox itself, not the table cell
|
|
22
|
+
- Body behavior: toggles the row selection state and reflects it visually
|
|
23
|
+
- Header behavior: acts as select-all / deselect-all only in `selectionMode="multiple"`
|
|
24
|
+
- Header partial state: must support indeterminate state
|
|
25
|
+
- Auto-visibility:
|
|
26
|
+
- when `selectionMode="none"`, all selection checkboxes should disappear
|
|
27
|
+
- when `selectionMode="single"`, body checkboxes stay visible but the header checkbox should disappear
|
|
28
|
+
- The component should own its auto-hide behavior instead of pushing this responsibility to the consumer
|
|
29
|
+
|
|
30
|
+
## Non-Goals
|
|
31
|
+
|
|
32
|
+
- Do not add a separate slot-based table selection API for v1
|
|
33
|
+
- Do not require a dedicated selection column abstraction
|
|
34
|
+
- Do not reuse the generic `Checkbox.Root` implementation blindly if it complicates table focus/navigation integration
|
|
35
|
+
- Do not make row selection depend on clicking the full row when explicit checkbox UI is present
|
|
36
|
+
|
|
37
|
+
## Proposed Public Anatomy
|
|
38
|
+
|
|
39
|
+
```svelte
|
|
40
|
+
<Table.Root selectionMode="multiple" bind:selectedKeys>
|
|
41
|
+
<Table.Header>
|
|
42
|
+
<Table.Row>
|
|
43
|
+
<Table.Column id="selection">
|
|
44
|
+
<Table.ColumnHeaderCell>
|
|
45
|
+
<Table.Checkbox>
|
|
46
|
+
<Table.CheckboxIndicator>
|
|
47
|
+
<CheckIcon />
|
|
48
|
+
</Table.CheckboxIndicator>
|
|
49
|
+
</Table.Checkbox>
|
|
50
|
+
</Table.ColumnHeaderCell>
|
|
51
|
+
</Table.Column>
|
|
52
|
+
|
|
53
|
+
<Table.Column id="email" isRowHeader>
|
|
54
|
+
<Table.ColumnHeaderCell>Email</Table.ColumnHeaderCell>
|
|
55
|
+
</Table.Column>
|
|
56
|
+
</Table.Row>
|
|
57
|
+
</Table.Header>
|
|
58
|
+
|
|
59
|
+
<Table.Body>
|
|
60
|
+
{#each rows as row (row.id)}
|
|
61
|
+
<Table.Row id={row.id}>
|
|
62
|
+
<Table.Cell>
|
|
63
|
+
<Table.Checkbox>
|
|
64
|
+
<Table.CheckboxIndicator>
|
|
65
|
+
<CheckIcon />
|
|
66
|
+
</Table.CheckboxIndicator>
|
|
67
|
+
</Table.Checkbox>
|
|
68
|
+
</Table.Cell>
|
|
69
|
+
<Table.Cell>{row.email}</Table.Cell>
|
|
70
|
+
</Table.Row>
|
|
71
|
+
{/each}
|
|
72
|
+
</Table.Body>
|
|
73
|
+
</Table.Root>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Why This Shape
|
|
77
|
+
|
|
78
|
+
- It preserves the existing `Table` mental model: columns, header cells, body cells, footer cells.
|
|
79
|
+
- It avoids a parallel API such as `selection` slots or special root props that would only exist for one specific control.
|
|
80
|
+
- It keeps selection UI opt-in and composable.
|
|
81
|
+
- It allows consumers to position the checkbox column exactly where they need it.
|
|
82
|
+
|
|
83
|
+
## Section-Based Behavior
|
|
84
|
+
|
|
85
|
+
The component behavior depends on where it is rendered.
|
|
86
|
+
|
|
87
|
+
| Location | `selectionMode="none"` | `selectionMode="single"` | `selectionMode="multiple"` |
|
|
88
|
+
| ------------------------ | ---------------------- | ------------------------ | ---------------------------- |
|
|
89
|
+
| `Table.ColumnHeaderCell` | hidden | hidden | visible, select-all checkbox |
|
|
90
|
+
| `Table.Cell` in body row | hidden | visible, row toggle | visible, row toggle |
|
|
91
|
+
| footer cell | hidden | hidden | hidden |
|
|
92
|
+
|
|
93
|
+
## Behavior Details
|
|
94
|
+
|
|
95
|
+
### Body Checkbox
|
|
96
|
+
|
|
97
|
+
- Renders only inside body rows when `selectionMode` is not `none`
|
|
98
|
+
- Checked state mirrors whether the current row is selected
|
|
99
|
+
- Disabled state mirrors whether the current row is disabled
|
|
100
|
+
- Clicking it toggles the row through the same selection pipeline used by the table
|
|
101
|
+
- Keyboard interaction should behave like a table navigation target, not like an isolated form field
|
|
102
|
+
|
|
103
|
+
### Header Checkbox
|
|
104
|
+
|
|
105
|
+
- Renders only inside header cells when `selectionMode="multiple"`
|
|
106
|
+
- Checked when all selectable rows are selected
|
|
107
|
+
- Indeterminate when some selectable rows are selected but not all
|
|
108
|
+
- Unchecked when no selectable rows are selected
|
|
109
|
+
- Clicking it selects all selectable rows or clears the current selection
|
|
110
|
+
- Disabled when there are no selectable rows
|
|
111
|
+
|
|
112
|
+
## Focus Model
|
|
113
|
+
|
|
114
|
+
The current table uses a roving tabindex model on cells. For `Table.Checkbox`, the desired behavior is different:
|
|
115
|
+
|
|
116
|
+
- the checkbox should receive DOM focus directly
|
|
117
|
+
- the table should still treat that checkbox as the focus target for the parent cell's grid position
|
|
118
|
+
- arrow-key navigation must continue to work from the checkbox
|
|
119
|
+
|
|
120
|
+
This implies a focus-delegation mechanism from `Table.Cell` to a child control.
|
|
121
|
+
|
|
122
|
+
### Proposed Focus Delegation
|
|
123
|
+
|
|
124
|
+
- `Table.Cell` keeps owning the grid key and participation in layout/focus bookkeeping
|
|
125
|
+
- a child control can register itself as the focus delegate for that cell
|
|
126
|
+
- when the table moves focus to that cell, the registered delegate receives DOM focus
|
|
127
|
+
- when the delegate receives focus, it synchronizes the table's focused-cell state
|
|
128
|
+
|
|
129
|
+
This is preferable to making the checkbox a completely separate navigable entity because it preserves the current grid architecture.
|
|
130
|
+
|
|
131
|
+
## Keyboard Expectations
|
|
132
|
+
|
|
133
|
+
When a `Table.Checkbox` is focused:
|
|
134
|
+
|
|
135
|
+
- `Space` toggles selection
|
|
136
|
+
- `Enter` toggles selection
|
|
137
|
+
- `ArrowUp` / `ArrowDown` move within the table grid
|
|
138
|
+
- `ArrowLeft` / `ArrowRight` move within the table grid
|
|
139
|
+
- `Home` / `End` move to row boundaries
|
|
140
|
+
- `Ctrl/Cmd + Home` and `Ctrl/Cmd + End` use the existing table-wide navigation behavior
|
|
141
|
+
- `Ctrl/Cmd + A` keeps the current multiple-selection behavior
|
|
142
|
+
|
|
143
|
+
The checkbox should not become a keyboard dead-end inside the table.
|
|
144
|
+
|
|
145
|
+
## State Requirements in `TableContext`
|
|
146
|
+
|
|
147
|
+
To support the header checkbox cleanly, the table context should expose a small amount of additional selection state:
|
|
148
|
+
|
|
149
|
+
- a way to determine whether all selectable rows are selected
|
|
150
|
+
- a way to determine whether some selectable rows are selected
|
|
151
|
+
- a way to clear the current selection without changing `selectionMode`
|
|
152
|
+
|
|
153
|
+
One reasonable shape is:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
type TableSelectionCheckboxState = 'none' | 'some' | 'all';
|
|
157
|
+
|
|
158
|
+
getSelectionCheckboxState(): TableSelectionCheckboxState;
|
|
159
|
+
deselectAllRows(): void;
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
This should build on the existing ordered selectable row computation rather than duplicating selection rules in the component.
|
|
163
|
+
|
|
164
|
+
## Accessibility Expectations
|
|
165
|
+
|
|
166
|
+
- The checkbox should expose `role="checkbox"`
|
|
167
|
+
- `aria-checked` should be:
|
|
168
|
+
- `"true"` when checked
|
|
169
|
+
- `"false"` when unchecked
|
|
170
|
+
- `"mixed"` when indeterminate
|
|
171
|
+
- Disabled state should map to `aria-disabled`
|
|
172
|
+
- The header checkbox should have an accessible label like `Select all rows`
|
|
173
|
+
- Row checkboxes should have an accessible label like `Select row` or a consumer-provided label if the row content needs more specificity
|
|
174
|
+
|
|
175
|
+
## Rendering Strategy
|
|
176
|
+
|
|
177
|
+
The component does not need to be a full form checkbox.
|
|
178
|
+
|
|
179
|
+
Because this control is tightly coupled to the table's grid navigation and selection logic, a lightweight table-specific implementation is likely more appropriate than directly wrapping the generic checkbox component. The generic checkbox has different responsibilities, including form integration, that are not required here.
|
|
180
|
+
|
|
181
|
+
## Open Questions
|
|
182
|
+
|
|
183
|
+
### Structural Validation
|
|
184
|
+
|
|
185
|
+
If consumers place `Table.Checkbox` manually, it becomes easier to create invalid layouts accidentally.
|
|
186
|
+
|
|
187
|
+
Examples:
|
|
188
|
+
|
|
189
|
+
- header includes a selection checkbox column but body rows do not
|
|
190
|
+
- some rows render fewer cells than others
|
|
191
|
+
- the checkbox is placed in a footer cell where it has no behavior
|
|
192
|
+
|
|
193
|
+
We should consider adding dev-time validation for mismatched column/cell counts and possibly invalid placement.
|
|
194
|
+
|
|
195
|
+
### Labeling API
|
|
196
|
+
|
|
197
|
+
The initial implementation can ship with sensible default labels, but we may want to support explicit labels later for highly customized row content.
|
|
198
|
+
|
|
199
|
+
### Generic Focus Delegates
|
|
200
|
+
|
|
201
|
+
If focus delegation is added for this part, it should be designed as a reusable mechanism rather than a one-off checkbox hack.
|
|
202
|
+
|
|
203
|
+
## Implementation Outline
|
|
204
|
+
|
|
205
|
+
### Phase 1: Context and Focus Plumbing
|
|
206
|
+
|
|
207
|
+
- extend table selection helpers for header checkbox state
|
|
208
|
+
- add `deselectAllRows()`
|
|
209
|
+
- add focus delegation support from cells to nested controls
|
|
210
|
+
|
|
211
|
+
### Phase 2: New Part
|
|
212
|
+
|
|
213
|
+
- add `packages/svelte/src/lib/table/selection-checkbox/`
|
|
214
|
+
- implement `table-selection-checkbox.svelte`
|
|
215
|
+
- export it from `index.parts.ts` and `index.ts`
|
|
216
|
+
|
|
217
|
+
### Phase 3: Tests
|
|
218
|
+
|
|
219
|
+
- body checkbox renders and toggles correctly
|
|
220
|
+
- header checkbox auto-hides correctly by selection mode
|
|
221
|
+
- header checkbox supports checked / mixed / unchecked states
|
|
222
|
+
- disabled rows stay disabled
|
|
223
|
+
- focus lands on the checkbox instead of the parent cell
|
|
224
|
+
- arrow navigation still works when the checkbox has focus
|
|
225
|
+
|
|
226
|
+
### Phase 4: Documentation and Demo
|
|
227
|
+
|
|
228
|
+
- add part README if the part becomes public
|
|
229
|
+
- update table README anatomy
|
|
230
|
+
- update the docs demo with a selection checkbox column
|
|
231
|
+
|
|
232
|
+
## Summary
|
|
233
|
+
|
|
234
|
+
`Table.Checkbox` should be a small, composable part that plugs into the existing table selection model rather than a new selection subsystem. `Table.CheckboxIndicator` keeps the visuals fully consumer-controlled. The key implementation challenge is not checkbox visuals, but integrating direct checkbox focus with the table's current roving-focus grid behavior.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Table TODO
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Ship a stable `Table` v1 with keyboard navigation, row selection, sorting, documentation, and reliable accessibility semantics.
|
|
6
|
+
|
|
7
|
+
## Backlog
|
|
8
|
+
|
|
9
|
+
### Bugs / Correctness
|
|
10
|
+
|
|
11
|
+
- [x] [M][P0][Area: Correctness][Owner: Unassigned][Target: Done] Deduplicate sync registration calls — `syncXxxRegistration()` runs both synchronously at mount and inside `$effect`, causing a redundant `notifyLayout()` per part on initial render (Column, Row, Cell, ColumnHeaderCell).
|
|
12
|
+
- [x] [S][P0][Area: Correctness][Owner: Unassigned][Target: Done] Make `cellIndex` in `Table.Cell` reactive — currently captured once via `row.registerCellToken(key)` and never updated if cells are dynamically reordered within a row.
|
|
13
|
+
- [x] [C][P1][Area: Correctness][Owner: Unassigned][Target: Done] Replace module-level monotonic counters (`columnInstanceId`, `rowInstanceId`, etc.) with per-`Table.Root` token generation so SSR and repeated tests do not share global instance state.
|
|
14
|
+
|
|
15
|
+
### Behavior
|
|
16
|
+
|
|
17
|
+
- [x] [M][P1][Area: Behavior][Owner: Unassigned][Target: Done] Align row focus state semantics — current row-level `data-focused` behaves more like `focus-within`; either rename/expose a distinct `data-focus-within` contract or implement true row focus semantics.
|
|
18
|
+
- [x] [M][P1][Area: Behavior][Owner: Unassigned][Target: Done] Define and document the text-selection policy when row selection is enabled — keep browser-native behavior or add an explicit opt-in/opt-out API instead of ad hoc styling in examples.
|
|
19
|
+
- [x] [S][P2][Area: Behavior][Owner: Unassigned][Target: Done] Verify that changing `selectionMode` between `multiple`, `single`, and `none` preserves the intended normalization rules in all controlled and uncontrolled flows.
|
|
20
|
+
- [x] [M][P0][Area: Behavior][Owner: Unassigned][Target: Done] Make `Table.ColumnResizer` keyboard interactions run the same resize lifecycle as pointer interactions so width freezing and resize callbacks stay consistent.
|
|
21
|
+
- [x] [M][P1][Area: Behavior][Owner: Unassigned][Target: Done] Allow cancelling an in-progress `Table.ColumnResizer` drag with `Escape`, restoring the starting width instead of forcing the partial drag result.
|
|
22
|
+
|
|
23
|
+
### Accessibility
|
|
24
|
+
|
|
25
|
+
- [x] [M][P1][Area: Accessibility][Owner: Unassigned][Target: Done] Enforce accessible name on `Table.Root` — warn in dev when neither `aria-label` nor `aria-labelledby` is provided (WCAG 4.1.2).
|
|
26
|
+
- [x] [M][P1][Area: Accessibility][Owner: Unassigned][Target: Done] Add `aria-disabled` to focusable body cells inside disabled rows — currently only the `<tr>` carries `aria-disabled`, leaving screen readers unaware at the cell level.
|
|
27
|
+
- [x] [M][P0][Area: Accessibility][Owner: Unassigned][Target: Done] Announce committed `Table.ColumnResizer` width changes through a polite live region and expose `aria-valuetext` so keyboard resizing has reliable screen reader feedback.
|
|
28
|
+
- [x] [M][P0][Area: Accessibility][Owner: Unassigned][Target: Done] Move `Table.ColumnResizer` drag handling to Pointer Events so touch, pen, and mouse resizing use the same path.
|
|
29
|
+
- [x] [S][P1][Area: Accessibility][Owner: Unassigned][Target: Done] Make `Table.ColumnResizer` keyboard arrow semantics respect RTL layouts so logical resize controls match the visual direction.
|
|
30
|
+
- [ ] [M][P1][Area: Accessibility][Owner: Unassigned][Target: TBD] Validate screen reader announcements for `rowheader`, `columnheader`, and `aria-sort` across NVDA and VoiceOver.
|
|
31
|
+
- [x] [M][P1][Area: Accessibility][Owner: Unassigned][Target: Done] Resolve footer grid semantics — footer cells live inside `role="grid"` but are unreachable by keyboard; either include footer in navigation or mark `<tfoot>` with `role="none"` to exclude it from the grid.
|
|
32
|
+
- [x] [S][P2][Area: Accessibility][Owner: Unassigned][Target: Done] Add `aria-rowcount` and `aria-colcount` to the grid element for screen reader dimension announcements.
|
|
33
|
+
- [x] [S][P2][Area: Accessibility][Owner: Unassigned][Target: Done] Add an `aria-live="polite"` visually-hidden region to announce sort changes (NVDA/JAWS do not always announce `aria-sort` updates).
|
|
34
|
+
- [x] [S][P2][Area: Accessibility][Owner: Unassigned][Target: Done] Add explicit `role="row"` to the `Table.EmptyState` `<tr>` for strict ARIA parent-child validation (`gridcell` requires `row` parent).
|
|
35
|
+
|
|
36
|
+
### Performance
|
|
37
|
+
|
|
38
|
+
- [x] [M][P1][Area: Performance][Owner: Unassigned][Target: Done] Cache `getOrderedRowTokens` result and invalidate on `notifyLayout` — currently re-sorts with `compareDocumentPosition` on every focus move, selection, and row count query.
|
|
39
|
+
- [x] [M][P1][Area: Performance][Owner: Unassigned][Target: Done] Replace repeated linear column-id scans in table resize helpers with an O(1) id-to-token lookup inside `Table.Root` context.
|
|
40
|
+
- [x] [S][P1][Area: Performance][Owner: Unassigned][Target: Done] Batch `Table.ColumnResizer` pointer drag updates with `requestAnimationFrame` so width writes and store updates stay aligned to paint frames.
|
|
41
|
+
- [x] [M][P2][Area: Performance][Owner: Unassigned][Target: Done] Cache `getNavigableCells()` / `getRowsWithCells()` and invalidate on layout changes — currently reconstructs full cell map on every `moveFocus` call.
|
|
42
|
+
- [ ] [S][P2][Area: Performance][Owner: Unassigned][Target: TBD] Migrate version stores from `writable` (svelte/store) to `$state` runes for idiomatic Svelte 5 reactivity and potential batching improvements.
|
|
43
|
+
|
|
44
|
+
### DX
|
|
45
|
+
|
|
46
|
+
- [x] [M][P1][Area: DX][Owner: Unassigned][Target: Done] Break the controlled `selectedKeys` feedback loop — the `$effect` that syncs `selectedKeys` to `ctx.setSelection` also fires after internal selection changes via `onSelectionChange`, causing a redundant `notifySelection`.
|
|
47
|
+
- [x] [S][P2][Area: DX][Owner: Unassigned][Target: Done] Remove inline `style="outline: none;"` from Cell and ColumnHeaderCell — it overrides consumer inline styles; let consumers handle focus-visible styling via `data-focus-visible` / `data-focused` attributes instead.
|
|
48
|
+
- [x] [S][P2][Area: DX][Owner: Unassigned][Target: Done] Document `defaultSelectedKeys` and `defaultSortDescriptor` props in the README and docs page.
|
|
49
|
+
- [x] [C][P2][Area: DX][Owner: Unassigned][Target: Done] Export component prop types (`TableRootProps`, `TableRowProps`, `TableCellProps`, etc.) so consumers can type wrapper components.
|
|
50
|
+
- [ ] [C][P2][Area: DX][Owner: Unassigned][Target: TBD] Evaluate whether exposing `context` as a `$bindable` prop on `Table.Root` is necessary or if a narrower public API would be safer.
|
|
51
|
+
- [ ] [C][P3][Area: DX][Owner: Unassigned][Target: TBD] Extract a shared registration helper to eliminate the duplicated sync-then-effect pattern across Column, Row, Cell, and ColumnHeaderCell.
|
|
52
|
+
|
|
53
|
+
### UX
|
|
54
|
+
|
|
55
|
+
- [x] [S][P2][Area: UX][Owner: Unassigned][Target: Done] Document the intentional behavior that clicking outside the table does not clear selection in `replace` mode.
|
|
56
|
+
- [ ] [C][P3][Area: UX][Owner: Unassigned][Target: TBD] Consider exposing `cursor` guidance via data attributes so sortable headers get `cursor: pointer` and non-sortable headers get `cursor: default` without custom CSS.
|
|
57
|
+
|
|
58
|
+
### API Design
|
|
59
|
+
|
|
60
|
+
- [x] [M][P1][Area: API][Owner: Unassigned][Target: Done] Decide whether controlled clearing of `sortDescriptor` should accept `undefined` explicitly or require an additional API.
|
|
61
|
+
- [x] [S][P2][Area: Behavior][Owner: Unassigned][Target: Done] Confirm whether disabled body rows should remain keyboard-focusable or be skipped by navigation.
|
|
62
|
+
- [ ] [S][P2][Area: API][Owner: Unassigned][Target: TBD] Decide whether `Table.Column` should hard-enforce a single `Table.ColumnHeaderCell` child.
|
|
63
|
+
- [ ] [S][P2][Area: API][Owner: Unassigned][Target: TBD] Decide whether clipboard-related behavior should remain fully browser-native in v1 or be deferred behind a future explicit cell-selection model.
|
|
64
|
+
- [x] [C][P1][Area: API][Owner: Unassigned][Target: Done] Add `onRowAction?: (id: TableSelectionKey) => void` to `Table.Root` and document its collection-level semantics across `selectionMode` and `selectionBehavior`.
|
|
65
|
+
- [x] [C][P1][Area: API][Owner: Unassigned][Target: Done] Add `disabledBehavior?: 'selection' | 'all'` to `Table.Root` with default `'all'`, and document that `'selection'` disables selection while preserving focus and row actions.
|
|
66
|
+
- [x] [S][P1][Area: API][Owner: Unassigned][Target: Done] Treat stable `selectionBehavior?: 'toggle' | 'replace'` support in `Table.Root` as an explicit prerequisite for the row-actions phase rather than an implicit assumption.
|
|
67
|
+
|
|
68
|
+
### Features
|
|
69
|
+
|
|
70
|
+
- [ ] [C][P1][Area: Features][Owner: Unassigned][Target: TBD] Add controlled and uncontrolled column filtering APIs — support per-column filters plus a global filter hook so `Table` can cover common data-grid scenarios without forcing consumers to build parallel filter state from scratch.
|
|
71
|
+
- [ ] [C][P1][Area: Features][Owner: Unassigned][Target: TBD] Add column visibility controls — allow columns to be shown/hidden dynamically while preserving keyboard navigation, sort state, selection column layout, and resize state for still-visible columns.
|
|
72
|
+
- [ ] [C][P1][Area: Features][Owner: Unassigned][Target: TBD] Add multi-column sorting — support ordered sort descriptors so users can compose secondary and tertiary sorts instead of being limited to a single active sort key.
|
|
73
|
+
- [ ] [C][P1][Area: Features][Owner: Unassigned][Target: TBD] Add pagination primitives — define a controlled pagination model for large datasets, including page index, page size, and total row count integration without coupling `Table` to a specific data-fetching strategy.
|
|
74
|
+
- [ ] [C][P1][Area: Features][Owner: Unassigned][Target: TBD] Evaluate row virtualization support — provide a path for very large tables while preserving grid semantics, roving tabindex behavior, selection, and resize interactions.
|
|
75
|
+
- [ ] [C][P2][Area: Features][Owner: Unassigned][Target: TBD] Add sticky header and pinned-column support — enable frozen headers and utility columns (selection, row headers, actions) for wide or scroll-heavy tables.
|
|
76
|
+
- [ ] [C][P2][Area: Features][Owner: Unassigned][Target: TBD] Add expandable rows / subrows — support master-detail rows and tree-like disclosure patterns without forcing consumers to break the table's row and cell registration model.
|
|
77
|
+
- [ ] [C][P2][Area: Features][Owner: Unassigned][Target: TBD] Add inline cell and row editing primitives — define an opt-in editing model that can coexist with current focus, selection, and keyboard navigation contracts.
|
|
78
|
+
- [ ] [M][P2][Area: Features][Owner: Unassigned][Target: TBD] Add column action primitives — expose a path for header menus, quick sort/filter actions, and future column management UI without requiring consumers to hand-roll header action composition every time.
|
|
79
|
+
- [ ] [M][P3][Area: Features][Owner: Unassigned][Target: TBD] Add row actions patterns — document or expose a composable pattern for common trailing actions columns so selection, row press, and nested interactive controls do not conflict.
|
|
80
|
+
- [x] [C][P1][Area: Features][Owner: Unassigned][Target: Done] Implement collection-level row actions in `Table.Root` so body rows can trigger `onRowAction` using RAC-style interaction rules without introducing a separate `rowPressBehavior` prop.
|
|
81
|
+
|
|
82
|
+
### Tests
|
|
83
|
+
|
|
84
|
+
- [x] [M][P1][Area: Tests][Owner: Unassigned][Target: Done] Add tests for `Home`, `End`, `Ctrl+Home`, and `Ctrl+End` keyboard navigation.
|
|
85
|
+
- [x] [S][P2][Area: Tests][Owner: Unassigned][Target: Done] Add test for full sort cycle via keyboard (ascending → descending) and verify no way to clear sort with keyboard is intentional.
|
|
86
|
+
- [x] [S][P2][Area: Tests][Owner: Unassigned][Target: Done] Add test verifying disabled rows are not selected when arrow-navigated in `replace` mode.
|
|
87
|
+
- [x] [S][P2][Area: Tests][Owner: Unassigned][Target: Done] Add tests covering `selectionMode` transitions after mount, including collapsing multiple selections to one on `single`.
|
|
88
|
+
- [x] [C][P1][Area: Tests][Owner: Unassigned][Target: Done] Add the full row action matrix to `Table.Root` tests: click/action in `selectionMode="none"`, toggle-mode action when selection is empty, toggle-mode selection when selection is active, and replace-mode double-click actions.
|
|
89
|
+
- [x] [M][P1][Area: Tests][Owner: Unassigned][Target: Done] Add keyboard interaction tests proving `Enter` triggers `onRowAction` and `Space` triggers selection when both behaviors are available.
|
|
90
|
+
- [x] [M][P1][Area: Tests][Owner: Unassigned][Target: Done] Add `disabledBehavior` regression tests covering `'selection'` vs `'all'` for row focusability, checkbox disabled state, row action availability, and selection blocking.
|
|
91
|
+
- [x] [S][P1][Area: Tests][Owner: Unassigned][Target: Done] Add an explicit edge-case test proving a disabled row under `disabledBehavior="selection"` still fires `onRowAction` on `Enter` while remaining non-selectable.
|
|
92
|
+
- [x] [S][P1][Area: Tests][Owner: Unassigned][Target: Done] Add a callback-ordering test proving `selectionBehavior="replace"` double click fires `onSelectionChange` before `onRowAction`.
|
|
93
|
+
|
|
94
|
+
### Docs
|
|
95
|
+
|
|
96
|
+
- [ ] [C][P2][Area: Docs][Owner: Unassigned][Target: TBD] Add richer styling examples and sorting guidance to the docs page.
|
|
97
|
+
- [x] [C][P3][Area: Docs][Owner: Unassigned][Target: Done] Document that `Table.Column` is a logical-only wrapper (no DOM output) prominently in the README anatomy section.
|
|
98
|
+
- [x] [S][P2][Area: Docs][Owner: Unassigned][Target: Done] Document `selectionMode="none"` normalization behavior and clarify that selection is cleared internally when selection is disabled.
|
|
99
|
+
- [ ] [C][P1][Area: Docs][Owner: Unassigned][Target: TBD] Document row actions vs row selection in the Table README and docs page, including the different pointer rules for `toggle` and `replace` when `onRowAction` is provided.
|
|
100
|
+
- [ ] [M][P1][Area: Docs][Owner: Unassigned][Target: TBD] Document `disabledBehavior="selection"` and clarify that it disables selection only, not row actions or focus.
|
|
101
|
+
- [ ] [S][P1][Area: Docs][Owner: Unassigned][Target: TBD] Call out explicitly that `toggle` mode changes row-click behavior dynamically once an active selection exists, and treat this as an intentional RAC-style model rather than an accidental inconsistency.
|
|
102
|
+
- [ ] [S][P1][Area: Docs][Owner: Unassigned][Target: TBD] Document callback ordering for `replace`-mode double click: `onSelectionChange` fires before `onRowAction`.
|
|
103
|
+
|
|
104
|
+
### Selection Checkbox
|
|
105
|
+
|
|
106
|
+
- [ ] [M][P1][Area: Performance][Owner: Unassigned][Target: TBD] Cache `getOrderedSelectableRowIds()` and invalidate on layout/selection changes — currently rebuilds the full selectable-row array on every call to `getSelectionCheckboxState()`, `hasSelectableRows()`, `selectAllRows()`, and `extendSelectionToRow()`, causing O(n) work per selection change.
|
|
107
|
+
- [ ] [M][P1][Area: Accessibility][Owner: Unassigned][Target: TBD] Validate `Table.Checkbox` screen reader announcements across NVDA and VoiceOver — verify that `aria-checked="mixed"` transitions in the header checkbox and row selection toggles are announced correctly.
|
|
108
|
+
- [ ] [M][P1][Area: Correctness][Owner: Unassigned][Target: TBD] Document or resolve `Table.Checkbox` bypass of `pressRow()` — the checkbox always calls `toggleRowSelection()` directly, ignoring `selectionBehavior="replace"` semantics (Shift+click range, Ctrl+click toggle). This is intentional for checkbox UX but undocumented and inconsistent with row-click behavior.
|
|
109
|
+
- [ ] [M][P1][Area: Correctness][Owner: Unassigned][Target: TBD] Add dev-time structural validation for `Table.Checkbox` placement — warn when header includes a selection checkbox column but body rows do not, or when the checkbox is placed in a footer cell where it has no behavior.
|
|
110
|
+
- [x] [M][P1][Area: Correctness][Owner: Unassigned][Target: Done] Ensure `Table.Checkbox` respects `disabledBehavior="selection"` by disabling explicit selection controls without suppressing row actions on the rest of the row.
|
|
111
|
+
|
|
112
|
+
### Row Actions
|
|
113
|
+
|
|
114
|
+
- [x] [C][P1][Area: Correctness][Owner: Unassigned][Target: Done] Refactor the current `pressRow()` pipeline so selection and row actions are distinct internal pathways rather than a single selection-oriented press abstraction.
|
|
115
|
+
- [x] [C][P1][Area: Correctness][Owner: Unassigned][Target: Done] Split row disabled-state helpers into selection-disabled vs action-disabled semantics so `disabledBehavior="selection"` does not incorrectly suppress focus or actions.
|
|
116
|
+
- [x] [M][P1][Area: Behavior][Owner: Unassigned][Target: Done] Preserve existing `replace`-mode selection extension (`Shift+Arrow`, `Ctrl/Cmd+Space`, click replace) while layering `onRowAction` on top.
|
|
117
|
+
- [x] [M][P1][Area: Accessibility][Owner: Unassigned][Target: Done] Revisit `aria-disabled` semantics for rows under `disabledBehavior="selection"` so actionable rows are not announced as fully disabled.
|
|
118
|
+
- [x] [M][P1][Area: DX][Owner: Unassigned][Target: Done] Evaluate whether row/cell data attributes should expose actionable and selection-disabled states for styling and debugging once `onRowAction` ships.
|
|
119
|
+
- [x] [S][P1][Area: DX][Owner: Unassigned][Target: Done] Make `data-actionable` part of the required styling contract for actionable rows so consumers can reliably style cursor and affordances.
|
|
120
|
+
|
|
121
|
+
### Code Quality
|
|
122
|
+
|
|
123
|
+
- [x] [C][P3][Area: Code Quality][Owner: Unassigned][Target: Done] Remove unused keyboard/click handlers from `Table.Cell` when rendering in footer scope — currently handlers are bound but short-circuit via guards.
|
|
124
|
+
- [x] [M][P2][Area: Code Quality][Owner: Unassigned][Target: Done] Extract shared keyboard handler between `Table.Row` and `Table.Cell` — both components duplicate ~60 lines of nearly identical `handleKeyDown` logic (ArrowUp/Down/Left/Right, Home/End, Ctrl+Home/End, Ctrl+A, Enter, Space) with only minor differences in Home/End targets.
|
|
125
|
+
- [x] [S][P2][Area: Code Quality][Owner: Unassigned][Target: Done] Add a defensive `isRowDisabled` guard inside `pressRow()` in context — currently callers (Row, Cell) check disabled state before calling, but `pressRow` itself does not validate, so a direct call bypasses the check.
|
|
126
|
+
|
|
127
|
+
### Bugs / Phase 3
|
|
128
|
+
|
|
129
|
+
- [x] [M][P1][Area: Correctness][Owner: Unassigned][Target: Done] Fix `keyboard-space` ignoring interaction modifiers in `pressRow()` — the `keyboard-space` branch calls `toggleRowSelection(id)` directly, discarding `shiftKey`/`ctrlKey`/`metaKey`. This breaks `Shift+Space` (should extend selection) and `Ctrl+Space` semantics in `replace` + `multiple` mode. Should route through `pressRowSelection(id, interaction)` instead.
|
|
130
|
+
|
|
131
|
+
### Accessibility / Phase 3
|
|
132
|
+
|
|
133
|
+
- [x] [S][P2][Area: Accessibility][Owner: Unassigned][Target: Done] Clarify ARIA semantics for rows under `disabledBehavior="selection"` without a checkbox — a selection-disabled but actionable row has no `aria-disabled` (correct) but also no ARIA hint that selection is unavailable; the checkbox disabled state announces it, but rows without a checkbox column have no signal for assistive technology.
|
|
134
|
+
|
|
135
|
+
### Performance / Phase 3
|
|
136
|
+
|
|
137
|
+
- [x] [S][P2][Area: Performance][Owner: Unassigned][Target: Done] Use O(1) id-to-token lookup in `isColumnSortable()` — currently iterates all columns with `Array.from(columns.values()).some(...)` instead of using `getColumnRegistrationById(columnId)?.allowsSorting`.
|
|
138
|
+
- [x] [S][P2][Area: Performance][Owner: Unassigned][Target: Done] Cache `getVisibleColumnWidths()` result — it filters `getColumnWidths()` on every call but is used in the render path of `Table.Root` for `managedTableWidth` derivation; should share a cache invalidated alongside `columnWidthsCache`.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- markdownlint-disable MD024 -->
|
|
2
|
+
|
|
3
|
+
# Table.Body
|
|
4
|
+
|
|
5
|
+
## API reference
|
|
6
|
+
|
|
7
|
+
### Table.Body
|
|
8
|
+
|
|
9
|
+
Name: `Table.Body`
|
|
10
|
+
Description: Body rowgroup for table data rows. It can render authored rows directly, or render item-driven rows with optional fixed-height virtualization. It also exposes empty-state markers when no logical body rows are available.
|
|
11
|
+
|
|
12
|
+
Public prop type: `TableBodyProps`
|
|
13
|
+
|
|
14
|
+
| Prop | Type | Default | Description |
|
|
15
|
+
| ------------- | --------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
16
|
+
| `items` | `readonly T[]` | `undefined` | Logical row collection for item-driven mode. When present, `children(item)` renders once per item with `item` inferred from `items`. |
|
|
17
|
+
| `virtualizer` | `TableBodyVirtualizer` | `undefined` | Optional fixed-height row virtualization config with `rowHeight` and `overscan`. |
|
|
18
|
+
| `class` | `string` | `''` | Class names for the `tbody` element. |
|
|
19
|
+
| `children` | `Snippet` or `Snippet<[T]>` | `undefined` | Manual body content when `items` is omitted, or `children(item)` in item-driven mode. |
|
|
20
|
+
| `empty` | `Snippet` | `undefined` | Optional empty-state snippet for item-driven mode. |
|
|
21
|
+
|
|
22
|
+
### TableBodyVirtualizer
|
|
23
|
+
|
|
24
|
+
Name: `TableBodyVirtualizer`
|
|
25
|
+
Description: Fixed-height body virtualization settings.
|
|
26
|
+
|
|
27
|
+
| Prop | Type | Default | Description |
|
|
28
|
+
| ----------- | -------- | ------- | -------------------------------------------------------------- |
|
|
29
|
+
| `rowHeight` | `number` | `-` | Required fixed pixel height used to compute the visible range. |
|
|
30
|
+
| `overscan` | `number` | `18` | Extra rows rendered above and below the viewport. |
|
|
31
|
+
|
|
32
|
+
### Context utilities
|
|
33
|
+
|
|
34
|
+
Name: `Table.Body` section context
|
|
35
|
+
Description: Publishes the `body` section scope for descendant rows, cells, and empty state.
|
|
36
|
+
|
|
37
|
+
| Prop | Type | Default | Description |
|
|
38
|
+
| ------------------------ | --------------------------- | ------- | -------------------------------- |
|
|
39
|
+
| `useTableSectionContext` | `() => TableSectionContext` | `-` | Reads the current section scope. |
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Table } from '../index';
|
|
3
|
+
|
|
4
|
+
type DemoRow = {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string;
|
|
7
|
+
group: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const rows: DemoRow[] = Array.from({ length: 120 }, (_, index) => {
|
|
11
|
+
const sequence = index + 1;
|
|
12
|
+
return {
|
|
13
|
+
id: `row-${String(sequence).padStart(3, '0')}`,
|
|
14
|
+
email: `user${sequence}@example.com`,
|
|
15
|
+
group: sequence % 2 === 0 ? 'Admin' : 'Developer'
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<div style="max-height: 240px; overflow: auto;">
|
|
21
|
+
<Table.Root aria-label="Virtualized users table">
|
|
22
|
+
<Table.Header>
|
|
23
|
+
<Table.Row>
|
|
24
|
+
<Table.Column id="email" isRowHeader textValue="Email">
|
|
25
|
+
<Table.ColumnHeaderCell>Email</Table.ColumnHeaderCell>
|
|
26
|
+
</Table.Column>
|
|
27
|
+
<Table.Column id="group" textValue="Group">
|
|
28
|
+
<Table.ColumnHeaderCell>Group</Table.ColumnHeaderCell>
|
|
29
|
+
</Table.Column>
|
|
30
|
+
</Table.Row>
|
|
31
|
+
</Table.Header>
|
|
32
|
+
|
|
33
|
+
<Table.Body items={rows} virtualizer={{ rowHeight: 32 }}>
|
|
34
|
+
{#snippet children(row)}
|
|
35
|
+
<Table.Row id={row.id} data-item-id={row.id}>
|
|
36
|
+
<Table.Cell>{row.email}</Table.Cell>
|
|
37
|
+
<Table.Cell>{row.group}</Table.Cell>
|
|
38
|
+
</Table.Row>
|
|
39
|
+
{/snippet}
|
|
40
|
+
{#snippet empty()}
|
|
41
|
+
<Table.EmptyState>No users found.</Table.EmptyState>
|
|
42
|
+
{/snippet}
|
|
43
|
+
</Table.Body>
|
|
44
|
+
</Table.Root>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const TableBodyItemsTest: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type TableBodyItemsTest = InstanceType<typeof TableBodyItemsTest>;
|
|
18
|
+
export default TableBodyItemsTest;
|