@qijenchen/design-system 0.1.0-beta.145 → 0.1.0-beta.147

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 (576) hide show
  1. package/dist/components/Accordion/accordion.d.ts +1 -1
  2. package/dist/components/Accordion/accordion.d.ts.map +1 -1
  3. package/dist/components/Accordion/accordion.js +8 -3
  4. package/dist/components/Accordion/accordion.js.map +1 -1
  5. package/dist/components/AccountMenu/account-menu.d.ts.map +1 -1
  6. package/dist/components/AccountMenu/account-menu.js.map +1 -1
  7. package/dist/components/AgentPanel/agent-panel-fab.d.ts +7 -1
  8. package/dist/components/AgentPanel/agent-panel-fab.d.ts.map +1 -1
  9. package/dist/components/AgentPanel/agent-panel-fab.js +36 -14
  10. package/dist/components/AgentPanel/agent-panel-fab.js.map +1 -1
  11. package/dist/components/AgentPanel/agent-panel-logo.d.ts +3 -3
  12. package/dist/components/AgentPanel/agent-panel-logo.js.map +1 -1
  13. package/dist/components/AgentPanel/agent-panel.d.ts +1 -1
  14. package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -1
  15. package/dist/components/AgentPanel/agent-panel.js +28 -22
  16. package/dist/components/AgentPanel/agent-panel.js.map +1 -1
  17. package/dist/components/AppShell/app-shell.d.ts +1 -1
  18. package/dist/components/AppShell/app-shell.js +1 -1
  19. package/dist/components/AppShell/app-shell.js.map +1 -1
  20. package/dist/components/Avatar/avatar.d.ts +95 -1
  21. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  22. package/dist/components/Avatar/avatar.js +106 -15
  23. package/dist/components/Avatar/avatar.js.map +1 -1
  24. package/dist/components/Avatar/index.js +14 -2
  25. package/dist/components/Breadcrumb/breadcrumb.d.ts +4 -2
  26. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  27. package/dist/components/Breadcrumb/breadcrumb.js +2 -2
  28. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  29. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  30. package/dist/components/BulkActionBar/bulk-action-bar.js +27 -2
  31. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  32. package/dist/components/Button/button.d.ts +2 -2
  33. package/dist/components/Button/button.d.ts.map +1 -1
  34. package/dist/components/Button/button.js +118 -22
  35. package/dist/components/Button/button.js.map +1 -1
  36. package/dist/components/Calendar/calendar.d.ts +34 -10
  37. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  38. package/dist/components/Calendar/calendar.js +210 -36
  39. package/dist/components/Calendar/calendar.js.map +1 -1
  40. package/dist/components/Carousel/carousel.d.ts +1 -1
  41. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  42. package/dist/components/Carousel/carousel.js +3 -2
  43. package/dist/components/Carousel/carousel.js.map +1 -1
  44. package/dist/components/Chart/chart.d.ts +1 -0
  45. package/dist/components/Chart/chart.d.ts.map +1 -1
  46. package/dist/components/Chart/chart.js +8 -0
  47. package/dist/components/Chart/chart.js.map +1 -1
  48. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  49. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  50. package/dist/components/Checkbox/checkbox.js +10 -2
  51. package/dist/components/Checkbox/checkbox.js.map +1 -1
  52. package/dist/components/Chip/chip.d.ts +1 -1
  53. package/dist/components/Chip/chip.d.ts.map +1 -1
  54. package/dist/components/Chip/chip.js +4 -2
  55. package/dist/components/Chip/chip.js.map +1 -1
  56. package/dist/components/Combobox/combobox.d.ts +1 -1
  57. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  58. package/dist/components/Combobox/combobox.js +37 -11
  59. package/dist/components/Combobox/combobox.js.map +1 -1
  60. package/dist/components/Command/command.d.ts +1 -1
  61. package/dist/components/Command/command.d.ts.map +1 -1
  62. package/dist/components/Command/command.js +106 -8
  63. package/dist/components/Command/command.js.map +1 -1
  64. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  65. package/dist/components/DataTable/cell-registry.js +3 -2
  66. package/dist/components/DataTable/cell-registry.js.map +1 -1
  67. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
  68. package/dist/components/DataTable/data-table-column-visibility-panel.js +24 -24
  69. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
  70. package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -1
  71. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  72. package/dist/components/DataTable/data-table-interaction-layer.js +3 -4
  73. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  74. package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -1
  75. package/dist/components/DataTable/data-table-sort-manager.js +20 -20
  76. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
  77. package/dist/components/DataTable/data-table.d.ts +8 -5
  78. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  79. package/dist/components/DataTable/data-table.js +197 -71
  80. package/dist/components/DataTable/data-table.js.map +1 -1
  81. package/dist/components/DateGrid/date-grid.d.ts +1 -1
  82. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  83. package/dist/components/DateGrid/date-grid.js +358 -225
  84. package/dist/components/DateGrid/date-grid.js.map +1 -1
  85. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  86. package/dist/components/DatePicker/date-picker.js +16 -1
  87. package/dist/components/DatePicker/date-picker.js.map +1 -1
  88. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  89. package/dist/components/Dialog/dialog.js +55 -43
  90. package/dist/components/Dialog/dialog.js.map +1 -1
  91. package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts +86 -0
  92. package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts.map +1 -0
  93. package/dist/components/DropdownMenu/dropdown-menu-keyboard.js +172 -0
  94. package/dist/components/DropdownMenu/dropdown-menu-keyboard.js.map +1 -0
  95. package/dist/components/DropdownMenu/dropdown-menu.d.ts +6 -1
  96. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  97. package/dist/components/DropdownMenu/dropdown-menu.js +50 -39
  98. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  99. package/dist/components/Field/field-context.d.ts +4 -0
  100. package/dist/components/Field/field-context.d.ts.map +1 -1
  101. package/dist/components/Field/field-context.js +1 -2
  102. package/dist/components/Field/field-context.js.map +1 -1
  103. package/dist/components/Field/field-edit-keys.d.ts +8 -0
  104. package/dist/components/Field/field-edit-keys.d.ts.map +1 -1
  105. package/dist/components/Field/field-edit-keys.js +3 -0
  106. package/dist/components/Field/field-edit-keys.js.map +1 -1
  107. package/dist/components/Field/field-wrapper.d.ts +18 -1
  108. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  109. package/dist/components/Field/field-wrapper.js +39 -10
  110. package/dist/components/Field/field-wrapper.js.map +1 -1
  111. package/dist/components/Field/field.d.ts +3 -2
  112. package/dist/components/Field/field.d.ts.map +1 -1
  113. package/dist/components/Field/field.js +2 -1
  114. package/dist/components/Field/field.js.map +1 -1
  115. package/dist/components/FileItem/file-item.d.ts +26 -2
  116. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  117. package/dist/components/FileItem/file-item.js +82 -25
  118. package/dist/components/FileItem/file-item.js.map +1 -1
  119. package/dist/components/FileItem/index.js +4 -2
  120. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  121. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  122. package/dist/components/FileUpload/file-upload.js +132 -55
  123. package/dist/components/FileUpload/file-upload.js.map +1 -1
  124. package/dist/components/FileViewer/file-viewer.d.ts +1 -1
  125. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  126. package/dist/components/FileViewer/file-viewer.js +9 -4
  127. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
  129. package/dist/components/InlineEdit/inline-edit.js +1 -1
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -1
  131. package/dist/components/Input/input.d.ts.map +1 -1
  132. package/dist/components/Input/input.js +6 -1
  133. package/dist/components/Input/input.js.map +1 -1
  134. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  135. package/dist/components/LinkInput/link-input.js +20 -4
  136. package/dist/components/LinkInput/link-input.js.map +1 -1
  137. package/dist/components/Notice/notice.js +1 -1
  138. package/dist/components/Notice/notice.js.map +1 -1
  139. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  140. package/dist/components/NumberInput/number-input.js +6 -1
  141. package/dist/components/NumberInput/number-input.js.map +1 -1
  142. package/dist/components/OverflowIndicator/index.js +2 -1
  143. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +19 -1
  144. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  145. package/dist/components/OverflowIndicator/overflow-indicator.js +47 -27
  146. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  147. package/dist/components/Pagination/pagination.d.ts +1 -1
  148. package/dist/components/Pagination/pagination.js +1 -1
  149. package/dist/components/Pagination/pagination.js.map +1 -1
  150. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +7 -6
  151. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -1
  152. package/dist/components/PeoplePicker/avatar-stack-overflow.js +6 -7
  153. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -1
  155. package/dist/components/PeoplePicker/people-picker-helpers.js +1 -1
  156. package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -1
  157. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  158. package/dist/components/PeoplePicker/people-picker.js +2 -2
  159. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  161. package/dist/components/PeoplePicker/person-display.js +26 -28
  162. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  163. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
  164. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  165. package/dist/components/RadioGroup/radio-group.d.ts +1 -1
  166. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  167. package/dist/components/RadioGroup/radio-group.js +10 -4
  168. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  169. package/dist/components/Rating/rating.d.ts +28 -6
  170. package/dist/components/Rating/rating.d.ts.map +1 -1
  171. package/dist/components/Rating/rating.js +97 -80
  172. package/dist/components/Rating/rating.js.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.d.ts +1 -1
  174. package/dist/components/ScrollArea/scroll-area.js +1 -1
  175. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  176. package/dist/components/SegmentedControl/segmented-control.d.ts +1 -1
  177. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  178. package/dist/components/SegmentedControl/segmented-control.js +3 -2
  179. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  180. package/dist/components/Select/select.d.ts.map +1 -1
  181. package/dist/components/Select/select.js +15 -8
  182. package/dist/components/Select/select.js.map +1 -1
  183. package/dist/components/SelectMenu/index.js +2 -1
  184. package/dist/components/SelectMenu/index.js.map +1 -1
  185. package/dist/components/SelectMenu/select-menu-keyboard.d.ts +59 -0
  186. package/dist/components/SelectMenu/select-menu-keyboard.d.ts.map +1 -0
  187. package/dist/components/SelectMenu/select-menu-keyboard.js +107 -0
  188. package/dist/components/SelectMenu/select-menu-keyboard.js.map +1 -0
  189. package/dist/components/SelectMenu/select-menu.d.ts +1 -22
  190. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  191. package/dist/components/SelectMenu/select-menu.js +18 -34
  192. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  193. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
  194. package/dist/components/SelectionControl/selection-item.js +1 -0
  195. package/dist/components/SelectionControl/selection-item.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +7 -9
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +171 -50
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts +1 -1
  201. package/dist/components/Slider/slider.d.ts.map +1 -1
  202. package/dist/components/Slider/slider.js +9 -4
  203. package/dist/components/Slider/slider.js.map +1 -1
  204. package/dist/components/Steps/steps.d.ts.map +1 -1
  205. package/dist/components/Steps/steps.js +54 -26
  206. package/dist/components/Steps/steps.js.map +1 -1
  207. package/dist/components/Switch/switch.d.ts +1 -1
  208. package/dist/components/Switch/switch.d.ts.map +1 -1
  209. package/dist/components/Switch/switch.js +7 -2
  210. package/dist/components/Switch/switch.js.map +1 -1
  211. package/dist/components/Tabs/tabs.d.ts +1 -1
  212. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  213. package/dist/components/Tabs/tabs.js +39 -4
  214. package/dist/components/Tabs/tabs.js.map +1 -1
  215. package/dist/components/Tag/tag.d.ts +1 -1
  216. package/dist/components/Tag/tag.d.ts.map +1 -1
  217. package/dist/components/Tag/tag.js +3 -2
  218. package/dist/components/Tag/tag.js.map +1 -1
  219. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  220. package/dist/components/Textarea/textarea.js +8 -2
  221. package/dist/components/Textarea/textarea.js.map +1 -1
  222. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  223. package/dist/components/TimePicker/time-columns.js +8 -4
  224. package/dist/components/TimePicker/time-columns.js.map +1 -1
  225. package/dist/components/TimePicker/time-picker.d.ts +1 -1
  226. package/dist/components/TimePicker/time-picker.js +1 -1
  227. package/dist/components/TimePicker/time-picker.js.map +1 -1
  228. package/dist/components/TreeView/tree-view.d.ts +9 -5
  229. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  230. package/dist/components/TreeView/tree-view.js +266 -214
  231. package/dist/components/TreeView/tree-view.js.map +1 -1
  232. package/dist/hooks/use-input-modality.d.ts +12 -17
  233. package/dist/hooks/use-input-modality.d.ts.map +1 -1
  234. package/dist/hooks/use-input-modality.js +4 -34
  235. package/dist/hooks/use-input-modality.js.map +1 -1
  236. package/dist/hooks/use-overflow-items.d.ts.map +1 -1
  237. package/dist/hooks/use-overflow-items.js +2 -0
  238. package/dist/hooks/use-overflow-items.js.map +1 -1
  239. package/dist/hooks/use-truncated.d.ts.map +1 -1
  240. package/dist/hooks/use-truncated.js.map +1 -1
  241. package/dist/index.d.ts +3 -0
  242. package/dist/index.d.ts.map +1 -1
  243. package/dist/index.js +23 -3
  244. package/dist/index.js.map +1 -1
  245. package/dist/lib/drag-announcements.d.ts +32 -0
  246. package/dist/lib/drag-announcements.d.ts.map +1 -1
  247. package/dist/lib/drag-announcements.js +39 -1
  248. package/dist/lib/drag-announcements.js.map +1 -1
  249. package/dist/lib/focus-after-trigger.d.ts +45 -0
  250. package/dist/lib/focus-after-trigger.d.ts.map +1 -0
  251. package/dist/lib/focus-after-trigger.js +66 -0
  252. package/dist/lib/focus-after-trigger.js.map +1 -0
  253. package/dist/lib/overlay-coexistence.js +1 -1
  254. package/dist/lib/roving-list-keyboard.d.ts +208 -0
  255. package/dist/lib/roving-list-keyboard.d.ts.map +1 -0
  256. package/dist/lib/roving-list-keyboard.js +174 -0
  257. package/dist/lib/roving-list-keyboard.js.map +1 -0
  258. package/dist/lib/utils.d.ts.map +1 -1
  259. package/dist/lib/utils.js +6 -1
  260. package/dist/lib/utils.js.map +1 -1
  261. package/dist/patterns/element-anatomy/item-anatomy.d.ts +4 -4
  262. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  263. package/dist/patterns/element-anatomy/item-anatomy.js +14 -4
  264. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  265. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -1
  266. package/dist/patterns/horizontal-overflow/horizontal-overflow.js +25 -0
  267. package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -1
  268. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  269. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  270. package/dist/tokens/categorical-color.d.ts +6 -1
  271. package/dist/tokens/categorical-color.d.ts.map +1 -1
  272. package/dist/tokens/categorical-color.js.map +1 -1
  273. package/dist/tokens/uiSize/icon-size.d.ts +1 -1
  274. package/dist/tokens/uiSize/stack-gap.d.ts +18 -0
  275. package/dist/tokens/uiSize/stack-gap.d.ts.map +1 -0
  276. package/dist/tokens/uiSize/stack-gap.js +5 -0
  277. package/dist/tokens/uiSize/stack-gap.js.map +1 -0
  278. package/ds-canonical/fork/codex/agents/skills/performance-audit/SKILL.md +1 -1
  279. package/ds-canonical/fork/codex/hooks.json +1 -1
  280. package/ds-canonical/fork/consumer/lock.json +17 -14
  281. package/ds-canonical/fork/consumer/managed-files/423729840acdd43c812f17c245b871716c6b60f76e4d3e94864d0e34a815bf8d.blob +9 -0
  282. package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +47 -9
  283. package/ds-canonical/fork/consumer/managed-files/5a0d134a2645114c8caac20458070b00a7f0fd55b3e8805b7325cb4cf52fa15e.blob +110 -0
  284. package/ds-canonical/fork/consumer/managed-files/5af0a46760af338d51fd0f7950675f8e97f7d2f09386b8818fcd7a58e6654e75.blob +790 -0
  285. package/ds-canonical/fork/consumer/managed-files/68bfcddff9c4a16388c248cd34fb66163e9e64b3d809a48ef3984f6ae4ff6d12.blob +211 -0
  286. package/ds-canonical/fork/consumer/managed-files/7eb6cc60abfdabaf6617c336058fad1454ccde08889295767bfd9b7fd153cc6e.blob +45 -6
  287. package/ds-canonical/fork/consumer/managed-files/92e4828cdcb96ff0d01daa16f6885f24045a8e72820665650f2a1890dc3a446c.blob +42 -2
  288. package/ds-canonical/fork/consumer/managed-files/ab072e7f2eca51f0e18a5e18c4b333260ee5d219a12cc6df5bb2d683f0b2734d.blob +27 -1
  289. package/ds-canonical/fork/consumer/managed-files/e71c65f45c6af7ce12b6b3c0d8028f185da5b719e2050c9b2a6b243d41ae4878.blob +62 -14
  290. package/ds-canonical/fork/governance.lock +41 -17
  291. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +16 -4
  292. package/ds-canonical/fork/hooks/check_consumer_code_quality.sh +3 -1
  293. package/ds-canonical/fork/hooks/check_pattern_invariants.sh +13 -9
  294. package/ds-canonical/fork/launchers/settings-hooks.json +1 -1
  295. package/ds-canonical/fork/manifest.json +17 -11
  296. package/ds-canonical/fork/providers/claude/skills/performance-audit/SKILL.md +1 -1
  297. package/ds-canonical/fork/providers/codex/hook-config.json +1 -1
  298. package/ds-canonical/fork/providers/codex/skills/performance-audit/SKILL.md +1 -1
  299. package/ds-canonical/fork/skills/performance-audit/SKILL.md +1 -1
  300. package/ds-canonical/hooks/check_consumer_app_invariants.sh +16 -4
  301. package/ds-canonical/hooks/check_consumer_code_quality.sh +3 -1
  302. package/ds-canonical/hooks/check_datatable_invariants.sh +4 -1
  303. package/ds-canonical/hooks/check_pattern_invariants.sh +13 -9
  304. package/ds-canonical/hooks/check_plugin_fork_health.sh +8 -1
  305. package/ds-canonical/hooks/check_propose_discipline.sh +8 -1
  306. package/ds-canonical/hooks/check_storybook_addon_packaging.sh +8 -1
  307. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +64 -2
  308. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +5 -2
  309. package/ds-canonical/hooks/registrations.json +12 -7
  310. package/ds-canonical/hooks/session_start_governance_check.sh +16 -0
  311. package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +25 -0
  312. package/ds-canonical/hooks/tests/test_check_consumer_code_quality.sh +4 -0
  313. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +14 -0
  314. package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +24 -0
  315. package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +32 -0
  316. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +59 -0
  317. package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +32 -1
  318. package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +21 -0
  319. package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +21 -0
  320. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +97 -0
  321. package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +49 -0
  322. package/ds-canonical/references/README.md +12 -6
  323. package/ds-canonical/references/drag-canonical.md +3 -1
  324. package/ds-canonical/references/focus-canonical.md +26 -13
  325. package/ds-canonical/references/governance-audit-coverage.md +1 -1
  326. package/ds-canonical/references/hit-area-canonical.md +361 -0
  327. package/ds-canonical/references/item-anatomy-recipe.md +4 -2
  328. package/ds-canonical/references/keyboard-model-canonical.md +559 -0
  329. package/ds-canonical/rules/meta-patterns.md +4 -4
  330. package/ds-canonical/rules/self-verify.md +4 -4
  331. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1 -1
  332. package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +96 -0
  333. package/ds-canonical/skills/knowledge-prune/SKILL.md +4 -1
  334. package/ds-canonical/skills/performance-audit/SKILL.md +1 -1
  335. package/ds-story-manifest.json +19 -7
  336. package/llms-full.txt +2 -2
  337. package/llms.txt +2 -2
  338. package/package.json +3 -1
  339. package/src/components/Accordion/accordion.anatomy.stories.tsx +3 -3
  340. package/src/components/Accordion/accordion.spec.md +1 -1
  341. package/src/components/Accordion/accordion.tsx +8 -3
  342. package/src/components/AccountMenu/account-menu.spec.md +2 -3
  343. package/src/components/AccountMenu/account-menu.tsx +0 -1
  344. package/src/components/AgentPanel/agent-decision-card.spec.md +88 -0
  345. package/src/components/AgentPanel/agent-panel-fab.spec.md +151 -0
  346. package/src/components/AgentPanel/agent-panel-fab.tsx +67 -24
  347. package/src/components/AgentPanel/agent-panel-logo.spec.md +87 -0
  348. package/src/components/AgentPanel/agent-panel-logo.tsx +3 -3
  349. package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +1 -1
  350. package/src/components/AgentPanel/agent-panel.principles.stories.tsx +1 -1
  351. package/src/components/AgentPanel/agent-panel.spec.md +30 -275
  352. package/src/components/AgentPanel/agent-panel.stories.tsx +113 -8
  353. package/src/components/AgentPanel/agent-panel.tsx +59 -22
  354. package/src/components/Alert/alert.anatomy.stories.tsx +1 -1
  355. package/src/components/AppShell/app-shell.tsx +1 -1
  356. package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +10 -15
  357. package/src/components/Avatar/avatar.anatomy.stories.tsx +23 -26
  358. package/src/components/Avatar/avatar.principles.stories.tsx +10 -10
  359. package/src/components/Avatar/avatar.spec.md +45 -6
  360. package/src/components/Avatar/avatar.stories.tsx +8 -8
  361. package/src/components/Avatar/avatar.tsx +227 -21
  362. package/src/components/Badge/badge.anatomy.stories.tsx +16 -21
  363. package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +3 -3
  364. package/src/components/Breadcrumb/breadcrumb.spec.md +3 -3
  365. package/src/components/Breadcrumb/breadcrumb.tsx +5 -3
  366. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +1 -1
  367. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +1 -1
  368. package/src/components/BulkActionBar/bulk-action-bar.spec.md +1 -0
  369. package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +57 -2
  370. package/src/components/BulkActionBar/bulk-action-bar.tsx +32 -2
  371. package/src/components/Button/button.anatomy.stories.tsx +174 -33
  372. package/src/components/Button/button.spec.md +23 -8
  373. package/src/components/Button/button.tsx +116 -21
  374. package/src/components/Calendar/calendar.anatomy.stories.tsx +34 -11
  375. package/src/components/Calendar/calendar.principles.stories.tsx +44 -1
  376. package/src/components/Calendar/calendar.spec.md +97 -20
  377. package/src/components/Calendar/calendar.stories.tsx +101 -4
  378. package/src/components/Calendar/calendar.tsx +379 -74
  379. package/src/components/Carousel/carousel.anatomy.stories.tsx +16 -17
  380. package/src/components/Carousel/carousel.spec.md +48 -2
  381. package/src/components/Carousel/carousel.tsx +9 -3
  382. package/src/components/Chart/chart.anatomy.stories.tsx +7 -5
  383. package/src/components/Chart/chart.spec.md +32 -7
  384. package/src/components/Chart/chart.tsx +9 -0
  385. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +21 -28
  386. package/src/components/Checkbox/checkbox.spec.md +4 -2
  387. package/src/components/Checkbox/checkbox.tsx +10 -2
  388. package/src/components/Chip/chip.anatomy.stories.tsx +1 -1
  389. package/src/components/Chip/chip.spec.md +2 -1
  390. package/src/components/Chip/chip.tsx +4 -2
  391. package/src/components/Combobox/combobox.anatomy.stories.tsx +30 -37
  392. package/src/components/Combobox/combobox.spec.md +11 -3
  393. package/src/components/Combobox/combobox.tsx +43 -12
  394. package/src/components/Command/command.spec.md +11 -0
  395. package/src/components/Command/command.tsx +143 -10
  396. package/src/components/DataTable/cell-registry.tsx +5 -1
  397. package/src/components/DataTable/data-table-column-visibility-panel.tsx +5 -6
  398. package/src/components/DataTable/data-table-interaction-layer.tsx +27 -14
  399. package/src/components/DataTable/data-table-known-defects.spec.md +72 -0
  400. package/src/components/DataTable/data-table-scroll-performance.spec.md +295 -0
  401. package/src/components/DataTable/data-table-sort-manager.tsx +5 -6
  402. package/src/components/DataTable/data-table.anatomy.stories.tsx +1 -1
  403. package/src/components/DataTable/data-table.css +64 -0
  404. package/src/components/DataTable/data-table.spec.md +70 -346
  405. package/src/components/DataTable/data-table.stories.tsx +56 -9
  406. package/src/components/DataTable/data-table.tsx +392 -103
  407. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +2 -2
  408. package/src/components/DateGrid/date-grid.spec.md +163 -1
  409. package/src/components/DateGrid/date-grid.tsx +270 -7
  410. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +18 -27
  411. package/src/components/DatePicker/date-picker.spec.md +6 -2
  412. package/src/components/DatePicker/date-picker.tsx +20 -1
  413. package/src/components/Dialog/dialog.spec.md +6 -2
  414. package/src/components/Dialog/dialog.stories.tsx +18 -9
  415. package/src/components/Dialog/dialog.tsx +83 -48
  416. package/src/components/DropdownMenu/dropdown-menu-keyboard.ts +255 -0
  417. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +32 -33
  418. package/src/components/DropdownMenu/dropdown-menu.spec.md +18 -5
  419. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +58 -1
  420. package/src/components/DropdownMenu/dropdown-menu.tsx +70 -33
  421. package/src/components/Empty/empty.spec.md +1 -2
  422. package/src/components/Field/field-context.ts +9 -4
  423. package/src/components/Field/field-controls.spec.md +5 -2
  424. package/src/components/Field/field-edit-keys.ts +12 -0
  425. package/src/components/Field/field-wrapper.tsx +76 -10
  426. package/src/components/Field/field.anatomy.stories.tsx +1 -1
  427. package/src/components/Field/field.spec.md +11 -6
  428. package/src/components/Field/field.stories.tsx +24 -1
  429. package/src/components/Field/field.tsx +10 -4
  430. package/src/components/FileItem/file-item.anatomy.stories.tsx +20 -10
  431. package/src/components/FileItem/file-item.principles.stories.tsx +14 -7
  432. package/src/components/FileItem/file-item.spec.md +50 -48
  433. package/src/components/FileItem/file-item.stories.tsx +41 -28
  434. package/src/components/FileItem/file-item.tsx +184 -50
  435. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +11 -15
  436. package/src/components/FileUpload/file-upload.spec.md +27 -1
  437. package/src/components/FileUpload/file-upload.stories.tsx +33 -0
  438. package/src/components/FileUpload/file-upload.tsx +173 -43
  439. package/src/components/FileViewer/file-viewer.tsx +9 -4
  440. package/src/components/HoverCard/hover-card.stories.tsx +2 -2
  441. package/src/components/InlineEdit/inline-edit.spec.md +2 -0
  442. package/src/components/InlineEdit/inline-edit.tsx +8 -3
  443. package/src/components/Input/input.anatomy.stories.tsx +23 -31
  444. package/src/components/Input/input.spec.md +11 -0
  445. package/src/components/Input/input.tsx +6 -1
  446. package/src/components/LinkInput/link-input.anatomy.stories.tsx +18 -21
  447. package/src/components/LinkInput/link-input.principles.stories.tsx +4 -4
  448. package/src/components/LinkInput/link-input.spec.md +12 -1
  449. package/src/components/LinkInput/link-input.tsx +37 -4
  450. package/src/components/Menu/menu-item.anatomy.stories.tsx +50 -56
  451. package/src/components/Menu/menu-item.spec.md +1 -1
  452. package/src/components/Menu/menu-item.stories.tsx +48 -42
  453. package/src/components/Notice/notice.anatomy.stories.tsx +8 -16
  454. package/src/components/Notice/notice.spec.md +1 -1
  455. package/src/components/Notice/notice.tsx +1 -1
  456. package/src/components/NumberInput/number-input.anatomy.stories.tsx +21 -28
  457. package/src/components/NumberInput/number-input.spec.md +2 -0
  458. package/src/components/NumberInput/number-input.tsx +8 -1
  459. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +28 -48
  460. package/src/components/OverflowIndicator/overflow-indicator.spec.md +13 -1
  461. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +12 -9
  462. package/src/components/OverflowIndicator/overflow-indicator.tsx +32 -12
  463. package/src/components/Pagination/pagination.spec.md +1 -0
  464. package/src/components/Pagination/pagination.tsx +1 -1
  465. package/src/components/PeoplePicker/avatar-stack-overflow.ts +14 -13
  466. package/src/components/PeoplePicker/people-picker-helpers.ts +5 -2
  467. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +1 -1
  468. package/src/components/PeoplePicker/people-picker.spec.md +4 -2
  469. package/src/components/PeoplePicker/people-picker.tsx +1 -4
  470. package/src/components/PeoplePicker/person-display.tsx +45 -28
  471. package/src/components/Popover/popover.anatomy.stories.tsx +1 -1
  472. package/src/components/Popover/popover.principles.stories.tsx +3 -12
  473. package/src/components/Popover/popover.spec.md +7 -3
  474. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  475. package/src/components/ProfileCard/profile-card.spec.md +1 -1
  476. package/src/components/ProfileCard/profile-card.tsx +0 -3
  477. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +11 -21
  478. package/src/components/ProgressBar/progress-bar.spec.md +1 -1
  479. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +17 -24
  480. package/src/components/RadioGroup/radio-group.spec.md +1 -1
  481. package/src/components/RadioGroup/radio-group.tsx +22 -4
  482. package/src/components/Rating/rating.anatomy.stories.tsx +131 -124
  483. package/src/components/Rating/rating.principles.stories.tsx +69 -43
  484. package/src/components/Rating/rating.spec.md +142 -63
  485. package/src/components/Rating/rating.stories.tsx +11 -15
  486. package/src/components/Rating/rating.tsx +131 -117
  487. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  488. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +6 -3
  489. package/src/components/ScrollArea/scroll-area.spec.md +3 -1
  490. package/src/components/ScrollArea/scroll-area.stories.tsx +5 -2
  491. package/src/components/ScrollArea/scroll-area.tsx +1 -1
  492. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
  493. package/src/components/SegmentedControl/segmented-control.spec.md +2 -2
  494. package/src/components/SegmentedControl/segmented-control.tsx +3 -2
  495. package/src/components/Select/select.anatomy.stories.tsx +26 -35
  496. package/src/components/Select/select.spec.md +4 -3
  497. package/src/components/Select/select.tsx +11 -4
  498. package/src/components/SelectMenu/select-menu-keyboard.ts +218 -0
  499. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +6 -17
  500. package/src/components/SelectMenu/select-menu.spec.md +12 -4
  501. package/src/components/SelectMenu/select-menu.tsx +21 -56
  502. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +9 -33
  503. package/src/components/SelectionControl/selection-item.spec.md +2 -2
  504. package/src/components/SelectionControl/selection-item.tsx +3 -1
  505. package/src/components/Separator/separator.stories.tsx +4 -4
  506. package/src/components/Sheet/sheet.principles.stories.tsx +31 -13
  507. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +1 -1
  508. package/src/components/Sidebar/sidebar.spec.md +73 -6
  509. package/src/components/Sidebar/sidebar.stories.tsx +82 -4
  510. package/src/components/Sidebar/sidebar.tsx +281 -64
  511. package/src/components/Skeleton/skeleton.spec.md +1 -1
  512. package/src/components/Slider/slider.anatomy.stories.tsx +1 -1
  513. package/src/components/Slider/slider.spec.md +6 -5
  514. package/src/components/Slider/slider.tsx +13 -8
  515. package/src/components/Steps/steps-state-visuals.spec.md +157 -0
  516. package/src/components/Steps/steps.anatomy.stories.tsx +1 -0
  517. package/src/components/Steps/steps.spec.md +59 -142
  518. package/src/components/Steps/steps.stories.tsx +1 -1
  519. package/src/components/Steps/steps.tsx +125 -33
  520. package/src/components/Switch/switch.spec.md +3 -3
  521. package/src/components/Switch/switch.tsx +6 -1
  522. package/src/components/Tabs/tabs.spec.md +5 -1
  523. package/src/components/Tabs/tabs.tsx +42 -3
  524. package/src/components/Tag/tag.anatomy.stories.tsx +24 -28
  525. package/src/components/Tag/tag.spec.md +10 -11
  526. package/src/components/Tag/tag.tsx +3 -3
  527. package/src/components/Textarea/textarea.tsx +7 -1
  528. package/src/components/TimePicker/time-columns.tsx +9 -4
  529. package/src/components/TimePicker/time-picker.spec.md +4 -1
  530. package/src/components/TimePicker/time-picker.tsx +1 -1
  531. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +6 -15
  532. package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -16
  533. package/src/components/Tooltip/tooltip.spec.md +2 -1
  534. package/src/components/TreeView/tree-view.anatomy.stories.tsx +35 -13
  535. package/src/components/TreeView/tree-view.spec.md +67 -38
  536. package/src/components/TreeView/tree-view.stories.tsx +221 -12
  537. package/src/components/TreeView/tree-view.tsx +463 -356
  538. package/src/hooks/use-input-modality.ts +17 -46
  539. package/src/hooks/use-overflow-items.ts +4 -0
  540. package/src/hooks/use-truncated.ts +3 -2
  541. package/src/index.ts +17 -0
  542. package/src/lib/README.md +2 -0
  543. package/src/lib/drag-announcements.ts +78 -0
  544. package/src/lib/focus-after-trigger.ts +102 -0
  545. package/src/lib/roving-list-keyboard.ts +400 -0
  546. package/src/lib/utils.ts +5 -0
  547. package/src/patterns/action-bar/action-bar.spec.md +2 -0
  548. package/src/patterns/element-anatomy/inline-action.spec.md +16 -12
  549. package/src/patterns/element-anatomy/item-anatomy.spec.md +98 -6
  550. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +75 -70
  551. package/src/patterns/element-anatomy/item-anatomy.tsx +17 -6
  552. package/src/patterns/element-anatomy/truncated-text.spec.md +1 -0
  553. package/src/patterns/header-canonical/header-canonical.spec.md +3 -2
  554. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +2 -0
  555. package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +36 -0
  556. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +28 -0
  557. package/src/patterns/overlay-surface/overlay-chrome-sizing.spec.md +180 -0
  558. package/src/patterns/overlay-surface/overlay-surface.spec.md +8 -162
  559. package/src/patterns/overlay-surface/overlay-surface.tsx +5 -3
  560. package/src/patterns/resize-handle/resize-handle.spec.md +3 -3
  561. package/src/styles/base.css +1 -1
  562. package/src/tokens/categorical-color.ts +6 -1
  563. package/src/tokens/color/color.spec.md +91 -24
  564. package/src/tokens/color/color.stories.tsx +50 -2
  565. package/src/tokens/color/primitives.css +41 -38
  566. package/src/tokens/color/semantic.css +105 -36
  567. package/src/tokens/layoutSpace/layoutSpace.spec.md +2 -0
  568. package/src/tokens/motion/motion.spec.md +31 -8
  569. package/src/tokens/orphan-tokens.spec.md +1 -1
  570. package/src/tokens/uiSize/icon-size.ts +1 -1
  571. package/src/tokens/uiSize/stack-gap.ts +17 -0
  572. package/src/tokens/uiSize/uiSize.css +12 -0
  573. package/src/tokens/uiSize/uiSize.spec.md +17 -16
  574. package/src/tokens/uiSize/uiSize.stories.tsx +1 -1
  575. package/dist/node_modules/aria-hidden/dist/es2015/index.js +0 -147
  576. package/dist/node_modules/aria-hidden/dist/es2015/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"selection-item.js","sources":["../../../src/components/SelectionControl/selection-item.tsx"],"sourcesContent":["/**\n * @internal — DS-internal 單元(per `packages/design-system/ds-canonical/rules/ui-development.md` Public vs Internal canonical;spec frontmatter `isInternal`)。\n * 不進 root barrel front-door;由 Checkbox / RadioGroup wrap 消費,end-user app 請用 wrapper 元件。\n */\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'\nimport { ICON_SIZE, AVATAR_SIZE } from '@/design-system/patterns/element-anatomy/item-anatomy'\n\n// ── Selection Item Styles ───────────────────────────────────────────────────\n// Checkbox 和 RadioGroup 共用的 item 佈局。\n//\n// 結構(item-anatomy.spec.md 4-slot 模型):\n// [control] [optional prefix(icon|avatar)] [content(label/desc)](3-slot,見 spec「定位」)\n//\n// padding 公式:py = (field-height - 1lh) / 2\n// - 單行時 item 高度 = field-height(對齊同 size 的 Input)\n// - 多行時 padding 不變(文字間距一致)\n// - density 切換時 field-height 自動調整,padding 跟著算\n//\n// 容器設 text-body / text-body-lg 建立 1lh context(div 上正常繼承)。\n//\n// ── 為什麼 NOT 消費 ROW_PADDING_BY_SIZE(item-anatomy.tsx SSOT,2026-04-24 consolidation)──\n// menu / sidebar / tree 3 cva 統一消費 ROW_PADDING_BY_SIZE;SelectionItem 刻意不消費,\n// 因 typography 不同(mode 差異,非 drift):\n// - ROW_PADDING_BY_SIZE:`text-body leading-compact`(scanning mode,緊湊)\n// - SelectionItem:`text-body`(**無 leading-compact** — reading mode,Checkbox/Radio 搭配\n// 較長 label + description,需預設 1.5 leading 而非 1.3 compact)\n// py 公式本身相同 — 若 field-height token 變動,本檔需手動同步(contained,由本註解 anchor 追)。\n\n// code-quality-allow: dead-export — public API surface — consumer-exposed for future use\nexport const selectionItemStyles = cva(\n 'flex items-start gap-2',\n {\n variants: {\n size: {\n sm: 'text-body py-[calc((var(--field-height-sm)_-_1lh)_/_2)]',\n md: 'text-body py-[calc((var(--field-height-md)_-_1lh)_/_2)]',\n lg: 'text-body-lg py-[calc((var(--field-height-lg)_-_1lh)_/_2)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n)\n\ntype SizeKey = 'sm' | 'md' | 'lg'\n\n// Avatar 尺寸 + Icon 尺寸從 item-layout module 共用,不在此 re-declare(避免漂移)\n// AVATAR_SIZE / ICON_SIZE 都是 item-layout 的 canonical 常數。\n//\n// SelectionItem 跟 MenuItem 的差異:SelectionItem 有 control(checkbox/radio)。\n// block 模式時 **control 跟 prefix 一起走 block 高度**——兩者都在 text block center,\n// 維持「selection + identity」是一組的視覺語意,不會歪斜。\nconst AVATAR_PX = AVATAR_SIZE\n\n// ── Block 對齊容器 ──\n// sm/md: reading mode (body 14/1.5 + body 14/1.5) — gap token `reading`\n// lg: reading-lg mode (body-lg 16/1.5 + body 14/1.5) — gap token `reading-lg`\n// desc 永遠 body(14) line-height;`1lh` 會 resolve 到 label 的 line-height(sm/md=21, lg=24)\nconst blockAlignClass: Record<SizeKey, string> = {\n sm: 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]',\n md: 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]',\n lg: 'h-[calc(1lh+var(--item-gap-label-desc-reading-lg)+var(--font-body-size)*1.5)]',\n}\n\n// ── Selection Item ──────────────────────────────────────────────────────────\n// 通用 item 行:control + 可選 prefix(icon/avatar) + label + description。\n// control 永遠包在 h-[1lh] 容器內,對齊第一行 label。\n// prefix 走 24px 閾值規則,各自獨立對齊。\n\nexport interface SelectionItemProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof selectionItemStyles> {\n /** Checkbox 或 RadioGroupItem 元素(永遠存在,永遠 inline 對齊) */\n control: React.ReactNode\n /** Label 文字 */\n label: React.ReactNode\n /** 描述文字(fg-secondary;reading mode 永遠 14px) */\n description?: React.ReactNode\n /**\n * 可選的左側 icon(在 control 之後、label 之前)。LucideIcon 型別,元件內部控制尺寸\n * (16/16/20px @ sm/md/lg)。**永遠 inline 對齊第一行 label**(icon ≤24px)。\n * 與 `avatar` 互斥。\n */\n icon?: LucideIcon\n /**\n * 可選的左側 avatar(在 control 之後、label 之前)。`AvatarData` 資料型別,元件內部渲染 Avatar。\n * 尺寸由 `description` 自動決定(跟 MenuItem 同 convention):\n * - 無 desc → inline(20/24/24px),跟 control 同步在 label 第一行\n * - 有 desc → block(32/32/40px),跟 control 同步在 text block center\n *\n * Block 模式時 **control(checkbox/radio)也一起走 block 高度**——兩者都在\n * text block center,不會歪斜。與 `icon` 互斥。\n */\n avatar?: AvatarData\n /** htmlFor(label 指向 control 的 id) */\n htmlFor?: string\n /** disabled 狀態影響 label 顏色 */\n disabled?: boolean\n /**\n * Label 最大行數(line-clamp 截斷)。\n *\n * - `undefined`(預設 prop 值未傳)→ 套用元件預設 `'none'`(form 欄位允許任意長度)\n * - 數字 → 截斷到該行數\n * - `'none'` → 明確不截斷(語意等同預設)\n *\n * 為什麼用 `'none'` 而不是 `undefined`?React props 的 destructure default 在\n * `undefined` 時會接管,要明確覆寫必須用非 undefined 的 sentinel。\n */\n labelMaxLines?: number | 'none'\n /**\n * Description 最大行數。預設 `'none'`(不截)。\n */\n descMaxLines?: number | 'none'\n className?: string\n}\n\n/** 把 maxLines 轉成 line-clamp class;'none' / 0 → 空字串 */\nfunction lineClampClass(maxLines: number | 'none'): string {\n if (maxLines === 'none' || !maxLines) return ''\n if (maxLines === 1) return 'line-clamp-1'\n if (maxLines === 2) return 'line-clamp-2'\n if (maxLines === 3) return 'line-clamp-3'\n if (maxLines === 4) return 'line-clamp-4'\n if (maxLines === 5) return 'line-clamp-5'\n if (maxLines === 6) return 'line-clamp-6'\n return ''\n}\n\n// ── PrefixSlot — 24px 閾值規則 ──\n// icon(永遠 ≤24px)→ inline;avatar + 無 desc → inline;avatar + 有 desc → block(centered on text block)\ntype PrefixSlotProps = {\n icon: LucideIcon | undefined\n avatar: AvatarData | undefined\n sizeKey: SizeKey\n alignClass: string\n avatarPx: number\n disabled: boolean | undefined\n}\nfunction PrefixSlot({ icon: Icon, avatar, sizeKey, alignClass, avatarPx, disabled }: PrefixSlotProps) {\n if (!Icon && !avatar) return null\n return (\n <div className={cn(alignClass, 'flex items-center shrink-0')}>\n {Icon && (\n <Icon\n size={ICON_SIZE[sizeKey]}\n className={cn('shrink-0', disabled && 'text-fg-disabled')}\n aria-hidden\n />\n )}\n {!Icon && avatar && (\n <Avatar src={avatar.src} alt={avatar.alt} color={avatar.color} hoverCard={avatar.hoverCard} size={avatarPx} />\n )}\n </div>\n )\n}\n\n// ── ContentSlot — label + optional description ──\n// inline-style fontSize 繞 tailwind-merge 把 text-body / text-fg-secondary 誤判同組衝突的 bug\ntype ContentSlotProps = {\n htmlFor: string | undefined\n disabled: boolean | undefined\n label: React.ReactNode\n description: React.ReactNode | undefined\n sizeKey: SizeKey\n labelClampClass: string\n descClampClass: string\n}\nfunction ContentSlot({ htmlFor, disabled, label, description, sizeKey, labelClampClass, descClampClass }: ContentSlotProps) {\n return (\n <div className=\"min-w-0 flex-1\">\n <label\n htmlFor={htmlFor}\n // 2026-06-10 a11y:styled-disabled label 明告 inactive(WCAG 1.4.3 豁免可機判;對齊 FieldLabel 同修;a11y 補強不動 SSOT = AUTO 分權,user verbatim「確保所有的任務你都有做到完美做到完整」)\n aria-disabled={disabled || undefined}\n className={cn(\n 'cursor-pointer block break-words',\n labelClampClass,\n disabled ? 'text-fg-disabled cursor-not-allowed' : 'text-foreground',\n )}\n >\n {label}\n </label>\n {description && (\n <p\n className={cn(\n sizeKey === 'lg' ? 'mt-[var(--item-gap-label-desc-reading-lg)]' : 'mt-[var(--item-gap-label-desc-reading)]',\n 'break-words',\n descClampClass,\n disabled ? 'text-fg-disabled' : 'text-fg-secondary',\n )}\n style={{ fontSize: 'var(--font-body-size)' }}\n >\n {description}\n </p>\n )}\n </div>\n )\n}\n\nconst SelectionItem = React.forwardRef<HTMLDivElement, SelectionItemProps>(\n (\n {\n control,\n label,\n description,\n icon: Icon,\n avatar,\n htmlFor,\n disabled,\n size,\n labelMaxLines = 'none',\n descMaxLines = 'none',\n className,\n ...props\n },\n ref\n ) => {\n const sizeKey: SizeKey = size ?? 'md'\n if (process.env.NODE_ENV !== 'production' && Icon && avatar) {\n // eslint-disable-next-line no-console\n console.warn('[SelectionItem] `icon` 和 `avatar` 互斥,只會渲染 icon。')\n }\n // Block 對齊:control 跟 prefix(avatar)一起走 block 高度,「selection + identity」視覺單元不歪斜\n const useBlock = !!avatar && !Icon && !!description && AVATAR_PX.block[sizeKey] > 24\n const avatarPx = useBlock ? AVATAR_PX.block[sizeKey] : AVATAR_PX.inline[sizeKey]\n const alignClass = useBlock ? blockAlignClass[sizeKey] : 'h-[1lh]'\n\n return (\n <div ref={ref} className={cn(selectionItemStyles({ size }), className)} {...props}>\n <div className={cn(alignClass, 'flex items-center shrink-0')}>{control}</div>\n <PrefixSlot icon={Icon} avatar={avatar} sizeKey={sizeKey} alignClass={alignClass} avatarPx={avatarPx} disabled={disabled} />\n <ContentSlot\n htmlFor={htmlFor}\n disabled={disabled}\n label={label}\n description={description}\n sizeKey={sizeKey}\n labelClampClass={lineClampClass(labelMaxLines)}\n descClampClass={lineClampClass(descMaxLines)}\n />\n </div>\n )\n }\n)\nSelectionItem.displayName = 'SelectionItem'\n\n// Story auto-compile metadata — Phase 1+2 migration\nexport const selectionItemMeta = {\n component: 'SelectionItem',\n family: 2,\n variants: {},\n sizes: {\n sm: {},\n md: {},\n lg: {},\n },\n defaultSize: 'md',\n states: ['default', 'disabled'], // disabled 是唯一視覺狀態;selected / hover 屬傳入的 control(spec「為何無 ColorMatrix / StateBehavior」)\n tokens: {\n fg: ['text-foreground', 'text-fg-secondary', 'text-fg-disabled'],\n },\n} as const\n\nexport { SelectionItem }\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"selection-item.js","sources":["../../../src/components/SelectionControl/selection-item.tsx"],"sourcesContent":["/**\n * @internal — DS-internal 單元(per `packages/design-system/ds-canonical/rules/ui-development.md` Public vs Internal canonical;spec frontmatter `isInternal`)。\n * 不進 root barrel front-door;由 Checkbox / RadioGroup wrap 消費,end-user app 請用 wrapper 元件。\n */\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'\nimport { ICON_SIZE, AVATAR_SIZE } from '@/design-system/patterns/element-anatomy/item-anatomy'\n\n// ── Selection Item Styles ───────────────────────────────────────────────────\n// Checkbox 和 RadioGroup 共用的 item 佈局。\n//\n// 結構(item-anatomy.spec.md 4-slot 模型):\n// [control] [optional prefix(icon|avatar)] [content(label/desc)](3-slot,見 spec「定位」)\n//\n// padding 公式:py = (field-height - 1lh) / 2\n// - 單行時 item 高度 = field-height(對齊同 size 的 Input)\n// - 多行時 padding 不變(文字間距一致)\n// - density 切換時 field-height 自動調整,padding 跟著算\n//\n// 容器設 text-body / text-body-lg 建立 1lh context(div 上正常繼承)。\n//\n// ── 為什麼 NOT 消費 ROW_PADDING_BY_SIZE(item-anatomy.tsx SSOT,2026-04-24 consolidation)──\n// menu / sidebar / tree 3 cva 統一消費 ROW_PADDING_BY_SIZE;SelectionItem 刻意不消費,\n// 因 typography 不同(mode 差異,非 drift):\n// - ROW_PADDING_BY_SIZE:`text-body leading-compact`(scanning mode,緊湊)\n// - SelectionItem:`text-body`(**無 leading-compact** — reading mode,Checkbox/Radio 搭配\n// 較長 label + description,需預設 1.5 leading 而非 1.3 compact)\n// py 公式本身相同 — 若 field-height token 變動,本檔需手動同步(contained,由本註解 anchor 追)。\n\n// code-quality-allow: dead-export — public API surface — consumer-exposed for future use\nexport const selectionItemStyles = cva(\n 'flex items-start gap-2',\n {\n variants: {\n size: {\n sm: 'text-body py-[calc((var(--field-height-sm)_-_1lh)_/_2)]',\n md: 'text-body py-[calc((var(--field-height-md)_-_1lh)_/_2)]',\n lg: 'text-body-lg py-[calc((var(--field-height-lg)_-_1lh)_/_2)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n)\n\ntype SizeKey = 'sm' | 'md' | 'lg'\n\n// Avatar 尺寸 + Icon 尺寸從 item-layout module 共用,不在此 re-declare(避免漂移)\n// AVATAR_SIZE / ICON_SIZE 都是 item-layout 的 canonical 常數。\n//\n// SelectionItem 跟 MenuItem 的差異:SelectionItem 有 control(checkbox/radio)。\n// block 模式時 **control 跟 prefix 一起走 block 高度**——兩者都在 text block center,\n// 維持「selection + identity」是一組的視覺語意,不會歪斜。\nconst AVATAR_PX = AVATAR_SIZE\n\n// ── Block 對齊容器 ──\n// sm/md: reading mode (body 14/1.5 + body 14/1.5) — gap token `reading`\n// lg: reading-lg mode (body-lg 16/1.5 + body 14/1.5) — gap token `reading-lg`\n// desc 永遠 body(14) line-height;`1lh` 會 resolve 到 label 的 line-height(sm/md=21, lg=24)\nconst blockAlignClass: Record<SizeKey, string> = {\n sm: 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]',\n md: 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]',\n lg: 'h-[calc(1lh+var(--item-gap-label-desc-reading-lg)+var(--font-body-size)*1.5)]',\n}\n\n// ── Selection Item ──────────────────────────────────────────────────────────\n// 通用 item 行:control + 可選 prefix(icon/avatar) + label + description。\n// control 永遠包在 h-[1lh] 容器內,對齊第一行 label。\n// prefix 走 24px 閾值規則,各自獨立對齊。\n\nexport interface SelectionItemProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof selectionItemStyles> {\n /** Checkbox 或 RadioGroupItem 元素(永遠存在,永遠 inline 對齊) */\n control: React.ReactNode\n /** Label 文字 */\n label: React.ReactNode\n /** 描述文字(fg-secondary;reading mode 永遠 14px) */\n description?: React.ReactNode\n /**\n * 可選的左側 icon(在 control 之後、label 之前)。LucideIcon 型別,元件內部控制尺寸\n * (16/16/20px @ sm/md/lg)。**永遠 inline 對齊第一行 label**(icon ≤24px)。\n * 與 `avatar` 互斥。\n */\n icon?: LucideIcon\n /**\n * 可選的左側 avatar(在 control 之後、label 之前)。`AvatarData` 資料型別,元件內部渲染 Avatar。\n * 尺寸由 `description` 自動決定(跟 MenuItem 同 convention):\n * - 無 desc → inline(20/24/24px),跟 control 同步在 label 第一行\n * - 有 desc → block(32/32/40px),跟 control 同步在 text block center\n *\n * Block 模式時 **control(checkbox/radio)也一起走 block 高度**——兩者都在\n * text block center,不會歪斜。與 `icon` 互斥。\n */\n avatar?: AvatarData\n /** htmlFor(label 指向 control 的 id) */\n htmlFor?: string\n /** disabled 狀態影響 label 顏色 */\n disabled?: boolean\n /**\n * Label 最大行數(line-clamp 截斷)。\n *\n * - `undefined`(預設 prop 值未傳)→ 套用元件預設 `'none'`(form 欄位允許任意長度)\n * - 數字 → 截斷到該行數\n * - `'none'` → 明確不截斷(語意等同預設)\n *\n * 為什麼用 `'none'` 而不是 `undefined`?React props 的 destructure default 在\n * `undefined` 時會接管,要明確覆寫必須用非 undefined 的 sentinel。\n */\n labelMaxLines?: number | 'none'\n /**\n * Description 最大行數。預設 `'none'`(不截)。\n */\n descMaxLines?: number | 'none'\n className?: string\n}\n\n/** 把 maxLines 轉成 line-clamp class;'none' / 0 → 空字串 */\nfunction lineClampClass(maxLines: number | 'none'): string {\n if (maxLines === 'none' || !maxLines) return ''\n if (maxLines === 1) return 'line-clamp-1'\n if (maxLines === 2) return 'line-clamp-2'\n if (maxLines === 3) return 'line-clamp-3'\n if (maxLines === 4) return 'line-clamp-4'\n if (maxLines === 5) return 'line-clamp-5'\n if (maxLines === 6) return 'line-clamp-6'\n return ''\n}\n\n// ── PrefixSlot — 24px 閾值規則 ──\n// icon(永遠 ≤24px)→ inline;avatar + 無 desc → inline;avatar + 有 desc → block(centered on text block)\ntype PrefixSlotProps = {\n icon: LucideIcon | undefined\n avatar: AvatarData | undefined\n sizeKey: SizeKey\n alignClass: string\n avatarPx: number\n disabled: boolean | undefined\n}\nfunction PrefixSlot({ icon: Icon, avatar, sizeKey, alignClass, avatarPx, disabled }: PrefixSlotProps) {\n if (!Icon && !avatar) return null\n return (\n <div className={cn(alignClass, 'flex items-center shrink-0')}>\n {Icon && (\n <Icon\n size={ICON_SIZE[sizeKey]}\n className={cn('shrink-0', disabled && 'text-fg-disabled')}\n aria-hidden\n />\n )}\n {!Icon && avatar && (\n <Avatar src={avatar.src} alt={avatar.alt} color={avatar.color} hoverCard={avatar.hoverCard} size={avatarPx} />\n )}\n </div>\n )\n}\n\n// ── ContentSlot — label + optional description ──\n// inline-style fontSize 繞 tailwind-merge 把 text-body / text-fg-secondary 誤判同組衝突的 bug\ntype ContentSlotProps = {\n htmlFor: string | undefined\n disabled: boolean | undefined\n label: React.ReactNode\n description: React.ReactNode | undefined\n sizeKey: SizeKey\n labelClampClass: string\n descClampClass: string\n}\nfunction ContentSlot({ htmlFor, disabled, label, description, sizeKey, labelClampClass, descClampClass }: ContentSlotProps) {\n return (\n <div className=\"min-w-0 flex-1\">\n <label\n htmlFor={htmlFor}\n // 2026-06-10 a11y:styled-disabled label 明告 inactive(WCAG 1.4.3 豁免可機判;對齊 FieldLabel 同修;a11y 補強不動 SSOT = AUTO 分權,user verbatim「確保所有的任務你都有做到完美做到完整」)\n aria-disabled={disabled || undefined}\n className={cn(\n 'cursor-pointer block break-words',\n labelClampClass,\n disabled ? 'text-fg-disabled cursor-not-allowed' : 'text-foreground',\n )}\n >\n {label}\n </label>\n {description && (\n <p\n // 2026-09-29 a11y(待辦總帳 OE21):與上方 label 同一條理由 —— 說明文字跟著降成 fg-disabled 時也要明告 inactive,\n // 否則 axe color-contrast 把它當一般文字誤報(RadioGroup 狀態行為 / SelectionControl 前綴圖示兩則 story)\n aria-disabled={disabled || undefined}\n className={cn(\n sizeKey === 'lg' ? 'mt-[var(--item-gap-label-desc-reading-lg)]' : 'mt-[var(--item-gap-label-desc-reading)]',\n 'break-words',\n descClampClass,\n disabled ? 'text-fg-disabled' : 'text-fg-secondary',\n )}\n style={{ fontSize: 'var(--font-body-size)' }}\n >\n {description}\n </p>\n )}\n </div>\n )\n}\n\nconst SelectionItem = React.forwardRef<HTMLDivElement, SelectionItemProps>(\n (\n {\n control,\n label,\n description,\n icon: Icon,\n avatar,\n htmlFor,\n disabled,\n size,\n labelMaxLines = 'none',\n descMaxLines = 'none',\n className,\n ...props\n },\n ref\n ) => {\n const sizeKey: SizeKey = size ?? 'md'\n if (process.env.NODE_ENV !== 'production' && Icon && avatar) {\n console.warn('[SelectionItem] `icon` 和 `avatar` 互斥,只會渲染 icon。')\n }\n // Block 對齊:control 跟 prefix(avatar)一起走 block 高度,「selection + identity」視覺單元不歪斜\n const useBlock = !!avatar && !Icon && !!description && AVATAR_PX.block[sizeKey] > 24\n const avatarPx = useBlock ? AVATAR_PX.block[sizeKey] : AVATAR_PX.inline[sizeKey]\n const alignClass = useBlock ? blockAlignClass[sizeKey] : 'h-[1lh]'\n\n return (\n <div ref={ref} className={cn(selectionItemStyles({ size }), className)} {...props}>\n <div className={cn(alignClass, 'flex items-center shrink-0')}>{control}</div>\n <PrefixSlot icon={Icon} avatar={avatar} sizeKey={sizeKey} alignClass={alignClass} avatarPx={avatarPx} disabled={disabled} />\n <ContentSlot\n htmlFor={htmlFor}\n disabled={disabled}\n label={label}\n description={description}\n sizeKey={sizeKey}\n labelClampClass={lineClampClass(labelMaxLines)}\n descClampClass={lineClampClass(descMaxLines)}\n />\n </div>\n )\n }\n)\nSelectionItem.displayName = 'SelectionItem'\n\n// Story auto-compile metadata — Phase 1+2 migration\nexport const selectionItemMeta = {\n component: 'SelectionItem',\n family: 2,\n variants: {},\n sizes: {\n sm: {},\n md: {},\n lg: {},\n },\n defaultSize: 'md',\n states: ['default', 'disabled'], // disabled 是唯一視覺狀態;selected / hover 屬傳入的 control(spec「為何無 ColorMatrix / StateBehavior」)\n tokens: {\n fg: ['text-foreground', 'text-fg-secondary', 'text-fg-disabled'],\n },\n} as const\n\nexport { SelectionItem }\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  import type { LucideIcon } from "lucide-react";
4
4
  import { TooltipContent } from "../../components/Tooltip/tooltip";
5
- import { type RowSize, type InlineActionConfig } from "../../patterns/element-anatomy/item-anatomy";
5
+ import { type ItemInlineActionButtonProps, type RowSize, type InlineActionConfig } from "../../patterns/element-anatomy/item-anatomy";
6
6
  type SidebarSize = RowSize;
7
7
  type SidebarContextProps = {
8
8
  state: "expanded" | "collapsed";
@@ -106,9 +106,7 @@ declare const SidebarGroupLabel: React.ForwardRefExoticComponent<Omit<React.Clas
106
106
  } & VariantProps<(props?: ({
107
107
  size?: RowSize | null | undefined;
108
108
  } & import("class-variance-authority/types").ClassProp) | undefined) => string>, "ref"> & React.RefAttributes<HTMLDivElement>>;
109
- declare const SidebarGroupAction: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & {
110
- asChild?: boolean;
111
- }, "ref"> & React.RefAttributes<HTMLButtonElement>>;
109
+ declare const SidebarGroupAction: React.ForwardRefExoticComponent<Omit<ItemInlineActionButtonProps, "size"> & React.RefAttributes<HTMLButtonElement>>;
112
110
  declare const SidebarMenu: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "ref"> & React.RefAttributes<HTMLUListElement>>;
113
111
  declare const SidebarMenuItem: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & React.RefAttributes<HTMLLIElement>>;
114
112
  declare const SidebarMenuButton: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "id"> & {
@@ -147,17 +145,17 @@ declare const SidebarMenuButton: React.ForwardRefExoticComponent<Omit<Omit<React
147
145
  /**
148
146
  * Inline actions 的顯示模式:
149
147
  * - `false`(預設):永遠顯示
150
- * - `"hover"`:row hover 時才淡入(TreeView 模式)
148
+ * - `"hover"`:滑過這一列、或鍵盤焦點在這一列時才出現,瞬間出現、不淡入(TreeView 模式;
149
+ * 待辦總帳 L9,sidebar.spec.md「Inline actions」出現時機列)
151
150
  */
152
151
  actionsReveal?: false | "hover";
153
152
  } & VariantProps<(props?: ({
154
153
  size?: "sm" | "md" | "lg" | null | undefined;
155
154
  variant?: "meta" | "default" | null | undefined;
156
155
  } & import("class-variance-authority/types").ClassProp) | undefined) => string>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
157
- declare const SidebarMenuAction: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & {
158
- asChild?: boolean;
156
+ declare const SidebarMenuAction: React.ForwardRefExoticComponent<Omit<ItemInlineActionButtonProps, "size"> & {
159
157
  showOnHover?: boolean;
160
- }, "ref"> & React.RefAttributes<HTMLButtonElement>>;
158
+ } & React.RefAttributes<HTMLButtonElement>>;
161
159
  declare const SidebarMenuBadge: React.ForwardRefExoticComponent<(Omit<import("../../components/Badge/badge").BadgeDotProps & React.RefAttributes<HTMLSpanElement>, "ref"> | Omit<import("../../components/Badge/badge").BadgeCountProps & React.RefAttributes<HTMLSpanElement>, "ref">) & React.RefAttributes<HTMLSpanElement>>;
162
160
  declare const SidebarMenuSkeleton: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
163
161
  showIcon?: boolean;
@@ -193,7 +191,7 @@ export declare const sidebarMeta: {
193
191
  readonly tokens: {
194
192
  readonly bg: readonly ["bg-neutral-hover", "bg-neutral-selected", "bg-surface", "bg-transparent"];
195
193
  readonly fg: readonly ["text-fg-muted", "text-fg-secondary", "text-foreground"];
196
- readonly ring: readonly ["ring-ring"];
194
+ readonly ring: readonly ["focus-ring-inset"];
197
195
  };
198
196
  readonly defaultSize: "md";
199
197
  };
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/Sidebar/sidebar.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/Sidebar/sidebar.tsx"],"names":[],"mappings":"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"}
@@ -15,7 +15,8 @@ import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from "
15
15
  import { Skeleton } from "../Skeleton/skeleton.js";
16
16
  import { ChromeHeader } from "../../patterns/header-canonical/chrome-header.js";
17
17
  import { Tooltip, TooltipTrigger, TooltipContent } from "../Tooltip/tooltip.js";
18
- import { ItemInlineActionButton, ICON_SIZE, ItemInlineAction, getUniformPrefixSlotStyle, AVATAR_SIZE, RowSizeProvider, ROW_PADDING_BY_SIZE, ItemIcon, ItemLabel } from "../../patterns/element-anatomy/item-anatomy.js";
18
+ import { ItemInlineActionButton, ICON_SIZE, ItemSuffix, ItemInlineAction, getUniformPrefixSlotStyle, AVATAR_SIZE, RowSizeProvider, ROW_PADDING_BY_SIZE, ItemIcon, ItemLabel } from "../../patterns/element-anatomy/item-anatomy.js";
19
+ import { pickRovingTabStop, setRovingTabIndex, removeRovingControlsFromTabOrder, isRovingControlReachable, resolveRovingKey, isTextEntryElement, applyRovingAction } from "../../lib/roving-list-keyboard.js";
19
20
  const SIDEBAR_COOKIE_NAME = "sidebar_state";
20
21
  const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
21
22
  const SIDEBAR_KEYBOARD_SHORTCUT = "b";
@@ -383,7 +384,7 @@ const SidebarContent = React.forwardRef(({ className, children, ...props }, ref)
383
384
  className
384
385
  ),
385
386
  ...props,
386
- children: /* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col", children }) })
387
+ children: /* @__PURE__ */ jsx(ScrollArea, { className: "flex-1", viewportTabIndex: -1, children: /* @__PURE__ */ jsx("div", { className: "flex flex-col", children }) })
387
388
  }
388
389
  );
389
390
  });
@@ -511,33 +512,132 @@ const SidebarGroupLabel = React.forwardRef(({ className, asChild = false, size:
511
512
  );
512
513
  });
513
514
  SidebarGroupLabel.displayName = "SidebarGroupLabel";
514
- const SidebarGroupAction = React.forwardRef(({ className, asChild = false, ...props }, ref) => {
515
- const Comp = asChild ? Slot : "button";
515
+ const SidebarGroupAction = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
516
+ ItemInlineActionButton,
517
+ {
518
+ ref,
519
+ "data-sidebar": "group-action",
520
+ className: cn(
521
+ "absolute right-[var(--layout-space-loose)] top-2",
522
+ "group-data-[collapsible=icon]:hidden",
523
+ className
524
+ ),
525
+ ...props
526
+ }
527
+ ));
528
+ SidebarGroupAction.displayName = "SidebarGroupAction";
529
+ const SIDEBAR_MENU_BUTTON = '[data-sidebar="menu-button"]';
530
+ const SIDEBAR_ROW_ACTIONS = '[data-sidebar="menu-inline-actions"] :is(button, a[href], [role="button"]), [data-sidebar="menu-action"]';
531
+ function getSidebarMenuRows(menu) {
532
+ const rows = [];
533
+ for (const child of Array.from(menu.children)) {
534
+ if (child.tagName !== "LI") continue;
535
+ const button = child.querySelector(SIDEBAR_MENU_BUTTON);
536
+ if (!button) continue;
537
+ rows.push({ button, actions: Array.from(child.querySelectorAll(SIDEBAR_ROW_ACTIONS)) });
538
+ }
539
+ return rows;
540
+ }
541
+ const isFocusableSidebarTarget = (el) => !el.disabled;
542
+ const isRenderedSidebarTarget = (el) => el.getClientRects().length > 0;
543
+ function sidebarRowNavigability(menu, rows) {
544
+ const checkRendered = isRenderedSidebarTarget(menu) && rows.some((row) => isFocusableSidebarTarget(row.button) && isRenderedSidebarTarget(row.button));
545
+ return (button) => isFocusableSidebarTarget(button) && (!checkRendered || isRenderedSidebarTarget(button));
546
+ }
547
+ function syncSidebarMenuTabStops(menu, remembered) {
548
+ const rows = getSidebarMenuRows(menu);
549
+ const stop = pickRovingTabStop(rows.map((row) => row.button), {
550
+ remembered,
551
+ isCurrent: (button) => button.getAttribute("aria-current") === "page",
552
+ isNavigable: sidebarRowNavigability(menu, rows)
553
+ });
554
+ for (const row of rows) {
555
+ setRovingTabIndex(row.button, row.button === stop ? 0 : -1);
556
+ removeRovingControlsFromTabOrder(row.actions);
557
+ }
558
+ }
559
+ const SidebarMenu = React.forwardRef(({ className, onKeyDownCapture, onFocus, ...props }, ref) => {
560
+ const menuRef = React.useRef(null);
561
+ const rememberedRef = React.useRef(null);
562
+ const sidebarContext = React.useContext(SidebarContext);
563
+ const sidebarState = sidebarContext == null ? void 0 : sidebarContext.state;
564
+ const sidebarIsMobile = sidebarContext == null ? void 0 : sidebarContext.isMobile;
565
+ const setRefs = React.useCallback(
566
+ (el) => {
567
+ menuRef.current = el;
568
+ if (typeof ref === "function") ref(el);
569
+ else if (ref) ref.current = el;
570
+ },
571
+ [ref]
572
+ );
573
+ React.useLayoutEffect(() => {
574
+ if (menuRef.current) syncSidebarMenuTabStops(menuRef.current, rememberedRef.current);
575
+ }, [sidebarState, sidebarIsMobile]);
576
+ React.useEffect(() => {
577
+ const menu = menuRef.current;
578
+ if (!menu || typeof MutationObserver === "undefined") return;
579
+ const observer = new MutationObserver(() => syncSidebarMenuTabStops(menu, rememberedRef.current));
580
+ observer.observe(menu, {
581
+ childList: true,
582
+ subtree: true,
583
+ attributes: true,
584
+ attributeFilter: ["disabled", "aria-current"]
585
+ });
586
+ return () => observer.disconnect();
587
+ }, []);
588
+ const handleFocus = (event) => {
589
+ onFocus == null ? void 0 : onFocus(event);
590
+ const menu = event.currentTarget;
591
+ const target = event.target;
592
+ const row = getSidebarMenuRows(menu).find(
593
+ (r) => r.button === target || r.actions.includes(target)
594
+ );
595
+ if (!row) return;
596
+ rememberedRef.current = row.button;
597
+ syncSidebarMenuTabStops(menu, row.button);
598
+ };
599
+ const handleKeyDownCapture = (event) => {
600
+ onKeyDownCapture == null ? void 0 : onKeyDownCapture(event);
601
+ const menu = event.currentTarget;
602
+ const target = event.target;
603
+ const rows = getSidebarMenuRows(menu);
604
+ const row = rows.find((r) => r.button === target || r.actions.includes(target));
605
+ if (!row) return;
606
+ const onRow = row.button === target;
607
+ const controls = row.actions.filter(isRovingControlReachable);
608
+ const action = resolveRovingKey({
609
+ key: event.key,
610
+ focus: onRow ? "item" : "control",
611
+ controlCount: controls.length,
612
+ controlIndex: onRow ? -1 : controls.indexOf(target),
613
+ controlIsTextEntry: !onRow && isTextEntryElement(target),
614
+ defaultPrevented: event.defaultPrevented,
615
+ metaKey: event.metaKey,
616
+ ctrlKey: event.ctrlKey,
617
+ altKey: event.altKey,
618
+ shiftKey: event.shiftKey
619
+ });
620
+ const isNavigable = sidebarRowNavigability(menu, rows);
621
+ applyRovingAction(action, {
622
+ event,
623
+ item: row.button,
624
+ controls,
625
+ items: rows.map((r) => r.button),
626
+ isNavigable
627
+ });
628
+ };
516
629
  return /* @__PURE__ */ jsx(
517
- Comp,
630
+ "ul",
518
631
  {
519
- ref,
520
- "data-sidebar": "group-action",
521
- className: cn(
522
- "absolute right-[var(--layout-space-loose)] top-2 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-fg-muted hover:bg-neutral-hover hover:text-fg-secondary [&>svg]:size-4 [&>svg]:shrink-0",
523
- "after:absolute after:-inset-2 after:md:hidden",
524
- "group-data-[collapsible=icon]:hidden",
525
- className
526
- ),
632
+ ref: setRefs,
633
+ "data-sidebar": "menu",
634
+ className: cn("flex w-full min-w-0 flex-col", className),
635
+ onFocus: handleFocus,
636
+ onKeyDownCapture: handleKeyDownCapture,
527
637
  ...props
528
638
  }
529
639
  );
530
640
  });
531
- SidebarGroupAction.displayName = "SidebarGroupAction";
532
- const SidebarMenu = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
533
- "ul",
534
- {
535
- ref,
536
- "data-sidebar": "menu",
537
- className: cn("flex w-full min-w-0 flex-col", className),
538
- ...props
539
- }
540
- ));
541
641
  SidebarMenu.displayName = "SidebarMenu";
542
642
  const SidebarMenuItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
543
643
  "li",
@@ -575,13 +675,28 @@ const sidebarMenuButtonVariants = cva(
575
675
  // 對齊 MUI MiniDrawer + shadcn canonical(width morph + overflow clip + row geometry 不變)。
576
676
  // hover 底色瞬間切換,不做過渡(user 2026-09-10 拍板「第三題改成全部瞬間」;SSOT = tokens/motion/motion.spec.md「hover 回饋不做過渡」)
577
677
  "hover:bg-neutral-hover hover:text-foreground",
678
+ // 巢狀 hover(2026-09-25,user 選「卡片保留、按鈕再亮一層」;SSOT = sidebar.spec.md「Inline actions」段「指標在動作鈕上時(巢狀 hover)」):
679
+ // 指標移到同一列的動作鈕(inlineActions 的 suffix span / SidebarMenuAction)上,列保留上一行的 hover,動作鈕再亮自己那層。
680
+ // 需要這兩行是因為動作鈕是列鈕的**同層兄弟**(避免 button 包 button,見下方 suffixNode 註解)—— 指標在兄弟上時列鈕不算 :hover。
681
+ // - `~` 只往後找:動作必須排在列鈕後面(兩個內建出口都是;SidebarMenuAction 的 peer-data 也早就要求這個順序)。
682
+ // - 外層包 `:where()` 把特異性壓回 (0,1,0),下方 `data-[active=true]` 選中色 (0,2,0) 照樣釘住;不包會是 (0,3,0),選中列指到動作鈕時選中色被 hover 色蓋掉(2026-09-25 Chromium 實測)。
683
+ // - 不掛在 li 的 `group-hover/menu-item`:li 收任意子元素,指到 li 裡的子項目時父列會誤亮(同日實測)。
684
+ // - `[@media(hover:hover)]` 對齊上一行 `hover:` 的媒體條件(Tailwind 4 的 hover: 只在能懸停的裝置生效),觸控裝置不留殘亮。
685
+ // 值與上一行 `hover:` 是同一對;改那一行必須同步改這兩行。
686
+ "[@media(hover:hover)]:[&:where(:has(~:is([data-sidebar=menu-inline-actions],[data-sidebar=menu-action]):hover))]:bg-neutral-hover",
687
+ "[@media(hover:hover)]:[&:where(:has(~:is([data-sidebar=menu-inline-actions],[data-sidebar=menu-action]):hover))]:text-foreground",
578
688
  // 鍵盤游標一律畫框、不上底色(focus-canonical 規則二,user 2026-09-09 拍板);選單鈕撐滿側欄寬度 → 內描邊。
579
689
  // 2026-09-09 之前非當前項的焦點用 hover 同色底(AI 推導,user 撤回);hover 的底色與文字色只屬於滑鼠。
580
690
  "focus-visible:focus-ring-inset",
581
691
  // 2026-05-31 M24:SidebarMenuButton 主要為 icon+label(currentColor 可改寫)→ 用 semantic
582
692
  // text-fg-disabled 對齊 MenuItem primitive(menu-item.tsx:198/221/248 + item-anatomy.tsx:374),
583
693
  // 非 opacity-disabled(opacity 保留給圖片/avatar/Switch 等無法改寫內部色者,per color.spec.md:103/118/701)。
584
- "disabled:pointer-events-none disabled:text-fg-disabled",
694
+ // 原生 disabled 的 button 本來就不會發 click,不再 pointer-events-none:留著接指標只為了掛禁止符號
695
+ //(hit-area-canonical.md 滑過原則一-3「停用的用禁止符號」;2026-09-29 全站掃出:「混合內容」的「delta(已封存)」游標是箭頭,
696
+ // 因為 pointer-events-none 讓 cursor 由 li 決定)。上方 hover 的底色 / 字色由 disabled:hover 釘住(:disabled:hover 特異性高過 :hover)。
697
+ "disabled:text-fg-disabled disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-fg-disabled",
698
+ // aria-disabled(asChild 的 <a> 等非 button 宿主)仍靠 pointer-events-none 擋掉點擊 / 導覽 —— 那是它唯一的擋法;
699
+ // 代價是游標由外層決定(箭頭)。要拿掉這裡的 pointer-events-none,得先在 asChild 宿主補 click guard(另案)。
585
700
  "aria-disabled:pointer-events-none aria-disabled:text-fg-disabled",
586
701
  "data-[active=true]:bg-neutral-selected data-[active=true]:text-foreground",
587
702
  // 2026-08-11 user 拍板(SSOT = item-anatomy「選中 × 互動疊加」):滑鼠 hover 當前項釘住不變
@@ -689,6 +804,7 @@ const SidebarMenuButton = React.forwardRef(
689
804
  ref,
690
805
  "data-sidebar": "menu-button",
691
806
  "data-active": isActive,
807
+ "aria-current": isActive ? "page" : void 0,
692
808
  className: cn(sidebarMenuButtonVariants({ size, variant }), className),
693
809
  style: hasActions ? { paddingRight: buttonPaddingRight } : void 0,
694
810
  onClick: handleClick,
@@ -697,19 +813,22 @@ const SidebarMenuButton = React.forwardRef(
697
813
  }
698
814
  );
699
815
  const suffixNode = hasActions ? /* @__PURE__ */ jsx(
700
- "span",
816
+ ItemSuffix,
701
817
  {
702
818
  "data-sidebar": "menu-inline-actions",
819
+ hoverReveal: actionsReveal === "hover",
820
+ hoverGroup: "menu-item",
703
821
  className: cn(
704
- "absolute top-1/2 -translate-y-1/2 flex items-center gap-2",
822
+ "absolute top-1/2 -translate-y-1/2",
705
823
  "right-[var(--layout-space-loose)]",
706
824
  // Icon 模式隱藏(跟 SidebarMenuBadge / SidebarMenuAction 一致)
707
825
  "group-data-[collapsible=icon]:hidden",
708
- // hover-reveal:滑鼠 hover 或鍵盤 focus(但不是 mouse click 的 focus)時顯示。
709
- // 用 `:has(:focus-visible)` 而非 `:focus-within`——focus-within 會被
710
- // mouse click 觸發,導致 click 之後 actions 永久顯示直到焦點移走;
711
- // focus-visible 只在鍵盤 tab 時啟動,mouse click 不會觸發,符合使用者直覺。
712
- actionsReveal === "hover" && "opacity-0 group-hover/menu-item:opacity-100 group-has-[:focus-visible]/menu-item:opacity-100 transition-opacity duration-150 motion-reduce:duration-0"
826
+ // 兩顆動作鈕之間的空隙歸列(2026-09-26,待辦總帳 N53 ①,user:「這些看起來幾乎都是bug」;修法 = R20「讓亮著的地方點得到」):
827
+ // 空隙在滑過時讓列亮著(sidebar.spec.md「Inline actions」段「兩顆動作鈕之間的空隙也算在內」),
828
+ // 點下去卻落在這個容器、列不導覽 —— 看得到亮卻點不到(hit-area-canonical.md「看到亮起來卻點不到」)。
829
+ // 容器本身不接指標,只有裡面可以按的東西接;空隙、以及插槽裡不能按的裝飾都穿到底下的列鈕(列鈕 paddingRight 已讓出這一段)。
830
+ // 指到按鈕上時容器仍是 :hover 的祖先,列的巢狀滑過(上方 cva 的 `~` 選擇器)照舊。
831
+ "pointer-events-none [&_:is(button,a[href],[role=button],[tabindex])]:pointer-events-auto"
713
832
  ),
714
833
  children: hasSlot ? inlineActionsSlot : inlineActions.map((action, i) => /* @__PURE__ */ jsx(ItemInlineAction, { action }, action.label + i))
715
834
  }
@@ -737,24 +856,26 @@ const SidebarMenuButton = React.forwardRef(
737
856
  }
738
857
  );
739
858
  SidebarMenuButton.displayName = "SidebarMenuButton";
740
- const SidebarMenuAction = React.forwardRef(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
741
- const Comp = asChild ? Slot : "button";
742
- return /* @__PURE__ */ jsx(
743
- Comp,
744
- {
745
- ref,
746
- "data-sidebar": "menu-action",
747
- className: cn(
748
- "absolute right-[var(--layout-space-loose)] top-1/2 -translate-y-1/2 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-fg-muted hover:bg-neutral-hover hover:text-fg-secondary [&>svg]:size-4 [&>svg]:shrink-0",
749
- "after:absolute after:-inset-2 after:md:hidden",
750
- "group-data-[collapsible=icon]:hidden",
751
- showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-foreground md:opacity-0",
752
- className
753
- ),
754
- ...props
755
- }
756
- );
757
- });
859
+ const SidebarMenuAction = React.forwardRef(({ className, showOnHover = false, ...props }, ref) => /* @__PURE__ */ jsx(
860
+ ItemInlineActionButton,
861
+ {
862
+ ref,
863
+ "data-sidebar": "menu-action",
864
+ className: cn(
865
+ "absolute right-[var(--layout-space-loose)] top-1/2 -translate-y-1/2",
866
+ "group-data-[collapsible=icon]:hidden",
867
+ showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-foreground md:opacity-0",
868
+ // 當前項旁的動作鈕:靜止已是 foreground(上一行),滑過 / 按下**釘住 foreground**,不讓 ItemInlineActionButton 的
869
+ // `hover:/active:text-fg-secondary` (0,2,0) 把它降回一階(2026-09-25 合成情境量測:淺 #252525→#545454、深 #FFFFFF→#E1E1E1;目前 DS 內無 showOnHover 消費者)。
870
+ // 依據:inline-action.spec.md「Icon 色彩」的階梯 root invariant `fg-muted → fg-secondary → foreground`,滑過只准往前一階;
871
+ // 這顆的靜止已站在最高一階 foreground,沒有下一階可升就留在原地,不得往回掉 ——
872
+ // 同列鈕「選中 × 滑過釘住」的寫法(上方 cva 的 `data-[active=true]:hover:…`)。特異性 (0,3,0) > hover:/active: 的 (0,2,0)。
873
+ showOnHover && "peer-data-[active=true]/menu-button:hover:text-foreground peer-data-[active=true]/menu-button:active:text-foreground",
874
+ className
875
+ ),
876
+ ...props
877
+ }
878
+ ));
758
879
  SidebarMenuAction.displayName = "SidebarMenuAction";
759
880
  const SidebarMenuBadge = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
760
881
  Badge,
@@ -844,7 +965,7 @@ const sidebarMeta = {
844
965
  tokens: {
845
966
  bg: ["bg-neutral-hover", "bg-neutral-selected", "bg-surface", "bg-transparent"],
846
967
  fg: ["text-fg-muted", "text-fg-secondary", "text-foreground"],
847
- ring: ["ring-ring"]
968
+ ring: ["focus-ring-inset"]
848
969
  },
849
970
  defaultSize: "md"
850
971
  };