@qijenchen/design-system 0.1.0-beta.83 → 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 +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_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 +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 +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 +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
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
import * as React from 'react'
|
|
5
5
|
import { X, ChevronDown } from 'lucide-react'
|
|
6
6
|
import { cn } from '@/lib/utils'
|
|
7
|
-
import type { FieldMode, FieldVariant } from '@/design-system/components/Field/field-types'
|
|
8
|
-
import { fieldWrapperStyles,
|
|
9
|
-
import { useFieldContext, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant, useResolvedFieldInvalid } from '@/design-system/components/Field/field-context'
|
|
7
|
+
import type { FieldMode, FieldVariant, FieldVariantInternal, FieldWidth } from '@/design-system/components/Field/field-types'
|
|
8
|
+
import { fieldWrapperStyles, nakedCellRowModeAlign, fieldDisplayTextClass } from '@/design-system/components/Field/field-wrapper'
|
|
9
|
+
import { useFieldContext, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant, useResolvedFieldInvalid, useFieldEmptyDisplay, fieldEmptyColorClass } from '@/design-system/components/Field/field-context'
|
|
10
10
|
import { Tag } from '@/design-system/components/Tag/tag'
|
|
11
11
|
import { ItemInlineAction, ItemSuffix } from '@/design-system/patterns/element-anatomy/item-anatomy'
|
|
12
12
|
import { OverflowIndicator } from '@/design-system/components/OverflowIndicator/overflow-indicator'
|
|
@@ -326,8 +326,9 @@ function ComboboxTagStack({
|
|
|
326
326
|
value?: string[] | null; options?: ComboboxOption[]; tagSize?: 'sm' | 'md' | 'lg'
|
|
327
327
|
wrap?: boolean; containerRef?: React.RefObject<HTMLDivElement | null>; disabled?: boolean
|
|
328
328
|
}) {
|
|
329
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
329
330
|
const ownRef = React.useRef<HTMLDivElement>(null)
|
|
330
|
-
if (!value || value.length === 0) return <span className=
|
|
331
|
+
if (!value || value.length === 0) return <span className={fieldEmptyColorClass(disabled ? 'disabled' : 'display')}>{emptyDisplay}</span>
|
|
331
332
|
const items = value.map(v => ({ value: v, label: options?.find(o => o.value === v)?.label ?? v }))
|
|
332
333
|
const disabledClass = disabled ? 'bg-disabled text-fg-disabled' : undefined
|
|
333
334
|
|
|
@@ -366,6 +367,10 @@ export interface ComboboxProps {
|
|
|
366
367
|
mode?: FieldMode
|
|
367
368
|
/** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */
|
|
368
369
|
variant?: FieldVariant
|
|
370
|
+
/** 寬度軸 — `fill` 填滿容器(default)/ `hug` 依內容收縮:value 寬 + slot 元素寬 + gap +
|
|
371
|
+
* field 內 padding;chrome 與互動不變。場景 = detail pane inline metadata。
|
|
372
|
+
* SSOT → field-controls.spec.md「寬度軸(width: fill / hug)」。 */
|
|
373
|
+
width?: FieldWidth
|
|
369
374
|
error?: boolean
|
|
370
375
|
size?: 'sm' | 'md' | 'lg'
|
|
371
376
|
options: ComboboxOption[]
|
|
@@ -485,9 +490,13 @@ const getIconSize = (size: string) => ICON_SIZE[size as 'sm' | 'md' | 'lg']
|
|
|
485
490
|
// ── Shared readonly/disabled/display render ─────────────────────────────────
|
|
486
491
|
|
|
487
492
|
function ReadonlyMultiSelect({
|
|
488
|
-
mode, variant: variantProp, size, options, value, wrap, className, showDisplayEndIcon = false,
|
|
489
|
-
}: Pick<ComboboxProps, 'mode' | '
|
|
493
|
+
mode, variant: variantProp, width, size, options, value, wrap, className, showDisplayEndIcon = false,
|
|
494
|
+
}: Pick<ComboboxProps, 'mode' | 'width' | 'size' | 'options' | 'value' | 'wrap' | 'className' | 'showDisplayEndIcon'> & {
|
|
495
|
+
/** @internal 2026-07-14 API 策展 E:內部 render helper 吃 FieldVariantInternal(naked 由 cell-registry 通道傳入)*/
|
|
496
|
+
variant?: FieldVariantInternal
|
|
497
|
+
}) {
|
|
490
498
|
const resolvedMode = mode ?? 'readonly'
|
|
499
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
491
500
|
const variant = variantProp ?? 'default'
|
|
492
501
|
const sz = size ?? 'md'
|
|
493
502
|
const iconSize = sz === 'lg' ? 20 : 16
|
|
@@ -503,20 +512,20 @@ function ReadonlyMultiSelect({
|
|
|
503
512
|
if (!showDisplayEndIcon) {
|
|
504
513
|
// 2026-05-14 I2 fix(spec contract (e) display typography canonical):empty bare span 套
|
|
505
514
|
// `fieldDisplayTextClass(sz)`(sm/md→text-body,lg→text-body-lg)— 對齊跨 Field family 統一。
|
|
506
|
-
if (!hasTags) return <span className={cn(fieldDisplayTextClass(sz),
|
|
515
|
+
if (!hasTags) return <span className={cn(fieldDisplayTextClass(sz), fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
|
|
507
516
|
return (
|
|
508
517
|
<ComboboxTagStack value={value} options={options} tagSize={sz} wrap={wrap} />
|
|
509
518
|
)
|
|
510
519
|
}
|
|
511
520
|
return (
|
|
512
521
|
<div
|
|
513
|
-
className={cn(fieldWrapperStyles({ mode: 'display', variant, size: sz }), hasTags && tagPadding[sz], className)}
|
|
522
|
+
className={cn(fieldWrapperStyles({ mode: 'display', variant, width, size: sz }), hasTags && tagPadding[sz], className)}
|
|
514
523
|
data-field-mode="display"
|
|
515
524
|
>
|
|
516
525
|
{hasTags ? (
|
|
517
526
|
<ComboboxTagStack value={value} options={options} tagSize={sz} wrap={wrap} />
|
|
518
527
|
) : (
|
|
519
|
-
<span className={cn('flex-1 min-w-0',
|
|
528
|
+
<span className={cn('flex-1 min-w-0', fieldEmptyColorClass(resolvedMode))}>{emptyDisplay}</span>
|
|
520
529
|
)}
|
|
521
530
|
<ItemSuffix className="pointer-events-none">
|
|
522
531
|
<ChevronDown size={iconSize} className="shrink-0 text-fg-muted" aria-hidden />
|
|
@@ -527,7 +536,7 @@ function ReadonlyMultiSelect({
|
|
|
527
536
|
|
|
528
537
|
return (
|
|
529
538
|
<div ref={containerRef}
|
|
530
|
-
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant, size: sz }), hasTags && tagPadding[sz],
|
|
539
|
+
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant, width, size: sz }), hasTags && tagPadding[sz],
|
|
531
540
|
// 2026-05-18 #6A Round 1 Step 1/4(per user 拍板「決策6選a」+ codex M31 Step 5 verdict cite combobox.tsx:451):
|
|
532
541
|
// readonly/disabled path 對齊 L293 display wrapper 已 ship 的 overflow-hidden fix。
|
|
533
542
|
// M10 propagation:原 overflow-visible 讓 readonly tag 越界蓋 indicator,跟 display 不對稱。
|
|
@@ -540,7 +549,7 @@ function ReadonlyMultiSelect({
|
|
|
540
549
|
<ComboboxTagStack value={value} options={options} tagSize={sz} wrap={wrap}
|
|
541
550
|
containerRef={containerRef} disabled={resolvedMode === 'disabled'} />
|
|
542
551
|
) : (
|
|
543
|
-
<span className=
|
|
552
|
+
<span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>
|
|
544
553
|
)}
|
|
545
554
|
{/* 2026-06-26 類型身份 indicator:edit 顯示 / readonly 不顯示(純值、不可開下拉) / disabled 保留(fg-disabled,對齊原生 <select disabled>);naked cell 依 showDisplayEndIcon */}
|
|
546
555
|
{(variant === 'naked' ? !!showDisplayEndIcon : resolvedMode === 'disabled') && (
|
|
@@ -567,12 +576,16 @@ function ReadonlyMultiSelect({
|
|
|
567
576
|
type ComboboxInternalProps = ComboboxProps & { __triggerRef?: React.Ref<HTMLDivElement> }
|
|
568
577
|
|
|
569
578
|
function NativeCombobox({
|
|
570
|
-
mode, variant: variantProp, error = false, size = 'md', options, value = [], onChange, placeholder,
|
|
579
|
+
mode, variant: variantProp, width, error = false, size = 'md', options, value = [], onChange, placeholder,
|
|
571
580
|
className, disabled: disabledProp, wrap = false, clearable = false, showDisplayEndIcon = false,
|
|
572
581
|
__triggerRef,
|
|
582
|
+
'aria-label': ariaLabel,
|
|
573
583
|
}: ComboboxInternalProps) {
|
|
584
|
+
// a11y(2026-07-14 dim10):touch/native 路徑同樣接 fieldCtx — id 讓 FieldLabel htmlFor
|
|
585
|
+
// 命名 native <select>;describedby/errormessage/required 對齊 desktop CustomCombobox trigger。
|
|
586
|
+
const fieldCtx = useFieldContext()
|
|
574
587
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
575
|
-
const variant:
|
|
588
|
+
const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
576
589
|
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
|
|
577
590
|
const resolvedMode = useResolvedFieldMode({ mode, disabled })
|
|
578
591
|
const iconSize = getIconSize(size)
|
|
@@ -588,7 +601,7 @@ function NativeCombobox({
|
|
|
588
601
|
const tagAreaRef = React.useRef<HTMLDivElement>(null)
|
|
589
602
|
|
|
590
603
|
if (resolvedMode !== 'edit') {
|
|
591
|
-
return <ReadonlyMultiSelect mode={resolvedMode} variant={variant} size={size} options={options} value={value} wrap={wrap} className={className} showDisplayEndIcon={showDisplayEndIcon} />
|
|
604
|
+
return <ReadonlyMultiSelect mode={resolvedMode} variant={variant} width={width} size={size} options={options} value={value} wrap={wrap} className={className} showDisplayEndIcon={showDisplayEndIcon} />
|
|
592
605
|
}
|
|
593
606
|
|
|
594
607
|
const items = value.map(v => ({ value: v, label: options.find(o => o.value === v)?.label ?? v }))
|
|
@@ -597,6 +610,15 @@ function NativeCombobox({
|
|
|
597
610
|
|
|
598
611
|
const selectDropdown = unselected.length > 0 ? (
|
|
599
612
|
<select ref={selectRef} value="" onChange={(e) => handleAdd(e.target.value)}
|
|
613
|
+
// a11y(2026-07-14 dim10):accessible name — FieldLabel htmlFor 經 id 命名 native select;
|
|
614
|
+
// consumer aria-label 優先,否則 fieldCtx.labelId fallback(對齊 select.tsx:240 accname 優先序)。
|
|
615
|
+
id={fieldCtx?.id}
|
|
616
|
+
aria-label={ariaLabel}
|
|
617
|
+
aria-labelledby={ariaLabel ? undefined : fieldCtx?.labelId}
|
|
618
|
+
aria-invalid={error || undefined}
|
|
619
|
+
aria-required={fieldCtx?.required || undefined}
|
|
620
|
+
aria-describedby={fieldCtx?.descriptionId}
|
|
621
|
+
aria-errormessage={error ? fieldCtx?.errorId : undefined}
|
|
600
622
|
className={cn('bg-transparent outline-none border-none p-0 text-[inherit] font-[inherit] leading-[inherit] text-fg-muted cursor-pointer appearance-none',
|
|
601
623
|
value.length > 0 ? 'absolute inset-0 w-full h-full opacity-0 z-0 cursor-pointer' : 'relative z-10 flex-1 min-w-20')}>
|
|
602
624
|
<option value="" disabled>{placeholder ?? '選擇...'}</option>
|
|
@@ -605,7 +627,7 @@ function NativeCombobox({
|
|
|
605
627
|
) : null
|
|
606
628
|
|
|
607
629
|
return (
|
|
608
|
-
<div ref={__triggerRef} className={cn(fieldWrapperStyles({ mode: 'edit', variant: variant, size, error }), value.length > 0 && tagPadding[size], 'relative',
|
|
630
|
+
<div ref={__triggerRef} className={cn(fieldWrapperStyles({ mode: 'edit', variant: variant, width, size, error }), value.length > 0 && tagPadding[size], 'relative',
|
|
609
631
|
wrap && 'items-start py-1', className)}
|
|
610
632
|
style={{ paddingRight: 'var(--field-px)', ...(wrap ? { height: 'auto' } : undefined) }} data-field-mode="edit" data-error={error ? '' : undefined}
|
|
611
633
|
onClick={(e) => { if (e.target === e.currentTarget) { selectRef.current?.showPicker?.(); selectRef.current?.focus() } }}>
|
|
@@ -642,7 +664,7 @@ function NativeCombobox({
|
|
|
642
664
|
// ── Custom Combobox (desktop — consumes SelectMenu) ───────────────────
|
|
643
665
|
|
|
644
666
|
function CustomCombobox({
|
|
645
|
-
mode, variant: variantProp, error: errorProp = false, size = 'md', options, value = [], onChange, placeholder,
|
|
667
|
+
mode, variant: variantProp, width, error: errorProp = false, size = 'md', options, value = [], onChange, placeholder,
|
|
646
668
|
className, disabled: disabledProp, wrap = false, clearable = false, searchable = false, loading, searchIn = 'menu',
|
|
647
669
|
searchPlaceholder = '搜尋…', // i18n-allow: DS default
|
|
648
670
|
searchAriaLabel = '搜尋選項', // i18n-allow: DS default
|
|
@@ -668,7 +690,7 @@ function CustomCombobox({
|
|
|
668
690
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
669
691
|
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
|
|
670
692
|
const resolvedMode = useResolvedFieldMode({ mode, disabled })
|
|
671
|
-
const variant:
|
|
693
|
+
const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
672
694
|
const iconSize = getIconSize(size)
|
|
673
695
|
const showClear = clearable && value.length > 0 && resolvedMode === 'edit'
|
|
674
696
|
const [open, setOpen] = React.useState(defaultOpen)
|
|
@@ -723,7 +745,7 @@ function CustomCombobox({
|
|
|
723
745
|
)
|
|
724
746
|
|
|
725
747
|
if (resolvedMode !== 'edit') {
|
|
726
|
-
return <ReadonlyMultiSelect mode={resolvedMode} variant={variant} size={size} options={options} value={value} wrap={wrap} className={className} showDisplayEndIcon={showDisplayEndIcon} />
|
|
748
|
+
return <ReadonlyMultiSelect mode={resolvedMode} variant={variant} width={width} size={size} options={options} value={value} wrap={wrap} className={className} showDisplayEndIcon={showDisplayEndIcon} />
|
|
727
749
|
}
|
|
728
750
|
|
|
729
751
|
const chevronEl = <ChevronDown size={iconSize} className={cn('shrink-0 text-fg-muted transition-transform', open && 'rotate-180')} aria-hidden />
|
|
@@ -734,11 +756,14 @@ function CustomCombobox({
|
|
|
734
756
|
id={fieldCtx?.id}
|
|
735
757
|
role="combobox" aria-expanded={open} aria-haspopup="listbox" aria-controls={listboxId} tabIndex={0}
|
|
736
758
|
aria-label={ariaLabel}
|
|
759
|
+
// a11y(2026-07-14 dim-10):div-based role=combobox 的 <label for> 無效,接 FieldLabel labelId
|
|
760
|
+
// (field-context.ts labelId jsDoc);consumer aria-label 優先 — 與 sibling select.tsx:705 同款 guard。
|
|
761
|
+
aria-labelledby={ariaLabel ? undefined : fieldCtx?.labelId}
|
|
737
762
|
aria-invalid={error || undefined}
|
|
738
763
|
aria-required={fieldCtx?.required || undefined}
|
|
739
764
|
aria-describedby={fieldCtx?.descriptionId}
|
|
740
765
|
aria-errormessage={error ? fieldCtx?.errorId : undefined}
|
|
741
|
-
className={cn(fieldWrapperStyles({ mode: 'edit', variant: variant, size, error }), value.length > 0 && tagPadding[size], 'relative cursor-pointer',
|
|
766
|
+
className={cn(fieldWrapperStyles({ mode: 'edit', variant: variant, width, size, error }), value.length > 0 && tagPadding[size], 'relative cursor-pointer',
|
|
742
767
|
wrap && 'items-start py-1',
|
|
743
768
|
// 2026-05-06 v13.3 SSOT retire:per-control `open && 'border-primary'` 移除。Field default
|
|
744
769
|
// 統一處理 — open=灰深(data-state)/ focus=藍;2026-07-04 Q1:error 亦收進 error variant。
|
|
@@ -752,6 +777,15 @@ function CustomCombobox({
|
|
|
752
777
|
// open 後不 preventDefault 讓方向鍵自由流向選單導覽)。
|
|
753
778
|
// 純 additive:此 trigger 原無 onKeyDown,不覆寫既有 handler;open 邏輯仍走 setOpen SSOT。
|
|
754
779
|
onKeyDown={(e) => {
|
|
780
|
+
// a11y(2026-07-14 dim-10):Enter/Space 來自 descendant 互動元素(Tag 移除 / clear 按鈕)
|
|
781
|
+
// 時直接放行 —— 否則下方 preventDefault 會取消 native button activation(鍵盤永遠按不動
|
|
782
|
+
// 按鈕)。guard 限 Enter/Space + button 類:search input 的 Enter 仍走 cmdk 選項選取
|
|
783
|
+
// (forwardKeyToListbox),Escape / 方向鍵仍走 combobox 導覽。
|
|
784
|
+
if (
|
|
785
|
+
(e.key === 'Enter' || e.key === ' ') &&
|
|
786
|
+
e.target !== e.currentTarget &&
|
|
787
|
+
(e.target as HTMLElement).closest?.('button, a, [role="button"]')
|
|
788
|
+
) return
|
|
755
789
|
// 2026-07-05 D4 P0:open 後 ArrowUp/Down/Enter 轉送 cmdk root(select-menu.tsx forwardKeyToListbox)
|
|
756
790
|
if (open && forwardKeyToListbox(listboxId, e)) return
|
|
757
791
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Inspector / ColorMatrix / SizeMatrix / StateBehavior N/A — Command 是
|
|
3
3
|
// headless Internal primitive(cmdk passthrough),不被 App 直接消費,而是透過
|
|
4
4
|
// SelectMenu 等外層元件呈現。色彩 / 尺寸 / 狀態都由消費方(SelectMenu / Combobox /
|
|
5
|
-
// PeoplePicker)決定並在各自的 anatomy
|
|
6
|
-
//
|
|
5
|
+
// PeoplePicker)決定並在各自的 anatomy 詳述。本檔保留 Overview(教結構與
|
|
6
|
+
// 消費路徑)+ Accessibility(6-canonical 中適用的 2 個;2026-05-17 per Dim 13 加)。
|
|
7
7
|
import type { Meta, StoryObj } from '@storybook/react'
|
|
8
8
|
import { Settings, User, LogOut, FileText } from 'lucide-react'
|
|
9
9
|
import {
|
|
@@ -30,7 +30,7 @@ export const UsageGuidance: Story = {
|
|
|
30
30
|
<LinkTo kind="Design System/Internal/Command/展示" name="行內搜尋清單"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">行內搜尋清單 — Gmail 式 sidebar 信件資料夾過濾</span></LinkTo>
|
|
31
31
|
</li>
|
|
32
32
|
<li>
|
|
33
|
-
<LinkTo kind="Design System/Internal/Command/展示" name="
|
|
33
|
+
<LinkTo kind="Design System/Internal/Command/展示" name="純動作指令"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">純動作指令 — 選中立即執行的快速動作清單</span></LinkTo>
|
|
34
34
|
</li>
|
|
35
35
|
<li>
|
|
36
36
|
<LinkTo kind="Design System/Internal/Command/展示" name="無結果狀態"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">搜尋無結果時的空狀態文案(CommandEmpty)</span></LinkTo>
|
|
@@ -200,47 +200,79 @@ export const InlineCommand: Story = {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
203
|
-
Story 3
|
|
203
|
+
Story 3:純動作指令(action command,無 form value 儲存)
|
|
204
|
+
2026-07-14 dim-68 修:原「外觀切換器」只 2 項固定 action 配搜尋框 —— 正向示範了
|
|
205
|
+
command.spec.md:75 明文禁止的「< 6 項短選單用 Command」誤用(短選單該用 DropdownMenu /
|
|
206
|
+
SegmentedControl)。改為快速動作清單(7 項、2 群組),保留本 story 獨有教學點:
|
|
207
|
+
「選中立即執行、不保留 form value」的純 action palette。
|
|
204
208
|
═══════════════════════════════════════════════════════════════════════════ */
|
|
205
209
|
|
|
206
|
-
const
|
|
210
|
+
const ActionCommandDemo = () => {
|
|
207
211
|
const [theme, setTheme] = useState<'light' | 'dark'>('light')
|
|
212
|
+
const [lastAction, setLastAction] = useState<string | null>(null)
|
|
208
213
|
|
|
209
214
|
return (
|
|
210
215
|
<div className="flex flex-col gap-3 max-w-md">
|
|
211
216
|
<p className="text-caption text-fg-muted">
|
|
212
|
-
純 action palette — 選中立即執行(切 theme),不保留 form value。
|
|
217
|
+
純 action palette — 選中立即執行(切 theme / 觸發動作),不保留 form value。
|
|
218
|
+
動作多到需要搜尋才用 Command;< 6 項的短選單用 DropdownMenu(spec「與 DropdownMenu 的分界」)。
|
|
213
219
|
</p>
|
|
214
220
|
<div
|
|
215
221
|
className="rounded-lg border border-border bg-surface-raised overflow-hidden"
|
|
216
222
|
style={{ boxShadow: 'var(--elevation-100)' }}
|
|
217
223
|
>
|
|
218
224
|
<Command>
|
|
219
|
-
<CommandInput placeholder="
|
|
225
|
+
<CommandInput placeholder="輸入指令…" />
|
|
220
226
|
<CommandList>
|
|
221
|
-
<CommandEmpty
|
|
227
|
+
<CommandEmpty>沒有符合的指令</CommandEmpty>
|
|
222
228
|
<CommandGroup heading="外觀">
|
|
223
|
-
<CommandItem onSelect={() => setTheme('light')}>
|
|
229
|
+
<CommandItem onSelect={() => { setTheme('light'); setLastAction('切換淺色模式') }}>
|
|
224
230
|
<Sun />
|
|
225
231
|
<span>淺色模式</span>
|
|
226
232
|
{theme === 'light' && <CommandShortcut>當前</CommandShortcut>}
|
|
227
233
|
</CommandItem>
|
|
228
|
-
<CommandItem onSelect={() => setTheme('dark')}>
|
|
234
|
+
<CommandItem onSelect={() => { setTheme('dark'); setLastAction('切換深色模式') }}>
|
|
229
235
|
<MoonStar />
|
|
230
236
|
<span>深色模式</span>
|
|
231
237
|
{theme === 'dark' && <CommandShortcut>當前</CommandShortcut>}
|
|
232
238
|
</CommandItem>
|
|
233
239
|
</CommandGroup>
|
|
240
|
+
<CommandSeparator />
|
|
241
|
+
<CommandGroup heading="快速動作">
|
|
242
|
+
<CommandItem onSelect={() => setLastAction('建立新文件')}>
|
|
243
|
+
<Plus />
|
|
244
|
+
<span>建立新文件</span>
|
|
245
|
+
<CommandShortcut>⌘N</CommandShortcut>
|
|
246
|
+
</CommandItem>
|
|
247
|
+
<CommandItem onSelect={() => setLastAction('開啟收件匣')}>
|
|
248
|
+
<Inbox />
|
|
249
|
+
<span>開啟收件匣</span>
|
|
250
|
+
</CommandItem>
|
|
251
|
+
<CommandItem onSelect={() => setLastAction('加入我的最愛')}>
|
|
252
|
+
<Star />
|
|
253
|
+
<span>加入我的最愛</span>
|
|
254
|
+
</CommandItem>
|
|
255
|
+
<CommandItem onSelect={() => setLastAction('封存目前頁面')}>
|
|
256
|
+
<Archive />
|
|
257
|
+
<span>封存目前頁面</span>
|
|
258
|
+
</CommandItem>
|
|
259
|
+
<CommandItem onSelect={() => setLastAction('開啟設定')}>
|
|
260
|
+
<Settings />
|
|
261
|
+
<span>開啟設定</span>
|
|
262
|
+
<CommandShortcut>⌘,</CommandShortcut>
|
|
263
|
+
</CommandItem>
|
|
264
|
+
</CommandGroup>
|
|
234
265
|
</CommandList>
|
|
235
266
|
</Command>
|
|
236
267
|
</div>
|
|
268
|
+
{lastAction && <p className="text-caption text-fg-muted">已執行:{lastAction}</p>}
|
|
237
269
|
</div>
|
|
238
270
|
)
|
|
239
271
|
}
|
|
240
272
|
|
|
241
|
-
export const
|
|
242
|
-
name: '
|
|
243
|
-
render: () => <
|
|
273
|
+
export const ActionCommand: Story = {
|
|
274
|
+
name: '純動作指令',
|
|
275
|
+
render: () => <ActionCommandDemo />,
|
|
244
276
|
}
|
|
245
277
|
|
|
246
278
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
//
|
|
10
10
|
// 設計原則:
|
|
11
11
|
// - 每個 cell component 接同一組 props(`CellComponentProps`)
|
|
12
|
-
// - 用 `variant="naked"` — DataTable cell-as-input substrate(
|
|
12
|
+
// - 用 `variant="naked"` — DataTable cell-as-input substrate(Field chrome variant;bare 2026-07-09 退役)
|
|
13
13
|
// - 消費 full Field 家族 primitive(無 stub)
|
|
14
14
|
// - 不再用 `meta._editable` 私有 flag — `isEditable` 直接顯式入參(消除 M1 hack)
|
|
15
15
|
//
|
|
@@ -21,19 +21,37 @@ import type { ComponentType } from 'react'
|
|
|
21
21
|
import { Pencil } from 'lucide-react'
|
|
22
22
|
import { cn } from '@/lib/utils'
|
|
23
23
|
import type { ColumnType } from './column-types'
|
|
24
|
-
import { Input } from '@/design-system/components/Input/input'
|
|
25
|
-
import { Textarea } from '@/design-system/components/Textarea/textarea'
|
|
26
|
-
import { NumberInput } from '@/design-system/components/NumberInput/number-input'
|
|
27
|
-
import { Select } from '@/design-system/components/Select/select'
|
|
28
|
-
import { Combobox } from '@/design-system/components/Combobox/combobox'
|
|
29
|
-
import { DatePicker } from '@/design-system/components/DatePicker/date-picker'
|
|
30
|
-
import { TimePicker } from '@/design-system/components/TimePicker/time-picker'
|
|
31
|
-
import { PeoplePicker } from '@/design-system/components/PeoplePicker/people-picker'
|
|
32
|
-
import { LinkInput } from '@/design-system/components/LinkInput/link-input'
|
|
33
|
-
import { Checkbox } from '@/design-system/components/Checkbox/checkbox'
|
|
24
|
+
import { Input as InputPublic } from '@/design-system/components/Input/input'
|
|
25
|
+
import { Textarea as TextareaPublic } from '@/design-system/components/Textarea/textarea'
|
|
26
|
+
import { NumberInput as NumberInputPublic } from '@/design-system/components/NumberInput/number-input'
|
|
27
|
+
import { Select as SelectPublic } from '@/design-system/components/Select/select'
|
|
28
|
+
import { Combobox as ComboboxPublic } from '@/design-system/components/Combobox/combobox'
|
|
29
|
+
import { DatePicker as DatePickerPublic } from '@/design-system/components/DatePicker/date-picker'
|
|
30
|
+
import { TimePicker as TimePickerPublic } from '@/design-system/components/TimePicker/time-picker'
|
|
31
|
+
import { PeoplePicker as PeoplePickerPublic } from '@/design-system/components/PeoplePicker/people-picker'
|
|
32
|
+
import { LinkInput as LinkInputPublic } from '@/design-system/components/LinkInput/link-input'
|
|
33
|
+
import { Checkbox as CheckboxPublic } from '@/design-system/components/Checkbox/checkbox'
|
|
34
34
|
import { Button } from '@/design-system/components/Button/button'
|
|
35
35
|
import type { PersonValue } from '@/design-system/components/PeoplePicker/person-display'
|
|
36
|
-
import { FieldSurfaceProvider, FieldSurfaceSizeProvider } from '@/design-system/components/Field/field-context'
|
|
36
|
+
import { FieldSurfaceProvider, FieldSurfaceSizeProvider, FieldSurfaceEditableProvider } from '@/design-system/components/Field/field-context'
|
|
37
|
+
import { makeEditSettleKeyHandler } from '@/design-system/components/Field/field-edit-keys'
|
|
38
|
+
import type { WithFieldVariantInternal } from '@/design-system/components/Field/field-types'
|
|
39
|
+
|
|
40
|
+
// ── @internal naked variant 通道(2026-07-14 API 策展 E,user 拍板「全部收窄」)──────────────
|
|
41
|
+
// `naked` 已從公開 FieldVariant 拆出(field-types.ts `FieldVariantInternal`);本檔是唯一合法
|
|
42
|
+
// naked 消費者(field-controls.spec.md「軸二 variant」明文)。以 `WithFieldVariantInternal`
|
|
43
|
+
// 型別層 widen 各 Field control 的 `variant` prop — 純型別、零 runtime;元件內部 cva / resolver
|
|
44
|
+
// 分支本就吃 FieldVariantInternal,widen 不引入 unsound 行為。
|
|
45
|
+
const Input = InputPublic as WithFieldVariantInternal<typeof InputPublic>
|
|
46
|
+
const Textarea = TextareaPublic as WithFieldVariantInternal<typeof TextareaPublic>
|
|
47
|
+
const NumberInput = NumberInputPublic as WithFieldVariantInternal<typeof NumberInputPublic>
|
|
48
|
+
const Select = SelectPublic as WithFieldVariantInternal<typeof SelectPublic>
|
|
49
|
+
const Combobox = ComboboxPublic as WithFieldVariantInternal<typeof ComboboxPublic>
|
|
50
|
+
const DatePicker = DatePickerPublic as WithFieldVariantInternal<typeof DatePickerPublic>
|
|
51
|
+
const TimePicker = TimePickerPublic as WithFieldVariantInternal<typeof TimePickerPublic>
|
|
52
|
+
const PeoplePicker = PeoplePickerPublic as WithFieldVariantInternal<typeof PeoplePickerPublic>
|
|
53
|
+
const LinkInput = LinkInputPublic as WithFieldVariantInternal<typeof LinkInputPublic>
|
|
54
|
+
const Checkbox = CheckboxPublic as WithFieldVariantInternal<typeof CheckboxPublic>
|
|
37
55
|
|
|
38
56
|
// ── Types ────────────────────────────────────────────────────────────────────
|
|
39
57
|
|
|
@@ -81,18 +99,15 @@ function makeKeyHandler(
|
|
|
81
99
|
onCancel?: () => void,
|
|
82
100
|
parseValue?: (raw: string) => unknown,
|
|
83
101
|
) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return
|
|
89
|
-
if (e.key === 'Escape') { e.preventDefault(); onCancel?.() }
|
|
90
|
-
if (e.key === 'Enter') {
|
|
91
|
-
e.preventDefault()
|
|
102
|
+
// 消費 edit-in-place 鍵盤結算 SSOT(field-edit-keys.ts):IME guard + Enter/Esc dispatch 統一
|
|
103
|
+
// (2026-07-09 抽出;原本 InlineEdit 漏 IME guard = bug,現同源)。value 讀取為 input-specific,留本地。
|
|
104
|
+
return makeEditSettleKeyHandler({
|
|
105
|
+
onCommit: (e) => {
|
|
92
106
|
const raw = (e.target as HTMLInputElement).value
|
|
93
107
|
onCommit?.(parseValue ? parseValue(raw) : raw)
|
|
94
|
-
}
|
|
95
|
-
|
|
108
|
+
},
|
|
109
|
+
onCancel: () => onCancel?.(),
|
|
110
|
+
})
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
const sizeForInput = (size: CellSize): CellSize => size
|
|
@@ -151,15 +166,13 @@ function StringCell({ value, meta, mode, size, isDisabled, autoRowHeight, onComm
|
|
|
151
166
|
style={{ fieldSizing: 'content' } as React.CSSProperties}
|
|
152
167
|
onChange={(e) => onDraft?.((e.target as HTMLTextAreaElement).value)}
|
|
153
168
|
onBlur={(e) => onCommit?.((e.target as HTMLTextAreaElement).value)}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
}}
|
|
169
|
+
// 多行:走 edit-in-place 鍵盤結算 SSOT(IME guard + Esc + Cmd/Ctrl+Enter commit;
|
|
170
|
+
// plain Enter=換行)。commitOnEnter:false → 純 Enter 不攔。
|
|
171
|
+
onKeyDown={makeEditSettleKeyHandler({
|
|
172
|
+
onCommit: (e) => onCommit?.((e.target as HTMLTextAreaElement).value),
|
|
173
|
+
onCancel: () => onCancel?.(),
|
|
174
|
+
commitOnEnter: false,
|
|
175
|
+
})}
|
|
163
176
|
/>
|
|
164
177
|
)
|
|
165
178
|
}
|
|
@@ -216,12 +229,12 @@ function NumberCell({ value, meta, mode, size, isDisabled, onCommit, onCancel, o
|
|
|
216
229
|
suffix={meta?.suffix}
|
|
217
230
|
precision={meta?.precision}
|
|
218
231
|
onBlur={() => onCommit?.(localValue)}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}}
|
|
232
|
+
// 單行:走 edit-in-place 鍵盤結算 SSOT(IME guard + Esc + Enter commit)。
|
|
233
|
+
// commit localValue(controlled state,非 e.target.value)。
|
|
234
|
+
onKeyDown={makeEditSettleKeyHandler({
|
|
235
|
+
onCommit: () => onCommit?.(localValue),
|
|
236
|
+
onCancel: () => onCancel?.(),
|
|
237
|
+
})}
|
|
225
238
|
/>
|
|
226
239
|
)
|
|
227
240
|
}
|
|
@@ -237,7 +250,7 @@ const dismissOnClose = (onCancel?: () => void) => (open: boolean) => { if (!open
|
|
|
237
250
|
// Fix:`key={mode}` 強制 React unmount + remount,每次切 mode 都重跑 useState init。
|
|
238
251
|
// 對齊 Notion / Airtable cell-as-input「display 跟 edit 是不同 mount cycle」語義。
|
|
239
252
|
|
|
240
|
-
function DateCell({ value, meta, mode, size, isDisabled,
|
|
253
|
+
function DateCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: CellComponentProps) {
|
|
241
254
|
if (mode === 'display') {
|
|
242
255
|
return (
|
|
243
256
|
<DatePicker
|
|
@@ -248,10 +261,10 @@ function DateCell({ value, meta, mode, size, isDisabled, isEditable, onCommit, o
|
|
|
248
261
|
size={size}
|
|
249
262
|
formatOptions={meta?.formatOptions}
|
|
250
263
|
locale={meta?.locale}
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
|
|
264
|
+
// 2026-07-08 user 拍板 A 案(推翻 2026-05-10/06-26 兩次拍板,per 6 家 benchmark 6/6 共識
|
|
265
|
+
// Ant/MUI X/AG Grid/Atlaskit/Notion/Airtable:display 態零恆顯型別 icon;editable
|
|
266
|
+
// affordance 統一 = hover outline(field.spec.md L4)。showDisplayEndIcon 不再傳
|
|
267
|
+
//(prop 保留為 spreadsheet-flavored 消費端 opt-in 逃生門,見 field.spec.md L6)。
|
|
255
268
|
/>
|
|
256
269
|
)
|
|
257
270
|
}
|
|
@@ -270,7 +283,7 @@ function DateCell({ value, meta, mode, size, isDisabled, isEditable, onCommit, o
|
|
|
270
283
|
)
|
|
271
284
|
}
|
|
272
285
|
|
|
273
|
-
function TimeCell({ value, meta, mode, size, isDisabled,
|
|
286
|
+
function TimeCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: CellComponentProps) {
|
|
274
287
|
if (mode === 'display') {
|
|
275
288
|
return (
|
|
276
289
|
<TimePicker
|
|
@@ -281,7 +294,7 @@ function TimeCell({ value, meta, mode, size, isDisabled, isEditable, onCommit, o
|
|
|
281
294
|
size={size}
|
|
282
295
|
formatOptions={meta?.formatOptions}
|
|
283
296
|
locale={meta?.locale}
|
|
284
|
-
showDisplayEndIcon
|
|
297
|
+
// showDisplayEndIcon 不傳 — 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
|
|
285
298
|
/>
|
|
286
299
|
)
|
|
287
300
|
}
|
|
@@ -301,7 +314,7 @@ function TimeCell({ value, meta, mode, size, isDisabled, isEditable, onCommit, o
|
|
|
301
314
|
)
|
|
302
315
|
}
|
|
303
316
|
|
|
304
|
-
function SelectCell({ value, meta, mode, size, isDisabled,
|
|
317
|
+
function SelectCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: CellComponentProps) {
|
|
305
318
|
// Display canonical(2026-05-05):cell IS variant,default plain text(no Tag pill 疊在 cell border 內)。
|
|
306
319
|
// Consumer 可在 column meta.display='tag' opt-in 內容導向的 Tag 視覺(category 含色彩標籤等)。
|
|
307
320
|
// 對齊 JTable / AG Grid「renderer/editor 視覺一致」canonical。
|
|
@@ -316,7 +329,8 @@ function SelectCell({ value, meta, mode, size, isDisabled, isEditable, onCommit,
|
|
|
316
329
|
options={meta?.options ?? []}
|
|
317
330
|
size={size}
|
|
318
331
|
display={displayMode}
|
|
319
|
-
showDisplayEndIcon
|
|
332
|
+
// showDisplayEndIcon 不傳 — 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
|
|
333
|
+
selectedItemRenderer={meta?.selectedItemRenderer} // 2026-07-08 WM 戰役:status 類彩色 cell 顯示通道
|
|
320
334
|
/>
|
|
321
335
|
)
|
|
322
336
|
}
|
|
@@ -326,6 +340,7 @@ function SelectCell({ value, meta, mode, size, isDisabled, isEditable, onCommit,
|
|
|
326
340
|
autoFocus
|
|
327
341
|
variant="naked"
|
|
328
342
|
size={sizeForInput(size)}
|
|
343
|
+
selectedItemRenderer={meta?.selectedItemRenderer}
|
|
329
344
|
options={meta?.options ?? []}
|
|
330
345
|
value={value as string | null | undefined}
|
|
331
346
|
onChange={(v) => onCommit?.(v)}
|
|
@@ -339,7 +354,7 @@ function SelectCell({ value, meta, mode, size, isDisabled, isEditable, onCommit,
|
|
|
339
354
|
)
|
|
340
355
|
}
|
|
341
356
|
|
|
342
|
-
function MultiSelectCell({ value, meta, mode, size, isDisabled, autoRowHeight,
|
|
357
|
+
function MultiSelectCell({ value, meta, mode, size, isDisabled, autoRowHeight, onCommitLive, onCancel }: CellComponentProps) {
|
|
343
358
|
const wrap = autoRowHeight && meta?.wrap === true
|
|
344
359
|
if (mode === 'display') {
|
|
345
360
|
return (
|
|
@@ -351,7 +366,7 @@ function MultiSelectCell({ value, meta, mode, size, isDisabled, autoRowHeight, i
|
|
|
351
366
|
options={meta?.options ?? []}
|
|
352
367
|
wrap={wrap}
|
|
353
368
|
size={size}
|
|
354
|
-
showDisplayEndIcon
|
|
369
|
+
// showDisplayEndIcon 不傳 — 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
|
|
355
370
|
/>
|
|
356
371
|
)
|
|
357
372
|
}
|
|
@@ -371,10 +386,10 @@ function MultiSelectCell({ value, meta, mode, size, isDisabled, autoRowHeight, i
|
|
|
371
386
|
)
|
|
372
387
|
}
|
|
373
388
|
|
|
374
|
-
function PersonCell({ value, mode, size, isDisabled,
|
|
389
|
+
function PersonCell({ value, mode, size, isDisabled, onCommit, onCancel, meta }: CellComponentProps) {
|
|
375
390
|
if (mode === 'display') {
|
|
376
|
-
// 2026-
|
|
377
|
-
return <PeoplePicker key="display" variant="naked" mode={displayOrDisabled(isDisabled)} value={value as PersonValue | null} size={size}
|
|
391
|
+
// 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
|
|
392
|
+
return <PeoplePicker key="display" variant="naked" mode={displayOrDisabled(isDisabled)} value={value as PersonValue | null} size={size} />
|
|
378
393
|
}
|
|
379
394
|
return (
|
|
380
395
|
<PeoplePicker
|
|
@@ -391,10 +406,10 @@ function PersonCell({ value, mode, size, isDisabled, isEditable, onCommit, onCan
|
|
|
391
406
|
)
|
|
392
407
|
}
|
|
393
408
|
|
|
394
|
-
function MultiPersonCell({ value, mode, size, isDisabled,
|
|
409
|
+
function MultiPersonCell({ value, mode, size, isDisabled, onCommitLive, onCancel, meta }: CellComponentProps) {
|
|
395
410
|
if (mode === 'display') {
|
|
396
|
-
// 2026-
|
|
397
|
-
return <PeoplePicker key="display" variant="naked" mode={displayOrDisabled(isDisabled)} value={(value as PersonValue[]) ?? []} size={size}
|
|
411
|
+
// 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
|
|
412
|
+
return <PeoplePicker key="display" variant="naked" mode={displayOrDisabled(isDisabled)} value={(value as PersonValue[]) ?? []} size={size} />
|
|
398
413
|
}
|
|
399
414
|
// Multi 用 onCommitLive(commit 但不 exit edit)— 每勾一人即時生效,popover 持續開
|
|
400
415
|
// 直到點外面;onOpenChange(false) → onCancel exit edit。對齊 multiSelect canonical。
|
|
@@ -418,7 +433,8 @@ function BooleanCell({ value, mode, meta, size, isEditable, isDisabled, onCommit
|
|
|
418
433
|
// onCheckedChange 仍 fire(violate disabled contract)。Fix:`!isEditable || isDisabled` →
|
|
419
434
|
// 走 display branch,Checkbox 拿 disabled mode + 不接 onCheckedChange。
|
|
420
435
|
if (mode === 'display' && (!isEditable || isDisabled)) {
|
|
421
|
-
|
|
436
|
+
// size 傳入 → boolean 值 icon(Check/X)@lg 縮放對齊其他 cell(對齊 editable 分支同 size 邏輯)
|
|
437
|
+
return <Checkbox variant="naked" size={size === 'lg' ? 'lg' : 'md'} mode={displayOrDisabled(isDisabled)} checked={value === true} />
|
|
422
438
|
}
|
|
423
439
|
return (
|
|
424
440
|
<Checkbox
|
|
@@ -431,17 +447,19 @@ function BooleanCell({ value, mode, meta, size, isEditable, isDisabled, onCommit
|
|
|
431
447
|
}
|
|
432
448
|
|
|
433
449
|
/**
|
|
434
|
-
* UrlCell
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
450
|
+
* UrlCell(2026-07-14 docblock 對齊實作):
|
|
451
|
+
* display branch = `<LinkInput mode={displayOrDisabled(isDisabled)}>`(URL parse / hostname
|
|
452
|
+
* 顯示一致性 SSOT);editable 互動:hover 時右側出 Pencil 鈕 → 進 edit(保留 link click 語意)。
|
|
453
|
+
* edit branch = plain `<Input variant="naked">`(LinkInput edit 的 controlled value 衝突
|
|
454
|
+
* revert,詳下方 edit branch 註解);URL 驗證 deferred 到 onCommit(consumer 端 validate)。
|
|
439
455
|
*/
|
|
440
456
|
function UrlCell({ value, meta, mode, size, isDisabled, isEditable, onRequestEdit, onCommit, onCancel }: CellComponentProps) {
|
|
441
457
|
if (mode === 'display') {
|
|
442
|
-
// showDisplayEndIcon ← D path Phase 2(2026-05-08):Field naked wrapper 包 anchor,與 Input edit 同 chrome
|
|
458
|
+
// showDisplayEndIcon ← D path Phase 2(2026-05-08):Field naked wrapper 包 anchor,與 Input edit 同 chrome。
|
|
459
|
+
// LinkInput 此 prop = wrapper-only(無 icon,field.spec.md L6 例外)→ A 案(2026-07-08)不撤;
|
|
460
|
+
// 但修 I1:原無條件 true 違反「= isEditable」knob 等式(field-controls.spec.md cell 例外),改等式。
|
|
443
461
|
const display = (
|
|
444
|
-
<LinkInput variant="naked" mode={displayOrDisabled(isDisabled)} value={value as string | null} label={meta?.linkLabel} size={size} showDisplayEndIcon />
|
|
462
|
+
<LinkInput variant="naked" mode={displayOrDisabled(isDisabled)} value={value as string | null} label={meta?.linkLabel} size={size} showDisplayEndIcon={isEditable === true} />
|
|
445
463
|
)
|
|
446
464
|
// 2026-05-13 codex V1 fix:disabled URL 不顯 Pencil affordance(parent onRequestEdit 已被攔但 UI 仍誤導)
|
|
447
465
|
if (!isEditable || isDisabled) return display
|
|
@@ -521,7 +539,12 @@ function buildCellWithSurface(Inner: ComponentType<CellComponentProps>, key: str
|
|
|
521
539
|
{/* 2026-06-08:把 table-density size 經獨立 surface-size context 注給 child Field controls,
|
|
522
540
|
漏傳 size 的 cell 也自動繼承(根治「新 cell 漏傳 size」class);size primitive 不破壞 memo identity。*/}
|
|
523
541
|
<FieldSurfaceSizeProvider size={props.size}>
|
|
524
|
-
|
|
542
|
+
{/* 2026-07-08 user 拍板:cell 可編輯訊號經獨立 boolean context 注給 child Field controls,
|
|
543
|
+
讓 useFieldEmptyDisplay 分流「可編輯 cell 空 display → 空白」vs「不可編輯 cell → '-'」。
|
|
544
|
+
boolean primitive 不破壞 memo identity(同 size context)。 */}
|
|
545
|
+
<FieldSurfaceEditableProvider isEditable={props.isEditable ?? false}>
|
|
546
|
+
<Inner {...props} />
|
|
547
|
+
</FieldSurfaceEditableProvider>
|
|
525
548
|
</FieldSurfaceSizeProvider>
|
|
526
549
|
</FieldSurfaceProvider>
|
|
527
550
|
)
|
|
@@ -122,7 +122,16 @@ declare module '@tanstack/react-table' {
|
|
|
122
122
|
precision?: number
|
|
123
123
|
locale?: string
|
|
124
124
|
/** Select/multiSelect options — maps value to display label */
|
|
125
|
-
|
|
125
|
+
/** select/multiSelect 選項:消費 Select 的 SelectOption 完整 schema(M30 wrapper-extends-primitive;
|
|
126
|
+
* 2026-07-08 原 {value,label} 窄型別讓 icon/description/iconClassName 傳不進 = 假 SSOT)*/
|
|
127
|
+
options?: Array<import('../Select/select').SelectOption>
|
|
128
|
+
/** select cell 的 trigger/display 自訂渲染(轉發 Select.selectedItemRenderer;status 彩色 icon 場景)*/
|
|
129
|
+
selectedItemRenderer?: (opt: import('../Select/select').SelectOption) => React.ReactNode
|
|
130
|
+
/** select cell 顯示模式(轉發 Select.display;cell-registry SelectCell 消費 `meta?.display`)。
|
|
131
|
+
* default `'plain'` 純文字;`'tag'` opt-in 內容導向 Tag 視覺(status / category 彩色標籤,
|
|
132
|
+
* 搭配 options 的 `tagVariant`)。2026-07-14 deep-audit 補型別:runtime 一直消費此欄位
|
|
133
|
+
* (cell-registry.tsx SelectCell displayMode),但 ColumnMeta 漏宣告 → typed consumer 傳不進(假 SSOT)。 */
|
|
134
|
+
display?: 'plain' | 'tag'
|
|
126
135
|
/** Date: Intl.DateTimeFormat options */
|
|
127
136
|
formatOptions?: Intl.DateTimeFormatOptions
|
|
128
137
|
/**
|