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

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 +40 -0
  24. package/dist/components/AgentPanel/agent-logo.d.ts.map +1 -0
  25. package/dist/components/AgentPanel/agent-logo.js +344 -0
  26. package/dist/components/AgentPanel/agent-logo.js.map +1 -0
  27. package/dist/components/AgentPanel/agent-panel.d.ts +148 -0
  28. package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -0
  29. package/dist/components/AgentPanel/agent-panel.js +670 -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 +13 -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} +43 -0
  656. package/dist/index.d.ts +121 -67
  657. package/dist/index.d.ts.map +1 -1
  658. package/dist/index.js +140 -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 +1286 -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 +1286 -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 +626 -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 +1786 -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 +111 -0
  1242. package/src/components/AgentPanel/agent-logo.tsx +417 -0
  1243. package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +124 -0
  1244. package/src/components/AgentPanel/agent-panel.css +43 -0
  1245. package/src/components/AgentPanel/agent-panel.principles.stories.tsx +40 -0
  1246. package/src/components/AgentPanel/agent-panel.spec.md +226 -0
  1247. package/src/components/AgentPanel/agent-panel.stories.tsx +215 -0
  1248. package/src/components/AgentPanel/agent-panel.tsx +0 -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 +648 -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 +58 -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
@@ -0,0 +1,2311 @@
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
+ // same-row-mixed-allow: file 含 toolbar Button iconOnly + row ItemInlineActionButton,但兩者在不同 row(toolbar 跟 panel row 分離)
3
+ import React from 'react'
4
+ import type { Meta, StoryObj } from '@storybook/react'
5
+ import { expect, userEvent, waitFor, within } from '@storybook/test'
6
+ import { createColumnHelper, type ColumnDef } from '@tanstack/react-table'
7
+ import { Pencil, Trash2, MoreVertical, Search, Filter, Eye, Download, Plus, ArrowUpDown } from 'lucide-react'
8
+ import { DataTable, type DataTableSelection } from './data-table'
9
+ import { DataTableSortManager } from './data-table-sort-manager'
10
+ import { DataTableColumnVisibilityPanel } from './data-table-column-visibility-panel'
11
+ import {
12
+ DataTableFilterPanel,
13
+ evaluateTree,
14
+ createEmptyFilterTree,
15
+ isFilterTreeActive,
16
+ type DataTableFilterPanelLabels,
17
+ type FilterTree,
18
+ } from './data-table-filter-panel'
19
+ import { getFilteredRowModel, type SortingState } from '@tanstack/react-table'
20
+ import { Button } from '@/design-system/components/Button/button'
21
+ import { Empty } from '@/design-system/components/Empty/empty'
22
+ import { Input } from '@/design-system/components/Input/input'
23
+ import { BulkActionBar } from '@/design-system/components/BulkActionBar/bulk-action-bar'
24
+ import { Alert } from '@/design-system/components/Alert/alert'
25
+ import { Popover, PopoverTrigger, PopoverContent } from '@/design-system/components/Popover/popover'
26
+ // Issue 3 cleanup(2026-05-10):ScrollArea / ButtonDivider / ItemPrefix / ItemLabel /
27
+ // ItemInlineActionButton / ROW_PADDING_BY_SIZE / cn / DnD / dragSourceStyle imports retired —
28
+ // 全 column visibility row state machine 移到 <DataTableColumnVisibilityPanel> primitive。
29
+ import './column-types' // ColumnMeta declaration merging
30
+
31
+ // ── Sample Data ──────────────────────────────────────────────────────────────
32
+
33
+ // ── Person sample data canonical ──
34
+ // 對齊 ProfileCard.stories「Default」預設呈現:name + subtitle + status + statusMessage + fields
35
+ // avatar.spec.md DS-wide:所有 person avatar hover 必出現 ProfileCard,展示資訊一致(不可精簡)
36
+ import type { PersonData } from '@/design-system/components/PeoplePicker/person-display'
37
+
38
+ const SELLERS: PersonData[] = [
39
+ { name: 'Alice Wonderland Wang', avatarUrl: 'https://i.pravatar.cc/128?u=alice', description: 'Sales|Tokyo|EMP-1001', status: 'online', statusMessage: '出差中,週四回。緊急請聯絡 @bob 代理。', fields: [{ label: 'ID', value: 'AWW001' }, { label: '部門', value: 'Sales / APAC' }, { label: '時區', value: 'JST (GMT+9)' }] },
40
+ { name: 'Bob Christopher Chen', avatarUrl: 'https://i.pravatar.cc/128?u=bob', description: 'Sales|Taipei|EMP-1002', status: 'busy', statusMessage: '會議中,訊息我會儘快回。', fields: [{ label: 'ID', value: 'BCC002' }, { label: '部門', value: 'Sales / APAC' }, { label: '時區', value: 'TST (GMT+8)' }] },
41
+ { name: 'Carol Liu', avatarUrl: 'https://i.pravatar.cc/128?u=carol', description: 'Sales|Singapore|EMP-1003', status: 'online', statusMessage: '今日彈性工作。', fields: [{ label: 'ID', value: 'CL003' }, { label: '部門', value: 'Sales / APAC' }, { label: '時區', value: 'SGT (GMT+8)' }] },
42
+ { name: 'Alexander Hamilton Zhang', avatarUrl: 'https://i.pravatar.cc/128?u=alex', description: 'Sales|Shanghai|EMP-1004', status: 'away', statusMessage: '已離開辦公室,週一回。', fields: [{ label: 'ID', value: 'AHZ004' }, { label: '部門', value: 'Sales / APAC' }, { label: '時區', value: 'CST (GMT+8)' }] },
43
+ { name: 'David Wu', avatarUrl: 'https://i.pravatar.cc/128?u=david', description: 'Sales|Hong Kong|EMP-1005', status: 'online', statusMessage: '可線上協助。', fields: [{ label: 'ID', value: 'DW005' }, { label: '部門', value: 'Sales / APAC' }, { label: '時區', value: 'HKT (GMT+8)' }] },
44
+ { name: 'Elizabeth Montgomery Johnson', avatarUrl: 'https://i.pravatar.cc/128?u=elizabeth', description: 'Sales|Sydney|EMP-1006', status: 'offline', statusMessage: '已下線,明早 9:00 上線。', fields: [{ label: 'ID', value: 'EMJ006' }, { label: '部門', value: 'Sales / APAC' }, { label: '時區', value: 'AEST (GMT+10)' }] },
45
+ ]
46
+
47
+ interface Product {
48
+ sku: string
49
+ name: string
50
+ category: string
51
+ stock: string
52
+ seller: PersonData
53
+ updatedAt: string
54
+ price?: number
55
+ note?: string
56
+ }
57
+
58
+ const sampleData: Product[] = [
59
+ { sku: 'PRD-001', name: 'Wireless Bluetooth Headphones', category: 'Electronics', stock: 'In stock', seller: SELLERS[0], updatedAt: '2025/03/12', price: 2490 },
60
+ { sku: 'PRD-002', name: 'Ergonomic Office Chair with Lumbar Support', category: 'Furniture', stock: 'Low stock', seller: SELLERS[1], updatedAt: '2025/03/14', price: 8900 },
61
+ { sku: 'PRD-003', name: 'Organic Green Tea 100 Bags', category: 'Food', stock: 'In stock', seller: SELLERS[2], updatedAt: '2025/03/15', price: 350 },
62
+ { sku: 'PRD-004', name: 'USB-C Hub 7-in-1 Adapter', category: 'Electronics', stock: 'Out of stock', seller: SELLERS[3], updatedAt: '2025/03/16', price: 1290 },
63
+ { sku: 'PRD-005', name: 'Stainless Steel Water Bottle 750ml', category: 'Lifestyle', stock: 'In stock', seller: SELLERS[4], updatedAt: '2025/03/18', price: 680 },
64
+ { sku: 'PRD-006', name: 'Mechanical Keyboard with Cherry MX Brown Switches and RGB Backlight', category: 'Electronics', stock: 'In stock', seller: SELLERS[5], updatedAt: '2025/03/20', price: 3200 },
65
+ ]
66
+
67
+ const dataWithNotes: Product[] = sampleData.map((p, i) => ({
68
+ ...p,
69
+ note: i % 2 === 0
70
+ ? 'This product requires special packaging for international shipping. Please verify customs documentation before dispatch.'
71
+ : 'Standard delivery.',
72
+ }))
73
+
74
+ // 真實商品名池(品名 × 規格版本組合,避免 "Product item N" 佔位符)
75
+ const PRODUCT_NAMES: Record<string, string[]> = {
76
+ Electronics: ['Wireless Bluetooth Headphones', 'USB-C 7-in-1 Hub', 'Mechanical Keyboard', '4K Webcam', 'Portable SSD 1TB', '65W GaN Charger', 'Noise-Cancelling Earbuds', 'Ergonomic Wireless Mouse'],
77
+ Furniture: ['Ergonomic Office Chair', 'Standing Desk Converter', '5-Tier Bookshelf', 'Storage Cabinet', '3-Seat Fabric Sofa', 'Bedside Table', 'Coat Rack Stand', 'Adjustable Monitor Arm'],
78
+ Food: ['Organic Green Tea 100 Bags', 'Single-Origin Coffee Beans', 'Mixed Nuts Gift Box', 'Dark Chocolate Bar', 'Rolled Oats 1kg', 'Manuka Honey Jar', 'Herbal Tea Sampler', 'Cold-Pressed Olive Oil'],
79
+ Lifestyle: ['Stainless Steel Water Bottle', 'Scented Candle Set', 'Cordless Vacuum Cleaner', 'HEPA Air Purifier', 'Leather Notebook A5', 'Non-Slip Yoga Mat', 'Aroma Diffuser', 'Weighted Blanket'],
80
+ }
81
+ const PRODUCT_EDITIONS = ['Standard', 'Pro', 'Lite', 'Max', 'Mini', '2-Pack', 'Bundle', 'Refill']
82
+
83
+ function generateLargeData(count: number): Product[] {
84
+ const categories = ['Electronics', 'Furniture', 'Food', 'Lifestyle']
85
+ const stocks = ['In stock', 'Low stock', 'Out of stock', 'Pre-order']
86
+ return Array.from({ length: count }, (_, i) => {
87
+ const category = categories[i % 4]
88
+ const names = PRODUCT_NAMES[category]
89
+ const baseName = names[i % names.length]
90
+ const edition = PRODUCT_EDITIONS[Math.floor(i / names.length) % PRODUCT_EDITIONS.length]
91
+ return {
92
+ sku: `PRD-${String(i + 1).padStart(4, '0')}`,
93
+ name: `${baseName} (${edition})`,
94
+ category,
95
+ stock: stocks[i % 4],
96
+ seller: SELLERS[i % SELLERS.length],
97
+ updatedAt: `2025/03/${String(1 + (i % 28)).padStart(2, '0')}`,
98
+ price: Math.round(100 + Math.random() * 9900),
99
+ }
100
+ })
101
+ }
102
+
103
+ // ── Column Definitions ───────────────────────────────────────────────────────
104
+
105
+ const col = createColumnHelper<Product>()
106
+
107
+ // 2026-05-06 v14.3 DS canonical:column 寬度走 `meta.width` / `meta.minWidth`
108
+ // (避開 `size: 'sm'|'md'|'lg'` density 命名衝突)。內部 pre-process copy 到 TanStack root size。
109
+ const baseColumns = [
110
+ col.accessor('sku', { header: 'SKU', meta: { type: 'string', width: 100, minWidth: 80 } }),
111
+ col.accessor('name', { header: 'Product', meta: { type: 'string', width: 280, minWidth: 120 } }),
112
+ col.accessor('category', { header: 'Category', meta: { type: 'select', width: 120 } }),
113
+ col.accessor('stock', { header: 'Stock', meta: { type: 'select', width: 110 } }),
114
+ col.accessor('seller', { header: 'Seller', meta: { type: 'person', width: 150 } }),
115
+ col.accessor('updatedAt', { header: 'Updated', meta: { type: 'date', width: 120 } }),
116
+ ]
117
+
118
+ const columnsWithPrice = [
119
+ ...baseColumns,
120
+ col.accessor('price', {
121
+ header: 'Price',
122
+ meta: { type: 'currency', prefix: '$', width: 120 },
123
+ }),
124
+ ]
125
+
126
+ const columnsWithNote = [
127
+ col.accessor('sku', { header: 'SKU', meta: { type: 'string', width: 100 } }),
128
+ col.accessor('name', { header: 'Product', meta: { type: 'string', width: 200 } }),
129
+ col.accessor('note', {
130
+ header: 'Note', meta: { type: 'string', wrap: true, width: 300 } }),
131
+ col.accessor('category', { header: 'Category', meta: { type: 'select', width: 120 } }),
132
+ col.accessor('seller', { header: 'Seller', meta: { type: 'person', width: 150 } }),
133
+ ]
134
+
135
+ // ── Stories ───────────────────────────────────────────────────────────────────
136
+
137
+ const meta: Meta<typeof DataTable> = {
138
+ title: 'Design System/Components/DataTable/展示',
139
+ component: DataTable as any,
140
+ tags: ['autodocs'],
141
+ parameters: {
142
+ docs: {
143
+ description: {
144
+ component: '用於對齊掃視多筆同結構資料,並在需要時加上排序、篩選、選取或列內編輯。單一實體的唯讀屬性改用 DescriptionList,深層階層改用 TreeView,少量圖文資料則用自訂 list / grid。',
145
+ },
146
+ },
147
+ },
148
+ }
149
+
150
+ export default meta
151
+ type Story = StoryObj
152
+
153
+ // Retired 2026-05-16 audit Dim 24:`ColumnTypes` 跟 anatomy.stories.tsx:167 重複(同 9-type 自動渲染 + col helper demo)。
154
+ // Anatomy 是 type-system structural canonical home(用 Product col helper 對齊其他 anatomy 範例);
155
+ // 本 showcase 版用 custom `TypeDemo` interface,不對齊 anatomy 通用 type → noise。Retire showcase 版,anatomy 保留。
156
+
157
+ // Retired 2026-07-14 audit Dim 24:`NumberAlignment` 跟 anatomy.stories.tsx AlignmentRule 重複
158
+ // (同「數字/金額靠右、文字靠左」規則,anatomy 版含完整 rationale Desc + column type 對照)。
159
+ // Alignment 規則 canonical home = anatomy `AlignmentRule`;showcase 版無額外內容 → retire(earn-existence 2-test 雙 NO)。
160
+
161
+ /* ── Column resize(2026-05-06 v11):table 層級開關 + handle hover 變色 ── */
162
+ export const ColumnResize: Story = {
163
+ name: '欄寬調整',
164
+ render: () => {
165
+ const [widths, setWidths] = React.useState<Record<string, number>>({})
166
+ const [pinnedWidths, setPinnedWidths] = React.useState<Record<string, number>>({})
167
+ return (
168
+ <div className="flex flex-col gap-8 max-w-5xl">
169
+ <div>
170
+ <h3 className="text-body font-bold text-foreground mb-2">基本 — 全 data column 可拖</h3>
171
+ <p className="text-caption text-fg-muted mb-3">
172
+ 拖 header 右側分隔線可調整欄寬。滑到分隔線上會變色提示,拖動時會跟著游標即時調整。
173
+ 勾選欄等系統欄位寬度固定,不可調整。
174
+ <br />目前各欄寬度:{JSON.stringify(widths)}
175
+ </p>
176
+ <DataTable
177
+ columns={columnsWithPrice}
178
+ data={sampleData}
179
+ height="auto"
180
+ enableColumnResize
181
+ onColumnResize={(id, w) => setWidths(prev => ({ ...prev, [id]: w }))}
182
+ />
183
+ </div>
184
+ <div>
185
+ <h3 className="text-body font-bold text-foreground mb-2">欄位釘選與欄寬調整並存</h3>
186
+ <p className="text-caption text-fg-muted mb-3">
187
+ 把 SKU 跟產品名稱固定在左側,依然可以拖動分隔線調整這兩欄的寬度。
188
+ <br />目前各欄寬度:{JSON.stringify(pinnedWidths)}
189
+ </p>
190
+ <DataTable
191
+ columns={columnsWithPrice}
192
+ data={sampleData}
193
+ height="auto"
194
+ pinnedLeftColumns={['sku', 'name']}
195
+ enableColumnResize
196
+ onColumnResize={(id, w) => setPinnedWidths(prev => ({ ...prev, [id]: w }))}
197
+ />
198
+ </div>
199
+ </div>
200
+ )
201
+ },
202
+ }
203
+
204
+ /* ── 欄拖曳重排 — enableColumnReorder + columnDef.meta.locked ──
205
+ 對齊 Notion / Linear / Airtable 設計準則:header 任一 reorderable cell 可拖,
206
+ drop indicator 在 target column 邊緣。SKU 標 `meta.locked=true` 鎖定不可拖,亦不可
207
+ 接受 drop(Notion 「primary column」pattern)。System column(__select__)永遠鎖。
208
+ Pinned column 仍可 reorder 但只在自己 region 內(left/center/right 不跨 region)。 */
209
+ export const ColumnReorder: Story = {
210
+ name: '欄位拖曳重排',
211
+ render: () => {
212
+ const initialOrder = ['sku', 'name', 'category', 'price', 'stock', 'updatedAt']
213
+ const [columnOrder, setColumnOrder] = React.useState<string[]>(initialOrder)
214
+ const lockedCols = columnsWithPrice.map((c) => {
215
+ const ak = (c as { accessorKey?: string }).accessorKey
216
+ return ak === 'sku' ? { ...c, meta: { ...(c.meta ?? {}), locked: true } } : c
217
+ }) as ColumnDef<Product>[]
218
+ const handleColumnReorder = (sourceId: string, targetId: string, position: 'before' | 'after') => {
219
+ setColumnOrder((prev) => {
220
+ const next = prev.filter((id) => id !== sourceId)
221
+ const targetIdx = next.indexOf(targetId)
222
+ if (targetIdx === -1) return prev
223
+ const insertAt = position === 'before' ? targetIdx : targetIdx + 1
224
+ next.splice(insertAt, 0, sourceId)
225
+ return next
226
+ })
227
+ }
228
+ return (
229
+ <div className="flex flex-col gap-3 max-w-5xl">
230
+ <p className="text-caption text-fg-muted">
231
+ 開啟欄位重排(enableColumnReorder)後,拖住欄標題即可移動整欄:拖曳中欄位以半透明
232
+ 浮影跟著游標,目標欄的左或右邊緣會出現落點提示線(依游標位置判定放在前或後)。
233
+ <br />
234
+ - <strong>SKU 鎖定</strong>(<code>meta.locked=true</code>):不可拖曳,也不會成為落點
235
+ (對照 Notion 的主欄固定做法)
236
+ <br />
237
+ - System columns(__select__)永遠鎖
238
+ <br />
239
+ 目前 order:{columnOrder.join(' → ')}
240
+ </p>
241
+ <DataTable
242
+ columns={lockedCols}
243
+ data={sampleData}
244
+ height="auto"
245
+ tableOptions={{ state: { columnOrder } }}
246
+ enableColumnReorder
247
+ onColumnReorder={handleColumnReorder}
248
+ />
249
+ </div>
250
+ )
251
+ },
252
+ }
253
+
254
+ /* ── 行高模式 — autoRowHeight prop(每 row 內容驅動高度) ── */
255
+ export const RowAutoHeightInlineEdit: Story = {
256
+ name: '自動行高 × 就地編輯',
257
+ render: () => {
258
+ // 2026-05-14 I7 fix(per codex verdict):note 初始化進 state 一次,commit 寫同一 state。
259
+ // 原 `dataWithNotes = list.map(...)` 每 render derive 覆蓋 commit value → user 看似不能編。
260
+ const [list, setList] = React.useState<(Product & { note: string })[]>(() =>
261
+ generateLargeData(4).map((r, i) => ({
262
+ ...r,
263
+ note: i % 2 === 0
264
+ ? 'This product requires special packaging for international shipping. Please verify customs documentation before dispatch.'
265
+ : 'Standard delivery.',
266
+ }))
267
+ )
268
+ const cols: ColumnDef<Product & { note: string }>[] = [
269
+ { accessorKey: 'sku', header: 'SKU', meta: { type: 'string', width: 100 } },
270
+ { accessorKey: 'name', header: 'Product', meta: { type: 'string', editable: true, width: 240 } },
271
+ { accessorKey: 'category', header: 'Category', meta: { type: 'select', editable: true, width: 160, options: [
272
+ { value: 'Electronics', label: 'Electronics' },
273
+ { value: 'Furniture', label: 'Furniture' },
274
+ { value: 'Food', label: 'Food' },
275
+ { value: 'Lifestyle', label: 'Lifestyle' },
276
+ ] } },
277
+ { accessorKey: 'note', header: 'Note (wrap text)', meta: { type: 'string', editable: true, width: 360 } },
278
+ { accessorKey: 'price', header: 'Price', meta: { type: 'currency', editable: true, width: 100 } },
279
+ ]
280
+ return (
281
+ <div className="max-w-5xl">
282
+ <p className="text-caption text-fg-muted mb-2">
283
+ autoRowHeight=true。Note 欄位 wrap text 撐高 row。其他單行 cell 在高 row 中應頂對齊。
284
+ Click 任一 cell 進 edit:文字位置 view↔edit 不偏移(仍頂對齊),
285
+ frame 填 cell,Field 自帶 state ring(focus-within → primary)。
286
+ </p>
287
+ <DataTable
288
+ columns={cols} data={list} height="auto" autoRowHeight inlineEdit
289
+ onCellCommit={(rowId, col, val) => {
290
+ setList((prev) => prev.map((r) => r.sku === rowId ? { ...r, [col]: val as never } : r))
291
+ }}
292
+ getRowId={(r) => r.sku}
293
+ />
294
+ </div>
295
+ )
296
+ },
297
+ }
298
+
299
+ export const RowAutoHeight: Story = {
300
+ name: '自動行高',
301
+ render: () => (
302
+ <div className="flex flex-col gap-8">
303
+ <div>
304
+ <h3 className="text-body font-bold text-foreground mb-2">固定行高(預設)</h3>
305
+ <p className="text-caption text-fg-muted mb-3">所有內容垂直置中,文字截斷</p>
306
+ <DataTable columns={baseColumns} data={sampleData} height="auto" />
307
+ </div>
308
+ <div>
309
+ <h3 className="text-body font-bold text-foreground mb-2">自動行高(autoRowHeight)</h3>
310
+ <p className="text-caption text-fg-muted mb-3">內容頂部對齊,wrap 欄位可撐高 row</p>
311
+ <DataTable columns={columnsWithNote} data={dataWithNotes} height="auto" autoRowHeight />
312
+ </div>
313
+ </div>
314
+ ),
315
+ }
316
+
317
+ /* ── Empty State ── */
318
+ // 「預設空狀態」pane = 「自訂空狀態」的對照基線;Empty primitive 消費教學 canonical → anatomy.EmptyState,此處不重複教學
319
+ export const EmptyState: Story = {
320
+ name: '空狀態',
321
+ render: () => (
322
+ <div className="flex flex-col gap-8">
323
+ <div>
324
+ <h3 className="text-body font-bold text-foreground mb-2">預設空狀態</h3>
325
+ <DataTable columns={baseColumns} data={[]} />
326
+ </div>
327
+ <div>
328
+ <h3 className="text-body font-bold text-foreground mb-2">自訂空狀態</h3>
329
+ <DataTable
330
+ columns={baseColumns}
331
+ data={[]}
332
+ emptyState={
333
+ <Empty title="尚無商品" description="點擊上方「新增」開始建立" />
334
+ }
335
+ />
336
+ </div>
337
+ </div>
338
+ ),
339
+ }
340
+
341
+ /* ── Container 高度模式 — height prop(table 容器約束) ── */
342
+ // Bordered showcase retired — anatomy.BorderedProp 已 canonical 涵蓋(prop table + 何時用 false 的 rationale + 對照),showcase 純重複
343
+ export const ContainerHeight: Story = {
344
+ name: '容器高度',
345
+ render: () => {
346
+ const manyRows = React.useMemo(() => generateLargeData(50), [])
347
+ return (
348
+ <div className="flex flex-col gap-10">
349
+ <div>
350
+ <h3 className="text-body font-bold text-foreground mb-1">無約束</h3>
351
+ <p className="text-caption text-fg-muted mb-3">height="auto",table 高度完全取決於內容,不出現捲軸</p>
352
+ <DataTable columns={baseColumns} data={sampleData} height="auto" />
353
+ </div>
354
+
355
+ <div>
356
+ <h3 className="text-body font-bold text-foreground mb-1">有約束</h3>
357
+ <p className="text-caption text-fg-muted mb-3">height="300px",兩張 table 在同樣的高度上限內。資料少時只佔內容高度,資料多時撐到上限後出現捲軸</p>
358
+ <div className="grid grid-cols-2 gap-6">
359
+ <div className="bg-muted rounded-lg p-4">
360
+ <p className="text-footnote text-fg-muted mb-3">3 筆資料</p>
361
+ <DataTable columns={baseColumns} data={sampleData.slice(0, 3)} height="300px" />
362
+ </div>
363
+ <div className="bg-muted rounded-lg p-4">
364
+ <p className="text-footnote text-fg-muted mb-3">50 筆資料</p>
365
+ <DataTable columns={baseColumns} data={manyRows} height="300px" />
366
+ </div>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ )
371
+ },
372
+ }
373
+
374
+ /* ── Row Actions ── */
375
+ export const RowActions: Story = {
376
+ name: '列操作',
377
+ render: () => (
378
+ <div className="flex flex-col gap-8">
379
+ <div>
380
+ <h3 className="text-body font-bold text-foreground mb-2">Row Actions(常駐)</h3>
381
+ <p className="text-caption text-fg-muted mb-3">actions 在獨立的右側固定欄位,常駐顯示。full-height 分隔線標示 frozen 邊界。</p>
382
+ <DataTable
383
+ columns={baseColumns}
384
+ data={sampleData}
385
+ height="auto"
386
+ rowActions={() => (
387
+ <>
388
+ <Button variant="text" size="xs" iconOnly startIcon={Pencil} aria-label="編輯" />
389
+ <Button variant="text" size="xs" iconOnly startIcon={Trash2} aria-label="刪除" />
390
+ </>
391
+ )}
392
+ />
393
+ </div>
394
+ <div>
395
+ <h3 className="text-body font-bold text-foreground mb-2">3+ actions:MoreVertical 收納</h3>
396
+ <p className="text-caption text-fg-muted mb-3">前 1-2 個高頻 action inline + MoreVertical dropdown</p>
397
+ <DataTable
398
+ columns={baseColumns}
399
+ data={sampleData.slice(0, 3)}
400
+ height="auto"
401
+ rowActions={() => (
402
+ <>
403
+ <Button variant="text" size="xs" iconOnly startIcon={Pencil} aria-label="編輯" />
404
+ <Button variant="text" size="xs" iconOnly startIcon={MoreVertical} aria-label="更多操作" />
405
+ </>
406
+ )}
407
+ />
408
+ </div>
409
+ </div>
410
+ ),
411
+ }
412
+
413
+ /* ── Pinned Columns ── */
414
+ export const PinnedColumns: Story = {
415
+ name: '欄位釘選',
416
+ render: () => {
417
+ const manyRows = React.useMemo(() => generateLargeData(50), [])
418
+ return (
419
+ <div className="flex flex-col gap-8">
420
+ <div>
421
+ <h3 className="text-body font-bold text-foreground mb-2">Left pinned + Row Actions(水平捲動)</h3>
422
+ <p className="text-caption text-fg-muted mb-3">SKU 固定左側,actions 固定右側,中間水平捲動。</p>
423
+ <div style={{ maxWidth: 700 }}>
424
+ <DataTable
425
+ columns={columnsWithPrice}
426
+ data={sampleData}
427
+ height="auto"
428
+ pinnedLeftColumns={['sku']}
429
+ rowActions={() => (
430
+ <>
431
+ <Button variant="text" size="xs" iconOnly startIcon={Pencil} aria-label="編輯" />
432
+ <Button variant="text" size="xs" iconOnly startIcon={MoreVertical} aria-label="更多操作" />
433
+ </>
434
+ )}
435
+ />
436
+ </div>
437
+ </div>
438
+ <div>
439
+ <h3 className="text-body font-bold text-foreground mb-2">垂直捲動 + Pinned + Row Actions</h3>
440
+ <p className="text-caption text-fg-muted mb-3">header 固定頂部,SKU 固定左側,actions 固定右側,50 筆資料垂直捲動。</p>
441
+ <div style={{ maxWidth: 700 }}>
442
+ <DataTable
443
+ columns={columnsWithPrice}
444
+ data={manyRows}
445
+ height="300px"
446
+ pinnedLeftColumns={['sku']}
447
+ rowActions={() => (
448
+ <>
449
+ <Button variant="text" size="xs" iconOnly startIcon={Pencil} aria-label="編輯" />
450
+ <Button variant="text" size="xs" iconOnly startIcon={MoreVertical} aria-label="更多操作" />
451
+ </>
452
+ )}
453
+ />
454
+ </div>
455
+ </div>
456
+ </div>
457
+ )
458
+ },
459
+ }
460
+
461
+ /* ── Inline Edit(視覺模式)── */
462
+ /* ── Inline Edit canonical(2026-05-05 v3 user 統一):單一 story 覆蓋全 11 cell type ── */
463
+ const CATEGORY_OPTIONS = [
464
+ { value: 'Electronics', label: 'Electronics' },
465
+ { value: 'Furniture', label: 'Furniture' },
466
+ { value: 'Food', label: 'Food' },
467
+ { value: 'Lifestyle', label: 'Lifestyle' },
468
+ ]
469
+ const STOCK_OPTIONS = [
470
+ { value: 'In stock', label: 'In stock' },
471
+ { value: 'Low stock', label: 'Low stock' },
472
+ { value: 'Out of stock', label: 'Out of stock' },
473
+ ]
474
+ // 11 cell type 全覆蓋 sample(對齊 cell-registry types):string / number / currency /
475
+ // date / time / select / multiSelect / person / multiPerson / boolean / url。
476
+ const TAG_OPTIONS = [
477
+ { value: 'urgent', label: '緊急' },
478
+ { value: 'review', label: '待審' },
479
+ { value: 'archived', label: '已封存' },
480
+ ]
481
+ // SAMPLE_PEOPLE 完整 PersonData(2026-05-06 v11):每筆都有 default field values(email/phone/
482
+ // department/location)+ status + statusMessage,讓 ProfileCard hoverCard 永遠完整顯示一致。
483
+ // 對齊 ProfileCard always-render canonical(NAMECARD_DEFAULT_FIELD_KEYS SSOT)。
484
+ // **2026-05-07 v15.7**:ProfileCard default fields 改 ['id', 'employeeNumber'] only。
485
+ // Email / Phone / Department / Location 透過 `fields` array opt-in。
486
+ const SAMPLE_PEOPLE: PersonData[] = [
487
+ {
488
+ name: 'Alice Chen', avatarUrl: 'https://i.pravatar.cc/48?u=alice', description: 'Design',
489
+ id: 'AC001', employeeNumber: 'EMP-1001',
490
+ status: 'online', statusMessage: '本週設計評審,週四前 standup 移到 4pm',
491
+ fields: [
492
+ { label: 'Email', value: 'alice.chen@example.com' },
493
+ { label: 'Phone', value: '+886-2-2700-0001' },
494
+ { label: 'Department', value: 'Design / APAC' },
495
+ { label: 'Location', value: 'Taipei' },
496
+ ],
497
+ },
498
+ {
499
+ name: 'Bob Lin', avatarUrl: 'https://i.pravatar.cc/48?u=bob', description: 'Engineering',
500
+ id: 'BL002', employeeNumber: 'EMP-1002',
501
+ status: 'busy', statusMessage: 'Code review 中,訊息我會晚點回',
502
+ fields: [
503
+ { label: 'Email', value: 'bob.lin@example.com' },
504
+ { label: 'Phone', value: '+886-2-2700-0002' },
505
+ { label: 'Department', value: 'Engineering / Platform' },
506
+ { label: 'Location', value: 'Taipei' },
507
+ ],
508
+ },
509
+ {
510
+ name: 'Charlie Wu', avatarUrl: 'https://i.pravatar.cc/48?u=charlie', description: 'Product',
511
+ id: 'CWU003', employeeNumber: 'EMP-1003',
512
+ status: 'online', statusMessage: '今日 OKR 規劃日,可線上協助',
513
+ fields: [
514
+ { label: 'Email', value: 'charlie.wu@example.com' },
515
+ { label: 'Phone', value: '+852-2700-0003' },
516
+ { label: 'Department', value: 'Product / Growth' },
517
+ { label: 'Location', value: 'Hong Kong' },
518
+ ],
519
+ },
520
+ {
521
+ name: 'Diana Huang', avatarUrl: 'https://i.pravatar.cc/48?u=diana', description: 'Marketing',
522
+ id: 'DH004', employeeNumber: 'EMP-1004',
523
+ status: 'away', statusMessage: '客戶會議中,週四上午回辦公室',
524
+ fields: [
525
+ { label: 'Email', value: 'diana.huang@example.com' },
526
+ { label: 'Phone', value: '+65-6700-0004' },
527
+ { label: 'Department', value: 'Marketing / Brand' },
528
+ { label: 'Location', value: 'Singapore' },
529
+ ],
530
+ },
531
+ ]
532
+ interface EditableProduct {
533
+ sku: string
534
+ name: string
535
+ qty: number
536
+ category: string
537
+ stock: string
538
+ tags: string[]
539
+ owner: PersonData | null
540
+ reviewers: PersonData[]
541
+ inStock: boolean
542
+ url: string
543
+ price: number
544
+ releaseDate: string
545
+ reminderTime: string
546
+ }
547
+ const editableSampleData: EditableProduct[] = sampleData.slice(0, 4).map((p, i) => ({
548
+ sku: p.sku,
549
+ name: p.name,
550
+ qty: 100 + i * 12,
551
+ category: p.category,
552
+ stock: p.stock,
553
+ tags: i === 0 ? ['urgent'] : i === 1 ? ['review', 'urgent'] : i === 2 ? [] : ['archived'],
554
+ owner: SAMPLE_PEOPLE[i],
555
+ reviewers: i % 2 === 0 ? [SAMPLE_PEOPLE[(i + 1) % 4], SAMPLE_PEOPLE[(i + 2) % 4]] : [SAMPLE_PEOPLE[(i + 3) % 4]],
556
+ inStock: p.stock === 'In stock',
557
+ url: 'https://shop.example.com/' + p.sku.toLowerCase(),
558
+ price: p.price ?? 0,
559
+ releaseDate: `2025-0${(i % 9) + 1}-15`,
560
+ reminderTime: `0${9 + i}:30`,
561
+ }))
562
+
563
+ export const InlineEdit: Story = {
564
+ name: '就地編輯',
565
+ render: () => {
566
+ const [data, setData] = React.useState(editableSampleData)
567
+ const editCol = createColumnHelper<EditableProduct>()
568
+ const editableColumns = React.useMemo(
569
+ () => [
570
+ editCol.accessor('sku', { header: 'SKU', meta: { type: 'string', width: 100 } }), // 唯讀
571
+ editCol.accessor('name', { header: 'Product (string)', meta: { type: 'string', editable: true, width: 200 } }),
572
+ editCol.accessor('qty', { header: 'Qty (number)', meta: { type: 'number', editable: true, width: 110 } }),
573
+ editCol.accessor('category', { header: 'Category (select)', meta: { type: 'select', options: CATEGORY_OPTIONS, editable: true, width: 150 } }),
574
+ editCol.accessor('stock', { header: 'Stock (select)', meta: { type: 'select', options: STOCK_OPTIONS, editable: true, width: 140 } }),
575
+ editCol.accessor('tags', { header: 'Tags (multiSelect)', meta: { type: 'multiSelect', options: TAG_OPTIONS, editable: true, width: 180 } }),
576
+ editCol.accessor('owner', { header: 'Owner (person)', meta: { type: 'person', people: SAMPLE_PEOPLE, editable: true, width: 160 } }),
577
+ editCol.accessor('reviewers', { header: 'Reviewers (multiPerson)', meta: { type: 'multiPerson', people: SAMPLE_PEOPLE, editable: true, width: 180 } }),
578
+ editCol.accessor('inStock', { header: 'In (boolean)', meta: { type: 'boolean', editable: true, width: 90 } }),
579
+ editCol.accessor('url', { header: 'URL', meta: { type: 'url', editable: true, width: 180 } }),
580
+ editCol.accessor('price', { header: 'Price (currency)', meta: { type: 'currency', prefix: '$', editable: true, width: 130 } }),
581
+ editCol.accessor('releaseDate', { header: 'Release (date)', meta: { type: 'date', editable: true, width: 140 } }),
582
+ editCol.accessor('reminderTime', { header: 'Reminder (time)', meta: { type: 'time', editable: true, width: 130 } }),
583
+ ],
584
+ []
585
+ )
586
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
587
+ setData((prev) => prev.map((row) => row.sku === rowId ? { ...row, [colId]: value } : row))
588
+ }
589
+ return (
590
+ <div>
591
+ <p className="text-caption text-fg-muted mb-3">
592
+ 所有資料型別都能就地編輯:文字、數字、金額、日期、時間、單/多選、人員、人員列表、開關、連結。
593
+ SKU 是唯讀的;開關欄位直接點即可切換;連結欄位 hover 才顯示鉛筆改值,直接點開連結;
594
+ 其他點一下進編輯,Enter 或失焦存檔,Esc 取消。
595
+ </p>
596
+ <DataTable
597
+ columns={editableColumns}
598
+ data={data}
599
+ height="auto"
600
+ inlineEdit
601
+ tableOptions={{ getRowId: (row) => row.sku }}
602
+ getRowId={(row) => row.sku}
603
+ onCellCommit={handleCommit}
604
+ />
605
+ </div>
606
+ )
607
+ },
608
+ }
609
+
610
+ /**
611
+ * Slice D spreadsheet semantics + overlay 整合 demo(2026-05-10 Issue 7 移過來)。
612
+ *
613
+ * 啟 4 條 spreadsheet flag:
614
+ * 1. `inlineEdit` — base inline edit
615
+ * 2. `experimentalSpreadsheetOverlay` — hover/selected/range overlay layer(Contract 8 「one
616
+ * geometry owner, two paint owners」)
617
+ * 3. `spreadsheetMode` — Excel-like cell selection: click 1=select / click 2=edit /
618
+ * Shift+click=range / ArrowKeys=nav
619
+ * 4. `experimentalActiveEditorController` — portal Field active editor(Slice D Step 5 D.3,
620
+ * cell 永遠 mode="view" SSOT preserved + portal host renders mode="edit")
621
+ *
622
+ * 驗證點:
623
+ * - hover editable cell → 1px overlay 邊框 var(--border-hover)
624
+ * - sku(readonly)/ inStock(boolean)/ url(openAction)→ 不出現 hover overlay(Contract 15)
625
+ * - click 1 → cell selected(1px `--primary` border outline,`CELL_RING_STYLES.selected`)
626
+ * - click 2 / Enter / F2 → enter edit(portal Field, cell mode 不變)
627
+ * - Shift+click → range(focus = 1px primary outline + 內 cells `--primary-subtle` bg)
628
+ * - cell border-box 對齊(float coords 直接 pass-through 不 round / 不 snap,overlay outline
629
+ * -1px 剛好壓 cell 邊線;dtCellGrid right-edge inset divider + row border-b 共軌)
630
+ * - Issue 6 viewport clip:H scroll cell out → overlay 被 panel ClipMask 裁切不溢出
631
+ */
632
+ export const InlineEditWithSpreadsheetOverlay: Story = {
633
+ name: '就地編輯 + 試算表浮層',
634
+ render: () => {
635
+ const [data, setData] = React.useState(editableSampleData)
636
+ const editCol = createColumnHelper<EditableProduct>()
637
+ const editableColumns = React.useMemo(
638
+ () => [
639
+ editCol.accessor('sku', { header: 'SKU', meta: { type: 'string', width: 100 } }),
640
+ editCol.accessor('name', { header: 'Product', meta: { type: 'string', editable: true, width: 200 } }),
641
+ editCol.accessor('qty', { header: 'Qty', meta: { type: 'number', editable: true, width: 110 } }),
642
+ editCol.accessor('category', { header: 'Category', meta: { type: 'select', options: CATEGORY_OPTIONS, editable: true, width: 150 } }),
643
+ editCol.accessor('inStock', { header: 'In', meta: { type: 'boolean', editable: true, width: 90 } }),
644
+ editCol.accessor('url', { header: 'URL', meta: { type: 'url', editable: true, width: 180 } }),
645
+ ],
646
+ []
647
+ )
648
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
649
+ setData((prev) => prev.map((row) => row.sku === rowId ? { ...row, [colId]: value } : row))
650
+ }
651
+ return (
652
+ <div>
653
+ <p className="text-caption text-fg-muted mb-3">
654
+ 試算表式操作:第一次點 cell 選取(藍框),第二次點才進編輯。Shift+點另一格選範圍,
655
+ 方向鍵移動。Hover 可編輯的 cell 會出現淺邊框提示;唯讀 / 開關 / 連結欄位沒有 hover 提示
656
+ (這些格子不需編輯,點下去直接 toggle 或開連結)。
657
+ </p>
658
+ <DataTable
659
+ columns={editableColumns}
660
+ data={data}
661
+ height="auto"
662
+ inlineEdit
663
+ experimentalSpreadsheetOverlay
664
+ spreadsheetMode
665
+ experimentalActiveEditorController
666
+ tableOptions={{ getRowId: (row) => row.sku }}
667
+ getRowId={(row) => row.sku}
668
+ onCellCommit={handleCommit}
669
+ />
670
+ </div>
671
+ )
672
+ },
673
+ }
674
+
675
+ /**
676
+ * Issue 9 cell error system(2026-05-10):consumer-supplied `cellErrors` map shows error message
677
+ * 14px text-error 在 view content 下方,gap-1 spacing。Edit cell 自動 clear visual error。
678
+ * Multi-error 用 array → ul li 分行。aria-describedby + aria-invalid for AT。
679
+ *
680
+ * 對齊 AG Grid `cellClassRules='ag-cell-error'` + Material X-DataGrid `errorMessage` cell prop +
681
+ * Airtable record validation idiom。
682
+ */
683
+ export const CellErrors: Story = {
684
+ name: '欄位錯誤訊息',
685
+ render: () => {
686
+ const [data, setData] = React.useState(editableSampleData)
687
+ const editCol = createColumnHelper<EditableProduct>()
688
+ const editableColumns = React.useMemo(
689
+ () => [
690
+ editCol.accessor('sku', { header: 'SKU', meta: { type: 'string', width: 110 } }),
691
+ editCol.accessor('name', { header: 'Product', meta: { type: 'string', editable: true, width: 240 } }),
692
+ editCol.accessor('qty', { header: 'Qty', meta: { type: 'number', editable: true, width: 110 } }),
693
+ editCol.accessor('category', { header: 'Category', meta: { type: 'select', options: CATEGORY_OPTIONS, editable: true, width: 160 } }),
694
+ ],
695
+ []
696
+ )
697
+ // Demo cellErrors map(consumer 自管 state;edit commit 後可清 / 加 error)
698
+ const [cellErrors, setCellErrors] = React.useState<Record<string, string | string[]>>({
699
+ 'PRD-001:name': '必填欄位:Product 名稱不可為空白',
700
+ 'PRD-002:qty': ['必須 ≥ 0', '必須是整數(目前小數)'],
701
+ 'PRD-003:category': '選擇的分類已不在 active catalog,請改選有效項目',
702
+ })
703
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
704
+ setData((prev) => prev.map((row) => row.sku === rowId ? { ...row, [colId]: value } : row))
705
+ // 範例:commit 後 clear 該 cell error
706
+ setCellErrors((prev) => {
707
+ const next = { ...prev }
708
+ delete next[`${rowId}:${colId}`]
709
+ return next
710
+ })
711
+ }
712
+ return (
713
+ <div className="flex flex-col gap-3 max-w-4xl">
714
+ <p className="text-caption text-fg-muted">
715
+ 欄位驗證錯誤直接顯示在內容下方,不蓋住資料。一格多個錯誤分行條列。點進該格編輯時暫時隱藏錯誤,
716
+ 交給使用者修正;commit 後由 app 端決定是否還要顯示。
717
+ </p>
718
+ {/* 2026-05-10 fix(user 第二次糾正):restore `autoRowHeight` — 原本 story 用全表
719
+ auto-row 是正確 baseline,error row 自然撐高 + 其他 row 仍 auto(內容驅動)。 */}
720
+ <DataTable
721
+ columns={editableColumns}
722
+ data={data}
723
+ height="auto"
724
+ inlineEdit
725
+ autoRowHeight
726
+ getRowId={(row) => row.sku}
727
+ tableOptions={{ getRowId: (row) => row.sku }}
728
+ onCellCommit={handleCommit}
729
+ cellErrors={cellErrors}
730
+ />
731
+ </div>
732
+ )
733
+ },
734
+ }
735
+
736
+ /**
737
+ * 固定行高表格遇到欄位錯誤時的特殊行為(2026-05-10 per user 確認 ask):
738
+ * 整個 table 預設 fixed 行高,但**任一格出現錯誤訊息的那一 row 會自動撐高**(改成 auto)讓
739
+ * 訊息完整顯示。其他沒錯誤的 row 維持 fixed 高度不受影響。錯誤被修掉之後該 row 自動回 fixed。
740
+ * 這是 per-row 行為,不是整表切換 mode。
741
+ */
742
+ export const CellErrorsFixedRowOverride: Story = {
743
+ name: '欄位錯誤訊息(固定行高 + 逐列撐高)',
744
+ render: () => {
745
+ const [data, setData] = React.useState(editableSampleData)
746
+ const editCol = createColumnHelper<EditableProduct>()
747
+ const editableColumns = React.useMemo(
748
+ () => [
749
+ editCol.accessor('sku', { header: 'SKU', meta: { type: 'string', width: 110 } }),
750
+ editCol.accessor('name', { header: 'Product', meta: { type: 'string', editable: true, width: 240 } }),
751
+ editCol.accessor('qty', { header: 'Qty', meta: { type: 'number', editable: true, width: 110 } }),
752
+ editCol.accessor('category', { header: 'Category', meta: { type: 'select', options: CATEGORY_OPTIONS, editable: true, width: 160 } }),
753
+ ],
754
+ []
755
+ )
756
+ const [cellErrors, setCellErrors] = React.useState<Record<string, string | string[]>>({
757
+ 'PRD-001:name': '必填欄位:Product 名稱不可為空白',
758
+ 'PRD-003:category': '選擇的分類已不在 active catalog,請改選有效項目',
759
+ })
760
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
761
+ setData((prev) => prev.map((row) => row.sku === rowId ? { ...row, [colId]: value } : row))
762
+ setCellErrors((prev) => {
763
+ const next = { ...prev }
764
+ delete next[`${rowId}:${colId}`]
765
+ return next
766
+ })
767
+ }
768
+ return (
769
+ <div className="flex flex-col gap-3 max-w-4xl">
770
+ <p className="text-caption text-fg-muted">
771
+ 表格本身是固定行高(沒開 autoRowHeight),但 PRD-001 跟 PRD-003 有錯誤訊息 → 這兩 row
772
+ 自動撐高顯示訊息;PRD-002、PRD-004 沒錯誤,維持原本的固定行高,內容垂直置中。
773
+ 觀察 row 之間高度差,以及同一 row 內所有 cell 對齊一致(撐高 row 全頂對齊,固定 row 全置中)。
774
+ </p>
775
+ <DataTable
776
+ columns={editableColumns}
777
+ data={data}
778
+ height="auto"
779
+ inlineEdit
780
+ getRowId={(row) => row.sku}
781
+ tableOptions={{ getRowId: (row) => row.sku }}
782
+ onCellCommit={handleCommit}
783
+ cellErrors={cellErrors}
784
+ />
785
+ </div>
786
+ )
787
+ },
788
+ }
789
+
790
+ /* ── Nested rows (tree-table) ── */
791
+ interface TaskRow {
792
+ id: string
793
+ task: string
794
+ owner: string
795
+ status: string
796
+ children?: TaskRow[]
797
+ }
798
+ const NESTED_DATA: TaskRow[] = [
799
+ {
800
+ id: 'task-1',
801
+ task: 'Q1 行銷活動',
802
+ owner: 'Alice Wang',
803
+ status: 'In progress',
804
+ children: [
805
+ {
806
+ id: 'task-1-1',
807
+ task: '社群素材設計',
808
+ owner: 'Bob Chen',
809
+ status: 'Done',
810
+ children: [
811
+ { id: 'task-1-1-1', task: 'Instagram post 設計', owner: 'Bob Chen', status: 'Done' },
812
+ { id: 'task-1-1-2', task: 'Facebook cover 設計', owner: 'Bob Chen', status: 'Done' },
813
+ ],
814
+ },
815
+ { id: 'task-1-2', task: 'KOL 合作協調', owner: 'Carol Liu', status: 'In progress' },
816
+ { id: 'task-1-3', task: '預算審核', owner: 'Alice Wang', status: 'Blocked' },
817
+ ],
818
+ },
819
+ {
820
+ id: 'task-2',
821
+ task: 'Q2 產品上架',
822
+ owner: 'David Wu',
823
+ status: 'Not started',
824
+ children: [
825
+ { id: 'task-2-1', task: '產品文案撰寫', owner: 'Carol Liu', status: 'Not started' },
826
+ { id: 'task-2-2', task: 'SKU 設定', owner: 'David Wu', status: 'Not started' },
827
+ ],
828
+ },
829
+ ]
830
+
831
+ const NESTED_STATUS_OPTIONS = [
832
+ { value: 'Not started', label: 'Not started' },
833
+ { value: 'In progress', label: 'In progress' },
834
+ { value: 'Blocked', label: 'Blocked' },
835
+ { value: 'Done', label: 'Done' },
836
+ ]
837
+ const nestedTaskColumn = createColumnHelper<TaskRow>()
838
+ const NESTED_COLUMNS = [
839
+ nestedTaskColumn.accessor('task', { header: '任務', meta: { type: 'string', width: 360 } }),
840
+ nestedTaskColumn.accessor('owner', { header: '負責人', meta: { type: 'string', width: 160 } }),
841
+ nestedTaskColumn.accessor('status', { header: '狀態', meta: { type: 'select', options: NESTED_STATUS_OPTIONS, width: 140 } }),
842
+ ]
843
+
844
+ export const NestedRows: Story = {
845
+ name: '巢狀列(樹狀表格)',
846
+ render: () => {
847
+ const [expanded, setExpanded] = React.useState<Record<string, boolean>>({ 'task-1': true, 'task-1-1': true })
848
+ return (
849
+ <div>
850
+ {/* 實作:forward TanStack getSubRows;縮排共用 --tree-indent-{sm,md,lg} token(跨 TreeView
851
+ 設計語言);chevron click stopPropagation 不觸發 row select。 */}
852
+ <p className="text-caption text-fg-muted mb-3">
853
+ 樹狀表格:點列首的三角形展開 / 收合子任務,子任務逐層縮排(與 TreeView 同一套縮排節奏);
854
+ 點三角形只切換展開,不會順帶選取整列。
855
+ </p>
856
+ <DataTable
857
+ columns={NESTED_COLUMNS}
858
+ data={NESTED_DATA}
859
+ height="auto"
860
+ getRowId={(row) => row.id}
861
+ selectable
862
+ tableOptions={{
863
+ getSubRows: (row: TaskRow) => row.children,
864
+ getRowCanExpand: (row) => Boolean(row.original.children?.length),
865
+ state: { expanded },
866
+ onExpandedChange: setExpanded as any,
867
+ }}
868
+ />
869
+ </div>
870
+ )
871
+ },
872
+ }
873
+
874
+ export const NestedRowsExpanderHoverState: Story = {
875
+ name: '巢狀列展開鈕:滑鼠移過狀態',
876
+ tags: ['test-only'],
877
+ render: () => {
878
+ const [expanded, setExpanded] = React.useState<Record<string, boolean>>({})
879
+ return (
880
+ <div className="max-w-3xl p-6">
881
+ <p className="text-caption text-fg-secondary mb-3">
882
+ 真實滑鼠停在第一列的展開鈕,驗證弱化圖示只前進一階到次要文字色。
883
+ </p>
884
+ <DataTable
885
+ columns={NESTED_COLUMNS}
886
+ data={NESTED_DATA}
887
+ height="auto"
888
+ getRowId={(row) => row.id}
889
+ tableOptions={{
890
+ getSubRows: (row: TaskRow) => row.children,
891
+ getRowCanExpand: (row) => Boolean(row.original.children?.length),
892
+ state: { expanded },
893
+ onExpandedChange: setExpanded as any,
894
+ }}
895
+ />
896
+ </div>
897
+ )
898
+ },
899
+ play: ({ canvasElement }) => {
900
+ const canvas = within(canvasElement)
901
+ const expander = canvas.getAllByRole('button', { name: '展開' })[0]
902
+ expect(expander).toHaveAttribute('aria-expanded', 'false')
903
+ // play 只做 deterministic target selection;真 hover 完全由 visual-audit
904
+ // 的 Playwright locator.hover() 擁有,避免 synthetic userEvent 假綠。
905
+ expander.dataset.visualHoverTarget = 'true'
906
+ expect(canvasElement.querySelectorAll('[data-visual-hover-target]')).toHaveLength(1)
907
+ },
908
+ }
909
+
910
+ /* ── 巢狀 row × 拖曳重排(tree-table drag)──
911
+ Tree drag 設計準則(2026-05-06 v14.7,對齊 spec.md「Cross-parent drop 禁止」)
912
+ - **Top-level rows**:有 drag handle(absolute pinned to row left edge),可拖重排
913
+ - **Sub-rows**(`row.depth > 0`):**無 handle**,不可拖(設計保守對齊 Notion)
914
+ - **Cross-parent drop**:過濾,顯 invalid signal(handle cursor `not-allowed`)
915
+ - **Drop indicator**:水平 2px primary line(top/bottom)— 主檔對齊 TreeView */
916
+ export const NestedRowsWithDrag: Story = {
917
+ name: '巢狀列 × 拖曳重排',
918
+ render: () => {
919
+ const [expanded, setExpanded] = React.useState<Record<string, boolean>>({ 'task-1': true })
920
+ const [list, setList] = React.useState<TaskRow[]>(NESTED_DATA)
921
+ const handleReorder = (sourceId: string, targetId: string, position: 'before' | 'after') => {
922
+ setList((prev) => {
923
+ // top-level reorder only(sub-rows 不可拖)
924
+ const sourceIdx = prev.findIndex((r) => r.id === sourceId)
925
+ const targetIdx = prev.findIndex((r) => r.id === targetId)
926
+ if (sourceIdx === -1 || targetIdx === -1) return prev
927
+ const next = [...prev]
928
+ const [moved] = next.splice(sourceIdx, 1)
929
+ const adjustedTarget = next.findIndex((r) => r.id === targetId)
930
+ const insertAt = position === 'before' ? adjustedTarget : adjustedTarget + 1
931
+ next.splice(insertAt, 0, moved)
932
+ return next
933
+ })
934
+ }
935
+ return (
936
+ <div className="flex flex-col gap-3 max-w-3xl">
937
+ <p className="text-caption text-fg-muted">
938
+ Tree-table drag 設計準則:top-level rows 可拖(handle 浮在 row 左緣),
939
+ sub-rows 無 handle 不可拖(對齊 Notion 保守)。Cross-parent drop 過濾,
940
+ 顯 invalid signal。Drop indicator 水平 2px primary line — 主檔對齊 TreeView。
941
+ </p>
942
+ <DataTable
943
+ columns={NESTED_COLUMNS}
944
+ data={list}
945
+ height="auto"
946
+ getRowId={(row) => row.id}
947
+ enableRowDrag
948
+ onRowReorder={handleReorder}
949
+ tableOptions={{
950
+ getSubRows: (row: TaskRow) => row.children,
951
+ getRowCanExpand: (row) => Boolean(row.original.children?.length),
952
+ state: { expanded },
953
+ onExpandedChange: setExpanded as any,
954
+ }}
955
+ />
956
+ </div>
957
+ )
958
+ },
959
+ }
960
+
961
+ /* ── 虛擬捲動(大量資料)── */
962
+ export const VirtualScroll: Story = {
963
+ name: '大量資料',
964
+ render: () => {
965
+ const largeData = React.useMemo(() => generateLargeData(10000), [])
966
+ return (
967
+ <DataTable
968
+ columns={columnsWithPrice}
969
+ data={largeData}
970
+ height="500px"
971
+ overscan={10}
972
+ />
973
+ )
974
+ },
975
+ }
976
+
977
+ /* ── L2 Selection — DataTable + BulkActionBar inline composition(canonical) ──
978
+ 保留 toolbar 功能(filter / sort / search 在選取期間仍可用)— 對齊 Linear / Notion /
979
+ Apple Mail / iOS Files / ref 圖 additive 派
980
+
981
+ 排版設計準則(本 showcase):
982
+ - Toolbar:左 search input / 右 ops 群(Gmail / Linear / Notion idiom)
983
+ - 各 chrome 元件 self-pad px-loose;table mx-loose 對齊 chrome 內容左右邊界
984
+ - bordered=true(height="100%" 為垂直滾動 trigger,per spec)
985
+ - Alert variant="neutral"(資訊性 hint,非 info hue) */
986
+ // Issue 3(2026-05-10):VisibilityRow inline helper retired — 移到
987
+ // `<DataTableColumnVisibilityPanel>` primitive 內部(SSOT)。
988
+
989
+ export const WithBulkActions: Story = {
990
+ name: '選取 + 批次操作',
991
+ parameters: { layout: 'fullscreen' },
992
+ render: () => {
993
+ const [selection, setSelection] = React.useState<DataTableSelection>({ mode: 'include', ids: [] })
994
+ const [search, setSearch] = React.useState('')
995
+ const [columnVisibility, setColumnVisibility] = React.useState<Record<string, boolean>>({})
996
+ // Issue 3(2026-05-10):columnSearch 移到 `<DataTableColumnVisibilityPanel>` 內 own,
997
+ // story 不再 hold;columnOrder 仍 hold(table 跟 panel 共用同 state)。
998
+ const [columnOrder, setColumnOrder] = React.useState<string[]>(() =>
999
+ baseColumns.map((c) => (c as any).accessorKey ?? (c as any).id)
1000
+ )
1001
+ const [sorting, setSorting] = React.useState<SortingState>([])
1002
+ const [filterTree, setFilterTree] = React.useState<FilterTree>(() => createEmptyFilterTree('flat'))
1003
+ const [filterPrefilledId, setFilterPrefilledId] = React.useState<string | undefined>(undefined)
1004
+ const [filterOpen, setFilterOpen] = React.useState(false)
1005
+ const [sortOpen, setSortOpen] = React.useState(false)
1006
+ const TOTAL = 5370
1007
+ const filteredData = React.useMemo(
1008
+ () => search ? sampleData.filter(p => p.name.toLowerCase().includes(search.toLowerCase()) || p.sku.toLowerCase().includes(search.toLowerCase())) : sampleData,
1009
+ [search]
1010
+ )
1011
+ const VISIBLE = filteredData.length
1012
+ // 反向選取(inverted)showcase:include 全可見已選且 dataset 更大 → offer「選取全部 M」;
1013
+ // all 模式 → 顯示「已選取全部 M(排除 K)」。count = M − excluded(consumer 端計算)。
1014
+ const isAll = selection.mode === 'all'
1015
+ const visibleIds = filteredData.map((p) => p.sku)
1016
+ const selectedCount = isAll ? TOTAL - selection.excluded.length : selection.ids.length
1017
+ const visibleSelectedIds = isAll
1018
+ ? visibleIds.filter((id) => !selection.excluded.includes(id))
1019
+ : selection.ids.filter((id) => visibleIds.includes(id))
1020
+ const allVisibleSelected = VISIBLE > 0 && visibleSelectedIds.length === VISIBLE
1021
+ const showHint = isAll || (allVisibleSelected && TOTAL > VISIBLE)
1022
+
1023
+ return (
1024
+ // 撐滿 parent(layout=fullscreen);
1025
+ // toolbar 自帶 py = toolbar→table 間距(無父 gap);table→底部 chrome group = loose(footer 呼吸 canonical)
1026
+ <div className="flex flex-col w-full h-screen bg-canvas">
1027
+ {/* Toolbar — 左 search / 右 ops(Gmail / Linear / Notion idiom)*/}
1028
+ <div className="flex items-center justify-between gap-2 px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]">
1029
+ <div className="flex-1 max-w-sm">
1030
+ <Input
1031
+ size="sm"
1032
+ placeholder="搜尋商品 / SKU"
1033
+ value={search}
1034
+ onChange={(e) => setSearch(e.target.value)}
1035
+ startIcon={Search}
1036
+ />
1037
+ </div>
1038
+ <div className="flex items-center gap-2">
1039
+ {/* L3 Filter:global panel(ClickUp / Airtable / Notion 派 — flat conditions MVP)
1040
+ pressed prop:套用條件後 trigger 維持 active 視覺(toggle pressed,Button 設計準則) */}
1041
+ <Popover open={filterOpen} onOpenChange={setFilterOpen}>
1042
+ <PopoverTrigger asChild>
1043
+ <Button variant="text" size="sm" iconOnly startIcon={Filter} aria-label="篩選" pressed={isFilterTreeActive(filterTree)} />
1044
+ </PopoverTrigger>
1045
+ <PopoverContent align="end" className="w-auto p-0">
1046
+ <DataTableFilterPanel
1047
+ columns={baseColumns}
1048
+ value={filterTree}
1049
+ onChange={setFilterTree}
1050
+ prefilledColumnId={filterPrefilledId}
1051
+ onPrefillConsumed={() => setFilterPrefilledId(undefined)}
1052
+ onClose={() => setFilterOpen(false)}
1053
+ />
1054
+ </PopoverContent>
1055
+ </Popover>
1056
+ {/* L3 Sort:global panel(Notion-style 多欄條件)
1057
+ pressed prop:套用條件後 trigger 維持 active 視覺 */}
1058
+ <Popover open={sortOpen} onOpenChange={setSortOpen}>
1059
+ <PopoverTrigger asChild>
1060
+ <Button variant="text" size="sm" iconOnly startIcon={ArrowUpDown} aria-label="排序" pressed={sorting.length > 0} />
1061
+ </PopoverTrigger>
1062
+ <PopoverContent align="end" className="w-auto p-0">
1063
+ <DataTableSortManager
1064
+ columns={baseColumns}
1065
+ sorting={sorting}
1066
+ onSortingChange={setSorting}
1067
+ onReset={() => setSorting([])}
1068
+ onClose={() => setSortOpen(false)}
1069
+ />
1070
+ </PopoverContent>
1071
+ </Popover>
1072
+ {/* L3 column visibility:Popover panel(對齊 Notion / Airtable column-settings panel)
1073
+ 標題 / search input / column list with Checkbox / Show all
1074
+ drag-reorder 留 A.4(跟 column reorder 一起做)*/}
1075
+ <Popover>
1076
+ <PopoverTrigger asChild>
1077
+ <Button variant="text" size="sm" iconOnly startIcon={Eye} aria-label="欄位顯示" />
1078
+ </PopoverTrigger>
1079
+ <PopoverContent align="end" className="w-72 p-0">
1080
+ {/* Issue 3(2026-05-10):從 inline 149-line panel 改用 SSOT primitive
1081
+ `<DataTableColumnVisibilityPanel>`(全 feature flag opt-in:search +
1082
+ reset + DnD reorder + lock)。SKU 永遠鎖在第一位 = `lockedIds=['sku']`。 */}
1083
+ <DataTableColumnVisibilityPanel
1084
+ columns={baseColumns.map((c) => ({
1085
+ id: ((c as any).accessorKey ?? (c as any).id) as string,
1086
+ label: typeof (c as any).header === 'string' ? (c as any).header : ((c as any).accessorKey ?? (c as any).id),
1087
+ }))}
1088
+ visibility={columnVisibility}
1089
+ onVisibilityChange={setColumnVisibility}
1090
+ columnOrder={columnOrder}
1091
+ onColumnOrderChange={setColumnOrder}
1092
+ lockedIds={['sku']}
1093
+ searchable
1094
+ resettable
1095
+ />
1096
+ </PopoverContent>
1097
+ </Popover>
1098
+ <Button variant="primary" size="sm" startIcon={Plus}>新增商品</Button>
1099
+ <Button variant="text" size="sm" iconOnly startIcon={MoreVertical} aria-label="更多" />
1100
+ </div>
1101
+ </div>
1102
+
1103
+ {/* DataTable — bordered=true(height 約束 = 垂直滾動 trigger,per spec line 150)
1104
+ mx-loose:水平 padding(規則 1)
1105
+ mb-loose:fw → 容器底 / viewport 底 / 底部 chrome 都是 loose(規則 4)— 永遠保留底部呼吸,不貼邊 */}
1106
+ <div className="flex-1 min-h-0 mx-[var(--layout-space-loose)] mb-[var(--layout-space-loose)]">
1107
+ <DataTable
1108
+ columns={baseColumns}
1109
+ data={filteredData}
1110
+ height="100%"
1111
+ selectable
1112
+ selection={selection}
1113
+ onSelectionChange={setSelection}
1114
+ columnVisibility={columnVisibility}
1115
+ onColumnVisibilityChange={setColumnVisibility}
1116
+ getRowId={(row) => row.sku}
1117
+ onColumnFilterTrigger={(columnId) => {
1118
+ setFilterPrefilledId(columnId)
1119
+ setFilterOpen(true)
1120
+ }}
1121
+ tableOptions={{
1122
+ state: { sorting, globalFilter: filterTree, columnOrder },
1123
+ onColumnOrderChange: (updater) => {
1124
+ setColumnOrder(typeof updater === 'function' ? updater(columnOrder) : updater)
1125
+ },
1126
+ onSortingChange: (updater) => {
1127
+ setSorting(typeof updater === 'function' ? updater(sorting) : updater)
1128
+ },
1129
+ onGlobalFilterChange: setFilterTree,
1130
+ globalFilterFn: (row, _columnId, t: FilterTree) => evaluateTree(t, row.original),
1131
+ getFilteredRowModel: getFilteredRowModel(),
1132
+ }}
1133
+ />
1134
+ </div>
1135
+
1136
+ {/* 底部 chrome group(撤回前一版 absolute overlay,2026-05-04 user 抓 BulkActionBar 沒底色 + 蓋表底列 regression):
1137
+ 回 flex flow 自然推 table。Q7 mount-time growth 真因 = virtualizer estimateRowHeight ≠ token,已在 DataTable 內修(estimate size-aware) */}
1138
+ {(showHint || selectedCount > 0) && (
1139
+ <div className="flex flex-col">
1140
+ {showHint && (
1141
+ <Alert
1142
+ variant="neutral"
1143
+ placement="fixed"
1144
+ dismissible={false}
1145
+ title={
1146
+ isAll ? (
1147
+ <>
1148
+ 已選取全部 {TOTAL} 個項目{selection.excluded.length > 0 ? `(排除 ${selection.excluded.length} 個)` : ''}。{' '}
1149
+ <button
1150
+ type="button"
1151
+ onClick={() => setSelection({ mode: 'include', ids: [] })}
1152
+ className="text-primary hover:text-primary-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-sm"
1153
+ >
1154
+ 清除選取項目
1155
+ </button>
1156
+ </>
1157
+ ) : (
1158
+ <>
1159
+ 已選取本頁全部 {selectedCount} 個。{' '}
1160
+ <button
1161
+ type="button"
1162
+ onClick={() => setSelection({ mode: 'all', excluded: [] })}
1163
+ className="text-primary hover:text-primary-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-sm"
1164
+ >
1165
+ 點此選取全部 {TOTAL} 個項目
1166
+ </button>
1167
+ </>
1168
+ )
1169
+ }
1170
+ />
1171
+ )}
1172
+ {selectedCount > 0 && (
1173
+ <BulkActionBar
1174
+ selection={visibleSelectedIds}
1175
+ totalSelected={selectedCount}
1176
+ onClearSelection={() => setSelection({ mode: 'include', ids: [] })}
1177
+ actions={
1178
+ <>
1179
+ <Button variant="tertiary" size="md" startIcon={Download}>下載</Button>
1180
+ <Button variant="tertiary" size="md" startIcon={Trash2}>移除</Button>
1181
+ </>
1182
+ }
1183
+ />
1184
+ )}
1185
+ </div>
1186
+ )}
1187
+ </div>
1188
+ )
1189
+ },
1190
+ }
1191
+
1192
+ /* ── L2 Selection — Shift-click + 鍵盤(Cmd+A / Esc)── */
1193
+ export const SelectionKeyboardAndShift: Story = {
1194
+ name: '範圍選取與鍵盤',
1195
+ render: () => {
1196
+ const [selection, setSelection] = React.useState<string[]>([])
1197
+ const data = generateLargeData(15)
1198
+ return (
1199
+ <div className="flex flex-col gap-2 max-w-4xl">
1200
+ <p className="text-caption text-fg-muted">
1201
+ 試試:點第一 row checkbox → <kbd>Shift</kbd>+點第五 row → 1-5 全選 ·
1202
+ 整 table 點任意 row 後按 <kbd>Cmd/Ctrl+A</kbd> 全選 · 按 <kbd>Esc</kbd> 清除 ·
1203
+ checkbox focus 時按 <kbd>Space</kbd> 帶 <kbd>Shift</kbd> 也能擴選。
1204
+ </p>
1205
+ <div className="text-caption font-mono text-fg-muted">selection: {JSON.stringify(selection)}</div>
1206
+ <DataTable
1207
+ columns={baseColumns}
1208
+ data={data}
1209
+ height="400px"
1210
+ selectable
1211
+ selection={selection}
1212
+ onSelectionChange={(s) => setSelection(s.mode === 'include' ? s.ids : [])}
1213
+ getRowId={(row) => row.sku}
1214
+ />
1215
+ </div>
1216
+ )
1217
+ },
1218
+ }
1219
+
1220
+ /* ── L2 Selection — Single mode(每次只選一個)── */
1221
+ export const SelectionSingleMode: Story = {
1222
+ name: '單選模式',
1223
+ render: () => {
1224
+ const [selection, setSelection] = React.useState<string[]>([])
1225
+ return (
1226
+ <div className="flex flex-col gap-2 max-w-4xl">
1227
+ <p className="text-caption text-fg-muted">
1228
+ <code>selectable=&quot;single&quot;</code>:每次只選一個,點新 row 自動清舊 row。
1229
+ 視覺用 <strong>Radio</strong>(對齊 Material DataGrid / Polaris IndexTable 共識),
1230
+ header checkbox 抑制(single 沒「全選」概念)。
1231
+ </p>
1232
+ <div className="text-caption font-mono text-fg-muted">selected: {selection[0] ?? '(none)'}</div>
1233
+ <DataTable
1234
+ columns={baseColumns}
1235
+ data={sampleData}
1236
+ height="auto"
1237
+ selectable="single"
1238
+ selection={selection}
1239
+ onSelectionChange={(s) => setSelection(s.mode === 'include' ? s.ids : [])}
1240
+ getRowId={(row) => row.sku}
1241
+ />
1242
+ </div>
1243
+ )
1244
+ },
1245
+ }
1246
+
1247
+ /* ── L2 Selection — disabled rows + filter 互動 ── */
1248
+ export const SelectionDisabledRows: Story = {
1249
+ name: '不可選取的列',
1250
+ render: () => {
1251
+ const [selection, setSelection] = React.useState<string[]>([])
1252
+ return (
1253
+ <div className="flex flex-col gap-2 max-w-4xl">
1254
+ <p className="text-caption text-fg-muted">
1255
+ Out of stock 商品不可選 — 只 disable checkbox,row 內容正常 render(對齊 spec L2 五)。
1256
+ </p>
1257
+ <DataTable
1258
+ columns={baseColumns}
1259
+ data={sampleData}
1260
+ height="auto"
1261
+ selectable
1262
+ selection={selection}
1263
+ onSelectionChange={(s) => setSelection(s.mode === 'include' ? s.ids : [])}
1264
+ getRowId={(row) => row.sku}
1265
+ isRowSelectable={(row) => row.stock !== 'Out of stock'}
1266
+ />
1267
+ </div>
1268
+ )
1269
+ },
1270
+ }
1271
+
1272
+ /* ────────────────────────────────────────────────────────────────────────────
1273
+ 進階篩選(Filter Panel)— 2026-05-04 從 data-table-filter-panel.stories.tsx
1274
+ inline 過來,sidebar 收斂於 DataTable/展示 同一層(Q1 設計準則)
1275
+ ──────────────────────────────────────────────────────────────────────────── */
1276
+
1277
+ const FILTER_COLUMNS = [
1278
+ col.accessor('sku', { header: 'SKU', meta: { type: 'string', filterable: true } }),
1279
+ col.accessor('name', { header: '名稱', meta: { type: 'string', filterable: true } }),
1280
+ col.accessor('category', { header: '類別', meta: {
1281
+ type: 'select', filterable: true,
1282
+ options: [
1283
+ { value: 'Electronics', label: 'Electronics' },
1284
+ { value: 'Furniture', label: 'Furniture' },
1285
+ { value: 'Food', label: 'Food' },
1286
+ { value: 'Lifestyle', label: 'Lifestyle' },
1287
+ ],
1288
+ }}),
1289
+ col.accessor('stock', { header: '庫存', meta: { type: 'select', filterable: true,
1290
+ options: [
1291
+ { value: 'In stock', label: 'In stock' },
1292
+ { value: 'Low stock', label: 'Low stock' },
1293
+ { value: 'Out of stock', label: 'Out of stock' },
1294
+ ],
1295
+ }}),
1296
+ // 2026-05-07 v15.3:加 seller(person column)demo,讓 user 在 FilterPanel demo 中
1297
+ // 看見 PeoplePicker filter UI 真實渲染(否則 picker render 但 people pool=undefined → 選項空)。
1298
+ col.accessor('seller', { header: '負責人', meta: { type: 'person', filterable: true, people: SELLERS } }),
1299
+ col.accessor('updatedAt', { header: '更新時間', meta: { type: 'date', filterable: true, includeTime: true } }),
1300
+ ] as const
1301
+
1302
+ const FILTER_COLUMNS_ENGLISH = [
1303
+ col.accessor('name', { header: 'Name', meta: { type: 'string', filterable: true } }),
1304
+ col.accessor('category', { header: 'Category', meta: {
1305
+ type: 'select',
1306
+ filterable: true,
1307
+ options: [
1308
+ { value: 'Electronics', label: 'Electronics' },
1309
+ { value: 'Furniture', label: 'Furniture' },
1310
+ ],
1311
+ } }),
1312
+ col.accessor('seller', { header: 'Owner', meta: {
1313
+ type: 'person',
1314
+ filterable: true,
1315
+ people: SELLERS,
1316
+ } }),
1317
+ col.accessor('updatedAt', { header: 'Updated at', meta: { type: 'date', filterable: true } }),
1318
+ ] as const
1319
+
1320
+ const FILTER_CHILD_PICKER_COLUMNS = [
1321
+ col.accessor('category', { header: 'Category', meta: {
1322
+ type: 'select',
1323
+ filterable: true,
1324
+ options: [],
1325
+ } }),
1326
+ col.accessor('seller', { header: 'Owner', meta: {
1327
+ type: 'person',
1328
+ filterable: true,
1329
+ people: [],
1330
+ } }),
1331
+ ] as const
1332
+
1333
+ const FILTER_PANEL_ENGLISH_LABELS: Partial<DataTableFilterPanelLabels> = {
1334
+ title: 'Filters',
1335
+ resetToDefault: 'Reset to default',
1336
+ close: 'Close',
1337
+ where: 'Where',
1338
+ and: 'And',
1339
+ or: 'Or',
1340
+ conjunctionAriaLabel: 'Conjunction for this group',
1341
+ fieldPlaceholder: 'Choose field',
1342
+ fieldAriaLabel: 'Filter field',
1343
+ operatorPlaceholder: 'Operator',
1344
+ operatorAriaLabel: 'Filter operator',
1345
+ valuePlaceholder: 'Enter value…',
1346
+ numberPlaceholder: 'Enter number…',
1347
+ relativeDatePlaceholder: 'Choose relative date',
1348
+ singleSelectPlaceholder: 'Choose value',
1349
+ multiSelectPlaceholder: 'Choose values…',
1350
+ multiSelectEmptyText: 'No matching values',
1351
+ peoplePlaceholder: 'Choose people',
1352
+ peopleSearchPlaceholder: 'Search people…',
1353
+ peopleSearchAriaLabel: 'Search filter people',
1354
+ peopleEmptyText: 'No matching people',
1355
+ filterValueAriaLabel: (columnLabel) => columnLabel ? `${columnLabel} filter value` : 'Filter value',
1356
+ deleteCondition: 'Delete condition',
1357
+ addFilter: 'Add filter',
1358
+ addGroup: 'Add filter group',
1359
+ addNestedFilter: 'Add nested filter',
1360
+ removeEmptyGroup: 'Remove empty group',
1361
+ operatorLabels: {
1362
+ contains: 'contains',
1363
+ does_not_contain: 'does not contain',
1364
+ is: 'is',
1365
+ is_not: 'is not',
1366
+ starts_with: 'starts with',
1367
+ ends_with: 'ends with',
1368
+ equals: 'equals',
1369
+ not_equals: 'does not equal',
1370
+ gt: 'is greater than',
1371
+ gte: 'is greater than or equal to',
1372
+ lt: 'is less than',
1373
+ lte: 'is less than or equal to',
1374
+ is_before: 'is before',
1375
+ is_after: 'is after',
1376
+ is_on_or_before: 'is on or before',
1377
+ is_on_or_after: 'is on or after',
1378
+ is_between: 'is between',
1379
+ is_relative: 'is relative',
1380
+ has_any_of: 'has any of',
1381
+ has_all_of: 'has all of',
1382
+ has_none_of: 'has none of',
1383
+ is_set: 'is set',
1384
+ is_not_set: 'is not set',
1385
+ is_true: 'is checked',
1386
+ is_false: 'is not checked',
1387
+ },
1388
+ relativeDateGroupLabels: {
1389
+ past: 'Past',
1390
+ current: 'Current',
1391
+ future: 'Future',
1392
+ },
1393
+ relativeDateOptionLabels: {
1394
+ past_30_days: 'Past 30 days',
1395
+ past_7_days: 'Past 7 days',
1396
+ last_month: 'Last month',
1397
+ last_week: 'Last week',
1398
+ yesterday: 'Yesterday',
1399
+ today: 'Today',
1400
+ this_week: 'This week',
1401
+ this_month: 'This month',
1402
+ tomorrow: 'Tomorrow',
1403
+ next_week: 'Next week',
1404
+ next_month: 'Next month',
1405
+ next_7_days: 'Next 7 days',
1406
+ next_30_days: 'Next 30 days',
1407
+ },
1408
+ }
1409
+
1410
+ /* ── 進階篩選 — 空狀態 ── */
1411
+ export const FilterPanelEmpty: Story = {
1412
+ name: '進階篩選 — 空狀態',
1413
+ render: () => {
1414
+ const [value, setValue] = React.useState<FilterTree>(() => createEmptyFilterTree('flat'))
1415
+ return (
1416
+ <div className="w-full max-w-[680px]">
1417
+ <DataTableFilterPanel
1418
+ columns={[...FILTER_COLUMNS]}
1419
+ value={value}
1420
+ onChange={setValue}
1421
+
1422
+ />
1423
+ </div>
1424
+ )
1425
+ },
1426
+ }
1427
+
1428
+ /* ── 進階篩選 — 已填條件 ── */
1429
+ export const FilterPanelWithConditions: Story = {
1430
+ name: '進階篩選 — 已填條件',
1431
+ render: () => {
1432
+ const [value, setValue] = React.useState<FilterTree>(() => ({
1433
+ mode: 'flat', conjunction: 'and',
1434
+ children: [
1435
+ { kind: 'cond', id: 'c1', field: 'name', op: 'contains', value: 'phone' },
1436
+ { kind: 'cond', id: 'c2', field: 'category', op: 'is', value: ['Electronics'] },
1437
+ { kind: 'cond', id: 'c3', field: 'stock', op: 'is', value: ['In stock'] },
1438
+ ],
1439
+ }))
1440
+ return (
1441
+ <div className="w-full max-w-[680px]">
1442
+ <DataTableFilterPanel
1443
+ columns={[...FILTER_COLUMNS]}
1444
+ value={value}
1445
+ onChange={setValue}
1446
+
1447
+ />
1448
+ </div>
1449
+ )
1450
+ },
1451
+ }
1452
+
1453
+ /* ── 進階篩選 — 巢狀群組 ── */
1454
+ export const FilterPanelNested: Story = {
1455
+ name: '進階篩選 — 巢狀群組',
1456
+ render: () => {
1457
+ const [value, setValue] = React.useState<FilterTree>(() => ({
1458
+ mode: 'nested', conjunction: 'or',
1459
+ children: [
1460
+ {
1461
+ kind: 'group', id: 'g1', conjunction: 'and',
1462
+ children: [
1463
+ { kind: 'cond', id: 'c1', field: 'category', op: 'is', value: ['Electronics'] },
1464
+ { kind: 'cond', id: 'c2', field: 'stock', op: 'is', value: ['In stock'] },
1465
+ ],
1466
+ },
1467
+ {
1468
+ kind: 'group', id: 'g2', conjunction: 'and',
1469
+ children: [
1470
+ { kind: 'cond', id: 'c3', field: 'category', op: 'is', value: ['Furniture'] },
1471
+ { kind: 'cond', id: 'c4', field: 'stock', op: 'is', value: ['Low stock'] },
1472
+ ],
1473
+ },
1474
+ ],
1475
+ }))
1476
+ return (
1477
+ <div className="w-full max-w-[680px]">
1478
+ <DataTableFilterPanel
1479
+ columns={[...FILTER_COLUMNS]}
1480
+ value={value}
1481
+ onChange={setValue}
1482
+
1483
+ />
1484
+ </div>
1485
+ )
1486
+ },
1487
+ }
1488
+
1489
+ /* ── 進階篩選 — 相對時間群組 ── */
1490
+ export const FilterPanelRelativeDate: Story = {
1491
+ name: '進階篩選 — 相對時間群組',
1492
+ render: () => {
1493
+ const [value, setValue] = React.useState<FilterTree>(() => ({
1494
+ mode: 'flat', conjunction: 'and',
1495
+ children: [
1496
+ { kind: 'cond', id: 'c1', field: 'updatedAt', op: 'is_relative', value: 'past_7_days' },
1497
+ ],
1498
+ }))
1499
+ return (
1500
+ <div className="w-full max-w-[680px]">
1501
+ <p className="text-caption text-fg-muted mb-3">時間下拉分 過去 / 目前 / 未來 三組(Linear/Notion 共識)。</p>
1502
+ <DataTableFilterPanel
1503
+ columns={[...FILTER_COLUMNS]}
1504
+ value={value}
1505
+ onChange={setValue}
1506
+
1507
+ />
1508
+ </div>
1509
+ )
1510
+ },
1511
+ }
1512
+
1513
+ /* ── 進階篩選 — 已改動(refresh icon)── */
1514
+ export const FilterPanelModified: Story = {
1515
+ name: '進階篩選 — 已改動',
1516
+ render: () => {
1517
+ const initial: FilterTree = {
1518
+ mode: 'flat', conjunction: 'and',
1519
+ children: [{ kind: 'cond', id: 'c1', field: 'category', op: 'is', value: ['Electronics'] }],
1520
+ }
1521
+ const modified: FilterTree = {
1522
+ mode: 'flat', conjunction: 'and',
1523
+ children: [{ kind: 'cond', id: 'c1', field: 'category', op: 'is', value: ['Furniture'] }],
1524
+ }
1525
+ const [value, setValue] = React.useState<FilterTree>(modified)
1526
+ return (
1527
+ <div className="w-full max-w-[680px]">
1528
+ <p className="text-caption text-fg-muted mb-3">值偏離 default 時 header 出現 ↻ — 點擊 reset 回 default。</p>
1529
+ <DataTableFilterPanel
1530
+ columns={[...FILTER_COLUMNS]}
1531
+ value={value}
1532
+ defaultValue={initial}
1533
+ onChange={setValue}
1534
+
1535
+ />
1536
+ </div>
1537
+ )
1538
+ },
1539
+ }
1540
+
1541
+ /* ── 進階篩選 — 長標籤溢出 ── */
1542
+ export const FilterPanelLongTagOverflow: Story = {
1543
+ name: '進階篩選 — 長標籤溢出',
1544
+ render: () => {
1545
+ // 製造業 ERP 的產品分類名稱普遍很長 — 示範多選後 Combobox tag 溢出時的 +N 摘要收斂
1546
+ const longLabelColumns = [
1547
+ col.accessor('category', {
1548
+ header: '類別',
1549
+ meta: { type: 'select', filterable: true, options: [
1550
+ { value: 'Heavy Industrial Manufacturing Equipment', label: 'Heavy Industrial Manufacturing Equipment' },
1551
+ { value: 'Premium Consumer Electronics & Accessories', label: 'Premium Consumer Electronics & Accessories' },
1552
+ { value: 'Sustainable Organic Food & Beverage Products', label: 'Sustainable Organic Food & Beverage Products' },
1553
+ { value: 'Lifestyle Home & Garden Decoration', label: 'Lifestyle Home & Garden Decoration' },
1554
+ ] },
1555
+ }),
1556
+ ]
1557
+ const [value, setValue] = React.useState<FilterTree>(() => ({
1558
+ mode: 'flat', conjunction: 'and',
1559
+ children: [
1560
+ { kind: 'cond', id: 'c1', field: 'category', op: 'is', value: [
1561
+ 'Heavy Industrial Manufacturing Equipment',
1562
+ 'Premium Consumer Electronics & Accessories',
1563
+ 'Sustainable Organic Food & Beverage Products',
1564
+ ]},
1565
+ ],
1566
+ }))
1567
+ return (
1568
+ <div className="w-full max-w-[680px]">
1569
+ <p className="text-caption text-fg-muted mb-3">產品分類名稱很長(製造業 ERP 常見)時,已選的多個標籤超出單行寬度,Combobox 自動收斂為 +N 摘要。</p>
1570
+ <DataTableFilterPanel
1571
+ columns={[...longLabelColumns]}
1572
+ value={value}
1573
+ onChange={setValue}
1574
+ />
1575
+ </div>
1576
+ )
1577
+ },
1578
+ }
1579
+
1580
+ const FilterPanelLabelsAndLimitHarness = () => {
1581
+ const [childPickerLabels, setChildPickerLabels] = React.useState<FilterTree>({
1582
+ mode: 'flat',
1583
+ conjunction: 'and',
1584
+ children: [
1585
+ { kind: 'cond', id: 'labels-category', field: 'category', op: 'is', value: [] },
1586
+ { kind: 'cond', id: 'labels-owner', field: 'seller', op: 'is', value: [] },
1587
+ ],
1588
+ })
1589
+ const [flat, setFlat] = React.useState<FilterTree>({
1590
+ mode: 'flat',
1591
+ conjunction: 'and',
1592
+ children: [
1593
+ { kind: 'cond', id: 'flat-1', field: 'updatedAt', op: 'is_relative', value: 'past_7_days' },
1594
+ ],
1595
+ })
1596
+ const [nestedCondition, setNestedCondition] = React.useState<FilterTree>({
1597
+ mode: 'nested',
1598
+ conjunction: 'and',
1599
+ children: [{
1600
+ kind: 'group',
1601
+ id: 'nested-condition-group',
1602
+ conjunction: 'and',
1603
+ children: [{ kind: 'cond', id: 'nested-condition-1', field: 'name', op: 'contains', value: 'phone' }],
1604
+ }],
1605
+ })
1606
+ const [nestedGroup, setNestedGroup] = React.useState<FilterTree>({
1607
+ mode: 'nested',
1608
+ conjunction: 'and',
1609
+ children: [{
1610
+ kind: 'group',
1611
+ id: 'nested-group-1',
1612
+ conjunction: 'and',
1613
+ children: [{ kind: 'cond', id: 'nested-group-cond-1', field: 'name', op: 'contains', value: 'phone' }],
1614
+ }],
1615
+ })
1616
+ const [mountCapZero, setMountCapZero] = React.useState<FilterTree>(() => createEmptyFilterTree('flat'))
1617
+ const [prefillValue, setPrefillValue] = React.useState<FilterTree>({
1618
+ mode: 'flat',
1619
+ conjunction: 'and',
1620
+ children: [{ kind: 'cond', id: 'prefill-1', field: 'name', op: 'contains', value: 'phone' }],
1621
+ })
1622
+ const [prefilledColumnId, setPrefilledColumnId] = React.useState<string | undefined>('category')
1623
+ const [prefillConsumed, setPrefillConsumed] = React.useState(false)
1624
+
1625
+ return (
1626
+ <div className="flex flex-col gap-10">
1627
+ <div data-testid="filter-label-child-pickers">
1628
+ <h3 className="text-body font-medium mb-2">English child-picker labels</h3>
1629
+ <DataTableFilterPanel
1630
+ columns={[...FILTER_CHILD_PICKER_COLUMNS]}
1631
+ value={childPickerLabels}
1632
+ onChange={setChildPickerLabels}
1633
+ maxConditions={2}
1634
+ labels={FILTER_PANEL_ENGLISH_LABELS}
1635
+ />
1636
+ </div>
1637
+
1638
+ <div data-testid="filter-limit-flat">
1639
+ <h3 className="text-body font-medium mb-2">English labels + flat cap</h3>
1640
+ <DataTableFilterPanel
1641
+ columns={[...FILTER_COLUMNS_ENGLISH]}
1642
+ value={flat}
1643
+ onChange={setFlat}
1644
+ maxConditions={2}
1645
+ labels={FILTER_PANEL_ENGLISH_LABELS}
1646
+ />
1647
+ </div>
1648
+
1649
+ <div data-testid="filter-limit-nested-condition">
1650
+ <h3 className="text-body font-medium mb-2">Nested condition cap</h3>
1651
+ <DataTableFilterPanel
1652
+ columns={[...FILTER_COLUMNS_ENGLISH]}
1653
+ value={nestedCondition}
1654
+ onChange={setNestedCondition}
1655
+ maxConditions={2}
1656
+ labels={FILTER_PANEL_ENGLISH_LABELS}
1657
+ />
1658
+ </div>
1659
+
1660
+ <div data-testid="filter-limit-nested-group">
1661
+ <h3 className="text-body font-medium mb-2">Nested group cap</h3>
1662
+ <DataTableFilterPanel
1663
+ columns={[...FILTER_COLUMNS_ENGLISH]}
1664
+ value={nestedGroup}
1665
+ onChange={setNestedGroup}
1666
+ maxConditions={2}
1667
+ labels={FILTER_PANEL_ENGLISH_LABELS}
1668
+ />
1669
+ </div>
1670
+
1671
+ <div data-testid="filter-limit-mount-zero">
1672
+ <h3 className="text-body font-medium mb-2">Initial mount at zero capacity</h3>
1673
+ <DataTableFilterPanel
1674
+ columns={[...FILTER_COLUMNS_ENGLISH]}
1675
+ value={mountCapZero}
1676
+ onChange={setMountCapZero}
1677
+ maxConditions={0}
1678
+ labels={FILTER_PANEL_ENGLISH_LABELS}
1679
+ />
1680
+ </div>
1681
+
1682
+ <div data-testid="filter-limit-prefill">
1683
+ <h3 className="text-body font-medium mb-2">Prefill at capacity</h3>
1684
+ <p data-testid="prefill-consumed" className="text-caption text-fg-secondary mb-2">
1685
+ Prefill consumed: {prefillConsumed ? 'yes' : 'no'}
1686
+ </p>
1687
+ <DataTableFilterPanel
1688
+ columns={[...FILTER_COLUMNS_ENGLISH]}
1689
+ value={prefillValue}
1690
+ onChange={setPrefillValue}
1691
+ prefilledColumnId={prefilledColumnId}
1692
+ onPrefillConsumed={() => {
1693
+ setPrefilledColumnId(undefined)
1694
+ setPrefillConsumed(true)
1695
+ }}
1696
+ maxConditions={1}
1697
+ labels={FILTER_PANEL_ENGLISH_LABELS}
1698
+ />
1699
+ </div>
1700
+ </div>
1701
+ )
1702
+ }
1703
+
1704
+ export const FilterPanelLabelsAndLimit: Story = {
1705
+ name: '進階篩選 — 標籤與條件上限',
1706
+ render: () => <FilterPanelLabelsAndLimitHarness />,
1707
+ play: async ({ canvasElement }) => {
1708
+ const canvas = within(canvasElement)
1709
+ const page = within(canvasElement.ownerDocument.body)
1710
+
1711
+ const childPickers = within(canvas.getByTestId('filter-label-child-pickers'))
1712
+ const categoryValue = childPickers.getByRole('combobox', { name: 'Category filter value' })
1713
+ await expect(categoryValue).toHaveTextContent('Choose values…')
1714
+ await userEvent.click(categoryValue)
1715
+ await expect(page.getAllByText('No matching values')).toHaveLength(2)
1716
+ await userEvent.keyboard('{Escape}')
1717
+
1718
+ await userEvent.click(childPickers.getByRole('combobox', { name: 'Owner filter value' }))
1719
+ const peopleSearch = await page.findByPlaceholderText('Search people…')
1720
+ await expect(peopleSearch).toHaveAccessibleName('Search filter people')
1721
+ await expect(page.getAllByText('No matching people')).toHaveLength(2)
1722
+ await userEvent.keyboard('{Escape}')
1723
+
1724
+ const flat = within(canvas.getByTestId('filter-limit-flat'))
1725
+ await expect(flat.getByText('Filters')).toBeInTheDocument()
1726
+ await expect(flat.getByText('Where')).toBeInTheDocument()
1727
+ await expect(flat.getByText('is relative')).toBeInTheDocument()
1728
+ await expect(flat.getByText('Past 7 days')).toBeInTheDocument()
1729
+ await userEvent.click(flat.getByRole('button', { name: 'Add filter' }))
1730
+ await waitFor(() => expect(flat.getAllByLabelText('Filter field')).toHaveLength(2))
1731
+ await expect(flat.getByRole('button', { name: 'Add filter' })).toBeDisabled()
1732
+
1733
+ const nestedCondition = within(canvas.getByTestId('filter-limit-nested-condition'))
1734
+ await userEvent.click(nestedCondition.getByRole('button', { name: 'Add nested filter' }))
1735
+ await waitFor(() => expect(nestedCondition.getAllByLabelText('Filter field')).toHaveLength(2))
1736
+ await expect(nestedCondition.getByRole('button', { name: 'Add nested filter' })).toBeDisabled()
1737
+ await expect(nestedCondition.getByRole('button', { name: 'Add filter group' })).toBeDisabled()
1738
+
1739
+ const nestedGroup = within(canvas.getByTestId('filter-limit-nested-group'))
1740
+ await userEvent.click(nestedGroup.getByRole('button', { name: 'Add filter group' }))
1741
+ await waitFor(() => expect(nestedGroup.getAllByLabelText('Filter field')).toHaveLength(2))
1742
+ for (const button of nestedGroup.getAllByRole('button', { name: 'Add nested filter' })) {
1743
+ await expect(button).toBeDisabled()
1744
+ }
1745
+ await expect(nestedGroup.getByRole('button', { name: 'Add filter group' })).toBeDisabled()
1746
+
1747
+ const mountCapZero = within(canvas.getByTestId('filter-limit-mount-zero'))
1748
+ await expect(mountCapZero.queryAllByLabelText('Filter field')).toHaveLength(0)
1749
+ await expect(mountCapZero.getByRole('button', { name: 'Add filter' })).toBeDisabled()
1750
+
1751
+ const prefill = within(canvas.getByTestId('filter-limit-prefill'))
1752
+ await waitFor(() => expect(prefill.getByTestId('prefill-consumed')).toHaveTextContent('yes'))
1753
+ await expect(prefill.getAllByLabelText('Filter field')).toHaveLength(1)
1754
+ await expect(prefill.getByRole('button', { name: 'Add filter' })).toBeDisabled()
1755
+ },
1756
+ }
1757
+
1758
+ /* ── 列拖曳重排(Jira-style + 3-panel pinned columns)──────────────────────
1759
+ enableRowDrag + onRowReorder 整合範例(v3 Jira 設計準則):
1760
+ - handle 浮在 row 左緣(fixed-position;Button tertiary iconOnly xs = elevated chip)
1761
+ - 不佔 column 空間 — table 看起來乾淨,沒有預留拖曳欄位
1762
+ - hover row → handle 浮現(JS 控 opacity)
1763
+ - 拖曳 row → @dnd-kit/core useDraggable + useDroppable(v15.0 Path B);放下 → onRowReorder(sourceId, targetId, 'before' | 'after')
1764
+ - consumer 自管 data array mutation(同 Notion / Airtable / Linear pattern)
1765
+ - sort 啟用時 drag handle 自動 disabled + Tooltip 解釋
1766
+ - pinned-left + pinned-right 同時存在 → source 留原位,2px drop indicator 跨三 region 同步標示落點
1767
+ (per-region useDraggable / useDroppable,不 auto-shift) */
1768
+ export const RowDragInteractive: Story = {
1769
+ name: '列拖曳重排(含釘選欄)',
1770
+ render: () => {
1771
+ const [list, setList] = React.useState<Product[]>(sampleData)
1772
+ const handleReorder = (sourceId: string, targetId: string, position: 'before' | 'after') => {
1773
+ setList((prev) => {
1774
+ const sourceIdx = prev.findIndex((r) => r.sku === sourceId)
1775
+ const targetIdx = prev.findIndex((r) => r.sku === targetId)
1776
+ if (sourceIdx === -1 || targetIdx === -1) return prev
1777
+ const next = [...prev]
1778
+ const [moved] = next.splice(sourceIdx, 1)
1779
+ // splice 後 target 可能位移,重算
1780
+ const adjustedTarget = next.findIndex((r) => r.sku === targetId)
1781
+ const insertAt = position === 'before' ? adjustedTarget : adjustedTarget + 1
1782
+ next.splice(insertAt, 0, moved)
1783
+ return next
1784
+ })
1785
+ }
1786
+ return (
1787
+ <div className="flex flex-col gap-3 max-w-3xl">
1788
+ <p className="text-caption text-fg-muted">
1789
+ handle 浮在 row 左緣(不佔 column 空間,Jira 設計準則)。pinned-left(SKU)+ pinned-right(Updated)+
1790
+ center 中段欄。拖曳時 source 列留在原位(半透明壓住視覺),2px 主色落點提示線在左固定欄、
1791
+ 中段、右固定欄三區同步標出,其他列不會先行讓位。
1792
+ </p>
1793
+ <DataTable
1794
+ columns={columnsWithPrice}
1795
+ data={list}
1796
+ height="auto"
1797
+ getRowId={(row) => row.sku}
1798
+ pinnedLeftColumns={['sku']}
1799
+ pinnedRightColumns={['updatedAt']}
1800
+ enableRowDrag
1801
+ onRowReorder={handleReorder}
1802
+ />
1803
+ </div>
1804
+ )
1805
+ },
1806
+ }
1807
+
1808
+ /* ── 列拖曳 × 虛擬捲動(200 列)────────────────────────────────────────────
1809
+ v3 fix(2026-05-05)— scroll bug 修法:
1810
+ 1. enableRowDrag 時 overscan 自動拉到 Math.max(overscan, 5)(避免 row unmount 時 useDraggable/useDroppable subscription 跟著
1811
+ 消失導致 dnd-kit stale lookup → 拖到該 id 視覺錯位)
1812
+ 2. drag 進行中(activeDragId != null)整個略過 measureElement(任一 row 重新量測會跟 dnd-kit
1813
+ transform 競爭,長 list 累積錯位)
1814
+ 3. DndContext modifier 用 snapToCursorModifier(ghost top-left 對齊 cursor,不鎖軸)— row drag
1815
+ 期間 ghost 跟隨游標
1816
+ - 200 列 + 固定高度 → virtualizer 啟用
1817
+ - 拖曳長距離 + 持續往下捲 → 視覺位置仍對齊,放下後 onRowReorder 收到正確 sourceId / targetId */
1818
+ export const RowDragWithVirtualization: Story = {
1819
+ name: '列拖曳 × 虛擬捲動',
1820
+ render: () => {
1821
+ const [list, setList] = React.useState<Product[]>(() => generateLargeData(200))
1822
+ const handleReorder = (sourceId: string, targetId: string, position: 'before' | 'after') => {
1823
+ setList((prev) => {
1824
+ const sourceIdx = prev.findIndex((r) => r.sku === sourceId)
1825
+ const targetIdx = prev.findIndex((r) => r.sku === targetId)
1826
+ if (sourceIdx === -1 || targetIdx === -1) return prev
1827
+ const next = [...prev]
1828
+ const [moved] = next.splice(sourceIdx, 1)
1829
+ const adjustedTarget = next.findIndex((r) => r.sku === targetId)
1830
+ const insertAt = position === 'before' ? adjustedTarget : adjustedTarget + 1
1831
+ next.splice(insertAt, 0, moved)
1832
+ return next
1833
+ })
1834
+ }
1835
+ return (
1836
+ <div className="flex flex-col gap-3 max-w-3xl">
1837
+ {/* 實作(v3):enableRowDrag 自動拉高 overscan ≥ 5;drag 期間 freeze measureElement;
1838
+ snapToCursorModifier 讓 ghost 對齊游標(不鎖軸)— 三者合修「拖曳 + 捲動錯位」。 */}
1839
+ <p className="text-caption text-fg-muted">
1840
+ 200 列 + 虛擬捲動:拖住一列往下捲動,浮影一路跟著游標,落點在長清單任何位置都能正確對齊。
1841
+ </p>
1842
+ <DataTable
1843
+ columns={baseColumns}
1844
+ data={list}
1845
+ height="500px"
1846
+ getRowId={(row) => row.sku}
1847
+ enableRowDrag
1848
+ onRowReorder={handleReorder}
1849
+ />
1850
+ </div>
1851
+ )
1852
+ },
1853
+ }
1854
+
1855
+ /* ────────────────────────────────────────────────────────────────────────────
1856
+ * RoadmapInteractive — Slice A RFC §Demo deliverable(per S5 codex feedback +
1857
+ * USER #50 verbatim「DataTable demo 就可以開始做了啊」+ codex 2026-05-10 review red-light fixes)。
1858
+ *
1859
+ * 場景:Product Initiative Roadmap(Q2 2026 PM OKR)。13 column 全 cell type 覆蓋。
1860
+ *
1861
+ * Cell type:string(readonly id + editable title)/ select(status / priority)/
1862
+ * multiSelect(tags)/ person(owner)/ multiPerson(reviewers)/
1863
+ * date(start / due)/ number(progress / hours)/ url(spec)/ boolean(shipped)
1864
+ *
1865
+ * World-class M22 cite(per codex review,2026-05-10):
1866
+ * - Linear Display options: https://linear.app/docs/display-options
1867
+ * - Asana Custom fields: https://developers.asana.com/docs/custom-fields-guide
1868
+ * - Jira Product Discovery fields reference: https://support.atlassian.com/jira-product-discovery/docs/jira-product-discovery-fields-reference/
1869
+ * ──────────────────────────────────────────────────────────────────────────── */
1870
+
1871
+ interface RoadmapItem {
1872
+ id: string
1873
+ title: string
1874
+ status: 'not-started' | 'in-progress' | 'blocked' | 'done' | 'cancelled'
1875
+ priority: 'P0' | 'P1' | 'P2' | 'P3'
1876
+ owner: PersonData
1877
+ reviewers: PersonData[]
1878
+ tags: string[]
1879
+ startDate: string
1880
+ dueDate: string
1881
+ progress: number
1882
+ spec: string
1883
+ hours: number
1884
+ /** Standup time(per user 2026-05-10 「補一個會出現 timepicker 的欄位」)。HH:MM 格式 */
1885
+ standup: string
1886
+ /** Nested sub-tasks(per Issue 7 nested rows requirement, 2026-05-10)*/
1887
+ children?: RoadmapItem[]
1888
+ }
1889
+
1890
+ const STATUS_OPTIONS = [
1891
+ { value: 'not-started', label: '未開始' },
1892
+ { value: 'in-progress', label: '進行中' },
1893
+ { value: 'blocked', label: '受阻' },
1894
+ { value: 'done', label: '完成' },
1895
+ { value: 'cancelled', label: '取消' },
1896
+ ]
1897
+
1898
+ const PRIORITY_OPTIONS = [
1899
+ { value: 'P0', label: 'P0', tagVariant: 'red' as const },
1900
+ { value: 'P1', label: 'P1', tagVariant: 'orange' as const },
1901
+ { value: 'P2', label: 'P2', tagVariant: 'yellow' as const },
1902
+ { value: 'P3', label: 'P3', tagVariant: 'neutral' as const },
1903
+ ]
1904
+
1905
+ const TAG_LABELS = [
1906
+ { value: 'design', label: 'design' },
1907
+ { value: 'frontend', label: 'frontend' },
1908
+ { value: 'backend', label: 'backend' },
1909
+ { value: 'qa', label: 'qa' },
1910
+ { value: 'ops', label: 'ops' },
1911
+ { value: 'docs', label: 'docs' },
1912
+ { value: 'mobile', label: 'mobile' },
1913
+ { value: 'spike', label: 'spike' },
1914
+ ]
1915
+
1916
+ const ROADMAP_DATA: RoadmapItem[] = [
1917
+ { id: 'RDM-001', title: '結帳流程改版 v2', status: 'in-progress', priority: 'P0', owner: SELLERS[0], reviewers: [SELLERS[1], SELLERS[2]], tags: ['frontend', 'design'], startDate: '2026-04-01', dueDate: '2026-05-30', progress: 65, spec: 'https://notion.so/checkout-v2', hours: 120, standup: '10:00' },
1918
+ { id: 'RDM-002', title: '會員忠誠度系統', status: 'not-started', priority: 'P1', owner: SELLERS[1], reviewers: [SELLERS[3]], tags: ['backend', 'spike'], startDate: '2026-05-15', dueDate: '2026-07-30', progress: 0, spec: 'https://notion.so/loyalty', hours: 0, standup: '10:00' },
1919
+ { id: 'RDM-003', title: '行動端 push 通知', status: 'blocked', priority: 'P1', owner: SELLERS[2], reviewers: [SELLERS[0], SELLERS[4]], tags: ['mobile', 'backend'], startDate: '2026-04-15', dueDate: '2026-06-15', progress: 30, spec: 'https://notion.so/push', hours: 45, standup: '10:00' },
1920
+ { id: 'RDM-004', title: '搜尋 SEO 優化', status: 'done', priority: 'P2', owner: SELLERS[3], reviewers: [SELLERS[2]], tags: ['frontend', 'docs'], startDate: '2026-02-01', dueDate: '2026-04-01', progress: 100, spec: 'https://notion.so/seo', hours: 80, standup: '10:00' },
1921
+ { id: 'RDM-005', title: '客服 CSAT 儀表板', status: 'in-progress', priority: 'P2', owner: SELLERS[4], reviewers: [SELLERS[5]], tags: ['frontend', 'design', 'docs'], startDate: '2026-04-10', dueDate: '2026-05-25', progress: 50, spec: 'https://notion.so/csat-dashboard', hours: 65, standup: '10:00' },
1922
+ { id: 'RDM-006', title: '物流即時追蹤', status: 'not-started', priority: 'P3', owner: SELLERS[5], reviewers: [SELLERS[1]], tags: ['backend', 'qa'], startDate: '2026-06-01', dueDate: '2026-09-15', progress: 0, spec: 'https://notion.so/tracking', hours: 0, standup: '10:00' },
1923
+ { id: 'RDM-007', title: 'A/B 測試平台', status: 'cancelled', priority: 'P3', owner: SELLERS[0], reviewers: [], tags: ['ops', 'spike'], startDate: '2026-03-01', dueDate: '2026-05-01', progress: 15, spec: 'https://notion.so/ab-test', hours: 20, standup: '10:00' },
1924
+ { id: 'RDM-008', title: 'Dark mode 全站支援', status: 'in-progress', priority: 'P2', owner: SELLERS[1], reviewers: [SELLERS[0], SELLERS[3]], tags: ['frontend', 'design'], startDate: '2026-04-20', dueDate: '2026-06-10', progress: 75, spec: 'https://notion.so/dark-mode', hours: 90, standup: '10:00' },
1925
+ ]
1926
+
1927
+ // 大量 roadmap row 衍生用的真實工作範疇後綴(避免 "(#N)" 佔位符計數)
1928
+ const ROADMAP_SCOPES = ['行動版', '桌面版', 'API 層', '後台管理', '資料遷移', '效能優化', '無障礙改善', '國際化', '監控告警', '權限控管']
1929
+
1930
+ // Roadmap shared columns helper(主 demo + 5 stress stories 共用)
1931
+ function useRoadmapColumns() {
1932
+ const col = createColumnHelper<RoadmapItem>()
1933
+ return React.useMemo(
1934
+ () => [
1935
+ col.accessor('id', { header: 'ID', meta: { type: 'string', width: 100 } }),
1936
+ col.accessor('title', { header: '標題', meta: { type: 'string', editable: true, width: 240 } }),
1937
+ col.accessor('status', { header: '狀態', meta: { type: 'select', options: STATUS_OPTIONS, editable: true, width: 130 } }),
1938
+ col.accessor('priority', { header: '優先級', meta: { type: 'select', options: PRIORITY_OPTIONS, editable: true, width: 100 } }),
1939
+ col.accessor('owner', { header: '負責人', meta: { type: 'person', people: SELLERS, editable: true, width: 160 } }),
1940
+ col.accessor('reviewers', { header: '審核', meta: { type: 'multiPerson', people: SELLERS, editable: true, width: 140 } }),
1941
+ col.accessor('tags', { header: '標籤', meta: { type: 'multiSelect', options: TAG_LABELS, editable: true, width: 200 } }),
1942
+ col.accessor('startDate', { header: '開始', meta: { type: 'date', editable: true, width: 120 } }),
1943
+ col.accessor('dueDate', { header: '截止', meta: { type: 'date', editable: true, width: 120 } }),
1944
+ col.accessor('progress', { header: '進度%', meta: { type: 'number', editable: true, width: 100 } }),
1945
+ col.accessor('spec', { header: '規格', meta: { type: 'url', editable: true, width: 180 } }),
1946
+ col.accessor('hours', { header: '工時', meta: { type: 'number', editable: true, width: 90 } }),
1947
+ // 2026-05-10(per user 補 timepicker 欄位):time column type 用 standup HH:MM
1948
+ col.accessor('standup', { header: '站立', meta: { type: 'time', editable: true, width: 100 } }),
1949
+ // 已出(shipped boolean)retired per user directive 2026-05-10
1950
+ ],
1951
+ []
1952
+ )
1953
+ }
1954
+
1955
+ /**
1956
+ * **單一整合 demo**(2026-05-10 user 拍板「全部合起來放在同一個範例方便我檢查」+ codex Layer B
1957
+ * 比稿 confirm「one primary integrated demo」):取代 6 個分散 stories(原 RoadmapInteractive +
1958
+ * 5 stress stories: Pinned / AllSizes / SpreadsheetOverlay / Selection / BigData)。
1959
+ *
1960
+ * 整合所有 DataTable 主功能,模擬真實 product UI(無 inner title / 無 demo description,
1961
+ * 對齊 user 圖4 reference「整個範例看起來是真實的」+ codex Q4.2 confirm):
1962
+ * - Search(consumer-side filter via Input)
1963
+ * - Filter panel(DataTableFilterPanel + evaluateTree)
1964
+ * - Sort manager(DataTableSortManager 多欄條件)
1965
+ * - Column visibility(Popover + checkbox per column)
1966
+ * - Selection + bulk actions(BulkActionBar)
1967
+ * - Pinned columns(left=id,right=shipped)
1968
+ * - Spreadsheet overlay(experimentalSpreadsheetOverlay + Contract 8/15)
1969
+ * - 500 rows + virtualization(per fold-in BigData)
1970
+ * - Inline edit(per Contract 12)
1971
+ *
1972
+ * Play function assertion(virtualization invariant per codex Q-3):500 rows + 固定高 →
1973
+ * rendered rows ≤ 30(VIRTUAL_THRESHOLD + overscan;非全 500)。從原 RoadmapBigData fold 進。
1974
+ *
1975
+ * Layer C dissent vs codex Layer B:codex 建議 retain BigData 獨立,Layer A own DISAGREE
1976
+ * 採 user explicit「全部合起來」— play assertion fold 進整合 demo 不另留 separate story。
1977
+ */
1978
+ export const RoadmapAllInOne: Story = {
1979
+ name: '專案排程全功能整合',
1980
+ parameters: { layout: 'fullscreen' },
1981
+ render: () => {
1982
+ // 500 top-level rows derived from ROADMAP_DATA(fold-in BigData per codex Q4.1 + user 整合 ask)。
1983
+ // **Issue 7(2026-05-10):前 8 rows 補 sub-tasks** 展示 nested row tree-table — 其餘 row 維持 flat
1984
+ // 確保 virtualization invariant 仍在 500-row scale 驗證。
1985
+ const bigData = React.useMemo(() => {
1986
+ const arr: RoadmapItem[] = []
1987
+ for (let i = 0; i < 500; i++) {
1988
+ const base = ROADMAP_DATA[i % ROADMAP_DATA.length]
1989
+ const id = `RDM-${String(i + 100).padStart(3, '0')}`
1990
+ const item: RoadmapItem = {
1991
+ ...base,
1992
+ id,
1993
+ title: `${base.title} — ${ROADMAP_SCOPES[i % ROADMAP_SCOPES.length]}`,
1994
+ }
1995
+ // 前 8 個 top row 補 sub-tasks(展示 nested row + drag canonical:top-level only)
1996
+ if (i < 8) {
1997
+ item.children = [
1998
+ { ...base, id: `${id}-1`, title: `${base.title}:介面設計與前端實作`, progress: Math.min(100, base.progress + 10), hours: Math.max(0, Math.floor(base.hours / 3)) },
1999
+ { ...base, id: `${id}-2`, title: `${base.title}:API 整合與 QA 驗收`, progress: Math.max(0, base.progress - 10), hours: Math.max(0, Math.floor(base.hours / 4)) },
2000
+ ]
2001
+ }
2002
+ arr.push(item)
2003
+ }
2004
+ return arr
2005
+ }, [])
2006
+ const [data, setData] = React.useState(bigData)
2007
+ const columns = useRoadmapColumns()
2008
+ const [search, setSearch] = React.useState('')
2009
+ const [selection, setSelection] = React.useState<string[]>([])
2010
+ const [columnVisibility, setColumnVisibility] = React.useState<Record<string, boolean>>({})
2011
+ const [sorting, setSorting] = React.useState<SortingState>([])
2012
+ const [filterTree, setFilterTree] = React.useState<FilterTree>(() => createEmptyFilterTree('flat'))
2013
+ const [filterOpen, setFilterOpen] = React.useState(false)
2014
+ const [sortOpen, setSortOpen] = React.useState(false)
2015
+ // Issue 7:nested row expansion state(預設展開前 2 個 top-row 的 sub-tasks)
2016
+ const [expanded, setExpanded] = React.useState<Record<string, boolean>>({ 'RDM-100': true, 'RDM-101': true })
2017
+ // Issue 7:column order(enableColumnReorder 用 controlled state,DnD 後 setColumnOrder)
2018
+ const [columnOrder, setColumnOrder] = React.useState<string[]>([])
2019
+
2020
+ // Search consumer-side filter(per codex Q4.3「Search not a DataTable prop;
2021
+ // story implements consumer-side filtering」)。Filter / sort 走 TanStack state。
2022
+ const filteredData = React.useMemo(
2023
+ () => search
2024
+ ? data.filter(r => r.title.toLowerCase().includes(search.toLowerCase()) || r.id.toLowerCase().includes(search.toLowerCase()))
2025
+ : data,
2026
+ [data, search]
2027
+ )
2028
+
2029
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
2030
+ const updateRow = (rows: RoadmapItem[]): RoadmapItem[] =>
2031
+ rows.map((r) => {
2032
+ if (r.id === rowId) return { ...r, [colId]: value }
2033
+ if (r.children) return { ...r, children: updateRow(r.children) }
2034
+ return r
2035
+ })
2036
+ setData((prev) => updateRow(prev))
2037
+ }
2038
+
2039
+ // Issue 7:enableRowDrag handler — top-level only(nested children 不可拖,per NestedRowsWithDrag canonical)
2040
+ const handleRowReorder = (sourceId: string, targetId: string, position: 'before' | 'after') => {
2041
+ setData((prev) => {
2042
+ const sourceIdx = prev.findIndex((r) => r.id === sourceId)
2043
+ const targetIdx = prev.findIndex((r) => r.id === targetId)
2044
+ if (sourceIdx === -1 || targetIdx === -1) return prev
2045
+ const next = [...prev]
2046
+ const [moved] = next.splice(sourceIdx, 1)
2047
+ const adjustedTarget = next.findIndex((r) => r.id === targetId)
2048
+ const insertAt = position === 'before' ? adjustedTarget : adjustedTarget + 1
2049
+ next.splice(insertAt, 0, moved)
2050
+ return next
2051
+ })
2052
+ }
2053
+
2054
+ // Issue 7:enableColumnReorder handler(對齊 ColumnReorder canonical L256-265)
2055
+ const handleColumnReorder = (sourceId: string, targetId: string, position: 'before' | 'after') => {
2056
+ setColumnOrder((prev) => {
2057
+ // 用既有 column accessorKey 順序作 fallback initial
2058
+ const accessorKeys = columns.map((c) => (c as any).accessorKey ?? (c as any).id) as string[]
2059
+ const base = prev.length > 0 ? prev : accessorKeys
2060
+ const next = base.filter((id) => id !== sourceId)
2061
+ const targetIdx = next.indexOf(targetId)
2062
+ if (targetIdx === -1) return prev
2063
+ const insertAt = position === 'before' ? targetIdx : targetIdx + 1
2064
+ next.splice(insertAt, 0, sourceId)
2065
+ return next
2066
+ })
2067
+ }
2068
+
2069
+ return (
2070
+ <div className="flex flex-col w-full h-screen bg-canvas">
2071
+ {/* Toolbar — 左 search / 右 ops(對齊 WithBulkActions canonical L922+ Gmail/Linear/Notion idiom)*/}
2072
+ <div className="flex items-center justify-between gap-2 px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]">
2073
+ <div className="flex-1 max-w-sm">
2074
+ <Input
2075
+ size="sm"
2076
+ placeholder="搜尋 ID / 標題"
2077
+ value={search}
2078
+ onChange={(e) => setSearch(e.target.value)}
2079
+ startIcon={Search}
2080
+ />
2081
+ </div>
2082
+ <div className="flex items-center gap-2">
2083
+ <Popover open={filterOpen} onOpenChange={setFilterOpen}>
2084
+ <PopoverTrigger asChild>
2085
+ <Button variant="text" size="sm" iconOnly startIcon={Filter} aria-label="篩選" pressed={isFilterTreeActive(filterTree)} />
2086
+ </PopoverTrigger>
2087
+ <PopoverContent align="end" className="w-auto p-0">
2088
+ <DataTableFilterPanel
2089
+ columns={columns}
2090
+ value={filterTree}
2091
+ onChange={setFilterTree}
2092
+ onClose={() => setFilterOpen(false)}
2093
+ />
2094
+ </PopoverContent>
2095
+ </Popover>
2096
+ <Popover open={sortOpen} onOpenChange={setSortOpen}>
2097
+ <PopoverTrigger asChild>
2098
+ <Button variant="text" size="sm" iconOnly startIcon={ArrowUpDown} aria-label="排序" pressed={sorting.length > 0} />
2099
+ </PopoverTrigger>
2100
+ <PopoverContent align="end" className="w-auto p-0">
2101
+ <DataTableSortManager
2102
+ columns={columns}
2103
+ sorting={sorting}
2104
+ onSortingChange={setSorting}
2105
+ onReset={() => setSorting([])}
2106
+ onClose={() => setSortOpen(false)}
2107
+ />
2108
+ </PopoverContent>
2109
+ </Popover>
2110
+ <Popover>
2111
+ <PopoverTrigger asChild>
2112
+ <Button variant="text" size="sm" iconOnly startIcon={Eye} aria-label="欄位顯示" />
2113
+ </PopoverTrigger>
2114
+ <PopoverContent align="end" className="w-72 p-0">
2115
+ {/* Issue 3(2026-05-10)+ F1 fix(2026-05-10):primitive
2116
+ `<DataTableColumnVisibilityPanel>` + columnOrder/onColumnOrderChange wired
2117
+ → panel 內啟 drag handle(per user 抓「為什麼還會有偏移?為什麼沒 drag?」)。
2118
+ Roadmap 跟 WithBulkActions(L1050+ 設計準則)現在對齊 — panel 內 drag 是
2119
+ primary reorder UX,DataTable header drag handle 是 secondary parallel
2120
+ affordance。 */}
2121
+ <DataTableColumnVisibilityPanel
2122
+ columns={columns.map((c) => ({
2123
+ id: ((c as any).accessorKey ?? (c as any).id) as string,
2124
+ label: typeof (c as any).header === 'string' ? (c as any).header : ((c as any).accessorKey ?? (c as any).id),
2125
+ }))}
2126
+ visibility={columnVisibility}
2127
+ onVisibilityChange={setColumnVisibility}
2128
+ columnOrder={columnOrder.length > 0 ? columnOrder : columns.map((c) => ((c as any).accessorKey ?? (c as any).id) as string)}
2129
+ onColumnOrderChange={setColumnOrder}
2130
+ searchable
2131
+ resettable
2132
+ />
2133
+ </PopoverContent>
2134
+ </Popover>
2135
+ <Button variant="primary" size="sm" startIcon={Plus}>新增</Button>
2136
+ <Button variant="text" size="sm" iconOnly startIcon={MoreVertical} aria-label="更多" />
2137
+ </div>
2138
+ </div>
2139
+
2140
+ {/* DataTable container — flex-1 min-h-0(撐滿 toolbar 跟 footer 之間 space) */}
2141
+ <div className="flex-1 min-h-0 mx-[var(--layout-space-loose)] mb-[var(--layout-space-loose)] flex flex-col">
2142
+ <DataTable
2143
+ columns={columns}
2144
+ data={filteredData}
2145
+ height="100%"
2146
+ inlineEdit
2147
+ selectable
2148
+ selection={selection}
2149
+ onSelectionChange={(s) => setSelection(s.mode === 'include' ? s.ids : [])}
2150
+ columnVisibility={columnVisibility}
2151
+ onColumnVisibilityChange={setColumnVisibility}
2152
+ pinnedLeftColumns={['id']}
2153
+ // 2026-05-10:retire pinnedRightColumns(原 shipped boolean,user 拿掉「已出」欄位)
2154
+ // 2026-05-10 B4:啟 enableColumnResize(per user「Roadmap demo 應該要有欄寬調整」)。
2155
+ // H2 fix:pinned 欄位右邊也可 resize(panel boundary col hot zone 可拖)。
2156
+ // H3:system cols + meta.resizable=false col 自動 lock 不允許拖。
2157
+ enableColumnResize
2158
+ enableRowDrag
2159
+ onRowReorder={handleRowReorder}
2160
+ enableColumnReorder
2161
+ onColumnReorder={handleColumnReorder}
2162
+ // 2026-05-10(per user「操作列只要 ⋯ 一個 action」):3 buttons → 1 MoreVertical
2163
+ rowActions={() => (
2164
+ <Button variant="text" size="xs" iconOnly startIcon={MoreVertical} aria-label="更多操作" />
2165
+ )}
2166
+ getRowId={(row) => row.id}
2167
+ onCellCommit={handleCommit}
2168
+ tableOptions={{
2169
+ state: {
2170
+ sorting,
2171
+ globalFilter: filterTree,
2172
+ expanded,
2173
+ ...(columnOrder.length > 0 ? { columnOrder } : {}),
2174
+ },
2175
+ onSortingChange: (updater) => {
2176
+ setSorting(typeof updater === 'function' ? updater(sorting) : updater)
2177
+ },
2178
+ onGlobalFilterChange: setFilterTree,
2179
+ globalFilterFn: (row, _columnId, t: FilterTree) => evaluateTree(t, row.original),
2180
+ getFilteredRowModel: getFilteredRowModel(),
2181
+ // Issue 7 nested rows:tree-table 啟用
2182
+ getSubRows: (row: RoadmapItem) => row.children,
2183
+ getRowCanExpand: (row) => Boolean(row.original.children?.length),
2184
+ onExpandedChange: setExpanded as any,
2185
+ }}
2186
+ />
2187
+ </div>
2188
+
2189
+ {/* Bulk action bar — 底部 chrome,只在 selection 有值時顯示 */}
2190
+ {selection.length > 0 && (
2191
+ <BulkActionBar
2192
+ selection={selection}
2193
+ onClearSelection={() => setSelection([])}
2194
+ actions={
2195
+ <>
2196
+ <Button variant="tertiary" size="md" startIcon={Download}>匯出</Button>
2197
+ <Button variant="tertiary" size="md" startIcon={Trash2}>移除</Button>
2198
+ </>
2199
+ }
2200
+ />
2201
+ )}
2202
+ </div>
2203
+ )
2204
+ },
2205
+ play: async ({ canvasElement }) => {
2206
+ // Virtualization perf invariant(fold-in 自原 RoadmapBigData play function,per codex Q-3):
2207
+ // 500 rows + height 100% → rendered rows 應 << 500(virtualizer 應只 render visible viewport
2208
+ // + overscan)。Threshold 100 height-aware:full-screen viewport(~1080px viewport)~ 25 visible
2209
+ // rows + overscan padding → 50-70 typical;遠 < 200 → virtualization work。
2210
+ await new Promise((r) => setTimeout(r, 300))
2211
+ const dataRows = canvasElement.querySelectorAll('[role="row"][data-row-index]')
2212
+ const visibleCount = dataRows.length
2213
+ if (visibleCount > 200) {
2214
+ throw new Error(`Virtualization broken:rendered ${visibleCount} rows,expected ≤ 200(viewport-aware)`)
2215
+ }
2216
+ if (visibleCount < 5) {
2217
+ throw new Error(`Virtualization too aggressive:rendered only ${visibleCount} rows`)
2218
+ }
2219
+ },
2220
+ }
2221
+
2222
+ /* ── Feature-split perf budget story(2026-05-14 codex perf debate verdict;2026-06-12 deep-audit
2223
+ R2 重建 — 2026-05-17 stories 整併批次誤 retire,但 spec「六之三」Case B hard gate +
2224
+ scripts/runtime-perf-datatable.mjs:20 仍指向本 story,gate 形同不可跑):──────────────────
2225
+ 獨立 perf 量測 story — 同 Roadmap 13 cols rich-cell data(useRoadmapColumns SSOT),但**禁用**
2226
+ row drag / column reorder / column resize / selection / spreadsheet overlay,只保 inline edit
2227
+ view。目的:隔離 feature-stack 疊加 cost(SortableRowProvider / filter / sort / columnOrder
2228
+ state),驗證 rich cell 本體 scroll budget(avg ≤ 50ms / p95 ≤ 80ms / long-task ≤ 1,CPU 4x
2229
+ throttle)。**不動** RoadmapAllInOne demo IA(user 2026-05-10 directive 全合一)。
2230
+ 重建版去掉原手刻說明 banner(px-loose + border-b border-divider = R9 chrome-header drift
2231
+ 簽名,且量測 story 不需 chrome;說明留本註解)。 */
2232
+ export const RoadmapPerfBudget: Story = {
2233
+ name: '效能預算量測',
2234
+ parameters: { layout: 'fullscreen' },
2235
+ tags: ['test-only'],
2236
+ render: () => {
2237
+ const bigData = React.useMemo(() => {
2238
+ const arr: RoadmapItem[] = []
2239
+ for (let i = 0; i < 500; i++) {
2240
+ const base = ROADMAP_DATA[i % ROADMAP_DATA.length]
2241
+ const id = `RDM-${String(i + 100).padStart(3, '0')}`
2242
+ arr.push({ ...base, id, title: `${base.title} — ${ROADMAP_SCOPES[i % ROADMAP_SCOPES.length]}` })
2243
+ }
2244
+ return arr
2245
+ }, [])
2246
+ const [data, setData] = React.useState(bigData)
2247
+ const columns = useRoadmapColumns()
2248
+ const handleCommit = (rowId: string, colId: string, value: unknown) => {
2249
+ setData((prev) => prev.map((r) => (r.id === rowId ? { ...r, [colId]: value } : r)))
2250
+ }
2251
+ return (
2252
+ <div className="mx-[var(--layout-space-loose)] mb-[var(--layout-space-loose)]">
2253
+ <DataTable
2254
+ columns={columns}
2255
+ data={data}
2256
+ height="600px"
2257
+ inlineEdit
2258
+ getRowId={(row) => row.id}
2259
+ onCellCommit={handleCommit}
2260
+ />
2261
+ </div>
2262
+ )
2263
+ },
2264
+ }
2265
+
2266
+ // ── L5 分頁(2026-07-06)─────────────────────────────────────────────────────
2267
+
2268
+ type OrderRow = { id: string; orderNo: string; customer: string; amount: number; placedAt: string }
2269
+
2270
+ // 128 筆訂單(電商後台真實規模;deterministic 生成,無 Math.random)
2271
+ const ORDER_ROWS: OrderRow[] = Array.from({ length: 128 }, (_, i) => ({
2272
+ id: `order-${i + 1}`,
2273
+ orderNo: `SO-2026-${String(1001 + i)}`,
2274
+ customer: ['Acme Corp', 'Globex', 'Initech', 'Umbrella', 'Stark Industries', 'Wayne Enterprises'][i % 6],
2275
+ amount: 1200 + (i * 137) % 8800,
2276
+ placedAt: `2026-0${(i % 6) + 1}-${String((i % 27) + 1).padStart(2, '0')}`,
2277
+ }))
2278
+
2279
+ const orderColumns: ColumnDef<OrderRow>[] = [
2280
+ { accessorKey: 'orderNo', header: '訂單編號' },
2281
+ { accessorKey: 'customer', header: '客戶' },
2282
+ { accessorKey: 'amount', header: '金額', meta: { type: 'currency', prefix: '$' } },
2283
+ { accessorKey: 'placedAt', header: '成立日期' },
2284
+ ]
2285
+
2286
+ export const WithPagination: Story = {
2287
+ name: '分頁',
2288
+ render: () => (
2289
+ <div className="mx-[var(--layout-space-loose)] my-[var(--layout-space-loose)] flex flex-col gap-8">
2290
+ <div>
2291
+ <p className="text-caption text-fg-muted mb-2">
2292
+ 預設形態:`pagination` 傳 true — 128 筆 / 每頁 20 = 7 頁,分頁列間距 tight、頁碼靠右
2293
+ (spec「L5:分頁」canonical);與虛擬滾動互斥(分頁時 useVirtual 關閉)。
2294
+ </p>
2295
+ <DataTable columns={orderColumns} data={ORDER_ROWS} pagination getRowId={(row) => row.id} />
2296
+ </div>
2297
+ <div>
2298
+ <p className="text-caption text-fg-muted mb-2">
2299
+ 完整形態:「共 N 筆」opt-in(showTotal)+ 每頁筆數 Select(pageSizeOptions)——
2300
+ 左資訊右頁碼 justify-between;換每頁筆數自動回第 1 頁;filter 縮小自動 clamp 當前頁。
2301
+ </p>
2302
+ <DataTable
2303
+ columns={orderColumns}
2304
+ data={ORDER_ROWS}
2305
+ pagination={{ pageSize: 20, pageSizeOptions: [10, 20, 50], showTotal: true }}
2306
+ getRowId={(row) => row.id}
2307
+ />
2308
+ </div>
2309
+ </div>
2310
+ ),
2311
+ }