@qijenchen/design-system 0.1.0-beta.82 → 0.1.0-beta.84
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/CLAUDE.md +8 -8
- package/README.md +3 -2
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +22 -2
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +4 -4
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -2
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +12 -3
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +13 -5
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +7 -1
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +8 -3
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +1 -0
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +1 -1
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +8 -4
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +1 -1
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +10 -3
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +5 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +30 -13
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +53 -62
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/column-types.d.ts +10 -4
- package/dist/components/DataTable/column-types.d.ts.map +1 -1
- package/dist/components/DataTable/column-types.js.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.js +607 -0
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +140 -0
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
- package/dist/components/DataTable/data-table.d.ts +5 -6
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +36 -15
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-operators.js +140 -0
- package/dist/components/DataTable/filter-operators.js.map +1 -0
- package/dist/components/DataTable/filter-tree.js +312 -0
- package/dist/components/DataTable/filter-tree.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +3 -0
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +12 -1
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/DataTable/lib/column-meta.js +25 -0
- package/dist/components/DataTable/lib/column-meta.js.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +3 -1
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +7 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +105 -74
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts +20 -3
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +38 -20
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +45 -5
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +19 -0
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-edit-keys.d.ts +21 -0
- package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
- package/dist/components/Field/field-edit-keys.js +19 -0
- package/dist/components/Field/field-edit-keys.js.map +1 -0
- package/dist/components/Field/field-types.d.ts +20 -1
- package/dist/components/Field/field-types.d.ts.map +1 -1
- package/dist/components/Field/field-types.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +3 -2
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +38 -39
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +2 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +1 -1
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts +1 -1
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +7 -2
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
- package/dist/components/FileViewer/image-renderer.js +22 -1
- package/dist/components/FileViewer/image-renderer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +5 -3
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/InlineEdit/index.d.ts +2 -0
- package/dist/components/InlineEdit/index.d.ts.map +1 -0
- package/dist/components/InlineEdit/index.js +5 -0
- package/dist/components/InlineEdit/index.js.map +1 -0
- package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
- package/dist/components/InlineEdit/inline-edit.js +164 -0
- package/dist/components/InlineEdit/inline-edit.js.map +1 -0
- package/dist/components/Input/input.d.ts +6 -11
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +43 -13
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +2 -2
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +6 -5
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts +14 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +25 -3
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts +3 -3
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +6 -5
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/pagination.js +1 -1
- package/dist/components/Pagination/pagination.js.map +1 -1
- package/dist/components/PeoplePicker/index.js +7 -1
- package/dist/components/PeoplePicker/index.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +23 -10
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +6 -3
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +19 -14
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/Popover/popover.d.ts.map +1 -1
- package/dist/components/Popover/popover.js +3 -1
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +2 -2
- package/dist/components/ProfileCard/profile-card.js +3 -3
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +15 -9
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js +6 -3
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/Select/select.d.ts +46 -5
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +109 -28
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +3 -1
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +8 -1
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
- package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
- package/dist/components/SelectionControl/boolean-value.js +23 -0
- package/dist/components/SelectionControl/boolean-value.js.map +1 -0
- package/dist/components/SelectionControl/index.d.ts +1 -0
- package/dist/components/SelectionControl/index.d.ts.map +1 -1
- package/dist/components/SelectionControl/index.js +2 -0
- package/dist/components/SelectionControl/index.js.map +1 -1
- package/dist/components/Sheet/index.js +2 -1
- package/dist/components/Sheet/sheet.d.ts +7 -1
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +5 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +9 -4
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +8 -10
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +6 -6
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +3 -2
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +15 -1
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +2 -2
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +50 -42
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +42 -38
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +8 -6
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/tooltip.js +7 -5
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +56 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +211 -12
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/index.d.ts +115 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -108
- package/dist/index.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/tokens/categorical-color.js +15 -0
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/motion/motion.d.ts +7 -6
- package/dist/tokens/motion/motion.d.ts.map +1 -1
- package/dist/tokens/motion/motion.js +6 -6
- package/dist/tokens/motion/motion.js.map +1 -1
- package/dist/tokens/motion/overlay-motion.d.ts +19 -0
- package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
- package/dist/tokens/motion/overlay-motion.js +9 -0
- package/dist/tokens/motion/overlay-motion.js.map +1 -0
- package/dist/tokens/uiSize/icon-size.js +5 -0
- package/dist/tokens/uiSize/icon-size.js.map +1 -0
- package/ds-canonical/fork/governance.lock +37 -19
- package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
- package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
- package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
- package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
- package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/fork/manifest.json +20 -0
- package/ds-canonical/fork/preamble.md +22 -18
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
- package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
- package/ds-canonical/hooks/README.md +1 -1
- package/ds-canonical/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
- package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
- package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
- package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
- package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
- package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
- package/ds-canonical/hooks/check_story_determinism.sh +39 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
- package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
- package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
- package/ds-canonical/hooks/stop_self_audit.sh +31 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
- package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
- package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
- package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
- package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
- package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
- package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
- package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
- package/ds-canonical/references/build-ui-canonicals.md +2 -1
- package/ds-canonical/references/failure-class-registry.json +145 -0
- package/ds-canonical/references/governance-audit-coverage.md +33 -0
- package/ds-canonical/references/item-anatomy-recipe.md +2 -2
- package/ds-canonical/references/scenario-definition.md +6 -9
- package/ds-canonical/references/ssot-consultation.md +2 -2
- package/ds-canonical/references/ssot-index.md +5 -4
- package/ds-canonical/references/story-baseline-registry.json +8 -2
- package/ds-canonical/references/structural-token-retention.md +6 -9
- package/ds-canonical/rules/meta-patterns.md +8 -8
- package/ds-canonical/rules/self-verify.md +4 -3
- package/ds-canonical/rules/spec-rules.md +1 -1
- package/ds-canonical/rules/story-rules.md +2 -2
- package/ds-canonical/rules/ui-development.md +4 -2
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
- package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
- package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
- package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
- package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
- package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
- package/ds-canonical/skills/governance-health/SKILL.md +2 -1
- package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
- package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
- package/ds-canonical/skills/new-component/SKILL.md +7 -5
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
- package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
- package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
- package/ds-canonical/skills/story-writing/SKILL.md +3 -3
- package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
- package/ds-story-manifest.json +29 -20
- package/llms-full.txt +22 -1
- package/llms.txt +5 -4
- package/package.json +7 -3
- package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
- package/src/components/Accordion/accordion.stories.tsx +16 -1
- package/src/components/Alert/alert.principles.stories.tsx +1 -1
- package/src/components/Alert/alert.spec.md +8 -10
- package/src/components/Alert/alert.stories.tsx +28 -28
- package/src/components/Alert/alert.tsx +1 -1
- package/src/components/AppShell/_demo-helpers.tsx +6 -3
- package/src/components/AppShell/app-shell.spec.md +4 -4
- package/src/components/AppShell/app-shell.tsx +28 -2
- package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
- package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
- package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
- package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
- package/src/components/Avatar/avatar.spec.md +2 -2
- package/src/components/Avatar/avatar.stories.tsx +8 -6
- package/src/components/Avatar/avatar.tsx +13 -5
- package/src/components/Badge/badge.principles.stories.tsx +1 -1
- package/src/components/Badge/badge.spec.md +2 -0
- package/src/components/Badge/badge.stories.tsx +4 -2
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
- package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
- package/src/components/Button/button.principles.stories.tsx +1 -1
- package/src/components/Button/button.spec.md +2 -2
- package/src/components/Button/button.tsx +18 -3
- package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
- package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
- package/src/components/Calendar/calendar.spec.md +5 -4
- package/src/components/Calendar/calendar.stories.tsx +7 -4
- package/src/components/Calendar/calendar.tsx +26 -7
- package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
- package/src/components/Carousel/carousel.spec.md +2 -2
- package/src/components/Carousel/carousel.tsx +11 -3
- package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
- package/src/components/Chart/chart.principles.stories.tsx +1 -1
- package/src/components/Chart/chart.stories.tsx +2 -8
- package/src/components/Chart/chart.tsx +3 -0
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
- package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.spec.md +11 -26
- package/src/components/Checkbox/checkbox.stories.tsx +11 -8
- package/src/components/Checkbox/checkbox.tsx +18 -13
- package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
- package/src/components/Chip/chip.principles.stories.tsx +1 -1
- package/src/components/Chip/chip.spec.md +5 -4
- package/src/components/Chip/chip.tsx +5 -1
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
- package/src/components/CircularProgress/circular-progress.spec.md +3 -3
- package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
- package/src/components/Coachmark/coachmark.spec.md +5 -5
- package/src/components/Coachmark/coachmark.stories.tsx +3 -1
- package/src/components/Coachmark/coachmark.tsx +10 -3
- package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
- package/src/components/Combobox/combobox.tsx +53 -19
- package/src/components/Command/command.anatomy.stories.tsx +2 -2
- package/src/components/Command/command.principles.stories.tsx +1 -1
- package/src/components/Command/command.stories.tsx +42 -10
- package/src/components/DataTable/cell-registry.tsx +86 -63
- package/src/components/DataTable/column-types.ts +10 -1
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
- package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
- package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
- package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
- package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
- package/src/components/DataTable/data-table.spec.md +32 -12
- package/src/components/DataTable/data-table.stories.tsx +16 -17
- package/src/components/DataTable/data-table.tsx +103 -60
- package/src/components/DataTable/index.ts +3 -0
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
- package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
- package/src/components/DateGrid/date-grid.spec.md +1 -1
- package/src/components/DateGrid/date-grid.tsx +3 -1
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
- package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
- package/src/components/DatePicker/date-picker.spec.md +3 -3
- package/src/components/DatePicker/date-picker.stories.tsx +4 -5
- package/src/components/DatePicker/date-picker.tsx +99 -45
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
- package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.spec.md +3 -3
- package/src/components/DescriptionList/description-list.stories.tsx +7 -6
- package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
- package/src/components/Dialog/dialog.spec.md +9 -0
- package/src/components/Dialog/dialog.stories.tsx +66 -5
- package/src/components/Dialog/dialog.tsx +60 -25
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
- package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
- package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
- package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
- package/src/components/Empty/empty.spec.md +2 -2
- package/src/components/Field/field-context.ts +69 -5
- package/src/components/Field/field-controls.spec.md +62 -8
- package/src/components/Field/field-edit-keys.ts +66 -0
- package/src/components/Field/field-types.ts +58 -9
- package/src/components/Field/field-wrapper.tsx +50 -42
- package/src/components/Field/field.anatomy.stories.tsx +9 -6
- package/src/components/Field/field.spec.md +1 -1
- package/src/components/Field/field.stories.tsx +1 -1
- package/src/components/Field/field.tsx +2 -1
- package/src/components/Field/form-validation.spec.md +3 -3
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
- package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
- package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
- package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
- package/src/components/FileItem/file-item.spec.md +14 -8
- package/src/components/FileItem/file-item.stories.tsx +36 -25
- package/src/components/FileItem/file-item.tsx +8 -6
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
- package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
- package/src/components/FileUpload/file-upload.spec.md +1 -1
- package/src/components/FileUpload/file-upload.tsx +1 -1
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
- package/src/components/FileViewer/file-viewer.spec.md +30 -12
- package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
- package/src/components/FileViewer/file-viewer.tsx +12 -4
- package/src/components/FileViewer/image-renderer.tsx +35 -7
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
- package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
- package/src/components/HoverCard/hover-card.spec.md +5 -5
- package/src/components/HoverCard/hover-card.stories.tsx +16 -16
- package/src/components/HoverCard/hover-card.tsx +5 -3
- package/src/components/InlineEdit/index.ts +5 -0
- package/src/components/InlineEdit/inline-edit.spec.md +149 -0
- package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
- package/src/components/InlineEdit/inline-edit.tsx +287 -0
- package/src/components/Input/input.anatomy.stories.tsx +8 -7
- package/src/components/Input/input.principles.stories.tsx +2 -12
- package/src/components/Input/input.spec.md +13 -18
- package/src/components/Input/input.tsx +69 -22
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
- package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
- package/src/components/LinkInput/link-input.tsx +11 -10
- package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
- package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
- package/src/components/Menu/menu-item.spec.md +22 -15
- package/src/components/Menu/menu-item.stories.tsx +39 -11
- package/src/components/Menu/menu-item.tsx +38 -4
- package/src/components/Notice/notice.principles.stories.tsx +1 -1
- package/src/components/Notice/notice.spec.md +16 -3
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
- package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
- package/src/components/NumberInput/number-input.spec.md +4 -4
- package/src/components/NumberInput/number-input.tsx +19 -12
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
- package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
- package/src/components/Pagination/pagination.spec.md +1 -1
- package/src/components/Pagination/pagination.stories.tsx +2 -6
- package/src/components/Pagination/pagination.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
- package/src/components/PeoplePicker/people-picker.spec.md +6 -6
- package/src/components/PeoplePicker/people-picker.tsx +56 -16
- package/src/components/PeoplePicker/person-display.tsx +32 -16
- package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
- package/src/components/Popover/popover.tsx +3 -1
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
- package/src/components/ProfileCard/profile-card.spec.md +3 -3
- package/src/components/ProfileCard/profile-card.tsx +6 -6
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
- package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
- package/src/components/RadioGroup/radio-group.tsx +41 -15
- package/src/components/Rating/rating.spec.md +11 -3
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.spec.md +7 -3
- package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.tsx +17 -4
- package/src/components/Select/select.anatomy.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +27 -17
- package/src/components/Select/select.stories.tsx +33 -0
- package/src/components/Select/select.tsx +190 -36
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
- package/src/components/SelectMenu/select-menu.spec.md +15 -7
- package/src/components/SelectMenu/select-menu.tsx +16 -3
- package/src/components/SelectionControl/boolean-value.tsx +39 -0
- package/src/components/SelectionControl/index.ts +1 -0
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.spec.md +3 -3
- package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
- package/src/components/Separator/separator.spec.md +2 -2
- package/src/components/Separator/separator.stories.tsx +6 -27
- package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
- package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
- package/src/components/Sheet/sheet.spec.md +2 -2
- package/src/components/Sheet/sheet.tsx +9 -5
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
- package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
- package/src/components/Sidebar/sidebar.spec.md +13 -15
- package/src/components/Sidebar/sidebar.stories.tsx +8 -7
- package/src/components/Sidebar/sidebar.tsx +37 -25
- package/src/components/Skeleton/skeleton.stories.tsx +4 -11
- package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
- package/src/components/Slider/slider.principles.stories.tsx +2 -2
- package/src/components/Slider/slider.spec.md +5 -5
- package/src/components/Slider/slider.tsx +3 -1
- package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
- package/src/components/Steps/steps.principles.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +1 -1
- package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
- package/src/components/Switch/switch.principles.stories.tsx +4 -4
- package/src/components/Switch/switch.spec.md +8 -8
- package/src/components/Switch/switch.stories.tsx +9 -24
- package/src/components/Switch/switch.tsx +17 -13
- package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
- package/src/components/Tabs/tabs.spec.md +1 -1
- package/src/components/Tabs/tabs.tsx +21 -1
- package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
- package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
- package/src/components/Textarea/textarea.spec.md +4 -4
- package/src/components/Textarea/textarea.tsx +72 -46
- package/src/components/TimePicker/time-columns.tsx +6 -2
- package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
- package/src/components/TimePicker/time-picker.spec.md +3 -3
- package/src/components/TimePicker/time-picker.tsx +16 -10
- package/src/components/Toast/toast.stories.tsx +7 -4
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
- package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
- package/src/components/Tooltip/tooltip.spec.md +1 -1
- package/src/components/Tooltip/tooltip.stories.tsx +4 -39
- package/src/components/Tooltip/tooltip.tsx +8 -6
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
- package/src/components/TreeView/tree-view.spec.md +42 -11
- package/src/components/TreeView/tree-view.stories.tsx +1 -0
- package/src/components/TreeView/tree-view.tsx +322 -17
- package/src/index.ts +584 -60
- package/src/patterns/action-bar/action-bar.spec.md +9 -0
- package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
- package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
- package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
- package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
- package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
- package/src/styles/tokens.css +3 -0
- package/src/tokens/README.md +1 -1
- package/src/tokens/color/color.spec.md +3 -3
- package/src/tokens/color/color.stories.tsx +3 -3
- package/src/tokens/density/density.stories.tsx +16 -3
- package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
- package/src/tokens/motion/motion.css +33 -21
- package/src/tokens/motion/motion.spec.md +32 -15
- package/src/tokens/motion/motion.stories.tsx +58 -5
- package/src/tokens/motion/motion.ts +7 -6
- package/src/tokens/motion/overlay-motion.ts +26 -0
- package/src/tokens/orphan-tokens.spec.md +4 -4
- package/src/tokens/token-system.spec.md +1 -0
- package/src/tokens/uiSize/uiSize.spec.md +1 -1
- package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
- package/src/tokens/utility-registry.json +160 -23
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Locked 欄位(`lockedIds`)— 顯 Lock icon,不可 toggle / 不可 drag
|
|
11
11
|
* - 可選 search filter(`searchable`,跨欄位 label match)
|
|
12
12
|
* - 可選 column drag reorder(`onColumnOrderChange` 傳 → 啟 DnD)
|
|
13
|
-
* - 可選 reset 按鈕(`
|
|
13
|
+
* - 可選 reset 按鈕(`resettable: boolean` opt-in,header 區 RotateCcw;點擊 `onVisibilityChange({})` 還原全顯示,無獨立 onReset prop)
|
|
14
14
|
* - Bidirectional bulk toggle(footer button:全可見 → 全部隱藏 / 任一隱藏 → 顯示全部)
|
|
15
15
|
*
|
|
16
16
|
* **Why 抽 primitive**(per Issue 3 Rule-of-3):RoadmapAllInOne + WithBulkActions + 未來 product
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
|
|
2
2
|
// same-row-mixed-allow: header chrome corner buttons(close)跟 row inline actions(trash)不在同 row
|
|
3
|
-
// code-quality-allow: file-size — 2026-05-03 M21 retract:filter-value-picker.tsx(187 行 / 1 consumer)inline
|
|
3
|
+
// code-quality-allow: file-size — 2026-05-03 M21 retract:filter-value-picker.tsx(187 行 / 1 consumer)inline 回本檔(505 → 687 行)。2026-07-14 deep-audit 誠實更新:現 822 行,**已過 800 hard cap** — 非 stale escape 留著;拆檔候選 = filter-value-picker 區段(等第 2 個 consumer 接入)+ nested-group renderer,屬結構 refactor 需獨立 branch 做 + 完整驗證,列入 file-size escalation 追蹤,禁再增量。
|
|
4
4
|
import * as React from 'react'
|
|
5
5
|
import { Plus, Trash2, X as XIcon, RotateCcw } from 'lucide-react'
|
|
6
6
|
import type { ColumnDef } from '@tanstack/react-table'
|
|
@@ -439,6 +439,9 @@ function DataTableFilterPanelInner<TData>({
|
|
|
439
439
|
field: prefilledColumnId,
|
|
440
440
|
op: getDefaultOperator(colInfo.type),
|
|
441
441
|
value: '',
|
|
442
|
+
// 2026-07-14 deep-audit fix:補 datePrecision(原漏 → datetime(includeTime=true)欄
|
|
443
|
+
// prefill 掉到 undefined=day 精度忽略 ms;對齊初始 add / changeField 路徑的 datePrecisionOf)
|
|
444
|
+
datePrecision: datePrecisionOf(colInfo),
|
|
442
445
|
}
|
|
443
446
|
if (value.mode === 'flat') {
|
|
444
447
|
onChange({ ...value, children: [...value.children, cond] })
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @internal — DS-internal 單元(viewport 覆蓋 paint layer,只被 data-table.tsx 內部消費);不隨 index.ts re-export 進 npm public surface。
|
|
1
2
|
/**
|
|
2
3
|
* DataTableInteractionLayer — Slice D Step 1A scaffold(per `.claude/planning/datatable-spreadsheet-rfc.md`)
|
|
3
4
|
*
|
|
@@ -30,15 +31,16 @@ interface CellRect {
|
|
|
30
31
|
interface DataTableInteractionLayerProps {
|
|
31
32
|
/** Flag default false:不破現有 outline。enable 後 hover/editor 走 overlay。 */
|
|
32
33
|
enabled: boolean
|
|
33
|
-
/** Container ref;
|
|
34
|
+
/** Container ref;geometry source(getCellRect 由此 query cell DOM)。layer root 本身是
|
|
35
|
+
* position:fixed inset:0 viewport-anchor(見 render),非 container-origin absolute */
|
|
34
36
|
containerRef: React.RefObject<HTMLDivElement | null>
|
|
35
37
|
/** Per Contract 15:`cellClickEntersEdit` predicate;hover overlay 顯示與否 */
|
|
36
38
|
cellClickEntersEdit?: (cellId: CellId) => boolean
|
|
37
39
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* Active editor cell id。null = 無 active editor。
|
|
41
|
+
* 已接線(Slice D Step 5 完成,2026-07-14 docblock 對齊):activeEditorEnabled +
|
|
42
|
+
* activeEditorCellId + activeEditorRender 齊 → ActiveEditorHost(z 3)portal render
|
|
43
|
+
* 真 edit Field(per Contract 8「two paint owners」)。
|
|
42
44
|
*/
|
|
43
45
|
activeEditorCellId?: CellId | null
|
|
44
46
|
/**
|
|
@@ -55,12 +57,6 @@ interface DataTableInteractionLayerProps {
|
|
|
55
57
|
* Layer renders solid border SelectionRect(per user「不要 dash 直接實的就好」)。
|
|
56
58
|
*/
|
|
57
59
|
selectedCellId?: CellId | null
|
|
58
|
-
/**
|
|
59
|
-
* Slice D Step 4 range support(per user「應該支援 range」+ codex Q2.1 Airtable/AG Grid
|
|
60
|
-
* cite):range cell IDs from anchor↔focus rectangle。Layer renders bg-fill RangeRect
|
|
61
|
-
* (z 1,bg `--primary-subtle`)+ selection border on focus cell。
|
|
62
|
-
*/
|
|
63
|
-
rangeCellIds?: CellId[]
|
|
64
60
|
/**
|
|
65
61
|
* Slice D Step 5(D.3 portal Field,2026-05-10 user 拍板「在乎完美乾淨」+ codex Q6.1
|
|
66
62
|
* 撤回 defer):active editor render callback。當 activeEditorEnabled + activeEditorCellId
|
|
@@ -222,10 +218,11 @@ function useHoveredCell(
|
|
|
222
218
|
}
|
|
223
219
|
|
|
224
220
|
/**
|
|
225
|
-
* Singleton interaction layer。
|
|
221
|
+
* Singleton interaction layer(全 sub-layer 已接線;2026-07-14 docblock 對齊實作)。
|
|
226
222
|
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
223
|
+
* 現況:HoverCellRect(z 1)+ SelectionRing(z 2)+ ActiveEditorHost(z 3,portal edit Field);
|
|
224
|
+
* range 視覺走 cell 自身 CSS `[data-range-cell]`(RangeRect / rangeCellIds prop 已 retire)。
|
|
225
|
+
* layer root = position:fixed inset:0 viewport-anchor,pointerEvents:none(僅 ActiveEditorHost 開 auto)。
|
|
229
226
|
*/
|
|
230
227
|
export function DataTableInteractionLayer({
|
|
231
228
|
enabled,
|
|
@@ -235,8 +232,6 @@ export function DataTableInteractionLayer({
|
|
|
235
232
|
activeEditorEnabled = false,
|
|
236
233
|
activeEditorRender,
|
|
237
234
|
selectedCellId = null,
|
|
238
|
-
// rangeCellIds retired 2026-05-10(outer ring 已 retire,range visual 靠 cell-bg `[data-range-cell]`)
|
|
239
|
-
rangeCellIds: _rangeCellIds,
|
|
240
235
|
}: DataTableInteractionLayerProps) {
|
|
241
236
|
const hoveredCellId = useHoveredCell(containerRef, enabled)
|
|
242
237
|
// 2026-05-10 RWD/scroll sync(per user mandate「所有 overlay 在各種 RWD 和捲動時都處在正確位置」):
|
|
@@ -264,7 +259,7 @@ export function DataTableInteractionLayer({
|
|
|
264
259
|
? getCellRect(containerRef.current, activeEditorCellId)
|
|
265
260
|
: null
|
|
266
261
|
|
|
267
|
-
// Slice D Step 4(spreadsheet semantics):
|
|
262
|
+
// Slice D Step 4(spreadsheet semantics):SelectionRing with viewport clip(RangeRect 已 retire — range 視覺走 CSS [data-range-cell])。
|
|
268
263
|
const selectedGeo = enabled && selectedCellId != null
|
|
269
264
|
? getCellGeometry(containerRef.current, selectedCellId)
|
|
270
265
|
: null
|
|
@@ -341,9 +336,10 @@ function toRelRect(cellRect: CellRect, clipRect: CellRect): CellRect {
|
|
|
341
336
|
|
|
342
337
|
// ── Private primitives(per codex unified-ring-overlay-2026-05-10 Final A')──────
|
|
343
338
|
//
|
|
344
|
-
// 三個 private primitive 各自 own 一個 paint concern
|
|
339
|
+
// 三個 private primitive 各自 own 一個 paint concern(2026-07-14 對齊實作:CellRangeFill
|
|
340
|
+
// 不存在 — range bg 走 cell 自身 CSS `[data-range-cell]`,非 layer 元件):
|
|
345
341
|
// 1. CellRingOverlay — outline ring(hover / selected / future focus / error)
|
|
346
|
-
// 2.
|
|
342
|
+
// 2. ClipMask — panel viewport 裁切 wrapper(Issue 6 partial-visibility)
|
|
347
343
|
// 3. ActiveEditorHost — opaque host(portal Field edit)
|
|
348
344
|
//
|
|
349
345
|
// SSOT pattern(共 3 primitives):rect float pass-through + boxSizing:border-box +
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// @anatomy-rationale:
|
|
2
2
|
// SizeMatrix represented as RowHeightMatrix per row-density semantics —
|
|
3
|
-
// DataTable 的 size
|
|
4
|
-
// comfortable),語意對應「掃描 vs
|
|
3
|
+
// DataTable 的 size 主軸是 row-height tier(compact / cozy /
|
|
4
|
+
// comfortable),語意對應「掃描 vs 閱讀」資料密度;lg 同時連動字級放大
|
|
5
|
+
// (sm/md → text-body / lg → text-body-lg,對齊 Field,SSOT fieldDisplayTextClass)。命名沿用
|
|
5
6
|
// Linear / Notion / Airtable 業界共識(row density,非 component size)。
|
|
6
7
|
// StateBehavior covered by ColorMatrix「Row 狀態色彩」段(default / hover /
|
|
7
8
|
// selected / disabled)+ Features「排序」段。Row 互動是 row-level
|
|
@@ -131,7 +132,7 @@ export const Inspector: Story = {
|
|
|
131
132
|
bordered: { control: 'boolean', description: '外框(嵌入已帶框容器時可設 false 避免雙重邊框)' },
|
|
132
133
|
pinnedLeft: { control: 'boolean', description: 'Pin 產品名稱欄到左側,橫向捲動時保持可見' },
|
|
133
134
|
pinnedRight: { control: 'boolean', description: 'Pin 上架日期欄到右側' },
|
|
134
|
-
inlineEdit: { control: 'boolean', description: 'inline edit 視覺:cell 間加垂直分隔線(dtCellGrid)。
|
|
135
|
+
inlineEdit: { control: 'boolean', description: 'inline edit 視覺:cell 間加垂直分隔線(dtCellGrid)。display 態零恆顯 chevron(2026-07-08 A 案,editable affordance = hover outline);edit 態才有控件 chrome' },
|
|
135
136
|
height: {
|
|
136
137
|
control: 'select',
|
|
137
138
|
options: ['auto', '300px'],
|
|
@@ -171,8 +172,9 @@ export const ColumnTypes: Story = {
|
|
|
171
172
|
const columns = [
|
|
172
173
|
col.accessor('name', { header: 'text', meta: { type: 'string', width: 200 } }),
|
|
173
174
|
col.accessor('price', { header: 'currency', meta: { type: 'currency', prefix: '$', width: 120 } }),
|
|
174
|
-
|
|
175
|
-
col.accessor('
|
|
175
|
+
// display:'tag' opt-in 讓 demo 與 header「select(Tag)」名實相符(SelectCell 預設 plain 純文字)
|
|
176
|
+
col.accessor('stock', { header: 'select(Tag)', meta: { type: 'select', options: STATUS_OPTIONS, width: 140, display: 'tag' } }),
|
|
177
|
+
col.accessor('available', { header: 'boolean(勾選框)', meta: { type: 'boolean', width: 100 } }),
|
|
176
178
|
col.accessor('launchDate', { header: 'date', meta: { type: 'date', width: 140 } }),
|
|
177
179
|
]
|
|
178
180
|
|
|
@@ -194,7 +196,7 @@ export const ColumnTypes: Story = {
|
|
|
194
196
|
<tr><Td mono>number</Td><Td mono>{`<NumberInput mode="display">`}</Td><Td>right</Td><Td>數量、年齡</Td></tr>
|
|
195
197
|
<tr><Td mono>currency</Td><Td mono>{`<NumberInput mode="display">`}(+ prefix)</Td><Td>right</Td><Td>金額、價格</Td></tr>
|
|
196
198
|
<tr><Td mono>date</Td><Td mono>{`<DatePicker mode="display">`}</Td><Td>left</Td><Td>日期、時間戳</Td></tr>
|
|
197
|
-
<tr><Td mono>boolean</Td><Td mono>{`<Checkbox mode="display">`}(
|
|
199
|
+
<tr><Td mono>boolean</Td><Td mono>{`<Checkbox mode="display">`}(勾 / 叉 icon)</Td><Td>left</Td><Td>啟用 / 可見</Td></tr>
|
|
198
200
|
<tr><Td mono>select</Td><Td mono>{`<Select mode="display">`}</Td><Td>left</Td><Td>狀態、類別</Td></tr>
|
|
199
201
|
<tr><Td mono>multiSelect</Td><Td mono>{`<Combobox mode="display">`}</Td><Td>left</Td><Td>多選 tags</Td></tr>
|
|
200
202
|
<tr><Td mono>person</Td><Td mono>PersonDisplay / MultiPersonDisplay</Td><Td>left</Td><Td>指派者、reviewer</Td></tr>
|
|
@@ -202,7 +204,7 @@ export const ColumnTypes: Story = {
|
|
|
202
204
|
</tbody>
|
|
203
205
|
</table>
|
|
204
206
|
</div>
|
|
205
|
-
<p className="text-footnote text-fg-muted mt-3">擴充新 type:在 `column-types.ts`
|
|
207
|
+
<p className="text-footnote text-fg-muted mt-3">擴充新 type:在 `cell-registry.tsx` 的 `cellRegistry` map 註冊對應 Cell component(display/edit 渲染 SSOT);`column-types.ts` 只設 `align` / default metadata。兩處對齊後自動跟所有 DataTable 整合</p>
|
|
206
208
|
</div>
|
|
207
209
|
</div>
|
|
208
210
|
)
|
|
@@ -260,8 +262,8 @@ export const AlignmentRule: Story = {
|
|
|
260
262
|
return (
|
|
261
263
|
<div className="flex flex-col gap-8">
|
|
262
264
|
<div>
|
|
263
|
-
<H3>Column type
|
|
264
|
-
<Desc>數字靠右方便縱向比較位數(Excel / 會計軟體 / 財務系統共識);文字靠左方便閱讀;boolean 靠左跟其他文字欄一致,維持掃視時的左緣節奏。Consumer
|
|
265
|
+
<H3>Column type 提供對齊預設(column-types.ts 定義),consumer 可用 meta.align 覆寫</H3>
|
|
266
|
+
<Desc>數字靠右方便縱向比較位數(Excel / 會計軟體 / 財務系統共識);文字靠左方便閱讀;boolean 靠左跟其他文字欄一致,維持掃視時的左緣節奏。Consumer 通常不需要設 `align`——column type 已給預設;需要時仍可用 `meta.align` 在 column 層級覆寫。</Desc>
|
|
265
267
|
<DataTable columns={columns} data={SAMPLE_DATA} height="auto" />
|
|
266
268
|
</div>
|
|
267
269
|
|
|
@@ -273,7 +275,7 @@ export const AlignmentRule: Story = {
|
|
|
273
275
|
<tbody>
|
|
274
276
|
<tr><Td>text / select / person / date / link</Td><Td mono>left</Td><Td>閱讀從左到右</Td></tr>
|
|
275
277
|
<tr><Td>number / currency</Td><Td mono>right</Td><Td>縱向比較位數(小數點縱向對齊)</Td></tr>
|
|
276
|
-
<tr><Td>boolean(
|
|
278
|
+
<tr><Td>boolean(勾 / 叉 icon)</Td><Td mono>left</Td><Td>跟其他文字欄一致靠左,維持掃視時的左緣節奏</Td></tr>
|
|
277
279
|
<tr><Td>actions(在 cell 內的按鈕)</Td><Td mono>right</Td><Td>動線尾端,不干擾資料掃視</Td></tr>
|
|
278
280
|
</tbody>
|
|
279
281
|
</table>
|
|
@@ -437,10 +439,10 @@ export const ColorMatrix: Story = {
|
|
|
437
439
|
</thead>
|
|
438
440
|
<tbody>
|
|
439
441
|
<tr><Td mono>text / date / number / currency</Td><Td><TokenCell token="--foreground" /></Td></tr>
|
|
440
|
-
<tr><Td mono>select
|
|
442
|
+
<tr><Td mono>select</Td><Td>預設 plain 純文字 foreground;`meta.display='tag'` opt-in 才走 Tag 的 variant 色(green / yellow / red / blue…)</Td></tr>
|
|
441
443
|
<tr><Td mono>person</Td><Td>Avatar + foreground 文字</Td></tr>
|
|
442
444
|
<tr><Td mono>link</Td><Td><TokenCell token="--primary" /></Td></tr>
|
|
443
|
-
<tr><Td mono>boolean</Td><Td
|
|
445
|
+
<tr><Td mono>boolean</Td><Td>naked Checkbox(true = <TokenCell token="--primary" display="primary 底白勾" /> / false = 空框 <TokenCell token="--border" />),非 X / Check icon</Td></tr>
|
|
444
446
|
</tbody>
|
|
445
447
|
</table>
|
|
446
448
|
</div>
|
|
@@ -513,7 +515,7 @@ export const Accessibility = {
|
|
|
513
515
|
render: () => (
|
|
514
516
|
<div className="max-w-3xl text-body text-fg-secondary">
|
|
515
517
|
<h3 className="text-h5 text-foreground mb-2">無障礙設計</h3>
|
|
516
|
-
<p className="whitespace-pre-line">{"DataTable 用一般 div 搭配表格語意標記,而非原生 table 元素——因為虛擬捲動需要絕對定位每一列,而 table 的佈局模型做不到。輔助技術(螢幕報讀器)會把它當成表格朗讀。\n\n 表格語意 :最外層標記為表格、每一列標記為列、每一格標記為儲存格,表頭那一格標記為欄位標題。\n\n 排序 :可排序的表頭會標示目前的排序方向(升冪 / 降冪 / 未排序),報讀器讀得出來。\n\n 選取 :每一列的勾選框都有說明文字(由使用方傳入,沒傳就用「選取此列」),全選框的說明文字是「全選可見列」。\n\n 鍵盤 :一般表格模式下,用 Tab 進入表格後可操作排序與勾選;方向鍵在儲存格之間移動是試算表模式(spreadsheetMode)
|
|
518
|
+
<p className="whitespace-pre-line">{"DataTable 用一般 div 搭配表格語意標記,而非原生 table 元素——因為虛擬捲動需要絕對定位每一列,而 table 的佈局模型做不到。輔助技術(螢幕報讀器)會把它當成表格朗讀。\n\n 表格語意 :最外層標記為表格、每一列標記為列、每一格標記為儲存格,表頭那一格標記為欄位標題。\n\n 排序 :可排序的表頭會標示目前的排序方向(升冪 / 降冪 / 未排序),報讀器讀得出來。\n\n 選取 :每一列的勾選框都有說明文字(由使用方傳入,沒傳就用「選取此列」),全選框的說明文字是「全選可見列」。\n\n 鍵盤 :一般表格模式下,用 Tab 進入表格後可操作排序與勾選;方向鍵在儲存格之間移動是試算表模式(spreadsheetMode)才開啟的功能,不是預設。列上的更多操作(`rowActions` 為使用方提供的 callback,DataTable 不代管收納)建議在 3 個以上時由使用方自行收進右側的「更多」選單,以確保不用滑鼠也能操作全部動作。\n\n 焦點 :一般元件(排序鈕 / 勾選框)鍵盤聚焦時顯示清楚外框,與設計系統聚焦樣式一致;啟用選取 / 試算表模式時,表格本身可被 Tab 聚焦,焦點以「選取儲存格」的方框呈現(表格外層刻意不另畫外框),初次 Tab 尚未選取儲存格時焦點落在表格容器。\n\n 驗證 :Storybook 無障礙檢查面板應該沒有嚴重問題;全程鍵盤可操作,不必用到滑鼠;文字對比度達到無障礙標準。"}</p>
|
|
517
519
|
</div>
|
|
518
520
|
),
|
|
519
521
|
}
|
|
@@ -93,10 +93,10 @@ export const UsageGuidance: Story = {
|
|
|
93
93
|
</Rule>
|
|
94
94
|
|
|
95
95
|
<Rule
|
|
96
|
-
title="❌ 不用 DataTable
|
|
97
|
-
note="DataTable
|
|
96
|
+
title="❌ 不用 DataTable 表達深層階層結構(部門 / 資料夾 tree)"
|
|
97
|
+
note="DataTable 支援淺層 nested-rows(展開子列,如任務 / 子任務);但深層多階縮排 + 大量節點的 folder / dept tree 語意仍屬 TreeView。Notion 的資料庫可以 expand row,但側欄階層樹用 TreeView"
|
|
98
98
|
>
|
|
99
|
-
<Label warn
|
|
99
|
+
<Label warn>深層階層樹用 TreeView(無限深度展開 / 收合);淺層子列 DataTable 可用</Label>
|
|
100
100
|
</Rule>
|
|
101
101
|
|
|
102
102
|
<Rule
|
|
@@ -107,10 +107,10 @@ export const UsageGuidance: Story = {
|
|
|
107
107
|
</Rule>
|
|
108
108
|
|
|
109
109
|
<Rule
|
|
110
|
-
title="❌ 不用 DataTable
|
|
111
|
-
note="DataTable
|
|
110
|
+
title="❌ 不用 DataTable 做公式 / cell-level 計算"
|
|
111
|
+
note="DataTable 的 spreadsheetMode 支援跨 cell 選取 / Shift 矩形範圍 / 方向鍵導覽 / cell 編輯;但公式與 cell-level 計算超出範圍 → AG Grid Enterprise / Handsontable。Airtable 確實像表,但 DataTable 不是設計來做這個"
|
|
112
112
|
>
|
|
113
|
-
<Label warn
|
|
113
|
+
<Label warn>公式 / 計算用專門 library,不往 DataTable 塞;跨 cell 選取 / 編輯用 spreadsheetMode</Label>
|
|
114
114
|
</Rule>
|
|
115
115
|
</div>
|
|
116
116
|
</div>
|
|
@@ -140,14 +140,14 @@ export const ColumnTypeRule: Story = {
|
|
|
140
140
|
|
|
141
141
|
<Rule
|
|
142
142
|
title="❌ 手寫 cell render 自訂格式化"
|
|
143
|
-
note="每 column 自己寫 `cell: (info) => ...` 會繞過 `mode='display'` 系統——**格式化邏輯會漂移**。一個 table 的 price 顯示「$2,490」,另一個 table 的 price 顯示「2490」,一個 boolean
|
|
143
|
+
note="每 column 自己寫 `cell: (info) => ...` 會繞過 `mode='display'` 系統——**格式化邏輯會漂移**。一個 table 的 price 顯示「$2,490」,另一個 table 的 price 顯示「2490」,一個 boolean 顯示勾 icon,另一個 boolean 顯示「是」——整個系統 format 失去一致性"
|
|
144
144
|
>
|
|
145
145
|
<Label warn>除非真的需要 `mode='display'` 無法提供的客製視覺,否則一律走 meta.type 系統。客製化時完全跳過 type 讓 display 渲染不要干預</Label>
|
|
146
146
|
</Rule>
|
|
147
147
|
|
|
148
148
|
<Rule
|
|
149
|
-
title="擴充新 type:到
|
|
150
|
-
note="新增資料類型(如 `percentage`、`relative-time`)在 `column-types.ts`
|
|
149
|
+
title="擴充新 type:到 cell-registry.tsx 註冊"
|
|
150
|
+
note="新增資料類型(如 `percentage`、`relative-time`)在 `cell-registry.tsx` 的 `cellRegistry` map 註冊對應 Cell component(display/edit 渲染 SSOT);`column-types.ts` 只設 align / default metadata。兩處對齊後自動跟所有 DataTable 整合,不在單一 table 硬寫"
|
|
151
151
|
>
|
|
152
152
|
<Label>讓 column type 系統成為 single source of truth,所有 table 受惠同一次更新</Label>
|
|
153
153
|
</Rule>
|
|
@@ -44,10 +44,10 @@ DataTable 是基於 TanStack Table 的資料表格元件,提供排序、篩選
|
|
|
44
44
|
| 場景 | 改用 | 原因 |
|
|
45
45
|
|------|------|------|
|
|
46
46
|
| 唯讀的 key-value 展示(profile 屬性列表)| `DescriptionList` | DataTable 是多 row 集合,DescriptionList 是單一實體的屬性 |
|
|
47
|
-
|
|
|
47
|
+
| 深層階層結構(部門 / 資料夾 tree)| `TreeView` | DataTable 支援淺層 nested-rows(L4 展開子列),但深層多階縮排 + 大量節點的 folder/dept tree 語意仍屬 TreeView |
|
|
48
48
|
| 卡片式瀏覽(圖文並列)| 自訂 grid / list | Table 是密集 row,不適合大圖 |
|
|
49
49
|
| 只有 2-3 筆且不需互動 | 直接 `<dl>` 或自訂 layout | DataTable 的 overhead 對小資料集過度工程 |
|
|
50
|
-
| 試算表(公式 /
|
|
50
|
+
| 試算表(公式 / cell-level 計算)| 超出範圍,用專門試算表 library | DataTable 的 `spreadsheetMode` 支援跨 cell 選取 / Shift 矩形範圍 / 方向鍵導覽 / cell 編輯,但不做公式或 cell-level 計算 |
|
|
51
51
|
| 需要複雜群組 header + 合併 cell | 自訂或 TanStack 原始 API | DataTable 對 header group 的抽象層有限 |
|
|
52
52
|
|
|
53
53
|
---
|
|
@@ -139,7 +139,7 @@ Table 層級的模式切換,不是 column 層級。跟 AG Grid / Airtable 的
|
|
|
139
139
|
|
|
140
140
|
### 七、Column Type
|
|
141
141
|
|
|
142
|
-
**Column type 是資料行為的預設合約。** 指定 type 自動獲得對齊 / 渲染 / 排序 / 篩選行為,可在 column 層級覆寫。Header 對齊永遠跟該欄 body cell 一致。
|
|
142
|
+
**Column type 是資料行為的預設合約。** 指定 type 自動獲得對齊 / 渲染 / 排序 / 篩選行為,可在 column 層級覆寫。Header 對齊永遠跟該欄 body cell 一致。select/multiSelect 的 `meta.options` 消費 Select 的完整 `SelectOption` schema(M30 wrapper-extends-primitive;含 icon / iconClassName / description),`meta.selectedItemRenderer` 轉發 Select 同名 API 供 status 類彩色 cell(2026-07-08 補——原 `{value,label}` 窄型別 = 假 SSOT,WM 被迫手刻 bare trigger 實證)。
|
|
143
143
|
|
|
144
144
|
### 八、Row 狀態
|
|
145
145
|
|
|
@@ -154,7 +154,7 @@ Table 層級的模式切換,不是 column 層級。跟 AG Grid / Airtable 的
|
|
|
154
154
|
|
|
155
155
|
**世界級對照**:Material DataGrid `GridActionsCellItem`(IconButton small)/ Polaris IndexTable hover 20-24px / Atlassian Dynamic Table small iconOnly / Apple HIG Finder list row ≤24px — 全派固定不放大。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
**收納邏輯(consumer 自建)**:`rowActions` 是 raw callback `(row)=>ReactNode`,DataTable 原樣渲染回傳內容,**不代管計數 / 不自動 MoreVertical 收納**。建議 consumer 自行實作:1-2 個 → icon buttons 並排(全 size="xs");3+ → 前 1-2 個 inline + MoreVertical dropdown(全 size="xs";dropdown 包含所有操作,確保鍵盤可存取全部)。**Header/body 寬度同步**(DataTable 代管):header 渲染同一 `rowActions` 輸出但設為 invisible 佔位,確保 header 和 body 的 right region 同寬。
|
|
158
158
|
|
|
159
159
|
### 九之二、Cell action primitive 分類(2026-04-29 codified)
|
|
160
160
|
|
|
@@ -164,7 +164,7 @@ SSOT → `patterns/element-anatomy/inline-action.spec.md`「Real case 表」+ Pr
|
|
|
164
164
|
|------|-----------|
|
|
165
165
|
| Header cell internal(sort / ⌄ menu / filter funnel / pin)| `ItemInlineActionButton` `size="md"`(對齊 AG Grid / Material / Airtable / Notion / Polaris) | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
166
166
|
| **Multi-sort header(≥2 columns sorted)** | **隱藏 header arrow + 取消排序 dropdown option**(K7,2026-05-04)— 無 order 編號的單個 arrow 在 multi-sort 是 partial info → 反而混淆;user 走 SortManager panel 看完整 priority(SSOT)。0/1 sort 仍秀 arrow 完整資訊。理由:現行 DS 不顯 sort order 編號,跟 Airtable / Linear / Atlassian / Carbon 純箭頭派一致;multi-sort 時這派需 SortManager fallback(world-class 共識) |
|
|
167
|
-
| Body cell internal(display endAction / clear / edit indicator)| Field family endAction(自動繼承) |
|
|
167
|
+
| Body cell internal(display endAction / clear / edit indicator)| Field family endAction(自動繼承)。**Display 態零恆顯型別 icon(2026-07-08 A 案)**:editable affordance = hover outline(SSOT → field.spec.md L4/L6,`nakedCellEditableDisplayHover`);boolean = live Checkbox(AG Grid 同);url = hover Pencil(click-opens-link 與 edit 衝突的功能性入口,非型別 indicator)。**cell 空值 = 全空白**(2026-07-08 B 案,SSOT → field-controls.spec.md「null / undefined 值」surface 分流表) |
|
|
168
168
|
| Row dedicated action column | Button `xs iconOnly` 24px(見「九、Row Actions」) |
|
|
169
169
|
| Toolbar | Button(action-bar 共識) |
|
|
170
170
|
|
|
@@ -213,13 +213,13 @@ type DataTableSelection =
|
|
|
213
213
|
selection?: string[] | DataTableSelection // controlled;傳 string[] = include shorthand(向後相容)
|
|
214
214
|
defaultSelection?: string[] | DataTableSelection // uncontrolled
|
|
215
215
|
onSelectionChange?: (next: DataTableSelection) => void // 一律 emit union
|
|
216
|
-
totalCount
|
|
216
|
+
// (無 totalCount prop — 全集筆數 M 由 consumer 自持;2026-07-13 D1 拍板移除 DS 內零消費 no-op prop)
|
|
217
217
|
selectable?: boolean | 'single' | 'multi' // default false(不啟用);true 等同 'multi';single 永遠 include
|
|
218
218
|
isRowSelectable?: (row: TData) => boolean
|
|
219
219
|
preserveSelectionOnFilter?: boolean // default false
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
-
對齊 `useControllableState` idiom(Field / Switch / Checkbox 已用)+ MUI X DataGrid v8 `rowSelectionModel { type:'include'|'exclude', ids }` / AG Grid `selectAll + toggledNodes` 反向選取共識。**計數(consumer)**:`mode==='all' ?
|
|
222
|
+
對齊 `useControllableState` idiom(Field / Switch / Checkbox 已用)+ MUI X DataGrid v8 `rowSelectionModel { type:'include'|'exclude', ids }` / AG Grid `selectAll + toggledNodes` 反向選取共識。**計數(consumer)**:`mode==='all' ? M − excluded.length : ids.length`(M = consumer 自持的全集筆數,DataTable 不收 totalCount prop)。**向後相容**:傳 `string[]` 自動正規化為 `{ mode:'include' }`;但 `onSelectionChange` 一律 emit union(consumer 讀取端需處理兩 mode)。
|
|
223
223
|
|
|
224
224
|
### 二、Checkbox column
|
|
225
225
|
|
|
@@ -235,7 +235,7 @@ preserveSelectionOnFilter?: boolean // default false
|
|
|
235
235
|
1. Header checkbox click(none → all)→ 選**目前可見** rows(filter 後 visible-only)= `{ mode:'include', ids:[…visible] }`
|
|
236
236
|
2. 全頁可見已選 → BulkActionBar hint:「已選取本頁 N 個。**點此選取全部 M 個**」
|
|
237
237
|
3. 點 hint → consumer `setSelection({ mode:'all', excluded:[] })` 擴 dataset 全選,hint 改:「已選取全部 M 個。**清除選取項目**」
|
|
238
|
-
4. **反向選取(inverted)**:all 模式下取消勾選某幾筆 → 加進 `excluded`(`選取 = 全集 − excluded`);再勾回 → 移出 `excluded`。對 10k 筆只載 50 筆**不需列舉其餘 ID**,任意 toggle 順序封閉、O(1)。count = `
|
|
238
|
+
4. **反向選取(inverted)**:all 模式下取消勾選某幾筆 → 加進 `excluded`(`選取 = 全集 − excluded`);再勾回 → 移出 `excluded`。對 10k 筆只載 50 筆**不需列舉其餘 ID**,任意 toggle 順序封閉、O(1)。count = `M − excluded.length`(M = consumer 自持全集筆數),hint 顯示「已選取全部 M 個(排除 K 個)」。
|
|
239
239
|
|
|
240
240
|
不**一鍵**直接擴 dataset(避免誤觸大量資料,必先 2-step);擴選後的反向扣除由 inverted 模型自動處理。
|
|
241
241
|
|
|
@@ -255,7 +255,7 @@ preserveSelectionOnFilter?: boolean // default false
|
|
|
255
255
|
### 六、Selection × filter / sort 互動
|
|
256
256
|
|
|
257
257
|
- **`include` 模式**:filter 套用 → filtered-out 的 selected rows 預設清掉(對齊 Material / AG Grid / Polaris / GitHub / Gmail consensus) <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
258
|
-
- **`all`(反向)模式**:語意 = 「全部**符合當前 filter**的列 − excluded」→ filter 變動時 selection set 隨 filter **自然重算**(M 跟著變),`excluded` 保留不清(被 filter 掉的 excluded 列無害,回到該 filter 時仍排除);**不**套用上面的 include-mode 清除。consumer
|
|
258
|
+
- **`all`(反向)模式**:語意 = 「全部**符合當前 filter**的列 − excluded」→ filter 變動時 selection set 隨 filter **自然重算**(M 跟著變),`excluded` 保留不清(被 filter 掉的 excluded 列無害,回到該 filter 時仍排除);**不**套用上面的 include-mode 清除。consumer 計數用更新後的全集筆數 M(consumer 自持)。
|
|
259
259
|
- **opt-in `preserveSelectionOnFilter={true}`**(僅 include 模式)→ 給 productivity scope(Linear / Airtable 用法),保留 hidden selected,BulkActionBar 顯示「{visible} selected ({hidden} hidden by filter)」
|
|
260
260
|
- sort 套用 → selection 全保留(sort 不影響可見性,兩 mode 同)
|
|
261
261
|
|
|
@@ -265,7 +265,7 @@ preserveSelectionOnFilter?: boolean // default false
|
|
|
265
265
|
|
|
266
266
|
### 八、a11y 預設
|
|
267
267
|
|
|
268
|
-
- 每個 row checkbox 必有 `aria-label`:consumer 提供 `getRowAriaLabel?: (row) => string`,fallback `
|
|
268
|
+
- 每個 row checkbox 必有 `aria-label`:consumer 提供 `getRowAriaLabel?: (row) => string`,fallback `'選取此列'`
|
|
269
269
|
- header checkbox `aria-label="全選可見列"`
|
|
270
270
|
- 鍵盤:`Space` toggle / `Shift+Space` 擴 range / `Cmd/Ctrl+A` 選全可見 / `Esc` clear
|
|
271
271
|
- Selection 變更可選 `aria-live="polite"` 通知(consumer-implemented)
|
|
@@ -357,6 +357,17 @@ ValueShape ↔ DS picker 對照(canonical 2026-05-02):
|
|
|
357
357
|
|
|
358
358
|
## L4 Inline Edit / Nested rows / Row drag(2026-05-04;對齊 Notion / Airtable type-aware editor + Jira drag idiom @benchmark-unverified)
|
|
359
359
|
|
|
360
|
+
### Inline create row(表格底部「+ 新增」列)— 只定義 idle 態(2026-07-08 WM 戰役 codify,user 拍板)
|
|
361
|
+
|
|
362
|
+
**點擊後的編輯內容 consumer 自組**(常被客製,不 canonical 化、不加 DS API):TanStack headless 無此 feature(https://tanstack.com/table/v8/docs/guide/custom-features)、AG Grid 無內建(官方 blog 教 pinned row DIY:https://blog.ag-grid.com/add-new-rows-using-a-pinned-row-at-the-top-of-the-grid/)、Ant ProComponents 只定義 trigger 列。**可定義的只有尚未點擊的 idle 列**,幾何全消費既有 token(零新值):
|
|
363
|
+
|
|
364
|
+
- **高度** = `h-table-row-{size}`(與 data row 精確同高 — 上方「三 region row 精確同高」延伸到此列)
|
|
365
|
+
- **左 padding** = `--table-cell-px`,「+ icon + 文字」對齊**第一資料欄**內容起點(啟 selection / drag 系統欄時同樣對齊第一資料欄,Notion / Airtable 同)
|
|
366
|
+
- **Typography** = cell 同字級(`fieldDisplayTextClass(size)`)+ `text-fg-muted`(placeholder 語感);Plus icon 同 `fg-muted`
|
|
367
|
+
- **Hover** = 整列 `neutral-hover` + cursor-pointer,**整列可點**(hit-target 對齊 L2「整 cell 區可點擊」)
|
|
368
|
+
- **點擊 → inline**(不強制開 dialog;欄位複雜的 create 另走 Dialog 可並存);建議行為(非契約):Enter 提交後保持編輯態連續新增(Jira inline create idiom)、Esc 還原 idle 列
|
|
369
|
+
- **拒絕**:Ant 式全寬 dashed 按鈕(表單語境 idiom,dashed 不在 DS 視覺語言);idle 列是 row 形(Notion「+ New」/ Airtable plus row / Asana「Add task…」line 資料庫工具共識)
|
|
370
|
+
|
|
360
371
|
### Inline Edit — per-column opt-in
|
|
361
372
|
|
|
362
373
|
`columnDef.meta.editable: boolean | (row) => boolean`(`true` / fn-true 才開)。Commit:blur or Enter → `onCellCommit(rowId, colId, value)`;Cancel:Esc。例外:autoRowHeight string cell 的 edit 是 `Textarea` — Enter 換行、`Cmd/Ctrl+Enter` commit(blur 同 commit)。
|
|
@@ -369,7 +380,16 @@ ValueShape ↔ DS picker 對照(canonical 2026-05-02):
|
|
|
369
380
|
| select / multiSelect | click cell | `<Select>` / `<Combobox>` |
|
|
370
381
|
| person / multiPerson | click cell | `<PeoplePicker variant="naked">`(選人 picker) |
|
|
371
382
|
| **boolean** | direct toggle | `<Checkbox>` 無 mode 切換 |
|
|
372
|
-
| **url** | **hover cell → Pencil 按鈕(xs iconOnly tertiary)→ click** | `<Input>`(read 永遠是連結;cell click 走 anchor 開連結,**不**進 edit)
|
|
383
|
+
| **url** | **hover cell → Pencil 按鈕(xs iconOnly tertiary)→ click** | `<Input>`(read 永遠是連結;cell click 走 anchor 開連結,**不**進 edit)— 屬下方「navigate-valued cell 通用類別」|
|
|
384
|
+
|
|
385
|
+
### Navigate-valued cell 通用類別(2026-07-08 user 拍板 codify — 原 url 專屬條文升級)
|
|
386
|
+
|
|
387
|
+
**定義**:凡「點值的主行為 = 導航/開啟而非編輯」的型別(url;未來 parent / email / file / relation 同類),一律繼承四條 — 新型別只在上表登記一行,其餘全繼承,禁逐型別重刻:
|
|
388
|
+
|
|
389
|
+
1. **排除 click-to-edit 與 hover outline**(code gate `data-table.tsx` editable-click 判斷排除該型別 — 此前只活在 code,本段為條文 SSOT):值可點 = click 屬導航,cell 不再是「點擊進 edit」目標,hover outline(field.spec.md L4)一併不套
|
|
390
|
+
2. **排除 Enter / F2 進 edit**(下方鍵盤段「非 boolean/url」既有規則,類別化後隨表繼承)
|
|
391
|
+
3. **唯一 edit affordance = hover Pencil**(xs iconOnly tertiary,`opacity-0 group-hover/cell:opacity-100`,onClick `stopPropagation` + `onRequestEdit`)— 對齊 AG Grid 官方三件套(`suppressClickEdit` + 「including a button in your cell renderer」+ `startEditingCell()`,https://www.ag-grid.com/react-data-grid/cell-editing-start-stop/)+ Jira hover-pencil + Notion title cell hover-OPEN 鏡像;Atlaskit target-tag 分流(點 `<a>` 導航、點空白區編輯)為次選已評估不採(與 hover-outline 統一 affordance 衝突)
|
|
392
|
+
4. **edit 觸發後 = 一般 field 行為契約**:Pencil 只負責「進入 edit」一步;進入後 autoFocus 進輸入、Esc 取消、Enter/blur commit、驗證時機、focus 樣式全部回歸 field-controls edit-mode canonical,與其他型別 cell edit 零特例。若 edit 態控件與 form 場景不同(url 用 plain `<Input>` 非 LinkInput — LinkInput edit 預設顯 link 態,cell 需直接輸入),**必在上表該行寫明 documented 例外 + rationale**,禁只留 code 註解
|
|
373
393
|
|
|
374
394
|
### Nested rows — forward TanStack
|
|
375
395
|
|
|
@@ -407,7 +427,7 @@ Row drag + column reorder + TreeView 共用 `lib/drag-visual.ts`:source `opacity
|
|
|
407
427
|
- **bar 本體 SSOT 在 `<Pagination>` 完整形態**(2026-07-06 user 拍板「Pagination 元件提供完整功能、Table 按一致定義套用」):showTotal range 資訊、「N 筆/頁」選單、「資訊左、操作右」layout 全在 `../Pagination/pagination.spec.md`「完整形態」段——DataTable **只轉發 config + own TanStack state**(controlled 消費),不自拼分頁列
|
|
408
428
|
- **間距**:表格 → 分頁列 = `--layout-space-tight`(layoutSpace spec 規則 3「跨範疇 functional 交互」;Ant Table margin 16px / shadcn py-4 同量級)
|
|
409
429
|
- **對齊**:純頁碼形態**靠右**(shadcn `justify-end` / Ant Table 預設 `bottomEnd` / MUI TablePagination / Carbon 控制群 4 家實證);完整形態由 Pagination 自帶 w-full justify-between
|
|
410
|
-
- **`total` 數源** = `getPrePaginationRowModel().rows.length`(filter 後全集)——**不是** selection all-mode 的
|
|
430
|
+
- **`total` 數源** = `getPrePaginationRowModel().rows.length`(filter 後全集)——**不是** selection all-mode 的 server-side 全集數 M(那由 consumer 自持,語意不同)
|
|
411
431
|
- filter / data 縮小時自動 clamp 當前頁(對齊 MUI X);`isEmpty` 時分頁列整條不渲染(Empty 已渲染)
|
|
412
432
|
|
|
413
433
|
**與虛擬滾動互斥**:啟用分頁 → `useVirtual` 強制關閉——TanStack 官方定位兩者為互斥替代策略(分頁 = 每頁固定筆數主動換頁;虛擬滾動 = 連續滾動只渲可視列)。分頁時無虛擬化保護,建議 `pageSize ≤ 100`。
|
|
@@ -131,13 +131,9 @@ type Story = StoryObj
|
|
|
131
131
|
// Anatomy 是 type-system structural canonical home(用 Product col helper 對齊其他 anatomy 範例);
|
|
132
132
|
// 本 showcase 版用 custom `TypeDemo` interface,不對齊 anatomy 通用 type → noise。Retire showcase 版,anatomy 保留。
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
render: () => (
|
|
138
|
-
<DataTable columns={columnsWithPrice} data={sampleData} height="auto" />
|
|
139
|
-
),
|
|
140
|
-
}
|
|
134
|
+
// Retired 2026-07-14 audit Dim 24:`NumberAlignment` 跟 anatomy.stories.tsx AlignmentRule 重複
|
|
135
|
+
// (同「數字/金額靠右、文字靠左」規則,anatomy 版含完整 rationale Desc + column type 對照)。
|
|
136
|
+
// Alignment 規則 canonical home = anatomy `AlignmentRule`;showcase 版無額外內容 → retire(earn-existence 2-test 雙 NO)。
|
|
141
137
|
|
|
142
138
|
/* ── Column resize(2026-05-06 v11):table 層級開關 + handle hover 變色 ── */
|
|
143
139
|
export const ColumnResize: Story = {
|
|
@@ -209,11 +205,11 @@ export const ColumnReorder: Story = {
|
|
|
209
205
|
return (
|
|
210
206
|
<div className="flex flex-col gap-3 max-w-5xl">
|
|
211
207
|
<p className="text-caption text-fg-muted">
|
|
212
|
-
enableColumnReorder
|
|
213
|
-
|
|
208
|
+
開啟欄位重排(enableColumnReorder)後,拖住欄標題即可移動整欄:拖曳中欄位以半透明
|
|
209
|
+
浮影跟著游標,目標欄的左或右邊緣會出現落點提示線(依游標位置判定放在前或後)。
|
|
214
210
|
<br />
|
|
215
|
-
- <strong>SKU 鎖定</strong>(<code>meta.locked=true</code>)
|
|
216
|
-
|
|
211
|
+
- <strong>SKU 鎖定</strong>(<code>meta.locked=true</code>):不可拖曳,也不會成為落點
|
|
212
|
+
(對照 Notion 的主欄固定做法)
|
|
217
213
|
<br />
|
|
218
214
|
- System columns(__select__)永遠鎖
|
|
219
215
|
<br />
|
|
@@ -830,8 +826,11 @@ export const NestedRows: Story = {
|
|
|
830
826
|
)
|
|
831
827
|
return (
|
|
832
828
|
<div>
|
|
829
|
+
{/* 實作:forward TanStack getSubRows;縮排共用 --tree-indent-{sm,md,lg} token(跨 TreeView
|
|
830
|
+
設計語言);chevron click stopPropagation 不觸發 row select。 */}
|
|
833
831
|
<p className="text-caption text-fg-muted mb-3">
|
|
834
|
-
|
|
832
|
+
樹狀表格:點列首的三角形展開 / 收合子任務,子任務逐層縮排(與 TreeView 同一套縮排節奏);
|
|
833
|
+
點三角形只切換展開,不會順帶選取整列。
|
|
835
834
|
</p>
|
|
836
835
|
<DataTable
|
|
837
836
|
columns={taskColumns}
|
|
@@ -1071,7 +1070,6 @@ export const WithBulkActions: Story = {
|
|
|
1071
1070
|
selectable
|
|
1072
1071
|
selection={selection}
|
|
1073
1072
|
onSelectionChange={setSelection}
|
|
1074
|
-
totalCount={TOTAL}
|
|
1075
1073
|
columnVisibility={columnVisibility}
|
|
1076
1074
|
onColumnVisibilityChange={setColumnVisibility}
|
|
1077
1075
|
getRowId={(row) => row.sku}
|
|
@@ -1468,8 +1466,8 @@ export const RowDragInteractive: Story = {
|
|
|
1468
1466
|
<div className="flex flex-col gap-3 max-w-3xl">
|
|
1469
1467
|
<p className="text-caption text-fg-muted">
|
|
1470
1468
|
handle 浮在 row 左緣(不佔 column 空間,Jira 設計準則)。pinned-left(SKU)+ pinned-right(Updated)+
|
|
1471
|
-
center 中段欄。拖曳時 source
|
|
1472
|
-
|
|
1469
|
+
center 中段欄。拖曳時 source 列留在原位(半透明壓住視覺),2px 主色落點提示線在左固定欄、
|
|
1470
|
+
中段、右固定欄三區同步標出,其他列不會先行讓位。
|
|
1473
1471
|
</p>
|
|
1474
1472
|
<DataTable
|
|
1475
1473
|
columns={columnsWithPrice}
|
|
@@ -1515,9 +1513,10 @@ export const RowDragWithVirtualization: Story = {
|
|
|
1515
1513
|
}
|
|
1516
1514
|
return (
|
|
1517
1515
|
<div className="flex flex-col gap-3 max-w-3xl">
|
|
1516
|
+
{/* 實作(v3):enableRowDrag 自動拉高 overscan ≥ 5;drag 期間 freeze measureElement;
|
|
1517
|
+
snapToCursorModifier 讓 ghost 對齊游標(不鎖軸)— 三者合修「拖曳 + 捲動錯位」。 */}
|
|
1518
1518
|
<p className="text-caption text-fg-muted">
|
|
1519
|
-
200 列 +
|
|
1520
|
-
measureElement、snapToCursorModifier ghost 對齊游標(不鎖軸)— 拖曳 + 持續往下捲不再錯位。
|
|
1519
|
+
200 列 + 虛擬捲動:拖住一列往下捲動,浮影一路跟著游標,落點在長清單任何位置都能正確對齊。
|
|
1521
1520
|
</p>
|
|
1522
1521
|
<DataTable
|
|
1523
1522
|
columns={baseColumns}
|