@qijenchen/design-system 0.1.0-beta.95 → 0.1.0-beta.99

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 (355) hide show
  1. package/README.md +1 -0
  2. package/dist/components/AccountMenu/account-menu.d.ts +86 -0
  3. package/dist/components/AccountMenu/account-menu.d.ts.map +1 -0
  4. package/dist/components/AccountMenu/account-menu.js +64 -0
  5. package/dist/components/AccountMenu/account-menu.js.map +1 -0
  6. package/dist/components/AccountMenu/index.d.ts +2 -0
  7. package/dist/components/AccountMenu/index.d.ts.map +1 -0
  8. package/dist/components/AccountMenu/index.js +6 -0
  9. package/dist/components/AccountMenu/index.js.map +1 -0
  10. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  11. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  12. package/dist/components/AppShell/app-shell.js +2 -2
  13. package/dist/components/AppShell/app-shell.js.map +1 -1
  14. package/dist/components/Badge/badge.d.ts +1 -1
  15. package/dist/components/Button/button.d.ts +3 -3
  16. package/dist/components/Button/button.d.ts.map +1 -1
  17. package/dist/components/Button/button.js +3 -2
  18. package/dist/components/Button/button.js.map +1 -1
  19. package/dist/components/Calendar/calendar.d.ts +10 -21
  20. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  21. package/dist/components/Calendar/calendar.js +52 -59
  22. package/dist/components/Calendar/calendar.js.map +1 -1
  23. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  24. package/dist/components/Combobox/combobox.js +1 -0
  25. package/dist/components/Combobox/combobox.js.map +1 -1
  26. package/dist/components/Command/command.d.ts.map +1 -1
  27. package/dist/components/Command/command.js +3 -1
  28. package/dist/components/Command/command.js.map +1 -1
  29. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  30. package/dist/components/DataTable/cell-registry.js +1 -5
  31. package/dist/components/DataTable/cell-registry.js.map +1 -1
  32. package/dist/components/DataTable/data-table-filter-group.d.ts +6 -2
  33. package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -1
  34. package/dist/components/DataTable/data-table-filter-group.js +32 -27
  35. package/dist/components/DataTable/data-table-filter-group.js.map +1 -1
  36. package/dist/components/DataTable/data-table-filter-labels.d.ts +44 -0
  37. package/dist/components/DataTable/data-table-filter-labels.d.ts.map +1 -0
  38. package/dist/components/DataTable/data-table-filter-labels.js +55 -0
  39. package/dist/components/DataTable/data-table-filter-labels.js.map +1 -0
  40. package/dist/components/DataTable/data-table-filter-panel.d.ts +11 -0
  41. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  42. package/dist/components/DataTable/data-table-filter-panel.js +33 -10
  43. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -1
  44. package/dist/components/DataTable/data-table-filter-value-picker.d.ts +4 -1
  45. package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -1
  46. package/dist/components/DataTable/data-table-filter-value-picker.js +22 -8
  47. package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -1
  48. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  49. package/dist/components/DataTable/data-table.js +5 -4
  50. package/dist/components/DataTable/data-table.js.map +1 -1
  51. package/dist/components/DataTable/index.js +2 -0
  52. package/dist/components/DataTable/index.js.map +1 -1
  53. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  54. package/dist/components/DatePicker/date-picker.js +187 -156
  55. package/dist/components/DatePicker/date-picker.js.map +1 -1
  56. package/dist/components/Dialog/dialog.d.ts +1 -1
  57. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  58. package/dist/components/Dialog/dialog.js +4 -2
  59. package/dist/components/Dialog/dialog.js.map +1 -1
  60. package/dist/components/DropdownMenu/dropdown-menu.d.ts +4 -1
  61. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  62. package/dist/components/DropdownMenu/dropdown-menu.js +46 -14
  63. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  64. package/dist/components/Field/field-context.d.ts +12 -0
  65. package/dist/components/Field/field-context.d.ts.map +1 -1
  66. package/dist/components/Field/field-context.js +10 -1
  67. package/dist/components/Field/field-context.js.map +1 -1
  68. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  69. package/dist/components/Field/field-wrapper.js +7 -1
  70. package/dist/components/Field/field-wrapper.js.map +1 -1
  71. package/dist/components/Field/field.d.ts.map +1 -1
  72. package/dist/components/Field/field.js +11 -2
  73. package/dist/components/Field/field.js.map +1 -1
  74. package/dist/components/FieldControlGroup/field-control-group.d.ts +2 -5
  75. package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -1
  76. package/dist/components/FieldControlGroup/field-control-group.js +2 -2
  77. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  78. package/dist/components/FileUpload/file-upload.js +1 -1
  79. package/dist/components/FileUpload/file-upload.js.map +1 -1
  80. package/dist/components/FileViewer/file-viewer.d.ts +1 -1
  81. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  82. package/dist/components/FileViewer/file-viewer.js +20 -3
  83. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  84. package/dist/components/InlineEdit/inline-edit.d.ts +5 -0
  85. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
  86. package/dist/components/InlineEdit/inline-edit.js +65 -33
  87. package/dist/components/InlineEdit/inline-edit.js.map +1 -1
  88. package/dist/components/Input/input.d.ts.map +1 -1
  89. package/dist/components/Input/input.js +3 -2
  90. package/dist/components/Input/input.js.map +1 -1
  91. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  92. package/dist/components/LinkInput/link-input.js +2 -1
  93. package/dist/components/LinkInput/link-input.js.map +1 -1
  94. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  95. package/dist/components/Menu/menu-item.js +4 -2
  96. package/dist/components/Menu/menu-item.js.map +1 -1
  97. package/dist/components/PeoplePicker/people-picker.d.ts +2 -0
  98. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  99. package/dist/components/PeoplePicker/people-picker.js +4 -0
  100. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  101. package/dist/components/Popover/popover.d.ts.map +1 -1
  102. package/dist/components/Popover/popover.js +4 -2
  103. package/dist/components/Popover/popover.js.map +1 -1
  104. package/dist/components/ScrollArea/scroll-area.d.ts +4 -3
  105. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  106. package/dist/components/ScrollArea/scroll-area.js +1 -1
  107. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  108. package/dist/components/Select/select.d.ts.map +1 -1
  109. package/dist/components/Select/select.js +59 -37
  110. package/dist/components/Select/select.js.map +1 -1
  111. package/dist/components/SelectMenu/select-menu.d.ts +2 -0
  112. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  113. package/dist/components/SelectMenu/select-menu.js +3 -1
  114. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  115. package/dist/components/Sheet/sheet.d.ts +1 -1
  116. package/dist/components/Sidebar/sidebar.js +2 -2
  117. package/dist/components/Sidebar/sidebar.js.map +1 -1
  118. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  119. package/dist/components/Tabs/tabs.js +3 -0
  120. package/dist/components/Tabs/tabs.js.map +1 -1
  121. package/dist/components/Tag/tag.d.ts +1 -1
  122. package/dist/components/Tag/tag.d.ts.map +1 -1
  123. package/dist/components/Tag/tag.js +4 -3
  124. package/dist/components/Tag/tag.js.map +1 -1
  125. package/dist/components/Textarea/textarea.d.ts +11 -0
  126. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  127. package/dist/components/Textarea/textarea.js +22 -5
  128. package/dist/components/Textarea/textarea.js.map +1 -1
  129. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  130. package/dist/components/TimePicker/time-picker.js +4 -3
  131. package/dist/components/TimePicker/time-picker.js.map +1 -1
  132. package/dist/components/Tooltip/tooltip.d.ts +1 -1
  133. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  134. package/dist/components/Tooltip/tooltip.js +26 -1
  135. package/dist/components/Tooltip/tooltip.js.map +1 -1
  136. package/dist/components/TreeView/tree-view.d.ts +2 -0
  137. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  138. package/dist/components/TreeView/tree-view.js +3 -2
  139. package/dist/components/TreeView/tree-view.js.map +1 -1
  140. package/dist/index.d.ts +5 -3
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +4 -0
  143. package/dist/index.js.map +1 -1
  144. package/dist/patterns/element-anatomy/item-anatomy.d.ts +10 -1
  145. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  146. package/dist/patterns/element-anatomy/item-anatomy.js +77 -29
  147. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  148. package/dist/patterns/header-canonical/chrome-header.d.ts +11 -4
  149. package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -1
  150. package/dist/patterns/header-canonical/chrome-header.js +1 -1
  151. package/dist/patterns/header-canonical/chrome-header.js.map +1 -1
  152. package/dist/patterns/overlay-surface/overlay-surface.d.ts +4 -3
  153. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  154. package/dist/patterns/overlay-surface/overlay-surface.js +1 -0
  155. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  156. package/dist/patterns/resize-handle/resize-handle.d.ts +9 -11
  157. package/dist/patterns/resize-handle/resize-handle.d.ts.map +1 -1
  158. package/dist/patterns/resize-handle/resize-handle.js +3 -6
  159. package/dist/patterns/resize-handle/resize-handle.js.map +1 -1
  160. package/ds-canonical/adapters/claude/agents/canonical-reviewer.md +1 -1
  161. package/ds-canonical/adapters/claude-root-instructions.md +1 -1
  162. package/ds-canonical/adapters/claude-settings-base.json +2 -5
  163. package/ds-canonical/fork/AGENTS.md +21 -10
  164. package/ds-canonical/fork/codex/hooks.json +1 -1
  165. package/ds-canonical/fork/common/instruction.md +21 -10
  166. package/ds-canonical/fork/consumer/governance-check.mjs +101 -13
  167. package/ds-canonical/fork/consumer/lock.json +14 -15
  168. package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +26 -3
  169. package/ds-canonical/fork/consumer/managed-files/63061e05969667005020166ea2ae7df3c96663f7a928e7dd3eebc1471022df56.blob +61 -5
  170. package/ds-canonical/fork/consumer/managed-files/93a89f16f6717d1e4e4e27ec20ef916e3355c7aa890ca74cd9b12db30d8a899f.blob +3 -10
  171. package/ds-canonical/fork/consumer/managed-files/bc44cabad181f766611dab6a8f52d81100afadd50ac59799015e8ba7bf46d9eb.blob +3 -2
  172. package/ds-canonical/fork/governance.lock +17 -33
  173. package/ds-canonical/fork/hooks/check_consumer_code_quality.sh +33 -0
  174. package/ds-canonical/fork/hooks/check_pattern_invariants.sh +39 -0
  175. package/ds-canonical/fork/hooks/check_sidebar_menu_button_implicit_wrap.sh +6 -4
  176. package/ds-canonical/fork/launchers/provider-hook-normalization.mjs +5 -11
  177. package/ds-canonical/fork/launchers/settings-hooks.json +2 -2
  178. package/ds-canonical/fork/manifest.json +11 -13
  179. package/ds-canonical/fork/providers/claude/hook-config.json +1 -7
  180. package/ds-canonical/fork/providers/codex/hook-config.json +1 -1
  181. package/ds-canonical/fork/references/story-baseline-registry.json +7 -1
  182. package/ds-canonical/hooks/check_consumer_code_quality.sh +33 -0
  183. package/ds-canonical/hooks/check_pattern_invariants.sh +39 -0
  184. package/ds-canonical/hooks/check_sidebar_menu_button_implicit_wrap.sh +6 -4
  185. package/ds-canonical/hooks/session_start_governance_check.sh +5 -6
  186. package/ds-canonical/hooks/tests/test_check_consumer_code_quality.sh +23 -1
  187. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +36 -2
  188. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  189. package/ds-canonical/references/failure-class-registry.json +151 -144
  190. package/ds-canonical/references/preflight-gate-baseline.json +16 -12
  191. package/ds-canonical/references/story-baseline-registry.json +7 -1
  192. package/ds-canonical/rules/meta-patterns.md +3 -3
  193. package/ds-canonical/skills/design-system-audit/SKILL.md +1 -1
  194. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1 -1
  195. package/ds-canonical/templates/dashboard-app.tsx +31 -8
  196. package/llms-full.txt +6 -1
  197. package/llms.txt +2 -1
  198. package/package.json +1 -1
  199. package/src/components/Accordion/accordion.principles.stories.tsx +16 -26
  200. package/src/components/Accordion/accordion.stories.tsx +22 -40
  201. package/src/components/AccountMenu/account-menu.anatomy.stories.tsx +115 -0
  202. package/src/components/AccountMenu/account-menu.principles.stories.tsx +99 -0
  203. package/src/components/AccountMenu/account-menu.spec.md +101 -0
  204. package/src/components/AccountMenu/account-menu.stories.tsx +61 -0
  205. package/src/components/AccountMenu/account-menu.tsx +170 -0
  206. package/src/components/AccountMenu/index.ts +5 -0
  207. package/src/components/AppShell/_demo-helpers.tsx +53 -53
  208. package/src/components/AppShell/app-shell.spec.md +5 -1
  209. package/src/components/AppShell/app-shell.tsx +14 -12
  210. package/src/components/Avatar/avatar.principles.stories.tsx +4 -4
  211. package/src/components/Avatar/avatar.stories.tsx +20 -5
  212. package/src/components/Breadcrumb/breadcrumb.spec.md +1 -1
  213. package/src/components/Button/button.spec.md +1 -1
  214. package/src/components/Button/button.stories.tsx +21 -9
  215. package/src/components/Button/button.tsx +5 -4
  216. package/src/components/Calendar/calendar.anatomy.stories.tsx +19 -17
  217. package/src/components/Calendar/calendar.principles.stories.tsx +5 -6
  218. package/src/components/Calendar/calendar.spec.md +25 -29
  219. package/src/components/Calendar/calendar.stories.tsx +5 -7
  220. package/src/components/Calendar/calendar.tsx +75 -87
  221. package/src/components/Carousel/carousel.principles.stories.tsx +5 -1
  222. package/src/components/Chart/chart.spec.md +1 -1
  223. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +14 -5
  224. package/src/components/Chip/chip.spec.md +1 -1
  225. package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +7 -6
  226. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +8 -6
  227. package/src/components/CircularProgress/circular-progress.stories.tsx +3 -3
  228. package/src/components/Combobox/combobox.tsx +1 -0
  229. package/src/components/Command/command.spec.md +1 -0
  230. package/src/components/Command/command.tsx +4 -1
  231. package/src/components/DataTable/cell-registry.tsx +3 -7
  232. package/src/components/DataTable/data-table-filter-group.tsx +44 -27
  233. package/src/components/DataTable/data-table-filter-labels.ts +100 -0
  234. package/src/components/DataTable/data-table-filter-panel.tsx +48 -8
  235. package/src/components/DataTable/data-table-filter-value-picker.tsx +25 -8
  236. package/src/components/DataTable/data-table.spec.md +18 -1
  237. package/src/components/DataTable/data-table.stories.tsx +346 -33
  238. package/src/components/DataTable/data-table.tsx +11 -4
  239. package/src/components/DataTable/filter-operators.spec.md +2 -2
  240. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +24 -20
  241. package/src/components/DateGrid/date-grid.principles.stories.tsx +27 -21
  242. package/src/components/DateGrid/date-grid.stories.tsx +22 -13
  243. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +3 -3
  244. package/src/components/DatePicker/date-picker.spec.md +4 -4
  245. package/src/components/DatePicker/date-picker.stories.tsx +33 -9
  246. package/src/components/DatePicker/date-picker.tsx +210 -147
  247. package/src/components/Dialog/dialog.spec.md +1 -1
  248. package/src/components/Dialog/dialog.tsx +8 -2
  249. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  250. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -0
  251. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +3 -17
  252. package/src/components/DropdownMenu/dropdown-menu.tsx +58 -16
  253. package/src/components/Field/field-context.ts +25 -1
  254. package/src/components/Field/field-wrapper.tsx +7 -1
  255. package/src/components/Field/field.spec.md +8 -1
  256. package/src/components/Field/field.tsx +14 -2
  257. package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +3 -3
  258. package/src/components/FieldControlGroup/field-control-group.spec.md +2 -3
  259. package/src/components/FieldControlGroup/field-control-group.stories.tsx +2 -1
  260. package/src/components/FieldControlGroup/field-control-group.tsx +6 -9
  261. package/src/components/FileItem/file-item.spec.md +1 -1
  262. package/src/components/FileItem/file-item.stories.tsx +1 -1
  263. package/src/components/FileUpload/file-upload.stories.tsx +32 -0
  264. package/src/components/FileUpload/file-upload.tsx +1 -1
  265. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +1 -1
  266. package/src/components/FileViewer/file-viewer.spec.md +1 -1
  267. package/src/components/FileViewer/file-viewer.stories.tsx +7 -0
  268. package/src/components/FileViewer/file-viewer.tsx +23 -5
  269. package/src/components/InlineEdit/inline-edit.spec.md +12 -0
  270. package/src/components/InlineEdit/inline-edit.stories.tsx +30 -19
  271. package/src/components/InlineEdit/inline-edit.tsx +94 -31
  272. package/src/components/Input/input.anatomy.stories.tsx +28 -12
  273. package/src/components/Input/input.principles.stories.tsx +23 -18
  274. package/src/components/Input/input.stories.tsx +9 -1
  275. package/src/components/Input/input.tsx +7 -2
  276. package/src/components/LinkInput/link-input.principles.stories.tsx +7 -7
  277. package/src/components/LinkInput/link-input.spec.md +1 -1
  278. package/src/components/LinkInput/link-input.tsx +5 -1
  279. package/src/components/Menu/menu-item.anatomy.stories.tsx +1 -1
  280. package/src/components/Menu/menu-item.tsx +9 -2
  281. package/src/components/NumberInput/number-input.anatomy.stories.tsx +44 -10
  282. package/src/components/NumberInput/number-input.principles.stories.tsx +20 -14
  283. package/src/components/NumberInput/number-input.spec.md +1 -1
  284. package/src/components/NumberInput/number-input.stories.tsx +12 -5
  285. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +7 -0
  286. package/src/components/PeoplePicker/people-picker.spec.md +3 -1
  287. package/src/components/PeoplePicker/people-picker.tsx +5 -0
  288. package/src/components/Popover/popover.tsx +7 -2
  289. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +14 -12
  290. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +5 -1
  291. package/src/components/RadioGroup/radio-group.spec.md +1 -1
  292. package/src/components/Rating/rating.principles.stories.tsx +2 -2
  293. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  294. package/src/components/ScrollArea/scroll-area.spec.md +3 -3
  295. package/src/components/ScrollArea/scroll-area.tsx +5 -4
  296. package/src/components/Select/select.principles.stories.tsx +4 -3
  297. package/src/components/Select/select.stories.tsx +7 -6
  298. package/src/components/Select/select.tsx +61 -29
  299. package/src/components/SelectMenu/select-menu.spec.md +1 -1
  300. package/src/components/SelectMenu/select-menu.tsx +4 -1
  301. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +19 -8
  302. package/src/components/SelectionControl/selection-item.stories.tsx +7 -7
  303. package/src/components/Sheet/sheet.spec.md +1 -1
  304. package/src/components/Sidebar/sidebar.spec.md +3 -2
  305. package/src/components/Sidebar/sidebar.stories.tsx +67 -37
  306. package/src/components/Sidebar/sidebar.tsx +3 -3
  307. package/src/components/Slider/slider.principles.stories.tsx +9 -9
  308. package/src/components/Steps/steps.spec.md +1 -0
  309. package/src/components/Steps/steps.stories.tsx +18 -1
  310. package/src/components/Switch/switch.anatomy.stories.tsx +11 -11
  311. package/src/components/Switch/switch.principles.stories.tsx +11 -8
  312. package/src/components/Tabs/tabs.principles.stories.tsx +24 -0
  313. package/src/components/Tabs/tabs.spec.md +6 -4
  314. package/src/components/Tabs/tabs.tsx +11 -0
  315. package/src/components/Tag/tag.anatomy.stories.tsx +5 -2
  316. package/src/components/Tag/tag.spec.md +4 -3
  317. package/src/components/Tag/tag.stories.tsx +19 -0
  318. package/src/components/Tag/tag.tsx +14 -5
  319. package/src/components/Textarea/textarea.anatomy.stories.tsx +15 -9
  320. package/src/components/Textarea/textarea.principles.stories.tsx +21 -5
  321. package/src/components/Textarea/textarea.spec.md +10 -1
  322. package/src/components/Textarea/textarea.tsx +38 -5
  323. package/src/components/TimePicker/time-picker.tsx +11 -5
  324. package/src/components/Tooltip/tooltip.spec.md +10 -0
  325. package/src/components/Tooltip/tooltip.tsx +34 -3
  326. package/src/components/TreeView/tree-view.spec.md +3 -3
  327. package/src/components/TreeView/tree-view.stories.tsx +68 -9
  328. package/src/components/TreeView/tree-view.tsx +7 -2
  329. package/src/index.ts +9 -1
  330. package/src/patterns/element-anatomy/inline-action.spec.md +12 -8
  331. package/src/patterns/element-anatomy/item-anatomy.spec.md +8 -1
  332. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +24 -5
  333. package/src/patterns/element-anatomy/item-anatomy.tsx +120 -35
  334. package/src/patterns/element-anatomy/truncated-text.spec.md +13 -2
  335. package/src/patterns/header-canonical/chrome-header.tsx +14 -5
  336. package/src/patterns/header-canonical/header-canonical.spec.md +10 -7
  337. package/src/patterns/header-canonical/header-canonical.stories.tsx +77 -0
  338. package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +2 -0
  339. package/src/patterns/overlay-surface/overlay-surface.spec.md +1 -0
  340. package/src/patterns/overlay-surface/overlay-surface.stories.tsx +17 -1
  341. package/src/patterns/overlay-surface/overlay-surface.tsx +8 -4
  342. package/src/patterns/resize-handle/resize-handle.spec.md +11 -13
  343. package/src/patterns/resize-handle/resize-handle.stories.tsx +1 -3
  344. package/src/patterns/resize-handle/resize-handle.tsx +13 -18
  345. package/src/tokens/color/semantic.css +3 -1
  346. package/src/tokens/layoutSpace/layoutSpace.stories.tsx +1 -1
  347. package/src/tokens/opacity/opacity.stories.tsx +1 -1
  348. package/src/tokens/radius/radius.stories.tsx +3 -3
  349. package/src/tokens/uiSize/uiSize.css +11 -0
  350. package/src/tokens/uiSize/uiSize.spec.md +1 -0
  351. package/ds-canonical/commands/gov-status.md +0 -9
  352. package/ds-canonical/fork/consumer/managed-files/77e06f62670dfee01e9b5e8b0f8dad085ce711d75538c1fb0679d9818acaca82.blob +0 -424
  353. package/ds-canonical/fork/preamble.md +0 -500
  354. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +0 -8
  355. package/ds-canonical/hooks/tests/test_check_post_main_ssot_propagate.sh +0 -37
package/README.md CHANGED
@@ -135,6 +135,7 @@ Token `--font-sans` stack = `Roboto, -apple-system, BlinkMacSystemFont, "Segoe U
135
135
  | `react-dom` | `>= 18.0.0` | peer |
136
136
  | `tailwindcss` | `>= 4.0.0` | peer,Tailwind v4 only |
137
137
  | `lucide-react` | `>= 0.400.0` | peer(consumer 已裝,DS 不重複,避免 hoisting 雙裝)|
138
+ | Document direction | **LTR only** | RTL 不在目前支援矩陣;元件可能使用 physical left/right、LTR scrollLeft 與未鏡像 directional icons。consumer 不得把 `dir="rtl"` 視為已支援。若未來要支援,必須以 DS-wide proposal 同步 tokens、layout、icons、keyboard/scroll behavior 與 visual/a11y matrix,不能逐元件局部宣稱。|
138
139
 
139
140
  ---
140
141
 
@@ -0,0 +1,86 @@
1
+ /**
2
+ * AccountMenu — 全域 chrome「自己的帳號入口」(24px avatar 觸發 + 帳號選單)
3
+ *
4
+ * ── 定位 ──
5
+ * Primary-header 派 globalHeader 右側(desktop)/ mobile Sheet SidebarHeader 右側的
6
+ * 帳號入口成品元件:點 avatar 開「個人資料 / 設定 / 登出」navigation 選單。
7
+ * 是「自己」的入口,不是看「別人」的 ProfileCard(後者預設動作 Chat/通話,語義是聯絡某人)。
8
+ * **Placement-agnostic**:哪個 mode 放哪裡是 consumer 職責,放置 canonical owner =
9
+ * `../AppShell/app-shell.spec.md`「帳號入口(Account entry)放置 SSOT」(本元件不收 mode prop,
10
+ * 不複製該 SSOT;consumer 讀 `useAppShell().layout` + `useSidebar().isMobile` 決定放置)。
11
+ *
12
+ * ── 實作基礎 ──
13
+ * 消費:Avatar(raw size=24 trigger)+ DropdownMenu(Trigger asChild / Content / Group / Label / Item)
14
+ * 對應 pattern:patterns/header-canonical(4.5 chrome header avatar SSOT)
15
+ *
16
+ * ── 消費的 SSOT ──
17
+ * - components: [Avatar, DropdownMenu(DropdownMenuTrigger/Content/Group/Label/Item)]
18
+ * - patterns: [header-canonical 4.5(chrome header avatar = raw `<Avatar size={24}>`,非 ItemAvatar)]
19
+ * - tokens: [--chrome-header-avatar-size(JS 端 24 literal sync), --ring(focus-visible ring canonical)]
20
+ * - spec refs: app-shell.spec.md「帳號入口(Account entry)放置 SSOT」/ header-canonical.spec.md 4.5
21
+ * / dropdown-menu.spec.md / profile-card.spec.md(近親分界:看別人 vs 自己)
22
+ *
23
+ * 升級歷程:2026-06-17 `AppShell/_demo-helpers.tsx` demo helper 誕生(user directive)→
24
+ * 2026-07-30 F9 升 public:app-shell.spec.md + sidebar.spec.md 兩處 canonical 都 mandate
25
+ * 消費本元件,「文件教得到、import 拿不到」= DT-EXPORT 斷鏈同款缺口(gen-component-indexes.mjs
26
+ * 檔頭 anchor),npm consumer 被迫整包重造。世界級對照:Atlassian `@atlaskit/atlassian-navigation`
27
+ * 出貨專門 `Profile` 元件作 top bar 帳號 trigger(ProfileProps = IconButtonProps,選單內容
28
+ * composition;https://unpkg.com/@atlaskit/atlassian-navigation/dist/types/index.d.ts +
29
+ * dist/types/components/Profile/types.d.ts);shadcn / Primer 走 DropdownMenu / ActionMenu
30
+ * composition recipe(https://ui.shadcn.com/docs/components/dropdown-menu「An account switcher
31
+ * dropdown triggered by an avatar」/ https://primer.style/components/action-menu)。本元件 =
32
+ * Atlassian 專門元件 + shadcn canonical 內容組(Label(user)+ Groups)的收斂。
33
+ */
34
+ import * as React from 'react';
35
+ import { type AvatarData } from '../../components/Avatar/avatar';
36
+ export interface AccountMenuUser {
37
+ /** 顯示名(選單 Label 區;alt 未傳時同時作 avatar alt fallback) */
38
+ name: string;
39
+ /**
40
+ * Avatar 資料(消費既有 `AvatarData` type)。`hoverCard` 刻意排除:帳號入口是「自己」,
41
+ * 不掛 ProfileCard(per app-shell.spec.md 帳號入口 SSOT「不用 ProfileCard」);
42
+ * `alt` 可省,fallback `name`。
43
+ */
44
+ avatar?: Omit<AvatarData, 'hoverCard' | 'alt'> & {
45
+ alt?: string;
46
+ };
47
+ }
48
+ export interface AccountMenuProps {
49
+ /** 當前登入使用者 */
50
+ user: AccountMenuUser;
51
+ /** 「個人資料」item handler(default 選單消費;命名對齊 `PersonData.onViewProfile` 既有 canonical) */
52
+ onViewProfile?: () => void;
53
+ /** 「設定」item handler(default 選單消費) */
54
+ onOpenSettings?: () => void;
55
+ /** 「登出」item handler(default 選單消費) */
56
+ onSignOut?: () => void;
57
+ /**
58
+ * 取代 default 選單內容(自組 `DropdownMenuGroup` / `DropdownMenuItem`;i18n / 產品自訂項走這)。
59
+ * Identity Label(user.name)恆由本元件渲染於選單頂(對齊 shadcn account 例 Label(user)慣例);
60
+ * 傳入 children 時三個 default callback 不再消費。
61
+ */
62
+ children?: React.ReactNode;
63
+ /** 選單對齊(轉傳 DropdownMenuContent `align`)。預設 `'end'`:右上入口靠右展開(demo baseline) */
64
+ align?: 'start' | 'center' | 'end';
65
+ /** Trigger aria-label(i18n override,對齊 Avatar `badgeAriaLabel` pattern)。預設「帳號與設定」 */
66
+ triggerAriaLabel?: string;
67
+ /** 預設展開(uncontrolled,Radix passthrough)。Storybook OpenSnapshot(M15 visual-audit coverable)用 */
68
+ defaultOpen?: boolean;
69
+ }
70
+ export declare function AccountMenu({ user, onViewProfile, onOpenSettings, onSignOut, children, align, triggerAriaLabel, defaultOpen, }: AccountMenuProps): import("react/jsx-runtime").JSX.Element;
71
+ export declare namespace AccountMenu {
72
+ var displayName: string;
73
+ }
74
+ export declare const accountMenuMeta: {
75
+ readonly component: "AccountMenu";
76
+ readonly family: null;
77
+ readonly variants: {};
78
+ readonly sizes: {};
79
+ readonly states: readonly ["default", "focus-visible"];
80
+ readonly tokens: {
81
+ readonly bg: readonly [];
82
+ readonly fg: readonly [];
83
+ readonly ring: readonly ["--ring"];
84
+ };
85
+ };
86
+ //# sourceMappingURL=account-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../../src/components/AccountMenu/account-menu.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAA;AAYlF,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAA;IACZ;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,KAAK,CAAC,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAClE;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc;IACd,IAAI,EAAE,eAAe,CAAA;IACrB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAID,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,aAAa,EACb,cAAc,EACd,SAAS,EACT,QAAQ,EACR,KAAa,EACb,gBAA0B,EAC1B,WAAW,GACZ,EAAE,gBAAgB,2CA6DlB;yBAtEe,WAAW;;;AA2E3B,eAAO,MAAM,eAAe;;;;;;;;;;;CAWlB,CAAA"}
@@ -0,0 +1,64 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { User, Settings, LogOut } from "lucide-react";
3
+ import { Avatar } from "../Avatar/avatar.js";
4
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem } from "../DropdownMenu/dropdown-menu.js";
5
+ function AccountMenu({
6
+ user,
7
+ onViewProfile,
8
+ onOpenSettings,
9
+ onSignOut,
10
+ children,
11
+ align = "end",
12
+ triggerAriaLabel = "帳號與設定",
13
+ defaultOpen
14
+ }) {
15
+ if (process.env.NODE_ENV !== "production" && !children && !onViewProfile && !onOpenSettings && !onSignOut) {
16
+ console.warn(
17
+ "[DS AccountMenu] default 選單項未接 onViewProfile/onOpenSettings/onSignOut——item 點擊無反應。請傳入 callback 或自組 children。"
18
+ );
19
+ }
20
+ const avatar = user.avatar ?? {};
21
+ return /* @__PURE__ */ jsxs(DropdownMenu, { defaultOpen, children: [
22
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
23
+ "button",
24
+ {
25
+ type: "button",
26
+ "aria-label": triggerAriaLabel,
27
+ className: "flex items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
28
+ children: /* @__PURE__ */ jsx(Avatar, { size: 24, ...avatar, alt: avatar.alt ?? user.name })
29
+ }
30
+ ) }),
31
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align, children: children ? /* @__PURE__ */ jsxs(Fragment, { children: [
32
+ /* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuLabel, { children: user.name }) }),
33
+ children
34
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
35
+ /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
36
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { children: user.name }),
37
+ /* @__PURE__ */ jsx(DropdownMenuItem, { startIcon: User, onSelect: onViewProfile, children: "個人資料" }),
38
+ /* @__PURE__ */ jsx(DropdownMenuItem, { startIcon: Settings, onSelect: onOpenSettings, children: "設定" })
39
+ ] }),
40
+ /* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuItem, { startIcon: LogOut, onSelect: onSignOut, children: "登出" }) })
41
+ ] }) })
42
+ ] });
43
+ }
44
+ AccountMenu.displayName = "AccountMenu";
45
+ const accountMenuMeta = {
46
+ component: "AccountMenu",
47
+ family: null,
48
+ // composite(trigger = chrome header 24px avatar;浮層 = DropdownMenu Family 1 消費者)
49
+ variants: {},
50
+ sizes: {},
51
+ // trigger avatar 24px density-fixed(header-canonical.spec.md 4.5),無 size 軸 → 兩欄留空為 intentional
52
+ states: ["default", "focus-visible"],
53
+ tokens: {
54
+ bg: [],
55
+ fg: [],
56
+ ring: ["--ring"]
57
+ // trigger focus-visible ring canonical
58
+ }
59
+ };
60
+ export {
61
+ AccountMenu,
62
+ accountMenuMeta
63
+ };
64
+ //# sourceMappingURL=account-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-menu.js","sources":["../../../src/components/AccountMenu/account-menu.tsx"],"sourcesContent":["/**\n * AccountMenu — 全域 chrome「自己的帳號入口」(24px avatar 觸發 + 帳號選單)\n *\n * ── 定位 ──\n * Primary-header 派 globalHeader 右側(desktop)/ mobile Sheet SidebarHeader 右側的\n * 帳號入口成品元件:點 avatar 開「個人資料 / 設定 / 登出」navigation 選單。\n * 是「自己」的入口,不是看「別人」的 ProfileCard(後者預設動作 Chat/通話,語義是聯絡某人)。\n * **Placement-agnostic**:哪個 mode 放哪裡是 consumer 職責,放置 canonical owner =\n * `../AppShell/app-shell.spec.md`「帳號入口(Account entry)放置 SSOT」(本元件不收 mode prop,\n * 不複製該 SSOT;consumer 讀 `useAppShell().layout` + `useSidebar().isMobile` 決定放置)。\n *\n * ── 實作基礎 ──\n * 消費:Avatar(raw size=24 trigger)+ DropdownMenu(Trigger asChild / Content / Group / Label / Item)\n * 對應 pattern:patterns/header-canonical(4.5 chrome header avatar SSOT)\n *\n * ── 消費的 SSOT ──\n * - components: [Avatar, DropdownMenu(DropdownMenuTrigger/Content/Group/Label/Item)]\n * - patterns: [header-canonical 4.5(chrome header avatar = raw `<Avatar size={24}>`,非 ItemAvatar)]\n * - tokens: [--chrome-header-avatar-size(JS 端 24 literal sync), --ring(focus-visible ring canonical)]\n * - spec refs: app-shell.spec.md「帳號入口(Account entry)放置 SSOT」/ header-canonical.spec.md 4.5\n * / dropdown-menu.spec.md / profile-card.spec.md(近親分界:看別人 vs 自己)\n *\n * 升級歷程:2026-06-17 `AppShell/_demo-helpers.tsx` demo helper 誕生(user directive)→\n * 2026-07-30 F9 升 public:app-shell.spec.md + sidebar.spec.md 兩處 canonical 都 mandate\n * 消費本元件,「文件教得到、import 拿不到」= DT-EXPORT 斷鏈同款缺口(gen-component-indexes.mjs\n * 檔頭 anchor),npm consumer 被迫整包重造。世界級對照:Atlassian `@atlaskit/atlassian-navigation`\n * 出貨專門 `Profile` 元件作 top bar 帳號 trigger(ProfileProps = IconButtonProps,選單內容\n * composition;https://unpkg.com/@atlaskit/atlassian-navigation/dist/types/index.d.ts +\n * dist/types/components/Profile/types.d.ts);shadcn / Primer 走 DropdownMenu / ActionMenu\n * composition recipe(https://ui.shadcn.com/docs/components/dropdown-menu「An account switcher\n * dropdown triggered by an avatar」/ https://primer.style/components/action-menu)。本元件 =\n * Atlassian 專門元件 + shadcn canonical 內容組(Label(user)+ Groups)的收斂。\n */\nimport * as React from 'react'\nimport { User, Settings, LogOut } from 'lucide-react'\nimport { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuGroup,\n} from '@/design-system/components/DropdownMenu/dropdown-menu'\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface AccountMenuUser {\n /** 顯示名(選單 Label 區;alt 未傳時同時作 avatar alt fallback) */\n name: string\n /**\n * Avatar 資料(消費既有 `AvatarData` type)。`hoverCard` 刻意排除:帳號入口是「自己」,\n * 不掛 ProfileCard(per app-shell.spec.md 帳號入口 SSOT「不用 ProfileCard」);\n * `alt` 可省,fallback `name`。\n */\n avatar?: Omit<AvatarData, 'hoverCard' | 'alt'> & { alt?: string }\n}\n\nexport interface AccountMenuProps {\n /** 當前登入使用者 */\n user: AccountMenuUser\n /** 「個人資料」item handler(default 選單消費;命名對齊 `PersonData.onViewProfile` 既有 canonical) */\n onViewProfile?: () => void\n /** 「設定」item handler(default 選單消費) */\n onOpenSettings?: () => void\n /** 「登出」item handler(default 選單消費) */\n onSignOut?: () => void\n /**\n * 取代 default 選單內容(自組 `DropdownMenuGroup` / `DropdownMenuItem`;i18n / 產品自訂項走這)。\n * Identity Label(user.name)恆由本元件渲染於選單頂(對齊 shadcn account 例 Label(user)慣例);\n * 傳入 children 時三個 default callback 不再消費。\n */\n children?: React.ReactNode\n /** 選單對齊(轉傳 DropdownMenuContent `align`)。預設 `'end'`:右上入口靠右展開(demo baseline) */\n align?: 'start' | 'center' | 'end'\n /** Trigger aria-label(i18n override,對齊 Avatar `badgeAriaLabel` pattern)。預設「帳號與設定」 */\n triggerAriaLabel?: string\n /** 預設展開(uncontrolled,Radix passthrough)。Storybook OpenSnapshot(M15 visual-audit coverable)用 */\n defaultOpen?: boolean\n}\n\n// ── AccountMenu ─────────────────────────────────────────────────────────────\n\nexport function AccountMenu({\n user,\n onViewProfile,\n onOpenSettings,\n onSignOut,\n children,\n align = 'end',\n triggerAriaLabel = '帳號與設定',\n defaultOpen,\n}: AccountMenuProps) {\n // Dev-mode warning(對齊 ProfileCardDefaultActions dev-warn 先例):default 選單項沒接任何\n // handler = item 點了永遠沒反應;production 必接 callback 或自組 children。\n if (\n process.env.NODE_ENV !== 'production' &&\n !children &&\n !onViewProfile &&\n !onOpenSettings &&\n !onSignOut\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n '[DS AccountMenu] default 選單項未接 onViewProfile/onOpenSettings/onSignOut——item 點擊無反應。請傳入 callback 或自組 children。'\n )\n }\n const avatar = user.avatar ?? {}\n return (\n <DropdownMenu defaultOpen={defaultOpen}>\n <DropdownMenuTrigger asChild>\n {/* 互動感由 focus-visible ring 提供(無 hover bg,chrome 輕量 entry),不放大到 field height\n — per app-shell.spec.md「Avatar 尺寸 + 邊距」+ header-canonical.spec.md 4.5 */}\n <button\n type=\"button\"\n aria-label={triggerAriaLabel}\n className=\"flex items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\"\n >\n {/* 24 per header-canonical.spec.md 4.5 chrome header avatar canonical(brand + account 同尺寸); sync with --chrome-header-avatar-size */}\n <Avatar size={24} {...avatar} alt={avatar.alt ?? user.name} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align={align}>\n {children ? (\n <>\n <DropdownMenuGroup>\n <DropdownMenuLabel>{user.name}</DropdownMenuLabel>\n </DropdownMenuGroup>\n {children}\n </>\n ) : (\n <>\n {/* Default 選單集合 = app-shell.spec.md「入口開什麼」canonical(個人資料 / 設定 / 登出,\n 登出獨立 group — 破壞性動作分區,對齊 GitHub / Gmail / Slack 帳號選單慣例) */}\n <DropdownMenuGroup>\n <DropdownMenuLabel>{user.name}</DropdownMenuLabel>\n <DropdownMenuItem startIcon={User} onSelect={onViewProfile}>\n 個人資料\n </DropdownMenuItem>\n <DropdownMenuItem startIcon={Settings} onSelect={onOpenSettings}>\n 設定\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuGroup>\n <DropdownMenuItem startIcon={LogOut} onSelect={onSignOut}>\n 登出\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\nAccountMenu.displayName = 'AccountMenu'\n\n// Story auto-compile metadata — F9 public 升級(2026-07-30)\n// Phase 2 fill needed: purpose descriptions + when rationale\nexport const accountMenuMeta = {\n component: 'AccountMenu',\n family: null, // composite(trigger = chrome header 24px avatar;浮層 = DropdownMenu Family 1 消費者)\n variants: {},\n sizes: {}, // trigger avatar 24px density-fixed(header-canonical.spec.md 4.5),無 size 軸 → 兩欄留空為 intentional\n states: ['default', 'focus-visible'],\n tokens: {\n bg: [],\n fg: [],\n ring: ['--ring'], // trigger focus-visible ring canonical\n },\n} as const\n"],"names":[],"mappings":";;;;AAmFO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB;AACF,GAAqB;AAGnB,MACE,QAAQ,IAAI,aAAa,gBACzB,CAAC,YACD,CAAC,iBACD,CAAC,kBACD,CAAC,WACD;AAEA,YAAQ;AAAA,MACN;AAAA,IAAA;AAAA,EAEJ;AACA,QAAM,SAAS,KAAK,UAAU,CAAA;AAC9B,SACE,qBAAC,gBAAa,aACZ,UAAA;AAAA,IAAA,oBAAC,qBAAA,EAAoB,SAAO,MAG1B,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,WAAU;AAAA,QAGV,UAAA,oBAAC,QAAA,EAAO,MAAM,IAAK,GAAG,QAAQ,KAAK,OAAO,OAAO,KAAK,KAAA,CAAM;AAAA,MAAA;AAAA,IAAA,GAEhE;AAAA,IACA,oBAAC,qBAAA,EAAoB,OAClB,UAAA,WACC,qBAAA,UAAA,EACE,UAAA;AAAA,MAAA,oBAAC,mBAAA,EACC,UAAA,oBAAC,mBAAA,EAAmB,UAAA,KAAK,MAAK,GAChC;AAAA,MACC;AAAA,IAAA,EAAA,CACH,IAEA,qBAAA,UAAA,EAGE,UAAA;AAAA,MAAA,qBAAC,mBAAA,EACC,UAAA;AAAA,QAAA,oBAAC,mBAAA,EAAmB,eAAK,KAAA,CAAK;AAAA,4BAC7B,kBAAA,EAAiB,WAAW,MAAM,UAAU,eAAe,UAAA,QAE5D;AAAA,4BACC,kBAAA,EAAiB,WAAW,UAAU,UAAU,gBAAgB,UAAA,KAAA,CAEjE;AAAA,MAAA,GACF;AAAA,MACA,oBAAC,qBACC,UAAA,oBAAC,kBAAA,EAAiB,WAAW,QAAQ,UAAU,WAAW,UAAA,KAAA,CAE1D,EAAA,CACF;AAAA,IAAA,EAAA,CACF,EAAA,CAEJ;AAAA,EAAA,GACF;AAEJ;AACA,YAAY,cAAc;AAInB,MAAM,kBAAkB;AAAA,EAC7B,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA,EACR,UAAU,CAAA;AAAA,EACV,OAAO,CAAA;AAAA;AAAA,EACP,QAAQ,CAAC,WAAW,eAAe;AAAA,EACnC,QAAQ;AAAA,IACN,IAAI,CAAA;AAAA,IACJ,IAAI,CAAA;AAAA,IACJ,MAAM,CAAC,QAAQ;AAAA;AAAA,EAAA;AAEnB;"}
@@ -0,0 +1,2 @@
1
+ export * from './account-menu';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/AccountMenu/index.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { AccountMenu, accountMenuMeta } from "./account-menu.js";
2
+ export {
3
+ AccountMenu,
4
+ accountMenuMeta
5
+ };
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"_demo-helpers.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/_demo-helpers.tsx"],"names":[],"mappings":"AAmDA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;EAOX,CAAA;AAqBV,eAAO,MAAM,cAAc,+CAQ1B,CAAA;AAID,eAAO,MAAM,UAAU,+CAwBtB,CAAA;AAQD,wBAAgB,WAAW,CAAC,EAC1B,gBAAgB,EAChB,qBAA4B,EAC5B,iBAAwB,GACzB,GAAE;IACD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAA;CACvB,2CAwDL;AAWD,wBAAgB,WAAW,4CAyB1B;AAQD,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAE;IAAE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAO,2CAY/E;AASD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,qBAA4B,GAC7B,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,2CAOA"}
1
+ {"version":3,"file":"_demo-helpers.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/_demo-helpers.tsx"],"names":[],"mappings":"AAkDA,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;EAOX,CAAA;AAqBV,eAAO,MAAM,cAAc,+CAQ1B,CAAA;AAOD,eAAO,MAAM,UAAU,+CAkBtB,CAAA;AAQD,wBAAgB,WAAW,CAAC,EAC1B,gBAAgB,EAChB,qBAA4B,EAC5B,iBAAwB,GACzB,GAAE;IACD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAA;CACvB,2CAwDL;AA4BD,wBAAgB,WAAW,4CAY1B;AAQD,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,GAAE;IAAE,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAO,2CAY/E;AASD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,qBAA4B,GAC7B,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,2CAOA"}
@@ -1 +1 @@
1
- {"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/app-shell.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgB9B,KAAK,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAE1D,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACzE,6FAA6F;IAC7F,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,qFAAqF;IACrF,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,iDAAiD;IACjD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,uBAAuB;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAID,UAAU,oBAAoB;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,OAAO,CAAA;CAClB;AAID,iBAAS,WAAW,IAAI,oBAAoB,CAI3C;AA+DD,QAAA,MAAM,QAAQ,sFAiIb,CAAA;AAKD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,aAAa,wFA6FlB,CAAA;AAQD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/app-shell.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAgB9B,KAAK,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAA;AAE1D,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACzE,6FAA6F;IAC7F,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,qFAAqF;IACrF,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3C,iDAAiD;IACjD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,uBAAuB;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAID,UAAU,oBAAoB;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,OAAO,CAAA;CAClB;AAID,iBAAS,WAAW,IAAI,oBAAoB,CAI3C;AAiED,QAAA,MAAM,QAAQ,sFAiIb,CAAA;AAKD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,aAAa,wFA6FlB,CAAA;AAQD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA"}
@@ -41,7 +41,7 @@ function resolveAsideWidth(width, isXl) {
41
41
  return ASIDE_WIDTH_DEFAULT;
42
42
  }
43
43
  function SkipToMain() {
44
- return /* @__PURE__ */ jsx(
44
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Skip links", children: /* @__PURE__ */ jsx(
45
45
  "a",
46
46
  {
47
47
  href: "#app-shell-main",
@@ -54,7 +54,7 @@ function SkipToMain() {
54
54
  ),
55
55
  children: "Skip to main content"
56
56
  }
57
- );
57
+ ) });
58
58
  }
59
59
  const AppShell = React.forwardRef(
60
60
  ({
@@ -1 +1 @@
1
- {"version":3,"file":"app-shell.js","sources":["../../../src/components/AppShell/app-shell.tsx"],"sourcesContent":["// @benchmark-cited: 2026-05-19 — Mantine AppShell / Ant Layout / Material 3 Drawer / Atlassian Navigation System cite in app-shell.spec.md frontmatter.\n/**\n * AppShell — web service page-level layout primitive。\n *\n * 組合 Sidebar + ChromeHeader + Aside + main 成完整 page shell。SSOT 邊界:本 composite component only\n * own slot composition + layout mode + Aside responsive mode;不 own sidebar / header /\n * sheet 視覺(各自 spec own)。\n *\n * 對齊 Mantine AppShell compound API + Ant Layout slot 模式 + Material 3 standard/modal\n * drawer canonical(per spec.md frontmatter cite)。\n *\n * Spec SSOT:`components/AppShell/app-shell.spec.md`\n */\n\nimport * as React from 'react'\nimport { X as XIcon } from 'lucide-react'\nimport {\n Sheet,\n SheetContent,\n SheetTitle,\n handleSheetOpenAutoFocus,\n} from '@/design-system/components/Sheet/sheet'\nimport { Button } from '@/design-system/components/Button/button'\nimport { ScrollArea } from '@/design-system/components/ScrollArea/scroll-area'\nimport { ChromeHeader } from '@/design-system/patterns/header-canonical/chrome-header'\nimport { useIsNarrowViewport } from '@/design-system/hooks/use-is-narrow-viewport'\nimport { cn } from '@/lib/utils'\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\ntype AppShellLayout = 'primary-sidebar' | 'primary-header'\n\nexport interface AppShellProps extends React.HTMLAttributes<HTMLDivElement> {\n /** primary-sidebar (Linear/Notion 派) | primary-header (GitHub/Slack 派);預設 primary-sidebar */\n layout?: AppShellLayout\n /** Sidebar 元素(應傳 Sidebar primitive,per Consumer 紀律;型別 optional 不機械強制,對齊 spec「應」措辭)*/\n sidebar?: React.ReactNode\n /**\n * Local page header(永遠 render 在 main column 頂部,當前頁 actions / breadcrumb / page-level filter)。\n * 兩 layout mode 都會 render 此 slot — `primary-header` mode 多了 globalHeader 在上方,\n * **不取代** local header(per 2026-05-20 user clarification「primary-header = primary-sidebar + 一條 global header」)。\n */\n header?: React.ReactNode\n /**\n * Global header(僅 `primary-header` mode render)。橫跨整 viewport 的頂部 bar:\n * account avatar / workspace switcher / global search / notifications。\n * 對齊 GitHub top nav / Slack workspace bar / Gmail logo bar 慣例。\n * `primary-sidebar` mode 傳此 prop 會被忽略。\n */\n globalHeader?: React.ReactNode\n /** Aside 元素(`<AppShellAside>` sub-component);可選 */\n aside?: React.ReactNode\n /** Aside open state(modal mode 必須)*/\n asideOpen?: boolean\n onAsideOpenChange?: (open: boolean) => void\n /** Main content;`<main>` landmark + padding=0 */\n children: React.ReactNode\n}\n\nexport interface AppShellAsideProps {\n /** Required:modal mode 走 Sheet → aria-labelledby 強制,per sheet.spec.md:98 */\n title: string\n /** Width(number 或 breakpoint-keyed object);clamp min:240 max:640 */\n width?: number | { md?: number; xl?: number }\n /** Children content */\n children: React.ReactNode\n className?: string\n}\n\n// ── Context ──────────────────────────────────────────────────────────────────\n\ninterface AppShellContextValue {\n layout: AppShellLayout\n asideOpen: boolean\n setAsideOpen: (open: boolean) => void\n isMobile: boolean\n}\n\nconst AppShellContext = React.createContext<AppShellContextValue | null>(null)\n\nfunction useAppShell(): AppShellContextValue {\n const ctx = React.useContext(AppShellContext)\n if (!ctx) throw new Error('AppShellAside must be used within <AppShell>')\n return ctx\n}\n\n// Mobile breakpoint:**消費既有 `useIsNarrowViewport`**(`hooks/use-is-narrow-viewport.ts` SSOT,\n// 768px,跟 Sidebar SSOT 同源)— 不發明 local hook,per codex Layer B D2/D4 verdict 避 drift。\n\n// xl breakpoint(對齊 Tailwind v4 xl = 1280px,DS-wide consensus)\nconst XL_BREAKPOINT_PX = 1280\n\nfunction useIsXl(): boolean {\n const [isXl, setIsXl] = React.useState<boolean>(() => {\n if (typeof window === 'undefined') return false\n return window.matchMedia(`(min-width: ${XL_BREAKPOINT_PX}px)`).matches\n })\n\n React.useEffect(() => {\n const mq = window.matchMedia(`(min-width: ${XL_BREAKPOINT_PX}px)`)\n const handler = (e: MediaQueryListEvent) => setIsXl(e.matches)\n mq.addEventListener('change', handler)\n return () => mq.removeEventListener('change', handler)\n }, [])\n\n return isXl\n}\n\n// ── Width resolve(consumer 自傳 + clamp 240-640)──────────────────────────────\n\nconst ASIDE_WIDTH_MIN = 240\nconst ASIDE_WIDTH_MAX = 640\nconst ASIDE_WIDTH_DEFAULT = 320\n\nfunction resolveAsideWidth(width: AppShellAsideProps['width'], isXl: boolean): number {\n if (typeof width === 'number') {\n return Math.max(ASIDE_WIDTH_MIN, Math.min(ASIDE_WIDTH_MAX, width))\n }\n if (width && typeof width === 'object') {\n // breakpoint-keyed:xl viewport(≥1280px)用 xl,否則 md\n const v = (isXl ? width.xl ?? width.md : width.md) ?? ASIDE_WIDTH_DEFAULT\n return Math.max(ASIDE_WIDTH_MIN, Math.min(ASIDE_WIDTH_MAX, v))\n }\n return ASIDE_WIDTH_DEFAULT\n}\n\n// ── Skip-to-main link(a11y WCAG 2.4.1)───────────────────────────────────────\n\nfunction SkipToMain() {\n return (\n <a\n href=\"#app-shell-main\"\n className={cn(\n 'sr-only focus:not-sr-only',\n 'focus:fixed focus:top-2 focus:left-2 focus:z-50',\n 'focus:px-3 focus:py-2 focus:rounded-md',\n 'focus:bg-surface focus:text-foreground focus:shadow-[var(--elevation-200)]',\n 'focus:outline-none focus:ring-2 focus:ring-primary'\n )}\n >\n Skip to main content\n </a>\n )\n}\n\n// ── AppShell root ────────────────────────────────────────────────────────────\n\nconst AppShell = React.forwardRef<HTMLDivElement, AppShellProps>(\n (\n {\n layout = 'primary-sidebar',\n sidebar,\n header,\n globalHeader,\n aside,\n asideOpen: asideOpenProp,\n onAsideOpenChange,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const [asideOpenInternal, setAsideOpenInternal] = React.useState(false)\n const isControlled = asideOpenProp !== undefined\n const asideOpen = isControlled ? asideOpenProp : asideOpenInternal\n\n const setAsideOpen = React.useCallback(\n (open: boolean) => {\n if (!isControlled) setAsideOpenInternal(open)\n onAsideOpenChange?.(open)\n },\n [isControlled, onAsideOpenChange]\n )\n\n const isMobile = useIsNarrowViewport()\n\n // ── Keyboard: cmd+. toggle aside ──\n // ⌘B sidebar toggle by Sidebar SSOT(本 component 不重覆 register)\n React.useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === '.' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n setAsideOpen(!asideOpen)\n }\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [asideOpen, setAsideOpen])\n\n const ctxValue = React.useMemo<AppShellContextValue>(\n () => ({ layout, asideOpen, setAsideOpen, isMobile }),\n [layout, asideOpen, setAsideOpen, isMobile]\n )\n\n // ── Layout grid(2 mode)──\n // primary-sidebar:\n // row1: [sidebar (頂天)][main col (header + main)][aside (頂天)]\n // primary-header:\n // row1: [header (橫跨整 viewport, banner role)]\n // row2: [sidebar][main][aside]\n\n // AppShellAside 自決 inline vs modal mode(via AppShellContext.isMobile)。\n // AppShell 一律只 render `{aside}` 一次,AppShellAside 內部根據 isMobile 決定 render 形式。\n\n if (layout === 'primary-header') {\n // primary-header layout(2026-05-21 v2 — user clarification「primary-header = primary-sidebar + 一條 global header」):\n // 結構:row1 globalHeader(全寬 global bar)/ row2 [sidebar][main col: localHeader + main][aside]\n // - globalHeader = 跨頁 account / workspace switcher / notifications(對齊 GitHub top nav / Slack workspace bar)\n // - header = local page header,**仍存在**(per page actions / breadcrumb,對齊 GitHub repo header / Slack channel header / Gmail email-list toolbar 2-layer 慣例)\n // Consumer 必傳 `<Sidebar viewportInsetTop=\"var(--chrome-header-height)\">` 讓 sidebar 從 globalHeader 下方起算。\n return (\n <AppShellContext.Provider value={ctxValue}>\n <div\n ref={ref}\n className={cn('flex h-svh w-full flex-col overflow-hidden bg-canvas', className)}\n {...props}\n >\n <SkipToMain />\n {/* Row 1:Global header(account / workspace switcher / notifications,橫跨整 viewport)*/}\n {globalHeader && <div className=\"flex-shrink-0\">{globalHeader}</div>}\n {/* Row 2:[sidebar][main col][aside]horizontal row */}\n <div className=\"flex flex-1 min-h-0 w-full\">\n {sidebar}\n {/* Main column:local header + main content(per user model「primary-header = primary-sidebar + global header」)*/}\n <div className=\"flex flex-col flex-1 min-w-0 min-h-0 overflow-hidden\">\n {header && <div className=\"flex-shrink-0\">{header}</div>}\n <main\n id=\"app-shell-main\"\n tabIndex={-1}\n className=\"flex-1 min-w-0 min-h-0 overflow-y-auto focus:outline-none\"\n >\n {children}\n </main>\n </div>\n {aside}\n </div>\n </div>\n </AppShellContext.Provider>\n )\n }\n\n // primary-sidebar layout\n return (\n <AppShellContext.Provider value={ctxValue}>\n <div\n ref={ref}\n className={cn('flex h-svh w-full overflow-hidden bg-canvas', className)}\n {...props}\n >\n <SkipToMain />\n {/* Sidebar — 頂天 */}\n {sidebar}\n {/* Main column(header + main 垂直堆)*/}\n <div className=\"flex flex-col flex-1 min-w-0 min-h-0 overflow-hidden\">\n {header && (\n // Header 在 main column 內(main col sibling,非 main descendant)。ChromeHeader 自\n // 2026-05-20 起 render `<header>`(chrome-header.tsx);依 W3C HTML-AAM,`<div>` wrapper\n // 不 scope out banner(只有 main/article/aside/nav/section 能)→ 仍得 implicit banner ✓\n // (對齊 app-shell.spec.md「W3C ARIA in HTML banner rule」段)。\n <div className=\"flex-shrink-0\">{header}</div>\n )}\n <main\n id=\"app-shell-main\"\n tabIndex={-1}\n className=\"flex-1 min-h-0 overflow-y-auto focus:outline-none\"\n >\n {children}\n </main>\n </div>\n {/* Aside slot — desktop inline OR mobile Sheet,內部自決 */}\n {aside}\n </div>\n </AppShellContext.Provider>\n )\n }\n)\nAppShell.displayName = 'AppShell'\n\n// ── AppShellAside sub-component ──────────────────────────────────────────────\n\n/**\n * AppShellAside — right panel:standard inline(desktop) vs modal overlay(mobile)。\n *\n * Desktop(viewport ≥ 768px):\n * - Render 直接放 layout grid 右側(AppShell 恆 render {aside};AppShellAside 於 !asideOpen 自行 return null — 內部自決,非 via parent)\n * - 不蓋 mask / background 可操作 / 佔 layout 寬\n * - Vertical extent:primary-sidebar → 頂天立地 / primary-header → header 下方\n *\n * Mobile(viewport < 768px):\n * - Render 走 Sheet primitive(side=\"right\",per sheet.spec.md)\n * - Mask 蓋 / background 不可操作 / 不佔 layout 寬\n * - title 強制(aria-labelledby per sheet.spec.md:98)\n */\nconst AppShellAside = React.forwardRef<HTMLElement, AppShellAsideProps>(\n ({ title, width, children, className }, ref) => {\n const { asideOpen, setAsideOpen, isMobile } = useAppShell()\n const isXl = useIsXl()\n const resolvedWidth = resolveAsideWidth(width, isXl)\n\n // Shared frame:always-on header(title + close X)+ body(ScrollArea + layoutSpace 規則 1B 父層 padding)\n // 對齊 codex Layer B 2026-05-20「container mode 可變,panel role/content 不該變」+ Notion/Figma right\n // panel 共識(modal vs inline 結構相同,host wrapper 不同)。\n // 2026-05-20 migrate 消費 ChromeHeader primitive(撤回自刻 + 撤回 bg-surface 疊加 — 對齊\n // `header-canonical.spec.md`「6. Background ownership」段「Nested chrome header 透明繼承\n // parent」:aside container 自身已 bg-surface,內 header 不該再畫 bg 避免疊加 drift)。\n // titleNode 依 mode 不同:modal(Sheet)用 SheetTitle 綁 Radix Dialog titleId — 否則\n // SheetContent 的 aria-labelledby 指向不存在的 id → SR 念「unnamed dialog」+ Radix\n // TitleWarning console.error(違 sheet.spec.md:98「Sheet content 必有可見 title」)。\n // inline(aside)用純 <h2>:aside 自身已 aria-label={title},且無 Dialog context 不可用 SheetTitle。\n // R1:mobile Sheet 關閉後焦點還原目標(open 時 snapshot)\n const asideOpenerRef = React.useRef<HTMLElement | null>(null)\n\n const renderFrame = (titleNode: React.ReactNode) => (\n <>\n <ChromeHeader>\n {titleNode}\n <Button\n iconOnly\n dismiss\n size=\"sm\"\n startIcon={XIcon}\n aria-label=\"關閉\"\n onClick={() => setAsideOpen(false)}\n />\n </ChromeHeader>\n <ScrollArea className=\"flex-1 min-h-0\">\n {children}\n </ScrollArea>\n </>\n )\n\n // Modal mode(mobile)— Sheet from right\n // 2026-07-14 dim-9 修:同步轉交 forwarded ref + 合併 consumer className —— 原 mobile 分支\n // 兩者皆遺失,同一 API(ref / className)隨 breakpoint 靜默失效(desktop 有效、mobile 無效)。\n if (isMobile) {\n return (\n <Sheet open={asideOpen} onOpenChange={setAsideOpen}>\n <SheetContent\n ref={ref as React.Ref<HTMLDivElement>}\n side=\"right\"\n // R1 WCAG 2.4.3(2026-07-14,Claude+codex A′ 共識):controlled Sheet 無 SheetTrigger →\n // Radix onCloseAutoFocus triggerRef=null + preventDefault 吃掉 fallback → 焦點掉 <body>。\n // 解:開啟時 snapshot opener(事件 dispatch 時 Radix 尚未移焦;MUI/React Aria/Ant snapshot\n // 共識 + DatePicker Range 先例 date-picker.tsx:1061),關閉手動還原;opener 已 unmount →\n // fallback skip-link main(#app-shell-main tabIndex=-1)。\n onOpenAutoFocus={(e) => {\n asideOpenerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null\n handleSheetOpenAutoFocus(e) // 接力 DS 預設 body-focus(自訂 handler 覆寫預設,故顯式呼叫)\n }}\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n const opener = asideOpenerRef.current\n asideOpenerRef.current = null\n if (opener?.isConnected) { opener.focus({ preventScroll: true }); return }\n document.getElementById('app-shell-main')?.focus({ preventScroll: true })\n }}\n className={cn(\n 'w-[min(90vw,var(--app-shell-aside-modal-width))] flex flex-col p-0 [&>button]:hidden',\n className\n )}\n style={{ ['--app-shell-aside-modal-width' as string]: `${resolvedWidth}px` }}\n >\n {renderFrame(<SheetTitle className=\"flex-1\">{title}</SheetTitle>)}\n </SheetContent>\n </Sheet>\n )\n }\n\n // Standard inline mode(desktop)\n if (!asideOpen) return null\n\n return (\n <aside\n ref={ref}\n aria-label={title}\n className={cn(\n 'flex flex-col h-full min-h-0 overflow-hidden',\n 'bg-surface border-l border-divider',\n className\n )}\n style={{ width: resolvedWidth }}\n >\n {renderFrame(<h2 className=\"text-body-lg font-medium flex-1 truncate\">{title}</h2>)}\n </aside>\n )\n }\n)\nAppShellAside.displayName = 'AppShellAside'\n\n// ── Exports ──────────────────────────────────────────────────────────────────\n\n// code-quality-allow: dead-export useAppShell — public compound API hook(consumer 可自拼 custom aside layout,\n// 對齊 Radix `useDialogContext` / MUI `useFormControl` 慣例)。內部 AppShellAside 已消費(L294),\n// audit script 抓「無 cross-file import」是 false positive(2026-05-21 D2 codify)。\nexport { AppShell, AppShellAside, useAppShell }\n"],"names":["XIcon"],"mappings":"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"}
1
+ {"version":3,"file":"app-shell.js","sources":["../../../src/components/AppShell/app-shell.tsx"],"sourcesContent":["// @benchmark-cited: 2026-05-19 — Mantine AppShell / Ant Layout / Material 3 Drawer / Atlassian Navigation System cite in app-shell.spec.md frontmatter.\n/**\n * AppShell — web service page-level layout primitive。\n *\n * 組合 Sidebar + ChromeHeader + Aside + main 成完整 page shell。SSOT 邊界:本 composite component only\n * own slot composition + layout mode + Aside responsive mode;不 own sidebar / header /\n * sheet 視覺(各自 spec own)。\n *\n * 對齊 Mantine AppShell compound API + Ant Layout slot 模式 + Material 3 standard/modal\n * drawer canonical(per spec.md frontmatter cite)。\n *\n * Spec SSOT:`components/AppShell/app-shell.spec.md`\n */\n\nimport * as React from 'react'\nimport { X as XIcon } from 'lucide-react'\nimport {\n Sheet,\n SheetContent,\n SheetTitle,\n handleSheetOpenAutoFocus,\n} from '@/design-system/components/Sheet/sheet'\nimport { Button } from '@/design-system/components/Button/button'\nimport { ScrollArea } from '@/design-system/components/ScrollArea/scroll-area'\nimport { ChromeHeader } from '@/design-system/patterns/header-canonical/chrome-header'\nimport { useIsNarrowViewport } from '@/design-system/hooks/use-is-narrow-viewport'\nimport { cn } from '@/lib/utils'\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\ntype AppShellLayout = 'primary-sidebar' | 'primary-header'\n\nexport interface AppShellProps extends React.HTMLAttributes<HTMLDivElement> {\n /** primary-sidebar (Linear/Notion 派) | primary-header (GitHub/Slack 派);預設 primary-sidebar */\n layout?: AppShellLayout\n /** Sidebar 元素(應傳 Sidebar primitive,per Consumer 紀律;型別 optional 不機械強制,對齊 spec「應」措辭)*/\n sidebar?: React.ReactNode\n /**\n * Local page header(永遠 render 在 main column 頂部,當前頁 actions / breadcrumb / page-level filter)。\n * 兩 layout mode 都會 render 此 slot — `primary-header` mode 多了 globalHeader 在上方,\n * **不取代** local header(per 2026-05-20 user clarification「primary-header = primary-sidebar + 一條 global header」)。\n */\n header?: React.ReactNode\n /**\n * Global header(僅 `primary-header` mode render)。橫跨整 viewport 的頂部 bar:\n * account avatar / workspace switcher / global search / notifications。\n * 對齊 GitHub top nav / Slack workspace bar / Gmail logo bar 慣例。\n * `primary-sidebar` mode 傳此 prop 會被忽略。\n */\n globalHeader?: React.ReactNode\n /** Aside 元素(`<AppShellAside>` sub-component);可選 */\n aside?: React.ReactNode\n /** Aside open state(modal mode 必須)*/\n asideOpen?: boolean\n onAsideOpenChange?: (open: boolean) => void\n /** Main content;`<main>` landmark + padding=0 */\n children: React.ReactNode\n}\n\nexport interface AppShellAsideProps {\n /** Required:modal mode 走 Sheet → aria-labelledby 強制,per sheet.spec.md:98 */\n title: string\n /** Width(number 或 breakpoint-keyed object);clamp min:240 max:640 */\n width?: number | { md?: number; xl?: number }\n /** Children content */\n children: React.ReactNode\n className?: string\n}\n\n// ── Context ──────────────────────────────────────────────────────────────────\n\ninterface AppShellContextValue {\n layout: AppShellLayout\n asideOpen: boolean\n setAsideOpen: (open: boolean) => void\n isMobile: boolean\n}\n\nconst AppShellContext = React.createContext<AppShellContextValue | null>(null)\n\nfunction useAppShell(): AppShellContextValue {\n const ctx = React.useContext(AppShellContext)\n if (!ctx) throw new Error('AppShellAside must be used within <AppShell>')\n return ctx\n}\n\n// Mobile breakpoint:**消費既有 `useIsNarrowViewport`**(`hooks/use-is-narrow-viewport.ts` SSOT,\n// 768px,跟 Sidebar SSOT 同源)— 不發明 local hook,per codex Layer B D2/D4 verdict 避 drift。\n\n// xl breakpoint(對齊 Tailwind v4 xl = 1280px,DS-wide consensus)\nconst XL_BREAKPOINT_PX = 1280\n\nfunction useIsXl(): boolean {\n const [isXl, setIsXl] = React.useState<boolean>(() => {\n if (typeof window === 'undefined') return false\n return window.matchMedia(`(min-width: ${XL_BREAKPOINT_PX}px)`).matches\n })\n\n React.useEffect(() => {\n const mq = window.matchMedia(`(min-width: ${XL_BREAKPOINT_PX}px)`)\n const handler = (e: MediaQueryListEvent) => setIsXl(e.matches)\n mq.addEventListener('change', handler)\n return () => mq.removeEventListener('change', handler)\n }, [])\n\n return isXl\n}\n\n// ── Width resolve(consumer 自傳 + clamp 240-640)──────────────────────────────\n\nconst ASIDE_WIDTH_MIN = 240\nconst ASIDE_WIDTH_MAX = 640\nconst ASIDE_WIDTH_DEFAULT = 320\n\nfunction resolveAsideWidth(width: AppShellAsideProps['width'], isXl: boolean): number {\n if (typeof width === 'number') {\n return Math.max(ASIDE_WIDTH_MIN, Math.min(ASIDE_WIDTH_MAX, width))\n }\n if (width && typeof width === 'object') {\n // breakpoint-keyed:xl viewport(≥1280px)用 xl,否則 md\n const v = (isXl ? width.xl ?? width.md : width.md) ?? ASIDE_WIDTH_DEFAULT\n return Math.max(ASIDE_WIDTH_MIN, Math.min(ASIDE_WIDTH_MAX, v))\n }\n return ASIDE_WIDTH_DEFAULT\n}\n\n// ── Skip-to-main link(a11y WCAG 2.4.1)───────────────────────────────────────\n\nfunction SkipToMain() {\n return (\n <nav aria-label=\"Skip links\">\n <a\n href=\"#app-shell-main\"\n className={cn(\n 'sr-only focus:not-sr-only',\n 'focus:fixed focus:top-2 focus:left-2 focus:z-50',\n 'focus:px-3 focus:py-2 focus:rounded-md',\n 'focus:bg-surface focus:text-foreground focus:shadow-[var(--elevation-200)]',\n 'focus:outline-none focus:ring-2 focus:ring-primary'\n )}\n >\n Skip to main content\n </a>\n </nav>\n )\n}\n\n// ── AppShell root ────────────────────────────────────────────────────────────\n\nconst AppShell = React.forwardRef<HTMLDivElement, AppShellProps>(\n (\n {\n layout = 'primary-sidebar',\n sidebar,\n header,\n globalHeader,\n aside,\n asideOpen: asideOpenProp,\n onAsideOpenChange,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const [asideOpenInternal, setAsideOpenInternal] = React.useState(false)\n const isControlled = asideOpenProp !== undefined\n const asideOpen = isControlled ? asideOpenProp : asideOpenInternal\n\n const setAsideOpen = React.useCallback(\n (open: boolean) => {\n if (!isControlled) setAsideOpenInternal(open)\n onAsideOpenChange?.(open)\n },\n [isControlled, onAsideOpenChange]\n )\n\n const isMobile = useIsNarrowViewport()\n\n // ── Keyboard: cmd+. toggle aside ──\n // ⌘B sidebar toggle by Sidebar SSOT(本 component 不重覆 register)\n React.useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === '.' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n setAsideOpen(!asideOpen)\n }\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [asideOpen, setAsideOpen])\n\n const ctxValue = React.useMemo<AppShellContextValue>(\n () => ({ layout, asideOpen, setAsideOpen, isMobile }),\n [layout, asideOpen, setAsideOpen, isMobile]\n )\n\n // ── Layout grid(2 mode)──\n // primary-sidebar:\n // row1: [sidebar (頂天)][main col (header + main)][aside (頂天)]\n // primary-header:\n // row1: [header (橫跨整 viewport, banner role)]\n // row2: [sidebar][main][aside]\n\n // AppShellAside 自決 inline vs modal mode(via AppShellContext.isMobile)。\n // AppShell 一律只 render `{aside}` 一次,AppShellAside 內部根據 isMobile 決定 render 形式。\n\n if (layout === 'primary-header') {\n // primary-header layout(2026-05-21 v2 — user clarification「primary-header = primary-sidebar + 一條 global header」):\n // 結構:row1 globalHeader(全寬 global bar)/ row2 [sidebar][main col: localHeader + main][aside]\n // - globalHeader = 跨頁 account / workspace switcher / notifications(對齊 GitHub top nav / Slack workspace bar)\n // - header = local page header,**仍存在**(per page actions / breadcrumb,對齊 GitHub repo header / Slack channel header / Gmail email-list toolbar 2-layer 慣例)\n // Consumer 必傳 `<Sidebar viewportInsetTop=\"var(--chrome-header-height)\">` 讓 sidebar 從 globalHeader 下方起算。\n return (\n <AppShellContext.Provider value={ctxValue}>\n <div\n ref={ref}\n className={cn('flex h-svh w-full flex-col overflow-hidden bg-canvas', className)}\n {...props}\n >\n <SkipToMain />\n {/* Row 1:Global header(account / workspace switcher / notifications,橫跨整 viewport)*/}\n {globalHeader && <div className=\"flex-shrink-0\">{globalHeader}</div>}\n {/* Row 2:[sidebar][main col][aside]horizontal row */}\n <div className=\"flex flex-1 min-h-0 w-full\">\n {sidebar}\n {/* Main column:local header + main content(per user model「primary-header = primary-sidebar + global header」)*/}\n <div className=\"flex flex-col flex-1 min-w-0 min-h-0 overflow-hidden\">\n {header && <div className=\"flex-shrink-0\">{header}</div>}\n <main\n id=\"app-shell-main\"\n tabIndex={-1}\n className=\"flex-1 min-w-0 min-h-0 overflow-y-auto focus:outline-none\"\n >\n {children}\n </main>\n </div>\n {aside}\n </div>\n </div>\n </AppShellContext.Provider>\n )\n }\n\n // primary-sidebar layout\n return (\n <AppShellContext.Provider value={ctxValue}>\n <div\n ref={ref}\n className={cn('flex h-svh w-full overflow-hidden bg-canvas', className)}\n {...props}\n >\n <SkipToMain />\n {/* Sidebar — 頂天 */}\n {sidebar}\n {/* Main column(header + main 垂直堆)*/}\n <div className=\"flex flex-col flex-1 min-w-0 min-h-0 overflow-hidden\">\n {header && (\n // Header 在 main column 內(main col sibling,非 main descendant)。ChromeHeader 自\n // 2026-05-20 起 render `<header>`(chrome-header.tsx);依 W3C HTML-AAM,`<div>` wrapper\n // 不 scope out banner(只有 main/article/aside/nav/section 能)→ 仍得 implicit banner ✓\n // (對齊 app-shell.spec.md「W3C ARIA in HTML banner rule」段)。\n <div className=\"flex-shrink-0\">{header}</div>\n )}\n <main\n id=\"app-shell-main\"\n tabIndex={-1}\n className=\"flex-1 min-h-0 overflow-y-auto focus:outline-none\"\n >\n {children}\n </main>\n </div>\n {/* Aside slot — desktop inline OR mobile Sheet,內部自決 */}\n {aside}\n </div>\n </AppShellContext.Provider>\n )\n }\n)\nAppShell.displayName = 'AppShell'\n\n// ── AppShellAside sub-component ──────────────────────────────────────────────\n\n/**\n * AppShellAside — right panel:standard inline(desktop) vs modal overlay(mobile)。\n *\n * Desktop(viewport ≥ 768px):\n * - Render 直接放 layout grid 右側(AppShell 恆 render {aside};AppShellAside 於 !asideOpen 自行 return null — 內部自決,非 via parent)\n * - 不蓋 mask / background 可操作 / 佔 layout 寬\n * - Vertical extent:primary-sidebar → 頂天立地 / primary-header → header 下方\n *\n * Mobile(viewport < 768px):\n * - Render 走 Sheet primitive(side=\"right\",per sheet.spec.md)\n * - Mask 蓋 / background 不可操作 / 不佔 layout 寬\n * - title 強制(aria-labelledby per sheet.spec.md:98)\n */\nconst AppShellAside = React.forwardRef<HTMLElement, AppShellAsideProps>(\n ({ title, width, children, className }, ref) => {\n const { asideOpen, setAsideOpen, isMobile } = useAppShell()\n const isXl = useIsXl()\n const resolvedWidth = resolveAsideWidth(width, isXl)\n\n // Shared frame:always-on header(title + close X)+ body(ScrollArea + layoutSpace 規則 1B 父層 padding)\n // 對齊 codex Layer B 2026-05-20「container mode 可變,panel role/content 不該變」+ Notion/Figma right\n // panel 共識(modal vs inline 結構相同,host wrapper 不同)。\n // 2026-05-20 migrate 消費 ChromeHeader primitive(撤回自刻 + 撤回 bg-surface 疊加 — 對齊\n // `header-canonical.spec.md`「6. Background ownership」段「Nested chrome header 透明繼承\n // parent」:aside container 自身已 bg-surface,內 header 不該再畫 bg 避免疊加 drift)。\n // titleNode 依 mode 不同:modal(Sheet)用 SheetTitle 綁 Radix Dialog titleId — 否則\n // SheetContent 的 aria-labelledby 指向不存在的 id → SR 念「unnamed dialog」+ Radix\n // TitleWarning console.error(違 sheet.spec.md:98「Sheet content 必有可見 title」)。\n // inline(aside)用純 <h2>:aside 自身已 aria-label={title},且無 Dialog context 不可用 SheetTitle。\n // R1:mobile Sheet 關閉後焦點還原目標(open 時 snapshot)\n const asideOpenerRef = React.useRef<HTMLElement | null>(null)\n\n const renderFrame = (titleNode: React.ReactNode) => (\n <>\n <ChromeHeader>\n {titleNode}\n <Button\n iconOnly\n dismiss\n size=\"sm\"\n startIcon={XIcon}\n aria-label=\"關閉\"\n onClick={() => setAsideOpen(false)}\n />\n </ChromeHeader>\n <ScrollArea className=\"flex-1 min-h-0\">\n {children}\n </ScrollArea>\n </>\n )\n\n // Modal mode(mobile)— Sheet from right\n // 2026-07-14 dim-9 修:同步轉交 forwarded ref + 合併 consumer className —— 原 mobile 分支\n // 兩者皆遺失,同一 API(ref / className)隨 breakpoint 靜默失效(desktop 有效、mobile 無效)。\n if (isMobile) {\n return (\n <Sheet open={asideOpen} onOpenChange={setAsideOpen}>\n <SheetContent\n ref={ref as React.Ref<HTMLDivElement>}\n side=\"right\"\n // R1 WCAG 2.4.3(2026-07-14,Claude+codex A′ 共識):controlled Sheet 無 SheetTrigger →\n // Radix onCloseAutoFocus triggerRef=null + preventDefault 吃掉 fallback → 焦點掉 <body>。\n // 解:開啟時 snapshot opener(事件 dispatch 時 Radix 尚未移焦;MUI/React Aria/Ant snapshot\n // 共識 + DatePicker Range 先例 date-picker.tsx:1061),關閉手動還原;opener 已 unmount →\n // fallback skip-link main(#app-shell-main tabIndex=-1)。\n onOpenAutoFocus={(e) => {\n asideOpenerRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null\n handleSheetOpenAutoFocus(e) // 接力 DS 預設 body-focus(自訂 handler 覆寫預設,故顯式呼叫)\n }}\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n const opener = asideOpenerRef.current\n asideOpenerRef.current = null\n if (opener?.isConnected) { opener.focus({ preventScroll: true }); return }\n document.getElementById('app-shell-main')?.focus({ preventScroll: true })\n }}\n className={cn(\n 'w-[min(90vw,var(--app-shell-aside-modal-width))] flex flex-col p-0 [&>button]:hidden',\n className\n )}\n style={{ ['--app-shell-aside-modal-width' as string]: `${resolvedWidth}px` }}\n >\n {renderFrame(<SheetTitle className=\"flex-1\">{title}</SheetTitle>)}\n </SheetContent>\n </Sheet>\n )\n }\n\n // Standard inline mode(desktop)\n if (!asideOpen) return null\n\n return (\n <aside\n ref={ref}\n aria-label={title}\n className={cn(\n 'flex flex-col h-full min-h-0 overflow-hidden',\n 'bg-surface border-l border-divider',\n className\n )}\n style={{ width: resolvedWidth }}\n >\n {renderFrame(<h2 className=\"text-body-lg font-medium flex-1 truncate\">{title}</h2>)}\n </aside>\n )\n }\n)\nAppShellAside.displayName = 'AppShellAside'\n\n// ── Exports ──────────────────────────────────────────────────────────────────\n\n// code-quality-allow: dead-export useAppShell — public compound API hook(consumer 可自拼 custom aside layout,\n// 對齊 Radix `useDialogContext` / MUI `useFormControl` 慣例)。內部 AppShellAside 已消費(L294),\n// audit script 抓「無 cross-file import」是 false positive(2026-05-21 D2 codify)。\nexport { AppShell, AppShellAside, useAppShell }\n"],"names":["XIcon"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  declare const badgeVariants: (props?: ({
3
- variant?: "high" | "low" | "medium" | "critical" | null | undefined;
3
+ variant?: "high" | "low" | "critical" | "medium" | null | undefined;
4
4
  dot?: boolean | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  type BadgeBaseProps = Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'>;
@@ -49,9 +49,9 @@ import type { LucideIcon } from 'lucide-react';
49
49
  * <Button asChild><Link to="/home">回首頁</Link></Button>
50
50
  */
51
51
  declare const buttonVariants: (props?: ({
52
- variant?: "text" | "link" | "primary" | "secondary" | "tertiary" | null | undefined;
52
+ variant?: "text" | "link" | "secondary" | "primary" | "tertiary" | null | undefined;
53
53
  danger?: boolean | null | undefined;
54
- pressedTone?: "emphasis" | "neutral" | null | undefined;
54
+ pressedTone?: "neutral" | "emphasis" | null | undefined;
55
55
  size?: "sm" | "md" | "lg" | "xs" | null | undefined;
56
56
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
57
57
  interface ButtonGroupContextValue {
@@ -120,7 +120,7 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
120
120
  * 自動套用:
121
121
  * - `variant="text"`(強制 override 其他 variant)
122
122
  * - `iconOnly=true`(強制)
123
- * - Icon 色 override:`fg-muted` → hover `foreground`(跟 Inline Action dismiss 視覺一致)
123
+ * - Icon 色 override:`fg-muted` → hover `fg-secondary`(跟 Inline Action dismiss 視覺一致)
124
124
  *
125
125
  * 典型 case:Dialog / Sheet / Popover / Alert / Toast / Coachmark 的 **chrome corner close X**
126
126
  * (action group region — corner 可多 action,close 左側加 Separator + refresh / share 等)。
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAK9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,QAAA,MAAM,cAAc;;;;;8EAoKnB,CAAA;AAKD,UAAU,uBAAuB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AACD,yIAAyI;AACzI,QAAA,MAAM,kBAAkB,wCAAmD,CAAA;AAI3E,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EACnD,IAAI,CAAC,YAAY,CAAC,OAAO,cAAc,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjE;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;IAChE,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;IACpC,sDAAsD;IACtD,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,oCAAoC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAcD,QAAA,MAAM,MAAM,uFAwNX,CAAA;AAGD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bb,CAAA;AAEV,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAK9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,QAAA,MAAM,cAAc;;;;;8EAoKnB,CAAA;AAKD,UAAU,uBAAuB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AACD,yIAAyI;AACzI,QAAA,MAAM,kBAAkB,wCAAmD,CAAA;AAI3E,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EACnD,IAAI,CAAC,YAAY,CAAC,OAAO,cAAc,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjE;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;IAChE,kFAAkF;IAClF,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;IACpC,sDAAsD;IACtD,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,oCAAoC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAcD,QAAA,MAAM,MAAM,uFAyNX,CAAA;AAGD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bb,CAAA;AAEV,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAA"}
@@ -255,9 +255,10 @@ const Button = React.forwardRef(
255
255
  // iconOnly 鐵律:padding-free + aspect-square + flex-center (Polaris idiom)
256
256
  // 0 magic-number 0 公式自動正方形。詳 ICON_ONLY_BASE rationale。
257
257
  resolvedIconOnly && ICON_ONLY_BASE,
258
- // Dismiss 視覺弱化:override Button text variant 預設 foreground 為 fg-muted → hover foreground
258
+ // Dismiss 視覺弱化:override Button text variant 預設 foreground 為 fg-muted → hover fg-secondary
259
259
  // 跟 Inline Action dismiss 視覺一致(cross-implementation dimming canonical)
260
- dismiss && "text-fg-muted hover:text-foreground",
260
+ // 弱化 icon hover 一階(item-anatomy.tsx ItemInlineActionButton 同階梯 SSOT)
261
+ dismiss && "text-fg-muted hover:text-fg-secondary",
261
262
  resolvedFullWidth && "w-full"
262
263
  );
263
264
  const { onClick: slotConsumerOnClick, ...slotRest } = restProps;