@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
|
@@ -152,9 +152,6 @@ export interface DataTableProps<TData>
|
|
|
152
152
|
defaultSelection?: string[] | DataTableSelection
|
|
153
153
|
/** Selection 變更 callback(emit DataTableSelection union;include / all 兩模型) */
|
|
154
154
|
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
155
|
/** 是否啟用 selection / 模式;true 等同 'multi' */
|
|
159
156
|
selectable?: boolean | 'single' | 'multi'
|
|
160
157
|
/** Row 是否可選(disabled rows 只 disable checkbox,row 內容正常 render) */
|
|
@@ -203,7 +200,7 @@ export interface DataTableProps<TData>
|
|
|
203
200
|
*
|
|
204
201
|
* **v2(2026-05-05)修正**:
|
|
205
202
|
* - Virtualizer × transform:被拖 row 略過 `measureElement`(透過 SortableRowCtx 廣播 active id),避免 transform 干擾測量
|
|
206
|
-
* - 3-panel mirror sync
|
|
203
|
+
* - 3-panel mirror sync:primary region 呼叫 `useDraggable` + `useDroppable`;mirror region 只 `useDroppable`(v15.4 split),isDragging 由 `useDndContext` active.id 同步 → 三 region 視覺一致
|
|
207
204
|
* - Cross-parent drop:nested 全 row 各自 `useDroppable`,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`
|
|
208
205
|
*
|
|
209
206
|
* 詳 `data-table.spec.md`「L4 Row drag」段。
|
|
@@ -265,7 +262,7 @@ export interface DataTablePaginationOptions {
|
|
|
265
262
|
pageSize?: number
|
|
266
263
|
/** 每頁筆數選項;傳了才渲染「每頁 N 筆」Select(消費既有 Select size="sm") */
|
|
267
264
|
pageSizeOptions?: number[]
|
|
268
|
-
/** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的
|
|
265
|
+
/** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 server-side 全集數 M — 那是 consumer 自持) */
|
|
269
266
|
showTotal?: boolean
|
|
270
267
|
/** 當前頁(1-based,controlled;不傳 = uncontrolled) */
|
|
271
268
|
page?: number
|
|
@@ -312,7 +309,9 @@ const SELECT_COL_ID = '__select__'
|
|
|
312
309
|
* 解決「全選 10k 筆只載 50 筆 → 無法列舉其餘 ID」:all 模式「選取 = 全集 − excluded」,
|
|
313
310
|
* 任何 toggle 都只是 excluded 的 add/remove,對任意順序封閉、O(1)、不需列舉未載入 ID。
|
|
314
311
|
*
|
|
315
|
-
* 計數(consumer):mode==='all' ?
|
|
312
|
+
* 計數(consumer):mode==='all' ? M − excluded.length : ids.length(M = consumer 自持的
|
|
313
|
+
* server-side / filter 後全集筆數;2026-07-13 D1 拍板:DataTable 不收 totalCount prop — DS 內部
|
|
314
|
+
* 零消費 no-op 已移除,計數本來就全由 consumer 端算)。
|
|
316
315
|
* 進入 all 模式:consumer 在「選取全部 M」hint 點擊時 setSelection({ mode: 'all', excluded: [] })。
|
|
317
316
|
*/
|
|
318
317
|
export type DataTableSelection =
|
|
@@ -446,12 +445,13 @@ function TruncateCell({ children, className }: { children: React.ReactNode; clas
|
|
|
446
445
|
return <Tooltip><TooltipTrigger asChild>{span}</TooltipTrigger><TooltipContent>{children}</TooltipContent></Tooltip>
|
|
447
446
|
}
|
|
448
447
|
|
|
449
|
-
// ── L4 Row Drag: SortableRowContext
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
//
|
|
454
|
-
//
|
|
448
|
+
// ── L4 Row Drag: SortableRowContext(v15 Path B;2026-07-14 JSDoc 對齊實作)──────
|
|
449
|
+
// 每 region(left / center / right)各 mount 一次 SortableRowProvider,依 role 分流(v15.4 split):
|
|
450
|
+
// primary → SourceRowProvider(useDraggable + useDroppable)= 唯一 drag source;
|
|
451
|
+
// mirror → MirrorRowProvider(useDroppable only),isDragging 走 useDndContext active.id 同步。
|
|
452
|
+
// 無 SortableContext / useSortable(v15.0 Path B 已砍,見檔頭 import 註解)。listeners 全走
|
|
453
|
+
// RowDragHandle Button(v15.6 button-only;row 本身不接 listeners)。primary = left region 若存在否則 center。
|
|
454
|
+
// `invalidDrop`(cross-parent over)走 prop 廣播給 RowDragHandle 切 cursor-not-allowed。
|
|
455
455
|
interface SortableRowCtxValue {
|
|
456
456
|
setNodeRef: (el: HTMLElement | null) => void
|
|
457
457
|
role: 'primary' | 'mirror'
|
|
@@ -477,10 +477,11 @@ interface SortableRowCtxValue {
|
|
|
477
477
|
}
|
|
478
478
|
const SortableRowCtx = React.createContext<SortableRowCtxValue | null>(null)
|
|
479
479
|
|
|
480
|
-
/** Per-region per-row
|
|
481
|
-
* 同 row.id 在 left/center/right 三 region 各 mount
|
|
482
|
-
*
|
|
483
|
-
*
|
|
480
|
+
/** Per-region per-row drag wrapper(v15.4 architectural split)。
|
|
481
|
+
* 同 row.id 在 left/center/right 三 region 各 mount 一次,但 hook mount tree 完全分離:
|
|
482
|
+
* primary → SourceRowProvider(useDraggable + useDroppable);mirror → MirrorRowProvider
|
|
483
|
+
* (useDroppable only,isDragging 由 useDndContext 同步)。activator / listeners 只給
|
|
484
|
+
* primary 的 RowDragHandle Button(v15.6 button-only);mirror 不提供避免雙觸發。 */
|
|
484
485
|
function SortableRowProvider(props: {
|
|
485
486
|
id: string
|
|
486
487
|
disabled?: boolean
|
|
@@ -593,14 +594,15 @@ function MirrorRowProvider({
|
|
|
593
594
|
return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>
|
|
594
595
|
}
|
|
595
596
|
|
|
596
|
-
/** DraggableHeaderCell — wrap header cell 跟 dnd-kit
|
|
597
|
+
/** DraggableHeaderCell — wrap header cell 跟 dnd-kit useDraggable + useDroppable 接軌
|
|
598
|
+
* (2026-05-06 v14.2;v15.0 Path B 改分離 hooks,無 SortableContext)。
|
|
597
599
|
*
|
|
598
600
|
* Why wrap-not-rewrite:`headerCellEl` 既有邏輯複雜(sort / resize / select column / right region 等),
|
|
599
|
-
* 改 inline
|
|
601
|
+
* 改 inline useDraggable/useDroppable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render
|
|
600
602
|
* 保持 untouched,單一職責 = 加 drag affordance。
|
|
601
603
|
*
|
|
602
604
|
* Behavior:
|
|
603
|
-
* -
|
|
605
|
+
* - useDraggable + useDroppable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners
|
|
604
606
|
* - `data: { type: 'column', columnId }` 餵 dnd-kit handleDragStart / handleDragEnd 區分 row/column drag
|
|
605
607
|
* - 注入 ref(setNodeRef)+ transform style + transition + opacity(drag 時 source invisible,DragOverlay 顯 ghost)
|
|
606
608
|
* - draggable 時注入 attributes + listeners + cursor:grab / `data-column-id` (DragOverlay snapshot 用)
|
|
@@ -660,8 +662,9 @@ function DraggableHeaderCell({
|
|
|
660
662
|
|
|
661
663
|
/** Row drag handle — Portal-rendered, position:fixed 真正水平置中於 table outer border line(Jira canonical)。
|
|
662
664
|
*
|
|
663
|
-
* v15.
|
|
664
|
-
*
|
|
665
|
+
* v15.6 button-only drag(推翻 v15.2「整列接 listeners」,2026-07-14 JSDoc 對齊):Button =
|
|
666
|
+
* 唯一 activator,接 handleSetActivatorNodeRef + handleListeners(SourceRowProvider ctx);
|
|
667
|
+
* row div 不接 listeners(rowListeners=undefined),row click 保留給 select / open detail 等 UX。
|
|
665
668
|
*
|
|
666
669
|
* Why Portal + position:fixed(2026-05-05 v4):
|
|
667
670
|
* DataTable 結構含三層 overflow-hidden(outer wrapper / leftBody / row),用 absolute + translate-x:-50%
|
|
@@ -923,7 +926,6 @@ function DataTableInner<TData>(
|
|
|
923
926
|
estimateRowHeight, tableOptions, rowActions, cellErrors,
|
|
924
927
|
pinnedLeftColumns, pinnedRightColumns, inlineEdit = false,
|
|
925
928
|
selection: selectionProp, defaultSelection, onSelectionChange,
|
|
926
|
-
totalCount,
|
|
927
929
|
selectable = false, isRowSelectable, getRowId, getRowAriaLabel,
|
|
928
930
|
preserveSelectionOnFilter = false,
|
|
929
931
|
columnVisibility: columnVisibilityProp, defaultColumnVisibility, onColumnVisibilityChange,
|
|
@@ -1262,7 +1264,7 @@ function DataTableInner<TData>(
|
|
|
1262
1264
|
// 2026-05-06 v10 DragOverlay canonical:retire windowed sticky range extractor (v4-v9 workaround)。
|
|
1263
1265
|
// 改用 `<DragOverlay>` portal 把 source row 視覺解耦 — source 即使 unmount(virtual scroll out)
|
|
1264
1266
|
// overlay 仍 render 由 cloned outerHTML 提供視覺。dnd-kit transform / collision 走 active item id
|
|
1265
|
-
// (
|
|
1267
|
+
// (DndContext store 以 active id 追蹤,跟 hook instance mount 狀態無關;v15 無 SortableContext)。
|
|
1266
1268
|
// 對齊 dnd-kit GitHub #1674 + drag-overlay docs canonical「virtualized list MUST use DragOverlay」。
|
|
1267
1269
|
// overscan 仍輕微拉高(避免 source row 旁邊 rows 也 unmount 致使 hover signal 計算抖動)。
|
|
1268
1270
|
const effectiveOverscan = enableRowDrag ? Math.max(overscan, 5) : overscan
|
|
@@ -1392,10 +1394,9 @@ function DataTableInner<TData>(
|
|
|
1392
1394
|
|
|
1393
1395
|
// ── Phase 9 Issue 1 fix(2026-05-10):range cells lifted compute + Set ────
|
|
1394
1396
|
// 計算 spreadsheet range cell IDs(Shift+click rectangle from anchor↔focus),
|
|
1395
|
-
//
|
|
1396
|
-
//
|
|
1397
|
-
//
|
|
1398
|
-
// (per codex Q1 verdict:bg fill 移到 cell bg layer 不在 overlay,內容才不被蓋)
|
|
1397
|
+
// 提供 `rangeCellIdSet` Set → cell wrapper data-range-cell attr for cell-bg fill
|
|
1398
|
+
// (per codex Q1 verdict:bg fill 走 cell bg layer 不在 overlay,內容才不被蓋;
|
|
1399
|
+
// layer 的 outer ring / rangeCellIds prop 已 retire — 2026-07-14 對齊清理)
|
|
1399
1400
|
const rangeCellIds = React.useMemo<string[] | undefined>(() => {
|
|
1400
1401
|
if (!spreadsheetMode || !rangeAnchor || !rangeFocus || rangeAnchor === rangeFocus) return undefined
|
|
1401
1402
|
const parseCell = (id: string) => {
|
|
@@ -1452,7 +1453,13 @@ function DataTableInner<TData>(
|
|
|
1452
1453
|
return () => obs.disconnect()
|
|
1453
1454
|
}, [hasLeft, hasRight, rows.length])
|
|
1454
1455
|
|
|
1455
|
-
|
|
1456
|
+
// 2026-07-09 root-cause fix(user 以 GitHub Pages 對比抓出 regression):
|
|
1457
|
+
// 舊 `h-table-row-${size}` 模板字串 Tailwind **靜態掃描看不到** → `.h-table-row-{sm,md,lg}` 規則
|
|
1458
|
+
// 唯一靠 uiSize.spec.md 裡的 literal 被 content-detection 掃到才生成;戰役期間掃描樹變動後未生成
|
|
1459
|
+
// → 規則消失 → row 塌成「內容高度」(非編輯 33px / 編輯 44px)而非固定 token 40px,連帶選取控件與
|
|
1460
|
+
// 列文字對不齊。改用 literal map(對齊 field-wrapper cva 的 `h-field-md` literal 慣例),Tailwind
|
|
1461
|
+
// 永遠掃得到、不再依賴脆弱的 spec.md literal → 永不再漂移。
|
|
1462
|
+
const rowHeight = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size] ?? 'h-table-row-md'
|
|
1456
1463
|
|
|
1457
1464
|
// ── Cross-region row hover (2026-04-22 D3 perf audit):event delegation 改 per-row closure
|
|
1458
1465
|
// 舊:每 row 建 `{ onMouseEnter, onMouseLeave }` + 2 arrow functions → 100 row = 200 closures/render
|
|
@@ -1573,8 +1580,8 @@ function DataTableInner<TData>(
|
|
|
1573
1580
|
const dragDisabled = sorting.length > 0
|
|
1574
1581
|
|
|
1575
1582
|
// ── L4 Row drag v2:nested rows + parent map ─────────────────────────────────
|
|
1576
|
-
// v2 cross-parent fix:全 row
|
|
1577
|
-
// 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
|
|
1583
|
+
// v2 cross-parent fix:全 row 各自掛 useDraggable/useDroppable(含 sub-rows;v15 無 SortableContext),
|
|
1584
|
+
// custom collisionDetection 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
|
|
1578
1585
|
// parentMap: rowId → parentId(top-level row 的 parent = '' 哨兵 string)
|
|
1579
1586
|
const { allRowIds, parentMap } = React.useMemo(() => {
|
|
1580
1587
|
const ids: string[] = []
|
|
@@ -1725,7 +1732,13 @@ function DataTableInner<TData>(
|
|
|
1725
1732
|
const canExpand = cell.row.getCanExpand?.() ?? false
|
|
1726
1733
|
const isExpanded = cell.row.getIsExpanded?.() ?? false
|
|
1727
1734
|
const toggleExpand = cell.row.getToggleExpandedHandler?.()
|
|
1728
|
-
|
|
1735
|
+
// 2026-07-08 sibling-aware 佔位(WM root-cause 戰役):spec:382「同層 sibling 有 expandable
|
|
1736
|
+
// 時 leaf 也佔位」原本沒實作 — depth-0 leaf(無 children 的頂層列)拿不到 w-4+mr-2 佔位,
|
|
1737
|
+
// 與同層有 chevron 的列左緣錯位(PDF「chevron 空間」問題)。同層 = 同 parent 的 subRows;
|
|
1738
|
+
// 頂層 = core rows。只在 isFirstContent 時計算,成本一列一次。
|
|
1739
|
+
const siblingRows = cell.row.getParentRow?.()?.subRows ?? table.getCoreRowModel().rows
|
|
1740
|
+
const siblingHasExpand = isFirstContent && siblingRows.some((r) => r.getCanExpand?.() ?? false)
|
|
1741
|
+
const showNestedPrefix = isFirstContent && (depth > 0 || canExpand || siblingHasExpand)
|
|
1729
1742
|
// Issue 9 cell error(2026-05-10):lookup `${rowId}:${colId}` in cellErrors map
|
|
1730
1743
|
// editing cell 自動 clear visual error(per spec 「edit-clears-own-cell」)— consumer 走
|
|
1731
1744
|
// onCellCommit 驗證後決定回填新 error(由 consumer 端控制 cellErrors map state)。
|
|
@@ -1802,6 +1815,9 @@ function DataTableInner<TData>(
|
|
|
1802
1815
|
// 跟 cell 4 邊 inset divider 視覺相疊(同 pixel)= 1 line visual,不雙線。
|
|
1803
1816
|
inlineEdit && 'dtCellGrid',
|
|
1804
1817
|
onEditableCellClick && ['cursor-pointer', nakedCellEditableDisplayHover], // editable cell display hover affordance(對齊 Notion / Airtable hover-cell-shows-border canonical)
|
|
1818
|
+
// a11y(2026-07-14 dim-10 修):非 spreadsheet inlineEdit cell 可 Tab 聚焦(見下方
|
|
1819
|
+
// tabIndex/onKeyDown)— focus-visible ring 對齊本檔 expand button / sortable header canonical。
|
|
1820
|
+
onEditableCellClick && !spreadsheetMode && 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',
|
|
1805
1821
|
// 2026-05-13 Q3 cell disabled SSOT(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):
|
|
1806
1822
|
// bg `--bg-disabled` component-state token(color.spec.md:671 owner)+ cursor 抑制 click affordance。
|
|
1807
1823
|
cellDisabled && 'bg-disabled cursor-not-allowed',
|
|
@@ -1818,6 +1834,19 @@ function DataTableInner<TData>(
|
|
|
1818
1834
|
...(experimentalSpreadsheetOverlay && { '--cell-hover-outline-color': 'transparent' } as React.CSSProperties),
|
|
1819
1835
|
}}
|
|
1820
1836
|
onClick={onEditableCellClick}
|
|
1837
|
+
// a11y(2026-07-14 dim-10 修):非 spreadsheet 的 inlineEdit cell 原本只有 onClick —
|
|
1838
|
+
// 鍵盤 user 無法聚焦 cell、無法進入編輯(WCAG 2.1.1)。對齊 Atlassian InlineEdit
|
|
1839
|
+
// read-view-focusable idiom:editable display cell 可 Tab 聚焦,Enter / F2 進 edit。
|
|
1840
|
+
// spreadsheetMode 不加(該模式走 table-level selectedCellId 鍵盤導覽 SSOT,per-cell
|
|
1841
|
+
// tab stop 會跟 roving 模型衝突);cell 內 embedded 控件事件不攔(target guard)。
|
|
1842
|
+
tabIndex={onEditableCellClick && !spreadsheetMode ? 0 : undefined}
|
|
1843
|
+
onKeyDown={onEditableCellClick && !spreadsheetMode ? (e) => {
|
|
1844
|
+
if (e.target !== e.currentTarget) return
|
|
1845
|
+
if (e.key === 'Enter' || e.key === 'F2') {
|
|
1846
|
+
e.preventDefault()
|
|
1847
|
+
setEditingCellId(cellEditId(cellRowId, cellColId))
|
|
1848
|
+
}
|
|
1849
|
+
} : undefined}
|
|
1821
1850
|
>
|
|
1822
1851
|
{/* Issue 9 cell error(2026-05-10):有 error → cell 內外結構切 flex-col,
|
|
1823
1852
|
上 row 渲既有 nested + content,下 row 渲 error message 14px text-error。
|
|
@@ -2009,11 +2038,20 @@ function DataTableInner<TData>(
|
|
|
2009
2038
|
// Phase B3 IME guard(2026-05-10 per codex Q-B3):中文輸入法組字中 ignore 所有 nav keys。
|
|
2010
2039
|
// 2026-05-16 Round 5 audit Dim 27 fix:`keyCode` deprecated but still in KeyboardEvent type — no cast needed。
|
|
2011
2040
|
if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return
|
|
2041
|
+
// 2026-07-14 dim-10 修:spreadsheet 分支排除 descendant 互動控件 — 焦點在 cell 內
|
|
2042
|
+
// action button / link / input 時,Enter 應 activate 該控件、方向鍵交還控件,
|
|
2043
|
+
// 原 handler 會 preventDefault 取消按鈕 activation、拿舊 selectedCellId 導覽。
|
|
2044
|
+
// 對齊下方 row-selection 分支 2026-07-09 既有 input-family guard + AG Grid
|
|
2045
|
+
// embedded-control convention(cell renderer 內控件 own keyboard)。
|
|
2046
|
+
const spreadsheetKbTarget = e.target as HTMLElement | null
|
|
2047
|
+
const targetIsEmbeddedControl = !!spreadsheetKbTarget?.closest?.(
|
|
2048
|
+
'button, a[href], input, select, textarea, [contenteditable="true"]',
|
|
2049
|
+
)
|
|
2012
2050
|
// 2026-07-05 D4 fix:spreadsheet 鍵盤入口 — selection 尚未建立時按方向鍵,seed 第一個
|
|
2013
2051
|
// visible cell(原本唯一 set 起點是 mouse click → 鍵盤-only 使用者 Tab 進 table 後方向鍵
|
|
2014
2052
|
// 全 no-op,整個 spreadsheet 導覽被滑鼠 gate,違反 spec「鍵盤完整可操作」驗證宣稱。
|
|
2015
2053
|
// 對齊 Excel / Google Sheets / AG Grid「focus grid → first cell active」canonical)。
|
|
2016
|
-
if (spreadsheetMode && selectedCellId == null && editingCellId == null
|
|
2054
|
+
if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId == null && editingCellId == null
|
|
2017
2055
|
&& ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
|
|
2018
2056
|
const allRows = table.getRowModel().rows.map((r) => r.id)
|
|
2019
2057
|
const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)
|
|
@@ -2026,7 +2064,7 @@ function DataTableInner<TData>(
|
|
|
2026
2064
|
}
|
|
2027
2065
|
return
|
|
2028
2066
|
}
|
|
2029
|
-
if (spreadsheetMode && selectedCellId != null && editingCellId == null) {
|
|
2067
|
+
if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId != null && editingCellId == null) {
|
|
2030
2068
|
const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Enter', 'F2', 'Escape']
|
|
2031
2069
|
if (!navKeys.includes(e.key)) return
|
|
2032
2070
|
const lastColon = selectedCellId.lastIndexOf(':')
|
|
@@ -2077,6 +2115,14 @@ function DataTableInner<TData>(
|
|
|
2077
2115
|
}
|
|
2078
2116
|
// ── Row selection mode keyboard handler(下方既有)──
|
|
2079
2117
|
if (!enabled) return
|
|
2118
|
+
// 2026-07-09 fix(圖一 Ctrl+A bug):焦點在可編輯輸入元素(cell edit / inline edit / 搜尋框)時,
|
|
2119
|
+
// 鍵盤(Cmd/Ctrl+A 全選、Esc)應交給該元素(全選 cell 文字 / 取消編輯),**不**攔成 row selection。
|
|
2120
|
+
// 對齊 Notion / Airtable / Linear:編輯格內 Ctrl+A = 選格內文字,非選全表列。
|
|
2121
|
+
const kbTarget = e.target as HTMLElement | null
|
|
2122
|
+
if (
|
|
2123
|
+
editingCellId != null ||
|
|
2124
|
+
(kbTarget && (kbTarget.tagName === 'INPUT' || kbTarget.tagName === 'TEXTAREA' || kbTarget.tagName === 'SELECT' || kbTarget.isContentEditable))
|
|
2125
|
+
) return
|
|
2080
2126
|
// Cmd/Ctrl+A:選全可見(扣 disabled)— 對齊 Mail / GitHub / Linear 慣例
|
|
2081
2127
|
if ((e.metaKey || e.ctrlKey) && e.key === 'a' && mode === 'multi') {
|
|
2082
2128
|
e.preventDefault()
|
|
@@ -2367,7 +2413,7 @@ function DataTableInner<TData>(
|
|
|
2367
2413
|
const meta = h.column.columnDef.meta as { locked?: boolean } | undefined
|
|
2368
2414
|
const isLocked = meta?.locked === true
|
|
2369
2415
|
const isSystem = isSystemColumn(colId)
|
|
2370
|
-
//
|
|
2416
|
+
// useDraggable + useDroppable per header(Rules of Hooks compliant — same hook count per render
|
|
2371
2417
|
// as long as headers count consistent;column reorder/hide 整 row reflow 自然觸發 React reconcile)。
|
|
2372
2418
|
// disabled=true 時仍 call hook 不啟動 listeners。
|
|
2373
2419
|
const isDraggable = enableColumnReorder && !isLocked && !isSystem
|
|
@@ -2417,13 +2463,13 @@ function DataTableInner<TData>(
|
|
|
2417
2463
|
const isPrimaryRegion = isCenter
|
|
2418
2464
|
const regionRole: 'primary' | 'mirror' = isPrimaryRegion ? 'primary' : 'mirror'
|
|
2419
2465
|
|
|
2420
|
-
// code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞
|
|
2466
|
+
// 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
2467
|
const rowEl = (row: typeof rows[number], idx: number, opts?: { virtual?: boolean; start?: number; isLast?: boolean }) => {
|
|
2422
2468
|
const showBorder = bordered !== false ? !opts?.isLast : true
|
|
2423
|
-
// L4 row drag v2:nested rows
|
|
2424
|
-
// sub-rows: depth>0
|
|
2469
|
+
// L4 row drag v2:nested rows 也可拖(配合 cross-parent collisionDetection 過濾)
|
|
2470
|
+
// sub-rows: depth>0 也各自掛 useDraggable/useDroppable,但 collisionDetection 只接受 same-parent over
|
|
2425
2471
|
const isThisRowDragging = enableRowDrag && activeDragId === row.id
|
|
2426
|
-
const
|
|
2472
|
+
const dragRowWrap = enableRowDrag
|
|
2427
2473
|
|
|
2428
2474
|
// H1 fix(2026-05-10,per user 確認):per-row autoRowHeight when any cell in this row has
|
|
2429
2475
|
// error。Fixed-height row 模式下,該 row 的任一 cell 有 error msg → THAT row 自動 auto-height
|
|
@@ -2525,20 +2571,20 @@ function DataTableInner<TData>(
|
|
|
2525
2571
|
</div>
|
|
2526
2572
|
)
|
|
2527
2573
|
|
|
2528
|
-
if (
|
|
2574
|
+
if (dragRowWrap) {
|
|
2529
2575
|
// invalidDrop 只對「正在被拖」的 row 顯示 — handle 在 active row 上,UI 警示只需該 row
|
|
2530
|
-
// code-quality-allow: long-function — 此 const 之下的整個 if-block 含
|
|
2576
|
+
// 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
2577
|
const rowInvalidDrop = isThisRowDragging && invalidDropActive
|
|
2532
2578
|
return (
|
|
2533
2579
|
<SortableRowProvider key={row.id} id={row.id} disabled={dragDisabled} role={regionRole} invalidDrop={rowInvalidDrop}>
|
|
2534
2580
|
{(ctx) => baseRowDiv({
|
|
2535
|
-
//
|
|
2536
|
-
//
|
|
2581
|
+
// primary 掛 useDraggable+useDroppable 合成 ref;mirror 只掛 useDroppable ref
|
|
2582
|
+
// (v15.4 split — mirror 不進 drag source store,isDragging 走 useDndContext 同步)
|
|
2537
2583
|
ref: ctx.setNodeRef,
|
|
2538
2584
|
style: ctx.style,
|
|
2539
2585
|
isDragging: ctx.isDragging,
|
|
2540
|
-
// v15.
|
|
2541
|
-
//
|
|
2586
|
+
// v15.6 button-only:rowListeners 恆 undefined(activator = RowDragHandle Button),
|
|
2587
|
+
// baseRowDiv spread `{...(extra?.listeners ?? {})}` 自動 noop;attributes 留空 = row 純 container
|
|
2542
2588
|
listeners: ctx.rowListeners,
|
|
2543
2589
|
attributes: ctx.rowAttributes,
|
|
2544
2590
|
})}
|
|
@@ -2619,10 +2665,10 @@ function DataTableInner<TData>(
|
|
|
2619
2665
|
)}
|
|
2620
2666
|
{/* Header 的 center 區保持 overflow-hidden(非 scroll)—— body 的 center 才有 scroll,
|
|
2621
2667
|
header 靠 JS 同步 scrollLeft(見 onCenterBodyScroll)。這樣不會出現雙 scrollbar。
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2668
|
+
V scrollbar 對齊:centerBody **刻意不用** `scrollbar-gutter: stable`(決策見 centerBody
|
|
2669
|
+
className 註解 — 永久預留 15px 會讓 content-fit 看起來像恆有 V 捲軸);trade-off =
|
|
2670
|
+
V scroll 出現時 body 內側少 ~15px、header 不縮 → 右端微 misalign,content-fit 乾淨優先。
|
|
2671
|
+
header 的 `scrollbar-gutter` 本就無效(overflow-hidden),刻意不設 */}
|
|
2626
2672
|
<div
|
|
2627
2673
|
ref={centerHeaderRef}
|
|
2628
2674
|
data-datatable-header-panel="center"
|
|
@@ -2670,8 +2716,6 @@ function DataTableInner<TData>(
|
|
|
2670
2716
|
<div
|
|
2671
2717
|
ref={centerBodyRef}
|
|
2672
2718
|
// 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
2719
|
data-datatable-hscroll
|
|
2676
2720
|
data-datatable-panel="center"
|
|
2677
2721
|
// overflow-x/y: auto — 沒 overflow 就不顯 bar。wrapper minWidth 仍 trigger H 真 overflow。
|
|
@@ -2837,13 +2881,12 @@ function DataTableInner<TData>(
|
|
|
2837
2881
|
</div>
|
|
2838
2882
|
)
|
|
2839
2883
|
} : 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
|
|
2884
|
+
// Slice D Step 4 spreadsheet semantics(2026-05-10;2026-07-14 對齊清理):
|
|
2885
|
+
// selectedCellId(click 1)= solid border SelectionRing z 2
|
|
2886
|
+
// range(Shift+click rectangle from anchor↔focus)= cell-bg fill via
|
|
2887
|
+
// CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫 range 視覺,
|
|
2888
|
+
// RangeOuterRing / rangeCellIds prop 已 retire)
|
|
2845
2889
|
selectedCellId={spreadsheetMode ? selectedCellId : null}
|
|
2846
|
-
rangeCellIds={rangeCellIds}
|
|
2847
2890
|
cellClickEntersEdit={(cellId) => {
|
|
2848
2891
|
// 2026-05-10 codex review red light fix(per dual-track verify):
|
|
2849
2892
|
// 1. cellId parse 用 lastIndexOf(':')(row id 可含 colon)
|
|
@@ -2872,14 +2915,14 @@ function DataTableInner<TData>(
|
|
|
2872
2915
|
|
|
2873
2916
|
// ── L4 Row drag DnD wrapper ───────────────────────────────────────────────
|
|
2874
2917
|
// Sensors:Pointer(8px activation distance,避免 cell click 誤觸 drag)+ Keyboard(a11y)
|
|
2875
|
-
// SortableContext
|
|
2876
|
-
// 同 parent level
|
|
2918
|
+
// v15.0 Path B:無 SortableContext — 每 row 各自 useDraggable / useDroppable;
|
|
2919
|
+
// 同 parent level 限制由自訂 collisionDetection 過濾 cross-parent target 成立(cross-parent over → invalidDrop)。
|
|
2877
2920
|
// DragEnd:active.id / over.id → 算 position(active vs over 視覺位置),呼叫 onRowReorder。
|
|
2878
2921
|
// hooks 必呼叫(rules-of-hooks)— 即使 enableRowDrag=false 也走 useSensors;wrap 才條件化。
|
|
2879
2922
|
// **codex P1 fix(2026-05-07 v15.13)**:KeyboardSensor 不傳 `coordinateGetter`,用
|
|
2880
2923
|
// dnd-kit 預設 25px 箭頭 stepping。`sortableKeyboardCoordinates` 是 `@dnd-kit/sortable`
|
|
2881
2924
|
// preset,需 `<SortableContext>` 才正確 resolve 下一個 sortable target — 但 v15.0
|
|
2882
|
-
// path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(
|
|
2925
|
+
// path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(見檔頭 import 註解),
|
|
2883
2926
|
// 此 getter 在無 context 下 keyboard nav 無法 reliable resolve target → keyboard
|
|
2884
2927
|
// drag/reorder regression。Default getter(arrow-key Δ25px)在 useDraggable 場景是
|
|
2885
2928
|
// dnd-kit canonical(`@dnd-kit/core/src/sensors/keyboard/defaults.ts` 預設行為)。
|
|
@@ -3157,7 +3200,7 @@ function DataTableInner<TData>(
|
|
|
3157
3200
|
// ── L5 分頁列(2026-07-06,詳 data-table.spec.md「L5:分頁」段)────────────────
|
|
3158
3201
|
// 間距 tight = layoutSpace spec 規則 3「跨範疇 functional 交互」;頁碼靠右(shadcn justify-end /
|
|
3159
3202
|
// Ant Table bottomEnd / MUI / Carbon 4 家實證,左側空也靠右);「共 N 筆」數源 = filter 後全集
|
|
3160
|
-
// getPrePaginationRowModel(≠ selection all-mode 的
|
|
3203
|
+
// getPrePaginationRowModel(≠ selection all-mode 的 server-side 全集數 M — consumer 自持,語意不同)。
|
|
3161
3204
|
// 2026-07-06 user 拍板:「Pagination 元件本身提供完整功能(showTotal / 每頁筆數)= SSOT,
|
|
3162
3205
|
// Table 按一致定義套用」—— 分頁列的資訊/選單/「資訊左、操作右」layout 全部 own 在
|
|
3163
3206
|
// <Pagination> 完整形態;DataTable 只轉發 config + own TanStack state(controlled 消費:
|
|
@@ -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 定位
|
|
@@ -211,7 +211,7 @@ export const Overview = {
|
|
|
211
211
|
<span className="rounded px-2 py-1 text-[11px] font-mono border border-dashed"
|
|
212
212
|
style={{ borderColor: 'var(--success)', backgroundColor: 'var(--success-subtle)', color: 'var(--success)' }}>formatted text (flex-1)</span>
|
|
213
213
|
</div>
|
|
214
|
-
<span className="text-[10px] text-fg-muted font-mono">Intl.DateTimeFormat · null 顯示
|
|
214
|
+
<span className="text-[10px] text-fg-muted font-mono">Intl.DateTimeFormat · null 顯示 - (hyphen)</span>
|
|
215
215
|
</div>
|
|
216
216
|
</div>
|
|
217
217
|
</div>
|
|
@@ -416,8 +416,8 @@ const InspectorInner = () => {
|
|
|
416
416
|
)}
|
|
417
417
|
{!isEdit && mode === 'readonly' && !value && (
|
|
418
418
|
<PropRow label="Empty">
|
|
419
|
-
<TokenValue value="--
|
|
420
|
-
<span className="text-[10px] text-fg-muted ml-1">
|
|
419
|
+
<TokenValue value="--foreground" />
|
|
420
|
+
<span className="text-[10px] text-fg-muted ml-1">hyphen -</span>
|
|
421
421
|
</PropRow>
|
|
422
422
|
)}
|
|
423
423
|
</div>
|
|
@@ -750,7 +750,7 @@ export const StateBehavior = {
|
|
|
750
750
|
|
|
751
751
|
{/* Empty value display */}
|
|
752
752
|
<div className="flex flex-col gap-4">
|
|
753
|
-
<span className="text-caption font-medium text-fg-secondary">空值 —
|
|
753
|
+
<span className="text-caption font-medium text-fg-secondary">空值 — 統一半形 hyphen(-)+ foreground</span>
|
|
754
754
|
<div className="flex flex-col gap-3">
|
|
755
755
|
<div className="flex items-center gap-3">
|
|
756
756
|
<span className="text-[11px] text-fg-muted w-20 shrink-0">readonly</span>
|
|
@@ -939,11 +939,11 @@ export const Accessibility = {
|
|
|
939
939
|
</ul>
|
|
940
940
|
</section>
|
|
941
941
|
<section>
|
|
942
|
-
<h3 className="text-body font-bold mb-2"
|
|
942
|
+
<h3 className="text-body font-bold mb-2">鍵盤</h3>
|
|
943
943
|
<ul className="list-disc list-inside text-caption text-fg-secondary space-y-1">
|
|
944
|
-
<li>Trigger
|
|
945
|
-
<li>Popover
|
|
946
|
-
<li>DateGrid:<kbd>←</kbd> <kbd>→</kbd> 切日 / <kbd>PgUp</kbd> <kbd>PgDn</kbd> 切月 / <kbd>Home</kbd> <kbd>End</kbd> 行首尾</li>
|
|
944
|
+
<li>Trigger 開 popover(<kbd>Space</kbd> / <kbd>Enter</kbd>):單一 DatePicker 的 <code>{`<div role="combobox">`}</code> 無 native Enter/Space→click,由元件<strong>自建 <code>onKeyDown</code></strong> 補開(date-picker.tsx:554;Radix PopoverTrigger 只 compose onClick)。Range 雙 trigger 為 native <code>{`<button>`}</code> onClick 開啟(同非 Radix Popover 內建)</li>
|
|
945
|
+
<li>Popover 開啟 <kbd>Esc</kbd> 關閉 + 回焦:單一 DatePicker 用 PopoverTrigger → Radix <strong>內建</strong> <code>triggerRef.focus()</code> 回焦;Range 只有 PopoverAnchor(triggerRef 恆 null,內建回焦為 no-op),改由元件<strong>自建 <code>onCloseAutoFocus</code></strong> 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)</li>
|
|
946
|
+
<li>DateGrid(react-day-picker v9 內建):<kbd>←</kbd> <kbd>→</kbd> 切日 / <kbd>PgUp</kbd> <kbd>PgDn</kbd> 切月 / <kbd>Home</kbd> <kbd>End</kbd> 行首尾</li>
|
|
947
947
|
<li>showTime:<kbd>Tab</kbd> 從 calendar 跳到右側 time panel,各 column <kbd>↑</kbd> <kbd>↓</kbd> 切 option</li>
|
|
948
948
|
</ul>
|
|
949
949
|
</section>
|
|
@@ -67,7 +67,7 @@ export const UsageGuidance: Story = {
|
|
|
67
67
|
|
|
68
68
|
<Rule
|
|
69
69
|
title="❌ 不用其他 calendar library 平行實作"
|
|
70
|
-
note="
|
|
70
|
+
note="Date Range / DateTime 已內建(DatePicker.Range / showTime,見下方近親規則)且都基於本 DateGrid(`../DateGrid/date-grid.tsx`);未來任何日曆類擴充也走 DateGrid,而非引入第二個 library——避免兩套視覺語言在同一系統並存"
|
|
71
71
|
>
|
|
72
72
|
<Label>實作細節見 Design System / Components / DatePicker / 設計規格</Label>
|
|
73
73
|
</Rule>
|
|
@@ -169,8 +169,8 @@ export const FormattingRule: Story = {
|
|
|
169
169
|
</Rule>
|
|
170
170
|
|
|
171
171
|
<Rule
|
|
172
|
-
title="null
|
|
173
|
-
note="Display 模式 null / undefined
|
|
172
|
+
title="null 值統一顯示半形連字號"
|
|
173
|
+
note="Display 模式 null / undefined 顯示半形 -(foreground,同 readonly value 色),與其他 Field 元件一致"
|
|
174
174
|
>
|
|
175
175
|
<DatePicker mode="readonly" value={null} />
|
|
176
176
|
</Rule>
|
|
@@ -267,7 +267,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
|
|
|
267
267
|
`clearable` prop 在有值時顯示 clear 按鈕(endAction)。
|
|
268
268
|
|
|
269
269
|
- 只在 edit 模式顯示
|
|
270
|
-
- 清除後 value 變為 `null`(Display
|
|
270
|
+
- 清除後 value 變為 `null`(Display 顯示半形 -,text-foreground)
|
|
271
271
|
- **Dual-state sync canonical**(2026-05-03 v10):X 點擊必同時 `onChange?.('')` + `setDraft(null)`(Range 同),否則 `needConfirm=true`(showTime 預設)且 popover 開著時 `displayValue=draft` 仍顯示舊值,trigger 看起來「沒清」。X 在 trigger 上是 standard clear affordance,不走 needConfirm「等確定」語義 — 立刻 commit + 同步 draft
|
|
272
272
|
|
|
273
273
|
---
|
|
@@ -295,7 +295,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
|
|
|
295
295
|
- Trigger:`role="combobox"` + `aria-haspopup="dialog"` + `aria-expanded={open}` + 必含 accessible name(`aria-label` / 或外層 `<label>` / 或 fieldCtx label)
|
|
296
296
|
- Popover content:`role="dialog"`;單一日期 popover 不重覆 `aria-label`(由 trigger 的 `role="combobox"` accessible name 標示),Range popover 加 `aria-label="日期區間選擇"`
|
|
297
297
|
- DateGrid 鍵盤:Arrow keys 切日 / PageUp/Down 切月 / Home/End 行首尾(react-day-picker v9 內建)
|
|
298
|
-
- Trigger
|
|
298
|
+
- Trigger 鍵盤(Space / Enter open;Esc close + 回焦):單一 DatePicker 的 `<div role="combobox">` 無 native Enter/Space→click,由元件**自建 `onKeyDown`** 開 popover(Radix PopoverTrigger 只 compose onClick;date-picker.tsx:554),Esc 關閉後靠 PopoverTrigger 的 Radix **內建** `triggerRef.focus()` 回焦;Range 用 native `<button>` onClick 開、只掛 PopoverAnchor(triggerRef 恆 null → 內建回焦 no-op),改由**自建 `onCloseAutoFocus`** 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)
|
|
299
299
|
- Range 雙 trigger:`activeEnd` state 指向當前編輯端,`aria-expanded` 對應只當該 trigger active 時 true
|
|
300
300
|
|
|
301
301
|
---
|
|
@@ -317,7 +317,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
|
|
|
317
317
|
- **Invalid date input**:Field validation 處理 `aria-invalid="true"` + error border + 下方 error message;DatePicker 本身不 own validation 規則。
|
|
318
318
|
- **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(Display / Edit / typeable / Range 雙 input 皆同)。
|
|
319
319
|
- **RTL**:未實作方向鏡像(trigger / Range 雙 input / DateGrid 皆以 LTR physical 方向設計);RTL 屬 DS-wide 決策,未定(與 Chip / Breadcrumb 同口徑)。
|
|
320
|
-
- **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell
|
|
320
|
+
- **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell 尺寸 density-aware(消費 `--field-height-sm`:md=28×28 / lg=32×32,對齊 L128 + `date-grid.spec.md:120`),隨 density 縮放而非固定。
|
|
321
321
|
|
|
322
322
|
---
|
|
323
323
|
|
|
@@ -136,7 +136,7 @@ export const RangePicker: Story = {
|
|
|
136
136
|
return (
|
|
137
137
|
<div className="flex flex-col gap-4 max-w-md">
|
|
138
138
|
<p className="text-caption text-fg-muted">
|
|
139
|
-
|
|
139
|
+
兩個輸入框加中間箭頭:點開始欄開月曆選起日,選完自動跳到結束欄選迄日;有值時右側出現清除鈕。
|
|
140
140
|
</p>
|
|
141
141
|
<DatePicker.Range value={range} onChange={setRange} clearable />
|
|
142
142
|
<p className="text-caption text-fg-muted">
|
|
@@ -160,7 +160,7 @@ export const WithError: Story = {
|
|
|
160
160
|
render: () => (
|
|
161
161
|
<div className="flex flex-col gap-4 max-w-xs">
|
|
162
162
|
<p className="text-caption text-fg-muted">
|
|
163
|
-
|
|
163
|
+
驗證失敗時外框轉紅色,滑過或聚焦時同步用較深的紅。
|
|
164
164
|
</p>
|
|
165
165
|
<DatePicker error value="2026-04-02" onChange={() => {}} />
|
|
166
166
|
<DatePicker error value={null} onChange={() => {}} placeholder="必填日期" />
|
|
@@ -226,7 +226,7 @@ export const ShowTimePopoverOpen: Story = {
|
|
|
226
226
|
/* ── OpenSnapshot:needConfirm date-only(2026-07-05 D4 修 footer gate 死路)── */
|
|
227
227
|
export const NeedConfirmDateOnlyOpen: Story = {
|
|
228
228
|
name: 'needConfirm:合約生效日確認',
|
|
229
|
-
parameters: { docs: { description: { story: '
|
|
229
|
+
parameters: { docs: { description: { story: '需確認模式:選日期只會先暫存(輸入框即時顯示),要按下方「確定」才真正套用。適用選錯成本高的日期,例如合約生效日、帳單結算起算日。' } } },
|
|
230
230
|
render: () => {
|
|
231
231
|
const [effectiveDate, setEffectiveDate] = React.useState('2026-08-01')
|
|
232
232
|
return (
|
|
@@ -297,8 +297,7 @@ export const ShowTimeRange: Story = {
|
|
|
297
297
|
return (
|
|
298
298
|
<div className="flex flex-col gap-4 max-w-lg">
|
|
299
299
|
<p className="text-caption text-fg-muted">
|
|
300
|
-
|
|
301
|
-
兩端都填好 + 按確定才 commit(needConfirm=true 預設)。
|
|
300
|
+
範圍 + 時間:點開始欄選起始日期與時間,點結束欄選結束的日期與時間;兩端都選好、按下方「確定」才會套用。
|
|
302
301
|
</p>
|
|
303
302
|
<DatePicker.Range
|
|
304
303
|
showTime
|