@ds-mo/ui 12.9.0 → 13.0.0

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 (430) hide show
  1. package/README.md +1 -0
  2. package/dist/.package-ready.json +1 -0
  3. package/dist/agent-patterns.json +124 -135
  4. package/dist/agent.json +249 -1108
  5. package/dist/angular/ds-bar-nav.d.ts +1 -1
  6. package/dist/angular/ds-bar-nav.js +3 -3
  7. package/dist/angular/ds-button-filled.d.ts +1 -1
  8. package/dist/angular/ds-button-filled.js +3 -3
  9. package/dist/angular/ds-card-data-viz.d.ts +18 -0
  10. package/dist/angular/{ds-card-data-viz-donut.js → ds-card-data-viz.js} +12 -12
  11. package/dist/angular/ds-card-overview.d.ts +1 -1
  12. package/dist/angular/ds-card-overview.js +3 -3
  13. package/dist/angular/ds-chart-bar.d.ts +1 -1
  14. package/dist/angular/ds-chart-bar.js +3 -3
  15. package/dist/angular/ds-menu.d.ts +1 -7
  16. package/dist/angular/ds-menu.js +2 -5
  17. package/dist/angular/ds-mobile-header.d.ts +1 -1
  18. package/dist/angular/ds-mobile-header.js +3 -3
  19. package/dist/angular/ds-mobile-section-switcher.d.ts +1 -1
  20. package/dist/angular/ds-mobile-section-switcher.js +3 -3
  21. package/dist/angular/ds-panel-tools.d.ts +1 -1
  22. package/dist/angular/ds-panel-tools.js +3 -3
  23. package/dist/angular/ds-select.d.ts +5 -4
  24. package/dist/angular/ds-select.js +3 -3
  25. package/dist/angular/ds-shell-app.d.ts +90 -1
  26. package/dist/angular/ds-shell-app.js +44 -4
  27. package/dist/angular/ds-shell-tools.d.ts +1 -1
  28. package/dist/angular/ds-shell-tools.js +3 -3
  29. package/dist/angular/index.d.ts +1 -1
  30. package/dist/angular/index.js +1 -8
  31. package/dist/angular/proxies.d.ts +1 -8
  32. package/dist/angular/proxies.js +1 -8
  33. package/dist/components/ds-agent-activity.js +1 -1
  34. package/dist/components/ds-agent-response.js +1 -1
  35. package/dist/components/ds-agent-source-list.js +1 -1
  36. package/dist/components/ds-agent-tool-call.js +1 -1
  37. package/dist/components/ds-attachment-list.js +1 -1
  38. package/dist/components/ds-badge.js +1 -1
  39. package/dist/components/ds-bar-nav.js +1 -1
  40. package/dist/components/ds-bar-nav.js.map +1 -1
  41. package/dist/components/ds-bar-title.js +1 -1
  42. package/dist/components/ds-bar-title.js.map +1 -1
  43. package/dist/components/ds-bar-workflow.js +1 -1
  44. package/dist/components/ds-breadcrumb.js +1 -1
  45. package/dist/components/ds-button-filled.js +1 -1
  46. package/dist/components/ds-button-unfilled.js +1 -1
  47. package/dist/components/{ds-select-multi.d.ts → ds-card-data-viz.d.ts} +4 -4
  48. package/dist/components/ds-card-data-viz.js +2 -0
  49. package/dist/components/ds-card-data-viz.js.map +1 -0
  50. package/dist/components/ds-card-overview.js +1 -1
  51. package/dist/components/ds-card-overview.js.map +1 -1
  52. package/dist/components/ds-card-setting.js +1 -1
  53. package/dist/components/ds-chart-bar.js +1 -1
  54. package/dist/components/ds-chart-bar.js.map +1 -1
  55. package/dist/components/ds-chart-donut.js +1 -1
  56. package/dist/components/ds-chart-legend.js +1 -1
  57. package/dist/components/ds-chart-legend.js.map +1 -1
  58. package/dist/components/ds-chart-line.js +1 -1
  59. package/dist/components/ds-chart-line.js.map +1 -1
  60. package/dist/components/ds-checkbox.js +1 -1
  61. package/dist/components/ds-chip.js +1 -1
  62. package/dist/components/ds-code-block.js +1 -1
  63. package/dist/components/ds-conversation-list-item.js +1 -1
  64. package/dist/components/ds-conversation-list-item.js.map +1 -1
  65. package/dist/components/ds-conversation-list-section.js +1 -1
  66. package/dist/components/ds-conversation-list.js +1 -1
  67. package/dist/components/ds-divider.js +1 -1
  68. package/dist/components/ds-empty-state.js +1 -1
  69. package/dist/components/ds-field.js +1 -1
  70. package/dist/components/ds-input.js +1 -1
  71. package/dist/components/ds-input.js.map +1 -1
  72. package/dist/components/ds-markdown.js +1 -1
  73. package/dist/components/ds-menu.js +1 -1
  74. package/dist/components/ds-message-bubble.js +1 -1
  75. package/dist/components/ds-message-composer.js +1 -1
  76. package/dist/components/ds-message-composer.js.map +1 -1
  77. package/dist/components/ds-message-scroller.js +1 -1
  78. package/dist/components/ds-message.js +1 -1
  79. package/dist/components/ds-mobile-bar-nav.js +1 -1
  80. package/dist/components/ds-mobile-bar-nav.js.map +1 -1
  81. package/dist/components/ds-mobile-header.js +1 -1
  82. package/dist/components/ds-mobile-section-switcher.js +1 -1
  83. package/dist/components/ds-mobile-sheet-nav.js +1 -1
  84. package/dist/components/ds-mobile-sheet-nav.js.map +1 -1
  85. package/dist/components/ds-modal.js +1 -1
  86. package/dist/components/ds-panel-nav.js +1 -1
  87. package/dist/components/ds-panel-nav.js.map +1 -1
  88. package/dist/components/ds-panel-sub-nav.js +1 -1
  89. package/dist/components/ds-panel-tool-header.js +1 -1
  90. package/dist/components/ds-panel-tool-search.js +1 -1
  91. package/dist/components/ds-panel-tools.js +1 -1
  92. package/dist/components/ds-radio.js +1 -1
  93. package/dist/components/ds-radio.js.map +1 -1
  94. package/dist/components/ds-scroll-overlay.js +1 -1
  95. package/dist/components/ds-select.js +1 -1
  96. package/dist/components/ds-select.js.map +1 -1
  97. package/dist/components/ds-shell-app.js +1 -1
  98. package/dist/components/ds-shell-app.js.map +1 -1
  99. package/dist/components/ds-shell-page.js +1 -1
  100. package/dist/components/ds-shell-page.js.map +1 -1
  101. package/dist/components/ds-shell-tools.js +1 -1
  102. package/dist/components/ds-shell-tools.js.map +1 -1
  103. package/dist/components/ds-skeleton.js +1 -1
  104. package/dist/components/ds-slider.js +1 -1
  105. package/dist/components/ds-slider.js.map +1 -1
  106. package/dist/components/ds-swatch-picker.js +1 -1
  107. package/dist/components/ds-switch.js +1 -1
  108. package/dist/components/ds-tab-group.js +1 -1
  109. package/dist/components/ds-tag.js +1 -1
  110. package/dist/components/ds-text.js +1 -1
  111. package/dist/components/ds-toast.js +1 -1
  112. package/dist/components/ds-tooltip-data-viz.js +1 -1
  113. package/dist/components/ds-tooltip.js +1 -1
  114. package/dist/components/ds-typing-indicator.js +1 -1
  115. package/dist/components/{p-CgEYdMee.js → p-6qXDqCj_.js} +2 -2
  116. package/dist/components/{p-Cr3tEx7o.js → p-Ay1AX7Ql.js} +2 -2
  117. package/dist/components/p-B-qDb_Zo.js +2 -0
  118. package/dist/components/p-B-qDb_Zo.js.map +1 -0
  119. package/dist/components/{p-BOCfICln.js → p-B1cbQ0SG.js} +2 -2
  120. package/dist/components/{p-BKOlvCGS.js → p-BUZXuod2.js} +2 -2
  121. package/dist/components/{p-DCvA3Dc9.js → p-BaUsq_VK.js} +2 -2
  122. package/dist/components/p-BbMJTilO.js +2 -0
  123. package/dist/components/p-BbMJTilO.js.map +1 -0
  124. package/dist/components/{p-BO5aqZcf.js → p-BcTYhmku.js} +2 -2
  125. package/dist/components/p-Bkv3UjZz.js +2 -0
  126. package/dist/components/p-Bkv3UjZz.js.map +1 -0
  127. package/dist/components/p-BnQXAbif.js +2 -0
  128. package/dist/components/p-BnQXAbif.js.map +1 -0
  129. package/dist/components/p-BnbbnuVC.js +2 -0
  130. package/dist/components/p-BnbbnuVC.js.map +1 -0
  131. package/dist/components/{p-BDKtu6Wb.js → p-BroVnDzE.js} +2 -2
  132. package/dist/components/{p-CIiBpjCn.js → p-BsoqsbBh.js} +2 -2
  133. package/dist/components/p-BwT6B5Fi.js +2 -0
  134. package/dist/components/p-BwT6B5Fi.js.map +1 -0
  135. package/dist/components/p-BybqPD8K.js +2 -0
  136. package/dist/components/p-BybqPD8K.js.map +1 -0
  137. package/dist/components/p-C-vRkDyn.js +2 -0
  138. package/dist/components/p-C-vRkDyn.js.map +1 -0
  139. package/dist/components/p-C3ArcO50.js +2 -0
  140. package/dist/components/p-C3ArcO50.js.map +1 -0
  141. package/dist/components/p-C4uYvyq6.js +2 -0
  142. package/dist/components/p-C4uYvyq6.js.map +1 -0
  143. package/dist/components/{p-C8HU4W8q.js → p-CBazaRlE.js} +2 -2
  144. package/dist/components/{p-BhV5e6vF.js → p-CHuh71-U.js} +2 -2
  145. package/dist/components/{p-CChcuL04.js → p-CMWata9g.js} +2 -2
  146. package/dist/components/p-CS6CHlHK.js +2 -0
  147. package/dist/components/p-CS6CHlHK.js.map +1 -0
  148. package/dist/components/p-CTTnM7cE.js +2 -0
  149. package/dist/components/p-CTTnM7cE.js.map +1 -0
  150. package/dist/components/{p-CCzG5xDD.js → p-CWoXKe_h.js} +2 -2
  151. package/dist/components/p-CWoXKe_h.js.map +1 -0
  152. package/dist/components/p-CwwuSGER.js +2 -0
  153. package/dist/components/p-CwwuSGER.js.map +1 -0
  154. package/dist/components/p-D09HINr_.js +2 -0
  155. package/dist/components/p-D09HINr_.js.map +1 -0
  156. package/dist/components/p-D2xWcVv6.js +2 -0
  157. package/dist/components/p-D2xWcVv6.js.map +1 -0
  158. package/dist/components/p-DAW6G8Sl.js +2 -0
  159. package/dist/components/p-DAW6G8Sl.js.map +1 -0
  160. package/dist/components/p-DEaszb15.js +2 -0
  161. package/dist/components/p-DEaszb15.js.map +1 -0
  162. package/dist/components/{p-BgGP65Nn.js → p-DOUk4KoT.js} +1 -1
  163. package/dist/components/p-DOUk4KoT.js.map +1 -0
  164. package/dist/components/p-DbQr7Kwr.js +2 -0
  165. package/dist/components/p-DbQr7Kwr.js.map +1 -0
  166. package/dist/components/p-DdvEZyX4.js +2 -0
  167. package/dist/components/p-DdvEZyX4.js.map +1 -0
  168. package/dist/components/{p-DRnIuCiT.js → p-DeQwkbT1.js} +2 -2
  169. package/dist/components/{p-Cuih680v.js → p-Df17mJqI.js} +2 -2
  170. package/dist/components/p-Dg1LBXJ2.js +2 -0
  171. package/dist/components/p-Dg1LBXJ2.js.map +1 -0
  172. package/dist/components/p-DsiCDzoF.js +2 -0
  173. package/dist/components/p-DsiCDzoF.js.map +1 -0
  174. package/dist/components/p-_DzUXA86.js +2 -0
  175. package/dist/components/p-_DzUXA86.js.map +1 -0
  176. package/dist/components/p-lyZNvRvO.js +2 -0
  177. package/dist/components/p-lyZNvRvO.js.map +1 -0
  178. package/dist/components/{p-YR1XeuZf.js → p-ohsLFap_.js} +2 -2
  179. package/dist/components/{p-DjbTFy2B.js → p-ymtdhOU5.js} +1 -1
  180. package/dist/components/p-ymtdhOU5.js.map +1 -0
  181. package/dist/components/p-z5RIrXuX.js +2 -0
  182. package/dist/components/p-z5RIrXuX.js.map +1 -0
  183. package/dist/docs/components.json +929 -2371
  184. package/dist/framework/angular.d.ts +0 -1
  185. package/dist/framework/angular.js +0 -1
  186. package/dist/lib/components/BarTitle/bar-title-types.d.ts +28 -0
  187. package/dist/lib/components/Breadcrumb/breadcrumb-types.d.ts +16 -0
  188. package/dist/lib/components/ButtonFilled/ButtonFilled.d.ts +83 -0
  189. package/dist/lib/components/MobileHeader/mobile-header-types.d.ts +4 -0
  190. package/dist/lib/components/PanelTools/panel-tools-types.d.ts +21 -7
  191. package/dist/lib/components/ShellApp/shell-app-types.d.ts +91 -0
  192. package/dist/lib/shell/index.d.ts +5 -13
  193. package/dist/lib/shell/index.js +87 -358
  194. package/dist/lib/shell/index.js.map +3 -3
  195. package/dist/lib/shell/shell-responsive.d.ts +2 -1
  196. package/dist/lib/utils/button-render.d.ts +17 -0
  197. package/dist/lib/utils/button-types.d.ts +10 -0
  198. package/dist/lib/utils/choice-list.d.ts +25 -0
  199. package/dist/lib/utils/control-press.d.ts +8 -0
  200. package/dist/lib/utils/form-association.d.ts +22 -0
  201. package/dist/lib/utils/index.d.ts +4 -0
  202. package/dist/lib/utils/index.js +63 -0
  203. package/dist/lib/utils/index.js.map +3 -3
  204. package/dist/lib/utils/required-validity.d.ts +1 -1
  205. package/dist/lib/utils/safe-url.d.ts +11 -0
  206. package/dist/mcp/cli.js +38 -10
  207. package/dist/mcp-data/registry/agent-source-list.json +1 -1
  208. package/dist/mcp-data/registry/attachment-list.json +1 -1
  209. package/dist/mcp-data/registry/bar-nav.json +3 -21
  210. package/dist/mcp-data/registry/breadcrumb.json +1 -1
  211. package/dist/mcp-data/registry/button-filled.json +4 -19
  212. package/dist/mcp-data/registry/button-unfilled.json +14 -11
  213. package/dist/mcp-data/registry/card-data-viz.json +241 -0
  214. package/dist/mcp-data/registry/card-overview.json +38 -10
  215. package/dist/mcp-data/registry/card-setting.json +2 -2
  216. package/dist/mcp-data/registry/chart-bar.json +66 -18
  217. package/dist/mcp-data/registry/chart-donut.json +5 -5
  218. package/dist/mcp-data/registry/chart-legend.json +7 -9
  219. package/dist/mcp-data/registry/chart-line.json +1 -2
  220. package/dist/mcp-data/registry/checkbox.json +2 -2
  221. package/dist/mcp-data/registry/conversation-list-item.json +1 -1
  222. package/dist/mcp-data/registry/field.json +2 -3
  223. package/dist/mcp-data/registry/input.json +1 -1
  224. package/dist/mcp-data/registry/markdown.json +1 -1
  225. package/dist/mcp-data/registry/menu.json +10 -21
  226. package/dist/mcp-data/registry/mobile-bar-nav.json +1 -1
  227. package/dist/mcp-data/registry/mobile-header.json +1 -37
  228. package/dist/mcp-data/registry/mobile-section-switcher.json +1 -19
  229. package/dist/mcp-data/registry/panel-nav.json +2 -2
  230. package/dist/mcp-data/registry/panel-tool-search.json +1 -1
  231. package/dist/mcp-data/registry/panel-tools.json +19 -55
  232. package/dist/mcp-data/registry/radio.json +1 -1
  233. package/dist/mcp-data/registry/registry.json +294 -1174
  234. package/dist/mcp-data/registry/select.json +59 -25
  235. package/dist/mcp-data/registry/shell-app.json +345 -20
  236. package/dist/mcp-data/registry/shell-page.json +1 -1
  237. package/dist/mcp-data/registry/shell-tools.json +12 -43
  238. package/dist/mcp-data/registry/slider.json +1 -1
  239. package/dist/mcp-data/registry/switch.json +1 -1
  240. package/dist/react/components.d.ts +1 -8
  241. package/dist/react/components.js +1 -8
  242. package/dist/react/ds-card-data-viz.d.ts +12 -0
  243. package/dist/react/ds-card-data-viz.js +12 -0
  244. package/dist/react/ds-menu.d.ts +1 -2
  245. package/dist/react/ds-menu.js +0 -1
  246. package/dist/react/ds-select.d.ts +2 -2
  247. package/dist/react/ds-shell-app.d.ts +24 -1
  248. package/dist/react/ds-shell-app.js +16 -1
  249. package/dist/types/components/AgentSourceList/AgentSourceList.d.ts +0 -1
  250. package/dist/types/components/BarNav/BarNav.d.ts +0 -2
  251. package/dist/types/components/BarNav/bar-nav-utils.d.ts +2 -4
  252. package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +5 -11
  253. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +13 -10
  254. package/dist/types/components/CardDataViz/CardDataViz.d.ts +32 -0
  255. package/dist/types/components/CardDataViz/index.d.ts +2 -0
  256. package/dist/types/components/CardOverview/CardOverview.d.ts +17 -0
  257. package/dist/types/components/CardOverview/card-overview-controller.d.ts +16 -0
  258. package/dist/types/components/ChartBar/ChartBar.d.ts +12 -1
  259. package/dist/types/components/ChartBar/index.d.ts +2 -1
  260. package/dist/types/components/Menu/Menu.d.ts +0 -4
  261. package/dist/types/components/Menu/menu-sections.d.ts +4 -0
  262. package/dist/types/components/Menu/menu-types.d.ts +2 -11
  263. package/dist/types/components/MobileHeader/MobileHeader.d.ts +0 -5
  264. package/dist/types/components/MobileSectionSwitcher/MobileSectionSwitcher.d.ts +0 -2
  265. package/dist/types/components/PanelTools/PanelTools.d.ts +0 -4
  266. package/dist/types/components/PanelTools/index.d.ts +1 -1
  267. package/dist/types/components/PanelTools/panel-tools-types.d.ts +21 -7
  268. package/dist/types/components/PanelTools/panel-tools-utils.d.ts +1 -1
  269. package/dist/types/components/Select/Select.d.ts +12 -4
  270. package/dist/types/components/Select/index.d.ts +1 -1
  271. package/dist/types/components/ShellApp/ShellApp.d.ts +98 -0
  272. package/dist/types/components/ShellApp/shell-app-types.d.ts +92 -0
  273. package/dist/types/components/ShellPage/ShellPage.d.ts +5 -0
  274. package/dist/types/components/ShellTools/ShellTools.d.ts +2 -2
  275. package/dist/types/components.d.ts +210 -889
  276. package/dist/types/shell/index.d.ts +5 -13
  277. package/dist/types/shell/shell-responsive.d.ts +2 -1
  278. package/dist/types/utils/button-render.d.ts +18 -0
  279. package/dist/types/utils/button-story-foundation.d.ts +9 -0
  280. package/dist/types/utils/button-types.d.ts +11 -0
  281. package/dist/types/utils/form-association.d.ts +23 -0
  282. package/dist/types/utils/index.d.ts +4 -0
  283. package/dist/types/utils/required-validity.d.ts +1 -1
  284. package/dist/types/utils/safe-url.d.ts +12 -0
  285. package/dist/types/utils/select-controller.d.ts +1 -1
  286. package/package.json +16 -8
  287. package/dist/.build-stamp +0 -1
  288. package/dist/angular/ds-card-data-viz-bar.d.ts +0 -18
  289. package/dist/angular/ds-card-data-viz-bar.js +0 -42
  290. package/dist/angular/ds-card-data-viz-donut.d.ts +0 -18
  291. package/dist/angular/ds-card-data-viz-line.d.ts +0 -18
  292. package/dist/angular/ds-card-data-viz-line.js +0 -42
  293. package/dist/angular/ds-card-shell-data-viz.d.ts +0 -12
  294. package/dist/angular/ds-card-shell-data-viz.js +0 -38
  295. package/dist/angular/ds-chart-bar-stacked.d.ts +0 -12
  296. package/dist/angular/ds-chart-bar-stacked.js +0 -38
  297. package/dist/angular/ds-select-multi.d.ts +0 -28
  298. package/dist/angular/ds-select-multi.js +0 -49
  299. package/dist/angular/ds-shell-gradient-picker.d.ts +0 -16
  300. package/dist/angular/ds-shell-gradient-picker.js +0 -42
  301. package/dist/angular/ds-shell-gradient-swatch.d.ts +0 -16
  302. package/dist/angular/ds-shell-gradient-swatch.js +0 -42
  303. package/dist/components/ds-card-data-viz-bar.d.ts +0 -11
  304. package/dist/components/ds-card-data-viz-bar.js +0 -2
  305. package/dist/components/ds-card-data-viz-bar.js.map +0 -1
  306. package/dist/components/ds-card-data-viz-donut.d.ts +0 -11
  307. package/dist/components/ds-card-data-viz-donut.js +0 -2
  308. package/dist/components/ds-card-data-viz-donut.js.map +0 -1
  309. package/dist/components/ds-card-data-viz-line.d.ts +0 -11
  310. package/dist/components/ds-card-data-viz-line.js +0 -2
  311. package/dist/components/ds-card-data-viz-line.js.map +0 -1
  312. package/dist/components/ds-card-shell-data-viz.d.ts +0 -11
  313. package/dist/components/ds-card-shell-data-viz.js +0 -2
  314. package/dist/components/ds-card-shell-data-viz.js.map +0 -1
  315. package/dist/components/ds-chart-bar-stacked.d.ts +0 -11
  316. package/dist/components/ds-chart-bar-stacked.js +0 -2
  317. package/dist/components/ds-chart-bar-stacked.js.map +0 -1
  318. package/dist/components/ds-select-multi.js +0 -2
  319. package/dist/components/ds-select-multi.js.map +0 -1
  320. package/dist/components/ds-shell-gradient-picker.d.ts +0 -11
  321. package/dist/components/ds-shell-gradient-picker.js +0 -2
  322. package/dist/components/ds-shell-gradient-picker.js.map +0 -1
  323. package/dist/components/ds-shell-gradient-swatch.d.ts +0 -11
  324. package/dist/components/ds-shell-gradient-swatch.js +0 -2
  325. package/dist/components/ds-shell-gradient-swatch.js.map +0 -1
  326. package/dist/components/p-2foAUsDN.js +0 -2
  327. package/dist/components/p-2foAUsDN.js.map +0 -1
  328. package/dist/components/p-8GK7B7K4.js +0 -2
  329. package/dist/components/p-8GK7B7K4.js.map +0 -1
  330. package/dist/components/p-B5tMlca-.js +0 -2
  331. package/dist/components/p-B5tMlca-.js.map +0 -1
  332. package/dist/components/p-B88n0pO3.js +0 -2
  333. package/dist/components/p-B88n0pO3.js.map +0 -1
  334. package/dist/components/p-BBePKRHC.js +0 -2
  335. package/dist/components/p-BBePKRHC.js.map +0 -1
  336. package/dist/components/p-BOQnc-M4.js +0 -2
  337. package/dist/components/p-BOQnc-M4.js.map +0 -1
  338. package/dist/components/p-BgGP65Nn.js.map +0 -1
  339. package/dist/components/p-BrusnEYP.js +0 -2
  340. package/dist/components/p-BrusnEYP.js.map +0 -1
  341. package/dist/components/p-C61yJkfr.js +0 -2
  342. package/dist/components/p-C61yJkfr.js.map +0 -1
  343. package/dist/components/p-CCzG5xDD.js.map +0 -1
  344. package/dist/components/p-CGVXbXv9.js +0 -2
  345. package/dist/components/p-CGVXbXv9.js.map +0 -1
  346. package/dist/components/p-CH3w-P2H.js +0 -2
  347. package/dist/components/p-CH3w-P2H.js.map +0 -1
  348. package/dist/components/p-Cuqxh-Tq.js +0 -2
  349. package/dist/components/p-Cuqxh-Tq.js.map +0 -1
  350. package/dist/components/p-D1HFMTdC.js +0 -2
  351. package/dist/components/p-D1HFMTdC.js.map +0 -1
  352. package/dist/components/p-D2x17ei-.js +0 -2
  353. package/dist/components/p-D2x17ei-.js.map +0 -1
  354. package/dist/components/p-DLZm_-sU.js +0 -2
  355. package/dist/components/p-DLZm_-sU.js.map +0 -1
  356. package/dist/components/p-DjKkSqrG.js +0 -2
  357. package/dist/components/p-DjKkSqrG.js.map +0 -1
  358. package/dist/components/p-DjbTFy2B.js.map +0 -1
  359. package/dist/components/p-DlscFn2m.js +0 -2
  360. package/dist/components/p-DlscFn2m.js.map +0 -1
  361. package/dist/components/p-DxkEC0hR.js +0 -2
  362. package/dist/components/p-DxkEC0hR.js.map +0 -1
  363. package/dist/components/p-Re2kPrXm.js +0 -2
  364. package/dist/components/p-Re2kPrXm.js.map +0 -1
  365. package/dist/components/p-XMZCaXs7.js +0 -2
  366. package/dist/components/p-XMZCaXs7.js.map +0 -1
  367. package/dist/components/p-dyUp3Adm.js +0 -2
  368. package/dist/components/p-dyUp3Adm.js.map +0 -1
  369. package/dist/components/p-nkYN0Bub.js +0 -2
  370. package/dist/components/p-nkYN0Bub.js.map +0 -1
  371. package/dist/framework/select-multi-value-accessor.d.ts +0 -9
  372. package/dist/framework/select-multi-value-accessor.js +0 -40
  373. package/dist/lib/shell/badge-gradient-ring.d.ts +0 -27
  374. package/dist/lib/shell/chrome-transition.d.ts +0 -32
  375. package/dist/lib/shell/shell-chrome-metrics.d.ts +0 -11
  376. package/dist/lib/shell/shell-gradient.d.ts +0 -41
  377. package/dist/lib/shell/shell-view-transition.d.ts +0 -23
  378. package/dist/mcp-data/registry/card-data-viz-bar.json +0 -213
  379. package/dist/mcp-data/registry/card-data-viz-donut.json +0 -214
  380. package/dist/mcp-data/registry/card-data-viz-line.json +0 -207
  381. package/dist/mcp-data/registry/card-shell-data-viz.json +0 -180
  382. package/dist/mcp-data/registry/chart-bar-stacked.json +0 -230
  383. package/dist/mcp-data/registry/select-multi.json +0 -758
  384. package/dist/mcp-data/registry/shell-gradient-picker.json +0 -195
  385. package/dist/mcp-data/registry/shell-gradient-swatch.json +0 -215
  386. package/dist/react/ds-card-data-viz-bar.d.ts +0 -12
  387. package/dist/react/ds-card-data-viz-bar.js +0 -12
  388. package/dist/react/ds-card-data-viz-donut.d.ts +0 -12
  389. package/dist/react/ds-card-data-viz-donut.js +0 -12
  390. package/dist/react/ds-card-data-viz-line.d.ts +0 -12
  391. package/dist/react/ds-card-data-viz-line.js +0 -12
  392. package/dist/react/ds-card-shell-data-viz.d.ts +0 -9
  393. package/dist/react/ds-card-shell-data-viz.js +0 -12
  394. package/dist/react/ds-chart-bar-stacked.d.ts +0 -9
  395. package/dist/react/ds-chart-bar-stacked.js +0 -12
  396. package/dist/react/ds-select-multi.d.ts +0 -14
  397. package/dist/react/ds-select-multi.js +0 -16
  398. package/dist/react/ds-shell-gradient-picker.d.ts +0 -12
  399. package/dist/react/ds-shell-gradient-picker.js +0 -12
  400. package/dist/react/ds-shell-gradient-swatch.d.ts +0 -12
  401. package/dist/react/ds-shell-gradient-swatch.js +0 -12
  402. package/dist/types/components/CardDataVizBar/CardDataVizBar.d.ts +0 -24
  403. package/dist/types/components/CardDataVizBar/index.d.ts +0 -2
  404. package/dist/types/components/CardDataVizDonut/CardDataVizDonut.d.ts +0 -28
  405. package/dist/types/components/CardDataVizDonut/index.d.ts +0 -2
  406. package/dist/types/components/CardDataVizLine/CardDataVizLine.d.ts +0 -24
  407. package/dist/types/components/CardDataVizLine/index.d.ts +0 -2
  408. package/dist/types/components/CardShellDataViz/CardShellDataViz.d.ts +0 -13
  409. package/dist/types/components/CardShellDataViz/index.d.ts +0 -2
  410. package/dist/types/components/ChartBarStacked/ChartBarStacked.d.ts +0 -26
  411. package/dist/types/components/ChartBarStacked/index.d.ts +0 -3
  412. package/dist/types/components/SelectMulti/SelectMulti.d.ts +0 -121
  413. package/dist/types/components/SelectMulti/index.d.ts +0 -2
  414. package/dist/types/components/ShellGradientPicker/ShellGradientPicker.d.ts +0 -12
  415. package/dist/types/components/ShellGradientSwatch/ShellGradientSwatch.d.ts +0 -15
  416. package/dist/types/components/ShellGradientSwatch/shell-gradient-swatch-types.d.ts +0 -4
  417. /package/dist/components/{p-CgEYdMee.js.map → p-6qXDqCj_.js.map} +0 -0
  418. /package/dist/components/{p-Cr3tEx7o.js.map → p-Ay1AX7Ql.js.map} +0 -0
  419. /package/dist/components/{p-BOCfICln.js.map → p-B1cbQ0SG.js.map} +0 -0
  420. /package/dist/components/{p-BKOlvCGS.js.map → p-BUZXuod2.js.map} +0 -0
  421. /package/dist/components/{p-DCvA3Dc9.js.map → p-BaUsq_VK.js.map} +0 -0
  422. /package/dist/components/{p-BO5aqZcf.js.map → p-BcTYhmku.js.map} +0 -0
  423. /package/dist/components/{p-BDKtu6Wb.js.map → p-BroVnDzE.js.map} +0 -0
  424. /package/dist/components/{p-CIiBpjCn.js.map → p-BsoqsbBh.js.map} +0 -0
  425. /package/dist/components/{p-C8HU4W8q.js.map → p-CBazaRlE.js.map} +0 -0
  426. /package/dist/components/{p-BhV5e6vF.js.map → p-CHuh71-U.js.map} +0 -0
  427. /package/dist/components/{p-CChcuL04.js.map → p-CMWata9g.js.map} +0 -0
  428. /package/dist/components/{p-DRnIuCiT.js.map → p-DeQwkbT1.js.map} +0 -0
  429. /package/dist/components/{p-Cuih680v.js.map → p-Df17mJqI.js.map} +0 -0
  430. /package/dist/components/{p-YR1XeuZf.js.map → p-ohsLFap_.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
3
  "name": "shell-app",
4
4
  "title": "ShellApp",
5
- "description": "The single required workspace root for standard authenticated application pages, coordinating primary and secondary navigation, tools chrome, responsive composition, content geometry, shared styling, and shell behavior.",
5
+ "description": "The standard managed workspace root for authenticated applications, assembling responsive navigation, page chrome, global tools, and stable application-owned content from typed data.",
6
6
  "type": "registry:ui",
7
7
  "meta": {
8
8
  "library": "@ds-mo/ui",
@@ -13,10 +13,10 @@
13
13
  "intent": {
14
14
  "audience": "specialized",
15
15
  "status": "stable",
16
- "summary": "The single required workspace root for standard authenticated application pages, coordinating primary and secondary navigation, tools chrome, responsive composition, content geometry, shared styling, and shell behavior.",
16
+ "summary": "The standard managed workspace root for authenticated applications, assembling responsive navigation, page chrome, global tools, and stable application-owned content from typed data.",
17
17
  "useWhen": [
18
18
  "Building any standard authenticated product or workspace page with CompoMo.",
19
- "PanelNav, BarNav, ShellTools, mobile navigation, page content, shared chrome, responsive behavior, and shell shortcuts must be composed as one application frame.",
19
+ "Navigation, page chrome, global tools, responsive behavior, and shell shortcuts must be composed as one application frame without parallel desktop and mobile owners.",
20
20
  "Future application templates need the supported base-page composition boundary."
21
21
  ],
22
22
  "avoidWhen": [
@@ -40,32 +40,34 @@
40
40
  "pattern:shell-page"
41
41
  ],
42
42
  "accessibility": [
43
- "Keep primary destinations in PanelNav and secondary route sections in BarNav.",
43
+ "Supply primary destinations through navigation and secondary route sections through pageChrome so managed ShellApp preserves their correct semantics.",
44
44
  "Ensure the default content region contains the page's single main landmark.",
45
- "Keep PanelNav, BarNav, and PanelTools-compatible chrome available in desktop and tablet compositions and the persistent mobile bar available below 768px.",
45
+ "Keep the managed desktop/tablet and mobile presentations available without conditionally recreating routed or tool content.",
46
46
  "Do not override browser keyboard chords when enabling shell shortcuts.",
47
47
  "Require Search and Help as the minimum PanelTools actions and provide accessible labels for every tool.",
48
48
  "Preserve focus and accessible names across navigation, collapse, overflow, and responsive presentation changes."
49
49
  ],
50
50
  "states": [
51
51
  "Render exactly one ShellApp as the workspace root and never nest it.",
52
- "PanelNav, BarNav, and ShellTools are the responsive shell regions; ShellTools contains at least Search and Help even when no additional product tools apply.",
52
+ "Managed composition is the standard. Supply navigation, pageChrome, and tools objects plus named tool-view and default page-content slots.",
53
53
  "The application router owns the current route, authorization filtering, Dashboard or Settings context, destination collections, section collections, and localized content labels.",
54
- "ShellApp propagates navStyle and resolved responsive mode and coordinates layout, gradient alignment, transitions, metrics, shortcuts, and mobile-stage visibility.",
55
- "The application controls mobileDestination and mobileSheetNavOpen and keeps router state independent from global tool-surface changes.",
54
+ "ShellApp renders the lower-level desktop, tablet, and mobile chrome, coordinates layout, gradient alignment, transitions, shortcuts, global surfaces, Inbox state, focus restoration, and mobile-stage visibility.",
55
+ "The application router owns authorization, current URLs, history, and route execution; ShellApp forwards navigation and page intent events without routing.",
56
+ "The application supplies each routed content owner and tool view once. ShellApp changes visibility, inert state, and presentation without recreating those nodes.",
57
+ "Use composition=slotted only for advanced application architectures that intentionally own all lower-level chrome wiring.",
56
58
  "Set gradientPreset to the single resolved global chrome preference: neutral by default, none for solid chrome, or cool, neutral, warm, and fresh for token-based washes.",
57
59
  "The application owns gradient preference persistence, cross-tab synchronization, and server or account precedence; ShellApp owns rendering the resolved preset across authenticated routes.",
58
60
  "Dashboard represents day-to-day operational work while Settings represents administrative and configuration work; route state selects the context.",
59
- "Update PanelNav groups, BarNav tabs and heading, navStyle, basePath, and currentUrl atomically from one resolved route state.",
60
- "BarNav remains present: it shows route-section tabs when available and the active PanelNav destination label as heading otherwise.",
61
- "Render one ShellPage as the default-slot child for each standard routed page; ShellApp owns the content scroller while ShellPage owns page header stickiness and content inset.",
61
+ "Replace navigation and pageChrome together from one completed route state.",
62
+ "When pageChrome.showBack marks a detail depth, mobile chrome keeps the page heading as its identity and presents only local subsections; peer route tabs remain in desktop BarNav rather than replacing the detail heading.",
63
+ "Managed ShellApp keeps BarNav and ShellPage presentations present and owns page header stickiness and the content scroller.",
62
64
  "The application filters unauthorized destinations, sections, and tools before passing them into shell components."
63
65
  ],
64
66
  "responsiveBehavior": [
65
67
  "ShellApp owns the fixed system breakpoints and resolves desktop at 1200px and wider, tablet from 768px through 1199px, and mobile below 768px.",
66
68
  "On desktop, PanelNav defaults expanded, permits user collapse or expansion, and respects the locally persisted desktop preference.",
67
69
  "On tablet, ShellApp keeps PanelNav permanently collapsed and prevents user expansion without overwriting the desktop preference.",
68
- "On mobile, ShellApp hides and inerts PanelNav and BarNav, uses a solid primary stage, and composes routed ShellPage MobileHeader presentations, MobileSheetNav, ShellTools, and the persistent five-item MobileBarNav.",
70
+ "On mobile, ShellApp hides and inerts desktop chrome, uses a solid primary stage, and composes MobileHeader, MobileSheetNav, ShellTools, and the persistent MobileBarNav around the same application-owned content.",
69
71
  "When the application enables viewport-fit=cover, ShellApp reserves the shared top safe-area inset once for the complete mobile stage; nested routed, sheet, and tool headers must not add a second top inset.",
70
72
  "Mobile global surfaces conceal and inert the routed workspace without unmounting it, preserving nested routes and scroll state.",
71
73
  "Keep PanelNav width, BarNav height, PanelTools chrome, and main-content origin stable except during intentional responsive or collapse transitions.",
@@ -73,15 +75,15 @@
73
75
  ],
74
76
  "frameworkCaveats": {
75
77
  "customElements": [
76
- "Assign complex navigation and tool collections as JavaScript properties on the slotted components.",
78
+ "Assign navigation, pageChrome, and tools as JavaScript properties on the managed ShellApp.",
77
79
  "Stamp route-derived nav-style before components connect when deterministic first paint is required."
78
80
  ],
79
81
  "react": [
80
- "Use generated wrappers and preserve native slot names for desktop navigation, responsive tools, mobile navigation, and main content.",
82
+ "Use the generated ShellApp wrapper, structured object props, named tool-view slots, and stable routed children.",
81
83
  "Resolve all shell inputs from one router state before rendering the composition."
82
84
  ],
83
85
  "angular": [
84
- "Use generated standalone adapters and preserve slot attributes in templates.",
86
+ "Use the generated standalone ShellApp adapter, bind structured object props, and preserve named tool-view slots.",
85
87
  "Bind complex inputs as properties and update navigation inputs atomically from one resolved router state.",
86
88
  "Bind both nav-style attributes and properties when deterministic first paint is required."
87
89
  ]
@@ -107,6 +109,15 @@
107
109
  },
108
110
  "api": {
109
111
  "props": {
112
+ "composition": {
113
+ "type": "ShellAppComposition",
114
+ "resolvedType": "\"managed\" | \"slotted\"",
115
+ "attribute": "composition",
116
+ "default": "'managed'",
117
+ "required": false,
118
+ "mutable": false,
119
+ "description": "Managed renders the complete responsive chrome; slotted exposes the advanced composition."
120
+ },
110
121
  "gradientPreset": {
111
122
  "type": "ShellGradientPreset",
112
123
  "resolvedType": "\"cool\" | \"fresh\" | \"neutral\" | \"none\" | \"warm\"",
@@ -143,6 +154,22 @@
143
154
  "mutable": false,
144
155
  "description": "Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`."
145
156
  },
157
+ "navigation": {
158
+ "type": "ShellNavigationConfig",
159
+ "resolvedType": "ShellNavigationConfig",
160
+ "default": "{}",
161
+ "required": false,
162
+ "mutable": false,
163
+ "description": "Router-owned navigation data used by managed composition."
164
+ },
165
+ "pageChrome": {
166
+ "type": "ShellPageChromeConfig",
167
+ "resolvedType": "ShellPageChromeConfig",
168
+ "default": "{}",
169
+ "required": false,
170
+ "mutable": false,
171
+ "description": "Route-owned page title and section data used by managed composition."
172
+ },
146
173
  "shortcutsEnabled": {
147
174
  "type": "boolean",
148
175
  "resolvedType": "boolean",
@@ -151,9 +178,97 @@
151
178
  "required": false,
152
179
  "mutable": false,
153
180
  "description": "When `true` (default), registers global shell keyboard shortcuts. `[` toggles panel nav; `]` closes tools; K, A, S, M, N, and / toggle tool drawers. Modifiers are ignored so browser chords like ⌘N stay native."
181
+ },
182
+ "tools": {
183
+ "type": "ShellToolsConfig",
184
+ "resolvedType": "ShellToolsConfig",
185
+ "default": "{}",
186
+ "required": false,
187
+ "mutable": false,
188
+ "description": "Product-owned global tool definitions used by managed composition."
154
189
  }
155
190
  },
156
191
  "events": [
192
+ {
193
+ "name": "dsBreadcrumbSelect",
194
+ "detail": "BreadcrumbSelectDetail",
195
+ "bubbles": true,
196
+ "cancelable": true,
197
+ "composed": true,
198
+ "description": "Managed breadcrumb intent from BarTitle."
199
+ },
200
+ {
201
+ "name": "dsBrowseContextChange",
202
+ "detail": "NavChromeStyle",
203
+ "bubbles": true,
204
+ "cancelable": true,
205
+ "composed": true,
206
+ "description": "Managed mobile Dashboard/Settings browsing intent."
207
+ },
208
+ {
209
+ "name": "dsHeaderAction",
210
+ "detail": "{ tool: PanelToolsToolId; id: string }",
211
+ "bubbles": true,
212
+ "cancelable": true,
213
+ "composed": true,
214
+ "description": "Managed tool-header action intent."
215
+ },
216
+ {
217
+ "name": "dsHeaderBack",
218
+ "detail": "{ tool: PanelToolsToolId }",
219
+ "bubbles": true,
220
+ "cancelable": true,
221
+ "composed": true,
222
+ "description": "Managed tool-header Back intent."
223
+ },
224
+ {
225
+ "name": "dsNavFooterAction",
226
+ "detail": "void",
227
+ "bubbles": true,
228
+ "cancelable": true,
229
+ "composed": true,
230
+ "description": "Managed account-footer action intent."
231
+ },
232
+ {
233
+ "name": "dsNavSelect",
234
+ "detail": "string",
235
+ "bubbles": true,
236
+ "cancelable": true,
237
+ "composed": true,
238
+ "description": "Managed primary-navigation intent; the application router performs navigation."
239
+ },
240
+ {
241
+ "name": "dsNavUserAction",
242
+ "detail": "PanelNavUserActionDetail",
243
+ "bubbles": true,
244
+ "cancelable": true,
245
+ "composed": true,
246
+ "description": "Managed user/account trigger intent."
247
+ },
248
+ {
249
+ "name": "dsPageAction",
250
+ "detail": "string",
251
+ "bubbles": true,
252
+ "cancelable": true,
253
+ "composed": true,
254
+ "description": "Managed page action intent from BarTitle."
255
+ },
256
+ {
257
+ "name": "dsPageBack",
258
+ "detail": "MouseEvent",
259
+ "bubbles": true,
260
+ "cancelable": true,
261
+ "composed": true,
262
+ "description": "Managed page-level Back intent."
263
+ },
264
+ {
265
+ "name": "dsPresentationChange",
266
+ "detail": "{ presentation: 'drawer' | 'fullscreen' }",
267
+ "bubbles": true,
268
+ "cancelable": true,
269
+ "composed": true,
270
+ "description": "Managed drawer/fullscreen presentation state."
271
+ },
157
272
  {
158
273
  "name": "dsResponsiveModeChange",
159
274
  "detail": "{ mode: ShellResponsiveMode }",
@@ -161,12 +276,61 @@
161
276
  "cancelable": true,
162
277
  "composed": true,
163
278
  "description": "Emitted after crossing the fixed 768px or 1200px shell boundaries."
279
+ },
280
+ {
281
+ "name": "dsSubsectionChange",
282
+ "detail": "string",
283
+ "bubbles": true,
284
+ "cancelable": true,
285
+ "composed": true,
286
+ "description": "Managed page-subsection intent from BarTitle or MobileHeader."
287
+ },
288
+ {
289
+ "name": "dsTabChange",
290
+ "detail": "string",
291
+ "bubbles": true,
292
+ "cancelable": true,
293
+ "composed": true,
294
+ "description": "Managed desktop BarNav or mobile section-selection intent."
295
+ },
296
+ {
297
+ "name": "dsToolChange",
298
+ "detail": "{ id: PanelToolsToolId; selected: boolean }",
299
+ "bubbles": true,
300
+ "cancelable": true,
301
+ "composed": true,
302
+ "description": "Managed tools selection state."
303
+ }
304
+ ],
305
+ "methods": [
306
+ {
307
+ "name": "activateTool",
308
+ "signature": "activateTool(id: PanelToolsToolId) => Promise<void>",
309
+ "description": "Open or toggle a managed global tool from application-owned UI."
310
+ },
311
+ {
312
+ "name": "closeGlobalSurface",
313
+ "signature": "closeGlobalSurface() => Promise<void>",
314
+ "description": "Close whichever managed global surface is currently visible."
315
+ },
316
+ {
317
+ "name": "setToolPresentation",
318
+ "signature": "setToolPresentation(presentation: \"drawer\" | \"fullscreen\") => Promise<void>",
319
+ "description": "Request drawer or fullscreen presentation for the active managed tool."
164
320
  }
165
321
  ],
166
- "methods": [],
167
322
  "slots": []
168
323
  },
169
324
  "props": {
325
+ "composition": {
326
+ "type": "ShellAppComposition",
327
+ "resolvedType": "\"managed\" | \"slotted\"",
328
+ "attribute": "composition",
329
+ "default": "'managed'",
330
+ "required": false,
331
+ "mutable": false,
332
+ "description": "Managed renders the complete responsive chrome; slotted exposes the advanced composition."
333
+ },
170
334
  "gradientPreset": {
171
335
  "type": "ShellGradientPreset",
172
336
  "resolvedType": "\"cool\" | \"fresh\" | \"neutral\" | \"none\" | \"warm\"",
@@ -203,6 +367,22 @@
203
367
  "mutable": false,
204
368
  "description": "Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`."
205
369
  },
370
+ "navigation": {
371
+ "type": "ShellNavigationConfig",
372
+ "resolvedType": "ShellNavigationConfig",
373
+ "default": "{}",
374
+ "required": false,
375
+ "mutable": false,
376
+ "description": "Router-owned navigation data used by managed composition."
377
+ },
378
+ "pageChrome": {
379
+ "type": "ShellPageChromeConfig",
380
+ "resolvedType": "ShellPageChromeConfig",
381
+ "default": "{}",
382
+ "required": false,
383
+ "mutable": false,
384
+ "description": "Route-owned page title and section data used by managed composition."
385
+ },
206
386
  "shortcutsEnabled": {
207
387
  "type": "boolean",
208
388
  "resolvedType": "boolean",
@@ -211,9 +391,97 @@
211
391
  "required": false,
212
392
  "mutable": false,
213
393
  "description": "When `true` (default), registers global shell keyboard shortcuts. `[` toggles panel nav; `]` closes tools; K, A, S, M, N, and / toggle tool drawers. Modifiers are ignored so browser chords like ⌘N stay native."
394
+ },
395
+ "tools": {
396
+ "type": "ShellToolsConfig",
397
+ "resolvedType": "ShellToolsConfig",
398
+ "default": "{}",
399
+ "required": false,
400
+ "mutable": false,
401
+ "description": "Product-owned global tool definitions used by managed composition."
214
402
  }
215
403
  },
216
404
  "events": [
405
+ {
406
+ "name": "dsBreadcrumbSelect",
407
+ "detail": "BreadcrumbSelectDetail",
408
+ "bubbles": true,
409
+ "cancelable": true,
410
+ "composed": true,
411
+ "description": "Managed breadcrumb intent from BarTitle."
412
+ },
413
+ {
414
+ "name": "dsBrowseContextChange",
415
+ "detail": "NavChromeStyle",
416
+ "bubbles": true,
417
+ "cancelable": true,
418
+ "composed": true,
419
+ "description": "Managed mobile Dashboard/Settings browsing intent."
420
+ },
421
+ {
422
+ "name": "dsHeaderAction",
423
+ "detail": "{ tool: PanelToolsToolId; id: string }",
424
+ "bubbles": true,
425
+ "cancelable": true,
426
+ "composed": true,
427
+ "description": "Managed tool-header action intent."
428
+ },
429
+ {
430
+ "name": "dsHeaderBack",
431
+ "detail": "{ tool: PanelToolsToolId }",
432
+ "bubbles": true,
433
+ "cancelable": true,
434
+ "composed": true,
435
+ "description": "Managed tool-header Back intent."
436
+ },
437
+ {
438
+ "name": "dsNavFooterAction",
439
+ "detail": "void",
440
+ "bubbles": true,
441
+ "cancelable": true,
442
+ "composed": true,
443
+ "description": "Managed account-footer action intent."
444
+ },
445
+ {
446
+ "name": "dsNavSelect",
447
+ "detail": "string",
448
+ "bubbles": true,
449
+ "cancelable": true,
450
+ "composed": true,
451
+ "description": "Managed primary-navigation intent; the application router performs navigation."
452
+ },
453
+ {
454
+ "name": "dsNavUserAction",
455
+ "detail": "PanelNavUserActionDetail",
456
+ "bubbles": true,
457
+ "cancelable": true,
458
+ "composed": true,
459
+ "description": "Managed user/account trigger intent."
460
+ },
461
+ {
462
+ "name": "dsPageAction",
463
+ "detail": "string",
464
+ "bubbles": true,
465
+ "cancelable": true,
466
+ "composed": true,
467
+ "description": "Managed page action intent from BarTitle."
468
+ },
469
+ {
470
+ "name": "dsPageBack",
471
+ "detail": "MouseEvent",
472
+ "bubbles": true,
473
+ "cancelable": true,
474
+ "composed": true,
475
+ "description": "Managed page-level Back intent."
476
+ },
477
+ {
478
+ "name": "dsPresentationChange",
479
+ "detail": "{ presentation: 'drawer' | 'fullscreen' }",
480
+ "bubbles": true,
481
+ "cancelable": true,
482
+ "composed": true,
483
+ "description": "Managed drawer/fullscreen presentation state."
484
+ },
217
485
  {
218
486
  "name": "dsResponsiveModeChange",
219
487
  "detail": "{ mode: ShellResponsiveMode }",
@@ -221,9 +489,49 @@
221
489
  "cancelable": true,
222
490
  "composed": true,
223
491
  "description": "Emitted after crossing the fixed 768px or 1200px shell boundaries."
492
+ },
493
+ {
494
+ "name": "dsSubsectionChange",
495
+ "detail": "string",
496
+ "bubbles": true,
497
+ "cancelable": true,
498
+ "composed": true,
499
+ "description": "Managed page-subsection intent from BarTitle or MobileHeader."
500
+ },
501
+ {
502
+ "name": "dsTabChange",
503
+ "detail": "string",
504
+ "bubbles": true,
505
+ "cancelable": true,
506
+ "composed": true,
507
+ "description": "Managed desktop BarNav or mobile section-selection intent."
508
+ },
509
+ {
510
+ "name": "dsToolChange",
511
+ "detail": "{ id: PanelToolsToolId; selected: boolean }",
512
+ "bubbles": true,
513
+ "cancelable": true,
514
+ "composed": true,
515
+ "description": "Managed tools selection state."
516
+ }
517
+ ],
518
+ "methods": [
519
+ {
520
+ "name": "activateTool",
521
+ "signature": "activateTool(id: PanelToolsToolId) => Promise<void>",
522
+ "description": "Open or toggle a managed global tool from application-owned UI."
523
+ },
524
+ {
525
+ "name": "closeGlobalSurface",
526
+ "signature": "closeGlobalSurface() => Promise<void>",
527
+ "description": "Close whichever managed global surface is currently visible."
528
+ },
529
+ {
530
+ "name": "setToolPresentation",
531
+ "signature": "setToolPresentation(presentation: \"drawer\" | \"fullscreen\") => Promise<void>",
532
+ "description": "Request drawer or fullscreen presentation for the active managed tool."
224
533
  }
225
534
  ],
226
- "methods": [],
227
535
  "slots": [],
228
536
  "exports": {
229
537
  "customElement": "ds-shell-app",
@@ -245,6 +553,7 @@
245
553
  "import": "import { DsShellApp } from '@ds-mo/ui/angular/ds-shell-app';",
246
554
  "example": "<ds-shell-app></ds-shell-app>"
247
555
  },
556
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: navigation, pageChrome, tools.",
248
557
  "peerDependencies": {
249
558
  "required": [
250
559
  "@ds-mo/tokens ^5.0.0",
@@ -258,16 +567,32 @@
258
567
  "@ds-mo/ui",
259
568
  "@ds-mo/tokens"
260
569
  ],
261
- "registryDependencies": [],
570
+ "registryDependencies": [
571
+ "bar-nav",
572
+ "bar-title",
573
+ "button-unfilled",
574
+ "mobile-bar-nav",
575
+ "mobile-header",
576
+ "mobile-sheet-nav",
577
+ "panel-nav",
578
+ "shell-page",
579
+ "shell-tools",
580
+ "tooltip"
581
+ ],
262
582
  "files": [
263
583
  {
264
584
  "path": "src/wc/components/ShellApp/ShellApp.css",
265
- "content": ":host {\n display: block;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow: hidden;\n overscroll-behavior: none;\n --ds-shell-panel-tools-width: var(--dimension-panel-width-xs);\n}\n\n.shell-app {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow: hidden;\n overscroll-behavior: none;\n font-family: var(--typography-font-family, system-ui);\n}\n\n:host {\n --_shell-chrome-bg: var(--color-background-secondary);\n}\n\n.shell-app__row {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n height: 100%;\n position: relative;\n}\n\n/*\n * One chrome layer behind the shell row. Wash uses background-attachment: fixed\n * so the pattern is locked to the viewport — panel/tools collapse only changes the\n * transparent window, not the pattern phase. JS sets wash background-size from\n * readShellViewportDimensions(), not the shell element box.\n */\n.shell-app__chrome {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 0;\n background-color: var(--_shell-chrome-bg);\n}\n\n:host(.shell-app--gradient) .shell-app__chrome::before {\n content: '';\n position: absolute;\n inset: 0;\n pointer-events: none;\n background-position: 0 0;\n background-attachment: fixed;\n z-index: 1;\n opacity: var(--ds-shell-gradient-opacity, 1);\n background-image: var(--ds-shell-gradient-image, none);\n background-size: var(--ds-shell-gradient-size, auto);\n background-repeat: no-repeat;\n}\n\n.shell-app__panel {\n flex: 0 0 auto;\n min-height: 0;\n height: 100%;\n position: relative;\n /* Above main so resize handle line can paint over the workspace edge */\n z-index: 2;\n}\n\n.shell-app__panel ::slotted(ds-panel-nav) {\n display: block;\n height: 100%;\n}\n\n.shell-app__main {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-areas:\n 'bar tools'\n 'content tools';\n position: relative;\n z-index: 1;\n}\n\n.shell-app__mobile-sheet-nav,\n.shell-app__mobile-bar-nav {\n display: none;\n}\n\n.shell-app__bar {\n grid-area: bar;\n flex: 0 0 auto;\n min-width: 0;\n}\n\n.shell-app__bar ::slotted(ds-bar-nav) {\n display: block;\n}\n\n.shell-app__content {\n grid-area: content;\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: none;\n /* Limit reflow to the page column — not on __main (breaks tools flex shrink). */\n contain: layout;\n}\n\n/* Opaque page surface — masks the fixed chrome layer in the content column. */\n.shell-app__content {\n position: relative;\n z-index: 1;\n background-color: var(--color-background-primary);\n}\n\n.shell-app__tools {\n grid-area: tools;\n flex: 0 0 auto;\n min-width: 0;\n min-height: 0;\n height: 100%;\n display: flex;\n position: relative;\n z-index: 0;\n overflow: hidden;\n}\n\n.shell-app__tools ::slotted(ds-panel-tools) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n.shell-app__tools ::slotted(ds-shell-tools) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n:host(.shell-app--tools-fullscreen) .shell-app__panel,\n:host(.shell-app--tools-fullscreen) .shell-app__bar,\n:host(.shell-app--tools-fullscreen) .shell-app__content {\n visibility: hidden;\n}\n\n:host(.shell-app--mobile) {\n --_shell-chrome-bg: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__chrome,\n:host(.shell-app--mobile) .shell-app__panel,\n:host(.shell-app--mobile) .shell-app__bar {\n display: none;\n}\n\n:host(.shell-app--mobile) .shell-app__main {\n width: 100%;\n padding-block-start: env(safe-area-inset-top);\n box-sizing: border-box;\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) auto;\n grid-template-areas:\n 'stage'\n 'mobile-bar-nav';\n background: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__content,\n:host(.shell-app--mobile) .shell-app__tools,\n:host(.shell-app--mobile) .shell-app__mobile-sheet-nav {\n grid-area: stage;\n min-width: 0;\n min-height: 0;\n height: 100%;\n position: relative;\n}\n\n:host(.shell-app--mobile) .shell-app__content {\n z-index: 1;\n overflow: auto;\n}\n\n:host(.shell-app--mobile) .shell-app__tools {\n z-index: 2;\n width: 100%;\n overflow: hidden;\n background: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__mobile-sheet-nav {\n display: block;\n z-index: 3;\n overflow: hidden;\n background: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__mobile-bar-nav {\n grid-area: mobile-bar-nav;\n display: block;\n min-width: 0;\n position: relative;\n z-index: 4;\n}\n\n:host(.shell-app--mobile) .shell-app__tools[hidden],\n:host(.shell-app--mobile) .shell-app__mobile-sheet-nav[hidden],\n:host(.shell-app--mobile) .shell-app__mobile-bar-nav[hidden] {\n display: none;\n}\n\n:host(.shell-app--mobile-tool-active) .shell-app__content,\n:host(.shell-app--mobile-sheet-nav-open) .shell-app__content,\n:host(.shell-app--mobile-sheet-nav-open) .shell-app__tools {\n visibility: hidden;\n}\n",
585
+ "content": ":host {\n display: block;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow: hidden;\n overscroll-behavior: none;\n --ds-shell-panel-tools-width: var(--dimension-panel-width-xs);\n}\n\n.shell-app {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow: hidden;\n overscroll-behavior: none;\n font-family: var(--typography-font-family, system-ui);\n}\n\n:host {\n --_shell-chrome-bg: var(--color-background-secondary);\n}\n\n.shell-app__row {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n height: 100%;\n position: relative;\n}\n\n/*\n * One chrome layer behind the shell row. Wash uses background-attachment: fixed\n * so the pattern is locked to the viewport — panel/tools collapse only changes the\n * transparent window, not the pattern phase. JS sets wash background-size from\n * readShellViewportDimensions(), not the shell element box.\n */\n.shell-app__chrome {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 0;\n background-color: var(--_shell-chrome-bg);\n}\n\n:host(.shell-app--gradient) .shell-app__chrome::before {\n content: '';\n position: absolute;\n inset: 0;\n pointer-events: none;\n background-position: 0 0;\n background-attachment: fixed;\n z-index: 1;\n opacity: var(--ds-shell-gradient-opacity, 1);\n background-image: var(--ds-shell-gradient-image, none);\n background-size: var(--ds-shell-gradient-size, auto);\n background-repeat: no-repeat;\n}\n\n.shell-app__panel {\n flex: 0 0 auto;\n min-height: 0;\n height: 100%;\n position: relative;\n /* Above main so resize handle line can paint over the workspace edge */\n z-index: 2;\n}\n\n.shell-app__panel ::slotted(ds-panel-nav) {\n display: block;\n height: 100%;\n}\n\n.shell-app__panel > ds-panel-nav {\n display: block;\n height: 100%;\n}\n\n.shell-app__main {\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-areas:\n 'bar tools'\n 'content tools';\n position: relative;\n z-index: 1;\n}\n\n.shell-app__mobile-sheet-nav,\n.shell-app__mobile-bar-nav {\n display: none;\n}\n\n.shell-app__bar {\n grid-area: bar;\n flex: 0 0 auto;\n min-width: 0;\n}\n\n.shell-app__bar ::slotted(ds-bar-nav) {\n display: block;\n}\n\n.shell-app__bar > ds-bar-nav {\n display: block;\n}\n\n.shell-app__content {\n grid-area: content;\n flex: 1 1 auto;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n overscroll-behavior: none;\n /* Limit reflow to the page column — not on __main (breaks tools flex shrink). */\n contain: layout;\n}\n\n/* Opaque page surface — masks the fixed chrome layer in the content column. */\n.shell-app__content {\n position: relative;\n z-index: 1;\n background-color: var(--color-background-primary);\n}\n\n.shell-app__tools {\n grid-area: tools;\n flex: 0 0 auto;\n min-width: 0;\n min-height: 0;\n height: 100%;\n display: flex;\n position: relative;\n z-index: 0;\n overflow: hidden;\n}\n\n.shell-app__tools ::slotted(ds-panel-tools) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n.shell-app__tools ::slotted(ds-shell-tools) {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n.shell-app__tools > ds-shell-tools {\n display: block;\n height: 100%;\n min-height: 0;\n}\n\n.shell-app__content > ds-shell-page {\n display: block;\n min-height: 100%;\n}\n\n:host(.shell-app--tools-fullscreen) .shell-app__panel,\n:host(.shell-app--tools-fullscreen) .shell-app__bar,\n:host(.shell-app--tools-fullscreen) .shell-app__content {\n visibility: hidden;\n}\n\n:host(.shell-app--mobile) {\n --_shell-chrome-bg: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__chrome,\n:host(.shell-app--mobile) .shell-app__panel,\n:host(.shell-app--mobile) .shell-app__bar {\n display: none;\n}\n\n:host(.shell-app--mobile) .shell-app__main {\n width: 100%;\n padding-block-start: env(safe-area-inset-top);\n box-sizing: border-box;\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(0, 1fr) auto;\n grid-template-areas:\n 'stage'\n 'mobile-bar-nav';\n background: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__content,\n:host(.shell-app--mobile) .shell-app__tools,\n:host(.shell-app--mobile) .shell-app__mobile-sheet-nav {\n grid-area: stage;\n min-width: 0;\n min-height: 0;\n height: 100%;\n position: relative;\n}\n\n:host(.shell-app--mobile) .shell-app__content {\n z-index: 1;\n overflow: auto;\n}\n\n:host(.shell-app--mobile) .shell-app__tools {\n z-index: 2;\n width: 100%;\n overflow: hidden;\n background: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__mobile-sheet-nav {\n display: block;\n z-index: 3;\n overflow: hidden;\n background: var(--color-background-primary);\n}\n\n:host(.shell-app--mobile) .shell-app__mobile-bar-nav {\n grid-area: mobile-bar-nav;\n display: block;\n min-width: 0;\n position: relative;\n z-index: 4;\n}\n\n:host(.shell-app--mobile) .shell-app__tools[hidden],\n:host(.shell-app--mobile) .shell-app__mobile-sheet-nav[hidden],\n:host(.shell-app--mobile) .shell-app__mobile-bar-nav[hidden] {\n display: none;\n}\n\n:host(.shell-app--mobile-tool-active) .shell-app__content,\n:host(.shell-app--mobile-sheet-nav-open) .shell-app__content,\n:host(.shell-app--mobile-sheet-nav-open) .shell-app__tools {\n visibility: hidden;\n}\n",
266
586
  "type": "registry:ui"
267
587
  },
268
588
  {
269
589
  "path": "src/wc/components/ShellApp/ShellApp.tsx",
270
- "content": "import {\n Component,\n Prop,\n Element,\n Event,\n EventEmitter,\n State,\n Watch,\n Listen,\n h,\n Host,\n} from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport {\n isEditableShortcutTarget,\n resolveShellShortcut,\n} from '../../shell/shell-shortcuts';\nimport type { PanelToolsToolId } from '../PanelTools/panel-tools-types';\nimport {\n DEFAULT_SHELL_GRADIENT_PRESET,\n normalizeShellGradientPreset,\n type ShellGradientPreset,\n} from '../../shell/shell-gradient-presets';\nimport {\n CHROME_TRANSITION_END,\n CHROME_TRANSITION_START,\n ChromeTransitionDepth,\n createRafCoalescer,\n readChromeTransitionSource,\n} from '../../shell/chrome-transition';\nimport {\n isPanelNavCollapsed,\n panelWidthPxFromTokens,\n readPanelNavWidthTokens,\n type PanelNavWidthTokens,\n} from '../../shell/shell-chrome-metrics';\nimport {\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n SHELL_GRADIENT_POSITION_BAR_VAR,\n SHELL_GRADIENT_POSITION_PANEL_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n buildShellRadialGradient,\n readShellViewportDimensions,\n shellGradientPositionBar,\n shellGradientPositionPanel,\n shellGradientPresetOpacity,\n shellGradientSize,\n} from '../../shell/shell-gradient';\nimport {\n resolveShellResponsiveMode,\n type MobileDestination,\n type ShellResponsiveMode,\n} from '../../shell/shell-responsive';\n\n@Component({\n tag: 'ds-shell-app',\n styleUrl: 'ShellApp.css',\n scoped: true,\n})\nexport class ShellApp {\n /** Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`. */\n @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';\n\n /**\n * Shell chrome wash preset. `none` renders solid chrome; the remaining\n * presets use token-based washes that adapt to the active color theme.\n */\n @Prop({ attribute: 'gradient-preset', reflect: true }) gradientPreset: ShellGradientPreset =\n DEFAULT_SHELL_GRADIENT_PRESET;\n\n /** When `true` (default), registers global shell keyboard shortcuts. `[` toggles panel nav; `]` closes tools; K, A, S, M, N, and / toggle tool drawers. Modifiers are ignored so browser chords like ⌘N stay native. */\n @Prop({ attribute: 'shortcuts-enabled' }) shortcutsEnabled: boolean = true;\n\n /** Controlled mobile surface shown above the persistent bottom bar. */\n @Prop({ attribute: 'mobile-destination' })\n mobileDestination: MobileDestination = 'area';\n\n /** Controlled full-stage Mobile Sheet Nav state. */\n @Prop({ attribute: 'mobile-sheet-nav-open' })\n mobileSheetNavOpen: boolean = false;\n\n /** Emitted after crossing the fixed 768px or 1200px shell boundaries. */\n @Event() dsResponsiveModeChange!: EventEmitter<{ mode: ShellResponsiveMode }>;\n\n @Element() el!: HTMLElement;\n @State() private toolsFullscreen = false;\n @State() private resolvedMode: ShellResponsiveMode = 'desktop';\n\n private resizeObserver: ResizeObserver | null = null;\n private hasLoaded = false;\n private readonly panelNavTransition = new ChromeTransitionDepth();\n private readonly chromeSyncCoalescer = createRafCoalescer(() => this.syncChrome());\n private panelWidthTokens: PanelNavWidthTokens = { expandedPx: 0, collapsedPx: 0 };\n private cachedViewportWidth = 0;\n private cachedViewportHeight = 0;\n private onWindowResize = () => {\n this.updateResponsiveMode();\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n private onVisualViewportChange = () => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n\n componentWillLoad() {\n if (typeof window !== 'undefined') {\n this.resolvedMode = resolveShellResponsiveMode(window.innerWidth);\n }\n }\n\n componentDidLoad() {\n this.hasLoaded = true;\n this.syncSlottedNavStyle();\n this.syncSlottedMobileState();\n this.connectMetricsObserver();\n this.connectViewportListeners();\n this.el.addEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.addEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n requestAnimationFrame(() => {\n this.cachePanelWidthTokens();\n this.scheduleChromeSync();\n });\n const tools = this.el.querySelector('ds-shell-tools, ds-panel-tools');\n this.toolsFullscreen = tools?.getAttribute('presentation') === 'fullscreen';\n }\n\n @Listen('dsPresentationChange')\n handleToolsPresentation(event: CustomEvent<{ presentation?: string }>) {\n this.toolsFullscreen = event.detail?.presentation === 'fullscreen';\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.disconnectViewportListeners();\n this.chromeSyncCoalescer.cancel();\n this.el.removeEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.removeEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n }\n\n @Watch('navStyle')\n @Watch('gradientPreset')\n onShellPropsChange() {\n this.syncSlottedNavStyle();\n this.scheduleChromeSync();\n }\n\n @Watch('mobileDestination')\n @Watch('mobileSheetNavOpen')\n onMobileStateChange(_next: unknown, previous: unknown) {\n this.syncSlottedMobileState();\n if (\n previous === true &&\n !this.mobileSheetNavOpen &&\n this.resolvedMode === 'mobile'\n ) {\n requestAnimationFrame(() => {\n const bar = this.el.querySelector('ds-mobile-bar-nav') as\n | (HTMLElement & {\n focusDestination?: (\n destination: MobileDestination | 'sheet-nav'\n ) => Promise<void>;\n })\n | null;\n const activeElement = document.activeElement;\n if (activeElement instanceof HTMLElement && bar?.contains(activeElement)) return;\n void bar?.focusDestination?.('sheet-nav');\n });\n }\n }\n\n private updateResponsiveMode() {\n if (typeof window === 'undefined') return;\n const next = resolveShellResponsiveMode(window.innerWidth);\n if (next === this.resolvedMode) return;\n this.resolvedMode = next;\n this.syncSlottedMobileState();\n this.scheduleChromeSync();\n if (this.hasLoaded) this.dsResponsiveModeChange.emit({ mode: next });\n }\n\n private onChromeTransitionStart = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.enter();\n const viewport = readShellViewportDimensions();\n this.cachedViewportWidth = viewport.width;\n this.cachedViewportHeight = viewport.height;\n this.syncChrome();\n };\n\n private onChromeTransitionEnd = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.exit();\n if (!this.panelNavTransition.isActive) {\n this.scheduleChromeSync();\n }\n };\n\n /** Coalesce ResizeObserver bursts to one layout read per frame. */\n private scheduleChromeSync() {\n this.chromeSyncCoalescer.schedule();\n }\n\n private syncSlottedNavStyle() {\n const panel = this.el.querySelector('ds-panel-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n const bar = this.el.querySelector('ds-bar-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n if (panel) {\n panel.setAttribute('nav-style', this.navStyle);\n panel.navStyle = this.navStyle;\n }\n if (bar) {\n bar.setAttribute('nav-style', this.navStyle);\n bar.navStyle = this.navStyle;\n }\n }\n\n private syncSlottedMobileState() {\n const tools = this.el.querySelector('ds-shell-tools') as\n | (HTMLElement & { responsiveMode: ShellResponsiveMode })\n | null;\n const bar = this.el.querySelector('ds-mobile-bar-nav') as\n | (HTMLElement & {\n activeDestination: MobileDestination;\n sheetNavExpanded: boolean;\n })\n | null;\n const sheetNav = this.el.querySelector('ds-mobile-sheet-nav') as\n | (HTMLElement & { open: boolean })\n | null;\n\n if (tools) {\n tools.setAttribute('responsive-mode', this.resolvedMode);\n tools.responsiveMode = this.resolvedMode;\n }\n if (bar) {\n bar.activeDestination = this.mobileDestination;\n bar.sheetNavExpanded = this.mobileSheetNavOpen;\n }\n if (sheetNav) {\n sheetNav.open = this.mobileSheetNavOpen;\n }\n }\n\n private connectMetricsObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n });\n this.resizeObserver.observe(this.el);\n const panelWrap = this.el.querySelector('.shell-app__panel');\n if (panelWrap) this.resizeObserver.observe(panelWrap);\n }\n\n private connectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.addEventListener('resize', this.onWindowResize, { passive: true });\n\n const visual = window.visualViewport;\n if (visual) {\n visual.addEventListener('resize', this.onVisualViewportChange, { passive: true });\n visual.addEventListener('scroll', this.onVisualViewportChange, { passive: true });\n }\n }\n\n private disconnectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.removeEventListener('resize', this.onWindowResize);\n\n const visual = window.visualViewport;\n if (visual) {\n visual.removeEventListener('resize', this.onVisualViewportChange);\n visual.removeEventListener('scroll', this.onVisualViewportChange);\n }\n }\n\n private cachePanelWidthTokens() {\n const navRoot = this.el.querySelector('ds-panel-nav .panel-nav') as HTMLElement | null;\n if (!navRoot) return;\n this.panelWidthTokens = readPanelNavWidthTokens(navRoot);\n }\n\n private applyGradientVars(target: HTMLElement, vars: Record<string, string | null>) {\n const style = target.style;\n for (const [name, value] of Object.entries(vars)) {\n if (value === null) style.removeProperty(name);\n else style.setProperty(name, value);\n }\n }\n\n private clearGradientPaintVars(targets: HTMLElement[]) {\n const keys = [\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n ];\n for (const target of targets) {\n for (const key of keys) target.style.removeProperty(key);\n }\n }\n\n /** Panel/bar wash offsets for scroll fades and badge rings. */\n private syncChromeLayoutVars(\n panel: HTMLElement | null,\n bar: HTMLElement | null,\n panelPosition: string,\n barPosition: string,\n ) {\n if (panel) {\n panel.style.setProperty(SHELL_GRADIENT_POSITION_PANEL_VAR, panelPosition);\n }\n if (bar) {\n bar.style.setProperty(SHELL_GRADIENT_POSITION_BAR_VAR, barPosition);\n }\n }\n\n private resolvePanelWidthPx(panelNav: HTMLElement | null): number {\n const navRoot = panelNav?.querySelector('.panel-nav') as HTMLElement | null;\n\n if (this.panelNavTransition.isActive && this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n const panelWrap = this.el.querySelector('.shell-app__panel') as HTMLElement | null;\n const measured = panelWrap?.getBoundingClientRect().width ?? 0;\n if (measured > 0) return measured;\n\n if (this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n return 0;\n }\n\n /** Fixed-attachment wash/grid size — always the viewport, never the shell element box. */\n private resolveViewportDimensions(): { width: number; height: number } {\n if (this.panelNavTransition.isActive && this.cachedViewportWidth > 0) {\n return {\n width: this.cachedViewportWidth,\n height: this.cachedViewportHeight,\n };\n }\n\n return readShellViewportDimensions();\n }\n\n private chromeLayerActive(): boolean {\n return (\n this.resolvedMode !== 'mobile' &&\n normalizeShellGradientPreset(this.gradientPreset) !== 'none'\n );\n }\n\n @Listen('keydown', { target: 'window', capture: true })\n handleWindowKeyDown(e: KeyboardEvent) {\n if (!this.shortcutsEnabled) return;\n if (isEditableShortcutTarget(e.target)) return;\n\n const action = resolveShellShortcut(e);\n if (!action) return;\n\n e.preventDefault();\n\n const panel = this.el.querySelector('ds-panel-nav') as HTMLDsPanelNavElement | null;\n const tools = this.el.querySelector('ds-shell-tools, ds-panel-tools') as\n | (HTMLElement & {\n closeDrawer?: () => Promise<void>;\n activateTool?: (id: PanelToolsToolId) => Promise<void>;\n })\n | null;\n\n if (action === 'toggle-panel-nav') {\n void panel?.toggleCollapsed();\n return;\n }\n\n if (action === 'close-panel-tools') {\n void tools?.closeDrawer?.();\n return;\n }\n\n if (action.startsWith('open-tool:') && tools) {\n const toolId = action.slice('open-tool:'.length) as PanelToolsToolId;\n void tools.activateTool?.(toolId);\n }\n }\n\n private syncChrome() {\n const panelNav = this.el.querySelector('ds-panel-nav') as HTMLElement | null;\n const bar = this.el.querySelector('ds-bar-nav') as HTMLElement | null;\n const targets = [this.el, panelNav, bar].filter((el): el is HTMLElement => el !== null);\n\n const clearLayoutVars = () => {\n if (panelNav) panelNav.style.removeProperty(SHELL_GRADIENT_POSITION_PANEL_VAR);\n if (bar) bar.style.removeProperty(SHELL_GRADIENT_POSITION_BAR_VAR);\n };\n\n const preset = normalizeShellGradientPreset(this.gradientPreset);\n if (preset === 'none' || this.resolvedMode === 'mobile') {\n this.clearGradientPaintVars(targets);\n clearLayoutVars();\n return;\n }\n\n const viewport = this.resolveViewportDimensions();\n const panelWidth = this.resolvePanelWidthPx(panelNav);\n\n const panelPosition = shellGradientPositionPanel();\n const barPosition = shellGradientPositionBar(panelWidth);\n\n this.syncChromeLayoutVars(panelNav, bar, panelPosition, barPosition);\n\n const image = buildShellRadialGradient(preset);\n\n const size = shellGradientSize({\n width: viewport.width,\n height: viewport.height,\n });\n const opacity = shellGradientPresetOpacity(preset);\n\n for (const target of targets) {\n if (target === this.el) {\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: barPosition,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n });\n continue;\n }\n\n const isBar = target.tagName.toLowerCase() === 'ds-bar-nav';\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: isBar ? null : panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: isBar ? barPosition : null,\n });\n }\n }\n\n render() {\n const chromeActive = this.chromeLayerActive();\n const mobile = this.resolvedMode === 'mobile';\n const mobileToolActive = mobile && this.mobileDestination !== 'area';\n const mobileStageBlocked = mobile && (mobileToolActive || this.mobileSheetNavOpen);\n const fullscreen = !mobile && this.toolsFullscreen;\n const shellCls: Record<string, boolean> = {\n 'shell-app': true,\n 'shell-app--gradient': chromeActive,\n [`shell-app--${this.navStyle}`]: true,\n [`shell-app--${this.resolvedMode}`]: true,\n 'shell-app--tools-fullscreen': fullscreen,\n 'shell-app--mobile-tool-active': mobileToolActive,\n 'shell-app--mobile-sheet-nav-open': mobile && this.mobileSheetNavOpen,\n };\n\n return (\n <Host class={shellCls} responsive-mode={this.resolvedMode}>\n <div class=\"shell-app__row\">\n <div class=\"shell-app__chrome\" aria-hidden=\"true\" />\n <div class=\"shell-app__panel\" aria-hidden={fullscreen ? 'true' : undefined} inert={fullscreen ? true : undefined}>\n <slot name=\"panel\" />\n </div>\n <div class=\"shell-app__main\">\n <div class=\"shell-app__bar\" aria-hidden={fullscreen ? 'true' : undefined} inert={fullscreen ? true : undefined}>\n <slot name=\"bar\" />\n </div>\n <div\n class=\"shell-app__tools\"\n aria-hidden={mobile && (!mobileToolActive || this.mobileSheetNavOpen) ? 'true' : undefined}\n inert={mobile && (!mobileToolActive || this.mobileSheetNavOpen) ? true : undefined}\n hidden={mobile && !mobileToolActive}\n >\n <slot name=\"tools\" />\n </div>\n <div\n class=\"shell-app__content\"\n aria-hidden={fullscreen || mobileStageBlocked ? 'true' : undefined}\n inert={fullscreen || mobileStageBlocked ? true : undefined}\n >\n <slot />\n </div>\n <div\n class=\"shell-app__mobile-sheet-nav\"\n hidden={!mobile || !this.mobileSheetNavOpen}\n aria-hidden={mobile && this.mobileSheetNavOpen ? undefined : 'true'}\n inert={mobile && this.mobileSheetNavOpen ? undefined : true}\n >\n <slot name=\"mobile-sheet-nav\" />\n </div>\n <div class=\"shell-app__mobile-bar-nav\" hidden={!mobile}>\n <slot name=\"mobile-bar-nav\" />\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n",
590
+ "content": "import {\n Component,\n Prop,\n Element,\n Event,\n EventEmitter,\n State,\n Watch,\n Listen,\n Method,\n h,\n Host,\n} from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport {\n isEditableShortcutTarget,\n resolveShellShortcut,\n} from '../../shell/shell-shortcuts';\nimport type {\n PanelToolsToolId,\n PanelToolsHeaderAction,\n} from '../PanelTools/panel-tools-types';\nimport { PANEL_TOOLS_DEFAULT_ITEMS } from '../PanelTools/panel-tools-types';\nimport type { BarTitleSectionItem } from '../BarTitle/bar-title-types';\nimport type { BreadcrumbSelectDetail } from '../Breadcrumb/breadcrumb-types';\nimport {\n DEFAULT_SHELL_GRADIENT_PRESET,\n normalizeShellGradientPreset,\n type ShellGradientPreset,\n} from '../../shell/shell-gradient-presets';\nimport {\n CHROME_TRANSITION_END,\n CHROME_TRANSITION_START,\n ChromeTransitionDepth,\n createRafCoalescer,\n readChromeTransitionSource,\n} from '../../shell/chrome-transition';\nimport {\n isPanelNavCollapsed,\n panelWidthPxFromTokens,\n readPanelNavWidthTokens,\n type PanelNavWidthTokens,\n} from '../../shell/shell-chrome-metrics';\nimport {\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n SHELL_GRADIENT_POSITION_BAR_VAR,\n SHELL_GRADIENT_POSITION_PANEL_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n buildShellRadialGradient,\n readShellViewportDimensions,\n shellGradientPositionBar,\n shellGradientPositionPanel,\n shellGradientPresetOpacity,\n shellGradientSize,\n} from '../../shell/shell-gradient';\nimport {\n isShellInboxTool,\n resolveAvailableInboxTool,\n resolveManagedShellPageCapacity,\n resolveShellResponsiveMode,\n SHELL_DESKTOP_BREAKPOINT,\n shellMobileDestinationForTool,\n type MobileDestination,\n type ShellInboxToolId,\n type ShellResponsiveMode,\n} from '../../shell/shell-responsive';\nimport { deriveActiveIdFromUrl } from '../PanelNav/panel-nav-utils';\nimport type { PanelNavItem } from '../PanelNav/panel-nav-types';\nimport type { PanelNavUserActionDetail } from '../PanelNav/panel-nav-types';\nimport type { MobileBarNavDestinationDetail } from '../MobileBarNav/mobile-bar-nav-types';\nimport type {\n ShellAppComposition,\n ShellNavigationConfig,\n ShellPageChromeConfig,\n ShellToolsConfig,\n} from './shell-app-types';\n\n@Component({\n tag: 'ds-shell-app',\n styleUrl: 'ShellApp.css',\n scoped: true,\n})\nexport class ShellApp {\n /** Managed renders the complete responsive chrome; slotted exposes the advanced composition. */\n @Prop({ reflect: true }) composition: ShellAppComposition = 'managed';\n\n /** Router-owned navigation data used by managed composition. */\n @Prop() navigation: ShellNavigationConfig = {};\n\n /** Route-owned page title and section data used by managed composition. */\n @Prop({ attribute: 'page-chrome' }) pageChrome: ShellPageChromeConfig = {};\n\n /** Product-owned global tool definitions used by managed composition. */\n @Prop() tools: ShellToolsConfig = {};\n\n /** Chrome style propagated to slotted `ds-panel-nav` and `ds-bar-nav`. */\n @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';\n\n /**\n * Shell chrome wash preset. `none` renders solid chrome; the remaining\n * presets use token-based washes that adapt to the active color theme.\n */\n @Prop({ attribute: 'gradient-preset', reflect: true }) gradientPreset: ShellGradientPreset =\n DEFAULT_SHELL_GRADIENT_PRESET;\n\n /** When `true` (default), registers global shell keyboard shortcuts. `[` toggles panel nav; `]` closes tools; K, A, S, M, N, and / toggle tool drawers. Modifiers are ignored so browser chords like ⌘N stay native. */\n @Prop({ attribute: 'shortcuts-enabled' }) shortcutsEnabled: boolean = true;\n\n /** Controlled mobile surface shown above the persistent bottom bar. */\n @Prop({ attribute: 'mobile-destination' })\n mobileDestination: MobileDestination = 'area';\n\n /** Controlled full-stage Mobile Sheet Nav state. */\n @Prop({ attribute: 'mobile-sheet-nav-open' })\n mobileSheetNavOpen: boolean = false;\n\n /** Emitted after crossing the fixed 768px or 1200px shell boundaries. */\n @Event() dsResponsiveModeChange!: EventEmitter<{ mode: ShellResponsiveMode }>;\n\n /** Managed primary-navigation intent; the application router performs navigation. */\n @Event() dsNavSelect!: EventEmitter<string>;\n\n /** Managed desktop BarNav or mobile section-selection intent. */\n @Event() dsTabChange!: EventEmitter<string>;\n\n /** Managed page-subsection intent from BarTitle or MobileHeader. */\n @Event() dsSubsectionChange!: EventEmitter<string>;\n\n /** Managed page-level Back intent. */\n @Event() dsPageBack!: EventEmitter<MouseEvent>;\n\n /** Managed breadcrumb intent from BarTitle. */\n @Event({ cancelable: true })\n dsBreadcrumbSelect!: EventEmitter<BreadcrumbSelectDetail>;\n\n /** Managed page action intent from BarTitle. */\n @Event() dsPageAction!: EventEmitter<string>;\n\n /** Managed tools selection state. */\n @Event() dsToolChange!: EventEmitter<{ id: PanelToolsToolId; selected: boolean }>;\n\n /** Managed tool-header Back intent. */\n @Event() dsHeaderBack!: EventEmitter<{ tool: PanelToolsToolId }>;\n\n /** Managed tool-header action intent. */\n @Event() dsHeaderAction!: EventEmitter<{ tool: PanelToolsToolId; id: string }>;\n\n /** Managed drawer/fullscreen presentation state. */\n @Event() dsPresentationChange!: EventEmitter<{ presentation: 'drawer' | 'fullscreen' }>;\n\n /** Managed mobile Dashboard/Settings browsing intent. */\n @Event() dsBrowseContextChange!: EventEmitter<NavChromeStyle>;\n\n /** Managed account-footer action intent. */\n @Event() dsNavFooterAction!: EventEmitter<void>;\n\n /** Managed user/account trigger intent. */\n @Event() dsNavUserAction!: EventEmitter<PanelNavUserActionDetail>;\n\n @Element() el!: HTMLElement;\n @State() private toolsFullscreen = false;\n @State() private resolvedMode: ShellResponsiveMode = 'desktop';\n @State() private managedToolsOpen = false;\n @State() private managedActiveTool: PanelToolsToolId | '' = '';\n @State() private managedToolPresentation: 'drawer' | 'fullscreen' = 'drawer';\n @State() private managedMobileDestination: MobileDestination = 'area';\n @State() private managedMobileSheetNavOpen = false;\n @State() private managedInboxTool: ShellInboxToolId | '' = '';\n @State() private managedBrowseContext: NavChromeStyle = 'dashboard';\n\n private resizeObserver: ResizeObserver | null = null;\n private hasLoaded = false;\n private readonly panelNavTransition = new ChromeTransitionDepth();\n private readonly chromeSyncCoalescer = createRafCoalescer(() => this.syncChrome());\n private panelWidthTokens: PanelNavWidthTokens = { expandedPx: 0, collapsedPx: 0 };\n private cachedViewportWidth = 0;\n private cachedViewportHeight = 0;\n private onWindowResize = () => {\n this.updateResponsiveMode();\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n private onVisualViewportChange = () => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n };\n\n private get managed(): boolean {\n return this.composition === 'managed';\n }\n\n private get effectiveMobileDestination(): MobileDestination {\n return this.managed ? this.managedMobileDestination : this.mobileDestination;\n }\n\n private get effectiveMobileSheetNavOpen(): boolean {\n return this.managed ? this.managedMobileSheetNavOpen : this.mobileSheetNavOpen;\n }\n\n private get resolvedNavigationGroups() {\n if (this.navigation.groups?.length) return this.navigation.groups;\n return this.managedBrowseContext === 'settings'\n ? (this.navigation.settingsGroups ?? [])\n : (this.navigation.dashboardGroups ?? []);\n }\n\n private get resolvedToolItems() {\n return this.tools.items ?? PANEL_TOOLS_DEFAULT_ITEMS;\n }\n\n private get availableInboxTools(): ShellInboxToolId[] {\n return this.resolvedToolItems\n .filter(\n item =>\n !item.isInactive &&\n (item.mobileDestination === 'inbox' || isShellInboxTool(item.id))\n )\n .map(item => item.id as ShellInboxToolId);\n }\n\n componentWillLoad() {\n if (typeof window !== 'undefined') {\n this.resolvedMode = resolveShellResponsiveMode(window.innerWidth);\n }\n this.managedBrowseContext = this.navigation.browseContext ?? this.navStyle;\n this.managedMobileDestination = this.mobileDestination;\n this.managedMobileSheetNavOpen = this.mobileSheetNavOpen;\n this.managedInboxTool = resolveAvailableInboxTool('', this.availableInboxTools);\n }\n\n componentDidLoad() {\n this.hasLoaded = true;\n this.syncSlottedNavStyle();\n this.syncSlottedMobileState();\n this.connectMetricsObserver();\n this.connectViewportListeners();\n this.el.addEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.addEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n requestAnimationFrame(() => {\n this.cachePanelWidthTokens();\n this.scheduleChromeSync();\n });\n const tools = this.el.querySelector('ds-shell-tools, ds-panel-tools');\n this.toolsFullscreen = tools?.getAttribute('presentation') === 'fullscreen';\n }\n\n @Listen('dsPresentationChange')\n handleToolsPresentation(event: CustomEvent<{ presentation?: string }>) {\n this.toolsFullscreen = event.detail?.presentation === 'fullscreen';\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.disconnectViewportListeners();\n this.chromeSyncCoalescer.cancel();\n this.el.removeEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n this.el.removeEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n }\n\n @Watch('navStyle')\n @Watch('gradientPreset')\n onShellPropsChange() {\n this.syncSlottedNavStyle();\n this.scheduleChromeSync();\n }\n\n @Watch('navigation')\n handleNavigationChange() {\n this.managedBrowseContext = this.navigation.browseContext ?? this.navStyle;\n }\n\n @Watch('tools')\n handleToolsChange() {\n if (\n this.managedActiveTool &&\n !this.resolvedToolItems.some(item => item.id === this.managedActiveTool)\n ) {\n this.managedToolsOpen = false;\n this.managedActiveTool = '';\n this.managedMobileDestination = 'area';\n }\n this.managedInboxTool = resolveAvailableInboxTool(\n this.managedInboxTool,\n this.availableInboxTools\n );\n }\n\n @Watch('mobileDestination')\n @Watch('mobileSheetNavOpen')\n onMobileStateChange(_next: unknown, previous: unknown) {\n if (this.managed) {\n this.managedMobileDestination = this.mobileDestination;\n this.managedMobileSheetNavOpen = this.mobileSheetNavOpen;\n }\n this.syncSlottedMobileState();\n if (\n previous === true &&\n !this.effectiveMobileSheetNavOpen &&\n this.resolvedMode === 'mobile'\n ) {\n requestAnimationFrame(() => {\n const bar = this.el.querySelector('ds-mobile-bar-nav') as\n | (HTMLElement & {\n focusDestination?: (\n destination: MobileDestination | 'sheet-nav'\n ) => Promise<void>;\n })\n | null;\n const activeElement = document.activeElement;\n if (activeElement instanceof HTMLElement && bar?.contains(activeElement)) return;\n void bar?.focusDestination?.('sheet-nav');\n });\n }\n }\n\n private updateResponsiveMode() {\n if (typeof window === 'undefined') return;\n const next = resolveShellResponsiveMode(window.innerWidth);\n if (next === this.resolvedMode) return;\n this.resolvedMode = next;\n this.syncSlottedMobileState();\n this.scheduleChromeSync();\n if (this.hasLoaded) this.dsResponsiveModeChange.emit({ mode: next });\n }\n\n private onChromeTransitionStart = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.enter();\n const viewport = readShellViewportDimensions();\n this.cachedViewportWidth = viewport.width;\n this.cachedViewportHeight = viewport.height;\n this.syncChrome();\n };\n\n private onChromeTransitionEnd = (event: Event) => {\n if (readChromeTransitionSource(event) !== 'panel-nav') return;\n\n this.panelNavTransition.exit();\n if (!this.panelNavTransition.isActive) {\n this.scheduleChromeSync();\n }\n };\n\n /** Coalesce ResizeObserver bursts to one layout read per frame. */\n private scheduleChromeSync() {\n this.chromeSyncCoalescer.schedule();\n }\n\n private syncSlottedNavStyle() {\n const panel = this.el.querySelector('ds-panel-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n const bar = this.el.querySelector('ds-bar-nav') as (HTMLElement & { navStyle: NavChromeStyle }) | null;\n if (panel) {\n panel.setAttribute('nav-style', this.navStyle);\n panel.navStyle = this.navStyle;\n }\n if (bar) {\n bar.setAttribute('nav-style', this.navStyle);\n bar.navStyle = this.navStyle;\n }\n }\n\n private syncSlottedMobileState() {\n const tools = this.el.querySelector('ds-shell-tools') as\n | (HTMLElement & { responsiveMode: ShellResponsiveMode })\n | null;\n const bar = this.el.querySelector('ds-mobile-bar-nav') as\n | (HTMLElement & {\n activeDestination: MobileDestination;\n sheetNavExpanded: boolean;\n })\n | null;\n const sheetNav = this.el.querySelector('ds-mobile-sheet-nav') as\n | (HTMLElement & { open: boolean })\n | null;\n\n if (tools) {\n tools.setAttribute('responsive-mode', this.resolvedMode);\n tools.responsiveMode = this.resolvedMode;\n }\n if (bar) {\n bar.activeDestination = this.effectiveMobileDestination;\n bar.sheetNavExpanded = this.effectiveMobileSheetNavOpen;\n }\n if (sheetNav) {\n sheetNav.open = this.effectiveMobileSheetNavOpen;\n }\n }\n\n private connectMetricsObserver() {\n this.resizeObserver = new ResizeObserver(() => {\n if (this.panelNavTransition.isActive) return;\n this.scheduleChromeSync();\n });\n this.resizeObserver.observe(this.el);\n const panelWrap = this.el.querySelector('.shell-app__panel');\n if (panelWrap) this.resizeObserver.observe(panelWrap);\n }\n\n private connectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.addEventListener('resize', this.onWindowResize, { passive: true });\n\n const visual = window.visualViewport;\n if (visual) {\n visual.addEventListener('resize', this.onVisualViewportChange, { passive: true });\n visual.addEventListener('scroll', this.onVisualViewportChange, { passive: true });\n }\n }\n\n private disconnectViewportListeners() {\n if (typeof window === 'undefined') return;\n\n window.removeEventListener('resize', this.onWindowResize);\n\n const visual = window.visualViewport;\n if (visual) {\n visual.removeEventListener('resize', this.onVisualViewportChange);\n visual.removeEventListener('scroll', this.onVisualViewportChange);\n }\n }\n\n private cachePanelWidthTokens() {\n const navRoot = this.el.querySelector('ds-panel-nav .panel-nav') as HTMLElement | null;\n if (!navRoot) return;\n this.panelWidthTokens = readPanelNavWidthTokens(navRoot);\n }\n\n private applyGradientVars(target: HTMLElement, vars: Record<string, string | null>) {\n const style = target.style;\n for (const [name, value] of Object.entries(vars)) {\n if (value === null) style.removeProperty(name);\n else style.setProperty(name, value);\n }\n }\n\n private clearGradientPaintVars(targets: HTMLElement[]) {\n const keys = [\n SHELL_GRADIENT_IMAGE_VAR,\n SHELL_GRADIENT_SIZE_VAR,\n SHELL_GRADIENT_OPACITY_VAR,\n ];\n for (const target of targets) {\n for (const key of keys) target.style.removeProperty(key);\n }\n }\n\n /** Panel/bar wash offsets for scroll fades and badge rings. */\n private syncChromeLayoutVars(\n panel: HTMLElement | null,\n bar: HTMLElement | null,\n panelPosition: string,\n barPosition: string,\n ) {\n if (panel) {\n panel.style.setProperty(SHELL_GRADIENT_POSITION_PANEL_VAR, panelPosition);\n }\n if (bar) {\n bar.style.setProperty(SHELL_GRADIENT_POSITION_BAR_VAR, barPosition);\n }\n }\n\n private resolvePanelWidthPx(panelNav: HTMLElement | null): number {\n const navRoot = panelNav?.querySelector('.panel-nav') as HTMLElement | null;\n\n if (this.panelNavTransition.isActive && this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n const panelWrap = this.el.querySelector('.shell-app__panel') as HTMLElement | null;\n const measured = panelWrap?.getBoundingClientRect().width ?? 0;\n if (measured > 0) return measured;\n\n if (this.panelWidthTokens.expandedPx > 0) {\n const collapsed = isPanelNavCollapsed(panelNav, navRoot);\n return panelWidthPxFromTokens(this.panelWidthTokens, collapsed);\n }\n\n return 0;\n }\n\n /** Fixed-attachment wash/grid size — always the viewport, never the shell element box. */\n private resolveViewportDimensions(): { width: number; height: number } {\n if (this.panelNavTransition.isActive && this.cachedViewportWidth > 0) {\n return {\n width: this.cachedViewportWidth,\n height: this.cachedViewportHeight,\n };\n }\n\n return readShellViewportDimensions();\n }\n\n private chromeLayerActive(): boolean {\n return (\n this.resolvedMode !== 'mobile' &&\n normalizeShellGradientPreset(this.gradientPreset) !== 'none'\n );\n }\n\n @Listen('keydown', { target: 'window', capture: true })\n handleWindowKeyDown(e: KeyboardEvent) {\n if (!this.shortcutsEnabled) return;\n if (isEditableShortcutTarget(e.target)) return;\n\n const action = resolveShellShortcut(e);\n if (!action) return;\n\n e.preventDefault();\n\n const panel = this.el.querySelector('ds-panel-nav') as HTMLDsPanelNavElement | null;\n const tools = this.el.querySelector('ds-shell-tools, ds-panel-tools') as\n | (HTMLElement & {\n closeDrawer?: () => Promise<void>;\n activateTool?: (id: PanelToolsToolId) => Promise<void>;\n })\n | null;\n\n if (action === 'toggle-panel-nav') {\n void panel?.toggleCollapsed();\n return;\n }\n\n if (action === 'close-panel-tools') {\n void tools?.closeDrawer?.();\n return;\n }\n\n if (action.startsWith('open-tool:') && tools) {\n const toolId = action.slice('open-tool:'.length) as PanelToolsToolId;\n void tools.activateTool?.(toolId);\n }\n }\n\n /** Open or toggle a managed global tool from application-owned UI. */\n @Method()\n async activateTool(id: PanelToolsToolId) {\n const tools = this.el.querySelector('ds-shell-tools, ds-panel-tools') as\n | (HTMLElement & { activateTool?: (tool: PanelToolsToolId) => Promise<void> })\n | null;\n await tools?.activateTool?.(id);\n }\n\n /** Close whichever managed global surface is currently visible. */\n @Method()\n async closeGlobalSurface() {\n if (this.managedMobileSheetNavOpen) {\n this.managedMobileSheetNavOpen = false;\n return;\n }\n const tools = this.el.querySelector('ds-shell-tools, ds-panel-tools') as\n | (HTMLElement & { closeDrawer?: () => Promise<void> })\n | null;\n await tools?.closeDrawer?.();\n }\n\n /** Request drawer or fullscreen presentation for the active managed tool. */\n @Method()\n async setToolPresentation(presentation: 'drawer' | 'fullscreen') {\n this.managedToolPresentation = presentation;\n this.toolsFullscreen = presentation === 'fullscreen';\n }\n\n private handleManagedNavSelect = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.dsNavSelect.emit(event.detail);\n };\n\n private handleManagedTabChange = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.dsTabChange.emit(event.detail);\n };\n\n private handleManagedPageBack = (event: CustomEvent<MouseEvent>) => {\n event.stopPropagation();\n this.dsPageBack.emit(event.detail);\n };\n\n private handleManagedBreadcrumbSelect = (\n event: CustomEvent<BreadcrumbSelectDetail>\n ) => {\n event.stopPropagation();\n const forwarded = this.dsBreadcrumbSelect.emit(event.detail);\n if (forwarded.defaultPrevented) event.preventDefault();\n };\n\n private handleManagedSubsectionChange = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.dsSubsectionChange.emit(event.detail);\n };\n\n private handleManagedPageAction = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.dsPageAction.emit(event.detail);\n };\n\n private handleManagedToolChange = (\n event: CustomEvent<{ id: PanelToolsToolId; selected: boolean }>\n ) => {\n event.stopPropagation();\n const { id, selected } = event.detail;\n this.managedActiveTool = id;\n this.managedToolsOpen = selected;\n const item = this.resolvedToolItems.find(candidate => candidate.id === id);\n if (item?.mobileDestination === 'inbox' || isShellInboxTool(id)) {\n this.managedInboxTool = id;\n }\n this.managedMobileDestination = selected\n ? (item?.mobileDestination ?? shellMobileDestinationForTool(true, id))\n : 'area';\n this.managedMobileSheetNavOpen = false;\n this.dsToolChange.emit(event.detail);\n };\n\n private handleManagedPresentationChange = (\n event: CustomEvent<{ presentation: 'drawer' | 'fullscreen' }>\n ) => {\n event.stopPropagation();\n this.managedToolPresentation = event.detail.presentation;\n this.toolsFullscreen = event.detail.presentation === 'fullscreen';\n this.dsPresentationChange.emit(event.detail);\n };\n\n private handleManagedHeaderBack = (event: CustomEvent<{ tool: PanelToolsToolId }>) => {\n event.stopPropagation();\n this.dsHeaderBack.emit(event.detail);\n };\n\n private handleManagedHeaderAction = (\n event: CustomEvent<{ tool: PanelToolsToolId; id: string }>\n ) => {\n event.stopPropagation();\n this.dsHeaderAction.emit(event.detail);\n };\n\n private handleManagedSheetToggle = (event: CustomEvent<boolean>) => {\n event.stopPropagation();\n this.managedMobileSheetNavOpen = event.detail;\n if (event.detail) {\n this.managedMobileDestination = 'area';\n this.managedToolsOpen = false;\n }\n };\n\n private handleManagedMobileDestination = (\n event: CustomEvent<MobileBarNavDestinationDetail>\n ) => {\n event.stopPropagation();\n const destination = event.detail.destination;\n this.managedMobileSheetNavOpen = false;\n this.managedMobileDestination = destination;\n\n if (destination === 'area') {\n this.managedToolsOpen = false;\n return;\n }\n\n const canonicalId =\n destination === 'inbox'\n ? resolveAvailableInboxTool(this.managedInboxTool, this.availableInboxTools)\n : destination;\n if (!canonicalId) return;\n\n const item = this.resolvedToolItems.find(\n candidate =>\n candidate.id === canonicalId ||\n (destination !== 'inbox' && candidate.mobileDestination === destination)\n );\n if (!item || item.isInactive) return;\n const id = item.id;\n this.managedActiveTool = id;\n this.managedToolsOpen = true;\n if (isShellInboxTool(id)) this.managedInboxTool = id;\n this.dsToolChange.emit({ id: id as PanelToolsToolId, selected: true });\n };\n\n private handleManagedAreaSelect = (event: CustomEvent<string>) => {\n event.stopPropagation();\n this.managedMobileSheetNavOpen = false;\n this.managedMobileDestination = 'area';\n this.dsNavSelect.emit(event.detail);\n };\n\n private handleManagedBrowseContext = (event: CustomEvent<NavChromeStyle>) => {\n event.stopPropagation();\n this.managedBrowseContext = event.detail;\n this.dsBrowseContextChange.emit(event.detail);\n };\n\n private handleManagedSheetClose = (event: CustomEvent<void>) => {\n event.stopPropagation();\n this.managedMobileSheetNavOpen = false;\n };\n\n private handleManagedNavFooterAction = (event: CustomEvent<void>) => {\n event.stopPropagation();\n this.dsNavFooterAction.emit();\n };\n\n private handleManagedNavUserAction = (\n event: CustomEvent<PanelNavUserActionDetail>\n ) => {\n event.stopPropagation();\n this.dsNavUserAction.emit(event.detail);\n };\n\n private get currentArea(): PanelNavItem {\n const groups = [\n ...(this.navigation.dashboardGroups ?? []),\n ...(this.navigation.settingsGroups ?? []),\n ...this.resolvedNavigationGroups,\n ];\n const items = groups.flatMap(group => group.items);\n const activeId =\n this.navigation.activeId ||\n deriveActiveIdFromUrl(\n this.navigation.currentUrl ?? this.pageChrome.currentUrl ?? '',\n items\n );\n return (\n items.find(item => item.id === activeId) ??\n items[0] ?? {\n id: 'area',\n icon: 'MapPage',\n label: this.pageChrome.heading || 'Area',\n }\n );\n }\n\n private toolDot(id: PanelToolsToolId): boolean {\n return this.resolvedToolItems.find(item => item.id === id)?.dot ?? false;\n }\n\n private syncChrome() {\n const panelNav = this.el.querySelector('ds-panel-nav') as HTMLElement | null;\n const bar = this.el.querySelector('ds-bar-nav') as HTMLElement | null;\n const targets = [this.el, panelNav, bar].filter((el): el is HTMLElement => el !== null);\n\n const clearLayoutVars = () => {\n if (panelNav) panelNav.style.removeProperty(SHELL_GRADIENT_POSITION_PANEL_VAR);\n if (bar) bar.style.removeProperty(SHELL_GRADIENT_POSITION_BAR_VAR);\n };\n\n const preset = normalizeShellGradientPreset(this.gradientPreset);\n if (preset === 'none' || this.resolvedMode === 'mobile') {\n this.clearGradientPaintVars(targets);\n clearLayoutVars();\n return;\n }\n\n const viewport = this.resolveViewportDimensions();\n const panelWidth = this.resolvePanelWidthPx(panelNav);\n\n const panelPosition = shellGradientPositionPanel();\n const barPosition = shellGradientPositionBar(panelWidth);\n\n this.syncChromeLayoutVars(panelNav, bar, panelPosition, barPosition);\n\n const image = buildShellRadialGradient(preset);\n\n const size = shellGradientSize({\n width: viewport.width,\n height: viewport.height,\n });\n const opacity = shellGradientPresetOpacity(preset);\n\n for (const target of targets) {\n if (target === this.el) {\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: barPosition,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n });\n continue;\n }\n\n const isBar = target.tagName.toLowerCase() === 'ds-bar-nav';\n this.applyGradientVars(target, {\n [SHELL_GRADIENT_IMAGE_VAR]: image,\n [SHELL_GRADIENT_SIZE_VAR]: size,\n [SHELL_GRADIENT_OPACITY_VAR]: opacity,\n [SHELL_GRADIENT_POSITION_PANEL_VAR]: isBar ? null : panelPosition,\n [SHELL_GRADIENT_POSITION_BAR_VAR]: isBar ? barPosition : null,\n });\n }\n }\n\n private renderManagedPanelNav() {\n const navigation = this.navigation;\n return (\n <ds-panel-nav\n navStyle={this.navStyle}\n groups={this.resolvedNavigationGroups}\n breakpoint={SHELL_DESKTOP_BREAKPOINT}\n routerMode={navigation.routerMode ?? 'event'}\n activeId={navigation.activeId ?? ''}\n currentUrl={navigation.currentUrl ?? this.pageChrome.currentUrl ?? ''}\n storageKey={navigation.storageKey ?? ''}\n userName={navigation.userName ?? ''}\n userInitial={navigation.userInitial ?? ''}\n accountMenuExpanded={navigation.accountMenuExpanded ?? false}\n dashboardLabel={navigation.dashboardLabel ?? 'Dashboard'}\n settingsLabel={navigation.settingsLabel ?? 'Settings'}\n accountLabel={navigation.accountLabel ?? 'Account'}\n dashboardNavigationLabel={\n navigation.dashboardNavigationLabel ?? 'Dashboard navigation'\n }\n settingsNavigationLabel={\n navigation.settingsNavigationLabel ?? 'Settings navigation'\n }\n navigationItemsLabel={navigation.navigationLabel ?? 'Navigation items'}\n onDsNavSelect={this.handleManagedNavSelect}\n onDsNavFooterAction={this.handleManagedNavFooterAction}\n onDsNavUserAction={this.handleManagedNavUserAction}\n />\n );\n }\n\n private renderManagedBarNav() {\n return (\n <ds-bar-nav\n navStyle={this.navStyle}\n tabs={this.pageChrome.tabs ?? []}\n value={this.pageChrome.value ?? ''}\n heading={this.pageChrome.routeHeading ?? this.pageChrome.heading}\n basePath={this.pageChrome.basePath ?? ''}\n currentUrl={this.pageChrome.currentUrl ?? this.navigation.currentUrl ?? ''}\n onDsTabChange={this.handleManagedTabChange}\n />\n );\n }\n\n private renderManagedToolSlots() {\n const ids = this.resolvedToolItems.map(item => item.id);\n return ids.flatMap(id => [\n <slot name={id} slot={id} />,\n <slot name={`${id}-view`} slot={`${id}-view`} />,\n ]);\n }\n\n private renderManagedTools() {\n const tools = this.tools;\n return (\n <ds-shell-tools\n responsiveMode={this.resolvedMode}\n open={this.managedToolsOpen}\n activeTool={this.managedActiveTool}\n presentation={this.managedToolPresentation}\n fullscreenHeaderMode={tools.fullscreenHeaderMode ?? 'shared'}\n items={this.resolvedToolItems}\n headers={tools.headers ?? {}}\n storageKey={tools.storageKey ?? ''}\n toolsLabel={tools.toolsLabel ?? 'Tools'}\n toolShortcutsLabel={tools.toolShortcutsLabel ?? 'Tool shortcuts'}\n inboxLabel={tools.inboxLabel ?? 'Inbox'}\n inboxNavigationLabel={tools.inboxNavigationLabel ?? 'Inbox sections'}\n onDsToolChange={this.handleManagedToolChange}\n onDsPresentationChange={this.handleManagedPresentationChange}\n onDsHeaderBack={this.handleManagedHeaderBack}\n onDsHeaderAction={this.handleManagedHeaderAction}\n >\n {this.renderManagedToolSlots()}\n </ds-shell-tools>\n );\n }\n\n private renderManagedMobileSheetNav() {\n const navigation = this.navigation;\n return (\n <ds-mobile-sheet-nav\n open={this.managedMobileSheetNavOpen}\n browseContext={this.managedBrowseContext}\n dashboardGroups={navigation.dashboardGroups ?? navigation.groups ?? []}\n settingsGroups={navigation.settingsGroups ?? []}\n currentUrl={navigation.currentUrl ?? this.pageChrome.currentUrl ?? ''}\n navigationLabel={navigation.navigationLabel ?? 'Application navigation'}\n dashboardLabel={navigation.dashboardLabel ?? 'Dashboard'}\n settingsLabel={navigation.settingsLabel ?? 'Settings'}\n accountLabel={navigation.accountLabel ?? 'Account'}\n onDsAreaSelect={this.handleManagedAreaSelect}\n onDsBrowseContextChange={this.handleManagedBrowseContext}\n onDsClose={this.handleManagedSheetClose}\n />\n );\n }\n\n private renderManagedMobileBarNav() {\n return (\n <ds-mobile-bar-nav\n hidden={this.tools.mobileBarHidden ?? false}\n activeDestination={this.managedMobileDestination}\n currentArea={this.currentArea}\n sheetNavExpanded={this.managedMobileSheetNavOpen}\n searchLabel={this.tools.items?.find(item => item.id === 'search')?.ariaLabel ?? 'Search'}\n agentsLabel={this.tools.items?.find(item => item.id === 'agents')?.ariaLabel ?? 'Agents'}\n inboxLabel={this.tools.inboxLabel ?? 'Inbox'}\n helpLabel={this.tools.items?.find(item => item.id === 'help')?.ariaLabel ?? 'Help & Support'}\n searchDot={this.toolDot('search')}\n agentsDot={this.toolDot('agents')}\n inboxDot={\n this.toolDot('messages') || this.toolDot('stacks') || this.toolDot('activity')\n }\n onDsSheetNavToggle={this.handleManagedSheetToggle}\n onDsDestinationChange={this.handleManagedMobileDestination}\n />\n );\n }\n\n private renderManagedMobileLeading() {\n if (!this.pageChrome.showBack) {\n return <slot name=\"page-header-leading\" slot=\"leading\" />;\n }\n return [\n <ds-tooltip\n slot=\"leading\"\n label={this.pageChrome.backAriaLabel ?? 'Back'}\n side=\"bottom\"\n size=\"sm\"\n >\n <ds-button-unfilled\n variant=\"icon\"\n icon={this.pageChrome.backIcon ?? 'ChevronLeft'}\n size=\"md\"\n aria-label={this.pageChrome.backAriaLabel ?? 'Back'}\n activeFill={false}\n hasBorder={false}\n onDsClick={(event: CustomEvent<MouseEvent>) =>\n this.dsPageBack.emit(event.detail)\n }\n />\n </ds-tooltip>,\n <slot name=\"page-header-leading\" slot=\"leading\" />,\n ];\n }\n\n private renderManagedMobileActions() {\n const actions = this.pageChrome.mobileActions ?? [];\n return [\n ...actions.map((action: PanelToolsHeaderAction) => (\n <ds-tooltip\n slot=\"trailing\"\n key={action.id}\n label={action.ariaLabel}\n side=\"bottom\"\n size=\"sm\"\n >\n <ds-button-unfilled\n id={action.triggerId || undefined}\n variant=\"icon\"\n icon={action.icon}\n size=\"md\"\n aria-label={action.ariaLabel}\n haspopup={action.haspopup}\n controls={action.controls}\n expanded={action.expanded}\n pressed={action.pressed}\n isActive={!!action.expanded}\n isInactive={action.isInactive}\n activeFill={false}\n hasBorder={false}\n onDsClick={() => this.dsPageAction.emit(action.id)}\n />\n </ds-tooltip>\n )),\n <slot name=\"page-header-trailing\" slot=\"trailing\" />,\n ];\n }\n\n private renderManagedPage() {\n const page = this.pageChrome;\n const mobileSections = page.showBack ? [] : (page.tabs ?? []);\n const barTitleSections: BarTitleSectionItem[] = (page.subsections ?? []).map(item =>\n 'type' in item\n ? { type: 'divider' }\n : {\n id: item.id,\n label: item.label,\n isInactive: item.isInactive,\n }\n );\n return (\n <ds-shell-page\n responsiveMode={this.resolvedMode}\n headerCapacity={resolveManagedShellPageCapacity(\n this.resolvedMode,\n this.managedToolsOpen\n )}\n contentInset={page.contentInset ?? 'default'}\n >\n <ds-bar-title\n slot=\"header\"\n heading={page.heading ?? ''}\n description={page.description ?? ''}\n showBack={page.showBack ?? false}\n backAriaLabel={page.backAriaLabel ?? 'Back'}\n backLabel={page.backLabel ?? 'Back'}\n breadcrumbs={page.breadcrumbs ?? []}\n breadcrumbAriaLabel={page.breadcrumbAriaLabel ?? 'Breadcrumb'}\n sections={barTitleSections}\n value={page.subvalue ?? ''}\n sectionsAriaLabel={page.subsectionsAriaLabel ?? 'Change page subsection'}\n primaryAction={page.primaryAction ?? null}\n actions={page.actions ?? []}\n actionsAriaLabel={page.actionsAriaLabel ?? 'More page actions'}\n onDsBack={this.handleManagedPageBack}\n onDsBreadcrumbSelect={this.handleManagedBreadcrumbSelect}\n onDsSectionChange={this.handleManagedSubsectionChange}\n onDsAction={this.handleManagedPageAction}\n />\n <ds-mobile-header\n slot=\"mobile-header\"\n heading={page.heading ?? ''}\n headingLevel={page.headingLevel ?? 'h1'}\n sections={mobileSections}\n value={page.showBack ? '' : (page.value ?? '')}\n sectionsAriaLabel={page.sectionsAriaLabel ?? 'Change page section'}\n subsections={page.subsections ?? []}\n subvalue={page.subvalue ?? ''}\n subsectionsAriaLabel={\n page.subsectionsAriaLabel ?? 'Change page subsection'\n }\n tone={page.tone ?? 'default'}\n onDsSectionChange={this.handleManagedTabChange}\n onDsSubsectionChange={this.handleManagedSubsectionChange}\n >\n {this.renderManagedMobileLeading()}\n {this.renderManagedMobileActions()}\n </ds-mobile-header>\n <slot />\n </ds-shell-page>\n );\n }\n\n private renderSlottedShell(\n shellCls: Record<string, boolean>,\n mobile: boolean,\n mobileToolActive: boolean,\n mobileStageBlocked: boolean,\n fullscreen: boolean\n ) {\n return (\n <Host class={shellCls} responsive-mode={this.resolvedMode}>\n <div class=\"shell-app__row\">\n <div class=\"shell-app__chrome\" aria-hidden=\"true\" />\n <div\n class=\"shell-app__panel\"\n aria-hidden={fullscreen ? 'true' : undefined}\n inert={fullscreen ? true : undefined}\n >\n <slot name=\"panel\" />\n </div>\n <div class=\"shell-app__main\">\n <div\n class=\"shell-app__bar\"\n aria-hidden={fullscreen ? 'true' : undefined}\n inert={fullscreen ? true : undefined}\n >\n <slot name=\"bar\" />\n </div>\n <div\n class=\"shell-app__tools\"\n aria-hidden={\n mobile && (!mobileToolActive || this.mobileSheetNavOpen)\n ? 'true'\n : undefined\n }\n inert={\n mobile && (!mobileToolActive || this.mobileSheetNavOpen)\n ? true\n : undefined\n }\n hidden={mobile && !mobileToolActive}\n >\n <slot name=\"tools\" />\n </div>\n <div\n class=\"shell-app__content\"\n aria-hidden={fullscreen || mobileStageBlocked ? 'true' : undefined}\n inert={fullscreen || mobileStageBlocked ? true : undefined}\n >\n <slot />\n </div>\n <div\n class=\"shell-app__mobile-sheet-nav\"\n hidden={!mobile || !this.mobileSheetNavOpen}\n aria-hidden={\n mobile && this.mobileSheetNavOpen ? undefined : 'true'\n }\n inert={mobile && this.mobileSheetNavOpen ? undefined : true}\n >\n <slot name=\"mobile-sheet-nav\" />\n </div>\n <div class=\"shell-app__mobile-bar-nav\" hidden={!mobile}>\n <slot name=\"mobile-bar-nav\" />\n </div>\n </div>\n </div>\n </Host>\n );\n }\n\n render() {\n const chromeActive = this.chromeLayerActive();\n const mobile = this.resolvedMode === 'mobile';\n const mobileToolActive = mobile && this.effectiveMobileDestination !== 'area';\n const mobileStageBlocked =\n mobile && (mobileToolActive || this.effectiveMobileSheetNavOpen);\n const fullscreen = !mobile && this.toolsFullscreen;\n const shellCls: Record<string, boolean> = {\n 'shell-app': true,\n 'shell-app--gradient': chromeActive,\n [`shell-app--${this.navStyle}`]: true,\n [`shell-app--${this.resolvedMode}`]: true,\n 'shell-app--tools-fullscreen': fullscreen,\n 'shell-app--mobile-tool-active': mobileToolActive,\n 'shell-app--mobile-sheet-nav-open':\n mobile && this.effectiveMobileSheetNavOpen,\n 'shell-app--managed': this.managed,\n 'shell-app--slotted': !this.managed,\n };\n\n if (!this.managed) {\n return this.renderSlottedShell(\n shellCls,\n mobile,\n mobileToolActive,\n mobileStageBlocked,\n fullscreen\n );\n }\n\n return (\n <Host class={shellCls} responsive-mode={this.resolvedMode}>\n <div class=\"shell-app__row\">\n <div class=\"shell-app__chrome\" aria-hidden=\"true\" />\n <div class=\"shell-app__panel\" aria-hidden={fullscreen ? 'true' : undefined} inert={fullscreen ? true : undefined}>\n {this.renderManagedPanelNav()}\n </div>\n <div class=\"shell-app__main\">\n <div class=\"shell-app__bar\" aria-hidden={fullscreen ? 'true' : undefined} inert={fullscreen ? true : undefined}>\n {this.renderManagedBarNav()}\n </div>\n <div\n class=\"shell-app__tools\"\n aria-hidden={\n mobile && (!mobileToolActive || this.effectiveMobileSheetNavOpen)\n ? 'true'\n : undefined\n }\n inert={\n mobile && (!mobileToolActive || this.effectiveMobileSheetNavOpen)\n ? true\n : undefined\n }\n hidden={mobile && !mobileToolActive}\n >\n {this.renderManagedTools()}\n </div>\n <div\n class=\"shell-app__content\"\n aria-hidden={fullscreen || mobileStageBlocked ? 'true' : undefined}\n inert={fullscreen || mobileStageBlocked ? true : undefined}\n >\n {this.renderManagedPage()}\n </div>\n <div\n class=\"shell-app__mobile-sheet-nav\"\n hidden={!mobile || !this.effectiveMobileSheetNavOpen}\n aria-hidden={\n mobile && this.effectiveMobileSheetNavOpen ? undefined : 'true'\n }\n inert={mobile && this.effectiveMobileSheetNavOpen ? undefined : true}\n >\n {this.renderManagedMobileSheetNav()}\n </div>\n <div class=\"shell-app__mobile-bar-nav\" hidden={!mobile}>\n {this.renderManagedMobileBarNav()}\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n",
591
+ "type": "registry:ui"
592
+ },
593
+ {
594
+ "path": "src/wc/components/ShellApp/shell-app-types.ts",
595
+ "content": "import type { BarNavTab } from '../BarNav/bar-nav-types';\nimport type {\n BarTitleActionItem,\n BarTitlePrimaryAction,\n} from '../BarTitle/bar-title-types';\nimport type { BreadcrumbItem } from '../Breadcrumb/breadcrumb-types';\nimport type { MobileHeaderTone } from '../MobileHeader/mobile-header-types';\nimport type {\n PanelNavGroup,\n PanelNavItem,\n PanelNavRouterMode,\n} from '../PanelNav/panel-nav-types';\nimport type {\n PanelToolsHeaders,\n PanelToolsHeaderAction,\n PanelToolsItem,\n} from '../PanelTools/panel-tools-types';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\n\nexport type ShellAppComposition = 'managed' | 'slotted';\n\n/**\n * Router-owned application navigation supplied to managed ShellApp.\n * ShellApp renders the responsive chrome but never performs route changes.\n */\nexport interface ShellNavigationConfig {\n /** Groups shown in the current desktop/tablet PanelNav context. */\n groups?: PanelNavGroup[];\n /** Complete Dashboard collection used by the mobile navigation sheet. */\n dashboardGroups?: PanelNavGroup[];\n /** Complete Settings collection used by the mobile navigation sheet. */\n settingsGroups?: PanelNavGroup[];\n /** Current application URL used for active-item matching. */\n currentUrl?: string;\n /** Optional explicit active destination when URL matching is unavailable. */\n activeId?: string;\n /** Current Dashboard or Settings browsing context. */\n browseContext?: NavChromeStyle;\n /** Managed shells default to event routing so the application router stays authoritative. */\n routerMode?: PanelNavRouterMode;\n /** Persisted desktop PanelNav collapse preference key. */\n storageKey?: string;\n userName?: string;\n userInitial?: string;\n accountMenuExpanded?: boolean;\n dashboardLabel?: string;\n settingsLabel?: string;\n accountLabel?: string;\n navigationLabel?: string;\n dashboardNavigationLabel?: string;\n settingsNavigationLabel?: string;\n}\n\n/**\n * Route-owned page chrome. The same data drives desktop BarNav/BarTitle and\n * the intentionally different mobile MobileHeader presentation.\n */\nexport interface ShellPageChromeConfig {\n heading?: string;\n /** Desktop/tablet route-navigation heading when it differs from the page h1. */\n routeHeading?: string;\n description?: string;\n headingLevel?: 'h1' | 'h2';\n tabs?: BarNavTab[];\n value?: string;\n basePath?: string;\n currentUrl?: string;\n sectionsAriaLabel?: string;\n subsections?: BarNavTab[];\n subvalue?: string;\n subsectionsAriaLabel?: string;\n showBack?: boolean;\n backAriaLabel?: string;\n backIcon?: string;\n backLabel?: string;\n breadcrumbs?: BreadcrumbItem[];\n breadcrumbAriaLabel?: string;\n primaryAction?: BarTitlePrimaryAction | null;\n actions?: BarTitleActionItem[];\n /** Icon actions rendered in the mobile header's trailing lane. */\n mobileActions?: PanelToolsHeaderAction[];\n actionsAriaLabel?: string;\n tone?: MobileHeaderTone;\n contentInset?: 'default' | 'none';\n}\n\n/**\n * Product-owned global tools supplied to managed ShellApp. Tool view content\n * remains mounted in the corresponding named `*-view` slots.\n */\nexport interface ShellToolsConfig {\n items?: PanelToolsItem[];\n headers?: PanelToolsHeaders;\n storageKey?: string;\n fullscreenHeaderMode?: 'shared' | 'split';\n toolsLabel?: string;\n toolShortcutsLabel?: string;\n inboxLabel?: string;\n inboxNavigationLabel?: string;\n /** Temporarily conceal the mobile bar while a tool-owned keyboard interaction needs the space. */\n mobileBarHidden?: boolean;\n}\n\nexport interface ShellNavigationSelectDetail {\n id: string;\n item?: PanelNavItem;\n}\n",
271
596
  "type": "registry:ui"
272
597
  }
273
598
  ]