@qijenchen/design-system 0.1.0-beta.61 → 0.1.0-beta.63

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 (507) hide show
  1. package/CLAUDE.md +6 -6
  2. package/dist/components/Accordion/accordion.d.ts +1 -1
  3. package/dist/components/Accordion/accordion.js +1 -1
  4. package/dist/components/Accordion/accordion.js.map +1 -1
  5. package/dist/components/Alert/alert.d.ts +2 -2
  6. package/dist/components/Alert/alert.js +4 -3
  7. package/dist/components/Alert/alert.js.map +1 -1
  8. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  9. package/dist/components/AppShell/app-shell.js +4 -3
  10. package/dist/components/AppShell/app-shell.js.map +1 -1
  11. package/dist/components/Avatar/avatar.d.ts +1 -1
  12. package/dist/components/Avatar/avatar.js +2 -1
  13. package/dist/components/Avatar/avatar.js.map +1 -1
  14. package/dist/components/Badge/badge.d.ts +1 -1
  15. package/dist/components/Badge/badge.js +2 -1
  16. package/dist/components/Badge/badge.js.map +1 -1
  17. package/dist/components/Breadcrumb/breadcrumb.d.ts +1 -1
  18. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  19. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  20. package/dist/components/Button/button.d.ts +5 -5
  21. package/dist/components/Button/button.d.ts.map +1 -1
  22. package/dist/components/Button/button.js +4 -3
  23. package/dist/components/Button/button.js.map +1 -1
  24. package/dist/components/Calendar/calendar.d.ts +1 -1
  25. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  26. package/dist/components/Calendar/calendar.js +80 -69
  27. package/dist/components/Calendar/calendar.js.map +1 -1
  28. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  29. package/dist/components/Carousel/carousel.js +5 -3
  30. package/dist/components/Carousel/carousel.js.map +1 -1
  31. package/dist/components/Checkbox/checkbox-group.d.ts +2 -1
  32. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
  33. package/dist/components/Checkbox/checkbox-group.js.map +1 -1
  34. package/dist/components/Checkbox/checkbox.d.ts +9 -3
  35. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  36. package/dist/components/Checkbox/checkbox.js +8 -3
  37. package/dist/components/Checkbox/checkbox.js.map +1 -1
  38. package/dist/components/Chip/chip.d.ts +2 -2
  39. package/dist/components/Chip/chip.js +3 -2
  40. package/dist/components/Chip/chip.js.map +1 -1
  41. package/dist/components/CircularProgress/circular-progress.d.ts +1 -1
  42. package/dist/components/CircularProgress/circular-progress.js +2 -1
  43. package/dist/components/CircularProgress/circular-progress.js.map +1 -1
  44. package/dist/components/Coachmark/coachmark.d.ts +4 -4
  45. package/dist/components/Coachmark/coachmark.js +2 -1
  46. package/dist/components/Coachmark/coachmark.js.map +1 -1
  47. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  48. package/dist/components/Combobox/combobox.js +17 -13
  49. package/dist/components/Combobox/combobox.js.map +1 -1
  50. package/dist/components/Command/command.d.ts +4 -0
  51. package/dist/components/Command/command.d.ts.map +1 -1
  52. package/dist/components/Command/command.js.map +1 -1
  53. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  54. package/dist/components/DataTable/data-table.js.map +1 -1
  55. package/dist/components/DateGrid/date-grid.d.ts +8 -4
  56. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  57. package/dist/components/DateGrid/date-grid.js +2 -2
  58. package/dist/components/DateGrid/date-grid.js.map +1 -1
  59. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  60. package/dist/components/DatePicker/date-picker.js +6 -4
  61. package/dist/components/DatePicker/date-picker.js.map +1 -1
  62. package/dist/components/DescriptionList/description-list.js +1 -1
  63. package/dist/components/DescriptionList/description-list.js.map +1 -1
  64. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  65. package/dist/components/Dialog/dialog.js.map +1 -1
  66. package/dist/components/DropdownMenu/dropdown-menu.d.ts +1 -1
  67. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  68. package/dist/components/DropdownMenu/dropdown-menu.js +0 -1
  69. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  70. package/dist/components/Empty/empty.d.ts +1 -1
  71. package/dist/components/Empty/empty.js.map +1 -1
  72. package/dist/components/Field/field-wrapper.js +1 -1
  73. package/dist/components/Field/field-wrapper.js.map +1 -1
  74. package/dist/components/Field/field.d.ts.map +1 -1
  75. package/dist/components/Field/field.js +1 -0
  76. package/dist/components/Field/field.js.map +1 -1
  77. package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -1
  78. package/dist/components/FieldControlGroup/field-control-group.js +1 -1
  79. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  80. package/dist/components/FileUpload/file-upload.d.ts +8 -1
  81. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  82. package/dist/components/FileUpload/file-upload.js +7 -3
  83. package/dist/components/FileUpload/file-upload.js.map +1 -1
  84. package/dist/components/FileViewer/file-viewer.d.ts +1 -1
  85. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  86. package/dist/components/FileViewer/file-viewer.js +25 -14
  87. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  88. package/dist/components/HoverCard/hover-card.d.ts +5 -1
  89. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  90. package/dist/components/HoverCard/hover-card.js +2 -1
  91. package/dist/components/HoverCard/hover-card.js.map +1 -1
  92. package/dist/components/Menu/menu-item.d.ts +6 -2
  93. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  94. package/dist/components/Menu/menu-item.js.map +1 -1
  95. package/dist/components/Notice/notice.d.ts +5 -1
  96. package/dist/components/Notice/notice.d.ts.map +1 -1
  97. package/dist/components/Notice/notice.js +2 -1
  98. package/dist/components/Notice/notice.js.map +1 -1
  99. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +4 -0
  100. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  101. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -2
  102. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  103. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  104. package/dist/components/PeoplePicker/people-picker.js +6 -2
  105. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  106. package/dist/components/Popover/popover.d.ts +1 -1
  107. package/dist/components/Popover/popover.js +2 -1
  108. package/dist/components/Popover/popover.js.map +1 -1
  109. package/dist/components/ProfileCard/profile-card.d.ts +9 -4
  110. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
  111. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  112. package/dist/components/RadioGroup/radio-group.d.ts +6 -0
  113. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  114. package/dist/components/RadioGroup/radio-group.js +4 -0
  115. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  116. package/dist/components/ScrollArea/scroll-area.js +1 -1
  117. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  118. package/dist/components/Select/select.d.ts.map +1 -1
  119. package/dist/components/Select/select.js +14 -4
  120. package/dist/components/Select/select.js.map +1 -1
  121. package/dist/components/SelectMenu/select-menu.d.ts +4 -0
  122. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  123. package/dist/components/SelectMenu/select-menu.js +6 -3
  124. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  125. package/dist/components/SelectionControl/selection-item.d.ts +5 -1
  126. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
  127. package/dist/components/SelectionControl/selection-item.js +3 -1
  128. package/dist/components/SelectionControl/selection-item.js.map +1 -1
  129. package/dist/components/Sheet/sheet.d.ts +6 -5
  130. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  131. package/dist/components/Sheet/sheet.js.map +1 -1
  132. package/dist/components/Sidebar/sidebar.d.ts +1 -1
  133. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  134. package/dist/components/Sidebar/sidebar.js +3 -2
  135. package/dist/components/Sidebar/sidebar.js.map +1 -1
  136. package/dist/components/Skeleton/skeleton.d.ts +1 -1
  137. package/dist/components/Skeleton/skeleton.js +2 -1
  138. package/dist/components/Skeleton/skeleton.js.map +1 -1
  139. package/dist/components/Slider/slider.d.ts +1 -1
  140. package/dist/components/Slider/slider.d.ts.map +1 -1
  141. package/dist/components/Slider/slider.js +7 -3
  142. package/dist/components/Slider/slider.js.map +1 -1
  143. package/dist/components/Steps/steps.d.ts +1 -1
  144. package/dist/components/Steps/steps.d.ts.map +1 -1
  145. package/dist/components/Steps/steps.js +9 -6
  146. package/dist/components/Steps/steps.js.map +1 -1
  147. package/dist/components/Switch/switch.d.ts +5 -5
  148. package/dist/components/Switch/switch.js +3 -3
  149. package/dist/components/Switch/switch.js.map +1 -1
  150. package/dist/components/Tabs/tabs.js +1 -1
  151. package/dist/components/Tabs/tabs.js.map +1 -1
  152. package/dist/components/Textarea/textarea.js +1 -1
  153. package/dist/components/Textarea/textarea.js.map +1 -1
  154. package/dist/components/TimePicker/time-columns.js +1 -1
  155. package/dist/components/TimePicker/time-columns.js.map +1 -1
  156. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  157. package/dist/components/TimePicker/time-picker.js +2 -1
  158. package/dist/components/TimePicker/time-picker.js.map +1 -1
  159. package/dist/components/Toast/toast.js.map +1 -1
  160. package/dist/components/Tooltip/tooltip.d.ts +1 -1
  161. package/dist/components/Tooltip/tooltip.js +2 -1
  162. package/dist/components/Tooltip/tooltip.js.map +1 -1
  163. package/dist/components/TreeView/tree-view.d.ts +4 -4
  164. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  165. package/dist/components/TreeView/tree-view.js +3 -3
  166. package/dist/components/TreeView/tree-view.js.map +1 -1
  167. package/dist/patterns/element-anatomy/item-anatomy.d.ts +3 -3
  168. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  169. package/dist/patterns/header-canonical/chrome-header.d.ts +3 -2
  170. package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -1
  171. package/dist/patterns/header-canonical/chrome-header.js.map +1 -1
  172. package/dist/patterns/overlay-surface/overlay-surface.d.ts +3 -2
  173. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  174. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  175. package/ds-canonical/hooks/_log-fire.sh +3 -1
  176. package/ds-canonical/hooks/check_audit_post_report_validator.sh +21 -1
  177. package/ds-canonical/hooks/check_audit_sample_escape.sh +6 -3
  178. package/ds-canonical/hooks/check_chrome_header_avatar_canonical.sh +8 -0
  179. package/ds-canonical/hooks/check_consumer_app_invariants.sh +321 -0
  180. package/ds-canonical/hooks/check_datatable_invariants.sh +75 -12
  181. package/ds-canonical/hooks/check_escape_marker_abuse.sh +15 -1
  182. package/ds-canonical/hooks/check_field_family_invariants.sh +12 -2
  183. package/ds-canonical/hooks/check_plugin_fork_health.sh +137 -0
  184. package/ds-canonical/hooks/check_propose_discipline.sh +147 -0
  185. package/ds-canonical/hooks/check_solo_workflow.sh +11 -1
  186. package/ds-canonical/hooks/check_story_invariants.sh +63 -9
  187. package/ds-canonical/hooks/check_storybook_addon_packaging.sh +151 -0
  188. package/ds-canonical/hooks/check_tailwind_wildcard_in_docs.sh +8 -2
  189. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +25 -4
  190. package/ds-canonical/hooks/lib/_token_hygiene.sh +9 -1
  191. package/ds-canonical/hooks/session_start_governance_check.sh +7 -2
  192. package/ds-canonical/hooks/stop_self_audit.sh +2 -2
  193. package/ds-canonical/hooks/tests/test_check_addon_subdir_ship.sh +3 -2
  194. package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +12 -0
  195. package/ds-canonical/hooks/tests/test_check_consumer_app_story_title.sh +3 -2
  196. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +6 -4
  197. package/ds-canonical/hooks/tests/test_check_consumer_no_ds_catalog.sh +7 -4
  198. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +6 -4
  199. package/ds-canonical/hooks/tests/test_check_data_table_size_num_to_meta_width.sh +3 -2
  200. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -2
  201. package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +9 -0
  202. package/ds-canonical/hooks/tests/test_check_propose_cite_required.sh +3 -2
  203. package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +10 -0
  204. package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +3 -2
  205. package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +10 -0
  206. package/ds-canonical/hooks/tests/test_check_storybook_addon_preset_cjs.sh +3 -2
  207. package/ds-canonical/references/build-ui-canonicals.md +2 -2
  208. package/ds-canonical/references/composition-fidelity.md +3 -3
  209. package/ds-canonical/references/naming-conventions.md +1 -0
  210. package/ds-canonical/references/ssot-consultation.md +1 -1
  211. package/ds-canonical/references/ssot-index.md +7 -7
  212. package/ds-canonical/rules/meta-patterns.md +5 -5
  213. package/ds-canonical/rules/self-verify.md +1 -1
  214. package/ds-canonical/rules/story-rules.md +2 -0
  215. package/ds-canonical/rules/ui-development.md +1 -1
  216. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +11 -2
  217. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +1 -1
  218. package/ds-canonical/skills/design-system-audit/SKILL.md +15 -15
  219. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +4 -3
  220. package/ds-story-manifest.json +15 -21
  221. package/llms-full.txt +9 -5
  222. package/llms.txt +2 -2
  223. package/package.json +1 -1
  224. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  225. package/src/components/Accordion/accordion.spec.md +22 -5
  226. package/src/components/Accordion/accordion.tsx +1 -1
  227. package/src/components/Alert/alert.anatomy.stories.tsx +4 -4
  228. package/src/components/Alert/alert.principles.stories.tsx +5 -5
  229. package/src/components/Alert/alert.spec.md +16 -11
  230. package/src/components/Alert/alert.stories.tsx +5 -5
  231. package/src/components/Alert/alert.tsx +2 -2
  232. package/src/components/AppShell/app-shell.principles.stories.tsx +68 -21
  233. package/src/components/AppShell/app-shell.spec.md +17 -24
  234. package/src/components/AppShell/app-shell.tsx +4 -3
  235. package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +3 -3
  236. package/src/components/AspectRatio/aspect-ratio.spec.md +15 -1
  237. package/src/components/Avatar/avatar.anatomy.stories.tsx +1 -1
  238. package/src/components/Avatar/avatar.principles.stories.tsx +8 -8
  239. package/src/components/Avatar/avatar.spec.md +25 -54
  240. package/src/components/Avatar/avatar.tsx +2 -2
  241. package/src/components/Badge/badge.principles.stories.tsx +2 -2
  242. package/src/components/Badge/badge.spec.md +22 -13
  243. package/src/components/Badge/badge.tsx +1 -1
  244. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +5 -2
  245. package/src/components/Breadcrumb/breadcrumb.spec.md +25 -25
  246. package/src/components/Breadcrumb/breadcrumb.stories.tsx +7 -32
  247. package/src/components/Breadcrumb/breadcrumb.tsx +1 -1
  248. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +2 -2
  249. package/src/components/BulkActionBar/bulk-action-bar.spec.md +20 -6
  250. package/src/components/BulkActionBar/bulk-action-bar.tsx +2 -2
  251. package/src/components/Button/button.anatomy.stories.tsx +2 -2
  252. package/src/components/Button/button.spec.md +19 -17
  253. package/src/components/Button/button.stories.tsx +1 -1
  254. package/src/components/Button/button.tsx +10 -9
  255. package/src/components/Calendar/calendar.anatomy.stories.tsx +1 -1
  256. package/src/components/Calendar/calendar.spec.md +37 -17
  257. package/src/components/Calendar/calendar.tsx +26 -22
  258. package/src/components/Carousel/carousel.anatomy.stories.tsx +6 -6
  259. package/src/components/Carousel/carousel.principles.stories.tsx +1 -1
  260. package/src/components/Carousel/carousel.spec.md +23 -3
  261. package/src/components/Carousel/carousel.tsx +19 -4
  262. package/src/components/Chart/chart.anatomy.stories.tsx +1 -1
  263. package/src/components/Chart/chart.spec.md +20 -1
  264. package/src/components/Checkbox/checkbox-group.tsx +2 -1
  265. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +4 -4
  266. package/src/components/Checkbox/checkbox.principles.stories.tsx +2 -2
  267. package/src/components/Checkbox/checkbox.spec.md +35 -15
  268. package/src/components/Checkbox/checkbox.stories.tsx +1 -1
  269. package/src/components/Checkbox/checkbox.tsx +14 -3
  270. package/src/components/Chip/chip.anatomy.stories.tsx +5 -5
  271. package/src/components/Chip/chip.principles.stories.tsx +9 -3
  272. package/src/components/Chip/chip.spec.md +8 -9
  273. package/src/components/Chip/chip.tsx +2 -2
  274. package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +6 -6
  275. package/src/components/CircularProgress/circular-progress.spec.md +10 -11
  276. package/src/components/CircularProgress/circular-progress.stories.tsx +36 -43
  277. package/src/components/CircularProgress/circular-progress.tsx +1 -1
  278. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +1 -1
  279. package/src/components/Coachmark/coachmark.principles.stories.tsx +14 -29
  280. package/src/components/Coachmark/coachmark.spec.md +21 -13
  281. package/src/components/Coachmark/coachmark.tsx +4 -4
  282. package/src/components/Combobox/combobox.anatomy.stories.tsx +28 -28
  283. package/src/components/Combobox/combobox.principles.stories.tsx +1 -1
  284. package/src/components/Combobox/combobox.spec.md +25 -7
  285. package/src/components/Combobox/combobox.tsx +12 -3
  286. package/src/components/Command/command.anatomy.stories.tsx +1 -1
  287. package/src/components/Command/command.principles.stories.tsx +8 -8
  288. package/src/components/Command/command.spec.md +18 -8
  289. package/src/components/Command/command.tsx +8 -3
  290. package/src/components/DataTable/data-table-sort-manager.tsx +1 -1
  291. package/src/components/DataTable/data-table.anatomy.stories.tsx +9 -7
  292. package/src/components/DataTable/data-table.principles.stories.tsx +3 -3
  293. package/src/components/DataTable/data-table.spec.md +15 -11
  294. package/src/components/DataTable/data-table.stories.tsx +58 -13
  295. package/src/components/DataTable/data-table.tsx +13 -0
  296. package/src/components/DataTable/filter-operators.spec.md +19 -27
  297. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +8 -8
  298. package/src/components/DateGrid/date-grid.principles.stories.tsx +7 -7
  299. package/src/components/DateGrid/date-grid.spec.md +17 -14
  300. package/src/components/DateGrid/date-grid.tsx +8 -4
  301. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +11 -15
  302. package/src/components/DatePicker/date-picker.principles.stories.tsx +8 -8
  303. package/src/components/DatePicker/date-picker.spec.md +40 -36
  304. package/src/components/DatePicker/date-picker.stories.tsx +23 -53
  305. package/src/components/DatePicker/date-picker.tsx +12 -6
  306. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +2 -2
  307. package/src/components/DescriptionList/description-list.principles.stories.tsx +4 -18
  308. package/src/components/DescriptionList/description-list.spec.md +9 -3
  309. package/src/components/DescriptionList/description-list.stories.tsx +2 -18
  310. package/src/components/DescriptionList/description-list.tsx +1 -1
  311. package/src/components/Dialog/dialog.principles.stories.tsx +1 -1
  312. package/src/components/Dialog/dialog.spec.md +26 -11
  313. package/src/components/Dialog/dialog.stories.tsx +159 -184
  314. package/src/components/Dialog/dialog.tsx +2 -1
  315. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +2 -2
  316. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +16 -17
  317. package/src/components/DropdownMenu/dropdown-menu.spec.md +10 -15
  318. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +13 -15
  319. package/src/components/DropdownMenu/dropdown-menu.tsx +12 -2
  320. package/src/components/Empty/empty.spec.md +19 -18
  321. package/src/components/Empty/empty.tsx +1 -1
  322. package/src/components/Field/field-controls.spec.md +52 -41
  323. package/src/components/Field/field-wrapper.tsx +2 -2
  324. package/src/components/Field/field.anatomy.stories.tsx +6 -5
  325. package/src/components/Field/field.principles.stories.tsx +8 -7
  326. package/src/components/Field/field.spec.md +42 -20
  327. package/src/components/Field/field.stories.tsx +9 -7
  328. package/src/components/Field/field.tsx +6 -3
  329. package/src/components/Field/form-validation.spec.md +20 -19
  330. package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +16 -15
  331. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +5 -1
  332. package/src/components/FieldControlGroup/field-control-group.spec.md +17 -1
  333. package/src/components/FieldControlGroup/field-control-group.stories.tsx +9 -9
  334. package/src/components/FieldControlGroup/field-control-group.tsx +4 -3
  335. package/src/components/FileItem/file-item.anatomy.stories.tsx +7 -17
  336. package/src/components/FileItem/file-item.principles.stories.tsx +7 -7
  337. package/src/components/FileItem/file-item.spec.md +24 -24
  338. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +4 -2
  339. package/src/components/FileUpload/file-upload.principles.stories.tsx +10 -12
  340. package/src/components/FileUpload/file-upload.spec.md +37 -8
  341. package/src/components/FileUpload/file-upload.tsx +5 -3
  342. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +16 -11
  343. package/src/components/FileViewer/file-viewer.principles.stories.tsx +4 -4
  344. package/src/components/FileViewer/file-viewer.spec.md +7 -19
  345. package/src/components/FileViewer/file-viewer.stories.tsx +3 -3
  346. package/src/components/FileViewer/file-viewer.tsx +42 -16
  347. package/src/components/HoverCard/hover-card.spec.md +20 -10
  348. package/src/components/HoverCard/hover-card.stories.tsx +1 -1
  349. package/src/components/HoverCard/hover-card.tsx +12 -1
  350. package/src/components/Input/input.anatomy.stories.tsx +4 -4
  351. package/src/components/Input/input.principles.stories.tsx +4 -31
  352. package/src/components/Input/input.spec.md +16 -4
  353. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  354. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  355. package/src/components/LinkInput/link-input.spec.md +14 -1
  356. package/src/components/Menu/menu-item.principles.stories.tsx +5 -5
  357. package/src/components/Menu/menu-item.spec.md +24 -12
  358. package/src/components/Menu/menu-item.tsx +7 -3
  359. package/src/components/Notice/notice.principles.stories.tsx +7 -7
  360. package/src/components/Notice/notice.spec.md +7 -5
  361. package/src/components/Notice/notice.tsx +5 -1
  362. package/src/components/NumberInput/number-input.anatomy.stories.tsx +4 -4
  363. package/src/components/NumberInput/number-input.principles.stories.tsx +13 -35
  364. package/src/components/NumberInput/number-input.spec.md +19 -0
  365. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +4 -3
  366. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +2 -5
  367. package/src/components/OverflowIndicator/overflow-indicator.spec.md +9 -1
  368. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +6 -42
  369. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -3
  370. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +11 -2
  371. package/src/components/PeoplePicker/people-picker.spec.md +26 -12
  372. package/src/components/PeoplePicker/people-picker.stories.tsx +14 -15
  373. package/src/components/PeoplePicker/people-picker.tsx +12 -4
  374. package/src/components/Popover/popover.spec.md +20 -11
  375. package/src/components/Popover/popover.tsx +2 -2
  376. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  377. package/src/components/ProfileCard/profile-card.principles.stories.tsx +29 -25
  378. package/src/components/ProfileCard/profile-card.spec.md +30 -10
  379. package/src/components/ProfileCard/profile-card.tsx +12 -7
  380. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +1 -1
  381. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +7 -5
  382. package/src/components/ProgressBar/progress-bar.spec.md +9 -1
  383. package/src/components/ProgressBar/progress-bar.stories.tsx +1 -1
  384. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +6 -3
  385. package/src/components/RadioGroup/radio-group.principles.stories.tsx +6 -13
  386. package/src/components/RadioGroup/radio-group.spec.md +7 -1
  387. package/src/components/RadioGroup/radio-group.tsx +10 -0
  388. package/src/components/Rating/rating.anatomy.stories.tsx +1 -0
  389. package/src/components/Rating/rating.principles.stories.tsx +9 -6
  390. package/src/components/Rating/rating.spec.md +13 -7
  391. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +44 -24
  392. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +51 -57
  393. package/src/components/ScrollArea/scroll-area.spec.md +5 -7
  394. package/src/components/ScrollArea/scroll-area.stories.tsx +110 -60
  395. package/src/components/ScrollArea/scroll-area.tsx +1 -1
  396. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
  397. package/src/components/SegmentedControl/segmented-control.spec.md +15 -14
  398. package/src/components/SegmentedControl/segmented-control.stories.tsx +1 -1
  399. package/src/components/Select/select.anatomy.stories.tsx +12 -11
  400. package/src/components/Select/select.principles.stories.tsx +3 -3
  401. package/src/components/Select/select.spec.md +34 -8
  402. package/src/components/Select/select.stories.tsx +2 -2
  403. package/src/components/Select/select.tsx +18 -3
  404. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +2 -2
  405. package/src/components/SelectMenu/select-menu.principles.stories.tsx +5 -5
  406. package/src/components/SelectMenu/select-menu.spec.md +19 -12
  407. package/src/components/SelectMenu/select-menu.stories.tsx +34 -27
  408. package/src/components/SelectMenu/select-menu.tsx +14 -3
  409. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
  410. package/src/components/SelectionControl/selection-item.spec.md +13 -2
  411. package/src/components/SelectionControl/selection-item.stories.tsx +1 -1
  412. package/src/components/SelectionControl/selection-item.tsx +8 -2
  413. package/src/components/Separator/separator.principles.stories.tsx +2 -2
  414. package/src/components/Separator/separator.spec.md +11 -5
  415. package/src/components/Sheet/sheet.anatomy.stories.tsx +7 -6
  416. package/src/components/Sheet/sheet.principles.stories.tsx +18 -38
  417. package/src/components/Sheet/sheet.spec.md +9 -11
  418. package/src/components/Sheet/sheet.stories.tsx +2 -2
  419. package/src/components/Sheet/sheet.tsx +6 -5
  420. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +42 -33
  421. package/src/components/Sidebar/sidebar.principles.stories.tsx +4 -4
  422. package/src/components/Sidebar/sidebar.spec.md +22 -17
  423. package/src/components/Sidebar/sidebar.stories.tsx +16 -0
  424. package/src/components/Sidebar/sidebar.tsx +15 -7
  425. package/src/components/Skeleton/skeleton.anatomy.stories.tsx +2 -2
  426. package/src/components/Skeleton/skeleton.principles.stories.tsx +20 -7
  427. package/src/components/Skeleton/skeleton.spec.md +6 -4
  428. package/src/components/Skeleton/skeleton.stories.tsx +34 -26
  429. package/src/components/Skeleton/skeleton.tsx +1 -1
  430. package/src/components/Slider/slider.principles.stories.tsx +3 -3
  431. package/src/components/Slider/slider.spec.md +16 -12
  432. package/src/components/Slider/slider.stories.tsx +2 -18
  433. package/src/components/Slider/slider.tsx +6 -2
  434. package/src/components/Steps/steps.anatomy.stories.tsx +3 -3
  435. package/src/components/Steps/steps.principles.stories.tsx +9 -12
  436. package/src/components/Steps/steps.spec.md +31 -25
  437. package/src/components/Steps/steps.stories.tsx +5 -40
  438. package/src/components/Steps/steps.tsx +17 -12
  439. package/src/components/Switch/switch.principles.stories.tsx +1 -1
  440. package/src/components/Switch/switch.spec.md +13 -0
  441. package/src/components/Switch/switch.tsx +3 -3
  442. package/src/components/Tabs/tabs.anatomy.stories.tsx +4 -4
  443. package/src/components/Tabs/tabs.principles.stories.tsx +1 -1
  444. package/src/components/Tabs/tabs.spec.md +13 -6
  445. package/src/components/Tabs/tabs.stories.tsx +3 -3
  446. package/src/components/Tabs/tabs.tsx +2 -2
  447. package/src/components/Tag/tag.anatomy.stories.tsx +15 -15
  448. package/src/components/Tag/tag.principles.stories.tsx +1 -1
  449. package/src/components/Tag/tag.spec.md +25 -5
  450. package/src/components/Textarea/textarea.anatomy.stories.tsx +3 -3
  451. package/src/components/Textarea/textarea.principles.stories.tsx +7 -7
  452. package/src/components/Textarea/textarea.spec.md +15 -3
  453. package/src/components/Textarea/textarea.tsx +1 -1
  454. package/src/components/TimePicker/time-columns.tsx +1 -1
  455. package/src/components/TimePicker/time-picker.anatomy.stories.tsx +8 -2
  456. package/src/components/TimePicker/time-picker.spec.md +23 -3
  457. package/src/components/TimePicker/time-picker.tsx +5 -3
  458. package/src/components/Toast/toast.anatomy.stories.tsx +1 -1
  459. package/src/components/Toast/toast.spec.md +7 -4
  460. package/src/components/Toast/toast.stories.tsx +12 -6
  461. package/src/components/Toast/toast.tsx +1 -1
  462. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +1 -1
  463. package/src/components/Tooltip/tooltip.spec.md +11 -8
  464. package/src/components/Tooltip/tooltip.tsx +1 -1
  465. package/src/components/TreeView/tree-view.anatomy.stories.tsx +25 -9
  466. package/src/components/TreeView/tree-view.principles.stories.tsx +5 -5
  467. package/src/components/TreeView/tree-view.spec.md +11 -9
  468. package/src/components/TreeView/tree-view.stories.tsx +5 -3
  469. package/src/components/TreeView/tree-view.tsx +8 -5
  470. package/src/patterns/action-bar/action-bar.spec.md +11 -4
  471. package/src/patterns/element-anatomy/element-anatomy.spec.md +8 -6
  472. package/src/patterns/element-anatomy/inline-action.spec.md +18 -18
  473. package/src/patterns/element-anatomy/item-anatomy.spec.md +47 -42
  474. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -6
  475. package/src/patterns/element-anatomy/item-anatomy.tsx +3 -3
  476. package/src/patterns/header-canonical/chrome-header.tsx +3 -2
  477. package/src/patterns/header-canonical/header-canonical.spec.md +24 -11
  478. package/src/patterns/header-canonical/header-canonical.stories.tsx +9 -9
  479. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +22 -12
  480. package/src/patterns/overlay-surface/overlay-surface.spec.md +43 -39
  481. package/src/patterns/overlay-surface/overlay-surface.tsx +3 -2
  482. package/src/patterns/resize-handle/resize-handle.spec.md +10 -1
  483. package/src/patterns/resize-handle/resize-handle.stories.tsx +7 -7
  484. package/src/tokens/README.md +5 -2
  485. package/src/tokens/color/color.spec.md +17 -10
  486. package/src/tokens/color/semantic.css +2 -0
  487. package/src/tokens/density/density.spec.md +4 -14
  488. package/src/tokens/elevation/elevation.spec.md +7 -8
  489. package/src/tokens/layoutSpace/layoutSpace.spec.md +20 -27
  490. package/src/tokens/motion/motion.spec.md +15 -7
  491. package/src/tokens/opacity/opacity.spec.md +15 -26
  492. package/src/tokens/orphan-tokens.spec.md +14 -3
  493. package/src/tokens/radius/radius.spec.md +13 -15
  494. package/src/tokens/token-system.spec.md +10 -13
  495. package/src/tokens/typography/typography.spec.md +8 -12
  496. package/src/tokens/uiSize/uiSize.spec.md +28 -16
  497. /package/ds-canonical/hooks/{check_addon_subdir_ship.sh → retired/2026-06-11-prune-merge/check_addon_subdir_ship.sh} +0 -0
  498. /package/ds-canonical/hooks/{check_consumer_app_story_title.sh → retired/2026-06-11-prune-merge/check_consumer_app_story_title.sh} +0 -0
  499. /package/ds-canonical/hooks/{check_consumer_ds_primitive_misuse.sh → retired/2026-06-11-prune-merge/check_consumer_ds_primitive_misuse.sh} +0 -0
  500. /package/ds-canonical/hooks/{check_consumer_no_ds_catalog.sh → retired/2026-06-11-prune-merge/check_consumer_no_ds_catalog.sh} +0 -0
  501. /package/ds-canonical/hooks/{check_consumer_story_baseline.sh → retired/2026-06-11-prune-merge/check_consumer_story_baseline.sh} +0 -0
  502. /package/ds-canonical/hooks/{check_data_table_size_num_to_meta_width.sh → retired/2026-06-11-prune-merge/check_data_table_size_num_to_meta_width.sh} +0 -0
  503. /package/ds-canonical/hooks/{check_fork_user_plugin_install.sh → retired/2026-06-11-prune-merge/check_fork_user_plugin_install.sh} +0 -0
  504. /package/ds-canonical/hooks/{check_plugin_freshness.sh → retired/2026-06-11-prune-merge/check_plugin_freshness.sh} +0 -0
  505. /package/ds-canonical/hooks/{check_propose_cite_required.sh → retired/2026-06-11-prune-merge/check_propose_cite_required.sh} +0 -0
  506. /package/ds-canonical/hooks/{check_propose_plain_chinese.sh → retired/2026-06-11-prune-merge/check_propose_plain_chinese.sh} +0 -0
  507. /package/ds-canonical/hooks/{check_storybook_addon_preset_cjs.sh → retired/2026-06-11-prune-merge/check_storybook_addon_preset_cjs.sh} +0 -0
@@ -29,9 +29,9 @@ TanStack Table 負責邏輯,DataTable 負責視覺與互動。
29
29
 
30
30
  **Layout Family**:非上述 family — composite / multi-section(多區塊組合,自 own layout)。
31
31
 
32
- ### 檔案結構(2026-05-03 split matrix)
32
+ ### 檔案結構
33
33
 
34
- 12 file,每個過 M21 / M17 / Rule-of-3 test:`data-table.tsx`(主,foundational)/ `data-table-filter-panel.tsx` + `data-table-sort-manager.tsx`(panel state 隔離)/ `column-types.ts` + `filter-operators.ts`(✓ Rule-of-3 SSOT,3+ consumer)/ `filter-tree.ts`(pure data + eval,test isolation)/ `lib/column-meta.ts`(Internal SSOT,消 5 處 `(col as any)`)+ stories/spec/css。**M21 retract**:`filter-value-picker.tsx` 1 consumer → 已 inline 回 panel
34
+ 檔案拆分架構(12 file split matrix)與工程決策史屬 code home `data-table.tsx` 檔頭 docblock(2026-06-11 遷移,Level 4;spec 只管設計語言)。
35
35
 
36
36
  ---
37
37
 
@@ -64,7 +64,7 @@ TanStack Table 負責邏輯,DataTable 負責視覺與互動。
64
64
  |------|------|------|
65
65
  | **L1 基礎結構** | 骨架、尺寸、border、色彩、高度模式、行高模式 | ✅ 完成(本文件 L1 段)|
66
66
  | **L2 選取** | row selection、checkbox、單/多選、bulk action 整合 | ✅ 完成(本文件 L2 段)|
67
- | **L3 欄位互動** | 排序(本文件 L3)、resize、reorder、pin、顯示隱藏 | ✅ 完成(sort + resize + reorder + pin + visibility 全 props 支援:`enableColumnResize` / `enableColumnReorder` / `columnVisibility` / `pinnedLeftColumns` / `pinnedRightColumns`,見 data-table.tsx L87-88,143,201,217)|
67
+ | **L3 欄位互動** | 排序(本文件 L3)、resize、reorder、pin、顯示隱藏 | ✅ 完成(sort + resize + reorder + pin + visibility 全 props 支援:`enableColumnResize` / `enableColumnReorder` / `columnVisibility` / `pinnedLeftColumns` / `pinnedRightColumns`,見 `data-table.tsx` `DataTableProps` 宣告)|
68
68
  | **L4 資料操作 + Cell 能力** | 進階篩選(本文件 L4 Filter)、inline edit、nested rows、row drag(本文件 L4 段)| ✅ Filter / Inline edit / Nested rows / Row drag v3 完成(Jira canonical + virtualization fix) |
69
69
  | **L5 進階** | 分組、搜尋、tree data v2 enhancements、export CSV/Excel | 待 v2 |
70
70
 
@@ -105,17 +105,17 @@ Table 分三層:
105
105
 
106
106
  完整 class / overflow 規則見 `data-table.tsx`。
107
107
 
108
- **Header 在 scroll 容器外面。** 不用 CSS sticky——header 結構性地在 body 上方,永遠固定在頂部。Header bg 用 `neutral-2-opaque`(不透明),不受底層色影響。
108
+ **Header 在 scroll 容器外面。** 不用 CSS sticky——header 結構性地在 body 上方,永遠固定在頂部。Header bg 用 `--muted`(code `HEADER_BG = 'bg-muted'`,比 surface 深一階,同 anatomy ColorMatrix)。
109
109
 
110
110
  **三個 region 共享垂直捲動。** body-viewport 是唯一的垂直 scroll container,三個 body region 是它的 flex children。垂直捲動天然同步,不需 JS。
111
111
 
112
- **只有 center 水平捲動。** center-body `overflow-x: auto`。center-header `overflow: hidden`,用 JS sync:`centerBody.scrollLeft → centerHeader.scrollLeft`。
112
+ **只有 center 水平捲動。** center-body 是唯一的水平 scroll container,center-header 跟隨其捲動位置同步(同步機制見「捲軸」段 + `data-table.tsx`)。
113
113
 
114
- **Left / right 不水平捲動。** `overflow: hidden`。Frozen 邊界用 `border-divider`(全高度)。
114
+ **Left / right 不水平捲動。** Frozen 邊界用 `border-divider`(全高度)。
115
115
 
116
116
  **固定行高確保跨 region 對齊。** 所有 row 用 `h-table-row-{size}`,三個 region 的 row 精確同高。
117
117
 
118
- **Header/body region 寬度同步。** Header region 寬度由內容決定(columns + actions),body region 用 ResizeObserver 量測 header 寬度並同步。
118
+ **Header/body region 寬度同步。** Header region 寬度由內容決定(columns + actions),body region 量測 header 寬度同步(機制見 `data-table.tsx`)。
119
119
 
120
120
  ### 四、行高模式
121
121
 
@@ -173,10 +173,12 @@ Row actions 欄本質上是 frozen right column,左邊界也使用 full-height
173
173
  | Case | Story | Avg / p95 / long-task | Gate |
174
174
  |---|---|---|---|
175
175
  | A Plain virt | `VirtualScroll` | ≤16.67/≤33/0 | hard |
176
- | B Rich budget | `RoadmapPerfBudget`(500×13 rich+inline-edit,fixed 600px) | ≤50/≤80/≤1 | hard |
176
+ | B Rich budget | `RoadmapPerfBudget`(500×13 rich+inline-edit,fixed 600px;2026-05-17 整併誤 retire → 2026-06-12 R2 重建,gate 恢復可跑) | ≤50/≤80/≤1 | hard |
177
177
  | C Row drag | `RowDragWithVirtualization` | ≤33/≤50/longest<100 | soft(DnD thermal) |
178
178
  | D Edit isolation | `<Profiler>` TBD | skip ≥ visible−active | hard |
179
179
 
180
+ **2026-06-12 重建後實測**(static build,3 runs/case):1x CPU — A 16.56/16.8/0、B 24.0/33.4/0、C 16.67/16.8/0 全過 gate;script 預設 4x throttle 在有背景負載機器上全 case 一致 ~2.3x 超標(含未動過的對照組 A)→ 本表門檻實證對應 1x/閒置條件,4x 門檻是否重校 = user 決策(本表數字不動)。
181
+
180
182
  **Anti-pattern**:`RoadmapAllInOne`(全 features stack)≈117ms 不達 B,因 SortableRowProvider/column reorder/resize/selection/overlay 同時開。Consumer:13+ cols rich-cell → 拆 detail drawer / column visibility 預設 hide,不該期 60fps + 全 feature stack。Cite + Phase 1/2 history → `cell-registry.tsx:480-499` JSDoc + commits log。
181
183
 
182
184
  ### 七、Column Type
@@ -446,7 +448,7 @@ Row drag + column reorder + TreeView 共用 `lib/drag-visual.ts`:source `opacity
446
448
 
447
449
  `enableRowDrag?: boolean` + `onRowReorder?: (sourceId, targetId, 'before' | 'after')`。Library:@dnd-kit/core(v15.0 Path B 用 `useDraggable` + `useDroppable`,不用 `@dnd-kit/sortable`)。**必填 `getRowId`**(否則 dnd 用 row.index reorder 後錯位)。
448
450
 
449
- - **Handle**:`<Button variant="tertiary" iconOnly size="xs" startIcon={GripVertical} />` 24px chip,所有 state(idle / hover / aria-disabled)統一 `bg-surface-raised`(border / shadow 已 retire,2026-05-12 per user「我有叫你加 elevation 嗎」),`absolute left-1 top-1/2 -translate-y-1/2` 4px inset 不佔 column 空間;**hover-reveal** `opacity-0 group-hover/row:opacity-100`。對齊 Jira backlog(@benchmark-unverified,M22)。Tertiary chip 非 ItemInlineAction 因透明背景撞 table border。
451
+ - **Handle**:Button tertiary iconOnly xs(GripVertical)24px chip,所有 state(idle / hover / aria-disabled)統一 `bg-surface-raised`(border / shadow 已 retire,2026-05-12 per user「我有叫你加 elevation 嗎」),fixed-position 浮層貼 row 左緣、不佔 column 空間(位置 JS 計算,實作見 `data-table.tsx`);**hover-reveal** JS 控 visibility / opacity(row 或 handle hover 顯示;drag 中 source 強制顯示、其他列隱藏)。對齊 Jira backlog(@benchmark-unverified,M22)。Tertiary chip 非 ItemInlineAction 因透明背景撞 table border。
450
452
  - **Sort × Drag 互斥**:sort.length>0 → handle disabled+Tooltip。**Top-level only**(`row.depth>0` 不顯 handle)。**Position**:active vs over 視覺位置 → `'after'`/`'before'` 對齊 `arrayMove`。**Consumer-managed mutation**:`onRowReorder(sourceId, targetId, position)`,DS 不持 row order(Notion/Airtable/Linear)。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
451
453
  - **Virtualization 整合**(v3 2026-05-05):enableRowDrag 自動把 overscan 拉到 `Math.max(overscan, 5)` + drag 期 freeze `measureElement` + `modifiers={[snapToCursorModifier]}`(ghost top-left 對齊 cursor,不鎖軸)。**3-panel mirror sync**:各 region 對同 row id 各呼叫 `useDraggable` + `useDroppable`,mirror 自然取得相同 transform;handle 只 render primary region(left 優先 → center)避雙觸發。**Cross-parent drop 禁止**(已知 limit):nested 只同 top-level 重排,collisionDetection 過濾,顯 invalid signal。
452
454
 
@@ -517,12 +519,14 @@ DataTable 是 composite multi-section 元件,**不套 canonical 5**(Inspector /
517
519
 
518
520
  **Why not radio-group**:之前 boilerplate 從 RadioGroup spec 誤抄。DataTable 是 multi-row / multi-column composite,not single-choice selection group;a11y semantics 完全不同(grid vs radio-group)。 <!-- @benchmark-verified: 2026-05-18 D1 rewrite -->
519
521
 
520
-
521
522
  ## 被引用(auto-maintained,Dim 3 reciprocal audit)
522
523
 
523
524
  > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
524
525
 
526
+ - `bulk-action-bar.spec.md`
525
527
  - `carousel.spec.md`
526
528
  - `circular-progress.spec.md`
529
+ - `description-list.spec.md`
530
+ - `opacity.spec.md`
527
531
  - `scroll-area.spec.md`
528
- - `item-anatomy.spec.md`
532
+ - `tree-view.spec.md`
@@ -163,7 +163,7 @@ export const ColumnResize: Story = {
163
163
  />
164
164
  </div>
165
165
  <div>
166
- <h3 className="text-body font-bold text-foreground mb-2">Pinned + Resize 並存(USER #43 sanity)</h3>
166
+ <h3 className="text-body font-bold text-foreground mb-2">欄位釘選與欄寬調整並存</h3>
167
167
  <p className="text-caption text-fg-muted mb-3">
168
168
  把 SKU 跟產品名稱固定在左側,依然可以拖動分隔線調整這兩欄的寬度。
169
169
  <br />目前各欄寬度:{JSON.stringify(pinnedWidths)}
@@ -296,6 +296,7 @@ export const RowAutoHeight: Story = {
296
296
  }
297
297
 
298
298
  /* ── Empty State ── */
299
+ // 「預設空狀態」pane = 「自訂空狀態」的對照基線;Empty primitive 消費教學 canonical → anatomy.EmptyState,此處不重複教學
299
300
  export const EmptyState: Story = {
300
301
  name: '空狀態',
301
302
  render: () => (
@@ -1390,11 +1391,11 @@ export const FilterPanelModified: Story = {
1390
1391
  },
1391
1392
  }
1392
1393
 
1393
- /* ── 進階篩選 — tag 溢出測試(A5 reproduce)── */
1394
+ /* ── 進階篩選 — 長標籤溢出 ── */
1394
1395
  export const FilterPanelLongTagOverflow: Story = {
1395
1396
  name: '進階篩選 — 長標籤溢出',
1396
1397
  render: () => {
1397
- // 故意用 select_multi op + 多個長 label values,測試 Combobox tag overflow + +N indicator
1398
+ // 製造業 ERP 的產品分類名稱普遍很長 示範多選後 Combobox tag 溢出時的 +N 摘要收斂
1398
1399
  const longLabelColumns = [
1399
1400
  col.accessor('category', {
1400
1401
  header: '類別',
@@ -1418,7 +1419,7 @@ export const FilterPanelLongTagOverflow: Story = {
1418
1419
  }))
1419
1420
  return (
1420
1421
  <div className="w-full max-w-[680px]">
1421
- <p className="text-caption text-fg-muted mb-3">A5 reproduce 多個超長 label values 是否觸發 Combobox `+N` overflow indicator?</p>
1422
+ <p className="text-caption text-fg-muted mb-3">產品分類名稱很長(製造業 ERP 常見)時,已選的多個標籤超出單行寬度,Combobox 自動收斂為 +N 摘要。</p>
1422
1423
  <DataTableFilterPanel
1423
1424
  mode="flat"
1424
1425
  columns={[...longLabelColumns]}
@@ -1432,14 +1433,14 @@ export const FilterPanelLongTagOverflow: Story = {
1432
1433
 
1433
1434
  /* ── 列拖曳重排(Jira-style + 3-panel pinned columns)──────────────────────
1434
1435
  enableRowDrag + onRowReorder 整合範例(v3 Jira 設計準則):
1435
- - handle absolute 浮在 row 左 border(Button tertiary iconOnly xs = elevated chip)
1436
+ - handle 浮在 row 左緣(fixed-position;Button tertiary iconOnly xs = elevated chip)
1436
1437
  - 不佔 column 空間 — table 看起來乾淨,沒有預留拖曳欄位
1437
- - hover row → handle 浮現(opacity 0 → 100)
1438
- - 拖曳 row → @dnd-kit/sortable 重排;放下 → onRowReorder(sourceId, targetId, 'before' | 'after')
1438
+ - hover row → handle 浮現(JS opacity)
1439
+ - 拖曳 row → @dnd-kit/core useDraggable + useDroppable(v15.0 Path B);放下 → onRowReorder(sourceId, targetId, 'before' | 'after')
1439
1440
  - consumer 自管 data array mutation(同 Notion / Airtable / Linear pattern)
1440
1441
  - sort 啟用時 drag handle 自動 disabled + Tooltip 解釋
1441
- - pinned-left + pinned-right 同時存在 → mirror regions 跟動 transform(per-region useSortable
1442
- 共享同 SortableContext state) */
1442
+ - pinned-left + pinned-right 同時存在 → source 留原位,2px drop indicator 跨三 region 同步標示落點
1443
+ (per-region useDraggable / useDroppable,不 auto-shift) */
1443
1444
  export const RowDragInteractive: Story = {
1444
1445
  name: '列拖曳重排(含釘選欄)',
1445
1446
  render: () => {
@@ -1462,8 +1463,8 @@ export const RowDragInteractive: Story = {
1462
1463
  <div className="flex flex-col gap-3 max-w-3xl">
1463
1464
  <p className="text-caption text-fg-muted">
1464
1465
  handle 浮在 row 左緣(不佔 column 空間,Jira 設計準則)。pinned-left(SKU)+ pinned-right(Updated)+
1465
- center 中段欄。拖曳任一列時,三個 region row 會同步跟動 transform(per-region
1466
- <code>useSortable</code> 共享同 SortableContext state)。
1466
+ center 中段欄。拖曳時 source 列留在原位(壓住視覺),2px 主色 drop indicator 跨三個 region
1467
+ 同步標示落點(per-region <code>useDraggable</code> / <code>useDroppable</code>,不 auto-shift)。
1467
1468
  </p>
1468
1469
  <DataTable
1469
1470
  columns={columnsWithPrice}
@@ -1510,8 +1511,8 @@ export const RowDragWithVirtualization: Story = {
1510
1511
  return (
1511
1512
  <div className="flex flex-col gap-3 max-w-3xl">
1512
1513
  <p className="text-caption text-fg-muted">
1513
- 200 列 + 虛擬捲動。v3 修正:enableRowDrag 自動拉高 overscan ≥ 10、drag 期間 freeze
1514
- measureElement、modifier Y 軸 — 拖曳 + 持續往下捲不再錯位。
1514
+ 200 列 + 虛擬捲動。v3 修正:enableRowDrag 自動拉高 overscan ≥ 5、drag 期間 freeze
1515
+ measureElement、snapToCursorModifier ghost 對齊游標(不鎖軸)— 拖曳 + 持續往下捲不再錯位。
1515
1516
  </p>
1516
1517
  <DataTable
1517
1518
  columns={baseColumns}
@@ -1890,3 +1891,47 @@ export const RoadmapAllInOne: Story = {
1890
1891
  }
1891
1892
  },
1892
1893
  }
1894
+
1895
+ /* ── Feature-split perf budget story(2026-05-14 codex perf debate verdict;2026-06-12 deep-audit
1896
+ R2 重建 — 2026-05-17 stories 整併批次誤 retire,但 spec「六之三」Case B hard gate +
1897
+ scripts/runtime-perf-datatable.mjs:20 仍指向本 story,gate 形同不可跑):──────────────────
1898
+ 獨立 perf 量測 story — 同 Roadmap 13 cols rich-cell data(useRoadmapColumns SSOT),但**禁用**
1899
+ row drag / column reorder / column resize / selection / spreadsheet overlay,只保 inline edit
1900
+ display。目的:隔離 feature-stack 疊加 cost(SortableRowProvider / filter / sort / columnOrder
1901
+ state),驗證 rich cell 本體 scroll budget(avg ≤ 50ms / p95 ≤ 80ms / long-task ≤ 1,CPU 4x
1902
+ throttle)。**不動** RoadmapAllInOne demo IA(user 2026-05-10 directive 全合一)。
1903
+ 重建版去掉原手刻說明 banner(px-loose + border-b border-divider = R9 chrome-header drift
1904
+ 簽名,且量測 story 不需 chrome;說明留本註解)。 */
1905
+ export const RoadmapPerfBudget: Story = {
1906
+ name: '效能預算量測',
1907
+ parameters: { layout: 'fullscreen' },
1908
+ tags: ['!autodocs'],
1909
+ render: () => {
1910
+ const bigData = React.useMemo(() => {
1911
+ const arr: RoadmapItem[] = []
1912
+ for (let i = 0; i < 500; i++) {
1913
+ const base = ROADMAP_DATA[i % ROADMAP_DATA.length]
1914
+ const id = `RDM-${String(i + 100).padStart(3, '0')}`
1915
+ arr.push({ ...base, id, title: `${base.title} (#${i + 1})` })
1916
+ }
1917
+ return arr
1918
+ }, [])
1919
+ const [data, setData] = React.useState(bigData)
1920
+ const columns = useRoadmapColumns()
1921
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
1922
+ setData((prev) => prev.map((r) => (r.id === rowId ? { ...r, [colId]: value } : r)))
1923
+ }
1924
+ return (
1925
+ <div className="mx-[var(--layout-space-loose)] mb-[var(--layout-space-loose)]">
1926
+ <DataTable
1927
+ columns={columns}
1928
+ data={data}
1929
+ height="600px"
1930
+ inlineEdit
1931
+ getRowId={(row) => row.id}
1932
+ onCellCommit={handleCommit}
1933
+ />
1934
+ </div>
1935
+ )
1936
+ },
1937
+ }
@@ -1,5 +1,17 @@
1
1
  // @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
2
2
  // code-quality-allow: file-size — foundational composite — 拆檔會複雜化 context / ref / state 同步
3
+ //
4
+ // ── 檔案結構(2026-05-03 split matrix;2026-06-11 自 data-table.spec.md 遷入,Level 4 code home)──
5
+ // 每個檔過 M21 / M17 / Rule-of-3 三 test:
6
+ // - data-table.tsx(主,foundational)
7
+ // - data-table-filter-panel.tsx + data-table-sort-manager.tsx + data-table-column-visibility-panel.tsx(panel state 隔離)
8
+ // - cell-registry.tsx(column type → cell display / edit 解析 SSOT)
9
+ // - data-table-interaction-layer.tsx + active-editor-controller.ts(spreadsheet overlay + portal editor)
10
+ // - column-types.ts + filter-operators.ts(✓ Rule-of-3 SSOT,3+ consumer)
11
+ // - filter-tree.ts(pure data + eval,test isolation)
12
+ // - lib/column-meta.ts(Internal SSOT,消 5 處 `(col as any)`)
13
+ // - + stories / spec / css
14
+ // M21 retract:filter-value-picker.tsx 1 consumer → 已 inline 回 panel。
3
15
  import * as React from 'react'
4
16
  import { createPortal } from 'react-dom'
5
17
  import { Empty } from '@/design-system/components/Empty/empty'
@@ -56,6 +68,7 @@ type TableSize = 'sm' | 'md' | 'lg'
56
68
  export interface DataTableProps<TData>
57
69
  extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,
58
70
  VariantProps<typeof dataTableVariants> {
71
+ // any-allow: TanStack ColumnDef TValue idiom(per-column value 型別異質,官方範例同)— 對齊本 module 既有 escape 紀律
59
72
  columns: ColumnDef<TData, any>[]
60
73
  data: TData[]
61
74
  size?: TableSize
@@ -1,6 +1,6 @@
1
- # Advanced Filter Operator × ColumnType × ValueShape SSOT(DRAFT v3)
1
+ # Advanced Filter 設計原則(Operator × ColumnType × ValueShape SSOT,v3)
2
2
 
3
- > **狀態**:Draft for review。Phase A 結案版 + datetime 擴充。確認後升 `filter-operators.spec.md` + 寫成 `filter-operators.ts` registry
3
+ > **狀態**:已落地 registry 寫成 `filter-operators.ts`,`filter-tree.ts` + `data-table-filter-panel.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/` 再搬。
@@ -10,7 +10,7 @@
10
10
  - **砍 `number.between`**(9→8 ops)— Notion + Airtable 共識,同 field 重複 condition 可組合 `gte X AND lte Y`,無自然視覺也無業界 NumberRangeInput 元件
11
11
  - **加 `column.meta.includeTime: boolean` 旗標** — 對齊 Notion idiom,不另設 datetime column type
12
12
  - **加 ValueShape `datetime_single` / `datetime_range`** — `includeTime=true` 時切到這兩個 shape
13
- - **加 ValueShape `datetime_relative`**(同 date_relative,relative 邏輯不變)
13
+ - **datetime 不另設 relative shape** — `is_relative` 維持 `date_relative`(relative 邏輯不變;12-shape 表與 code `ValueShape` union 皆無 `datetime_relative`)
14
14
  - **filter 比對精度**:`includeTime=true` 走 ms 精度(避開 Airtable 著名地雷:filter 忽略 time)
15
15
  - **不新增 `time-only` column type**(業界沒人做,罕見場景)
16
16
 
@@ -33,8 +33,8 @@
33
33
  | `select_single` | `<Select>` from `column.meta.options` | (預留)罕用 |
34
34
  | `person_single` | `<PeoplePicker>` 單選 | (預留)罕用 |
35
35
 
36
- **date_relative 預設選項**(11 ):
37
- `today / yesterday / tomorrow / this_week / last_week / next_week / this_month / last_month / next_month / past_7_days / past_30_days`
36
+ **date_relative 預設選項**(13 個,分過去 / 目前 / 未來三組 — 對齊 code `DATE_RELATIVE_OPTIONS` / `DATE_RELATIVE_GROUPS`):
37
+ `today / yesterday / tomorrow / this_week / last_week / next_week / this_month / last_month / next_month / past_7_days / past_30_days / next_7_days / next_30_days`
38
38
 
39
39
  **`number_range` 已砍**(配合 `number.between` 砍除)。
40
40
 
@@ -189,30 +189,15 @@
189
189
  | 統一用 `is_set` / `is_not_set`(不混 `is_empty`) | 9 types 全用(boolean 豁免) |
190
190
  | select / person 用 `is` 配多值 picker(不另設 `is_any_of`) | ✓ 對齊 CU UX |
191
191
  | multiSelect / multiPerson 用 `has_*` 動詞(對應 CU labels Any/All/None) | ✓ |
192
- | number `between` 對應 CU RANGE | ✓ |
192
+ | number 不設 `between`(v3 field `gte AND lte` 組合替代,見拍板 #10) | ✓ |
193
193
  | date 用 `before/after/between/relative` + `is_set` 不混 Airtable `is_empty` 風 | ✓ |
194
194
  | 6 ops 擴充項皆有 ≥ 2 家 world-class DS 採用,且不衝突 CU 設計語言 | ✓ |
195
195
 
196
196
  **未跑 audit / test 驗證**,僅與 web-researched ClickUp / Airtable / Notion docs 自我比對。
197
197
 
198
- ## 5. TypeScript 結構草案
198
+ ## 5. TypeScript 結構(已落地)
199
199
 
200
- ```ts
201
- export type ValueShape =
202
- | 'none' | 'text' | 'number' | 'number_range'
203
- | 'date_single' | 'date_range' | 'date_relative'
204
- | 'select_single' | 'select_multi'
205
- | 'person_single' | 'person_multi'
206
-
207
- export interface OperatorSpec {
208
- op: string // e.g. 'contains'
209
- label: string // e.g. '包含'(暫硬編,留 i18n hook)
210
- valueShape: ValueShape
211
- }
212
-
213
- export const OPERATOR_REGISTRY: Record<ColumnType, OperatorSpec[]> = { ... }
214
- export const DEFAULT_OPERATOR: Record<ColumnType, string> = { ... }
215
- ```
200
+ 型別與 registry 落地於 `filter-operators.ts`(`ValueShape` 12 種含 `datetime_*`、無 `number_range`;`OPERATOR_REGISTRY` / `DEFAULT_OPERATOR`;`getValueShape` 處理 `includeTime` auto-promote)。Tree 型別與求值在 `filter-tree.ts`。原 v2 草案已退役,以 code 為準。
216
201
 
217
202
  ## 6. 拍板紀錄
218
203
 
@@ -253,12 +238,19 @@ export const DEFAULT_OPERATOR: Record<ColumnType, string> = { ... }
253
238
 
254
239
  **技術坑(信心 85%,Phase B spec.md 詳)**:TanStack `ColumnFiltersState` per-column 一筆 filter value,N 條同 column 會 AND-chain 不能 OR。**業界標準解法**:棄用 `columnFilters`,改自管 FilterTree state + 用 `globalFilter` + 自訂 `globalFilterFn` 走樹求 boolean。
255
240
 
256
- ## 8. Phase B 進度
241
+ ## 8. 邊界案例(code 真值 — `filter-tree.ts` / `data-table-filter-panel.tsx`)
242
+
243
+ - **Condition 值空 / 未選 field**:視為 incomplete,求值 **pass-through**(不過濾任何 row);空值 ≠ `is_not_set`(後者是顯式 op)— `isConditionComplete` 守門
244
+ - **群組刪光 condition**:空群組保留並 pass-through(true),panel 顯示「移除空群組」按鈕由 user 顯式刪除,不自動消失
245
+ - **巢狀深度**:1-level cap 由 TypeScript 型別鎖死(`FilterGroup.children: FilterCondition[]`),無 runtime guard;繞過型別塞入的非 condition 物件缺 `field`/`op` → incomplete → pass-through,不 crash
246
+ - **relative 區間邊界**:全部 local time、雙端 inclusive(`startOfDay`–`endOfDay`);`past_7_days` = 7 天前 00:00 起**含今天整天**;week 以週一起算(`weekStartsOn: 1`)
247
+
248
+ ## 9. Phase B 進度
257
249
 
258
- - [x] ValueShape × DS 元件對照 — 完成,coverage 8/12 直接消費 + 4 預留 + 2 新建(DateTimePicker / DateTimeRangePicker)
250
+ - [x] ValueShape × DS 元件對照 — 完成,coverage 8/12 直接消費 + 4 預留;datetime `<DatePicker showTime>` / `<DatePickerRange showTime>` prop variant(M21,非新元件)
259
251
  - [x] InputSurface 議題消失(配合砍 `number.between`)
260
- - [] `advanced-filter.draft.md` FilterTree data model + DataTable 耦合(本 turn 同步寫)
261
- - [] `datetime-picker.draft.md` — DateTimePicker / Range spec(本 turn 同步寫)
252
+ - [x] FilterTree data model + DataTable 耦合 — 已落地 `filter-tree.ts` + `data-table-filter-panel.tsx`(原規劃 `advanced-filter.draft.md` 未另立檔,內容即本 spec + code)
253
+ - [x] datetime spec — 併入本 spec v3(原規劃 `datetime-picker.draft.md` 不需要,無新元件)
262
254
  - [x] i18n 策略 — 暫硬編繁中,留 i18n hook(對齊 DS 既有元件慣例)
263
255
  - [→] Phase B.5 lock canonical via `/ensure-canonical`(spec 全收斂後)
264
256
 
@@ -105,7 +105,7 @@ export const Overview = {
105
105
  <div>
106
106
  <H3>視覺一覽</H3>
107
107
  <Desc>實際渲染 — single mode,已選今日的前一日展示 selected 視覺,today 以數字下方藍色底線標示。</Desc>
108
- <div className="inline-flex bg-surface-raised border border-border rounded-lg p-2 w-fit">
108
+ <div className="inline-flex bg-surface-raised border border-border rounded-lg w-fit">
109
109
  <DateGrid
110
110
  mode="single"
111
111
  selected={(() => {
@@ -196,7 +196,7 @@ export const Inspector = {
196
196
  {/* Left: live preview + blueprint */}
197
197
  <div className="flex flex-col gap-5">
198
198
  <div className="px-6 py-6 rounded-lg bg-canvas border border-divider flex items-center justify-center">
199
- <div className="bg-surface-raised border border-border rounded-lg p-2">
199
+ <div className="bg-surface-raised border border-border rounded-lg">
200
200
  <DateGrid
201
201
  mode="single"
202
202
  selected={selected}
@@ -288,7 +288,7 @@ export const Inspector = {
288
288
  return (
289
289
  <div className="flex flex-col gap-4">
290
290
  <H3>元件檢閱器</H3>
291
- <Desc>DateGrid 的所有 layout token 一覽。theme / density 切換時色彩自動反轉,日格尺寸保持不變(浮層 / dashboard 專用,不配對 field-height family)。</Desc>
291
+ <Desc>DateGrid 的所有 layout token 一覽。theme / density 切換時色彩自動反轉,日格走 h-field-sm 隨 density 縮放(28×28 md / 32×32 lg),與 field 家族保持比例。</Desc>
292
292
  <InspectorInner />
293
293
  </div>
294
294
  )
@@ -442,13 +442,13 @@ export const SizeMatrix = {
442
442
  <div className="flex flex-wrap gap-6 items-start">
443
443
  <div className="flex flex-col gap-2">
444
444
  <span className="text-caption font-medium text-fg-secondary">單月(預設)</span>
445
- <div className="bg-surface-raised border border-border rounded-lg p-2">
445
+ <div className="bg-surface-raised border border-border rounded-lg">
446
446
  <DateGrid mode="single" defaultMonth={new Date()} locale={zhTW} />
447
447
  </div>
448
448
  </div>
449
449
  <div className="flex flex-col gap-2">
450
450
  <span className="text-caption font-medium text-fg-secondary">雙月並排(range 常用)</span>
451
- <div className="bg-surface-raised border border-border rounded-lg p-2">
451
+ <div className="bg-surface-raised border border-border rounded-lg">
452
452
  <DateGrid mode="single" defaultMonth={new Date()} locale={zhTW} numberOfMonths={2} />
453
453
  </div>
454
454
  </div>
@@ -483,7 +483,7 @@ export const StateBehavior = {
483
483
  <div className="flex flex-wrap gap-6 items-start">
484
484
  <div className="flex flex-col gap-2 min-w-0">
485
485
  <span className="text-caption font-medium text-fg-secondary">mode="single"</span>
486
- <div className="bg-surface-raised border border-border rounded-lg p-2">
486
+ <div className="bg-surface-raised border border-border rounded-lg">
487
487
  <DateGrid
488
488
  mode="single"
489
489
  selected={single}
@@ -499,7 +499,7 @@ export const StateBehavior = {
499
499
 
500
500
  <div className="flex flex-col gap-2 min-w-0">
501
501
  <span className="text-caption font-medium text-fg-secondary">mode="multiple"</span>
502
- <div className="bg-surface-raised border border-border rounded-lg p-2">
502
+ <div className="bg-surface-raised border border-border rounded-lg">
503
503
  <DateGrid
504
504
  mode="multiple"
505
505
  selected={multiple}
@@ -515,7 +515,7 @@ export const StateBehavior = {
515
515
 
516
516
  <div className="flex flex-col gap-2 min-w-0">
517
517
  <span className="text-caption font-medium text-fg-secondary">mode="range"</span>
518
- <div className="bg-surface-raised border border-border rounded-lg p-2">
518
+ <div className="bg-surface-raised border border-border rounded-lg">
519
519
  <DateGrid
520
520
  mode="range"
521
521
  selected={range}
@@ -80,7 +80,7 @@ export const UsageGuidance: Story = {
80
80
  <LinkTo kind="Design System/Internal/DateGrid/展示" name="範圍 — 分析時段 / 訂單範圍"><span className="text-primary hover:underline font-medium cursor-pointer">Range — 分析時段 / 訂單範圍</span></LinkTo>
81
81
  </li>
82
82
  <li>
83
- <LinkTo kind="Design System/Internal/DateGrid/展示" name="行內 — 儀表板小卡"><span className="text-primary hover:underline font-medium cursor-pointer">行內 — 儀表板小卡</span></LinkTo>
83
+ <LinkTo kind="Design System/Internal/DateGrid/展示" name="行內 — 儀表板小卡"><span className="text-primary hover:underline font-medium cursor-pointer">行內 — Linear 專案截止日小卡</span></LinkTo>
84
84
  </li>
85
85
  </ul>
86
86
  <p className="text-fg-muted mt-3">判斷不確定時:對照 spec.md「何時用 / 何時不用」段;若仍不符,改用近親元件(見下方「vs 近親」)。</p>
@@ -120,10 +120,10 @@ export const UsageGuidance: Story = {
120
120
  </Rule>
121
121
  </Section>
122
122
 
123
- <Section title="vs 近親 — Calendar(inline) vs DatePicker(field trigger)">
123
+ <Section title="vs 近親 — DateGrid(inline)vs DatePicker(field trigger)">
124
124
  <Rule
125
- title="Calendar — inline 月曆,頁面上常駐可見"
126
- note="dashboard 小卡、側欄 widget、日期 filter bar。使用者一眼就看到整月,不需點開。Calendar 是純 primitive,不自包 Popover。"
125
+ title="DateGrid — inline 月曆,頁面上常駐可見"
126
+ note="dashboard 小卡、側欄 widget、日期 filter bar。使用者一眼就看到整月,不需點開。DateGrid 是純 primitive,不自包 Popover。"
127
127
  >
128
128
  <Demo title="Linear 專案截止日 widget">
129
129
  <div className="flex flex-col gap-2 w-fit">
@@ -152,7 +152,7 @@ export const UsageGuidance: Story = {
152
152
 
153
153
  <Rule
154
154
  title="判斷法 — 看「頁面是否常駐顯示整月」"
155
- note="常駐(月曆是主要內容)→ Calendar;輔助(主要是一個欄位,偶爾改)→ DatePicker。空間有限的表單永遠用 DatePicker,不要塞整個月曆進表單。"
155
+ note="常駐(月曆是主要內容)→ DateGrid;輔助(主要是一個欄位,偶爾改)→ DatePicker。空間有限的表單永遠用 DatePicker,不要塞整個月曆進表單。"
156
156
  >
157
157
  <Label>
158
158
  常駐月曆 = 使用者「在選日的脈絡中」(排班、活動、分析時段篩選);
@@ -304,9 +304,9 @@ export const LocaleRule: Story = {
304
304
  <div>
305
305
  <Rule
306
306
  title="locale prop 控制週首日與星期標頭語言"
307
- note="react-day-picker 接受 date-fns locale 物件。週首日由 locale 物件決定,不以語言籠統判斷:zhTW 週日起、en-US 週日起,但 en-GB / de / fr 週一起(同樣是英文,en-US en-GB 週首日就不同)。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,DateGrid 不內建語言。"
308
308
  >
309
- <Demo title="zhTW(繁體中文 · 週日起)">
309
+ <Demo title="zhTW(繁體中文 · 週一起)">
310
310
  <DateGrid mode="single" defaultMonth={new Date(2026, 3, 1)} locale={zhTW} />
311
311
  </Demo>
312
312
  <Demo title="預設(en-US · 週日起)">
@@ -26,7 +26,7 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
26
26
 
27
27
  **Layout Family**:非上述 family — composite / multi-section(月份 caption + 星期標頭 + 日期網格 + nav 按鈕,多區塊組合)。
28
28
 
29
- **Storybook title 層級**:`Design System/Internal/DateGrid/*`(非 Components/,因為它是 DatePicker 的 internal primitive;對齊 CLAUDE.md「Internal vs Components 判斷 test」:無預設視覺 context、所有 consumer 透過 DatePicker )。
29
+ **Storybook title 層級**:`Design System/Internal/DateGrid/*`(非 Components/,因為它是 DatePicker 的 internal primitive;對齊 `.claude/rules/ui-development.md`「Public component vs Internal primitive canonical」(intent-based 判準):consumer `DatePicker` wrapper 取得,不直接 import 本元件)。
30
30
 
31
31
  **世界級命名對照(為什麼不叫 Calendar)**:
32
32
 
@@ -46,6 +46,8 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
46
46
 
47
47
  ## 何時用
48
48
 
49
+ DateGrid 是 internal primitive(見「定位」),一般 consumer 經 `DatePicker` 取得;以下為 DS 內部組合或進階 inline 場景:
50
+
49
51
  - **Inline 月曆顯示**:dashboard / 行事曆小卡 / 日期 filter bar
50
52
  - **DatePicker 浮層內嵌**:DatePicker 消費本元件作為選日 popup(見 `../DatePicker/date-picker.spec.md`)
51
53
  - **範圍選擇**:`mode="range"` 適用「from → to」場景(訂單日期範圍、查詢時段)
@@ -57,7 +59,7 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
57
59
  |------|------|------|
58
60
  | 日期輸入欄位 | `DatePicker` | DateGrid 是 inline,欄位需要 trigger + popup 結構 |
59
61
  | 純顯示單日期 | `<DatePicker mode="display">` / `Intl.DateTimeFormat` | 不需 interactive 月曆 |
60
- | 時間選擇(時分) | ⚠️ 未來 TimePicker | DateGrid 只處理日期層級 |
62
+ | 時間選擇(時分) | `TimePicker`(見 `../TimePicker/time-picker.spec.md`)| DateGrid 只處理日期層級 |
61
63
  | 事件行事曆(日程本) | 專用行事曆元件 | DateGrid 是日期選擇;事件日誌需要 event overlay / drag / week/month view 切換 |
62
64
 
63
65
  ---
@@ -70,6 +72,8 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
70
72
  | `multiple` | 可勾選多個不連續日期 | event 報名多日 |
71
73
  | `range` | from → to 連續範圍 | 訂單日期範圍 / 查詢時段 |
72
74
 
75
+ **range vs multiple 分界**:選的是「連續區間」(只在乎起迄兩端)→ `range`;選的是「各自獨立的日子」(可不連續、逐日增減)→ `multiple`。起迄日場景(訂單 / 查詢時段)固定走 `range`;簽核 / 報名這類逐日勾選走 `multiple`。
76
+
73
77
  ---
74
78
 
75
79
  ## 實作機制:classNames 鏡射 modifier keys(2026-04-21 AR43 修正)
@@ -99,10 +103,10 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
99
103
  | **today + selected** | 數字下方短圓桿(白) | bar 色切 `on-emphasis` | 選中藍底上藍 bar 隱形,必切白;以 state 疊加 selector 覆寫 |
100
104
  | **disabled** | 灰底 + 淡字 | `bg-disabled` + `fg-disabled` + `cursor-not-allowed` | 跟 Button disabled token 一致,不自創 palette |
101
105
  | **outside(非本月)**| 淡字(只文字) | `fg-muted` | 比 disabled 弱:outside 仍可 hover / 可點,純是「非焦點月份」的標示 |
102
- | **selected / range 端點** | 藍底白字圓 | button `primary` 底 + `on-emphasis` 字(cell `data-selected="true"`) | range_start / range_end 共用此視覺 |
103
- | **range 端點 cell bg** | 灰底半圓 track,**高度 = button** | `before:` pseudo `inset-y-0`(滿 cell 高度)+ `rounded-l/r-full` + start `left-0 -right-[2px]` / end `-left-[2px] right-0`(向 middle 外擴 2px bridge gap)(M8 對齊 Ant `cell-range-start::before { border-radius: 9999px 0 0 9999px }` — [ant-design picker style](https://github.com/ant-design/ant-design/blob/master/components/date-picker/style/panel.ts) `@benchmark-unverified` style file path,Material X / Apple / Google `@benchmark-unverified` visual)| 圓弧半徑 = button 半徑無錯位;舊版 cell-level bg 圓弧半徑 16px 比 button 14px 大 = 視覺 misalign |
104
- | **range track(中間)** | 灰底矩形,**高度 = button**(28×28 @ md)| `before:` pseudo `inset-y-0 -inset-x-[2px]` `bg-neutral-selected`(對齊 range_start/end pseudo + tsx L146-159 實作);button 透明顯露 track | track 高度跟 selected 圓一致,不留 2px「fat」邊;cell 寬度維持 32px → 相鄰 pseudo 接合連貫橫向 track |
105
- | **hover(未選中)** | 藍圈 outline(無 fill) | button hover ring 色 `primary`,寬度 1.5px,無 bg | 1.5px ring 對齊 Apple HIG `@benchmark-unverified` / Ant `@benchmark-unverified`(visual,non-source-citable) |
106
+ | **selected / range 端點** | 藍底白字圓 | button `primary` 底 + `on-emphasis` 字 | range_start / range_end 共用此視覺 |
107
+ | **range 端點 cell bg** | 灰底半圓 track,**高度 = button**,向 middle 外擴 2px bridge gap | `neutral-selected`;class 細節見「Range track canonical」+ tsx | 圓弧半徑 = button 半徑無錯位;舊版 cell-level bg 圓弧半徑 16px 比 button 14px 大 = 視覺 misalign |
108
+ | **range track(中間)** | 灰底矩形,**高度 = button**(28×28 @ md),左右各外擴 2px 接合相鄰 cell | `neutral-selected`;button 透明顯露 track(class 細節見 tsx)| track 高度跟 selected 圓一致,不留 2px「fat」邊;相鄰 pseudo 接合連貫橫向 track |
109
+ | **hover(未選中)** | 藍圈 outline(無 fill) | button hover ring 色 `primary`,無 bg(ring 寬度等 class 細節見 tsx)| ring 對齊 Apple HIG `@benchmark-unverified` / Ant `@benchmark-unverified`(visual,non-source-citable) |
106
110
 
107
111
  ## 組合狀態(state stacking order)
108
112
 
@@ -110,7 +114,7 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
110
114
  - range-start / range-end → selected 規則(cell 半圓 track + button 圓)
111
115
  - range-middle → track 規則(cell 灰底矩形 + button 透明)
112
116
  - today + range-middle → track(灰底)+ today bar(藍色仍可見,cell 未 selected)
113
- - hover 在 selected / range-middle 上被 ring-0 壓制(避免二次 hover 出現方框 bug)
117
+ - hover 在 selected / disabled 上被 ring-0 壓制(避免二次 hover 出現方框 bug);range-middle 的 button 透明顯露 track,hover ring 仍顯示(見 tsx `range_middle` 註解)
114
118
 
115
119
  ## Spacing canonical(2026-05-03 v8)
116
120
 
@@ -136,7 +140,7 @@ Prev/Next chevron 用 `<Button variant="text" size="xs" iconOnly>`(DS primitive
136
140
  - `fg-muted`(45%)專屬 dismiss / inline action / placeholder(spec.md 既有定義)
137
141
  - chevron nav 是 functional navigation,不是 dismiss → 不該套 fg-muted 自開新 tier
138
142
 
139
- 歷史(2026-05-03):v6-v8 我憑印象引「Ant chevron muted」(`@benchmark-unverified` 印象,non-cited claim)覆蓋 DS canonical(text-fg-muted 45%)→ user 4 輪糾正後撤回(M23 防再犯)。
143
+ 歷史(2026-05-03):v6-v8 曾以未驗證的「Ant chevron muted」印象覆蓋 DS canonical,已撤回(M23 防再犯)。
140
144
 
141
145
  ⚠️ RDP `PreviousMonthButton` override 必丟 `children`(RDP 把 `<Chevron>` 當 children 傳)否則 double svg(2026-05-03 v8 抓到 bug)。
142
146
 
@@ -147,9 +151,8 @@ Prev/Next chevron 用 `<Button variant="text" size="xs" iconOnly>`(DS primitive
147
151
  ## Range track canonical(2026-05-03 v8)
148
152
 
149
153
  對齊 Ant `cell-range-start::before { border-radius: 9999px 0 0 9999px }`(stadium pattern): <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
150
- - `range_start` cell pseudo:`before:left-0 -right-[2px] inset-y-0 rounded-l-full bg-neutral-selected`
151
- - `range_end` cell pseudo:鏡像 `rounded-r-full`
152
- - `range_middle` cell pseudo:`before:-inset-x-[2px] inset-y-0 bg-neutral-selected`(無 rounding)
154
+ - `range_start` / `range_end` cell pseudo:左 / 右半圓 stadium,向 middle 側外擴 2px bridge gap(class 細節見 tsx `range_start` / `range_end`)
155
+ - `range_middle` cell pseudo:滿 cell 高矩形、左右各外擴 2px,無 rounding(class 細節見 tsx)
153
156
  - pseudo 蓋全 cell + bridge 4px gap → button 圓的 corner triangle 看到 pseudo bg(對齊 button 圓的左/右半弧,無「凸出」)
154
157
  - `bg-neutral-selected`(semantic = neutral-2)— 對齊 TimePicker 選中項目樣式
155
158
 
@@ -173,7 +176,7 @@ react-day-picker v9 自動處理:
173
176
  - **Focus**:`autoFocus` prop 自動 focus 到選中日(或今天)
174
177
  - **Locale**:`locale` prop 控制週首日、星期標頭語言
175
178
 
176
- Consumer 無需額外處理,保留 react-day-picker API 即可。
179
+ **DS 自訂部分**:day button 的 focus ring 由本元件 classNames 覆寫為 DS canonical(`focus-visible:ring-2 ring-ring`,非 RDP 預設樣式);nav 按鈕為 DS `<Button>` 並帶 `aria-label`(上一個月 / 下一個月)。其餘 consumer 無需額外處理,保留 react-day-picker API 即可。
177
180
 
178
181
  ---
179
182
 
@@ -195,9 +198,9 @@ DateGrid 本元件是**對 `react-day-picker` 的 `<DayPicker>` 元件薄包裝*
195
198
 
196
199
  - **Disabled day**:`disabled` prop 走 react-day-picker matcher;disabled cell 視覺 `text-fg-disabled`(M24)、`cursor-not-allowed`、click 不觸發 onSelect、鍵盤導覽自動 skip。
197
200
  - **Loading(server-rendered grid)**:DateGrid 為 sync render(date math 在 client),非 async surface。consumer 若需 async disabled-dates fetch(如後端 holiday list),應先 disable trigger 直到 fetch 完成,DateGrid 開啟後立即 ready。
198
- - **Empty(全 disabled days)**:極端場景(所有日期都被 disabled matcher 命中),DateGrid 渲完整 grid 但全部 cell 為 disabled state,鍵盤焦點停留無導覽目標(react-day-picker v9 內建)。
201
+ - **Empty(全 disabled days)**:極端場景(所有日期都被 disabled matcher 命中),DateGrid 渲完整 grid 但全部 cell 為 disabled state,鍵盤焦點停留無導覽目標(react-day-picker v9 內建)。Enter / Space 在 disabled cell 上無動作不報錯(RDP DayButton 對 disabled day 渲染 native `disabled`,focus target 時改掛 `aria-disabled`),Tab 走 roving tabIndex 整個 grid 只停一格。
199
202
  - **Dark mode**:走 semantic token(primary / neutral / fg-muted)自動 adapt。
200
- - **Density**:DateGrid day cell 走 `h-field-sm w-[var(--field-height-sm)]`,**隨 density 縮放**(md = 28×28 / lg = 32×32,token `--field-height-sm` 在 `[data-density="lg"]` override 為 `2rem`),跟 popup 內 Input / Button 等 field 家族一起放大保持比例(見 L128 + L120)。
203
+ - **Density**:DateGrid day cell 走 `h-field-sm w-[var(--field-height-sm)]`,**隨 density 縮放**(md = 28×28 / lg = 32×32,token `--field-height-sm` 在 `[data-density="lg"]` override 為 `2rem`),跟 popup 內 Input / Button 等 field 家族一起放大保持比例(見 L128 + L120)。grid 寬度為 intrinsic(7 × cell + 4px gap + `p-3`),lg 下整體變寬;DateGrid 無內部 overflow / responsive 縮排機制,容器(Popover / parent)以內容寬呈現。
201
204
 
202
205
  ---
203
206
 
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @internal — DS-internal 單元(per `.claude/rules/ui-development.md` Public vs Internal canonical;spec frontmatter `isInternal`)。
3
+ * 不進 root barrel front-door;由 DatePicker wrap 消費,end-user app 請用 wrapper 元件。
4
+ */
1
5
  // @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
2
6
  // M22 retrofit DONE 2026-05-03 v11(real source URLs added inline at lines 38 + 111)
3
7
  import * as React from 'react'
@@ -17,8 +21,8 @@ import { Button } from '@/design-system/components/Button/button'
17
21
  * |------|------|
18
22
  * | Outer padding | `p-3`(12px 四邊對稱) |
19
23
  * | Nav + Month caption row | h-field-xs(24px)單行,chevron(xs)分居左右 / 月份置中垂直對齊 |
20
- * | Nav → Weekday gap | 12px(mt-3) |
21
- * | Weekday | text-body(14px)text-fg-secondary(neutral-8) |
24
+ * | Nav → Weekday gap | 12px(month_caption mb-3) |
25
+ * | Weekday | text-body(14px)text-foreground font-medium(neutral-9,同 caption 權重;撤銷 v3 fg-secondary) |
22
26
  * | Cell gap(水平 + 垂直)| 4px(gap-1) |
23
27
  * | Day cell size | h-field-sm w-[var(--field-height-sm)](28×28 md / 32×32 lg) |
24
28
  * | Day button | rounded-full 填滿 cell |
@@ -200,8 +204,8 @@ export const dateGridMeta = {
200
204
  },
201
205
  states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
202
206
  tokens: {
203
- bg: ['bg-disabled', 'bg-primary', 'bg-primary-hover', 'bg-transparent'],
204
- fg: ['text-fg-disabled', 'text-fg-muted', 'text-fg-secondary', 'text-foreground'],
207
+ bg: ['bg-disabled', 'bg-neutral-selected', 'bg-on-emphasis', 'bg-primary', 'bg-primary-hover', 'bg-transparent'],
208
+ fg: ['text-fg-disabled', 'text-fg-muted', 'text-foreground', 'text-on-emphasis'],
205
209
  ring: ['ring-primary', 'ring-ring'],
206
210
  },
207
211
  } as const