@qijenchen/design-system 0.1.0-beta.83 → 0.1.0-beta.85
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-group.d.ts +47 -0
- package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-group.js +154 -0
- package/dist/components/DataTable/data-table-filter-group.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 +285 -0
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
- package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
- package/dist/components/DataTable/data-table-filter-value-picker.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/Field/index.d.ts +1 -0
- package/dist/components/Field/index.d.ts.map +1 -1
- package/dist/components/Field/index.js +2 -0
- package/dist/components/Field/index.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 +95 -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 +31 -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 +2 -1
- 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 +28 -0
- package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -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 +15 -0
- package/ds-canonical/fork/preamble.md +20 -18
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
- 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 +2 -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_codex_brief_invariants.sh +28 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
- 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 +28 -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_ssot_header_declaration.sh +3 -1
- package/ds-canonical/hooks/check_story_determinism.sh +2 -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_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_opacity_token_usage.sh +39 -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/story-rules.md +2 -2
- package/ds-canonical/rules/ui-development.md +2 -2
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -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 +51 -58
- 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 +1 -1
- package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
- 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 +1 -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 +5 -5
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
- 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 +2 -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 +13 -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-group.tsx +231 -0
- package/src/components/DataTable/data-table-filter-panel.tsx +16 -430
- package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
- 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 +33 -13
- package/src/components/DataTable/data-table.stories.tsx +16 -17
- package/src/components/DataTable/data-table.tsx +107 -61
- package/src/components/DataTable/filter-operators.spec.md +3 -3
- 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/Field/index.ts +1 -0
- 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 +5 -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 +29 -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 +588 -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 +4 -4
- 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.css +1 -1
- 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
|
@@ -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}
|
|
@@ -5,13 +5,16 @@
|
|
|
5
5
|
// 每個檔過 M21 / M17 / Rule-of-3 三 test:
|
|
6
6
|
// - data-table.tsx(主,foundational)
|
|
7
7
|
// - data-table-filter-panel.tsx + data-table-sort-manager.tsx + data-table-column-visibility-panel.tsx(panel state 隔離)
|
|
8
|
+
// - data-table-filter-group.tsx + data-table-filter-value-picker.tsx(@internal;2026-07-14 filter panel
|
|
9
|
+
// 過 800 hard cap 拆檔 — row/nested-group renderer + ValueShape picker,只被 panel 消費)
|
|
8
10
|
// - cell-registry.tsx(column type → cell display / edit 解析 SSOT)
|
|
9
11
|
// - data-table-interaction-layer.tsx + active-editor-controller.ts(spreadsheet overlay + portal editor)
|
|
10
12
|
// - column-types.ts + filter-operators.ts(✓ Rule-of-3 SSOT,3+ consumer)
|
|
11
13
|
// - filter-tree.ts(pure data + eval,test isolation)
|
|
12
14
|
// - lib/column-meta.ts(Internal SSOT,消 5 處 `(col as any)`)
|
|
13
15
|
// - + stories / spec / css
|
|
14
|
-
// M21 retract:filter-value-picker.tsx 1 consumer →
|
|
16
|
+
// M21 retract:filter-value-picker.tsx 1 consumer → 2026-05-03 inline 回 panel(上列 2026-07-14
|
|
17
|
+
// @internal 拆檔非 M21 迴轉:非 public 抽象,file-size hard cap 驅動,consumer 仍只見 panel)。
|
|
15
18
|
import * as React from 'react'
|
|
16
19
|
import { createPortal } from 'react-dom'
|
|
17
20
|
import { Empty } from '@/design-system/components/Empty/empty'
|
|
@@ -152,9 +155,6 @@ export interface DataTableProps<TData>
|
|
|
152
155
|
defaultSelection?: string[] | DataTableSelection
|
|
153
156
|
/** Selection 變更 callback(emit DataTableSelection union;include / all 兩模型) */
|
|
154
157
|
onSelectionChange?: (next: DataTableSelection) => void
|
|
155
|
-
/** 全資料集筆數 M(server-side / filter 後);all 模式 count = totalCount − excluded.length。
|
|
156
|
-
* **DS 內部零消費(no-op prop)**:僅型別文件 + destructure 防 spread 到 DOM;count 全由 consumer 計算 */
|
|
157
|
-
totalCount?: number
|
|
158
158
|
/** 是否啟用 selection / 模式;true 等同 'multi' */
|
|
159
159
|
selectable?: boolean | 'single' | 'multi'
|
|
160
160
|
/** Row 是否可選(disabled rows 只 disable checkbox,row 內容正常 render) */
|
|
@@ -203,7 +203,7 @@ export interface DataTableProps<TData>
|
|
|
203
203
|
*
|
|
204
204
|
* **v2(2026-05-05)修正**:
|
|
205
205
|
* - Virtualizer × transform:被拖 row 略過 `measureElement`(透過 SortableRowCtx 廣播 active id),避免 transform 干擾測量
|
|
206
|
-
* - 3-panel mirror sync
|
|
206
|
+
* - 3-panel mirror sync:primary region 呼叫 `useDraggable` + `useDroppable`;mirror region 只 `useDroppable`(v15.4 split),isDragging 由 `useDndContext` active.id 同步 → 三 region 視覺一致
|
|
207
207
|
* - Cross-parent drop:nested 全 row 各自 `useDroppable`,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`
|
|
208
208
|
*
|
|
209
209
|
* 詳 `data-table.spec.md`「L4 Row drag」段。
|
|
@@ -265,7 +265,7 @@ export interface DataTablePaginationOptions {
|
|
|
265
265
|
pageSize?: number
|
|
266
266
|
/** 每頁筆數選項;傳了才渲染「每頁 N 筆」Select(消費既有 Select size="sm") */
|
|
267
267
|
pageSizeOptions?: number[]
|
|
268
|
-
/** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的
|
|
268
|
+
/** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 server-side 全集數 M — 那是 consumer 自持) */
|
|
269
269
|
showTotal?: boolean
|
|
270
270
|
/** 當前頁(1-based,controlled;不傳 = uncontrolled) */
|
|
271
271
|
page?: number
|
|
@@ -312,7 +312,9 @@ const SELECT_COL_ID = '__select__'
|
|
|
312
312
|
* 解決「全選 10k 筆只載 50 筆 → 無法列舉其餘 ID」:all 模式「選取 = 全集 − excluded」,
|
|
313
313
|
* 任何 toggle 都只是 excluded 的 add/remove,對任意順序封閉、O(1)、不需列舉未載入 ID。
|
|
314
314
|
*
|
|
315
|
-
* 計數(consumer):mode==='all' ?
|
|
315
|
+
* 計數(consumer):mode==='all' ? M − excluded.length : ids.length(M = consumer 自持的
|
|
316
|
+
* server-side / filter 後全集筆數;2026-07-13 D1 拍板:DataTable 不收 totalCount prop — DS 內部
|
|
317
|
+
* 零消費 no-op 已移除,計數本來就全由 consumer 端算)。
|
|
316
318
|
* 進入 all 模式:consumer 在「選取全部 M」hint 點擊時 setSelection({ mode: 'all', excluded: [] })。
|
|
317
319
|
*/
|
|
318
320
|
export type DataTableSelection =
|
|
@@ -446,12 +448,13 @@ function TruncateCell({ children, className }: { children: React.ReactNode; clas
|
|
|
446
448
|
return <Tooltip><TooltipTrigger asChild>{span}</TooltipTrigger><TooltipContent>{children}</TooltipContent></Tooltip>
|
|
447
449
|
}
|
|
448
450
|
|
|
449
|
-
// ── L4 Row Drag: SortableRowContext
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
//
|
|
454
|
-
//
|
|
451
|
+
// ── L4 Row Drag: SortableRowContext(v15 Path B;2026-07-14 JSDoc 對齊實作)──────
|
|
452
|
+
// 每 region(left / center / right)各 mount 一次 SortableRowProvider,依 role 分流(v15.4 split):
|
|
453
|
+
// primary → SourceRowProvider(useDraggable + useDroppable)= 唯一 drag source;
|
|
454
|
+
// mirror → MirrorRowProvider(useDroppable only),isDragging 走 useDndContext active.id 同步。
|
|
455
|
+
// 無 SortableContext / useSortable(v15.0 Path B 已砍,見檔頭 import 註解)。listeners 全走
|
|
456
|
+
// RowDragHandle Button(v15.6 button-only;row 本身不接 listeners)。primary = left region 若存在否則 center。
|
|
457
|
+
// `invalidDrop`(cross-parent over)走 prop 廣播給 RowDragHandle 切 cursor-not-allowed。
|
|
455
458
|
interface SortableRowCtxValue {
|
|
456
459
|
setNodeRef: (el: HTMLElement | null) => void
|
|
457
460
|
role: 'primary' | 'mirror'
|
|
@@ -477,10 +480,11 @@ interface SortableRowCtxValue {
|
|
|
477
480
|
}
|
|
478
481
|
const SortableRowCtx = React.createContext<SortableRowCtxValue | null>(null)
|
|
479
482
|
|
|
480
|
-
/** Per-region per-row
|
|
481
|
-
* 同 row.id 在 left/center/right 三 region 各 mount
|
|
482
|
-
*
|
|
483
|
-
*
|
|
483
|
+
/** Per-region per-row drag wrapper(v15.4 architectural split)。
|
|
484
|
+
* 同 row.id 在 left/center/right 三 region 各 mount 一次,但 hook mount tree 完全分離:
|
|
485
|
+
* primary → SourceRowProvider(useDraggable + useDroppable);mirror → MirrorRowProvider
|
|
486
|
+
* (useDroppable only,isDragging 由 useDndContext 同步)。activator / listeners 只給
|
|
487
|
+
* primary 的 RowDragHandle Button(v15.6 button-only);mirror 不提供避免雙觸發。 */
|
|
484
488
|
function SortableRowProvider(props: {
|
|
485
489
|
id: string
|
|
486
490
|
disabled?: boolean
|
|
@@ -593,14 +597,15 @@ function MirrorRowProvider({
|
|
|
593
597
|
return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>
|
|
594
598
|
}
|
|
595
599
|
|
|
596
|
-
/** DraggableHeaderCell — wrap header cell 跟 dnd-kit
|
|
600
|
+
/** DraggableHeaderCell — wrap header cell 跟 dnd-kit useDraggable + useDroppable 接軌
|
|
601
|
+
* (2026-05-06 v14.2;v15.0 Path B 改分離 hooks,無 SortableContext)。
|
|
597
602
|
*
|
|
598
603
|
* Why wrap-not-rewrite:`headerCellEl` 既有邏輯複雜(sort / resize / select column / right region 等),
|
|
599
|
-
* 改 inline
|
|
604
|
+
* 改 inline useDraggable/useDroppable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render
|
|
600
605
|
* 保持 untouched,單一職責 = 加 drag affordance。
|
|
601
606
|
*
|
|
602
607
|
* Behavior:
|
|
603
|
-
* -
|
|
608
|
+
* - useDraggable + useDroppable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners
|
|
604
609
|
* - `data: { type: 'column', columnId }` 餵 dnd-kit handleDragStart / handleDragEnd 區分 row/column drag
|
|
605
610
|
* - 注入 ref(setNodeRef)+ transform style + transition + opacity(drag 時 source invisible,DragOverlay 顯 ghost)
|
|
606
611
|
* - draggable 時注入 attributes + listeners + cursor:grab / `data-column-id` (DragOverlay snapshot 用)
|
|
@@ -660,8 +665,9 @@ function DraggableHeaderCell({
|
|
|
660
665
|
|
|
661
666
|
/** Row drag handle — Portal-rendered, position:fixed 真正水平置中於 table outer border line(Jira canonical)。
|
|
662
667
|
*
|
|
663
|
-
* v15.
|
|
664
|
-
*
|
|
668
|
+
* v15.6 button-only drag(推翻 v15.2「整列接 listeners」,2026-07-14 JSDoc 對齊):Button =
|
|
669
|
+
* 唯一 activator,接 handleSetActivatorNodeRef + handleListeners(SourceRowProvider ctx);
|
|
670
|
+
* row div 不接 listeners(rowListeners=undefined),row click 保留給 select / open detail 等 UX。
|
|
665
671
|
*
|
|
666
672
|
* Why Portal + position:fixed(2026-05-05 v4):
|
|
667
673
|
* DataTable 結構含三層 overflow-hidden(outer wrapper / leftBody / row),用 absolute + translate-x:-50%
|
|
@@ -923,7 +929,6 @@ function DataTableInner<TData>(
|
|
|
923
929
|
estimateRowHeight, tableOptions, rowActions, cellErrors,
|
|
924
930
|
pinnedLeftColumns, pinnedRightColumns, inlineEdit = false,
|
|
925
931
|
selection: selectionProp, defaultSelection, onSelectionChange,
|
|
926
|
-
totalCount,
|
|
927
932
|
selectable = false, isRowSelectable, getRowId, getRowAriaLabel,
|
|
928
933
|
preserveSelectionOnFilter = false,
|
|
929
934
|
columnVisibility: columnVisibilityProp, defaultColumnVisibility, onColumnVisibilityChange,
|
|
@@ -1262,7 +1267,7 @@ function DataTableInner<TData>(
|
|
|
1262
1267
|
// 2026-05-06 v10 DragOverlay canonical:retire windowed sticky range extractor (v4-v9 workaround)。
|
|
1263
1268
|
// 改用 `<DragOverlay>` portal 把 source row 視覺解耦 — source 即使 unmount(virtual scroll out)
|
|
1264
1269
|
// overlay 仍 render 由 cloned outerHTML 提供視覺。dnd-kit transform / collision 走 active item id
|
|
1265
|
-
// (
|
|
1270
|
+
// (DndContext store 以 active id 追蹤,跟 hook instance mount 狀態無關;v15 無 SortableContext)。
|
|
1266
1271
|
// 對齊 dnd-kit GitHub #1674 + drag-overlay docs canonical「virtualized list MUST use DragOverlay」。
|
|
1267
1272
|
// overscan 仍輕微拉高(避免 source row 旁邊 rows 也 unmount 致使 hover signal 計算抖動)。
|
|
1268
1273
|
const effectiveOverscan = enableRowDrag ? Math.max(overscan, 5) : overscan
|
|
@@ -1392,10 +1397,9 @@ function DataTableInner<TData>(
|
|
|
1392
1397
|
|
|
1393
1398
|
// ── Phase 9 Issue 1 fix(2026-05-10):range cells lifted compute + Set ────
|
|
1394
1399
|
// 計算 spreadsheet range cell IDs(Shift+click rectangle from anchor↔focus),
|
|
1395
|
-
//
|
|
1396
|
-
//
|
|
1397
|
-
//
|
|
1398
|
-
// (per codex Q1 verdict:bg fill 移到 cell bg layer 不在 overlay,內容才不被蓋)
|
|
1400
|
+
// 提供 `rangeCellIdSet` Set → cell wrapper data-range-cell attr for cell-bg fill
|
|
1401
|
+
// (per codex Q1 verdict:bg fill 走 cell bg layer 不在 overlay,內容才不被蓋;
|
|
1402
|
+
// layer 的 outer ring / rangeCellIds prop 已 retire — 2026-07-14 對齊清理)
|
|
1399
1403
|
const rangeCellIds = React.useMemo<string[] | undefined>(() => {
|
|
1400
1404
|
if (!spreadsheetMode || !rangeAnchor || !rangeFocus || rangeAnchor === rangeFocus) return undefined
|
|
1401
1405
|
const parseCell = (id: string) => {
|
|
@@ -1452,7 +1456,13 @@ function DataTableInner<TData>(
|
|
|
1452
1456
|
return () => obs.disconnect()
|
|
1453
1457
|
}, [hasLeft, hasRight, rows.length])
|
|
1454
1458
|
|
|
1455
|
-
|
|
1459
|
+
// 2026-07-09 root-cause fix(user 以 GitHub Pages 對比抓出 regression):
|
|
1460
|
+
// 舊 `h-table-row-${size}` 模板字串 Tailwind **靜態掃描看不到** → `.h-table-row-{sm,md,lg}` 規則
|
|
1461
|
+
// 唯一靠 uiSize.spec.md 裡的 literal 被 content-detection 掃到才生成;戰役期間掃描樹變動後未生成
|
|
1462
|
+
// → 規則消失 → row 塌成「內容高度」(非編輯 33px / 編輯 44px)而非固定 token 40px,連帶選取控件與
|
|
1463
|
+
// 列文字對不齊。改用 literal map(對齊 field-wrapper cva 的 `h-field-md` literal 慣例),Tailwind
|
|
1464
|
+
// 永遠掃得到、不再依賴脆弱的 spec.md literal → 永不再漂移。
|
|
1465
|
+
const rowHeight = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size] ?? 'h-table-row-md'
|
|
1456
1466
|
|
|
1457
1467
|
// ── Cross-region row hover (2026-04-22 D3 perf audit):event delegation 改 per-row closure
|
|
1458
1468
|
// 舊:每 row 建 `{ onMouseEnter, onMouseLeave }` + 2 arrow functions → 100 row = 200 closures/render
|
|
@@ -1573,8 +1583,8 @@ function DataTableInner<TData>(
|
|
|
1573
1583
|
const dragDisabled = sorting.length > 0
|
|
1574
1584
|
|
|
1575
1585
|
// ── L4 Row drag v2:nested rows + parent map ─────────────────────────────────
|
|
1576
|
-
// v2 cross-parent fix:全 row
|
|
1577
|
-
// 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
|
|
1586
|
+
// v2 cross-parent fix:全 row 各自掛 useDraggable/useDroppable(含 sub-rows;v15 無 SortableContext),
|
|
1587
|
+
// custom collisionDetection 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
|
|
1578
1588
|
// parentMap: rowId → parentId(top-level row 的 parent = '' 哨兵 string)
|
|
1579
1589
|
const { allRowIds, parentMap } = React.useMemo(() => {
|
|
1580
1590
|
const ids: string[] = []
|
|
@@ -1725,7 +1735,13 @@ function DataTableInner<TData>(
|
|
|
1725
1735
|
const canExpand = cell.row.getCanExpand?.() ?? false
|
|
1726
1736
|
const isExpanded = cell.row.getIsExpanded?.() ?? false
|
|
1727
1737
|
const toggleExpand = cell.row.getToggleExpandedHandler?.()
|
|
1728
|
-
|
|
1738
|
+
// 2026-07-08 sibling-aware 佔位(WM root-cause 戰役):spec:382「同層 sibling 有 expandable
|
|
1739
|
+
// 時 leaf 也佔位」原本沒實作 — depth-0 leaf(無 children 的頂層列)拿不到 w-4+mr-2 佔位,
|
|
1740
|
+
// 與同層有 chevron 的列左緣錯位(PDF「chevron 空間」問題)。同層 = 同 parent 的 subRows;
|
|
1741
|
+
// 頂層 = core rows。只在 isFirstContent 時計算,成本一列一次。
|
|
1742
|
+
const siblingRows = cell.row.getParentRow?.()?.subRows ?? table.getCoreRowModel().rows
|
|
1743
|
+
const siblingHasExpand = isFirstContent && siblingRows.some((r) => r.getCanExpand?.() ?? false)
|
|
1744
|
+
const showNestedPrefix = isFirstContent && (depth > 0 || canExpand || siblingHasExpand)
|
|
1729
1745
|
// Issue 9 cell error(2026-05-10):lookup `${rowId}:${colId}` in cellErrors map
|
|
1730
1746
|
// editing cell 自動 clear visual error(per spec 「edit-clears-own-cell」)— consumer 走
|
|
1731
1747
|
// onCellCommit 驗證後決定回填新 error(由 consumer 端控制 cellErrors map state)。
|
|
@@ -1802,6 +1818,9 @@ function DataTableInner<TData>(
|
|
|
1802
1818
|
// 跟 cell 4 邊 inset divider 視覺相疊(同 pixel)= 1 line visual,不雙線。
|
|
1803
1819
|
inlineEdit && 'dtCellGrid',
|
|
1804
1820
|
onEditableCellClick && ['cursor-pointer', nakedCellEditableDisplayHover], // editable cell display hover affordance(對齊 Notion / Airtable hover-cell-shows-border canonical)
|
|
1821
|
+
// a11y(2026-07-14 dim-10 修):非 spreadsheet inlineEdit cell 可 Tab 聚焦(見下方
|
|
1822
|
+
// tabIndex/onKeyDown)— focus-visible ring 對齊本檔 expand button / sortable header canonical。
|
|
1823
|
+
onEditableCellClick && !spreadsheetMode && 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',
|
|
1805
1824
|
// 2026-05-13 Q3 cell disabled SSOT(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):
|
|
1806
1825
|
// bg `--bg-disabled` component-state token(color.spec.md:671 owner)+ cursor 抑制 click affordance。
|
|
1807
1826
|
cellDisabled && 'bg-disabled cursor-not-allowed',
|
|
@@ -1818,6 +1837,19 @@ function DataTableInner<TData>(
|
|
|
1818
1837
|
...(experimentalSpreadsheetOverlay && { '--cell-hover-outline-color': 'transparent' } as React.CSSProperties),
|
|
1819
1838
|
}}
|
|
1820
1839
|
onClick={onEditableCellClick}
|
|
1840
|
+
// a11y(2026-07-14 dim-10 修):非 spreadsheet 的 inlineEdit cell 原本只有 onClick —
|
|
1841
|
+
// 鍵盤 user 無法聚焦 cell、無法進入編輯(WCAG 2.1.1)。對齊 Atlassian InlineEdit
|
|
1842
|
+
// read-view-focusable idiom:editable display cell 可 Tab 聚焦,Enter / F2 進 edit。
|
|
1843
|
+
// spreadsheetMode 不加(該模式走 table-level selectedCellId 鍵盤導覽 SSOT,per-cell
|
|
1844
|
+
// tab stop 會跟 roving 模型衝突);cell 內 embedded 控件事件不攔(target guard)。
|
|
1845
|
+
tabIndex={onEditableCellClick && !spreadsheetMode ? 0 : undefined}
|
|
1846
|
+
onKeyDown={onEditableCellClick && !spreadsheetMode ? (e) => {
|
|
1847
|
+
if (e.target !== e.currentTarget) return
|
|
1848
|
+
if (e.key === 'Enter' || e.key === 'F2') {
|
|
1849
|
+
e.preventDefault()
|
|
1850
|
+
setEditingCellId(cellEditId(cellRowId, cellColId))
|
|
1851
|
+
}
|
|
1852
|
+
} : undefined}
|
|
1821
1853
|
>
|
|
1822
1854
|
{/* Issue 9 cell error(2026-05-10):有 error → cell 內外結構切 flex-col,
|
|
1823
1855
|
上 row 渲既有 nested + content,下 row 渲 error message 14px text-error。
|
|
@@ -2009,11 +2041,20 @@ function DataTableInner<TData>(
|
|
|
2009
2041
|
// Phase B3 IME guard(2026-05-10 per codex Q-B3):中文輸入法組字中 ignore 所有 nav keys。
|
|
2010
2042
|
// 2026-05-16 Round 5 audit Dim 27 fix:`keyCode` deprecated but still in KeyboardEvent type — no cast needed。
|
|
2011
2043
|
if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return
|
|
2044
|
+
// 2026-07-14 dim-10 修:spreadsheet 分支排除 descendant 互動控件 — 焦點在 cell 內
|
|
2045
|
+
// action button / link / input 時,Enter 應 activate 該控件、方向鍵交還控件,
|
|
2046
|
+
// 原 handler 會 preventDefault 取消按鈕 activation、拿舊 selectedCellId 導覽。
|
|
2047
|
+
// 對齊下方 row-selection 分支 2026-07-09 既有 input-family guard + AG Grid
|
|
2048
|
+
// embedded-control convention(cell renderer 內控件 own keyboard)。
|
|
2049
|
+
const spreadsheetKbTarget = e.target as HTMLElement | null
|
|
2050
|
+
const targetIsEmbeddedControl = !!spreadsheetKbTarget?.closest?.(
|
|
2051
|
+
'button, a[href], input, select, textarea, [contenteditable="true"]',
|
|
2052
|
+
)
|
|
2012
2053
|
// 2026-07-05 D4 fix:spreadsheet 鍵盤入口 — selection 尚未建立時按方向鍵,seed 第一個
|
|
2013
2054
|
// visible cell(原本唯一 set 起點是 mouse click → 鍵盤-only 使用者 Tab 進 table 後方向鍵
|
|
2014
2055
|
// 全 no-op,整個 spreadsheet 導覽被滑鼠 gate,違反 spec「鍵盤完整可操作」驗證宣稱。
|
|
2015
2056
|
// 對齊 Excel / Google Sheets / AG Grid「focus grid → first cell active」canonical)。
|
|
2016
|
-
if (spreadsheetMode && selectedCellId == null && editingCellId == null
|
|
2057
|
+
if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId == null && editingCellId == null
|
|
2017
2058
|
&& ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
|
|
2018
2059
|
const allRows = table.getRowModel().rows.map((r) => r.id)
|
|
2019
2060
|
const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)
|
|
@@ -2026,7 +2067,7 @@ function DataTableInner<TData>(
|
|
|
2026
2067
|
}
|
|
2027
2068
|
return
|
|
2028
2069
|
}
|
|
2029
|
-
if (spreadsheetMode && selectedCellId != null && editingCellId == null) {
|
|
2070
|
+
if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId != null && editingCellId == null) {
|
|
2030
2071
|
const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Enter', 'F2', 'Escape']
|
|
2031
2072
|
if (!navKeys.includes(e.key)) return
|
|
2032
2073
|
const lastColon = selectedCellId.lastIndexOf(':')
|
|
@@ -2077,6 +2118,14 @@ function DataTableInner<TData>(
|
|
|
2077
2118
|
}
|
|
2078
2119
|
// ── Row selection mode keyboard handler(下方既有)──
|
|
2079
2120
|
if (!enabled) return
|
|
2121
|
+
// 2026-07-09 fix(圖一 Ctrl+A bug):焦點在可編輯輸入元素(cell edit / inline edit / 搜尋框)時,
|
|
2122
|
+
// 鍵盤(Cmd/Ctrl+A 全選、Esc)應交給該元素(全選 cell 文字 / 取消編輯),**不**攔成 row selection。
|
|
2123
|
+
// 對齊 Notion / Airtable / Linear:編輯格內 Ctrl+A = 選格內文字,非選全表列。
|
|
2124
|
+
const kbTarget = e.target as HTMLElement | null
|
|
2125
|
+
if (
|
|
2126
|
+
editingCellId != null ||
|
|
2127
|
+
(kbTarget && (kbTarget.tagName === 'INPUT' || kbTarget.tagName === 'TEXTAREA' || kbTarget.tagName === 'SELECT' || kbTarget.isContentEditable))
|
|
2128
|
+
) return
|
|
2080
2129
|
// Cmd/Ctrl+A:選全可見(扣 disabled)— 對齊 Mail / GitHub / Linear 慣例
|
|
2081
2130
|
if ((e.metaKey || e.ctrlKey) && e.key === 'a' && mode === 'multi') {
|
|
2082
2131
|
e.preventDefault()
|
|
@@ -2367,7 +2416,7 @@ function DataTableInner<TData>(
|
|
|
2367
2416
|
const meta = h.column.columnDef.meta as { locked?: boolean } | undefined
|
|
2368
2417
|
const isLocked = meta?.locked === true
|
|
2369
2418
|
const isSystem = isSystemColumn(colId)
|
|
2370
|
-
//
|
|
2419
|
+
// useDraggable + useDroppable per header(Rules of Hooks compliant — same hook count per render
|
|
2371
2420
|
// as long as headers count consistent;column reorder/hide 整 row reflow 自然觸發 React reconcile)。
|
|
2372
2421
|
// disabled=true 時仍 call hook 不啟動 listeners。
|
|
2373
2422
|
const isDraggable = enableColumnReorder && !isLocked && !isSystem
|
|
@@ -2417,13 +2466,13 @@ function DataTableInner<TData>(
|
|
|
2417
2466
|
const isPrimaryRegion = isCenter
|
|
2418
2467
|
const regionRole: 'primary' | 'mirror' = isPrimaryRegion ? 'primary' : 'mirror'
|
|
2419
2468
|
|
|
2420
|
-
// code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞
|
|
2469
|
+
// code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞 dnd-kit hooks 跟 row idx 的 stable binding
|
|
2421
2470
|
const rowEl = (row: typeof rows[number], idx: number, opts?: { virtual?: boolean; start?: number; isLast?: boolean }) => {
|
|
2422
2471
|
const showBorder = bordered !== false ? !opts?.isLast : true
|
|
2423
|
-
// L4 row drag v2:nested rows
|
|
2424
|
-
// sub-rows: depth>0
|
|
2472
|
+
// L4 row drag v2:nested rows 也可拖(配合 cross-parent collisionDetection 過濾)
|
|
2473
|
+
// sub-rows: depth>0 也各自掛 useDraggable/useDroppable,但 collisionDetection 只接受 same-parent over
|
|
2425
2474
|
const isThisRowDragging = enableRowDrag && activeDragId === row.id
|
|
2426
|
-
const
|
|
2475
|
+
const dragRowWrap = enableRowDrag
|
|
2427
2476
|
|
|
2428
2477
|
// H1 fix(2026-05-10,per user 確認):per-row autoRowHeight when any cell in this row has
|
|
2429
2478
|
// error。Fixed-height row 模式下,該 row 的任一 cell 有 error msg → THAT row 自動 auto-height
|
|
@@ -2525,20 +2574,20 @@ function DataTableInner<TData>(
|
|
|
2525
2574
|
</div>
|
|
2526
2575
|
)
|
|
2527
2576
|
|
|
2528
|
-
if (
|
|
2577
|
+
if (dragRowWrap) {
|
|
2529
2578
|
// invalidDrop 只對「正在被拖」的 row 顯示 — handle 在 active row 上,UI 警示只需該 row
|
|
2530
|
-
// code-quality-allow: long-function — 此 const 之下的整個 if-block 含
|
|
2579
|
+
// code-quality-allow: long-function — 此 const 之下的整個 if-block 含 dnd-kit hooks + SortableRowProvider + baseRowDiv composition;audit 把 const 誤認為 function entry,實 long body 在 closure 內 dnd-kit + per-row state 多 capture,拆會破壞 hook order invariant
|
|
2531
2580
|
const rowInvalidDrop = isThisRowDragging && invalidDropActive
|
|
2532
2581
|
return (
|
|
2533
2582
|
<SortableRowProvider key={row.id} id={row.id} disabled={dragDisabled} role={regionRole} invalidDrop={rowInvalidDrop}>
|
|
2534
2583
|
{(ctx) => baseRowDiv({
|
|
2535
|
-
//
|
|
2536
|
-
//
|
|
2584
|
+
// primary 掛 useDraggable+useDroppable 合成 ref;mirror 只掛 useDroppable ref
|
|
2585
|
+
// (v15.4 split — mirror 不進 drag source store,isDragging 走 useDndContext 同步)
|
|
2537
2586
|
ref: ctx.setNodeRef,
|
|
2538
2587
|
style: ctx.style,
|
|
2539
2588
|
isDragging: ctx.isDragging,
|
|
2540
|
-
// v15.
|
|
2541
|
-
//
|
|
2589
|
+
// v15.6 button-only:rowListeners 恆 undefined(activator = RowDragHandle Button),
|
|
2590
|
+
// baseRowDiv spread `{...(extra?.listeners ?? {})}` 自動 noop;attributes 留空 = row 純 container
|
|
2542
2591
|
listeners: ctx.rowListeners,
|
|
2543
2592
|
attributes: ctx.rowAttributes,
|
|
2544
2593
|
})}
|
|
@@ -2619,10 +2668,10 @@ function DataTableInner<TData>(
|
|
|
2619
2668
|
)}
|
|
2620
2669
|
{/* Header 的 center 區保持 overflow-hidden(非 scroll)—— body 的 center 才有 scroll,
|
|
2621
2670
|
header 靠 JS 同步 scrollLeft(見 onCenterBodyScroll)。這樣不會出現雙 scrollbar。
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2671
|
+
V scrollbar 對齊:centerBody **刻意不用** `scrollbar-gutter: stable`(決策見 centerBody
|
|
2672
|
+
className 註解 — 永久預留 15px 會讓 content-fit 看起來像恆有 V 捲軸);trade-off =
|
|
2673
|
+
V scroll 出現時 body 內側少 ~15px、header 不縮 → 右端微 misalign,content-fit 乾淨優先。
|
|
2674
|
+
header 的 `scrollbar-gutter` 本就無效(overflow-hidden),刻意不設 */}
|
|
2626
2675
|
<div
|
|
2627
2676
|
ref={centerHeaderRef}
|
|
2628
2677
|
data-datatable-header-panel="center"
|
|
@@ -2670,8 +2719,6 @@ function DataTableInner<TData>(
|
|
|
2670
2719
|
<div
|
|
2671
2720
|
ref={centerBodyRef}
|
|
2672
2721
|
// Center body 同時擁有 H + V scroll;maxHeight 限制讓 H scrollbar 落在 visible 底部
|
|
2673
|
-
// `scrollbar-gutter: stable` 永遠預留 V scrollbar 寬度(~15-17px),避免 body 出現 V
|
|
2674
|
-
// scrollbar 時右端被縮,跟 header 右端產生 gap(Windows/Linux native scrollbar 吃寬)
|
|
2675
2722
|
data-datatable-hscroll
|
|
2676
2723
|
data-datatable-panel="center"
|
|
2677
2724
|
// overflow-x/y: auto — 沒 overflow 就不顯 bar。wrapper minWidth 仍 trigger H 真 overflow。
|
|
@@ -2837,13 +2884,12 @@ function DataTableInner<TData>(
|
|
|
2837
2884
|
</div>
|
|
2838
2885
|
)
|
|
2839
2886
|
} : undefined}
|
|
2840
|
-
// Slice D Step 4 spreadsheet semantics(2026-05-10):
|
|
2841
|
-
// selectedCellId(click 1)= solid border
|
|
2842
|
-
//
|
|
2843
|
-
// CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫
|
|
2844
|
-
// RangeOuterRing
|
|
2887
|
+
// Slice D Step 4 spreadsheet semantics(2026-05-10;2026-07-14 對齊清理):
|
|
2888
|
+
// selectedCellId(click 1)= solid border SelectionRing z 2
|
|
2889
|
+
// range(Shift+click rectangle from anchor↔focus)= cell-bg fill via
|
|
2890
|
+
// CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫 range 視覺,
|
|
2891
|
+
// RangeOuterRing / rangeCellIds prop 已 retire)
|
|
2845
2892
|
selectedCellId={spreadsheetMode ? selectedCellId : null}
|
|
2846
|
-
rangeCellIds={rangeCellIds}
|
|
2847
2893
|
cellClickEntersEdit={(cellId) => {
|
|
2848
2894
|
// 2026-05-10 codex review red light fix(per dual-track verify):
|
|
2849
2895
|
// 1. cellId parse 用 lastIndexOf(':')(row id 可含 colon)
|
|
@@ -2872,14 +2918,14 @@ function DataTableInner<TData>(
|
|
|
2872
2918
|
|
|
2873
2919
|
// ── L4 Row drag DnD wrapper ───────────────────────────────────────────────
|
|
2874
2920
|
// Sensors:Pointer(8px activation distance,避免 cell click 誤觸 drag)+ Keyboard(a11y)
|
|
2875
|
-
// SortableContext
|
|
2876
|
-
// 同 parent level
|
|
2921
|
+
// v15.0 Path B:無 SortableContext — 每 row 各自 useDraggable / useDroppable;
|
|
2922
|
+
// 同 parent level 限制由自訂 collisionDetection 過濾 cross-parent target 成立(cross-parent over → invalidDrop)。
|
|
2877
2923
|
// DragEnd:active.id / over.id → 算 position(active vs over 視覺位置),呼叫 onRowReorder。
|
|
2878
2924
|
// hooks 必呼叫(rules-of-hooks)— 即使 enableRowDrag=false 也走 useSensors;wrap 才條件化。
|
|
2879
2925
|
// **codex P1 fix(2026-05-07 v15.13)**:KeyboardSensor 不傳 `coordinateGetter`,用
|
|
2880
2926
|
// dnd-kit 預設 25px 箭頭 stepping。`sortableKeyboardCoordinates` 是 `@dnd-kit/sortable`
|
|
2881
2927
|
// preset,需 `<SortableContext>` 才正確 resolve 下一個 sortable target — 但 v15.0
|
|
2882
|
-
// path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(
|
|
2928
|
+
// path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(見檔頭 import 註解),
|
|
2883
2929
|
// 此 getter 在無 context 下 keyboard nav 無法 reliable resolve target → keyboard
|
|
2884
2930
|
// drag/reorder regression。Default getter(arrow-key Δ25px)在 useDraggable 場景是
|
|
2885
2931
|
// dnd-kit canonical(`@dnd-kit/core/src/sensors/keyboard/defaults.ts` 預設行為)。
|
|
@@ -3157,7 +3203,7 @@ function DataTableInner<TData>(
|
|
|
3157
3203
|
// ── L5 分頁列(2026-07-06,詳 data-table.spec.md「L5:分頁」段)────────────────
|
|
3158
3204
|
// 間距 tight = layoutSpace spec 規則 3「跨範疇 functional 交互」;頁碼靠右(shadcn justify-end /
|
|
3159
3205
|
// Ant Table bottomEnd / MUI / Carbon 4 家實證,左側空也靠右);「共 N 筆」數源 = filter 後全集
|
|
3160
|
-
// getPrePaginationRowModel(≠ selection all-mode 的
|
|
3206
|
+
// getPrePaginationRowModel(≠ selection all-mode 的 server-side 全集數 M — consumer 自持,語意不同)。
|
|
3161
3207
|
// 2026-07-06 user 拍板:「Pagination 元件本身提供完整功能(showTotal / 每頁筆數)= SSOT,
|
|
3162
3208
|
// Table 按一致定義套用」—— 分頁列的資訊/選單/「資訊左、操作右」layout 全部 own 在
|
|
3163
3209
|
// <Pagination> 完整形態;DataTable 只轉發 config + own TanStack state(controlled 消費:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Advanced Filter 設計原則(Operator × ColumnType × ValueShape SSOT,v3)
|
|
2
2
|
|
|
3
|
-
> **狀態**:已落地 — registry 寫成 `filter-operators.ts`,`filter-tree.ts` + `data-table-filter-panel.tsx`
|
|
3
|
+
> **狀態**:已落地 — registry 寫成 `filter-operators.ts`,`filter-tree.ts` + filter panel 家族消費(`data-table-filter-panel.tsx`;row/picker 直接消費點在 2026-07-14 拆檔子模組 `data-table-filter-group.tsx` / `data-table-filter-value-picker.tsx`)(原 draft 兩個升級條件皆已達成,2026-06-11 對齊)。
|
|
4
4
|
> **M8 benchmark**:對照 ClickUp(CU)/ Airtable(AT)/ Notion(NT)三家。**v3 加 datetime / includeTime + 砍 number.between(2/3 業界共識)**。
|
|
5
5
|
> **設計路線**:**ClickUp 為 baseline**,合理 + 不衝突 + 真實用的擴充採納。
|
|
6
6
|
> **檔位**:暫放 DataTable/,若決定抽 `patterns/advanced-filter/` 再搬。
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
| 1-to-1 比對 | ✓ `is` / `is_not`(picker 多選 OR-語意) | ✗ 不適用(陣列比單值 ambiguous) |
|
|
134
134
|
| 集合運算 | ✗ 不適用 | ✓ `has_any_of` / `has_all_of` / `has_none_of` |
|
|
135
135
|
|
|
136
|
-
差異**根源於 cell 資料形狀**,不是 picker 不同。Value picker 兩者都共用 `<Combobox>` DS 既有元件(code 真值 `data-table-filter-
|
|
136
|
+
差異**根源於 cell 資料形狀**,不是 picker 不同。Value picker 兩者都共用 `<Combobox>` DS 既有元件(code 真值 `data-table-filter-value-picker.tsx` select_multi case;2026-07-14 拆檔自 panel)。
|
|
137
137
|
|
|
138
138
|
### `person`(4 ops — 跟 select 同邏輯)
|
|
139
139
|
| op key | 中 | en | valueShape | CU | AT | NT |
|
|
@@ -238,7 +238,7 @@
|
|
|
238
238
|
|
|
239
239
|
**技術坑(信心 85%,Phase B spec.md 詳)**:TanStack `ColumnFiltersState` per-column 一筆 filter value,N 條同 column 會 AND-chain 不能 OR。**業界標準解法**:棄用 `columnFilters`,改自管 FilterTree state + 用 `globalFilter` + 自訂 `globalFilterFn` 走樹求 boolean。
|
|
240
240
|
|
|
241
|
-
## 8. 邊界案例(code 真值 — `filter-tree.ts` /
|
|
241
|
+
## 8. 邊界案例(code 真值 — `filter-tree.ts` / filter panel 家族:`data-table-filter-panel.tsx` + `data-table-filter-group.tsx`)
|
|
242
242
|
|
|
243
243
|
- **Condition 值空 / 未選 field**:視為 incomplete,求值 **pass-through**(不過濾任何 row);空值 ≠ `is_not_set`(後者是顯式 op)— `isConditionComplete` 守門
|
|
244
244
|
- **群組刪光 condition**:空群組保留並 pass-through(true),panel 顯示「移除空群組」按鈕由 user 顯式刪除,不自動消失
|
|
@@ -3,3 +3,6 @@
|
|
|
3
3
|
// import { ... } from '@qijenchen/design-system/{components,patterns}/<Dir>'
|
|
4
4
|
// Regenerate: node scripts/gen-component-indexes.mjs
|
|
5
5
|
export * from './data-table'
|
|
6
|
+
export * from './data-table-column-visibility-panel'
|
|
7
|
+
export * from './data-table-filter-panel'
|
|
8
|
+
export * from './data-table-sort-manager'
|
|
@@ -38,7 +38,7 @@ interface PartSpec {
|
|
|
38
38
|
const PARTS: Record<PartKey, PartSpec> = {
|
|
39
39
|
caption: { label: '月份標題', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'text-body font-medium' },
|
|
40
40
|
nav: { label: 'Nav 按鈕', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'Button variant=text size=xs iconOnly · hover 藍圈' },
|
|
41
|
-
weekday: { label: '星期標頭', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'text-body font-medium · h-
|
|
41
|
+
weekday: { label: '星期標頭', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'text-body font-medium · h-field-sm(28/32 隨 density)' },
|
|
42
42
|
day: { label: '日格(default)', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'h-field-sm w-[var(--field-height-sm)] rounded-full' },
|
|
43
43
|
daySelected: { label: 'Selected', bg: '--primary', text: 'white', border: 'transparent' },
|
|
44
44
|
dayToday: { label: 'Today(未選)', bg: 'transparent', text: '--foreground', border: 'transparent', extra: '數字下方藍色底線(underline bar)' },
|
|
@@ -83,7 +83,7 @@ export const Overview = {
|
|
|
83
83
|
<div className="flex flex-col gap-10">
|
|
84
84
|
<div>
|
|
85
85
|
<H3>結構(Anatomy)</H3>
|
|
86
|
-
<Desc>DateGrid 由四個區塊組成:月份 caption、星期標頭、日期網格、左右 nav
|
|
86
|
+
<Desc>DateGrid 由四個區塊組成:月份 caption、星期標頭、日期網格、左右 nav 按鈕。各區塊以 classNames prop 用 DS token 覆寫 react-day-picker 的視覺樣式;元件載入 RDP style.css 作結構基底,未覆寫的結構 key 沿用原生 .rdp-* 預設。</Desc>
|
|
87
87
|
|
|
88
88
|
<div className="inline-flex flex-col gap-2 border-2 border-dashed border-primary/30 rounded-lg p-4 bg-surface">
|
|
89
89
|
<div className="flex items-center justify-between gap-2">
|
|
@@ -211,7 +211,7 @@ export const Inspector = {
|
|
|
211
211
|
<Legend c={Z.pad} label="外層 p-3" />
|
|
212
212
|
<Legend c={Z.head} label="月份 caption h-field-xs" />
|
|
213
213
|
<Legend c={Z.grid} label="日格 h-field-sm" />
|
|
214
|
-
<Legend c={Z.cell} label="星期標頭 h-
|
|
214
|
+
<Legend c={Z.cell} label="星期標頭 h-field-sm" />
|
|
215
215
|
</div>
|
|
216
216
|
|
|
217
217
|
<div className="inline-flex flex-col gap-0 rounded-md overflow-hidden" style={{ padding: 12, background: Z.pad.bg, border: `2px solid rgba(0,0,0,0.1)` }}>
|
|
@@ -248,7 +248,7 @@ export const Inspector = {
|
|
|
248
248
|
<PropRow label="外層 padding">p-3 · 12px</PropRow>
|
|
249
249
|
<PropRow label="月份並排 gap">gap-4 · 16px</PropRow>
|
|
250
250
|
<PropRow label="日格尺寸">h-field-sm · 28×28 (md) / 32×32 (lg)</PropRow>
|
|
251
|
-
<PropRow label="星期標頭">h-
|
|
251
|
+
<PropRow label="星期標頭">h-field-sm · md 28 / lg 32(與 day cell 同 token 同節奏;寬度 table-native 自動)</PropRow>
|
|
252
252
|
<PropRow label="Nav 按鈕">size=xs iconOnly · 24×24</PropRow>
|
|
253
253
|
<PropRow label="Cell gap">border-spacing-1 · 4px(H+V)</PropRow>
|
|
254
254
|
</div>
|
|
@@ -304,7 +304,7 @@ export const LocaleRule: Story = {
|
|
|
304
304
|
<div>
|
|
305
305
|
<Rule
|
|
306
306
|
title="locale prop 控制週首日與星期標頭語言"
|
|
307
|
-
note="react-day-picker 接受 date-fns locale 物件。週首日由 locale 物件決定,不以語言籠統判斷:en-US 週日起、en-GB 週一起——同樣是英文,週首日就不同;zhTW / de / fr(date-fns 內建值)都是週一起。下方對照:zhTW 首欄是週一,en-US 首欄是週日。Consumer 決定傳哪個 locale
|
|
307
|
+
note="react-day-picker 接受 date-fns locale 物件。週首日由 locale 物件決定,不以語言籠統判斷:en-US 週日起、en-GB 週一起——同樣是英文,週首日就不同;zhTW / de / fr(date-fns 內建值)都是週一起。下方對照:zhTW 首欄是週一,en-US 首欄是週日。Consumer 決定傳哪個 locale;locale 只控制「可見」的日期格式與週首日,不內建可見語言層。註:螢幕報讀器 aria-label(上/下月、日期朗讀等)DS 內建繁中 default,可透過 labels prop 逐鍵覆寫做 i18n(見 tsx labels 段)。"
|
|
308
308
|
>
|
|
309
309
|
<Demo title="zhTW(繁體中文 · 週一起)">
|
|
310
310
|
<DateGrid mode="single" defaultMonth={new Date(2026, 3, 1)} locale={zhTW} />
|
|
@@ -22,7 +22,7 @@ benchmark:
|
|
|
22
22
|
|
|
23
23
|
DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後導航 + 日 cell),**不直接面向 consumer**。2026-04-21 從原本的 `Calendar/` 改名為 `DateGrid/`,因為「Calendar」此命名在世界級 DS 慣例專指**事件檢視 canvas**(見 `../Calendar/calendar.spec.md`),而本元件只是「選日期用的格網」,不做事件呈現。保留 Calendar 名字給 event view 元件是世界級對齊。
|
|
24
24
|
|
|
25
|
-
**實作基礎**:`react-day-picker@9` 包裝 + 本 DS token
|
|
25
|
+
**實作基礎**:`react-day-picker@9` 包裝 + 本 DS token 覆寫預設視覺。**載入 RDP `style.css` 為結構基底**(tsx `import 'react-day-picker/style.css'`),再以 `classNames` prop 逐 key 用 DS token 覆寫視覺層(caption / weekday / day / range 等);**未列出的結構 key 沿用 RDP 原生 `.rdp-*` 預設**。故非「零 rdp-*」,而是「DS token 管視覺層、rdp-* 提供結構層」。
|
|
26
26
|
|
|
27
27
|
**Layout Family**:非上述 family — composite / multi-section(月份 caption + 星期標頭 + 日期網格 + nav 按鈕,多區塊組合)。
|
|
28
28
|
|
|
@@ -108,7 +108,9 @@ const DateGrid = React.forwardRef<HTMLDivElement, DateGridProps>(function DateGr
|
|
|
108
108
|
// weekday 列標跟 caption「April 2026」同視覺權重(都屬 calendar header 區),
|
|
109
109
|
// 不弱化(撤銷 v3 fg-secondary 的 mistake)。對齊 icon-only Button 預設 neutral-9 一致。
|
|
110
110
|
'text-foreground text-body font-medium',
|
|
111
|
-
|
|
111
|
+
// h-field-sm(md=28/lg=32 隨 density):對齊 day cell 同 token 同 row cadence
|
|
112
|
+
// (spec:127 既定 canonical;Ant 36/36、Carbon 40/40 header/day 同節奏;2026-07-14 修 h-7 固定 drift)
|
|
113
|
+
'h-[var(--field-height-sm)] align-middle text-center',
|
|
112
114
|
),
|
|
113
115
|
week: '', // tr default
|
|
114
116
|
// Cell **就是** button 容器(28×28 @ md / 32×32 @ lg),`relative` 讓 before pseudo 定位
|