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