@qijenchen/design-system 0.1.0-beta.13 → 0.1.0-beta.131

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 (1751) hide show
  1. package/AGENTS.md +8 -0
  2. package/CLAUDE.md +3 -199
  3. package/README.md +6 -4
  4. package/cli-init.mjs +30 -2
  5. package/dist/components/Accordion/accordion.d.ts +3 -3
  6. package/dist/components/Accordion/accordion.d.ts.map +1 -1
  7. package/dist/components/Accordion/accordion.js +6 -3
  8. package/dist/components/Accordion/accordion.js.map +1 -1
  9. package/dist/components/Accordion/index.d.ts +2 -0
  10. package/dist/components/Accordion/index.d.ts.map +1 -0
  11. package/dist/components/Accordion/index.js +9 -0
  12. package/dist/components/Accordion/index.js.map +1 -0
  13. package/dist/components/AccountMenu/account-menu.d.ts +93 -0
  14. package/dist/components/AccountMenu/account-menu.d.ts.map +1 -0
  15. package/dist/components/AccountMenu/account-menu.js +73 -0
  16. package/dist/components/AccountMenu/account-menu.js.map +1 -0
  17. package/dist/components/AccountMenu/index.d.ts +2 -0
  18. package/dist/components/AccountMenu/index.d.ts.map +1 -0
  19. package/dist/components/AccountMenu/index.js +6 -0
  20. package/dist/components/AccountMenu/index.js.map +1 -0
  21. package/dist/components/AgentPanel/agent-fab.d.ts +24 -0
  22. package/dist/components/AgentPanel/agent-fab.d.ts.map +1 -0
  23. package/dist/components/AgentPanel/agent-logo.d.ts +75 -0
  24. package/dist/components/AgentPanel/agent-logo.d.ts.map +1 -0
  25. package/dist/components/AgentPanel/agent-logo.js +371 -0
  26. package/dist/components/AgentPanel/agent-logo.js.map +1 -0
  27. package/dist/components/AgentPanel/agent-panel.d.ts +183 -0
  28. package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -0
  29. package/dist/components/AgentPanel/agent-panel.js +900 -0
  30. package/dist/components/AgentPanel/agent-panel.js.map +1 -0
  31. package/dist/components/AgentPanel/index.d.ts +2 -0
  32. package/dist/components/AgentPanel/index.d.ts.map +1 -0
  33. package/dist/components/AgentPanel/index.js +16 -0
  34. package/dist/components/AgentPanel/index.js.map +1 -0
  35. package/dist/components/Alert/alert.d.ts +7 -2
  36. package/dist/components/Alert/alert.d.ts.map +1 -1
  37. package/dist/components/Alert/alert.js +12 -8
  38. package/dist/components/Alert/alert.js.map +1 -1
  39. package/dist/components/Alert/index.d.ts +2 -0
  40. package/dist/components/Alert/index.d.ts.map +1 -0
  41. package/dist/components/Alert/index.js +7 -0
  42. package/dist/components/Alert/index.js.map +1 -0
  43. package/dist/components/AppShell/_demo-helpers.d.ts +3 -1
  44. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  45. package/dist/components/AppShell/app-shell.d.ts +19 -4
  46. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  47. package/dist/components/AppShell/app-shell.js +48 -11
  48. package/dist/components/AppShell/app-shell.js.map +1 -1
  49. package/dist/components/AppShell/index.d.ts +2 -0
  50. package/dist/components/AppShell/index.d.ts.map +1 -0
  51. package/dist/components/AppShell/index.js +8 -0
  52. package/dist/components/AppShell/index.js.map +1 -0
  53. package/dist/components/AspectRatio/aspect-ratio.d.ts +3 -2
  54. package/dist/components/AspectRatio/aspect-ratio.d.ts.map +1 -1
  55. package/dist/components/AspectRatio/aspect-ratio.js +4 -2
  56. package/dist/components/AspectRatio/aspect-ratio.js.map +1 -1
  57. package/dist/components/AspectRatio/index.d.ts +2 -0
  58. package/dist/components/AspectRatio/index.d.ts.map +1 -0
  59. package/dist/components/AspectRatio/index.js +6 -0
  60. package/dist/components/AspectRatio/index.js.map +1 -0
  61. package/dist/components/Avatar/avatar.d.ts +14 -7
  62. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  63. package/dist/components/Avatar/avatar.js +24 -30
  64. package/dist/components/Avatar/avatar.js.map +1 -1
  65. package/dist/components/Avatar/index.d.ts +2 -0
  66. package/dist/components/Avatar/index.d.ts.map +1 -0
  67. package/dist/components/Avatar/index.js +6 -0
  68. package/dist/components/Avatar/index.js.map +1 -0
  69. package/dist/components/Badge/badge.d.ts +21 -9
  70. package/dist/components/Badge/badge.d.ts.map +1 -1
  71. package/dist/components/Badge/badge.js +9 -6
  72. package/dist/components/Badge/badge.js.map +1 -1
  73. package/dist/components/Badge/index.d.ts +2 -0
  74. package/dist/components/Badge/index.d.ts.map +1 -0
  75. package/dist/components/Badge/index.js +7 -0
  76. package/dist/components/Badge/index.js.map +1 -0
  77. package/dist/components/Breadcrumb/breadcrumb.d.ts +16 -3
  78. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  79. package/dist/components/Breadcrumb/breadcrumb.js +21 -53
  80. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  81. package/dist/components/Breadcrumb/index.d.ts +2 -0
  82. package/dist/components/Breadcrumb/index.d.ts.map +1 -0
  83. package/dist/components/Breadcrumb/index.js +12 -0
  84. package/dist/components/Breadcrumb/index.js.map +1 -0
  85. package/dist/components/BulkActionBar/bulk-action-bar.d.ts +7 -4
  86. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  87. package/dist/components/BulkActionBar/bulk-action-bar.js +8 -8
  88. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  89. package/dist/components/BulkActionBar/index.d.ts +2 -0
  90. package/dist/components/BulkActionBar/index.d.ts.map +1 -0
  91. package/dist/components/BulkActionBar/index.js +7 -0
  92. package/dist/components/BulkActionBar/index.js.map +1 -0
  93. package/dist/components/Button/button-group.d.ts +31 -5
  94. package/dist/components/Button/button-group.d.ts.map +1 -1
  95. package/dist/components/Button/button-group.js +31 -14
  96. package/dist/components/Button/button-group.js.map +1 -1
  97. package/dist/components/Button/button.d.ts +15 -14
  98. package/dist/components/Button/button.d.ts.map +1 -1
  99. package/dist/components/Button/button.js +94 -52
  100. package/dist/components/Button/button.js.map +1 -1
  101. package/dist/components/Button/index.d.ts +3 -0
  102. package/dist/components/Button/index.d.ts.map +1 -0
  103. package/dist/components/Button/index.js +11 -0
  104. package/dist/components/Button/index.js.map +1 -0
  105. package/dist/components/Calendar/calendar.d.ts +22 -19
  106. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  107. package/dist/components/Calendar/calendar.js +180 -135
  108. package/dist/components/Calendar/calendar.js.map +1 -1
  109. package/dist/components/Calendar/index.d.ts +2 -0
  110. package/dist/components/Calendar/index.d.ts.map +1 -0
  111. package/dist/components/Calendar/index.js +6 -0
  112. package/dist/components/Calendar/index.js.map +1 -0
  113. package/dist/components/Carousel/carousel.d.ts +15 -9
  114. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  115. package/dist/components/Carousel/carousel.js +91 -50
  116. package/dist/components/Carousel/carousel.js.map +1 -1
  117. package/dist/components/Carousel/index.d.ts +2 -0
  118. package/dist/components/Carousel/index.d.ts.map +1 -0
  119. package/dist/components/Carousel/index.js +11 -0
  120. package/dist/components/Carousel/index.js.map +1 -0
  121. package/dist/components/Chart/chart.d.ts +2 -2
  122. package/dist/components/Chart/chart.d.ts.map +1 -1
  123. package/dist/components/Chart/chart.js +5 -2
  124. package/dist/components/Chart/chart.js.map +1 -1
  125. package/dist/components/Chart/index.d.ts +2 -0
  126. package/dist/components/Chart/index.d.ts.map +1 -0
  127. package/dist/components/Chart/index.js +11 -0
  128. package/dist/components/Chart/index.js.map +1 -0
  129. package/dist/components/Checkbox/checkbox-group.d.ts +2 -1
  130. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
  131. package/dist/components/Checkbox/checkbox-group.js +21 -14
  132. package/dist/components/Checkbox/checkbox-group.js.map +1 -1
  133. package/dist/components/Checkbox/checkbox.d.ts +20 -11
  134. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  135. package/dist/components/Checkbox/checkbox.js +117 -18
  136. package/dist/components/Checkbox/checkbox.js.map +1 -1
  137. package/dist/components/Checkbox/index.d.ts +3 -0
  138. package/dist/components/Checkbox/index.d.ts.map +1 -0
  139. package/dist/components/Checkbox/index.js +10 -0
  140. package/dist/components/Checkbox/index.js.map +1 -0
  141. package/dist/components/Chip/chip.d.ts +30 -11
  142. package/dist/components/Chip/chip.d.ts.map +1 -1
  143. package/dist/components/Chip/chip.js +83 -33
  144. package/dist/components/Chip/chip.js.map +1 -1
  145. package/dist/components/Chip/index.d.ts +2 -0
  146. package/dist/components/Chip/index.d.ts.map +1 -0
  147. package/dist/components/Chip/index.js +8 -0
  148. package/dist/components/Chip/index.js.map +1 -0
  149. package/dist/components/CircularProgress/circular-progress.d.ts +2 -3
  150. package/dist/components/CircularProgress/circular-progress.d.ts.map +1 -1
  151. package/dist/components/CircularProgress/circular-progress.js +5 -4
  152. package/dist/components/CircularProgress/circular-progress.js.map +1 -1
  153. package/dist/components/CircularProgress/index.d.ts +2 -0
  154. package/dist/components/CircularProgress/index.d.ts.map +1 -0
  155. package/dist/components/CircularProgress/index.js +6 -0
  156. package/dist/components/CircularProgress/index.js.map +1 -0
  157. package/dist/components/Coachmark/coachmark-story-helpers.d.ts +22 -0
  158. package/dist/components/Coachmark/coachmark-story-helpers.d.ts.map +1 -0
  159. package/dist/components/Coachmark/coachmark.d.ts +15 -6
  160. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  161. package/dist/components/Coachmark/coachmark.js +12 -4
  162. package/dist/components/Coachmark/coachmark.js.map +1 -1
  163. package/dist/components/Coachmark/index.d.ts +2 -0
  164. package/dist/components/Coachmark/index.d.ts.map +1 -0
  165. package/dist/components/Coachmark/index.js +6 -0
  166. package/dist/components/Coachmark/index.js.map +1 -0
  167. package/dist/components/Combobox/combobox.d.ts +39 -15
  168. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  169. package/dist/components/Combobox/combobox.js +169 -65
  170. package/dist/components/Combobox/combobox.js.map +1 -1
  171. package/dist/components/Combobox/index.d.ts +2 -0
  172. package/dist/components/Combobox/index.d.ts.map +1 -0
  173. package/dist/components/Combobox/index.js +6 -0
  174. package/dist/components/Combobox/index.js.map +1 -0
  175. package/dist/components/Command/command.d.ts +7 -3
  176. package/dist/components/Command/command.d.ts.map +1 -1
  177. package/dist/components/Command/command.js +23 -10
  178. package/dist/components/Command/command.js.map +1 -1
  179. package/dist/components/Command/index.d.ts +2 -0
  180. package/dist/components/Command/index.d.ts.map +1 -0
  181. package/dist/components/Command/index.js +14 -0
  182. package/dist/components/Command/index.js.map +1 -0
  183. package/dist/components/DataTable/active-editor-controller.d.ts +4 -3
  184. package/dist/components/DataTable/active-editor-controller.d.ts.map +1 -1
  185. package/dist/components/DataTable/cell-registry.d.ts +5 -5
  186. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  187. package/dist/components/DataTable/cell-registry.js +89 -95
  188. package/dist/components/DataTable/cell-registry.js.map +1 -1
  189. package/dist/components/DataTable/column-types.d.ts +11 -21
  190. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  191. package/dist/components/DataTable/column-types.js.map +1 -1
  192. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +4 -3
  193. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
  194. package/dist/components/DataTable/data-table-column-visibility-panel.js +193 -0
  195. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
  196. package/dist/components/DataTable/data-table-filter-group.d.ts +51 -0
  197. package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
  198. package/dist/components/DataTable/data-table-filter-group.js +159 -0
  199. package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
  200. package/dist/components/DataTable/data-table-filter-labels.d.ts +44 -0
  201. package/dist/components/DataTable/data-table-filter-labels.d.ts.map +1 -0
  202. package/dist/components/DataTable/data-table-filter-labels.js +55 -0
  203. package/dist/components/DataTable/data-table-filter-labels.js.map +1 -0
  204. package/dist/components/DataTable/data-table-filter-panel.d.ts +12 -3
  205. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  206. package/dist/components/DataTable/data-table-filter-panel.js +316 -0
  207. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  208. package/dist/components/DataTable/data-table-filter-value-picker.d.ts +32 -0
  209. package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
  210. package/dist/components/DataTable/data-table-filter-value-picker.js +205 -0
  211. package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
  212. package/dist/components/DataTable/data-table-interaction-layer.d.ts +17 -20
  213. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  214. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  215. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  216. package/dist/components/DataTable/data-table-sort-manager.d.ts +5 -5
  217. package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -1
  218. package/dist/components/DataTable/data-table-sort-manager.js +150 -0
  219. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  220. package/dist/components/DataTable/data-table.d.ts +66 -15
  221. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  222. package/dist/components/DataTable/data-table.js +367 -185
  223. package/dist/components/DataTable/data-table.js.map +1 -1
  224. package/dist/components/DataTable/filter-operators.d.ts +1 -1
  225. package/dist/components/DataTable/filter-operators.js +140 -0
  226. package/dist/components/DataTable/filter-operators.js.map +1 -0
  227. package/dist/components/DataTable/filter-tree.d.ts +6 -1
  228. package/dist/components/DataTable/filter-tree.d.ts.map +1 -1
  229. package/dist/components/DataTable/filter-tree.js +318 -0
  230. package/dist/components/DataTable/filter-tree.js.map +1 -0
  231. package/dist/components/DataTable/index.d.ts +5 -0
  232. package/dist/components/DataTable/index.d.ts.map +1 -0
  233. package/dist/components/DataTable/index.js +21 -0
  234. package/dist/components/DataTable/index.js.map +1 -0
  235. package/dist/components/DataTable/lib/column-meta.js +25 -0
  236. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  237. package/dist/components/DateGrid/date-grid.d.ts +23 -19
  238. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  239. package/dist/components/DateGrid/date-grid.js +60 -12
  240. package/dist/components/DateGrid/date-grid.js.map +1 -1
  241. package/dist/components/DateGrid/index.d.ts +2 -0
  242. package/dist/components/DateGrid/index.d.ts.map +1 -0
  243. package/dist/components/DateGrid/index.js +6 -0
  244. package/dist/components/DateGrid/index.js.map +1 -0
  245. package/dist/components/DatePicker/date-picker.d.ts +12 -12
  246. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  247. package/dist/components/DatePicker/date-picker.js +418 -309
  248. package/dist/components/DatePicker/date-picker.js.map +1 -1
  249. package/dist/components/DatePicker/index.d.ts +2 -0
  250. package/dist/components/DatePicker/index.d.ts.map +1 -0
  251. package/dist/components/DatePicker/index.js +8 -0
  252. package/dist/components/DatePicker/index.js.map +1 -0
  253. package/dist/components/DescriptionList/description-list.d.ts +6 -6
  254. package/dist/components/DescriptionList/description-list.d.ts.map +1 -1
  255. package/dist/components/DescriptionList/description-list.js +11 -10
  256. package/dist/components/DescriptionList/description-list.js.map +1 -1
  257. package/dist/components/DescriptionList/index.d.ts +2 -0
  258. package/dist/components/DescriptionList/index.d.ts.map +1 -0
  259. package/dist/components/DescriptionList/index.js +7 -0
  260. package/dist/components/DescriptionList/index.js.map +1 -0
  261. package/dist/components/Dialog/dialog.d.ts +22 -5
  262. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  263. package/dist/components/Dialog/dialog.js +44 -23
  264. package/dist/components/Dialog/dialog.js.map +1 -1
  265. package/dist/components/Dialog/index.d.ts +2 -0
  266. package/dist/components/Dialog/index.d.ts.map +1 -0
  267. package/dist/components/Dialog/index.js +16 -0
  268. package/dist/components/Dialog/index.js.map +1 -0
  269. package/dist/components/DropdownMenu/dropdown-menu.d.ts +19 -10
  270. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  271. package/dist/components/DropdownMenu/dropdown-menu.js +79 -28
  272. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  273. package/dist/components/DropdownMenu/index.d.ts +2 -0
  274. package/dist/components/DropdownMenu/index.d.ts.map +1 -0
  275. package/dist/components/DropdownMenu/index.js +21 -0
  276. package/dist/components/DropdownMenu/index.js.map +1 -0
  277. package/dist/components/Empty/empty.d.ts +14 -6
  278. package/dist/components/Empty/empty.d.ts.map +1 -1
  279. package/dist/components/Empty/empty.js +7 -7
  280. package/dist/components/Empty/empty.js.map +1 -1
  281. package/dist/components/Empty/index.d.ts +2 -0
  282. package/dist/components/Empty/index.d.ts.map +1 -0
  283. package/dist/components/Empty/index.js +6 -0
  284. package/dist/components/Empty/index.js.map +1 -0
  285. package/dist/components/Field/field-context.d.ts +111 -4
  286. package/dist/components/Field/field-context.d.ts.map +1 -1
  287. package/dist/components/Field/field-context.js +70 -0
  288. package/dist/components/Field/field-context.js.map +1 -1
  289. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  290. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  291. package/dist/components/Field/field-edit-keys.js +19 -0
  292. package/dist/components/Field/field-edit-keys.js.map +1 -0
  293. package/dist/components/Field/field-types.d.ts +22 -3
  294. package/dist/components/Field/field-types.d.ts.map +1 -1
  295. package/dist/components/Field/field-types.js.map +1 -1
  296. package/dist/components/Field/field-wrapper.d.ts +24 -6
  297. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  298. package/dist/components/Field/field-wrapper.js +98 -74
  299. package/dist/components/Field/field-wrapper.js.map +1 -1
  300. package/dist/components/Field/field.d.ts +7 -4
  301. package/dist/components/Field/field.d.ts.map +1 -1
  302. package/dist/components/Field/field.js +39 -6
  303. package/dist/components/Field/field.js.map +1 -1
  304. package/dist/components/Field/index.d.ts +3 -0
  305. package/dist/components/Field/index.d.ts.map +1 -0
  306. package/dist/components/Field/index.js +14 -0
  307. package/dist/components/Field/index.js.map +1 -0
  308. package/dist/components/Field/use-form-validation.d.ts +92 -0
  309. package/dist/components/Field/use-form-validation.d.ts.map +1 -0
  310. package/dist/components/Field/use-form-validation.js +137 -0
  311. package/dist/components/Field/use-form-validation.js.map +1 -0
  312. package/dist/components/FieldControlGroup/field-control-group.d.ts +8 -11
  313. package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -1
  314. package/dist/components/FieldControlGroup/field-control-group.js +2 -2
  315. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  316. package/dist/components/FieldControlGroup/index.d.ts +2 -0
  317. package/dist/components/FieldControlGroup/index.d.ts.map +1 -0
  318. package/dist/components/FieldControlGroup/index.js +6 -0
  319. package/dist/components/FieldControlGroup/index.js.map +1 -0
  320. package/dist/components/FileItem/file-item.d.ts +14 -2
  321. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  322. package/dist/components/FileItem/file-item.js +45 -16
  323. package/dist/components/FileItem/file-item.js.map +1 -1
  324. package/dist/components/FileItem/index.d.ts +2 -0
  325. package/dist/components/FileItem/index.d.ts.map +1 -0
  326. package/dist/components/FileItem/index.js +6 -0
  327. package/dist/components/FileItem/index.js.map +1 -0
  328. package/dist/components/FileUpload/file-upload.d.ts +39 -19
  329. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  330. package/dist/components/FileUpload/file-upload.js +102 -32
  331. package/dist/components/FileUpload/file-upload.js.map +1 -1
  332. package/dist/components/FileUpload/index.d.ts +2 -0
  333. package/dist/components/FileUpload/index.d.ts.map +1 -0
  334. package/dist/components/FileUpload/index.js +6 -0
  335. package/dist/components/FileUpload/index.js.map +1 -0
  336. package/dist/components/FileViewer/can-render-image.d.ts +6 -0
  337. package/dist/components/FileViewer/can-render-image.d.ts.map +1 -0
  338. package/dist/components/FileViewer/can-render-image.js +11 -0
  339. package/dist/components/FileViewer/can-render-image.js.map +1 -0
  340. package/dist/components/FileViewer/file-viewer.d.ts +4 -4
  341. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  342. package/dist/components/FileViewer/file-viewer.js +88 -50
  343. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  344. package/dist/components/FileViewer/image-renderer.d.ts +0 -5
  345. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  346. package/dist/components/FileViewer/image-renderer.js +23 -10
  347. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  348. package/dist/components/FileViewer/index.d.ts +2 -0
  349. package/dist/components/FileViewer/index.d.ts.map +1 -0
  350. package/dist/components/FileViewer/index.js +7 -0
  351. package/dist/components/FileViewer/index.js.map +1 -0
  352. package/dist/components/HoverCard/hover-card.d.ts +9 -5
  353. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  354. package/dist/components/HoverCard/hover-card.js +12 -5
  355. package/dist/components/HoverCard/hover-card.js.map +1 -1
  356. package/dist/components/HoverCard/index.d.ts +2 -0
  357. package/dist/components/HoverCard/index.d.ts.map +1 -0
  358. package/dist/components/HoverCard/index.js +8 -0
  359. package/dist/components/HoverCard/index.js.map +1 -0
  360. package/dist/components/InlineEdit/index.d.ts +2 -0
  361. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  362. package/dist/components/InlineEdit/index.js +6 -0
  363. package/dist/components/InlineEdit/index.js.map +1 -0
  364. package/dist/components/InlineEdit/inline-edit.d.ts +86 -0
  365. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  366. package/dist/components/InlineEdit/inline-edit.js +254 -0
  367. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  368. package/dist/components/Input/index.d.ts +2 -0
  369. package/dist/components/Input/index.d.ts.map +1 -0
  370. package/dist/components/Input/index.js +6 -0
  371. package/dist/components/Input/index.js.map +1 -0
  372. package/dist/components/Input/input.d.ts +31 -10
  373. package/dist/components/Input/input.d.ts.map +1 -1
  374. package/dist/components/Input/input.js +67 -30
  375. package/dist/components/Input/input.js.map +1 -1
  376. package/dist/components/LinkInput/index.d.ts +2 -0
  377. package/dist/components/LinkInput/index.d.ts.map +1 -0
  378. package/dist/components/LinkInput/index.js +6 -0
  379. package/dist/components/LinkInput/index.js.map +1 -0
  380. package/dist/components/LinkInput/link-input.d.ts +9 -9
  381. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  382. package/dist/components/LinkInput/link-input.js +40 -37
  383. package/dist/components/LinkInput/link-input.js.map +1 -1
  384. package/dist/components/Menu/index.d.ts +2 -0
  385. package/dist/components/Menu/index.d.ts.map +1 -0
  386. package/dist/components/Menu/index.js +9 -0
  387. package/dist/components/Menu/index.js.map +1 -0
  388. package/dist/components/Menu/menu-item.d.ts +20 -4
  389. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  390. package/dist/components/Menu/menu-item.js +37 -9
  391. package/dist/components/Menu/menu-item.js.map +1 -1
  392. package/dist/components/Notice/index.d.ts +2 -0
  393. package/dist/components/Notice/index.d.ts.map +1 -0
  394. package/dist/components/Notice/index.js +8 -0
  395. package/dist/components/Notice/index.js.map +1 -0
  396. package/dist/components/Notice/notice.d.ts +35 -7
  397. package/dist/components/Notice/notice.d.ts.map +1 -1
  398. package/dist/components/Notice/notice.js +34 -10
  399. package/dist/components/Notice/notice.js.map +1 -1
  400. package/dist/components/NumberInput/index.d.ts +2 -0
  401. package/dist/components/NumberInput/index.d.ts.map +1 -0
  402. package/dist/components/NumberInput/index.js +7 -0
  403. package/dist/components/NumberInput/index.js.map +1 -0
  404. package/dist/components/NumberInput/number-input.d.ts +5 -5
  405. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  406. package/dist/components/NumberInput/number-input.js +40 -18
  407. package/dist/components/NumberInput/number-input.js.map +1 -1
  408. package/dist/components/OverflowIndicator/index.d.ts +2 -0
  409. package/dist/components/OverflowIndicator/index.d.ts.map +1 -0
  410. package/dist/components/OverflowIndicator/index.js +6 -0
  411. package/dist/components/OverflowIndicator/index.js.map +1 -0
  412. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +6 -2
  413. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  414. package/dist/components/OverflowIndicator/overflow-indicator.js +11 -7
  415. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  416. package/dist/components/Pagination/index.d.ts +2 -0
  417. package/dist/components/Pagination/index.d.ts.map +1 -0
  418. package/dist/components/Pagination/index.js +6 -0
  419. package/dist/components/Pagination/index.js.map +1 -0
  420. package/dist/components/Pagination/pagination.d.ts +49 -0
  421. package/dist/components/Pagination/pagination.d.ts.map +1 -0
  422. package/dist/components/Pagination/pagination.js +182 -0
  423. package/dist/components/Pagination/pagination.js.map +1 -0
  424. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +1 -1
  425. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
  426. package/dist/components/PeoplePicker/index.d.ts +2 -0
  427. package/dist/components/PeoplePicker/index.d.ts.map +1 -0
  428. package/dist/components/PeoplePicker/index.js +15 -0
  429. package/dist/components/PeoplePicker/index.js.map +1 -0
  430. package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -1
  431. package/dist/components/PeoplePicker/people-picker-helpers.js +2 -2
  432. package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -1
  433. package/dist/components/PeoplePicker/people-picker.d.ts +26 -10
  434. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  435. package/dist/components/PeoplePicker/people-picker.js +97 -65
  436. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  437. package/dist/components/PeoplePicker/person-display.d.ts +19 -11
  438. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  439. package/dist/components/PeoplePicker/person-display.js +39 -23
  440. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  441. package/dist/components/Popover/index.d.ts +2 -0
  442. package/dist/components/Popover/index.d.ts.map +1 -0
  443. package/dist/components/Popover/index.js +14 -0
  444. package/dist/components/Popover/index.js.map +1 -0
  445. package/dist/components/Popover/popover.d.ts +2 -2
  446. package/dist/components/Popover/popover.d.ts.map +1 -1
  447. package/dist/components/Popover/popover.js +72 -42
  448. package/dist/components/Popover/popover.js.map +1 -1
  449. package/dist/components/ProfileCard/index.d.ts +2 -0
  450. package/dist/components/ProfileCard/index.d.ts.map +1 -0
  451. package/dist/components/ProfileCard/index.js +8 -0
  452. package/dist/components/ProfileCard/index.js.map +1 -0
  453. package/dist/components/{NameCard/name-card.d.ts → ProfileCard/profile-card.d.ts} +34 -20
  454. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -0
  455. package/dist/components/{NameCard/name-card.js → ProfileCard/profile-card.js} +27 -16
  456. package/dist/components/ProfileCard/profile-card.js.map +1 -0
  457. package/dist/components/ProgressBar/index.d.ts +2 -0
  458. package/dist/components/ProgressBar/index.d.ts.map +1 -0
  459. package/dist/components/ProgressBar/index.js +6 -0
  460. package/dist/components/ProgressBar/index.js.map +1 -0
  461. package/dist/components/ProgressBar/progress-bar.d.ts +2 -14
  462. package/dist/components/ProgressBar/progress-bar.d.ts.map +1 -1
  463. package/dist/components/ProgressBar/progress-bar.js +5 -9
  464. package/dist/components/ProgressBar/progress-bar.js.map +1 -1
  465. package/dist/components/RadioGroup/index.d.ts +2 -0
  466. package/dist/components/RadioGroup/index.d.ts.map +1 -0
  467. package/dist/components/RadioGroup/index.js +8 -0
  468. package/dist/components/RadioGroup/index.js.map +1 -0
  469. package/dist/components/RadioGroup/radio-group.d.ts +18 -12
  470. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  471. package/dist/components/RadioGroup/radio-group.js +131 -40
  472. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  473. package/dist/components/Rating/index.d.ts +2 -0
  474. package/dist/components/Rating/index.d.ts.map +1 -0
  475. package/dist/components/Rating/index.js +6 -0
  476. package/dist/components/Rating/index.js.map +1 -0
  477. package/dist/components/Rating/rating.d.ts +6 -2
  478. package/dist/components/Rating/rating.d.ts.map +1 -1
  479. package/dist/components/Rating/rating.js +17 -10
  480. package/dist/components/Rating/rating.js.map +1 -1
  481. package/dist/components/ScrollArea/index.d.ts +2 -0
  482. package/dist/components/ScrollArea/index.d.ts.map +1 -0
  483. package/dist/components/ScrollArea/index.js +7 -0
  484. package/dist/components/ScrollArea/index.js.map +1 -0
  485. package/dist/components/ScrollArea/scroll-area.d.ts +16 -4
  486. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  487. package/dist/components/ScrollArea/scroll-area.js +9 -6
  488. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  489. package/dist/components/SegmentedControl/index.d.ts +2 -0
  490. package/dist/components/SegmentedControl/index.d.ts.map +1 -0
  491. package/dist/components/SegmentedControl/index.js +9 -0
  492. package/dist/components/SegmentedControl/index.js.map +1 -0
  493. package/dist/components/SegmentedControl/segmented-control.d.ts +8 -7
  494. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  495. package/dist/components/SegmentedControl/segmented-control.js +31 -20
  496. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  497. package/dist/components/Select/index.d.ts +2 -0
  498. package/dist/components/Select/index.d.ts.map +1 -0
  499. package/dist/components/Select/index.js +6 -0
  500. package/dist/components/Select/index.js.map +1 -0
  501. package/dist/components/Select/select.d.ts +70 -13
  502. package/dist/components/Select/select.d.ts.map +1 -1
  503. package/dist/components/Select/select.js +271 -83
  504. package/dist/components/Select/select.js.map +1 -1
  505. package/dist/components/SelectMenu/index.d.ts +2 -0
  506. package/dist/components/SelectMenu/index.d.ts.map +1 -0
  507. package/dist/components/SelectMenu/index.js +8 -0
  508. package/dist/components/SelectMenu/index.js.map +1 -0
  509. package/dist/components/SelectMenu/select-menu.d.ts +61 -10
  510. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  511. package/dist/components/SelectMenu/select-menu.js +216 -93
  512. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  513. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  514. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  515. package/dist/components/SelectionControl/boolean-value.js +23 -0
  516. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  517. package/dist/components/SelectionControl/index.d.ts +3 -0
  518. package/dist/components/SelectionControl/index.d.ts.map +1 -0
  519. package/dist/components/SelectionControl/index.js +9 -0
  520. package/dist/components/SelectionControl/index.js.map +1 -0
  521. package/dist/components/SelectionControl/selection-item.d.ts +5 -1
  522. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
  523. package/dist/components/SelectionControl/selection-item.js +3 -1
  524. package/dist/components/SelectionControl/selection-item.js.map +1 -1
  525. package/dist/components/Separator/index.d.ts +2 -0
  526. package/dist/components/Separator/index.d.ts.map +1 -0
  527. package/dist/components/Separator/index.js +6 -0
  528. package/dist/components/Separator/index.js.map +1 -0
  529. package/dist/components/Separator/separator.d.ts +2 -2
  530. package/dist/components/Separator/separator.js +4 -3
  531. package/dist/components/Separator/separator.js.map +1 -1
  532. package/dist/components/Sheet/index.d.ts +2 -0
  533. package/dist/components/Sheet/index.d.ts.map +1 -0
  534. package/dist/components/Sheet/index.js +18 -0
  535. package/dist/components/Sheet/index.js.map +1 -0
  536. package/dist/components/Sheet/sheet.d.ts +15 -8
  537. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  538. package/dist/components/Sheet/sheet.js +9 -5
  539. package/dist/components/Sheet/sheet.js.map +1 -1
  540. package/dist/components/Sidebar/index.d.ts +2 -0
  541. package/dist/components/Sidebar/index.d.ts.map +1 -0
  542. package/dist/components/Sidebar/index.js +24 -0
  543. package/dist/components/Sidebar/index.js.map +1 -0
  544. package/dist/components/Sidebar/sidebar.d.ts +17 -11
  545. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  546. package/dist/components/Sidebar/sidebar.js +78 -35
  547. package/dist/components/Sidebar/sidebar.js.map +1 -1
  548. package/dist/components/Skeleton/index.d.ts +2 -0
  549. package/dist/components/Skeleton/index.d.ts.map +1 -0
  550. package/dist/components/Skeleton/index.js +6 -0
  551. package/dist/components/Skeleton/index.js.map +1 -0
  552. package/dist/components/Skeleton/skeleton.d.ts +2 -2
  553. package/dist/components/Skeleton/skeleton.js +4 -3
  554. package/dist/components/Skeleton/skeleton.js.map +1 -1
  555. package/dist/components/Slider/index.d.ts +2 -0
  556. package/dist/components/Slider/index.d.ts.map +1 -0
  557. package/dist/components/Slider/index.js +7 -0
  558. package/dist/components/Slider/index.js.map +1 -0
  559. package/dist/components/Slider/slider.d.ts +7 -7
  560. package/dist/components/Slider/slider.d.ts.map +1 -1
  561. package/dist/components/Slider/slider.js +39 -17
  562. package/dist/components/Slider/slider.js.map +1 -1
  563. package/dist/components/Steps/index.d.ts +2 -0
  564. package/dist/components/Steps/index.d.ts.map +1 -0
  565. package/dist/components/Steps/index.js +12 -0
  566. package/dist/components/Steps/index.js.map +1 -0
  567. package/dist/components/Steps/steps.d.ts +8 -6
  568. package/dist/components/Steps/steps.d.ts.map +1 -1
  569. package/dist/components/Steps/steps.js +74 -32
  570. package/dist/components/Steps/steps.js.map +1 -1
  571. package/dist/components/Switch/index.d.ts +2 -0
  572. package/dist/components/Switch/index.d.ts.map +1 -0
  573. package/dist/components/Switch/index.js +7 -0
  574. package/dist/components/Switch/index.js.map +1 -0
  575. package/dist/components/Switch/switch.d.ts +20 -18
  576. package/dist/components/Switch/switch.d.ts.map +1 -1
  577. package/dist/components/Switch/switch.js +133 -26
  578. package/dist/components/Switch/switch.js.map +1 -1
  579. package/dist/components/Tabs/index.d.ts +2 -0
  580. package/dist/components/Tabs/index.d.ts.map +1 -0
  581. package/dist/components/Tabs/index.js +10 -0
  582. package/dist/components/Tabs/index.js.map +1 -0
  583. package/dist/components/Tabs/tabs-inline-action-geometry.d.ts +31 -0
  584. package/dist/components/Tabs/tabs-inline-action-geometry.d.ts.map +1 -0
  585. package/dist/components/Tabs/tabs-inline-action-geometry.js +43 -0
  586. package/dist/components/Tabs/tabs-inline-action-geometry.js.map +1 -0
  587. package/dist/components/Tabs/tabs.d.ts +14 -11
  588. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  589. package/dist/components/Tabs/tabs.js +184 -69
  590. package/dist/components/Tabs/tabs.js.map +1 -1
  591. package/dist/components/Tag/index.d.ts +2 -0
  592. package/dist/components/Tag/index.d.ts.map +1 -0
  593. package/dist/components/Tag/index.js +7 -0
  594. package/dist/components/Tag/index.js.map +1 -0
  595. package/dist/components/Tag/tag.d.ts +39 -23
  596. package/dist/components/Tag/tag.d.ts.map +1 -1
  597. package/dist/components/Tag/tag.js +71 -63
  598. package/dist/components/Tag/tag.js.map +1 -1
  599. package/dist/components/Textarea/index.d.ts +2 -0
  600. package/dist/components/Textarea/index.d.ts.map +1 -0
  601. package/dist/components/Textarea/index.js +7 -0
  602. package/dist/components/Textarea/index.js.map +1 -0
  603. package/dist/components/Textarea/textarea.d.ts +24 -17
  604. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  605. package/dist/components/Textarea/textarea.js +110 -72
  606. package/dist/components/Textarea/textarea.js.map +1 -1
  607. package/dist/components/TimePicker/index.d.ts +2 -0
  608. package/dist/components/TimePicker/index.d.ts.map +1 -0
  609. package/dist/components/TimePicker/index.js +6 -0
  610. package/dist/components/TimePicker/index.js.map +1 -0
  611. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  612. package/dist/components/TimePicker/time-columns.js +44 -36
  613. package/dist/components/TimePicker/time-columns.js.map +1 -1
  614. package/dist/components/TimePicker/time-picker.d.ts +8 -7
  615. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  616. package/dist/components/TimePicker/time-picker.js +71 -53
  617. package/dist/components/TimePicker/time-picker.js.map +1 -1
  618. package/dist/components/Toast/index.d.ts +2 -0
  619. package/dist/components/Toast/index.d.ts.map +1 -0
  620. package/dist/components/Toast/index.js +7 -0
  621. package/dist/components/Toast/index.js.map +1 -0
  622. package/dist/components/Toast/toast.d.ts +2 -2
  623. package/dist/components/Toast/toast.d.ts.map +1 -1
  624. package/dist/components/Toast/toast.js +82 -20
  625. package/dist/components/Toast/toast.js.map +1 -1
  626. package/dist/components/Tooltip/index.d.ts +2 -0
  627. package/dist/components/Tooltip/index.d.ts.map +1 -0
  628. package/dist/components/Tooltip/index.js +9 -0
  629. package/dist/components/Tooltip/index.js.map +1 -0
  630. package/dist/components/Tooltip/tooltip.d.ts +2 -2
  631. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  632. package/dist/components/Tooltip/tooltip.js +57 -25
  633. package/dist/components/Tooltip/tooltip.js.map +1 -1
  634. package/dist/components/TreeView/index.d.ts +2 -0
  635. package/dist/components/TreeView/index.d.ts.map +1 -0
  636. package/dist/components/TreeView/index.js +8 -0
  637. package/dist/components/TreeView/index.js.map +1 -0
  638. package/dist/components/TreeView/tree-view.d.ts +71 -14
  639. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  640. package/dist/components/TreeView/tree-view.js +313 -34
  641. package/dist/components/TreeView/tree-view.js.map +1 -1
  642. package/dist/hooks/use-controllable.d.ts.map +1 -1
  643. package/dist/hooks/use-controllable.js +4 -2
  644. package/dist/hooks/use-controllable.js.map +1 -1
  645. package/dist/hooks/use-is-touch-device.d.ts.map +1 -1
  646. package/dist/hooks/use-is-touch-device.js +3 -1
  647. package/dist/hooks/use-is-touch-device.js.map +1 -1
  648. package/dist/hooks/use-overflow-items.d.ts +10 -6
  649. package/dist/hooks/use-overflow-items.d.ts.map +1 -1
  650. package/dist/hooks/use-overflow-items.js.map +1 -1
  651. package/dist/hooks/use-truncated.d.ts +27 -0
  652. package/dist/hooks/use-truncated.d.ts.map +1 -0
  653. package/dist/hooks/use-truncated.js +57 -0
  654. package/dist/hooks/use-truncated.js.map +1 -0
  655. package/dist/{react-day-picker.css → index.css} +59 -0
  656. package/dist/index.d.ts +121 -67
  657. package/dist/index.d.ts.map +1 -1
  658. package/dist/index.js +143 -160
  659. package/dist/index.js.map +1 -1
  660. package/dist/lib/drag-visual.d.ts +2 -2
  661. package/dist/lib/drag-visual.js.map +1 -1
  662. package/dist/lib/utils.d.ts +1 -0
  663. package/dist/lib/utils.d.ts.map +1 -1
  664. package/dist/lib/utils.js +24 -2
  665. package/dist/lib/utils.js.map +1 -1
  666. package/dist/patterns/element-anatomy/index.d.ts +3 -0
  667. package/dist/patterns/element-anatomy/index.d.ts.map +1 -0
  668. package/dist/patterns/element-anatomy/index.js +22 -0
  669. package/dist/patterns/element-anatomy/index.js.map +1 -0
  670. package/dist/patterns/element-anatomy/item-anatomy.d.ts +32 -16
  671. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  672. package/dist/patterns/element-anatomy/item-anatomy.js +83 -35
  673. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  674. package/dist/patterns/element-anatomy/truncated-text.d.ts +27 -0
  675. package/dist/patterns/element-anatomy/truncated-text.d.ts.map +1 -0
  676. package/dist/patterns/element-anatomy/truncated-text.js +16 -0
  677. package/dist/patterns/element-anatomy/truncated-text.js.map +1 -0
  678. package/dist/patterns/header-canonical/chrome-header.d.ts +20 -4
  679. package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -1
  680. package/dist/patterns/header-canonical/chrome-header.js +4 -2
  681. package/dist/patterns/header-canonical/chrome-header.js.map +1 -1
  682. package/dist/patterns/header-canonical/index.d.ts +2 -0
  683. package/dist/patterns/header-canonical/index.d.ts.map +1 -0
  684. package/dist/patterns/header-canonical/index.js +6 -0
  685. package/dist/patterns/header-canonical/index.js.map +1 -0
  686. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts +1 -1
  687. package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -1
  688. package/dist/patterns/horizontal-overflow/index.d.ts +2 -0
  689. package/dist/patterns/horizontal-overflow/index.d.ts.map +1 -0
  690. package/dist/patterns/horizontal-overflow/index.js +14 -0
  691. package/dist/patterns/horizontal-overflow/index.js.map +1 -0
  692. package/dist/patterns/overlay-surface/index.d.ts +2 -0
  693. package/dist/patterns/overlay-surface/index.d.ts.map +1 -0
  694. package/dist/patterns/overlay-surface/index.js +8 -0
  695. package/dist/patterns/overlay-surface/index.js.map +1 -0
  696. package/dist/patterns/overlay-surface/overlay-surface.d.ts +12 -2
  697. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  698. package/dist/patterns/overlay-surface/overlay-surface.js +6 -2
  699. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  700. package/dist/patterns/resize-handle/index.d.ts +2 -0
  701. package/dist/patterns/resize-handle/index.d.ts.map +1 -0
  702. package/dist/patterns/resize-handle/index.js +5 -0
  703. package/dist/patterns/resize-handle/index.js.map +1 -0
  704. package/dist/patterns/resize-handle/resize-handle.d.ts +9 -11
  705. package/dist/patterns/resize-handle/resize-handle.d.ts.map +1 -1
  706. package/dist/patterns/resize-handle/resize-handle.js +3 -6
  707. package/dist/patterns/resize-handle/resize-handle.js.map +1 -1
  708. package/dist/story-governance/category-matrix.d.ts +35 -0
  709. package/dist/story-governance/category-matrix.d.ts.map +1 -0
  710. package/dist/tokens/categorical-color.d.ts +60 -0
  711. package/dist/tokens/categorical-color.d.ts.map +1 -0
  712. package/dist/tokens/categorical-color.js +125 -0
  713. package/dist/tokens/categorical-color.js.map +1 -0
  714. package/dist/tokens/motion/motion.d.ts +8 -7
  715. package/dist/tokens/motion/motion.d.ts.map +1 -1
  716. package/dist/tokens/motion/motion.js +6 -6
  717. package/dist/tokens/motion/motion.js.map +1 -1
  718. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  719. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  720. package/dist/tokens/motion/overlay-motion.js +9 -0
  721. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  722. package/dist/tokens/uiSize/icon-size.d.ts +3 -4
  723. package/dist/tokens/uiSize/icon-size.d.ts.map +1 -1
  724. package/dist/tokens/uiSize/icon-size.js +5 -0
  725. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  726. package/ds-canonical/adapters/claude/agents/README.md +58 -0
  727. package/ds-canonical/adapters/claude/agents/canonical-reviewer.md +14 -0
  728. package/ds-canonical/adapters/claude-root-instructions.md +24 -0
  729. package/ds-canonical/adapters/claude-settings-base.json +169 -0
  730. package/ds-canonical/commands/README.md +9 -14
  731. package/ds-canonical/fork/AGENTS.md +110 -0
  732. package/ds-canonical/fork/CLAUDE.md +54 -0
  733. package/ds-canonical/fork/codex/agents/skills/bug-fix-rhythm/SKILL.md +207 -0
  734. package/ds-canonical/fork/codex/agents/skills/code-quality-audit/SKILL.md +71 -0
  735. package/ds-canonical/fork/codex/agents/skills/delivery-handoff/SKILL.md +244 -0
  736. package/ds-canonical/fork/codex/agents/skills/delivery-handoff/references/flow-diagram.md +180 -0
  737. package/ds-canonical/fork/codex/agents/skills/delivery-handoff/references/handoff-template.md +177 -0
  738. package/ds-canonical/fork/codex/agents/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  739. package/ds-canonical/fork/codex/agents/skills/independent-review/SKILL.md +43 -0
  740. package/ds-canonical/fork/codex/agents/skills/independent-review/agents/openai.yaml +4 -0
  741. package/ds-canonical/fork/codex/agents/skills/independent-review/references/evidence-contract.md +23 -0
  742. package/ds-canonical/fork/codex/agents/skills/performance-audit/SKILL.md +114 -0
  743. package/ds-canonical/fork/codex/agents/skills/product-ui-audit/SKILL.md +252 -0
  744. package/ds-canonical/fork/codex/agents/skills/product-ui-audit/references/audit-checks.md +250 -0
  745. package/ds-canonical/fork/codex/agents/skills/product-ui-audit/references/common-misuses.md +329 -0
  746. package/ds-canonical/fork/codex/agents/skills/product-ui-audit/references/report-template.md +163 -0
  747. package/ds-canonical/fork/codex/agents/skills/propose-options/SKILL.md +190 -0
  748. package/ds-canonical/fork/codex/agents/skills/prototype/SKILL.md +246 -0
  749. package/ds-canonical/fork/codex/agents/skills/prototype/references/audit-checks.md +39 -0
  750. package/ds-canonical/fork/codex/agents/skills/prototype/references/benchmark-sources.md +94 -0
  751. package/ds-canonical/fork/codex/agents/skills/prototype/references/checkpoints.md +200 -0
  752. package/ds-canonical/fork/codex/agents/skills/prototype/references/evaluation-matrix.md +142 -0
  753. package/ds-canonical/fork/codex/agents/skills/prototype/references/ooux-template.md +198 -0
  754. package/ds-canonical/fork/codex/agents/skills/prototype/references/proposal-template.md +230 -0
  755. package/ds-canonical/fork/codex/agents/skills/scan-similar-bugs/SKILL.md +203 -0
  756. package/ds-canonical/fork/codex/agents/skills/ux-audit/SKILL.md +135 -0
  757. package/ds-canonical/fork/codex/agents/skills/visual-audit/SKILL.md +258 -0
  758. package/ds-canonical/fork/codex/agents/skills/visual-audit/output/.gitkeep +0 -0
  759. package/ds-canonical/fork/codex/agents/skills/visual-audit/references/audit-architecture.md +101 -0
  760. package/ds-canonical/fork/codex/agents/skills/visual-audit/references/visual-checklist.md +297 -0
  761. package/ds-canonical/fork/codex/agents/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  762. package/ds-canonical/fork/codex/hooks.json +57 -0
  763. package/ds-canonical/fork/common/closed-tool-execution.mjs +1005 -0
  764. package/ds-canonical/fork/common/instruction.md +110 -0
  765. package/ds-canonical/fork/consumer/governance-check.mjs +3163 -0
  766. package/ds-canonical/fork/consumer/lib/closed-tool-execution.mjs +1005 -0
  767. package/ds-canonical/fork/consumer/lock.json +189 -0
  768. package/ds-canonical/fork/consumer/lock.schema.json +338 -0
  769. package/ds-canonical/fork/consumer/managed-files/0235cf6b3fd402a3717881dc205b5bf77aed7632e7d7d6f1811a40e3033bd816.blob +145 -0
  770. package/ds-canonical/fork/consumer/managed-files/145aab4b4fc470fc9ba7679b4a1d87d4f6a6d604940bd40f8d675c8af696498f.blob +53 -0
  771. package/ds-canonical/fork/consumer/managed-files/189e551431181e4a88783c02130d2787b801ef731c86e35bcde89a7313aa020e.blob +149 -0
  772. package/ds-canonical/fork/consumer/managed-files/24ad71c8613ddcf6fd23818cb3bb477a1fb6d83af4550b0bad43099813088686.blob +28 -0
  773. package/ds-canonical/fork/consumer/managed-files/2d1ef5617a5ce3c39ad9aae1c42af7d199f9270c0a0ccb490b63d62dbc6913db.blob +1005 -0
  774. package/ds-canonical/fork/consumer/managed-files/3625e02235cf166a50649a4d704cfb68fead69d0e168c481df013ebae9f6be25.blob +1412 -0
  775. package/ds-canonical/fork/consumer/managed-files/3ddedc67b464bdfe3dde9803a2d917920c96d633678b802eee638a44cd47366a.blob +8 -0
  776. package/ds-canonical/fork/consumer/managed-files/423729840acdd43c812f17c245b871716c6b60f76e4d3e94864d0e34a815bf8d.blob +348 -0
  777. package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +549 -0
  778. package/ds-canonical/fork/consumer/managed-files/475fba657eaeb8abd88f60635f3eadab27a9d0d3114ba4fffc65f43a2a0fe6e2.blob +124 -0
  779. package/ds-canonical/fork/consumer/managed-files/5aeda1df235815f40dd755951f2b868d4e02035653d4536a8dde209cdc75b493.blob +268 -0
  780. package/ds-canonical/fork/consumer/managed-files/61c6aca6d7f04bedbf556eaa9d3043681fe48cbe0e93a8ccb1d69a7c5e23fdcf.blob +113 -0
  781. package/ds-canonical/fork/consumer/managed-files/63061e05969667005020166ea2ae7df3c96663f7a928e7dd3eebc1471022df56.blob +2454 -0
  782. package/ds-canonical/fork/consumer/managed-files/65410b66e8799a560e07b71779c186fed2a0ef50575ac44745df7a0938a9c2b4.blob +321 -0
  783. package/ds-canonical/fork/consumer/managed-files/6b746628ac11fcccbe277ef6fea94cc2a7b90ea2822e83536eae80d5ee4b3fa5.blob +167 -0
  784. package/ds-canonical/fork/consumer/managed-files/76d485470d30ff014afacf7ce643763de9f4f956d9fc8128dbc1814774cf2e63.blob +671 -0
  785. package/ds-canonical/fork/consumer/managed-files/7937321877e5c34c27dae36c0d507d21cd42fa3f46a8f11a284b8b4a52b6faa4.blob +84 -0
  786. package/ds-canonical/fork/consumer/managed-files/794bb911ba8ebef58ab0d44a55b9968a19d2c62bcfb310b1ee3a84166f087f21.blob +924 -0
  787. package/ds-canonical/fork/consumer/managed-files/7ab15a8aeca39485d7b9b57234bbc4a69e0b9e70b4a851dfe10f6447127cee78.blob +51 -0
  788. package/ds-canonical/fork/consumer/managed-files/7b17835d0ceb17cdcdcaf930540a3e5d0943a34a747ac43c12ca8cd485c11581.blob +44 -0
  789. package/ds-canonical/fork/consumer/managed-files/7eb6cc60abfdabaf6617c336058fad1454ccde08889295767bfd9b7fd153cc6e.blob +900 -0
  790. package/ds-canonical/fork/consumer/managed-files/81037efa5b3b9f4a875704005fb268acdc9233bb901f44902e4e37e1da92b8e3.blob +46 -0
  791. package/ds-canonical/fork/consumer/managed-files/884721550b56308812b20917adac7a12f36fdb4ecda6b02460a7f5a219c0c966.blob +82 -0
  792. package/ds-canonical/fork/consumer/managed-files/91f414b9462ddc1e4be1d4c6ca4ac7a7340a6eec9e98ee109cbc049d3b354b6a.blob +36 -0
  793. package/ds-canonical/fork/consumer/managed-files/92e4828cdcb96ff0d01daa16f6885f24045a8e72820665650f2a1890dc3a446c.blob +121 -0
  794. package/ds-canonical/fork/consumer/managed-files/93a89f16f6717d1e4e4e27ec20ef916e3355c7aa890ca74cd9b12db30d8a899f.blob +36 -0
  795. package/ds-canonical/fork/consumer/managed-files/974521d6b8fe796ea4c58b3c78b0c2b8a1be262b97100d77aaf4cc9c7724bcab.blob +45 -0
  796. package/ds-canonical/fork/consumer/managed-files/9791c85388d2e2e2bd564e2550fadc3351c4c960a47ce838098afcba7544eb90.blob +973 -0
  797. package/ds-canonical/fork/consumer/managed-files/a448d2222133335c30e6fda5116e26a40db3283a19d62ccc0663c30d272262a7.blob +174 -0
  798. package/ds-canonical/fork/consumer/managed-files/ab072e7f2eca51f0e18a5e18c4b333260ee5d219a12cc6df5bb2d683f0b2734d.blob +2639 -0
  799. package/ds-canonical/fork/consumer/managed-files/bc44cabad181f766611dab6a8f52d81100afadd50ac59799015e8ba7bf46d9eb.blob +620 -0
  800. package/ds-canonical/fork/consumer/managed-files/c4aa767f11714467de0038a2149cf78074baddc17fc6a9e074b6aed7544c6f3c.blob +80 -0
  801. package/ds-canonical/fork/consumer/managed-files/c893e9b734b162f4c631fef871128c16a9ab565f796a0e76d7f320f821f220f5.blob +41 -0
  802. package/ds-canonical/fork/consumer/managed-files/cd9c61f8ff24fb9bcc3663e346e2cfa419cfb84e02aae18d3dc66dd192681696.blob +9 -0
  803. package/ds-canonical/fork/consumer/managed-files/da2ad2737315d25a5300905ddefd62f1695056a8a1af155c5b34170ad9923bce.blob +38 -0
  804. package/ds-canonical/fork/consumer/managed-files/e26057408661597aac4a57cdf7e30e2f9d0afb1b9a2dbbb692c3805cd9028ca5.blob +250 -0
  805. package/ds-canonical/fork/consumer/managed-files/e68ae1915965d8e17d4b2441c00c2b97fe062ea308ae8535c9eebb2fc16fa245.blob +20 -0
  806. package/ds-canonical/fork/consumer/managed-files/e71c65f45c6af7ce12b6b3c0d8028f185da5b719e2050c9b2a6b243d41ae4878.blob +182 -0
  807. package/ds-canonical/fork/consumer/managed-files/e813096d69c49812e40e00be9ac8fa14d77f0ec1f97ab4c45cb096b3bedd35de.blob +3 -0
  808. package/ds-canonical/fork/consumer/managed-files/e930ebca6fd8eeb30802aac0930efae7bcc44cc0996f24de07c11ca6a081fedf.blob +277 -0
  809. package/ds-canonical/fork/consumer/managed-files/ea94e914d5c8acb84ad7660e5bda0f01b6ccc8cf96b0f6b1ce048f8938d0f5b5.blob +47 -0
  810. package/ds-canonical/fork/consumer/managed-files/f4db6e616d5229aa7e700c6a3ace022cb9d90baae74e38ca65fce617f18e0d9b.blob +110 -0
  811. package/ds-canonical/fork/consumer/managed-files/faa128c26102415dc5345e68698efbbd28a395c35ee278dceae044cf430692b2.blob +11 -0
  812. package/ds-canonical/fork/governance.lock +1696 -0
  813. package/ds-canonical/fork/hooks/_log-fire.sh +143 -0
  814. package/ds-canonical/fork/hooks/block_prototype_imports.py +241 -0
  815. package/ds-canonical/fork/hooks/check_chrome_header_avatar_canonical.sh +106 -0
  816. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +731 -0
  817. package/ds-canonical/fork/hooks/check_consumer_code_quality.sh +173 -0
  818. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +219 -0
  819. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +57 -0
  820. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +213 -0
  821. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +376 -0
  822. package/ds-canonical/fork/hooks/check_fork_product_quality.sh +38 -0
  823. package/ds-canonical/fork/hooks/check_item_list_gap.sh +56 -0
  824. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +160 -0
  825. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +319 -0
  826. package/ds-canonical/fork/hooks/check_pattern_invariants.sh +339 -0
  827. package/ds-canonical/fork/hooks/check_sidebar_menu_button_implicit_wrap.sh +99 -0
  828. package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
  829. package/ds-canonical/fork/hooks/check_story_invariants.sh +400 -0
  830. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +241 -0
  831. package/ds-canonical/fork/hooks/check_tailwind_wildcard_in_docs.sh +86 -0
  832. package/ds-canonical/fork/hooks/inject_deploy_url_after_push.sh +333 -0
  833. package/ds-canonical/fork/hooks/lib/_hook_integrity.sh +158 -0
  834. package/ds-canonical/fork/hooks/lib/_micro_geometry.sh +291 -0
  835. package/ds-canonical/fork/hooks/lib/_provider_paths.sh +162 -0
  836. package/ds-canonical/fork/launchers/approval-evidence.mjs +1321 -0
  837. package/ds-canonical/fork/launchers/authority-decision-evidence.mjs +413 -0
  838. package/ds-canonical/fork/launchers/canonical-order.mjs +8 -0
  839. package/ds-canonical/fork/launchers/fork-governance-dispatcher.sh +154 -0
  840. package/ds-canonical/fork/launchers/format-provider-hook-output.mjs +25 -0
  841. package/ds-canonical/fork/launchers/independent-review.mjs +490 -0
  842. package/ds-canonical/fork/launchers/inject_fork_governance_preamble.sh +99 -0
  843. package/ds-canonical/fork/launchers/normalize-provider-event.mjs +355 -0
  844. package/ds-canonical/fork/launchers/product-hook-dispatch-runtime.mjs +1067 -0
  845. package/ds-canonical/fork/launchers/provider-hook-normalization.mjs +1640 -0
  846. package/ds-canonical/fork/launchers/provider-hook-output-transport.mjs +540 -0
  847. package/ds-canonical/fork/launchers/settings-hooks.json +35 -0
  848. package/ds-canonical/fork/manifest.json +1984 -0
  849. package/ds-canonical/fork/providers/claude/hook-config.json +327 -0
  850. package/ds-canonical/fork/providers/claude/instruction.md +54 -0
  851. package/ds-canonical/fork/providers/claude/skills/bug-fix-rhythm/SKILL.md +207 -0
  852. package/ds-canonical/fork/providers/claude/skills/code-quality-audit/SKILL.md +71 -0
  853. package/ds-canonical/fork/providers/claude/skills/delivery-handoff/SKILL.md +244 -0
  854. package/ds-canonical/fork/providers/claude/skills/delivery-handoff/references/flow-diagram.md +180 -0
  855. package/ds-canonical/fork/providers/claude/skills/delivery-handoff/references/handoff-template.md +177 -0
  856. package/ds-canonical/fork/providers/claude/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  857. package/ds-canonical/fork/providers/claude/skills/independent-review/SKILL.md +43 -0
  858. package/ds-canonical/fork/providers/claude/skills/independent-review/agents/openai.yaml +4 -0
  859. package/ds-canonical/fork/providers/claude/skills/independent-review/references/evidence-contract.md +23 -0
  860. package/ds-canonical/fork/providers/claude/skills/performance-audit/SKILL.md +114 -0
  861. package/ds-canonical/fork/providers/claude/skills/product-ui-audit/SKILL.md +252 -0
  862. package/ds-canonical/fork/providers/claude/skills/product-ui-audit/references/audit-checks.md +250 -0
  863. package/ds-canonical/fork/providers/claude/skills/product-ui-audit/references/common-misuses.md +329 -0
  864. package/ds-canonical/fork/providers/claude/skills/product-ui-audit/references/report-template.md +163 -0
  865. package/ds-canonical/fork/providers/claude/skills/propose-options/SKILL.md +190 -0
  866. package/ds-canonical/fork/providers/claude/skills/prototype/SKILL.md +246 -0
  867. package/ds-canonical/fork/providers/claude/skills/prototype/references/audit-checks.md +39 -0
  868. package/ds-canonical/fork/providers/claude/skills/prototype/references/benchmark-sources.md +94 -0
  869. package/ds-canonical/fork/providers/claude/skills/prototype/references/checkpoints.md +200 -0
  870. package/ds-canonical/fork/providers/claude/skills/prototype/references/evaluation-matrix.md +142 -0
  871. package/ds-canonical/fork/providers/claude/skills/prototype/references/ooux-template.md +198 -0
  872. package/ds-canonical/fork/providers/claude/skills/prototype/references/proposal-template.md +230 -0
  873. package/ds-canonical/fork/providers/claude/skills/scan-similar-bugs/SKILL.md +203 -0
  874. package/ds-canonical/fork/providers/claude/skills/ux-audit/SKILL.md +135 -0
  875. package/ds-canonical/fork/providers/claude/skills/visual-audit/SKILL.md +258 -0
  876. package/ds-canonical/fork/providers/claude/skills/visual-audit/output/.gitkeep +0 -0
  877. package/ds-canonical/fork/providers/claude/skills/visual-audit/references/audit-architecture.md +101 -0
  878. package/ds-canonical/fork/providers/claude/skills/visual-audit/references/visual-checklist.md +297 -0
  879. package/ds-canonical/fork/providers/claude/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  880. package/ds-canonical/fork/providers/codex/hook-config.json +57 -0
  881. package/ds-canonical/fork/providers/codex/skills/bug-fix-rhythm/SKILL.md +207 -0
  882. package/ds-canonical/fork/providers/codex/skills/code-quality-audit/SKILL.md +71 -0
  883. package/ds-canonical/fork/providers/codex/skills/delivery-handoff/SKILL.md +244 -0
  884. package/ds-canonical/fork/providers/codex/skills/delivery-handoff/references/flow-diagram.md +180 -0
  885. package/ds-canonical/fork/providers/codex/skills/delivery-handoff/references/handoff-template.md +177 -0
  886. package/ds-canonical/fork/providers/codex/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  887. package/ds-canonical/fork/providers/codex/skills/independent-review/SKILL.md +43 -0
  888. package/ds-canonical/fork/providers/codex/skills/independent-review/agents/openai.yaml +4 -0
  889. package/ds-canonical/fork/providers/codex/skills/independent-review/references/evidence-contract.md +23 -0
  890. package/ds-canonical/fork/providers/codex/skills/performance-audit/SKILL.md +114 -0
  891. package/ds-canonical/fork/providers/codex/skills/product-ui-audit/SKILL.md +252 -0
  892. package/ds-canonical/fork/providers/codex/skills/product-ui-audit/references/audit-checks.md +250 -0
  893. package/ds-canonical/fork/providers/codex/skills/product-ui-audit/references/common-misuses.md +329 -0
  894. package/ds-canonical/fork/providers/codex/skills/product-ui-audit/references/report-template.md +163 -0
  895. package/ds-canonical/fork/providers/codex/skills/propose-options/SKILL.md +190 -0
  896. package/ds-canonical/fork/providers/codex/skills/prototype/SKILL.md +246 -0
  897. package/ds-canonical/fork/providers/codex/skills/prototype/references/audit-checks.md +39 -0
  898. package/ds-canonical/fork/providers/codex/skills/prototype/references/benchmark-sources.md +94 -0
  899. package/ds-canonical/fork/providers/codex/skills/prototype/references/checkpoints.md +200 -0
  900. package/ds-canonical/fork/providers/codex/skills/prototype/references/evaluation-matrix.md +142 -0
  901. package/ds-canonical/fork/providers/codex/skills/prototype/references/ooux-template.md +198 -0
  902. package/ds-canonical/fork/providers/codex/skills/prototype/references/proposal-template.md +230 -0
  903. package/ds-canonical/fork/providers/codex/skills/scan-similar-bugs/SKILL.md +203 -0
  904. package/ds-canonical/fork/providers/codex/skills/ux-audit/SKILL.md +135 -0
  905. package/ds-canonical/fork/providers/codex/skills/visual-audit/SKILL.md +258 -0
  906. package/ds-canonical/fork/providers/codex/skills/visual-audit/output/.gitkeep +0 -0
  907. package/ds-canonical/fork/providers/codex/skills/visual-audit/references/audit-architecture.md +101 -0
  908. package/ds-canonical/fork/providers/codex/skills/visual-audit/references/visual-checklist.md +297 -0
  909. package/ds-canonical/fork/providers/codex/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  910. package/ds-canonical/fork/references/story-baseline-registry.json +123 -0
  911. package/ds-canonical/fork/references/story-baseline-registry.schema.json +145 -0
  912. package/ds-canonical/fork/references/utility-registry.json +426 -0
  913. package/ds-canonical/fork/references/utility-registry.schema.json +409 -0
  914. package/ds-canonical/fork/review/canonical-order.mjs +8 -0
  915. package/ds-canonical/fork/review/provider-review-binding.mjs +2377 -0
  916. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +196 -0
  917. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +69 -0
  918. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +242 -0
  919. package/ds-canonical/fork/skills/delivery-handoff/references/flow-diagram.md +180 -0
  920. package/ds-canonical/fork/skills/delivery-handoff/references/handoff-template.md +177 -0
  921. package/ds-canonical/fork/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  922. package/ds-canonical/fork/skills/independent-review/SKILL.md +37 -0
  923. package/ds-canonical/fork/skills/independent-review/agents/openai.yaml +4 -0
  924. package/ds-canonical/fork/skills/independent-review/references/evidence-contract.md +23 -0
  925. package/ds-canonical/fork/skills/performance-audit/SKILL.md +112 -0
  926. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +250 -0
  927. package/ds-canonical/fork/skills/product-ui-audit/references/audit-checks.md +250 -0
  928. package/ds-canonical/fork/skills/product-ui-audit/references/common-misuses.md +329 -0
  929. package/ds-canonical/fork/skills/product-ui-audit/references/report-template.md +163 -0
  930. package/ds-canonical/fork/skills/propose-options/SKILL.md +179 -0
  931. package/ds-canonical/fork/skills/prototype/SKILL.md +244 -0
  932. package/ds-canonical/fork/skills/prototype/references/audit-checks.md +39 -0
  933. package/ds-canonical/fork/skills/prototype/references/benchmark-sources.md +94 -0
  934. package/ds-canonical/fork/skills/prototype/references/checkpoints.md +200 -0
  935. package/ds-canonical/fork/skills/prototype/references/evaluation-matrix.md +142 -0
  936. package/ds-canonical/fork/skills/prototype/references/ooux-template.md +198 -0
  937. package/ds-canonical/fork/skills/prototype/references/proposal-template.md +230 -0
  938. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +201 -0
  939. package/ds-canonical/fork/skills/ux-audit/SKILL.md +133 -0
  940. package/ds-canonical/fork/skills/visual-audit/SKILL.md +248 -0
  941. package/ds-canonical/fork/skills/visual-audit/output/.gitkeep +0 -0
  942. package/ds-canonical/fork/skills/visual-audit/references/audit-architecture.md +101 -0
  943. package/ds-canonical/fork/skills/visual-audit/references/visual-checklist.md +297 -0
  944. package/ds-canonical/fork/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  945. package/ds-canonical/hooks/README.md +39 -25
  946. package/ds-canonical/hooks/_log-fire.sh +111 -12
  947. package/ds-canonical/hooks/auto_regen_ds_barrel.sh +90 -0
  948. package/ds-canonical/hooks/block_prototype_imports.py +156 -26
  949. package/ds-canonical/hooks/check_audit_post_report_validator.sh +328 -32
  950. package/ds-canonical/hooks/check_audit_sample_escape.sh +10 -7
  951. package/ds-canonical/hooks/check_benchmark_citation.sh +41 -8
  952. package/ds-canonical/hooks/check_canonical_propagation.sh +85 -24
  953. package/ds-canonical/hooks/check_chrome_header_avatar_canonical.sh +106 -0
  954. package/ds-canonical/hooks/check_codex_brief_invariants.sh +138 -29
  955. package/ds-canonical/hooks/check_codex_collab_5step.sh +31 -25
  956. package/ds-canonical/hooks/check_consumer_app_invariants.sh +731 -0
  957. package/ds-canonical/hooks/check_consumer_code_quality.sh +173 -0
  958. package/ds-canonical/hooks/check_datatable_invariants.sh +173 -29
  959. package/ds-canonical/hooks/check_dim_count_drift.sh +8 -7
  960. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +219 -0
  961. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +57 -0
  962. package/ds-canonical/hooks/check_escape_marker_abuse.sh +213 -0
  963. package/ds-canonical/hooks/check_field_controls_contracts.sh +37 -8
  964. package/ds-canonical/hooks/check_field_family_invariants.sh +195 -24
  965. package/ds-canonical/hooks/check_file_size_budget.sh +32 -14
  966. package/ds-canonical/hooks/check_full_story_visual_interaction_sweep.sh +111 -0
  967. package/ds-canonical/hooks/check_item_list_gap.sh +56 -0
  968. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +160 -0
  969. package/ds-canonical/hooks/check_main_branch_workbench.sh +27 -68
  970. package/ds-canonical/hooks/check_naming_and_abstraction.sh +21 -10
  971. package/ds-canonical/hooks/check_opacity_token_usage.sh +238 -68
  972. package/ds-canonical/hooks/check_orphan_ds_css.sh +96 -0
  973. package/ds-canonical/hooks/check_overlay_open_focus_escape_probe.sh +110 -0
  974. package/ds-canonical/hooks/check_pattern_invariants.sh +160 -15
  975. package/ds-canonical/hooks/check_peoplepicker_ssot_drift.sh +4 -4
  976. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +6 -4
  977. package/ds-canonical/hooks/check_plugin_fork_health.sh +282 -0
  978. package/ds-canonical/hooks/check_propose_discipline.sh +255 -0
  979. package/ds-canonical/hooks/check_propose_pre_grep_verify.sh +6 -4
  980. package/ds-canonical/hooks/check_propose_without_benchmark.sh +71 -0
  981. package/ds-canonical/hooks/check_select_all_canonical.sh +1 -1
  982. package/ds-canonical/hooks/check_sidebar_menu_button_implicit_wrap.sh +99 -0
  983. package/ds-canonical/hooks/check_solo_workflow.sh +62 -168
  984. package/ds-canonical/hooks/check_spec_class_drift.sh +33 -19
  985. package/ds-canonical/hooks/check_ssot_header_declaration.sh +56 -0
  986. package/ds-canonical/hooks/check_story_determinism.sh +39 -0
  987. package/ds-canonical/hooks/check_story_invariants.sh +722 -222
  988. package/ds-canonical/hooks/check_storybook_addon_packaging.sh +201 -0
  989. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +143 -64
  990. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +241 -0
  991. package/ds-canonical/hooks/check_tailwind_wildcard_in_docs.sh +86 -0
  992. package/ds-canonical/hooks/check_wrapper_primitive_schema_drift.sh +15 -12
  993. package/ds-canonical/hooks/chrome_header_dispatcher.sh +105 -0
  994. package/ds-canonical/hooks/enforce_home_charter.sh +31 -10
  995. package/ds-canonical/hooks/governance_control_plane.sh +15 -0
  996. package/ds-canonical/hooks/inject_deploy_url_after_push.sh +333 -0
  997. package/ds-canonical/hooks/inject_pending_self_audit.sh +68 -21
  998. package/ds-canonical/hooks/lib/_app_shell_primary_header_consistency.sh +148 -0
  999. package/ds-canonical/hooks/lib/_chrome_header_handcraft.sh +121 -0
  1000. package/ds-canonical/hooks/lib/_code_quality.sh +9 -9
  1001. package/ds-canonical/hooks/lib/_cva_default_sync.sh +11 -13
  1002. package/ds-canonical/hooks/lib/_governance_coverage_check.sh +48 -21
  1003. package/ds-canonical/hooks/lib/_hardcoded_strings.sh +18 -10
  1004. package/ds-canonical/hooks/lib/_header_with_tabs_border.sh +107 -0
  1005. package/ds-canonical/hooks/lib/_hook_integrity.sh +158 -0
  1006. package/ds-canonical/hooks/lib/_layout_space_canonical.sh +5 -5
  1007. package/ds-canonical/hooks/lib/_micro_geometry.sh +291 -0
  1008. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +42 -23
  1009. package/ds-canonical/hooks/lib/_person_data_richness.sh +5 -5
  1010. package/ds-canonical/hooks/lib/_provider_paths.sh +162 -0
  1011. package/ds-canonical/hooks/lib/_story_compile_drift.sh +5 -5
  1012. package/ds-canonical/hooks/lib/_tab_lg_chrome_header_equal.sh +290 -0
  1013. package/ds-canonical/hooks/lib/_token_hygiene.sh +55 -20
  1014. package/ds-canonical/hooks/lib/approval-evidence.mjs +1321 -0
  1015. package/ds-canonical/hooks/lib/audit-report-validator.mjs +122 -0
  1016. package/ds-canonical/hooks/lib/provider-marker-regex.mjs +23 -0
  1017. package/ds-canonical/hooks/lib/tsx-governance-analysis.mjs +410 -0
  1018. package/ds-canonical/hooks/log_governance_fires.sh +45 -13
  1019. package/ds-canonical/hooks/log_skill_invokes.sh +8 -7
  1020. package/ds-canonical/hooks/post_edit_dispatcher.sh +106 -28
  1021. package/ds-canonical/hooks/registrations.json +488 -0
  1022. package/ds-canonical/hooks/registrations.schema.json +58 -0
  1023. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_addon_subdir_ship.sh +76 -0
  1024. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_app_story_title.sh +81 -0
  1025. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_ds_primitive_misuse.sh +120 -0
  1026. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_no_ds_catalog.sh +101 -0
  1027. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_story_baseline.sh +76 -0
  1028. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_data_table_size_num_to_meta_width.sh +68 -0
  1029. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_fork_user_plugin_install.sh +79 -0
  1030. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_plugin_freshness.sh +68 -0
  1031. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_propose_cite_required.sh +88 -0
  1032. package/ds-canonical/hooks/{check_propose_plain_chinese.sh → retired/2026-06-11-prune-merge/check_propose_plain_chinese.sh} +2 -2
  1033. package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_storybook_addon_preset_cjs.sh +87 -0
  1034. package/ds-canonical/hooks/{lib/_approval_re.sh → retired/_approval_re.sh.retired-2026-08-18} +6 -7
  1035. package/ds-canonical/hooks/retired/check_container_breathing.sh +1 -1
  1036. package/ds-canonical/hooks/retired/check_governance_compliance.sh +1 -1
  1037. package/ds-canonical/hooks/session_start_governance_check.sh +157 -69
  1038. package/ds-canonical/hooks/stop_audit_content_quality.sh +20 -0
  1039. package/ds-canonical/hooks/stop_extract_canonical_rules.sh +20 -0
  1040. package/ds-canonical/hooks/stop_passive_logging.sh +133 -59
  1041. package/ds-canonical/hooks/stop_self_audit.sh +472 -178
  1042. package/ds-canonical/hooks/tests/fixtures/transcripts/claude-transcript-jsonl-v1.jsonl +3 -0
  1043. package/ds-canonical/hooks/tests/fixtures/transcripts/claude-transcript-jsonl-v2.jsonl +3 -0
  1044. package/ds-canonical/hooks/tests/registration-output-contracts.mjs +151 -0
  1045. package/ds-canonical/hooks/tests/run-all.sh +35 -5
  1046. package/ds-canonical/hooks/tests/test_auto_regen_ds_barrel.sh +224 -0
  1047. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +181 -9
  1048. package/ds-canonical/hooks/tests/test_check_addon_subdir_ship.sh +171 -0
  1049. package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +275 -81
  1050. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +292 -14
  1051. package/ds-canonical/hooks/tests/test_check_audit_sample_escape.sh +0 -0
  1052. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +41 -9
  1053. package/ds-canonical/hooks/tests/test_check_canonical_propagation.sh +56 -5
  1054. package/ds-canonical/hooks/tests/test_check_chrome_header_avatar_canonical.sh +198 -0
  1055. package/ds-canonical/hooks/tests/test_check_chrome_header_handcraft.sh +197 -81
  1056. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +375 -0
  1057. package/ds-canonical/hooks/tests/test_check_codex_collab_5step.sh +49 -5
  1058. package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +140 -0
  1059. package/ds-canonical/hooks/tests/test_check_consumer_app_story_title.sh +164 -0
  1060. package/ds-canonical/hooks/tests/test_check_consumer_code_quality.sh +86 -0
  1061. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +417 -0
  1062. package/ds-canonical/hooks/tests/test_check_consumer_no_ds_catalog.sh +214 -0
  1063. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +209 -0
  1064. package/ds-canonical/hooks/tests/test_check_data_table_size_num_to_meta_width.sh +71 -0
  1065. package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +126 -12
  1066. package/ds-canonical/hooks/tests/test_check_dim_count_drift.sh +13 -8
  1067. package/ds-canonical/hooks/tests/test_check_ds_anchor_preflight.sh +150 -0
  1068. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  1069. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +278 -0
  1070. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +108 -18
  1071. package/ds-canonical/hooks/tests/test_check_file_size_budget.sh +67 -5
  1072. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +151 -0
  1073. package/ds-canonical/hooks/tests/test_check_full_story_visual_interaction_sweep.sh +200 -0
  1074. package/ds-canonical/hooks/tests/test_check_header_with_tabs_border.sh +178 -68
  1075. package/ds-canonical/hooks/tests/test_check_item_list_gap.sh +44 -0
  1076. package/ds-canonical/hooks/tests/test_check_layout_space_magic_numbers.sh +264 -0
  1077. package/ds-canonical/hooks/tests/test_check_main_branch_workbench.sh +45 -110
  1078. package/ds-canonical/hooks/tests/test_check_naming_and_abstraction.sh +19 -2
  1079. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +151 -6
  1080. package/ds-canonical/hooks/tests/test_check_orphan_ds_css.sh +228 -0
  1081. package/ds-canonical/hooks/tests/test_check_overlay_open_focus_escape_probe.sh +191 -0
  1082. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +103 -7
  1083. package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +132 -0
  1084. package/ds-canonical/hooks/tests/test_check_propose_cite_required.sh +181 -0
  1085. package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +69 -0
  1086. package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +10 -7
  1087. package/ds-canonical/hooks/tests/test_check_propose_pre_grep_verify.sh +5 -5
  1088. package/ds-canonical/hooks/tests/test_check_propose_without_benchmark.sh +100 -0
  1089. package/ds-canonical/hooks/tests/test_check_sidebar_menu_button_implicit_wrap.sh +224 -0
  1090. package/ds-canonical/hooks/tests/test_check_solo_workflow.sh +86 -105
  1091. package/ds-canonical/hooks/tests/test_check_spec_class_drift.sh +35 -7
  1092. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  1093. package/ds-canonical/hooks/tests/{test_check_story_anatomy.sh.broken → test_check_story_anatomy.sh} +73 -4
  1094. package/ds-canonical/hooks/tests/test_check_story_category.sh +411 -0
  1095. package/ds-canonical/hooks/tests/test_check_story_determinism.sh +39 -0
  1096. package/ds-canonical/hooks/tests/test_check_story_invariants.sh +734 -43
  1097. package/ds-canonical/hooks/tests/{test_check_story_name_jargon.sh.broken → test_check_story_name_jargon.sh} +22 -1
  1098. package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +89 -0
  1099. package/ds-canonical/hooks/tests/test_check_storybook_addon_preset_cjs.sh +200 -0
  1100. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +672 -28
  1101. package/ds-canonical/hooks/tests/test_check_tab_lg_chrome_header_equal.sh +182 -97
  1102. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  1103. package/ds-canonical/hooks/tests/test_check_tailwind_wildcard_in_docs.sh +182 -0
  1104. package/ds-canonical/hooks/tests/test_check_token_hygiene.sh +63 -15
  1105. package/ds-canonical/hooks/tests/test_check_wrapper_primitive_schema_drift.sh +12 -6
  1106. package/ds-canonical/hooks/tests/test_chrome_header_dispatcher.sh +125 -0
  1107. package/ds-canonical/hooks/tests/test_enforce_home_charter.sh +58 -4
  1108. package/ds-canonical/hooks/tests/test_governance_control_plane.sh +66 -0
  1109. package/ds-canonical/hooks/tests/test_governance_coverage_check.sh +88 -0
  1110. package/ds-canonical/hooks/tests/test_hook_integrity_classification.sh +217 -0
  1111. package/ds-canonical/hooks/tests/test_inject_deploy_url_after_push.sh +276 -0
  1112. package/ds-canonical/hooks/tests/test_inject_pending_self_audit.sh +116 -11
  1113. package/ds-canonical/hooks/tests/test_log_governance_fires.sh +117 -1
  1114. package/ds-canonical/hooks/tests/test_log_skill_invokes.sh +74 -5
  1115. package/ds-canonical/hooks/tests/test_post_edit_dispatcher.sh +234 -77
  1116. package/ds-canonical/hooks/tests/test_provider_peer_symmetry.sh +76 -0
  1117. package/ds-canonical/hooks/tests/test_registration_output_contracts.sh +20 -0
  1118. package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +145 -22
  1119. package/ds-canonical/hooks/tests/test_stop_audit_content_quality.sh +75 -0
  1120. package/ds-canonical/hooks/tests/test_stop_capture_metrics.sh +101 -23
  1121. package/ds-canonical/hooks/tests/test_stop_extract_canonical_rules.sh +75 -0
  1122. package/ds-canonical/hooks/tests/{test_stop_governance_drift_check.sh.broken → test_stop_governance_drift_check.sh} +22 -12
  1123. package/ds-canonical/hooks/tests/test_stop_passive_logging.sh +102 -1
  1124. package/ds-canonical/hooks/tests/test_stop_repository_command_context.sh +38 -0
  1125. package/ds-canonical/hooks/tests/test_stop_self_audit.sh +427 -13
  1126. package/ds-canonical/references/README.md +19 -11
  1127. package/ds-canonical/references/build-ui-canonicals.md +23 -6
  1128. package/ds-canonical/references/certified-surfaces.md +46 -0
  1129. package/ds-canonical/references/composition-fidelity.md +47 -0
  1130. package/ds-canonical/references/cva-patterns.md +2 -2
  1131. package/ds-canonical/references/drag-canonical.md +67 -311
  1132. package/ds-canonical/references/failure-class-registry.json +160 -0
  1133. package/ds-canonical/references/governance-audit-coverage.md +34 -0
  1134. package/ds-canonical/references/item-anatomy-recipe.md +3 -3
  1135. package/ds-canonical/references/naming-conventions.md +2 -1
  1136. package/ds-canonical/references/principle-dim-map.json +136 -9
  1137. package/ds-canonical/references/props-naming.md +18 -3
  1138. package/ds-canonical/references/repository-hygiene-policy.json +143 -0
  1139. package/ds-canonical/references/repository-hygiene.md +106 -0
  1140. package/ds-canonical/references/runtime-evidence-retention.md +88 -0
  1141. package/ds-canonical/references/scenario-definition.md +146 -0
  1142. package/ds-canonical/references/spec-rules.md +1 -1
  1143. package/ds-canonical/references/ssot-consultation.md +5 -5
  1144. package/ds-canonical/references/ssot-index.md +11 -10
  1145. package/ds-canonical/references/story-baseline-registry.json +55 -11
  1146. package/ds-canonical/references/story-baseline-registry.schema.json +145 -0
  1147. package/ds-canonical/references/structural-token-retention.md +7 -10
  1148. package/ds-canonical/references/tailwind-gotchas.md +4 -4
  1149. package/ds-canonical/references/ui-dev-rules.md +22 -1
  1150. package/ds-canonical/rules/README.md +15 -10
  1151. package/ds-canonical/rules/meta-patterns.md +30 -30
  1152. package/ds-canonical/rules/self-verify.md +22 -12
  1153. package/ds-canonical/rules/spec-rules.md +2 -2
  1154. package/ds-canonical/rules/story-rules.md +36 -9
  1155. package/ds-canonical/rules/ui-development.md +23 -15
  1156. package/ds-canonical/skills/README.md +29 -17
  1157. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +26 -13
  1158. package/ds-canonical/skills/canonical-reviewer/SKILL.md +29 -0
  1159. package/ds-canonical/skills/code-quality-audit/SKILL.md +15 -11
  1160. package/ds-canonical/skills/codex-collab/SKILL.md +22 -235
  1161. package/ds-canonical/skills/codex-collab/references/brief-template.md +37 -43
  1162. package/ds-canonical/skills/codex-collab/references/transport.md +38 -57
  1163. package/ds-canonical/skills/codify-corrections/SKILL.md +37 -36
  1164. package/ds-canonical/skills/codify-principle/SKILL.md +35 -34
  1165. package/ds-canonical/skills/component-quality-gate/SKILL.md +17 -17
  1166. package/ds-canonical/skills/component-quality-gate/references/checklist.md +8 -8
  1167. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +47 -224
  1168. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +36 -102
  1169. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +33 -147
  1170. package/ds-canonical/skills/deep-audit-cross-codex/references/skill-relationships-antipatterns-benchmarks.md +28 -0
  1171. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +15 -80
  1172. package/ds-canonical/skills/deep-audit-cross-codex/references/upstream-directives-r-mapping.md +34 -0
  1173. package/ds-canonical/skills/delivery-handoff/SKILL.md +19 -8
  1174. package/ds-canonical/skills/design-system-audit/SKILL.md +130 -76
  1175. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +207 -105
  1176. package/ds-canonical/skills/design-system-audit/references/checkpoints.md +59 -50
  1177. package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +33 -9
  1178. package/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md +51 -32
  1179. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +57 -53
  1180. package/ds-canonical/skills/ensure-canonical/SKILL.md +37 -35
  1181. package/ds-canonical/skills/governance-health/SKILL.md +31 -25
  1182. package/ds-canonical/skills/governance-status/SKILL.md +30 -0
  1183. package/ds-canonical/skills/independent-review/SKILL.md +37 -0
  1184. package/ds-canonical/skills/independent-review/agents/openai.yaml +4 -0
  1185. package/ds-canonical/skills/independent-review/references/evidence-contract.md +23 -0
  1186. package/ds-canonical/skills/knowledge-prune/SKILL.md +57 -114
  1187. package/ds-canonical/skills/knowledge-prune/references/phase-z-cross-repo-ssot-propagation.md +15 -0
  1188. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +57 -0
  1189. package/ds-canonical/skills/knowledge-prune/references/world-class-prune-alignment.md +7 -0
  1190. package/ds-canonical/skills/new-component/SKILL.md +33 -25
  1191. package/ds-canonical/skills/new-component/references/new-component-checklist.md +12 -11
  1192. package/ds-canonical/skills/performance-audit/SKILL.md +15 -12
  1193. package/ds-canonical/skills/product-ui-audit/SKILL.md +52 -34
  1194. package/ds-canonical/skills/product-ui-audit/references/audit-checks.md +10 -7
  1195. package/ds-canonical/skills/product-ui-audit/references/report-template.md +30 -26
  1196. package/ds-canonical/skills/propose-options/SKILL.md +23 -23
  1197. package/ds-canonical/skills/prototype/SKILL.md +19 -21
  1198. package/ds-canonical/skills/prototype/references/audit-checks.md +6 -5
  1199. package/ds-canonical/skills/prototype/references/checkpoints.md +26 -17
  1200. package/ds-canonical/skills/prototype/references/evaluation-matrix.md +2 -2
  1201. package/ds-canonical/skills/prototype/references/ooux-template.md +1 -1
  1202. package/ds-canonical/skills/prototype/references/proposal-template.md +5 -5
  1203. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +29 -28
  1204. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +26 -25
  1205. package/ds-canonical/skills/story-writing/SKILL.md +25 -14
  1206. package/ds-canonical/skills/story-writing/references/anatomy-standard.md +2 -2
  1207. package/ds-canonical/skills/story-writing/references/category-templates.md +15 -15
  1208. package/ds-canonical/skills/ux-audit/SKILL.md +13 -10
  1209. package/ds-canonical/skills/visual-audit/SKILL.md +47 -46
  1210. package/ds-canonical/skills/visual-audit/references/audit-architecture.md +7 -7
  1211. package/ds-canonical/skills/visual-audit/references/visual-checklist.md +14 -14
  1212. package/ds-canonical/skills/visual-audit/references/world-class-benchmarks.md +3 -3
  1213. package/ds-canonical/templates/_README.md +22 -0
  1214. package/ds-canonical/templates/consumer-governance.md +82 -0
  1215. package/ds-canonical/templates/dashboard-app.tsx +186 -0
  1216. package/ds-canonical/templates/product-launchers/fork-governance-dispatcher.sh +154 -0
  1217. package/ds-canonical/templates/product-launchers/format-provider-hook-output.mjs +25 -0
  1218. package/ds-canonical/templates/product-launchers/independent-review.mjs +490 -0
  1219. package/ds-canonical/templates/product-launchers/inject_fork_governance_preamble.sh +99 -0
  1220. package/ds-canonical/templates/product-launchers/normalize-provider-event.mjs +355 -0
  1221. package/ds-canonical/templates/product-launchers/product-hook-dispatch-runtime.mjs +1067 -0
  1222. package/ds-canonical/templates/product-provider-wiring.json +82 -0
  1223. package/ds-canonical/templates/product-provider-wiring.schema.json +153 -0
  1224. package/ds-story-manifest.json +1791 -0
  1225. package/llms-full.txt +450 -0
  1226. package/llms.txt +74 -0
  1227. package/package.json +43 -10
  1228. package/src/README.md +1 -1
  1229. package/src/components/Accordion/accordion.anatomy.stories.tsx +496 -0
  1230. package/src/components/Accordion/accordion.principles.stories.tsx +365 -0
  1231. package/src/components/Accordion/accordion.spec.md +31 -5
  1232. package/src/components/Accordion/accordion.stories.tsx +192 -0
  1233. package/src/components/Accordion/accordion.tsx +13 -5
  1234. package/src/components/Accordion/index.ts +5 -0
  1235. package/src/components/AccountMenu/account-menu.anatomy.stories.tsx +117 -0
  1236. package/src/components/AccountMenu/account-menu.principles.stories.tsx +99 -0
  1237. package/src/components/AccountMenu/account-menu.spec.md +127 -0
  1238. package/src/components/AccountMenu/account-menu.stories.tsx +65 -0
  1239. package/src/components/AccountMenu/account-menu.tsx +194 -0
  1240. package/src/components/AccountMenu/index.ts +5 -0
  1241. package/src/components/AgentPanel/agent-fab.tsx +126 -0
  1242. package/src/components/AgentPanel/agent-logo.tsx +491 -0
  1243. package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +127 -0
  1244. package/src/components/AgentPanel/agent-panel.css +59 -0
  1245. package/src/components/AgentPanel/agent-panel.principles.stories.tsx +57 -0
  1246. package/src/components/AgentPanel/agent-panel.spec.md +319 -0
  1247. package/src/components/AgentPanel/agent-panel.stories.tsx +360 -0
  1248. package/src/components/AgentPanel/agent-panel.tsx +1241 -0
  1249. package/src/components/AgentPanel/index.ts +5 -0
  1250. package/src/components/Alert/alert.anatomy.stories.tsx +241 -0
  1251. package/src/components/Alert/alert.principles.stories.tsx +214 -0
  1252. package/src/components/Alert/alert.spec.md +28 -26
  1253. package/src/components/Alert/alert.stories.tsx +136 -0
  1254. package/src/components/Alert/alert.tsx +19 -8
  1255. package/src/components/Alert/index.ts +5 -0
  1256. package/src/components/AppShell/_demo-helpers.tsx +107 -28
  1257. package/src/components/AppShell/app-shell.anatomy.stories.tsx +185 -0
  1258. package/src/components/AppShell/app-shell.principles.stories.tsx +140 -0
  1259. package/src/components/AppShell/app-shell.spec.md +84 -48
  1260. package/src/components/AppShell/app-shell.stories.tsx +445 -0
  1261. package/src/components/AppShell/app-shell.tsx +77 -24
  1262. package/src/components/AppShell/index.ts +5 -0
  1263. package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +208 -0
  1264. package/src/components/AspectRatio/aspect-ratio.principles.stories.tsx +303 -0
  1265. package/src/components/AspectRatio/aspect-ratio.spec.md +24 -12
  1266. package/src/components/AspectRatio/aspect-ratio.stories.tsx +91 -0
  1267. package/src/components/AspectRatio/aspect-ratio.tsx +6 -3
  1268. package/src/components/AspectRatio/index.ts +5 -0
  1269. package/src/components/Avatar/avatar.anatomy.stories.tsx +705 -0
  1270. package/src/components/Avatar/avatar.principles.stories.tsx +249 -0
  1271. package/src/components/Avatar/avatar.spec.md +66 -103
  1272. package/src/components/Avatar/avatar.stories.tsx +156 -0
  1273. package/src/components/Avatar/avatar.tsx +85 -64
  1274. package/src/components/Avatar/index.ts +5 -0
  1275. package/src/components/Badge/badge.anatomy.stories.tsx +591 -0
  1276. package/src/components/Badge/badge.principles.stories.tsx +391 -0
  1277. package/src/components/Badge/badge.spec.md +43 -23
  1278. package/src/components/Badge/badge.stories.tsx +82 -0
  1279. package/src/components/Badge/badge.tsx +38 -14
  1280. package/src/components/Badge/index.ts +5 -0
  1281. package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +462 -0
  1282. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +353 -0
  1283. package/src/components/Breadcrumb/breadcrumb.spec.md +55 -43
  1284. package/src/components/Breadcrumb/breadcrumb.stories.tsx +381 -0
  1285. package/src/components/Breadcrumb/breadcrumb.tsx +43 -86
  1286. package/src/components/Breadcrumb/index.ts +5 -0
  1287. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +225 -0
  1288. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +255 -0
  1289. package/src/components/BulkActionBar/bulk-action-bar.spec.md +64 -36
  1290. package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +124 -0
  1291. package/src/components/BulkActionBar/bulk-action-bar.tsx +26 -18
  1292. package/src/components/BulkActionBar/index.ts +5 -0
  1293. package/src/components/Button/button-group.tsx +64 -21
  1294. package/src/components/Button/button.anatomy.stories.tsx +729 -0
  1295. package/src/components/Button/button.principles.stories.tsx +369 -0
  1296. package/src/components/Button/button.spec.md +42 -39
  1297. package/src/components/Button/button.stories.tsx +368 -0
  1298. package/src/components/Button/button.tsx +109 -55
  1299. package/src/components/Button/index.ts +6 -0
  1300. package/src/components/Calendar/calendar.anatomy.stories.tsx +237 -0
  1301. package/src/components/Calendar/calendar.principles.stories.tsx +152 -0
  1302. package/src/components/Calendar/calendar.spec.md +80 -55
  1303. package/src/components/Calendar/calendar.stories.tsx +108 -0
  1304. package/src/components/Calendar/calendar.tsx +200 -134
  1305. package/src/components/Calendar/index.ts +5 -0
  1306. package/src/components/Carousel/carousel.anatomy.stories.tsx +517 -0
  1307. package/src/components/Carousel/carousel.principles.stories.tsx +334 -0
  1308. package/src/components/Carousel/carousel.spec.md +51 -15
  1309. package/src/components/Carousel/carousel.stories.tsx +125 -0
  1310. package/src/components/Carousel/carousel.tsx +139 -56
  1311. package/src/components/Carousel/index.ts +5 -0
  1312. package/src/components/Chart/chart.anatomy.stories.tsx +310 -0
  1313. package/src/components/Chart/chart.principles.stories.tsx +437 -0
  1314. package/src/components/Chart/chart.spec.md +24 -5
  1315. package/src/components/Chart/chart.stories.tsx +263 -0
  1316. package/src/components/Chart/chart.tsx +10 -3
  1317. package/src/components/Chart/index.ts +5 -0
  1318. package/src/components/Checkbox/checkbox-group.tsx +28 -16
  1319. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +614 -0
  1320. package/src/components/Checkbox/checkbox.principles.stories.tsx +216 -0
  1321. package/src/components/Checkbox/checkbox.spec.md +65 -42
  1322. package/src/components/Checkbox/checkbox.stories.tsx +119 -0
  1323. package/src/components/Checkbox/checkbox.tsx +189 -32
  1324. package/src/components/Checkbox/index.ts +6 -0
  1325. package/src/components/Chip/chip.anatomy.stories.tsx +442 -0
  1326. package/src/components/Chip/chip.principles.stories.tsx +228 -0
  1327. package/src/components/Chip/chip.spec.md +52 -40
  1328. package/src/components/Chip/chip.stories.tsx +111 -0
  1329. package/src/components/Chip/chip.tsx +130 -45
  1330. package/src/components/Chip/index.ts +5 -0
  1331. package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +177 -0
  1332. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +265 -0
  1333. package/src/components/CircularProgress/circular-progress.spec.md +32 -32
  1334. package/src/components/CircularProgress/circular-progress.stories.tsx +149 -0
  1335. package/src/components/CircularProgress/circular-progress.tsx +5 -6
  1336. package/src/components/CircularProgress/index.ts +5 -0
  1337. package/src/components/Coachmark/coachmark-story-helpers.tsx +39 -0
  1338. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +356 -0
  1339. package/src/components/Coachmark/coachmark.principles.stories.tsx +356 -0
  1340. package/src/components/Coachmark/coachmark.spec.md +36 -29
  1341. package/src/components/Coachmark/coachmark.stories.tsx +220 -0
  1342. package/src/components/Coachmark/coachmark.tsx +36 -10
  1343. package/src/components/Coachmark/index.ts +5 -0
  1344. package/src/components/Combobox/combobox.anatomy.stories.tsx +926 -0
  1345. package/src/components/Combobox/combobox.principles.stories.tsx +238 -0
  1346. package/src/components/Combobox/combobox.spec.md +45 -16
  1347. package/src/components/Combobox/combobox.stories.tsx +194 -0
  1348. package/src/components/Combobox/combobox.tsx +278 -97
  1349. package/src/components/Combobox/index.ts +5 -0
  1350. package/src/components/Command/command.anatomy.stories.tsx +107 -0
  1351. package/src/components/Command/command.principles.stories.tsx +86 -0
  1352. package/src/components/Command/command.spec.md +33 -23
  1353. package/src/components/Command/command.stories.tsx +312 -0
  1354. package/src/components/Command/command.tsx +28 -12
  1355. package/src/components/Command/index.ts +5 -0
  1356. package/src/components/DataTable/active-editor-controller.ts +4 -3
  1357. package/src/components/DataTable/cell-registry.tsx +161 -120
  1358. package/src/components/DataTable/column-types.ts +14 -18
  1359. package/src/components/DataTable/data-table-column-visibility-panel.tsx +28 -12
  1360. package/src/components/DataTable/data-table-filter-group.tsx +248 -0
  1361. package/src/components/DataTable/data-table-filter-labels.ts +100 -0
  1362. package/src/components/DataTable/data-table-filter-panel.tsx +85 -448
  1363. package/src/components/DataTable/data-table-filter-value-picker.tsx +254 -0
  1364. package/src/components/DataTable/data-table-interaction-layer.tsx +26 -29
  1365. package/src/components/DataTable/data-table-sort-manager.tsx +19 -11
  1366. package/src/components/DataTable/data-table.anatomy.stories.tsx +522 -0
  1367. package/src/components/DataTable/data-table.css +34 -8
  1368. package/src/components/DataTable/data-table.principles.stories.tsx +270 -0
  1369. package/src/components/DataTable/data-table.spec.md +186 -172
  1370. package/src/components/DataTable/data-table.stories.tsx +2311 -0
  1371. package/src/components/DataTable/data-table.tsx +678 -278
  1372. package/src/components/DataTable/filter-operators.spec.md +269 -0
  1373. package/src/components/DataTable/filter-operators.ts +1 -1
  1374. package/src/components/DataTable/filter-tree.ts +194 -44
  1375. package/src/components/DataTable/index.ts +8 -0
  1376. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +587 -0
  1377. package/src/components/DateGrid/date-grid.principles.stories.tsx +344 -0
  1378. package/src/components/DateGrid/date-grid.spec.md +46 -41
  1379. package/src/components/DateGrid/date-grid.stories.tsx +204 -0
  1380. package/src/components/DateGrid/date-grid.tsx +89 -28
  1381. package/src/components/DateGrid/index.ts +5 -0
  1382. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +946 -0
  1383. package/src/components/DatePicker/date-picker.principles.stories.tsx +205 -0
  1384. package/src/components/DatePicker/date-picker.spec.md +61 -57
  1385. package/src/components/DatePicker/date-picker.stories.tsx +364 -0
  1386. package/src/components/DatePicker/date-picker.tsx +382 -198
  1387. package/src/components/DatePicker/index.ts +5 -0
  1388. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +254 -0
  1389. package/src/components/DescriptionList/description-list.principles.stories.tsx +309 -0
  1390. package/src/components/DescriptionList/description-list.spec.md +35 -30
  1391. package/src/components/DescriptionList/description-list.stories.tsx +113 -0
  1392. package/src/components/DescriptionList/description-list.tsx +16 -14
  1393. package/src/components/DescriptionList/index.ts +5 -0
  1394. package/src/components/Dialog/dialog.anatomy.stories.tsx +485 -0
  1395. package/src/components/Dialog/dialog.principles.stories.tsx +261 -0
  1396. package/src/components/Dialog/dialog.spec.md +58 -32
  1397. package/src/components/Dialog/dialog.stories.tsx +548 -0
  1398. package/src/components/Dialog/dialog.tsx +81 -36
  1399. package/src/components/Dialog/index.ts +5 -0
  1400. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +971 -0
  1401. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +341 -0
  1402. package/src/components/DropdownMenu/dropdown-menu.spec.md +40 -22
  1403. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +276 -0
  1404. package/src/components/DropdownMenu/dropdown-menu.tsx +153 -40
  1405. package/src/components/DropdownMenu/index.ts +5 -0
  1406. package/src/components/Empty/empty.anatomy.stories.tsx +275 -0
  1407. package/src/components/Empty/empty.principles.stories.tsx +314 -0
  1408. package/src/components/Empty/empty.spec.md +42 -42
  1409. package/src/components/Empty/empty.stories.tsx +69 -0
  1410. package/src/components/Empty/empty.tsx +23 -11
  1411. package/src/components/Empty/index.ts +5 -0
  1412. package/src/components/Field/field-context.ts +196 -4
  1413. package/src/components/Field/field-controls.spec.md +161 -54
  1414. package/src/components/Field/field-edit-keys.ts +66 -0
  1415. package/src/components/Field/field-types.ts +71 -20
  1416. package/src/components/Field/field-wrapper.tsx +139 -89
  1417. package/src/components/Field/field.anatomy.stories.tsx +547 -0
  1418. package/src/components/Field/field.principles.stories.tsx +255 -0
  1419. package/src/components/Field/field.spec.md +76 -34
  1420. package/src/components/Field/field.stories.tsx +751 -0
  1421. package/src/components/Field/field.tsx +65 -12
  1422. package/src/components/Field/form-validation.spec.md +60 -34
  1423. package/src/components/Field/index.ts +6 -0
  1424. package/src/components/Field/use-form-validation.ts +270 -0
  1425. package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +119 -0
  1426. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +121 -0
  1427. package/src/components/FieldControlGroup/field-control-group.spec.md +41 -19
  1428. package/src/components/FieldControlGroup/field-control-group.stories.tsx +162 -0
  1429. package/src/components/FieldControlGroup/field-control-group.tsx +13 -15
  1430. package/src/components/FieldControlGroup/index.ts +5 -0
  1431. package/src/components/FileItem/file-item.anatomy.stories.tsx +346 -0
  1432. package/src/components/FileItem/file-item.principles.stories.tsx +245 -0
  1433. package/src/components/FileItem/file-item.spec.md +133 -104
  1434. package/src/components/FileItem/file-item.stories.tsx +289 -0
  1435. package/src/components/FileItem/file-item.tsx +85 -39
  1436. package/src/components/FileItem/index.ts +5 -0
  1437. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +446 -0
  1438. package/src/components/FileUpload/file-upload.principles.stories.tsx +312 -0
  1439. package/src/components/FileUpload/file-upload.spec.md +66 -24
  1440. package/src/components/FileUpload/file-upload.stories.tsx +219 -0
  1441. package/src/components/FileUpload/file-upload.tsx +138 -43
  1442. package/src/components/FileUpload/index.ts +5 -0
  1443. package/src/components/FileViewer/can-render-image.ts +15 -0
  1444. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +1130 -0
  1445. package/src/components/FileViewer/file-viewer.principles.stories.tsx +636 -0
  1446. package/src/components/FileViewer/file-viewer.spec.md +70 -58
  1447. package/src/components/FileViewer/file-viewer.stories.tsx +417 -0
  1448. package/src/components/FileViewer/file-viewer.tsx +157 -72
  1449. package/src/components/FileViewer/image-renderer.tsx +38 -15
  1450. package/src/components/FileViewer/index.ts +5 -0
  1451. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +151 -0
  1452. package/src/components/HoverCard/hover-card.principles.stories.tsx +211 -0
  1453. package/src/components/HoverCard/hover-card.spec.md +38 -28
  1454. package/src/components/HoverCard/hover-card.stories.tsx +304 -0
  1455. package/src/components/HoverCard/hover-card.tsx +23 -6
  1456. package/src/components/HoverCard/index.ts +5 -0
  1457. package/src/components/InlineEdit/index.ts +5 -0
  1458. package/src/components/InlineEdit/inline-edit.anatomy.stories.tsx +250 -0
  1459. package/src/components/InlineEdit/inline-edit.principles.stories.tsx +142 -0
  1460. package/src/components/InlineEdit/inline-edit.spec.md +186 -0
  1461. package/src/components/InlineEdit/inline-edit.stories.tsx +261 -0
  1462. package/src/components/InlineEdit/inline-edit.tsx +455 -0
  1463. package/src/components/Input/index.ts +5 -0
  1464. package/src/components/Input/input.anatomy.stories.tsx +780 -0
  1465. package/src/components/Input/input.principles.stories.tsx +260 -0
  1466. package/src/components/Input/input.spec.md +34 -26
  1467. package/src/components/Input/input.stories.tsx +150 -0
  1468. package/src/components/Input/input.tsx +102 -45
  1469. package/src/components/LinkInput/index.ts +5 -0
  1470. package/src/components/LinkInput/link-input.anatomy.stories.tsx +748 -0
  1471. package/src/components/LinkInput/link-input.principles.stories.tsx +182 -0
  1472. package/src/components/LinkInput/link-input.spec.md +25 -7
  1473. package/src/components/LinkInput/link-input.stories.tsx +133 -0
  1474. package/src/components/LinkInput/link-input.tsx +89 -66
  1475. package/src/components/Menu/index.ts +5 -0
  1476. package/src/components/Menu/menu-item.anatomy.stories.tsx +780 -0
  1477. package/src/components/Menu/menu-item.principles.stories.tsx +81 -0
  1478. package/src/components/Menu/menu-item.spec.md +55 -32
  1479. package/src/components/Menu/menu-item.stories.tsx +242 -0
  1480. package/src/components/Menu/menu-item.tsx +71 -12
  1481. package/src/components/Notice/index.ts +5 -0
  1482. package/src/components/Notice/notice.anatomy.stories.tsx +614 -0
  1483. package/src/components/Notice/notice.principles.stories.tsx +102 -0
  1484. package/src/components/Notice/notice.spec.md +39 -18
  1485. package/src/components/Notice/notice.stories.tsx +257 -0
  1486. package/src/components/Notice/notice.tsx +62 -16
  1487. package/src/components/NumberInput/index.ts +5 -0
  1488. package/src/components/NumberInput/number-input.anatomy.stories.tsx +822 -0
  1489. package/src/components/NumberInput/number-input.principles.stories.tsx +206 -0
  1490. package/src/components/NumberInput/number-input.spec.md +35 -16
  1491. package/src/components/NumberInput/number-input.stories.tsx +167 -0
  1492. package/src/components/NumberInput/number-input.tsx +65 -31
  1493. package/src/components/OverflowIndicator/index.ts +5 -0
  1494. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +550 -0
  1495. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +76 -0
  1496. package/src/components/OverflowIndicator/overflow-indicator.spec.md +36 -26
  1497. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +222 -0
  1498. package/src/components/OverflowIndicator/overflow-indicator.tsx +22 -7
  1499. package/src/components/Pagination/index.ts +5 -0
  1500. package/src/components/Pagination/pagination.anatomy.stories.tsx +144 -0
  1501. package/src/components/Pagination/pagination.principles.stories.tsx +81 -0
  1502. package/src/components/Pagination/pagination.spec.md +150 -0
  1503. package/src/components/Pagination/pagination.stories.tsx +97 -0
  1504. package/src/components/Pagination/pagination.tsx +263 -0
  1505. package/src/components/PeoplePicker/avatar-stack-overflow.ts +1 -1
  1506. package/src/components/PeoplePicker/index.ts +5 -0
  1507. package/src/components/PeoplePicker/people-picker-helpers.ts +5 -5
  1508. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +437 -0
  1509. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +196 -0
  1510. package/src/components/PeoplePicker/people-picker.spec.md +97 -40
  1511. package/src/components/PeoplePicker/people-picker.stories.tsx +245 -0
  1512. package/src/components/PeoplePicker/people-picker.tsx +225 -108
  1513. package/src/components/PeoplePicker/person-display.tsx +83 -47
  1514. package/src/components/Popover/index.ts +5 -0
  1515. package/src/components/Popover/popover.anatomy.stories.tsx +282 -0
  1516. package/src/components/Popover/popover.principles.stories.tsx +316 -0
  1517. package/src/components/Popover/popover.spec.md +41 -31
  1518. package/src/components/Popover/popover.stories.tsx +120 -0
  1519. package/src/components/Popover/popover.tsx +106 -47
  1520. package/src/components/ProfileCard/index.ts +5 -0
  1521. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +493 -0
  1522. package/src/components/ProfileCard/profile-card.principles.stories.tsx +225 -0
  1523. package/src/components/ProfileCard/profile-card.spec.md +189 -0
  1524. package/src/components/ProfileCard/profile-card.stories.tsx +57 -0
  1525. package/src/components/{NameCard/name-card.tsx → ProfileCard/profile-card.tsx} +66 -39
  1526. package/src/components/ProgressBar/index.ts +5 -0
  1527. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +441 -0
  1528. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +326 -0
  1529. package/src/components/ProgressBar/progress-bar.spec.md +25 -21
  1530. package/src/components/ProgressBar/progress-bar.stories.tsx +133 -0
  1531. package/src/components/ProgressBar/progress-bar.tsx +6 -23
  1532. package/src/components/README.md +5 -4
  1533. package/src/components/RadioGroup/index.ts +5 -0
  1534. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +672 -0
  1535. package/src/components/RadioGroup/radio-group.principles.stories.tsx +163 -0
  1536. package/src/components/RadioGroup/radio-group.spec.md +15 -9
  1537. package/src/components/RadioGroup/radio-group.stories.tsx +204 -0
  1538. package/src/components/RadioGroup/radio-group.tsx +219 -67
  1539. package/src/components/Rating/index.ts +5 -0
  1540. package/src/components/Rating/rating.anatomy.stories.tsx +498 -0
  1541. package/src/components/Rating/rating.principles.stories.tsx +296 -0
  1542. package/src/components/Rating/rating.spec.md +41 -29
  1543. package/src/components/Rating/rating.stories.tsx +119 -0
  1544. package/src/components/Rating/rating.tsx +37 -18
  1545. package/src/components/ScrollArea/index.ts +5 -0
  1546. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +451 -0
  1547. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +331 -0
  1548. package/src/components/ScrollArea/scroll-area.spec.md +24 -22
  1549. package/src/components/ScrollArea/scroll-area.stories.tsx +247 -0
  1550. package/src/components/ScrollArea/scroll-area.tsx +24 -7
  1551. package/src/components/SegmentedControl/index.ts +5 -0
  1552. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +295 -0
  1553. package/src/components/SegmentedControl/segmented-control.principles.stories.tsx +284 -0
  1554. package/src/components/SegmentedControl/segmented-control.spec.md +38 -39
  1555. package/src/components/SegmentedControl/segmented-control.stories.tsx +37 -0
  1556. package/src/components/SegmentedControl/segmented-control.tsx +44 -24
  1557. package/src/components/Select/index.ts +5 -0
  1558. package/src/components/Select/select.anatomy.stories.tsx +834 -0
  1559. package/src/components/Select/select.principles.stories.tsx +312 -0
  1560. package/src/components/Select/select.spec.md +99 -39
  1561. package/src/components/Select/select.stories.tsx +273 -0
  1562. package/src/components/Select/select.tsx +389 -97
  1563. package/src/components/SelectMenu/index.ts +5 -0
  1564. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +830 -0
  1565. package/src/components/SelectMenu/select-menu.principles.stories.tsx +106 -0
  1566. package/src/components/SelectMenu/select-menu.spec.md +51 -32
  1567. package/src/components/SelectMenu/select-menu.stories.tsx +143 -0
  1568. package/src/components/SelectMenu/select-menu.tsx +276 -33
  1569. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  1570. package/src/components/SelectionControl/index.ts +6 -0
  1571. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +580 -0
  1572. package/src/components/SelectionControl/selection-item.principles.stories.tsx +77 -0
  1573. package/src/components/SelectionControl/selection-item.spec.md +30 -16
  1574. package/src/components/SelectionControl/selection-item.stories.tsx +137 -0
  1575. package/src/components/SelectionControl/selection-item.tsx +8 -2
  1576. package/src/components/Separator/index.ts +5 -0
  1577. package/src/components/Separator/separator.anatomy.stories.tsx +125 -0
  1578. package/src/components/Separator/separator.principles.stories.tsx +141 -0
  1579. package/src/components/Separator/separator.spec.md +15 -9
  1580. package/src/components/Separator/separator.stories.tsx +106 -0
  1581. package/src/components/Separator/separator.tsx +2 -2
  1582. package/src/components/Sheet/index.ts +5 -0
  1583. package/src/components/Sheet/sheet.anatomy.stories.tsx +269 -0
  1584. package/src/components/Sheet/sheet.principles.stories.tsx +353 -0
  1585. package/src/components/Sheet/sheet.spec.md +16 -17
  1586. package/src/components/Sheet/sheet.stories.tsx +172 -0
  1587. package/src/components/Sheet/sheet.tsx +24 -14
  1588. package/src/components/Sidebar/index.ts +5 -0
  1589. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +776 -0
  1590. package/src/components/Sidebar/sidebar.principles.stories.tsx +507 -0
  1591. package/src/components/Sidebar/sidebar.spec.md +65 -62
  1592. package/src/components/Sidebar/sidebar.stories.tsx +535 -0
  1593. package/src/components/Sidebar/sidebar.tsx +134 -57
  1594. package/src/components/Skeleton/index.ts +5 -0
  1595. package/src/components/Skeleton/skeleton.anatomy.stories.tsx +145 -0
  1596. package/src/components/Skeleton/skeleton.principles.stories.tsx +234 -0
  1597. package/src/components/Skeleton/skeleton.spec.md +15 -14
  1598. package/src/components/Skeleton/skeleton.stories.tsx +134 -0
  1599. package/src/components/Skeleton/skeleton.tsx +2 -2
  1600. package/src/components/Slider/index.ts +5 -0
  1601. package/src/components/Slider/slider.anatomy.stories.tsx +237 -0
  1602. package/src/components/Slider/slider.principles.stories.tsx +250 -0
  1603. package/src/components/Slider/slider.spec.md +66 -118
  1604. package/src/components/Slider/slider.stories.tsx +115 -0
  1605. package/src/components/Slider/slider.tsx +83 -26
  1606. package/src/components/Steps/index.ts +5 -0
  1607. package/src/components/Steps/steps.anatomy.stories.tsx +448 -0
  1608. package/src/components/Steps/steps.principles.stories.tsx +300 -0
  1609. package/src/components/Steps/steps.spec.md +91 -74
  1610. package/src/components/Steps/steps.stories.tsx +306 -0
  1611. package/src/components/Steps/steps.tsx +99 -37
  1612. package/src/components/Switch/index.ts +5 -0
  1613. package/src/components/Switch/switch.anatomy.stories.tsx +227 -0
  1614. package/src/components/Switch/switch.principles.stories.tsx +177 -0
  1615. package/src/components/Switch/switch.spec.md +53 -24
  1616. package/src/components/Switch/switch.stories.tsx +95 -0
  1617. package/src/components/Switch/switch.tsx +176 -43
  1618. package/src/components/Tabs/index.ts +5 -0
  1619. package/src/components/Tabs/tabs-inline-action-geometry.ts +94 -0
  1620. package/src/components/Tabs/tabs.anatomy.stories.tsx +424 -0
  1621. package/src/components/Tabs/tabs.principles.stories.tsx +291 -0
  1622. package/src/components/Tabs/tabs.spec.md +58 -69
  1623. package/src/components/Tabs/tabs.stories.tsx +257 -0
  1624. package/src/components/Tabs/tabs.tsx +262 -82
  1625. package/src/components/Tag/index.ts +5 -0
  1626. package/src/components/Tag/tag.anatomy.stories.tsx +667 -0
  1627. package/src/components/Tag/tag.principles.stories.tsx +270 -0
  1628. package/src/components/Tag/tag.spec.md +112 -100
  1629. package/src/components/Tag/tag.stories.tsx +88 -0
  1630. package/src/components/Tag/tag.tsx +120 -80
  1631. package/src/components/Textarea/index.ts +5 -0
  1632. package/src/components/Textarea/textarea.anatomy.stories.tsx +310 -0
  1633. package/src/components/Textarea/textarea.principles.stories.tsx +192 -0
  1634. package/src/components/Textarea/textarea.spec.md +35 -16
  1635. package/src/components/Textarea/textarea.stories.tsx +57 -0
  1636. package/src/components/Textarea/textarea.tsx +154 -83
  1637. package/src/components/TimePicker/index.ts +5 -0
  1638. package/src/components/TimePicker/time-columns.tsx +15 -3
  1639. package/src/components/TimePicker/time-picker.anatomy.stories.tsx +283 -0
  1640. package/src/components/TimePicker/time-picker.principles.stories.tsx +133 -0
  1641. package/src/components/TimePicker/time-picker.spec.md +58 -52
  1642. package/src/components/TimePicker/time-picker.stories.tsx +193 -0
  1643. package/src/components/TimePicker/time-picker.tsx +119 -60
  1644. package/src/components/Toast/index.ts +5 -0
  1645. package/src/components/Toast/toast.anatomy.stories.tsx +328 -0
  1646. package/src/components/Toast/toast.principles.stories.tsx +216 -0
  1647. package/src/components/Toast/toast.spec.md +26 -16
  1648. package/src/components/Toast/toast.stories.tsx +241 -0
  1649. package/src/components/Toast/toast.tsx +101 -23
  1650. package/src/components/Tooltip/index.ts +5 -0
  1651. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +422 -0
  1652. package/src/components/Tooltip/tooltip.principles.stories.tsx +204 -0
  1653. package/src/components/Tooltip/tooltip.spec.md +37 -23
  1654. package/src/components/Tooltip/tooltip.stories.tsx +82 -0
  1655. package/src/components/Tooltip/tooltip.tsx +58 -12
  1656. package/src/components/TreeView/index.ts +5 -0
  1657. package/src/components/TreeView/tree-view.anatomy.stories.tsx +436 -0
  1658. package/src/components/TreeView/tree-view.principles.stories.tsx +223 -0
  1659. package/src/components/TreeView/tree-view.spec.md +103 -54
  1660. package/src/components/TreeView/tree-view.stories.tsx +365 -0
  1661. package/src/components/TreeView/tree-view.tsx +501 -58
  1662. package/src/hooks/use-controllable.ts +7 -2
  1663. package/src/hooks/use-is-touch-device.ts +8 -1
  1664. package/src/hooks/use-overflow-items.ts +10 -6
  1665. package/src/hooks/use-truncated.ts +111 -0
  1666. package/src/index.ts +651 -71
  1667. package/src/lib/drag-visual.ts +2 -2
  1668. package/src/lib/utils.ts +21 -1
  1669. package/src/patterns/README.md +20 -16
  1670. package/src/patterns/action-bar/action-bar.spec.md +63 -45
  1671. package/src/patterns/action-bar/action-bar.stories.tsx +619 -0
  1672. package/src/patterns/element-anatomy/element-anatomy.spec.md +17 -13
  1673. package/src/patterns/element-anatomy/index.ts +6 -0
  1674. package/src/patterns/element-anatomy/inline-action.spec.md +33 -22
  1675. package/src/patterns/element-anatomy/item-anatomy.spec.md +108 -79
  1676. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +1648 -0
  1677. package/src/patterns/element-anatomy/item-anatomy.tsx +147 -56
  1678. package/src/patterns/element-anatomy/truncated-text.spec.md +68 -0
  1679. package/src/patterns/element-anatomy/truncated-text.tsx +61 -0
  1680. package/src/patterns/header-canonical/chrome-header.tsx +26 -6
  1681. package/src/patterns/header-canonical/header-canonical.css +3 -4
  1682. package/src/patterns/header-canonical/header-canonical.spec.md +96 -42
  1683. package/src/patterns/header-canonical/header-canonical.stories.tsx +257 -0
  1684. package/src/patterns/header-canonical/index.ts +5 -0
  1685. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +36 -15
  1686. package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +139 -0
  1687. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +1 -1
  1688. package/src/patterns/horizontal-overflow/index.ts +5 -0
  1689. package/src/patterns/overlay-surface/index.ts +5 -0
  1690. package/src/patterns/overlay-surface/overlay-surface.spec.md +94 -58
  1691. package/src/patterns/overlay-surface/overlay-surface.stories.tsx +132 -0
  1692. package/src/patterns/overlay-surface/overlay-surface.tsx +37 -18
  1693. package/src/patterns/resize-handle/index.ts +5 -0
  1694. package/src/patterns/resize-handle/resize-handle.spec.md +22 -13
  1695. package/src/patterns/resize-handle/resize-handle.stories.tsx +73 -0
  1696. package/src/patterns/resize-handle/resize-handle.tsx +13 -18
  1697. package/src/story-governance/category-matrix.json +132 -0
  1698. package/src/story-governance/category-matrix.ts +55 -0
  1699. package/src/styles/base.css +99 -0
  1700. package/src/styles/tokens.css +14 -0
  1701. package/src/tokens/README.md +10 -5
  1702. package/src/tokens/categorical-color.ts +164 -0
  1703. package/src/tokens/color/color.spec.md +95 -72
  1704. package/src/tokens/color/color.stories.tsx +403 -0
  1705. package/src/tokens/color/primitives.css +23 -7
  1706. package/src/tokens/color/semantic.css +75 -21
  1707. package/src/tokens/density/density.spec.md +33 -30
  1708. package/src/tokens/density/density.stories.tsx +254 -0
  1709. package/src/tokens/elevation/elevation.spec.md +11 -14
  1710. package/src/tokens/elevation/elevation.stories.tsx +99 -0
  1711. package/src/tokens/layoutSpace/layoutSpace.css +1 -1
  1712. package/src/tokens/layoutSpace/layoutSpace.spec.md +44 -31
  1713. package/src/tokens/layoutSpace/layoutSpace.stories.tsx +76 -0
  1714. package/src/tokens/motion/motion.css +49 -20
  1715. package/src/tokens/motion/motion.spec.md +45 -21
  1716. package/src/tokens/motion/motion.stories.tsx +196 -0
  1717. package/src/tokens/motion/motion.ts +8 -7
  1718. package/src/tokens/motion/overlay-motion.ts +26 -0
  1719. package/src/tokens/opacity/opacity.spec.md +15 -20
  1720. package/src/tokens/opacity/opacity.stories.tsx +66 -0
  1721. package/src/tokens/orphan-tokens.spec.md +22 -11
  1722. package/src/tokens/radius/radius.spec.md +14 -11
  1723. package/src/tokens/radius/radius.stories.tsx +87 -0
  1724. package/src/tokens/token-system.spec.md +241 -0
  1725. package/src/tokens/typography/typography.css +1 -1
  1726. package/src/tokens/typography/typography.spec.md +12 -8
  1727. package/src/tokens/typography/typography.stories.tsx +134 -0
  1728. package/src/tokens/uiSize/icon-size.ts +3 -4
  1729. package/src/tokens/uiSize/uiSize.css +60 -1
  1730. package/src/tokens/uiSize/uiSize.spec.md +61 -32
  1731. package/src/tokens/uiSize/uiSize.stories.tsx +106 -0
  1732. package/src/tokens/utility-registry.json +426 -0
  1733. package/src/tokens/utility-registry.schema.json +409 -0
  1734. package/tools/README.md +9 -0
  1735. package/tools/codemods/cli.mjs +93 -0
  1736. package/tools/codemods/index.mjs +582 -0
  1737. package/tools/shared/safe-filesystem.mjs +371 -0
  1738. package/tools/visual-baseline/cli.mjs +97 -0
  1739. package/tools/visual-baseline/index.mjs +522 -0
  1740. package/dist/components/NameCard/name-card.d.ts.map +0 -1
  1741. package/dist/components/NameCard/name-card.js.map +0 -1
  1742. package/ds-canonical/commands/gov-status.md +0 -79
  1743. package/ds-canonical/hooks/check_app_shell_primary_header_consistency.sh +0 -68
  1744. package/ds-canonical/hooks/check_chrome_header_handcraft.sh +0 -70
  1745. package/ds-canonical/hooks/check_header_with_tabs_border.sh +0 -87
  1746. package/ds-canonical/hooks/check_tab_lg_chrome_header_equal.sh +0 -66
  1747. package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +0 -15
  1748. package/ds-canonical/hooks/tests/test_check_story_category.sh.broken +0 -187
  1749. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +0 -74
  1750. package/ds-canonical/skills/design-system-audit/references/spec-template.md +0 -66
  1751. package/src/components/NameCard/name-card.spec.md +0 -171
@@ -1,13 +1,32 @@
1
1
  // @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
2
2
  // code-quality-allow: file-size — foundational composite — 拆檔會複雜化 context / ref / state 同步
3
+ //
4
+ // ── 檔案結構(2026-05-03 split matrix;2026-06-11 自 data-table.spec.md 遷入,Level 4 code home)──
5
+ // 每個檔過 M21 / M17 / Rule-of-3 三 test:
6
+ // - data-table.tsx(主,foundational)
7
+ // - data-table-filter-panel.tsx + data-table-sort-manager.tsx + data-table-column-visibility-panel.tsx(panel state 隔離)
8
+ // - data-table-filter-group.tsx + data-table-filter-value-picker.tsx(@internal;2026-07-14 filter panel
9
+ // 過 800 hard cap 拆檔 — row/nested-group renderer + ValueShape picker,只被 panel 消費)
10
+ // - cell-registry.tsx(column type → cell view / edit 解析 SSOT)
11
+ // - data-table-interaction-layer.tsx + active-editor-controller.ts(spreadsheet overlay + portal editor)
12
+ // - column-types.ts + filter-operators.ts(✓ Rule-of-3 SSOT,3+ consumer)
13
+ // - filter-tree.ts(pure data + eval,test isolation)
14
+ // - lib/column-meta.ts(Internal SSOT,消 5 處 `(col as any)`)
15
+ // - + stories / spec / css
16
+ // M21 retract:filter-value-picker.tsx 1 consumer → 2026-05-03 inline 回 panel(上列 2026-07-14
17
+ // @internal 拆檔非 M21 迴轉:非 public 抽象,file-size hard cap 驅動,consumer 仍只見 panel)。
3
18
  import * as React from 'react'
4
19
  import { createPortal } from 'react-dom'
5
20
  import { Empty } from '@/design-system/components/Empty/empty'
21
+ // L5 分頁(2026-07-06):Pagination = 分頁完整功能 SSOT(頁碼 + showTotal + 每頁筆數選單
22
+ // 全 own 在 Pagination;共用模式,Ant Table 消費 Pagination 同派)—— DataTable 只轉發 config
23
+ import { Pagination } from '@/design-system/components/Pagination/pagination'
6
24
  import {
7
25
  useReactTable,
8
26
  getCoreRowModel,
9
27
  getSortedRowModel,
10
28
  getExpandedRowModel,
29
+ getPaginationRowModel,
11
30
  flexRender,
12
31
  type ColumnDef,
13
32
  type SortingState,
@@ -24,12 +43,13 @@ import { DndContext, DragOverlay, useDraggable, useDroppable, useDndContext, poi
24
43
  import { cn } from '@/lib/utils'
25
44
  import { ICON_SIZE } from '@/design-system/tokens/uiSize/icon-size'
26
45
  import { dragSourceStyle, dropIndicatorRow, dropIndicatorColumn, dragActiveCursor, isReorderNoop, reconstructFullRowGhost, snapToCursorModifier } from '@/design-system/lib/drag-visual'
27
- import { nakedCellEditableDisplayHover } from '@/design-system/components/Field/field-wrapper'
46
+ import { nakedCellEditableDisplayHover, fieldDisplayTextClass } from '@/design-system/components/Field/field-wrapper'
28
47
  import { Tooltip, TooltipContent, TooltipTrigger } from '@/design-system/components/Tooltip/tooltip'
48
+ import { TruncatedText } from '@/design-system/patterns/element-anatomy/truncated-text'
29
49
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from '@/design-system/components/DropdownMenu/dropdown-menu'
30
50
  import { ItemInlineActionButton } from '@/design-system/patterns/element-anatomy/item-anatomy'
31
51
  import { columnTypeDefaults, type ColumnType } from './column-types'
32
- import { resolveCellComponent } from './cell-registry'
52
+ import { resolveCellComponent, type CellComponentProps } from './cell-registry'
33
53
  import { DataTableInteractionLayer } from './data-table-interaction-layer'
34
54
  import { Checkbox } from '@/design-system/components/Checkbox/checkbox'
35
55
  import { RadioGroupItem } from '@/design-system/components/RadioGroup/radio-group'
@@ -56,10 +76,17 @@ type TableSize = 'sm' | 'md' | 'lg'
56
76
  export interface DataTableProps<TData>
57
77
  extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,
58
78
  VariantProps<typeof dataTableVariants> {
79
+ // any-allow: TanStack ColumnDef TValue idiom(per-column value 型別異質,官方範例同)— 對齊本 module 既有 escape 紀律
59
80
  columns: ColumnDef<TData, any>[]
60
81
  data: TData[]
61
82
  size?: TableSize
62
83
  autoRowHeight?: boolean
84
+ /**
85
+ * 容器高度。預設 '400px'(body 內捲動);'auto' = 自然高度(hug rows);'100%' = fill parent。
86
+ * L5 分頁(2026-07-06):啟用 `pagination` 且未顯式傳 height 時預設改 'auto' —— 分頁的
87
+ * 導覽通道是頁碼,再疊 body 內捲動 = 雙重導覽(一頁 20 筆只露 10 筆);對齊 Ant Table
88
+ * 無預設高度罩、`scroll.y` 顯式選配的慣例。顯式傳 height 照舊尊重(分頁 + 頁內捲動可並用)。
89
+ */
63
90
  height?: string
64
91
  overscan?: number
65
92
  emptyState?: React.ReactNode
@@ -70,7 +97,7 @@ export interface DataTableProps<TData>
70
97
  /**
71
98
  * Issue 9 cell error system(2026-05-10)。
72
99
  *
73
- * Map of `${rowId}:${colId}` → error message(string | string[])。Cell display mode 在 content
100
+ * Map of `${rowId}:${colId}` → error message(string | string[])。Cell view mode 在 content
74
101
  * 下方渲 `text-body text-error` 訊息,gap-1 spacing。Multi-error 用 array → ul / li 分行渲。
75
102
  *
76
103
  * **使用建議**:
@@ -92,7 +119,8 @@ export interface DataTableProps<TData>
92
119
  * Slice D Step 1B(2026-05-10):啟用 spreadsheet-grade interaction overlay。
93
120
  * Default false(backward-compat)。Enable 後 hover/editor/selected/range 由
94
121
  * `DataTableInteractionLayer` overlay 統一畫,per `.claude/planning/datatable-spreadsheet-rfc.md`。
95
- * 漸進切換階段,當前 v1 minimal:hover overlay 1 layer。
122
+ * 現況:hover ring + selection ring + active editor host 三個 sub-layer
123
+ * (詳 `data-table-interaction-layer.tsx` 檔頭)。
96
124
  */
97
125
  experimentalSpreadsheetOverlay?: boolean
98
126
  /**
@@ -108,32 +136,33 @@ export interface DataTableProps<TData>
108
136
  * Slice D Step 4(spreadsheet semantics,2026-05-10 user 拍板 + codex Layer B Q2.1 confirm):
109
137
  * Excel-like cell selection:click 1=select / click 2=edit / Shift+click=range。
110
138
  * Default false opt-in(per codex「DataTable is not a spreadsheet」既有原則 +
111
- * data-table.principles.stories.tsx L283-292)。
139
+ * data-table.principles.stories.tsx「不是試算表」principle story)。
112
140
  * Enable 後 inlineEdit cell click 行為:
113
141
  * - Plain click → setSelectedCellId,**不**進 edit mode
114
142
  * - Click on already-selected → enter edit
115
143
  * - Shift+click → extend range from anchor
116
144
  * - Double-click / Enter / F2 / printable(deferred) → enter edit on selected
117
145
  * - Click empty area → clear selection
118
- * 視覺:Layer 渲 SelectionRect(solid `--primary` 2px border)+ RangeRect
119
- * (`--primary-subtle` bg fill)— per user「不要 dash 直接實的就好」+ codex Q2.2 token。
146
+ * 視覺:selection ring 1px `--primary`(layer `CELL_RING_STYLES.selected`);range 視覺
147
+ * = cell-bg `--primary-subtle`(`[data-range-cell]` CSS),outer ring 已 2026-05-10 retire
148
+ * — per user「不要 dash 直接實的就好」+ codex Q2.2 token。
120
149
  */
121
150
  spreadsheetMode?: boolean
122
151
 
123
152
  // ── L2 Selection(see data-table.spec.md「L2 選取」)──
124
- /** 已選 row IDs(controlled) */
125
- selection?: string[]
126
- /** 預設選取(uncontrolled) */
127
- defaultSelection?: string[]
128
- /** Selection 變更 callback */
129
- onSelectionChange?: (next: string[]) => void
153
+ /** 已選列(controlled)。傳 string[] = include shorthand;傳 DataTableSelection 支援反向選取(all + excluded) */
154
+ selection?: string[] | DataTableSelection
155
+ /** 預設選取(uncontrolled);同上接受 string[] 或 DataTableSelection */
156
+ defaultSelection?: string[] | DataTableSelection
157
+ /** Selection 變更 callback(emit DataTableSelection union;include / all 兩模型) */
158
+ onSelectionChange?: (next: DataTableSelection) => void
130
159
  /** 是否啟用 selection / 模式;true 等同 'multi' */
131
160
  selectable?: boolean | 'single' | 'multi'
132
161
  /** Row 是否可選(disabled rows 只 disable checkbox,row 內容正常 render) */
133
162
  isRowSelectable?: (row: TData) => boolean
134
163
  /** 取 row 唯一 ID(selection 用);default `(row, index) => String(index)` */
135
164
  getRowId?: (row: TData, index: number) => string
136
- /** Checkbox aria-label fallback;default `'Select row'` */
165
+ /** Checkbox aria-label fallback;default `'選取此列'` */
137
166
  getRowAriaLabel?: (row: TData) => string
138
167
  /** Filter 後 hidden selected rows 是否保留(default false,對齊 Material/AG Grid 共識) */
139
168
  preserveSelectionOnFilter?: boolean
@@ -175,8 +204,8 @@ export interface DataTableProps<TData>
175
204
  *
176
205
  * **v2(2026-05-05)修正**:
177
206
  * - Virtualizer × transform:被拖 row 略過 `measureElement`(透過 SortableRowCtx 廣播 active id),避免 transform 干擾測量
178
- * - 3-panel mirror sync:每 region 都呼叫 `useSortable({id})`(同 SortableContext 共用 state),mirror 自然取得相同 transform
179
- * - Cross-parent drop:nested 全 row 進 SortableContext.items,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`
207
+ * - 3-panel mirror sync:primary region 呼叫 `useDraggable` + `useDroppable`;mirror region 只 `useDroppable`(v15.4 split),isDragging 由 `useDndContext` active.id 同步 → 三 region 視覺一致
208
+ * - Cross-parent drop:nested 全 row 各自 `useDroppable`,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`
180
209
  *
181
210
  * 詳 `data-table.spec.md`「L4 Row drag」段。
182
211
  */
@@ -222,19 +251,42 @@ export interface DataTableProps<TData>
222
251
  * @param position 'before' | 'after'
223
252
  */
224
253
  onColumnReorder?: (sourceId: string, targetId: string, position: 'before' | 'after') => void
254
+ /**
255
+ * L5 分頁(2026-07-06):`true` 或 config 物件啟用——內部接 TanStack `getPaginationRowModel`,
256
+ * 表格下方渲染分頁列(消費 `<Pagination>` 獨立元件,間距 tight、頁碼靠右)。
257
+ * 啟用時虛擬滾動自動關閉(TanStack 官方:互斥替代策略)。v1 = client-side only。
258
+ * 詳 data-table.spec.md「L5:分頁」段。
259
+ */
260
+ pagination?: boolean | DataTablePaginationOptions
261
+ }
262
+
263
+ /** L5 分頁 config(頁碼 1-based 對外,對齊 Pagination / Ant;詳 data-table.spec.md「L5:分頁」段) */
264
+ export interface DataTablePaginationOptions {
265
+ /** 每頁筆數(預設 20) */
266
+ pageSize?: number
267
+ /** 每頁筆數選項;傳了才渲染「每頁 N 筆」Select(消費既有 Select size="sm") */
268
+ pageSizeOptions?: number[]
269
+ /** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 server-side 全集數 M — 那是 consumer 自持) */
270
+ showTotal?: boolean
271
+ /** 當前頁(1-based,controlled;不傳 = uncontrolled) */
272
+ page?: number
273
+ /** uncontrolled 初始頁(1-based,預設 1) */
274
+ defaultPage?: number
275
+ onPageChange?: (page: number) => void
276
+ onPageSizeChange?: (pageSize: number) => void
225
277
  }
226
278
 
227
279
  // ── Cell Rendering(Phase C 2026-05-05 — type-keyed registry SSOT)─────────────
228
280
  //
229
281
  // 原 `renderTypedValue` switch + `EditableCellContent` switch 兩條平行 type-switch
230
282
  // 已 collapse 為單一 `cellRegistry`(./cell-registry.ts)— 每個 type → 一個 cell component,
231
- // 同時處理 display + edit mode(底層 Field control 的 mode prop)。對齊 M17 SSOT consolidation。
283
+ // 同時處理 view + edit mode(底層 Field control 的 mode prop)。對齊 M17 SSOT consolidation。
232
284
  //
233
285
  // 對齊 Notion / Airtable type-aware inline edit canonical(詳 spec §十二):
234
286
  // - string / number / currency:cell click → inline edit
235
287
  // - date / time / select / multiSelect / person / multiPerson:cell click → 進 edit mode
236
288
  // - boolean:不分 read/edit mode,直接 `<Checkbox>` 點即 toggle + commit
237
- // - url:read = LinkInput display + hover Pencil button,click Pencil 才進 edit mode
289
+ // - url:read = LinkInput view + hover Pencil button,click Pencil 才進 edit mode
238
290
  //
239
291
  // Cell id format: `${rowId}__${columnId}`(編輯狀態 keying)
240
292
  // Commit: blur OR Enter OR overlay close → 呼叫 onCellCommit
@@ -251,6 +303,50 @@ const cellEditId = (rowId: string, colId: string) => `${rowId}__${colId}`
251
303
  // (詳 ./data-table.css)— consumer 可走 CSS override 改值,不再 hard-code in TS。
252
304
  // L2 selection 內部 column id(避免 magic string 重複)
253
305
  const SELECT_COL_ID = '__select__'
306
+
307
+ /**
308
+ * L2 選取模型(discriminated union,2026-06-22 對齊 MUI X DataGrid v8
309
+ * rowSelectionModel { type: include | exclude, ids } + AG Grid selectAll + toggledNodes)。
310
+ *
311
+ * - mode==='include' (ids):只選 ids 列(預設;= 載入/可見列逐一選取)。
312
+ * - mode==='all' (excluded):全資料集(filter 後)選取,扣掉 excluded —— 反向選取(inverted)。
313
+ * 解決「全選 10k 筆只載 50 筆 → 無法列舉其餘 ID」:all 模式「選取 = 全集 − excluded」,
314
+ * 任何 toggle 都只是 excluded 的 add/remove,對任意順序封閉、O(1)、不需列舉未載入 ID。
315
+ *
316
+ * 計數(consumer):mode==='all' ? M − excluded.length : ids.length(M = consumer 自持的
317
+ * server-side / filter 後全集筆數;2026-07-13 D1 拍板:DataTable 不收 totalCount prop — DS 內部
318
+ * 零消費 no-op 已移除,計數本來就全由 consumer 端算)。
319
+ * 進入 all 模式:consumer 在「選取全部 M」hint 點擊時 setSelection({ mode: 'all', excluded: [] })。
320
+ */
321
+ export type DataTableSelection =
322
+ | { mode: 'include'; ids: string[] }
323
+ | { mode: 'all'; excluded: string[] }
324
+
325
+ // 正規化:string[] shorthand → { mode:'include' }(向後相容既有 consumer 傳 ID 陣列)
326
+ function normalizeSelection(
327
+ input: string[] | DataTableSelection | undefined,
328
+ ): DataTableSelection | undefined {
329
+ if (input === undefined) return undefined
330
+ if (Array.isArray(input)) return { mode: 'include', ids: input }
331
+ return input
332
+ }
333
+
334
+ // union-aware「把 ids 設成 willSelect 狀態」純函式(對任意 toggle 順序封閉)
335
+ function applySelectIds(
336
+ sel: DataTableSelection,
337
+ ids: string[],
338
+ willSelect: boolean,
339
+ ): DataTableSelection {
340
+ if (sel.mode === 'include') {
341
+ const set = new Set(sel.ids)
342
+ ids.forEach((id) => { if (willSelect) set.add(id); else set.delete(id) })
343
+ return { mode: 'include', ids: Array.from(set) }
344
+ }
345
+ // all 模式:選取 = 全集 − excluded → willSelect 移出 excluded;取消選取 加進 excluded
346
+ const set = new Set(sel.excluded)
347
+ ids.forEach((id) => { if (willSelect) set.delete(id); else set.add(id) })
348
+ return { mode: 'all', excluded: Array.from(set) }
349
+ }
254
350
  const cellPadding: React.CSSProperties = { paddingBlock: 'var(--table-cell-py)', paddingInline: 'var(--table-cell-px)' }
255
351
  const HEADER_BG = 'bg-muted'
256
352
 
@@ -298,67 +394,29 @@ function columnSizeStyle(
298
394
  //
299
395
  // **flex-basis: baseSize(2026-05-06 v14.2)**:把 baseSize 當 explicit basis(不是 `0%`)。
300
396
  // 為什麼:flex item base = basis + padding(box-sizing: border-box content-box 行為)。前 `0%`
301
- // basis → cell padding 變 base 一部分。display(padding 12)vs edit(padding 0,Field 接管)
302
- // 兩態 base 不同 → flex 重分配 → user 報「Price cell 進 edit 寬度縮 12px」(verify by
303
- // debug-v14-1-display-edit-rect-match.mjs:Price display 130.5 → edit 118.5 = -12px)。
304
- // explicit basis = baseSize 讓 padding 不參與 base 計算 → display↔edit 寬度穩定。
397
+ // basis → cell padding 變 base 一部分。view(padding 12)vs edit(padding 0,Field 接管)
398
+ // 兩態 base 不同 → flex 重分配 → user 報「Price cell 進 edit 寬度縮 12px」
399
+ // (量測:Price view 130.5 → edit 118.5 = -12px)。
400
+ // explicit basis = baseSize 讓 padding 不參與 base 計算 → view↔edit 寬度穩定。
305
401
  return { flex: `1 1 ${baseSize}px`, minWidth: baseSize, maxWidth: maxSize }
306
402
  }
307
403
 
308
404
  const SYSTEM_COL_IDS = new Set([SELECT_COL_ID, '__drag__', '__actions__'])
309
405
  const isSystemColumn = (colId: string) => SYSTEM_COL_IDS.has(colId)
310
406
 
311
- // ── TruncateCell ─────────────────────────────────────────────────────────────
312
- // Shared ResizeObserver(2026-04-22 D3 perf audit):從 per-cell RO 改為全 DS 共用一個 RO
313
- // dispatch 到 per-element callback。10 col × 100 row = 1 RO(before:1000 RO)。
314
- // 跨 OS 一致的 RO 行為;element 卸載時 cleanup。
315
-
316
- type RoCallback = (entry: ResizeObserverEntry) => void
317
- let sharedResizeObserver: ResizeObserver | null = null
318
- const roCallbacks = new WeakMap<Element, RoCallback>()
319
-
320
- function getSharedRO(): ResizeObserver {
321
- if (sharedResizeObserver) return sharedResizeObserver
322
- sharedResizeObserver = new ResizeObserver((entries) => {
323
- entries.forEach((entry) => {
324
- const cb = roCallbacks.get(entry.target)
325
- if (cb) cb(entry)
326
- })
327
- })
328
- return sharedResizeObserver
329
- }
330
-
331
- function observeShared(el: Element, cb: RoCallback): () => void {
332
- const obs = getSharedRO()
333
- roCallbacks.set(el, cb)
334
- obs.observe(el)
335
- return () => {
336
- roCallbacks.delete(el)
337
- obs.unobserve(el)
338
- }
339
- }
340
-
341
- function TruncateCell({ children, className }: { children: React.ReactNode; className?: string }) {
342
- const ref = React.useRef<HTMLSpanElement>(null)
343
- const [isTruncated, setIsTruncated] = React.useState(false)
344
- React.useEffect(() => {
345
- const el = ref.current
346
- if (!el) return
347
- const check = () => setIsTruncated(el.scrollWidth > el.clientWidth)
348
- check()
349
- return observeShared(el, check)
350
- }, [])
351
- const span = <span ref={ref} className={cn('truncate min-w-0', className)}>{children}</span>
352
- if (!isTruncated) return span
353
- return <Tooltip><TooltipTrigger asChild>{span}</TooltipTrigger><TooltipContent>{children}</TooltipContent></Tooltip>
354
- }
355
-
356
- // ── L4 Row Drag: SortableRowContext (v2) ─────────────────────────────────────
357
- // v2:每 region(left / center / right)各 mount 一次 SortableRowProvider — 多個 useSortable
358
- // 共用同一 SortableContext / 同 row id 時,dnd-kit 內部以 id 為 unit 分發 transform / isDragging,
359
- // 各 hook instance 取得相同值,因此 mirror region 自然跟動(v1 mirror static bug 修正)。
360
- // listeners 仍只走 primary region(避免 pointer 事件雙重觸發);primary = left region 若存在否則 center。
361
- // `invalidDrop`(cross-parent over)走 prop 廣播給 DragHandleCell 切 cursor-not-allowed。
407
+ // ── TruncatedText ── 2026-07-19:truncate+tooltip 引擎 + presentation 已抽成 SSOT primitive
408
+ // `patterns/element-anatomy/truncated-text`(`<TruncatedText>` 消費 `useTruncated` hook)。原 file-local
409
+ // shared RO(2026-04-22 D3 perf audit 的「全 DS 共用單一 RO」特性由 hook 承接)+ TruncateCell 已移除,
410
+ // 改用 `<TruncatedText tooltip={children} className={...}>`(display 預設 inline,保 cell baseline)。
411
+ // compound 欄位仍在 renderCellContent bypass(見下)—— 只 primitive string/number 走 TruncatedText。
412
+
413
+ // ── L4 Row Drag: SortableRowContext(v15 Path B;2026-07-14 JSDoc 對齊實作)──────
414
+ // 每 region(left / center / right)各 mount 一次 SortableRowProvider,依 role 分流(v15.4 split):
415
+ // primary → SourceRowProvider(useDraggable + useDroppable)= 唯一 drag source;
416
+ // mirror → MirrorRowProvider(useDroppable only),isDragging 走 useDndContext active.id 同步。
417
+ // 無 SortableContext / useSortable(v15.0 Path B 已砍,見檔頭 import 註解)。listeners 全走
418
+ // RowDragHandle Button(v15.6 button-only;row 本身不接 listeners)。primary = left region 若存在否則 center。
419
+ // `invalidDrop`(cross-parent over)走 prop 廣播給 RowDragHandle 切 cursor-not-allowed。
362
420
  interface SortableRowCtxValue {
363
421
  setNodeRef: (el: HTMLElement | null) => void
364
422
  role: 'primary' | 'mirror'
@@ -384,10 +442,11 @@ interface SortableRowCtxValue {
384
442
  }
385
443
  const SortableRowCtx = React.createContext<SortableRowCtxValue | null>(null)
386
444
 
387
- /** Per-region per-row sortable wrapper(v2 multi-instance pattern)。
388
- * 同 row.id 在 left/center/right 三 region 各 mount 一次 — useSortable 共享同 SortableContext
389
- * state,各 instance 取得相同 transform → mirror 自動跟動。
390
- * primary instance 額外提供 listeners 給 DragHandleCell;mirror 不提供避免雙觸發。 */
445
+ /** Per-region per-row drag wrapper(v15.4 architectural split)。
446
+ * 同 row.id 在 left/center/right 三 region 各 mount 一次,但 hook mount tree 完全分離:
447
+ * primary → SourceRowProvider(useDraggable + useDroppable);mirror → MirrorRowProvider
448
+ * (useDroppable only,isDragging 由 useDndContext 同步)。activator / listeners 只給
449
+ * primary 的 RowDragHandle Button(v15.6 button-only);mirror 不提供避免雙觸發。 */
391
450
  function SortableRowProvider(props: {
392
451
  id: string
393
452
  disabled?: boolean
@@ -427,7 +486,6 @@ function SourceRowProvider({
427
486
  droppable.setNodeRef(el)
428
487
  }, [draggable.setNodeRef, droppable.setNodeRef])
429
488
  const isDragging = draggable.isDragging
430
- const style: React.CSSProperties = { ...dragSourceStyle(isDragging) }
431
489
  // a11y(2026-05-07 v15.10 codex P1 fix):button-only drag mode 下,row 本身不該成為
432
490
  // keyboard tab stop。dnd-kit `useDraggable.attributes` 含 `role="button" tabIndex=0
433
491
  // aria-roledescription="..."` 全給 activator 用,套到 row div 會讓每筆 row tabbable
@@ -435,10 +493,14 @@ function SourceRowProvider({
435
493
  // **拆分**:rowAttributes 留空(row 是 passive container)/ handleAttributes 全給
436
494
  // RowDragHandle Button(它是真 activator,Button 自帶 role/tabIndex 完全相容)。
437
495
  const handleAttrs = draggable.attributes as unknown as Record<string, unknown>
438
- const ctxValue: SortableRowCtxValue = {
496
+ // 2026-07-05 D3 perf fix:ctxValue useMemo — 原每 render 新 object,RowDragHandle 的
497
+ // useLayoutEffect deps [rowEl, ctx] 在每次 DataTableInner render 都 teardown/重掛
498
+ // MutationObserver + window scroll/resize listener(×每個 visible primary row)。
499
+ // memo 後 identity 只在 drag 相關值真變(isDragging / invalidDrop 等)時才換。
500
+ const ctxValue: SortableRowCtxValue = React.useMemo(() => ({
439
501
  setNodeRef: setRefs,
440
502
  role,
441
- style,
503
+ style: { ...dragSourceStyle(isDragging) },
442
504
  attributes: {},
443
505
  isDragging,
444
506
  // row 不接 listeners(button-only),baseRowDiv `{...(extra?.listeners ?? {})}` 自動 noop
@@ -451,7 +513,7 @@ function SourceRowProvider({
451
513
  handleListeners: draggable.listeners as unknown as Record<string, unknown> | undefined,
452
514
  handleAttributes: handleAttrs,
453
515
  invalidDrop,
454
- }
516
+ }), [setRefs, role, isDragging, draggable.setActivatorNodeRef, draggable.listeners, handleAttrs, invalidDrop])
455
517
  return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>
456
518
  }
457
519
 
@@ -479,7 +541,9 @@ function MirrorRowProvider({
479
541
  const droppable = useDroppable({ id, disabled, data: { type: 'row' } })
480
542
  const dndCtx = useDndContext()
481
543
  const isDragging = dndCtx.active?.id === id
482
- const ctxValue: SortableRowCtxValue = {
544
+ // 2026-07-05 D3 perf fix:ctxValue useMemo(同 SourceRowProvider — 消掉 RowDragHandle
545
+ // effect 的每 render observer/listener churn;mirror 雖不渲 handle,identity 穩定仍省下游 diff)
546
+ const ctxValue: SortableRowCtxValue = React.useMemo(() => ({
483
547
  setNodeRef: droppable.setNodeRef,
484
548
  role,
485
549
  style: { ...dragSourceStyle(isDragging) },
@@ -491,18 +555,19 @@ function MirrorRowProvider({
491
555
  handleListeners: undefined,
492
556
  handleAttributes: {},
493
557
  invalidDrop,
494
- }
558
+ }), [droppable.setNodeRef, role, isDragging, invalidDrop])
495
559
  return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>
496
560
  }
497
561
 
498
- /** DraggableHeaderCell — wrap header cell 跟 dnd-kit useSortable 接軌(2026-05-06 v14.2)。
562
+ /** DraggableHeaderCell — wrap header cell 跟 dnd-kit useDraggable + useDroppable 接軌
563
+ * (2026-05-06 v14.2;v15.0 Path B 改分離 hooks,無 SortableContext)。
499
564
  *
500
565
  * Why wrap-not-rewrite:`headerCellEl` 既有邏輯複雜(sort / resize / select column / right region 等),
501
- * 改 inline useSortable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render
566
+ * 改 inline useDraggable/useDroppable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render
502
567
  * 保持 untouched,單一職責 = 加 drag affordance。
503
568
  *
504
569
  * Behavior:
505
- * - useSortable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners
570
+ * - useDraggable + useDroppable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners
506
571
  * - `data: { type: 'column', columnId }` 餵 dnd-kit handleDragStart / handleDragEnd 區分 row/column drag
507
572
  * - 注入 ref(setNodeRef)+ transform style + transition + opacity(drag 時 source invisible,DragOverlay 顯 ghost)
508
573
  * - draggable 時注入 attributes + listeners + cursor:grab / `data-column-id` (DragOverlay snapshot 用)
@@ -546,12 +611,33 @@ function DraggableHeaderCell({
546
611
  : dropIndicatorSide === 'after'
547
612
  ? dropIndicatorColumn.pseudoAfter
548
613
  : ''
614
+ // dnd-kit KeyboardSensor 的 activator = listeners.onKeyDown,掛在整個 header cell 上(column
615
+ // 無獨立 activator node,不像 row drag 的 button-only handle)。巢狀互動 descendant(more-menu
616
+ // 按鈕 / resize separator / 排序 chevron)的 Enter/Space 冒泡到此 → dnd-kit preventDefault 啟動
617
+ // 欄位拖曳,吃掉按鈕原生啟動。包一層 guard:事件來自互動 descendant(非 header cell 本身)時
618
+ // 交回原生,不啟動拖曳。對齊 dnd-kit「activator node 排除互動 descendant」idiom。
619
+ const rawListeners = draggable.listeners as Record<string, ((e: React.SyntheticEvent) => void) | undefined> | undefined
620
+ const guardedListeners: Record<string, unknown> | undefined = rawListeners
621
+ ? {
622
+ ...rawListeners,
623
+ onKeyDown: (e: React.KeyboardEvent) => {
624
+ const target = e.target as HTMLElement
625
+ if (
626
+ target !== e.currentTarget &&
627
+ target.closest('button, a, input, select, textarea, [role="menuitem"], [role="separator"]')
628
+ ) {
629
+ return
630
+ }
631
+ rawListeners.onKeyDown?.(e)
632
+ },
633
+ }
634
+ : rawListeners
549
635
  return React.cloneElement(children as React.ReactElement<Record<string, unknown>>, {
550
636
  ref: setRefs,
551
637
  style: { ...(childProps.style ?? {}), ...dragStyle },
552
638
  'data-column-id': id,
553
639
  'data-column-locked': isLocked || undefined,
554
- ...(disabled ? {} : { ...draggableAttrs, ...(draggable.listeners as unknown as Record<string, unknown>) }),
640
+ ...(disabled ? {} : { ...draggableAttrs, ...(guardedListeners ?? {}) }),
555
641
  // 2026-05-06 v14.9 cursor canonical(對齊 Notion / Jira):
556
642
  // **idle hover NOT 顯 cursor-grab** — header click 觸發 sort,grab cursor 會誤導 user 以為「點 = 拖」;
557
643
  // **drag activation 後**(isDragging=true,過 8px activationConstraint)才顯 cursor-grabbing。
@@ -562,8 +648,9 @@ function DraggableHeaderCell({
562
648
 
563
649
  /** Row drag handle — Portal-rendered, position:fixed 真正水平置中於 table outer border line(Jira canonical)。
564
650
  *
565
- * v15.2 重構:**Button 純視覺 affordance**,不再 spread drag listeners — 改由 row div 整列接 listeners
566
- * (TreeView SSOT)。Button 只負責顯示「此 row 可拖」的視覺暗示。
651
+ * v15.6 button-only drag(推翻 v15.2「整列接 listeners」,2026-07-14 JSDoc 對齊):Button =
652
+ * 唯一 activator,接 handleSetActivatorNodeRef + handleListeners(SourceRowProvider ctx);
653
+ * row div 不接 listeners(rowListeners=undefined),row click 保留給 select / open detail 等 UX。
567
654
  *
568
655
  * Why Portal + position:fixed(2026-05-05 v4):
569
656
  * DataTable 結構含三層 overflow-hidden(outer wrapper / leftBody / row),用 absolute + translate-x:-50%
@@ -604,11 +691,16 @@ function RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDrag
604
691
  // v15.1:drag 期間 source button hide(visible 邏輯已 guard isDragging),
605
692
  // 此處只報「真實 hover」狀態,不疊 isDragging mask。
606
693
  const rowHovered = rowEl.hasAttribute('data-hovered')
607
- setPos({
608
- top: rRect.top + rRect.height / 2,
609
- left: tRect.left, // table outer 左 border line position(viewport coords)
610
- rowHovered,
611
- })
694
+ const top = rRect.top + rRect.height / 2
695
+ const left = tRect.left // table outer 左 border line position(viewport coords)
696
+ // 2026-07-05 D3 perf fix:prev 值比對 — 位置/hover 沒變時回傳 prev reference,
697
+ // React Object.is bail out(原每 scroll frame 無條件新 object → 每個 visible handle
698
+ // 每 frame 必 re-render Button + Tooltip + portal,即使位置根本沒動)。
699
+ setPos((prev) =>
700
+ prev && prev.top === top && prev.left === left && prev.rowHovered === rowHovered
701
+ ? prev
702
+ : { top, left, rowHovered },
703
+ )
612
704
  }
613
705
 
614
706
  update()
@@ -623,6 +715,11 @@ function RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDrag
623
715
  // useOverflowCount fix `combobox.tsx:130`)。
624
716
  let scrollRafId = 0
625
717
  const onScroll = () => {
718
+ // D3 NO-SAMPLE audit(2026-08-02):non-hovered virtual rows still share the window
719
+ // listener, but their hidden handles do not need rect reads. Without this guard a
720
+ // 50-row virtual window scheduled 50 rAF callbacks + getBoundingClientRect calls
721
+ // for every scroll frame even though only one handle can be visible.
722
+ if (!rowEl.hasAttribute('data-hovered') && !buttonHovered && !ctx.isDragging) return
626
723
  if (scrollRafId) cancelAnimationFrame(scrollRafId)
627
724
  scrollRafId = requestAnimationFrame(() => {
628
725
  scrollRafId = 0
@@ -638,7 +735,7 @@ function RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDrag
638
735
  window.removeEventListener('scroll', onScroll, true)
639
736
  window.removeEventListener('resize', onScroll)
640
737
  }
641
- }, [rowEl, ctx])
738
+ }, [rowEl, ctx, buttonHovered])
642
739
 
643
740
  // 永遠 render anchor span(讓 anchorRef 可拿到 row element)。
644
741
  // A3 fix(2026-05-05):顯式 `top:0 left:0 pointer-events:none` — 雖 width/height=0 不該佔
@@ -694,13 +791,13 @@ function RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDrag
694
791
  // 2026-05-12 fix v2(user 抓「drag column sort 啟用時 button 不是 disable 視覺」):
695
792
  // 前 Round 4.5 加 `aria-disabled:opacity-[var(--opacity-disabled)]` 在 Button cva
696
793
  // 沒生效 — 因為 inline style `opacity` 永遠 win over Tailwind class。Fix:把 disabled
697
- // state opacity 也 compute 進 inline style。priority order:invisible 0 → drag 0.5 →
698
- // canDrag=false(sort active)disabled visual var(--opacity-disabled) 0.45 → idle 1。
794
+ // state opacity 也 compute 進 inline style。priority order:invisible 0 → drag var(--opacity-disabled)
795
+ // 0.45(2026-07-04 修:原硬寫 0.5 違 lib/drag-visual.ts SSOT)→ canDrag=false(sort active)
796
+ // disabled visual var(--opacity-disabled) 0.45 → idle 1。
699
797
  opacity: visible
700
- ? (ctx.isDragging ? 0.5 : (canDrag ? 1 : 'var(--opacity-disabled)' as unknown as number))
798
+ ? (ctx.isDragging ? 'var(--opacity-disabled)' as unknown as number : (canDrag ? 1 : 'var(--opacity-disabled)' as unknown as number))
701
799
  : 0,
702
800
  pointerEvents: visible ? 'auto' : 'none',
703
- transition: 'opacity 150ms ease',
704
801
  }}
705
802
  className={cn(
706
803
  // 2026-05-12 debug fix(user 抓「hover 還是透明」)— Round 4.5 我未授權加
@@ -712,6 +809,7 @@ function RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDrag
712
809
  // row 任何 state 視覺都有 token-level 對比(在 token 差異存在的 mode;light mode --surface-raised
713
810
  // 等於 --surface 是 design token semantic,非本 fix scope)。
714
811
  'bg-surface-raised hover:bg-surface-raised aria-disabled:bg-surface-raised',
812
+ 'transition-opacity duration-150 ease-in-out motion-reduce:duration-0',
715
813
  canDrag && !showInvalid && 'cursor-grab',
716
814
  canDrag && showInvalid && 'cursor-not-allowed !text-error !border-error',
717
815
  // drag 進行中 source button cursor(opacity 0.5 via style;aria-disabled visual 由 Button cva 接管)
@@ -738,25 +836,80 @@ function RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDrag
738
836
  }
739
837
 
740
838
  // ══════════════════════════════════════════════════════════════════════════════
741
- // AG Grid 模式:header 在 scroll 外面,body 是唯一的垂直 scroll container。
839
+ // AG Grid 模式:header 在 scroll 外面,V scroll 在 center-body(AR44 後現況)。
742
840
  //
743
841
  // table
744
842
  // ├── header(固定頂部,不在 scroll 內)
745
843
  // │ ├── left-header
746
844
  // │ ├── center-header(overflow:hidden,JS sync scrollLeft)
747
845
  // │ └── right-header
748
- // └── body-viewport(overflow-y:auto,display:flex)
749
- // ├── left-body(overflow:hidden)
750
- // ├── center-body(overflow-x:auto, overflow-y:hidden)
751
- // └── right-body(overflow:hidden)
846
+ // └── body-viewport(display:flex,無 overflow — AR44 後不再是 scroll container)
847
+ // ├── left-body(overflow:hidden,JS sync scrollTop)
848
+ // ├── center-body(overflow-x:auto, overflow-y:auto — 唯一 V scroll,
849
+ // │ onCenterBodyScroll 同步兩側 scrollTop + header scrollLeft)
850
+ // └── right-body(overflow:hidden,JS sync scrollTop)
752
851
  //
753
- // 不用 CSS sticky。Header 永遠在頂部。
852
+ // 不用 CSS sticky。Header 永遠在頂部。細節見下方「JS scroll sync(AR44)」註解。
754
853
  // ══════════════════════════════════════════════════════════════════════════════
755
854
 
855
+ // ── MemoCellSlot(2026-07-05 D3 perf fix)────────────────────────────────────
856
+ // cell-registry 2026-05-13 已把每個 cell type 包成 module-level cached `React.memo(CellWithSurface)`,
857
+ // 但 renderCellContent 每次 render 傳 3 個全新 inline closure(onCommit / onCommitLive /
858
+ // onRequestEdit)+ `meta ?? {}` 新 object → memo shallow-compare 100% fail,防線靜默失效
859
+ // (DataTableInner 任何 re-render — scroll / resize / drag / spreadsheet 選取 / portal keystroke —
860
+ // 都讓全部 visible cells 的 Field view subtree 整棵重渲)。
861
+ // Fix:中介 memo slot — 從 parent 接 stable callback(commitCell / cancelCellEdit / onCellCommit /
862
+ // enterCellEdit)+ primitive rowId / colId,在 slot 內 useCallback 綁 per-cell closure;
863
+ // props 全 primitive / stable reference → memo 真命中,unchanged cells render 成本歸零。
864
+ // Cite world-class:AG Grid「cell renderer stable reference」/ MUI X DataGrid memoized subcomponents。
865
+ const EMPTY_META: Record<string, unknown> = {}
866
+
867
+ interface MemoCellSlotProps {
868
+ Cell: React.ComponentType<CellComponentProps>
869
+ rowId: string
870
+ colId: string
871
+ // any-allow: free-form column value(consumer-defined,同 CellComponentProps.value)
872
+ value: any
873
+ // any-allow: free-form consumer meta bag(同 CellComponentProps.meta)
874
+ meta: Record<string, any>
875
+ mode: 'view' | 'edit'
876
+ size: 'sm' | 'md' | 'lg'
877
+ autoRowHeight: boolean
878
+ isEditable: boolean
879
+ onCommitCell: (rowId: string, colId: string, next: unknown) => void
880
+ onCancelCell: (rowId: string, colId: string) => void
881
+ onCellCommitLive?: (rowId: string, colId: string, next: unknown) => void
882
+ onEnterEdit: (rowId: string, colId: string) => void
883
+ }
884
+
885
+ const MemoCellSlot = React.memo(function MemoCellSlot({
886
+ Cell, rowId, colId, value, meta, mode, size, autoRowHeight,
887
+ isEditable, onCommitCell, onCancelCell, onCellCommitLive, onEnterEdit,
888
+ }: MemoCellSlotProps) {
889
+ const onCommit = React.useCallback((next: unknown) => onCommitCell(rowId, colId, next), [onCommitCell, rowId, colId])
890
+ const onCommitLive = React.useCallback((next: unknown) => onCellCommitLive?.(rowId, colId, next), [onCellCommitLive, rowId, colId])
891
+ const onCancel = React.useCallback(() => onCancelCell(rowId, colId), [onCancelCell, rowId, colId])
892
+ const onRequestEdit = React.useCallback(() => onEnterEdit(rowId, colId), [onEnterEdit, rowId, colId])
893
+ return (
894
+ <Cell
895
+ value={value}
896
+ meta={meta}
897
+ mode={mode}
898
+ size={size}
899
+ autoRowHeight={autoRowHeight}
900
+ isEditable={isEditable}
901
+ onCommit={onCommit}
902
+ onCommitLive={onCommitLive}
903
+ onCancel={onCancel}
904
+ onRequestEdit={onRequestEdit}
905
+ />
906
+ )
907
+ })
908
+
756
909
  // code-quality-allow: long-function — foundational composite main body — 拆 sub-fn 會複雜化 local state / ref / context binding
757
910
  function DataTableInner<TData>(
758
911
  {
759
- columns, data, size = 'md', autoRowHeight = false, height = '400px',
912
+ columns, data, size = 'md', autoRowHeight = false, height: heightProp,
760
913
  overscan = 5, emptyState, enableHover = true, bordered,
761
914
  estimateRowHeight, tableOptions, rowActions, cellErrors,
762
915
  pinnedLeftColumns, pinnedRightColumns, inlineEdit = false,
@@ -776,22 +929,25 @@ function DataTableInner<TData>(
776
929
  experimentalSpreadsheetOverlay = false,
777
930
  experimentalActiveEditorController = false,
778
931
  spreadsheetMode = false,
932
+ pagination,
779
933
  className, ...props
780
934
  }: DataTableProps<TData>,
781
935
  ref: React.ForwardedRef<HTMLDivElement>
782
936
  ) {
937
+ // L5 分頁 × height 預設(2026-07-06):未顯式傳 height 時 —— 分頁 = 'auto' 自然高度
938
+ // (頁碼是唯一導覽通道,不疊 body 內捲動;Ant Table 無預設高度罩慣例),
939
+ // 未分頁 = 既有 '400px' 預設不變。顯式傳 height 一律尊重(prop docblock 有完整規則)。
940
+ const height = heightProp ?? (pagination ? 'auto' : '400px')
783
941
  // ── L4 Inline edit state ──
784
942
  // editingCellId: `${rowId}__${columnId}` 標識當前進 edit mode 的 cell;null = 無
785
943
  const [editingCellId, setEditingCellId] = React.useState<string | null>(null)
786
944
  // Phase 7 D.3 portal Field virtualizer unmount preserve draft(2026-05-10 per codex Q-B4 verdict):
787
945
  // Lifted draft state in DataTable — Cell DOM unmount(virtualizer scroll out)時 draft 不丟,
788
946
  // mount-back 時 portal Field value=draft 而非 row.value,user 編輯中字保留。
789
- // editingCellId 變時 useEffect reset draft 到新 cell row.value(全新 edit session)。
947
+ // draft 生命週期(2026-07-05 D4 fix):cancelCellEdit / commitCell 清 draft;Tab 換格
948
+ // (handleEditTab)先 commit 當前 draft 再換格 — 原註解宣稱「editingCellId 變時 useEffect
949
+ // reset draft」的 effect 從未存在,曾致 Tab 換格後下一格顯示上一格草稿。
790
950
  const [editingDraft, setEditingDraft] = React.useState<unknown>(undefined)
791
- const exitEdit = React.useCallback(() => {
792
- setEditingCellId(null)
793
- setEditingDraft(undefined)
794
- }, [])
795
951
 
796
952
  // ── Slice D Step 4 spreadsheet semantics state(2026-05-10) ──
797
953
  // selectedCellId:`${rowId}:${colId}` Excel-like 選取(click 1)
@@ -820,14 +976,44 @@ function DataTableInner<TData>(
820
976
  document.addEventListener('pointerdown', handler, true)
821
977
  return () => document.removeEventListener('pointerdown', handler, true)
822
978
  }, [spreadsheetMode, selectedCellId, rangeAnchor])
979
+ // 2026-07-05 D4 fix:edit 退出(commit / cancel)後還原 spreadsheet selection 到該 cell +
980
+ // 收回焦點到 table root — 原本只清 editingCellId,editor unmount 後 document.activeElement
981
+ // 掉到 body、selection 不還原 → 每次編輯後鍵盤導覽死巷(方向鍵全滅、必須滑鼠重點),違反
982
+ // datatable-spreadsheet-rfc.md Contract 11「退出後還給 active cell」(對齊 Excel / AG Grid / Sheets)。
983
+ const restoreCellSelection = React.useCallback((rowId: string, colId: string) => {
984
+ if (!spreadsheetMode) return
985
+ const cellId = `${rowId}:${colId}`
986
+ setSelectedCellId(cellId)
987
+ setRangeAnchor(cellId)
988
+ setRangeFocus(null)
989
+ // 等 editor unmount 完成後才收回焦點;activeElement 非 body(user 點了其他 focusable /
990
+ // Tab 換格後下一格 editor autoFocus)時不搶焦點。
991
+ requestAnimationFrame(() => {
992
+ const el = tableRef.current
993
+ if (!el) return
994
+ const active = document.activeElement
995
+ if (active === document.body || active === null) el.focus({ preventScroll: true })
996
+ })
997
+ }, [spreadsheetMode])
823
998
  const commitCell = React.useCallback(
824
999
  (rowId: string, colId: string, next: unknown) => {
825
1000
  onCellCommit?.(rowId, colId, next)
826
1001
  setEditingCellId(null)
827
1002
  setEditingDraft(undefined) // Phase 7:commit 後清 draft
1003
+ restoreCellSelection(rowId, colId) // 2026-07-05 D4:commit 後 selection 還原(Contract 11)
828
1004
  },
829
- [onCellCommit],
1005
+ [onCellCommit, restoreCellSelection],
830
1006
  )
1007
+ // cancel 路徑(Esc / popover dismiss)— 同 commit 還原 selection;取代舊無參數 exitEdit
1008
+ const cancelCellEdit = React.useCallback((rowId: string, colId: string) => {
1009
+ setEditingCellId(null)
1010
+ setEditingDraft(undefined)
1011
+ restoreCellSelection(rowId, colId)
1012
+ }, [restoreCellSelection])
1013
+ // edit 進入點(MemoCellSlot onEnterEdit 消費;stable identity 維持 memo 命中)
1014
+ const enterCellEdit = React.useCallback((rowId: string, colId: string) => {
1015
+ setEditingCellId(cellEditId(rowId, colId))
1016
+ }, [])
831
1017
  // 判 column meta.editable 對特定 row 是否成立(支援 fn)
832
1018
  // column meta 是 free-form consumer bag(同 renderTypedValue any policy),不適合窄型化
833
1019
  const isCellEditable = React.useCallback(
@@ -839,28 +1025,13 @@ function DataTableInner<TData>(
839
1025
  },
840
1026
  [],
841
1027
  )
842
- // 2026-05-13 Stream C Cluster B Q3 ship(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):
843
- // Mirror isCellEditable pattern。`column.meta.disabled` 接 bool 或 (row) => boolean fn。
844
- // cell disabled → (a) TD 加 `bg-disabled cursor-not-allowed` + 抑制 hover, (b) inner Field
845
- // 透過 isDisabled prop 走 mode='disabled'(各 Field type 內部具體 disabled token,非 wrapper blanket opacity),
846
- // (c) edit entry condition: `cellEditable && !cellDisabled`。
847
- const isCellDisabled = React.useCallback(
848
- // any-allow: free-form consumer meta — same rationale as L143 renderTypedValue
849
- (meta: Record<string, any> | undefined, row: unknown): boolean => {
850
- const d = meta?.disabled
851
- if (typeof d === 'function') return d(row) === true
852
- return d === true
853
- },
854
- [],
855
- )
856
- // 2026-05-13:canEditCell helper consolidation(per codex V4 follow-up + user「沒理由不做」拍板)
857
- // 抽 4-site repeated `editable && !disabled` pattern。3 path sites(keyboard / Tab / InteractionLayer)
858
- // call canEditCell;另 2 sites(renderCellContent + onEditableCellClick)用 already-computed `editable`/
859
- // `disabled` 變數(因為 disabled 還要單獨給 isDisabled prop + bg-disabled class),不 collapse to helper。
1028
+ // 2026-07-16 round16:cell「disabled」態廢除(世界級 grid 無 disabled cell;meta.disabled 全庫 0 消費)。
1029
+ // 鎖定 cell = `editable:(row)=>false`(= isCellEditable 模型),非灰化 disabled 態。原 isCellDisabled
1030
+ // helper + bg-disabled TD 灰化 + isDisabled prop 全移除;canEditCell 收斂為 isCellEditable。
860
1031
  const canEditCell = React.useCallback(
861
1032
  (meta: Record<string, unknown> | undefined, row: unknown): boolean =>
862
- isCellEditable(meta, row) && !isCellDisabled(meta, row),
863
- [isCellEditable, isCellDisabled],
1033
+ isCellEditable(meta, row),
1034
+ [isCellEditable],
864
1035
  )
865
1036
  const [sorting, setSorting] = React.useState<SortingState>(tableOptions?.state?.sorting as SortingState ?? [])
866
1037
 
@@ -874,9 +1045,9 @@ function DataTableInner<TData>(
874
1045
  // ── L2 Selection state ──
875
1046
  const enabled = selectable !== false
876
1047
  const mode = selectable === 'single' ? 'single' : 'multi'
877
- const [selection, setSelection] = useControllable<string[]>({
878
- value: selectionProp,
879
- defaultValue: defaultSelection ?? [],
1048
+ const [selection, setSelection] = useControllable<DataTableSelection>({
1049
+ value: normalizeSelection(selectionProp),
1050
+ defaultValue: normalizeSelection(defaultSelection) ?? { mode: 'include', ids: [] },
880
1051
  onChange: onSelectionChange,
881
1052
  })
882
1053
  // Shift-click anchor:存最後一次「單擊」的 row id,shift-click 時做區間選
@@ -942,6 +1113,20 @@ function DataTableInner<TData>(
942
1113
  // 注意:`...tableOptions` 必 spread 在 `state` 前,否則 user 傳的 tableOptions 會
943
1114
  // 整個 override 掉我們組的 state(含 __select__ 自動 pinning + columnOrder 注入)。
944
1115
  // 之前 bug:checkbox column 跑到右邊 = 此處 spread 順序錯。
1116
+ // ── L5 分頁 state(2026-07-06)──────────────────────────────────────────────
1117
+ // 共用模式(user 拍板):<Pagination> 獨立元件為頁碼視覺 SSOT,DataTable 內建接 TanStack
1118
+ // 分頁模型消費它(Ant Table 消費 Pagination / Atlassian DynamicTable rowsPerPage / MUI
1119
+ // DataGrid 同派;shadcn data-table 教學同款「分頁 render 在元件 JSX 內」)。
1120
+ const paginationEnabled = !!pagination
1121
+ const paginationOpts = typeof pagination === 'object' ? pagination : undefined
1122
+ const [pageSizeState, setPageSizeState] = React.useState(paginationOpts?.pageSize ?? 20)
1123
+ // 1-based 對外(對齊 Pagination / Ant);餵 TanStack state 時換算 0-based
1124
+ const [currentPage, setCurrentPage] = useControllable<number>({
1125
+ value: paginationOpts?.page,
1126
+ defaultValue: paginationOpts?.defaultPage ?? 1,
1127
+ onChange: paginationOpts?.onPageChange,
1128
+ })
1129
+
945
1130
  const table = useReactTable({
946
1131
  ...tableOptions,
947
1132
  data, columns: columnsWithSelection,
@@ -951,6 +1136,9 @@ function DataTableInner<TData>(
951
1136
  // columnPinning + columnOrder 在 user state 後 override,確保 __select__ 永遠左
952
1137
  columnPinning: { left: effectivePinnedLeft, right: pinnedRightColumns ?? [] },
953
1138
  ...(effectiveColumnOrder ? { columnOrder: effectiveColumnOrder } : {}),
1139
+ // L5 分頁:必在 ...tableOptions?.state 之後 spread(同 columnPinning override 理由——
1140
+ // 防 user state 蓋掉內建接線);頁碼變更由 <Pagination onPageChange> 驅動,不走 TanStack 內部 setter
1141
+ ...(paginationEnabled ? { pagination: { pageIndex: currentPage - 1, pageSize: pageSizeState } } : {}),
954
1142
  },
955
1143
  enableMultiSort,
956
1144
  // **#1 fix(2026-05-04)**:chain user `tableOptions.onSortingChange`(spread 在前被 override = 之前 bug)
@@ -968,6 +1156,8 @@ function DataTableInner<TData>(
968
1156
  getSortedRowModel: getSortedRowModel(),
969
1157
  // L4 nested rows:啟用 expanded row model(consumer 透過 tableOptions.getSubRows + state.expanded forward)
970
1158
  getExpandedRowModel: getExpandedRowModel(),
1159
+ // L5 分頁:條件掛載(TanStack 官方:pagination 與 virtualization 為互斥替代策略)
1160
+ ...(paginationEnabled ? { getPaginationRowModel: getPaginationRowModel() } : {}),
971
1161
  getRowId: getRowId,
972
1162
  // 2026-05-06 v14 column resize:`onChange` mode → drag 中 column 即時跟動 cursor(world-class
973
1163
  // canonical:TanStack docs / AG Grid / Excel / Google Sheets 全部 live resize)。前 v13.2
@@ -982,10 +1172,20 @@ function DataTableInner<TData>(
982
1172
  })
983
1173
 
984
1174
  // v13.2:onColumnResize callback 透過 useEffect 觀測 columnSizing state 變動 fire(uncontrolled state pattern)
1175
+ // 2026-07-06 D3 fix:兌現 prop docblock「commit-on-pointerup,非 live」契約 —
1176
+ // columnResizeMode:'onChange' 讓 drag 中 columnSizing 每 mousemove 變一次(視覺即時跟動,
1177
+ // 保留),原 effect 無 gate → callback 每 mousemove fire 一次;docblock 明文建議 consumer
1178
+ // 在此 callback 做 width persistence(localStorage / URL / API)= 每 mousemove I/O。
1179
+ // 改以 TanStack columnSizingInfo.isResizingColumn 為訊號:drag 進行中不 fire、也不推進
1180
+ // snapshot(保留 drag 前基準);pointerup(isResizingColumn 轉 false)才 diff snapshot,
1181
+ // fire 一次最終寬度。非 drag 路徑(「自動調整寬度」menu 的 setColumnSizing)不經
1182
+ // isResizingColumn,行為不變。
985
1183
  const columnSizingState = table.getState().columnSizing
1184
+ const isResizingColumn = table.getState().columnSizingInfo.isResizingColumn
986
1185
  const prevColumnSizingRef = React.useRef(columnSizingState)
987
1186
  React.useEffect(() => {
988
1187
  if (!onColumnResize) return
1188
+ if (isResizingColumn) return
989
1189
  const prev = prevColumnSizingRef.current
990
1190
  Object.keys(columnSizingState).forEach(id => {
991
1191
  if (columnSizingState[id] !== prev[id]) {
@@ -993,10 +1193,17 @@ function DataTableInner<TData>(
993
1193
  }
994
1194
  })
995
1195
  prevColumnSizingRef.current = columnSizingState
996
- }, [columnSizingState, onColumnResize])
1196
+ }, [columnSizingState, isResizingColumn, onColumnResize])
997
1197
 
998
1198
  const { rows } = table.getRowModel()
999
1199
  const isEmpty = rows.length === 0
1200
+
1201
+ // L5 分頁:filter / data 縮小時 TanStack 不自動 clamp 當前頁(會停在空頁);對齊 MUI X 自動 clamp
1202
+ const pageCount = paginationEnabled ? table.getPageCount() : 0
1203
+ React.useEffect(() => {
1204
+ if (!paginationEnabled) return
1205
+ if (pageCount > 0 && currentPage > pageCount) setCurrentPage(pageCount)
1206
+ }, [paginationEnabled, pageCount, currentPage, setCurrentPage])
1000
1207
  const hasHeightConstraint = height !== 'auto'
1001
1208
  // Fill-parent mode:height='100%' / '100vh' / 'fill' 等百分比 / 視口語義 → outer flex column + body flex-1 撐滿。
1002
1209
  // 固定 px/rem 仍維持 maxHeight cap 行為(資料少 = 內容高度,資料多 = 上限後 scroll)— 對齊既有 stories 預期。
@@ -1008,7 +1215,8 @@ function DataTableInner<TData>(
1008
1215
  // direct render 完全 bypass 此 race,且小資料下虛擬化沒效益(浪費 reflow)。
1009
1216
  // 對齊 AG Grid `suppressVirtualization` / TanStack Table virtualization-when-needed idiom。
1010
1217
  const VIRTUAL_THRESHOLD = 30
1011
- const useVirtual = hasHeightConstraint && !isEmpty && rows.length > VIRTUAL_THRESHOLD
1218
+ // L5 分頁互斥:分頁後每頁 rows ≤ pageSize,虛擬化無效益(TanStack 官方:兩者為互斥替代策略)
1219
+ const useVirtual = !paginationEnabled && hasHeightConstraint && !isEmpty && rows.length > VIRTUAL_THRESHOLD
1012
1220
  const hasRowActions = !!rowActions
1013
1221
 
1014
1222
  // Refs
@@ -1029,7 +1237,7 @@ function DataTableInner<TData>(
1029
1237
  // 2026-05-06 v10 DragOverlay canonical:retire windowed sticky range extractor (v4-v9 workaround)。
1030
1238
  // 改用 `<DragOverlay>` portal 把 source row 視覺解耦 — source 即使 unmount(virtual scroll out)
1031
1239
  // overlay 仍 render 由 cloned outerHTML 提供視覺。dnd-kit transform / collision 走 active item id
1032
- // (id 永遠在 SortableContext.items 集合,跟 hook instance mount 狀態無關)。
1240
+ // (DndContext store 以 active id 追蹤,跟 hook instance mount 狀態無關;v15 無 SortableContext)。
1033
1241
  // 對齊 dnd-kit GitHub #1674 + drag-overlay docs canonical「virtualized list MUST use DragOverlay」。
1034
1242
  // overscan 仍輕微拉高(避免 source row 旁邊 rows 也 unmount 致使 hover signal 計算抖動)。
1035
1243
  const effectiveOverscan = enableRowDrag ? Math.max(overscan, 5) : overscan
@@ -1060,6 +1268,8 @@ function DataTableInner<TData>(
1060
1268
  // 後續 measureElement 修正到 6×40 = 240,差 24px 視覺看起來像「table 慢慢長高」。fix = estimate
1061
1269
  // 預設 size-aware 對齊 token(見下方 estimateRowHeight default 計算)。
1062
1270
  const [bodyMaxHeight, setBodyMaxHeight] = React.useState<number | null>(null)
1271
+ // L5 分頁 × isFillHeight(2026-07-07 C12):bar 高度量測用 — compute() 需扣分頁列 footprint
1272
+ const paginationBarRef = React.useRef<HTMLDivElement | null>(null)
1063
1273
  React.useLayoutEffect(() => {
1064
1274
  if (!isFillHeight) { setBodyMaxHeight(null); return }
1065
1275
  // **R4 真根因 fix(2026-05-09 v2 — codex Q3.6 root cause + Q3.9 reproduce verified)**:
@@ -1102,7 +1312,15 @@ function DataTableInner<TData>(
1102
1312
  ?? tableRef.current.getBoundingClientRect().height
1103
1313
  const headerEl = tableRef.current.firstElementChild as HTMLElement | null
1104
1314
  const headerH = headerEl?.getBoundingClientRect().height ?? 0
1105
- const next = Math.max(0, slotH - headerH)
1315
+ // L5 分頁 × isFillHeight(2026-07-07 C12):啟用分頁時 parent slot = composedContent
1316
+ // wrapper(含分頁列 + tight gap),body 可用高必扣分頁列 footprint,否則 body 撐滿
1317
+ // 把分頁列擠出 / 被 overflow 裁掉
1318
+ const barEl = paginationBarRef.current
1319
+ const barFootprint = barEl
1320
+ ? barEl.getBoundingClientRect().height +
1321
+ (parseFloat(getComputedStyle(barEl.parentElement as Element).rowGap) || 0)
1322
+ : 0
1323
+ const next = Math.max(0, slotH - headerH - barFootprint)
1106
1324
  // Diff guard < 4px(濾 micro-step,real resize δ 必 ≫ 4px)
1107
1325
  if (lastValue != null && Math.abs(next - lastValue) < 4) return
1108
1326
  lastValue = next
@@ -1149,10 +1367,9 @@ function DataTableInner<TData>(
1149
1367
 
1150
1368
  // ── Phase 9 Issue 1 fix(2026-05-10):range cells lifted compute + Set ────
1151
1369
  // 計算 spreadsheet range cell IDs(Shift+click rectangle from anchor↔focus),
1152
- // 提供:
1153
- // 1. `rangeCellIds` array → pass to layer for outer ring 4 line div boundary
1154
- // 2. `rangeCellIdSet` Set → cell wrapper data-range-cell attr for cell-bg fill
1155
- // (per codex Q1 verdict:bg fill 移到 cell bg layer 不在 overlay,內容才不被蓋)
1370
+ // 提供 `rangeCellIdSet` Set → cell wrapper data-range-cell attr for cell-bg fill
1371
+ // (per codex Q1 verdict:bg fill 走 cell bg layer 不在 overlay,內容才不被蓋;
1372
+ // layer 的 outer ring / rangeCellIds prop 已 retire — 2026-07-14 對齊清理)
1156
1373
  const rangeCellIds = React.useMemo<string[] | undefined>(() => {
1157
1374
  if (!spreadsheetMode || !rangeAnchor || !rangeFocus || rangeAnchor === rangeFocus) return undefined
1158
1375
  const parseCell = (id: string) => {
@@ -1209,7 +1426,13 @@ function DataTableInner<TData>(
1209
1426
  return () => obs.disconnect()
1210
1427
  }, [hasLeft, hasRight, rows.length])
1211
1428
 
1212
- const rowHeight = `h-table-row-${size}`
1429
+ // 2026-07-09 root-cause fix(user 以 GitHub Pages 對比抓出 regression):
1430
+ // 舊 `h-table-row-${size}` 模板字串 Tailwind **靜態掃描看不到** → `.h-table-row-{sm,md,lg}` 規則
1431
+ // 唯一靠 uiSize.spec.md 裡的 literal 被 content-detection 掃到才生成;戰役期間掃描樹變動後未生成
1432
+ // → 規則消失 → row 塌成「內容高度」(非編輯 33px / 編輯 44px)而非固定 token 40px,連帶選取控件與
1433
+ // 列文字對不齊。改用 literal map(對齊 field-wrapper cva 的 `h-field-md` literal 慣例),Tailwind
1434
+ // 永遠掃得到、不再依賴脆弱的 spec.md literal → 永不再漂移。
1435
+ const rowHeight = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size] ?? 'h-table-row-md'
1213
1436
 
1214
1437
  // ── Cross-region row hover (2026-04-22 D3 perf audit):event delegation 改 per-row closure
1215
1438
  // 舊:每 row 建 `{ onMouseEnter, onMouseLeave }` + 2 arrow functions → 100 row = 200 closures/render
@@ -1249,56 +1472,58 @@ function DataTableInner<TData>(
1249
1472
  const hoverProps = (_idx: number): Record<string, never> => ({})
1250
1473
 
1251
1474
  // ── Cell render(Phase C 2026-05-05 — type-keyed registry SSOT)──
1252
- // 命中 columnType → 走 cellRegistry(display / edit mode 同元件 with `mode` prop);
1475
+ // 命中 columnType → 走 cellRegistry(view / edit mode 同元件 with `mode` prop);
1253
1476
  // 無 columnType → consumer 自訂 cell.columnDef.cell。
1254
1477
  const renderCellContent = (cell: ReturnType<typeof rows[number]['getVisibleCells']>[number]) => {
1255
1478
  const meta = cell.column.columnDef.meta
1256
1479
  const colType = meta?.type as ColumnType | undefined
1257
1480
  const wrap = autoRowHeight && meta?.wrap === true
1258
- // 已知 compound 欄位(Tag / PersonDisplay / LinkInput 等自帶 layout)直接 bypass TruncateCell,
1481
+ // 已知 compound 欄位(Tag / PersonDisplay / LinkInput 等自帶 layout)直接 bypass TruncatedText,
1259
1482
  // 因為 `truncate` 的 inline baseline context 會破壞自訂 layout 的垂直對齊。
1260
- // 2026-05-09 D-path:date / time 加入(showDisplayEndIcon → Field naked-display 需 full width 才能
1261
- // 右對齊 ItemSuffix。TruncateCell 的 `<span truncate min-w-0>` block-display 會 collapse Field
1483
+ // 2026-05-09 D-path:date / time 加入(showDisplayEndIcon → Field naked-view 需 full width 才能
1484
+ // 右對齊 ItemSuffix。TruncatedText 的 `<span truncate min-w-0>` block-display 會 collapse Field
1262
1485
  // to content size,讓 Calendar / Clock icon 緊貼 value text 而非右邊緣)。
1263
1486
  const isKnownCompound = colType === 'select' || colType === 'multiSelect' || colType === 'person' || colType === 'multiPerson' || colType === 'url' || colType === 'date' || colType === 'time'
1264
1487
  const rowId = cell.row.id
1265
1488
  const colId = cell.column.id
1266
1489
  const editable = isCellEditable(meta, cell.row.original)
1267
- const disabled = isCellDisabled(meta, cell.row.original)
1268
1490
  const isEditingThisCell = editingCellId === cellEditId(rowId, colId)
1269
1491
 
1270
1492
  let content: React.ReactNode
1271
1493
  if (colType) {
1272
1494
  const Cell = resolveCellComponent(colType)
1273
1495
  // 2026-05-10 Slice D Step 5(D.3 portal Field):當 portal flag 啟 + cell 編輯中 →
1274
- // cell 保持 display mode(SSOT preserved per codex Q6.2),portal layer 渲 edit Field 在上。
1275
- // 預設 inline-edit:isEditingThisCell ? edit : display。
1276
- // 2026-05-13 Q3 cell-disabled:disabled cell 永遠 display lifecycle(state overlay,不進 edit)。
1277
- const cellMode: 'edit' | 'display' =
1496
+ // cell 保持 view mode(SSOT preserved per codex Q6.2),portal layer 渲 edit Field 在上。
1497
+ // 預設 inline-edit:isEditingThisCell ? edit : view。
1498
+ const cellMode: 'edit' | 'view' =
1278
1499
  (experimentalActiveEditorController && isEditingThisCell)
1279
- ? 'display'
1280
- : (isEditingThisCell && !disabled) ? 'edit' : 'display'
1500
+ ? 'view'
1501
+ : isEditingThisCell ? 'edit' : 'view'
1502
+ // 2026-07-05 D3 perf fix:改經 MemoCellSlot — 原 inline closure props 讓 CellWithSurface
1503
+ // memo 100% miss(詳 MemoCellSlot 檔頭註解)。
1281
1504
  content = (
1282
- <Cell
1505
+ <MemoCellSlot
1506
+ Cell={Cell}
1507
+ rowId={rowId}
1508
+ colId={colId}
1283
1509
  value={cell.getValue()}
1284
- meta={meta ?? {}}
1510
+ meta={meta ?? EMPTY_META}
1285
1511
  mode={cellMode}
1286
1512
  size={size}
1287
1513
  autoRowHeight={autoRowHeight}
1288
1514
  isEditable={editable}
1289
- isDisabled={disabled}
1290
- onCommit={(next) => commitCell(rowId, colId, next)}
1291
- onCommitLive={(next) => onCellCommit?.(rowId, colId, next)}
1292
- onCancel={exitEdit}
1293
- onRequestEdit={() => !disabled && setEditingCellId(cellEditId(rowId, colId))}
1515
+ onCommitCell={commitCell}
1516
+ onCancelCell={cancelCellEdit}
1517
+ onCellCommitLive={onCellCommit}
1518
+ onEnterEdit={enterCellEdit}
1294
1519
  />
1295
1520
  )
1296
1521
  } else {
1297
1522
  content = flexRender(cell.column.columnDef.cell, cell.getContext())
1298
1523
  }
1299
1524
  // Consumer 自訂 cell(無 colType)若回傳 React element,視為 compound — consumer 自己處理
1300
- // 對齊與截斷。回傳 primitive(string / number)才走 TruncateCell。
1301
- // 理由:TruncateCell 的 `span.truncate` 強制 white-space:nowrap + inline baseline,
1525
+ // 對齊與截斷。回傳 primitive(string / number)才走 TruncatedText。
1526
+ // 理由:TruncatedText 的 `span.truncate` 強制 white-space:nowrap + inline baseline,
1302
1527
  // 對 inline-flex / icon+text 自訂結構會拉歪(見 circular-progress sync table 案例)。
1303
1528
  // **edit mode bypass**(2026-05-05 v9 Bug 2 修):editing cell 內部是 Field 控件
1304
1529
  // (Input/Textarea/Select etc.)自管 layout + 替代元素(textarea)不該被包進 inline span
@@ -1307,15 +1532,15 @@ function DataTableInner<TData>(
1307
1532
  return isEditingThisCell ? content
1308
1533
  : wrap ? <span className="break-words min-w-0">{content}</span>
1309
1534
  : (isKnownCompound || isConsumerCompound) ? content
1310
- : <TruncateCell>{content}</TruncateCell>
1535
+ : <TruncatedText>{content}</TruncatedText>
1311
1536
  }
1312
1537
 
1313
1538
  // 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)
1314
1539
  const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']
1315
1540
 
1316
1541
  // 2026-05-09 D-path retired:`getEditIndicator(colType)` parallel system 移除。
1317
- // Indicator authority 從 DataTable cellEl 移交 **Field naked-display branch via `showDisplayEndIcon` opt-in**
1318
- // — Select / TimePicker / DatePicker / Combobox / PeoplePicker 5 picker 的 display mode 內建
1542
+ // Indicator authority 從 DataTable cellEl 移交 **Field naked-view branch via `showDisplayEndIcon` opt-in**
1543
+ // — Select / TimePicker / DatePicker / Combobox / PeoplePicker 5 picker 的 view mode 內建
1319
1544
  // `<ItemSuffix>` 渲對應 trigger icon(同 edit DOM 結構)。LinkInput URL anchor 例外(無 suffix)。
1320
1545
  // SSOT chain:cell-registry.tsx(opt-in props)→ Field component(intrinsic icon + ItemSuffix DOM)→
1321
1546
  // item-anatomy ItemPrefix/ItemSuffix layout SSOT。詳 `.claude/planning/cell-indicator-ssot-rfc.md`。
@@ -1325,8 +1550,8 @@ function DataTableInner<TData>(
1325
1550
  const dragDisabled = sorting.length > 0
1326
1551
 
1327
1552
  // ── L4 Row drag v2:nested rows + parent map ─────────────────────────────────
1328
- // v2 cross-parent fix:全 row 進 SortableContext.items(含 sub-rows),custom collisionDetection
1329
- // 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
1553
+ // v2 cross-parent fix:全 row 各自掛 useDraggable/useDroppable(含 sub-rows;v15 無 SortableContext),
1554
+ // custom collisionDetection 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。
1330
1555
  // parentMap: rowId → parentId(top-level row 的 parent = '' 哨兵 string)
1331
1556
  const { allRowIds, parentMap } = React.useMemo(() => {
1332
1557
  const ids: string[] = []
@@ -1362,13 +1587,13 @@ function DataTableInner<TData>(
1362
1587
  const rowId = cell.row.id
1363
1588
  const rowOriginal = cell.row.original
1364
1589
  const isDisabled = isRowSelectable ? !isRowSelectable(rowOriginal) : false
1365
- const ariaLabel = getRowAriaLabel?.(rowOriginal) ?? 'Select row'
1590
+ const ariaLabel = getRowAriaLabel?.(rowOriginal) ?? '選取此列'
1366
1591
  const checkboxSize = size === 'lg' ? 'lg' : 'md'
1367
1592
  // Cell 整格可點:click cell padding 也觸發 toggle/select(對齊 Linear / Apple Mail / Material DataGrid)
1368
1593
  // 內部 checkbox/radio 用 stopPropagation 避免 double-fire
1369
1594
  const onCellClick = isDisabled ? undefined : (e: React.MouseEvent) => {
1370
1595
  e.stopPropagation()
1371
- if (mode === 'single') setSelection([rowId])
1596
+ if (mode === 'single') setSelection({ mode: 'include', ids: [rowId] })
1372
1597
  else toggleRow(rowId, rowOriginal, { shiftKey: e.shiftKey })
1373
1598
  }
1374
1599
  return (
@@ -1395,7 +1620,7 @@ function DataTableInner<TData>(
1395
1620
  ) : (
1396
1621
  <Checkbox
1397
1622
  size={checkboxSize}
1398
- checked={selectionSet.has(rowId)}
1623
+ checked={isSelectedId(rowId)}
1399
1624
  disabled={isDisabled}
1400
1625
  aria-label={ariaLabel}
1401
1626
  onClick={(e) => {
@@ -1423,17 +1648,15 @@ function DataTableInner<TData>(
1423
1648
  const cellRowId = cell.row.id
1424
1649
  const cellColId = cell.column.id
1425
1650
  const cellEditable = isCellEditable(meta, cell.row.original)
1426
- const cellDisabled = isCellDisabled(meta, cell.row.original)
1427
1651
  const isEditingThisCell = editingCellId === cellEditId(cellRowId, cellColId)
1428
- // Indicator canonical(2026-05-09 D-path retire):**Field naked-display branch own** via
1652
+ // Indicator canonical(2026-05-09 D-path retire):**Field naked-view branch own** via
1429
1653
  // `showDisplayEndIcon` opt-in(per-picker `<ItemSuffix>` 渲 ChevronDown/Calendar/Clock)。
1430
1654
  // DataTable cellEl 不再 render parallel indicator — SSOT 對齊 Field family。
1431
1655
  // 詳 `.claude/planning/cell-indicator-ssot-rfc.md` Step 9。
1432
1656
  // Cell click → 進 edit mode(boolean 不需 — 自己 toggle;url 不需 — 走內部 Pencil button,Phase C 由 UrlCell 內處理)
1433
1657
  const cellSpreadsheetId = `${cellRowId}:${cellColId}`
1434
1658
  const isSelectedCell = spreadsheetMode && selectedCellId === cellSpreadsheetId
1435
- // 2026-05-13 Q3:cellDisabled → 抑制 editable click(對齊 `editable && !disabled` invariant)
1436
- const onEditableCellClick = cellEditable && !cellDisabled && colType !== 'boolean' && colType !== 'url' && !isEditingThisCell
1659
+ const onEditableCellClick = cellEditable && colType !== 'boolean' && colType !== 'url' && !isEditingThisCell
1437
1660
  ? (e: React.MouseEvent) => {
1438
1661
  if (spreadsheetMode) {
1439
1662
  // Slice D Step 4 spreadsheet semantics(2026-05-10 user 拍板,2026-05-12 v2 fix):
@@ -1477,7 +1700,13 @@ function DataTableInner<TData>(
1477
1700
  const canExpand = cell.row.getCanExpand?.() ?? false
1478
1701
  const isExpanded = cell.row.getIsExpanded?.() ?? false
1479
1702
  const toggleExpand = cell.row.getToggleExpandedHandler?.()
1480
- const showNestedPrefix = isFirstContent && (depth > 0 || canExpand)
1703
+ // 2026-07-08 sibling-aware 佔位(WM root-cause 戰役):spec:382「同層 sibling 有 expandable
1704
+ // 時 leaf 也佔位」原本沒實作 — depth-0 leaf(無 children 的頂層列)拿不到 w-4+mr-2 佔位,
1705
+ // 與同層有 chevron 的列左緣錯位(PDF「chevron 空間」問題)。同層 = 同 parent 的 subRows;
1706
+ // 頂層 = core rows。只在 isFirstContent 時計算,成本一列一次。
1707
+ const siblingRows = cell.row.getParentRow?.()?.subRows ?? table.getCoreRowModel().rows
1708
+ const siblingHasExpand = isFirstContent && siblingRows.some((r) => r.getCanExpand?.() ?? false)
1709
+ const showNestedPrefix = isFirstContent && (depth > 0 || canExpand || siblingHasExpand)
1481
1710
  // Issue 9 cell error(2026-05-10):lookup `${rowId}:${colId}` in cellErrors map
1482
1711
  // editing cell 自動 clear visual error(per spec 「edit-clears-own-cell」)— consumer 走
1483
1712
  // onCellCommit 驗證後決定回填新 error(由 consumer 端控制 cellErrors map state)。
@@ -1503,7 +1732,7 @@ function DataTableInner<TData>(
1503
1732
  role="cell"
1504
1733
  // group/cell + data-row-mode:讓 Field naked 用 `group-data-[row-mode=...]/cell:items-X`
1505
1734
  // 從 cell 取 alignment(autoRowHeight=auto 頂對齊 / fixed=fixed 置中)。CSS propagation,
1506
- // Field API 不變;每個 mode 內 display↔edit 同 alignment(同 Field, 同 group → 同 items)。
1735
+ // Field API 不變;每個 mode 內 view↔edit 同 alignment(同 Field, 同 group → 同 items)。
1507
1736
  // H1(2026-05-10):per-row error → effectiveAutoRowForCell 同 row.tsx effectiveAutoRow
1508
1737
  data-row-mode={effectiveAutoRowForCell ? 'auto' : 'fixed'}
1509
1738
  data-column-id={cell.column.id}
@@ -1513,8 +1742,6 @@ function DataTableInner<TData>(
1513
1742
  // Phase 9 Issue 1 fix(2026-05-10):range cell bg fill via CSS [data-range-cell],
1514
1743
  // 不在 overlay layer(避免 layer fixed-position bg 蓋 cell content)。
1515
1744
  data-range-cell={spreadsheetMode && rangeCellIdSet.has(`${cell.row.id}:${cell.column.id}`) ? '' : undefined}
1516
- // 2026-05-13 V1.6:data-cell-disabled attribute 給 CSS `:not([data-cell-disabled])` 過濾,disabled cell 不被 range fill 蓋
1517
- data-cell-disabled={cellDisabled ? 'true' : undefined}
1518
1745
  // Issue 9 cell error(2026-05-10):aria-describedby 接 error message id 給 AT 讀
1519
1746
  aria-describedby={cellErrorId}
1520
1747
  aria-invalid={hasCellError || undefined}
@@ -1529,7 +1756,11 @@ function DataTableInner<TData>(
1529
1756
  // 「框框跟 cell 一樣大並取代 cell 的框且與 table 隔線無縫接軌」(2026-05-05)。
1530
1757
  // - **沒有** cell 自己 box-shadow ring — focus / hover / open ring 由 Field naked 自帶
1531
1758
  // state machine 提供(對齊 user「狀態樣式取決於原輸入框」reminder)
1532
- 'group/cell flex text-foreground text-body font-normal shrink-0 relative self-stretch',
1759
+ // 字級隨 size:sm/md text-body / lg text-body-lg(fieldDisplayTextClass),對齊 Field family
1760
+ // size→font SSOT。此為非-Field content(consumer 自訂 cell / TruncatedText 純文字)的 fallback 字級;
1761
+ // typed cell 各自的 Field 控件已自帶 size→font(cell-registry 傳 size)。
1762
+ 'group/cell flex text-foreground font-normal shrink-0 relative self-stretch',
1763
+ fieldDisplayTextClass(size),
1533
1764
  // Issue 9(2026-05-10):有 cell error → unset overflow-hidden 讓 error message
1534
1765
  // wrap 撐 row 高。**H1(2026-05-10)升級**:overflow-visible 條件改 `rowHasAnyError` —
1535
1766
  // row 內任一 cell 有 error 整 row 全 cells 都 overflow-visible(error 訊息可能多行
@@ -1541,22 +1772,24 @@ function DataTableInner<TData>(
1541
1772
  // Phase 9 Issue 8 fix(2026-05-10 user 撞 + codex 重比稿 verdict ADOPT):
1542
1773
  // 之前 `border-r border-divider` 只 right edge → hover overlay outline:-1px 只 right
1543
1774
  // 邊壓 cell border,上左下 sub-pixel 不一致(user 抓「右 1px / 上左下 2px」bug)。
1544
- // 改 `dtCellGrid` (data-table.css:96-110)用 `box-shadow: inset` 4 邊 1px divider,
1545
- // 不佔 layout(per user verbatim「在 cell 內容起始位置不變」前提)→ 4 邊一致 grid line
1546
- // → overlay outline:-1px 4 邊都剛好壓 cell border line。
1775
+ // 改 `dtCellGrid`(data-table.css「dtCellGrid v2/v3」段)box-shadow inset **只保右邊**
1776
+ // `inset -1px 0 0 var(--divider)`(bottom 由 row border-b 接管、:last-child 設 none 防 2px;
1777
+ // 2026-07-04 對齊 css 現況 — 原「4 邊 inset」敘述已被 v2/v3 取代),不佔 layout
1778
+ // (per user verbatim「在 cell 內容起始位置不變」前提)→ 視覺 4 邊 grid line 由
1779
+ // row border + 相鄰 cell 合成 → overlay outline:-1px 壓 cell border line。
1547
1780
  // Field naked edit border 仍 own(per Field SSOT)— 編輯時 Field 自帶 border 1px,
1548
1781
  // 跟 cell 4 邊 inset divider 視覺相疊(同 pixel)= 1 line visual,不雙線。
1549
1782
  inlineEdit && 'dtCellGrid',
1550
- onEditableCellClick && ['cursor-pointer', nakedCellEditableDisplayHover], // editable cell display hover affordance(對齊 Notion / Airtable hover-cell-shows-border canonical)
1551
- // 2026-05-13 Q3 cell disabled SSOT(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):
1552
- // bg `--bg-disabled` component-state token(color.spec.md:671 owner)+ cursor 抑制 click affordance。
1553
- cellDisabled && 'bg-disabled cursor-not-allowed',
1783
+ onEditableCellClick && ['cursor-pointer', nakedCellEditableDisplayHover], // editable cell view hover affordance(對齊 Notion / Airtable hover-cell-shows-border canonical)
1784
+ // a11y(2026-07-14 dim-10 修):非 spreadsheet inlineEdit cell 可 Tab 聚焦(見下方
1785
+ // tabIndex/onKeyDown)— focus-visible ring 對齊本檔 expand button / sortable header canonical。
1786
+ onEditableCellClick && !spreadsheetMode && 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset',
1554
1787
  // z-10 raise inline-edit cell;portal mode 不需(layer z-3 already on top)。
1555
1788
  isEditingThisCell && !experimentalActiveEditorController && 'z-10',
1556
1789
  )}
1557
1790
  style={{
1558
1791
  ...columnSizeStyle(cell.column, { resize: enableColumnResize, isSystemCol: isSystemColumn(cell.column.id) }),
1559
- // Padding override 只在 inline-edit cell(naked Field 撐滿 cell);portal mode cell 走正常 display padding
1792
+ // Padding override 只在 inline-edit cell(naked Field 撐滿 cell);portal mode cell 走正常 view padding
1560
1793
  ...(isEditingThisCell && !experimentalActiveEditorController ? {} : cellPadding),
1561
1794
  // Slice D Step 2(2026-05-10):flag 開時 set CSS variable 抑制 Field naked hover outline,
1562
1795
  // 讓 overlay layer 接管 hover ring paint(per RFC Contract 8 「one geometry owner, two paint owners」)。
@@ -1564,9 +1797,22 @@ function DataTableInner<TData>(
1564
1797
  ...(experimentalSpreadsheetOverlay && { '--cell-hover-outline-color': 'transparent' } as React.CSSProperties),
1565
1798
  }}
1566
1799
  onClick={onEditableCellClick}
1800
+ // a11y(2026-07-14 dim-10 修):非 spreadsheet 的 inlineEdit cell 原本只有 onClick —
1801
+ // 鍵盤 user 無法聚焦 cell、無法進入編輯(WCAG 2.1.1)。對齊 Atlassian InlineEdit
1802
+ // read-view-focusable idiom:editable view cell 可 Tab 聚焦,Enter / F2 進 edit。
1803
+ // spreadsheetMode 不加(該模式走 table-level selectedCellId 鍵盤導覽 SSOT,per-cell
1804
+ // tab stop 會跟 roving 模型衝突);cell 內 embedded 控件事件不攔(target guard)。
1805
+ tabIndex={onEditableCellClick && !spreadsheetMode ? 0 : undefined}
1806
+ onKeyDown={onEditableCellClick && !spreadsheetMode ? (e) => {
1807
+ if (e.target !== e.currentTarget) return
1808
+ if (e.key === 'Enter' || e.key === 'F2') {
1809
+ e.preventDefault()
1810
+ setEditingCellId(cellEditId(cellRowId, cellColId))
1811
+ }
1812
+ } : undefined}
1567
1813
  >
1568
1814
  {/* Issue 9 cell error(2026-05-10):有 error → cell 內外結構切 flex-col,
1569
- 上 row 渲既有 nested + content,下 row 渲 error message 14px text-error。
1815
+ 上 row 渲既有 nested + content,下 row 渲 error message `text-body text-error`。
1570
1816
  無 error 時走原 flex-row(backward-compat 0 layout shift)。 */}
1571
1817
  {hasCellError ? (
1572
1818
  <span className="flex flex-col self-stretch w-full min-w-0 gap-1">
@@ -1581,7 +1827,7 @@ function DataTableInner<TData>(
1581
1827
  type="button"
1582
1828
  aria-label={isExpanded ? '收合' : '展開'}
1583
1829
  aria-expanded={isExpanded}
1584
- className="inline-flex items-center justify-center shrink-0 w-4 h-4 mr-2 text-fg-muted hover:text-foreground rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-transform"
1830
+ className="inline-flex items-center justify-center shrink-0 w-4 h-4 mr-2 text-fg-muted hover:text-fg-secondary rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-transform motion-reduce:duration-0"
1585
1831
  style={{ transform: isExpanded ? 'rotate(90deg)' : undefined }}
1586
1832
  onClick={(e) => { e.stopPropagation(); toggleExpand?.() }}
1587
1833
  >
@@ -1626,7 +1872,7 @@ function DataTableInner<TData>(
1626
1872
  type="button"
1627
1873
  aria-label={isExpanded ? '收合' : '展開'}
1628
1874
  aria-expanded={isExpanded}
1629
- className="inline-flex items-center justify-center shrink-0 w-4 h-4 mr-2 text-fg-muted hover:text-foreground rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-transform"
1875
+ className="inline-flex items-center justify-center shrink-0 w-4 h-4 mr-2 text-fg-muted hover:text-fg-secondary rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-transform motion-reduce:duration-0"
1630
1876
  style={{ transform: isExpanded ? 'rotate(90deg)' : undefined }}
1631
1877
  onClick={(e) => { e.stopPropagation(); toggleExpand?.() }}
1632
1878
  >
@@ -1662,8 +1908,10 @@ function DataTableInner<TData>(
1662
1908
  React.useEffect(() => {
1663
1909
  if (!enabled || preserveSelectionOnFilter) return
1664
1910
  setSelection(prev => {
1665
- const filtered = prev.filter(id => visibleRowIdsSet.has(id))
1666
- return filtered.length === prev.length ? prev : filtered
1911
+ // all 模式 = 「全部符合當前 filter」→ 不清(excluded 留著,被 filter 掉的 excluded 列無害)
1912
+ if (prev.mode === 'all') return prev
1913
+ const filtered = prev.ids.filter(id => visibleRowIdsSet.has(id))
1914
+ return filtered.length === prev.ids.length ? prev : { mode: 'include', ids: filtered }
1667
1915
  })
1668
1916
  }, [visibleRowIdsKey, enabled, preserveSelectionOnFilter, visibleRowIdsSet, setSelection])
1669
1917
 
@@ -1675,9 +1923,22 @@ function DataTableInner<TData>(
1675
1923
  .map(r => r.id)
1676
1924
  }, [rows, enabled, isRowSelectable])
1677
1925
 
1926
+ // Union-aware「某列是否選取」+ 計數(include = ids 內;all = 不在 excluded 內)
1927
+ const includeSet = React.useMemo(
1928
+ () => (selection.mode === 'include' ? new Set(selection.ids) : new Set<string>()),
1929
+ [selection],
1930
+ )
1931
+ const excludeSet = React.useMemo(
1932
+ () => (selection.mode === 'all' ? new Set(selection.excluded) : new Set<string>()),
1933
+ [selection],
1934
+ )
1935
+ const isSelectedId = React.useCallback(
1936
+ (id: string) => (selection.mode === 'include' ? includeSet.has(id) : !excludeSet.has(id)),
1937
+ [selection.mode, includeSet, excludeSet],
1938
+ )
1939
+ const hasAnySelection = selection.mode === 'all' || includeSet.size > 0
1678
1940
  // Header tri-state checkbox value
1679
- const selectionSet = React.useMemo(() => new Set(selection), [selection])
1680
- const visibleSelectedCount = selectableVisibleIds.filter(id => selectionSet.has(id)).length
1941
+ const visibleSelectedCount = selectableVisibleIds.filter(id => isSelectedId(id)).length
1681
1942
  const headerCheckedState: boolean | 'indeterminate' =
1682
1943
  selectableVisibleIds.length === 0 ? false
1683
1944
  : visibleSelectedCount === 0 ? false
@@ -1691,20 +1952,16 @@ function DataTableInner<TData>(
1691
1952
  )
1692
1953
 
1693
1954
  const toggleHeaderCheckbox = React.useCallback(() => {
1694
- if (headerCheckedState === true) {
1695
- // 清掉本頁可見已選(保留可見外的 selection)
1696
- const visibleSet = new Set(selectableVisibleIds)
1697
- setSelection(prev => prev.filter(id => !visibleSet.has(id)))
1698
- } else {
1699
- // 選全可見(扣除 disabled);保留可見外的既有 selection
1700
- setSelection(prev => Array.from(new Set([...prev, ...selectableVisibleIds])))
1701
- }
1955
+ // header tri-state visible-scoped:全可見已選 → 取消可見;否則 → 選全可見。
1956
+ // include / all 兩模型由 applySelectIds 處理(all 模式 toggle 改寫 excluded)。
1957
+ const willSelect = headerCheckedState !== true
1958
+ setSelection(prev => applySelectIds(prev, selectableVisibleIds, willSelect))
1702
1959
  }, [headerCheckedState, selectableVisibleIds, setSelection])
1703
1960
 
1704
1961
  const toggleRow = React.useCallback((rowId: string, rowOriginal: TData, opts?: { shiftKey?: boolean }) => {
1705
1962
  if (isRowSelectable && !isRowSelectable(rowOriginal)) return
1706
1963
  if (mode === 'single') {
1707
- setSelection(selectionSet.has(rowId) ? [] : [rowId])
1964
+ setSelection(isSelectedId(rowId) ? { mode: 'include', ids: [] } : { mode: 'include', ids: [rowId] })
1708
1965
  anchorRowIdRef.current = rowId
1709
1966
  return
1710
1967
  }
@@ -1722,24 +1979,16 @@ function DataTableInner<TData>(
1722
1979
  return row && (!isRowSelectable || isRowSelectable(row.original))
1723
1980
  })
1724
1981
  // Mail / GitHub 慣例:shift-click 把 range 全變「rowId 點擊後該變的狀態」
1725
- const willCheck = !selectionSet.has(rowId)
1726
- setSelection(prev => {
1727
- const set = new Set(prev)
1728
- rangeIds.forEach(id => willCheck ? set.add(id) : set.delete(id))
1729
- return Array.from(set)
1730
- })
1982
+ const willCheck = !isSelectedId(rowId)
1983
+ setSelection(prev => applySelectIds(prev, rangeIds, willCheck))
1731
1984
  return
1732
1985
  }
1733
1986
  }
1734
- // 一般 toggle + 更新 anchor
1735
- setSelection(prev => {
1736
- const set = new Set(prev)
1737
- if (set.has(rowId)) set.delete(rowId)
1738
- else set.add(rowId)
1739
- return Array.from(set)
1740
- })
1987
+ // 一般 toggle + 更新 anchor(include / all 由 applySelectIds 處理)
1988
+ const willCheck = !isSelectedId(rowId)
1989
+ setSelection(prev => applySelectIds(prev, [rowId], willCheck))
1741
1990
  anchorRowIdRef.current = rowId
1742
- }, [isRowSelectable, mode, selectionSet, rows, visibleIdToRow, setSelection])
1991
+ }, [isRowSelectable, mode, isSelectedId, rows, visibleIdToRow, setSelection])
1743
1992
 
1744
1993
  // ── Cmd+A / Esc / Arrow keys 鍵盤 handler(table-level)──
1745
1994
  // code-quality-allow: long-function — single keyboard dispatch covering Cmd+A / Esc / Arrow / Space + selection state mutations,拆 sub-handler 會切散 keyboard mode coherence
@@ -1752,7 +2001,33 @@ function DataTableInner<TData>(
1752
2001
  // Phase B3 IME guard(2026-05-10 per codex Q-B3):中文輸入法組字中 ignore 所有 nav keys。
1753
2002
  // 2026-05-16 Round 5 audit Dim 27 fix:`keyCode` deprecated but still in KeyboardEvent type — no cast needed。
1754
2003
  if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return
1755
- if (spreadsheetMode && selectedCellId != null && editingCellId == null) {
2004
+ // 2026-07-14 dim-10 修:spreadsheet 分支排除 descendant 互動控件 — 焦點在 cell 內
2005
+ // action button / link / input 時,Enter 應 activate 該控件、方向鍵交還控件,
2006
+ // 原 handler 會 preventDefault 取消按鈕 activation、拿舊 selectedCellId 導覽。
2007
+ // 對齊下方 row-selection 分支 2026-07-09 既有 input-family guard + AG Grid
2008
+ // embedded-control convention(cell renderer 內控件 own keyboard)。
2009
+ const spreadsheetKbTarget = e.target as HTMLElement | null
2010
+ const targetIsEmbeddedControl = !!spreadsheetKbTarget?.closest?.(
2011
+ 'button, a[href], input, select, textarea, [contenteditable="true"]',
2012
+ )
2013
+ // 2026-07-05 D4 fix:spreadsheet 鍵盤入口 — selection 尚未建立時按方向鍵,seed 第一個
2014
+ // visible cell(原本唯一 set 起點是 mouse click → 鍵盤-only 使用者 Tab 進 table 後方向鍵
2015
+ // 全 no-op,整個 spreadsheet 導覽被滑鼠 gate,違反 spec「鍵盤完整可操作」驗證宣稱。
2016
+ // 對齊 Excel / Google Sheets / AG Grid「focus grid → first cell active」canonical)。
2017
+ if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId == null && editingCellId == null
2018
+ && ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
2019
+ const allRows = table.getRowModel().rows.map((r) => r.id)
2020
+ const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)
2021
+ if (allRows.length > 0 && allCols.length > 0) {
2022
+ e.preventDefault()
2023
+ const firstCellId = `${allRows[0]}:${allCols[0]}`
2024
+ setSelectedCellId(firstCellId)
2025
+ setRangeAnchor(firstCellId)
2026
+ setRangeFocus(null)
2027
+ }
2028
+ return
2029
+ }
2030
+ if (spreadsheetMode && !targetIsEmbeddedControl && selectedCellId != null && editingCellId == null) {
1756
2031
  const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Enter', 'F2', 'Escape']
1757
2032
  if (!navKeys.includes(e.key)) return
1758
2033
  const lastColon = selectedCellId.lastIndexOf(':')
@@ -1770,8 +2045,7 @@ function DataTableInner<TData>(
1770
2045
  else if (e.key === 'ArrowLeft' && curColIdx > 0) { nextColIdx = curColIdx - 1 }
1771
2046
  else if (e.key === 'ArrowRight' && curColIdx < allCols.length - 1) { nextColIdx = curColIdx + 1 }
1772
2047
  else if (e.key === 'Enter' || e.key === 'F2') {
1773
- // Enter / F2 → 進 edit(若 cell editable + 非 boolean / url + 非 disabled)
1774
- // 2026-05-13 codex V1 fix:加 `!isCellDisabled(meta, row)` gate(對齊 mouse click invariant)
2048
+ // Enter / F2 → 進 edit(若 cell editable + 非 boolean / url)。edit 入口統一走 canEditCell(= isCellEditable)。
1775
2049
  const row = table.getRowModel().rowsById[curRowId]
1776
2050
  const colDef = table.getAllLeafColumns().find((c) => c.id === curColId)
1777
2051
  // any-allow: column meta free-form
@@ -1803,22 +2077,33 @@ function DataTableInner<TData>(
1803
2077
  }
1804
2078
  // ── Row selection mode keyboard handler(下方既有)──
1805
2079
  if (!enabled) return
2080
+ // 2026-07-09 fix(圖一 Ctrl+A bug):焦點在可編輯輸入元素(cell edit / inline edit / 搜尋框)時,
2081
+ // 鍵盤(Cmd/Ctrl+A 全選、Esc)應交給該元素(全選 cell 文字 / 取消編輯),**不**攔成 row selection。
2082
+ // 對齊 Notion / Airtable / Linear:編輯格內 Ctrl+A = 選格內文字,非選全表列。
2083
+ const kbTarget = e.target as HTMLElement | null
2084
+ if (
2085
+ editingCellId != null ||
2086
+ (kbTarget && (kbTarget.tagName === 'INPUT' || kbTarget.tagName === 'TEXTAREA' || kbTarget.tagName === 'SELECT' || kbTarget.isContentEditable))
2087
+ ) return
1806
2088
  // Cmd/Ctrl+A:選全可見(扣 disabled)— 對齊 Mail / GitHub / Linear 慣例
1807
2089
  if ((e.metaKey || e.ctrlKey) && e.key === 'a' && mode === 'multi') {
1808
2090
  e.preventDefault()
1809
- setSelection(prev => Array.from(new Set([...prev, ...selectableVisibleIds])))
2091
+ setSelection(prev => applySelectIds(prev, selectableVisibleIds, true))
1810
2092
  return
1811
2093
  }
1812
2094
  // Esc:clear selection
1813
- if (e.key === 'Escape' && selection.length > 0) {
2095
+ if (e.key === 'Escape' && hasAnySelection) {
1814
2096
  e.preventDefault()
1815
- setSelection([])
2097
+ setSelection({ mode: 'include', ids: [] })
1816
2098
  anchorRowIdRef.current = null
1817
2099
  return
1818
2100
  }
1819
2101
  },
1820
- [enabled, mode, selection.length, selectableVisibleIds, setSelection,
1821
- spreadsheetMode, selectedCellId, editingCellId, table, isCellEditable]
2102
+ // D3 dep-hygiene fix(2026-07-06):handler 內(portal edit Enter 分支)呼叫的是 canEditCell,
2103
+ // 非 isCellEditable — 原 deps 列 isCellEditable 是靠 canEditCell identity-stable 才無實害的
2104
+ // stale-closure 地雷;改列真實依賴 canEditCell(其 useCallback deps 已含 isCellEditable)。
2105
+ [enabled, mode, hasAnySelection, selectableVisibleIds, setSelection,
2106
+ spreadsheetMode, selectedCellId, editingCellId, table, canEditCell]
1822
2107
  )
1823
2108
 
1824
2109
  // ── Header cell ──
@@ -1841,7 +2126,7 @@ function DataTableInner<TData>(
1841
2126
  checked={headerCheckedState}
1842
2127
  onClick={(e) => e.stopPropagation()}
1843
2128
  onCheckedChange={() => toggleHeaderCheckbox()}
1844
- aria-label="Select all visible rows"
2129
+ aria-label="全選可見列"
1845
2130
  disabled={selectableVisibleIds.length === 0}
1846
2131
  />
1847
2132
  )}
@@ -1875,7 +2160,10 @@ function DataTableInner<TData>(
1875
2160
  // absolute → hover 顯時佔位 → label 自動讓出空間給 sort + more,**不再重疊**(對齊
1876
2161
  // user 圖示質疑 + Notion / Airtable header layout 共識)。
1877
2162
  // cell padding 12px 由外層 cellPadding style 提供 → more 距 cell 右邊 = 12px。
1878
- 'group relative flex items-center gap-2 text-fg-secondary text-body font-normal shrink-0 overflow-hidden select-none',
2163
+ // header 字級也隨 size(原寫死 text-body → lg 表格 header 字偏小,跟 body 不一致)。
2164
+ // 對齊 cell wrapper + Field family size→font SSOT。色弱化由 text-fg-secondary 維持。
2165
+ 'group relative flex items-center gap-2 text-fg-secondary font-normal shrink-0 overflow-hidden select-none',
2166
+ fieldDisplayTextClass(size),
1879
2167
  align === 'right' && 'justify-end',
1880
2168
  align === 'center' && 'justify-center',
1881
2169
  )}
@@ -1891,17 +2179,22 @@ function DataTableInner<TData>(
1891
2179
  className={cn(
1892
2180
  'flex items-center min-w-0 flex-1 gap-1 outline-none',
1893
2181
  canSort && 'cursor-pointer hover:text-foreground transition-colors',
1894
- canSort && 'focus-visible:ring-2 focus-visible:ring-ring rounded-sm',
2182
+ // 2026-07-04:rounded-sm → rounded-md(radius.spec.md 設計哲學(4)rounded-sm 保留未使用,4px 一律 rounded-md)
2183
+ canSort && 'focus-visible:ring-2 focus-visible:ring-ring rounded-md',
1895
2184
  )}
1896
2185
  >
1897
- <TruncateCell className={cn('min-w-0', align === 'right' && 'text-right', align === 'center' && 'text-center')}>
2186
+ <TruncatedText className={cn('min-w-0', align === 'right' && 'text-right', align === 'center' && 'text-center')}>
1898
2187
  {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
1899
- </TruncateCell>
2188
+ </TruncatedText>
1900
2189
  {canSort && sortDir && !isMultiSort && (
1901
2190
  // 2026-05-18 改 per user 拍板「DataTable sort 跟 row size 變」+「做完」approval:
1902
2191
  // 原固定 14 違反 uiSize.spec.md Icon Tier(sm/md→16, lg→20)。改 ICON_SIZE[size]
1903
2192
  // 隨 DataTable size prop 變。
1904
- <SortIcon size={ICON_SIZE[size]} aria-hidden className="shrink-0 text-fg-secondary" />
2193
+ // 顏色不釘死(2026-08-18 user 拍板「與 label 同色連動」):繼承點擊區文字色 —
2194
+ // 靜止 fg-secondary、hover 隨父層 hover:text-foreground 與 label 同升。禁 fg-muted
2195
+ //(muted 家 = 永遠在場的裝飾/affordance 標記;排序箭頭 = 套用後才出現的狀態資訊)、
2196
+ // 禁 primary。SSOT → data-table.spec.md「Header cell internal」表 sort arrow 顏色列。
2197
+ <SortIcon size={ICON_SIZE[size]} aria-hidden className="shrink-0" />
1905
2198
  )}
1906
2199
  </div>
1907
2200
  {/* 右區:⌄ menu(hover/focus-within 才顯;**不顯示時不佔位**)
@@ -1985,16 +2278,40 @@ function DataTableInner<TData>(
1985
2278
  const colOptIn = colMeta?.resizable !== false
1986
2279
  const isResizable = enableColumnResize && !isSystemColumn(colId) && colOptIn
1987
2280
  const isResizing = header.column.getIsResizing?.()
2281
+ // 鍵盤 resize(WAI-ARIA window-splitter):方向鍵調整欄寬,公開目前值 + 下限。
2282
+ // effectiveMinWidth 對齊 drag 路徑(resolveColumnSizing minSize),step 16px。
2283
+ const effectiveMinWidth = header.column.columnDef.minSize ?? MIN_COLUMN_WIDTH
2284
+ const currentWidth = Math.round(header.column.getSize())
2285
+ const RESIZE_KEY_STEP = 16
1988
2286
  // H2: 不論 showDivider,只要 isResizable 就 render hot zone(panel boundary col 仍可拖)
1989
2287
  if (!showDivider && !isResizable) return null
1990
2288
  return (
1991
2289
  <span
1992
2290
  role={isResizable ? 'separator' : undefined}
1993
2291
  aria-orientation={isResizable ? 'vertical' : undefined}
1994
- aria-label={isResizable ? '拖曳調整欄寬' : undefined}
2292
+ aria-label={isResizable ? '調整欄寬' : undefined}
2293
+ // 鍵盤可操作 separator(WAI-ARIA window-splitter):focusable + 方向鍵調整 +
2294
+ // 公開目前寬度 / 下限。aria-valuetext 給 SR px 值(避免無 valuemax 時被誤讀成百分比)。
2295
+ tabIndex={isResizable ? 0 : undefined}
2296
+ aria-valuenow={isResizable ? currentWidth : undefined}
2297
+ aria-valuemin={isResizable ? effectiveMinWidth : undefined}
2298
+ aria-valuetext={isResizable ? `${currentWidth}px` : undefined}
2299
+ onKeyDown={isResizable ? (e: React.KeyboardEvent<HTMLSpanElement>) => {
2300
+ let next: number | null = null
2301
+ if (e.key === 'ArrowLeft') next = Math.max(effectiveMinWidth, currentWidth - RESIZE_KEY_STEP)
2302
+ else if (e.key === 'ArrowRight') next = currentWidth + RESIZE_KEY_STEP
2303
+ else if (e.key === 'Home') next = effectiveMinWidth
2304
+ if (next == null) return
2305
+ // stopPropagation:不讓方向鍵冒泡到 header 排序 / 欄位拖曳 keyboard listener。
2306
+ e.preventDefault()
2307
+ e.stopPropagation()
2308
+ table.setColumnSizing((prev) => ({ ...prev, [colId]: next as number }))
2309
+ // onColumnResize 由 columnSizing useEffect 自動 fire(非 drag 路徑不經 isResizingColumn)。
2310
+ } : undefined}
1995
2311
  className={cn(
1996
2312
  'group/resize absolute top-0 bottom-0 right-0 -mr-[3px] w-[7px]',
1997
2313
  isResizable && 'cursor-col-resize select-none',
2314
+ isResizable && 'focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring',
1998
2315
  )}
1999
2316
  // 2026-05-12 fix v2(user 抓 R3 stopPropagation 沒生效):dnd-kit PointerSensor
2000
2317
  // 監聽 `pointerdown`,我前一輪只 stop `onMouseDown` → pointerdown 仍冒泡 →
@@ -2054,6 +2371,18 @@ function DataTableInner<TData>(
2054
2371
  // 2026-05-06 v14.4 Notion blue line drop indicator(column reorder visual canonical)
2055
2372
  // 必須宣告在 renderHeaderRow 之前(closure 引用,避 minified bundler TDZ false-positive)
2056
2373
  const [dropIndicator, setDropIndicator] = React.useState<{ id: string; side: 'before' | 'after'; type: 'row' | 'column' } | null>(null)
2374
+ // 2026-07-05 D3 perf fix:shallow-compare setter — drag 中每次 over 變更 handleDragOver 都
2375
+ // set 全新 object,即使 id/side/type 沒變也觸發整個 DataTableInner 重渲(全 visible rows +
2376
+ // cells + header)。值相同 → 回傳 prev reference 讓 React bail out(對齊檔內 invalidRef guard
2377
+ // pattern;`setDropIndicator(null)` 自帶 Object.is bail out 不需經此)。
2378
+ const setDropIndicatorIfChanged = React.useCallback(
2379
+ (next: { id: string; side: 'before' | 'after'; type: 'row' | 'column' }) => {
2380
+ setDropIndicator((prev) =>
2381
+ prev && prev.id === next.id && prev.side === next.side && prev.type === next.type ? prev : next,
2382
+ )
2383
+ },
2384
+ [],
2385
+ )
2057
2386
  // ref for stable lookup in handleDragOver(避免 closure 抓舊值)
2058
2387
  const reorderableColumnIdsRef = React.useRef<string[]>([])
2059
2388
 
@@ -2074,7 +2403,7 @@ function DataTableInner<TData>(
2074
2403
  const meta = h.column.columnDef.meta as { locked?: boolean } | undefined
2075
2404
  const isLocked = meta?.locked === true
2076
2405
  const isSystem = isSystemColumn(colId)
2077
- // useSortable per header(Rules of Hooks compliant — same hook count per render
2406
+ // useDraggable + useDroppable per header(Rules of Hooks compliant — same hook count per render
2078
2407
  // as long as headers count consistent;column reorder/hide 整 row reflow 自然觸發 React reconcile)。
2079
2408
  // disabled=true 時仍 call hook 不啟動 listeners。
2080
2409
  const isDraggable = enableColumnReorder && !isLocked && !isSystem
@@ -2124,13 +2453,13 @@ function DataTableInner<TData>(
2124
2453
  const isPrimaryRegion = isCenter
2125
2454
  const regionRole: 'primary' | 'mirror' = isPrimaryRegion ? 'primary' : 'mirror'
2126
2455
 
2127
- // code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞 SortableContext / dnd-kit hooks 跟 row idx 的 stable binding
2456
+ // code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞 dnd-kit hooks 跟 row idx 的 stable binding
2128
2457
  const rowEl = (row: typeof rows[number], idx: number, opts?: { virtual?: boolean; start?: number; isLast?: boolean }) => {
2129
2458
  const showBorder = bordered !== false ? !opts?.isLast : true
2130
- // L4 row drag v2:nested rows 也 sortable(配合 cross-parent collisionDetection 過濾)
2131
- // sub-rows: depth>0 仍進 SortableContext,但 collisionDetection 只接受 same-parent over
2459
+ // L4 row drag v2:nested rows 也可拖(配合 cross-parent collisionDetection 過濾)
2460
+ // sub-rows: depth>0 也各自掛 useDraggable/useDroppable,但 collisionDetection 只接受 same-parent over
2132
2461
  const isThisRowDragging = enableRowDrag && activeDragId === row.id
2133
- const useSortableWrap = enableRowDrag
2462
+ const dragRowWrap = enableRowDrag
2134
2463
 
2135
2464
  // H1 fix(2026-05-10,per user 確認):per-row autoRowHeight when any cell in this row has
2136
2465
  // error。Fixed-height row 模式下,該 row 的任一 cell 有 error msg → THAT row 自動 auto-height
@@ -2145,8 +2474,9 @@ function DataTableInner<TData>(
2145
2474
  const effectiveAutoRow = autoRowHeight || rowHasError
2146
2475
 
2147
2476
  // L4 row drag:handle absolute 貼齊 row 左 border(Jira canonical),不佔 column 空間。
2148
- // 只在 primary region(left 若有,否則 center)+ depth===0 render — RowDragHandle
2149
- // 內部再用 ctx.role === 'primary' 守門避免 mirror region 重複 render。
2477
+ // 只在 primary region + depth===0 render — primary 永遠 = center(v15.4 撤銷「left 優先」,
2478
+ // 見上方 isPrimaryRegion 註解);RowDragHandle 內部再用 ctx.role === 'primary' 守門避免
2479
+ // mirror region 重複 render。
2150
2480
  const showDragHandle = enableRowDrag && (row.depth ?? 0) === 0 && isPrimaryRegion
2151
2481
  // v15.2 SSOT 對齊 TreeView:drag 期間 suppress 全表 hover state
2152
2482
  // (user directive「drag 時 row 不應 hover / drag button 不應出現」)
@@ -2184,7 +2514,10 @@ function DataTableInner<TData>(
2184
2514
  // 找 source row(避免 multi-region 場景挑錯 region 的 row 當 ghost)
2185
2515
  data-row-drag-source={enableRowDrag && isPrimaryRegion ? 'true' : undefined}
2186
2516
  role="row"
2187
- aria-rowindex={idx + 2}
2517
+ // L5 分頁(2026-07-07 C13):rowindex 加分頁 offset — aria-rowcount 是全集,
2518
+ // 第 2 頁起 index 必須接續(否則 AT 讀到「第 129 列中的第 2 列」錯位);
2519
+ // 不可用 row.index(sort/filter 後是原始資料序,非視覺序)
2520
+ aria-rowindex={(paginationEnabled ? (currentPage - 1) * pageSizeState : 0) + idx + 2}
2188
2521
  className={cn(
2189
2522
  'group/row flex relative',
2190
2523
  // H1 fix(2026-05-10):effectiveAutoRow 覆 global autoRowHeight,per-row 若有 cell error
@@ -2228,20 +2561,20 @@ function DataTableInner<TData>(
2228
2561
  </div>
2229
2562
  )
2230
2563
 
2231
- if (useSortableWrap) {
2564
+ if (dragRowWrap) {
2232
2565
  // invalidDrop 只對「正在被拖」的 row 顯示 — handle 在 active row 上,UI 警示只需該 row
2233
- // code-quality-allow: long-function — 此 const 之下的整個 if-block 含 useSortable hooks + SortableRowProvider + baseRowDiv composition;audit 把 const 誤認為 function entry,實 long body 在 closure 內 dnd-kit + per-row state 多 capture,拆會破壞 hook order invariant
2566
+ // code-quality-allow: long-function — 此 const 之下的整個 if-block 含 dnd-kit hooks + SortableRowProvider + baseRowDiv composition;audit 把 const 誤認為 function entry,實 long body 在 closure 內 dnd-kit + per-row state 多 capture,拆會破壞 hook order invariant
2234
2567
  const rowInvalidDrop = isThisRowDragging && invalidDropActive
2235
2568
  return (
2236
2569
  <SortableRowProvider key={row.id} id={row.id} disabled={dragDisabled} role={regionRole} invalidDrop={rowInvalidDrop}>
2237
2570
  {(ctx) => baseRowDiv({
2238
- // mirror 也掛 setNodeRef — dnd-kit 內部以 hook instance 為單元,
2239
- // 多 instance 同 id 時,measurement 走最後 mount 的;不影響 transform 一致性
2571
+ // primary 掛 useDraggable+useDroppable 合成 ref;mirror 只掛 useDroppable ref
2572
+ // (v15.4 split — mirror 不進 drag source store,isDragging 走 useDndContext 同步)
2240
2573
  ref: ctx.setNodeRef,
2241
2574
  style: ctx.style,
2242
2575
  isDragging: ctx.isDragging,
2243
- // v15.2 整列可拖:listeners + attributes spread 在 row div 上(只 primary,
2244
- // mirror region 沒 listeners 避免 a11y 重複 announce / pointer 雙觸發)
2576
+ // v15.6 button-only:rowListeners 恆 undefined(activator = RowDragHandle Button),
2577
+ // baseRowDiv spread `{...(extra?.listeners ?? {})}` 自動 noop;attributes 留空 = row 純 container
2245
2578
  listeners: ctx.rowListeners,
2246
2579
  attributes: ctx.rowAttributes,
2247
2580
  })}
@@ -2302,7 +2635,8 @@ function DataTableInner<TData>(
2302
2635
  // 行為:**永遠 hug rows**,只在被約束時才 cap + body shrink + V scroll。
2303
2636
  // 簡單需求:有約束 → rows 沒超就 hug;超就 cap+scroll;RWD 同理。
2304
2637
  style={isFillHeight ? { maxHeight: height } : undefined}
2305
- role="table" aria-rowcount={rows.length + 1}
2638
+ // L5 分頁:aria-rowcount = 全集筆數非當頁(ARIA 規範;getPrePaginationRowModel = filter 後全集)
2639
+ role="table" aria-rowcount={(paginationEnabled ? table.getPrePaginationRowModel().rows.length : rows.length) + 1}
2306
2640
  // Phase 9 Issue 12 fix(2026-05-10 codex 抓):**single tabIndex prop**,合併 selection
2307
2641
  // 跟 spreadsheet 兩 path。React 在 dup props 只 keep last 是 silent regression risk。
2308
2642
  tabIndex={enabled || spreadsheetMode ? 0 : undefined}
@@ -2321,10 +2655,10 @@ function DataTableInner<TData>(
2321
2655
  )}
2322
2656
  {/* Header 的 center 區保持 overflow-hidden(非 scroll)—— body 的 center 才有 scroll,
2323
2657
  header 靠 JS 同步 scrollLeft(見 onCenterBodyScroll)。這樣不會出現雙 scrollbar。
2324
- 為了對齊 body 的 V scrollbar(native 捲軸吃 ~15-17px 寬),header 等寬預留 gutter:
2325
- `scrollbar-gutter: stable` 放在 centerBody(真正有 V scroll 的 container)+
2326
- header 這層不需額外處理,因為 body 預留了空間後 H 內容寬度會自然等同 header。
2327
- 注意:header 的 `scrollbar-gutter` 無效(因為 overflow-hidden),刻意不設 */}
2658
+ V scrollbar 對齊:centerBody **刻意不用** `scrollbar-gutter: stable`(決策見 centerBody
2659
+ className 註解 — 永久預留 15px 會讓 content-fit 看起來像恆有 V 捲軸);trade-off =
2660
+ V scroll 出現時 body 內側少 ~15px、header 不縮 → 右端微 misalign,content-fit 乾淨優先。
2661
+ header 的 `scrollbar-gutter` 本就無效(overflow-hidden),刻意不設 */}
2328
2662
  <div
2329
2663
  ref={centerHeaderRef}
2330
2664
  data-datatable-header-panel="center"
@@ -2372,16 +2706,28 @@ function DataTableInner<TData>(
2372
2706
  <div
2373
2707
  ref={centerBodyRef}
2374
2708
  // Center body 同時擁有 H + V scroll;maxHeight 限制讓 H scrollbar 落在 visible 底部
2375
- // `scrollbar-gutter: stable` 永遠預留 V scrollbar 寬度(~15-17px),避免 body 出現 V
2376
- // scrollbar 時右端被縮,跟 header 右端產生 gap(Windows/Linux native scrollbar 吃寬)
2377
2709
  data-datatable-hscroll
2378
2710
  data-datatable-panel="center"
2711
+ // a11y(scrollable-region-focusable,對齊 DS ScrollArea Viewport canonical):唯讀表格
2712
+ // 的可捲動 body 若無任何 focusable descendant,鍵盤使用者無法捲動。read-only 模式
2713
+ // (非 enabled / spreadsheet)outer table 也不 focusable → 這裡補 tabIndex=0 + 具名 +
2714
+ // inset focus ring,讓鍵盤可聚焦後方向鍵捲動;互動模式已由 outer table keyboard handler
2715
+ // + focusable cells 覆蓋,不重複加 tab stop。
2716
+ // **role="rowgroup" 必要**(2026-07-29 WM beta.95 axe 錨例):focusable 的無 role
2717
+ // 中間層會被 axe aria-required-children 視為 role="table" 的不合法 owned child,
2718
+ // 打斷 table→row ownership(修 scrollable-region-focusable 反引爆 required-children,
2719
+ // 與 Tabs 2026-07-18 決策1 同型)。rowgroup = W3C ARIA 1.2 合法 table 子代 + 可具名
2720
+ // (Name from author §5.2.8.4)+ 容納 rows,兩規則唯一同時滿足解。
2721
+ // 空表例外:Empty 塊非 row → 不掛 rowgroup;空表無 overflow 也無需 tabIndex/名稱。
2722
+ role={isEmpty ? undefined : 'rowgroup'}
2723
+ tabIndex={enabled || spreadsheetMode || isEmpty ? undefined : 0}
2724
+ aria-label={enabled || spreadsheetMode || isEmpty ? undefined : '表格內容,可捲動'}
2379
2725
  // overflow-x/y: auto — 沒 overflow 就不顯 bar。wrapper minWidth 仍 trigger H 真 overflow。
2380
2726
  // **不**用 scrollbar-gutter: stable — 那會永遠保留 V 軸 15px 空間,
2381
2727
  // content fit 時看起來像「永遠有 V 捲軸」(Image #5 bug)。
2382
2728
  // trade-off:V scroll 出現時 body 內側少 15px,header 不縮 → 右端微 misalign,
2383
2729
  // 但 content fit 視覺乾淨優先(Mac 用戶 overlay scrollbar 不可見)。
2384
- className="flex-1 min-w-0 overflow-x-auto overflow-y-auto"
2730
+ className="flex-1 min-w-0 overflow-x-auto overflow-y-auto focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring"
2385
2731
  // isFillHeight:用 JS 算的 px(bodyMaxHeight),bypass CSS % 在 flex 場景的不可靠 shrink。
2386
2732
  // 固定 px(300px etc):直接套 height。
2387
2733
  style={
@@ -2434,7 +2780,7 @@ function DataTableInner<TData>(
2434
2780
  activeEditorEnabled={experimentalActiveEditorController}
2435
2781
  // Slice D Step 5(D.3 portal Field,2026-05-10):real portal Field render callback。
2436
2782
  // Layer 在 ActiveEditorHost(z 3 float rect)render `<Cell mode="edit" />` 同 registry。
2437
- // Cell wrapper 保持 mode="display"(SSOT preserved per codex Q6.2)。
2783
+ // Cell wrapper 保持 mode="view"(SSOT preserved per codex Q6.2)。
2438
2784
  activeEditorRender={experimentalActiveEditorController ? (cellId) => {
2439
2785
  const lastColon = cellId.lastIndexOf(':')
2440
2786
  if (lastColon < 0) return null
@@ -2505,12 +2851,25 @@ function DataTableInner<TData>(
2505
2851
  // 2026-05-13:canEditCell helper(per V4 consolidation,合 editable + !disabled invariant)
2506
2852
  if (!nextRow || !canEditCell(nextMeta, nextRow.original)) continue
2507
2853
  // 找到 next editable cell → commit current + start next edit
2854
+ // 2026-07-05 D4 fix:原本只 setEditingCellId —(a)同 type 相鄰 cell React 同位
2855
+ // 重用 input DOM,blur 不 fire → onBlur commit 不觸發,剛打的 draft 整段遺失;
2856
+ // (b)editingDraft 不清 → 下一格 portal value 顯示上一格草稿(甚至把上一格 draft
2857
+ // commit 進錯的 cell)。Fix:有 draft 先 commit 當前 cell(commitCell 內已清 draft),
2858
+ // 再換格;spreadsheet selection 對齊 edit-entry canonical 清空(commitCell 的
2859
+ // selection restore 對 Tab 換格不適用 — 下一格馬上進 edit)。
2860
+ if (editingDraft !== undefined) commitCell(rowId, colId, editingDraft)
2508
2861
  setEditingCellId(cellEditId(allRows[nextRowIdx], allCols[nextColIdx]))
2862
+ setSelectedCellId(null)
2863
+ setRangeAnchor(null)
2864
+ setRangeFocus(null)
2509
2865
  return
2510
2866
  }
2511
2867
  }
2512
2868
  return (
2513
- <div onKeyDownCapture={handleEditTab} style={{ width: '100%', height: '100%' }}>
2869
+ // 2026-07-05 D4 fix:key={cellId} 強制 per-cell remount — 相鄰同型欄位 Tab 過去時
2870
+ // uncontrolled Input / NumberCell localValue 原封不動(上一格的字跑到下一格)。
2871
+ // 對齊 cell-registry「mode-keyed remount canonical」(per-cell edit session 是不同 mount cycle)。
2872
+ <div key={cellId} onKeyDownCapture={handleEditTab} style={{ width: '100%', height: '100%' }}>
2514
2873
  <Cell
2515
2874
  value={value}
2516
2875
  meta={meta}
@@ -2520,19 +2879,18 @@ function DataTableInner<TData>(
2520
2879
  isEditable={cellEditable}
2521
2880
  onCommit={(next) => commitCell(rowId, colId, next)}
2522
2881
  onCommitLive={(next) => onCellCommit?.(rowId, colId, next)}
2523
- onCancel={exitEdit}
2882
+ onCancel={() => cancelCellEdit(rowId, colId)} // 2026-07-05 D4:cancel 還原 selection(Contract 11)
2524
2883
  onDraft={setEditingDraft} // Phase 7:每 keystroke 寫 draft → preserve across virtualizer unmount
2525
2884
  />
2526
2885
  </div>
2527
2886
  )
2528
2887
  } : undefined}
2529
- // Slice D Step 4 spreadsheet semantics(2026-05-10):
2530
- // selectedCellId(click 1)= solid border SelectionRect z 2
2531
- // rangeCellIds(Shift+click rectangle from anchor↔focus)= cell-bg fill via
2532
- // CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫 fill,只畫
2533
- // RangeOuterRing 4 line div boundary)
2888
+ // Slice D Step 4 spreadsheet semantics(2026-05-10;2026-07-14 對齊清理):
2889
+ // selectedCellId(click 1)= solid border SelectionRing z 2
2890
+ // range(Shift+click rectangle from anchor↔focus)= cell-bg fill via
2891
+ // CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫 range 視覺,
2892
+ // RangeOuterRing / rangeCellIds prop 已 retire)
2534
2893
  selectedCellId={spreadsheetMode ? selectedCellId : null}
2535
- rangeCellIds={rangeCellIds}
2536
2894
  cellClickEntersEdit={(cellId) => {
2537
2895
  // 2026-05-10 codex review red light fix(per dual-track verify):
2538
2896
  // 1. cellId parse 用 lastIndexOf(':')(row id 可含 colon)
@@ -2561,14 +2919,14 @@ function DataTableInner<TData>(
2561
2919
 
2562
2920
  // ── L4 Row drag DnD wrapper ───────────────────────────────────────────────
2563
2921
  // Sensors:Pointer(8px activation distance,避免 cell click 誤觸 drag)+ Keyboard(a11y)
2564
- // SortableContext items:**只 top-level row id**(nested sub-rows 不在 sortable 集合);
2565
- // 同 parent level 限制由「sub-rows 不在 items 內」自然成立。
2922
+ // v15.0 Path B:無 SortableContext — 每 row 各自 useDraggable / useDroppable;
2923
+ // 同 parent level 限制由自訂 collisionDetection 過濾 cross-parent target 成立(cross-parent over → invalidDrop)。
2566
2924
  // DragEnd:active.id / over.id → 算 position(active vs over 視覺位置),呼叫 onRowReorder。
2567
2925
  // hooks 必呼叫(rules-of-hooks)— 即使 enableRowDrag=false 也走 useSensors;wrap 才條件化。
2568
2926
  // **codex P1 fix(2026-05-07 v15.13)**:KeyboardSensor 不傳 `coordinateGetter`,用
2569
2927
  // dnd-kit 預設 25px 箭頭 stepping。`sortableKeyboardCoordinates` 是 `@dnd-kit/sortable`
2570
2928
  // preset,需 `<SortableContext>` 才正確 resolve 下一個 sortable target — 但 v15.0
2571
- // path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(line 21),
2929
+ // path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(見檔頭 import 註解),
2572
2930
  // 此 getter 在無 context 下 keyboard nav 無法 reliable resolve target → keyboard
2573
2931
  // drag/reorder regression。Default getter(arrow-key Δ25px)在 useDraggable 場景是
2574
2932
  // dnd-kit canonical(`@dnd-kit/core/src/sensors/keyboard/defaults.ts` 預設行為)。
@@ -2584,7 +2942,7 @@ function DataTableInner<TData>(
2584
2942
  // pointerWithin 要求 pointer 真在 droppable rect 內才返回 → release 在 gap 自然 over=null →
2585
2943
  // 不觸發 reorder → snap back 自然成立(對齊 Notion / TreeView 行為)。
2586
2944
  // rectIntersection fallback 給 keyboard sensor(無 pointer)。
2587
- // 詳 .claude/references/drag-canonical.md。
2945
+ // 詳 packages/design-system/ds-canonical/references/drag-canonical.md。
2588
2946
  const sameParentCollisionDetection: CollisionDetection = React.useCallback((args) => {
2589
2947
  const activeId = args.active?.id != null ? String(args.active.id) : null
2590
2948
  if (!activeId) {
@@ -2731,7 +3089,7 @@ function DataTableInner<TData>(
2731
3089
  const side: 'before' | 'after' = activeIdx < overIdx ? 'after' : 'before'
2732
3090
  // **v15.3 noop suppress**:drop position 等同原位 → 不顯 indicator(對齊 handleDragEnd noop guard)
2733
3091
  if (isReorderNoop(activeIdx, overIdx, side)) { setDropIndicator(null); return }
2734
- setDropIndicator({ id: String(over.id), side, type: 'column' })
3092
+ setDropIndicatorIfChanged({ id: String(over.id), side, type: 'column' })
2735
3093
  } else {
2736
3094
  // Row drag — 用 allRowIds 算位置(只 same-parent siblings,跨 parent collisionDetection 已過濾)
2737
3095
  const activeIdx = allRowIds.indexOf(String(active.id))
@@ -2739,9 +3097,9 @@ function DataTableInner<TData>(
2739
3097
  if (activeIdx === -1 || overIdx === -1) { setDropIndicator(null); return }
2740
3098
  const side: 'before' | 'after' = activeIdx < overIdx ? 'after' : 'before'
2741
3099
  if (isReorderNoop(activeIdx, overIdx, side)) { setDropIndicator(null); return }
2742
- setDropIndicator({ id: String(over.id), side, type: 'row' })
3100
+ setDropIndicatorIfChanged({ id: String(over.id), side, type: 'row' })
2743
3101
  }
2744
- }, [allRowIds, isReorderNoop])
3102
+ }, [allRowIds, isReorderNoop, setDropIndicatorIfChanged])
2745
3103
 
2746
3104
  const handleDragCancel = React.useCallback(() => {
2747
3105
  setActiveDragId(null)
@@ -2765,8 +3123,11 @@ function DataTableInner<TData>(
2765
3123
  const meta = table.getColumn(id)?.columnDef.meta as { locked?: boolean } | undefined
2766
3124
  return !meta?.locked
2767
3125
  })
3126
+ // D3 dep-hygiene fix(2026-07-06):補 columnVisibility — memo 讀 table.getVisibleLeafColumns()
3127
+ // (live,受 visibility 影響)原 deps 漏列,隱藏欄位後清單 stale(隱藏欄仍在 reorderable
3128
+ // 列表 → handleDragOver 的 drop side 計算錯位)。
2768
3129
  // eslint-disable-next-line react-hooks/exhaustive-deps
2769
- }, [table, columnsWithSelection, tableOptions?.state?.columnOrder])
3130
+ }, [table, columnsWithSelection, tableOptions?.state?.columnOrder, columnVisibility])
2770
3131
  // Sync ref(handleDragOver closure 抓不到最新 reorderableColumnIds)
2771
3132
  React.useEffect(() => { reorderableColumnIdsRef.current = reorderableColumnIds }, [reorderableColumnIds])
2772
3133
 
@@ -2840,6 +3201,43 @@ function DataTableInner<TData>(
2840
3201
  return sameParentCollisionDetection(args)
2841
3202
  }, [sameParentCollisionDetection])
2842
3203
 
3204
+ // ── L5 分頁列(2026-07-06,詳 data-table.spec.md「L5:分頁」段)────────────────
3205
+ // 間距 tight = layoutSpace spec 規則 3「跨範疇 functional 交互」;頁碼靠右(shadcn justify-end /
3206
+ // Ant Table bottomEnd / MUI / Carbon 4 家實證,左側空也靠右);「共 N 筆」數源 = filter 後全集
3207
+ // getPrePaginationRowModel(≠ selection all-mode 的 server-side 全集數 M — consumer 自持,語意不同)。
3208
+ // 2026-07-06 user 拍板:「Pagination 元件本身提供完整功能(showTotal / 每頁筆數)= SSOT,
3209
+ // Table 按一致定義套用」—— 分頁列的資訊/選單/「資訊左、操作右」layout 全部 own 在
3210
+ // <Pagination> 完整形態;DataTable 只轉發 config + own TanStack state(controlled 消費:
3211
+ // page/pageSize 狀態在本層、定義在 Pagination)。
3212
+ const totalRowCount = paginationEnabled ? table.getPrePaginationRowModel().rows.length : 0
3213
+ const paginationBar = paginationEnabled && !isEmpty ? (
3214
+ // 無條件 justify-end(2026-07-07 C16:原 paginationHasExtras 判斷式 = 平行重複 Pagination
3215
+ // 內部 hasExtras 拼寫,未來加 extra 必 drift)——完整形態 Pagination 自帶 w-full
3216
+ // justify-between,justify-end 對其為 no-op;純頁碼形態靠右 = 拍板 #6(shadcn justify-end /
3217
+ // Ant Table bottomEnd / MUI / Carbon 4 家)。ref 供 isFillHeight bodyMaxHeight 扣 bar 高(C12)。
3218
+ <div ref={paginationBarRef} className="flex justify-end">
3219
+ <Pagination
3220
+ total={totalRowCount}
3221
+ page={currentPage}
3222
+ onPageChange={setCurrentPage}
3223
+ pageSize={pageSizeState}
3224
+ onPageSizeChange={(next) => {
3225
+ setPageSizeState(next)
3226
+ paginationOpts?.onPageSizeChange?.(next)
3227
+ }}
3228
+ showTotal={paginationOpts?.showTotal}
3229
+ pageSizeOptions={paginationOpts?.pageSizeOptions}
3230
+ />
3231
+ </div>
3232
+ ) : null
3233
+ // isFillHeight 並用:外層接管高度(h-full min-h-0),tableContent 的 maxHeight cap 在內層照常生效
3234
+ const composedContent = paginationBar ? (
3235
+ <div className={cn('flex flex-col gap-[var(--layout-space-tight)]', isFillHeight && 'h-full min-h-0')}>
3236
+ {tableContent}
3237
+ {paginationBar}
3238
+ </div>
3239
+ ) : tableContent
3240
+
2843
3241
  const wrapWithDnd = (node: React.ReactNode): React.ReactNode => {
2844
3242
  if (!enableRowDrag && !enableColumnReorder) return node
2845
3243
  return (
@@ -2886,14 +3284,14 @@ function DataTableInner<TData>(
2886
3284
  if (enabled && mode === 'single') {
2887
3285
  return (
2888
3286
  <RadioGroupPrimitive.Root
2889
- value={selection[0] ?? ''}
2890
- onValueChange={(v) => v && setSelection([v])}
3287
+ value={selection.mode === 'include' ? (selection.ids[0] ?? '') : ''}
3288
+ onValueChange={(v) => v && setSelection({ mode: 'include', ids: [v] })}
2891
3289
  >
2892
- {wrapWithDnd(tableContent)}
3290
+ {wrapWithDnd(composedContent)}
2893
3291
  </RadioGroupPrimitive.Root>
2894
3292
  )
2895
3293
  }
2896
- return wrapWithDnd(tableContent)
3294
+ return wrapWithDnd(composedContent)
2897
3295
  }
2898
3296
 
2899
3297
  export const DataTable = React.forwardRef(DataTableInner) as <TData>(
@@ -2913,7 +3311,9 @@ export const dataTableMeta = {
2913
3311
  sizes: {
2914
3312
 
2915
3313
  },
2916
- states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
3314
+ // 'active' 移除 — 全檔無 Tailwind 按壓 utility(rg `active:` 僅命中 dnd-kit `e.active` 物件),
3315
+ // 無按壓專屬視覺態;row action / drag handle 的按壓屬內嵌 Button meta(2026-07-07 對抗稽核補修)。
3316
+ states: ['default', 'hover', 'focus-visible', 'disabled'],
2917
3317
  tokens: {
2918
3318
  bg: ['bg-muted', 'bg-neutral-hover', 'bg-surface'],
2919
3319
  fg: ['text-fg-muted', 'text-fg-secondary', 'text-foreground'],