@qijenchen/design-system 0.1.0-beta.83 → 0.1.0-beta.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +8 -8
- package/README.md +3 -2
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +22 -2
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +4 -4
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -2
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +12 -3
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +13 -5
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +7 -1
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +8 -3
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +1 -0
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +1 -1
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +8 -4
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +1 -1
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +10 -3
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +5 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +30 -13
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +53 -62
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/column-types.d.ts +10 -4
- package/dist/components/DataTable/column-types.d.ts.map +1 -1
- package/dist/components/DataTable/column-types.js.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-group.d.ts +47 -0
- package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-group.js +154 -0
- package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.js +285 -0
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
- package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
- package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +140 -0
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
- package/dist/components/DataTable/data-table.d.ts +5 -6
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +36 -15
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-operators.js +140 -0
- package/dist/components/DataTable/filter-operators.js.map +1 -0
- package/dist/components/DataTable/filter-tree.js +312 -0
- package/dist/components/DataTable/filter-tree.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +3 -0
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +12 -1
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/DataTable/lib/column-meta.js +25 -0
- package/dist/components/DataTable/lib/column-meta.js.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +3 -1
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +7 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +105 -74
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts +20 -3
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +38 -20
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +45 -5
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +19 -0
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-edit-keys.d.ts +21 -0
- package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
- package/dist/components/Field/field-edit-keys.js +19 -0
- package/dist/components/Field/field-edit-keys.js.map +1 -0
- package/dist/components/Field/field-types.d.ts +20 -1
- package/dist/components/Field/field-types.d.ts.map +1 -1
- package/dist/components/Field/field-types.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +3 -2
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +38 -39
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +2 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/Field/index.d.ts +1 -0
- package/dist/components/Field/index.d.ts.map +1 -1
- package/dist/components/Field/index.js +2 -0
- package/dist/components/Field/index.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +1 -1
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts +1 -1
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +7 -2
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
- package/dist/components/FileViewer/image-renderer.js +22 -1
- package/dist/components/FileViewer/image-renderer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +5 -3
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/InlineEdit/index.d.ts +2 -0
- package/dist/components/InlineEdit/index.d.ts.map +1 -0
- package/dist/components/InlineEdit/index.js +5 -0
- package/dist/components/InlineEdit/index.js.map +1 -0
- package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
- package/dist/components/InlineEdit/inline-edit.js +164 -0
- package/dist/components/InlineEdit/inline-edit.js.map +1 -0
- package/dist/components/Input/input.d.ts +6 -11
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +43 -13
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +2 -2
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +6 -5
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts +14 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +25 -3
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts +3 -3
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +6 -5
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/pagination.js +1 -1
- package/dist/components/Pagination/pagination.js.map +1 -1
- package/dist/components/PeoplePicker/index.js +7 -1
- package/dist/components/PeoplePicker/index.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +23 -10
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +6 -3
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +19 -14
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/Popover/popover.d.ts.map +1 -1
- package/dist/components/Popover/popover.js +3 -1
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +2 -2
- package/dist/components/ProfileCard/profile-card.js +3 -3
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +15 -9
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js +6 -3
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/Select/select.d.ts +46 -5
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +109 -28
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +3 -1
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +8 -1
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
- package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
- package/dist/components/SelectionControl/boolean-value.js +23 -0
- package/dist/components/SelectionControl/boolean-value.js.map +1 -0
- package/dist/components/SelectionControl/index.d.ts +1 -0
- package/dist/components/SelectionControl/index.d.ts.map +1 -1
- package/dist/components/SelectionControl/index.js +2 -0
- package/dist/components/SelectionControl/index.js.map +1 -1
- package/dist/components/Sheet/index.js +2 -1
- package/dist/components/Sheet/sheet.d.ts +7 -1
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +5 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +9 -4
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +8 -10
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +6 -6
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +3 -2
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +15 -1
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +2 -2
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +50 -42
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +42 -38
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +8 -6
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/tooltip.js +7 -5
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +56 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +211 -12
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/index.d.ts +115 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -108
- package/dist/index.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/tokens/categorical-color.js +15 -0
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/motion/motion.d.ts +7 -6
- package/dist/tokens/motion/motion.d.ts.map +1 -1
- package/dist/tokens/motion/motion.js +6 -6
- package/dist/tokens/motion/motion.js.map +1 -1
- package/dist/tokens/motion/overlay-motion.d.ts +19 -0
- package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
- package/dist/tokens/motion/overlay-motion.js +9 -0
- package/dist/tokens/motion/overlay-motion.js.map +1 -0
- package/dist/tokens/uiSize/icon-size.js +5 -0
- package/dist/tokens/uiSize/icon-size.js.map +1 -0
- package/ds-canonical/fork/governance.lock +31 -19
- package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +2 -1
- package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +28 -0
- package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -0
- package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
- package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/fork/manifest.json +15 -0
- package/ds-canonical/fork/preamble.md +20 -18
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
- package/ds-canonical/hooks/README.md +1 -1
- package/ds-canonical/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
- package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
- package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
- package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
- package/ds-canonical/hooks/check_story_determinism.sh +2 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
- package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
- package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
- package/ds-canonical/hooks/stop_self_audit.sh +31 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
- package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
- package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
- package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
- package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
- package/ds-canonical/references/build-ui-canonicals.md +2 -1
- package/ds-canonical/references/failure-class-registry.json +145 -0
- package/ds-canonical/references/governance-audit-coverage.md +33 -0
- package/ds-canonical/references/item-anatomy-recipe.md +2 -2
- package/ds-canonical/references/scenario-definition.md +6 -9
- package/ds-canonical/references/ssot-consultation.md +2 -2
- package/ds-canonical/references/ssot-index.md +5 -4
- package/ds-canonical/references/story-baseline-registry.json +8 -2
- package/ds-canonical/references/structural-token-retention.md +6 -9
- package/ds-canonical/rules/meta-patterns.md +8 -8
- package/ds-canonical/rules/self-verify.md +4 -3
- package/ds-canonical/rules/story-rules.md +2 -2
- package/ds-canonical/rules/ui-development.md +2 -2
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
- package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
- package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
- package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
- package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
- package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
- package/ds-canonical/skills/governance-health/SKILL.md +1 -1
- package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
- package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
- package/ds-canonical/skills/new-component/SKILL.md +5 -5
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
- package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
- package/ds-canonical/skills/story-writing/SKILL.md +3 -3
- package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
- package/ds-story-manifest.json +29 -20
- package/llms-full.txt +22 -1
- package/llms.txt +5 -4
- package/package.json +7 -3
- package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
- package/src/components/Accordion/accordion.stories.tsx +16 -1
- package/src/components/Alert/alert.principles.stories.tsx +1 -1
- package/src/components/Alert/alert.spec.md +8 -10
- package/src/components/Alert/alert.stories.tsx +28 -28
- package/src/components/Alert/alert.tsx +1 -1
- package/src/components/AppShell/_demo-helpers.tsx +6 -3
- package/src/components/AppShell/app-shell.spec.md +4 -4
- package/src/components/AppShell/app-shell.tsx +28 -2
- package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
- package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
- package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
- package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
- package/src/components/Avatar/avatar.spec.md +2 -2
- package/src/components/Avatar/avatar.stories.tsx +8 -6
- package/src/components/Avatar/avatar.tsx +13 -5
- package/src/components/Badge/badge.principles.stories.tsx +1 -1
- package/src/components/Badge/badge.spec.md +2 -0
- package/src/components/Badge/badge.stories.tsx +4 -2
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
- package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
- package/src/components/Button/button.principles.stories.tsx +1 -1
- package/src/components/Button/button.spec.md +2 -2
- package/src/components/Button/button.tsx +18 -3
- package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
- package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
- package/src/components/Calendar/calendar.spec.md +5 -4
- package/src/components/Calendar/calendar.stories.tsx +7 -4
- package/src/components/Calendar/calendar.tsx +26 -7
- package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
- package/src/components/Carousel/carousel.spec.md +2 -2
- package/src/components/Carousel/carousel.tsx +11 -3
- package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
- package/src/components/Chart/chart.principles.stories.tsx +1 -1
- package/src/components/Chart/chart.stories.tsx +2 -8
- package/src/components/Chart/chart.tsx +3 -0
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
- package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.spec.md +13 -26
- package/src/components/Checkbox/checkbox.stories.tsx +11 -8
- package/src/components/Checkbox/checkbox.tsx +18 -13
- package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
- package/src/components/Chip/chip.principles.stories.tsx +1 -1
- package/src/components/Chip/chip.spec.md +5 -4
- package/src/components/Chip/chip.tsx +5 -1
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
- package/src/components/CircularProgress/circular-progress.spec.md +3 -3
- package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
- package/src/components/Coachmark/coachmark.spec.md +5 -5
- package/src/components/Coachmark/coachmark.stories.tsx +3 -1
- package/src/components/Coachmark/coachmark.tsx +10 -3
- package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
- package/src/components/Combobox/combobox.tsx +53 -19
- package/src/components/Command/command.anatomy.stories.tsx +2 -2
- package/src/components/Command/command.principles.stories.tsx +1 -1
- package/src/components/Command/command.stories.tsx +42 -10
- package/src/components/DataTable/cell-registry.tsx +86 -63
- package/src/components/DataTable/column-types.ts +10 -1
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
- package/src/components/DataTable/data-table-filter-group.tsx +231 -0
- package/src/components/DataTable/data-table-filter-panel.tsx +16 -430
- package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
- package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
- package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
- package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
- package/src/components/DataTable/data-table.spec.md +33 -13
- package/src/components/DataTable/data-table.stories.tsx +16 -17
- package/src/components/DataTable/data-table.tsx +107 -61
- package/src/components/DataTable/filter-operators.spec.md +3 -3
- package/src/components/DataTable/index.ts +3 -0
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
- package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
- package/src/components/DateGrid/date-grid.spec.md +1 -1
- package/src/components/DateGrid/date-grid.tsx +3 -1
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
- package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
- package/src/components/DatePicker/date-picker.spec.md +3 -3
- package/src/components/DatePicker/date-picker.stories.tsx +4 -5
- package/src/components/DatePicker/date-picker.tsx +99 -45
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
- package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.spec.md +3 -3
- package/src/components/DescriptionList/description-list.stories.tsx +7 -6
- package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
- package/src/components/Dialog/dialog.spec.md +9 -0
- package/src/components/Dialog/dialog.stories.tsx +66 -5
- package/src/components/Dialog/dialog.tsx +60 -25
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
- package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
- package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
- package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
- package/src/components/Empty/empty.spec.md +2 -2
- package/src/components/Field/field-context.ts +69 -5
- package/src/components/Field/field-controls.spec.md +62 -8
- package/src/components/Field/field-edit-keys.ts +66 -0
- package/src/components/Field/field-types.ts +58 -9
- package/src/components/Field/field-wrapper.tsx +50 -42
- package/src/components/Field/field.anatomy.stories.tsx +9 -6
- package/src/components/Field/field.spec.md +1 -1
- package/src/components/Field/field.stories.tsx +1 -1
- package/src/components/Field/field.tsx +2 -1
- package/src/components/Field/form-validation.spec.md +3 -3
- package/src/components/Field/index.ts +1 -0
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
- package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
- package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
- package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
- package/src/components/FileItem/file-item.spec.md +5 -8
- package/src/components/FileItem/file-item.stories.tsx +36 -25
- package/src/components/FileItem/file-item.tsx +8 -6
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
- package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
- package/src/components/FileUpload/file-upload.spec.md +1 -1
- package/src/components/FileUpload/file-upload.tsx +1 -1
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
- package/src/components/FileViewer/file-viewer.spec.md +30 -12
- package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
- package/src/components/FileViewer/file-viewer.tsx +12 -4
- package/src/components/FileViewer/image-renderer.tsx +35 -7
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
- package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
- package/src/components/HoverCard/hover-card.spec.md +5 -5
- package/src/components/HoverCard/hover-card.stories.tsx +16 -16
- package/src/components/HoverCard/hover-card.tsx +5 -3
- package/src/components/InlineEdit/index.ts +5 -0
- package/src/components/InlineEdit/inline-edit.spec.md +149 -0
- package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
- package/src/components/InlineEdit/inline-edit.tsx +287 -0
- package/src/components/Input/input.anatomy.stories.tsx +8 -7
- package/src/components/Input/input.principles.stories.tsx +2 -12
- package/src/components/Input/input.spec.md +13 -18
- package/src/components/Input/input.tsx +69 -22
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
- package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
- package/src/components/LinkInput/link-input.tsx +11 -10
- package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
- package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
- package/src/components/Menu/menu-item.spec.md +22 -15
- package/src/components/Menu/menu-item.stories.tsx +39 -11
- package/src/components/Menu/menu-item.tsx +38 -4
- package/src/components/Notice/notice.principles.stories.tsx +1 -1
- package/src/components/Notice/notice.spec.md +16 -3
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
- package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
- package/src/components/NumberInput/number-input.spec.md +4 -4
- package/src/components/NumberInput/number-input.tsx +19 -12
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
- package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
- package/src/components/Pagination/pagination.spec.md +1 -1
- package/src/components/Pagination/pagination.stories.tsx +2 -6
- package/src/components/Pagination/pagination.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
- package/src/components/PeoplePicker/people-picker.spec.md +6 -6
- package/src/components/PeoplePicker/people-picker.tsx +56 -16
- package/src/components/PeoplePicker/person-display.tsx +32 -16
- package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
- package/src/components/Popover/popover.tsx +3 -1
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
- package/src/components/ProfileCard/profile-card.spec.md +3 -3
- package/src/components/ProfileCard/profile-card.tsx +6 -6
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
- package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
- package/src/components/RadioGroup/radio-group.tsx +41 -15
- package/src/components/Rating/rating.spec.md +11 -3
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.spec.md +7 -3
- package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.tsx +17 -4
- package/src/components/Select/select.anatomy.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +29 -17
- package/src/components/Select/select.stories.tsx +33 -0
- package/src/components/Select/select.tsx +190 -36
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
- package/src/components/SelectMenu/select-menu.spec.md +15 -7
- package/src/components/SelectMenu/select-menu.tsx +16 -3
- package/src/components/SelectionControl/boolean-value.tsx +39 -0
- package/src/components/SelectionControl/index.ts +1 -0
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.spec.md +3 -3
- package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
- package/src/components/Separator/separator.spec.md +2 -2
- package/src/components/Separator/separator.stories.tsx +6 -27
- package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
- package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
- package/src/components/Sheet/sheet.spec.md +2 -2
- package/src/components/Sheet/sheet.tsx +9 -5
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
- package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
- package/src/components/Sidebar/sidebar.spec.md +13 -15
- package/src/components/Sidebar/sidebar.stories.tsx +8 -7
- package/src/components/Sidebar/sidebar.tsx +37 -25
- package/src/components/Skeleton/skeleton.stories.tsx +4 -11
- package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
- package/src/components/Slider/slider.principles.stories.tsx +2 -2
- package/src/components/Slider/slider.spec.md +5 -5
- package/src/components/Slider/slider.tsx +3 -1
- package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
- package/src/components/Steps/steps.principles.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +1 -1
- package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
- package/src/components/Switch/switch.principles.stories.tsx +4 -4
- package/src/components/Switch/switch.spec.md +8 -8
- package/src/components/Switch/switch.stories.tsx +9 -24
- package/src/components/Switch/switch.tsx +17 -13
- package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
- package/src/components/Tabs/tabs.spec.md +1 -1
- package/src/components/Tabs/tabs.tsx +21 -1
- package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
- package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
- package/src/components/Textarea/textarea.spec.md +4 -4
- package/src/components/Textarea/textarea.tsx +72 -46
- package/src/components/TimePicker/time-columns.tsx +6 -2
- package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
- package/src/components/TimePicker/time-picker.spec.md +3 -3
- package/src/components/TimePicker/time-picker.tsx +16 -10
- package/src/components/Toast/toast.stories.tsx +7 -4
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
- package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
- package/src/components/Tooltip/tooltip.spec.md +1 -1
- package/src/components/Tooltip/tooltip.stories.tsx +4 -39
- package/src/components/Tooltip/tooltip.tsx +8 -6
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
- package/src/components/TreeView/tree-view.spec.md +42 -11
- package/src/components/TreeView/tree-view.stories.tsx +1 -0
- package/src/components/TreeView/tree-view.tsx +322 -17
- package/src/index.ts +588 -60
- package/src/patterns/action-bar/action-bar.spec.md +9 -0
- package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
- package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
- package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
- package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
- package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
- package/src/styles/tokens.css +3 -0
- package/src/tokens/README.md +1 -1
- package/src/tokens/color/color.spec.md +4 -4
- package/src/tokens/color/color.stories.tsx +3 -3
- package/src/tokens/density/density.stories.tsx +16 -3
- package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
- package/src/tokens/motion/motion.css +33 -21
- package/src/tokens/motion/motion.spec.md +32 -15
- package/src/tokens/motion/motion.stories.tsx +58 -5
- package/src/tokens/motion/motion.ts +7 -6
- package/src/tokens/motion/overlay-motion.ts +26 -0
- package/src/tokens/orphan-tokens.spec.md +4 -4
- package/src/tokens/token-system.spec.md +1 -0
- package/src/tokens/uiSize/uiSize.css +1 -1
- package/src/tokens/uiSize/uiSize.spec.md +1 -1
- package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
- package/src/tokens/utility-registry.json +160 -23
|
@@ -230,6 +230,118 @@ expect_silent "25. P8 nearmiss shadow-[var(--elevation-100)] → silent"
|
|
|
230
230
|
run_hook "$PROD_TSX" 'export const C = () => <div className="max-w-[600px] grid-cols-[1fr_2fr]">x</div>'
|
|
231
231
|
expect_silent "26. P8 nearmiss max-w-[600px]/grid-cols-[...](非色字 shadow)→ silent"
|
|
232
232
|
|
|
233
|
+
# ── 手刻 menu-item 可點列(2026-07-10 WM TypeSettingsDialog 左 rail 錨例)──
|
|
234
|
+
# 27. POSITIVE:手刻 button + hover:bg-neutral-hover + bg-neutral-selected 成對 → BLOCK
|
|
235
|
+
run_hook "$PROD_TSX" 'const cls = `flex w-full items-center gap-2 rounded-md hover:bg-neutral-hover ${sel ? "bg-neutral-selected" : ""}`; export const C = () => <button type="button" className={cls}>Task</button>'
|
|
236
|
+
expect_block "27. 手刻 nav row(hover+selected 成對)→ BLOCK"
|
|
237
|
+
|
|
238
|
+
# 28. NEGATIVE:同簽名 token 出現但已消費 <MenuItem>(正道)→ silent
|
|
239
|
+
run_hook "$PROD_TSX" 'export const C = () => <MenuItem size="sm" selected startContent={<Badge/>}>Task</MenuItem> /* hover:bg-neutral-hover bg-neutral-selected */'
|
|
240
|
+
expect_silent "28. 消費 <MenuItem> → silent"
|
|
241
|
+
|
|
242
|
+
# 29. NEGATIVE:只有 hover 無 selected(單純 hover row,非 menu-item family 簽名)→ silent
|
|
243
|
+
run_hook "$PROD_TSX" 'export const C = () => <button className="hover:bg-neutral-hover">row</button>'
|
|
244
|
+
expect_silent "29. 只 hover 無 selected → silent"
|
|
245
|
+
|
|
246
|
+
# 30. NEGATIVE:escape marker → silent
|
|
247
|
+
run_hook "$PROD_TSX" 'export const C = () => <div className="hover:bg-neutral-hover bg-neutral-selected">x</div> // @nav-row-handcraft-ok: calendar cell 非 menu 語義'
|
|
248
|
+
expect_silent "30. @nav-row-handcraft-ok escape → silent"
|
|
249
|
+
|
|
250
|
+
# ── 2026-07-10 批次 A(治理覆蓋 matrix 收官)──
|
|
251
|
+
# 31. C5 POSITIVE:亮色底 + text-white 對比配對違規 → BLOCK
|
|
252
|
+
run_hook "$PROD_TSX" 'export const T = () => <span className="bg-[var(--color-amber-6)] text-white size-4">A</span>'
|
|
253
|
+
expect_block "31. C5 亮色底+text-white 配對 → BLOCK"
|
|
254
|
+
|
|
255
|
+
# 32. C5 NEGATIVE:CAT_SOLID 正道(深字桶自帶 on-emphasis-dark)→ silent
|
|
256
|
+
run_hook "$PROD_TSX" 'export const T = () => <span className={`size-4 ${CAT_SOLID[hue]}`}>A</span>'
|
|
257
|
+
expect_silent "32. C5 消費 CAT_SOLID → silent"
|
|
258
|
+
|
|
259
|
+
# 33. C18 POSITIVE:children 計數括號串接 → BLOCK
|
|
260
|
+
run_hook "$PROD_TSX" 'export const H = () => <span>{group.label} ({items.length})</span>'
|
|
261
|
+
expect_block "33. C18 {label} ({count}) 串接 → BLOCK"
|
|
262
|
+
|
|
263
|
+
# 34. C18 NEGATIVE:aria-label 字串層(attr 非 children)→ silent
|
|
264
|
+
run_hook "$PROD_TSX" 'export const H = () => <span aria-label={`${label} (${count})`}>{label}</span>'
|
|
265
|
+
expect_silent "34. C18 aria-label 括號形 → silent"
|
|
266
|
+
|
|
267
|
+
# 35. C17 POSITIVE:vertical Separator 無 mx → BLOCK
|
|
268
|
+
run_hook "$PROD_TSX" 'export const B = () => <><Button>A</Button><Separator orientation="vertical" className="h-6" /><Button>B</Button></>'
|
|
269
|
+
expect_block "35. C17 vertical Separator 無 mx → BLOCK"
|
|
270
|
+
|
|
271
|
+
# 36. C17 NEGATIVE:h-6 mx-1 canonical → silent
|
|
272
|
+
run_hook "$PROD_TSX" 'export const B = () => <><Button>A</Button><Separator orientation="vertical" className="h-6 mx-1" /><Button>B</Button></>'
|
|
273
|
+
expect_silent "36. C17 h-6 mx-1 canonical → silent"
|
|
274
|
+
|
|
275
|
+
# 37. C20 POSITIVE:手刻 underline 連結字 → BLOCK
|
|
276
|
+
run_hook "$PROD_TSX" 'export const D = () => <span className="text-primary underline">upload</span>'
|
|
277
|
+
expect_block "37. C20 裸 underline 連結 → BLOCK"
|
|
278
|
+
|
|
279
|
+
# 38. C20 NEGATIVE:no-underline(合規移除底線)→ silent
|
|
280
|
+
run_hook "$PROD_TSX" 'export const D = () => <a className="no-underline text-primary">upload</a>'
|
|
281
|
+
expect_silent "38. C20 no-underline → silent"
|
|
282
|
+
|
|
283
|
+
# 39. C10 POSITIVE:spacer 把 Search 推最右 → BLOCK
|
|
284
|
+
run_hook "$PROD_TSX" 'export const T = () => <div><Button>Add</Button><span className="flex-1" /><Input placeholder="Search employees" /></div>'
|
|
285
|
+
expect_block "39. C10 業務 search 被推最右 → BLOCK"
|
|
286
|
+
|
|
287
|
+
# 40. C10 NEGATIVE:search 在業務層(無 spacer 前置)→ silent
|
|
288
|
+
run_hook "$PROD_TSX" 'export const T = () => <div><Button>Add</Button><Input placeholder="Search employees" /><span className="flex-1" /></div>'
|
|
289
|
+
expect_silent "40. C10 search 歸業務層 → silent"
|
|
290
|
+
|
|
291
|
+
# 41. C11 POSITIVE:DialogHeader 手放 X(雙 X)→ BLOCK
|
|
292
|
+
run_hook "$PROD_TSX" 'export const D = () => <DialogHeader><DialogTitle>Edit</DialogTitle><Button iconOnly startIcon={X} aria-label="Close" /></DialogHeader>'
|
|
293
|
+
expect_block "41. C11 DialogHeader 雙 X → BLOCK"
|
|
294
|
+
|
|
295
|
+
# 42. C11 NEGATIVE:header 操作走 actions slot → silent
|
|
296
|
+
run_hook "$PROD_TSX" 'export const D = () => <DialogHeader actions={<Button iconOnly startIcon={X} aria-label="Prev" />}><DialogTitle>Edit</DialogTitle></DialogHeader>'
|
|
297
|
+
expect_silent "42. C11 actions slot → silent"
|
|
298
|
+
|
|
299
|
+
# 43. C12 POSITIVE:Select 硬寬 w-36 → BLOCK
|
|
300
|
+
run_hook "$PROD_TSX" 'export const F = () => <Select className="w-36" options={opts} />'
|
|
301
|
+
expect_block "43. C12 Select 硬寬 w-36 → BLOCK"
|
|
302
|
+
|
|
303
|
+
# 44. C12 NEGATIVE:width="hug" 語義軸 → silent
|
|
304
|
+
run_hook "$PROD_TSX" 'export const F = () => <Select width="hug" options={opts} />'
|
|
305
|
+
expect_silent "44. C12 width=hug → silent"
|
|
306
|
+
|
|
307
|
+
# 45. named-import 除鏽 POSITIVE:無 DS. 前綴的 LinkInput placeholder-only 也要抓 → BLOCK
|
|
308
|
+
run_hook "$PROD_TSX" 'export const L = () => <LinkInput placeholder="https://" />'
|
|
309
|
+
expect_block "45. named-import <LinkInput placeholder-only → BLOCK(除鏽)"
|
|
310
|
+
|
|
311
|
+
# ── C19 兩欄 dialog 共用捲軸(2026-07-10 user 拍板組合 canonical)──
|
|
312
|
+
# 46. POSITIVE:兩欄(border-l)+ 只有 1 個 ScrollArea = 共用捲軸 → BLOCK
|
|
313
|
+
run_hook "$PROD_TSX" 'export const D = () => <DialogBody><ScrollArea><div className="flex"><div>main</div><aside className="border-l">meta</aside></div></ScrollArea></DialogBody>'
|
|
314
|
+
expect_block "46. C19 兩欄共用單一 ScrollArea → BLOCK"
|
|
315
|
+
|
|
316
|
+
# 47. NEGATIVE:各欄自帶 ScrollArea(組合 canonical)→ silent
|
|
317
|
+
run_hook "$PROD_TSX" 'export const D = () => <DialogBody><div className="flex"><ScrollArea>main</ScrollArea><aside className="border-l"><ScrollArea>meta</ScrollArea></aside></div></DialogBody>'
|
|
318
|
+
expect_silent "47. C19 各欄自帶 ScrollArea → silent"
|
|
319
|
+
|
|
320
|
+
# 48. NEGATIVE:escape → silent
|
|
321
|
+
run_hook "$PROD_TSX" 'export const D = () => <DialogBody><div className="flex border-l">x</div></DialogBody> // @two-pane-dialog-ok: 非兩欄,版面裝飾線'
|
|
322
|
+
expect_silent "48. C19 @two-pane-dialog-ok escape → silent"
|
|
323
|
+
|
|
324
|
+
# ── C7 SelectMenu 直用 + C13 手刻 section header(2026-07-10 收官)──
|
|
325
|
+
# 49. C7 POSITIVE:<SelectMenu> 直用 → BLOCK
|
|
326
|
+
run_hook "$PROD_TSX" 'export const M = () => <SelectMenu options={opts} onSelect={pick} />'
|
|
327
|
+
expect_block "49. C7 <SelectMenu> 直用 → BLOCK"
|
|
328
|
+
|
|
329
|
+
# 50. C7 NEGATIVE:<Select>(正道)→ silent
|
|
330
|
+
run_hook "$PROD_TSX" 'export const M = () => <Select options={opts} onChange={pick} />'
|
|
331
|
+
expect_silent "50. C7 <Select> 正道 → silent"
|
|
332
|
+
|
|
333
|
+
# 51. C13 POSITIVE:手刻可收合標題列(Chevron + justify-between + button)→ BLOCK
|
|
334
|
+
run_hook "$PROD_TSX" 'export const H = () => <button onClick={toggle} className="flex w-full items-center justify-between"><span>Description</span><ChevronDown className="size-4" /></button>'
|
|
335
|
+
expect_block "51. C13 手刻可收合標題列 → BLOCK"
|
|
336
|
+
|
|
337
|
+
# 52. C13 NEGATIVE:共用 SectionHeader 元件(正道)→ silent
|
|
338
|
+
run_hook "$PROD_TSX" 'export const H = () => <SectionHeader title="Description" collapsed={c} onToggle={toggle} />'
|
|
339
|
+
expect_silent "52. C13 共用 SectionHeader → silent"
|
|
340
|
+
|
|
341
|
+
# 53. C13 NEGATIVE:escape(非 section 標題語義)→ silent
|
|
342
|
+
run_hook "$PROD_TSX" 'export const P = () => <button onClick={next} className="flex justify-between">next<ChevronRight /></button> // @section-header-ok: 分頁導航非 section 標題'
|
|
343
|
+
expect_silent "53. C13 @section-header-ok escape → silent"
|
|
344
|
+
|
|
233
345
|
echo ""
|
|
234
346
|
echo "=== Summary ==="
|
|
235
347
|
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
@@ -161,12 +161,19 @@ expect_pass_silent "N4. DS internal stories → excluded silent"
|
|
|
161
161
|
run_hook "Read" "$CONSUMER_STORY" "$CONTENT_VIOLATION"
|
|
162
162
|
expect_pass_silent "N5. tool=Read → silent"
|
|
163
163
|
|
|
164
|
-
# N6. over-broad guard A:bare <Dialog>(no DS. namespace prefix)→ silent
|
|
164
|
+
# N6. over-broad guard A:bare <Dialog>(no DS. namespace prefix)from consumer-local import → silent
|
|
165
165
|
# consumer 用自己的 local Dialog,不是高風險 DS primitive → 不該 fire
|
|
166
166
|
CONTENT_BARE='import { Dialog } from "./local-dialog";
|
|
167
167
|
export const Basic = () => <Dialog open>hi</Dialog>;'
|
|
168
168
|
run_hook "Write" "$CONSUMER_STORY" "$CONTENT_BARE"
|
|
169
|
-
expect_pass_silent "N6. bare <Dialog> (
|
|
169
|
+
expect_pass_silent "N6. bare <Dialog> (local import) → silent (over-broad guard)"
|
|
170
|
+
|
|
171
|
+
# P5. named-import 除鏽 POSITIVE(2026-07-10):bare <Dialog> 但由 DS package named-import 進來
|
|
172
|
+
# → 是真 DS Dialog(fork 慣用 named import 繞過 <DS.> 前綴)→ 無 marker 必 BLOCK
|
|
173
|
+
CONTENT_NAMED='import { Dialog, Button } from "@qijenchen/design-system";
|
|
174
|
+
export const Basic = () => <Dialog open><Button>ok</Button></Dialog>;'
|
|
175
|
+
run_hook "Write" "$CONSUMER_STORY" "$CONTENT_NAMED"
|
|
176
|
+
expect_block "P5. named-import <Dialog> from DS pkg 無 marker → BLOCK" "CONSUMER-STORY-BASELINE BLOCKER"
|
|
170
177
|
|
|
171
178
|
# N7. over-broad guard B:comment / prose mentioning "Dialog DataTable Sheet" but no JSX usage → silent
|
|
172
179
|
CONTENT_PROSE='// This story demonstrates a layout. We avoid Dialog and DataTable here.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# test_check_dynamic_tailwind_class.sh — 動態 Tailwind class 哨測試
|
|
3
|
+
# (2026-07-10 補 hook-test-coverage debt;hook 2026-07-09 建,anchor = h-table-row-${size} row 塌)
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
cd "$(dirname "$0")/../../.."
|
|
6
|
+
HOOK=".claude/hooks/check_dynamic_tailwind_class.sh"
|
|
7
|
+
PASS=0; FAIL=0; FAILED_TESTS=""
|
|
8
|
+
|
|
9
|
+
TMP_DIR=$(mktemp -d)
|
|
10
|
+
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
11
|
+
export CLAUDE_PROJECT_DIR="$TMP_DIR"
|
|
12
|
+
mkdir -p "$TMP_DIR/.claude/logs"
|
|
13
|
+
|
|
14
|
+
PROD_TSX="/Users/x/proj/packages/design-system/src/components/DataTable/data-table.tsx"
|
|
15
|
+
|
|
16
|
+
run_hook() {
|
|
17
|
+
local file_path="$1"; local content="$2"
|
|
18
|
+
local payload
|
|
19
|
+
payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
|
|
20
|
+
'{tool_name:"Edit", tool_input:{file_path:$fp, new_string:$c}}')
|
|
21
|
+
STDERR=$(mktemp)
|
|
22
|
+
set +e
|
|
23
|
+
printf '%s' "$payload" | bash "$HOOK" >/dev/null 2>"$STDERR"
|
|
24
|
+
EXIT=$?
|
|
25
|
+
set -e
|
|
26
|
+
STDERR_TEXT=$(cat "$STDERR" 2>/dev/null); rm -f "$STDERR"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
expect_block() {
|
|
30
|
+
local name="$1"
|
|
31
|
+
if [ "$EXIT" = "2" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
32
|
+
else echo " FAIL $name (expected exit=2, got exit=$EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
33
|
+
}
|
|
34
|
+
expect_silent() {
|
|
35
|
+
local name="$1"
|
|
36
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
37
|
+
else echo " FAIL $name (expected silent exit=0, got exit=$EXIT, stderr=${STDERR_TEXT:+non-empty})"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# 1. POSITIVE:病根錨例 h-table-row-${size}(class 名含插值)→ BLOCK
|
|
41
|
+
run_hook "$PROD_TSX" 'const cls = `h-table-row-${size} flex`'
|
|
42
|
+
expect_block "1. h-table-row-\${size} → BLOCK"
|
|
43
|
+
|
|
44
|
+
# 2. POSITIVE:間距 utility gap-${g} → BLOCK
|
|
45
|
+
run_hook "$PROD_TSX" 'const cls = `flex gap-${g}`'
|
|
46
|
+
expect_block "2. gap-\${g} → BLOCK"
|
|
47
|
+
|
|
48
|
+
# 3. NEGATIVE:正解 literal map → silent
|
|
49
|
+
run_hook "$PROD_TSX" "const cls = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size]"
|
|
50
|
+
expect_silent "3. literal class 對照表 → silent"
|
|
51
|
+
|
|
52
|
+
# 4. NEGATIVE:arbitrary value 內插值(是值不是 class 名)→ silent
|
|
53
|
+
run_hook "$PROD_TSX" 'const cls = `h-[calc(100%_-_${offset}px)]`'
|
|
54
|
+
expect_silent "4. h-[calc(\${x})] arbitrary → silent"
|
|
55
|
+
|
|
56
|
+
# 5. NEGATIVE:var() 內插值 → silent
|
|
57
|
+
run_hook "$PROD_TSX" 'const cls = `w-[var(--col-${i})]`'
|
|
58
|
+
expect_silent "5. w-[var(--x-\${i})] → silent"
|
|
59
|
+
|
|
60
|
+
# 6. NEGATIVE:色彩 utility 不在 scope(hook 只鎖尺寸/間距)→ silent
|
|
61
|
+
run_hook "$PROD_TSX" 'const cls = `text-${color}`'
|
|
62
|
+
expect_silent "6. text-\${color}(非尺寸間距)→ silent"
|
|
63
|
+
|
|
64
|
+
# 7. NEGATIVE:escape 註解 → silent
|
|
65
|
+
run_hook "$PROD_TSX" 'const cls = `size-${px}` // @dynamic-tailwind-allow: 傳給 canvas 非 class'
|
|
66
|
+
expect_silent "7. @dynamic-tailwind-allow escape → silent"
|
|
67
|
+
|
|
68
|
+
# 8. NEGATIVE:非 production path(tests/)→ silent
|
|
69
|
+
run_hook "/Users/x/proj/scripts/gen-something.mjs" 'const cls = `h-${x}`'
|
|
70
|
+
expect_silent "8. 非 tsx production path → silent"
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "=== Summary ==="
|
|
74
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
75
|
+
if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
|
|
76
|
+
exit 0
|
|
@@ -182,6 +182,30 @@ expect_not_block "N8. empty content → not blocked"
|
|
|
182
182
|
run_hook_bypass "Write" "$CONSUMER" "content" "$C_3DISTINCT"
|
|
183
183
|
expect_not_block "N9. CLAUDE_BYPASS_ESCAPE_MARKER_AUDIT=1 override → not blocked"
|
|
184
184
|
|
|
185
|
+
# ── R-series:repo 級累計 ratchet(2026-07-08 WM 戰役 R4)──────────────────────
|
|
186
|
+
# 存量 ≥10(apps/** 全 repo)後,只擋「本次 edit 再新增 marker」;無 marker edit 不 brick。
|
|
187
|
+
mkdir -p "$TMP_DIR/apps/work/src"
|
|
188
|
+
for i in 1 2 3 4 5 6; do
|
|
189
|
+
printf '// @ds-misuse-allow: seeded reason %s\n// @layout-space-magic-ok: seeded reason %sb\n' "$i" "$i" \
|
|
190
|
+
> "$TMP_DIR/apps/work/src/seed$i.tsx"
|
|
191
|
+
done
|
|
192
|
+
|
|
193
|
+
# R1. 存量 12 ≥ cap 10 + 本次新增 1 marker → BLOCK(ratchet)
|
|
194
|
+
run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div /> // @ds-misuse-allow: one more'
|
|
195
|
+
expect_block "R1. repo 存量 12 ≥ cap + edit 加 marker → blocked (ratchet)" "ESCAPE-MARKER-REPO-RATCHET"
|
|
196
|
+
|
|
197
|
+
# R2. 存量 12 ≥ cap 但本次 edit 無 marker → not blocked(不因存量 brick 無關 edit)
|
|
198
|
+
run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div className="flex" />'
|
|
199
|
+
expect_not_block "R2. repo 存量 ≥ cap 但 edit 無 marker → not blocked"
|
|
200
|
+
|
|
201
|
+
# R3. 存量降到 4 < cap + 本次加 1 marker → not blocked
|
|
202
|
+
rm -f "$TMP_DIR/apps/work/src/seed3.tsx" "$TMP_DIR/apps/work/src/seed4.tsx" \
|
|
203
|
+
"$TMP_DIR/apps/work/src/seed5.tsx" "$TMP_DIR/apps/work/src/seed6.tsx"
|
|
204
|
+
run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div /> // @ds-misuse-allow: legit case'
|
|
205
|
+
expect_not_block "R3. repo 存量 4 < cap + edit 加 marker → not blocked"
|
|
206
|
+
|
|
207
|
+
rm -rf "$TMP_DIR/apps"
|
|
208
|
+
|
|
185
209
|
echo ""
|
|
186
210
|
echo "=== Summary ==="
|
|
187
211
|
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Tests for check_field_family_invariants.sh — merged
|
|
2
|
+
# Tests for check_field_family_invariants.sh — merged sub-rules(A.1-A.4 + A.6)
|
|
3
3
|
#
|
|
4
|
-
# Coverage(每 sub-rule pass + block 各 1 case
|
|
4
|
+
# Coverage(每 sub-rule pass + block 各 1 case):
|
|
5
5
|
# A.1 naked row-mode propagation:pass / block / allowlist
|
|
6
6
|
# A.2 FieldControlGroup wrapper child:pass / block / allowlist
|
|
7
7
|
# A.3 Field state ring SSOT:pass / 3 block(shadow inset / outline / per-control open)
|
|
8
8
|
# A.4 disabled placeholder color:pass / 1 stderr-warn(exit 0)/ allowlist
|
|
9
|
+
# A.6 空值顯示 SSOT(2026-07-08 半形 hyphen):非 owner import EMPTY_DISPLAY block /
|
|
10
|
+
# owner skip / 全形 em dash block / 半形 pass / allowlist
|
|
9
11
|
# non-target:non-tsx skip / SSOT host skip(field-wrapper.tsx)
|
|
10
12
|
|
|
11
13
|
set -u
|
|
@@ -183,6 +185,29 @@ else
|
|
|
183
185
|
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - A.4.3"
|
|
184
186
|
fi
|
|
185
187
|
|
|
188
|
+
echo ""
|
|
189
|
+
echo "=== A.6 空值顯示 SSOT(2026-07-08 半形 hyphen)==="
|
|
190
|
+
|
|
191
|
+
# 17. 非 owner import EMPTY_DISPLAY → BLOCK(應消費 useFieldEmptyDisplay hook 分流)
|
|
192
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "import { EMPTY_DISPLAY } from '@/design-system/components/Field/field-wrapper'"
|
|
193
|
+
expect_exit "A.6.1 非 owner import EMPTY_DISPLAY → BLOCK" 2 "EMPTY_DISPLAY 直引"
|
|
194
|
+
|
|
195
|
+
# 18. owner field-context.ts import EMPTY_DISPLAY → pass(SSOT owner skip)
|
|
196
|
+
run_hook "/r/packages/design-system/src/components/Field/field-context.ts" "import { EMPTY_DISPLAY } from './field-wrapper'"
|
|
197
|
+
expect_exit "A.6.1 owner field-context.ts import → pass" 0
|
|
198
|
+
|
|
199
|
+
# 19. components tsx hardcode 全形 em dash '—' → BLOCK
|
|
200
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const cls = value ?? '—'"
|
|
201
|
+
expect_exit "A.6.2 hardcode 全形 em dash → BLOCK" 2 "全形 em dash"
|
|
202
|
+
|
|
203
|
+
# 20. 半形 hyphen '-' → pass(非全形,不觸發)
|
|
204
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const sep = '-'"
|
|
205
|
+
expect_exit "A.6.2 半形 hyphen → pass" 0
|
|
206
|
+
|
|
207
|
+
# 21. allowlist → pass
|
|
208
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const cls = value ?? '—' // @empty-display-allow: legacy N/A marker"
|
|
209
|
+
expect_exit "A.6 allowlist → pass" 0
|
|
210
|
+
|
|
186
211
|
echo ""
|
|
187
212
|
echo "=== Skip cases ==="
|
|
188
213
|
|
|
@@ -56,6 +56,18 @@ expect_warn() {
|
|
|
56
56
|
fi
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
# #71 soft WARN tier(micro_gap / fraction):exit 0(不 block)+ stderr 含 'soft flag'
|
|
60
|
+
expect_soft_flag() {
|
|
61
|
+
local name="$1"
|
|
62
|
+
if [ "$EXIT" = "0" ] && echo "$STDERR_TEXT" | grep -qF "soft flag"; then
|
|
63
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
64
|
+
else
|
|
65
|
+
echo " FAIL $name (expected exit=0 + 'soft flag', got exit=$EXIT)"
|
|
66
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
67
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
59
71
|
echo "=== check_opacity_token_usage tests ==="
|
|
60
72
|
|
|
61
73
|
# 1. raw opacity-30 → warn
|
|
@@ -101,6 +113,33 @@ const b = "opacity-75"
|
|
|
101
113
|
'
|
|
102
114
|
expect_warn "7. multi opacity-N values → warn" "opacity-25"
|
|
103
115
|
|
|
116
|
+
# ── #71 micro_gap / fraction soft WARN tier(2026-07-11 接線)──────────────────
|
|
117
|
+
FP71="/repo/packages/design-system/src/components/Calendar/calendar.tsx"
|
|
118
|
+
|
|
119
|
+
# 8. gap-0.5(micro gap)→ soft flag(exit 0,非 block)
|
|
120
|
+
run_hook "$FP71" 'const a = <div className="gap-0.5" />'
|
|
121
|
+
expect_soft_flag "8. gap-0.5 micro gap → soft WARN(非 block)"
|
|
122
|
+
|
|
123
|
+
# 9. w-1/3(registry fraction)→ soft flag(exit 0)
|
|
124
|
+
run_hook "$FP71" 'const a = <div className="w-1/3" />'
|
|
125
|
+
expect_soft_flag "9. w-1/3 registry fraction → soft WARN"
|
|
126
|
+
|
|
127
|
+
# 10. w-1/2(合法,不在 registry 14 條)→ silent(不誤殺)
|
|
128
|
+
run_hook "$FP71" 'const a = <div className="w-1/2" />'
|
|
129
|
+
expect_pass_silent "10. w-1/2(合法留白)→ silent 不誤殺"
|
|
130
|
+
|
|
131
|
+
# 11. gap-2(合法)→ silent
|
|
132
|
+
run_hook "$FP71" 'const a = <div className="gap-2" />'
|
|
133
|
+
expect_pass_silent "11. gap-2(合法)→ silent"
|
|
134
|
+
|
|
135
|
+
# 12. 硬 violation + gap-0.5 → exit 2(hard block 不被 soft tier 弱化)
|
|
136
|
+
run_hook "$FP71" 'const a = <div className="text-muted-foreground gap-0.5" />'
|
|
137
|
+
expect_warn "12. 硬 violation + gap-0.5 → exit 2 block" "shadcn alias"
|
|
138
|
+
|
|
139
|
+
# 13. gap-0.5 + @token-registry-ok escape → silent
|
|
140
|
+
run_hook "$FP71" 'const a = <div className="gap-0.5" /> // @token-registry-ok: skeleton bone'
|
|
141
|
+
expect_pass_silent "13. gap-0.5 + escape → silent"
|
|
142
|
+
|
|
104
143
|
echo ""
|
|
105
144
|
echo "=== Summary ==="
|
|
106
145
|
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# test_check_tabs_content_chrome_body_double_gap.sh — overlay-body layout-space 哨測試
|
|
3
|
+
# (2026-07-10 補 hook-test-coverage debt;hook 2026-07-01 建,anchor = 專案設定 Dialog 雙 tight)
|
|
4
|
+
# 注意:本 hook 是 PostToolUse「讀完整檔」型(防 partial-edit 盲區)→ 測試必寫真實 temp 檔,
|
|
5
|
+
# 且路徑必須匹配 scope regex(packages/design-system/src/ 或 /apps/)。
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
cd "$(dirname "$0")/../../.."
|
|
8
|
+
HOOK=".claude/hooks/check_tabs_content_chrome_body_double_gap.sh"
|
|
9
|
+
PASS=0; FAIL=0; FAILED_TESTS=""
|
|
10
|
+
|
|
11
|
+
TMP_DIR=$(mktemp -d)
|
|
12
|
+
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
13
|
+
export CLAUDE_PROJECT_DIR="$TMP_DIR"
|
|
14
|
+
mkdir -p "$TMP_DIR/.claude/logs"
|
|
15
|
+
|
|
16
|
+
# scope 內的真實 temp 檔路徑(hook 讀 disk)
|
|
17
|
+
DS_DIR="$TMP_DIR/packages/design-system/src/components/Dialog"
|
|
18
|
+
mkdir -p "$DS_DIR"
|
|
19
|
+
|
|
20
|
+
run_hook_file() {
|
|
21
|
+
local file_path="$1"; local content="$2"
|
|
22
|
+
mkdir -p "$(dirname "$file_path")"
|
|
23
|
+
printf '%s' "$content" > "$file_path"
|
|
24
|
+
local payload
|
|
25
|
+
payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
|
|
26
|
+
'{tool_name:"Edit", tool_input:{file_path:$fp, new_string:$c}}')
|
|
27
|
+
STDERR=$(mktemp)
|
|
28
|
+
set +e
|
|
29
|
+
printf '%s' "$payload" | bash "$HOOK" >/dev/null 2>"$STDERR"
|
|
30
|
+
EXIT=$?
|
|
31
|
+
set -e
|
|
32
|
+
STDERR_TEXT=$(cat "$STDERR" 2>/dev/null); rm -f "$STDERR"
|
|
33
|
+
rm -f "$file_path"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
expect_block() {
|
|
37
|
+
local name="$1"
|
|
38
|
+
if [ "$EXIT" = "2" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
39
|
+
else echo " FAIL $name (expected exit=2, got exit=$EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
40
|
+
}
|
|
41
|
+
expect_silent() {
|
|
42
|
+
local name="$1"
|
|
43
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
44
|
+
else echo " FAIL $name (expected silent exit=0, got exit=$EXIT, stderr=${STDERR_TEXT:+non-empty})"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# 1. POSITIVE(Check 1 錨例):chrome body 內 TabsContent 無 mt-0 → 雙重 gap → BLOCK
|
|
48
|
+
run_hook_file "$DS_DIR/case1.stories.tsx" '<DialogBody><Tabs value={t}><TabsContent value="a"><p>內容</p></TabsContent></Tabs></DialogBody>'
|
|
49
|
+
expect_block "1. DialogBody 內 TabsContent 無 mt-0 → BLOCK"
|
|
50
|
+
|
|
51
|
+
# 2. NEGATIVE:TabsContent 帶 mt-0(ownership 轉移給 body)→ silent
|
|
52
|
+
run_hook_file "$DS_DIR/case2.stories.tsx" '<DialogBody><Tabs value={t}><TabsContent value="a" className="mt-0"><p>內容</p></TabsContent></Tabs></DialogBody>'
|
|
53
|
+
expect_silent "2. TabsContent className=mt-0 → silent"
|
|
54
|
+
|
|
55
|
+
# 3. NEGATIVE:TabsContent 不在 chrome body 內(頁面級 Tabs)→ silent
|
|
56
|
+
run_hook_file "$DS_DIR/case3.stories.tsx" '<Tabs value={t}><TabsList>…</TabsList><TabsContent value="a"><p>內容</p></TabsContent></Tabs>'
|
|
57
|
+
expect_silent "3. 頁面級 Tabs(無 chrome body)→ silent"
|
|
58
|
+
|
|
59
|
+
# 4. POSITIVE(Check 3 root 簽名):TabsList 手塞 DialogBody 同檔且無 tabsSlot → BLOCK
|
|
60
|
+
run_hook_file "$DS_DIR/case4.stories.tsx" '<DialogBody><TabsList size="sm"><TabsTrigger value="a">A</TabsTrigger></TabsList><TabsContent value="a" className="mt-0">x</TabsContent></DialogBody>'
|
|
61
|
+
expect_block "4. TabsList 手塞 chrome body 無 tabsSlot → BLOCK(root)"
|
|
62
|
+
|
|
63
|
+
# 5. NEGATIVE:escape 註解 → silent
|
|
64
|
+
run_hook_file "$DS_DIR/case5.stories.tsx" '{/* @tabs-content-gap-ok: 內容層分頁非 dialog chrome */}
|
|
65
|
+
<DialogBody><Tabs value={t}><TabsContent value="a">x</TabsContent></Tabs></DialogBody>'
|
|
66
|
+
expect_silent "5. @tabs-content-gap-ok escape → silent"
|
|
67
|
+
|
|
68
|
+
# 6. NEGATIVE:scope 外路徑(非 DS-src / apps)→ silent
|
|
69
|
+
run_hook_file "$TMP_DIR/docs/example.tsx" '<DialogBody><TabsContent value="a">x</TabsContent></DialogBody>'
|
|
70
|
+
expect_silent "6. scope 外路徑 → silent"
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "=== Summary ==="
|
|
74
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
75
|
+
if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
|
|
76
|
+
exit 0
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
| 真缺項 | 補的形式 | Commit |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| #13 i18n 硬寫字串 |
|
|
48
|
+
| #13 i18n 硬寫字串 | `post_edit_dispatcher.sh → lib/_hardcoded_strings.sh` PostToolUse flag(2026-05-13 由獨立 hook `check_hardcoded_strings.sh` folded 進 dispatcher lib),flag DS primitive tsx(非 stories)CJK ≥ 3 chars / 英文 sentence-case label;支援 `// i18n-allow: {rationale}` 白名單 | 本次 session |
|
|
49
49
|
| #3 Controlled / Uncontrolled + #12 Form dual-mode | `design-system-audit` Dim 26(新 Group J)— 掃 form + overlay 元件 value/defaultValue / open/defaultOpen / checked/defaultChecked 的 pair 完整性;V1-V4 violation types | 本次 session |
|
|
50
50
|
| #23 edge case(null / empty / rapid / success) | `/ux-audit` Phase 5 從 3 態 → 5 態 + null-safety + rapid-interaction + edge case corollary | 本次 session |
|
|
51
51
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
| 資料表格(含 header / sorting / sticky) | `<table><thead>...</thead><tbody>...</tbody></table>` | `<DataTable columns={...} data={...} />` |
|
|
19
19
|
| 檔案上傳列表 | `<div>filename</div><ProgressBar /><Paperclip />` | `<FileItem mode="compact" />` or `<FileUpload>` |
|
|
20
20
|
| 表單欄位(label + control + error) | `<label>...</label><input/><span className="text-error">...</span>` | `<Field><FieldLabel>...<Input />...<FieldError/>` |
|
|
21
|
+
| 表單提交驗證(何時顯錯 / 提交可點性) | 手刻 `useState(showErrors)` + `submitAttempt` 旗標自組顯錯時機 | `useFormValidation`(Field 家族 hook,`intent:'create'` = 提交恆可點、點擊時 validate 顯錯;搭 `<FieldError>`)|
|
|
21
22
|
| 全頁 / 區域 loading | `<div className="absolute inset-0 flex center"><Spinner /></div>` | `<Empty icon={<CircularProgress />} description="..." />` |
|
|
22
23
|
| 確認對話框 | raw `<div className="fixed inset-0 bg-black/50">...<button>OK</button>` | `<Dialog>` + `<DialogHeader>` etc |
|
|
23
24
|
| 分隔線 | `<hr className="..." />` or `<div className="h-px bg-..."/>` | `<Separator />`(必要時)or CSS border(見 separator.spec) |
|
|
@@ -60,7 +61,7 @@
|
|
|
60
61
|
- 以上都沒命中 → 才可自建,但 **建完要立刻回來加行**(防下一個人又重造輪子)
|
|
61
62
|
- **本規則同樣適用 story / consumer / exploration code**:不 hand-craft 已有 prop 能做的事(如 Input loading 走 `loading` prop 不自刻 `<div className="relative"><input/><div className="absolute">` / 全頁 loading 走 `<Empty icon={<CircularProgress/>}/>` 不自刻 `absolute inset-0`)。遇缺口**回元件 spec 擴 API**,不自刻繞過 — hand-craft 視覺對齊 bug 上游
|
|
62
63
|
|
|
63
|
-
具體 anti-pattern signals →
|
|
64
|
+
具體 anti-pattern signals → `design-system-audit/references/audit-prompts.md`「L1. 手刻繞 DS canonical」+ Dim 71 consumer 手刻(Pattern 10;現行 Dim 21 已是「連續 item list wrapper gap」,勿誤指);pixel-level 視覺 regression(API 用對但視覺仍跑掉)→ `/visual-audit`(D5)抓(原 memory `project_pending_tasks` 已 retire)。
|
|
64
65
|
|
|
65
66
|
---
|
|
66
67
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"invariant": "每類被抓過的 failure class 必須終有 ship 到 consumer 的機械防線(user 2026-07-10 verbatim「建立治理的基本原則」)。status 三態:protected(已有 MECHANICAL_CONSUMER / DS_API_FIXED 防線)/ remediating(必帶 plan 指標)/ judgment(regex 不可判,必帶 auditDim 兜底)。gate = scripts/audit-failure-class-coverage.mjs --check(deep-audit dim 91 chain)。",
|
|
4
|
+
"source": ".claude/logs/failure-class-coverage-matrix.json(2026-07-10 41-agent 對抗 workflow,每 verdict cite 驗證)",
|
|
5
|
+
"addRule": "新 failure class(deep-audit / user 抓 / codex 抓)→ 本 registry 加 row;沒 row 或 status 缺 = gate 紅燈。remediation 落地後把 status 升 protected 並記 landedAt。"
|
|
6
|
+
},
|
|
7
|
+
"classes": [
|
|
8
|
+
{
|
|
9
|
+
"id": "phantom-layout-token",
|
|
10
|
+
"name": "幻覺 layout token / utility",
|
|
11
|
+
"status": "protected",
|
|
12
|
+
"note": "check_layout_space_magic_numbers PHANTOM 白名單(SHIP_AS_IS)+ opacity hook 第 10 類幻覺 state 尾綴(2026-07-10)"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "handcraft-mini-table",
|
|
16
|
+
"name": "手刻 mini-table(grid-cols 黏死欄寬)",
|
|
17
|
+
"status": "protected",
|
|
18
|
+
"note": "r3 偽表格簽名 + magic-hook grid-cols px(皆 SHIP_AS_IS)"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "handcraft-menu-item-row",
|
|
22
|
+
"name": "手刻 menu-item 可點列",
|
|
23
|
+
"status": "protected",
|
|
24
|
+
"landedAt": "2026-07-10",
|
|
25
|
+
"note": "根因 MenuItem startContent(beta.84)+ r3 nav-row 簽名(hover+selected 成對)"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "export-chain-break",
|
|
29
|
+
"name": "export 斷鏈逼手刻(R2)",
|
|
30
|
+
"status": "protected",
|
|
31
|
+
"note": "DS_API_FIXED — barrel generator + preflight --check drift gate;beta.84 發版後 consumer 正式接上"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "contrast-pair-violation",
|
|
35
|
+
"name": "對比配對違規(亮色底 × text-white)",
|
|
36
|
+
"status": "protected",
|
|
37
|
+
"landedAt": "2026-07-10",
|
|
38
|
+
"note": "r3 C5 簽名 → CAT_SOLID pair"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "handcraft-form-validation",
|
|
42
|
+
"name": "手刻表單驗證 state",
|
|
43
|
+
"status": "protected",
|
|
44
|
+
"note": "r3 useFormValidation 零消費簽名(SHIP_AS_IS)"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "selectmenu-direct-use",
|
|
48
|
+
"name": "SelectMenu internal 直用",
|
|
49
|
+
"status": "protected",
|
|
50
|
+
"note": "r3 C7 簽名(<SelectMenu 直用 → BLOCK,escape @selectmenu-direct-ok:;select-menu.spec.md:53 明文禁直用特例)",
|
|
51
|
+
"landedAt": "2026-07-10"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "handcraft-header-tabs",
|
|
55
|
+
"name": "頁內手刻 header+TabsList(未走 tabsSlot)",
|
|
56
|
+
"status": "judgment",
|
|
57
|
+
"note": "dialog/surface 半邊已有 check_tabs_content_chrome_body_double_gap P0(SHIP_AS_IS);頁內 h2+TabsList 存在合法場景(TypeSettings 內容層分頁 @tabs-content-gap-ok 錨例)= context 判斷,倉促 regex = 誤殺",
|
|
58
|
+
"auditDim": "product-ui-audit + header-canonical.spec.md Rule W4"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "spacing-tier-semantic",
|
|
62
|
+
"name": "spacing 親疏語義誤用(tier 選錯)",
|
|
63
|
+
"status": "judgment",
|
|
64
|
+
"auditDim": "90(layout-space macro judgment sweep)+ product-ui-audit",
|
|
65
|
+
"note": "合法 token 用錯 tier = context 判斷,regex 不可判;magic/phantom 機械半邊已 protected"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "search-action-position",
|
|
69
|
+
"name": "業務 search 被推工具層位置",
|
|
70
|
+
"status": "protected",
|
|
71
|
+
"landedAt": "2026-07-10",
|
|
72
|
+
"note": "r3 C10 簽名(spacer+Search Input);業務 vs 工具判定本身 judgment → escape @search-right-ok"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "dialog-chrome-double-x",
|
|
76
|
+
"name": "dialog chrome 雙 X / header 操作不走 actions",
|
|
77
|
+
"status": "protected",
|
|
78
|
+
"landedAt": "2026-07-10",
|
|
79
|
+
"note": "r3 C11 簽名(DialogHeader 250 字窗)"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "field-width-misuse",
|
|
83
|
+
"name": "Field 家族硬寬 / hug-fill 語義",
|
|
84
|
+
"status": "protected",
|
|
85
|
+
"landedAt": "2026-07-10",
|
|
86
|
+
"note": "硬寬 w-N 機械(r3 C12);hug vs fill 語義選擇 = judgment 半邊歸 product-ui-audit"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "handcraft-section-header",
|
|
90
|
+
"name": "手刻可收合 section header",
|
|
91
|
+
"status": "protected",
|
|
92
|
+
"note": "R3-7 拍板 codify 進 item-anatomy.spec.md「可收合 section header 組合 canonical」(組合非元件,隨 npm ship)+ r3 C13 簽名(Chevron+justify-between+可點且無共用元件 → BLOCK)",
|
|
93
|
+
"landedAt": "2026-07-10"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"id": "avatar-anatomy-misuse",
|
|
97
|
+
"name": "avatar row-context 直用(未走 ItemAvatar/PersonValue 鏈)",
|
|
98
|
+
"status": "judgment",
|
|
99
|
+
"note": "前置已清:PersonValue/PersonDisplay/PersonAvatarTag 2026-07-10 補進 export 面(probe 驗 root barrel 解析)= 正道可 import;「row context 內 raw Avatar」判定 = context 判斷,regex 不可判(Avatar 合法 standalone 場景遍地)",
|
|
100
|
+
"auditDim": "product-ui-audit + item-anatomy.spec.md:178(Prefix 垂直對齊)"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"id": "datatable-density-structure",
|
|
104
|
+
"name": "DataTable 密度/tree 佔位/inline-create idle 未消費",
|
|
105
|
+
"status": "judgment",
|
|
106
|
+
"note": "tree 佔位半邊 DS_API_FIXED(data-table.tsx sibling-aware,beta.84 生效);size 密度選擇與 idle 列樣式 = context 判斷(嵌入式 vs 主表格),spec 隨 npm ship 供讀",
|
|
107
|
+
"auditDim": "product-ui-audit + data-table.spec.md:71/80(size 密度)+ :360(inline-create idle)"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "always-edit-cell",
|
|
111
|
+
"name": "恆-edit cell(display 態渲染 edit 控件)",
|
|
112
|
+
"status": "judgment",
|
|
113
|
+
"note": "機械半邊已上:story-baseline-registry antiPattern datatable-always-edit-cell(cell: 直渲 edit 控件 → R8 BLOCK,unless onCellCommit/editable/display);custom cell 元件包裹子集 regex 看不進去 + RoleCell 拍板反例證實 context 判斷 → judgment 兜底",
|
|
114
|
+
"auditDim": "product-ui-audit + data-table.spec.md:373(indicator A 案)"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "separator-geometry",
|
|
118
|
+
"name": "分隔線幾何(黏按鈕無 mx)",
|
|
119
|
+
"status": "protected",
|
|
120
|
+
"landedAt": "2026-07-10",
|
|
121
|
+
"note": "r3 C17 簽名 + magic-hook divider 行豁免(治理自我打架修正)"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "count-label-concat",
|
|
125
|
+
"name": "計數括號串接(children 層)",
|
|
126
|
+
"status": "protected",
|
|
127
|
+
"landedAt": "2026-07-10",
|
|
128
|
+
"note": "r3 C18 簽名(children 錨定,aria attr 合法)"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"id": "two-pane-dialog",
|
|
132
|
+
"name": "兩欄 dialog 版型 canonical 缺席",
|
|
133
|
+
"status": "protected",
|
|
134
|
+
"landedAt": "2026-07-10",
|
|
135
|
+
"note": "user 拍板:組合非元件(對齊 Atlassian/MUI composition verdict)→ overlay-surface.spec.md「兩欄 dialog 組合 canonical」(隨 npm ship)+ r3 C19 簽名(共用捲軸機械攔)"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"id": "handcraft-link-underline",
|
|
139
|
+
"name": "連結字手刻 underline",
|
|
140
|
+
"status": "protected",
|
|
141
|
+
"landedAt": "2026-07-10",
|
|
142
|
+
"note": "r3 C20 簽名(no-underline / hover:underline 形不誤殺)"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|