@qijenchen/design-system 0.1.0-beta.82 → 0.1.0-beta.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) 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-panel.d.ts.map +1 -1
  53. package/dist/components/DataTable/data-table-filter-panel.js +607 -0
  54. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  55. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  56. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  58. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  59. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  60. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  61. package/dist/components/DataTable/data-table.d.ts +5 -6
  62. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  63. package/dist/components/DataTable/data-table.js +36 -15
  64. package/dist/components/DataTable/data-table.js.map +1 -1
  65. package/dist/components/DataTable/filter-operators.js +140 -0
  66. package/dist/components/DataTable/filter-operators.js.map +1 -0
  67. package/dist/components/DataTable/filter-tree.js +312 -0
  68. package/dist/components/DataTable/filter-tree.js.map +1 -0
  69. package/dist/components/DataTable/index.d.ts +3 -0
  70. package/dist/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/components/DataTable/index.js +12 -1
  72. package/dist/components/DataTable/index.js.map +1 -1
  73. package/dist/components/DataTable/lib/column-meta.js +25 -0
  74. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  75. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  76. package/dist/components/DateGrid/date-grid.js +3 -1
  77. package/dist/components/DateGrid/date-grid.js.map +1 -1
  78. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  79. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  80. package/dist/components/DatePicker/date-picker.js +105 -74
  81. package/dist/components/DatePicker/date-picker.js.map +1 -1
  82. package/dist/components/Dialog/dialog.d.ts +20 -3
  83. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  84. package/dist/components/Dialog/dialog.js +38 -20
  85. package/dist/components/Dialog/dialog.js.map +1 -1
  86. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  87. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  88. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  89. package/dist/components/Field/field-context.d.ts +45 -5
  90. package/dist/components/Field/field-context.d.ts.map +1 -1
  91. package/dist/components/Field/field-context.js +19 -0
  92. package/dist/components/Field/field-context.js.map +1 -1
  93. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  94. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  95. package/dist/components/Field/field-edit-keys.js +19 -0
  96. package/dist/components/Field/field-edit-keys.js.map +1 -0
  97. package/dist/components/Field/field-types.d.ts +20 -1
  98. package/dist/components/Field/field-types.d.ts.map +1 -1
  99. package/dist/components/Field/field-types.js.map +1 -1
  100. package/dist/components/Field/field-wrapper.d.ts +3 -2
  101. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  102. package/dist/components/Field/field-wrapper.js +38 -39
  103. package/dist/components/Field/field-wrapper.js.map +1 -1
  104. package/dist/components/Field/field.d.ts +2 -1
  105. package/dist/components/Field/field.d.ts.map +1 -1
  106. package/dist/components/Field/field.js.map +1 -1
  107. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  108. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  109. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  110. package/dist/components/FileItem/file-item.js +1 -1
  111. package/dist/components/FileItem/file-item.js.map +1 -1
  112. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  113. package/dist/components/FileUpload/file-upload.js.map +1 -1
  114. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  115. package/dist/components/FileViewer/file-viewer.js +7 -2
  116. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  117. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  118. package/dist/components/FileViewer/image-renderer.js +22 -1
  119. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  120. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  121. package/dist/components/HoverCard/hover-card.js +5 -3
  122. package/dist/components/HoverCard/hover-card.js.map +1 -1
  123. package/dist/components/InlineEdit/index.d.ts +2 -0
  124. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  125. package/dist/components/InlineEdit/index.js +5 -0
  126. package/dist/components/InlineEdit/index.js.map +1 -0
  127. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  129. package/dist/components/InlineEdit/inline-edit.js +164 -0
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  131. package/dist/components/Input/input.d.ts +6 -11
  132. package/dist/components/Input/input.d.ts.map +1 -1
  133. package/dist/components/Input/input.js +43 -13
  134. package/dist/components/Input/input.js.map +1 -1
  135. package/dist/components/LinkInput/link-input.d.ts +2 -2
  136. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  137. package/dist/components/LinkInput/link-input.js +6 -5
  138. package/dist/components/LinkInput/link-input.js.map +1 -1
  139. package/dist/components/Menu/menu-item.d.ts +14 -2
  140. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  141. package/dist/components/Menu/menu-item.js +25 -3
  142. package/dist/components/Menu/menu-item.js.map +1 -1
  143. package/dist/components/NumberInput/number-input.d.ts +3 -3
  144. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  145. package/dist/components/NumberInput/number-input.js +6 -5
  146. package/dist/components/NumberInput/number-input.js.map +1 -1
  147. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  148. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  149. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  150. package/dist/components/Pagination/pagination.js +1 -1
  151. package/dist/components/Pagination/pagination.js.map +1 -1
  152. package/dist/components/PeoplePicker/index.js +7 -1
  153. package/dist/components/PeoplePicker/index.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  155. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  156. package/dist/components/PeoplePicker/people-picker.js +23 -10
  157. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  158. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  159. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.js +19 -14
  161. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  162. package/dist/components/Popover/popover.d.ts.map +1 -1
  163. package/dist/components/Popover/popover.js +3 -1
  164. package/dist/components/Popover/popover.js.map +1 -1
  165. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  166. package/dist/components/ProfileCard/profile-card.js +3 -3
  167. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  168. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  169. package/dist/components/RadioGroup/radio-group.js +15 -9
  170. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  171. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  172. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.js +6 -3
  174. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  175. package/dist/components/Select/select.d.ts +46 -5
  176. package/dist/components/Select/select.d.ts.map +1 -1
  177. package/dist/components/Select/select.js +109 -28
  178. package/dist/components/Select/select.js.map +1 -1
  179. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  180. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  181. package/dist/components/SelectMenu/select-menu.js +8 -1
  182. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  183. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  184. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  185. package/dist/components/SelectionControl/boolean-value.js +23 -0
  186. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  187. package/dist/components/SelectionControl/index.d.ts +1 -0
  188. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  189. package/dist/components/SelectionControl/index.js +2 -0
  190. package/dist/components/SelectionControl/index.js.map +1 -1
  191. package/dist/components/Sheet/index.js +2 -1
  192. package/dist/components/Sheet/sheet.d.ts +7 -1
  193. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  194. package/dist/components/Sheet/sheet.js +5 -2
  195. package/dist/components/Sheet/sheet.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +8 -10
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts.map +1 -1
  201. package/dist/components/Slider/slider.js.map +1 -1
  202. package/dist/components/Switch/switch.d.ts +6 -6
  203. package/dist/components/Switch/switch.d.ts.map +1 -1
  204. package/dist/components/Switch/switch.js +3 -2
  205. package/dist/components/Switch/switch.js.map +1 -1
  206. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  207. package/dist/components/Tabs/tabs.js +15 -1
  208. package/dist/components/Tabs/tabs.js.map +1 -1
  209. package/dist/components/Textarea/textarea.d.ts +2 -2
  210. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  211. package/dist/components/Textarea/textarea.js +50 -42
  212. package/dist/components/Textarea/textarea.js.map +1 -1
  213. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  214. package/dist/components/TimePicker/time-columns.js +42 -38
  215. package/dist/components/TimePicker/time-columns.js.map +1 -1
  216. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  217. package/dist/components/TimePicker/time-picker.js +8 -6
  218. package/dist/components/TimePicker/time-picker.js.map +1 -1
  219. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  220. package/dist/components/Tooltip/tooltip.js +7 -5
  221. package/dist/components/Tooltip/tooltip.js.map +1 -1
  222. package/dist/components/TreeView/tree-view.d.ts +56 -1
  223. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  224. package/dist/components/TreeView/tree-view.js +211 -12
  225. package/dist/components/TreeView/tree-view.js.map +1 -1
  226. package/dist/index.d.ts +115 -58
  227. package/dist/index.d.ts.map +1 -1
  228. package/dist/index.js +93 -108
  229. package/dist/index.js.map +1 -1
  230. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  231. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  232. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  233. package/dist/tokens/categorical-color.js +15 -0
  234. package/dist/tokens/categorical-color.js.map +1 -1
  235. package/dist/tokens/motion/motion.d.ts +7 -6
  236. package/dist/tokens/motion/motion.d.ts.map +1 -1
  237. package/dist/tokens/motion/motion.js +6 -6
  238. package/dist/tokens/motion/motion.js.map +1 -1
  239. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  240. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  241. package/dist/tokens/motion/overlay-motion.js +9 -0
  242. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  243. package/dist/tokens/uiSize/icon-size.js +5 -0
  244. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  245. package/ds-canonical/fork/governance.lock +37 -19
  246. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  247. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  248. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  249. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
  250. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  251. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  252. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  253. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  254. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
  256. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  257. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  258. package/ds-canonical/fork/manifest.json +20 -0
  259. package/ds-canonical/fork/preamble.md +22 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
  263. package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
  264. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  266. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  267. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  268. package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
  269. package/ds-canonical/hooks/README.md +1 -1
  270. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  271. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  272. package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
  273. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  274. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  275. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
  276. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  277. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  278. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  279. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  280. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  281. package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
  282. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  283. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  284. package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
  285. package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
  286. package/ds-canonical/hooks/check_story_determinism.sh +39 -0
  287. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  288. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  289. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  290. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  291. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  292. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  293. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  294. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
  295. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  296. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  297. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  298. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  299. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  300. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  301. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
  302. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
  303. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  304. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  305. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  306. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  307. package/ds-canonical/references/failure-class-registry.json +145 -0
  308. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  309. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  310. package/ds-canonical/references/scenario-definition.md +6 -9
  311. package/ds-canonical/references/ssot-consultation.md +2 -2
  312. package/ds-canonical/references/ssot-index.md +5 -4
  313. package/ds-canonical/references/story-baseline-registry.json +8 -2
  314. package/ds-canonical/references/structural-token-retention.md +6 -9
  315. package/ds-canonical/rules/meta-patterns.md +8 -8
  316. package/ds-canonical/rules/self-verify.md +4 -3
  317. package/ds-canonical/rules/spec-rules.md +1 -1
  318. package/ds-canonical/rules/story-rules.md +2 -2
  319. package/ds-canonical/rules/ui-development.md +4 -2
  320. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
  321. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  322. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  323. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  324. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  325. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  326. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  327. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
  328. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  329. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  330. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  331. package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
  332. package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
  333. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  334. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  335. package/ds-canonical/skills/governance-health/SKILL.md +2 -1
  336. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  337. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  338. package/ds-canonical/skills/new-component/SKILL.md +7 -5
  339. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  340. package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
  341. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  342. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  343. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  344. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  345. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  346. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  347. package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
  348. package/ds-story-manifest.json +29 -20
  349. package/llms-full.txt +22 -1
  350. package/llms.txt +5 -4
  351. package/package.json +7 -3
  352. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  353. package/src/components/Accordion/accordion.stories.tsx +16 -1
  354. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  355. package/src/components/Alert/alert.spec.md +8 -10
  356. package/src/components/Alert/alert.stories.tsx +28 -28
  357. package/src/components/Alert/alert.tsx +1 -1
  358. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  359. package/src/components/AppShell/app-shell.spec.md +4 -4
  360. package/src/components/AppShell/app-shell.tsx +28 -2
  361. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  362. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  363. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  364. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  365. package/src/components/Avatar/avatar.spec.md +2 -2
  366. package/src/components/Avatar/avatar.stories.tsx +8 -6
  367. package/src/components/Avatar/avatar.tsx +13 -5
  368. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  369. package/src/components/Badge/badge.spec.md +2 -0
  370. package/src/components/Badge/badge.stories.tsx +4 -2
  371. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  372. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  373. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  374. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  375. package/src/components/Button/button.principles.stories.tsx +1 -1
  376. package/src/components/Button/button.spec.md +2 -2
  377. package/src/components/Button/button.tsx +18 -3
  378. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  379. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  380. package/src/components/Calendar/calendar.spec.md +5 -4
  381. package/src/components/Calendar/calendar.stories.tsx +7 -4
  382. package/src/components/Calendar/calendar.tsx +26 -7
  383. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  384. package/src/components/Carousel/carousel.spec.md +2 -2
  385. package/src/components/Carousel/carousel.tsx +11 -3
  386. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  387. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  388. package/src/components/Chart/chart.stories.tsx +2 -8
  389. package/src/components/Chart/chart.tsx +3 -0
  390. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  391. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  392. package/src/components/Checkbox/checkbox.spec.md +11 -26
  393. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  394. package/src/components/Checkbox/checkbox.tsx +18 -13
  395. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  396. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  397. package/src/components/Chip/chip.spec.md +5 -4
  398. package/src/components/Chip/chip.tsx +5 -1
  399. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  400. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  401. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  402. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  403. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  404. package/src/components/Coachmark/coachmark.spec.md +5 -5
  405. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  406. package/src/components/Coachmark/coachmark.tsx +10 -3
  407. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  408. package/src/components/Combobox/combobox.tsx +53 -19
  409. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  410. package/src/components/Command/command.principles.stories.tsx +1 -1
  411. package/src/components/Command/command.stories.tsx +42 -10
  412. package/src/components/DataTable/cell-registry.tsx +86 -63
  413. package/src/components/DataTable/column-types.ts +10 -1
  414. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  415. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  416. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  417. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  418. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  419. package/src/components/DataTable/data-table.spec.md +32 -12
  420. package/src/components/DataTable/data-table.stories.tsx +16 -17
  421. package/src/components/DataTable/data-table.tsx +103 -60
  422. package/src/components/DataTable/index.ts +3 -0
  423. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  424. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  425. package/src/components/DateGrid/date-grid.spec.md +1 -1
  426. package/src/components/DateGrid/date-grid.tsx +3 -1
  427. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  428. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  429. package/src/components/DatePicker/date-picker.spec.md +3 -3
  430. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  431. package/src/components/DatePicker/date-picker.tsx +99 -45
  432. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  433. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  434. package/src/components/DescriptionList/description-list.spec.md +3 -3
  435. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  436. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  437. package/src/components/Dialog/dialog.spec.md +9 -0
  438. package/src/components/Dialog/dialog.stories.tsx +66 -5
  439. package/src/components/Dialog/dialog.tsx +60 -25
  440. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  441. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  442. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  443. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  444. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  445. package/src/components/Empty/empty.spec.md +2 -2
  446. package/src/components/Field/field-context.ts +69 -5
  447. package/src/components/Field/field-controls.spec.md +62 -8
  448. package/src/components/Field/field-edit-keys.ts +66 -0
  449. package/src/components/Field/field-types.ts +58 -9
  450. package/src/components/Field/field-wrapper.tsx +50 -42
  451. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  452. package/src/components/Field/field.spec.md +1 -1
  453. package/src/components/Field/field.stories.tsx +1 -1
  454. package/src/components/Field/field.tsx +2 -1
  455. package/src/components/Field/form-validation.spec.md +3 -3
  456. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  457. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  458. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  459. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  460. package/src/components/FileItem/file-item.spec.md +14 -8
  461. package/src/components/FileItem/file-item.stories.tsx +36 -25
  462. package/src/components/FileItem/file-item.tsx +8 -6
  463. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  464. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  465. package/src/components/FileUpload/file-upload.spec.md +1 -1
  466. package/src/components/FileUpload/file-upload.tsx +1 -1
  467. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  468. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  469. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  470. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  471. package/src/components/FileViewer/file-viewer.tsx +12 -4
  472. package/src/components/FileViewer/image-renderer.tsx +35 -7
  473. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  474. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  475. package/src/components/HoverCard/hover-card.spec.md +5 -5
  476. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  477. package/src/components/HoverCard/hover-card.tsx +5 -3
  478. package/src/components/InlineEdit/index.ts +5 -0
  479. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  480. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  481. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  482. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  483. package/src/components/Input/input.principles.stories.tsx +2 -12
  484. package/src/components/Input/input.spec.md +13 -18
  485. package/src/components/Input/input.tsx +69 -22
  486. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  487. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  488. package/src/components/LinkInput/link-input.tsx +11 -10
  489. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  490. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  491. package/src/components/Menu/menu-item.spec.md +22 -15
  492. package/src/components/Menu/menu-item.stories.tsx +39 -11
  493. package/src/components/Menu/menu-item.tsx +38 -4
  494. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  495. package/src/components/Notice/notice.spec.md +16 -3
  496. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  497. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  498. package/src/components/NumberInput/number-input.spec.md +4 -4
  499. package/src/components/NumberInput/number-input.tsx +19 -12
  500. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  501. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  502. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  503. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  504. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  505. package/src/components/Pagination/pagination.spec.md +1 -1
  506. package/src/components/Pagination/pagination.stories.tsx +2 -6
  507. package/src/components/Pagination/pagination.tsx +1 -1
  508. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  509. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  510. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  511. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  512. package/src/components/PeoplePicker/person-display.tsx +32 -16
  513. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  514. package/src/components/Popover/popover.tsx +3 -1
  515. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  516. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  517. package/src/components/ProfileCard/profile-card.tsx +6 -6
  518. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  519. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  520. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  521. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  522. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  523. package/src/components/RadioGroup/radio-group.tsx +41 -15
  524. package/src/components/Rating/rating.spec.md +11 -3
  525. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  526. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  527. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  528. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  529. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  530. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  531. package/src/components/Select/select.spec.md +27 -17
  532. package/src/components/Select/select.stories.tsx +33 -0
  533. package/src/components/Select/select.tsx +190 -36
  534. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  535. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  536. package/src/components/SelectMenu/select-menu.tsx +16 -3
  537. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  538. package/src/components/SelectionControl/index.ts +1 -0
  539. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  540. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  541. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  542. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  543. package/src/components/Separator/separator.spec.md +2 -2
  544. package/src/components/Separator/separator.stories.tsx +6 -27
  545. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  546. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  547. package/src/components/Sheet/sheet.spec.md +2 -2
  548. package/src/components/Sheet/sheet.tsx +9 -5
  549. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  550. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  551. package/src/components/Sidebar/sidebar.spec.md +13 -15
  552. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  553. package/src/components/Sidebar/sidebar.tsx +37 -25
  554. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  555. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  556. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  557. package/src/components/Slider/slider.spec.md +5 -5
  558. package/src/components/Slider/slider.tsx +3 -1
  559. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  560. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  561. package/src/components/Steps/steps.spec.md +1 -1
  562. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  563. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  564. package/src/components/Switch/switch.spec.md +8 -8
  565. package/src/components/Switch/switch.stories.tsx +9 -24
  566. package/src/components/Switch/switch.tsx +17 -13
  567. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  568. package/src/components/Tabs/tabs.spec.md +1 -1
  569. package/src/components/Tabs/tabs.tsx +21 -1
  570. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  571. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  572. package/src/components/Textarea/textarea.spec.md +4 -4
  573. package/src/components/Textarea/textarea.tsx +72 -46
  574. package/src/components/TimePicker/time-columns.tsx +6 -2
  575. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  576. package/src/components/TimePicker/time-picker.spec.md +3 -3
  577. package/src/components/TimePicker/time-picker.tsx +16 -10
  578. package/src/components/Toast/toast.stories.tsx +7 -4
  579. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  580. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  581. package/src/components/Tooltip/tooltip.spec.md +1 -1
  582. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  583. package/src/components/Tooltip/tooltip.tsx +8 -6
  584. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  585. package/src/components/TreeView/tree-view.spec.md +42 -11
  586. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  587. package/src/components/TreeView/tree-view.tsx +322 -17
  588. package/src/index.ts +584 -60
  589. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  590. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  591. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  592. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  593. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  594. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  595. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  596. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  597. package/src/styles/tokens.css +3 -0
  598. package/src/tokens/README.md +1 -1
  599. package/src/tokens/color/color.spec.md +3 -3
  600. package/src/tokens/color/color.stories.tsx +3 -3
  601. package/src/tokens/density/density.stories.tsx +16 -3
  602. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  603. package/src/tokens/motion/motion.css +33 -21
  604. package/src/tokens/motion/motion.spec.md +32 -15
  605. package/src/tokens/motion/motion.stories.tsx +58 -5
  606. package/src/tokens/motion/motion.ts +7 -6
  607. package/src/tokens/motion/overlay-motion.ts +26 -0
  608. package/src/tokens/orphan-tokens.spec.md +4 -4
  609. package/src/tokens/token-system.spec.md +1 -0
  610. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  611. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  612. package/src/tokens/utility-registry.json +160 -23
@@ -152,9 +152,6 @@ export interface DataTableProps<TData>
152
152
  defaultSelection?: string[] | DataTableSelection
153
153
  /** Selection 變更 callback(emit DataTableSelection union;include / all 兩模型) */
154
154
  onSelectionChange?: (next: DataTableSelection) => void
155
- /** 全資料集筆數 M(server-side / filter 後);all 模式 count = totalCount − excluded.length。
156
- * **DS 內部零消費(no-op prop)**:僅型別文件 + destructure 防 spread 到 DOM;count 全由 consumer 計算 */
157
- totalCount?: number
158
155
  /** 是否啟用 selection / 模式;true 等同 'multi' */
159
156
  selectable?: boolean | 'single' | 'multi'
160
157
  /** Row 是否可選(disabled rows 只 disable checkbox,row 內容正常 render) */
@@ -203,7 +200,7 @@ export interface DataTableProps<TData>
203
200
  *
204
201
  * **v2(2026-05-05)修正**:
205
202
  * - Virtualizer × transform:被拖 row 略過 `measureElement`(透過 SortableRowCtx 廣播 active id),避免 transform 干擾測量
206
- * - 3-panel mirror sync:每 region 對同 row id 各呼叫 `useDraggable` + `useDroppable`,mirror 自然取得相同 transform
203
+ * - 3-panel mirror sync:primary region 呼叫 `useDraggable` + `useDroppable`;mirror region 只 `useDroppable`(v15.4 split),isDragging 由 `useDndContext` active.id 同步 → 三 region 視覺一致
207
204
  * - Cross-parent drop:nested 全 row 各自 `useDroppable`,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`
208
205
  *
209
206
  * 詳 `data-table.spec.md`「L4 Row drag」段。
@@ -265,7 +262,7 @@ export interface DataTablePaginationOptions {
265
262
  pageSize?: number
266
263
  /** 每頁筆數選項;傳了才渲染「每頁 N 筆」Select(消費既有 Select size="sm") */
267
264
  pageSizeOptions?: number[]
268
- /** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 totalCount) */
265
+ /** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 server-side 全集數 M — 那是 consumer 自持) */
269
266
  showTotal?: boolean
270
267
  /** 當前頁(1-based,controlled;不傳 = uncontrolled) */
271
268
  page?: number
@@ -312,7 +309,9 @@ const SELECT_COL_ID = '__select__'
312
309
  * 解決「全選 10k 筆只載 50 筆 → 無法列舉其餘 ID」:all 模式「選取 = 全集 − excluded」,
313
310
  * 任何 toggle 都只是 excluded 的 add/remove,對任意順序封閉、O(1)、不需列舉未載入 ID。
314
311
  *
315
- * 計數(consumer):mode==='all' ? totalCount − excluded.length : ids.length(需傳 totalCount)。
312
+ * 計數(consumer):mode==='all' ? M − excluded.length : ids.length(M = consumer 自持的
313
+ * server-side / filter 後全集筆數;2026-07-13 D1 拍板:DataTable 不收 totalCount prop — DS 內部
314
+ * 零消費 no-op 已移除,計數本來就全由 consumer 端算)。
316
315
  * 進入 all 模式:consumer 在「選取全部 M」hint 點擊時 setSelection({ mode: 'all', excluded: [] })。
317
316
  */
318
317
  export type DataTableSelection =
@@ -446,12 +445,13 @@ function TruncateCell({ children, className }: { children: React.ReactNode; clas
446
445
  return <Tooltip><TooltipTrigger asChild>{span}</TooltipTrigger><TooltipContent>{children}</TooltipContent></Tooltip>
447
446
  }
448
447
 
449
- // ── L4 Row Drag: SortableRowContext (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
448
+ // ── L4 Row Drag: SortableRowContext(v15 Path B;2026-07-14 JSDoc 對齊實作)──────
449
+ // region(left / center / right)各 mount 一次 SortableRowProvider,依 role 分流(v15.4 split):
450
+ // primary SourceRowProvider(useDraggable + useDroppable)= 唯一 drag source;
451
+ // mirror MirrorRowProvider(useDroppable only),isDragging useDndContext active.id 同步。
452
+ // SortableContext / useSortable(v15.0 Path B 已砍,見檔頭 import 註解)。listeners 全走
453
+ // RowDragHandle Button(v15.6 button-only;row 本身不接 listeners)。primary = left region 若存在否則 center
454
+ // `invalidDrop`(cross-parent over)走 prop 廣播給 RowDragHandle 切 cursor-not-allowed。
455
455
  interface SortableRowCtxValue {
456
456
  setNodeRef: (el: HTMLElement | null) => void
457
457
  role: 'primary' | 'mirror'
@@ -477,10 +477,11 @@ interface SortableRowCtxValue {
477
477
  }
478
478
  const SortableRowCtx = React.createContext<SortableRowCtxValue | null>(null)
479
479
 
480
- /** Per-region per-row 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 不提供避免雙觸發。 */
480
+ /** Per-region per-row drag wrapper(v15.4 architectural split)。
481
+ * 同 row.id 在 left/center/right 三 region 各 mount 一次,但 hook mount tree 完全分離:
482
+ * primary SourceRowProvider(useDraggable + useDroppable);mirror MirrorRowProvider
483
+ * (useDroppable only,isDragging useDndContext 同步)。activator / listeners 只給
484
+ * primary 的 RowDragHandle Button(v15.6 button-only);mirror 不提供避免雙觸發。 */
484
485
  function SortableRowProvider(props: {
485
486
  id: string
486
487
  disabled?: boolean
@@ -593,14 +594,15 @@ function MirrorRowProvider({
593
594
  return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>
594
595
  }
595
596
 
596
- /** DraggableHeaderCell — wrap header cell 跟 dnd-kit useSortable 接軌(2026-05-06 v14.2)。
597
+ /** DraggableHeaderCell — wrap header cell 跟 dnd-kit useDraggable + useDroppable 接軌
598
+ * (2026-05-06 v14.2;v15.0 Path B 改分離 hooks,無 SortableContext)。
597
599
  *
598
600
  * Why wrap-not-rewrite:`headerCellEl` 既有邏輯複雜(sort / resize / select column / right region 等),
599
- * 改 inline useSortable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render
601
+ * 改 inline useDraggable/useDroppable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render
600
602
  * 保持 untouched,單一職責 = 加 drag affordance。
601
603
  *
602
604
  * Behavior:
603
- * - useSortable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners
605
+ * - useDraggable + useDroppable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners
604
606
  * - `data: { type: 'column', columnId }` 餵 dnd-kit handleDragStart / handleDragEnd 區分 row/column drag
605
607
  * - 注入 ref(setNodeRef)+ transform style + transition + opacity(drag 時 source invisible,DragOverlay 顯 ghost)
606
608
  * - draggable 時注入 attributes + listeners + cursor:grab / `data-column-id` (DragOverlay snapshot 用)
@@ -660,8 +662,9 @@ function DraggableHeaderCell({
660
662
 
661
663
  /** Row drag handle — Portal-rendered, position:fixed 真正水平置中於 table outer border line(Jira canonical)。
662
664
  *
663
- * v15.2 重構:**Button 純視覺 affordance**,不再 spread drag listeners 改由 row div 整列接 listeners
664
- * (TreeView SSOT)。Button 只負責顯示「此 row 可拖」的視覺暗示。
665
+ * v15.6 button-only drag(推翻 v15.2「整列接 listeners」,2026-07-14 JSDoc 對齊):Button =
666
+ * 唯一 activator,接 handleSetActivatorNodeRef + handleListeners(SourceRowProvider ctx);
667
+ * row div 不接 listeners(rowListeners=undefined),row click 保留給 select / open detail 等 UX。
665
668
  *
666
669
  * Why Portal + position:fixed(2026-05-05 v4):
667
670
  * DataTable 結構含三層 overflow-hidden(outer wrapper / leftBody / row),用 absolute + translate-x:-50%
@@ -923,7 +926,6 @@ function DataTableInner<TData>(
923
926
  estimateRowHeight, tableOptions, rowActions, cellErrors,
924
927
  pinnedLeftColumns, pinnedRightColumns, inlineEdit = false,
925
928
  selection: selectionProp, defaultSelection, onSelectionChange,
926
- totalCount,
927
929
  selectable = false, isRowSelectable, getRowId, getRowAriaLabel,
928
930
  preserveSelectionOnFilter = false,
929
931
  columnVisibility: columnVisibilityProp, defaultColumnVisibility, onColumnVisibilityChange,
@@ -1262,7 +1264,7 @@ function DataTableInner<TData>(
1262
1264
  // 2026-05-06 v10 DragOverlay canonical:retire windowed sticky range extractor (v4-v9 workaround)。
1263
1265
  // 改用 `<DragOverlay>` portal 把 source row 視覺解耦 — source 即使 unmount(virtual scroll out)
1264
1266
  // overlay 仍 render 由 cloned outerHTML 提供視覺。dnd-kit transform / collision 走 active item id
1265
- // (id 永遠在 SortableContext.items 集合,跟 hook instance mount 狀態無關)。
1267
+ // (DndContext store active id 追蹤,跟 hook instance mount 狀態無關;v15 無 SortableContext)。
1266
1268
  // 對齊 dnd-kit GitHub #1674 + drag-overlay docs canonical「virtualized list MUST use DragOverlay」。
1267
1269
  // overscan 仍輕微拉高(避免 source row 旁邊 rows 也 unmount 致使 hover signal 計算抖動)。
1268
1270
  const effectiveOverscan = enableRowDrag ? Math.max(overscan, 5) : overscan
@@ -1392,10 +1394,9 @@ function DataTableInner<TData>(
1392
1394
 
1393
1395
  // ── Phase 9 Issue 1 fix(2026-05-10):range cells lifted compute + Set ────
1394
1396
  // 計算 spreadsheet range cell IDs(Shift+click rectangle from anchor↔focus),
1395
- // 提供:
1396
- // 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,內容才不被蓋)
1397
+ // 提供 `rangeCellIdSet` Set → cell wrapper data-range-cell attr for cell-bg fill
1398
+ // (per codex Q1 verdict:bg fill cell bg layer 不在 overlay,內容才不被蓋;
1399
+ // layer outer ring / rangeCellIds prop retire — 2026-07-14 對齊清理)
1399
1400
  const rangeCellIds = React.useMemo<string[] | undefined>(() => {
1400
1401
  if (!spreadsheetMode || !rangeAnchor || !rangeFocus || rangeAnchor === rangeFocus) return undefined
1401
1402
  const parseCell = (id: string) => {
@@ -1452,7 +1453,13 @@ function DataTableInner<TData>(
1452
1453
  return () => obs.disconnect()
1453
1454
  }, [hasLeft, hasRight, rows.length])
1454
1455
 
1455
- const rowHeight = `h-table-row-${size}`
1456
+ // 2026-07-09 root-cause fix(user 以 GitHub Pages 對比抓出 regression):
1457
+ // 舊 `h-table-row-${size}` 模板字串 Tailwind **靜態掃描看不到** → `.h-table-row-{sm,md,lg}` 規則
1458
+ // 唯一靠 uiSize.spec.md 裡的 literal 被 content-detection 掃到才生成;戰役期間掃描樹變動後未生成
1459
+ // → 規則消失 → row 塌成「內容高度」(非編輯 33px / 編輯 44px)而非固定 token 40px,連帶選取控件與
1460
+ // 列文字對不齊。改用 literal map(對齊 field-wrapper cva 的 `h-field-md` literal 慣例),Tailwind
1461
+ // 永遠掃得到、不再依賴脆弱的 spec.md literal → 永不再漂移。
1462
+ const rowHeight = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size] ?? 'h-table-row-md'
1456
1463
 
1457
1464
  // ── Cross-region row hover (2026-04-22 D3 perf audit):event delegation 改 per-row closure
1458
1465
  // 舊:每 row 建 `{ onMouseEnter, onMouseLeave }` + 2 arrow functions → 100 row = 200 closures/render
@@ -1573,8 +1580,8 @@ function DataTableInner<TData>(
1573
1580
  const dragDisabled = sorting.length > 0
1574
1581
 
1575
1582
  // ── L4 Row drag v2:nested rows + parent map ─────────────────────────────────
1576
- // v2 cross-parent fix:全 row SortableContext.items(含 sub-rows),custom collisionDetection
1577
- // 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
1583
+ // v2 cross-parent fix:全 row 各自掛 useDraggable/useDroppable(含 sub-rows;v15 無 SortableContext),
1584
+ // custom collisionDetection 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
1578
1585
  // parentMap: rowId → parentId(top-level row 的 parent = '' 哨兵 string)
1579
1586
  const { allRowIds, parentMap } = React.useMemo(() => {
1580
1587
  const ids: string[] = []
@@ -1725,7 +1732,13 @@ function DataTableInner<TData>(
1725
1732
  const canExpand = cell.row.getCanExpand?.() ?? false
1726
1733
  const isExpanded = cell.row.getIsExpanded?.() ?? false
1727
1734
  const toggleExpand = cell.row.getToggleExpandedHandler?.()
1728
- const showNestedPrefix = isFirstContent && (depth > 0 || canExpand)
1735
+ // 2026-07-08 sibling-aware 佔位(WM root-cause 戰役):spec:382「同層 sibling expandable
1736
+ // 時 leaf 也佔位」原本沒實作 — depth-0 leaf(無 children 的頂層列)拿不到 w-4+mr-2 佔位,
1737
+ // 與同層有 chevron 的列左緣錯位(PDF「chevron 空間」問題)。同層 = 同 parent 的 subRows;
1738
+ // 頂層 = core rows。只在 isFirstContent 時計算,成本一列一次。
1739
+ const siblingRows = cell.row.getParentRow?.()?.subRows ?? table.getCoreRowModel().rows
1740
+ const siblingHasExpand = isFirstContent && siblingRows.some((r) => r.getCanExpand?.() ?? false)
1741
+ const showNestedPrefix = isFirstContent && (depth > 0 || canExpand || siblingHasExpand)
1729
1742
  // Issue 9 cell error(2026-05-10):lookup `${rowId}:${colId}` in cellErrors map
1730
1743
  // editing cell 自動 clear visual error(per spec 「edit-clears-own-cell」)— consumer 走
1731
1744
  // onCellCommit 驗證後決定回填新 error(由 consumer 端控制 cellErrors map state)。
@@ -1802,6 +1815,9 @@ function DataTableInner<TData>(
1802
1815
  // 跟 cell 4 邊 inset divider 視覺相疊(同 pixel)= 1 line visual,不雙線。
1803
1816
  inlineEdit && 'dtCellGrid',
1804
1817
  onEditableCellClick && ['cursor-pointer', nakedCellEditableDisplayHover], // editable cell display hover affordance(對齊 Notion / Airtable hover-cell-shows-border canonical)
1818
+ // a11y(2026-07-14 dim-10 修):非 spreadsheet inlineEdit cell 可 Tab 聚焦(見下方
1819
+ // tabIndex/onKeyDown)— focus-visible ring 對齊本檔 expand button / sortable header canonical。
1820
+ onEditableCellClick && !spreadsheetMode && 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',
1805
1821
  // 2026-05-13 Q3 cell disabled SSOT(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):
1806
1822
  // bg `--bg-disabled` component-state token(color.spec.md:671 owner)+ cursor 抑制 click affordance。
1807
1823
  cellDisabled && 'bg-disabled cursor-not-allowed',
@@ -1818,6 +1834,19 @@ function DataTableInner<TData>(
1818
1834
  ...(experimentalSpreadsheetOverlay && { '--cell-hover-outline-color': 'transparent' } as React.CSSProperties),
1819
1835
  }}
1820
1836
  onClick={onEditableCellClick}
1837
+ // a11y(2026-07-14 dim-10 修):非 spreadsheet 的 inlineEdit cell 原本只有 onClick —
1838
+ // 鍵盤 user 無法聚焦 cell、無法進入編輯(WCAG 2.1.1)。對齊 Atlassian InlineEdit
1839
+ // read-view-focusable idiom:editable display cell 可 Tab 聚焦,Enter / F2 進 edit。
1840
+ // spreadsheetMode 不加(該模式走 table-level selectedCellId 鍵盤導覽 SSOT,per-cell
1841
+ // tab stop 會跟 roving 模型衝突);cell 內 embedded 控件事件不攔(target guard)。
1842
+ tabIndex={onEditableCellClick && !spreadsheetMode ? 0 : undefined}
1843
+ onKeyDown={onEditableCellClick && !spreadsheetMode ? (e) => {
1844
+ if (e.target !== e.currentTarget) return
1845
+ if (e.key === 'Enter' || e.key === 'F2') {
1846
+ e.preventDefault()
1847
+ setEditingCellId(cellEditId(cellRowId, cellColId))
1848
+ }
1849
+ } : undefined}
1821
1850
  >
1822
1851
  {/* Issue 9 cell error(2026-05-10):有 error → cell 內外結構切 flex-col,
1823
1852
  上 row 渲既有 nested + content,下 row 渲 error message 14px text-error。
@@ -2009,11 +2038,20 @@ function DataTableInner<TData>(
2009
2038
  // Phase B3 IME guard(2026-05-10 per codex Q-B3):中文輸入法組字中 ignore 所有 nav keys。
2010
2039
  // 2026-05-16 Round 5 audit Dim 27 fix:`keyCode` deprecated but still in KeyboardEvent type — no cast needed。
2011
2040
  if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return
2041
+ // 2026-07-14 dim-10 修:spreadsheet 分支排除 descendant 互動控件 — 焦點在 cell 內
2042
+ // action button / link / input 時,Enter 應 activate 該控件、方向鍵交還控件,
2043
+ // 原 handler 會 preventDefault 取消按鈕 activation、拿舊 selectedCellId 導覽。
2044
+ // 對齊下方 row-selection 分支 2026-07-09 既有 input-family guard + AG Grid
2045
+ // embedded-control convention(cell renderer 內控件 own keyboard)。
2046
+ const spreadsheetKbTarget = e.target as HTMLElement | null
2047
+ const targetIsEmbeddedControl = !!spreadsheetKbTarget?.closest?.(
2048
+ 'button, a[href], input, select, textarea, [contenteditable="true"]',
2049
+ )
2012
2050
  // 2026-07-05 D4 fix:spreadsheet 鍵盤入口 — selection 尚未建立時按方向鍵,seed 第一個
2013
2051
  // visible cell(原本唯一 set 起點是 mouse click → 鍵盤-only 使用者 Tab 進 table 後方向鍵
2014
2052
  // 全 no-op,整個 spreadsheet 導覽被滑鼠 gate,違反 spec「鍵盤完整可操作」驗證宣稱。
2015
2053
  // 對齊 Excel / Google Sheets / AG Grid「focus grid → first cell active」canonical)。
2016
- if (spreadsheetMode && selectedCellId == null && editingCellId == null
2054
+ if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId == null && editingCellId == null
2017
2055
  && ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
2018
2056
  const allRows = table.getRowModel().rows.map((r) => r.id)
2019
2057
  const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)
@@ -2026,7 +2064,7 @@ function DataTableInner<TData>(
2026
2064
  }
2027
2065
  return
2028
2066
  }
2029
- if (spreadsheetMode && selectedCellId != null && editingCellId == null) {
2067
+ if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId != null && editingCellId == null) {
2030
2068
  const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Enter', 'F2', 'Escape']
2031
2069
  if (!navKeys.includes(e.key)) return
2032
2070
  const lastColon = selectedCellId.lastIndexOf(':')
@@ -2077,6 +2115,14 @@ function DataTableInner<TData>(
2077
2115
  }
2078
2116
  // ── Row selection mode keyboard handler(下方既有)──
2079
2117
  if (!enabled) return
2118
+ // 2026-07-09 fix(圖一 Ctrl+A bug):焦點在可編輯輸入元素(cell edit / inline edit / 搜尋框)時,
2119
+ // 鍵盤(Cmd/Ctrl+A 全選、Esc)應交給該元素(全選 cell 文字 / 取消編輯),**不**攔成 row selection。
2120
+ // 對齊 Notion / Airtable / Linear:編輯格內 Ctrl+A = 選格內文字,非選全表列。
2121
+ const kbTarget = e.target as HTMLElement | null
2122
+ if (
2123
+ editingCellId != null ||
2124
+ (kbTarget && (kbTarget.tagName === 'INPUT' || kbTarget.tagName === 'TEXTAREA' || kbTarget.tagName === 'SELECT' || kbTarget.isContentEditable))
2125
+ ) return
2080
2126
  // Cmd/Ctrl+A:選全可見(扣 disabled)— 對齊 Mail / GitHub / Linear 慣例
2081
2127
  if ((e.metaKey || e.ctrlKey) && e.key === 'a' && mode === 'multi') {
2082
2128
  e.preventDefault()
@@ -2367,7 +2413,7 @@ function DataTableInner<TData>(
2367
2413
  const meta = h.column.columnDef.meta as { locked?: boolean } | undefined
2368
2414
  const isLocked = meta?.locked === true
2369
2415
  const isSystem = isSystemColumn(colId)
2370
- // useSortable per header(Rules of Hooks compliant — same hook count per render
2416
+ // useDraggable + useDroppable per header(Rules of Hooks compliant — same hook count per render
2371
2417
  // as long as headers count consistent;column reorder/hide 整 row reflow 自然觸發 React reconcile)。
2372
2418
  // disabled=true 時仍 call hook 不啟動 listeners。
2373
2419
  const isDraggable = enableColumnReorder && !isLocked && !isSystem
@@ -2417,13 +2463,13 @@ function DataTableInner<TData>(
2417
2463
  const isPrimaryRegion = isCenter
2418
2464
  const regionRole: 'primary' | 'mirror' = isPrimaryRegion ? 'primary' : 'mirror'
2419
2465
 
2420
- // code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞 SortableContext / dnd-kit hooks 跟 row idx 的 stable binding
2466
+ // code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞 dnd-kit hooks 跟 row idx 的 stable binding
2421
2467
  const rowEl = (row: typeof rows[number], idx: number, opts?: { virtual?: boolean; start?: number; isLast?: boolean }) => {
2422
2468
  const showBorder = bordered !== false ? !opts?.isLast : true
2423
- // L4 row drag v2:nested rows 也 sortable(配合 cross-parent collisionDetection 過濾)
2424
- // sub-rows: depth>0 仍進 SortableContext,但 collisionDetection 只接受 same-parent over
2469
+ // L4 row drag v2:nested rows 也可拖(配合 cross-parent collisionDetection 過濾)
2470
+ // sub-rows: depth>0 也各自掛 useDraggable/useDroppable,但 collisionDetection 只接受 same-parent over
2425
2471
  const isThisRowDragging = enableRowDrag && activeDragId === row.id
2426
- const useSortableWrap = enableRowDrag
2472
+ const dragRowWrap = enableRowDrag
2427
2473
 
2428
2474
  // H1 fix(2026-05-10,per user 確認):per-row autoRowHeight when any cell in this row has
2429
2475
  // error。Fixed-height row 模式下,該 row 的任一 cell 有 error msg → THAT row 自動 auto-height
@@ -2525,20 +2571,20 @@ function DataTableInner<TData>(
2525
2571
  </div>
2526
2572
  )
2527
2573
 
2528
- if (useSortableWrap) {
2574
+ if (dragRowWrap) {
2529
2575
  // 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
2576
+ // code-quality-allow: long-function — 此 const 之下的整個 if-block 含 dnd-kit hooks + SortableRowProvider + baseRowDiv composition;audit 把 const 誤認為 function entry,實 long body 在 closure 內 dnd-kit + per-row state 多 capture,拆會破壞 hook order invariant
2531
2577
  const rowInvalidDrop = isThisRowDragging && invalidDropActive
2532
2578
  return (
2533
2579
  <SortableRowProvider key={row.id} id={row.id} disabled={dragDisabled} role={regionRole} invalidDrop={rowInvalidDrop}>
2534
2580
  {(ctx) => baseRowDiv({
2535
- // mirror 也掛 setNodeRef dnd-kit 內部以 hook instance 為單元,
2536
- // instance id 時,measurement 走最後 mount 的;不影響 transform 一致性
2581
+ // primary useDraggable+useDroppable 合成 ref;mirror 只掛 useDroppable ref
2582
+ // (v15.4 split mirror 不進 drag source store,isDragging useDndContext 同步)
2537
2583
  ref: ctx.setNodeRef,
2538
2584
  style: ctx.style,
2539
2585
  isDragging: ctx.isDragging,
2540
- // v15.2 整列可拖:listeners + attributes spread row div 上(只 primary,
2541
- // mirror region listeners 避免 a11y 重複 announce / pointer 雙觸發)
2586
+ // v15.6 button-only:rowListeners undefined(activator = RowDragHandle Button),
2587
+ // baseRowDiv spread `{...(extra?.listeners ?? {})}` 自動 noop;attributes 留空 = row 純 container
2542
2588
  listeners: ctx.rowListeners,
2543
2589
  attributes: ctx.rowAttributes,
2544
2590
  })}
@@ -2619,10 +2665,10 @@ function DataTableInner<TData>(
2619
2665
  )}
2620
2666
  {/* Header 的 center 區保持 overflow-hidden(非 scroll)—— body 的 center 才有 scroll,
2621
2667
  header 靠 JS 同步 scrollLeft(見 onCenterBodyScroll)。這樣不會出現雙 scrollbar。
2622
- 為了對齊 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),刻意不設 */}
2668
+ V scrollbar 對齊:centerBody **刻意不用** `scrollbar-gutter: stable`(決策見 centerBody
2669
+ className 註解 永久預留 15px 會讓 content-fit 看起來像恆有 V 捲軸);trade-off =
2670
+ V scroll 出現時 body 內側少 ~15px、header 不縮 → 右端微 misalign,content-fit 乾淨優先。
2671
+ header 的 `scrollbar-gutter` 本就無效(overflow-hidden),刻意不設 */}
2626
2672
  <div
2627
2673
  ref={centerHeaderRef}
2628
2674
  data-datatable-header-panel="center"
@@ -2670,8 +2716,6 @@ function DataTableInner<TData>(
2670
2716
  <div
2671
2717
  ref={centerBodyRef}
2672
2718
  // Center body 同時擁有 H + V scroll;maxHeight 限制讓 H scrollbar 落在 visible 底部
2673
- // `scrollbar-gutter: stable` 永遠預留 V scrollbar 寬度(~15-17px),避免 body 出現 V
2674
- // scrollbar 時右端被縮,跟 header 右端產生 gap(Windows/Linux native scrollbar 吃寬)
2675
2719
  data-datatable-hscroll
2676
2720
  data-datatable-panel="center"
2677
2721
  // overflow-x/y: auto — 沒 overflow 就不顯 bar。wrapper minWidth 仍 trigger H 真 overflow。
@@ -2837,13 +2881,12 @@ function DataTableInner<TData>(
2837
2881
  </div>
2838
2882
  )
2839
2883
  } : undefined}
2840
- // Slice D Step 4 spreadsheet semantics(2026-05-10):
2841
- // selectedCellId(click 1)= solid border 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)
2884
+ // Slice D Step 4 spreadsheet semantics(2026-05-10;2026-07-14 對齊清理):
2885
+ // selectedCellId(click 1)= solid border SelectionRing z 2
2886
+ // range(Shift+click rectangle from anchor↔focus)= cell-bg fill via
2887
+ // CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫 range 視覺,
2888
+ // RangeOuterRing / rangeCellIds prop 已 retire)
2845
2889
  selectedCellId={spreadsheetMode ? selectedCellId : null}
2846
- rangeCellIds={rangeCellIds}
2847
2890
  cellClickEntersEdit={(cellId) => {
2848
2891
  // 2026-05-10 codex review red light fix(per dual-track verify):
2849
2892
  // 1. cellId parse 用 lastIndexOf(':')(row id 可含 colon)
@@ -2872,14 +2915,14 @@ function DataTableInner<TData>(
2872
2915
 
2873
2916
  // ── L4 Row drag DnD wrapper ───────────────────────────────────────────────
2874
2917
  // Sensors:Pointer(8px activation distance,避免 cell click 誤觸 drag)+ Keyboard(a11y)
2875
- // SortableContext items:**只 top-level row id**(nested sub-rows 不在 sortable 集合);
2876
- // 同 parent level 限制由「sub-rows 不在 items 內」自然成立。
2918
+ // v15.0 Path B:無 SortableContext row 各自 useDraggable / useDroppable;
2919
+ // 同 parent level 限制由自訂 collisionDetection 過濾 cross-parent target 成立(cross-parent over → invalidDrop)。
2877
2920
  // DragEnd:active.id / over.id → 算 position(active vs over 視覺位置),呼叫 onRowReorder。
2878
2921
  // hooks 必呼叫(rules-of-hooks)— 即使 enableRowDrag=false 也走 useSensors;wrap 才條件化。
2879
2922
  // **codex P1 fix(2026-05-07 v15.13)**:KeyboardSensor 不傳 `coordinateGetter`,用
2880
2923
  // dnd-kit 預設 25px 箭頭 stepping。`sortableKeyboardCoordinates` 是 `@dnd-kit/sortable`
2881
2924
  // preset,需 `<SortableContext>` 才正確 resolve 下一個 sortable target — 但 v15.0
2882
- // path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(line 21),
2925
+ // path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(見檔頭 import 註解),
2883
2926
  // 此 getter 在無 context 下 keyboard nav 無法 reliable resolve target → keyboard
2884
2927
  // drag/reorder regression。Default getter(arrow-key Δ25px)在 useDraggable 場景是
2885
2928
  // dnd-kit canonical(`@dnd-kit/core/src/sensors/keyboard/defaults.ts` 預設行為)。
@@ -3157,7 +3200,7 @@ function DataTableInner<TData>(
3157
3200
  // ── L5 分頁列(2026-07-06,詳 data-table.spec.md「L5:分頁」段)────────────────
3158
3201
  // 間距 tight = layoutSpace spec 規則 3「跨範疇 functional 交互」;頁碼靠右(shadcn justify-end /
3159
3202
  // Ant Table bottomEnd / MUI / Carbon 4 家實證,左側空也靠右);「共 N 筆」數源 = filter 後全集
3160
- // getPrePaginationRowModel(≠ selection all-mode 的 totalCount prop,語意不同)。
3203
+ // getPrePaginationRowModel(≠ selection all-mode 的 server-side 全集數 M — consumer 自持,語意不同)。
3161
3204
  // 2026-07-06 user 拍板:「Pagination 元件本身提供完整功能(showTotal / 每頁筆數)= SSOT,
3162
3205
  // Table 按一致定義套用」—— 分頁列的資訊/選單/「資訊左、操作右」layout 全部 own 在
3163
3206
  // <Pagination> 完整形態;DataTable 只轉發 config + own TanStack state(controlled 消費:
@@ -3,3 +3,6 @@
3
3
  // import { ... } from '@qijenchen/design-system/{components,patterns}/<Dir>'
4
4
  // Regenerate: node scripts/gen-component-indexes.mjs
5
5
  export * from './data-table'
6
+ export * from './data-table-column-visibility-panel'
7
+ export * from './data-table-filter-panel'
8
+ export * from './data-table-sort-manager'
@@ -38,7 +38,7 @@ interface PartSpec {
38
38
  const PARTS: Record<PartKey, PartSpec> = {
39
39
  caption: { label: '月份標題', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'text-body font-medium' },
40
40
  nav: { label: 'Nav 按鈕', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'Button variant=text size=xs iconOnly · hover 藍圈' },
41
- weekday: { label: '星期標頭', bg: 'transparent', text: '--foreground', border: 'transparent', extra: 'text-body font-medium · h-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 定位
@@ -211,7 +211,7 @@ export const Overview = {
211
211
  <span className="rounded px-2 py-1 text-[11px] font-mono border border-dashed"
212
212
  style={{ borderColor: 'var(--success)', backgroundColor: 'var(--success-subtle)', color: 'var(--success)' }}>formatted text (flex-1)</span>
213
213
  </div>
214
- <span className="text-[10px] text-fg-muted font-mono">Intl.DateTimeFormat · null 顯示 (em dash)</span>
214
+ <span className="text-[10px] text-fg-muted font-mono">Intl.DateTimeFormat · null 顯示 - (hyphen)</span>
215
215
  </div>
216
216
  </div>
217
217
  </div>
@@ -416,8 +416,8 @@ const InspectorInner = () => {
416
416
  )}
417
417
  {!isEdit && mode === 'readonly' && !value && (
418
418
  <PropRow label="Empty">
419
- <TokenValue value="--fg-muted" />
420
- <span className="text-[10px] text-fg-muted ml-1">em dash —</span>
419
+ <TokenValue value="--foreground" />
420
+ <span className="text-[10px] text-fg-muted ml-1">hyphen -</span>
421
421
  </PropRow>
422
422
  )}
423
423
  </div>
@@ -750,7 +750,7 @@ export const StateBehavior = {
750
750
 
751
751
  {/* Empty value display */}
752
752
  <div className="flex flex-col gap-4">
753
- <span className="text-caption font-medium text-fg-secondary">空值 — 統一 em dash(—)+ fg-muted</span>
753
+ <span className="text-caption font-medium text-fg-secondary">空值 — 統一半形 hyphen(-)+ foreground</span>
754
754
  <div className="flex flex-col gap-3">
755
755
  <div className="flex items-center gap-3">
756
756
  <span className="text-[11px] text-fg-muted w-20 shrink-0">readonly</span>
@@ -939,11 +939,11 @@ export const Accessibility = {
939
939
  </ul>
940
940
  </section>
941
941
  <section>
942
- <h3 className="text-body font-bold mb-2">鍵盤(Radix Popover + react-day-picker v9 內建)</h3>
942
+ <h3 className="text-body font-bold mb-2">鍵盤</h3>
943
943
  <ul className="list-disc list-inside text-caption text-fg-secondary space-y-1">
944
- <li>Trigger:<kbd>Space</kbd> / <kbd>Enter</kbd> popover</li>
945
- <li>Popover 開啟:<kbd>Esc</kbd> 關閉 + focus return to trigger</li>
946
- <li>DateGrid:<kbd>←</kbd> <kbd>→</kbd> 切日 / <kbd>PgUp</kbd> <kbd>PgDn</kbd> 切月 / <kbd>Home</kbd> <kbd>End</kbd> 行首尾</li>
944
+ <li>Trigger 開 popover(<kbd>Space</kbd> / <kbd>Enter</kbd>):單一 DatePicker 的 <code>{`<div role="combobox">`}</code> 無 native Enter/Space→click,由元件<strong>自建 <code>onKeyDown</code></strong> 補開(date-picker.tsx:554;Radix PopoverTrigger 只 compose onClick)。Range 雙 trigger 為 native <code>{`<button>`}</code> onClick 開啟(同非 Radix Popover 內建)</li>
945
+ <li>Popover 開啟 <kbd>Esc</kbd> 關閉 + 回焦:單一 DatePicker 用 PopoverTrigger → Radix <strong>內建</strong> <code>triggerRef.focus()</code> 回焦;Range 只有 PopoverAnchor(triggerRef 恆 null,內建回焦為 no-op),改由元件<strong>自建 <code>onCloseAutoFocus</code></strong> 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)</li>
946
+ <li>DateGrid(react-day-picker v9 內建):<kbd>←</kbd> <kbd>→</kbd> 切日 / <kbd>PgUp</kbd> <kbd>PgDn</kbd> 切月 / <kbd>Home</kbd> <kbd>End</kbd> 行首尾</li>
947
947
  <li>showTime:<kbd>Tab</kbd> 從 calendar 跳到右側 time panel,各 column <kbd>↑</kbd> <kbd>↓</kbd> 切 option</li>
948
948
  </ul>
949
949
  </section>
@@ -67,7 +67,7 @@ export const UsageGuidance: Story = {
67
67
 
68
68
  <Rule
69
69
  title="❌ 不用其他 calendar library 平行實作"
70
- note="未來若需要 Date Range / DateTime,擴充本 DateGrid(`../DateGrid/date-grid.tsx`)而非引入第二個 library——避免兩套視覺語言在同一系統並存"
70
+ note="Date Range / DateTime 已內建(DatePicker.Range / showTime,見下方近親規則)且都基於本 DateGrid(`../DateGrid/date-grid.tsx`);未來任何日曆類擴充也走 DateGrid,而非引入第二個 library——避免兩套視覺語言在同一系統並存"
71
71
  >
72
72
  <Label>實作細節見 Design System / Components / DatePicker / 設計規格</Label>
73
73
  </Rule>
@@ -169,8 +169,8 @@ export const FormattingRule: Story = {
169
169
  </Rule>
170
170
 
171
171
  <Rule
172
- title="null 值統一顯示 em dash"
173
- note="Display 模式 null / undefined 顯示 (fg-muted),與其他 Field 元件一致"
172
+ title="null 值統一顯示半形連字號"
173
+ note="Display 模式 null / undefined 顯示半形 -(foreground,同 readonly value 色),與其他 Field 元件一致"
174
174
  >
175
175
  <DatePicker mode="readonly" value={null} />
176
176
  </Rule>
@@ -267,7 +267,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
267
267
  `clearable` prop 在有值時顯示 clear 按鈕(endAction)。
268
268
 
269
269
  - 只在 edit 模式顯示
270
- - 清除後 value 變為 `null`(Display 顯示 —)
270
+ - 清除後 value 變為 `null`(Display 顯示半形 -,text-foreground)
271
271
  - **Dual-state sync canonical**(2026-05-03 v10):X 點擊必同時 `onChange?.('')` + `setDraft(null)`(Range 同),否則 `needConfirm=true`(showTime 預設)且 popover 開著時 `displayValue=draft` 仍顯示舊值,trigger 看起來「沒清」。X 在 trigger 上是 standard clear affordance,不走 needConfirm「等確定」語義 — 立刻 commit + 同步 draft
272
272
 
273
273
  ---
@@ -295,7 +295,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
295
295
  - Trigger:`role="combobox"` + `aria-haspopup="dialog"` + `aria-expanded={open}` + 必含 accessible name(`aria-label` / 或外層 `<label>` / 或 fieldCtx label)
296
296
  - Popover content:`role="dialog"`;單一日期 popover 不重覆 `aria-label`(由 trigger 的 `role="combobox"` accessible name 標示),Range popover 加 `aria-label="日期區間選擇"`
297
297
  - DateGrid 鍵盤:Arrow keys 切日 / PageUp/Down 切月 / Home/End 行首尾(react-day-picker v9 內建)
298
- - Trigger 鍵盤:Space / Enter open;Esc close + focus return to trigger(Radix Popover 內建)
298
+ - Trigger 鍵盤(Space / Enter open;Esc close + 回焦):單一 DatePicker `<div role="combobox">` 無 native Enter/Space→click,由元件**自建 `onKeyDown`** 開 popover(Radix PopoverTrigger 只 compose onClick;date-picker.tsx:554),Esc 關閉後靠 PopoverTrigger 的 Radix **內建** `triggerRef.focus()` 回焦;Range 用 native `<button>` onClick 開、只掛 PopoverAnchor(triggerRef 恆 null → 內建回焦 no-op),改由**自建 `onCloseAutoFocus`** 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)
299
299
  - Range 雙 trigger:`activeEnd` state 指向當前編輯端,`aria-expanded` 對應只當該 trigger active 時 true
300
300
 
301
301
  ---
@@ -317,7 +317,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
317
317
  - **Invalid date input**:Field validation 處理 `aria-invalid="true"` + error border + 下方 error message;DatePicker 本身不 own validation 規則。
318
318
  - **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(Display / Edit / typeable / Range 雙 input 皆同)。
319
319
  - **RTL**:未實作方向鏡像(trigger / Range 雙 input / DateGrid 皆以 LTR physical 方向設計);RTL 屬 DS-wide 決策,未定(與 Chip / Breadcrumb 同口徑)。
320
- - **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell 尺寸固定不隨 density 漂移(date grid 為密度敏感不可變區)。
320
+ - **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell 尺寸 density-aware(消費 `--field-height-sm`:md=28×28 / lg=32×32,對齊 L128 + `date-grid.spec.md:120`),隨 density 縮放而非固定。
321
321
 
322
322
  ---
323
323
 
@@ -136,7 +136,7 @@ export const RangePicker: Story = {
136
136
  return (
137
137
  <div className="flex flex-col gap-4 max-w-md">
138
138
  <p className="text-caption text-fg-muted">
139
- 雙 input + 中間箭頭。點 start input 開 popover + activeEnd='start';點 end input 同理。Auto-advance:選完 start 自動切 end。clearable=true → trigger 顯示 X 清空按鈕。
139
+ 兩個輸入框加中間箭頭:點開始欄開月曆選起日,選完自動跳到結束欄選迄日;有值時右側出現清除鈕。
140
140
  </p>
141
141
  <DatePicker.Range value={range} onChange={setRange} clearable />
142
142
  <p className="text-caption text-fg-muted">
@@ -160,7 +160,7 @@ export const WithError: Story = {
160
160
  render: () => (
161
161
  <div className="flex flex-col gap-4 max-w-xs">
162
162
  <p className="text-caption text-fg-muted">
163
- error=true 時 trigger border 切 error palette,hover/focus 同步切 error-hover。
163
+ 驗證失敗時外框轉紅色,滑過或聚焦時同步用較深的紅。
164
164
  </p>
165
165
  <DatePicker error value="2026-04-02" onChange={() => {}} />
166
166
  <DatePicker error value={null} onChange={() => {}} placeholder="必填日期" />
@@ -226,7 +226,7 @@ export const ShowTimePopoverOpen: Story = {
226
226
  /* ── OpenSnapshot:needConfirm date-only(2026-07-05 D4 修 footer gate 死路)── */
227
227
  export const NeedConfirmDateOnlyOpen: Story = {
228
228
  name: 'needConfirm:合約生效日確認',
229
- parameters: { docs: { description: { story: 'date-only + needConfirm:點日期只暫存 draft(trigger 即時顯示),footer「確定」才 commit onChange——footer 渲染 gate = showTime || needConfirm(2026-07-05 D4 修 single 漏 || needConfirm 時「點了日期什麼都不會發生」的死路)。適用選錯成本高的日期(合約生效日 / 帳單結算起算日)。Visual-audit OpenSnapshot verify date-only popover 有渲 footer(此刻 / 確定)。' } } },
229
+ parameters: { docs: { description: { story: '需確認模式:選日期只會先暫存(輸入框即時顯示),要按下方「確定」才真正套用。適用選錯成本高的日期,例如合約生效日、帳單結算起算日。' } } },
230
230
  render: () => {
231
231
  const [effectiveDate, setEffectiveDate] = React.useState('2026-08-01')
232
232
  return (
@@ -297,8 +297,7 @@ export const ShowTimeRange: Story = {
297
297
  return (
298
298
  <div className="flex flex-col gap-4 max-w-lg">
299
299
  <p className="text-caption text-fg-muted">
300
- Range + showTime:點 start input → activeEnd='start' + TimeColumns 編 start 的時間;點 end input 同理。
301
- 兩端都填好 + 按確定才 commit(needConfirm=true 預設)。
300
+ 範圍 + 時間:點開始欄選起始日期與時間,點結束欄選結束的日期與時間;兩端都選好、按下方「確定」才會套用。
302
301
  </p>
303
302
  <DatePicker.Range
304
303
  showTime