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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/CLAUDE.md +8 -8
  2. package/README.md +3 -2
  3. package/dist/components/Alert/alert.js.map +1 -1
  4. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  5. package/dist/components/AppShell/app-shell.d.ts +1 -1
  6. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  7. package/dist/components/AppShell/app-shell.js +22 -2
  8. package/dist/components/AppShell/app-shell.js.map +1 -1
  9. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  10. package/dist/components/Avatar/avatar.js +4 -4
  11. package/dist/components/Avatar/avatar.js.map +1 -1
  12. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  13. package/dist/components/Breadcrumb/breadcrumb.js +1 -1
  14. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  15. package/dist/components/Button/button.d.ts +2 -2
  16. package/dist/components/Button/button.d.ts.map +1 -1
  17. package/dist/components/Button/button.js +12 -3
  18. package/dist/components/Button/button.js.map +1 -1
  19. package/dist/components/Calendar/calendar.d.ts +13 -5
  20. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  21. package/dist/components/Calendar/calendar.js +7 -1
  22. package/dist/components/Calendar/calendar.js.map +1 -1
  23. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  24. package/dist/components/Carousel/carousel.js +8 -3
  25. package/dist/components/Carousel/carousel.js.map +1 -1
  26. package/dist/components/Chart/chart.d.ts.map +1 -1
  27. package/dist/components/Chart/chart.js +1 -0
  28. package/dist/components/Chart/chart.js.map +1 -1
  29. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox/checkbox.js +8 -4
  32. package/dist/components/Checkbox/checkbox.js.map +1 -1
  33. package/dist/components/Chip/chip.d.ts +1 -1
  34. package/dist/components/Chip/chip.d.ts.map +1 -1
  35. package/dist/components/Chip/chip.js.map +1 -1
  36. package/dist/components/Coachmark/coachmark.d.ts +10 -3
  37. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  38. package/dist/components/Coachmark/coachmark.js.map +1 -1
  39. package/dist/components/Combobox/combobox.d.ts +5 -1
  40. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  41. package/dist/components/Combobox/combobox.js +30 -13
  42. package/dist/components/Combobox/combobox.js.map +1 -1
  43. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  44. package/dist/components/DataTable/cell-registry.js +53 -62
  45. package/dist/components/DataTable/cell-registry.js.map +1 -1
  46. package/dist/components/DataTable/column-types.d.ts +10 -4
  47. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  48. package/dist/components/DataTable/column-types.js.map +1 -1
  49. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
  50. package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
  51. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
  52. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  53. package/dist/components/DataTable/data-table-filter-panel.js +607 -0
  54. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  55. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  56. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  58. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  59. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  60. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  61. package/dist/components/DataTable/data-table.d.ts +5 -6
  62. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  63. package/dist/components/DataTable/data-table.js +36 -15
  64. package/dist/components/DataTable/data-table.js.map +1 -1
  65. package/dist/components/DataTable/filter-operators.js +140 -0
  66. package/dist/components/DataTable/filter-operators.js.map +1 -0
  67. package/dist/components/DataTable/filter-tree.js +312 -0
  68. package/dist/components/DataTable/filter-tree.js.map +1 -0
  69. package/dist/components/DataTable/index.d.ts +3 -0
  70. package/dist/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/components/DataTable/index.js +12 -1
  72. package/dist/components/DataTable/index.js.map +1 -1
  73. package/dist/components/DataTable/lib/column-meta.js +25 -0
  74. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  75. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  76. package/dist/components/DateGrid/date-grid.js +3 -1
  77. package/dist/components/DateGrid/date-grid.js.map +1 -1
  78. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  79. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  80. package/dist/components/DatePicker/date-picker.js +105 -74
  81. package/dist/components/DatePicker/date-picker.js.map +1 -1
  82. package/dist/components/Dialog/dialog.d.ts +20 -3
  83. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  84. package/dist/components/Dialog/dialog.js +38 -20
  85. package/dist/components/Dialog/dialog.js.map +1 -1
  86. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  87. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  88. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  89. package/dist/components/Field/field-context.d.ts +45 -5
  90. package/dist/components/Field/field-context.d.ts.map +1 -1
  91. package/dist/components/Field/field-context.js +19 -0
  92. package/dist/components/Field/field-context.js.map +1 -1
  93. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  94. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  95. package/dist/components/Field/field-edit-keys.js +19 -0
  96. package/dist/components/Field/field-edit-keys.js.map +1 -0
  97. package/dist/components/Field/field-types.d.ts +20 -1
  98. package/dist/components/Field/field-types.d.ts.map +1 -1
  99. package/dist/components/Field/field-types.js.map +1 -1
  100. package/dist/components/Field/field-wrapper.d.ts +3 -2
  101. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  102. package/dist/components/Field/field-wrapper.js +38 -39
  103. package/dist/components/Field/field-wrapper.js.map +1 -1
  104. package/dist/components/Field/field.d.ts +2 -1
  105. package/dist/components/Field/field.d.ts.map +1 -1
  106. package/dist/components/Field/field.js.map +1 -1
  107. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  108. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  109. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  110. package/dist/components/FileItem/file-item.js +1 -1
  111. package/dist/components/FileItem/file-item.js.map +1 -1
  112. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  113. package/dist/components/FileUpload/file-upload.js.map +1 -1
  114. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  115. package/dist/components/FileViewer/file-viewer.js +7 -2
  116. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  117. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  118. package/dist/components/FileViewer/image-renderer.js +22 -1
  119. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  120. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  121. package/dist/components/HoverCard/hover-card.js +5 -3
  122. package/dist/components/HoverCard/hover-card.js.map +1 -1
  123. package/dist/components/InlineEdit/index.d.ts +2 -0
  124. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  125. package/dist/components/InlineEdit/index.js +5 -0
  126. package/dist/components/InlineEdit/index.js.map +1 -0
  127. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  129. package/dist/components/InlineEdit/inline-edit.js +164 -0
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  131. package/dist/components/Input/input.d.ts +6 -11
  132. package/dist/components/Input/input.d.ts.map +1 -1
  133. package/dist/components/Input/input.js +43 -13
  134. package/dist/components/Input/input.js.map +1 -1
  135. package/dist/components/LinkInput/link-input.d.ts +2 -2
  136. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  137. package/dist/components/LinkInput/link-input.js +6 -5
  138. package/dist/components/LinkInput/link-input.js.map +1 -1
  139. package/dist/components/Menu/menu-item.d.ts +14 -2
  140. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  141. package/dist/components/Menu/menu-item.js +25 -3
  142. package/dist/components/Menu/menu-item.js.map +1 -1
  143. package/dist/components/NumberInput/number-input.d.ts +3 -3
  144. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  145. package/dist/components/NumberInput/number-input.js +6 -5
  146. package/dist/components/NumberInput/number-input.js.map +1 -1
  147. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  148. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  149. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  150. package/dist/components/Pagination/pagination.js +1 -1
  151. package/dist/components/Pagination/pagination.js.map +1 -1
  152. package/dist/components/PeoplePicker/index.js +7 -1
  153. package/dist/components/PeoplePicker/index.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  155. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  156. package/dist/components/PeoplePicker/people-picker.js +23 -10
  157. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  158. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  159. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.js +19 -14
  161. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  162. package/dist/components/Popover/popover.d.ts.map +1 -1
  163. package/dist/components/Popover/popover.js +3 -1
  164. package/dist/components/Popover/popover.js.map +1 -1
  165. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  166. package/dist/components/ProfileCard/profile-card.js +3 -3
  167. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  168. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  169. package/dist/components/RadioGroup/radio-group.js +15 -9
  170. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  171. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  172. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.js +6 -3
  174. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  175. package/dist/components/Select/select.d.ts +46 -5
  176. package/dist/components/Select/select.d.ts.map +1 -1
  177. package/dist/components/Select/select.js +109 -28
  178. package/dist/components/Select/select.js.map +1 -1
  179. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  180. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  181. package/dist/components/SelectMenu/select-menu.js +8 -1
  182. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  183. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  184. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  185. package/dist/components/SelectionControl/boolean-value.js +23 -0
  186. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  187. package/dist/components/SelectionControl/index.d.ts +1 -0
  188. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  189. package/dist/components/SelectionControl/index.js +2 -0
  190. package/dist/components/SelectionControl/index.js.map +1 -1
  191. package/dist/components/Sheet/index.js +2 -1
  192. package/dist/components/Sheet/sheet.d.ts +7 -1
  193. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  194. package/dist/components/Sheet/sheet.js +5 -2
  195. package/dist/components/Sheet/sheet.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +8 -10
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts.map +1 -1
  201. package/dist/components/Slider/slider.js.map +1 -1
  202. package/dist/components/Switch/switch.d.ts +6 -6
  203. package/dist/components/Switch/switch.d.ts.map +1 -1
  204. package/dist/components/Switch/switch.js +3 -2
  205. package/dist/components/Switch/switch.js.map +1 -1
  206. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  207. package/dist/components/Tabs/tabs.js +15 -1
  208. package/dist/components/Tabs/tabs.js.map +1 -1
  209. package/dist/components/Textarea/textarea.d.ts +2 -2
  210. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  211. package/dist/components/Textarea/textarea.js +50 -42
  212. package/dist/components/Textarea/textarea.js.map +1 -1
  213. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  214. package/dist/components/TimePicker/time-columns.js +42 -38
  215. package/dist/components/TimePicker/time-columns.js.map +1 -1
  216. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  217. package/dist/components/TimePicker/time-picker.js +8 -6
  218. package/dist/components/TimePicker/time-picker.js.map +1 -1
  219. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  220. package/dist/components/Tooltip/tooltip.js +7 -5
  221. package/dist/components/Tooltip/tooltip.js.map +1 -1
  222. package/dist/components/TreeView/tree-view.d.ts +56 -1
  223. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  224. package/dist/components/TreeView/tree-view.js +211 -12
  225. package/dist/components/TreeView/tree-view.js.map +1 -1
  226. package/dist/index.d.ts +115 -58
  227. package/dist/index.d.ts.map +1 -1
  228. package/dist/index.js +93 -108
  229. package/dist/index.js.map +1 -1
  230. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  231. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  232. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  233. package/dist/tokens/categorical-color.js +15 -0
  234. package/dist/tokens/categorical-color.js.map +1 -1
  235. package/dist/tokens/motion/motion.d.ts +7 -6
  236. package/dist/tokens/motion/motion.d.ts.map +1 -1
  237. package/dist/tokens/motion/motion.js +6 -6
  238. package/dist/tokens/motion/motion.js.map +1 -1
  239. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  240. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  241. package/dist/tokens/motion/overlay-motion.js +9 -0
  242. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  243. package/dist/tokens/uiSize/icon-size.js +5 -0
  244. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  245. package/ds-canonical/fork/governance.lock +37 -19
  246. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  247. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  248. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  249. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
  250. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  251. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  252. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  253. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  254. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
  256. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  257. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  258. package/ds-canonical/fork/manifest.json +20 -0
  259. package/ds-canonical/fork/preamble.md +22 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
  263. package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
  264. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  266. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  267. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  268. package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
  269. package/ds-canonical/hooks/README.md +1 -1
  270. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  271. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  272. package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
  273. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  274. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  275. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
  276. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  277. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  278. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  279. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  280. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  281. package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
  282. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  283. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  284. package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
  285. package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
  286. package/ds-canonical/hooks/check_story_determinism.sh +39 -0
  287. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  288. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  289. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  290. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  291. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  292. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  293. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  294. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
  295. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  296. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  297. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  298. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  299. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  300. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  301. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
  302. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
  303. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  304. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  305. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  306. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  307. package/ds-canonical/references/failure-class-registry.json +145 -0
  308. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  309. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  310. package/ds-canonical/references/scenario-definition.md +6 -9
  311. package/ds-canonical/references/ssot-consultation.md +2 -2
  312. package/ds-canonical/references/ssot-index.md +5 -4
  313. package/ds-canonical/references/story-baseline-registry.json +8 -2
  314. package/ds-canonical/references/structural-token-retention.md +6 -9
  315. package/ds-canonical/rules/meta-patterns.md +8 -8
  316. package/ds-canonical/rules/self-verify.md +4 -3
  317. package/ds-canonical/rules/spec-rules.md +1 -1
  318. package/ds-canonical/rules/story-rules.md +2 -2
  319. package/ds-canonical/rules/ui-development.md +4 -2
  320. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
  321. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  322. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  323. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  324. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  325. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  326. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  327. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
  328. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  329. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  330. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  331. package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
  332. package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
  333. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  334. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  335. package/ds-canonical/skills/governance-health/SKILL.md +2 -1
  336. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  337. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  338. package/ds-canonical/skills/new-component/SKILL.md +7 -5
  339. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  340. package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
  341. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  342. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  343. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  344. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  345. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  346. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  347. package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
  348. package/ds-story-manifest.json +29 -20
  349. package/llms-full.txt +22 -1
  350. package/llms.txt +5 -4
  351. package/package.json +7 -3
  352. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  353. package/src/components/Accordion/accordion.stories.tsx +16 -1
  354. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  355. package/src/components/Alert/alert.spec.md +8 -10
  356. package/src/components/Alert/alert.stories.tsx +28 -28
  357. package/src/components/Alert/alert.tsx +1 -1
  358. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  359. package/src/components/AppShell/app-shell.spec.md +4 -4
  360. package/src/components/AppShell/app-shell.tsx +28 -2
  361. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  362. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  363. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  364. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  365. package/src/components/Avatar/avatar.spec.md +2 -2
  366. package/src/components/Avatar/avatar.stories.tsx +8 -6
  367. package/src/components/Avatar/avatar.tsx +13 -5
  368. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  369. package/src/components/Badge/badge.spec.md +2 -0
  370. package/src/components/Badge/badge.stories.tsx +4 -2
  371. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  372. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  373. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  374. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  375. package/src/components/Button/button.principles.stories.tsx +1 -1
  376. package/src/components/Button/button.spec.md +2 -2
  377. package/src/components/Button/button.tsx +18 -3
  378. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  379. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  380. package/src/components/Calendar/calendar.spec.md +5 -4
  381. package/src/components/Calendar/calendar.stories.tsx +7 -4
  382. package/src/components/Calendar/calendar.tsx +26 -7
  383. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  384. package/src/components/Carousel/carousel.spec.md +2 -2
  385. package/src/components/Carousel/carousel.tsx +11 -3
  386. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  387. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  388. package/src/components/Chart/chart.stories.tsx +2 -8
  389. package/src/components/Chart/chart.tsx +3 -0
  390. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  391. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  392. package/src/components/Checkbox/checkbox.spec.md +11 -26
  393. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  394. package/src/components/Checkbox/checkbox.tsx +18 -13
  395. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  396. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  397. package/src/components/Chip/chip.spec.md +5 -4
  398. package/src/components/Chip/chip.tsx +5 -1
  399. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  400. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  401. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  402. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  403. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  404. package/src/components/Coachmark/coachmark.spec.md +5 -5
  405. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  406. package/src/components/Coachmark/coachmark.tsx +10 -3
  407. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  408. package/src/components/Combobox/combobox.tsx +53 -19
  409. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  410. package/src/components/Command/command.principles.stories.tsx +1 -1
  411. package/src/components/Command/command.stories.tsx +42 -10
  412. package/src/components/DataTable/cell-registry.tsx +86 -63
  413. package/src/components/DataTable/column-types.ts +10 -1
  414. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  415. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  416. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  417. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  418. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  419. package/src/components/DataTable/data-table.spec.md +32 -12
  420. package/src/components/DataTable/data-table.stories.tsx +16 -17
  421. package/src/components/DataTable/data-table.tsx +103 -60
  422. package/src/components/DataTable/index.ts +3 -0
  423. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  424. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  425. package/src/components/DateGrid/date-grid.spec.md +1 -1
  426. package/src/components/DateGrid/date-grid.tsx +3 -1
  427. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  428. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  429. package/src/components/DatePicker/date-picker.spec.md +3 -3
  430. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  431. package/src/components/DatePicker/date-picker.tsx +99 -45
  432. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  433. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  434. package/src/components/DescriptionList/description-list.spec.md +3 -3
  435. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  436. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  437. package/src/components/Dialog/dialog.spec.md +9 -0
  438. package/src/components/Dialog/dialog.stories.tsx +66 -5
  439. package/src/components/Dialog/dialog.tsx +60 -25
  440. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  441. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  442. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  443. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  444. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  445. package/src/components/Empty/empty.spec.md +2 -2
  446. package/src/components/Field/field-context.ts +69 -5
  447. package/src/components/Field/field-controls.spec.md +62 -8
  448. package/src/components/Field/field-edit-keys.ts +66 -0
  449. package/src/components/Field/field-types.ts +58 -9
  450. package/src/components/Field/field-wrapper.tsx +50 -42
  451. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  452. package/src/components/Field/field.spec.md +1 -1
  453. package/src/components/Field/field.stories.tsx +1 -1
  454. package/src/components/Field/field.tsx +2 -1
  455. package/src/components/Field/form-validation.spec.md +3 -3
  456. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  457. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  458. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  459. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  460. package/src/components/FileItem/file-item.spec.md +14 -8
  461. package/src/components/FileItem/file-item.stories.tsx +36 -25
  462. package/src/components/FileItem/file-item.tsx +8 -6
  463. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  464. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  465. package/src/components/FileUpload/file-upload.spec.md +1 -1
  466. package/src/components/FileUpload/file-upload.tsx +1 -1
  467. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  468. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  469. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  470. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  471. package/src/components/FileViewer/file-viewer.tsx +12 -4
  472. package/src/components/FileViewer/image-renderer.tsx +35 -7
  473. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  474. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  475. package/src/components/HoverCard/hover-card.spec.md +5 -5
  476. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  477. package/src/components/HoverCard/hover-card.tsx +5 -3
  478. package/src/components/InlineEdit/index.ts +5 -0
  479. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  480. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  481. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  482. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  483. package/src/components/Input/input.principles.stories.tsx +2 -12
  484. package/src/components/Input/input.spec.md +13 -18
  485. package/src/components/Input/input.tsx +69 -22
  486. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  487. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  488. package/src/components/LinkInput/link-input.tsx +11 -10
  489. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  490. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  491. package/src/components/Menu/menu-item.spec.md +22 -15
  492. package/src/components/Menu/menu-item.stories.tsx +39 -11
  493. package/src/components/Menu/menu-item.tsx +38 -4
  494. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  495. package/src/components/Notice/notice.spec.md +16 -3
  496. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  497. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  498. package/src/components/NumberInput/number-input.spec.md +4 -4
  499. package/src/components/NumberInput/number-input.tsx +19 -12
  500. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  501. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  502. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  503. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  504. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  505. package/src/components/Pagination/pagination.spec.md +1 -1
  506. package/src/components/Pagination/pagination.stories.tsx +2 -6
  507. package/src/components/Pagination/pagination.tsx +1 -1
  508. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  509. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  510. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  511. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  512. package/src/components/PeoplePicker/person-display.tsx +32 -16
  513. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  514. package/src/components/Popover/popover.tsx +3 -1
  515. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  516. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  517. package/src/components/ProfileCard/profile-card.tsx +6 -6
  518. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  519. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  520. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  521. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  522. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  523. package/src/components/RadioGroup/radio-group.tsx +41 -15
  524. package/src/components/Rating/rating.spec.md +11 -3
  525. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  526. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  527. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  528. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  529. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  530. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  531. package/src/components/Select/select.spec.md +27 -17
  532. package/src/components/Select/select.stories.tsx +33 -0
  533. package/src/components/Select/select.tsx +190 -36
  534. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  535. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  536. package/src/components/SelectMenu/select-menu.tsx +16 -3
  537. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  538. package/src/components/SelectionControl/index.ts +1 -0
  539. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  540. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  541. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  542. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  543. package/src/components/Separator/separator.spec.md +2 -2
  544. package/src/components/Separator/separator.stories.tsx +6 -27
  545. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  546. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  547. package/src/components/Sheet/sheet.spec.md +2 -2
  548. package/src/components/Sheet/sheet.tsx +9 -5
  549. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  550. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  551. package/src/components/Sidebar/sidebar.spec.md +13 -15
  552. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  553. package/src/components/Sidebar/sidebar.tsx +37 -25
  554. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  555. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  556. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  557. package/src/components/Slider/slider.spec.md +5 -5
  558. package/src/components/Slider/slider.tsx +3 -1
  559. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  560. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  561. package/src/components/Steps/steps.spec.md +1 -1
  562. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  563. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  564. package/src/components/Switch/switch.spec.md +8 -8
  565. package/src/components/Switch/switch.stories.tsx +9 -24
  566. package/src/components/Switch/switch.tsx +17 -13
  567. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  568. package/src/components/Tabs/tabs.spec.md +1 -1
  569. package/src/components/Tabs/tabs.tsx +21 -1
  570. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  571. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  572. package/src/components/Textarea/textarea.spec.md +4 -4
  573. package/src/components/Textarea/textarea.tsx +72 -46
  574. package/src/components/TimePicker/time-columns.tsx +6 -2
  575. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  576. package/src/components/TimePicker/time-picker.spec.md +3 -3
  577. package/src/components/TimePicker/time-picker.tsx +16 -10
  578. package/src/components/Toast/toast.stories.tsx +7 -4
  579. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  580. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  581. package/src/components/Tooltip/tooltip.spec.md +1 -1
  582. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  583. package/src/components/Tooltip/tooltip.tsx +8 -6
  584. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  585. package/src/components/TreeView/tree-view.spec.md +42 -11
  586. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  587. package/src/components/TreeView/tree-view.tsx +322 -17
  588. package/src/index.ts +584 -60
  589. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  590. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  591. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  592. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  593. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  594. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  595. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  596. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  597. package/src/styles/tokens.css +3 -0
  598. package/src/tokens/README.md +1 -1
  599. package/src/tokens/color/color.spec.md +3 -3
  600. package/src/tokens/color/color.stories.tsx +3 -3
  601. package/src/tokens/density/density.stories.tsx +16 -3
  602. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  603. package/src/tokens/motion/motion.css +33 -21
  604. package/src/tokens/motion/motion.spec.md +32 -15
  605. package/src/tokens/motion/motion.stories.tsx +58 -5
  606. package/src/tokens/motion/motion.ts +7 -6
  607. package/src/tokens/motion/overlay-motion.ts +26 -0
  608. package/src/tokens/orphan-tokens.spec.md +4 -4
  609. package/src/tokens/token-system.spec.md +1 -0
  610. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  611. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  612. package/src/tokens/utility-registry.json +160 -23
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-filter-panel.js","sources":["../../../src/components/DataTable/data-table-filter-panel.tsx"],"sourcesContent":["// @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.\n// same-row-mixed-allow: header chrome corner buttons(close)跟 row inline actions(trash)不在同 row\n// code-quality-allow: file-size — 2026-05-03 M21 retract:filter-value-picker.tsx(187 行 / 1 consumer)inline 回本檔(505 → 687 行)。2026-07-14 deep-audit 誠實更新:現 822 行,**已過 800 hard cap** — 非 stale escape 留著;拆檔候選 = filter-value-picker 區段(等第 2 個 consumer 接入)+ nested-group renderer,屬結構 refactor 需獨立 branch 做 + 完整驗證,列入 file-size escalation 追蹤,禁再增量。\nimport * as React from 'react'\nimport { Plus, Trash2, X as XIcon, RotateCcw } from 'lucide-react'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/design-system/components/Button/button'\nimport { Select, type SelectOption } from '@/design-system/components/Select/select'\nimport { Combobox } from '@/design-system/components/Combobox/combobox'\nimport { Input } from '@/design-system/components/Input/input'\nimport { NumberInput } from '@/design-system/components/NumberInput/number-input'\nimport { DatePicker, DatePickerRange } from '@/design-system/components/DatePicker/date-picker'\nimport { PeoplePicker } from '@/design-system/components/PeoplePicker/people-picker'\nimport type { PersonValue } from '@/design-system/components/PeoplePicker/person-display'\nimport { SurfaceHeader, SurfaceBody, COMPACT_HEADER_SLOT } from '@/design-system/patterns/overlay-surface/overlay-surface'\nimport { PopoverTitle, PopoverClose } from '@/design-system/components/Popover/popover'\nimport { ButtonDivider } from '@/design-system/components/Button/button-group'\nimport { FieldControlGroup } from '@/design-system/components/FieldControlGroup/field-control-group'\nimport type { ColumnType } from './column-types'\nimport { getColumnId, getColumnLabel, getColumnMeta } from './lib/column-meta'\nimport {\n OPERATOR_REGISTRY,\n DEFAULT_OPERATOR,\n DATE_RELATIVE_OPTIONS,\n DATE_RELATIVE_GROUPS,\n getOperatorSpec,\n getValueShape,\n type ValueShape,\n} from './filter-operators'\nimport {\n createEmptyFilterTree,\n isFilterTreeActive,\n isFilterTreeEqual,\n evaluateTree,\n dataTableFilterMatch,\n type Conjunction,\n type FilterCondition,\n type FilterGroup,\n type FilterTree,\n type FilterTreeFlat,\n type FilterTreeNested,\n} from './filter-tree'\n\n// Re-export public API from filter-tree(consumer 既有 import path 不變)\nexport {\n createEmptyFilterTree,\n isFilterTreeActive,\n evaluateTree,\n dataTableFilterMatch,\n}\nexport type { Conjunction, FilterCondition, FilterGroup, FilterTree, FilterTreeFlat, FilterTreeNested }\n\n/**\n * DataTableFilterPanel — ClickUp-style 進階篩選 panel\n *\n * 對齊 ClickUp / Airtable / Notion / Coda / Linear advanced-filter 派 —\n * parenthesized boolean expression builder。\n *\n * 兩種 mode 由 consumer 拍板:\n * - `flat`:root 下只能裝 condition,無 group\n * - `nested`:root 下裝 1+ group(灰底框),每個 group 內裝 1+ condition,**剛好 1 層**\n *\n * Source-of-truth:\n * - Operator definitions:`./filter-operators.ts` `OPERATOR_REGISTRY`(SSOT,禁 hardcode op 字串)\n * - Filter state:**FilterTree**(本檔自管;搭配 TanStack `globalFilter` 求值)\n *\n * 詳:`./filter-operators.spec.md`\n */\n\n// ── Internal — id seed ──────────────────────────────────────────────────\n\nlet _idSeed = 0\nconst newId = () => `f${++_idSeed}-${Date.now().toString(36)}`\n\n// ── Helpers — internal types ────────────────────────────────────────────\n\ninterface FilterColumn {\n id: string\n label: string\n type: ColumnType\n options?: Array<{ value: string; label: string }>\n /** People pool for person/multiPerson filter picker(對齊 cell-registry meta.people SSOT)*/\n people?: Array<{ name: string; avatarUrl?: string; description?: string }>\n includeTime?: boolean\n}\n\nfunction extractColumns<TData>(columns: ColumnDef<TData, any>[]): FilterColumn[] {\n const out: FilterColumn[] = []\n for (const col of columns) {\n const id = getColumnId(col)\n if (!id || id === '__select__') continue\n const meta = getColumnMeta(col)\n const type: ColumnType | undefined = meta?.type\n if (!type) continue\n if (meta?.filterable === false) continue\n out.push({\n id,\n label: getColumnLabel(col, id),\n type,\n options: meta?.options,\n people: meta?.people,\n includeTime: meta?.includeTime,\n })\n }\n return out\n}\n\nfunction getOperatorOptions(type?: ColumnType): SelectOption[] {\n const registry = type && OPERATOR_REGISTRY[type] ? OPERATOR_REGISTRY[type] : OPERATOR_REGISTRY.string\n return registry.map((op) => ({ value: op.op, label: op.label }))\n}\n\nfunction getDefaultOperator(type?: ColumnType): string {\n return (type && DEFAULT_OPERATOR[type]) || DEFAULT_OPERATOR.string\n}\n\n// Q6(2026-07-04):date 欄位把比對精度寫進 condition(includeTime=true → ms,否則 day)。\n// 'time' 欄暫不寫(值非完整日期,truncate 語意不成立;見 filter-operators.spec v3 time 註)。\nconst datePrecisionOf = (col: FilterColumn | undefined): 'day' | 'ms' | undefined =>\n col?.type === 'date' ? (col.includeTime ? 'ms' : 'day') : undefined\n\nconst newCondition = (firstCol: FilterColumn | undefined): FilterCondition => ({\n kind: 'cond',\n id: newId(),\n field: firstCol?.id ?? '',\n op: firstCol ? getDefaultOperator(firstCol.type) : '',\n value: '',\n datePrecision: datePrecisionOf(firstCol),\n})\n\n// **G fix(2026-05-04)**:initial-mount 用 — field 不預選,user 自選後 op/value 才 enable\n// Disabled state(field='')→ op + value 在 FilterRow 內走 `disabled={!hasField}` 自動連動\nconst newEmptyCondition = (): FilterCondition => ({\n kind: 'cond',\n id: newId(),\n field: '',\n op: '',\n value: '',\n})\n\nconst newGroup = (firstCol: FilterColumn | undefined): FilterGroup => ({\n kind: 'group',\n id: newId(),\n conjunction: 'or', // group 內 default OR(對齊 ref 圖)\n children: [newCondition(firstCol)],\n})\n\nconst newEmptyGroup = (): FilterGroup => ({\n kind: 'group',\n id: newId(),\n conjunction: 'or',\n children: [newEmptyCondition()],\n})\n\n// ── Internal — FilterValuePicker(value-picker switcher per ValueShape)──\n//\n// 2026-05-03 M21 retract:本 helper 原本獨立檔 `filter-value-picker.tsx`,\n// claim「未來 inline filter UI 共用」但只 1 consumer(本 panel)= 違 M21\n// premature abstraction。inline 回 panel,日後若真有第 2 consumer 再抽。\n\ninterface FilterValuePickerColInfo {\n id: string\n label: string\n options?: Array<{ value: string; label: string }>\n /** Person pool — person/multiPerson filter picker 用(2026-05-07 升級,SSOT 對齊 cell-registry) */\n people?: Array<{ name: string; avatarUrl?: string; description?: string }>\n}\n\ninterface FilterValuePickerProps {\n shape: ValueShape | null\n value: unknown\n onChange: (v: unknown) => void\n colInfo?: FilterValuePickerColInfo\n disabled?: boolean\n /** 用 column.label 組「{label} 篩選值」(panel 每 row 不顯式 label,a11y 必填) */\n ariaLabel?: string\n /** Forward 給內部 Field control 的 className(2026-05-04 #2 fix)\n * 避免外層包 wrapper div 破壞 FieldControlGroup CSS variants(rounded radii / margin overlap) */\n className?: string\n}\n\nfunction FilterValuePicker({\n shape,\n value,\n onChange,\n colInfo,\n disabled,\n ariaLabel,\n className,\n}: FilterValuePickerProps) {\n if (!shape || disabled) {\n return <Input size=\"sm\" value=\"\" onChange={() => {}} placeholder=\"輸入值…\" disabled aria-label={ariaLabel} className={className} />\n }\n\n switch (shape) {\n case 'none':\n return null\n\n case 'text':\n return (\n <Input\n size=\"sm\"\n value={String(value ?? '')}\n onChange={(e) => onChange(e.target.value)}\n placeholder=\"輸入值…\"\n aria-label={ariaLabel}\n className={className}\n />\n )\n\n case 'number':\n return (\n <NumberInput\n size=\"sm\"\n value={typeof value === 'number' ? value : null}\n onChange={(v) => onChange(v ?? '')}\n placeholder=\"輸入數字…\"\n aria-label={ariaLabel}\n className={className}\n />\n )\n\n case 'date_single':\n return (\n <DatePicker\n size=\"sm\"\n value={typeof value === 'string' ? value : null}\n onChange={(v) => onChange(v ?? '')}\n aria-label={ariaLabel}\n className={className}\n />\n )\n\n case 'date_range':\n return (\n <DatePickerRange\n size=\"sm\"\n value={Array.isArray(value) && value.length === 2\n ? (value as [string | null, string | null])\n : null}\n onChange={(v) => onChange(v)}\n aria-label={ariaLabel}\n className={className}\n />\n )\n\n case 'date_relative': {\n // 群組分類:Past / Current / Future(對齊 Linear / Notion idiom),走 Select.groups → SelectMenu\n const opts: SelectOption[] = DATE_RELATIVE_OPTIONS.map((o) => ({\n value: o.value,\n label: o.label,\n group: o.group,\n }))\n return (\n <Select\n size=\"sm\"\n options={opts}\n groups={DATE_RELATIVE_GROUPS as unknown as Array<{ key: string; label: string }>}\n value={String(value ?? '')}\n onChange={(v) => onChange(v)}\n placeholder=\"選擇相對日期\"\n aria-label={ariaLabel}\n className={className}\n />\n )\n }\n\n case 'select_single': {\n const opts: SelectOption[] = (colInfo?.options ?? []).map((o) => ({\n value: o.value,\n label: o.label,\n }))\n return (\n <Select\n size=\"sm\"\n options={opts}\n value={String(value ?? '')}\n onChange={(v) => onChange(v)}\n placeholder=\"選擇值\"\n aria-label={ariaLabel}\n className={className}\n />\n )\n }\n\n case 'select_multi': {\n const opts = (colInfo?.options ?? []).map((o) => ({\n value: o.value,\n label: o.label,\n }))\n const arr = Array.isArray(value) ? (value as string[]) : []\n return (\n <Combobox\n size=\"sm\"\n options={opts}\n value={arr}\n onChange={(v) => onChange(v)}\n placeholder=\"選擇值…\"\n aria-label={ariaLabel}\n className={className}\n />\n )\n }\n\n case 'datetime_single':\n return (\n <DatePicker\n size=\"sm\"\n showTime\n value={typeof value === 'string' ? value : null}\n onChange={(v) => onChange(v ?? '')}\n aria-label={ariaLabel}\n className={className}\n />\n )\n\n case 'datetime_range':\n return (\n <DatePickerRange\n size=\"sm\"\n showTime\n value={Array.isArray(value) && value.length === 2\n ? (value as [string | null, string | null])\n : null}\n onChange={(v) => onChange(v)}\n aria-label={ariaLabel}\n className={className}\n />\n )\n\n // person_single / person_multi — 走 PeoplePicker(2026-05-07 升級,對齊 cell-registry SSOT)。\n // colInfo.people 來自 column meta.people。Filter value:\n // - person_single:存 PersonValue | null(picker emit array,我們取 [0])\n // - person_multi:存 PersonValue[]\n case 'person_single': {\n const v = value as PersonValue | null | undefined\n return (\n <PeoplePicker\n size=\"sm\"\n value={v ?? null}\n people={colInfo?.people ?? []}\n onChange={(next) => onChange(next[0] ?? null)}\n aria-label={ariaLabel}\n className={className}\n />\n )\n }\n case 'person_multi': {\n const v = Array.isArray(value) ? (value as PersonValue[]) : []\n return (\n <PeoplePicker\n size=\"sm\"\n value={v}\n people={colInfo?.people ?? []}\n onChange={(next) => onChange(next)}\n aria-label={ariaLabel}\n className={className}\n />\n )\n }\n default:\n return null\n }\n}\n\n// ── Component Props ─────────────────────────────────────────────────────\n\nexport interface DataTableFilterPanelProps<TData> {\n /** flat(無 group)or nested(1-level group)— consumer 拍板 */\n mode: 'flat' | 'nested'\n /** 可被 filter 的 columns */\n columns: ColumnDef<TData, any>[]\n /** 當前 FilterTree(controlled) */\n value: FilterTree\n /** state 變更 callback */\n onChange: (next: FilterTree) => void\n /**\n * 管理員 set-as-default 的 baseline(refresh icon 顯示判定用)。\n * 當 `value` ≠ `defaultValue`(deep equal)→ panel header 顯示 refresh icon,\n * click → reset 回 defaultValue。對齊 sort 邏輯(相同 modified-from-default UX)。\n */\n defaultValue?: FilterTree\n /** Cell ⌄ menu「Filter by this」帶入的 column id(自動 add 一條 condition) */\n prefilledColumnId?: string\n onPrefillConsumed?: () => void\n onClose?: () => void\n className?: string\n}\n\n// ── Main Component ──────────────────────────────────────────────────────\n\n// 內部 fn — generic + ref 轉發。export 走 cast(對齊 DataTable 同 pattern)\nfunction DataTableFilterPanelInner<TData>({\n mode,\n columns,\n value,\n onChange,\n defaultValue,\n prefilledColumnId,\n onPrefillConsumed,\n onClose,\n className,\n}: DataTableFilterPanelProps<TData>, ref: React.ForwardedRef<HTMLDivElement>): React.ReactElement {\n const filterableColumns = React.useMemo(() => extractColumns(columns), [columns])\n const fieldOptions: SelectOption[] = React.useMemo(\n () => filterableColumns.map((c) => ({ value: c.id, label: c.label })),\n [filterableColumns],\n )\n // K13 後 firstCol 不再被 add* 消費(改用 newEmpty*),這裡只留 prefill effect 用(已直接讀 prefilledColumnId)。\n\n // **G fix(2026-05-04 v2)**:initial-mount 預設 1 empty row(field 未選 → op+value 自動 disabled)\n // useRef gate → 只 mount 一次;user 後續手動刪光 → 不 re-add → 維持「全清 = empty CTA only」UX\n // Two states clearly separated:\n // (a) Initial mount with empty value → auto-add 1 empty row(讓 user 看到 row shape,不必先點 CTA)\n // (b) User explicitly deletes all → empty CTA only(無 row,respect user intent)\n const initialMountDoneRef = React.useRef(false)\n React.useEffect(() => {\n if (initialMountDoneRef.current) return\n initialMountDoneRef.current = true\n if (filterableColumns.length === 0) return\n if (value.children.length > 0) return\n if (value.mode === 'flat') {\n onChange({ ...value, children: [newEmptyCondition()] } as FilterTreeFlat)\n } else {\n onChange({ ...value, children: [newEmptyGroup()] } as FilterTreeNested)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filterableColumns.length])\n\n // Prefill from cell ⌄ menu「Filter by this」\n React.useEffect(() => {\n if (!prefilledColumnId) return\n const colInfo = filterableColumns.find((c) => c.id === prefilledColumnId)\n if (colInfo) {\n const cond: FilterCondition = {\n kind: 'cond',\n id: newId(),\n field: prefilledColumnId,\n op: getDefaultOperator(colInfo.type),\n value: '',\n // 2026-07-14 deep-audit fix:補 datePrecision(原漏 → datetime(includeTime=true)欄\n // prefill 掉到 undefined=day 精度忽略 ms;對齊初始 add / changeField 路徑的 datePrecisionOf)\n datePrecision: datePrecisionOf(colInfo),\n }\n if (value.mode === 'flat') {\n onChange({ ...value, children: [...value.children, cond] })\n } else {\n // nested mode:add 到第 1 個 group(若無則新建)\n if (value.children.length === 0) {\n onChange({ ...value, children: [{ ...newGroup(colInfo), children: [cond] }] })\n } else {\n const updatedGroups = value.children.map((g, i) =>\n i === 0 ? { ...g, children: [...g.children, cond] } : g\n )\n onChange({ ...value, children: updatedGroups })\n }\n }\n }\n onPrefillConsumed?.()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [prefilledColumnId])\n\n // ── flat-mode mutators ──\n const flatTree = value.mode === 'flat' ? value : null\n const updateFlatCondition = (id: string, patch: Partial<FilterCondition>) => {\n if (!flatTree) return\n onChange({\n ...flatTree,\n children: flatTree.children.map((c) => (c.id === id ? { ...c, ...patch } : c)),\n })\n }\n const removeFlatCondition = (id: string) => {\n if (!flatTree) return\n onChange({ ...flatTree, children: flatTree.children.filter((c) => c.id !== id) })\n }\n const addFlatCondition = () => {\n if (!flatTree) return\n // K13 fix(2026-05-04):加篩選 → empty row(field 未選 → op+value disabled)\n // World-class:Notion / Coda / ClickUp 不 auto-select;對齊 initial mount canonical\n onChange({ ...flatTree, children: [...flatTree.children, newEmptyCondition()] })\n }\n const setFlatConjunction = (conj: Conjunction) => {\n if (!flatTree) return\n onChange({ ...flatTree, conjunction: conj })\n }\n\n // ── nested-mode mutators ──\n const nestedTree = value.mode === 'nested' ? value : null\n const updateGroup = (groupId: string, patch: Partial<FilterGroup>) => {\n if (!nestedTree) return\n onChange({\n ...nestedTree,\n children: nestedTree.children.map((g) => (g.id === groupId ? { ...g, ...patch } : g)),\n })\n }\n const updateGroupCondition = (groupId: string, condId: string, patch: Partial<FilterCondition>) => {\n if (!nestedTree) return\n onChange({\n ...nestedTree,\n children: nestedTree.children.map((g) =>\n g.id === groupId\n ? { ...g, children: g.children.map((c) => (c.id === condId ? { ...c, ...patch } : c)) }\n : g\n ),\n })\n }\n const removeGroupCondition = (groupId: string, condId: string) => {\n if (!nestedTree) return\n onChange({\n ...nestedTree,\n children: nestedTree.children.map((g) =>\n g.id === groupId ? { ...g, children: g.children.filter((c) => c.id !== condId) } : g\n ),\n })\n }\n // K13 fix(2026-05-04):同 addFlatCondition,巢狀內加條件也 empty row\n const addConditionToGroup = (groupId: string) => {\n if (!nestedTree) return\n onChange({\n ...nestedTree,\n children: nestedTree.children.map((g) =>\n g.id === groupId ? { ...g, children: [...g.children, newEmptyCondition()] } : g\n ),\n })\n }\n const removeGroup = (groupId: string) => {\n if (!nestedTree) return\n onChange({ ...nestedTree, children: nestedTree.children.filter((g) => g.id !== groupId) })\n }\n const addGroup = () => {\n if (!nestedTree) return\n // K13:加群組也用 empty group\n onChange({ ...nestedTree, children: [...nestedTree.children, newEmptyGroup()] })\n }\n const setRootConjunction = (conj: Conjunction) => {\n if (!nestedTree) return\n onChange({ ...nestedTree, conjunction: conj })\n }\n\n return (\n // 寬度策略:desktop 680px;mobile 縮到 viewport 內留 32px 邊(避溢出 popover 切右半)。\n // 對齊 Notion / Airtable 的 advanced filter 在 mobile 走 full-width 邊處理。\n // **#8 fix(2026-05-04)**:popover width by mode(由 cell min-w 與 group nested chrome 反推)\n // flat:cell ConjunctionLabel(80) + gap-2(8) + FCG(field-min 160 + op-min 120 + value 200) +\n // gap-2(8) + trash(28) + 2×loose padding(32) = ~636 → 640px\n // nested:再加 group p-2 (16) + outer ConjunctionLabel (80) + outer gap (8) → ~740 → 760px\n // 對齊 Airtable / Notion / Linear filter row 視覺密度 @benchmark-unverified(non-OSS)\n // **K11 fix(2026-05-04)**:viewport-aware scroll chain invariant\n // parent PopoverContent 是 flex flex-col + max-h + overflow-hidden,\n // panel root 必 forward `flex flex-col h-full` 才能讓 SurfaceBody flex-1 min-h-0 overflow-y-auto 生效\n // 無此 forward → 中間 wrapper 斷鏈 → body 不 scroll(ProfileCard 因為自身設 max-h flex-col 才繞過)\n // 詳 overlay-surface.spec.md「viewport-aware scroll chain invariant」段\n // K11 v2 fix(2026-05-04):flex item 預設 min-h:auto 讓 content 撐 height,h-full 失效。\n // 必加 `min-h-0` 才能讓 panel 在 PopoverContent max-h cap 下正確 shrink + body scroll。\n <div ref={ref} className={cn(\n 'flex flex-col h-full min-h-0',\n mode === 'nested'\n ? 'w-[min(760px,calc(100vw-2rem))]'\n : 'w-[min(640px,calc(100vw-2rem))]',\n className,\n )}>\n {/* Popover 派輕量 chrome — slot 走 COMPACT_HEADER_SLOT(=21,衍生自 PopoverTitle text-body line-box),header 自然 ~45px */}\n <SurfaceHeader className={COMPACT_HEADER_SLOT}>\n <PopoverTitle className=\"flex-1\">篩選</PopoverTitle>\n {/* Refresh icon — 只在 value ≠ defaultValue 時顯示(對齊 sort modified-from-default UX)\n 含 ButtonDivider 對齊「欄位顯示」+「排序」chrome corner action canonical(2026-05-04) */}\n {defaultValue && !isFilterTreeEqual(value, defaultValue) && (\n <>\n <Button\n variant=\"text\" size=\"sm\" iconOnly startIcon={RotateCcw}\n aria-label=\"恢復預設\"\n onClick={() => onChange(defaultValue)}\n />\n {onClose && <ButtonDivider />}\n </>\n )}\n {onClose && (\n <PopoverClose asChild>\n <Button data-dismiss iconOnly dismiss size=\"sm\" startIcon={XIcon} aria-label=\"關閉\" onClick={onClose} />\n </PopoverClose>\n )}\n </SurfaceHeader>\n\n {/* Body — flat / nested 條件;空條件 → 直接顯 + 加篩選 CTA(對齊 Notion / Airtable / Linear inline 派,\n 無條件時不需要 Empty 元件大區塊,單顆 CTA 引導即可。SurfaceFooter 整層拔除,\n + Add filter / + 加篩選器 inline 緊貼最後一條 row,讓 user 感受到「條件」與「加入」屬同一語境)*/}\n <SurfaceBody className=\"flex flex-col gap-[var(--layout-space-tight)]\">\n {flatTree && flatTree.children.map((cond, idx) => (\n <FilterRow\n key={cond.id}\n index={idx}\n condition={cond}\n conjunction={flatTree.conjunction}\n filterableColumns={filterableColumns}\n fieldOptions={fieldOptions}\n onChangeConjunction={setFlatConjunction}\n onChangeField={(v) => {\n const newCol = filterableColumns.find((c) => c.id === v)\n updateFlatCondition(cond.id, { field: v, op: getDefaultOperator(newCol?.type), value: '', datePrecision: datePrecisionOf(newCol) })\n }}\n onChangeOp={(v) => updateFlatCondition(cond.id, { op: v, value: '' })}\n onChangeValue={(v) => updateFlatCondition(cond.id, { value: v })}\n onRemove={() => removeFlatCondition(cond.id)}\n />\n ))}\n\n {nestedTree && nestedTree.children.map((group, gIdx) => (\n <GroupBlock\n key={group.id}\n index={gIdx}\n group={group}\n rootConjunction={nestedTree.conjunction}\n filterableColumns={filterableColumns}\n fieldOptions={fieldOptions}\n onChangeRootConjunction={setRootConjunction}\n onChangeGroupConjunction={(c) => updateGroup(group.id, { conjunction: c })}\n onChangeCondition={(condId, patch) => updateGroupCondition(group.id, condId, patch)}\n onRemoveCondition={(condId) => removeGroupCondition(group.id, condId)}\n onAddCondition={() => addConditionToGroup(group.id)}\n onRemoveGroup={() => removeGroup(group.id)}\n />\n ))}\n\n {/* Inline CTA(2026-05-04 A1)— root-level「加篩選」用 tertiary(視覺輕量但有邊界,\n 符合 root-CTA 視覺重量);nested 內「加入巢狀篩選」走 text variant(更輕,在 group 內 inline)\n 不放 SurfaceFooter:條件與「加入」屬同一語義群,中間插 footer 切斷敘事 */}\n <div>\n <Button\n variant=\"tertiary\" size=\"sm\" startIcon={Plus}\n onClick={mode === 'flat' ? addFlatCondition : addGroup}\n >\n {mode === 'nested' ? '加入篩選器' : '加篩選'}\n </Button>\n </div>\n </SurfaceBody>\n </div>\n )\n}\n\n// Generic + ref forward 套 cast 的 idiom — 對齊 DataTable(同檔家)。\n// React.forwardRef 對 generic component 會丟掉 type param,改 cast 成 generic-preserving signature。\nexport const DataTableFilterPanel = React.forwardRef(DataTableFilterPanelInner) as <TData>(\n props: DataTableFilterPanelProps<TData> & { ref?: React.ForwardedRef<HTMLDivElement> }\n) => React.ReactElement\n;(DataTableFilterPanel as { displayName?: string }).displayName = 'DataTableFilterPanel'\n\n// ── ConjunctionLabel ───────────────────────────────────────────────────\n\nconst CONJ_OPTIONS: SelectOption[] = [\n { value: 'and', label: 'And' },\n { value: 'or', label: 'Or' },\n]\n\nfunction ConjunctionLabel({\n index, conjunction, onChange,\n}: { index: number; conjunction: Conjunction; onChange: (c: Conjunction) => void }) {\n // index === 0:首 row 顯示靜態「Where」label\n // index === 1:**唯一可改**的 AND/OR Select(連動整 group conjunction)\n // index ≥ 2:被連動的 row,read-only 顯示當前 conjunction 文字(同 Where 視覺,A6 canonical)\n // 對齊 Airtable / Notion / Linear 共識 @benchmark-unverified(non-OSS)\n // px-[var(--field-px)] 對齊 Field 內部 padding 12px(Q13)\n if (index === 0) {\n return <div className=\"w-20 shrink-0 text-body text-fg-muted px-[var(--field-px)] self-center\">Where</div>\n }\n if (index >= 2) {\n const label = conjunction === 'and' ? 'And' : 'Or'\n return <div className=\"w-20 shrink-0 text-body text-fg-muted px-[var(--field-px)] self-center\">{label}</div>\n }\n // index === 1:可切換的 AND/OR Select\n // minRows={2} — And/Or 2 選項,顯式縮 menu 高度避免 reserve 3 row 空白(Q5)\n return (\n <div className=\"w-20 shrink-0\">\n <Select\n size=\"sm\"\n options={CONJ_OPTIONS}\n value={conjunction}\n onChange={(v) => onChange(v as Conjunction)}\n minRows={2}\n aria-label=\"連接詞 — 同 group 共用\"\n />\n </div>\n )\n}\n\n// ── FilterRow(flat 用 + group 內共用) ──────────────────────────────\n\nfunction FilterRow({\n index, condition, conjunction, filterableColumns, fieldOptions,\n onChangeConjunction, onChangeField, onChangeOp, onChangeValue, onRemove,\n}: {\n index: number\n condition: FilterCondition\n conjunction: Conjunction\n filterableColumns: FilterColumn[]\n fieldOptions: SelectOption[]\n onChangeConjunction: (c: Conjunction) => void\n onChangeField: (v: string) => void\n onChangeOp: (v: string) => void\n onChangeValue: (v: unknown) => void\n onRemove: () => void\n}) {\n const colInfo = filterableColumns.find((c) => c.id === condition.field)\n const operatorOptions = getOperatorOptions(colInfo?.type)\n const hasField = !!condition.field\n const opSpec = colInfo ? getOperatorSpec(colInfo.type, condition.op) : null\n const valueShape: ValueShape | null = colInfo && opSpec\n ? getValueShape(opSpec, colInfo.type, colInfo.includeTime)\n : null\n // op 'is_set' / 'is_not_set' 等 shape='none' → 無 value cell,op 自動 expand 填剩餘寬\n // 對齊 Notion / Airtable / Linear filter row 行為\n // 注意:valueShape=null(初始無 field 選)時仍 render value cell(disabled placeholder)— 只 'none' 才 fold\n const hasValueCell = valueShape !== 'none'\n\n // FieldControlGroup 接合 field + op + value 視覺(2026-05-04 E refactor + 多輪 fix):\n // - border collapse 取代 3 顆獨立 Select 並排,對齊 Airtable / Linear / Notion filter row idiom\n // - ConjunctionLabel + Trash 在 group 外層(meta actions,不屬 control 一體)\n // - **#5 fix**:row 內水平 gap = `gap-2` (8px),layoutSpace 規則 5 緊密相關\n // - **#9 fix**:cell 用 `min-w-[]`(field 160 / op 120),value flex-1 min-w-0,讓 long label 可撐寬\n // - **#2 fix**:FilterValuePicker 直接是 FieldControlGroup direct child(無 wrapper div),CSS variants 命中正確\n return (\n <div className=\"flex items-center gap-2\">\n <ConjunctionLabel index={index} conjunction={conjunction} onChange={onChangeConjunction} />\n {/* **#9 fix(2026-05-04 v4)**:Field controls trigger `w-full` override 外 className,改用 Tailwind `!`\n important 強制 override(`!w-[160px]` / `!w-[120px]`),value 用 `!flex-1 !min-w-0`。\n Select 元件本身沒 destructure `style` prop 所以 inline style flex-basis 行不通,只能用 className。 */}\n <FieldControlGroup block className=\"flex-1 min-w-0\">\n {/* 2026-05-23 Phase A.4 Decision 2:`!w-[160px]` / `!w-[120px]` → tokens\n `--data-table-filter-field-width` / `--data-table-filter-op-width`(SSOT in uiSize.css)\n Behavior preserved 完好如初:flat + nested 同 width(token 是 design constant) */}\n <Select\n className=\"!w-[var(--data-table-filter-field-width)] flex-shrink-0\"\n size=\"sm\"\n options={fieldOptions}\n value={condition.field}\n onChange={onChangeField}\n placeholder=\"選擇欄位\"\n aria-label=\"篩選欄位\"\n />\n <Select\n className={hasValueCell ? '!w-[var(--data-table-filter-op-width)] flex-shrink-0' : '!flex-1 !min-w-0'}\n size=\"sm\"\n options={operatorOptions}\n value={condition.op}\n onChange={onChangeOp}\n disabled={!hasField}\n placeholder=\"運算子\"\n aria-label=\"篩選運算子\"\n />\n {hasValueCell && (\n <FilterValuePicker\n shape={valueShape}\n value={condition.value}\n onChange={onChangeValue}\n colInfo={colInfo}\n disabled={!hasField}\n ariaLabel={colInfo ? `${colInfo.label} 篩選值` : '篩選值'}\n className=\"!flex-1 !min-w-0\"\n />\n )}\n </FieldControlGroup>\n {/* Trash 用 text Button — filter row 是 form-control row,Field 同高對齊(28 md) */}\n <Button variant=\"text\" size=\"sm\" iconOnly startIcon={Trash2} aria-label=\"刪除\" onClick={onRemove} />\n </div>\n )\n}\n\n// ── GroupBlock(nested 用) ────────────────────────────────────────────\n\nfunction GroupBlock({\n index, group, rootConjunction, filterableColumns, fieldOptions,\n onChangeRootConjunction, onChangeGroupConjunction,\n onChangeCondition, onRemoveCondition, onAddCondition, onRemoveGroup,\n}: {\n index: number\n group: FilterGroup\n rootConjunction: Conjunction\n filterableColumns: FilterColumn[]\n fieldOptions: SelectOption[]\n onChangeRootConjunction: (c: Conjunction) => void\n onChangeGroupConjunction: (c: Conjunction) => void\n onChangeCondition: (condId: string, patch: Partial<FilterCondition>) => void\n onRemoveCondition: (condId: string) => void\n onAddCondition: () => void\n onRemoveGroup: () => void\n}) {\n return (\n <div className=\"flex items-start gap-2\">\n <div className=\"pt-2\">\n <ConjunctionLabel index={index} conjunction={rootConjunction} onChange={onChangeRootConjunction} />\n </div>\n {/* Group container 灰底 — `bg-muted`(`--muted` neutral-2,user 2026-05-09 拍板 Q3 A)。對齊 color.spec.md L651-654 「table header / tab / code block / skeleton」靜態低重要 surface semantic */}\n <div className=\"flex-1 min-w-0 rounded-md bg-muted p-2 flex flex-col gap-2\">\n {group.children.map((cond, cIdx) => (\n <FilterRow\n key={cond.id}\n index={cIdx}\n condition={cond}\n conjunction={group.conjunction}\n filterableColumns={filterableColumns}\n fieldOptions={fieldOptions}\n onChangeConjunction={onChangeGroupConjunction}\n onChangeField={(v) => {\n const newCol = filterableColumns.find((c) => c.id === v)\n onChangeCondition(cond.id, { field: v, op: getDefaultOperator(newCol?.type), value: '', datePrecision: datePrecisionOf(newCol) })\n }}\n onChangeOp={(v) => onChangeCondition(cond.id, { op: v, value: '' })}\n onChangeValue={(v) => onChangeCondition(cond.id, { value: v })}\n onRemove={() => onRemoveCondition(cond.id)}\n />\n ))}\n {/* Q9 — text variant 對齊 inline 派 + 視覺輕量 */}\n <div className=\"flex items-center justify-between\">\n <Button variant=\"text\" size=\"sm\" startIcon={Plus} onClick={onAddCondition}>加入巢狀篩選</Button>\n {group.children.length === 0 && (\n <Button variant=\"text\" size=\"sm\" startIcon={Trash2} danger onClick={onRemoveGroup}>移除空群組</Button>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["DatePicker","XIcon"],"mappings":"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"}
@@ -26,15 +26,16 @@ interface CellRect {
26
26
  interface DataTableInteractionLayerProps {
27
27
  /** Flag default false:不破現有 outline。enable 後 hover/editor 走 overlay。 */
28
28
  enabled: boolean;
29
- /** Container ref;layer absolute position container origin */
29
+ /** Container ref;geometry source(getCellRect 由此 query cell DOM)。layer root 本身是
30
+ * position:fixed inset:0 viewport-anchor(見 render),非 container-origin absolute */
30
31
  containerRef: React.RefObject<HTMLDivElement | null>;
31
32
  /** Per Contract 15:`cellClickEntersEdit` predicate;hover overlay 顯示與否 */
32
33
  cellClickEntersEdit?: (cellId: CellId) => boolean;
33
34
  /**
34
- * Slice D Step 3 scaffold(2026-05-10):active editor cell id。null = 無 active editor。
35
- * 當前只 render rect placeholder layer(z-index 3,higher than hover ring z-index 1)。
36
- * Future:ActiveEditorHost portal active edit Field per Contract 8 「two paint owners」。
37
- * Wire-up codex Q-7 string-first canary(text cell first,picker types 漸進)。
35
+ * Active editor cell id。null = 無 active editor。
36
+ * 已接線(Slice D Step 5 完成,2026-07-14 docblock 對齊):activeEditorEnabled +
37
+ * activeEditorCellId + activeEditorRender ActiveEditorHost(z 3)portal render
38
+ * edit Field(per Contract 8「two paint owners」)。
38
39
  */
39
40
  activeEditorCellId?: CellId | null;
40
41
  /**
@@ -51,12 +52,6 @@ interface DataTableInteractionLayerProps {
51
52
  * Layer renders solid border SelectionRect(per user「不要 dash 直接實的就好」)。
52
53
  */
53
54
  selectedCellId?: CellId | null;
54
- /**
55
- * Slice D Step 4 range support(per user「應該支援 range」+ codex Q2.1 Airtable/AG Grid
56
- * cite):range cell IDs from anchor↔focus rectangle。Layer renders bg-fill RangeRect
57
- * (z 1,bg `--primary-subtle`)+ selection border on focus cell。
58
- */
59
- rangeCellIds?: CellId[];
60
55
  /**
61
56
  * Slice D Step 5(D.3 portal Field,2026-05-10 user 拍板「在乎完美乾淨」+ codex Q6.1
62
57
  * 撤回 defer):active editor render callback。當 activeEditorEnabled + activeEditorCellId
@@ -69,11 +64,12 @@ interface DataTableInteractionLayerProps {
69
64
  activeEditorRender?: (cellId: CellId, rect: CellRect) => React.ReactNode;
70
65
  }
71
66
  /**
72
- * Singleton interaction layer。
67
+ * Singleton interaction layer(全 sub-layer 已接線;2026-07-14 docblock 對齊實作)
73
68
  *
74
- * Slice D Step 1A:HoverCellRect only。
75
- * Slice D Step 2/3/4:SelectionRect / ActiveEditorHost / RangeRect 漸進加入。
69
+ * 現況:HoverCellRect(z 1)+ SelectionRing(z 2)+ ActiveEditorHost(z 3,portal edit Field);
70
+ * range 視覺走 cell 自身 CSS `[data-range-cell]`(RangeRect / rangeCellIds prop 已 retire)。
71
+ * layer root = position:fixed inset:0 viewport-anchor,pointerEvents:none(僅 ActiveEditorHost 開 auto)。
76
72
  */
77
- export declare function DataTableInteractionLayer({ enabled, containerRef, cellClickEntersEdit, activeEditorCellId, activeEditorEnabled, activeEditorRender, selectedCellId, rangeCellIds: _rangeCellIds, }: DataTableInteractionLayerProps): import("react/jsx-runtime").JSX.Element | null;
73
+ export declare function DataTableInteractionLayer({ enabled, containerRef, cellClickEntersEdit, activeEditorCellId, activeEditorEnabled, activeEditorRender, selectedCellId, }: DataTableInteractionLayerProps): import("react/jsx-runtime").JSX.Element | null;
78
74
  export {};
79
75
  //# sourceMappingURL=data-table-interaction-layer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-table-interaction-layer.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/data-table-interaction-layer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,KAAK,MAAM,GAAG,MAAM,CAAA;AAEpB,UAAU,QAAQ;IAChB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,8BAA8B;IACtC,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAA;IAChB,+DAA+D;IAC/D,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACpD,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;IACjD;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,KAAK,CAAC,SAAS,CAAA;CACzE;AAsJD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,mBAA2B,EAC3B,kBAAkB,EAClB,cAAqB,EAErB,YAAY,EAAE,aAAa,GAC5B,EAAE,8BAA8B,kDAqFhC"}
1
+ {"version":3,"file":"data-table-interaction-layer.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/data-table-interaction-layer.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,KAAK,MAAM,GAAG,MAAM,CAAA;AAEpB,UAAU,QAAQ;IAChB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,8BAA8B;IACtC,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAA;IAChB;uFACmF;IACnF,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACpD,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;IACjD;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,KAAK,CAAC,SAAS,CAAA;CACzE;AAsJD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,EACP,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,mBAA2B,EAC3B,kBAAkB,EAClB,cAAqB,GACtB,EAAE,8BAA8B,kDAqFhC"}
@@ -87,9 +87,7 @@ function DataTableInteractionLayer({
87
87
  activeEditorCellId,
88
88
  activeEditorEnabled = false,
89
89
  activeEditorRender,
90
- selectedCellId = null,
91
- // rangeCellIds retired 2026-05-10(outer ring 已 retire,range visual 靠 cell-bg `[data-range-cell]`)
92
- rangeCellIds: _rangeCellIds
90
+ selectedCellId = null
93
91
  }) {
94
92
  const hoveredCellId = useHoveredCell(containerRef, enabled);
95
93
  useReactiveRect(containerRef, enabled);
@@ -1 +1 @@
1
- {"version":3,"file":"data-table-interaction-layer.js","sources":["../../../src/components/DataTable/data-table-interaction-layer.tsx"],"sourcesContent":["/**\n * DataTableInteractionLayer — Slice D Step 1A scaffold(per `.claude/planning/datatable-spreadsheet-rfc.md`)\n *\n * Singleton overlay root inside DataTable(M21 private,不抽 global pattern)。\n * Sub-layer children(2026-07-04 對齊實作;原 RFC 5-layer 清單含未實作元件):\n * - HoverCellRect(z 1):hover 邊框,「one geometry owner, two paint owners」(Contract 8)\n * - SelectionRing(z 2):spreadsheet mode selected cell 1px ring(CELL_RING_STYLES.selected)\n * - ActiveEditorHost(z 3):portal active edit Field(Slice C wire-up)\n * -(range 視覺 = CSS [data-range-cell] cell-bg,非 layer 元件;nested popup 走 Radix idiom\n * 見 active-editor-controller.ts — RangeRect / NestedPortalRegistry 元件不存在)\n *\n * Slice D Step 1A scope:\n * - getCellRect(cellId)geometry source(per Contract 8)\n * - HoverCellRect 1 layer 先做(Contract 8 / Contract 15 cellClickEntersEdit predicate)\n * - 默認 disabled via `experimentalSpreadsheetOverlay` flag,不破現有 outline\n * - 後續 Step 1B/C/D 漸進切換 + 拆 outline\n */\n\nimport * as React from 'react'\n\ntype CellId = string\n\ninterface CellRect {\n x: number\n y: number\n width: number\n height: number\n}\n\ninterface DataTableInteractionLayerProps {\n /** Flag default false:不破現有 outline。enable 後 hover/editor 走 overlay。 */\n enabled: boolean\n /** Container ref;layer absolute position 對 container origin */\n containerRef: React.RefObject<HTMLDivElement | null>\n /** Per Contract 15:`cellClickEntersEdit` predicate;hover overlay 顯示與否 */\n cellClickEntersEdit?: (cellId: CellId) => boolean\n /**\n * Slice D Step 3 scaffold(2026-05-10):active editor cell id。null = 無 active editor。\n * 當前只 render rect placeholder layer(z-index 3,higher than hover ring z-index 1)。\n * Future:ActiveEditorHost portal active edit Field per Contract 8 「two paint owners」。\n * Wire-up 走 codex Q-7 string-first canary(text cell first,picker types 漸進)。\n */\n activeEditorCellId?: CellId | null\n /**\n * Slice D Step 3.x flag:啟用 ActiveEditorHost dashed scaffold rect rendering。\n * 2026-05-10 bug fix(user 圖1 雙 ring 同時顯示):dashed scaffold 之前綁\n * `enabled`(= experimentalSpreadsheetOverlay)→ 任何 cell 進 edit mode 就 leak\n * 出 dashed rect。改 gate 給 `experimentalActiveEditorController`(Step 3.3 真\n * portal Field 工作),hover overlay scope 不會看到 dashed scaffold。\n */\n activeEditorEnabled?: boolean\n /**\n * Slice D Step 4(spreadsheet semantics,2026-05-10 user 圖1 ask + RFC Contract 5):\n * Excel-like 選取 cell ID。Click 1 select / Click 2 enter edit。\n * Layer renders solid border SelectionRect(per user「不要 dash 直接實的就好」)。\n */\n selectedCellId?: CellId | null\n /**\n * Slice D Step 4 range support(per user「應該支援 range」+ codex Q2.1 Airtable/AG Grid\n * cite):range cell IDs from anchor↔focus rectangle。Layer renders bg-fill RangeRect\n * (z 1,bg `--primary-subtle`)+ selection border on focus cell。\n */\n rangeCellIds?: CellId[]\n /**\n * Slice D Step 5(D.3 portal Field,2026-05-10 user 拍板「在乎完美乾淨」+ codex Q6.1\n * 撤回 defer):active editor render callback。當 activeEditorEnabled + activeEditorCellId\n * truthy → layer call this 拿 React node(已 bind value/onCommit/onCancel from controller),\n * 在 ActiveEditorHost portal(z 3,float rect)render 之。\n *\n * Per codex Q6.2 outline:cell 永遠 mode=\"display\"(SSOT preserved);portal host 渲\n * mode=\"edit\" 同 registry component;float pass-through + z-index 3 cover display below。\n */\n activeEditorRender?: (cellId: CellId, rect: CellRect) => React.ReactNode\n}\n\n/**\n * `getCellRect(cellId)` geometry source(per Contract 8)。\n *\n * 從 DOM 量(per-call `getBoundingClientRect()`)而非 layoutCache,因為:\n * 1. cell DOM 是 React-rendered,getBoundingClientRect 永遠是 source of truth\n * 2. layoutCache 需另寫 invalidation logic,added complexity\n * 3. Hover overlay re-render 頻率低(per cell hover,不是 per frame)\n *\n * Float coords pass-through — no rounding / no snap(v3 fix,見下方 v3 註解;原 RFC 0.5px snap 已撤)。\n */\nfunction getCellRect(containerEl: HTMLElement | null, cellId: CellId): CellRect | null {\n if (!containerEl) return null\n const cellEl = containerEl.querySelector<HTMLElement>(`[data-cell-id=\"${cellId}\"]`)\n if (!cellEl) return null\n // Page-absolute coords for viewport-fixed layer(per Step 1C bug fix:layer\n // 用 position:fixed,讓 paint owner 跟 reference frame 解耦 outer container 的 positioning)。\n // 2026-05-10 v3 fix(user 圖5 SSOT consistency):**float coords no rounding**。\n // Cell 自身 layout 用 sub-pixel float position(CSS 不 snap to integer)— 跨 cell 累積\n // 常見 144.328 / 244.0 / 524.172 等 fractional。任何 Math.round / floor / ceil 都引入\n // varying rounding error(visual audit verified:dx=0.17/0.5/0.83 不一致)。\n // Float pass-through + outline + outline-offset:-1px(下方 paint)→ overlay 永遠跟\n // cell exact pixel-perfect overlap,user verbatim「在內容起始位置不變的前提下讓\n // overlay 的邊框直接剛好壓住 cell 邊框」達成。\n const rect = cellEl.getBoundingClientRect()\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n }\n}\n\n/**\n * Issue 6 viewport clip(2026-05-10):cell 跟 panel(left/center/right)bounding rect 一起取,\n * layer 用 panel rect 當 clip viewport intersect cell rect → overlay 永不畫到 panel 外。\n *\n * Per codex 13-issues verdict:「getCellRect 找最近 scroll viewport;intersect(cellRect, viewportRect),\n * 空 → 不 render,部分 → clipped rect render。」\n *\n * 對齊 AG Grid `cellsForRangeSet` viewport-aware paint / Glide DataGrid clip helpers /\n * Notion sticky-cell virtualizer mask。\n */\ninterface CellGeometry {\n /** Cell exact viewport rect(no rounding,float pass-through per Bug 5 SSOT) */\n rect: CellRect\n /** Nearest panel container rect(left/center/right body)— clip viewport for overlays */\n clipRect: CellRect\n /** Panel identifier(`left` / `center` / `right`)— grouped range outer ring 分段用 */\n panel: 'left' | 'center' | 'right'\n}\n\nfunction getCellGeometry(containerEl: HTMLElement | null, cellId: CellId): CellGeometry | null {\n if (!containerEl) return null\n const cellEl = containerEl.querySelector<HTMLElement>(`[data-cell-id=\"${cellId}\"]`)\n if (!cellEl) return null\n const panelEl = cellEl.closest<HTMLElement>('[data-datatable-panel]')\n if (!panelEl) return null\n const panel = panelEl.dataset.datatablePanel as 'left' | 'center' | 'right'\n const cellR = cellEl.getBoundingClientRect()\n const panelR = panelEl.getBoundingClientRect()\n return {\n rect: { x: cellR.x, y: cellR.y, width: cellR.width, height: cellR.height },\n clipRect: { x: panelR.x, y: panelR.y, width: panelR.width, height: panelR.height },\n panel,\n }\n}\n\n\n/**\n * Reactive rect sync hook — 確保 overlay rect 跨 RWD / scroll / resize 永遠對齊 cell(2026-05-10\n * user 拍板「所有 overlay 在各種 RWD 和捲動時都能處在正確位置上」)。\n *\n * 監聽 3 source(rAF coalesce 避 frame storm):\n * 1. window scroll(capture mode 抓 nested table body scroll + page scroll)\n * 2. window resize(viewport size change → cell width 變)\n * 3. ResizeObserver on container(column resize / table dimension 變)\n *\n * 每次事件 fire → setVersion(v+1) → 觸發 layer re-render → rect 用最新 getBoundingClientRect\n * 重算。getBoundingClientRect 本身永遠 return 當下 viewport-relative coords,沒 stale cache。\n *\n * Per codex(brief: codex-brief-rwd-future-2026-05-10):rAF coalesce 不需要 debounce,scroll\n * 跟到不延遲才對(Glide / AG Grid 同 idiom)。\n */\nfunction useReactiveRect(containerRef: React.RefObject<HTMLElement | null>, enabled: boolean) {\n const [, setVersion] = React.useState(0)\n React.useEffect(() => {\n if (!enabled) return\n let rafId: number | null = null\n const force = () => {\n if (rafId !== null) return\n rafId = requestAnimationFrame(() => {\n rafId = null\n setVersion((v) => v + 1)\n })\n }\n window.addEventListener('scroll', force, { capture: true, passive: true })\n window.addEventListener('resize', force, { passive: true })\n const container = containerRef.current\n let ro: ResizeObserver | null = null\n if (container && typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(force)\n ro.observe(container)\n }\n return () => {\n window.removeEventListener('scroll', force, { capture: true } as EventListenerOptions)\n window.removeEventListener('resize', force)\n if (ro) ro.disconnect()\n if (rafId !== null) cancelAnimationFrame(rafId)\n }\n }, [enabled, containerRef])\n}\n\n/**\n * Hover state hook — 監聽 container hover events,track hovered cell id。\n *\n * Implementation:event delegation on container(不 per-cell mount listeners),\n * 利用 `data-cell-id` attribute + closest()。\n */\nfunction useHoveredCell(\n containerRef: React.RefObject<HTMLElement | null>,\n enabled: boolean,\n): CellId | null {\n const [hoveredCellId, setHoveredCellId] = React.useState<CellId | null>(null)\n\n React.useEffect(() => {\n if (!enabled) { setHoveredCellId(null); return }\n const container = containerRef.current\n if (!container) return\n\n const handleMouseOver = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null\n const cellEl = target?.closest<HTMLElement>('[data-cell-id]')\n const id = cellEl?.dataset.cellId ?? null\n setHoveredCellId(id)\n }\n const handleMouseLeave = () => setHoveredCellId(null)\n\n container.addEventListener('mouseover', handleMouseOver)\n container.addEventListener('mouseleave', handleMouseLeave)\n return () => {\n container.removeEventListener('mouseover', handleMouseOver)\n container.removeEventListener('mouseleave', handleMouseLeave)\n }\n }, [enabled, containerRef])\n\n return hoveredCellId\n}\n\n/**\n * Singleton interaction layer。\n *\n * Slice D Step 1A:HoverCellRect only。\n * Slice D Step 2/3/4:SelectionRect / ActiveEditorHost / RangeRect 漸進加入。\n */\nexport function DataTableInteractionLayer({\n enabled,\n containerRef,\n cellClickEntersEdit,\n activeEditorCellId,\n activeEditorEnabled = false,\n activeEditorRender,\n selectedCellId = null,\n // rangeCellIds retired 2026-05-10(outer ring 已 retire,range visual 靠 cell-bg `[data-range-cell]`)\n rangeCellIds: _rangeCellIds,\n}: DataTableInteractionLayerProps) {\n const hoveredCellId = useHoveredCell(containerRef, enabled)\n // 2026-05-10 RWD/scroll sync(per user mandate「所有 overlay 在各種 RWD 和捲動時都處在正確位置」):\n // window scroll(capture)+ resize + ResizeObserver(container)→ rAF coalesced re-render → rect 重算\n useReactiveRect(containerRef, enabled)\n\n // Contract 14 state precedence:editing > selected > hover(per RFC §State Precedence Matrix)\n const isEditingHovered = activeEditorCellId != null && activeEditorCellId === hoveredCellId\n const isSelectedHovered = selectedCellId != null && selectedCellId === hoveredCellId\n const shouldShowHover = enabled && hoveredCellId != null && !isEditingHovered && !isSelectedHovered\n && (cellClickEntersEdit ? cellClickEntersEdit(hoveredCellId) : true)\n\n // Issue 6 viewport clip(2026-05-10):每個 overlay rect 都跟最近 panel(left/center/right body)\n // intersect。Cell scroll 出 panel viewport(H scroll / pinned 範圍)→ rect null → 不 render;\n // 部分 → 用 ClipMask wrap 在 panel viewport 內裁切,outline 永遠在 cell 真邊但被 mask 限制視覺。\n const hoverGeo = shouldShowHover\n ? getCellGeometry(containerRef.current, hoveredCellId!)\n : null\n\n // Slice D Step 3 scaffold:ActiveEditorHost rect placeholder(per Contract 8 active editor paint owner)。\n // 2026-05-10 bug fix:gate by `activeEditorEnabled` flag(Step 3.3 portal Field work)。\n // Issue 6:active editor host **不**做 viewport clip(per codex「editor 必可見」),\n // 仍走原 path 從 getCellRect 取 viewport coords。User 應將 active editor cell 滾到 viewport 內。\n const activeEditorRect = activeEditorEnabled && activeEditorCellId != null\n ? getCellRect(containerRef.current, activeEditorCellId)\n : null\n\n // Slice D Step 4(spreadsheet semantics):SelectionRect + RangeRect with viewport clip。\n const selectedGeo = enabled && selectedCellId != null\n ? getCellGeometry(containerRef.current, selectedCellId)\n : null\n\n // 2026-05-10 retire `rangeOuterRingsByPanel` calc + render(per user 抓 range 2px outer\n // ring 不需要 — cell-bg `--primary-subtle` 已給「這些 cell 在範圍內」訊號,outer ring 是\n // redundant visual)。`CellRangeOuterRing` primitive 已 retire(下方刪),getCellGeometry 仍\n // 給 hover / selected overlay 使用,保留。Future 若需 outer ring 復用,從 git history 取\n // commit `763b3ac`(Issue 6 viewport clip)的 implementation。\n\n if (!enabled) return null\n\n // Layer absolute fixed-position relative to viewport(避 outer container 缺 position:relative\n // 找錯 reference frame)。getCellRect 已 return container-relative,但這裡 set top/left 用\n // page coords 一致 — 改用 viewport-fixed 簡化。\n return (\n <div\n aria-hidden\n style={{ position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 1 }}\n >\n {/* HoverRing — kind=hover(1px var(--border-hover)) z 1。Wrap 在 ClipMask(panel viewport)\n 內 → cell scroll 出 panel 時 outline 自動被 mask 裁切,不會 leak 到 panel 外。 */}\n {hoverGeo && (\n <ClipMask clipRect={hoverGeo.clipRect}>\n <CellRingOverlay rect={toRelRect(hoverGeo.rect, hoverGeo.clipRect)} kind=\"hover\" />\n </ClipMask>\n )}\n {/* SelectionRing — kind=selected(1px var(--primary)) z 2,SSOT 同 hover wide */}\n {selectedGeo && (\n <ClipMask clipRect={selectedGeo.clipRect}>\n <CellRingOverlay\n rect={toRelRect(selectedGeo.rect, selectedGeo.clipRect)}\n kind=\"selected\"\n cellId={selectedCellId!}\n />\n </ClipMask>\n )}\n {/* 2026-05-10 retire RangeOuterRing(per user 抓 image 4 + verbatim「range 的 cell 本來就有顏色變化,\n 那樣就夠了,不需要再有 2px 藍色的框」)。Range visual now relies purely on cell-bg\n (`--primary-subtle` via `[data-range-cell]` CSS in `data-table.css`)+ focus cell 1px selected\n border。Outer 2px primary ring 從 Issue 6 ship 但 visual 太重 — bg-fill 已給「這些 cell 在範圍內」\n 訊號,outer ring 是 redundant。calc + render 皆已 retire(變數已移除;future 若需 reinstate\n 參考 git history 2026-05-10)。 */}\n {/* {rangeOuterRingsByPanel.map((group) => (\n <ClipMask key={group.panel} clipRect={group.clipRect}>\n <CellRangeOuterRing rect={toRelRect(group.bbox, group.clipRect)} />\n </ClipMask>\n ))} */}\n {/* ActiveEditorHost — z 3,float rect,pointerEvents:auto opaque host(NOT a ring)。\n Issue 6:active editor 不 clip(editor 必可見) — user 滾出 viewport 自負責。 */}\n {activeEditorRect && (\n <ActiveEditorHost rect={activeEditorRect}>\n {activeEditorRender ? activeEditorRender(activeEditorCellId!, activeEditorRect) : null}\n </ActiveEditorHost>\n )}\n </div>\n )\n}\n\n/**\n * `toRelRect(cellRect, clipRect)` — Issue 6 helper(2026-05-10):\n * 把 viewport coords cell rect 轉成 ClipMask containing-block 內 relative coords。\n * ClipMask 用 panel rect 做 absolute container + overflow:hidden,內部 child absolute 定位\n * 以 mask 為 reference frame,所以 cellRect.x - clipRect.x 才對齊 cell 真實位置。\n */\nfunction toRelRect(cellRect: CellRect, clipRect: CellRect): CellRect {\n return {\n x: cellRect.x - clipRect.x,\n y: cellRect.y - clipRect.y,\n width: cellRect.width,\n height: cellRect.height,\n }\n}\n\n// ── Private primitives(per codex unified-ring-overlay-2026-05-10 Final A')──────\n//\n// 三個 private primitive 各自 own 一個 paint concern:\n// 1. CellRingOverlay — outline ring(hover / selected / future focus / error)\n// 2. CellRangeFill — bg fill(range cells in spreadsheet mode)\n// 3. ActiveEditorHost — opaque host(portal Field edit)\n//\n// SSOT pattern(共 3 primitives):rect float pass-through + boxSizing:border-box +\n// pointerEvents 視 kind / position:absolute on viewport-fixed layer。\n//\n// Token mapping 集中 `CELL_RING_STYLES`(per codex Q3 verdict 不開 global `--cell-ring-*` token,\n// 在 primitive 內 kind → semantic token mapping)。\n\nconst CELL_RING_STYLES = {\n hover: { width: 1, color: 'var(--border-hover)', zIndex: 1 },\n selected: { width: 1, color: 'var(--primary)', zIndex: 2 },\n // future kinds(per codex Q6 outline,加 entry 即可擴展):\n // focus: { width: 2, color: 'var(--primary)', zIndex: 2 },\n // error: { width: 1, color: 'var(--error)', zIndex: 2 },\n} as const\n\ntype CellRingKind = keyof typeof CELL_RING_STYLES\n\nfunction rectStyle(rect: CellRect): React.CSSProperties {\n return {\n position: 'absolute',\n left: rect.x,\n top: rect.y,\n width: rect.width,\n height: rect.height,\n }\n}\n\n/**\n * CellRingOverlay — paint owner for hover / selected / future focus / error rings。\n *\n * 共用 SSOT(per Bug 5 fix + codex Q2 unified primitive):\n * - Float pass-through rect(getCellRect 不 round)\n * - outline + outline-offset:`-${width}px` paint 在 cell 既有 border 上 in-place\n * - boxSizing:border-box(避免 outline 影響 layout)\n * - pointerEvents:none(透視點擊穿透)\n * - transition:none(避 fade flash)\n */\nfunction CellRingOverlay({ rect, kind, cellId }: {\n rect: CellRect\n kind: CellRingKind\n cellId?: CellId\n}) {\n const ring = CELL_RING_STYLES[kind]\n const dataAttr = kind === 'selected' && cellId ? { 'data-selected-cell-id': cellId } : {}\n return (\n <div\n aria-hidden\n style={{\n ...rectStyle(rect),\n outline: `${ring.width}px solid ${ring.color}`,\n outlineOffset: `-${ring.width}px`,\n boxSizing: 'border-box',\n pointerEvents: 'none',\n transition: 'none',\n zIndex: ring.zIndex,\n }}\n {...dataAttr}\n />\n )\n}\n\n// `CellRangeOuterRing` primitive retired 2026-05-10(per user 「range cell 本來就有顏色變化\n// 那樣就夠了,不需要再有 2px 藍色的框」)。Source 留 git history commit `763b3ac`(Issue 6\n// viewport clip ship)若需 reinstate。\n\n/**\n * ClipMask — Issue 6 primitive(2026-05-10):panel viewport 裁切容器。\n *\n * 用在 hover / selected / range outer ring overlay,避免 cell 滾出 panel viewport(H scroll /\n * pinned 範圍)時 overlay 仍漂浮在 panel 外。Layer 是 `position: fixed` viewport-anchor,\n * ClipMask 用 panel rect 當 absolute container + `overflow: hidden` mask;child overlay 用\n * `toRelRect(cellRect, clipRect)` 算出 mask-relative 座標,在 mask 內精準定位但被 mask 邊緣裁切。\n *\n * 對齊 AG Grid `cellsForRangeSet` viewport-aware paint / Glide DataGrid clip helpers /\n * Notion sticky-cell virtualizer mask。\n */\nfunction ClipMask({ clipRect, children }: { clipRect: CellRect; children: React.ReactNode }) {\n return (\n <div\n aria-hidden\n style={{\n position: 'absolute',\n left: clipRect.x,\n top: clipRect.y,\n width: clipRect.width,\n height: clipRect.height,\n overflow: 'hidden',\n pointerEvents: 'none',\n }}\n >\n {children}\n </div>\n )\n}\n\n/**\n * ActiveEditorHost — opaque host for portal Field edit(D.3,Slice D Step 5)。\n *\n * Per codex Q2 verdict:不該進 CellRingOverlay primitive — 它是 host 不是 ring。\n * - pointerEvents:auto(child Field 接收 click / keyboard)\n * - background:var(--canvas)(opaque cover display Field below;Cell SSOT 保留)\n * - z-index 3(above hover / selected / range)\n * - children = activeEditorRender 的回傳 React node\n *\n * Empty children fallback = dashed debug indicator(no portal Field provided)。\n */\nfunction ActiveEditorHost({ rect, children }: { rect: CellRect; children: React.ReactNode }) {\n if (!children) {\n return (\n <div\n aria-hidden\n style={{\n ...rectStyle(rect),\n pointerEvents: 'none',\n zIndex: 3,\n border: '1px dashed var(--primary)',\n boxSizing: 'border-box',\n }}\n data-active-editor-host-scaffold\n />\n )\n }\n return (\n <div\n style={{\n ...rectStyle(rect),\n pointerEvents: 'auto',\n zIndex: 3,\n boxSizing: 'border-box',\n background: 'var(--canvas)',\n }}\n data-active-editor-host\n >\n {children}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-table-interaction-layer.js","sources":["../../../src/components/DataTable/data-table-interaction-layer.tsx"],"sourcesContent":["// @internal — DS-internal 單元(viewport 覆蓋 paint layer,只被 data-table.tsx 內部消費);不隨 index.ts re-export 進 npm public surface。\n/**\n * DataTableInteractionLayer — Slice D Step 1A scaffold(per `.claude/planning/datatable-spreadsheet-rfc.md`)\n *\n * Singleton overlay root inside DataTable(M21 private,不抽 global pattern)。\n * Sub-layer children(2026-07-04 對齊實作;原 RFC 5-layer 清單含未實作元件):\n * - HoverCellRect(z 1):hover 邊框,「one geometry owner, two paint owners」(Contract 8)\n * - SelectionRing(z 2):spreadsheet mode selected cell 1px ring(CELL_RING_STYLES.selected)\n * - ActiveEditorHost(z 3):portal active edit Field(Slice C wire-up)\n * -(range 視覺 = CSS [data-range-cell] cell-bg,非 layer 元件;nested popup 走 Radix idiom\n * 見 active-editor-controller.ts — RangeRect / NestedPortalRegistry 元件不存在)\n *\n * Slice D Step 1A scope:\n * - getCellRect(cellId)geometry source(per Contract 8)\n * - HoverCellRect 1 layer 先做(Contract 8 / Contract 15 cellClickEntersEdit predicate)\n * - 默認 disabled via `experimentalSpreadsheetOverlay` flag,不破現有 outline\n * - 後續 Step 1B/C/D 漸進切換 + 拆 outline\n */\n\nimport * as React from 'react'\n\ntype CellId = string\n\ninterface CellRect {\n x: number\n y: number\n width: number\n height: number\n}\n\ninterface DataTableInteractionLayerProps {\n /** Flag default false:不破現有 outline。enable 後 hover/editor 走 overlay。 */\n enabled: boolean\n /** Container ref;geometry source(getCellRect 由此 query cell DOM)。layer root 本身是\n * position:fixed inset:0 viewport-anchor(見 render),非 container-origin absolute */\n containerRef: React.RefObject<HTMLDivElement | null>\n /** Per Contract 15:`cellClickEntersEdit` predicate;hover overlay 顯示與否 */\n cellClickEntersEdit?: (cellId: CellId) => boolean\n /**\n * Active editor cell id。null = 無 active editor。\n * 已接線(Slice D Step 5 完成,2026-07-14 docblock 對齊):activeEditorEnabled +\n * activeEditorCellId + activeEditorRender 齊 → ActiveEditorHost(z 3)portal render\n * 真 edit Field(per Contract 8「two paint owners」)。\n */\n activeEditorCellId?: CellId | null\n /**\n * Slice D Step 3.x flag:啟用 ActiveEditorHost dashed scaffold rect rendering。\n * 2026-05-10 bug fix(user 圖1 雙 ring 同時顯示):dashed scaffold 之前綁\n * `enabled`(= experimentalSpreadsheetOverlay)→ 任何 cell 進 edit mode 就 leak\n * 出 dashed rect。改 gate 給 `experimentalActiveEditorController`(Step 3.3 真\n * portal Field 工作),hover overlay scope 不會看到 dashed scaffold。\n */\n activeEditorEnabled?: boolean\n /**\n * Slice D Step 4(spreadsheet semantics,2026-05-10 user 圖1 ask + RFC Contract 5):\n * Excel-like 選取 cell ID。Click 1 select / Click 2 enter edit。\n * Layer renders solid border SelectionRect(per user「不要 dash 直接實的就好」)。\n */\n selectedCellId?: CellId | null\n /**\n * Slice D Step 5(D.3 portal Field,2026-05-10 user 拍板「在乎完美乾淨」+ codex Q6.1\n * 撤回 defer):active editor render callback。當 activeEditorEnabled + activeEditorCellId\n * truthy → layer call this 拿 React node(已 bind value/onCommit/onCancel from controller),\n * 在 ActiveEditorHost portal(z 3,float rect)render 之。\n *\n * Per codex Q6.2 outline:cell 永遠 mode=\"display\"(SSOT preserved);portal host 渲\n * mode=\"edit\" 同 registry component;float pass-through + z-index 3 cover display below。\n */\n activeEditorRender?: (cellId: CellId, rect: CellRect) => React.ReactNode\n}\n\n/**\n * `getCellRect(cellId)` geometry source(per Contract 8)。\n *\n * 從 DOM 量(per-call `getBoundingClientRect()`)而非 layoutCache,因為:\n * 1. cell DOM 是 React-rendered,getBoundingClientRect 永遠是 source of truth\n * 2. layoutCache 需另寫 invalidation logic,added complexity\n * 3. Hover overlay re-render 頻率低(per cell hover,不是 per frame)\n *\n * Float coords pass-through — no rounding / no snap(v3 fix,見下方 v3 註解;原 RFC 0.5px snap 已撤)。\n */\nfunction getCellRect(containerEl: HTMLElement | null, cellId: CellId): CellRect | null {\n if (!containerEl) return null\n const cellEl = containerEl.querySelector<HTMLElement>(`[data-cell-id=\"${cellId}\"]`)\n if (!cellEl) return null\n // Page-absolute coords for viewport-fixed layer(per Step 1C bug fix:layer\n // 用 position:fixed,讓 paint owner 跟 reference frame 解耦 outer container 的 positioning)。\n // 2026-05-10 v3 fix(user 圖5 SSOT consistency):**float coords no rounding**。\n // Cell 自身 layout 用 sub-pixel float position(CSS 不 snap to integer)— 跨 cell 累積\n // 常見 144.328 / 244.0 / 524.172 等 fractional。任何 Math.round / floor / ceil 都引入\n // varying rounding error(visual audit verified:dx=0.17/0.5/0.83 不一致)。\n // Float pass-through + outline + outline-offset:-1px(下方 paint)→ overlay 永遠跟\n // cell exact pixel-perfect overlap,user verbatim「在內容起始位置不變的前提下讓\n // overlay 的邊框直接剛好壓住 cell 邊框」達成。\n const rect = cellEl.getBoundingClientRect()\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n }\n}\n\n/**\n * Issue 6 viewport clip(2026-05-10):cell 跟 panel(left/center/right)bounding rect 一起取,\n * layer 用 panel rect 當 clip viewport intersect cell rect → overlay 永不畫到 panel 外。\n *\n * Per codex 13-issues verdict:「getCellRect 找最近 scroll viewport;intersect(cellRect, viewportRect),\n * 空 → 不 render,部分 → clipped rect render。」\n *\n * 對齊 AG Grid `cellsForRangeSet` viewport-aware paint / Glide DataGrid clip helpers /\n * Notion sticky-cell virtualizer mask。\n */\ninterface CellGeometry {\n /** Cell exact viewport rect(no rounding,float pass-through per Bug 5 SSOT) */\n rect: CellRect\n /** Nearest panel container rect(left/center/right body)— clip viewport for overlays */\n clipRect: CellRect\n /** Panel identifier(`left` / `center` / `right`)— grouped range outer ring 分段用 */\n panel: 'left' | 'center' | 'right'\n}\n\nfunction getCellGeometry(containerEl: HTMLElement | null, cellId: CellId): CellGeometry | null {\n if (!containerEl) return null\n const cellEl = containerEl.querySelector<HTMLElement>(`[data-cell-id=\"${cellId}\"]`)\n if (!cellEl) return null\n const panelEl = cellEl.closest<HTMLElement>('[data-datatable-panel]')\n if (!panelEl) return null\n const panel = panelEl.dataset.datatablePanel as 'left' | 'center' | 'right'\n const cellR = cellEl.getBoundingClientRect()\n const panelR = panelEl.getBoundingClientRect()\n return {\n rect: { x: cellR.x, y: cellR.y, width: cellR.width, height: cellR.height },\n clipRect: { x: panelR.x, y: panelR.y, width: panelR.width, height: panelR.height },\n panel,\n }\n}\n\n\n/**\n * Reactive rect sync hook — 確保 overlay rect 跨 RWD / scroll / resize 永遠對齊 cell(2026-05-10\n * user 拍板「所有 overlay 在各種 RWD 和捲動時都能處在正確位置上」)。\n *\n * 監聽 3 source(rAF coalesce 避 frame storm):\n * 1. window scroll(capture mode 抓 nested table body scroll + page scroll)\n * 2. window resize(viewport size change → cell width 變)\n * 3. ResizeObserver on container(column resize / table dimension 變)\n *\n * 每次事件 fire → setVersion(v+1) → 觸發 layer re-render → rect 用最新 getBoundingClientRect\n * 重算。getBoundingClientRect 本身永遠 return 當下 viewport-relative coords,沒 stale cache。\n *\n * Per codex(brief: codex-brief-rwd-future-2026-05-10):rAF coalesce 不需要 debounce,scroll\n * 跟到不延遲才對(Glide / AG Grid 同 idiom)。\n */\nfunction useReactiveRect(containerRef: React.RefObject<HTMLElement | null>, enabled: boolean) {\n const [, setVersion] = React.useState(0)\n React.useEffect(() => {\n if (!enabled) return\n let rafId: number | null = null\n const force = () => {\n if (rafId !== null) return\n rafId = requestAnimationFrame(() => {\n rafId = null\n setVersion((v) => v + 1)\n })\n }\n window.addEventListener('scroll', force, { capture: true, passive: true })\n window.addEventListener('resize', force, { passive: true })\n const container = containerRef.current\n let ro: ResizeObserver | null = null\n if (container && typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(force)\n ro.observe(container)\n }\n return () => {\n window.removeEventListener('scroll', force, { capture: true } as EventListenerOptions)\n window.removeEventListener('resize', force)\n if (ro) ro.disconnect()\n if (rafId !== null) cancelAnimationFrame(rafId)\n }\n }, [enabled, containerRef])\n}\n\n/**\n * Hover state hook — 監聽 container hover events,track hovered cell id。\n *\n * Implementation:event delegation on container(不 per-cell mount listeners),\n * 利用 `data-cell-id` attribute + closest()。\n */\nfunction useHoveredCell(\n containerRef: React.RefObject<HTMLElement | null>,\n enabled: boolean,\n): CellId | null {\n const [hoveredCellId, setHoveredCellId] = React.useState<CellId | null>(null)\n\n React.useEffect(() => {\n if (!enabled) { setHoveredCellId(null); return }\n const container = containerRef.current\n if (!container) return\n\n const handleMouseOver = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null\n const cellEl = target?.closest<HTMLElement>('[data-cell-id]')\n const id = cellEl?.dataset.cellId ?? null\n setHoveredCellId(id)\n }\n const handleMouseLeave = () => setHoveredCellId(null)\n\n container.addEventListener('mouseover', handleMouseOver)\n container.addEventListener('mouseleave', handleMouseLeave)\n return () => {\n container.removeEventListener('mouseover', handleMouseOver)\n container.removeEventListener('mouseleave', handleMouseLeave)\n }\n }, [enabled, containerRef])\n\n return hoveredCellId\n}\n\n/**\n * Singleton interaction layer(全 sub-layer 已接線;2026-07-14 docblock 對齊實作)。\n *\n * 現況:HoverCellRect(z 1)+ SelectionRing(z 2)+ ActiveEditorHost(z 3,portal edit Field);\n * range 視覺走 cell 自身 CSS `[data-range-cell]`(RangeRect / rangeCellIds prop 已 retire)。\n * layer root = position:fixed inset:0 viewport-anchor,pointerEvents:none(僅 ActiveEditorHost 開 auto)。\n */\nexport function DataTableInteractionLayer({\n enabled,\n containerRef,\n cellClickEntersEdit,\n activeEditorCellId,\n activeEditorEnabled = false,\n activeEditorRender,\n selectedCellId = null,\n}: DataTableInteractionLayerProps) {\n const hoveredCellId = useHoveredCell(containerRef, enabled)\n // 2026-05-10 RWD/scroll sync(per user mandate「所有 overlay 在各種 RWD 和捲動時都處在正確位置」):\n // window scroll(capture)+ resize + ResizeObserver(container)→ rAF coalesced re-render → rect 重算\n useReactiveRect(containerRef, enabled)\n\n // Contract 14 state precedence:editing > selected > hover(per RFC §State Precedence Matrix)\n const isEditingHovered = activeEditorCellId != null && activeEditorCellId === hoveredCellId\n const isSelectedHovered = selectedCellId != null && selectedCellId === hoveredCellId\n const shouldShowHover = enabled && hoveredCellId != null && !isEditingHovered && !isSelectedHovered\n && (cellClickEntersEdit ? cellClickEntersEdit(hoveredCellId) : true)\n\n // Issue 6 viewport clip(2026-05-10):每個 overlay rect 都跟最近 panel(left/center/right body)\n // intersect。Cell scroll 出 panel viewport(H scroll / pinned 範圍)→ rect null → 不 render;\n // 部分 → 用 ClipMask wrap 在 panel viewport 內裁切,outline 永遠在 cell 真邊但被 mask 限制視覺。\n const hoverGeo = shouldShowHover\n ? getCellGeometry(containerRef.current, hoveredCellId!)\n : null\n\n // Slice D Step 3 scaffold:ActiveEditorHost rect placeholder(per Contract 8 active editor paint owner)。\n // 2026-05-10 bug fix:gate by `activeEditorEnabled` flag(Step 3.3 portal Field work)。\n // Issue 6:active editor host **不**做 viewport clip(per codex「editor 必可見」),\n // 仍走原 path 從 getCellRect 取 viewport coords。User 應將 active editor cell 滾到 viewport 內。\n const activeEditorRect = activeEditorEnabled && activeEditorCellId != null\n ? getCellRect(containerRef.current, activeEditorCellId)\n : null\n\n // Slice D Step 4(spreadsheet semantics):SelectionRing with viewport clip(RangeRect 已 retire — range 視覺走 CSS [data-range-cell])。\n const selectedGeo = enabled && selectedCellId != null\n ? getCellGeometry(containerRef.current, selectedCellId)\n : null\n\n // 2026-05-10 retire `rangeOuterRingsByPanel` calc + render(per user 抓 range 2px outer\n // ring 不需要 — cell-bg `--primary-subtle` 已給「這些 cell 在範圍內」訊號,outer ring 是\n // redundant visual)。`CellRangeOuterRing` primitive 已 retire(下方刪),getCellGeometry 仍\n // 給 hover / selected overlay 使用,保留。Future 若需 outer ring 復用,從 git history 取\n // commit `763b3ac`(Issue 6 viewport clip)的 implementation。\n\n if (!enabled) return null\n\n // Layer absolute fixed-position relative to viewport(避 outer container 缺 position:relative\n // 找錯 reference frame)。getCellRect 已 return container-relative,但這裡 set top/left 用\n // page coords 一致 — 改用 viewport-fixed 簡化。\n return (\n <div\n aria-hidden\n style={{ position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 1 }}\n >\n {/* HoverRing — kind=hover(1px var(--border-hover)) z 1。Wrap 在 ClipMask(panel viewport)\n 內 → cell scroll 出 panel 時 outline 自動被 mask 裁切,不會 leak 到 panel 外。 */}\n {hoverGeo && (\n <ClipMask clipRect={hoverGeo.clipRect}>\n <CellRingOverlay rect={toRelRect(hoverGeo.rect, hoverGeo.clipRect)} kind=\"hover\" />\n </ClipMask>\n )}\n {/* SelectionRing — kind=selected(1px var(--primary)) z 2,SSOT 同 hover wide */}\n {selectedGeo && (\n <ClipMask clipRect={selectedGeo.clipRect}>\n <CellRingOverlay\n rect={toRelRect(selectedGeo.rect, selectedGeo.clipRect)}\n kind=\"selected\"\n cellId={selectedCellId!}\n />\n </ClipMask>\n )}\n {/* 2026-05-10 retire RangeOuterRing(per user 抓 image 4 + verbatim「range 的 cell 本來就有顏色變化,\n 那樣就夠了,不需要再有 2px 藍色的框」)。Range visual now relies purely on cell-bg\n (`--primary-subtle` via `[data-range-cell]` CSS in `data-table.css`)+ focus cell 1px selected\n border。Outer 2px primary ring 從 Issue 6 ship 但 visual 太重 — bg-fill 已給「這些 cell 在範圍內」\n 訊號,outer ring 是 redundant。calc + render 皆已 retire(變數已移除;future 若需 reinstate\n 參考 git history 2026-05-10)。 */}\n {/* {rangeOuterRingsByPanel.map((group) => (\n <ClipMask key={group.panel} clipRect={group.clipRect}>\n <CellRangeOuterRing rect={toRelRect(group.bbox, group.clipRect)} />\n </ClipMask>\n ))} */}\n {/* ActiveEditorHost — z 3,float rect,pointerEvents:auto opaque host(NOT a ring)。\n Issue 6:active editor 不 clip(editor 必可見) — user 滾出 viewport 自負責。 */}\n {activeEditorRect && (\n <ActiveEditorHost rect={activeEditorRect}>\n {activeEditorRender ? activeEditorRender(activeEditorCellId!, activeEditorRect) : null}\n </ActiveEditorHost>\n )}\n </div>\n )\n}\n\n/**\n * `toRelRect(cellRect, clipRect)` — Issue 6 helper(2026-05-10):\n * 把 viewport coords cell rect 轉成 ClipMask containing-block 內 relative coords。\n * ClipMask 用 panel rect 做 absolute container + overflow:hidden,內部 child absolute 定位\n * 以 mask 為 reference frame,所以 cellRect.x - clipRect.x 才對齊 cell 真實位置。\n */\nfunction toRelRect(cellRect: CellRect, clipRect: CellRect): CellRect {\n return {\n x: cellRect.x - clipRect.x,\n y: cellRect.y - clipRect.y,\n width: cellRect.width,\n height: cellRect.height,\n }\n}\n\n// ── Private primitives(per codex unified-ring-overlay-2026-05-10 Final A')──────\n//\n// 三個 private primitive 各自 own 一個 paint concern(2026-07-14 對齊實作:CellRangeFill\n// 不存在 — range bg 走 cell 自身 CSS `[data-range-cell]`,非 layer 元件):\n// 1. CellRingOverlay — outline ring(hover / selected / future focus / error)\n// 2. ClipMask — panel viewport 裁切 wrapper(Issue 6 partial-visibility)\n// 3. ActiveEditorHost — opaque host(portal Field edit)\n//\n// SSOT pattern(共 3 primitives):rect float pass-through + boxSizing:border-box +\n// pointerEvents 視 kind / position:absolute on viewport-fixed layer。\n//\n// Token mapping 集中 `CELL_RING_STYLES`(per codex Q3 verdict 不開 global `--cell-ring-*` token,\n// 在 primitive 內 kind → semantic token mapping)。\n\nconst CELL_RING_STYLES = {\n hover: { width: 1, color: 'var(--border-hover)', zIndex: 1 },\n selected: { width: 1, color: 'var(--primary)', zIndex: 2 },\n // future kinds(per codex Q6 outline,加 entry 即可擴展):\n // focus: { width: 2, color: 'var(--primary)', zIndex: 2 },\n // error: { width: 1, color: 'var(--error)', zIndex: 2 },\n} as const\n\ntype CellRingKind = keyof typeof CELL_RING_STYLES\n\nfunction rectStyle(rect: CellRect): React.CSSProperties {\n return {\n position: 'absolute',\n left: rect.x,\n top: rect.y,\n width: rect.width,\n height: rect.height,\n }\n}\n\n/**\n * CellRingOverlay — paint owner for hover / selected / future focus / error rings。\n *\n * 共用 SSOT(per Bug 5 fix + codex Q2 unified primitive):\n * - Float pass-through rect(getCellRect 不 round)\n * - outline + outline-offset:`-${width}px` paint 在 cell 既有 border 上 in-place\n * - boxSizing:border-box(避免 outline 影響 layout)\n * - pointerEvents:none(透視點擊穿透)\n * - transition:none(避 fade flash)\n */\nfunction CellRingOverlay({ rect, kind, cellId }: {\n rect: CellRect\n kind: CellRingKind\n cellId?: CellId\n}) {\n const ring = CELL_RING_STYLES[kind]\n const dataAttr = kind === 'selected' && cellId ? { 'data-selected-cell-id': cellId } : {}\n return (\n <div\n aria-hidden\n style={{\n ...rectStyle(rect),\n outline: `${ring.width}px solid ${ring.color}`,\n outlineOffset: `-${ring.width}px`,\n boxSizing: 'border-box',\n pointerEvents: 'none',\n transition: 'none',\n zIndex: ring.zIndex,\n }}\n {...dataAttr}\n />\n )\n}\n\n// `CellRangeOuterRing` primitive retired 2026-05-10(per user 「range cell 本來就有顏色變化\n// 那樣就夠了,不需要再有 2px 藍色的框」)。Source 留 git history commit `763b3ac`(Issue 6\n// viewport clip ship)若需 reinstate。\n\n/**\n * ClipMask — Issue 6 primitive(2026-05-10):panel viewport 裁切容器。\n *\n * 用在 hover / selected / range outer ring overlay,避免 cell 滾出 panel viewport(H scroll /\n * pinned 範圍)時 overlay 仍漂浮在 panel 外。Layer 是 `position: fixed` viewport-anchor,\n * ClipMask 用 panel rect 當 absolute container + `overflow: hidden` mask;child overlay 用\n * `toRelRect(cellRect, clipRect)` 算出 mask-relative 座標,在 mask 內精準定位但被 mask 邊緣裁切。\n *\n * 對齊 AG Grid `cellsForRangeSet` viewport-aware paint / Glide DataGrid clip helpers /\n * Notion sticky-cell virtualizer mask。\n */\nfunction ClipMask({ clipRect, children }: { clipRect: CellRect; children: React.ReactNode }) {\n return (\n <div\n aria-hidden\n style={{\n position: 'absolute',\n left: clipRect.x,\n top: clipRect.y,\n width: clipRect.width,\n height: clipRect.height,\n overflow: 'hidden',\n pointerEvents: 'none',\n }}\n >\n {children}\n </div>\n )\n}\n\n/**\n * ActiveEditorHost — opaque host for portal Field edit(D.3,Slice D Step 5)。\n *\n * Per codex Q2 verdict:不該進 CellRingOverlay primitive — 它是 host 不是 ring。\n * - pointerEvents:auto(child Field 接收 click / keyboard)\n * - background:var(--canvas)(opaque cover display Field below;Cell SSOT 保留)\n * - z-index 3(above hover / selected / range)\n * - children = activeEditorRender 的回傳 React node\n *\n * Empty children fallback = dashed debug indicator(no portal Field provided)。\n */\nfunction ActiveEditorHost({ rect, children }: { rect: CellRect; children: React.ReactNode }) {\n if (!children) {\n return (\n <div\n aria-hidden\n style={{\n ...rectStyle(rect),\n pointerEvents: 'none',\n zIndex: 3,\n border: '1px dashed var(--primary)',\n boxSizing: 'border-box',\n }}\n data-active-editor-host-scaffold\n />\n )\n }\n return (\n <div\n style={{\n ...rectStyle(rect),\n pointerEvents: 'auto',\n zIndex: 3,\n boxSizing: 'border-box',\n background: 'var(--canvas)',\n }}\n data-active-editor-host\n >\n {children}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { RotateCcw, X, Plus, GripVertical, Trash2 } from "lucide-react";
4
+ import { DndContext, closestCenter } from "@dnd-kit/core";
5
+ import { SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
6
+ import { CSS } from "@dnd-kit/utilities";
7
+ import { cn } from "../../lib/utils.js";
8
+ import { dragSourceStyle, dragHandleCursorClass } from "../../lib/drag-visual.js";
9
+ import { Button } from "../Button/button.js";
10
+ import { Select } from "../Select/select.js";
11
+ import { SurfaceHeader, COMPACT_HEADER_SLOT, SurfaceBody } from "../../patterns/overlay-surface/overlay-surface.js";
12
+ import { ButtonDivider } from "../Button/button-group.js";
13
+ import { PopoverTitle, PopoverClose } from "../Popover/popover.js";
14
+ import { ItemInlineActionButton } from "../../patterns/element-anatomy/item-anatomy.js";
15
+ import { getColumnId, getColumnLabel } from "./lib/column-meta.js";
16
+ function extractColumns(columns) {
17
+ const out = [];
18
+ for (const col of columns) {
19
+ const id = getColumnId(col);
20
+ if (!id || id === "__select__") continue;
21
+ if (col.enableSorting === false) continue;
22
+ out.push({ id, label: getColumnLabel(col, id), enableSorting: true });
23
+ }
24
+ return out;
25
+ }
26
+ const DIRECTION_OPTIONS = [
27
+ { value: "asc", label: "升冪" },
28
+ { value: "desc", label: "降冪" }
29
+ ];
30
+ function DataTableSortManager({
31
+ columns,
32
+ sorting,
33
+ onSortingChange,
34
+ onReset,
35
+ onClose,
36
+ className
37
+ }) {
38
+ const sortableColumns = React.useMemo(() => extractColumns(columns), [columns]);
39
+ const fieldOptions = React.useMemo(
40
+ () => sortableColumns.map((c) => ({ value: c.id, label: c.label })),
41
+ [sortableColumns]
42
+ );
43
+ const updateAt = (index, patch) => {
44
+ const next = sorting.map((s, i) => i === index ? { ...s, ...patch } : s);
45
+ onSortingChange(next);
46
+ };
47
+ const removeAt = (index) => {
48
+ onSortingChange(sorting.filter((_, i) => i !== index));
49
+ };
50
+ const handleDragEnd = (event) => {
51
+ const { active, over } = event;
52
+ if (!over || active.id === over.id) return;
53
+ const oldIndex = sorting.findIndex((s) => s.id === active.id);
54
+ const newIndex = sorting.findIndex((s) => s.id === over.id);
55
+ if (oldIndex < 0 || newIndex < 0) return;
56
+ const next = [...sorting];
57
+ const [moved] = next.splice(oldIndex, 1);
58
+ next.splice(newIndex, 0, moved);
59
+ onSortingChange(next);
60
+ };
61
+ const addSort = () => {
62
+ const used = new Set(sorting.map((s) => s.id));
63
+ const firstUnused = sortableColumns.find((c) => !used.has(c.id));
64
+ if (!firstUnused) return;
65
+ onSortingChange([...sorting, { id: firstUnused.id, desc: false }]);
66
+ };
67
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full min-h-0 w-[var(--data-table-sort-panel-width)]", className), children: [
68
+ /* @__PURE__ */ jsxs(SurfaceHeader, { className: COMPACT_HEADER_SLOT, children: [
69
+ /* @__PURE__ */ jsx(PopoverTitle, { className: "flex-1", children: "排序" }),
70
+ onReset && sorting.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
71
+ /* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", iconOnly: true, startIcon: RotateCcw, "aria-label": "重置", onClick: onReset }),
72
+ onClose && /* @__PURE__ */ jsx(ButtonDivider, {})
73
+ ] }),
74
+ onClose && /* @__PURE__ */ jsx(PopoverClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { "data-dismiss": true, iconOnly: true, dismiss: true, size: "sm", startIcon: X, "aria-label": "關閉", onClick: onClose }) })
75
+ ] }),
76
+ /* @__PURE__ */ jsxs(SurfaceBody, { className: "flex flex-col gap-[var(--layout-space-tight)]", children: [
77
+ sorting.length > 0 && /* @__PURE__ */ jsx(DndContext, { collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsx(SortableContext, { items: sorting.map((s) => s.id), strategy: verticalListSortingStrategy, children: sorting.map((sort, index) => {
78
+ const usedByOthers = new Set(sorting.filter((_, i) => i !== index).map((s) => s.id));
79
+ const optionsForRow = fieldOptions.filter((o) => !usedByOthers.has(o.value));
80
+ return /* @__PURE__ */ jsx(
81
+ SortRow,
82
+ {
83
+ sort,
84
+ optionsForRow,
85
+ onChangeId: (v) => updateAt(index, { id: v }),
86
+ onChangeDir: (v) => updateAt(index, { desc: v === "desc" }),
87
+ onRemove: () => removeAt(index)
88
+ },
89
+ sort.id
90
+ );
91
+ }) }) }),
92
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
93
+ Button,
94
+ {
95
+ variant: "tertiary",
96
+ size: "sm",
97
+ startIcon: Plus,
98
+ onClick: addSort,
99
+ disabled: sorting.length >= sortableColumns.length,
100
+ children: "加排序"
101
+ }
102
+ ) })
103
+ ] })
104
+ ] });
105
+ }
106
+ DataTableSortManager.displayName = "DataTableSortManager";
107
+ function SortRow({
108
+ sort,
109
+ optionsForRow,
110
+ onChangeId,
111
+ onChangeDir,
112
+ onRemove
113
+ }) {
114
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: sort.id });
115
+ const style = {
116
+ transform: CSS.Transform.toString(transform),
117
+ transition,
118
+ ...dragSourceStyle(isDragging)
119
+ };
120
+ return /* @__PURE__ */ jsxs("div", { ref: setNodeRef, style, className: "flex items-center gap-2", children: [
121
+ /* @__PURE__ */ jsx(
122
+ ItemInlineActionButton,
123
+ {
124
+ icon: GripVertical,
125
+ size: "sm",
126
+ "aria-label": "拖曳重排",
127
+ className: dragHandleCursorClass,
128
+ ...attributes,
129
+ ...listeners
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx(Select, { size: "sm", options: optionsForRow, value: sort.id, onChange: onChangeId }) }),
133
+ /* @__PURE__ */ jsx("div", { className: "w-32 shrink-0", children: /* @__PURE__ */ jsx(Select, { size: "sm", options: DIRECTION_OPTIONS, value: sort.desc ? "desc" : "asc", onChange: onChangeDir, minRows: 2 }) }),
134
+ /* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", iconOnly: true, startIcon: Trash2, "aria-label": "刪除", onClick: onRemove })
135
+ ] });
136
+ }
137
+ export {
138
+ DataTableSortManager
139
+ };
140
+ //# sourceMappingURL=data-table-sort-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-sort-manager.js","sources":["../../../src/components/DataTable/data-table-sort-manager.tsx"],"sourcesContent":["// @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.\n// same-row-mixed-allow: header chrome corner buttons(refresh/close)跟 row inline actions(drag/trash)不在同 row\nimport * as React from 'react'\nimport { Plus, Trash2, X as XIcon, RotateCcw, GripVertical } from 'lucide-react'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DndContext, closestCenter, type DragEndEvent } from '@dnd-kit/core'\nimport { SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable'\nimport { CSS } from '@dnd-kit/utilities'\nimport { cn } from '@/lib/utils'\nimport { dragSourceStyle, dragHandleCursorClass } from '@/design-system/lib/drag-visual'\nimport { Button } from '@/design-system/components/Button/button'\nimport { Select, type SelectOption } from '@/design-system/components/Select/select'\nimport { SurfaceHeader, SurfaceBody, COMPACT_HEADER_SLOT } from '@/design-system/patterns/overlay-surface/overlay-surface'\nimport { ButtonDivider } from '@/design-system/components/Button/button-group'\nimport { PopoverTitle, PopoverClose } from '@/design-system/components/Popover/popover'\nimport { ItemInlineActionButton } from '@/design-system/patterns/element-anatomy/item-anatomy'\nimport { getColumnId, getColumnLabel } from './lib/column-meta'\n\n/**\n * DataTableSortManager — Notion-style 多欄排序管理 panel\n *\n * 對齊 ref/進階篩選/sort.png 設計:\n * Header(title + refresh + close)/ list(field + direction + delete + reorder)/\n * footer(+ 加排序)。\n *\n * Source-of-truth: TanStack `SortingState`(同 `useReactTable.state.sorting`)。\n * 跟 cell click sort 共享 state — single source-of-truth across cell + panel。\n *\n * Reorder:DnD(useSortable + GripVertical handle,見下方 SortRow)——原 MVP ↑/↓ button 已退役。\n */\n\ninterface SortColumn {\n id: string\n label: string\n enableSorting?: boolean\n}\n\nexport interface DataTableSortManagerProps<TData> {\n /** 可排序欄位來源(讀 columnDef.header / id);會自動排除 enableSorting=false */\n columns: ColumnDef<TData, any>[]\n /** 當前排序 state(TanStack SortingState) */\n sorting: SortingState\n /** 排序變更 callback */\n onSortingChange: (next: SortingState) => void\n /** Refresh 按鈕點擊(可選 — 重置或外部 refetch) */\n onReset?: () => void\n /** Close 按鈕點擊(若有 — 通常是包在 Popover 外層的 close 行為) */\n onClose?: () => void\n className?: string\n}\n\nfunction extractColumns<TData>(columns: ColumnDef<TData, any>[]): SortColumn[] {\n const out: SortColumn[] = []\n for (const col of columns) {\n const id = getColumnId(col)\n if (!id || id === '__select__') continue\n if (col.enableSorting === false) continue\n out.push({ id, label: getColumnLabel(col, id), enableSorting: true })\n }\n return out\n}\n\nconst DIRECTION_OPTIONS: SelectOption[] = [\n { value: 'asc', label: '升冪' },\n { value: 'desc', label: '降冪' },\n]\n\nexport function DataTableSortManager<TData>({\n columns,\n sorting,\n onSortingChange,\n onReset,\n onClose,\n className,\n}: DataTableSortManagerProps<TData>) {\n const sortableColumns = React.useMemo(() => extractColumns(columns), [columns])\n const fieldOptions: SelectOption[] = React.useMemo(\n () => sortableColumns.map((c) => ({ value: c.id, label: c.label })),\n [sortableColumns]\n )\n\n const updateAt = (index: number, patch: Partial<{ id: string; desc: boolean }>) => {\n const next = sorting.map((s, i) => (i === index ? { ...s, ...patch } : s))\n onSortingChange(next)\n }\n const removeAt = (index: number) => {\n onSortingChange(sorting.filter((_, i) => i !== index))\n }\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event\n if (!over || active.id === over.id) return\n const oldIndex = sorting.findIndex((s) => s.id === active.id)\n const newIndex = sorting.findIndex((s) => s.id === over.id)\n if (oldIndex < 0 || newIndex < 0) return\n const next = [...sorting]\n const [moved] = next.splice(oldIndex, 1)\n next.splice(newIndex, 0, moved)\n onSortingChange(next)\n }\n const addSort = () => {\n const used = new Set(sorting.map((s) => s.id))\n const firstUnused = sortableColumns.find((c) => !used.has(c.id))\n if (!firstUnused) return\n onSortingChange([...sorting, { id: firstUnused.id, desc: false }])\n }\n\n // K11 fix(2026-05-04): viewport-aware scroll chain invariant — 詳 overlay-surface.spec.md\n // 2026-05-23 Phase A.4 Decision 2: w-[480px] → token `--data-table-sort-panel-width`(SSOT in uiSize.css)\n return (\n <div className={cn('flex flex-col h-full min-h-0 w-[var(--data-table-sort-panel-width)]', className)}>\n {/* Popover 派輕量 chrome — slot 走 COMPACT_HEADER_SLOT(=21,衍生自 PopoverTitle text-body line-box),header 自然 ~45px */}\n <SurfaceHeader className={COMPACT_HEADER_SLOT}>\n <PopoverTitle className=\"flex-1\">排序</PopoverTitle>\n {onReset && sorting.length > 0 && (\n <>\n <Button variant=\"text\" size=\"sm\" iconOnly startIcon={RotateCcw} aria-label=\"重置\" onClick={onReset} />\n {onClose && <ButtonDivider />}\n </>\n )}\n {onClose && (\n <PopoverClose asChild>\n <Button data-dismiss iconOnly dismiss size=\"sm\" startIcon={XIcon} aria-label=\"關閉\" onClick={onClose} />\n </PopoverClose>\n )}\n </SurfaceHeader>\n\n {/* Body — 條件 list + inline 加排序 CTA(對齊 filter panel canonical Q3+Q6,2026-05-04)\n 無條件時 CTA 直接顯示,不需要 Empty 大區塊 */}\n <SurfaceBody className=\"flex flex-col gap-[var(--layout-space-tight)]\">\n {sorting.length > 0 && (\n <DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>\n <SortableContext items={sorting.map(s => s.id)} strategy={verticalListSortingStrategy}>\n {sorting.map((sort, index) => {\n const usedByOthers = new Set(sorting.filter((_, i) => i !== index).map((s) => s.id))\n const optionsForRow = fieldOptions.filter((o) => !usedByOthers.has(o.value))\n return (\n <SortRow\n key={sort.id}\n sort={sort}\n optionsForRow={optionsForRow}\n onChangeId={(v) => updateAt(index, { id: v })}\n onChangeDir={(v) => updateAt(index, { desc: v === 'desc' })}\n onRemove={() => removeAt(index)}\n />\n )\n })}\n </SortableContext>\n </DndContext>\n )}\n\n {/* B1 加排序 → tertiary,parallel filter「加篩選」(root-level CTA 對等視覺重量) */}\n <div>\n <Button\n variant=\"tertiary\"\n size=\"sm\"\n startIcon={Plus}\n onClick={addSort}\n disabled={sorting.length >= sortableColumns.length}\n >\n 加排序\n </Button>\n </div>\n </SurfaceBody>\n </div>\n )\n}\n\nDataTableSortManager.displayName = 'DataTableSortManager'\n\n// SortRow:DnD-enabled row。GripVertical 為 drag listener handle(對齊 Notion / Airtable 拖曳 idiom)。\nfunction SortRow({\n sort, optionsForRow, onChangeId, onChangeDir, onRemove,\n}: {\n sort: { id: string; desc: boolean }\n optionsForRow: SelectOption[]\n onChangeId: (v: string) => void\n onChangeDir: (v: string) => void\n onRemove: () => void\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: sort.id })\n // 對齊 lib/drag-visual.ts SSOT:source dim 用 `--opacity-disabled` token(不 hardcode 0.5)\n const style: React.CSSProperties = {\n transform: CSS.Transform.toString(transform),\n transition,\n ...dragSourceStyle(isDragging),\n }\n // **#5 fix(2026-05-04)**:row 內水平 gap = gap-2 (8px),layoutSpace 規則 5 緊密相關\n // SurfaceBody row↔row vertical 仍 tight(12)— 不同 row 不緊密\n return (\n <div ref={setNodeRef} style={style} className=\"flex items-center gap-2\">\n <ItemInlineActionButton\n icon={GripVertical}\n size=\"sm\"\n aria-label=\"拖曳重排\"\n className={dragHandleCursorClass}\n {...attributes}\n {...listeners}\n />\n <div className=\"flex-1 min-w-0\">\n <Select size=\"sm\" options={optionsForRow} value={sort.id} onChange={onChangeId} />\n </div>\n <div className=\"w-32 shrink-0\">\n {/* minRows={2} — 升冪/降冪只 2 選項,顯式縮 menu 高度(Q5) */}\n <Select size=\"sm\" options={DIRECTION_OPTIONS} value={sort.desc ? 'desc' : 'asc'} onChange={onChangeDir} minRows={2} />\n </div>\n {/* Trash 用 text Button(Q4 對齊 filter panel)— form-control row 必 Field 同高 */}\n <Button variant=\"text\" size=\"sm\" iconOnly startIcon={Trash2} aria-label=\"刪除\" onClick={onRemove} />\n </div>\n )\n}\n"],"names":["XIcon"],"mappings":"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"}
@@ -83,9 +83,6 @@ export interface DataTableProps<TData> extends Omit<React.HTMLAttributes<HTMLDiv
83
83
  defaultSelection?: string[] | DataTableSelection;
84
84
  /** Selection 變更 callback(emit DataTableSelection union;include / all 兩模型) */
85
85
  onSelectionChange?: (next: DataTableSelection) => void;
86
- /** 全資料集筆數 M(server-side / filter 後);all 模式 count = totalCount − excluded.length。
87
- * **DS 內部零消費(no-op prop)**:僅型別文件 + destructure 防 spread 到 DOM;count 全由 consumer 計算 */
88
- totalCount?: number;
89
86
  /** 是否啟用 selection / 模式;true 等同 'multi' */
90
87
  selectable?: boolean | 'single' | 'multi';
91
88
  /** Row 是否可選(disabled rows 只 disable checkbox,row 內容正常 render) */
@@ -124,7 +121,7 @@ export interface DataTableProps<TData> extends Omit<React.HTMLAttributes<HTMLDiv
124
121
  *
125
122
  * **v2(2026-05-05)修正**:
126
123
  * - Virtualizer × transform:被拖 row 略過 `measureElement`(透過 SortableRowCtx 廣播 active id),避免 transform 干擾測量
127
- * - 3-panel mirror sync:每 region 對同 row id 各呼叫 `useDraggable` + `useDroppable`,mirror 自然取得相同 transform
124
+ * - 3-panel mirror sync:primary region 呼叫 `useDraggable` + `useDroppable`;mirror region 只 `useDroppable`(v15.4 split),isDragging 由 `useDndContext` active.id 同步 → 三 region 視覺一致
128
125
  * - Cross-parent drop:nested 全 row 各自 `useDroppable`,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`
129
126
  *
130
127
  * 詳 `data-table.spec.md`「L4 Row drag」段。
@@ -185,7 +182,7 @@ export interface DataTablePaginationOptions {
185
182
  pageSize?: number;
186
183
  /** 每頁筆數選項;傳了才渲染「每頁 N 筆」Select(消費既有 Select size="sm") */
187
184
  pageSizeOptions?: number[];
188
- /** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 totalCount) */
185
+ /** 左側「共 N 筆」文字(opt-in,= Ant showTotal 邏輯;數源 = filter 後全集 getPrePaginationRowModel,非 selection all-mode 的 server-side 全集數 M — 那是 consumer 自持) */
189
186
  showTotal?: boolean;
190
187
  /** 當前頁(1-based,controlled;不傳 = uncontrolled) */
191
188
  page?: number;
@@ -203,7 +200,9 @@ export interface DataTablePaginationOptions {
203
200
  * 解決「全選 10k 筆只載 50 筆 → 無法列舉其餘 ID」:all 模式「選取 = 全集 − excluded」,
204
201
  * 任何 toggle 都只是 excluded 的 add/remove,對任意順序封閉、O(1)、不需列舉未載入 ID。
205
202
  *
206
- * 計數(consumer):mode==='all' ? totalCount − excluded.length : ids.length(需傳 totalCount)。
203
+ * 計數(consumer):mode==='all' ? M − excluded.length : ids.length(M = consumer 自持的
204
+ * server-side / filter 後全集筆數;2026-07-13 D1 拍板:DataTable 不收 totalCount prop — DS 內部
205
+ * 零消費 no-op 已移除,計數本來就全由 consumer 端算)。
207
206
  * 進入 all 模式:consumer 在「選取全部 M」hint 點擊時 setSelection({ mode: 'all', excluded: [] })。
208
207
  */
209
208
  export type DataTableSelection = {
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/data-table.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/data-table.tsx"],"names":[],"mappings":"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"}