@qijenchen/design-system 0.1.0-beta.85 → 0.1.0-beta.86

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 (477) hide show
  1. package/AGENTS.md +210 -0
  2. package/CLAUDE.md +17 -191
  3. package/cli-init.mjs +30 -2
  4. package/dist/components/Accordion/accordion.d.ts +2 -2
  5. package/dist/components/Accordion/accordion.d.ts.map +1 -1
  6. package/dist/components/Accordion/accordion.js.map +1 -1
  7. package/dist/components/Avatar/avatar.js +1 -1
  8. package/dist/components/Avatar/avatar.js.map +1 -1
  9. package/dist/components/BulkActionBar/bulk-action-bar.d.ts +1 -1
  10. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  11. package/dist/components/BulkActionBar/bulk-action-bar.js +3 -3
  12. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  13. package/dist/components/Button/button-group.d.ts +2 -2
  14. package/dist/components/Button/button-group.d.ts.map +1 -1
  15. package/dist/components/Button/button-group.js +2 -2
  16. package/dist/components/Button/button-group.js.map +1 -1
  17. package/dist/components/Button/button.d.ts +2 -1
  18. package/dist/components/Button/button.d.ts.map +1 -1
  19. package/dist/components/Button/button.js +1 -1
  20. package/dist/components/Button/button.js.map +1 -1
  21. package/dist/components/Carousel/carousel.d.ts +14 -8
  22. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  23. package/dist/components/Carousel/carousel.js +64 -37
  24. package/dist/components/Carousel/carousel.js.map +1 -1
  25. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
  26. package/dist/components/Checkbox/checkbox-group.js +21 -14
  27. package/dist/components/Checkbox/checkbox-group.js.map +1 -1
  28. package/dist/components/Checkbox/checkbox.d.ts +2 -2
  29. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  30. package/dist/components/Checkbox/checkbox.js +49 -10
  31. package/dist/components/Checkbox/checkbox.js.map +1 -1
  32. package/dist/components/Combobox/combobox.d.ts +15 -6
  33. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  34. package/dist/components/Combobox/combobox.js +13 -7
  35. package/dist/components/Combobox/combobox.js.map +1 -1
  36. package/dist/components/Command/command.d.ts.map +1 -1
  37. package/dist/components/Command/command.js +11 -2
  38. package/dist/components/Command/command.js.map +1 -1
  39. package/dist/components/DataTable/cell-registry.d.ts +5 -5
  40. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  41. package/dist/components/DataTable/cell-registry.js +41 -38
  42. package/dist/components/DataTable/cell-registry.js.map +1 -1
  43. package/dist/components/DataTable/column-types.d.ts +1 -17
  44. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  45. package/dist/components/DataTable/column-types.js.map +1 -1
  46. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
  47. package/dist/components/DataTable/data-table-column-visibility-panel.js +71 -64
  48. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
  49. package/dist/components/DataTable/data-table-filter-panel.d.ts +0 -2
  50. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  51. package/dist/components/DataTable/data-table-filter-panel.js +3 -4
  52. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -1
  53. package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -2
  54. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  55. package/dist/components/DataTable/data-table-sort-manager.js +2 -2
  56. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
  57. package/dist/components/DataTable/data-table.d.ts +1 -1
  58. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  59. package/dist/components/DataTable/data-table.js +44 -32
  60. package/dist/components/DataTable/data-table.js.map +1 -1
  61. package/dist/components/DatePicker/date-picker.d.ts +3 -3
  62. package/dist/components/DatePicker/date-picker.js +4 -4
  63. package/dist/components/DatePicker/date-picker.js.map +1 -1
  64. package/dist/components/DescriptionList/description-list.d.ts +3 -3
  65. package/dist/components/DescriptionList/description-list.d.ts.map +1 -1
  66. package/dist/components/DescriptionList/description-list.js +6 -6
  67. package/dist/components/DescriptionList/description-list.js.map +1 -1
  68. package/dist/components/Dialog/dialog.d.ts +2 -2
  69. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  70. package/dist/components/Dialog/dialog.js.map +1 -1
  71. package/dist/components/DropdownMenu/dropdown-menu.d.ts +8 -3
  72. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  73. package/dist/components/DropdownMenu/dropdown-menu.js +7 -7
  74. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  75. package/dist/components/Field/field-context.d.ts +16 -10
  76. package/dist/components/Field/field-context.d.ts.map +1 -1
  77. package/dist/components/Field/field-context.js.map +1 -1
  78. package/dist/components/Field/field-types.d.ts +2 -2
  79. package/dist/components/Field/field-types.d.ts.map +1 -1
  80. package/dist/components/Field/field-types.js.map +1 -1
  81. package/dist/components/Field/field-wrapper.d.ts +20 -4
  82. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  83. package/dist/components/Field/field-wrapper.js +30 -31
  84. package/dist/components/Field/field-wrapper.js.map +1 -1
  85. package/dist/components/Field/field.d.ts +1 -1
  86. package/dist/components/Field/field.d.ts.map +1 -1
  87. package/dist/components/Field/field.js +25 -3
  88. package/dist/components/Field/field.js.map +1 -1
  89. package/dist/components/Field/use-form-validation.d.ts +1 -1
  90. package/dist/components/Field/use-form-validation.js.map +1 -1
  91. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  92. package/dist/components/FileItem/file-item.js +2 -5
  93. package/dist/components/FileItem/file-item.js.map +1 -1
  94. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  95. package/dist/components/FileUpload/file-upload.js +5 -1
  96. package/dist/components/FileUpload/file-upload.js.map +1 -1
  97. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  98. package/dist/components/FileViewer/file-viewer.js +2 -1
  99. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  100. package/dist/components/HoverCard/hover-card.d.ts +2 -2
  101. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  102. package/dist/components/HoverCard/hover-card.js +4 -2
  103. package/dist/components/HoverCard/hover-card.js.map +1 -1
  104. package/dist/components/InlineEdit/inline-edit.d.ts +23 -16
  105. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
  106. package/dist/components/InlineEdit/inline-edit.js +104 -62
  107. package/dist/components/InlineEdit/inline-edit.js.map +1 -1
  108. package/dist/components/Input/input.d.ts +1 -1
  109. package/dist/components/Input/input.d.ts.map +1 -1
  110. package/dist/components/Input/input.js +6 -6
  111. package/dist/components/Input/input.js.map +1 -1
  112. package/dist/components/LinkInput/link-input.d.ts +5 -5
  113. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  114. package/dist/components/LinkInput/link-input.js +3 -3
  115. package/dist/components/LinkInput/link-input.js.map +1 -1
  116. package/dist/components/Notice/notice.d.ts +17 -1
  117. package/dist/components/Notice/notice.d.ts.map +1 -1
  118. package/dist/components/Notice/notice.js +7 -1
  119. package/dist/components/Notice/notice.js.map +1 -1
  120. package/dist/components/NumberInput/number-input.d.ts +1 -1
  121. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  122. package/dist/components/NumberInput/number-input.js +12 -1
  123. package/dist/components/NumberInput/number-input.js.map +1 -1
  124. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +1 -1
  125. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
  126. package/dist/components/PeoplePicker/people-picker.d.ts +5 -5
  127. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  128. package/dist/components/PeoplePicker/people-picker.js +7 -5
  129. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  130. package/dist/components/PeoplePicker/person-display.d.ts +1 -1
  131. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  132. package/dist/components/ProfileCard/profile-card.d.ts +1 -1
  133. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  134. package/dist/components/RadioGroup/radio-group.d.ts +3 -3
  135. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  136. package/dist/components/RadioGroup/radio-group.js +1 -1
  137. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  138. package/dist/components/Rating/rating.d.ts.map +1 -1
  139. package/dist/components/Rating/rating.js +4 -0
  140. package/dist/components/Rating/rating.js.map +1 -1
  141. package/dist/components/ScrollArea/scroll-area.d.ts +3 -2
  142. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  143. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  144. package/dist/components/SegmentedControl/segmented-control.d.ts +4 -3
  145. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  146. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  147. package/dist/components/Select/select.d.ts +16 -6
  148. package/dist/components/Select/select.d.ts.map +1 -1
  149. package/dist/components/Select/select.js +17 -5
  150. package/dist/components/Select/select.js.map +1 -1
  151. package/dist/components/SelectMenu/select-menu.d.ts +17 -1
  152. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  153. package/dist/components/SelectMenu/select-menu.js +17 -3
  154. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  155. package/dist/components/SelectionControl/boolean-value.d.ts +1 -1
  156. package/dist/components/SelectionControl/boolean-value.js.map +1 -1
  157. package/dist/components/Sheet/sheet.d.ts +2 -2
  158. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  159. package/dist/components/Sheet/sheet.js.map +1 -1
  160. package/dist/components/Sidebar/sidebar.d.ts +1 -1
  161. package/dist/components/Sidebar/sidebar.js +2 -2
  162. package/dist/components/Sidebar/sidebar.js.map +1 -1
  163. package/dist/components/Slider/slider.d.ts.map +1 -1
  164. package/dist/components/Slider/slider.js +6 -3
  165. package/dist/components/Slider/slider.js.map +1 -1
  166. package/dist/components/Steps/steps.d.ts +6 -4
  167. package/dist/components/Steps/steps.d.ts.map +1 -1
  168. package/dist/components/Steps/steps.js +19 -5
  169. package/dist/components/Steps/steps.js.map +1 -1
  170. package/dist/components/Switch/switch.d.ts +4 -4
  171. package/dist/components/Switch/switch.d.ts.map +1 -1
  172. package/dist/components/Switch/switch.js +3 -1
  173. package/dist/components/Switch/switch.js.map +1 -1
  174. package/dist/components/Tabs/tabs.d.ts +1 -1
  175. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  176. package/dist/components/Tabs/tabs.js +73 -23
  177. package/dist/components/Tabs/tabs.js.map +1 -1
  178. package/dist/components/Tag/tag.d.ts +3 -1
  179. package/dist/components/Tag/tag.d.ts.map +1 -1
  180. package/dist/components/Tag/tag.js +2 -2
  181. package/dist/components/Tag/tag.js.map +1 -1
  182. package/dist/components/Textarea/textarea.d.ts +4 -4
  183. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  184. package/dist/components/Textarea/textarea.js +15 -15
  185. package/dist/components/Textarea/textarea.js.map +1 -1
  186. package/dist/components/TimePicker/time-picker.d.ts +4 -4
  187. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  188. package/dist/components/TimePicker/time-picker.js +8 -5
  189. package/dist/components/TimePicker/time-picker.js.map +1 -1
  190. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  191. package/dist/components/Tooltip/tooltip.js +27 -23
  192. package/dist/components/Tooltip/tooltip.js.map +1 -1
  193. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  194. package/dist/components/TreeView/tree-view.js +16 -0
  195. package/dist/components/TreeView/tree-view.js.map +1 -1
  196. package/dist/index.d.ts +7 -7
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +6 -13
  199. package/dist/index.js.map +1 -1
  200. package/dist/lib/drag-visual.d.ts +2 -2
  201. package/dist/lib/drag-visual.js.map +1 -1
  202. package/dist/lib/utils.d.ts +1 -0
  203. package/dist/lib/utils.d.ts.map +1 -1
  204. package/dist/lib/utils.js +21 -1
  205. package/dist/lib/utils.js.map +1 -1
  206. package/dist/patterns/element-anatomy/item-anatomy.d.ts +2 -0
  207. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  208. package/dist/patterns/element-anatomy/item-anatomy.js +2 -2
  209. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  210. package/dist/tokens/categorical-color.d.ts +3 -3
  211. package/dist/tokens/categorical-color.d.ts.map +1 -1
  212. package/dist/tokens/categorical-color.js +2 -2
  213. package/dist/tokens/categorical-color.js.map +1 -1
  214. package/ds-canonical/fork/AGENTS.md +213 -0
  215. package/ds-canonical/fork/codex/agents/skills/independent-review/SKILL.md +33 -0
  216. package/ds-canonical/fork/codex/hooks.json +16 -0
  217. package/ds-canonical/fork/governance.lock +22 -7
  218. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +22 -1
  219. package/ds-canonical/fork/hooks/inject_deploy_url_after_push.sh +14 -2
  220. package/ds-canonical/fork/manifest.json +10 -1
  221. package/ds-canonical/fork/preamble.md +3 -2
  222. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +7 -7
  223. package/ds-canonical/fork/skills/ux-audit/SKILL.md +1 -1
  224. package/ds-canonical/fork/skills/visual-audit/SKILL.md +0 -1
  225. package/ds-canonical/hooks/check_codex_brief_invariants.sh +9 -3
  226. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +22 -1
  227. package/ds-canonical/hooks/check_overlay_open_focus_escape_probe.sh +11 -2
  228. package/ds-canonical/hooks/check_plugin_fork_health.sh +17 -1
  229. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +21 -4
  230. package/ds-canonical/hooks/inject_deploy_url_after_push.sh +14 -2
  231. package/ds-canonical/hooks/session_start_governance_check.sh +10 -2
  232. package/ds-canonical/references/certified-surfaces.md +20 -0
  233. package/ds-canonical/references/preflight-gate-baseline.json +5 -0
  234. package/ds-canonical/references/principle-dim-map.json +20 -2
  235. package/ds-canonical/references/props-naming.md +2 -1
  236. package/ds-canonical/references/ssot-index.md +2 -2
  237. package/ds-canonical/references/story-baseline-registry.json +2 -2
  238. package/ds-canonical/rules/story-rules.md +1 -1
  239. package/ds-canonical/rules/ui-development.md +2 -1
  240. package/ds-canonical/skills/codex-collab/SKILL.md +7 -7
  241. package/ds-canonical/skills/codex-collab/references/brief-template.md +5 -1
  242. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  243. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +5 -5
  244. package/ds-canonical/skills/design-system-audit/SKILL.md +5 -5
  245. package/ds-canonical/skills/product-ui-audit/SKILL.md +7 -7
  246. package/ds-canonical/skills/ux-audit/SKILL.md +1 -1
  247. package/ds-canonical/skills/visual-audit/SKILL.md +0 -1
  248. package/ds-story-manifest.json +21 -21
  249. package/llms-full.txt +3 -3
  250. package/llms.txt +1 -1
  251. package/package.json +2 -1
  252. package/src/components/Accordion/accordion.anatomy.stories.tsx +11 -11
  253. package/src/components/Accordion/accordion.principles.stories.tsx +21 -6
  254. package/src/components/Accordion/accordion.spec.md +10 -1
  255. package/src/components/Accordion/accordion.stories.tsx +10 -5
  256. package/src/components/Accordion/accordion.tsx +7 -2
  257. package/src/components/Alert/alert.principles.stories.tsx +2 -8
  258. package/src/components/AppShell/app-shell.anatomy.stories.tsx +19 -13
  259. package/src/components/AppShell/app-shell.principles.stories.tsx +21 -21
  260. package/src/components/AppShell/app-shell.spec.md +4 -0
  261. package/src/components/AppShell/app-shell.stories.tsx +4 -5
  262. package/src/components/Avatar/avatar.tsx +1 -1
  263. package/src/components/Badge/badge.spec.md +2 -2
  264. package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +7 -3
  265. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +4 -1
  266. package/src/components/Breadcrumb/breadcrumb.stories.tsx +1 -1
  267. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +6 -6
  268. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +18 -6
  269. package/src/components/BulkActionBar/bulk-action-bar.spec.md +15 -5
  270. package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +8 -24
  271. package/src/components/BulkActionBar/bulk-action-bar.tsx +4 -4
  272. package/src/components/Button/button-group.tsx +4 -4
  273. package/src/components/Button/button.anatomy.stories.tsx +26 -7
  274. package/src/components/Button/button.principles.stories.tsx +1 -1
  275. package/src/components/Button/button.spec.md +2 -2
  276. package/src/components/Button/button.stories.tsx +22 -28
  277. package/src/components/Button/button.tsx +2 -1
  278. package/src/components/Calendar/calendar.anatomy.stories.tsx +1 -1
  279. package/src/components/Calendar/calendar.spec.md +1 -1
  280. package/src/components/Carousel/carousel.spec.md +17 -1
  281. package/src/components/Carousel/carousel.tsx +93 -42
  282. package/src/components/Checkbox/checkbox-group.tsx +26 -15
  283. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +3 -3
  284. package/src/components/Checkbox/checkbox.spec.md +12 -3
  285. package/src/components/Checkbox/checkbox.stories.tsx +4 -4
  286. package/src/components/Checkbox/checkbox.tsx +79 -19
  287. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +5 -5
  288. package/src/components/Coachmark/coachmark.principles.stories.tsx +1 -1
  289. package/src/components/Combobox/combobox.anatomy.stories.tsx +11 -4
  290. package/src/components/Combobox/combobox.principles.stories.tsx +10 -11
  291. package/src/components/Combobox/combobox.spec.md +6 -2
  292. package/src/components/Combobox/combobox.stories.tsx +9 -36
  293. package/src/components/Combobox/combobox.tsx +42 -27
  294. package/src/components/Command/command.spec.md +3 -3
  295. package/src/components/Command/command.tsx +9 -2
  296. package/src/components/DataTable/cell-registry.tsx +75 -76
  297. package/src/components/DataTable/column-types.ts +4 -17
  298. package/src/components/DataTable/data-table-column-visibility-panel.tsx +20 -7
  299. package/src/components/DataTable/data-table-filter-panel.tsx +6 -6
  300. package/src/components/DataTable/data-table-interaction-layer.tsx +3 -3
  301. package/src/components/DataTable/data-table-sort-manager.tsx +2 -2
  302. package/src/components/DataTable/data-table.anatomy.stories.tsx +25 -24
  303. package/src/components/DataTable/data-table.css +2 -3
  304. package/src/components/DataTable/data-table.principles.stories.tsx +17 -11
  305. package/src/components/DataTable/data-table.spec.md +7 -7
  306. package/src/components/DataTable/data-table.stories.tsx +39 -29
  307. package/src/components/DataTable/data-table.tsx +90 -67
  308. package/src/components/DataTable/filter-operators.spec.md +2 -0
  309. package/src/components/DateGrid/date-grid.spec.md +1 -1
  310. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +9 -9
  311. package/src/components/DatePicker/date-picker.principles.stories.tsx +4 -4
  312. package/src/components/DatePicker/date-picker.spec.md +9 -9
  313. package/src/components/DatePicker/date-picker.stories.tsx +9 -9
  314. package/src/components/DatePicker/date-picker.tsx +13 -13
  315. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +5 -5
  316. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  317. package/src/components/DescriptionList/description-list.spec.md +12 -12
  318. package/src/components/DescriptionList/description-list.stories.tsx +3 -3
  319. package/src/components/DescriptionList/description-list.tsx +10 -10
  320. package/src/components/Dialog/dialog.tsx +4 -1
  321. package/src/components/DropdownMenu/dropdown-menu.tsx +27 -14
  322. package/src/components/Field/field-context.ts +17 -11
  323. package/src/components/Field/field-controls.spec.md +44 -37
  324. package/src/components/Field/field-types.ts +14 -12
  325. package/src/components/Field/field-wrapper.tsx +59 -43
  326. package/src/components/Field/field.anatomy.stories.tsx +6 -6
  327. package/src/components/Field/field.principles.stories.tsx +5 -28
  328. package/src/components/Field/field.spec.md +4 -4
  329. package/src/components/Field/field.stories.tsx +103 -72
  330. package/src/components/Field/field.tsx +36 -4
  331. package/src/components/Field/form-validation.spec.md +2 -0
  332. package/src/components/Field/use-form-validation.ts +1 -1
  333. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +3 -3
  334. package/src/components/FieldControlGroup/field-control-group.spec.md +3 -3
  335. package/src/components/FileItem/file-item.tsx +10 -8
  336. package/src/components/FileUpload/file-upload.principles.stories.tsx +7 -7
  337. package/src/components/FileUpload/file-upload.spec.md +3 -2
  338. package/src/components/FileUpload/file-upload.tsx +5 -1
  339. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +1 -1
  340. package/src/components/FileViewer/file-viewer.principles.stories.tsx +1 -1
  341. package/src/components/FileViewer/file-viewer.spec.md +1 -1
  342. package/src/components/FileViewer/file-viewer.stories.tsx +1 -1
  343. package/src/components/FileViewer/file-viewer.tsx +3 -2
  344. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -4
  345. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -1
  346. package/src/components/HoverCard/hover-card.spec.md +2 -2
  347. package/src/components/HoverCard/hover-card.tsx +4 -2
  348. package/src/components/InlineEdit/inline-edit.anatomy.stories.tsx +184 -0
  349. package/src/components/InlineEdit/inline-edit.principles.stories.tsx +142 -0
  350. package/src/components/InlineEdit/inline-edit.spec.md +71 -46
  351. package/src/components/InlineEdit/inline-edit.stories.tsx +20 -19
  352. package/src/components/InlineEdit/inline-edit.tsx +211 -125
  353. package/src/components/Input/input.anatomy.stories.tsx +15 -15
  354. package/src/components/Input/input.principles.stories.tsx +3 -3
  355. package/src/components/Input/input.spec.md +4 -4
  356. package/src/components/Input/input.stories.tsx +3 -3
  357. package/src/components/Input/input.tsx +13 -13
  358. package/src/components/LinkInput/link-input.anatomy.stories.tsx +2 -2
  359. package/src/components/LinkInput/link-input.principles.stories.tsx +1 -1
  360. package/src/components/LinkInput/link-input.spec.md +6 -2
  361. package/src/components/LinkInput/link-input.stories.tsx +8 -8
  362. package/src/components/LinkInput/link-input.tsx +21 -19
  363. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  364. package/src/components/Notice/notice.tsx +8 -2
  365. package/src/components/NumberInput/number-input.anatomy.stories.tsx +6 -6
  366. package/src/components/NumberInput/number-input.principles.stories.tsx +4 -4
  367. package/src/components/NumberInput/number-input.spec.md +6 -6
  368. package/src/components/NumberInput/number-input.stories.tsx +4 -4
  369. package/src/components/NumberInput/number-input.tsx +17 -5
  370. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +8 -4
  371. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +6 -7
  372. package/src/components/OverflowIndicator/overflow-indicator.spec.md +1 -1
  373. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +6 -30
  374. package/src/components/PeoplePicker/avatar-stack-overflow.ts +1 -1
  375. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +13 -10
  376. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +5 -1
  377. package/src/components/PeoplePicker/people-picker.stories.tsx +5 -5
  378. package/src/components/PeoplePicker/people-picker.tsx +39 -20
  379. package/src/components/PeoplePicker/person-display.tsx +3 -3
  380. package/src/components/Popover/popover.anatomy.stories.tsx +10 -7
  381. package/src/components/Popover/popover.principles.stories.tsx +49 -28
  382. package/src/components/Popover/popover.spec.md +4 -2
  383. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  384. package/src/components/ProfileCard/profile-card.tsx +1 -1
  385. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +14 -13
  386. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +8 -23
  387. package/src/components/ProgressBar/progress-bar.stories.tsx +8 -2
  388. package/src/components/README.md +1 -0
  389. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +8 -3
  390. package/src/components/RadioGroup/radio-group.stories.tsx +3 -3
  391. package/src/components/RadioGroup/radio-group.tsx +19 -14
  392. package/src/components/Rating/rating.anatomy.stories.tsx +1 -1
  393. package/src/components/Rating/rating.principles.stories.tsx +3 -3
  394. package/src/components/Rating/rating.spec.md +2 -2
  395. package/src/components/Rating/rating.stories.tsx +4 -18
  396. package/src/components/Rating/rating.tsx +5 -1
  397. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  398. package/src/components/ScrollArea/scroll-area.spec.md +1 -1
  399. package/src/components/ScrollArea/scroll-area.tsx +5 -2
  400. package/src/components/SegmentedControl/segmented-control.principles.stories.tsx +4 -1
  401. package/src/components/SegmentedControl/segmented-control.spec.md +5 -10
  402. package/src/components/SegmentedControl/segmented-control.tsx +6 -3
  403. package/src/components/Select/select.anatomy.stories.tsx +13 -7
  404. package/src/components/Select/select.principles.stories.tsx +3 -3
  405. package/src/components/Select/select.spec.md +9 -1
  406. package/src/components/Select/select.stories.tsx +41 -27
  407. package/src/components/Select/select.tsx +44 -26
  408. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +44 -26
  409. package/src/components/SelectMenu/select-menu.principles.stories.tsx +0 -1
  410. package/src/components/SelectMenu/select-menu.stories.tsx +7 -19
  411. package/src/components/SelectMenu/select-menu.tsx +38 -5
  412. package/src/components/SelectionControl/boolean-value.tsx +2 -2
  413. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
  414. package/src/components/SelectionControl/selection-item.principles.stories.tsx +4 -4
  415. package/src/components/Separator/separator.principles.stories.tsx +1 -1
  416. package/src/components/Sheet/sheet.principles.stories.tsx +5 -3
  417. package/src/components/Sheet/sheet.tsx +4 -1
  418. package/src/components/Sidebar/sidebar.tsx +1 -1
  419. package/src/components/Slider/slider.anatomy.stories.tsx +5 -4
  420. package/src/components/Slider/slider.principles.stories.tsx +6 -6
  421. package/src/components/Slider/slider.spec.md +13 -1
  422. package/src/components/Slider/slider.stories.tsx +44 -32
  423. package/src/components/Slider/slider.tsx +13 -4
  424. package/src/components/Steps/steps.anatomy.stories.tsx +7 -7
  425. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  426. package/src/components/Steps/steps.spec.md +4 -2
  427. package/src/components/Steps/steps.stories.tsx +4 -56
  428. package/src/components/Steps/steps.tsx +31 -7
  429. package/src/components/Switch/switch.anatomy.stories.tsx +3 -3
  430. package/src/components/Switch/switch.principles.stories.tsx +1 -1
  431. package/src/components/Switch/switch.spec.md +4 -4
  432. package/src/components/Switch/switch.stories.tsx +3 -3
  433. package/src/components/Switch/switch.tsx +16 -10
  434. package/src/components/Tabs/tabs.anatomy.stories.tsx +6 -0
  435. package/src/components/Tabs/tabs.principles.stories.tsx +10 -2
  436. package/src/components/Tabs/tabs.spec.md +5 -2
  437. package/src/components/Tabs/tabs.stories.tsx +36 -44
  438. package/src/components/Tabs/tabs.tsx +101 -36
  439. package/src/components/Tag/tag.anatomy.stories.tsx +2 -2
  440. package/src/components/Tag/tag.principles.stories.tsx +4 -4
  441. package/src/components/Tag/tag.spec.md +3 -1
  442. package/src/components/Tag/tag.tsx +5 -3
  443. package/src/components/Textarea/textarea.anatomy.stories.tsx +6 -6
  444. package/src/components/Textarea/textarea.spec.md +5 -5
  445. package/src/components/Textarea/textarea.tsx +24 -24
  446. package/src/components/TimePicker/time-picker.anatomy.stories.tsx +12 -11
  447. package/src/components/TimePicker/time-picker.principles.stories.tsx +37 -44
  448. package/src/components/TimePicker/time-picker.spec.md +6 -5
  449. package/src/components/TimePicker/time-picker.stories.tsx +3 -3
  450. package/src/components/TimePicker/time-picker.tsx +24 -14
  451. package/src/components/Toast/toast.principles.stories.tsx +1 -1
  452. package/src/components/Toast/toast.stories.tsx +1 -1
  453. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +15 -6
  454. package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -4
  455. package/src/components/Tooltip/tooltip.spec.md +9 -3
  456. package/src/components/Tooltip/tooltip.stories.tsx +1 -1
  457. package/src/components/Tooltip/tooltip.tsx +12 -2
  458. package/src/components/TreeView/tree-view.anatomy.stories.tsx +16 -14
  459. package/src/components/TreeView/tree-view.principles.stories.tsx +44 -11
  460. package/src/components/TreeView/tree-view.spec.md +8 -6
  461. package/src/components/TreeView/tree-view.stories.tsx +9 -43
  462. package/src/components/TreeView/tree-view.tsx +36 -0
  463. package/src/index.ts +13 -10
  464. package/src/lib/drag-visual.ts +2 -2
  465. package/src/lib/utils.ts +19 -0
  466. package/src/patterns/element-anatomy/inline-action.spec.md +1 -1
  467. package/src/patterns/element-anatomy/item-anatomy.tsx +4 -2
  468. package/src/patterns/header-canonical/header-canonical.spec.md +9 -0
  469. package/src/patterns/header-canonical/header-canonical.stories.tsx +31 -5
  470. package/src/tokens/categorical-color.ts +5 -5
  471. package/src/tokens/color/color.spec.md +4 -4
  472. package/src/tokens/color/primitives.css +9 -2
  473. package/src/tokens/opacity/opacity.spec.md +1 -1
  474. package/src/tokens/orphan-tokens.spec.md +1 -1
  475. package/src/tokens/typography/typography.spec.md +2 -0
  476. package/src/tokens/uiSize/uiSize.css +5 -0
  477. package/src/tokens/uiSize/uiSize.spec.md +1 -1
@@ -4,7 +4,7 @@
4
4
  //
5
5
  // 對齊 M17 SSOT consolidation + audit recommendation:
6
6
  // 原 `renderTypedValue` switch + `EditableCellContent` switch 兩條平行 type-switch 已 collapse
7
- // 為**一張 type → cell component** registry。每個 cell component 同時處理 display / edit mode,
7
+ // 為**一張 type → cell component** registry。每個 cell component 同時處理 view / edit mode,
8
8
  // 靠底層 Field control 的 `mode` prop 切換。
9
9
  //
10
10
  // 設計原則:
@@ -19,7 +19,7 @@
19
19
  import * as React from 'react'
20
20
  import type { ComponentType } from 'react'
21
21
  import { Pencil } from 'lucide-react'
22
- import { cn } from '@/lib/utils'
22
+ import { cn, lineClampClass } from '@/lib/utils'
23
23
  import type { ColumnType } from './column-types'
24
24
  import { Input as InputPublic } from '@/design-system/components/Input/input'
25
25
  import { Textarea as TextareaPublic } from '@/design-system/components/Textarea/textarea'
@@ -55,7 +55,7 @@ const Checkbox = CheckboxPublic as WithFieldVariantInternal<typeof CheckboxPubli
55
55
 
56
56
  // ── Types ────────────────────────────────────────────────────────────────────
57
57
 
58
- export type CellMode = 'display' | 'edit'
58
+ export type CellMode = 'view' | 'edit'
59
59
  export type CellSize = 'sm' | 'md' | 'lg'
60
60
 
61
61
  export interface CellComponentProps {
@@ -65,13 +65,13 @@ export interface CellComponentProps {
65
65
  meta: Record<string, any>
66
66
  mode: CellMode
67
67
  size: CellSize
68
+ /** 該 cell 的 accessible name(= 欄標題)。naked Field 控件在 cell 內無 FieldLabel,
69
+ * 漏此名 → editor 成無名控件(axe aria-input-field-name / select-name)。由 renderCellContent
70
+ * 從 columnDef.header 解析後注入。對齊 AG Grid / MUI X「editor aria-label = column headerName」。 */
71
+ ariaLabel?: string
68
72
  autoRowHeight: boolean
69
73
  /** 該 cell 是否可編。replaces 舊 `meta._editable` 私有 flag(Phase C M1 hack 移除)。 */
70
74
  isEditable?: boolean
71
- /** 2026-05-13:cell 是否 disabled(state overlay,orthogonal to display/edit lifecycle)。
72
- * per codex Q3 verdict:不擴 CellMode='disabled',加 prop。各 Cell function 收 true 時
73
- * 傳 `mode='disabled'` 給 inner Field control,各 Field 內部走具體 disabled token(非 wrapper opacity)。 */
74
- isDisabled?: boolean
75
75
  /** Cell 進 edit mode → 提交新值(blur / Enter / option select 都觸發)— 提交後**自動 exit edit**。
76
76
  * 適用 single-shot commit:string / number / select(single)/ person(single)/ date / time / boolean / url。 */
77
77
  onCommit?: (next: unknown) => void
@@ -112,44 +112,41 @@ function makeKeyHandler(
112
112
 
113
113
  const sizeForInput = (size: CellSize): CellSize => size
114
114
 
115
- /** 2026-05-13 Q3 helper(per codex Q3 verdict):cell display + isDisabled Field mode='disabled'。
116
- * Cell display lifecycle 不擴 CellMode='disabled',而是各 Cell display branch 翻譯 isDisabled
117
- * → Field mode='disabled' prop。inner Field 內部走具體 disabled token(text-fg-disabled / bg-disabled 等),
118
- * 非 wrapper blanket opacity-disabled 逃生艙(per color.spec.md:729)。 */
119
- const displayOrDisabled = (isDisabled?: boolean): 'display' | 'disabled' =>
120
- isDisabled ? 'disabled' : 'display'
115
+ // 2026-07-16 round16:cell「disabled」態廢除(世界級 grid disabled cell MUI X / AG Grid /
116
+ // Handsontable 皆只有 editable/readonly;meta.disabled 全庫 0 消費)。cell view 態一律 mode="view",
117
+ // 鎖定用 `editable:(row)=>false` 閘(= isCellEditable 模型)。原 displayOrDisabled helper 已移除。
121
118
 
122
119
  // ── Cell Components ──────────────────────────────────────────────────────────
123
120
 
124
- function StringCell({ value, meta, mode, size, isDisabled, autoRowHeight, onCommit, onCancel, onDraft }: CellComponentProps) {
121
+ function StringCell({ value, meta, mode, size, autoRowHeight, onCommit, onCancel, onDraft, ariaLabel }: CellComponentProps) {
125
122
  // 2026-05-14 I9 fix(per codex+Layer A 共識):meta.maxLines opt-in line-clamp。
126
- // display autoRow 用 Tailwind arbitrary line-clamp 支援 N rows;edit textarea field-sizing
123
+ // view autoRow 用 Tailwind arbitrary line-clamp 支援 N rows;edit textarea field-sizing
127
124
  // 已 auto-grow to content,natural match clamp。
128
125
  // 2026-05-16 Round 5 audit Dim 27 fix:narrow type 取代 `as any` cast。
129
126
  const maxLines: number | undefined = (meta as { maxLines?: number } | undefined)?.maxLines
130
- const clampClass = maxLines && autoRowHeight ? `line-clamp-[${maxLines}]` : undefined
127
+ const clampClass = autoRowHeight ? lineClampClass(maxLines) : undefined
131
128
  // string type canonical(2026-05-05 v2 user 校正:input space ≥ display space):
132
- // - autoRowHeight: Textarea(display + edit)— display wrap text 撐高 row,edit textarea
129
+ // - autoRowHeight: Textarea(view + edit)— view wrap text 撐高 row,edit textarea
133
130
  // 多行輸入、`!h-full` 填 cell。對齊 Notion long-text cell canonical。
134
- // - fixed: Input(display + edit)— 單行 truncate display,單行 input edit;Field naked intrinsic
135
- // 高 = cell 高 = h-field-md,文字位置 display↔edit 完全一致。對齊 AG Grid / Material X-Grid。
131
+ // - fixed: Input(view + edit)— 單行 truncate view,單行 input edit;Field naked intrinsic
132
+ // 高 = cell 高 = h-field-md,文字位置 view↔edit 完全一致。對齊 AG Grid / Material X-Grid。
136
133
  // - autoRowHeight 是 table 框架決定(consumer 不需 per-column 設 meta.wrap)。
137
134
  // - 互動(Textarea):Esc cancel / Cmd|Ctrl+Enter commit / blur commit;Enter 保留換行
138
135
  // - 互動(Input):Esc cancel / Enter commit / blur commit
139
136
  const v = value != null ? String(value) : ''
140
- if (mode === 'display') {
137
+ if (mode === 'view') {
141
138
  // size 必傳:DataTable cell 字級隨 size 變(sm/md text-body / lg text-body-lg),
142
139
  // 對齊 Field family size→font SSOT(field-wrapper.tsx:60-64)。漏傳 → fallback md → lg 表格
143
140
  // 字卡 14px 跟 Select/Date 等有傳 size 的 cell 不一致(2026-06-08 user 抓 frozen string 欄字偏小)。
144
141
  return autoRowHeight
145
- ? <Textarea variant="naked" mode={displayOrDisabled(isDisabled)} value={v} size={size} className={clampClass} />
146
- : <Input variant="naked" mode={displayOrDisabled(isDisabled)} value={v} size={size} />
142
+ ? <Textarea variant="naked" mode="view" value={v} size={size} className={clampClass} aria-label={ariaLabel} />
143
+ : <Input variant="naked" mode="view" value={v} size={size} aria-label={ariaLabel} />
147
144
  }
148
145
  if (autoRowHeight) {
149
146
  // 2026-05-14 I8 fix(per codex verdict + user 抓「edit cell shrink」):
150
147
  // 原 `wrapRows = value.length / 40` 字元估算不準(對應實際 column width 不同
151
148
  // → cell 進 edit shrink)。改 CSS `field-sizing: content`(Chrome 123+ / FF 122+ /
152
- // Safari 17+)讓 textarea 自動 grow to content,匹配 display wrap 真實高度。
149
+ // Safari 17+)讓 textarea 自動 grow to content,匹配 view wrap 真實高度。
153
150
  // Fallback rows 仍保留給舊 browser(rows attr 在 field-sizing 支援時被覆蓋)。
154
151
  const newlineRows = (v.match(/\n/g) || []).length + 1
155
152
  const wrapRows = Math.ceil(v.length / 40)
@@ -158,6 +155,7 @@ function StringCell({ value, meta, mode, size, isDisabled, autoRowHeight, onComm
158
155
  <Textarea
159
156
  autoFocus
160
157
  variant="naked"
158
+ aria-label={ariaLabel}
161
159
  size={sizeForInput(size)}
162
160
  rows={estimateRows}
163
161
  defaultValue={v}
@@ -180,6 +178,7 @@ function StringCell({ value, meta, mode, size, isDisabled, autoRowHeight, onComm
180
178
  <Input
181
179
  autoFocus
182
180
  variant="naked"
181
+ aria-label={ariaLabel}
183
182
  size={sizeForInput(size)}
184
183
  defaultValue={v}
185
184
  onChange={(e) => onDraft?.(e.target.value)}
@@ -189,20 +188,21 @@ function StringCell({ value, meta, mode, size, isDisabled, autoRowHeight, onComm
189
188
  )
190
189
  }
191
190
 
192
- function NumberCell({ value, meta, mode, size, isDisabled, onCommit, onCancel, onDraft }: CellComponentProps) {
191
+ function NumberCell({ value, meta, mode, size, onCommit, onCancel, onDraft, ariaLabel }: CellComponentProps) {
193
192
  // currency 透過 columnType-aware prefix:type='currency' → 預設 '$'(可 override)
194
193
  const isCurrency = meta?.type === 'currency'
195
194
  const prefix = isCurrency ? (meta?.prefix ?? '$') : meta?.prefix
196
- // React #310 fix:useState 必在 display early-return 前無條件呼叫。同一 memo'd cell instance
197
- // 在 display↔edit 切換時被重用(render site 無 key={mode},data-table.tsx:1352),hook 數量不可變,
195
+ // React #310 fix:useState 必在 view early-return 前無條件呼叫。同一 memo'd cell instance
196
+ // 在 view↔edit 切換時被重用(render site 無 key={mode},data-table.tsx:1352),hook 數量不可變,
198
197
  // 否則 Rules of Hooks violation → React #310 crash。對齊 combobox/select hoist pattern。
199
198
  const initial = typeof value === 'number' ? value : null
200
199
  const [localValue, setLocalValue] = React.useState<number | null>(initial)
201
- if (mode === 'display') {
200
+ if (mode === 'view') {
202
201
  return (
203
202
  <NumberInput
204
203
  variant="naked"
205
- mode={displayOrDisabled(isDisabled)}
204
+ mode="view"
205
+ aria-label={ariaLabel}
206
206
  value={value as number | null}
207
207
  // size 必傳(同 StringCell)— currency/number cell 字級隨 DataTable size 變,對齊 Field SSOT。
208
208
  size={size}
@@ -215,13 +215,14 @@ function NumberCell({ value, meta, mode, size, isDisabled, onCommit, onCancel, o
215
215
  }
216
216
  // Edit mode value pre-fill canonical(2026-05-05):NumberInput edit 強制 controlled
217
217
  // (`value={value ?? ''}`)— 若 NumberCell 以 `defaultValue` 傳入,NumberInput value=undefined → ''
218
- // empty。對齊 cell-as-input「edit mode 自動帶入 display 值」(對齊 Notion / Airtable 共識),
218
+ // empty。對齊 cell-as-input「edit mode 自動帶入 view 值」(對齊 Notion / Airtable 共識),
219
219
  // 改用 local state controlled。User typing → setLocalValue;blur/Enter → onCommit(localValue)。
220
- // (initial + useState 已 hoist 到 display-return 前 — 見上方 React #310 fix。)
220
+ // (initial + useState 已 hoist 到 view-return 前 — 見上方 React #310 fix。)
221
221
  return (
222
222
  <NumberInput
223
223
  autoFocus
224
224
  variant="naked"
225
+ aria-label={ariaLabel}
225
226
  size={sizeForInput(size)}
226
227
  value={localValue}
227
228
  onChange={(v) => { setLocalValue(v); onDraft?.(v) }}
@@ -244,25 +245,25 @@ function NumberCell({ value, meta, mode, size, isDisabled, onCommit, onCancel, o
244
245
  // (對齊 Airtable / Notion canonical:click 外即關)。
245
246
  const dismissOnClose = (onCancel?: () => void) => (open: boolean) => { if (!open) onCancel?.() }
246
247
 
247
- // Mode-keyed remount canonical(2026-05-05):display↔edit 切換時,因 React reconciliation 同 type 同
248
- // position 會重用 instance,導致 `useState(defaultOpen)` 只在首次 mount 跑(那時 mode='display'
248
+ // Mode-keyed remount canonical(2026-05-05):view↔edit 切換時,因 React reconciliation 同 type 同
249
+ // position 會重用 instance,導致 `useState(defaultOpen)` 只在首次 mount 跑(那時 mode='view'
249
250
  // defaultOpen 沒給→預設 false)。後續 mode='edit' 即使傳 defaultOpen=true 也無效。
250
251
  // Fix:`key={mode}` 強制 React unmount + remount,每次切 mode 都重跑 useState init。
251
- // 對齊 Notion / Airtable cell-as-input「display 跟 edit 是不同 mount cycle」語義。
252
+ // 對齊 Notion / Airtable cell-as-input「view 跟 edit 是不同 mount cycle」語義。
252
253
 
253
- function DateCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: CellComponentProps) {
254
- if (mode === 'display') {
254
+ function DateCell({ value, meta, mode, size, onCommit, onCancel }: CellComponentProps) {
255
+ if (mode === 'view') {
255
256
  return (
256
257
  <DatePicker
257
- key="display"
258
+ key="view"
258
259
  variant="naked"
259
- mode={displayOrDisabled(isDisabled)}
260
+ mode="view"
260
261
  value={value as string | null}
261
262
  size={size}
262
263
  formatOptions={meta?.formatOptions}
263
264
  locale={meta?.locale}
264
265
  // 2026-07-08 user 拍板 A 案(推翻 2026-05-10/06-26 兩次拍板,per 6 家 benchmark 6/6 共識
265
- // Ant/MUI X/AG Grid/Atlaskit/Notion/Airtable:display 態零恆顯型別 icon;editable
266
+ // Ant/MUI X/AG Grid/Atlaskit/Notion/Airtable:view 態零恆顯型別 icon;editable
266
267
  // affordance 統一 = hover outline(field.spec.md L4)。showDisplayEndIcon 不再傳
267
268
  //(prop 保留為 spreadsheet-flavored 消費端 opt-in 逃生門,見 field.spec.md L6)。
268
269
  />
@@ -283,18 +284,18 @@ function DateCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: C
283
284
  )
284
285
  }
285
286
 
286
- function TimeCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: CellComponentProps) {
287
- if (mode === 'display') {
287
+ function TimeCell({ value, meta, mode, size, onCommit, onCancel }: CellComponentProps) {
288
+ if (mode === 'view') {
288
289
  return (
289
290
  <TimePicker
290
- key="display"
291
+ key="view"
291
292
  variant="naked"
292
- mode={displayOrDisabled(isDisabled)}
293
+ mode="view"
293
294
  value={value as string | null}
294
295
  size={size}
295
296
  formatOptions={meta?.formatOptions}
296
297
  locale={meta?.locale}
297
- // showDisplayEndIcon 不傳 — 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
298
+ // showDisplayEndIcon 不傳 — 2026-07-08 A 案:view 態零恆顯 icon(同 DateCell 註)
298
299
  />
299
300
  )
300
301
  }
@@ -314,22 +315,22 @@ function TimeCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: C
314
315
  )
315
316
  }
316
317
 
317
- function SelectCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }: CellComponentProps) {
318
- // Display canonical(2026-05-05):cell IS variant,default plain text(no Tag pill 疊在 cell border 內)。
318
+ function SelectCell({ value, meta, mode, size, onCommit, onCancel }: CellComponentProps) {
319
+ // View canonical(2026-05-05):cell IS variant,default plain text(no Tag pill 疊在 cell border 內)。
319
320
  // Consumer 可在 column meta.display='tag' opt-in 內容導向的 Tag 視覺(category 含色彩標籤等)。
320
321
  // 對齊 JTable / AG Grid「renderer/editor 視覺一致」canonical。
321
322
  const displayMode = (meta?.display as 'plain' | 'tag' | undefined) ?? 'plain'
322
- if (mode === 'display') {
323
+ if (mode === 'view') {
323
324
  return (
324
325
  <Select
325
- key="display"
326
+ key="view"
326
327
  variant="naked"
327
- mode={displayOrDisabled(isDisabled)}
328
+ mode="view"
328
329
  value={value as string | null}
329
330
  options={meta?.options ?? []}
330
331
  size={size}
331
332
  display={displayMode}
332
- // showDisplayEndIcon 不傳 — 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
333
+ // showDisplayEndIcon 不傳 — 2026-07-08 A 案:view 態零恆顯 icon(同 DateCell 註)
333
334
  selectedItemRenderer={meta?.selectedItemRenderer} // 2026-07-08 WM 戰役:status 類彩色 cell 顯示通道
334
335
  />
335
336
  )
@@ -354,19 +355,19 @@ function SelectCell({ value, meta, mode, size, isDisabled, onCommit, onCancel }:
354
355
  )
355
356
  }
356
357
 
357
- function MultiSelectCell({ value, meta, mode, size, isDisabled, autoRowHeight, onCommitLive, onCancel }: CellComponentProps) {
358
+ function MultiSelectCell({ value, meta, mode, size, autoRowHeight, onCommitLive, onCancel }: CellComponentProps) {
358
359
  const wrap = autoRowHeight && meta?.wrap === true
359
- if (mode === 'display') {
360
+ if (mode === 'view') {
360
361
  return (
361
362
  <Combobox
362
- key="display"
363
+ key="view"
363
364
  variant="naked"
364
- mode={displayOrDisabled(isDisabled)}
365
+ mode="view"
365
366
  value={(value as string[] | null) ?? []}
366
367
  options={meta?.options ?? []}
367
368
  wrap={wrap}
368
369
  size={size}
369
- // showDisplayEndIcon 不傳 — 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
370
+ // showDisplayEndIcon 不傳 — 2026-07-08 A 案:view 態零恆顯 icon(同 DateCell 註)
370
371
  />
371
372
  )
372
373
  }
@@ -386,10 +387,10 @@ function MultiSelectCell({ value, meta, mode, size, isDisabled, autoRowHeight, o
386
387
  )
387
388
  }
388
389
 
389
- function PersonCell({ value, mode, size, isDisabled, onCommit, onCancel, meta }: CellComponentProps) {
390
- if (mode === 'display') {
391
- // 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
392
- return <PeoplePicker key="display" variant="naked" mode={displayOrDisabled(isDisabled)} value={value as PersonValue | null} size={size} />
390
+ function PersonCell({ value, mode, size, onCommit, onCancel, meta }: CellComponentProps) {
391
+ if (mode === 'view') {
392
+ // 2026-07-08 A 案:view 態零恆顯 icon(同 DateCell 註)
393
+ return <PeoplePicker key="view" variant="naked" mode="view" value={value as PersonValue | null} size={size} />
393
394
  }
394
395
  return (
395
396
  <PeoplePicker
@@ -406,10 +407,10 @@ function PersonCell({ value, mode, size, isDisabled, onCommit, onCancel, meta }:
406
407
  )
407
408
  }
408
409
 
409
- function MultiPersonCell({ value, mode, size, isDisabled, onCommitLive, onCancel, meta }: CellComponentProps) {
410
- if (mode === 'display') {
411
- // 2026-07-08 A 案:display 態零恆顯 icon(同 DateCell 註)
412
- return <PeoplePicker key="display" variant="naked" mode={displayOrDisabled(isDisabled)} value={(value as PersonValue[]) ?? []} size={size} />
410
+ function MultiPersonCell({ value, mode, size, onCommitLive, onCancel, meta }: CellComponentProps) {
411
+ if (mode === 'view') {
412
+ // 2026-07-08 A 案:view 態零恆顯 icon(同 DateCell 註)
413
+ return <PeoplePicker key="view" variant="naked" mode="view" value={(value as PersonValue[]) ?? []} size={size} />
413
414
  }
414
415
  // Multi 用 onCommitLive(commit 但不 exit edit)— 每勾一人即時生效,popover 持續開
415
416
  // 直到點外面;onOpenChange(false) → onCancel exit edit。對齊 multiSelect canonical。
@@ -427,14 +428,12 @@ function MultiPersonCell({ value, mode, size, isDisabled, onCommitLive, onCancel
427
428
  )
428
429
  }
429
430
 
430
- function BooleanCell({ value, mode, meta, size, isEditable, isDisabled, onCommit }: CellComponentProps) {
431
- // boolean 不分 read/edit mode — display 渲 mode='display' 純展示;editable 時直接 toggle Checkbox
432
- // 2026-05-13 codex V1 fix:editable=true + disabled=true 之前 fall through to live Checkbox,
433
- // onCheckedChange fire(violate disabled contract)。Fix:`!isEditable || isDisabled` →
434
- // 走 display branch,Checkbox 拿 disabled mode + 不接 onCheckedChange。
435
- if (mode === 'display' && (!isEditable || isDisabled)) {
431
+ function BooleanCell({ value, mode, meta, size, isEditable, onCommit }: CellComponentProps) {
432
+ // boolean 不分 read/edit mode — view 渲 mode='view' 純展示;editable 時直接 toggle Checkbox
433
+ // 不可編(!isEditable)→ view branch,Checkbox mode="view" 純展示不接 onCheckedChange。
434
+ if (mode === 'view' && !isEditable) {
436
435
  // size 傳入 → boolean 值 icon(Check/X)@lg 縮放對齊其他 cell(對齊 editable 分支同 size 邏輯)
437
- return <Checkbox variant="naked" size={size === 'lg' ? 'lg' : 'md'} mode={displayOrDisabled(isDisabled)} checked={value === true} />
436
+ return <Checkbox variant="naked" size={size === 'lg' ? 'lg' : 'md'} mode="view" checked={value === true} />
438
437
  }
439
438
  return (
440
439
  <Checkbox
@@ -448,21 +447,21 @@ function BooleanCell({ value, mode, meta, size, isEditable, isDisabled, onCommit
448
447
 
449
448
  /**
450
449
  * UrlCell(2026-07-14 docblock 對齊實作):
451
- * display branch = `<LinkInput mode={displayOrDisabled(isDisabled)}>`(URL parse / hostname
450
+ * view branch = `<LinkInput mode="view">`(URL parse / hostname
452
451
  * 顯示一致性 SSOT);editable 互動:hover 時右側出 Pencil 鈕 → 進 edit(保留 link click 語意)。
453
452
  * edit branch = plain `<Input variant="naked">`(LinkInput edit 的 controlled value 衝突
454
453
  * revert,詳下方 edit branch 註解);URL 驗證 deferred 到 onCommit(consumer 端 validate)。
455
454
  */
456
- function UrlCell({ value, meta, mode, size, isDisabled, isEditable, onRequestEdit, onCommit, onCancel }: CellComponentProps) {
457
- if (mode === 'display') {
455
+ function UrlCell({ value, meta, mode, size, isEditable, onRequestEdit, onCommit, onCancel }: CellComponentProps) {
456
+ if (mode === 'view') {
458
457
  // showDisplayEndIcon ← D path Phase 2(2026-05-08):Field naked wrapper 包 anchor,與 Input edit 同 chrome。
459
458
  // LinkInput 此 prop = wrapper-only(無 icon,field.spec.md L6 例外)→ A 案(2026-07-08)不撤;
460
459
  // 但修 I1:原無條件 true 違反「= isEditable」knob 等式(field-controls.spec.md cell 例外),改等式。
461
460
  const display = (
462
- <LinkInput variant="naked" mode={displayOrDisabled(isDisabled)} value={value as string | null} label={meta?.linkLabel} size={size} showDisplayEndIcon={isEditable === true} />
461
+ <LinkInput variant="naked" mode="view" value={value as string | null} label={meta?.linkLabel} size={size} showDisplayEndIcon={isEditable === true} />
463
462
  )
464
- // 2026-05-13 codex V1 fix:disabled URL 不顯 Pencil affordance(parent onRequestEdit 已被攔但 UI 仍誤導)
465
- if (!isEditable || isDisabled) return display
463
+ // 不可編 URL 不顯 Pencil affordance( view 顯示連結,無編輯入口)
464
+ if (!isEditable) return display
466
465
  // editable read mode:hover Pencil 鈕(對齊 spec 第十二段「url:read = 連結 + Pencil」)
467
466
  return (
468
467
  <span className="group/cell relative flex items-center w-full"> {/* @naked-row-mode-allow: URL hover-Pencil 是 inline action 不是 value content,items-center 鎖 Pencil 對齊行高第一行(autoRow 跟 fixed 皆同視覺正確) */}
@@ -540,7 +539,7 @@ function buildCellWithSurface(Inner: ComponentType<CellComponentProps>, key: str
540
539
  漏傳 size 的 cell 也自動繼承(根治「新 cell 漏傳 size」class);size primitive 不破壞 memo identity。*/}
541
540
  <FieldSurfaceSizeProvider size={props.size}>
542
541
  {/* 2026-07-08 user 拍板:cell 可編輯訊號經獨立 boolean context 注給 child Field controls,
543
- 讓 useFieldEmptyDisplay 分流「可編輯 cell 空 display → 空白」vs「不可編輯 cell → '-'」。
542
+ 讓 useFieldEmptyDisplay 分流「可編輯 cell 空 view → 空白」vs「不可編輯 cell → '-'」。
544
543
  boolean primitive 不破壞 memo identity(同 size context)。 */}
545
544
  <FieldSurfaceEditableProvider isEditable={props.isEditable ?? false}>
546
545
  <Inner {...props} />
@@ -65,7 +65,7 @@ declare module '@tanstack/react-table' {
65
65
  wrap?: boolean
66
66
  /**
67
67
  * Max visible lines before ellipsis(2026-05-14 I9 per codex verdict + user 拍板)。
68
- * Only effective when `autoRowHeight + wrap=true`。Display 用 `line-clamp-N`,edit textarea
68
+ * Only effective when `autoRowHeight + wrap=true`。view 用 `line-clamp-N`,edit textarea
69
69
  * 高度 match clamp。對齊 Notion 「Truncate」row toggle / AG Grid `cellClassRules` 上限 row height。
70
70
  * Default = undefined(無 clamp,完整 wrap)。
71
71
  */
@@ -162,22 +162,9 @@ declare module '@tanstack/react-table' {
162
162
  * Esc cancel / blur or Enter commit。Commit 觸發 `onCellCommit`。
163
163
  */
164
164
  editable?: boolean | ((row: TData) => boolean)
165
- /**
166
- * Inline disabled state(2026-05-13 Stream C Cluster B Q3 ship,per codex Q3 verdict):
167
- * cell 不可操作 state(orthogonal to editable readonly)。
168
- * - `true`:cell 永遠 disabled
169
- * - `false` / undef(default):cell normal
170
- * - `(row) => boolean`:per-row 動態(e.g. row.archived 或 row.locked 才 disabled)
171
- *
172
- * 視覺(per `color.spec.md` `--bg-disabled` component-state token):
173
- * - TD 外殼:`bg-disabled` + `cursor-not-allowed` + 抑制 hover ring
174
- * - Cell content(Field family):`mode='disabled'` → 各 Field type 內部走具體 disabled token
175
- * - edit entry 抑制:disabled cell 點擊不進 edit(對齊 `editable && !disabled` invariant)
176
- *
177
- * 跟 `editable=false` 區分:editable=false = readonly(可看不可編);disabled = 不可操作 state。
178
- * 對齊 MUI X `isCellEditable` + cellClassName / AG Grid `cellClassRules` / Notion locked properties。
179
- */
180
- disabled?: boolean | ((row: TData) => boolean)
165
+ // 2026-07-16 round16:cell `disabled` 已廢除。世界級 grid(MUI X isCellEditable / AG Grid editable /
166
+ // Handsontable readOnly)皆無 disabled cell 鎖定用 `editable:(row)=>false`(可看不可編、不灰化),
167
+ // 非 disabled 灰化態。原 `disabled?: boolean | ((row)=>boolean)` + bg-disabled TD 灰化全移除(全庫 0 消費)。
181
168
  /**
182
169
  * Locked column — column reorder 不可拖,Notion 「primary column」 pattern。
183
170
  * 對齊 SKU / ID 等不可移欄位。
@@ -27,8 +27,7 @@ import { Eye, EyeOff, Lock, GripVertical, Search, RotateCcw, X as XIcon } from '
27
27
  import { Button } from '@/design-system/components/Button/button'
28
28
  import { ButtonDivider } from '@/design-system/components/Button/button-group'
29
29
  import { Input } from '@/design-system/components/Input/input'
30
- import { ScrollArea } from '@/design-system/components/ScrollArea/scroll-area'
31
- import { PopoverHeader, PopoverFooter, PopoverTitle, PopoverClose } from '@/design-system/components/Popover/popover'
30
+ import { PopoverHeader, PopoverBody, PopoverFooter, PopoverTitle, PopoverClose } from '@/design-system/components/Popover/popover'
32
31
  import { ItemPrefix, ItemLabel, ItemInlineActionButton, ROW_PADDING_BY_SIZE } from '@/design-system/patterns/element-anatomy/item-anatomy'
33
32
  import { cn } from '@/lib/utils'
34
33
  import { DndContext, closestCenter, type DragEndEvent } from '@dnd-kit/core'
@@ -130,8 +129,19 @@ export function DataTableColumnVisibilityPanel({
130
129
  onColumnOrderChange!(next)
131
130
  }
132
131
 
132
+ // 2026-07-18 決策16 錯誤史(明記以免再犯):原本這個 panel 是 Fragment + fixed `ScrollArea max-h-72`,
133
+ // 與 sibling FilterPanel/SortManager(root-div + viewport-aware SurfaceBody)不一致。我給過**兩個都錯**
134
+ // 的辯護理由 —— (1)「PopoverHeader 用 -mx 負邊距、包 root 會破壞」= 錯(SurfaceHeader 用正 px-loose+border-b,
135
+ // 無 -mx);(2)「sibling 自刻 header 不用 primitive」= 錯(三 panel 皆消費 SurfaceHeader/PopoverHeader primitive)。
136
+ // 真正差異只是 body/scroll 策略。multi-agent SSOT consistency 稽核定案:**是 drift,該統一**(fixed 288px cap
137
+ // 在高螢幕多欄下劣於 sibling 的 viewport-adaptive;且是唯一不能當 template 複製的 panel)。故下方已改成 canonical shape。
133
138
  return (
134
- <>
139
+ // 決策16 定案(2026-07-18,SSOT consistency 稽核後):對齊 sibling FilterPanel/SortManager 的
140
+ // overlay-surface canonical shape —— root `<div flex flex-col h-full min-h-0>`(M25 viewport-aware
141
+ // scroll chain)+ viewport-adaptive `PopoverBody`(取代原 fixed `ScrollArea max-h-72`)。三個
142
+ // DataTable state-panel 收斂成同一形狀,body 隨視窗高度自適應(高螢幕多欄不再硬卡 288px)。
143
+ // 寬度仍由 consumer 的 `<PopoverContent w-72>` 提供(panel root w-full 撐滿)。
144
+ <div className="flex flex-col h-full min-h-0 w-full">
135
145
  <PopoverHeader hideClose>
136
146
  <div className="flex items-center gap-1 w-full min-w-0">
137
147
  <PopoverTitle className="flex-1">欄位顯示</PopoverTitle>
@@ -151,17 +161,20 @@ export function DataTableColumnVisibilityPanel({
151
161
  </div>
152
162
  </PopoverHeader>
153
163
  {searchable && (
154
- <div className="px-[var(--layout-space-loose)] pt-[var(--layout-space-tight)]">
164
+ <div className="shrink-0 px-[var(--layout-space-loose)] pt-[var(--layout-space-tight)]">
155
165
  <Input
156
166
  size="md"
157
167
  placeholder="搜尋欄位…"
168
+ aria-label="搜尋欄位"
158
169
  value={search}
159
170
  onChange={(e) => setSearch(e.target.value)}
160
171
  startIcon={Search}
161
172
  />
162
173
  </div>
163
174
  )}
164
- <ScrollArea className="max-h-72">
175
+ {/* viewport-adaptive body(List-as-region idiom:PopoverBody !px-0 !py-0 撤 chrome padding,
176
+ 內層 py-2 給垂直呼吸、row 自帶 px-loose 水平 padding)。取代原 fixed ScrollArea max-h-72。 */}
177
+ <PopoverBody className="!px-0 !py-0">
165
178
  <div className="py-2 flex flex-col" style={{ '--item-prefix-slot': '16px' } as React.CSSProperties}>
166
179
  {dndEnabled ? (
167
180
  <DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
@@ -196,13 +209,13 @@ export function DataTableColumnVisibilityPanel({
196
209
  ))
197
210
  )}
198
211
  </div>
199
- </ScrollArea>
212
+ </PopoverBody>
200
213
  <PopoverFooter className="justify-start">
201
214
  <Button variant="tertiary" size="sm" onClick={handleBulkToggle}>
202
215
  {allVisible ? '全部隱藏' : '顯示全部'}
203
216
  </Button>
204
217
  </PopoverFooter>
205
- </>
218
+ </div>
206
219
  )
207
220
  }
208
221
 
@@ -126,8 +126,9 @@ const newEmptyGroup = (): FilterGroup => ({
126
126
  // ── Component Props ─────────────────────────────────────────────────────
127
127
 
128
128
  export interface DataTableFilterPanelProps<TData> {
129
- /** flat(無 group)or nested(1-level group)— consumer 拍板 */
130
- mode: 'flat' | 'nested'
129
+ // 2026-07-18 決策17:移除獨立 `mode` prop(單一真相源 = `value.mode` discriminant)——
130
+ // 舊設計 mode + value.mode 兩來源型別允許矛盾(mode='nested' 配 flat value → CTA 錯文案 + 死操作);
131
+ // 無外部消費者傳 mode(grep 0),全由 value.mode 推導。對齊 MUI X GridFilterModel / AG Grid 單一 model。
131
132
  /** 可被 filter 的 columns */
132
133
  columns: ColumnDef<TData, any>[]
133
134
  /** 當前 FilterTree(controlled) */
@@ -151,7 +152,6 @@ export interface DataTableFilterPanelProps<TData> {
151
152
 
152
153
  // 內部 fn — generic + ref 轉發。export 走 cast(對齊 DataTable 同 pattern)
153
154
  function DataTableFilterPanelInner<TData>({
154
- mode,
155
155
  columns,
156
156
  value,
157
157
  onChange,
@@ -314,7 +314,7 @@ function DataTableFilterPanelInner<TData>({
314
314
  // 必加 `min-h-0` 才能讓 panel 在 PopoverContent max-h cap 下正確 shrink + body scroll。
315
315
  <div ref={ref} className={cn(
316
316
  'flex flex-col h-full min-h-0',
317
- mode === 'nested'
317
+ value.mode === 'nested'
318
318
  ? 'w-[min(760px,calc(100vw-2rem))]'
319
319
  : 'w-[min(640px,calc(100vw-2rem))]',
320
320
  className,
@@ -387,9 +387,9 @@ function DataTableFilterPanelInner<TData>({
387
387
  <div>
388
388
  <Button
389
389
  variant="tertiary" size="sm" startIcon={Plus}
390
- onClick={mode === 'flat' ? addFlatCondition : addGroup}
390
+ onClick={value.mode === 'flat' ? addFlatCondition : addGroup}
391
391
  >
392
- {mode === 'nested' ? '加入篩選器' : '加篩選'}
392
+ {value.mode === 'nested' ? '加入篩選器' : '加篩選'}
393
393
  </Button>
394
394
  </div>
395
395
  </SurfaceBody>
@@ -63,8 +63,8 @@ interface DataTableInteractionLayerProps {
63
63
  * truthy → layer call this 拿 React node(已 bind value/onCommit/onCancel from controller),
64
64
  * 在 ActiveEditorHost portal(z 3,float rect)render 之。
65
65
  *
66
- * Per codex Q6.2 outline:cell 永遠 mode="display"(SSOT preserved);portal host 渲
67
- * mode="edit" 同 registry component;float pass-through + z-index 3 cover display below。
66
+ * Per codex Q6.2 outline:cell 永遠 mode="view"(SSOT preserved);portal host 渲
67
+ * mode="edit" 同 registry component;float pass-through + z-index 3 cover view below。
68
68
  */
69
69
  activeEditorRender?: (cellId: CellId, rect: CellRect) => React.ReactNode
70
70
  }
@@ -441,7 +441,7 @@ function ClipMask({ clipRect, children }: { clipRect: CellRect; children: React.
441
441
  *
442
442
  * Per codex Q2 verdict:不該進 CellRingOverlay primitive — 它是 host 不是 ring。
443
443
  * - pointerEvents:auto(child Field 接收 click / keyboard)
444
- * - background:var(--canvas)(opaque cover display Field below;Cell SSOT 保留)
444
+ * - background:var(--canvas)(opaque cover view Field below;Cell SSOT 保留)
445
445
  * - z-index 3(above hover / selected / range)
446
446
  * - children = activeEditorRender 的回傳 React node
447
447
  *
@@ -197,11 +197,11 @@ function SortRow({
197
197
  {...listeners}
198
198
  />
199
199
  <div className="flex-1 min-w-0">
200
- <Select size="sm" options={optionsForRow} value={sort.id} onChange={onChangeId} />
200
+ <Select size="sm" aria-label="排序欄位" options={optionsForRow} value={sort.id} onChange={onChangeId} />
201
201
  </div>
202
202
  <div className="w-32 shrink-0">
203
203
  {/* minRows={2} — 升冪/降冪只 2 選項,顯式縮 menu 高度(Q5) */}
204
- <Select size="sm" options={DIRECTION_OPTIONS} value={sort.desc ? 'desc' : 'asc'} onChange={onChangeDir} minRows={2} />
204
+ <Select size="sm" aria-label="排序方向" options={DIRECTION_OPTIONS} value={sort.desc ? 'desc' : 'asc'} onChange={onChangeDir} minRows={2} />
205
205
  </div>
206
206
  {/* Trash 用 text Button(Q4 對齊 filter panel)— form-control row 必 Field 同高 */}
207
207
  <Button variant="text" size="sm" iconOnly startIcon={Trash2} aria-label="刪除" onClick={onRemove} />