@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.
Files changed (622) hide show
  1. package/CLAUDE.md +8 -8
  2. package/README.md +3 -2
  3. package/dist/components/Alert/alert.js.map +1 -1
  4. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  5. package/dist/components/AppShell/app-shell.d.ts +1 -1
  6. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  7. package/dist/components/AppShell/app-shell.js +22 -2
  8. package/dist/components/AppShell/app-shell.js.map +1 -1
  9. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  10. package/dist/components/Avatar/avatar.js +4 -4
  11. package/dist/components/Avatar/avatar.js.map +1 -1
  12. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  13. package/dist/components/Breadcrumb/breadcrumb.js +1 -1
  14. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  15. package/dist/components/Button/button.d.ts +2 -2
  16. package/dist/components/Button/button.d.ts.map +1 -1
  17. package/dist/components/Button/button.js +12 -3
  18. package/dist/components/Button/button.js.map +1 -1
  19. package/dist/components/Calendar/calendar.d.ts +13 -5
  20. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  21. package/dist/components/Calendar/calendar.js +7 -1
  22. package/dist/components/Calendar/calendar.js.map +1 -1
  23. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  24. package/dist/components/Carousel/carousel.js +8 -3
  25. package/dist/components/Carousel/carousel.js.map +1 -1
  26. package/dist/components/Chart/chart.d.ts.map +1 -1
  27. package/dist/components/Chart/chart.js +1 -0
  28. package/dist/components/Chart/chart.js.map +1 -1
  29. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox/checkbox.js +8 -4
  32. package/dist/components/Checkbox/checkbox.js.map +1 -1
  33. package/dist/components/Chip/chip.d.ts +1 -1
  34. package/dist/components/Chip/chip.d.ts.map +1 -1
  35. package/dist/components/Chip/chip.js.map +1 -1
  36. package/dist/components/Coachmark/coachmark.d.ts +10 -3
  37. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  38. package/dist/components/Coachmark/coachmark.js.map +1 -1
  39. package/dist/components/Combobox/combobox.d.ts +5 -1
  40. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  41. package/dist/components/Combobox/combobox.js +30 -13
  42. package/dist/components/Combobox/combobox.js.map +1 -1
  43. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  44. package/dist/components/DataTable/cell-registry.js +53 -62
  45. package/dist/components/DataTable/cell-registry.js.map +1 -1
  46. package/dist/components/DataTable/column-types.d.ts +10 -4
  47. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  48. package/dist/components/DataTable/column-types.js.map +1 -1
  49. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
  50. package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
  51. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
  52. package/dist/components/DataTable/data-table-filter-group.d.ts +47 -0
  53. package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
  54. package/dist/components/DataTable/data-table-filter-group.js +154 -0
  55. package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
  56. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-filter-panel.js +285 -0
  58. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  59. package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
  60. package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
  61. package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
  62. package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
  63. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  64. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  65. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  66. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  67. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  68. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  69. package/dist/components/DataTable/data-table.d.ts +5 -6
  70. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  71. package/dist/components/DataTable/data-table.js +36 -15
  72. package/dist/components/DataTable/data-table.js.map +1 -1
  73. package/dist/components/DataTable/filter-operators.js +140 -0
  74. package/dist/components/DataTable/filter-operators.js.map +1 -0
  75. package/dist/components/DataTable/filter-tree.js +312 -0
  76. package/dist/components/DataTable/filter-tree.js.map +1 -0
  77. package/dist/components/DataTable/index.d.ts +3 -0
  78. package/dist/components/DataTable/index.d.ts.map +1 -1
  79. package/dist/components/DataTable/index.js +12 -1
  80. package/dist/components/DataTable/index.js.map +1 -1
  81. package/dist/components/DataTable/lib/column-meta.js +25 -0
  82. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  83. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  84. package/dist/components/DateGrid/date-grid.js +3 -1
  85. package/dist/components/DateGrid/date-grid.js.map +1 -1
  86. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  87. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  88. package/dist/components/DatePicker/date-picker.js +105 -74
  89. package/dist/components/DatePicker/date-picker.js.map +1 -1
  90. package/dist/components/Dialog/dialog.d.ts +20 -3
  91. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  92. package/dist/components/Dialog/dialog.js +38 -20
  93. package/dist/components/Dialog/dialog.js.map +1 -1
  94. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  95. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  96. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  97. package/dist/components/Field/field-context.d.ts +45 -5
  98. package/dist/components/Field/field-context.d.ts.map +1 -1
  99. package/dist/components/Field/field-context.js +19 -0
  100. package/dist/components/Field/field-context.js.map +1 -1
  101. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  102. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  103. package/dist/components/Field/field-edit-keys.js +19 -0
  104. package/dist/components/Field/field-edit-keys.js.map +1 -0
  105. package/dist/components/Field/field-types.d.ts +20 -1
  106. package/dist/components/Field/field-types.d.ts.map +1 -1
  107. package/dist/components/Field/field-types.js.map +1 -1
  108. package/dist/components/Field/field-wrapper.d.ts +3 -2
  109. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  110. package/dist/components/Field/field-wrapper.js +38 -39
  111. package/dist/components/Field/field-wrapper.js.map +1 -1
  112. package/dist/components/Field/field.d.ts +2 -1
  113. package/dist/components/Field/field.d.ts.map +1 -1
  114. package/dist/components/Field/field.js.map +1 -1
  115. package/dist/components/Field/index.d.ts +1 -0
  116. package/dist/components/Field/index.d.ts.map +1 -1
  117. package/dist/components/Field/index.js +2 -0
  118. package/dist/components/Field/index.js.map +1 -1
  119. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  120. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  121. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  122. package/dist/components/FileItem/file-item.js +1 -1
  123. package/dist/components/FileItem/file-item.js.map +1 -1
  124. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  125. package/dist/components/FileUpload/file-upload.js.map +1 -1
  126. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  127. package/dist/components/FileViewer/file-viewer.js +7 -2
  128. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  129. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  130. package/dist/components/FileViewer/image-renderer.js +22 -1
  131. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  132. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  133. package/dist/components/HoverCard/hover-card.js +5 -3
  134. package/dist/components/HoverCard/hover-card.js.map +1 -1
  135. package/dist/components/InlineEdit/index.d.ts +2 -0
  136. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  137. package/dist/components/InlineEdit/index.js +5 -0
  138. package/dist/components/InlineEdit/index.js.map +1 -0
  139. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  140. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  141. package/dist/components/InlineEdit/inline-edit.js +164 -0
  142. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  143. package/dist/components/Input/input.d.ts +6 -11
  144. package/dist/components/Input/input.d.ts.map +1 -1
  145. package/dist/components/Input/input.js +43 -13
  146. package/dist/components/Input/input.js.map +1 -1
  147. package/dist/components/LinkInput/link-input.d.ts +2 -2
  148. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  149. package/dist/components/LinkInput/link-input.js +6 -5
  150. package/dist/components/LinkInput/link-input.js.map +1 -1
  151. package/dist/components/Menu/menu-item.d.ts +14 -2
  152. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  153. package/dist/components/Menu/menu-item.js +25 -3
  154. package/dist/components/Menu/menu-item.js.map +1 -1
  155. package/dist/components/NumberInput/number-input.d.ts +3 -3
  156. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  157. package/dist/components/NumberInput/number-input.js +6 -5
  158. package/dist/components/NumberInput/number-input.js.map +1 -1
  159. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  160. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  161. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  162. package/dist/components/Pagination/pagination.js +1 -1
  163. package/dist/components/Pagination/pagination.js.map +1 -1
  164. package/dist/components/PeoplePicker/index.js +7 -1
  165. package/dist/components/PeoplePicker/index.js.map +1 -1
  166. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  167. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  168. package/dist/components/PeoplePicker/people-picker.js +23 -10
  169. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  170. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  171. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  172. package/dist/components/PeoplePicker/person-display.js +19 -14
  173. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  174. package/dist/components/Popover/popover.d.ts.map +1 -1
  175. package/dist/components/Popover/popover.js +3 -1
  176. package/dist/components/Popover/popover.js.map +1 -1
  177. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  178. package/dist/components/ProfileCard/profile-card.js +3 -3
  179. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  180. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  181. package/dist/components/RadioGroup/radio-group.js +15 -9
  182. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  183. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  184. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  185. package/dist/components/ScrollArea/scroll-area.js +6 -3
  186. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  187. package/dist/components/Select/select.d.ts +46 -5
  188. package/dist/components/Select/select.d.ts.map +1 -1
  189. package/dist/components/Select/select.js +109 -28
  190. package/dist/components/Select/select.js.map +1 -1
  191. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  192. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  193. package/dist/components/SelectMenu/select-menu.js +8 -1
  194. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  195. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  196. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  197. package/dist/components/SelectionControl/boolean-value.js +23 -0
  198. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  199. package/dist/components/SelectionControl/index.d.ts +1 -0
  200. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  201. package/dist/components/SelectionControl/index.js +2 -0
  202. package/dist/components/SelectionControl/index.js.map +1 -1
  203. package/dist/components/Sheet/index.js +2 -1
  204. package/dist/components/Sheet/sheet.d.ts +7 -1
  205. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  206. package/dist/components/Sheet/sheet.js +5 -2
  207. package/dist/components/Sheet/sheet.js.map +1 -1
  208. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  209. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  210. package/dist/components/Sidebar/sidebar.js +8 -10
  211. package/dist/components/Sidebar/sidebar.js.map +1 -1
  212. package/dist/components/Slider/slider.d.ts.map +1 -1
  213. package/dist/components/Slider/slider.js.map +1 -1
  214. package/dist/components/Switch/switch.d.ts +6 -6
  215. package/dist/components/Switch/switch.d.ts.map +1 -1
  216. package/dist/components/Switch/switch.js +3 -2
  217. package/dist/components/Switch/switch.js.map +1 -1
  218. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  219. package/dist/components/Tabs/tabs.js +15 -1
  220. package/dist/components/Tabs/tabs.js.map +1 -1
  221. package/dist/components/Textarea/textarea.d.ts +2 -2
  222. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  223. package/dist/components/Textarea/textarea.js +50 -42
  224. package/dist/components/Textarea/textarea.js.map +1 -1
  225. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  226. package/dist/components/TimePicker/time-columns.js +42 -38
  227. package/dist/components/TimePicker/time-columns.js.map +1 -1
  228. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  229. package/dist/components/TimePicker/time-picker.js +8 -6
  230. package/dist/components/TimePicker/time-picker.js.map +1 -1
  231. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  232. package/dist/components/Tooltip/tooltip.js +7 -5
  233. package/dist/components/Tooltip/tooltip.js.map +1 -1
  234. package/dist/components/TreeView/tree-view.d.ts +56 -1
  235. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  236. package/dist/components/TreeView/tree-view.js +211 -12
  237. package/dist/components/TreeView/tree-view.js.map +1 -1
  238. package/dist/index.d.ts +115 -58
  239. package/dist/index.d.ts.map +1 -1
  240. package/dist/index.js +95 -108
  241. package/dist/index.js.map +1 -1
  242. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  243. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  244. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  245. package/dist/tokens/categorical-color.js +15 -0
  246. package/dist/tokens/categorical-color.js.map +1 -1
  247. package/dist/tokens/motion/motion.d.ts +7 -6
  248. package/dist/tokens/motion/motion.d.ts.map +1 -1
  249. package/dist/tokens/motion/motion.js +6 -6
  250. package/dist/tokens/motion/motion.js.map +1 -1
  251. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  252. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  253. package/dist/tokens/motion/overlay-motion.js +9 -0
  254. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  255. package/dist/tokens/uiSize/icon-size.js +5 -0
  256. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  257. package/ds-canonical/fork/governance.lock +31 -19
  258. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  259. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  260. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  261. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +2 -1
  262. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  263. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  264. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  265. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  266. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +28 -0
  267. package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -0
  268. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  269. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  270. package/ds-canonical/fork/manifest.json +15 -0
  271. package/ds-canonical/fork/preamble.md +20 -18
  272. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
  273. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  274. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
  275. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  276. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  277. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  278. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  279. package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
  280. package/ds-canonical/hooks/README.md +1 -1
  281. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  282. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  283. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  284. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  285. package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
  286. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
  287. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  288. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  289. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  290. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  291. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  292. package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
  293. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  294. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  295. package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
  296. package/ds-canonical/hooks/check_story_determinism.sh +2 -0
  297. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  298. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  299. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  300. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  301. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  302. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  303. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  304. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  305. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  306. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  307. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  308. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  309. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  310. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
  311. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  312. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  313. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  314. package/ds-canonical/references/failure-class-registry.json +145 -0
  315. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  316. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  317. package/ds-canonical/references/scenario-definition.md +6 -9
  318. package/ds-canonical/references/ssot-consultation.md +2 -2
  319. package/ds-canonical/references/ssot-index.md +5 -4
  320. package/ds-canonical/references/story-baseline-registry.json +8 -2
  321. package/ds-canonical/references/structural-token-retention.md +6 -9
  322. package/ds-canonical/rules/meta-patterns.md +8 -8
  323. package/ds-canonical/rules/self-verify.md +4 -3
  324. package/ds-canonical/rules/story-rules.md +2 -2
  325. package/ds-canonical/rules/ui-development.md +2 -2
  326. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
  327. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  328. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  329. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  330. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  331. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  332. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  333. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
  334. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  335. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  336. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  337. package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
  338. package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
  339. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  340. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  341. package/ds-canonical/skills/governance-health/SKILL.md +1 -1
  342. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  343. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  344. package/ds-canonical/skills/new-component/SKILL.md +5 -5
  345. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  346. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  347. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  348. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  349. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  350. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  351. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  352. package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
  353. package/ds-story-manifest.json +29 -20
  354. package/llms-full.txt +22 -1
  355. package/llms.txt +5 -4
  356. package/package.json +7 -3
  357. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  358. package/src/components/Accordion/accordion.stories.tsx +16 -1
  359. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  360. package/src/components/Alert/alert.spec.md +8 -10
  361. package/src/components/Alert/alert.stories.tsx +28 -28
  362. package/src/components/Alert/alert.tsx +1 -1
  363. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  364. package/src/components/AppShell/app-shell.spec.md +4 -4
  365. package/src/components/AppShell/app-shell.tsx +28 -2
  366. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  367. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  368. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  369. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  370. package/src/components/Avatar/avatar.spec.md +2 -2
  371. package/src/components/Avatar/avatar.stories.tsx +8 -6
  372. package/src/components/Avatar/avatar.tsx +13 -5
  373. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  374. package/src/components/Badge/badge.spec.md +2 -0
  375. package/src/components/Badge/badge.stories.tsx +4 -2
  376. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  377. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  378. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  379. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  380. package/src/components/Button/button.principles.stories.tsx +1 -1
  381. package/src/components/Button/button.spec.md +2 -2
  382. package/src/components/Button/button.tsx +18 -3
  383. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  384. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  385. package/src/components/Calendar/calendar.spec.md +5 -4
  386. package/src/components/Calendar/calendar.stories.tsx +7 -4
  387. package/src/components/Calendar/calendar.tsx +26 -7
  388. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  389. package/src/components/Carousel/carousel.spec.md +2 -2
  390. package/src/components/Carousel/carousel.tsx +11 -3
  391. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  392. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  393. package/src/components/Chart/chart.stories.tsx +2 -8
  394. package/src/components/Chart/chart.tsx +3 -0
  395. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  396. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  397. package/src/components/Checkbox/checkbox.spec.md +13 -26
  398. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  399. package/src/components/Checkbox/checkbox.tsx +18 -13
  400. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  401. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  402. package/src/components/Chip/chip.spec.md +5 -4
  403. package/src/components/Chip/chip.tsx +5 -1
  404. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  405. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  406. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  407. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  408. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  409. package/src/components/Coachmark/coachmark.spec.md +5 -5
  410. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  411. package/src/components/Coachmark/coachmark.tsx +10 -3
  412. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  413. package/src/components/Combobox/combobox.tsx +53 -19
  414. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  415. package/src/components/Command/command.principles.stories.tsx +1 -1
  416. package/src/components/Command/command.stories.tsx +42 -10
  417. package/src/components/DataTable/cell-registry.tsx +86 -63
  418. package/src/components/DataTable/column-types.ts +10 -1
  419. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  420. package/src/components/DataTable/data-table-filter-group.tsx +231 -0
  421. package/src/components/DataTable/data-table-filter-panel.tsx +16 -430
  422. package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
  423. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  424. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  425. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  426. package/src/components/DataTable/data-table.spec.md +33 -13
  427. package/src/components/DataTable/data-table.stories.tsx +16 -17
  428. package/src/components/DataTable/data-table.tsx +107 -61
  429. package/src/components/DataTable/filter-operators.spec.md +3 -3
  430. package/src/components/DataTable/index.ts +3 -0
  431. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  432. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  433. package/src/components/DateGrid/date-grid.spec.md +1 -1
  434. package/src/components/DateGrid/date-grid.tsx +3 -1
  435. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  436. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  437. package/src/components/DatePicker/date-picker.spec.md +3 -3
  438. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  439. package/src/components/DatePicker/date-picker.tsx +99 -45
  440. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  441. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  442. package/src/components/DescriptionList/description-list.spec.md +3 -3
  443. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  444. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  445. package/src/components/Dialog/dialog.spec.md +9 -0
  446. package/src/components/Dialog/dialog.stories.tsx +66 -5
  447. package/src/components/Dialog/dialog.tsx +60 -25
  448. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  449. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  450. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  451. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  452. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  453. package/src/components/Empty/empty.spec.md +2 -2
  454. package/src/components/Field/field-context.ts +69 -5
  455. package/src/components/Field/field-controls.spec.md +62 -8
  456. package/src/components/Field/field-edit-keys.ts +66 -0
  457. package/src/components/Field/field-types.ts +58 -9
  458. package/src/components/Field/field-wrapper.tsx +50 -42
  459. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  460. package/src/components/Field/field.spec.md +1 -1
  461. package/src/components/Field/field.stories.tsx +1 -1
  462. package/src/components/Field/field.tsx +2 -1
  463. package/src/components/Field/form-validation.spec.md +3 -3
  464. package/src/components/Field/index.ts +1 -0
  465. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  466. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  467. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  468. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  469. package/src/components/FileItem/file-item.spec.md +5 -8
  470. package/src/components/FileItem/file-item.stories.tsx +36 -25
  471. package/src/components/FileItem/file-item.tsx +8 -6
  472. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  473. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  474. package/src/components/FileUpload/file-upload.spec.md +1 -1
  475. package/src/components/FileUpload/file-upload.tsx +1 -1
  476. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  477. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  478. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  479. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  480. package/src/components/FileViewer/file-viewer.tsx +12 -4
  481. package/src/components/FileViewer/image-renderer.tsx +35 -7
  482. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  483. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  484. package/src/components/HoverCard/hover-card.spec.md +5 -5
  485. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  486. package/src/components/HoverCard/hover-card.tsx +5 -3
  487. package/src/components/InlineEdit/index.ts +5 -0
  488. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  489. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  490. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  491. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  492. package/src/components/Input/input.principles.stories.tsx +2 -12
  493. package/src/components/Input/input.spec.md +13 -18
  494. package/src/components/Input/input.tsx +69 -22
  495. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  496. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  497. package/src/components/LinkInput/link-input.tsx +11 -10
  498. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  499. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  500. package/src/components/Menu/menu-item.spec.md +22 -15
  501. package/src/components/Menu/menu-item.stories.tsx +39 -11
  502. package/src/components/Menu/menu-item.tsx +38 -4
  503. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  504. package/src/components/Notice/notice.spec.md +16 -3
  505. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  506. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  507. package/src/components/NumberInput/number-input.spec.md +4 -4
  508. package/src/components/NumberInput/number-input.tsx +19 -12
  509. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  510. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  511. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  512. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  513. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  514. package/src/components/Pagination/pagination.spec.md +1 -1
  515. package/src/components/Pagination/pagination.stories.tsx +2 -6
  516. package/src/components/Pagination/pagination.tsx +1 -1
  517. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  518. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  519. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  520. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  521. package/src/components/PeoplePicker/person-display.tsx +32 -16
  522. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  523. package/src/components/Popover/popover.tsx +3 -1
  524. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  525. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  526. package/src/components/ProfileCard/profile-card.tsx +6 -6
  527. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  528. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  529. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  530. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  531. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  532. package/src/components/RadioGroup/radio-group.tsx +41 -15
  533. package/src/components/Rating/rating.spec.md +11 -3
  534. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  535. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  536. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  537. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  538. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  539. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  540. package/src/components/Select/select.spec.md +29 -17
  541. package/src/components/Select/select.stories.tsx +33 -0
  542. package/src/components/Select/select.tsx +190 -36
  543. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  544. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  545. package/src/components/SelectMenu/select-menu.tsx +16 -3
  546. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  547. package/src/components/SelectionControl/index.ts +1 -0
  548. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  549. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  550. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  551. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  552. package/src/components/Separator/separator.spec.md +2 -2
  553. package/src/components/Separator/separator.stories.tsx +6 -27
  554. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  555. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  556. package/src/components/Sheet/sheet.spec.md +2 -2
  557. package/src/components/Sheet/sheet.tsx +9 -5
  558. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  559. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  560. package/src/components/Sidebar/sidebar.spec.md +13 -15
  561. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  562. package/src/components/Sidebar/sidebar.tsx +37 -25
  563. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  564. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  565. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  566. package/src/components/Slider/slider.spec.md +5 -5
  567. package/src/components/Slider/slider.tsx +3 -1
  568. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  569. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  570. package/src/components/Steps/steps.spec.md +1 -1
  571. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  572. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  573. package/src/components/Switch/switch.spec.md +8 -8
  574. package/src/components/Switch/switch.stories.tsx +9 -24
  575. package/src/components/Switch/switch.tsx +17 -13
  576. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  577. package/src/components/Tabs/tabs.spec.md +1 -1
  578. package/src/components/Tabs/tabs.tsx +21 -1
  579. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  580. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  581. package/src/components/Textarea/textarea.spec.md +4 -4
  582. package/src/components/Textarea/textarea.tsx +72 -46
  583. package/src/components/TimePicker/time-columns.tsx +6 -2
  584. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  585. package/src/components/TimePicker/time-picker.spec.md +3 -3
  586. package/src/components/TimePicker/time-picker.tsx +16 -10
  587. package/src/components/Toast/toast.stories.tsx +7 -4
  588. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  589. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  590. package/src/components/Tooltip/tooltip.spec.md +1 -1
  591. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  592. package/src/components/Tooltip/tooltip.tsx +8 -6
  593. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  594. package/src/components/TreeView/tree-view.spec.md +42 -11
  595. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  596. package/src/components/TreeView/tree-view.tsx +322 -17
  597. package/src/index.ts +588 -60
  598. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  599. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  600. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  601. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  602. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  603. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  604. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  605. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  606. package/src/styles/tokens.css +3 -0
  607. package/src/tokens/README.md +1 -1
  608. package/src/tokens/color/color.spec.md +4 -4
  609. package/src/tokens/color/color.stories.tsx +3 -3
  610. package/src/tokens/density/density.stories.tsx +16 -3
  611. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  612. package/src/tokens/motion/motion.css +33 -21
  613. package/src/tokens/motion/motion.spec.md +32 -15
  614. package/src/tokens/motion/motion.stories.tsx +58 -5
  615. package/src/tokens/motion/motion.ts +7 -6
  616. package/src/tokens/motion/overlay-motion.ts +26 -0
  617. package/src/tokens/orphan-tokens.spec.md +4 -4
  618. package/src/tokens/token-system.spec.md +1 -0
  619. package/src/tokens/uiSize/uiSize.css +1 -1
  620. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  621. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  622. package/src/tokens/utility-registry.json +160 -23
@@ -0,0 +1,237 @@
1
+ // @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved(2026-07-14 自 data-table-filter-panel.tsx 拆檔搬移,原檔級 escape 隨段落帶入)。
2
+ // @internal — DS-internal 單元(FilterValuePicker value-picker switcher,只被
3
+ // data-table-filter-group.tsx FilterRow 消費);不隨 index.ts re-export 進 npm public surface。
4
+ // ────────────────────────────── 消費的 SSOT ──────────────────────────────
5
+ // - Field controls(Family 4,統一 size="sm"):Input / NumberInput / Select / Combobox /
6
+ // DatePicker + DatePickerRange(showTime)/ PeoplePicker — 按 ValueShape dispatch
7
+ // (ValueShape ↔ picker 對照 canonical:./data-table.spec.md「三、Operator × ValueShape SSOT」)
8
+ // - className 直接 forward 給 inner Field control(不另開 wrapper div)—
9
+ // field-control-group.spec.md「forward className」canonical(2026-05-04 #2 fix)
10
+ // - Operator / ValueShape SSOT:./filter-operators.ts(DATE_RELATIVE_OPTIONS / DATE_RELATIVE_GROUPS)
11
+ // - Person pool:PeoplePicker PersonValue(對齊 cell-registry meta.people SSOT)
12
+ // 設計規則:./filter-operators.spec.md「ValueShape canonical」+ ./data-table.spec.md「進階篩選」段
13
+
14
+ import { Select, type SelectOption } from '@/design-system/components/Select/select'
15
+ import { Combobox } from '@/design-system/components/Combobox/combobox'
16
+ import { Input } from '@/design-system/components/Input/input'
17
+ import { NumberInput } from '@/design-system/components/NumberInput/number-input'
18
+ import { DatePicker, DatePickerRange } from '@/design-system/components/DatePicker/date-picker'
19
+ import { PeoplePicker } from '@/design-system/components/PeoplePicker/people-picker'
20
+ import type { PersonValue } from '@/design-system/components/PeoplePicker/person-display'
21
+ import {
22
+ DATE_RELATIVE_OPTIONS,
23
+ DATE_RELATIVE_GROUPS,
24
+ type ValueShape,
25
+ } from './filter-operators'
26
+
27
+ // ── FilterValuePicker(value-picker switcher per ValueShape)────────────────
28
+ //
29
+ // 2026-05-03 M21 retract:本 helper 原獨立檔 filter-value-picker.tsx(187 行 / 1 consumer),
30
+ // claim「未來 inline filter UI 共用」= premature abstraction → inline 回 panel。
31
+ // 2026-07-14 拆檔 refactor:panel 822 行過 800 hard cap(file-size escalation)→ 重新抽出為
32
+ // @internal 私有模組(非 public API 抽象,與 M21 不衝突;consumer 仍只見 DataTableFilterPanel)。
33
+
34
+ export interface FilterValuePickerColInfo {
35
+ id: string
36
+ label: string
37
+ options?: Array<{ value: string; label: string }>
38
+ /** Person pool — person/multiPerson filter picker 用(2026-05-07 升級,SSOT 對齊 cell-registry) */
39
+ people?: Array<{ name: string; avatarUrl?: string; description?: string }>
40
+ }
41
+
42
+ export interface FilterValuePickerProps {
43
+ shape: ValueShape | null
44
+ value: unknown
45
+ onChange: (v: unknown) => void
46
+ colInfo?: FilterValuePickerColInfo
47
+ disabled?: boolean
48
+ /** 用 column.label 組「{label} 篩選值」(panel 每 row 不顯式 label,a11y 必填) */
49
+ ariaLabel?: string
50
+ /** Forward 給內部 Field control 的 className(2026-05-04 #2 fix)
51
+ * 避免外層包 wrapper div 破壞 FieldControlGroup CSS variants(rounded radii / margin overlap) */
52
+ className?: string
53
+ }
54
+
55
+ export function FilterValuePicker({
56
+ shape,
57
+ value,
58
+ onChange,
59
+ colInfo,
60
+ disabled,
61
+ ariaLabel,
62
+ className,
63
+ }: FilterValuePickerProps) {
64
+ if (!shape || disabled) {
65
+ return <Input size="sm" value="" onChange={() => {}} placeholder="輸入值…" disabled aria-label={ariaLabel} className={className} />
66
+ }
67
+
68
+ switch (shape) {
69
+ case 'none':
70
+ return null
71
+
72
+ case 'text':
73
+ return (
74
+ <Input
75
+ size="sm"
76
+ value={String(value ?? '')}
77
+ onChange={(e) => onChange(e.target.value)}
78
+ placeholder="輸入值…"
79
+ aria-label={ariaLabel}
80
+ className={className}
81
+ />
82
+ )
83
+
84
+ case 'number':
85
+ return (
86
+ <NumberInput
87
+ size="sm"
88
+ value={typeof value === 'number' ? value : null}
89
+ onChange={(v) => onChange(v ?? '')}
90
+ placeholder="輸入數字…"
91
+ aria-label={ariaLabel}
92
+ className={className}
93
+ />
94
+ )
95
+
96
+ case 'date_single':
97
+ return (
98
+ <DatePicker
99
+ size="sm"
100
+ value={typeof value === 'string' ? value : null}
101
+ onChange={(v) => onChange(v ?? '')}
102
+ aria-label={ariaLabel}
103
+ className={className}
104
+ />
105
+ )
106
+
107
+ case 'date_range':
108
+ return (
109
+ <DatePickerRange
110
+ size="sm"
111
+ value={Array.isArray(value) && value.length === 2
112
+ ? (value as [string | null, string | null])
113
+ : null}
114
+ onChange={(v) => onChange(v)}
115
+ aria-label={ariaLabel}
116
+ className={className}
117
+ />
118
+ )
119
+
120
+ case 'date_relative': {
121
+ // 群組分類:Past / Current / Future(對齊 Linear / Notion idiom),走 Select.groups → SelectMenu
122
+ const opts: SelectOption[] = DATE_RELATIVE_OPTIONS.map((o) => ({
123
+ value: o.value,
124
+ label: o.label,
125
+ group: o.group,
126
+ }))
127
+ return (
128
+ <Select
129
+ size="sm"
130
+ options={opts}
131
+ groups={DATE_RELATIVE_GROUPS as unknown as Array<{ key: string; label: string }>}
132
+ value={String(value ?? '')}
133
+ onChange={(v) => onChange(v)}
134
+ placeholder="選擇相對日期"
135
+ aria-label={ariaLabel}
136
+ className={className}
137
+ />
138
+ )
139
+ }
140
+
141
+ case 'select_single': {
142
+ const opts: SelectOption[] = (colInfo?.options ?? []).map((o) => ({
143
+ value: o.value,
144
+ label: o.label,
145
+ }))
146
+ return (
147
+ <Select
148
+ size="sm"
149
+ options={opts}
150
+ value={String(value ?? '')}
151
+ onChange={(v) => onChange(v)}
152
+ placeholder="選擇值"
153
+ aria-label={ariaLabel}
154
+ className={className}
155
+ />
156
+ )
157
+ }
158
+
159
+ case 'select_multi': {
160
+ const opts = (colInfo?.options ?? []).map((o) => ({
161
+ value: o.value,
162
+ label: o.label,
163
+ }))
164
+ const arr = Array.isArray(value) ? (value as string[]) : []
165
+ return (
166
+ <Combobox
167
+ size="sm"
168
+ options={opts}
169
+ value={arr}
170
+ onChange={(v) => onChange(v)}
171
+ placeholder="選擇值…"
172
+ aria-label={ariaLabel}
173
+ className={className}
174
+ />
175
+ )
176
+ }
177
+
178
+ case 'datetime_single':
179
+ return (
180
+ <DatePicker
181
+ size="sm"
182
+ showTime
183
+ value={typeof value === 'string' ? value : null}
184
+ onChange={(v) => onChange(v ?? '')}
185
+ aria-label={ariaLabel}
186
+ className={className}
187
+ />
188
+ )
189
+
190
+ case 'datetime_range':
191
+ return (
192
+ <DatePickerRange
193
+ size="sm"
194
+ showTime
195
+ value={Array.isArray(value) && value.length === 2
196
+ ? (value as [string | null, string | null])
197
+ : null}
198
+ onChange={(v) => onChange(v)}
199
+ aria-label={ariaLabel}
200
+ className={className}
201
+ />
202
+ )
203
+
204
+ // person_single / person_multi — 走 PeoplePicker(2026-05-07 升級,對齊 cell-registry SSOT)。
205
+ // colInfo.people 來自 column meta.people。Filter value:
206
+ // - person_single:存 PersonValue | null(picker emit array,我們取 [0])
207
+ // - person_multi:存 PersonValue[]
208
+ case 'person_single': {
209
+ const v = value as PersonValue | null | undefined
210
+ return (
211
+ <PeoplePicker
212
+ size="sm"
213
+ value={v ?? null}
214
+ people={colInfo?.people ?? []}
215
+ onChange={(next) => onChange(next[0] ?? null)}
216
+ aria-label={ariaLabel}
217
+ className={className}
218
+ />
219
+ )
220
+ }
221
+ case 'person_multi': {
222
+ const v = Array.isArray(value) ? (value as PersonValue[]) : []
223
+ return (
224
+ <PeoplePicker
225
+ size="sm"
226
+ value={v}
227
+ people={colInfo?.people ?? []}
228
+ onChange={(next) => onChange(next)}
229
+ aria-label={ariaLabel}
230
+ className={className}
231
+ />
232
+ )
233
+ }
234
+ default:
235
+ return null
236
+ }
237
+ }
@@ -1,3 +1,4 @@
1
+ // @internal — DS-internal 單元(viewport 覆蓋 paint layer,只被 data-table.tsx 內部消費);不隨 index.ts re-export 進 npm public surface。
1
2
  /**
2
3
  * DataTableInteractionLayer — Slice D Step 1A scaffold(per `.claude/planning/datatable-spreadsheet-rfc.md`)
3
4
  *
@@ -30,15 +31,16 @@ interface CellRect {
30
31
  interface DataTableInteractionLayerProps {
31
32
  /** Flag default false:不破現有 outline。enable 後 hover/editor 走 overlay。 */
32
33
  enabled: boolean
33
- /** Container ref;layer absolute position container origin */
34
+ /** Container ref;geometry source(getCellRect 由此 query cell DOM)。layer root 本身是
35
+ * position:fixed inset:0 viewport-anchor(見 render),非 container-origin absolute */
34
36
  containerRef: React.RefObject<HTMLDivElement | null>
35
37
  /** Per Contract 15:`cellClickEntersEdit` predicate;hover overlay 顯示與否 */
36
38
  cellClickEntersEdit?: (cellId: CellId) => boolean
37
39
  /**
38
- * Slice D Step 3 scaffold(2026-05-10):active editor cell id。null = 無 active editor。
39
- * 當前只 render rect placeholder layer(z-index 3,higher than hover ring z-index 1)。
40
- * Future:ActiveEditorHost portal active edit Field per Contract 8 「two paint owners」。
41
- * Wire-up codex Q-7 string-first canary(text cell first,picker types 漸進)。
40
+ * Active editor cell id。null = 無 active editor。
41
+ * 已接線(Slice D Step 5 完成,2026-07-14 docblock 對齊):activeEditorEnabled +
42
+ * activeEditorCellId + activeEditorRender ActiveEditorHost(z 3)portal render
43
+ * edit Field(per Contract 8「two paint owners」)。
42
44
  */
43
45
  activeEditorCellId?: CellId | null
44
46
  /**
@@ -55,12 +57,6 @@ interface DataTableInteractionLayerProps {
55
57
  * Layer renders solid border SelectionRect(per user「不要 dash 直接實的就好」)。
56
58
  */
57
59
  selectedCellId?: CellId | null
58
- /**
59
- * Slice D Step 4 range support(per user「應該支援 range」+ codex Q2.1 Airtable/AG Grid
60
- * cite):range cell IDs from anchor↔focus rectangle。Layer renders bg-fill RangeRect
61
- * (z 1,bg `--primary-subtle`)+ selection border on focus cell。
62
- */
63
- rangeCellIds?: CellId[]
64
60
  /**
65
61
  * Slice D Step 5(D.3 portal Field,2026-05-10 user 拍板「在乎完美乾淨」+ codex Q6.1
66
62
  * 撤回 defer):active editor render callback。當 activeEditorEnabled + activeEditorCellId
@@ -222,10 +218,11 @@ function useHoveredCell(
222
218
  }
223
219
 
224
220
  /**
225
- * Singleton interaction layer。
221
+ * Singleton interaction layer(全 sub-layer 已接線;2026-07-14 docblock 對齊實作)
226
222
  *
227
- * Slice D Step 1A:HoverCellRect only。
228
- * Slice D Step 2/3/4:SelectionRect / ActiveEditorHost / RangeRect 漸進加入。
223
+ * 現況:HoverCellRect(z 1)+ SelectionRing(z 2)+ ActiveEditorHost(z 3,portal edit Field);
224
+ * range 視覺走 cell 自身 CSS `[data-range-cell]`(RangeRect / rangeCellIds prop 已 retire)。
225
+ * layer root = position:fixed inset:0 viewport-anchor,pointerEvents:none(僅 ActiveEditorHost 開 auto)。
229
226
  */
230
227
  export function DataTableInteractionLayer({
231
228
  enabled,
@@ -235,8 +232,6 @@ export function DataTableInteractionLayer({
235
232
  activeEditorEnabled = false,
236
233
  activeEditorRender,
237
234
  selectedCellId = null,
238
- // rangeCellIds retired 2026-05-10(outer ring 已 retire,range visual 靠 cell-bg `[data-range-cell]`)
239
- rangeCellIds: _rangeCellIds,
240
235
  }: DataTableInteractionLayerProps) {
241
236
  const hoveredCellId = useHoveredCell(containerRef, enabled)
242
237
  // 2026-05-10 RWD/scroll sync(per user mandate「所有 overlay 在各種 RWD 和捲動時都處在正確位置」):
@@ -264,7 +259,7 @@ export function DataTableInteractionLayer({
264
259
  ? getCellRect(containerRef.current, activeEditorCellId)
265
260
  : null
266
261
 
267
- // Slice D Step 4(spreadsheet semantics):SelectionRect + RangeRect with viewport clip
262
+ // Slice D Step 4(spreadsheet semantics):SelectionRing with viewport clip(RangeRect retire — range 視覺走 CSS [data-range-cell])
268
263
  const selectedGeo = enabled && selectedCellId != null
269
264
  ? getCellGeometry(containerRef.current, selectedCellId)
270
265
  : null
@@ -341,9 +336,10 @@ function toRelRect(cellRect: CellRect, clipRect: CellRect): CellRect {
341
336
 
342
337
  // ── Private primitives(per codex unified-ring-overlay-2026-05-10 Final A')──────
343
338
  //
344
- // 三個 private primitive 各自 own 一個 paint concern:
339
+ // 三個 private primitive 各自 own 一個 paint concern(2026-07-14 對齊實作:CellRangeFill
340
+ // 不存在 — range bg 走 cell 自身 CSS `[data-range-cell]`,非 layer 元件):
345
341
  // 1. CellRingOverlay — outline ring(hover / selected / future focus / error)
346
- // 2. CellRangeFill bg fill(range cells in spreadsheet mode)
342
+ // 2. ClipMask panel viewport 裁切 wrapper(Issue 6 partial-visibility)
347
343
  // 3. ActiveEditorHost — opaque host(portal Field edit)
348
344
  //
349
345
  // SSOT pattern(共 3 primitives):rect float pass-through + boxSizing:border-box +
@@ -1,7 +1,8 @@
1
1
  // @anatomy-rationale:
2
2
  // SizeMatrix represented as RowHeightMatrix per row-density semantics —
3
- // DataTable 的 size 不是字級放大而是 row-height tier(compact / cozy /
4
- // comfortable),語意對應「掃描 vs 閱讀」資料密度而非元件大小。命名沿用
3
+ // DataTable 的 size 主軸是 row-height tier(compact / cozy /
4
+ // comfortable),語意對應「掃描 vs 閱讀」資料密度;lg 同時連動字級放大
5
+ // (sm/md → text-body / lg → text-body-lg,對齊 Field,SSOT fieldDisplayTextClass)。命名沿用
5
6
  // Linear / Notion / Airtable 業界共識(row density,非 component size)。
6
7
  // StateBehavior covered by ColorMatrix「Row 狀態色彩」段(default / hover /
7
8
  // selected / disabled)+ Features「排序」段。Row 互動是 row-level
@@ -131,7 +132,7 @@ export const Inspector: Story = {
131
132
  bordered: { control: 'boolean', description: '外框(嵌入已帶框容器時可設 false 避免雙重邊框)' },
132
133
  pinnedLeft: { control: 'boolean', description: 'Pin 產品名稱欄到左側,橫向捲動時保持可見' },
133
134
  pinnedRight: { control: 'boolean', description: 'Pin 上架日期欄到右側' },
134
- inlineEdit: { control: 'boolean', description: 'inline edit 視覺:cell 間加垂直分隔線(dtCellGrid)。Select chevron column meta.editable 控制(showDisplayEndIcon),非本 prop' },
135
+ inlineEdit: { control: 'boolean', description: 'inline edit 視覺:cell 間加垂直分隔線(dtCellGrid)。display 態零恆顯 chevron(2026-07-08 A 案,editable affordance = hover outline);edit 態才有控件 chrome' },
135
136
  height: {
136
137
  control: 'select',
137
138
  options: ['auto', '300px'],
@@ -171,8 +172,9 @@ export const ColumnTypes: Story = {
171
172
  const columns = [
172
173
  col.accessor('name', { header: 'text', meta: { type: 'string', width: 200 } }),
173
174
  col.accessor('price', { header: 'currency', meta: { type: 'currency', prefix: '$', width: 120 } }),
174
- col.accessor('stock', { header: 'select(Tag)', meta: { type: 'select', options: STATUS_OPTIONS, width: 140 } }),
175
- col.accessor('available', { header: 'boolean(✓/—)', meta: { type: 'boolean', width: 100 } }),
175
+ // display:'tag' opt-in 讓 demo 與 headerselect(Tag)」名實相符(SelectCell 預設 plain 純文字)
176
+ col.accessor('stock', { header: 'select(Tag)', meta: { type: 'select', options: STATUS_OPTIONS, width: 140, display: 'tag' } }),
177
+ col.accessor('available', { header: 'boolean(勾選框)', meta: { type: 'boolean', width: 100 } }),
176
178
  col.accessor('launchDate', { header: 'date', meta: { type: 'date', width: 140 } }),
177
179
  ]
178
180
 
@@ -194,7 +196,7 @@ export const ColumnTypes: Story = {
194
196
  <tr><Td mono>number</Td><Td mono>{`<NumberInput mode="display">`}</Td><Td>right</Td><Td>數量、年齡</Td></tr>
195
197
  <tr><Td mono>currency</Td><Td mono>{`<NumberInput mode="display">`}(+ prefix)</Td><Td>right</Td><Td>金額、價格</Td></tr>
196
198
  <tr><Td mono>date</Td><Td mono>{`<DatePicker mode="display">`}</Td><Td>left</Td><Td>日期、時間戳</Td></tr>
197
- <tr><Td mono>boolean</Td><Td mono>{`<Checkbox mode="display">`}( / )</Td><Td>left</Td><Td>啟用 / 可見</Td></tr>
199
+ <tr><Td mono>boolean</Td><Td mono>{`<Checkbox mode="display">`}( / 叉 icon)</Td><Td>left</Td><Td>啟用 / 可見</Td></tr>
198
200
  <tr><Td mono>select</Td><Td mono>{`<Select mode="display">`}</Td><Td>left</Td><Td>狀態、類別</Td></tr>
199
201
  <tr><Td mono>multiSelect</Td><Td mono>{`<Combobox mode="display">`}</Td><Td>left</Td><Td>多選 tags</Td></tr>
200
202
  <tr><Td mono>person</Td><Td mono>PersonDisplay / MultiPersonDisplay</Td><Td>left</Td><Td>指派者、reviewer</Td></tr>
@@ -202,7 +204,7 @@ export const ColumnTypes: Story = {
202
204
  </tbody>
203
205
  </table>
204
206
  </div>
205
- <p className="text-footnote text-fg-muted mt-3">擴充新 type:在 `column-types.ts` 註冊 `renderDisplay` + `align`,自動跟所有 DataTable 整合</p>
207
+ <p className="text-footnote text-fg-muted mt-3">擴充新 type:在 `cell-registry.tsx` 的 `cellRegistry` map 註冊對應 Cell component(display/edit 渲染 SSOT);`column-types.ts` 只設 `align` / default metadata。兩處對齊後自動跟所有 DataTable 整合</p>
206
208
  </div>
207
209
  </div>
208
210
  )
@@ -260,8 +262,8 @@ export const AlignmentRule: Story = {
260
262
  return (
261
263
  <div className="flex flex-col gap-8">
262
264
  <div>
263
- <H3>Column type 決定對齊(column-types.ts 定義,不讓 consumer 手動設)</H3>
264
- <Desc>數字靠右方便縱向比較位數(Excel / 會計軟體 / 財務系統共識);文字靠左方便閱讀;boolean 靠左跟其他文字欄一致,維持掃視時的左緣節奏。Consumer 不需要設 `align`,column type 就決定了。</Desc>
265
+ <H3>Column type 提供對齊預設(column-types.ts 定義),consumer 可用 meta.align 覆寫</H3>
266
+ <Desc>數字靠右方便縱向比較位數(Excel / 會計軟體 / 財務系統共識);文字靠左方便閱讀;boolean 靠左跟其他文字欄一致,維持掃視時的左緣節奏。Consumer 通常不需要設 `align`——column type 已給預設;需要時仍可用 `meta.align` 在 column 層級覆寫。</Desc>
265
267
  <DataTable columns={columns} data={SAMPLE_DATA} height="auto" />
266
268
  </div>
267
269
 
@@ -273,7 +275,7 @@ export const AlignmentRule: Story = {
273
275
  <tbody>
274
276
  <tr><Td>text / select / person / date / link</Td><Td mono>left</Td><Td>閱讀從左到右</Td></tr>
275
277
  <tr><Td>number / currency</Td><Td mono>right</Td><Td>縱向比較位數(小數點縱向對齊)</Td></tr>
276
- <tr><Td>boolean( / )</Td><Td mono>left</Td><Td>跟其他文字欄一致靠左,維持掃視時的左緣節奏</Td></tr>
278
+ <tr><Td>boolean( / 叉 icon)</Td><Td mono>left</Td><Td>跟其他文字欄一致靠左,維持掃視時的左緣節奏</Td></tr>
277
279
  <tr><Td>actions(在 cell 內的按鈕)</Td><Td mono>right</Td><Td>動線尾端,不干擾資料掃視</Td></tr>
278
280
  </tbody>
279
281
  </table>
@@ -437,10 +439,10 @@ export const ColorMatrix: Story = {
437
439
  </thead>
438
440
  <tbody>
439
441
  <tr><Td mono>text / date / number / currency</Td><Td><TokenCell token="--foreground" /></Td></tr>
440
- <tr><Td mono>select(Tag)</Td><Td>Tag 的 variant 色(green / yellow / red / blue…)</Td></tr>
442
+ <tr><Td mono>select</Td><Td>預設 plain 純文字 foreground;`meta.display='tag'` opt-in 才走 Tag 的 variant 色(green / yellow / red / blue…)</Td></tr>
441
443
  <tr><Td mono>person</Td><Td>Avatar + foreground 文字</Td></tr>
442
444
  <tr><Td mono>link</Td><Td><TokenCell token="--primary" /></Td></tr>
443
- <tr><Td mono>boolean</Td><Td><TokenCell token="--fg-secondary" display=" / 均用 fg-secondary" /></Td></tr>
445
+ <tr><Td mono>boolean</Td><Td>naked Checkbox(true = <TokenCell token="--primary" display="primary 底白勾" /> / false = 空框 <TokenCell token="--border" />),非 X / Check icon</Td></tr>
444
446
  </tbody>
445
447
  </table>
446
448
  </div>
@@ -513,7 +515,7 @@ export const Accessibility = {
513
515
  render: () => (
514
516
  <div className="max-w-3xl text-body text-fg-secondary">
515
517
  <h3 className="text-h5 text-foreground mb-2">無障礙設計</h3>
516
- <p className="whitespace-pre-line">{"DataTable 用一般 div 搭配表格語意標記,而非原生 table 元素——因為虛擬捲動需要絕對定位每一列,而 table 的佈局模型做不到。輔助技術(螢幕報讀器)會把它當成表格朗讀。\n\n 表格語意 :最外層標記為表格、每一列標記為列、每一格標記為儲存格,表頭那一格標記為欄位標題。\n\n 排序 :可排序的表頭會標示目前的排序方向(升冪 / 降冪 / 未排序),報讀器讀得出來。\n\n 選取 :每一列的勾選框都有說明文字(由使用方傳入,沒傳就用「選取此列」),全選框的說明文字是「全選可見列」。\n\n 鍵盤 :一般表格模式下,用 Tab 進入表格後可操作排序與勾選;方向鍵在儲存格之間移動是試算表模式(spreadsheetMode)才開啟的功能,不是預設。列上的更多操作都收進右側的「更多」選單,確保不用滑鼠也能用。\n\n 焦點 :鍵盤聚焦時顯示清楚的外框,與整個設計系統的聚焦樣式一致。\n\n 驗證 :Storybook 無障礙檢查面板應該沒有嚴重問題;全程鍵盤可操作,不必用到滑鼠;文字對比度達到無障礙標準。"}</p>
518
+ <p className="whitespace-pre-line">{"DataTable 用一般 div 搭配表格語意標記,而非原生 table 元素——因為虛擬捲動需要絕對定位每一列,而 table 的佈局模型做不到。輔助技術(螢幕報讀器)會把它當成表格朗讀。\n\n 表格語意 :最外層標記為表格、每一列標記為列、每一格標記為儲存格,表頭那一格標記為欄位標題。\n\n 排序 :可排序的表頭會標示目前的排序方向(升冪 / 降冪 / 未排序),報讀器讀得出來。\n\n 選取 :每一列的勾選框都有說明文字(由使用方傳入,沒傳就用「選取此列」),全選框的說明文字是「全選可見列」。\n\n 鍵盤 :一般表格模式下,用 Tab 進入表格後可操作排序與勾選;方向鍵在儲存格之間移動是試算表模式(spreadsheetMode)才開啟的功能,不是預設。列上的更多操作(`rowActions` 為使用方提供的 callback,DataTable 不代管收納)建議在 3 個以上時由使用方自行收進右側的「更多」選單,以確保不用滑鼠也能操作全部動作。\n\n 焦點 :一般元件(排序鈕 / 勾選框)鍵盤聚焦時顯示清楚外框,與設計系統聚焦樣式一致;啟用選取 / 試算表模式時,表格本身可被 Tab 聚焦,焦點以「選取儲存格」的方框呈現(表格外層刻意不另畫外框),初次 Tab 尚未選取儲存格時焦點落在表格容器。\n\n 驗證 :Storybook 無障礙檢查面板應該沒有嚴重問題;全程鍵盤可操作,不必用到滑鼠;文字對比度達到無障礙標準。"}</p>
517
519
  </div>
518
520
  ),
519
521
  }
@@ -93,10 +93,10 @@ export const UsageGuidance: Story = {
93
93
  </Rule>
94
94
 
95
95
  <Rule
96
- title="❌ 不用 DataTable 表達階層結構(部門 / 資料夾)"
97
- note="DataTable 是平面 row。階層結構(可展開收合)改用 TreeView。Notion 的資料庫可以 expand row,但階層樹用 TreeView"
96
+ title="❌ 不用 DataTable 表達深層階層結構(部門 / 資料夾 tree)"
97
+ note="DataTable 支援淺層 nested-rows(展開子列,如任務 / 子任務);但深層多階縮排 + 大量節點的 folder / dept tree 語意仍屬 TreeView。Notion 的資料庫可以 expand row,但側欄階層樹用 TreeView"
98
98
  >
99
- <Label warn>階層結構用 TreeView,支援無限深度展開 / 收合</Label>
99
+ <Label warn>深層階層樹用 TreeView(無限深度展開 / 收合);淺層子列 DataTable 可用</Label>
100
100
  </Rule>
101
101
 
102
102
  <Rule
@@ -107,10 +107,10 @@ export const UsageGuidance: Story = {
107
107
  </Rule>
108
108
 
109
109
  <Rule
110
- title="❌ 不用 DataTable 做試算表(公式、跨 cell 選取)"
111
- note="DataTable 是資料展示,不支援 Excel 功能。需要試算表能力 → AG Grid Enterprise / Handsontable。Airtable 確實像表,但 DataTable 不是設計來做這個"
110
+ title="❌ 不用 DataTable 做公式 / cell-level 計算"
111
+ note="DataTable spreadsheetMode 支援跨 cell 選取 / Shift 矩形範圍 / 方向鍵導覽 / cell 編輯;但公式與 cell-level 計算超出範圍 → AG Grid Enterprise / Handsontable。Airtable 確實像表,但 DataTable 不是設計來做這個"
112
112
  >
113
- <Label warn>試算表功能用專門 library,不往 DataTable 塞</Label>
113
+ <Label warn>公式 / 計算用專門 library,不往 DataTable 塞;跨 cell 選取 / 編輯用 spreadsheetMode</Label>
114
114
  </Rule>
115
115
  </div>
116
116
  </div>
@@ -140,14 +140,14 @@ export const ColumnTypeRule: Story = {
140
140
 
141
141
  <Rule
142
142
  title="❌ 手寫 cell render 自訂格式化"
143
- note="每 column 自己寫 `cell: (info) => ...` 會繞過 `mode='display'` 系統——**格式化邏輯會漂移**。一個 table 的 price 顯示「$2,490」,另一個 table 的 price 顯示「2490」,一個 boolean 顯示「✓」,另一個 boolean 顯示「是」——整個系統 format 失去一致性"
143
+ note="每 column 自己寫 `cell: (info) => ...` 會繞過 `mode='display'` 系統——**格式化邏輯會漂移**。一個 table 的 price 顯示「$2,490」,另一個 table 的 price 顯示「2490」,一個 boolean 顯示勾 icon,另一個 boolean 顯示「是」——整個系統 format 失去一致性"
144
144
  >
145
145
  <Label warn>除非真的需要 `mode='display'` 無法提供的客製視覺,否則一律走 meta.type 系統。客製化時完全跳過 type 讓 display 渲染不要干預</Label>
146
146
  </Rule>
147
147
 
148
148
  <Rule
149
- title="擴充新 type:到 column-types.ts 註冊"
150
- note="新增資料類型(如 `percentage`、`relative-time`)在 `column-types.ts` 註冊 renderDisplay + align,自動跟所有 DataTable 整合。不在單一 table 硬寫"
149
+ title="擴充新 type:到 cell-registry.tsx 註冊"
150
+ note="新增資料類型(如 `percentage`、`relative-time`)在 `cell-registry.tsx` 的 `cellRegistry` map 註冊對應 Cell component(display/edit 渲染 SSOT);`column-types.ts` 只設 align / default metadata。兩處對齊後自動跟所有 DataTable 整合,不在單一 table 硬寫"
151
151
  >
152
152
  <Label>讓 column type 系統成為 single source of truth,所有 table 受惠同一次更新</Label>
153
153
  </Rule>
@@ -44,10 +44,10 @@ DataTable 是基於 TanStack Table 的資料表格元件,提供排序、篩選
44
44
  | 場景 | 改用 | 原因 |
45
45
  |------|------|------|
46
46
  | 唯讀的 key-value 展示(profile 屬性列表)| `DescriptionList` | DataTable 是多 row 集合,DescriptionList 是單一實體的屬性 |
47
- | 階層結構(部門 / 資料夾 tree)| `TreeView` | DataTable 是平面 row,不支援階層展開收合 |
47
+ | 深層階層結構(部門 / 資料夾 tree)| `TreeView` | DataTable 支援淺層 nested-rows(L4 展開子列),但深層多階縮排 + 大量節點的 folder/dept tree 語意仍屬 TreeView |
48
48
  | 卡片式瀏覽(圖文並列)| 自訂 grid / list | Table 是密集 row,不適合大圖 |
49
49
  | 只有 2-3 筆且不需互動 | 直接 `<dl>` 或自訂 layout | DataTable 的 overhead 對小資料集過度工程 |
50
- | 試算表(公式 / cell 選取)| 超出範圍,用專門試算表 library | DataTable 不做 cell-level 計算 |
50
+ | 試算表(公式 / cell-level 計算)| 超出範圍,用專門試算表 library | DataTable `spreadsheetMode` 支援跨 cell 選取 / Shift 矩形範圍 / 方向鍵導覽 / cell 編輯,但不做公式或 cell-level 計算 |
51
51
  | 需要複雜群組 header + 合併 cell | 自訂或 TanStack 原始 API | DataTable 對 header group 的抽象層有限 |
52
52
 
53
53
  ---
@@ -139,7 +139,7 @@ Table 層級的模式切換,不是 column 層級。跟 AG Grid / Airtable 的
139
139
 
140
140
  ### 七、Column Type
141
141
 
142
- **Column type 是資料行為的預設合約。** 指定 type 自動獲得對齊 / 渲染 / 排序 / 篩選行為,可在 column 層級覆寫。Header 對齊永遠跟該欄 body cell 一致。
142
+ **Column type 是資料行為的預設合約。** 指定 type 自動獲得對齊 / 渲染 / 排序 / 篩選行為,可在 column 層級覆寫。Header 對齊永遠跟該欄 body cell 一致。select/multiSelect 的 `meta.options` 消費 Select 的完整 `SelectOption` schema(M30 wrapper-extends-primitive;含 icon / iconClassName / description),`meta.selectedItemRenderer` 轉發 Select 同名 API 供 status 類彩色 cell(2026-07-08 補——原 `{value,label}` 窄型別 = 假 SSOT,WM 被迫手刻 bare trigger 實證)。
143
143
 
144
144
  ### 八、Row 狀態
145
145
 
@@ -154,7 +154,7 @@ Table 層級的模式切換,不是 column 層級。跟 AG Grid / Airtable 的
154
154
 
155
155
  **世界級對照**:Material DataGrid `GridActionsCellItem`(IconButton small)/ Polaris IndexTable hover 20-24px / Atlassian Dynamic Table small iconOnly / Apple HIG Finder list row ≤24px — 全派固定不放大。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
156
156
 
157
- **收納邏輯**:1-2 個 → icon buttons 並排(全 size="xs");3+ → 前 1-2 個 inline + MoreVertical dropdown(全 size="xs";dropdown 包含所有操作,確保鍵盤可存取全部)。**Header/body 寬度同步**:header 渲染 invisible buttons 佔位(同 size="xs"),確保 header 和 body 的 right region 同寬。
157
+ **收納邏輯(consumer 自建)**:`rowActions` 是 raw callback `(row)=>ReactNode`,DataTable 原樣渲染回傳內容,**不代管計數 / 不自動 MoreVertical 收納**。建議 consumer 自行實作:1-2 個 → icon buttons 並排(全 size="xs");3+ → 前 1-2 個 inline + MoreVertical dropdown(全 size="xs";dropdown 包含所有操作,確保鍵盤可存取全部)。**Header/body 寬度同步**(DataTable 代管):header 渲染同一 `rowActions` 輸出但設為 invisible 佔位,確保 header 和 body 的 right region 同寬。
158
158
 
159
159
  ### 九之二、Cell action primitive 分類(2026-04-29 codified)
160
160
 
@@ -164,7 +164,7 @@ SSOT → `patterns/element-anatomy/inline-action.spec.md`「Real case 表」+ Pr
164
164
  |------|-----------|
165
165
  | Header cell internal(sort / ⌄ menu / filter funnel / pin)| `ItemInlineActionButton` `size="md"`(對齊 AG Grid / Material / Airtable / Notion / Polaris) | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
166
166
  | **Multi-sort header(≥2 columns sorted)** | **隱藏 header arrow + 取消排序 dropdown option**(K7,2026-05-04)— 無 order 編號的單個 arrow 在 multi-sort 是 partial info → 反而混淆;user 走 SortManager panel 看完整 priority(SSOT)。0/1 sort 仍秀 arrow 完整資訊。理由:現行 DS 不顯 sort order 編號,跟 Airtable / Linear / Atlassian / Carbon 純箭頭派一致;multi-sort 時這派需 SortManager fallback(world-class 共識) |
167
- | Body cell internal(display endAction / clear / edit indicator)| Field family endAction(自動繼承) |
167
+ | Body cell internal(display endAction / clear / edit indicator)| Field family endAction(自動繼承)。**Display 態零恆顯型別 icon(2026-07-08 A 案)**:editable affordance = hover outline(SSOT → field.spec.md L4/L6,`nakedCellEditableDisplayHover`);boolean = live Checkbox(AG Grid 同);url = hover Pencil(click-opens-link 與 edit 衝突的功能性入口,非型別 indicator)。**cell 空值 = 全空白**(2026-07-08 B 案,SSOT → field-controls.spec.md「null / undefined 值」surface 分流表) |
168
168
  | Row dedicated action column | Button `xs iconOnly` 24px(見「九、Row Actions」) |
169
169
  | Toolbar | Button(action-bar 共識) |
170
170
 
@@ -213,13 +213,13 @@ type DataTableSelection =
213
213
  selection?: string[] | DataTableSelection // controlled;傳 string[] = include shorthand(向後相容)
214
214
  defaultSelection?: string[] | DataTableSelection // uncontrolled
215
215
  onSelectionChange?: (next: DataTableSelection) => void // 一律 emit union
216
- totalCount?: number // 全集筆數 M(server-side / filter );all 模式計數用
216
+ // (無 totalCount prop 全集筆數 M 由 consumer 自持;2026-07-13 D1 拍板移除 DS 內零消費 no-op prop)
217
217
  selectable?: boolean | 'single' | 'multi' // default false(不啟用);true 等同 'multi';single 永遠 include
218
218
  isRowSelectable?: (row: TData) => boolean
219
219
  preserveSelectionOnFilter?: boolean // default false
220
220
  ```
221
221
 
222
- 對齊 `useControllableState` idiom(Field / Switch / Checkbox 已用)+ MUI X DataGrid v8 `rowSelectionModel { type:'include'|'exclude', ids }` / AG Grid `selectAll + toggledNodes` 反向選取共識。**計數(consumer)**:`mode==='all' ? totalCount − excluded.length : ids.length`。**向後相容**:傳 `string[]` 自動正規化為 `{ mode:'include' }`;但 `onSelectionChange` 一律 emit union(consumer 讀取端需處理兩 mode)。
222
+ 對齊 `useControllableState` idiom(Field / Switch / Checkbox 已用)+ MUI X DataGrid v8 `rowSelectionModel { type:'include'|'exclude', ids }` / AG Grid `selectAll + toggledNodes` 反向選取共識。**計數(consumer)**:`mode==='all' ? M − excluded.length : ids.length`(M = consumer 自持的全集筆數,DataTable 不收 totalCount prop)。**向後相容**:傳 `string[]` 自動正規化為 `{ mode:'include' }`;但 `onSelectionChange` 一律 emit union(consumer 讀取端需處理兩 mode)。
223
223
 
224
224
  ### 二、Checkbox column
225
225
 
@@ -235,7 +235,7 @@ preserveSelectionOnFilter?: boolean // default false
235
235
  1. Header checkbox click(none → all)→ 選**目前可見** rows(filter 後 visible-only)= `{ mode:'include', ids:[…visible] }`
236
236
  2. 全頁可見已選 → BulkActionBar hint:「已選取本頁 N 個。**點此選取全部 M 個**」
237
237
  3. 點 hint → consumer `setSelection({ mode:'all', excluded:[] })` 擴 dataset 全選,hint 改:「已選取全部 M 個。**清除選取項目**」
238
- 4. **反向選取(inverted)**:all 模式下取消勾選某幾筆 → 加進 `excluded`(`選取 = 全集 − excluded`);再勾回 → 移出 `excluded`。對 10k 筆只載 50 筆**不需列舉其餘 ID**,任意 toggle 順序封閉、O(1)。count = `totalCount − excluded.length`,hint 顯示「已選取全部 M 個(排除 K 個)」。
238
+ 4. **反向選取(inverted)**:all 模式下取消勾選某幾筆 → 加進 `excluded`(`選取 = 全集 − excluded`);再勾回 → 移出 `excluded`。對 10k 筆只載 50 筆**不需列舉其餘 ID**,任意 toggle 順序封閉、O(1)。count = `M − excluded.length`(M = consumer 自持全集筆數),hint 顯示「已選取全部 M 個(排除 K 個)」。
239
239
 
240
240
  不**一鍵**直接擴 dataset(避免誤觸大量資料,必先 2-step);擴選後的反向扣除由 inverted 模型自動處理。
241
241
 
@@ -255,7 +255,7 @@ preserveSelectionOnFilter?: boolean // default false
255
255
  ### 六、Selection × filter / sort 互動
256
256
 
257
257
  - **`include` 模式**:filter 套用 → filtered-out 的 selected rows 預設清掉(對齊 Material / AG Grid / Polaris / GitHub / Gmail consensus) <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
258
- - **`all`(反向)模式**:語意 = 「全部**符合當前 filter**的列 − excluded」→ filter 變動時 selection set 隨 filter **自然重算**(M 跟著變),`excluded` 保留不清(被 filter 掉的 excluded 列無害,回到該 filter 時仍排除);**不**套用上面的 include-mode 清除。consumer 計數用更新後的 `totalCount`。
258
+ - **`all`(反向)模式**:語意 = 「全部**符合當前 filter**的列 − excluded」→ filter 變動時 selection set 隨 filter **自然重算**(M 跟著變),`excluded` 保留不清(被 filter 掉的 excluded 列無害,回到該 filter 時仍排除);**不**套用上面的 include-mode 清除。consumer 計數用更新後的全集筆數 M(consumer 自持)。
259
259
  - **opt-in `preserveSelectionOnFilter={true}`**(僅 include 模式)→ 給 productivity scope(Linear / Airtable 用法),保留 hidden selected,BulkActionBar 顯示「{visible} selected ({hidden} hidden by filter)」
260
260
  - sort 套用 → selection 全保留(sort 不影響可見性,兩 mode 同)
261
261
 
@@ -265,7 +265,7 @@ preserveSelectionOnFilter?: boolean // default false
265
265
 
266
266
  ### 八、a11y 預設
267
267
 
268
- - 每個 row checkbox 必有 `aria-label`:consumer 提供 `getRowAriaLabel?: (row) => string`,fallback `"Select row"`
268
+ - 每個 row checkbox 必有 `aria-label`:consumer 提供 `getRowAriaLabel?: (row) => string`,fallback `'選取此列'`
269
269
  - header checkbox `aria-label="全選可見列"`
270
270
  - 鍵盤:`Space` toggle / `Shift+Space` 擴 range / `Cmd/Ctrl+A` 選全可見 / `Esc` clear
271
271
  - Selection 變更可選 `aria-live="polite"` 通知(consumer-implemented)
@@ -305,7 +305,7 @@ type FilterTreeNested = { mode: 'nested'; conjunction: 'and'|'or'; children: Fil
305
305
 
306
306
  ### 三、Operator × ValueShape SSOT
307
307
 
308
- `filter-operators.ts` 的 `OPERATOR_REGISTRY: Record<ColumnType, OperatorSpec[]>` 是唯一 truth。Panel 完全 data-driven:field 選 → load op set → 選 op → 由 `valueShape` dispatch picker(`filter-value-picker.tsx`)。`is_set` / `is_not_set` / `is_true` / `is_false`(`ValueShape='none'`)不渲 picker。
308
+ `filter-operators.ts` 的 `OPERATOR_REGISTRY: Record<ColumnType, OperatorSpec[]>` 是唯一 truth。Panel 完全 data-driven:field 選 → load op set → 選 op → 由 `valueShape` dispatch picker(`data-table-filter-value-picker.tsx`,@internal;2026-07-14 file-size 拆檔自 panel)。`is_set` / `is_not_set` / `is_true` / `is_false`(`ValueShape='none'`)不渲 picker。
309
309
 
310
310
  ValueShape ↔ DS picker 對照(canonical 2026-05-02):
311
311
 
@@ -357,6 +357,17 @@ ValueShape ↔ DS picker 對照(canonical 2026-05-02):
357
357
 
358
358
  ## L4 Inline Edit / Nested rows / Row drag(2026-05-04;對齊 Notion / Airtable type-aware editor + Jira drag idiom @benchmark-unverified)
359
359
 
360
+ ### Inline create row(表格底部「+ 新增」列)— 只定義 idle 態(2026-07-08 WM 戰役 codify,user 拍板)
361
+
362
+ **點擊後的編輯內容 consumer 自組**(常被客製,不 canonical 化、不加 DS API):TanStack headless 無此 feature(https://tanstack.com/table/v8/docs/guide/custom-features)、AG Grid 無內建(官方 blog 教 pinned row DIY:https://blog.ag-grid.com/add-new-rows-using-a-pinned-row-at-the-top-of-the-grid/)、Ant ProComponents 只定義 trigger 列。**可定義的只有尚未點擊的 idle 列**,幾何全消費既有 token(零新值):
363
+
364
+ - **高度** = `h-table-row-{size}`(與 data row 精確同高 — 上方「三 region row 精確同高」延伸到此列)
365
+ - **左 padding** = `--table-cell-px`,「+ icon + 文字」對齊**第一資料欄**內容起點(啟 selection / drag 系統欄時同樣對齊第一資料欄,Notion / Airtable 同)
366
+ - **Typography** = cell 同字級(`fieldDisplayTextClass(size)`)+ `text-fg-muted`(placeholder 語感);Plus icon 同 `fg-muted`
367
+ - **Hover** = 整列 `neutral-hover` + cursor-pointer,**整列可點**(hit-target 對齊 L2「整 cell 區可點擊」)
368
+ - **點擊 → inline**(不強制開 dialog;欄位複雜的 create 另走 Dialog 可並存);建議行為(非契約):Enter 提交後保持編輯態連續新增(Jira inline create idiom)、Esc 還原 idle 列
369
+ - **拒絕**:Ant 式全寬 dashed 按鈕(表單語境 idiom,dashed 不在 DS 視覺語言);idle 列是 row 形(Notion「+ New」/ Airtable plus row / Asana「Add task…」line 資料庫工具共識)
370
+
360
371
  ### Inline Edit — per-column opt-in
361
372
 
362
373
  `columnDef.meta.editable: boolean | (row) => boolean`(`true` / fn-true 才開)。Commit:blur or Enter → `onCellCommit(rowId, colId, value)`;Cancel:Esc。例外:autoRowHeight string cell 的 edit 是 `Textarea` — Enter 換行、`Cmd/Ctrl+Enter` commit(blur 同 commit)。
@@ -369,7 +380,16 @@ ValueShape ↔ DS picker 對照(canonical 2026-05-02):
369
380
  | select / multiSelect | click cell | `<Select>` / `<Combobox>` |
370
381
  | person / multiPerson | click cell | `<PeoplePicker variant="naked">`(選人 picker) |
371
382
  | **boolean** | direct toggle | `<Checkbox>` 無 mode 切換 |
372
- | **url** | **hover cell → Pencil 按鈕(xs iconOnly tertiary)→ click** | `<Input>`(read 永遠是連結;cell click 走 anchor 開連結,**不**進 edit)|
383
+ | **url** | **hover cell → Pencil 按鈕(xs iconOnly tertiary)→ click** | `<Input>`(read 永遠是連結;cell click 走 anchor 開連結,**不**進 edit)— 屬下方「navigate-valued cell 通用類別」|
384
+
385
+ ### Navigate-valued cell 通用類別(2026-07-08 user 拍板 codify — 原 url 專屬條文升級)
386
+
387
+ **定義**:凡「點值的主行為 = 導航/開啟而非編輯」的型別(url;未來 parent / email / file / relation 同類),一律繼承四條 — 新型別只在上表登記一行,其餘全繼承,禁逐型別重刻:
388
+
389
+ 1. **排除 click-to-edit 與 hover outline**(code gate `data-table.tsx` editable-click 判斷排除該型別 — 此前只活在 code,本段為條文 SSOT):值可點 = click 屬導航,cell 不再是「點擊進 edit」目標,hover outline(field.spec.md L4)一併不套
390
+ 2. **排除 Enter / F2 進 edit**(下方鍵盤段「非 boolean/url」既有規則,類別化後隨表繼承)
391
+ 3. **唯一 edit affordance = hover Pencil**(xs iconOnly tertiary,`opacity-0 group-hover/cell:opacity-100`,onClick `stopPropagation` + `onRequestEdit`)— 對齊 AG Grid 官方三件套(`suppressClickEdit` + 「including a button in your cell renderer」+ `startEditingCell()`,https://www.ag-grid.com/react-data-grid/cell-editing-start-stop/)+ Jira hover-pencil + Notion title cell hover-OPEN 鏡像;Atlaskit target-tag 分流(點 `<a>` 導航、點空白區編輯)為次選已評估不採(與 hover-outline 統一 affordance 衝突)
392
+ 4. **edit 觸發後 = 一般 field 行為契約**:Pencil 只負責「進入 edit」一步;進入後 autoFocus 進輸入、Esc 取消、Enter/blur commit、驗證時機、focus 樣式全部回歸 field-controls edit-mode canonical,與其他型別 cell edit 零特例。若 edit 態控件與 form 場景不同(url 用 plain `<Input>` 非 LinkInput — LinkInput edit 預設顯 link 態,cell 需直接輸入),**必在上表該行寫明 documented 例外 + rationale**,禁只留 code 註解
373
393
 
374
394
  ### Nested rows — forward TanStack
375
395
 
@@ -407,7 +427,7 @@ Row drag + column reorder + TreeView 共用 `lib/drag-visual.ts`:source `opacity
407
427
  - **bar 本體 SSOT 在 `<Pagination>` 完整形態**(2026-07-06 user 拍板「Pagination 元件提供完整功能、Table 按一致定義套用」):showTotal range 資訊、「N 筆/頁」選單、「資訊左、操作右」layout 全在 `../Pagination/pagination.spec.md`「完整形態」段——DataTable **只轉發 config + own TanStack state**(controlled 消費),不自拼分頁列
408
428
  - **間距**:表格 → 分頁列 = `--layout-space-tight`(layoutSpace spec 規則 3「跨範疇 functional 交互」;Ant Table margin 16px / shadcn py-4 同量級)
409
429
  - **對齊**:純頁碼形態**靠右**(shadcn `justify-end` / Ant Table 預設 `bottomEnd` / MUI TablePagination / Carbon 控制群 4 家實證);完整形態由 Pagination 自帶 w-full justify-between
410
- - **`total` 數源** = `getPrePaginationRowModel().rows.length`(filter 後全集)——**不是** selection all-mode 的 `totalCount` prop(那是 server-side 全集數,語意不同)
430
+ - **`total` 數源** = `getPrePaginationRowModel().rows.length`(filter 後全集)——**不是** selection all-mode 的 server-side 全集數 M(那由 consumer 自持,語意不同)
411
431
  - filter / data 縮小時自動 clamp 當前頁(對齊 MUI X);`isEmpty` 時分頁列整條不渲染(Empty 已渲染)
412
432
 
413
433
  **與虛擬滾動互斥**:啟用分頁 → `useVirtual` 強制關閉——TanStack 官方定位兩者為互斥替代策略(分頁 = 每頁固定筆數主動換頁;虛擬滾動 = 連續滾動只渲可視列)。分頁時無虛擬化保護,建議 `pageSize ≤ 100`。