@ds-mo/ui 13.10.0 → 13.11.1
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.
- package/dist/.package-ready.json +1 -1
- package/dist/agent-patterns.json +9 -6
- package/dist/agent.json +34 -14
- package/dist/angular/ds-mobile-bar-nav.d.ts +1 -1
- package/dist/angular/ds-mobile-bar-nav.js +3 -3
- package/dist/angular/ds-shell-page.d.ts +1 -1
- package/dist/angular/ds-shell-page.js +3 -3
- package/dist/components/ds-agent-activity.js +1 -1
- package/dist/components/ds-agent-response.js +1 -1
- package/dist/components/ds-agent-source-list.js +1 -1
- package/dist/components/ds-agent-tool-call.js +1 -1
- package/dist/components/ds-attachment-list.js +1 -1
- package/dist/components/ds-avatar.js +1 -1
- package/dist/components/ds-banner.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-title.js +1 -1
- package/dist/components/ds-bar-workflow.js +1 -1
- package/dist/components/ds-button-filled.js +1 -1
- package/dist/components/ds-button-unfilled.js +1 -1
- package/dist/components/ds-card-chart.js +1 -1
- package/dist/components/ds-card-overview.js +1 -1
- package/dist/components/ds-card-overview.js.map +1 -1
- package/dist/components/ds-card-setting.js +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-code-block.js +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-icon.js +1 -1
- package/dist/components/ds-input.js +1 -1
- package/dist/components/ds-markdown.js +1 -1
- package/dist/components/ds-message-actions.js +1 -1
- package/dist/components/ds-message-composer.js +1 -1
- package/dist/components/ds-message-scroller.js +1 -1
- package/dist/components/ds-mobile-bar-nav.js +1 -1
- package/dist/components/ds-mobile-sheet-nav.js +1 -1
- package/dist/components/ds-modal.js +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-tool-header.js +1 -1
- package/dist/components/ds-panel-tool-search.js +1 -1
- package/dist/components/ds-panel-tools.js +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-shell-app.js +1 -1
- package/dist/components/ds-shell-app.js.map +1 -1
- package/dist/components/ds-shell-page.js +1 -1
- package/dist/components/ds-shell-tools.js +1 -1
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-tag.js +1 -1
- package/dist/components/ds-toast.js +1 -1
- package/dist/components/p-BHb3Ws8e.js +2 -0
- package/dist/components/p-BHb3Ws8e.js.map +1 -0
- package/dist/components/{p-BtS5na9O.js → p-BRajO-Za.js} +2 -2
- package/dist/components/{p-BQDi0v_h.js → p-BX57q1Lo.js} +2 -2
- package/dist/components/{p-Dv8_hmUZ.js → p-C5gZHZHU.js} +2 -2
- package/dist/components/p-CE82aQZr.js +2 -0
- package/dist/components/p-CE82aQZr.js.map +1 -0
- package/dist/components/{p-HIg1XX62.js → p-CIlO_j3q.js} +2 -2
- package/dist/components/p-CIlO_j3q.js.map +1 -0
- package/dist/components/{p-CnbrksLl.js → p-CVmtbj-6.js} +2 -2
- package/dist/components/{p-BjoyHNaM.js → p-CdFnvBem.js} +2 -2
- package/dist/components/{p-BP-EtYbR.js → p-DAbaMtEX.js} +2 -2
- package/dist/components/{p-KFHFBznh.js → p-DBJJiSP0.js} +2 -2
- package/dist/components/{p-D8qgVmHn.js → p-DBchq8Zw.js} +2 -2
- package/dist/components/{p-BYB0f1_F.js → p-DCN04sgt.js} +2 -2
- package/dist/components/{p-D2dQyoyK.js → p-DGkWMhHO.js} +2 -2
- package/dist/components/{p-2inC7Jm-.js → p-DJGdoPMG.js} +2 -2
- package/dist/components/p-DNpE0RBz.js +2 -0
- package/dist/components/p-DNpE0RBz.js.map +1 -0
- package/dist/components/{p-BjIYFiuQ.js → p-DcmqsAMP.js} +2 -2
- package/dist/components/p-DkhE3BsH.js +2 -0
- package/dist/components/p-DkhE3BsH.js.map +1 -0
- package/dist/components/{p-B4VlfBNc.js → p-Doz2uwRv.js} +2 -2
- package/dist/components/p-DumWT7NN.js +2 -0
- package/dist/components/p-DumWT7NN.js.map +1 -0
- package/dist/components/{p-Cog5NTLa.js → p-Xftomzsv.js} +2 -2
- package/dist/components/{p-DJ0XMH9E.js → p-c1pY-Mqq.js} +2 -2
- package/dist/docs/components.json +121 -9
- package/dist/lib/components/PanelTools/panel-tools-types.d.ts +3 -3
- package/dist/lib/components/ShellApp/shell-app-types.d.ts +4 -1
- package/dist/lib/components/ShellPage/shell-page-types.d.ts +5 -0
- package/dist/lib/shell/index.d.ts +1 -0
- package/dist/lib/shell/index.js +12 -11
- package/dist/lib/shell/index.js.map +2 -2
- package/dist/lib/shell/shell-responsive.d.ts +1 -1
- package/dist/mcp-data/registry/agent-activity.json +1 -1
- package/dist/mcp-data/registry/agent-response.json +1 -1
- package/dist/mcp-data/registry/agent-source-list.json +1 -1
- package/dist/mcp-data/registry/agent-tool-call.json +1 -1
- package/dist/mcp-data/registry/attachment-list.json +1 -1
- package/dist/mcp-data/registry/avatar.json +1 -1
- package/dist/mcp-data/registry/badge.json +1 -1
- package/dist/mcp-data/registry/banner.json +1 -1
- package/dist/mcp-data/registry/bar-nav.json +1 -1
- package/dist/mcp-data/registry/bar-title.json +3 -2
- package/dist/mcp-data/registry/bar-workflow.json +1 -1
- package/dist/mcp-data/registry/breadcrumb.json +1 -1
- package/dist/mcp-data/registry/button-filled.json +1 -1
- package/dist/mcp-data/registry/button-unfilled.json +1 -1
- package/dist/mcp-data/registry/card-chart.json +1 -1
- package/dist/mcp-data/registry/card-overview.json +5 -5
- package/dist/mcp-data/registry/card-setting.json +1 -1
- package/dist/mcp-data/registry/chart-legend.json +1 -1
- package/dist/mcp-data/registry/chart.json +1 -1
- package/dist/mcp-data/registry/checkbox.json +1 -1
- package/dist/mcp-data/registry/chip.json +1 -1
- package/dist/mcp-data/registry/code-block.json +1 -1
- package/dist/mcp-data/registry/conversation-list-item.json +1 -1
- package/dist/mcp-data/registry/conversation-list-section.json +1 -1
- package/dist/mcp-data/registry/conversation-list.json +1 -1
- package/dist/mcp-data/registry/divider.json +1 -1
- package/dist/mcp-data/registry/empty-state.json +1 -1
- package/dist/mcp-data/registry/field.json +1 -1
- package/dist/mcp-data/registry/icon.json +2 -2
- package/dist/mcp-data/registry/input.json +1 -1
- package/dist/mcp-data/registry/loader.json +1 -1
- package/dist/mcp-data/registry/markdown.json +1 -1
- package/dist/mcp-data/registry/menu.json +1 -1
- package/dist/mcp-data/registry/message-actions.json +1 -1
- package/dist/mcp-data/registry/message-bubble.json +1 -1
- package/dist/mcp-data/registry/message-composer.json +1 -1
- package/dist/mcp-data/registry/message-scroller.json +1 -1
- package/dist/mcp-data/registry/message.json +1 -1
- package/dist/mcp-data/registry/mobile-bar-nav.json +39 -7
- package/dist/mcp-data/registry/mobile-header.json +1 -1
- package/dist/mcp-data/registry/mobile-section-switcher.json +1 -1
- package/dist/mcp-data/registry/mobile-sheet-nav.json +1 -1
- package/dist/mcp-data/registry/modal.json +1 -1
- package/dist/mcp-data/registry/panel-nav.json +1 -1
- package/dist/mcp-data/registry/panel-sub-nav.json +1 -1
- package/dist/mcp-data/registry/panel-tool-header.json +1 -1
- package/dist/mcp-data/registry/panel-tool-search.json +1 -1
- package/dist/mcp-data/registry/panel-tools.json +3 -3
- package/dist/mcp-data/registry/radio.json +1 -1
- package/dist/mcp-data/registry/registry.json +34 -14
- package/dist/mcp-data/registry/scroll-overlay.json +1 -1
- package/dist/mcp-data/registry/select.json +1 -1
- package/dist/mcp-data/registry/shell-app.json +6 -5
- package/dist/mcp-data/registry/shell-page.json +33 -9
- package/dist/mcp-data/registry/shell-tools.json +4 -4
- package/dist/mcp-data/registry/skeleton.json +1 -1
- package/dist/mcp-data/registry/slider.json +1 -1
- package/dist/mcp-data/registry/swatch-picker.json +1 -1
- package/dist/mcp-data/registry/switch.json +1 -1
- package/dist/mcp-data/registry/tab-group.json +1 -1
- package/dist/mcp-data/registry/tag.json +1 -1
- package/dist/mcp-data/registry/text.json +1 -1
- package/dist/mcp-data/registry/toast.json +1 -1
- package/dist/mcp-data/registry/tooltip-chart.json +1 -1
- package/dist/mcp-data/registry/tooltip.json +1 -1
- package/dist/mcp-data/registry/typing-indicator.json +1 -1
- package/dist/types/components/CardOverview/card-overview-types.d.ts +0 -2
- package/dist/types/components/MobileBarNav/MobileBarNav.d.ts +4 -2
- package/dist/types/components/PanelTools/panel-tools-types.d.ts +3 -3
- package/dist/types/components/ShellApp/shell-app-types.d.ts +4 -1
- package/dist/types/components/ShellPage/ShellPage.d.ts +3 -1
- package/dist/types/components/ShellPage/index.d.ts +1 -1
- package/dist/types/components/ShellPage/shell-page-types.d.ts +1 -0
- package/dist/types/components.d.ts +33 -4
- package/dist/types/shell/index.d.ts +1 -0
- package/dist/types/shell/shell-responsive.d.ts +1 -1
- package/package.json +4 -4
- package/dist/components/p-B16OuqyJ.js +0 -2
- package/dist/components/p-B16OuqyJ.js.map +0 -1
- package/dist/components/p-BAfG3M8z.js +0 -2
- package/dist/components/p-BAfG3M8z.js.map +0 -1
- package/dist/components/p-BkWhTEqe.js +0 -2
- package/dist/components/p-BkWhTEqe.js.map +0 -1
- package/dist/components/p-BnQXAbif.js +0 -2
- package/dist/components/p-BnQXAbif.js.map +0 -1
- package/dist/components/p-HIg1XX62.js.map +0 -1
- package/dist/components/p-iyiOFsws.js +0 -2
- package/dist/components/p-iyiOFsws.js.map +0 -1
- /package/dist/components/{p-BtS5na9O.js.map → p-BRajO-Za.js.map} +0 -0
- /package/dist/components/{p-BQDi0v_h.js.map → p-BX57q1Lo.js.map} +0 -0
- /package/dist/components/{p-Dv8_hmUZ.js.map → p-C5gZHZHU.js.map} +0 -0
- /package/dist/components/{p-CnbrksLl.js.map → p-CVmtbj-6.js.map} +0 -0
- /package/dist/components/{p-BjoyHNaM.js.map → p-CdFnvBem.js.map} +0 -0
- /package/dist/components/{p-BP-EtYbR.js.map → p-DAbaMtEX.js.map} +0 -0
- /package/dist/components/{p-KFHFBznh.js.map → p-DBJJiSP0.js.map} +0 -0
- /package/dist/components/{p-D8qgVmHn.js.map → p-DBchq8Zw.js.map} +0 -0
- /package/dist/components/{p-BYB0f1_F.js.map → p-DCN04sgt.js.map} +0 -0
- /package/dist/components/{p-D2dQyoyK.js.map → p-DGkWMhHO.js.map} +0 -0
- /package/dist/components/{p-2inC7Jm-.js.map → p-DJGdoPMG.js.map} +0 -0
- /package/dist/components/{p-BjIYFiuQ.js.map → p-DcmqsAMP.js.map} +0 -0
- /package/dist/components/{p-B4VlfBNc.js.map → p-Doz2uwRv.js.map} +0 -0
- /package/dist/components/{p-Cog5NTLa.js.map → p-Xftomzsv.js.map} +0 -0
- /package/dist/components/{p-DJ0XMH9E.js.map → p-c1pY-Mqq.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
3
|
"name": "shell-page",
|
|
4
4
|
"title": "ShellPage",
|
|
5
|
-
"description": "The standard routed-page boundary inside ShellApp, owning sticky BarTitle or BarWorkflow placement, application-supplied BarTitle capacity, stable scroll compaction, and
|
|
5
|
+
"description": "The standard routed-page boundary inside ShellApp, owning sticky BarTitle or BarWorkflow placement, application-supplied BarTitle capacity, stable scroll compaction, and independent page-content inset and canvas surface without creating a nested scroll container.",
|
|
6
6
|
"type": "registry:ui",
|
|
7
7
|
"meta": {
|
|
8
8
|
"library": "@ds-mo/ui",
|
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
"intent": {
|
|
14
14
|
"audience": "general",
|
|
15
15
|
"status": "stable",
|
|
16
|
-
"summary": "The standard routed-page boundary inside ShellApp, owning sticky BarTitle or BarWorkflow placement, application-supplied BarTitle capacity, stable scroll compaction, and
|
|
16
|
+
"summary": "The standard routed-page boundary inside ShellApp, owning sticky BarTitle or BarWorkflow placement, application-supplied BarTitle capacity, stable scroll compaction, and independent page-content inset and canvas surface without creating a nested scroll container.",
|
|
17
17
|
"useWhen": [
|
|
18
18
|
"Rendering a standard routed page inside ShellApp's default content region.",
|
|
19
19
|
"BarTitle should expand at a roomy page top, compact after scroll, or use constrained action layout when the application shell reports reduced capacity.",
|
|
20
20
|
"BarWorkflow needs sticky page-level placement while remaining compact.",
|
|
21
|
-
"Pages need consistent content gutters with an explicit full-bleed option."
|
|
21
|
+
"Pages need consistent content gutters with an explicit full-bleed option.",
|
|
22
|
+
"The page canvas surrounding routed content must use either the primary or secondary application surface."
|
|
22
23
|
],
|
|
23
24
|
"avoidWhen": [
|
|
24
25
|
"Building authentication, onboarding, public, modal, drawer, or intentionally focused fullscreen layouts outside the standard ShellApp page region.",
|
|
@@ -57,6 +58,8 @@
|
|
|
57
58
|
"headerPresentation=auto selects the matching header variant from headerCapacity and scroll position.",
|
|
58
59
|
"expanded, compact, and constrained are explicit overrides for exceptional layouts and deterministic examples.",
|
|
59
60
|
"contentInset=default supplies standard page gutters; none permits maps, canvases, and other full-bleed content.",
|
|
61
|
+
"contentSurface=primary keeps the standard page canvas; secondary paints both the inset gutter and the canvas beneath routed content. Desktop and tablet BarTitle chrome matches that canvas in expanded, compact, and constrained presentations; MobileHeader remains primary.",
|
|
62
|
+
"contentInset and contentSurface are independent: either surface supports standard responsive gutters or a full-bleed page-owned layout.",
|
|
60
63
|
"The header slot accepts one desktop BarTitle or BarWorkflow; mobile-header accepts the corresponding MobileHeader presentation. The default slot owns router output and all page product content."
|
|
61
64
|
],
|
|
62
65
|
"responsiveBehavior": [
|
|
@@ -65,7 +68,10 @@
|
|
|
65
68
|
"A ShellPage-managed BarTitle remains concealed until headerCapacity is available and its rendered variant matches the resolved presentation, preventing a default-variant flash during route activation.",
|
|
66
69
|
"responsiveMode=mobile hides and inerts the desktop header, exposes mobile-header, and disables desktop scroll-compaction geometry.",
|
|
67
70
|
"Update headerCapacity synchronously with shell layout state so opening tools or crossing application breakpoints cannot briefly render the wrong presentation.",
|
|
68
|
-
"The default content inset is 32px in desktop mode and 16px in tablet and mobile modes
|
|
71
|
+
"The default content inset is balanced on every side: 32px in desktop mode and 16px in tablet and mobile modes.",
|
|
72
|
+
"The selected content surface persists unchanged across desktop, tablet, and mobile modes.",
|
|
73
|
+
"On a secondary desktop or tablet page, BarTitle matches the page canvas across capacity and scroll-driven variant changes; the separate mobile-header presentation remains primary.",
|
|
74
|
+
"The flow-preservation spacer follows contentSurface so compacting a secondary page cannot expose a primary strip before its content.",
|
|
69
75
|
"On roomy pages, the expanded header scrolls upward until its title and action row reaches the compact row position, while its bottom divider progressively extends from the expanded inset to edge-to-edge; it then snaps variants without moving that shared visual anchor.",
|
|
70
76
|
"Scroll compaction preserves the expanded page flow offset so content never jumps beneath the sticky header.",
|
|
71
77
|
"ShellPage relies on ShellApp's content scroller and never introduces nested scrolling.",
|
|
@@ -78,7 +84,7 @@
|
|
|
78
84
|
],
|
|
79
85
|
"react": [
|
|
80
86
|
"Render the desktop header with slot=header and DsMobileHeader with slot=mobile-header inside DsShellPage.",
|
|
81
|
-
"Use contentInset none only for deliberately full-bleed page products."
|
|
87
|
+
"Use contentInset none only for deliberately full-bleed page products, and choose contentSurface independently from the page's spacing model."
|
|
82
88
|
],
|
|
83
89
|
"angular": [
|
|
84
90
|
"Import the generated standalone DsShellPage adapter with the desktop header and DsMobileHeader, preserve both header slots, and place router-outlet in the default slot.",
|
|
@@ -111,6 +117,15 @@
|
|
|
111
117
|
"mutable": false,
|
|
112
118
|
"description": "Standard page gutters, or no inset for full-bleed page content."
|
|
113
119
|
},
|
|
120
|
+
"contentSurface": {
|
|
121
|
+
"type": "ShellPageContentSurface",
|
|
122
|
+
"resolvedType": "\"primary\" | \"secondary\"",
|
|
123
|
+
"attribute": "content-surface",
|
|
124
|
+
"default": "'primary'",
|
|
125
|
+
"required": false,
|
|
126
|
+
"mutable": false,
|
|
127
|
+
"description": "Canvas surface painted around and beneath routed page content."
|
|
128
|
+
},
|
|
114
129
|
"headerCapacity": {
|
|
115
130
|
"type": "ShellPageCapacity",
|
|
116
131
|
"resolvedType": "\"compact\" | \"constrained\" | \"roomy\" | undefined",
|
|
@@ -152,6 +167,15 @@
|
|
|
152
167
|
"mutable": false,
|
|
153
168
|
"description": "Standard page gutters, or no inset for full-bleed page content."
|
|
154
169
|
},
|
|
170
|
+
"contentSurface": {
|
|
171
|
+
"type": "ShellPageContentSurface",
|
|
172
|
+
"resolvedType": "\"primary\" | \"secondary\"",
|
|
173
|
+
"attribute": "content-surface",
|
|
174
|
+
"default": "'primary'",
|
|
175
|
+
"required": false,
|
|
176
|
+
"mutable": false,
|
|
177
|
+
"description": "Canvas surface painted around and beneath routed page content."
|
|
178
|
+
},
|
|
155
179
|
"headerCapacity": {
|
|
156
180
|
"type": "ShellPageCapacity",
|
|
157
181
|
"resolvedType": "\"compact\" | \"constrained\" | \"roomy\" | undefined",
|
|
@@ -205,7 +229,7 @@
|
|
|
205
229
|
"peerDependencies": {
|
|
206
230
|
"required": [
|
|
207
231
|
"@ds-mo/tokens ^6.0.0",
|
|
208
|
-
"@ds-mo/icons ^6.
|
|
232
|
+
"@ds-mo/icons ^6.5.0"
|
|
209
233
|
],
|
|
210
234
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
211
235
|
}
|
|
@@ -219,12 +243,12 @@
|
|
|
219
243
|
"files": [
|
|
220
244
|
{
|
|
221
245
|
"path": "src/wc/components/ShellPage/ShellPage.css",
|
|
222
|
-
"content": ":host {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 100%;\n box-sizing: border-box;\n background: var(--color-background-
|
|
246
|
+
"content": ":host {\n --_shell-page-content-background: var(--color-background-primary);\n --_shell-page-header-background: var(--color-background-primary);\n display: block;\n position: relative;\n min-width: 0;\n min-height: 100%;\n box-sizing: border-box;\n background: var(--_shell-page-content-background);\n}\n\n:host(.shell-page-host--surface-secondary) {\n --_shell-page-content-background: var(--color-background-secondary);\n}\n\n:host(.shell-page-host--surface-secondary[responsive-mode='desktop']),\n:host(.shell-page-host--surface-secondary[responsive-mode='tablet']) {\n --_shell-page-header-background: var(--color-background-secondary);\n}\n\n.shell-page__scroll-sentinel {\n position: absolute;\n inset-block-start: var(--ds-shell-page-header-travel, 0);\n inset-inline-start: 0;\n width: var(--dimension-stroke-width-012);\n height: var(--dimension-stroke-width-012);\n pointer-events: none;\n}\n\n.shell-page__sticky-header {\n position: sticky;\n inset-block-start: var(--ds-shell-page-sticky-offset, 0);\n z-index: var(--dimension-z-index-raised);\n min-width: 0;\n background: var(--_shell-page-header-background);\n overflow: visible;\n overflow-anchor: none;\n}\n\n.shell-page__desktop-header ::slotted(ds-bar-title),\n.shell-page__desktop-header ::slotted(ds-bar-workflow),\n.shell-page__mobile-header ::slotted(ds-mobile-header) {\n display: block;\n min-width: 0;\n}\n\n.shell-page__desktop-header[hidden],\n.shell-page__mobile-header[hidden] {\n display: none;\n}\n\n:host(.shell-page-host--mobile) .shell-page__scroll-sentinel,\n:host(.shell-page-host--mobile) .shell-page__flow-spacer {\n display: none;\n}\n\n.shell-page__flow-spacer {\n height: var(--ds-shell-page-flow-spacer, 0);\n background: var(--_shell-page-content-background);\n}\n\n.shell-page__content {\n min-width: 0;\n box-sizing: border-box;\n background: var(--_shell-page-content-background);\n}\n\n:host(.shell-page-host--inset-default) .shell-page__content {\n padding: var(--dimension-space-400);\n}\n\n:host(.shell-page-host--inset-default[responsive-mode='tablet']) .shell-page__content,\n:host(.shell-page-host--inset-default[responsive-mode='mobile']) .shell-page__content {\n padding: var(--dimension-space-200);\n}\n\n:host(.shell-page-host--inset-none) .shell-page__content {\n padding: 0;\n}\n",
|
|
223
247
|
"type": "registry:ui"
|
|
224
248
|
},
|
|
225
249
|
{
|
|
226
250
|
"path": "src/wc/components/ShellPage/ShellPage.tsx",
|
|
227
|
-
"content": "import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';\nimport type { ShellResponsiveMode } from '../../shell/shell-responsive';\nimport { resolveCssLengthPx } from '../../utils/resolve-css-length-px';\nimport type { BarTitleVariant } from '../BarTitle/bar-title-types';\nimport { resolveShellPageHeaderVariant } from './shell-page-responsive';\nimport type {\n ShellPageCapacity,\n ShellPageContentInset,\n ShellPageHeaderPresentation,\n} from './shell-page-types';\n\ntype BarTitleElement = HTMLElement & { variant: BarTitleVariant };\n\n@Component({\n tag: 'ds-shell-page',\n styleUrl: 'ShellPage.css',\n scoped: true,\n})\nexport class ShellPage {\n private static readonly MAX_HEADER_REVEAL_FRAMES = 12;\n private static readonly MAX_HEADER_GEOMETRY_FRAMES = 12;\n\n @Element() el!: HTMLElement;\n\n /** Automatic capacity/scroll behavior, or an explicit header variant override. */\n @Prop() headerPresentation: ShellPageHeaderPresentation = 'auto';\n\n /** Available page-header capacity supplied by the owning application shell. */\n @Prop() headerCapacity?: ShellPageCapacity;\n\n /** Standard page gutters, or no inset for full-bleed page content. */\n @Prop() contentInset: ShellPageContentInset = 'default';\n\n /** Explicit shell breakpoint presentation. Mobile uses the dedicated mobile-header slot. */\n @Prop({ attribute: 'responsive-mode', reflect: true })\n responsiveMode: ShellResponsiveMode = 'desktop';\n\n @State() private pageTopVisible = true;\n\n private sentinelEl: HTMLElement | null = null;\n private spacerEl: HTMLElement | null = null;\n private stickyHeaderEl: HTMLElement | null = null;\n private headerEl: BarTitleElement | null = null;\n private expandedHeaderHeight = 0;\n private headerTravel = 0;\n private expandedGeometryFrozen = false;\n private headerResizeObserver: ResizeObserver | null = null;\n private headerMutationObserver: MutationObserver | null = null;\n private headerRevealFrame: number | null = null;\n private headerGeometryFrame: number | null = null;\n private reconnectFrame: number | null = null;\n private scrollRoot: HTMLElement | Window | null = null;\n private hasLoaded = false;\n\n @Watch('headerCapacity')\n @Watch('headerPresentation')\n handleHeaderContractChange() {\n this.syncHeaderVariant(true);\n }\n\n @Watch('responsiveMode')\n handleResponsiveModeChange() {\n this.observeHeader(this.responsiveMode === 'mobile' ? null : this.findHeader());\n }\n\n componentDidLoad() {\n this.hasLoaded = true;\n this.connectRuntime();\n }\n\n componentDidRender() {\n this.syncHeaderVariant();\n }\n\n connectedCallback() {\n if (!this.hasLoaded) return;\n if (this.reconnectFrame !== null) cancelAnimationFrame(this.reconnectFrame);\n this.reconnectFrame = requestAnimationFrame(() => {\n this.reconnectFrame = null;\n if (this.el.isConnected) this.connectRuntime();\n });\n }\n\n disconnectedCallback() {\n if (this.reconnectFrame !== null) cancelAnimationFrame(this.reconnectFrame);\n this.reconnectFrame = null;\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.headerEl?.style.removeProperty('--ds-bar-title-divider-inset');\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = null;\n }\n\n private connectRuntime() {\n this.observeHeader(this.responsiveMode === 'mobile' ? null : this.findHeader());\n this.connectScrollRoot();\n }\n\n private get effectiveVariant(): BarTitleVariant {\n return resolveShellPageHeaderVariant(\n this.headerPresentation,\n this.headerCapacity ?? 'roomy',\n this.pageTopVisible\n );\n }\n\n private get headerContractResolved(): boolean {\n return this.headerPresentation !== 'auto' || this.headerCapacity !== undefined;\n }\n\n private get isScrollCompacted(): boolean {\n return (\n this.headerPresentation === 'auto' && this.headerCapacity === 'roomy' && !this.pageTopVisible\n );\n }\n\n private composedParent(element: Element): Element | null {\n return (element as HTMLElement).assignedSlot?.parentElement ?? element.parentElement;\n }\n\n private findScrollRoot(): HTMLElement | Window {\n let ancestor = this.composedParent(this.el);\n while (ancestor && ancestor !== document.documentElement) {\n const overflow = getComputedStyle(ancestor).overflowY;\n if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') {\n return ancestor as HTMLElement;\n }\n ancestor = this.composedParent(ancestor);\n }\n return window;\n }\n\n private connectScrollRoot() {\n const next = this.findScrollRoot();\n if (next === this.scrollRoot) return;\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = next;\n this.scrollRoot.addEventListener('scroll', this.handleScroll, { passive: true });\n this.handleScroll();\n }\n\n private get scrollRootResolved(): boolean {\n const shell = this.el.closest('ds-shell-app');\n if (!shell) return true;\n const expected = shell.querySelector<HTMLElement>('.shell-app__content');\n return expected !== null && this.scrollRoot === expected;\n }\n\n private handleScroll = () => {\n if (!this.sentinelEl || !this.scrollRoot) return;\n const rootTop =\n this.scrollRoot === window ? 0 : (this.scrollRoot as HTMLElement).getBoundingClientRect().top;\n this.syncHeaderDividerInset(rootTop);\n const nextPageTopVisible = this.sentinelEl.getBoundingClientRect().top >= rootTop;\n if (\n !nextPageTopVisible &&\n this.pageTopVisible &&\n this.headerEl?.classList.contains(this.variantClass('expanded'))\n ) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n this.expandedGeometryFrozen = true;\n }\n if (\n nextPageTopVisible &&\n this.expandedGeometryFrozen &&\n this.el.getBoundingClientRect().top >= rootTop\n ) {\n this.expandedGeometryFrozen = false;\n if (this.headerEl?.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n }\n }\n this.pageTopVisible = nextPageTopVisible;\n };\n\n private findHeader(): BarTitleElement | null {\n return this.el.querySelector<BarTitleElement>('ds-bar-title');\n }\n\n private get compactHeaderHeight(): number {\n return resolveCssLengthPx('--dimension-size-600', 0);\n }\n\n private syncHeaderDividerInset(rootTop?: number) {\n const header = this.headerEl;\n if (!header) return;\n\n const ownsScrollTransition =\n this.headerPresentation === 'auto' && this.headerCapacity === 'roomy';\n const expandedInset = resolveCssLengthPx('--dimension-space-400', 0);\n if (\n !ownsScrollTransition ||\n !this.sentinelEl ||\n !this.scrollRoot ||\n this.headerTravel <= 0 ||\n expandedInset <= 0\n ) {\n header.style.removeProperty('--ds-bar-title-divider-inset');\n return;\n }\n\n const scrollRootTop =\n rootTop ??\n (this.scrollRoot === window\n ? 0\n : (this.scrollRoot as HTMLElement).getBoundingClientRect().top);\n const remainingTravel = this.sentinelEl.getBoundingClientRect().top - scrollRootTop;\n const progress = Math.min(1, Math.max(0, 1 - remainingTravel / this.headerTravel));\n header.style.setProperty('--ds-bar-title-divider-inset', `${expandedInset * (1 - progress)}px`);\n }\n\n private setHeaderTravel(distance: number) {\n const next = Math.max(0, distance);\n if (Math.abs(next - this.headerTravel) < 0.5) return;\n this.headerTravel = next;\n this.el.style.setProperty('--ds-shell-page-header-travel', `${next}px`);\n this.handleScroll();\n }\n\n private measureHeaderTravel(header: BarTitleElement) {\n const anchor = header.querySelector<HTMLElement>('[data-shell-page-header-anchor]');\n const compactHeight = this.compactHeaderHeight;\n if (!anchor || compactHeight <= 0) return;\n\n const headerRect = header.getBoundingClientRect();\n const anchorRect = anchor.getBoundingClientRect();\n if (headerRect.height <= 0 || anchorRect.height <= 0) return;\n\n const expandedAnchorTop = anchorRect.top - headerRect.top;\n const compactAnchorTop = Math.max(0, (compactHeight - anchorRect.height) / 2);\n this.setHeaderTravel(expandedAnchorTop - compactAnchorTop);\n }\n\n private captureExpandedHeaderGeometry(header: BarTitleElement) {\n this.expandedHeaderHeight = header.getBoundingClientRect().height;\n this.measureHeaderTravel(header);\n }\n\n private setSpacerHeight(height: number) {\n if (!this.spacerEl) return;\n this.spacerEl.style.setProperty('--ds-shell-page-flow-spacer', `${Math.max(0, height)}px`);\n }\n\n private variantClass(variant: BarTitleVariant): string {\n return `bar-title-host--${variant}`;\n }\n\n private setStickyHeaderOffset(renderedVariant: BarTitleVariant) {\n this.stickyHeaderEl?.style.setProperty(\n '--ds-shell-page-sticky-offset',\n renderedVariant === 'expanded' &&\n this.headerPresentation === 'auto' &&\n this.headerCapacity === 'roomy'\n ? `${-this.headerTravel}px`\n : '0px'\n );\n }\n\n private syncRenderedHeaderGeometry(header: BarTitleElement) {\n const renderedVariant = this.effectiveVariant;\n if (!header.classList.contains(this.variantClass(renderedVariant))) return;\n\n // Update both flow-preservation pieces before reading layout. Otherwise a\n // reverse compact → expanded render can briefly contain the tall header and\n // the compact spacer together, giving browser scroll anchoring a transient\n // height change to compensate.\n this.setSpacerHeight(\n this.isScrollCompacted ? this.expandedHeaderHeight - this.compactHeaderHeight : 0\n );\n this.setStickyHeaderOffset(renderedVariant);\n\n if (renderedVariant === 'expanded' && !this.expandedGeometryFrozen) {\n this.captureExpandedHeaderGeometry(header);\n this.setStickyHeaderOffset(renderedVariant);\n }\n }\n\n private cancelHeaderGeometrySync() {\n if (this.headerGeometryFrame !== null) cancelAnimationFrame(this.headerGeometryFrame);\n this.headerGeometryFrame = null;\n }\n\n private scheduleHeaderGeometrySync(header: BarTitleElement) {\n this.cancelHeaderGeometrySync();\n let framesRemaining = ShellPage.MAX_HEADER_GEOMETRY_FRAMES;\n let framesElapsed = 0;\n const sync = () => {\n if (this.headerEl !== header) return;\n framesRemaining -= 1;\n framesElapsed += 1;\n // In WebKit a child's componentDidLoad can precede its assignment into\n // the parent's rendered slot. Revalidate after ShellApp has had a frame\n // to expose the actual content scroller.\n this.connectScrollRoot();\n this.syncRenderedHeaderGeometry(header);\n const geometryReady =\n this.effectiveVariant !== 'expanded' ||\n (this.expandedHeaderHeight > 0 && this.headerTravel > 0);\n if (\n (geometryReady && this.scrollRootResolved && framesElapsed >= 2) ||\n framesRemaining <= 0\n ) {\n this.headerGeometryFrame = null;\n return;\n }\n this.headerGeometryFrame = requestAnimationFrame(sync);\n };\n this.headerGeometryFrame = requestAnimationFrame(sync);\n }\n\n private cancelHeaderReveal() {\n if (this.headerRevealFrame !== null) cancelAnimationFrame(this.headerRevealFrame);\n this.headerRevealFrame = null;\n this.headerEl?.removeAttribute('data-shell-page-syncing');\n }\n\n private revealHeaderWhenSynced(header: BarTitleElement, variant: BarTitleVariant) {\n // Stencil normally re-renders within a frame or two of a prop change. Stop\n // polling at the cap, but fail closed: a stale variant must never paint.\n let framesRemaining = ShellPage.MAX_HEADER_REVEAL_FRAMES;\n const reveal = () => {\n if (this.headerEl !== header) {\n header.removeAttribute('data-shell-page-syncing');\n return;\n }\n framesRemaining -= 1;\n if (header.classList.contains(this.variantClass(variant))) {\n header.removeAttribute('data-shell-page-syncing');\n this.headerRevealFrame = null;\n return;\n }\n if (framesRemaining <= 0) {\n this.headerRevealFrame = null;\n return;\n }\n this.headerRevealFrame = requestAnimationFrame(reveal);\n };\n this.headerRevealFrame = requestAnimationFrame(reveal);\n }\n\n private syncHeaderVariant(concealUntilSynced = false) {\n const header = this.headerEl;\n if (!header) return;\n\n this.syncHeaderDividerInset();\n if (!this.headerContractResolved) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n return;\n }\n\n const next = this.effectiveVariant;\n const renderedVariantIsStale = !header.classList.contains(this.variantClass(next));\n if (!renderedVariantIsStale) this.syncRenderedHeaderGeometry(header);\n if (concealUntilSynced) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n }\n if (header.variant !== next) header.variant = next;\n if (concealUntilSynced) {\n this.revealHeaderWhenSynced(header, next);\n }\n }\n\n private observeHeader(header: BarTitleElement | null) {\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.headerEl?.style.removeProperty('--ds-bar-title-divider-inset');\n this.headerEl = header;\n this.expandedHeaderHeight = 0;\n this.expandedGeometryFrozen = false;\n this.setHeaderTravel(0);\n this.setSpacerHeight(0);\n this.stickyHeaderEl?.style.setProperty('--ds-shell-page-sticky-offset', '0px');\n\n if (!header) return;\n if (header.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(header);\n }\n if (typeof ResizeObserver !== 'undefined') {\n this.headerResizeObserver = new ResizeObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerResizeObserver.observe(header);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.headerMutationObserver = new MutationObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerMutationObserver.observe(header, {\n attributes: true,\n attributeFilter: ['class'],\n childList: true,\n subtree: true,\n });\n }\n this.syncHeaderVariant(true);\n this.scheduleHeaderGeometrySync(header);\n }\n\n private handleHeaderSlotChange = (event: Event) => {\n if (this.responsiveMode === 'mobile') return;\n const slot = event.target as HTMLSlotElement;\n const header = slot\n .assignedElements()\n .find(element => element.tagName.toLowerCase() === 'ds-bar-title');\n this.observeHeader((header as BarTitleElement | undefined) ?? null);\n };\n\n render() {\n const mobile = this.responsiveMode === 'mobile';\n return (\n <Host\n role=\"main\"\n class={{\n 'shell-page-host--inset-default': this.contentInset === 'default',\n 'shell-page-host--inset-none': this.contentInset === 'none',\n 'shell-page-host--mobile': mobile,\n [`shell-page-host--header-${this.effectiveVariant}`]: true,\n }}\n >\n <div\n ref={el => {\n this.sentinelEl = el ?? null;\n }}\n class=\"shell-page__scroll-sentinel\"\n aria-hidden=\"true\"\n />\n <div\n ref={el => {\n this.stickyHeaderEl = el ?? null;\n }}\n class=\"shell-page__sticky-header\"\n >\n <div\n class=\"shell-page__desktop-header\"\n hidden={mobile}\n aria-hidden={mobile ? 'true' : undefined}\n inert={mobile ? true : undefined}\n >\n <slot name=\"header\" onSlotchange={this.handleHeaderSlotChange} />\n </div>\n <div\n class=\"shell-page__mobile-header\"\n hidden={!mobile}\n aria-hidden={!mobile ? 'true' : undefined}\n inert={!mobile ? true : undefined}\n >\n <slot name=\"mobile-header\" />\n </div>\n </div>\n <div\n ref={el => {\n this.spacerEl = el ?? null;\n }}\n class=\"shell-page__flow-spacer\"\n aria-hidden=\"true\"\n />\n <div class=\"shell-page__content\">\n <slot />\n </div>\n </Host>\n );\n }\n}\n",
|
|
251
|
+
"content": "import { Component, Element, h, Host, Prop, State, Watch } from '@stencil/core';\nimport type { ShellResponsiveMode } from '../../shell/shell-responsive';\nimport { resolveCssLengthPx } from '../../utils/resolve-css-length-px';\nimport type { BarTitleVariant } from '../BarTitle/bar-title-types';\nimport { resolveShellPageHeaderVariant } from './shell-page-responsive';\nimport type {\n ShellPageCapacity,\n ShellPageContentInset,\n ShellPageContentSurface,\n ShellPageHeaderPresentation,\n} from './shell-page-types';\n\ntype BarTitleElement = HTMLElement & { variant: BarTitleVariant };\n\n@Component({\n tag: 'ds-shell-page',\n styleUrl: 'ShellPage.css',\n scoped: true,\n})\nexport class ShellPage {\n private static readonly MAX_HEADER_REVEAL_FRAMES = 12;\n private static readonly MAX_HEADER_GEOMETRY_FRAMES = 12;\n\n @Element() el!: HTMLElement;\n\n /** Automatic capacity/scroll behavior, or an explicit header variant override. */\n @Prop() headerPresentation: ShellPageHeaderPresentation = 'auto';\n\n /** Available page-header capacity supplied by the owning application shell. */\n @Prop() headerCapacity?: ShellPageCapacity;\n\n /** Standard page gutters, or no inset for full-bleed page content. */\n @Prop() contentInset: ShellPageContentInset = 'default';\n\n /** Canvas surface painted around and beneath routed page content. */\n @Prop() contentSurface: ShellPageContentSurface = 'primary';\n\n /** Explicit shell breakpoint presentation. Mobile uses the dedicated mobile-header slot. */\n @Prop({ attribute: 'responsive-mode', reflect: true })\n responsiveMode: ShellResponsiveMode = 'desktop';\n\n @State() private pageTopVisible = true;\n\n private sentinelEl: HTMLElement | null = null;\n private spacerEl: HTMLElement | null = null;\n private stickyHeaderEl: HTMLElement | null = null;\n private headerEl: BarTitleElement | null = null;\n private expandedHeaderHeight = 0;\n private headerTravel = 0;\n private expandedGeometryFrozen = false;\n private headerResizeObserver: ResizeObserver | null = null;\n private headerMutationObserver: MutationObserver | null = null;\n private headerRevealFrame: number | null = null;\n private headerGeometryFrame: number | null = null;\n private reconnectFrame: number | null = null;\n private scrollRoot: HTMLElement | Window | null = null;\n private hasLoaded = false;\n\n @Watch('headerCapacity')\n @Watch('headerPresentation')\n handleHeaderContractChange() {\n this.syncHeaderVariant(true);\n }\n\n @Watch('responsiveMode')\n handleResponsiveModeChange() {\n this.observeHeader(this.responsiveMode === 'mobile' ? null : this.findHeader());\n }\n\n componentDidLoad() {\n this.hasLoaded = true;\n this.connectRuntime();\n }\n\n componentDidRender() {\n this.syncHeaderVariant();\n }\n\n connectedCallback() {\n if (!this.hasLoaded) return;\n if (this.reconnectFrame !== null) cancelAnimationFrame(this.reconnectFrame);\n this.reconnectFrame = requestAnimationFrame(() => {\n this.reconnectFrame = null;\n if (this.el.isConnected) this.connectRuntime();\n });\n }\n\n disconnectedCallback() {\n if (this.reconnectFrame !== null) cancelAnimationFrame(this.reconnectFrame);\n this.reconnectFrame = null;\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.headerEl?.style.removeProperty('--ds-bar-title-divider-inset');\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = null;\n }\n\n private connectRuntime() {\n this.observeHeader(this.responsiveMode === 'mobile' ? null : this.findHeader());\n this.connectScrollRoot();\n }\n\n private get effectiveVariant(): BarTitleVariant {\n return resolveShellPageHeaderVariant(\n this.headerPresentation,\n this.headerCapacity ?? 'roomy',\n this.pageTopVisible\n );\n }\n\n private get headerContractResolved(): boolean {\n return this.headerPresentation !== 'auto' || this.headerCapacity !== undefined;\n }\n\n private get isScrollCompacted(): boolean {\n return (\n this.headerPresentation === 'auto' && this.headerCapacity === 'roomy' && !this.pageTopVisible\n );\n }\n\n private composedParent(element: Element): Element | null {\n return (element as HTMLElement).assignedSlot?.parentElement ?? element.parentElement;\n }\n\n private findScrollRoot(): HTMLElement | Window {\n let ancestor = this.composedParent(this.el);\n while (ancestor && ancestor !== document.documentElement) {\n const overflow = getComputedStyle(ancestor).overflowY;\n if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') {\n return ancestor as HTMLElement;\n }\n ancestor = this.composedParent(ancestor);\n }\n return window;\n }\n\n private connectScrollRoot() {\n const next = this.findScrollRoot();\n if (next === this.scrollRoot) return;\n this.scrollRoot?.removeEventListener('scroll', this.handleScroll);\n this.scrollRoot = next;\n this.scrollRoot.addEventListener('scroll', this.handleScroll, { passive: true });\n this.handleScroll();\n }\n\n private get scrollRootResolved(): boolean {\n const shell = this.el.closest('ds-shell-app');\n if (!shell) return true;\n const expected = shell.querySelector<HTMLElement>('.shell-app__content');\n return expected !== null && this.scrollRoot === expected;\n }\n\n private handleScroll = () => {\n if (!this.sentinelEl || !this.scrollRoot) return;\n const rootTop =\n this.scrollRoot === window ? 0 : (this.scrollRoot as HTMLElement).getBoundingClientRect().top;\n this.syncHeaderDividerInset(rootTop);\n const nextPageTopVisible = this.sentinelEl.getBoundingClientRect().top >= rootTop;\n if (\n !nextPageTopVisible &&\n this.pageTopVisible &&\n this.headerEl?.classList.contains(this.variantClass('expanded'))\n ) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n this.expandedGeometryFrozen = true;\n }\n if (\n nextPageTopVisible &&\n this.expandedGeometryFrozen &&\n this.el.getBoundingClientRect().top >= rootTop\n ) {\n this.expandedGeometryFrozen = false;\n if (this.headerEl?.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(this.headerEl);\n }\n }\n this.pageTopVisible = nextPageTopVisible;\n };\n\n private findHeader(): BarTitleElement | null {\n return this.el.querySelector<BarTitleElement>('ds-bar-title');\n }\n\n private get compactHeaderHeight(): number {\n return resolveCssLengthPx('--dimension-size-600', 0);\n }\n\n private syncHeaderDividerInset(rootTop?: number) {\n const header = this.headerEl;\n if (!header) return;\n\n const ownsScrollTransition =\n this.headerPresentation === 'auto' && this.headerCapacity === 'roomy';\n const expandedInset = resolveCssLengthPx('--dimension-space-400', 0);\n if (\n !ownsScrollTransition ||\n !this.sentinelEl ||\n !this.scrollRoot ||\n this.headerTravel <= 0 ||\n expandedInset <= 0\n ) {\n header.style.removeProperty('--ds-bar-title-divider-inset');\n return;\n }\n\n const scrollRootTop =\n rootTop ??\n (this.scrollRoot === window\n ? 0\n : (this.scrollRoot as HTMLElement).getBoundingClientRect().top);\n const remainingTravel = this.sentinelEl.getBoundingClientRect().top - scrollRootTop;\n const progress = Math.min(1, Math.max(0, 1 - remainingTravel / this.headerTravel));\n header.style.setProperty('--ds-bar-title-divider-inset', `${expandedInset * (1 - progress)}px`);\n }\n\n private setHeaderTravel(distance: number) {\n const next = Math.max(0, distance);\n if (Math.abs(next - this.headerTravel) < 0.5) return;\n this.headerTravel = next;\n this.el.style.setProperty('--ds-shell-page-header-travel', `${next}px`);\n this.handleScroll();\n }\n\n private measureHeaderTravel(header: BarTitleElement) {\n const anchor = header.querySelector<HTMLElement>('[data-shell-page-header-anchor]');\n const compactHeight = this.compactHeaderHeight;\n if (!anchor || compactHeight <= 0) return;\n\n const headerRect = header.getBoundingClientRect();\n const anchorRect = anchor.getBoundingClientRect();\n if (headerRect.height <= 0 || anchorRect.height <= 0) return;\n\n const expandedAnchorTop = anchorRect.top - headerRect.top;\n const compactAnchorTop = Math.max(0, (compactHeight - anchorRect.height) / 2);\n this.setHeaderTravel(expandedAnchorTop - compactAnchorTop);\n }\n\n private captureExpandedHeaderGeometry(header: BarTitleElement) {\n this.expandedHeaderHeight = header.getBoundingClientRect().height;\n this.measureHeaderTravel(header);\n }\n\n private setSpacerHeight(height: number) {\n if (!this.spacerEl) return;\n this.spacerEl.style.setProperty('--ds-shell-page-flow-spacer', `${Math.max(0, height)}px`);\n }\n\n private variantClass(variant: BarTitleVariant): string {\n return `bar-title-host--${variant}`;\n }\n\n private setStickyHeaderOffset(renderedVariant: BarTitleVariant) {\n this.stickyHeaderEl?.style.setProperty(\n '--ds-shell-page-sticky-offset',\n renderedVariant === 'expanded' &&\n this.headerPresentation === 'auto' &&\n this.headerCapacity === 'roomy'\n ? `${-this.headerTravel}px`\n : '0px'\n );\n }\n\n private syncRenderedHeaderGeometry(header: BarTitleElement) {\n const renderedVariant = this.effectiveVariant;\n if (!header.classList.contains(this.variantClass(renderedVariant))) return;\n\n // Update both flow-preservation pieces before reading layout. Otherwise a\n // reverse compact → expanded render can briefly contain the tall header and\n // the compact spacer together, giving browser scroll anchoring a transient\n // height change to compensate.\n this.setSpacerHeight(\n this.isScrollCompacted ? this.expandedHeaderHeight - this.compactHeaderHeight : 0\n );\n this.setStickyHeaderOffset(renderedVariant);\n\n if (renderedVariant === 'expanded' && !this.expandedGeometryFrozen) {\n this.captureExpandedHeaderGeometry(header);\n this.setStickyHeaderOffset(renderedVariant);\n }\n }\n\n private cancelHeaderGeometrySync() {\n if (this.headerGeometryFrame !== null) cancelAnimationFrame(this.headerGeometryFrame);\n this.headerGeometryFrame = null;\n }\n\n private scheduleHeaderGeometrySync(header: BarTitleElement) {\n this.cancelHeaderGeometrySync();\n let framesRemaining = ShellPage.MAX_HEADER_GEOMETRY_FRAMES;\n let framesElapsed = 0;\n const sync = () => {\n if (this.headerEl !== header) return;\n framesRemaining -= 1;\n framesElapsed += 1;\n // In WebKit a child's componentDidLoad can precede its assignment into\n // the parent's rendered slot. Revalidate after ShellApp has had a frame\n // to expose the actual content scroller.\n this.connectScrollRoot();\n this.syncRenderedHeaderGeometry(header);\n const geometryReady =\n this.effectiveVariant !== 'expanded' ||\n (this.expandedHeaderHeight > 0 && this.headerTravel > 0);\n if (\n (geometryReady && this.scrollRootResolved && framesElapsed >= 2) ||\n framesRemaining <= 0\n ) {\n this.headerGeometryFrame = null;\n return;\n }\n this.headerGeometryFrame = requestAnimationFrame(sync);\n };\n this.headerGeometryFrame = requestAnimationFrame(sync);\n }\n\n private cancelHeaderReveal() {\n if (this.headerRevealFrame !== null) cancelAnimationFrame(this.headerRevealFrame);\n this.headerRevealFrame = null;\n this.headerEl?.removeAttribute('data-shell-page-syncing');\n }\n\n private revealHeaderWhenSynced(header: BarTitleElement, variant: BarTitleVariant) {\n // Stencil normally re-renders within a frame or two of a prop change. Stop\n // polling at the cap, but fail closed: a stale variant must never paint.\n let framesRemaining = ShellPage.MAX_HEADER_REVEAL_FRAMES;\n const reveal = () => {\n if (this.headerEl !== header) {\n header.removeAttribute('data-shell-page-syncing');\n return;\n }\n framesRemaining -= 1;\n if (header.classList.contains(this.variantClass(variant))) {\n header.removeAttribute('data-shell-page-syncing');\n this.headerRevealFrame = null;\n return;\n }\n if (framesRemaining <= 0) {\n this.headerRevealFrame = null;\n return;\n }\n this.headerRevealFrame = requestAnimationFrame(reveal);\n };\n this.headerRevealFrame = requestAnimationFrame(reveal);\n }\n\n private syncHeaderVariant(concealUntilSynced = false) {\n const header = this.headerEl;\n if (!header) return;\n\n this.syncHeaderDividerInset();\n if (!this.headerContractResolved) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n return;\n }\n\n const next = this.effectiveVariant;\n const renderedVariantIsStale = !header.classList.contains(this.variantClass(next));\n if (!renderedVariantIsStale) this.syncRenderedHeaderGeometry(header);\n if (concealUntilSynced) {\n this.cancelHeaderReveal();\n header.setAttribute('data-shell-page-syncing', '');\n }\n if (header.variant !== next) header.variant = next;\n if (concealUntilSynced) {\n this.revealHeaderWhenSynced(header, next);\n }\n }\n\n private observeHeader(header: BarTitleElement | null) {\n this.cancelHeaderReveal();\n this.cancelHeaderGeometrySync();\n this.headerResizeObserver?.disconnect();\n this.headerResizeObserver = null;\n this.headerMutationObserver?.disconnect();\n this.headerMutationObserver = null;\n this.headerEl?.style.removeProperty('--ds-bar-title-divider-inset');\n this.headerEl = header;\n this.expandedHeaderHeight = 0;\n this.expandedGeometryFrozen = false;\n this.setHeaderTravel(0);\n this.setSpacerHeight(0);\n this.stickyHeaderEl?.style.setProperty('--ds-shell-page-sticky-offset', '0px');\n\n if (!header) return;\n if (header.classList.contains(this.variantClass('expanded'))) {\n this.captureExpandedHeaderGeometry(header);\n }\n if (typeof ResizeObserver !== 'undefined') {\n this.headerResizeObserver = new ResizeObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerResizeObserver.observe(header);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.headerMutationObserver = new MutationObserver(() => {\n this.syncRenderedHeaderGeometry(header);\n });\n this.headerMutationObserver.observe(header, {\n attributes: true,\n attributeFilter: ['class'],\n childList: true,\n subtree: true,\n });\n }\n this.syncHeaderVariant(true);\n this.scheduleHeaderGeometrySync(header);\n }\n\n private handleHeaderSlotChange = (event: Event) => {\n if (this.responsiveMode === 'mobile') return;\n const slot = event.target as HTMLSlotElement;\n const header = slot\n .assignedElements()\n .find(element => element.tagName.toLowerCase() === 'ds-bar-title');\n this.observeHeader((header as BarTitleElement | undefined) ?? null);\n };\n\n render() {\n const mobile = this.responsiveMode === 'mobile';\n return (\n <Host\n role=\"main\"\n class={{\n 'shell-page-host--inset-default': this.contentInset === 'default',\n 'shell-page-host--inset-none': this.contentInset === 'none',\n 'shell-page-host--surface-primary': this.contentSurface === 'primary',\n 'shell-page-host--surface-secondary': this.contentSurface === 'secondary',\n 'shell-page-host--mobile': mobile,\n [`shell-page-host--header-${this.effectiveVariant}`]: true,\n }}\n >\n <div\n ref={el => {\n this.sentinelEl = el ?? null;\n }}\n class=\"shell-page__scroll-sentinel\"\n aria-hidden=\"true\"\n />\n <div\n ref={el => {\n this.stickyHeaderEl = el ?? null;\n }}\n class=\"shell-page__sticky-header\"\n >\n <div\n class=\"shell-page__desktop-header\"\n hidden={mobile}\n aria-hidden={mobile ? 'true' : undefined}\n inert={mobile ? true : undefined}\n >\n <slot name=\"header\" onSlotchange={this.handleHeaderSlotChange} />\n </div>\n <div\n class=\"shell-page__mobile-header\"\n hidden={!mobile}\n aria-hidden={!mobile ? 'true' : undefined}\n inert={!mobile ? true : undefined}\n >\n <slot name=\"mobile-header\" />\n </div>\n </div>\n <div\n ref={el => {\n this.spacerEl = el ?? null;\n }}\n class=\"shell-page__flow-spacer\"\n aria-hidden=\"true\"\n />\n <div class=\"shell-page__content\">\n <slot />\n </div>\n </Host>\n );\n }\n}\n",
|
|
228
252
|
"type": "registry:ui"
|
|
229
253
|
},
|
|
230
254
|
{
|
|
@@ -234,7 +258,7 @@
|
|
|
234
258
|
},
|
|
235
259
|
{
|
|
236
260
|
"path": "src/wc/components/ShellPage/shell-page-types.ts",
|
|
237
|
-
"content": "import type { BarTitleVariant } from '../BarTitle/bar-title-types';\n\nexport type ShellPageHeaderPresentation = 'auto' | BarTitleVariant;\n\nexport type ShellPageContentInset = 'default' | 'none';\n\nexport type ShellPageCapacity = 'roomy' | 'compact' | 'constrained';\n",
|
|
261
|
+
"content": "import type { BarTitleVariant } from '../BarTitle/bar-title-types';\n\nexport type ShellPageHeaderPresentation = 'auto' | BarTitleVariant;\n\nexport type ShellPageContentInset = 'default' | 'none';\n\nexport type ShellPageContentSurface = 'primary' | 'secondary';\n\nexport type ShellPageCapacity = 'roomy' | 'compact' | 'constrained';\n",
|
|
238
262
|
"type": "registry:ui"
|
|
239
263
|
}
|
|
240
264
|
]
|
|
@@ -41,17 +41,17 @@
|
|
|
41
41
|
"accessibility": [
|
|
42
42
|
"Only the active mobile tool view participates in focus or the accessibility tree.",
|
|
43
43
|
"Header Back and application-owned header actions preserve the PanelTools event contract.",
|
|
44
|
-
"Inbox uses the MobileSectionSwitcher popup trigger for
|
|
44
|
+
"Inbox uses the MobileSectionSwitcher popup trigger for Stacks and Activity and never relies on a gesture-only interaction; Messages remains a direct mobile destination."
|
|
45
45
|
],
|
|
46
46
|
"states": [
|
|
47
47
|
"The application owns open and activeTool and replaces headers when tool depth changes.",
|
|
48
|
-
"Items with mobileDestination inbox map to one mobile Inbox destination while retaining the actual active tool id; the canonical recipe groups
|
|
48
|
+
"Items with mobileDestination inbox map to one mobile Inbox destination while retaining the actual active tool id; the canonical recipe groups Stacks and Activity, while Messages remains a separate destination.",
|
|
49
49
|
"Stable tool ids own named slots; label, order, rail placement, shortcut, and mobile destination are explicit item data.",
|
|
50
50
|
"Switching responsive mode must not recreate application-owned slotted product elements."
|
|
51
51
|
],
|
|
52
52
|
"responsiveBehavior": [
|
|
53
53
|
"Desktop and tablet compose PanelTools-compatible rail and drawer chrome.",
|
|
54
|
-
"Mobile renders one centered MobileHeader for every tool
|
|
54
|
+
"Mobile renders one centered MobileHeader for every tool; Stacks and Activity use Inbox section titles, while Messages remains a direct tool destination."
|
|
55
55
|
],
|
|
56
56
|
"frameworkCaveats": {
|
|
57
57
|
"customElements": [
|
|
@@ -391,7 +391,7 @@
|
|
|
391
391
|
"peerDependencies": {
|
|
392
392
|
"required": [
|
|
393
393
|
"@ds-mo/tokens ^6.0.0",
|
|
394
|
-
"@ds-mo/icons ^6.
|
|
394
|
+
"@ds-mo/icons ^6.5.0"
|
|
395
395
|
],
|
|
396
396
|
"frameworks": "Custom Elements; React 18/19 wrappers; Angular 19-22 standalone adapters."
|
|
397
397
|
}
|
|
@@ -9,8 +9,6 @@ export type SafetyScoreLevel = 'fair' | 'good' | 'excellent';
|
|
|
9
9
|
* product decision rather than a design-system one.
|
|
10
10
|
*/
|
|
11
11
|
export interface OverviewScore {
|
|
12
|
-
/** Category before the trend and figure, for example `Safety score`. */
|
|
13
|
-
label: string;
|
|
14
12
|
/** Display-ready headline figure. */
|
|
15
13
|
value: string | number;
|
|
16
14
|
/** Change against the comparison period. Omit when there is nothing to report. */
|
|
@@ -9,12 +9,14 @@ export declare class MobileBarNav {
|
|
|
9
9
|
sheetNavExpanded: boolean;
|
|
10
10
|
menuLabel: string;
|
|
11
11
|
searchLabel: string;
|
|
12
|
-
agentsLabel: string;
|
|
13
12
|
inboxLabel: string;
|
|
13
|
+
messagesLabel: string;
|
|
14
|
+
agentsLabel: string;
|
|
14
15
|
helpLabel: string;
|
|
15
16
|
searchDot: boolean;
|
|
16
|
-
agentsDot: boolean;
|
|
17
17
|
inboxDot: boolean;
|
|
18
|
+
messagesDot: boolean;
|
|
19
|
+
agentsDot: boolean;
|
|
18
20
|
private pressedItemId;
|
|
19
21
|
dsSheetNavToggle: EventEmitter<boolean>;
|
|
20
22
|
dsDestinationChange: EventEmitter<MobileBarNavDestinationDetail>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Application-owned tool id for the shell rail and responsive tool views. */
|
|
2
2
|
export type PanelToolsToolId = string;
|
|
3
3
|
/** Canonical Motive shell recipe used when item metadata is omitted. */
|
|
4
|
-
export type CanonicalPanelToolsToolId = 'search' | '
|
|
4
|
+
export type CanonicalPanelToolsToolId = 'search' | 'messages' | 'agents' | 'stacks' | 'activity' | 'help';
|
|
5
5
|
export declare const PANEL_TOOLS_TOOL_IDS: CanonicalPanelToolsToolId[];
|
|
6
6
|
/** Rail header slot — mirrors panel-nav M logo row. */
|
|
7
7
|
export declare const PANEL_TOOLS_PRIMARY_TOOL_ID: CanonicalPanelToolsToolId;
|
|
@@ -21,8 +21,8 @@ export interface PanelToolsItem {
|
|
|
21
21
|
order?: number;
|
|
22
22
|
/** Optional shortcut label displayed by the tooltip. */
|
|
23
23
|
shortcutKey?: string;
|
|
24
|
-
/** Mobile destination recipe; canonical ids retain their
|
|
25
|
-
mobileDestination?: 'search' | '
|
|
24
|
+
/** Mobile destination recipe; canonical ids retain their explicit defaults. */
|
|
25
|
+
mobileDestination?: 'search' | 'inbox' | 'messages' | 'agents' | 'help';
|
|
26
26
|
/** Whether this rail button is currently pressed/active. */
|
|
27
27
|
selected?: boolean;
|
|
28
28
|
/** Show a notification dot. */
|
|
@@ -5,6 +5,7 @@ import type { MobileHeaderTone } from '../MobileHeader/mobile-header-types';
|
|
|
5
5
|
import type { PanelNavGroup, PanelNavItem, PanelNavRouterMode } from '../PanelNav/panel-nav-types';
|
|
6
6
|
import type { PanelToolsHeaders, PanelToolsHeaderAction, PanelToolsItem } from '../PanelTools/panel-tools-types';
|
|
7
7
|
import type { NavChromeStyle } from '../../shell/nav-chrome';
|
|
8
|
+
import type { ShellPageContentInset, ShellPageContentSurface } from '../ShellPage/shell-page-types';
|
|
8
9
|
export type ShellAppComposition = 'managed' | 'slotted';
|
|
9
10
|
/**
|
|
10
11
|
* Router-owned application navigation supplied to managed ShellApp.
|
|
@@ -67,7 +68,9 @@ export interface ShellPageChromeConfig {
|
|
|
67
68
|
mobileActions?: PanelToolsHeaderAction[];
|
|
68
69
|
actionsAriaLabel?: string;
|
|
69
70
|
tone?: MobileHeaderTone;
|
|
70
|
-
contentInset?:
|
|
71
|
+
contentInset?: ShellPageContentInset;
|
|
72
|
+
/** Canvas surface painted by ShellPage around and beneath routed content. */
|
|
73
|
+
contentSurface?: ShellPageContentSurface;
|
|
71
74
|
}
|
|
72
75
|
/**
|
|
73
76
|
* Product-owned global tools supplied to managed ShellApp. Tool view content
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ShellResponsiveMode } from '../../shell/shell-responsive';
|
|
2
|
-
import type { ShellPageCapacity, ShellPageContentInset, ShellPageHeaderPresentation } from './shell-page-types';
|
|
2
|
+
import type { ShellPageCapacity, ShellPageContentInset, ShellPageContentSurface, ShellPageHeaderPresentation } from './shell-page-types';
|
|
3
3
|
export declare class ShellPage {
|
|
4
4
|
private static readonly MAX_HEADER_REVEAL_FRAMES;
|
|
5
5
|
private static readonly MAX_HEADER_GEOMETRY_FRAMES;
|
|
@@ -10,6 +10,8 @@ export declare class ShellPage {
|
|
|
10
10
|
headerCapacity?: ShellPageCapacity;
|
|
11
11
|
/** Standard page gutters, or no inset for full-bleed page content. */
|
|
12
12
|
contentInset: ShellPageContentInset;
|
|
13
|
+
/** Canvas surface painted around and beneath routed page content. */
|
|
14
|
+
contentSurface: ShellPageContentSurface;
|
|
13
15
|
/** Explicit shell breakpoint presentation. Mobile uses the dedicated mobile-header slot. */
|
|
14
16
|
responsiveMode: ShellResponsiveMode;
|
|
15
17
|
private pageTopVisible;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { ShellPage } from './ShellPage';
|
|
2
|
-
export type { ShellPageCapacity, ShellPageContentInset, ShellPageHeaderPresentation, } from './shell-page-types';
|
|
2
|
+
export type { ShellPageCapacity, ShellPageContentInset, ShellPageContentSurface, ShellPageHeaderPresentation, } from './shell-page-types';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BarTitleVariant } from '../BarTitle/bar-title-types';
|
|
2
2
|
export type ShellPageHeaderPresentation = 'auto' | BarTitleVariant;
|
|
3
3
|
export type ShellPageContentInset = 'default' | 'none';
|
|
4
|
+
export type ShellPageContentSurface = 'primary' | 'secondary';
|
|
4
5
|
export type ShellPageCapacity = 'roomy' | 'compact' | 'constrained';
|
|
5
6
|
//# sourceMappingURL=shell-page-types.d.ts.map
|
|
@@ -52,7 +52,7 @@ import { ScrollOverlayScrollDetail } from "./components/ScrollOverlay/ScrollOver
|
|
|
52
52
|
import { SelectBackground, SelectOption, SelectSection, SelectSize, SelectValue, SelectWidth } from "./components/Select/Select";
|
|
53
53
|
import { ShellAppComposition, ShellNavigationConfig, ShellPageChromeConfig, ShellToolsConfig } from "./components/ShellApp/shell-app-types";
|
|
54
54
|
import { ShellGradientPreset } from "./shell/shell-gradient-presets";
|
|
55
|
-
import { ShellPageCapacity, ShellPageContentInset, ShellPageHeaderPresentation } from "./components/ShellPage/shell-page-types";
|
|
55
|
+
import { ShellPageCapacity, ShellPageContentInset, ShellPageContentSurface, ShellPageHeaderPresentation } from "./components/ShellPage/shell-page-types";
|
|
56
56
|
import { SkeletonBackground, SkeletonVariant } from "./components/Skeleton/Skeleton";
|
|
57
57
|
import { LineTruncation, TextAlign, TextColor, TextDecoration, TextElement, TextFontFeature, TextVariant, TextWrap } from "./components/Text/text-types";
|
|
58
58
|
import { ControlSize } from "./utils/control-text";
|
|
@@ -111,7 +111,7 @@ export { ScrollOverlayScrollDetail } from "./components/ScrollOverlay/ScrollOver
|
|
|
111
111
|
export { SelectBackground, SelectOption, SelectSection, SelectSize, SelectValue, SelectWidth } from "./components/Select/Select";
|
|
112
112
|
export { ShellAppComposition, ShellNavigationConfig, ShellPageChromeConfig, ShellToolsConfig } from "./components/ShellApp/shell-app-types";
|
|
113
113
|
export { ShellGradientPreset } from "./shell/shell-gradient-presets";
|
|
114
|
-
export { ShellPageCapacity, ShellPageContentInset, ShellPageHeaderPresentation } from "./components/ShellPage/shell-page-types";
|
|
114
|
+
export { ShellPageCapacity, ShellPageContentInset, ShellPageContentSurface, ShellPageHeaderPresentation } from "./components/ShellPage/shell-page-types";
|
|
115
115
|
export { SkeletonBackground, SkeletonVariant } from "./components/Skeleton/Skeleton";
|
|
116
116
|
export { LineTruncation, TextAlign, TextColor, TextDecoration, TextElement, TextFontFeature, TextVariant, TextWrap } from "./components/Text/text-types";
|
|
117
117
|
export { ControlSize } from "./utils/control-text";
|
|
@@ -1426,6 +1426,14 @@ export namespace Components {
|
|
|
1426
1426
|
* @default 'Menu'
|
|
1427
1427
|
*/
|
|
1428
1428
|
"menuLabel": string;
|
|
1429
|
+
/**
|
|
1430
|
+
* @default false
|
|
1431
|
+
*/
|
|
1432
|
+
"messagesDot": boolean;
|
|
1433
|
+
/**
|
|
1434
|
+
* @default 'Messages'
|
|
1435
|
+
*/
|
|
1436
|
+
"messagesLabel": string;
|
|
1429
1437
|
/**
|
|
1430
1438
|
* @default false
|
|
1431
1439
|
*/
|
|
@@ -2148,6 +2156,11 @@ export namespace Components {
|
|
|
2148
2156
|
* @default 'default'
|
|
2149
2157
|
*/
|
|
2150
2158
|
"contentInset": ShellPageContentInset;
|
|
2159
|
+
/**
|
|
2160
|
+
* Canvas surface painted around and beneath routed page content.
|
|
2161
|
+
* @default 'primary'
|
|
2162
|
+
*/
|
|
2163
|
+
"contentSurface": ShellPageContentSurface;
|
|
2151
2164
|
/**
|
|
2152
2165
|
* Available page-header capacity supplied by the owning application shell.
|
|
2153
2166
|
*/
|
|
@@ -5286,6 +5299,14 @@ declare namespace LocalJSX {
|
|
|
5286
5299
|
* @default 'Menu'
|
|
5287
5300
|
*/
|
|
5288
5301
|
"menuLabel"?: string;
|
|
5302
|
+
/**
|
|
5303
|
+
* @default false
|
|
5304
|
+
*/
|
|
5305
|
+
"messagesDot"?: boolean;
|
|
5306
|
+
/**
|
|
5307
|
+
* @default 'Messages'
|
|
5308
|
+
*/
|
|
5309
|
+
"messagesLabel"?: string;
|
|
5289
5310
|
"onDsDestinationChange"?: (event: DsMobileBarNavCustomEvent<MobileBarNavDestinationDetail>) => void;
|
|
5290
5311
|
"onDsSheetNavToggle"?: (event: DsMobileBarNavCustomEvent<boolean>) => void;
|
|
5291
5312
|
/**
|
|
@@ -6128,6 +6149,11 @@ declare namespace LocalJSX {
|
|
|
6128
6149
|
* @default 'default'
|
|
6129
6150
|
*/
|
|
6130
6151
|
"contentInset"?: ShellPageContentInset;
|
|
6152
|
+
/**
|
|
6153
|
+
* Canvas surface painted around and beneath routed page content.
|
|
6154
|
+
* @default 'primary'
|
|
6155
|
+
*/
|
|
6156
|
+
"contentSurface"?: ShellPageContentSurface;
|
|
6131
6157
|
/**
|
|
6132
6158
|
* Available page-header capacity supplied by the owning application shell.
|
|
6133
6159
|
*/
|
|
@@ -7033,12 +7059,14 @@ declare namespace LocalJSX {
|
|
|
7033
7059
|
"sheetNavExpanded": boolean;
|
|
7034
7060
|
"menuLabel": string;
|
|
7035
7061
|
"searchLabel": string;
|
|
7036
|
-
"agentsLabel": string;
|
|
7037
7062
|
"inboxLabel": string;
|
|
7063
|
+
"messagesLabel": string;
|
|
7064
|
+
"agentsLabel": string;
|
|
7038
7065
|
"helpLabel": string;
|
|
7039
7066
|
"searchDot": boolean;
|
|
7040
|
-
"agentsDot": boolean;
|
|
7041
7067
|
"inboxDot": boolean;
|
|
7068
|
+
"messagesDot": boolean;
|
|
7069
|
+
"agentsDot": boolean;
|
|
7042
7070
|
}
|
|
7043
7071
|
interface DsMobileHeaderAttributes {
|
|
7044
7072
|
"heading": string;
|
|
@@ -7191,6 +7219,7 @@ declare namespace LocalJSX {
|
|
|
7191
7219
|
"headerPresentation": ShellPageHeaderPresentation;
|
|
7192
7220
|
"headerCapacity": ShellPageCapacity;
|
|
7193
7221
|
"contentInset": ShellPageContentInset;
|
|
7222
|
+
"contentSurface": ShellPageContentSurface;
|
|
7194
7223
|
"responsiveMode": ShellResponsiveMode;
|
|
7195
7224
|
}
|
|
7196
7225
|
interface DsShellToolsAttributes {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type { NavChromeStyle } from './nav-chrome';
|
|
2
2
|
export type { PanelNavGroup, PanelNavItem, } from '../components/PanelNav/panel-nav-types';
|
|
3
3
|
export type { BarNavTab } from '../components/BarNav/bar-nav-types';
|
|
4
|
+
export type { ShellPageContentInset, ShellPageContentSurface, } from '../components/ShellPage/shell-page-types';
|
|
4
5
|
export type { ShellAppComposition, ShellNavigationConfig, ShellNavigationSelectDetail, ShellPageChromeConfig, ShellToolsConfig, } from '../components/ShellApp/shell-app-types';
|
|
5
6
|
export type { PanelToolsHeaderAction, PanelToolsHeaderConfig, PanelToolsHeaders, PanelToolsItem, PanelToolsToolId, } from '../components/PanelTools/panel-tools-types';
|
|
6
7
|
export { PANEL_TOOLS_DEFAULT_ITEMS } from '../components/PanelTools/panel-tools-types';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PanelToolsToolId } from '../components/PanelTools/panel-tools-types';
|
|
2
2
|
export type ShellResponsiveMode = 'desktop' | 'tablet' | 'mobile';
|
|
3
|
-
export type MobileDestination = 'area' | 'search' | '
|
|
3
|
+
export type MobileDestination = 'area' | 'search' | 'inbox' | 'messages' | 'agents' | 'help';
|
|
4
4
|
export type ShellInboxToolId = PanelToolsToolId;
|
|
5
5
|
export declare const SHELL_DESKTOP_BREAKPOINT = 1200;
|
|
6
6
|
export declare const SHELL_MOBILE_BREAKPOINT = 768;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ds-mo/ui",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.11.1",
|
|
4
4
|
"description": "CompoMo — composable web components styled with TokoMo design tokens",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"peerDependencies": {
|
|
108
108
|
"@angular/core": ">=19 <23",
|
|
109
109
|
"@angular/forms": ">=19 <23",
|
|
110
|
-
"@ds-mo/icons": "^6.
|
|
110
|
+
"@ds-mo/icons": "^6.5.0",
|
|
111
111
|
"@ds-mo/tokens": "^6.0.0",
|
|
112
112
|
"react": "^18 || ^19",
|
|
113
113
|
"react-dom": "^18 || ^19",
|
|
@@ -136,8 +136,8 @@
|
|
|
136
136
|
"@angular/core": "^22.0.7",
|
|
137
137
|
"@angular/forms": "^22.0.7",
|
|
138
138
|
"@axe-core/playwright": "^4.12.1",
|
|
139
|
-
"@ds-mo/icons": "^6.
|
|
140
|
-
"@ds-mo/tokens": "^6.0.
|
|
139
|
+
"@ds-mo/icons": "^6.5.0",
|
|
140
|
+
"@ds-mo/tokens": "^6.0.2",
|
|
141
141
|
"@eslint/js": "^10.0.1",
|
|
142
142
|
"@modelcontextprotocol/client": "^2.0.0",
|
|
143
143
|
"@modelcontextprotocol/server": "^2.0.0",
|