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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/CLAUDE.md +8 -8
  2. package/README.md +3 -2
  3. package/dist/components/Alert/alert.js.map +1 -1
  4. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  5. package/dist/components/AppShell/app-shell.d.ts +1 -1
  6. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  7. package/dist/components/AppShell/app-shell.js +22 -2
  8. package/dist/components/AppShell/app-shell.js.map +1 -1
  9. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  10. package/dist/components/Avatar/avatar.js +4 -4
  11. package/dist/components/Avatar/avatar.js.map +1 -1
  12. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  13. package/dist/components/Breadcrumb/breadcrumb.js +1 -1
  14. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  15. package/dist/components/Button/button.d.ts +2 -2
  16. package/dist/components/Button/button.d.ts.map +1 -1
  17. package/dist/components/Button/button.js +12 -3
  18. package/dist/components/Button/button.js.map +1 -1
  19. package/dist/components/Calendar/calendar.d.ts +13 -5
  20. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  21. package/dist/components/Calendar/calendar.js +7 -1
  22. package/dist/components/Calendar/calendar.js.map +1 -1
  23. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  24. package/dist/components/Carousel/carousel.js +8 -3
  25. package/dist/components/Carousel/carousel.js.map +1 -1
  26. package/dist/components/Chart/chart.d.ts.map +1 -1
  27. package/dist/components/Chart/chart.js +1 -0
  28. package/dist/components/Chart/chart.js.map +1 -1
  29. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox/checkbox.js +8 -4
  32. package/dist/components/Checkbox/checkbox.js.map +1 -1
  33. package/dist/components/Chip/chip.d.ts +1 -1
  34. package/dist/components/Chip/chip.d.ts.map +1 -1
  35. package/dist/components/Chip/chip.js.map +1 -1
  36. package/dist/components/Coachmark/coachmark.d.ts +10 -3
  37. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  38. package/dist/components/Coachmark/coachmark.js.map +1 -1
  39. package/dist/components/Combobox/combobox.d.ts +5 -1
  40. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  41. package/dist/components/Combobox/combobox.js +30 -13
  42. package/dist/components/Combobox/combobox.js.map +1 -1
  43. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  44. package/dist/components/DataTable/cell-registry.js +53 -62
  45. package/dist/components/DataTable/cell-registry.js.map +1 -1
  46. package/dist/components/DataTable/column-types.d.ts +10 -4
  47. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  48. package/dist/components/DataTable/column-types.js.map +1 -1
  49. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
  50. package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
  51. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
  52. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  53. package/dist/components/DataTable/data-table-filter-panel.js +607 -0
  54. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  55. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  56. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  58. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  59. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  60. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  61. package/dist/components/DataTable/data-table.d.ts +5 -6
  62. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  63. package/dist/components/DataTable/data-table.js +36 -15
  64. package/dist/components/DataTable/data-table.js.map +1 -1
  65. package/dist/components/DataTable/filter-operators.js +140 -0
  66. package/dist/components/DataTable/filter-operators.js.map +1 -0
  67. package/dist/components/DataTable/filter-tree.js +312 -0
  68. package/dist/components/DataTable/filter-tree.js.map +1 -0
  69. package/dist/components/DataTable/index.d.ts +3 -0
  70. package/dist/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/components/DataTable/index.js +12 -1
  72. package/dist/components/DataTable/index.js.map +1 -1
  73. package/dist/components/DataTable/lib/column-meta.js +25 -0
  74. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  75. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  76. package/dist/components/DateGrid/date-grid.js +3 -1
  77. package/dist/components/DateGrid/date-grid.js.map +1 -1
  78. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  79. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  80. package/dist/components/DatePicker/date-picker.js +105 -74
  81. package/dist/components/DatePicker/date-picker.js.map +1 -1
  82. package/dist/components/Dialog/dialog.d.ts +20 -3
  83. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  84. package/dist/components/Dialog/dialog.js +38 -20
  85. package/dist/components/Dialog/dialog.js.map +1 -1
  86. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  87. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  88. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  89. package/dist/components/Field/field-context.d.ts +45 -5
  90. package/dist/components/Field/field-context.d.ts.map +1 -1
  91. package/dist/components/Field/field-context.js +19 -0
  92. package/dist/components/Field/field-context.js.map +1 -1
  93. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  94. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  95. package/dist/components/Field/field-edit-keys.js +19 -0
  96. package/dist/components/Field/field-edit-keys.js.map +1 -0
  97. package/dist/components/Field/field-types.d.ts +20 -1
  98. package/dist/components/Field/field-types.d.ts.map +1 -1
  99. package/dist/components/Field/field-types.js.map +1 -1
  100. package/dist/components/Field/field-wrapper.d.ts +3 -2
  101. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  102. package/dist/components/Field/field-wrapper.js +38 -39
  103. package/dist/components/Field/field-wrapper.js.map +1 -1
  104. package/dist/components/Field/field.d.ts +2 -1
  105. package/dist/components/Field/field.d.ts.map +1 -1
  106. package/dist/components/Field/field.js.map +1 -1
  107. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  108. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  109. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  110. package/dist/components/FileItem/file-item.js +1 -1
  111. package/dist/components/FileItem/file-item.js.map +1 -1
  112. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  113. package/dist/components/FileUpload/file-upload.js.map +1 -1
  114. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  115. package/dist/components/FileViewer/file-viewer.js +7 -2
  116. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  117. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  118. package/dist/components/FileViewer/image-renderer.js +22 -1
  119. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  120. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  121. package/dist/components/HoverCard/hover-card.js +5 -3
  122. package/dist/components/HoverCard/hover-card.js.map +1 -1
  123. package/dist/components/InlineEdit/index.d.ts +2 -0
  124. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  125. package/dist/components/InlineEdit/index.js +5 -0
  126. package/dist/components/InlineEdit/index.js.map +1 -0
  127. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  129. package/dist/components/InlineEdit/inline-edit.js +164 -0
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  131. package/dist/components/Input/input.d.ts +6 -11
  132. package/dist/components/Input/input.d.ts.map +1 -1
  133. package/dist/components/Input/input.js +43 -13
  134. package/dist/components/Input/input.js.map +1 -1
  135. package/dist/components/LinkInput/link-input.d.ts +2 -2
  136. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  137. package/dist/components/LinkInput/link-input.js +6 -5
  138. package/dist/components/LinkInput/link-input.js.map +1 -1
  139. package/dist/components/Menu/menu-item.d.ts +14 -2
  140. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  141. package/dist/components/Menu/menu-item.js +25 -3
  142. package/dist/components/Menu/menu-item.js.map +1 -1
  143. package/dist/components/NumberInput/number-input.d.ts +3 -3
  144. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  145. package/dist/components/NumberInput/number-input.js +6 -5
  146. package/dist/components/NumberInput/number-input.js.map +1 -1
  147. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  148. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  149. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  150. package/dist/components/Pagination/pagination.js +1 -1
  151. package/dist/components/Pagination/pagination.js.map +1 -1
  152. package/dist/components/PeoplePicker/index.js +7 -1
  153. package/dist/components/PeoplePicker/index.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  155. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  156. package/dist/components/PeoplePicker/people-picker.js +23 -10
  157. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  158. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  159. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.js +19 -14
  161. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  162. package/dist/components/Popover/popover.d.ts.map +1 -1
  163. package/dist/components/Popover/popover.js +3 -1
  164. package/dist/components/Popover/popover.js.map +1 -1
  165. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  166. package/dist/components/ProfileCard/profile-card.js +3 -3
  167. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  168. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  169. package/dist/components/RadioGroup/radio-group.js +15 -9
  170. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  171. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  172. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.js +6 -3
  174. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  175. package/dist/components/Select/select.d.ts +46 -5
  176. package/dist/components/Select/select.d.ts.map +1 -1
  177. package/dist/components/Select/select.js +109 -28
  178. package/dist/components/Select/select.js.map +1 -1
  179. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  180. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  181. package/dist/components/SelectMenu/select-menu.js +8 -1
  182. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  183. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  184. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  185. package/dist/components/SelectionControl/boolean-value.js +23 -0
  186. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  187. package/dist/components/SelectionControl/index.d.ts +1 -0
  188. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  189. package/dist/components/SelectionControl/index.js +2 -0
  190. package/dist/components/SelectionControl/index.js.map +1 -1
  191. package/dist/components/Sheet/index.js +2 -1
  192. package/dist/components/Sheet/sheet.d.ts +7 -1
  193. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  194. package/dist/components/Sheet/sheet.js +5 -2
  195. package/dist/components/Sheet/sheet.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +8 -10
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts.map +1 -1
  201. package/dist/components/Slider/slider.js.map +1 -1
  202. package/dist/components/Switch/switch.d.ts +6 -6
  203. package/dist/components/Switch/switch.d.ts.map +1 -1
  204. package/dist/components/Switch/switch.js +3 -2
  205. package/dist/components/Switch/switch.js.map +1 -1
  206. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  207. package/dist/components/Tabs/tabs.js +15 -1
  208. package/dist/components/Tabs/tabs.js.map +1 -1
  209. package/dist/components/Textarea/textarea.d.ts +2 -2
  210. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  211. package/dist/components/Textarea/textarea.js +50 -42
  212. package/dist/components/Textarea/textarea.js.map +1 -1
  213. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  214. package/dist/components/TimePicker/time-columns.js +42 -38
  215. package/dist/components/TimePicker/time-columns.js.map +1 -1
  216. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  217. package/dist/components/TimePicker/time-picker.js +8 -6
  218. package/dist/components/TimePicker/time-picker.js.map +1 -1
  219. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  220. package/dist/components/Tooltip/tooltip.js +7 -5
  221. package/dist/components/Tooltip/tooltip.js.map +1 -1
  222. package/dist/components/TreeView/tree-view.d.ts +56 -1
  223. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  224. package/dist/components/TreeView/tree-view.js +211 -12
  225. package/dist/components/TreeView/tree-view.js.map +1 -1
  226. package/dist/index.d.ts +115 -58
  227. package/dist/index.d.ts.map +1 -1
  228. package/dist/index.js +93 -108
  229. package/dist/index.js.map +1 -1
  230. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  231. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  232. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  233. package/dist/tokens/categorical-color.js +15 -0
  234. package/dist/tokens/categorical-color.js.map +1 -1
  235. package/dist/tokens/motion/motion.d.ts +7 -6
  236. package/dist/tokens/motion/motion.d.ts.map +1 -1
  237. package/dist/tokens/motion/motion.js +6 -6
  238. package/dist/tokens/motion/motion.js.map +1 -1
  239. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  240. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  241. package/dist/tokens/motion/overlay-motion.js +9 -0
  242. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  243. package/dist/tokens/uiSize/icon-size.js +5 -0
  244. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  245. package/ds-canonical/fork/governance.lock +37 -19
  246. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  247. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  248. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  249. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
  250. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  251. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  252. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  253. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  254. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
  256. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  257. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  258. package/ds-canonical/fork/manifest.json +20 -0
  259. package/ds-canonical/fork/preamble.md +22 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
  263. package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
  264. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  266. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  267. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  268. package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
  269. package/ds-canonical/hooks/README.md +1 -1
  270. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  271. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  272. package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
  273. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  274. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  275. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
  276. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  277. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  278. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  279. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  280. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  281. package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
  282. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  283. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  284. package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
  285. package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
  286. package/ds-canonical/hooks/check_story_determinism.sh +39 -0
  287. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  288. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  289. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  290. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  291. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  292. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  293. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  294. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
  295. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  296. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  297. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  298. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  299. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  300. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  301. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
  302. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
  303. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  304. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  305. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  306. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  307. package/ds-canonical/references/failure-class-registry.json +145 -0
  308. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  309. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  310. package/ds-canonical/references/scenario-definition.md +6 -9
  311. package/ds-canonical/references/ssot-consultation.md +2 -2
  312. package/ds-canonical/references/ssot-index.md +5 -4
  313. package/ds-canonical/references/story-baseline-registry.json +8 -2
  314. package/ds-canonical/references/structural-token-retention.md +6 -9
  315. package/ds-canonical/rules/meta-patterns.md +8 -8
  316. package/ds-canonical/rules/self-verify.md +4 -3
  317. package/ds-canonical/rules/spec-rules.md +1 -1
  318. package/ds-canonical/rules/story-rules.md +2 -2
  319. package/ds-canonical/rules/ui-development.md +4 -2
  320. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
  321. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  322. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  323. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  324. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  325. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  326. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  327. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
  328. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  329. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  330. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  331. package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
  332. package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
  333. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  334. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  335. package/ds-canonical/skills/governance-health/SKILL.md +2 -1
  336. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  337. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  338. package/ds-canonical/skills/new-component/SKILL.md +7 -5
  339. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  340. package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
  341. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  342. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  343. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  344. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  345. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  346. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  347. package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
  348. package/ds-story-manifest.json +29 -20
  349. package/llms-full.txt +22 -1
  350. package/llms.txt +5 -4
  351. package/package.json +7 -3
  352. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  353. package/src/components/Accordion/accordion.stories.tsx +16 -1
  354. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  355. package/src/components/Alert/alert.spec.md +8 -10
  356. package/src/components/Alert/alert.stories.tsx +28 -28
  357. package/src/components/Alert/alert.tsx +1 -1
  358. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  359. package/src/components/AppShell/app-shell.spec.md +4 -4
  360. package/src/components/AppShell/app-shell.tsx +28 -2
  361. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  362. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  363. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  364. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  365. package/src/components/Avatar/avatar.spec.md +2 -2
  366. package/src/components/Avatar/avatar.stories.tsx +8 -6
  367. package/src/components/Avatar/avatar.tsx +13 -5
  368. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  369. package/src/components/Badge/badge.spec.md +2 -0
  370. package/src/components/Badge/badge.stories.tsx +4 -2
  371. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  372. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  373. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  374. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  375. package/src/components/Button/button.principles.stories.tsx +1 -1
  376. package/src/components/Button/button.spec.md +2 -2
  377. package/src/components/Button/button.tsx +18 -3
  378. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  379. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  380. package/src/components/Calendar/calendar.spec.md +5 -4
  381. package/src/components/Calendar/calendar.stories.tsx +7 -4
  382. package/src/components/Calendar/calendar.tsx +26 -7
  383. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  384. package/src/components/Carousel/carousel.spec.md +2 -2
  385. package/src/components/Carousel/carousel.tsx +11 -3
  386. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  387. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  388. package/src/components/Chart/chart.stories.tsx +2 -8
  389. package/src/components/Chart/chart.tsx +3 -0
  390. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  391. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  392. package/src/components/Checkbox/checkbox.spec.md +11 -26
  393. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  394. package/src/components/Checkbox/checkbox.tsx +18 -13
  395. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  396. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  397. package/src/components/Chip/chip.spec.md +5 -4
  398. package/src/components/Chip/chip.tsx +5 -1
  399. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  400. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  401. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  402. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  403. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  404. package/src/components/Coachmark/coachmark.spec.md +5 -5
  405. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  406. package/src/components/Coachmark/coachmark.tsx +10 -3
  407. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  408. package/src/components/Combobox/combobox.tsx +53 -19
  409. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  410. package/src/components/Command/command.principles.stories.tsx +1 -1
  411. package/src/components/Command/command.stories.tsx +42 -10
  412. package/src/components/DataTable/cell-registry.tsx +86 -63
  413. package/src/components/DataTable/column-types.ts +10 -1
  414. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  415. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  416. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  417. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  418. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  419. package/src/components/DataTable/data-table.spec.md +32 -12
  420. package/src/components/DataTable/data-table.stories.tsx +16 -17
  421. package/src/components/DataTable/data-table.tsx +103 -60
  422. package/src/components/DataTable/index.ts +3 -0
  423. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  424. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  425. package/src/components/DateGrid/date-grid.spec.md +1 -1
  426. package/src/components/DateGrid/date-grid.tsx +3 -1
  427. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  428. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  429. package/src/components/DatePicker/date-picker.spec.md +3 -3
  430. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  431. package/src/components/DatePicker/date-picker.tsx +99 -45
  432. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  433. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  434. package/src/components/DescriptionList/description-list.spec.md +3 -3
  435. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  436. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  437. package/src/components/Dialog/dialog.spec.md +9 -0
  438. package/src/components/Dialog/dialog.stories.tsx +66 -5
  439. package/src/components/Dialog/dialog.tsx +60 -25
  440. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  441. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  442. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  443. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  444. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  445. package/src/components/Empty/empty.spec.md +2 -2
  446. package/src/components/Field/field-context.ts +69 -5
  447. package/src/components/Field/field-controls.spec.md +62 -8
  448. package/src/components/Field/field-edit-keys.ts +66 -0
  449. package/src/components/Field/field-types.ts +58 -9
  450. package/src/components/Field/field-wrapper.tsx +50 -42
  451. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  452. package/src/components/Field/field.spec.md +1 -1
  453. package/src/components/Field/field.stories.tsx +1 -1
  454. package/src/components/Field/field.tsx +2 -1
  455. package/src/components/Field/form-validation.spec.md +3 -3
  456. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  457. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  458. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  459. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  460. package/src/components/FileItem/file-item.spec.md +14 -8
  461. package/src/components/FileItem/file-item.stories.tsx +36 -25
  462. package/src/components/FileItem/file-item.tsx +8 -6
  463. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  464. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  465. package/src/components/FileUpload/file-upload.spec.md +1 -1
  466. package/src/components/FileUpload/file-upload.tsx +1 -1
  467. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  468. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  469. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  470. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  471. package/src/components/FileViewer/file-viewer.tsx +12 -4
  472. package/src/components/FileViewer/image-renderer.tsx +35 -7
  473. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  474. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  475. package/src/components/HoverCard/hover-card.spec.md +5 -5
  476. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  477. package/src/components/HoverCard/hover-card.tsx +5 -3
  478. package/src/components/InlineEdit/index.ts +5 -0
  479. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  480. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  481. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  482. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  483. package/src/components/Input/input.principles.stories.tsx +2 -12
  484. package/src/components/Input/input.spec.md +13 -18
  485. package/src/components/Input/input.tsx +69 -22
  486. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  487. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  488. package/src/components/LinkInput/link-input.tsx +11 -10
  489. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  490. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  491. package/src/components/Menu/menu-item.spec.md +22 -15
  492. package/src/components/Menu/menu-item.stories.tsx +39 -11
  493. package/src/components/Menu/menu-item.tsx +38 -4
  494. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  495. package/src/components/Notice/notice.spec.md +16 -3
  496. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  497. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  498. package/src/components/NumberInput/number-input.spec.md +4 -4
  499. package/src/components/NumberInput/number-input.tsx +19 -12
  500. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  501. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  502. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  503. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  504. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  505. package/src/components/Pagination/pagination.spec.md +1 -1
  506. package/src/components/Pagination/pagination.stories.tsx +2 -6
  507. package/src/components/Pagination/pagination.tsx +1 -1
  508. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  509. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  510. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  511. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  512. package/src/components/PeoplePicker/person-display.tsx +32 -16
  513. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  514. package/src/components/Popover/popover.tsx +3 -1
  515. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  516. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  517. package/src/components/ProfileCard/profile-card.tsx +6 -6
  518. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  519. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  520. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  521. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  522. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  523. package/src/components/RadioGroup/radio-group.tsx +41 -15
  524. package/src/components/Rating/rating.spec.md +11 -3
  525. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  526. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  527. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  528. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  529. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  530. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  531. package/src/components/Select/select.spec.md +27 -17
  532. package/src/components/Select/select.stories.tsx +33 -0
  533. package/src/components/Select/select.tsx +190 -36
  534. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  535. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  536. package/src/components/SelectMenu/select-menu.tsx +16 -3
  537. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  538. package/src/components/SelectionControl/index.ts +1 -0
  539. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  540. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  541. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  542. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  543. package/src/components/Separator/separator.spec.md +2 -2
  544. package/src/components/Separator/separator.stories.tsx +6 -27
  545. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  546. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  547. package/src/components/Sheet/sheet.spec.md +2 -2
  548. package/src/components/Sheet/sheet.tsx +9 -5
  549. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  550. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  551. package/src/components/Sidebar/sidebar.spec.md +13 -15
  552. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  553. package/src/components/Sidebar/sidebar.tsx +37 -25
  554. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  555. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  556. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  557. package/src/components/Slider/slider.spec.md +5 -5
  558. package/src/components/Slider/slider.tsx +3 -1
  559. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  560. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  561. package/src/components/Steps/steps.spec.md +1 -1
  562. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  563. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  564. package/src/components/Switch/switch.spec.md +8 -8
  565. package/src/components/Switch/switch.stories.tsx +9 -24
  566. package/src/components/Switch/switch.tsx +17 -13
  567. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  568. package/src/components/Tabs/tabs.spec.md +1 -1
  569. package/src/components/Tabs/tabs.tsx +21 -1
  570. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  571. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  572. package/src/components/Textarea/textarea.spec.md +4 -4
  573. package/src/components/Textarea/textarea.tsx +72 -46
  574. package/src/components/TimePicker/time-columns.tsx +6 -2
  575. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  576. package/src/components/TimePicker/time-picker.spec.md +3 -3
  577. package/src/components/TimePicker/time-picker.tsx +16 -10
  578. package/src/components/Toast/toast.stories.tsx +7 -4
  579. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  580. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  581. package/src/components/Tooltip/tooltip.spec.md +1 -1
  582. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  583. package/src/components/Tooltip/tooltip.tsx +8 -6
  584. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  585. package/src/components/TreeView/tree-view.spec.md +42 -11
  586. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  587. package/src/components/TreeView/tree-view.tsx +322 -17
  588. package/src/index.ts +584 -60
  589. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  590. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  591. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  592. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  593. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  594. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  595. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  596. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  597. package/src/styles/tokens.css +3 -0
  598. package/src/tokens/README.md +1 -1
  599. package/src/tokens/color/color.spec.md +3 -3
  600. package/src/tokens/color/color.stories.tsx +3 -3
  601. package/src/tokens/density/density.stories.tsx +16 -3
  602. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  603. package/src/tokens/motion/motion.css +33 -21
  604. package/src/tokens/motion/motion.spec.md +32 -15
  605. package/src/tokens/motion/motion.stories.tsx +58 -5
  606. package/src/tokens/motion/motion.ts +7 -6
  607. package/src/tokens/motion/overlay-motion.ts +26 -0
  608. package/src/tokens/orphan-tokens.spec.md +4 -4
  609. package/src/tokens/token-system.spec.md +1 -0
  610. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  611. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  612. package/src/tokens/utility-registry.json +160 -23
@@ -58,6 +58,20 @@ components/
58
58
 
59
59
  ---
60
60
 
61
+ ## Field 框架地圖(兩軸 + InlineEdit 疊上層)— SSOT(2026-07-09 user 拍板收斂)
62
+
63
+ Field 家族 = **一個 `fieldWrapperStyles` cva + 兩條正交軸**;`InlineEdit` 是**疊在其上的組合 primitive**,不屬於任一軸。此段為「框架為何長這樣」的單一住所。
64
+
65
+ **軸一 `mode`(4)× 軸二 `variant`(2)**:`variant` 只有 `default`(公開,完整 chrome)與 `naked`(`@internal`,cell-as-input:edit×naked 自畫 border-based state machine,display/readonly/disabled×naked 用 transparent border 由 host cell 供視覺邊框;只 DataTable `cell-registry.tsx` 消費)。`bare`(透明外殼)**2026-07-09 退役**——零真實消費者 + 假理由(toolbar 小輸入用 `default`+`autoWidth`,cell 用 `naked`);SSOT `field-types.ts` `FieldVariant`。有效組合:default × {edit/display/readonly/disabled} 全用於表單/詳情;naked × {edit/display/disabled} 用於 DataTable 格;`naked+readonly` 目前無 live consumer(格子非 readonly 模式),保留 compound 為軸對稱。readonly 2026-07-09 補鍵盤 focus ring(WCAG 2.4.7,見「Focus 行為」)。**型別層已拆 public/internal union(2026-07-14 API 策展 E,user 拍板「全部收窄」)**:公開 `FieldVariant = 'default'`;`naked` 收進 `FieldVariantInternal`(`@internal`),cell-registry 經 `WithFieldVariantInternal` 型別通道消費(純型別 widen、零 runtime),PeoplePicker wrapper 同通道 forward 給 Select / Combobox。
66
+
67
+ **InlineEdit ≠ mode ≠ variant**:它是 **read↔edit 二態切換**——靜止 = 純文字(文字 + 隱形 Pressable),點擊/Enter 才生一個 **Field 控件**(edit view,預設 `<Input>`,可 `renderEdit` 換 Textarea/Select)。它**消費** Field edit mode 當「edit 那一半」,站在 mode 軸**之上**(比喻:Field edit = 燈泡,InlineEdit = 開關)。世界級對照 [Atlassian inline-edit](https://github.com/pioug/atlassian-frontend-mirror/blob/main/design-system/inline-edit/src/internal/read-view.tsx)。
68
+
69
+ **`naked` vs `InlineEdit`(不同層級,非冗餘)**:`naked` = 視覺外殼變體(chrome 層),靜止態**仍是控件**(裸 input,直接可編輯),邊框由 host cell 管,對應 in-cell 即時編輯(spreadsheet / grid 慣例);`InlineEdit` = 互動組合(behavior 層),靜止態**不是控件**(純文字),自帶 read chrome,對應 click-to-edit([Atlassian inline-edit](https://github.com/pioug/atlassian-frontend-mirror/blob/main/design-system/inline-edit/src/internal/read-view.tsx))。naked 做不到「靜止純文字、點了才變輸入框」;InlineEdit 塞不進格子當永遠在線編輯器 → 各自獨立。
70
+
71
+ **InlineEdit 多行 / padding / 零位移契約**:read view 文字可換行(`w-full min-w-0` 無 nowrap)。**多行(`multiline` prop,2026-07-09 L2)**:edit view **自動**用 `<Textarea>`(Enter=換行、Cmd/Ctrl+Enter 或 blur 提交),read view `whitespace-pre-wrap` 保留換行,**不需手傳 renderEdit**(對齊 DataTable 可換行格 `autoRowHeight`+`<Textarea variant="naked">`+`line-clamp`,`cell-registry.tsx`)。垂直 padding:**單行** read 用 `min-h-[--field-height-{size}]`+flex 置中、無 `py`(與 Textarea `py-2` 不同);**多行** read 用 `items-start py-1.5`(對齊 Textarea 多行閱讀語意)。進 edit **零位移**:read 恆帶透明 border(預留 1px border-box)+ `px-[--field-px]`(= edit Input 同值)→ 左右/邊框零跳;垂直單行時 read `min-h` = edit height 零跳(多行須配 Textarea 否則垂直不齊)。
72
+
73
+ ---
74
+
61
75
  ## Mode — 表單三態 (display 見下方 Display 段)
62
76
 
63
77
  下表涵蓋 Form-context 三態(edit / readonly / disabled);完整 `FieldMode` 為四值(`'edit' | 'display' | 'readonly' | 'disabled'`),`display` 模式於下方 `## Display` 段記載。
@@ -139,7 +153,7 @@ Error 是 boolean prop,獨立於 mode。只在 `edit` 模式下有視覺效果
139
153
  - Error 訊息在 Form 層級:help text 顯示在 input 下方
140
154
  - Field 不在尾部放狀態 icon(如 ⚠️)——邊框顏色已經傳達了 error 狀態
141
155
 
142
- Form wrapper 可透過 context 注入 `error` prop,消費者不需要在每個 Field 上手動傳。
156
+ Field wrapper 透過 context 注入的 key 是 `invalid`(**非 `error`**;field.tsx:122/211);各控件以 `useResolvedFieldInvalid` 合併自身 `error` prop 與 context `invalid`,消費者不需在每個控件手動傳。(`error` 另為 `fieldWrapperStyles` 內部 cva 軸名 + 各控件公開 boolean prop;Field 容器層 / context 一律用 `invalid`。)
143
157
 
144
158
  ---
145
159
 
@@ -183,11 +197,30 @@ Form wrapper 可透過 context 注入 `error` prop,消費者不需要在每個
183
197
 
184
198
  ---
185
199
 
200
+ ## 寬度軸(width: fill / hug)— 正交軸(2026-07-08 user 拍板)
201
+
202
+ Field 家族 wrapper 的寬度軸,與 mode / variant / size / error 全部正交:
203
+
204
+ | width | 行為 | 何時用 |
205
+ |-------|------|--------|
206
+ | `fill`(default)| `w-full` 填滿容器 — 原行為,零回歸 | form 表單直欄(欄位左緣對齊)、DataTable cell |
207
+ | `hug` | `w-fit max-w-full` 依內容收縮 | detail pane inline metadata(狀態/優先級/負責人 點擊即編輯)、toolbar 內 field |
208
+
209
+ **定義(user verbatim)**:hug 寬 = value 寬 + 其中各元素寬 + 彼此間距 + field 內部 padding —— **框線、互動、樣式全部不變,只有寬度變**(就是一般 field 把寬度改 hug)。`max-w-full` 保證窄容器不溢出(`min-w-0` + truncate 照常)。
210
+
211
+ - 鋪線範圍:`fieldWrapperStyles` cva 軸(SSOT)+ Select / Combobox / DatePicker / PeoplePicker 轉發 `width?: FieldWidth`(型別 `Field/field-types.ts`)
212
+ - **何時不用**:form 直欄(fill 對齊)、DataTable cell(naked 已 `!h-full` 滿格,cell 寬由 column 管)
213
+ - Benchmark(M22):shadcn v4 SelectTrigger 預設 `w-fit`(https://raw.githubusercontent.com/shadcn-ui/ui/main/apps/v4/registry/new-york-v4/ui/select.tsx)/ Radix Select Trigger intrinsic sizing(https://www.radix-ui.com/primitives/docs/components/select)
214
+
215
+ ---
216
+
186
217
  ## Focus 行為
187
218
 
188
219
  `<input>` 元素在點擊和鍵盤 Tab 時都觸發 `:focus-visible`(瀏覽器規範:文字輸入永遠 focus-visible),CSS 無法區分。
189
220
 
190
- 統一使用 `border-primary`(1px),不加 ring、不加粗。
221
+ **可編輯文字輸入(edit / naked mode 的 input / textarea)**:統一 `border-primary`(1px),不加 ring、不加粗。
222
+
223
+ **readonly(可聚焦但不可編輯的 input,2026-07-09 補 — 消解框架地圖 cross-ref)**:用 **ring idiom**(`[&:has(:focus-visible)]:ring-2 ring-ring ring-offset-1`;native text input 的 :focus-visible 在滑鼠點擊時**亦 match** — 對齊本段開頭「文字輸入永遠 focus-visible、CSS 無法區分點擊與 Tab」,勿宣稱僅鍵盤),**非** border-primary —— readonly 邊框 transparent 無可染,且 ring 語義=「可聚焦但非文字輸入」(對齊 Button / Tab / Checkbox);滿足 WCAG 2.4.7(readonly 有值渲染可聚焦 native input 需 focus 指示)。詳 `field-wrapper.tsx` readonly compound JSDoc。
191
224
 
192
225
  ---
193
226
 
@@ -232,7 +265,7 @@ Select / Combobox 的 ChevronDown、DatePicker 的 Calendar、TimePicker 的 Clo
232
265
 
233
266
  - edit:`fg-muted`;**readonly:不顯示 indicator**;**disabled:`fg-disabled`**(對齊上方 Icon 色彩原則)
234
267
  - 不可互動(`pointer-events-none`)——下拉由 select 元素本身觸發
235
- - **Cell(naked variant)例外**:indicator `showDisplayEndIcon`(= cell isEditable)——非可編欄不顯(2026-05-10 cell canonical「indicator = editable affordance」);**可編欄的 disabled cell 顯示 + fg-disabled**(同表單邏輯)
268
+ - **Cell(naked variant)**:**display 態零恆顯 indicator(2026-07-08 user 拍板 A 案,推翻 2026-05-10「indicator = editable affordance」)** —— editable affordance 統一 = hover outline(field.spec.md L4)。Benchmark 6/6 product-table 域(Ant editable-cells / MUI X singleSelect / AG Grid / Atlaskit inline-edit(v2.0.0 移除 hover-pencil 後 9 版未回歸)/ Notion / Airtable)display 態皆純值零 icon;恆顯派僅 Google Sheets Chip/Arrow(spreadsheet 域可選檔位)。`showDisplayEndIcon` prop 保留為 opt-in 逃生門(spreadsheet-flavored 消費端);cell-registry 6 個 picker 站不再傳、url 站傳 `isEditable === true`(LinkInput 例外 = wrapper-only 無 icon,取 display↔edit 像素對齊)。edit 態 indicator 照舊(本節上方 form 規則);opt-in 時 disabled cell 顯示 + fg-disabled(同表單邏輯)
236
269
  - locked(readonly/disabled)wrapper 並設 `aria-disabled`(disabled 時)——styled-disabled 非原生元素需明告 AT inactive,亦使 axe 正確套用 WCAG 1.4.3 inactive-UI 豁免
237
270
  - clearable 有值時:clear X 在左,ChevronDown 在右
238
271
  - **右側元素(clear / chevron / calendar / clock)右緣水平內距 = `--field-px`(12px,SSOT `tokens/uiSize/uiSize.css`),edit / readonly / disabled / display 全 mode 一致**(跟 Input 一致)。**tag 模式特例**:左側 `tagPadding` 用對稱 px-calc(≈8px)貼齊 tags、會吃掉右緣,故 tag 容器(含 readonly/disabled)**必 re-assert `paddingRight: var(--field-px)`** 對齊 edit;漏接 = chevron 右緣偏移 bug(2026-06-27 修 Select:354 / Combobox ReadonlyMultiSelect)
@@ -249,6 +282,8 @@ Select 支援兩種顯示模式(`display` prop):
249
282
 
250
283
  `plain` 模式可搭配 `startIcon`(代表 value 的圖示,如狀態 icon;2026-05-01 由 `text` 改名 `plain`,rationale 見 `select.spec.md`)。
251
284
 
285
+ `selectedItemRenderer` 設定時優先於 plain / tag 預設呈現,且 **4 mode(edit/display/readonly/disabled)共享**(共享 contract (a),見下方)— display 態渲染 renderer 輸出(值內容),無 chrome 無 chevron。
286
+
252
287
  `tag` 模式的 edit 用 hidden select overlay(跟 Combobox 同模式),Tag 用 `pointer-events-none`,點擊穿透到 select。右側元素右緣 = `--field-px`(見上方「右側元素」canonical;tag 模式 readonly/disabled 必 re-assert)。
253
288
 
254
289
  tagPadding 只在有 Tag 時才套用。Placeholder/空值狀態使用 fieldWrapper 的標準 `--field-px`(`px-[var(--field-px)]`)padding,確保文字與邊框有足夠間距。
@@ -291,11 +326,30 @@ Display 的消費者:
291
326
  - **DataTable cell**:cell-registry 根據 `meta.type` 選對應 Field 元件並傳 `mode="display"`(disabled cell 傳 `"disabled"`)
292
327
  - **Field readonly 模式**:內部使用相同的格式化邏輯
293
328
 
294
- ### null / undefined 值
329
+ ### null / undefined 值(2026-07-08 user 拍板 — 半形 hyphen + editable × surface 分流)
330
+
331
+ > **user verbatim**:「table cell 不可編輯的空值,單獨不可編輯的 display 的空值,單獨的 readonly 的空值都用"-";單獨可以編輯的 edit 輸入框的空值則是 placeholder;table cell 內可編輯的 display 的空值就是為空」+「我從頭到尾哪裡有說要用全形的」。
332
+
333
+ 空值符號 = **半形 hyphen `-`(U+002D)**,**非**全形 em dash `—`(U+2014)。分流看 **surface × 是否可編輯 × mode**(SSOT 機械層 = `field-context.ts` `useFieldEmptyDisplay()` + `EMPTY_DISPLAY` 常數 `field-wrapper.tsx`;全 Field family display/readonly/disabled 空值渲染必經此 hook,**禁**直接引 `EMPTY_DISPLAY` 常數):
334
+
335
+ | 情境 | 判準 | 空值顯示 | 依據 |
336
+ |---|---|---|---|
337
+ | 不可編輯 — standalone display / readonly | mode ∈ {display, readonly} 且非可編輯 table cell | **半形 `-` + `text-foreground`** | 唯讀資料「此欄無值」明示;Ant ProTable `columnEmptyText` 預設 `'-'`(https://github.com/ant-design/pro-components/blob/master/src/table/Table.tsx)|
338
+ | 不可編輯 — table cell(readonly cell)| `surface==='table-cell'` 且 `isEditable===false` | **半形 `-`** | 同上;非可編欄位視同唯讀資料 |
339
+ | **可編輯** — table cell display 靜止態 | `surface==='table-cell'` 且 `isEditable===true` 且 mode='display' | **全空白 `''`** | grid 域壓倒性共識(MUI X `valueToRender?.toString()` null 短路 / AG Grid `_toString(null)`→不設 textContent / Ant core rc-table 裸值 / Notion / Airtable);表格密集時「-」海 = 視覺噪音。空 editable cell 的 affordance = hover outline(field.spec.md L4),非佔位符 |
340
+ | **可編輯** — form / panel edit 輸入框 | mode='edit' 且非 table cell | **native placeholder** | 標準表單輸入提示;「hover 才顯 placeholder」十路查證零家採用,**禁** |
341
+ | **可編輯** — table cell edit / focus | `surface==='table-cell'` 且 mode='edit' | **全空白**(DataTable cell 不接 placeholder)| 對齊 Notion / Airtable cell 編輯裸輸入 |
342
+
343
+ 收斂式:`surface==='table-cell' && isEditable ? '' : '-'`(可編輯 form edit 走 native placeholder,不經此 hook)。`isEditable` 由 DataTable cell registry 經 `FieldSurfaceEditableProvider` boolean context 注入(standalone / form 無此 context → 預設 false → `-`)。
344
+
345
+ **readonly native input 兩派統一**(2026-07-08):Input / Textarea 的 readonly **空值** 改走 display-span 顯 `-`(原走 native `<input readOnly>` 吐 native placeholder / 空白);readonly **有值** 仍走 native input 保留選取/複製語意。NumberInput 早已 `resolvedMode !== 'edit'` 統一走 span,無需改。「有值」判定(2026-07-14 補註,dual-model consensus;不改空值顯 `-` 規則本身):uncontrolled(只傳 `defaultValue`)同樣算有值 —— 機械層 = `useControllable` 內部 resolved value(defaultValue 初始 + 打字寫回,native element 由 `value={resolved}` 內部驅動)+ form.reset() bridge(HTML reset 不發 input event → uncontrolled 掛 form `reset` listener 把 resolved 歸位 defaultValue),切 display / readonly(native element unmount/remount)後判定與 DOM 真值一致、不顯 stale 值;controlled 純 passthrough 行為不變。
295
346
 
296
- Display 模式統一顯示 em dash `—`,顏色 `text-fg-muted`。edit 模式顯示空白。
347
+ **空值符號顏色**(2026-07-09 user 拍板 verbatim「「-」代表的是不可編輯只拿來供檢視的值所以應該跟readonly 的value同樣顏色吧」):不可編輯「-」= `text-foreground`(同 readonly value 色,非 placeholder 提示的裝飾語意);disabled → `text-fg-disabled`(M24)。SSOT helper = `field-context.ts` `fieldEmptyColorClass(resolvedMode)`,全 Field family display/readonly/disabled 空值 span 消費(禁散寫 `text-fg-muted`)。
297
348
 
298
- 此規則適用於所有 Field 類型,boolean 例外(顯示 unchecked 狀態)。
349
+ **例外表**(唯一去處,禁散落各元件 spec):
350
+ - **boolean** → 顯示 unchecked 狀態(非空白非 dash)
351
+ - **disabled** → 同該情境上文字(`-` 或空白)+ `text-fg-disabled`(M24:disabled 顯著性 > muted)
352
+ - **Select display 傳 `placeholder`** → 顯 placeholder 而非 dash/空白(`select.tsx` `emptyText = placeholder ?? emptyDisplay`,2026-07-08 codify — 原為 spec 未載明的 code 行為)
299
353
 
300
354
  ### DataTable 整合
301
355
 
@@ -321,7 +375,7 @@ col.accessor('status', {
321
375
 
322
376
  ## 共享 contract(2026-05-12 Stream C — Selected renderer / Placeholder vocabulary / Cell surface)
323
377
 
324
- **(a) Selected value renderer**:rich display(avatar+name/icon+label)元件**必**提供 consumer renderer slot,**display/readonly/disabled/edit** 4 mode 共享同一 renderer(禁 edit-only)。`Select.selectedItemRenderer` / `Combobox.tagRenderer`(edit 已接;display path unify deferred cycle)/ PeoplePicker 走 `PersonDisplay`+`MultiPersonDisplay`+`Combobox.tagRenderer`。對齊 MUI Autocomplete `renderValue` / Ant Select `tagRender`+`labelRender`+`optionRender` / MUI DataGrid `renderCell`+`renderEditCell` 共享 params。 <!-- @benchmark-unverified -->
378
+ **(a) Selected value renderer**:rich display(avatar+name/icon+label)元件**必**提供 consumer renderer slot,**display/readonly/disabled/edit** 4 mode 共享同一 renderer(禁 edit-only)。`Select.selectedItemRenderer`(4 mode 已全接 — 2026-07-08 A 案回歸修正,display/readonly/disabled 的 ReadonlyDisplay 消費 renderer 輸出;renderer 輸出屬「值內容」,display 態照常渲染,與 affordance 分層見 `field.spec.md` L6)/ `Combobox.tagRenderer`(edit 已接;display path 走 ComboboxTagStack 預設 Tag,consumer tagRenderer unify deferred,見 `combobox.tsx` 檔頭 `@renderer-symmetry-allow`;現行唯一 tagRenderer consumer = PeoplePicker,其 display 走 MultiPersonDisplay 不經此 path,無實際丟失)/ PeoplePicker 走 `PersonDisplay`+`MultiPersonDisplay`+`Combobox.tagRenderer`。對齊 MUI Autocomplete `renderValue` / Ant Select `tagRender`+`labelRender`+`optionRender` / MUI DataGrid `renderCell`+`renderEditCell` 共享 params。 <!-- @benchmark-unverified -->
325
379
 
326
380
  **(b) Placeholder vocabulary**(3 props 對 3 UI state,**不可混用**):
327
381
  - `placeholder` — trigger empty(沒選值,例「請選擇人員」)— Ant/Polaris/Carbon canonical
@@ -353,7 +407,7 @@ col.accessor('status', {
353
407
  - ❌ 不在 input 尾部放 error 狀態 icon——邊框顏色已傳達 error
354
408
  - ❌ endAction 不可傳入 ReactNode——使用 InlineActionConfig 宣告式 API
355
409
  - ❌ endAction 的 inline action 不可省略 `aria-label`(即 `label` 欄位)
356
- - ❌ Display null 值不可顯示空白——統一使用 `—`(em dash)+ `text-fg-muted`
410
+ - ❌ 不可編輯 display / readonly 空值用全形 em dash `—` 或 `text-fg-muted`——半形 `-` + `text-foreground`(「-」是供檢視的值,同 readonly value 色;disabled → fg-disabled);可編輯 table cell display 空值為空白(見「null / undefined 值」分流表)
357
411
  - ❌ Field 的 readonly 模式不可用於 DataTable cell——readonly 有底色和 wrapper 開銷,table cell 用 Display 元件
358
412
 
359
413
  ## 被引用(auto-maintained,Dim 3 reciprocal audit)
@@ -0,0 +1,66 @@
1
+ // @internal — DS-internal 單元(edit-in-place 鍵盤結算 SSOT);consumer 用 InlineEdit / DataTable,不直用。
2
+ // ── 消費的 SSOT ──
3
+ // (本檔即是被消費的 SSOT;不 import 其他 canonical)
4
+ //
5
+ // ── 為什麼存在 ──
6
+ // 「就地編輯(edit-in-place)」的鍵盤結算契約 —— Enter=commit / Esc=cancel + **中文 IME 組字 guard** ——
7
+ // 原本在兩處各寫一份、且**已分歧**:
8
+ // - DataTable `cell-registry.tsx` makeKeyHandler:有 IME guard(2026-07-05 D4 fix)
9
+ // - InlineEdit `inline-edit.tsx`:**無 IME guard** → 中文使用者按 Enter 確認選字時,會把半截組字
10
+ // 提交並退出 edit(Esc 則丟棄整個 draft)= latent bug。
11
+ // 2026-07-09 edit-in-place SSOT 研究(6-agent + 世界級)結論:**不抽大的共用狀態機**(兩 host 的 draft
12
+ // 擁有權 / state locus / focus model 根本不同,強抽違 M21 + 破壞表格虛擬捲動效能),**但抽這一片**——
13
+ // 唯一在兩處逐字重複、且現在分歧、且不碰 draft/state/focus 的純鍵盤結算邏輯。抽出後 InlineEdit 順手
14
+ // 得到 IME guard(修 bug)。對齊世界級「controls + 型別 registry 共用,orchestration 各自」split。
15
+ //
16
+ // **不含**:blur=commit(各 host 的 blur 語意不同)、finalizedRef 單次結算 guard(InlineEdit 專屬,
17
+ // 防 blur-after-Enter 雙 commit)、draft 管理(host-specific)。這些刻意留在各 host。
18
+ //
19
+ // ── 新增 edit-in-place host 的規矩(2026-07-10)──
20
+ // 之後任何新的「就地編輯」host(第 3 個以上),**Enter/Esc/Cmd·Ctrl+Enter/IME 組字結算一律消費本
21
+ // helper**,禁再手刻 `isComposing || keyCode===229` guard 或 Enter/Esc dispatch —— 現有 3 host
22
+ // (cell string / cell number / InlineEdit multiline)已全數收斂於此,手刻 = drift 回頭路(正是 2026-07
23
+ // 之前 InlineEdit 漏 IME guard 的病根)。單行傳 `commitOnEnter` 預設;多行傳 `commitOnEnter:false`
24
+ // (本 helper 內建 Cmd/Ctrl+Enter=commit)。此為文件層 SSOT 規矩,不另設 hook(host 少 + 避治理膨脹)。
25
+
26
+ import type * as React from 'react'
27
+
28
+ export interface EditSettleKeyOptions {
29
+ /** Enter(非組字中)→ 呼叫。已 preventDefault。 */
30
+ onCommit: (e: React.KeyboardEvent) => void
31
+ /** Escape(非組字中)→ 呼叫。已 preventDefault。 */
32
+ onCancel: (e: React.KeyboardEvent) => void
33
+ /**
34
+ * Enter 是否 = commit。預設 true。
35
+ * 多行(Textarea)場景設 false:plain Enter = 換行(不攔,交還 Textarea 預設),
36
+ * Cmd/Ctrl+Enter = commit(**本 handler 內建**,consumer 不需另接 capture handler),
37
+ * 其餘 commit 走 blur。
38
+ */
39
+ commitOnEnter?: boolean
40
+ }
41
+
42
+ /**
43
+ * edit-in-place 鍵盤結算 handler(SSOT)。IME 組字 guard 為第一道:中文/日文選字的 Enter 是
44
+ * 組字確認、Esc 是取消組字,非 commit/cancel 意圖 —— 無 guard 會誤送半截組字。`isComposing` 為主,
45
+ * `keyCode === 229` 補 Safari / 舊 Chrome(該分支不 emit isComposing)。
46
+ */
47
+ export function makeEditSettleKeyHandler(opts: EditSettleKeyOptions) {
48
+ const commitOnEnter = opts.commitOnEnter ?? true
49
+ return (e: React.KeyboardEvent) => {
50
+ // IME 組字 guard(見檔頭)—— 對齊 cell-registry 既有寫法 + data-table nav handler。
51
+ if (e.nativeEvent.isComposing || (e.nativeEvent as { keyCode?: number }).keyCode === 229) return
52
+ if (e.key === 'Escape') {
53
+ e.preventDefault()
54
+ opts.onCancel(e)
55
+ } else if (e.key === 'Enter') {
56
+ // 單行(commitOnEnter):Enter = commit。
57
+ // 多行(commitOnEnter:false):plain Enter = 換行(不攔,交還 Textarea 預設),
58
+ // Cmd/Ctrl+Enter = commit —— 此契約由本 SSOT 擁有,3 個 consumer
59
+ // (cell string/number + InlineEdit multiline)不再各自手刻 capture handler。
60
+ if (commitOnEnter || e.metaKey || e.ctrlKey) {
61
+ e.preventDefault()
62
+ opts.onCommit(e)
63
+ }
64
+ }
65
+ }
66
+ }
@@ -20,19 +20,68 @@ export type FieldMode = 'edit' | 'display' | 'readonly' | 'disabled'
20
20
 
21
21
  // ── Field Variant ────────────────────────────────────────────────────────────
22
22
  //
23
- // 視覺外殼(對齊主流 DS canonical M22 verified 2026-05-05):
24
- // - Ant Design `Input variant`: 'outlined' | 'borderless' | 'filled' | 'underlined'
25
- // - MUI `TextField variant`: 'outlined' | 'standard' | 'filled'
23
+ // 視覺外殼(公開 1 + internal 1;2026-07-09 user 拍板退役 `bare`,2026-07-14 API 策展 E user 拍板
24
+ // 「全部收窄」把 naked 從公開 union 拆出 見下方 note):
25
+ // default border + bg(一般 form input,= Ant outlined / MUI outlined)。公開 FieldVariant 唯一值
26
+ // naked — @internal(FieldVariantInternal)。cell-as-input(host cell substrate)。edit×naked 自畫
27
+ // border-based state machine(rest → hover → focus-within:border-primary → error 紅框);
28
+ // display/readonly/disabled×naked 用 transparent border,由 host cell 提供視覺邊框。
29
+ // 對齊 Airtable / Notion / Excel cell editing。唯一合法消費者 = DataTable cell-registry
30
+ // (field-controls.spec.md「軸二 variant」明文)— consumer 直傳 `<Input variant="naked">`
31
+ // 會繞過 canonical chrome / focus,故公開型別排除
26
32
  //
27
- // default 含 border + bg(一般 form input,= Ant outlined / MUI outlined)
28
- // bare — 透明 variant,hover/focus reveal inner border(VS Code/Figma toolbar inline editing idiom,
29
- // Ant borderless,但保留 hover/focus reveal)
30
- // naked — 完全無 chrome / 無 focus ring on wrapper(cell-as-input host cell 提供 border + focus visual)
31
- // 對齊 Airtable / Notion / Excel cell editing — cell 本身扮演 input frame,內無 wrapper
33
+ // **`bare` 退役紀錄(2026-07-09)**:原「透明外殼、hover/focus 才顯 border」variant,2026-05-05 加入時
34
+ // 宣稱用途 = toolbar inline editing(FileViewer zoom / config toolbar)。實測全 repo(DS + apps + stories)
35
+ // `variant="bare"` **零真實 JSX 消費者**:唯一出現處是一個 ❌ 反例 story + 過時註解(含錯誤宣稱 FileViewer
36
+ // 縮放用 bare實為 `<Input size="sm" autoWidth>` default variant)。其目標場景已被 default(toolbar,
37
+ // 對齊「邊框給互動元素、輸入框就該有邊框」原則)與 naked(cell-as-input)覆蓋 純冗餘,移除。
38
+ // ⚠️ 注意:被大量 import 的 `bareInputStyles` 常數(field-wrapper.tsx)是**內層 <input> 的重置樣式**
39
+ // (透明底 / 無 border / 繼承字體),與本 variant 同名但不同物,**保留不動**(8 個控件共用)。
32
40
  //
33
41
  // 透傳機制:Field 透過 FieldContext.variant 一次宣告,所有 child Field control 自動繼承。
34
42
  // per-control prop override 可覆寫 context。
35
- export type FieldVariant = 'default' | 'bare' | 'naked'
43
+ //
44
+ // Benchmark(M22 verified 2026-07-09):Ant `Input variant` 有 borderless(https://ant.design/components/input/)
45
+ // → 「無邊框輸入框」概念世界級合法;但 Material M3 只有 filled/outlined 無無邊框變體
46
+ // (https://m3.material.io/components/text-fields/guidelines),MUI standard(underline)已 deprecated。
47
+ // 我們的取捨:無真實消費場景 → 不保留純預留 variant(對齊自家「消費既有、不憑空造」原則)。
48
+ export type FieldVariant = 'default'
49
+
50
+ /**
51
+ * @internal Substrate union — 公開 FieldVariant + `naked`(cell-as-input)。
52
+ * 2026-07-14 API 策展 E(user 拍板「全部收窄」):naked 從公開 union 拆出,型別層防 consumer
53
+ * `<Input variant="naked">` 繞過 canonical chrome / focus。內部實作(field-wrapper cva、各控件
54
+ * useResolvedFieldVariant 分支)吃本型別;唯一合法 naked 傳入點 = DataTable cell-registry
55
+ * (field-controls.spec.md「軸二 variant」明文)。
56
+ */
57
+ export type FieldVariantInternal = FieldVariant | 'naked'
58
+
59
+ /**
60
+ * @internal 型別層 naked 通道 — 把 Field control 的公開 `variant?: FieldVariant` widen 為
61
+ * FieldVariantInternal(純型別、零 runtime;元件 runtime 本就支援 naked)。消費者:DataTable
62
+ * cell-registry(naked 起點)+ PeoplePicker(wrapper forward 給 Select / Combobox,M30 全 surface
63
+ * forward)。保留原 call signature 與 statics(`Pick<C, keyof C>`),widen 方向與函式參數
64
+ * contravariance 相容,故單次 assertion 可過(非 `as unknown as` 雙跳,型別仍受檢)。
65
+ */
66
+ export type WithFieldVariantInternal<C> = C extends (props: infer P) => infer R
67
+ ? ((props: Omit<P, 'variant'> & { variant?: FieldVariantInternal }) => R) & Pick<C, keyof C>
68
+ : never
69
+
70
+ // ── Field Width ──────────────────────────────────────────────────────────────
71
+ //
72
+ // 寬度軸(2026-07-08 user 拍板,正交於 mode / variant / size — 只改寬度,chrome 與互動不變):
73
+ // fill — `w-full` 填滿容器(default;form 直欄對齊 / DataTable cell 滿格)
74
+ // hug — `w-fit max-w-full` 依內容收縮:value 寬 + 各 slot 元素寬 + gap + field 內 padding
75
+ // (detail pane inline metadata / toolbar 內 field 場景)
76
+ //
77
+ // Benchmark(M22 verified):
78
+ // shadcn v4 SelectTrigger 預設 `w-fit`
79
+ // https://raw.githubusercontent.com/shadcn-ui/ui/main/apps/v4/registry/new-york-v4/ui/select.tsx
80
+ // Radix Select Trigger intrinsic sizing
81
+ // https://www.radix-ui.com/primitives/docs/components/select
82
+ //
83
+ // SSOT:fieldWrapperStyles `width` variant(field-wrapper.tsx)+ field-controls.spec.md「寬度軸」。
84
+ export type FieldWidth = 'fill' | 'hug'
36
85
 
37
86
  // ── Menu List Min Height ─────────────────────────────────────────────────────
38
87
  // SelectMenu / Select / Combobox 共用的 CommandList minHeight 計算。
@@ -1,3 +1,4 @@
1
+ // @internal — DS-internal 單元(Field 家族 chrome 基底,consumer 用 Field/Input 等 wrapper 不直用);不隨 index.ts re-export 進 npm public surface。
1
2
  // @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
3
  import { cva } from 'class-variance-authority'
3
4
 
@@ -11,9 +12,11 @@ import { cva } from 'class-variance-authority'
11
12
  // readonly — bg-readonly(neutral-2), 無邊框, 文字正常色(input chrome 但鎖定;token 獨立於 disabled)
12
13
  // disabled — bg-disabled(neutral-2), 無邊框, 文字灰化
13
14
  //
14
- // 2 種視覺外殼(variant):
15
+ // 2 種視覺外殼(variant;2026-07-09 `bare` 退役後):
15
16
  // default — 完整 chrome(form input 場景)
16
- // bare 透明 chrome(cell-as-input substrate / Toolbar inline editing)
17
+ // naked — cell-as-input substrate(DataTable);**edit×naked 自畫 border-based state machine**
18
+ // (border-border → hover:border-border-hover → focus-within:border-primary → error 紅框);
19
+ // display/readonly/disabled×naked 用 transparent border,由 host cell 提供視覺邊框
17
20
  //
18
21
  // 高度:固定 h = field-height token(rem),與 Button 共用同一組 token。
19
22
 
@@ -32,7 +35,9 @@ export const fieldWrapperStyles = cva(
32
35
  // 修一處全 Field family 跟動(Input/Select/Combobox/DatePicker/TimePicker/LinkInput/
33
36
  // Textarea/NumberInput/PeoplePicker)— 對齊 M17/M19/M23 一處 SSOT + data-table.spec.md:233
34
37
  // 「禁硬裁無 ellipsis」DS canonical + MUI X DataGrid / Ant Table column.ellipsis 共識。
35
- 'inline-flex items-center w-full min-w-0 rounded-md',
38
+ // 2026-07-08 width 軸:`w-full` base 移入 `width` variant(fill = 原行為 default,
39
+ // 零回歸;hug = w-fit 依內容收縮)。詳 field-controls.spec.md「寬度軸(width: fill / hug)」。
40
+ 'inline-flex items-center min-w-0 rounded-md',
36
41
  'text-foreground font-normal',
37
42
  'transition-colors duration-150',
38
43
  ],
@@ -47,13 +52,13 @@ export const fieldWrapperStyles = cva(
47
52
  variant: {
48
53
  // default — 完整 Field wrapper chrome(bg-surface、明顯 border、hover/focus 回饋)
49
54
  default: '',
50
- // bare透明 variant,hover / focus 才出現 border。適用 Toolbar inline editing
51
- // (FileViewer zoom input / chart config / rich text toolbar number input 等)。
52
- // 世界級對照:VS Code settings / Figma toolbar number / Notion prop input。
53
- bare: '',
54
- // naked — 完全無 variant,hover/focus 也不出 border。適用 cell-as-input
55
- // (host cell 自管 border + focus visual,內部 input 純文字承載)。
55
+ // nakedcell-as-input(Notion / Airtable / Excel canonical)。**edit×naked 自畫** border +
56
+ // hover:border-border-hover + focus-within:border-primary + error 紅框(v14 border-based state
57
+ // machine,見下方 compoundVariants L182-196);display/readonly/disabled×naked transparent
58
+ // border 由 host cell 提供視覺邊框,內部 input 純文字承載。
56
59
  // 世界級對照:Airtable / Notion / Excel / Google Sheets cell editing。
60
+ // (2026-07-09 `bare` variant 已退役 — 見 field-types.ts FieldVariant 註解;
61
+ // 被 import 的 `bareInputStyles` 常數是內層 input 重置樣式、與此不同物、保留。)
57
62
  naked: '',
58
63
  },
59
64
  size: {
@@ -61,6 +66,19 @@ export const fieldWrapperStyles = cva(
61
66
  md: 'text-body h-field-md px-[var(--field-px)] gap-2',
62
67
  lg: 'text-body-lg h-field-lg px-[var(--field-px)] gap-2',
63
68
  },
69
+ // width(2026-07-08 user 拍板,正交軸):寬度軸 — 只改寬度,chrome / hover / focus /
70
+ // error / mode compoundVariants 全部不動(user verbatim「框線和互動和樣式都不變,
71
+ // 只有寬度有變而已 … 把 field 和 value 的寬度都改成 hug」)。
72
+ // fill(default)— `w-full` 填滿容器 = 與移軸前 base 完全等價(零回歸不變量)
73
+ // hug — `w-fit` 依內容收縮:value 寬 + 各 slot 元素寬 + gap + field 內 padding;
74
+ // `max-w-full` 保證窄容器不溢出(min-w-0 保留,仍可 truncate)
75
+ // Benchmark(M22):shadcn v4 SelectTrigger 預設 `w-fit`
76
+ // https://raw.githubusercontent.com/shadcn-ui/ui/main/apps/v4/registry/new-york-v4/ui/select.tsx
77
+ // Radix Select Trigger intrinsic sizing https://www.radix-ui.com/primitives/docs/components/select
78
+ width: {
79
+ fill: 'w-full',
80
+ hug: 'w-fit max-w-full',
81
+ },
64
82
  // error(2026-07-04 Q1 拍板,SSOT 集中):原散在各控件的 error border classes 因
65
83
  // focus-within:!border-primary(!important)被蓋 = dead code(聚焦永遠藍)。
66
84
  // Benchmark 實查證偽舊宣稱:MUI(紅框加粗)/ Ant(紅框紅 glow)/ Polaris(紅 border
@@ -119,7 +137,18 @@ export const fieldWrapperStyles = cva(
119
137
  {
120
138
  mode: 'readonly',
121
139
  variant: 'default',
122
- className: 'bg-readonly border border-transparent',
140
+ // 2026-07-09 A11y fix(WCAG 2.4.7 Focus Visible):readonly **有值** 渲染 native `<input readOnly>`
141
+ // = 可 Tab 聚焦、可選取/複製,但原 compound 無任何 focus 指示 → 鍵盤使用者聚焦不可見 = 違反。
142
+ // 補 focus ring 採 **ring idiom**(`ring-2 ring-ring ring-offset-1`,與 Button/Checkbox/Tabs/
143
+ // Switch 同一套 focus-visible canonical;`--ring == --primary` semantic.css:334)而非 edit mode
144
+ // 的 `border-primary` idiom —— readonly 邊框 transparent 無可染;且 ring 語義 = 「可聚焦但非文字
145
+ // 輸入」(對齊 button/tab/checkbox 這類 focusable-非-text-entry 控件的視覺語言)。
146
+ // `:has(:focus-visible)`:readonly 渲 native `<input readOnly>`。⚠️ 瀏覽器對 text-entry 控件的
147
+ // :focus-visible 啟發式在滑鼠點擊時**亦 match**(text input 恆視為 focus-visible,對齊
148
+ // field-controls.spec.md「Focus 行為」段『文字輸入永遠 focus-visible、CSS 無法區分點擊與 Tab』),
149
+ // 故點擊 readonly input 也會顯 ring,勿宣稱僅鍵盤觸發(button 的 focus-visible 才滑鼠不觸發,
150
+ // input 不同;真要滑鼠抑制需 JS 追蹤 input modality,屬 API 擴充)。
151
+ className: 'bg-readonly border border-transparent [&:has(:focus-visible)]:ring-2 [&:has(:focus-visible)]:ring-ring [&:has(:focus-visible)]:ring-offset-1',
123
152
  },
124
153
  {
125
154
  // 2026-05-13 R3.5(per codex Q3 verdict + user 拍「想盡辦法 auto-handle prereq」):
@@ -130,42 +159,14 @@ export const fieldWrapperStyles = cva(
130
159
  variant: 'default',
131
160
  className: 'bg-disabled border border-transparent cursor-not-allowed',
132
161
  },
133
- // bare variant chrome by mode
134
- {
135
- mode: 'edit',
136
- variant: 'bare',
137
- className: [
138
- 'bg-transparent border border-transparent',
139
- 'hover:border-border',
140
- // 同 default chrome v13.3 SSOT:focus-within !important 強制勝過 data-state
141
- //(2026-07-04 Q1:同 default,focus 藍移到 error:false compound)
142
- 'data-[state=open]:border-border',
143
- ],
144
- },
145
- { mode: 'edit', variant: 'bare', error: false, className: 'focus-within:!border-primary focus-within:hover:!border-primary' },
162
+ // (2026-07-09 `bare` variant 退役:原 edit×bare / edit×bare×error compounds 已移除。)
146
163
  // error chrome(mode=edit 限定,variant 不分 — naked cell 內 error 同樣紅框,保留既有控件層行為):
147
164
  {
148
165
  mode: 'edit',
149
166
  error: true,
150
167
  className: 'border-error hover:border-error-hover focus-within:!border-error focus-within:hover:!border-error',
151
168
  },
152
- {
153
- mode: 'display',
154
- variant: 'bare',
155
- // bare + display:cell-as-input default state(無 variant,完全融入 cell;hover/focus 才有 affordance 等 user 點下去切 edit mode)
156
- className: 'bg-transparent border border-transparent',
157
- },
158
- {
159
- mode: 'readonly',
160
- variant: 'bare',
161
- className: 'bg-transparent border border-transparent',
162
- },
163
- {
164
- // 2026-05-13 R3.5:移除 `opacity-disabled` blanket(per Avatar self-dim canonical)
165
- mode: 'disabled',
166
- variant: 'bare',
167
- className: 'bg-transparent border border-transparent cursor-not-allowed',
168
- },
169
+ // (2026-07-09 `bare` variant 退役:原 display×bare / readonly×bare / disabled×bare compounds 已移除。)
169
170
  // naked variant — cell-as-input substrate(Notion / Airtable / Excel canonical)
170
171
  //
171
172
  // ── 2026-05-06 v14:revert v12 → v9 baseline + keep v13.3 ──
@@ -248,6 +249,7 @@ export const fieldWrapperStyles = cva(
248
249
  mode: 'edit',
249
250
  variant: 'default',
250
251
  size: 'md',
252
+ width: 'fill',
251
253
  error: false,
252
254
  },
253
255
  }
@@ -351,12 +353,18 @@ export const nakedCellEditableDisplayHover = 'hover:outline hover:outline-1 hove
351
353
  // - 多行 wrapper items-start → slot 1lh 鎖頂 = 第一行中線
352
354
  // 不需 conditional `group-data-[row-mode=auto]/cell:` — 我前 v4 自加的 conditional 是過度設計。
353
355
  //
354
- // State ring 3 const 仍留(下方)— 是 Field naked 專屬,MenuItem / TreeView 用 bg hover 不用 outline。
356
+ // State ring 唯一 const `nakedCellEditableDisplayHover` 仍留(下方 L332,見其自述「sole remaining ring const」)— 是 Field naked 專屬,MenuItem / TreeView 用 bg hover 不用 outline。
355
357
  // `nakedCellRowModeAlign`(wrapper 級)仍留 — 是 cell-context row-mode → wrapper alignment 適配,正交 slot 級。
356
358
 
357
359
  // ── Empty Value Display ─────────────────────────────────────────────────────
358
360
 
359
- export const EMPTY_DISPLAY = '—'
361
+ // 2026-07-08 user 拍板(verbatim「我從頭到尾哪裡有說要用全形的」):空值符號 = **半形 hyphen
362
+ // `-`(U+002D)**,非全形 em dash `—`(U+2014)。不可編輯(readonly / standalone display /
363
+ // table 不可編輯 cell)空值一律此符號 + `text-fg-muted`。分流邏輯 SSOT = field-context.ts
364
+ // `useFieldEmptyDisplay()`(table-cell 可編輯 → 空白;其餘 → 本常數)。
365
+ // 世界級對照:Ant ProTable `columnEmptyText` 預設 `'-'`(U+002D 半形)
366
+ // https://github.com/ant-design/pro-components/blob/master/src/table/Table.tsx
367
+ export const EMPTY_DISPLAY = '-'
360
368
 
361
369
  /**
362
370
  * 2026-05-14 I2 fix(per field-controls.spec.md contract (e) display typography canonical):
@@ -38,7 +38,7 @@ export const Overview: Story = {
38
38
  </Field>
39
39
  </FieldGroup>
40
40
  </div>
41
- <p className="text-footnote text-fg-muted mt-3">FieldLabel(必有)+ Control(必有)+ FieldDescription(選填)+ FieldError( invalid 時顯示)</p>
41
+ <p className="text-footnote text-fg-muted mt-3">FieldLabel(必有)+ Control(必有)+ FieldDescription(選填)+ FieldError(consumer 傳 error 文字時渲染;children 有值即顯、固定 role=alert,非讀 Field.invalid 自動隱藏)</p>
42
42
  </div>
43
43
 
44
44
  <div>
@@ -73,7 +73,7 @@ export const Overview: Story = {
73
73
  ['disabled', 'boolean', 'false', 'context.disabled 傳給 control'],
74
74
  ['size', "'sm' | 'md' | 'lg'", "'md'", 'context.size 傳給 input-class control(Input / NumberInput / Select);primitive 不讀'],
75
75
  ['mode', "'edit' | 'display' | 'readonly' | 'disabled'", "'edit'", 'context.mode 傳給 Field Controls'],
76
- ['variant', "'default' | 'bare' | 'naked'", "'default'", "視覺外殼:default 含 border+bg / bare hover-reveal(toolbar inline edit)/ naked chrome(DataTable cell substrate)"],
76
+ ['variant', "'default'", "'default'", "視覺外殼(公開型別僅 'default',2026-07-14 收窄;naked = @internal FieldVariantInternal):default 含 border+bg / naked = DataTable cell substrate:edit×naked 自畫 border-based state machine(rest/hover/focus/error),display/readonly/disabled×naked transparent border;2026-07-09 `bare` 退役"],
77
77
  ['controlLayout', "'inline' | 'block'", '(自動偵測)', '逃生艙:覆寫 control area 佈局(consumer 手寫 JSX 當 control 無法偵測時用)'],
78
78
  ].map(([p, t, d, desc]) => (
79
79
  <tr key={p}><Td mono>{p}</Td><Td mono>{t}</Td><Td mono>{d}</Td><Td>{desc}</Td></tr>
@@ -248,8 +248,11 @@ export const OrientationMatrix: Story = {
248
248
  <Switch defaultChecked className="ml-0" />
249
249
  </Field>
250
250
  <Field orientation="horizontal">
251
- <FieldLabel>個人檔案公開</FieldLabel>
252
- <Checkbox label="允許搜尋引擎索引" />
251
+ <FieldLabel>允許搜尋引擎索引</FieldLabel>
252
+ {/* 單一布林欄位只用 FieldLabel,不再給 Checkbox label —— field.spec.md 禁止事項
253
+ 「不得同時放 FieldLabel 和 primitive label」(Field context 會抑制 primitive label,
254
+ 傳了不生效且重複宣告);與上方 Switch 列同款 pattern */}
255
+ <Checkbox />
253
256
  </Field>
254
257
  </FieldGroup>
255
258
  </div>
@@ -411,9 +414,9 @@ export const ColorMatrix: Story = {
411
414
  </tr>
412
415
  <tr>
413
416
  <Td mono>FieldError</Td>
414
- <Td>—(不渲染)</Td>
417
+ <Td>—(無 error children → 不渲染;children-gated,非 invalid-gated)</Td>
415
418
  <Td><TokenCell token="--error-text" display="error-text" /></Td>
416
- <Td>—</Td>
419
+ <Td><TokenCell token="--error-text" display="error-text(不 dim)" /></Td>
417
420
  </tr>
418
421
  <tr>
419
422
  <Td mono>Control border(傳給 Field Controls)</Td>
@@ -418,7 +418,7 @@ Field 內的資料輸入控件(Input / NumberInput / DatePicker / Select / Com
418
418
  | **L3 State machine** | **繼承 Field default v13.3**(↑ 上方 SSOT)| 不重定義 |
419
419
  | **L4 Display hover** | `field-wrapper.tsx` `nakedCellEditableDisplayHover` | editable cell display mode `outline-1 outline-offset:-1 outline-[var(--cell-hover-outline-color,var(--border-hover))]`(cell wrapper outline;2026-05-10 Slice D:spreadsheet overlay 啟用時 DataTable cell host 可 set `--cell-hover-outline-color: transparent` 抑制 outline、讓 overlay layer 接管 hover ring paint,fallback 即 `--border-hover` 既有行為不變)。**v15.13 design intent(user-accepted 2026-05-07)**:hover ring 蓋 cell.borderRight。**known asymmetry**(2026-05-09 user 重抓):只 **right** 邊 outline 跟 cell own border-r 同位置覆蓋成 1 條;top/left/bottom 邊 outline 在 cell.outer 內 1px,grid lines(前 row border-b / 前 cell border-r / row 自己 border-b 在 cell.outer 外 1px)露出 → 視覺 4 邊不對稱。**Pending design decision**(等 user 拍板才 ship):4 邊都蓋(spec 1 selection-style)vs 4 邊都不蓋(spec 2 inset 1px)vs 維持現狀。三層 SSOT:state source = cell wrapper / paint owner = 混合(hover=cell / edit=Field)/ grid divider = DataTable own |
420
420
  | **L5 Position(v14,2026-05-06 revert v12)** | naked compoundVariant flow | Field 留 layout flow,**不**用 `!absolute`(v12 absolute 跟 autoRowHeight 不相容)。視覺接受 cell `border-r grid` + Field border 2px 雙線;cell border-r divider 永遠保留(對齊 L4 Invariant divider-owner / editor-owner 分離)|
421
- | **L6 Cell trigger indicator(v15,2026-05-09)** | naked-display branch + `showDisplayEndIcon?: boolean` opt-in | DataTable cell-registry 顯式傳 `showDisplayEndIcon` Field component 內部 `<ItemSuffix>` 渲對應 trigger icon(Select/Combobox/PeoplePicker → ChevronDown / DatePicker → CalendarIcon / TimePicker → Clock / LinkInput 例外無 suffix)。table 外用法不傳此 prop = 純展示無 icon。詳 `.claude/planning/cell-indicator-ssot-rfc.md`。|
421
+ | **L6 Cell trigger indicator(v16,2026-07-08 user 拍板 A 案)** | naked-display branch + `showDisplayEndIcon?: boolean` opt-in(**default off,production 不再傳**)| **display 態零恆顯型別 icon** — editable affordance 統一 = L4 hover outline。Benchmark 6/6(Ant editable-cells 純文字+hover border / MUI X singleSelect display 純文字 / AG Grid 無內建 indicator / Atlaskit v2.0.0 移除 hover-pencil 後 9 版未回歸 / Notion / Airtable click-to-edit)display 態皆無恆顯 icon;唯一反例 Google Sheets Chip/Arrow 為 spreadsheet 域可選檔位。prop 保留為 spreadsheet-flavored 消費端 opt-in 逃生門:傳 true → `<ItemSuffix>` 渲型別 icon(Select/Combobox/PeoplePicker → ChevronDown / DatePicker → Calendar / TimePicker → Clock / **LinkInput 例外 = wrapper-only 無 icon**)。cell-registry 現況:6 picker 站不傳;url 站傳 `isEditable === true`(取 wrapper chrome 對齊 edit Input,非 icon)。edit 態 chevron 照舊(edit-trigger 通道,不受此 prop 管)。**值內容 vs affordance 分層(2026-07-08 user Q2 拍板)**:值內容(`selectedItemRenderer` 輸出 / avatar / type icon 等語意呈現)歸 value renderer,display 態照常渲染,恆顯**不**違反本條;本條管的是 affordance(chevron / pencil / outline)。前身 v15 恆顯制(2026-05-10/06-26 拍板)由本輪 benchmark 重判推翻。詳 `.claude/planning/cell-indicator-ssot-rfc.md`。|
422
422
 
423
423
  **前身 retire**:v4-v8 `outline-2` 平行 state(已下沉 L3)/ v9 border-only(focus 跟 open specificity tie)/ per-control `open && 'border-primary'`(v13.3 retire)/ `nakedCell{Hover,Focus,Open}Ring` 三 const / `nakedCell{Prefix,Suffix}Slot`(下沉 L1)/ **v12 `!absolute -inset-px` seamless grid**(2026-05-06 revert — autoRowHeight 不相容)/ **DataTable parallel `getEditIndicator`**(2026-05-09 D-path retire — 由 Field naked-display 透過 `showDisplayEndIcon` opt-in 自渲 ItemSuffix,跨元件 SSOT 統一)。
424
424
 
@@ -86,7 +86,7 @@ export const StateCascade: Story = {
86
86
  </div>
87
87
  </div>
88
88
  <div>
89
- <p className="text-body-sm font-medium text-fg-secondary mb-3">{'<Field mode="readonly"> — 鎖定表單:文字控件灰框;boolean/單選 = 灰框 + ✓/—/選中項(2026-06-12 拍板);Rating 星星鎖定、Slider 鎖互動保留視覺'}</p>
89
+ <p className="text-body-sm font-medium text-fg-secondary mb-3">{'<Field mode="readonly"> — 鎖定表單:文字控件灰框;boolean/單選 = 灰框 + 勾/叉 icon/選中項(2026-06-12 拍板);Rating 星星鎖定、Slider 鎖互動保留視覺'}</p>
90
90
  <div className="flex flex-wrap gap-x-8 gap-y-4 max-w-3xl">
91
91
  <Field mode="readonly" className="w-44"><FieldLabel>負責人</FieldLabel><Input value="王小明" onChange={() => {}} /></Field>
92
92
  <Field mode="readonly" className="w-44"><FieldLabel>同意條款</FieldLabel><Checkbox checked /></Field>
@@ -110,7 +110,8 @@ export interface FieldProps extends Omit<React.HTMLAttributes<HTMLDivElement>, '
110
110
  /**
111
111
  * 視覺外殼(2026-05-05)。
112
112
  * - `default`(預設)— 含 border + bg(一般 form input)
113
- * - `bare` — 透明 variant,hover/focus reveal(cell-as-input substrate;VS Code/Figma toolbar idiom)
113
+ * - `naked` — cell-as-input(@internal;不在公開 FieldVariant 型別 — 2026-07-14 收窄至 FieldVariantInternal;2026-07-09 `bare` 退役)。edit×naked 自畫 border-based state
114
+ * machine(rest/hover/focus/error);display/readonly/disabled×naked 用 transparent border,host cell 提供視覺邊框
114
115
  *
115
116
  * 透傳機制:Field 一次宣告,所有 child Field control 自動繼承(per-control prop override 可覆寫)。
116
117
  */
@@ -41,7 +41,7 @@
41
41
  ### Submit 驗證
42
42
 
43
43
  7. **Submit 驗證全部**——點擊 submit 時對所有欄位執行驗證(不依賴個別 field 的 blur 狀態)
44
- 8. **Anchor 到第一個錯誤**——若有任何欄位出錯,scroll 並 focus 到第一個錯誤欄位(**「第一個」= DOM 視覺順序**,非 validate key 宣告順序;對齊瀏覽器原生 reportValidity + react-hook-form shouldFocusError,2026-07-07 code 同步)。多次 submit 重試時,每次都重新驗證全部欄位並重新計算「第一個錯誤」(rule 7 的自然結果),不保持上次 anchor 位置
44
+ 8. **Anchor 到第一個錯誤**——若有任何欄位出錯,scroll 並 focus 到第一個錯誤欄位(focus 僅對可由 DOM `name` 定位的 native input 生效,非 native 控件(Select / Combobox / RadioGroup 等)fallback 為 scroll + error 視覺,見下方「v1 邊界」(b);**「第一個」= DOM 視覺順序**,非 validate key 宣告順序;對齊瀏覽器原生 reportValidity + react-hook-form shouldFocusError,2026-07-07 code 同步)。多次 submit 重試時,每次都重新驗證全部欄位並重新計算「第一個錯誤」(rule 7 的自然結果),不保持上次 anchor 位置
45
45
  9. **Async / cross-field 驗證 defer 到 submit**——某些驗證無法在 blur 當下完成(如「名稱是否重複」需要 API 查詢、跨欄位邏輯如「結束日不得早於開始日」),這些在 submit 時統一判斷。若有錯誤,同樣 anchor 到第一個出錯欄位。
46
46
 
47
47
  **Double-submit 防護(2026-07-05 D4 codify,規則 9 的必然配套)**:async onSubmit 進行期間,重複 submit(連點按鈕 / 連按 Enter)一律忽略——否則業務層被並發呼叫兩次(重複建立資源的經典事故)。submit 期間狀態以 `isSubmitting` 暴露(餵 Button loading / disabled;`submitDisabled` 同步為 true);onSubmit 拋錯時先復位 `isSubmitting` 再讓錯誤原樣上拋(不吞錯,表單回到可重送狀態)。對齊 react-hook-form `formState.isSubmitting` / Polaris / Mantine form submitting 內建。 <!-- @benchmark-unverified -->
@@ -151,8 +151,8 @@ Email 格式 / URL 格式 / 必填等「single-field 純 syntax」blur 即可判
151
151
  Form validation 的 ARIA / 鍵盤行為(對齊 WCAG 3.3.1 Error Identification + 3.3.3 Error Suggestion):
152
152
 
153
153
  - **Error message ARIA**:`<FieldError>` 容器 id = `{fieldId}-error`(fieldId 為 Field 的 `id` prop / `useId`,field.tsx:174),控件經 Field context 自動接 `aria-errormessage`(有 error 時指向 errorId)+ `aria-invalid="true"`;`aria-describedby` 保留給 FieldDescription(descriptionId)。SR 在 focus field 時可得 label + error 完整資訊;接線 SSOT 見 `field.spec.md`「驗證與 aria 屬性」段(input.tsx:187-190)
154
- - **Submit error scroll**:submit 失敗後,focus 自動 jump 到第一個 invalid field(`field.focus()` + `scrollIntoView({block: 'center'})`);對齊 Material / Atlassian 慣例 <!-- @benchmark-unverified -->
155
- - **Error live region**:跨欄位 / async error `aria-live="polite"` 容器宣告 SR 在空閒時讀出,不中斷使用者打字
154
+ - **Submit error scroll**:submit 失敗後,focus 自動 jump 到第一個 invalid field(`field.focus()` + `scrollIntoView({block: 'center'})`;focus 僅對 DOM `name`-locatable native input 生效,非 native 控件 fallback 為 scroll + error 視覺,見「v1 邊界」(b));對齊 Material / Atlassian 慣例 <!-- @benchmark-unverified -->
155
+ - **Error 宣告**:`<FieldError>` 為 `role="alert"`(隱含 `aria-live="assertive"`,field.tsx:468)——error 文字一出現即由 SR 宣讀;children 有值才渲染(children-gated,非讀 Field.invalid)。目前**無**獨立 `aria-live="polite"` 容器,跨欄位 / async error 亦透過對應 field 的 `<FieldError>` 呈現
156
156
  - **Required indicator**:label 的 `*` 為純視覺、對讀屏隱藏(`aria-hidden="true"`,field.tsx:395);required 語意由內部輸入控件的 `aria-required`(input.tsx:188)承擔,避免讀屏讀出「asterisk」語義不清
157
157
  - **Color-only error 警告**:error border 紅色之外必有文字訊息(WCAG 1.4.1 不僅靠顏色)— 由 `<FieldError>` 文字承擔;DS **不**在 input 內放 error 狀態 icon(見 `field-controls.spec.md`「禁止事項」)
158
158
 
@@ -38,7 +38,7 @@ export const UsageGuidance: Story = {
38
38
  </ul>
39
39
  <div className="mt-3">
40
40
  <FieldControlGroup block>
41
- <Input className="flex-1" startIcon={Search} placeholder="搜尋..." />
41
+ <Input className="flex-1" startIcon={Search} placeholder="搜尋..." aria-label="搜尋" />
42
42
  <Button variant="primary">搜尋</Button>
43
43
  </FieldControlGroup>
44
44
  </div>
@@ -101,8 +101,8 @@ export const UsageGuidance: Story = {
101
101
  <Field>
102
102
  <FieldLabel>聯絡電話</FieldLabel>
103
103
  <FieldControlGroup block>
104
- <Select className="!w-[88px]" options={CODES} value="+886" onChange={() => {}} />
105
- <Input className="flex-1" placeholder="912 345 678" />
104
+ <Select className="!w-[88px]" options={CODES} value="+886" onChange={() => {}} aria-label="國碼" />
105
+ <Input className="flex-1" placeholder="912 345 678" aria-label="電話號碼" />
106
106
  </FieldControlGroup>
107
107
  </Field>
108
108
  <p className="text-caption text-fg-muted mt-2">Field label / description / error 對 group 整體生效;children 的 size 各自從外層 Field context 繼承(FCG 不傳遞 size)。</p>
@@ -111,9 +111,9 @@ export const UsageGuidance: Story = {
111
111
  <section>
112
112
  <h2 className="text-body-lg font-bold mb-3">Mode B — Filter row 場景</h2>
113
113
  <FieldControlGroup block>
114
- <Select className="!w-[140px]" options={FIELDS} value="name" onChange={() => {}} />
115
- <Select className="!w-[120px]" options={OPS} value="contains" onChange={() => {}} />
116
- <Input className="flex-1" defaultValue="無線滑鼠" />
114
+ <Select className="!w-[140px]" options={FIELDS} value="name" onChange={() => {}} aria-label="篩選欄位" />
115
+ <Select className="!w-[120px]" options={OPS} value="contains" onChange={() => {}} aria-label="篩選運算子" />
116
+ <Input className="flex-1" defaultValue="無線滑鼠" aria-label="篩選值" />
117
117
  </FieldControlGroup>
118
118
  </section>
119
119
  </div>