@ds-mo/ui 1.3.0 → 1.5.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.
- package/dist/.build-stamp +1 -0
- package/dist/components/ds-app-shell.d.ts +11 -0
- package/dist/components/ds-app-shell.js +2 -0
- package/dist/components/ds-app-shell.js.map +1 -0
- package/dist/components/ds-bar-nav-action.js +1 -1
- package/dist/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-nav.js.map +1 -1
- package/dist/components/ds-breadcrumb.js +1 -1
- package/dist/components/ds-button-group.js +1 -1
- package/dist/components/ds-button.js +1 -1
- package/dist/components/ds-card.js +1 -1
- package/dist/components/ds-checkbox.js +1 -1
- package/dist/components/ds-chip.js +1 -1
- package/dist/components/ds-divider.js +1 -1
- package/dist/components/ds-empty-state.js +1 -1
- package/dist/components/ds-fade.js +1 -1
- package/dist/components/ds-field.js +1 -1
- package/dist/components/ds-header.js +1 -1
- package/dist/components/ds-icon.js +1 -1
- package/dist/components/ds-input.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-nav.js.map +1 -1
- package/dist/components/ds-radio-group.js +1 -1
- package/dist/components/ds-radio-group.js.map +1 -1
- package/dist/components/ds-scrollbar.js +1 -1
- package/dist/components/ds-select.js +1 -1
- package/dist/components/ds-slider.js +1 -1
- package/dist/components/ds-surface.js +1 -1
- package/dist/components/ds-tab-group-nav.js +1 -1
- package/dist/components/ds-tab-group.js +1 -1
- package/dist/components/ds-table.js +1 -1
- package/dist/components/ds-table.js.map +1 -1
- package/dist/components/ds-tag.js +1 -1
- package/dist/components/ds-text.js +1 -1
- package/dist/components/ds-toast-provider.js +1 -1
- package/dist/components/ds-toggle-button-group.js +1 -1
- package/dist/components/ds-toggle-button.js +1 -1
- package/dist/components/ds-toggle.js +1 -1
- package/dist/components/ds-tooltip.js +1 -1
- package/dist/components/index.d.ts +3 -4
- package/dist/components/index.js +1 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/{p-COsKOwZR.js → p--YDw8Q4o.js} +2 -2
- package/dist/components/{p-OT-Q-NxH.js → p-C9za7IDu.js} +2 -2
- package/dist/components/p-DceSoh5V.js +2 -0
- package/dist/components/p-DceSoh5V.js.map +1 -0
- package/dist/components/{p-DrDrPeVV.js → p-DqBCQRRd.js} +2 -2
- package/dist/components/p-DznbYg1m.js +2 -0
- package/dist/components/p-DznbYg1m.js.map +1 -0
- package/dist/components/{p-qfvbc9w-.js → p-_LI2ymhS.js} +2 -2
- package/dist/components/p-_LI2ymhS.js.map +1 -0
- package/dist/components/{p-U1A-rprN.js → p-uMN1Ppw2.js} +2 -2
- package/dist/components/{p-X1N_ggsY.js → p-vW9EMP8s.js} +2 -2
- package/dist/types/components/AppShell/AppShell.d.ts +25 -0
- package/dist/types/{.stencil → components}/BarNav/BarNav.d.ts +6 -17
- package/dist/types/components/BarNav/bar-nav-types.d.ts +14 -0
- package/dist/types/{.stencil → components}/BarNav/bar-nav-utils.d.ts +1 -1
- package/dist/types/components/BarNav/index.d.ts +3 -0
- package/dist/types/{.stencil → components}/BarNavAction/BarNavAction.d.ts +1 -1
- package/dist/types/{.stencil → components}/PanelNav/PanelNav.d.ts +11 -26
- package/dist/types/components/PanelNav/index.d.ts +4 -0
- package/dist/types/components/PanelNav/panel-nav-types.d.ts +20 -0
- package/dist/types/components/PanelNav/panel-nav-utils.d.ts +26 -0
- package/dist/types/{.stencil → components}/TabGroupNav/TabGroupNav.d.ts +1 -1
- package/dist/types/components.d.ts +78 -28
- package/dist/types/nav/index.d.ts +7 -0
- package/dist/types/nav/nav-chrome.d.ts +14 -0
- package/dist/types/nav/shell-gradient.d.ts +25 -0
- package/dist/types/nav/shell-view-transition.d.ts +21 -0
- package/package.json +9 -4
- package/src/angular/index.ts +1 -0
- package/src/angular/proxies.ts +27 -4
- package/src/react/components.ts +1 -0
- package/src/react/ds-app-shell.ts +26 -0
- package/src/wc/components/AppShell/AppShell.tsx +180 -0
- package/src/wc/components/BarNav/BarNav.tsx +18 -26
- package/src/wc/components/BarNav/bar-nav-types.ts +15 -0
- package/src/wc/components/BarNav/bar-nav-utils.ts +1 -1
- package/src/wc/components/BarNav/index.ts +2 -1
- package/src/wc/components/BarNavAction/BarNavAction.tsx +2 -1
- package/src/wc/components/PanelNav/PanelNav.tsx +46 -90
- package/src/wc/components/PanelNav/index.ts +9 -4
- package/src/wc/components/PanelNav/panel-nav-types.ts +22 -0
- package/src/wc/components/PanelNav/panel-nav-utils.ts +32 -64
- package/src/wc/components/TabGroupNav/TabGroupNav.tsx +8 -2
- package/src/wc/components.d.ts +78 -28
- package/src/wc/nav/index.ts +33 -0
- package/src/wc/nav/nav-chrome.ts +45 -0
- package/src/wc/nav/shell-gradient.ts +44 -0
- package/src/wc/nav/shell-view-transition.ts +102 -0
- package/dist/components/p-DOtcc9UU.js +0 -2
- package/dist/components/p-DOtcc9UU.js.map +0 -1
- package/dist/components/p-qfvbc9w-.js.map +0 -1
- package/dist/types/.stencil/BarNav/index.d.ts +0 -2
- package/dist/types/.stencil/PanelNav/index.d.ts +0 -3
- package/dist/types/.stencil/PanelNav/panel-nav-utils.d.ts +0 -27
- /package/dist/components/{p-COsKOwZR.js.map → p--YDw8Q4o.js.map} +0 -0
- /package/dist/components/{p-OT-Q-NxH.js.map → p-C9za7IDu.js.map} +0 -0
- /package/dist/components/{p-DrDrPeVV.js.map → p-DqBCQRRd.js.map} +0 -0
- /package/dist/components/{p-U1A-rprN.js.map → p-uMN1Ppw2.js.map} +0 -0
- /package/dist/components/{p-X1N_ggsY.js.map → p-vW9EMP8s.js.map} +0 -0
- /package/dist/types/{.stencil → components}/Accordion/Accordion.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Badge/Badge.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Badge/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Banner/Banner.d.ts +0 -0
- /package/dist/types/{.stencil → components}/BarNav/bar-nav-dom-utils.d.ts +0 -0
- /package/dist/types/{.stencil → components}/BarNav/bar-nav-tabs-menu-utils.d.ts +0 -0
- /package/dist/types/{.stencil → components}/BarNavAction/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Breadcrumb/Breadcrumb.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Button/Button.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Button/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/ButtonGroup/ButtonGroup.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Card/Card.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Checkbox/Checkbox.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Checkbox/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Chip/Chip.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Chip/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Divider/Divider.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Divider/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/EmptyState/EmptyState.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Fade/Fade.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Fade/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Field/Field.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Header/Header.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Icon/Icon.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Icon/flag-icon-catalog.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Icon/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Icon/system-icon-catalog.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Input/Input.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Input/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Loader/Loader.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Loader/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Menu/Menu.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Modal/Modal.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Pagination/Pagination.d.ts +0 -0
- /package/dist/types/{.stencil → components}/RadioGroup/RadioGroup.d.ts +0 -0
- /package/dist/types/{.stencil → components}/RadioGroup/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Scrollbar/Scrollbar.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Select/Select.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Sidebar/Sidebar.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Skeleton/Skeleton.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Skeleton/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Slider/Slider.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Slider/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Surface/Surface.d.ts +0 -0
- /package/dist/types/{.stencil → components}/TabGroup/TabGroup.d.ts +0 -0
- /package/dist/types/{.stencil → components}/TabGroup/tab-item-utils.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Table/Table.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Tag/Tag.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Tag/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Text/Text.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Text/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Toast/Toast.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Toast/toast-service.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Toggle/Toggle.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Toggle/index.d.ts +0 -0
- /package/dist/types/{.stencil → components}/ToggleButton/ToggleButton.d.ts +0 -0
- /package/dist/types/{.stencil → components}/ToggleButtonGroup/ToggleButtonGroup.d.ts +0 -0
- /package/dist/types/{.stencil → components}/Tooltip/Tooltip.d.ts +0 -0
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { Component, Prop, Event, EventEmitter, Watch, State, Element, h, Host } from '@stencil/core';
|
|
2
|
+
import type { NavChromeStyle } from '../../nav/nav-chrome';
|
|
3
|
+
import {
|
|
4
|
+
animateShellNavRadialReveal,
|
|
5
|
+
ensureShellNavVtStyle,
|
|
6
|
+
resolveShellNavRevealOrigin,
|
|
7
|
+
setShellNavRevealOriginVars,
|
|
8
|
+
} from '../../nav/shell-view-transition';
|
|
2
9
|
import {
|
|
3
10
|
deriveActiveIdFromUrl,
|
|
4
|
-
ensurePanelNavVtStyle,
|
|
5
11
|
parsePanelNavGroups,
|
|
6
12
|
resolvePanelNavDisableVt,
|
|
7
|
-
|
|
13
|
+
resolvePanelNavStyle,
|
|
8
14
|
shouldResyncPanelNavGroups,
|
|
9
|
-
|
|
15
|
+
shouldResyncPanelNavStyle,
|
|
10
16
|
} from './panel-nav-utils';
|
|
17
|
+
import type { PanelNavGroup, PanelNavItem, PanelNavRouterMode } from './panel-nav-types';
|
|
11
18
|
|
|
12
|
-
// Module-level WeakMaps
|
|
13
|
-
// class fields avoids Stencil generating getter-only property descriptors on
|
|
14
|
-
// the host element for private fields, which throws in strict environments.
|
|
15
|
-
// Minimal typings for the View Transitions API, which isn't in our TS lib target.
|
|
19
|
+
// Module-level WeakMaps
|
|
16
20
|
interface ViewTransition {
|
|
17
21
|
finished: Promise<void>;
|
|
18
22
|
skipTransition: () => void;
|
|
@@ -24,50 +28,17 @@ type DocumentWithViewTransition = Document & {
|
|
|
24
28
|
const vtTransitions = new WeakMap<object, ViewTransition>();
|
|
25
29
|
const vtResolvers = new WeakMap<object, () => void>();
|
|
26
30
|
|
|
27
|
-
/** Parse a CSS <time> value to milliseconds. Handles `s`, `ms`, and unitless
|
|
28
|
-
* (assumed ms). Critically: `parseFloat('.75s')` is 0.75 — WAAPI treats that as
|
|
29
|
-
* 0.75ms (instant/invisible), so the `s` unit must be scaled to ms. Design
|
|
30
|
-
* tokens (e.g. `--effect-animation-duration-long-1`) are authored in seconds. */
|
|
31
|
-
function parseCssTimeMs(value: string, fallback: number): number {
|
|
32
|
-
const v = value.trim();
|
|
33
|
-
const num = parseFloat(v);
|
|
34
|
-
if (Number.isNaN(num)) return fallback;
|
|
35
|
-
if (/ms\s*$/.test(v)) return num;
|
|
36
|
-
if (/s\s*$/.test(v)) return num * 1000;
|
|
37
|
-
return num;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type PanelNavVariant = 'dashboard' | 'settings';
|
|
41
|
-
export type PanelNavRouterMode = 'anchor' | 'event';
|
|
42
|
-
|
|
43
|
-
export interface PanelNavItem {
|
|
44
|
-
id: string;
|
|
45
|
-
icon: string;
|
|
46
|
-
label: string;
|
|
47
|
-
/** Show a notification dot badge on the item */
|
|
48
|
-
dot?: boolean;
|
|
49
|
-
flag?: boolean;
|
|
50
|
-
/** Route path used for `currentUrl` matching. In `anchor` mode also sets `<a href>`.
|
|
51
|
-
* In `event` mode navigation is delegated to the host via `dsNavSelect`. */
|
|
52
|
-
href?: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface PanelNavGroup {
|
|
56
|
-
id?: string;
|
|
57
|
-
label?: string;
|
|
58
|
-
items: PanelNavItem[];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
31
|
@Component({
|
|
62
32
|
tag: 'ds-panel-nav',
|
|
63
33
|
styleUrl: 'PanelNav.css',
|
|
64
34
|
scoped: true,
|
|
65
35
|
})
|
|
66
36
|
export class PanelNav {
|
|
67
|
-
/**
|
|
68
|
-
|
|
37
|
+
/** Chrome style: `navigation` = navigation tokens, `default` = standard app tokens.
|
|
38
|
+
* Property: `navStyle`. HTML attribute: `nav-style`. */
|
|
39
|
+
@Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'navigation';
|
|
69
40
|
|
|
70
|
-
/** When `true`, the component does not run its own View Transition on
|
|
41
|
+
/** When `true`, the component does not run its own View Transition on style
|
|
71
42
|
* change — it just updates the rendered surface synchronously. Use this when
|
|
72
43
|
* the host app orchestrates the page transition itself (e.g. Angular Router's
|
|
73
44
|
* `withViewTransitions`), so the two don't fight or nest. */
|
|
@@ -122,9 +93,9 @@ export class PanelNav {
|
|
|
122
93
|
|
|
123
94
|
@Element() el!: HTMLElement;
|
|
124
95
|
|
|
125
|
-
/** Mirrors `
|
|
96
|
+
/** Mirrors `style` but is only updated inside the VT callback so the
|
|
126
97
|
* View Transition captures a clean before/after snapshot. */
|
|
127
|
-
@State() private
|
|
98
|
+
@State() private renderedStyle: NavChromeStyle = 'navigation';
|
|
128
99
|
|
|
129
100
|
@State() private parsedGroups: PanelNavGroup[] = [];
|
|
130
101
|
@State() private atBottom = false;
|
|
@@ -193,44 +164,35 @@ export class PanelNav {
|
|
|
193
164
|
this.syncActiveFromUrl();
|
|
194
165
|
}
|
|
195
166
|
|
|
196
|
-
@Watch('
|
|
197
|
-
async
|
|
167
|
+
@Watch('navStyle')
|
|
168
|
+
async onNavStyleChange(newVal: NavChromeStyle) {
|
|
198
169
|
// Host app drives the transition (e.g. Angular Router withViewTransitions):
|
|
199
170
|
// just reflect the new surface so the app's transition captures it.
|
|
200
171
|
if (this.effectiveDisableViewTransition) {
|
|
201
|
-
this.
|
|
172
|
+
this.renderedStyle = newVal;
|
|
202
173
|
return;
|
|
203
174
|
}
|
|
204
175
|
|
|
205
|
-
// Skip any in-progress transition immediately so rapid
|
|
206
|
-
// (e.g. quick dashboard → settings → dashboard) never leave the nav stuck.
|
|
176
|
+
// Skip any in-progress transition immediately so rapid style changes never leave the nav stuck.
|
|
207
177
|
vtTransitions.get(this)?.skipTransition();
|
|
208
178
|
vtTransitions.delete(this);
|
|
209
179
|
|
|
210
180
|
const doc = document as DocumentWithViewTransition;
|
|
211
181
|
if (typeof doc.startViewTransition !== 'function') {
|
|
212
|
-
this.
|
|
182
|
+
this.renderedStyle = newVal;
|
|
213
183
|
return;
|
|
214
184
|
}
|
|
215
185
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const y = rect ? Math.round(rect.top + rect.height / 2) : Math.round(window.innerHeight / 2);
|
|
222
|
-
const maxR = Math.ceil(Math.hypot(
|
|
223
|
-
Math.max(x, window.innerWidth - x),
|
|
224
|
-
Math.max(y, window.innerHeight - y),
|
|
225
|
-
));
|
|
226
|
-
|
|
227
|
-
document.documentElement.style.setProperty('--vt-x', `${x}px`);
|
|
228
|
-
document.documentElement.style.setProperty('--vt-y', `${y}px`);
|
|
186
|
+
ensureShellNavVtStyle();
|
|
187
|
+
const origin = resolveShellNavRevealOrigin(
|
|
188
|
+
this.el.querySelector('.panel-nav__footer-btn') as HTMLElement | null,
|
|
189
|
+
);
|
|
190
|
+
setShellNavRevealOriginVars(origin);
|
|
229
191
|
|
|
230
192
|
const transition = doc.startViewTransition(() =>
|
|
231
193
|
new Promise<void>(resolve => {
|
|
232
194
|
vtResolvers.set(this, resolve);
|
|
233
|
-
this.
|
|
195
|
+
this.renderedStyle = newVal;
|
|
234
196
|
})
|
|
235
197
|
);
|
|
236
198
|
|
|
@@ -240,19 +202,13 @@ export class PanelNav {
|
|
|
240
202
|
vtResolvers.delete(this);
|
|
241
203
|
});
|
|
242
204
|
|
|
243
|
-
transition.ready
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const duration = parseCssTimeMs(durToken, 750);
|
|
247
|
-
document.documentElement.animate(
|
|
248
|
-
{ clipPath: [`circle(0px at ${x}px ${y}px)`, `circle(${maxR}px at ${x}px ${y}px)`] },
|
|
249
|
-
{ duration, easing: 'ease-in-out', fill: 'forwards', pseudoElement: '::view-transition-new(root)' },
|
|
250
|
-
);
|
|
251
|
-
}).catch(() => { /* transition was skipped or aborted */ });
|
|
205
|
+
transition.ready
|
|
206
|
+
.then(() => animateShellNavRadialReveal(origin))
|
|
207
|
+
.catch(() => { /* transition was skipped or aborted */ });
|
|
252
208
|
}
|
|
253
209
|
|
|
254
210
|
componentWillLoad() {
|
|
255
|
-
this.
|
|
211
|
+
this.renderedStyle = resolvePanelNavStyle(this.navStyle, this.el.getAttribute('nav-style'));
|
|
256
212
|
if (this.storageKey) {
|
|
257
213
|
try {
|
|
258
214
|
const stored = localStorage.getItem(this.storageKey);
|
|
@@ -331,7 +287,7 @@ export class PanelNav {
|
|
|
331
287
|
|
|
332
288
|
/** Re-parse props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */
|
|
333
289
|
private syncHostPropsIfNeeded() {
|
|
334
|
-
this.
|
|
290
|
+
this.syncRenderedStyleIfNeeded();
|
|
335
291
|
|
|
336
292
|
if (shouldResyncPanelNavGroups(this.parsedGroups, this.groups)) {
|
|
337
293
|
this.onGroupsChange(this.groups);
|
|
@@ -340,16 +296,16 @@ export class PanelNav {
|
|
|
340
296
|
}
|
|
341
297
|
}
|
|
342
298
|
|
|
343
|
-
/** Align `
|
|
344
|
-
private
|
|
345
|
-
if (!
|
|
299
|
+
/** Align `renderedStyle` with `style` when host bindings land after first paint. */
|
|
300
|
+
private syncRenderedStyleIfNeeded() {
|
|
301
|
+
if (!shouldResyncPanelNavStyle(this.renderedStyle, this.navStyle)) return;
|
|
346
302
|
|
|
347
303
|
if (this.effectiveDisableViewTransition) {
|
|
348
304
|
vtTransitions.get(this)?.skipTransition();
|
|
349
305
|
vtTransitions.delete(this);
|
|
350
|
-
this.
|
|
306
|
+
this.renderedStyle = this.navStyle;
|
|
351
307
|
} else {
|
|
352
|
-
void this.
|
|
308
|
+
void this.onNavStyleChange(this.navStyle);
|
|
353
309
|
}
|
|
354
310
|
}
|
|
355
311
|
|
|
@@ -546,14 +502,14 @@ export class PanelNav {
|
|
|
546
502
|
}
|
|
547
503
|
|
|
548
504
|
render() {
|
|
549
|
-
const
|
|
505
|
+
const isNavigation = this.renderedStyle === 'navigation';
|
|
550
506
|
const collapsed = this.collapsed || this.viewportNarrow;
|
|
551
507
|
const { userName, userInitial } = this;
|
|
552
508
|
|
|
553
509
|
const navCls: Record<string, boolean> = {
|
|
554
510
|
'panel-nav': true,
|
|
555
|
-
'panel-nav--
|
|
556
|
-
'panel-nav--
|
|
511
|
+
'panel-nav--navigation': isNavigation,
|
|
512
|
+
'panel-nav--default': !isNavigation,
|
|
557
513
|
'panel-nav--collapsed': collapsed,
|
|
558
514
|
'panel-nav--animating': this.isAnimating,
|
|
559
515
|
'panel-nav--at-bottom': this.atBottom,
|
|
@@ -561,7 +517,7 @@ export class PanelNav {
|
|
|
561
517
|
|
|
562
518
|
return (
|
|
563
519
|
<Host style={{ display: 'block', position: 'relative' }}>
|
|
564
|
-
<nav class={navCls} aria-label={
|
|
520
|
+
<nav class={navCls} aria-label={isNavigation ? 'Main navigation' : 'Settings navigation'}>
|
|
565
521
|
|
|
566
522
|
{/* ── Header: Motive logo, reveals collapse toggle on hover ── */}
|
|
567
523
|
<div class="panel-nav__header">
|
|
@@ -620,15 +576,15 @@ export class PanelNav {
|
|
|
620
576
|
visible={!this.atBottom}
|
|
621
577
|
/>
|
|
622
578
|
|
|
623
|
-
{/* Left icon button — Gear in
|
|
579
|
+
{/* Left icon button — Gear in navigation style, Dashboard in default style */}
|
|
624
580
|
<button
|
|
625
581
|
type="button"
|
|
626
582
|
class="panel-nav__footer-btn"
|
|
627
|
-
title={
|
|
628
|
-
aria-label={
|
|
583
|
+
title={isNavigation ? 'Settings' : 'Dashboard'}
|
|
584
|
+
aria-label={isNavigation ? 'Open settings' : 'Go to dashboard'}
|
|
629
585
|
onClick={() => this.handleFooterAction()}
|
|
630
586
|
>
|
|
631
|
-
<ds-icon name={
|
|
587
|
+
<ds-icon name={isNavigation ? 'Gear' : 'Dashboard'} size="md" color="inherit" />
|
|
632
588
|
</button>
|
|
633
589
|
|
|
634
590
|
{/* Right user — label fades like nav items; right icon cross-fades chevron ↔ circle+initial */}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type { PanelNavRouterMode, PanelNavItem, PanelNavGroup } from './panel-nav-types';
|
|
2
|
+
export type { NavChromeStyle } from '../../nav/nav-chrome';
|
|
2
3
|
export {
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
NAV_STYLE_HINT_ATTR,
|
|
5
|
+
setNavStyleHint,
|
|
6
|
+
clearNavStyleHint,
|
|
7
|
+
resolvePanelNavStyle,
|
|
8
|
+
shouldResyncPanelNavStyle,
|
|
5
9
|
ensurePanelNavVtStyle,
|
|
6
|
-
|
|
10
|
+
deriveActiveIdFromUrl,
|
|
11
|
+
parsePanelNavGroups,
|
|
7
12
|
} from './panel-nav-utils';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { NavChromeStyle } from '../../nav/nav-chrome';
|
|
2
|
+
|
|
3
|
+
export type { NavChromeStyle };
|
|
4
|
+
export type PanelNavRouterMode = 'anchor' | 'event';
|
|
5
|
+
|
|
6
|
+
export interface PanelNavItem {
|
|
7
|
+
id: string;
|
|
8
|
+
icon: string;
|
|
9
|
+
label: string;
|
|
10
|
+
/** Show a notification dot badge on the item */
|
|
11
|
+
dot?: boolean;
|
|
12
|
+
flag?: boolean;
|
|
13
|
+
/** Route path used for `currentUrl` matching. In `anchor` mode also sets `<a href>`.
|
|
14
|
+
* In `event` mode navigation is delegated to the host via `dsNavSelect`. */
|
|
15
|
+
href?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PanelNavGroup {
|
|
19
|
+
id?: string;
|
|
20
|
+
label?: string;
|
|
21
|
+
items: PanelNavItem[];
|
|
22
|
+
}
|
|
@@ -1,4 +1,35 @@
|
|
|
1
|
-
import type { PanelNavGroup, PanelNavItem
|
|
1
|
+
import type { PanelNavGroup, PanelNavItem } from './panel-nav-types';
|
|
2
|
+
import {
|
|
3
|
+
NAV_STYLE_HINT_ATTR,
|
|
4
|
+
clearNavStyleHint,
|
|
5
|
+
readNavStyleAttr,
|
|
6
|
+
resolveNavChromeStyle,
|
|
7
|
+
setNavStyleHint,
|
|
8
|
+
shouldResyncNavChromeStyle,
|
|
9
|
+
} from '../../nav/nav-chrome';
|
|
10
|
+
import { ensureShellNavVtStyle } from '../../nav/shell-view-transition';
|
|
11
|
+
|
|
12
|
+
export type { NavChromeStyle } from '../../nav/nav-chrome';
|
|
13
|
+
export {
|
|
14
|
+
NAV_STYLE_HINT_ATTR,
|
|
15
|
+
readNavStyleAttr,
|
|
16
|
+
setNavStyleHint,
|
|
17
|
+
clearNavStyleHint,
|
|
18
|
+
resolveNavChromeStyle as resolvePanelNavStyle,
|
|
19
|
+
shouldResyncNavChromeStyle as shouldResyncPanelNavStyle,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** @deprecated Use `setNavStyleHint` */
|
|
23
|
+
export const setPanelNavStyleHint = setNavStyleHint;
|
|
24
|
+
|
|
25
|
+
/** @deprecated Use `clearNavStyleHint` */
|
|
26
|
+
export const clearPanelNavStyleHint = clearNavStyleHint;
|
|
27
|
+
|
|
28
|
+
/** @deprecated Use `NAV_STYLE_HINT_ATTR` */
|
|
29
|
+
export const PANEL_NAV_STYLE_HINT_ATTR = NAV_STYLE_HINT_ATTR;
|
|
30
|
+
|
|
31
|
+
/** @deprecated Use `ensureShellNavVtStyle` */
|
|
32
|
+
export const ensurePanelNavVtStyle = ensureShellNavVtStyle;
|
|
2
33
|
|
|
3
34
|
/** Whether `path` matches `href` at a segment boundary (exact or child path). */
|
|
4
35
|
export function hrefMatchesPath(path: string, href: string): boolean {
|
|
@@ -42,41 +73,6 @@ export function parsePanelNavGroups(groups: string | unknown): PanelNavGroup[] {
|
|
|
42
73
|
return [];
|
|
43
74
|
}
|
|
44
75
|
|
|
45
|
-
/** `document.documentElement` attribute for pre-bootstrap variant hints (SPA hard reload). */
|
|
46
|
-
export const PANEL_NAV_VARIANT_HINT_ATTR = 'data-panel-nav-variant';
|
|
47
|
-
|
|
48
|
-
/** Parse `variant` from a host attribute value. */
|
|
49
|
-
export function readPanelNavVariantAttr(attr: string | null): PanelNavVariant | undefined {
|
|
50
|
-
if (attr === 'settings' || attr === 'dashboard') return attr;
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Set a document-level variant hint before the custom element upgrades (hard reload). */
|
|
55
|
-
export function setPanelNavVariantHint(variant: PanelNavVariant): void {
|
|
56
|
-
if (typeof document === 'undefined') return;
|
|
57
|
-
document.documentElement.setAttribute(PANEL_NAV_VARIANT_HINT_ATTR, variant);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function clearPanelNavVariantHint(): void {
|
|
61
|
-
if (typeof document === 'undefined') return;
|
|
62
|
-
document.documentElement.removeAttribute(PANEL_NAV_VARIANT_HINT_ATTR);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Resolve initial variant — host attr, then document hint, then prop default. */
|
|
66
|
-
export function resolvePanelNavVariant(
|
|
67
|
-
variantProp: PanelNavVariant,
|
|
68
|
-
variantAttr: string | null,
|
|
69
|
-
documentVariantAttr: string | null = typeof document !== 'undefined'
|
|
70
|
-
? document.documentElement.getAttribute(PANEL_NAV_VARIANT_HINT_ATTR)
|
|
71
|
-
: null,
|
|
72
|
-
): PanelNavVariant {
|
|
73
|
-
return (
|
|
74
|
-
readPanelNavVariantAttr(variantAttr) ??
|
|
75
|
-
readPanelNavVariantAttr(documentVariantAttr) ??
|
|
76
|
-
variantProp
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
76
|
/** Resolve whether VT is disabled from prop and/or host attribute. */
|
|
81
77
|
export function resolvePanelNavDisableVt(prop: boolean, attr: string | null): boolean {
|
|
82
78
|
if (prop) return true;
|
|
@@ -84,14 +80,6 @@ export function resolvePanelNavDisableVt(prop: boolean, attr: string | null): bo
|
|
|
84
80
|
return attr !== 'false';
|
|
85
81
|
}
|
|
86
82
|
|
|
87
|
-
/** True when internal rendered surface lags the host `variant` prop. */
|
|
88
|
-
export function shouldResyncPanelNavVariant(
|
|
89
|
-
renderedVariant: PanelNavVariant,
|
|
90
|
-
variant: PanelNavVariant,
|
|
91
|
-
): boolean {
|
|
92
|
-
return renderedVariant !== variant;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
83
|
/** True when host `groups` has items but internal parsed state is still empty. */
|
|
96
84
|
export function shouldResyncPanelNavGroups(
|
|
97
85
|
parsedGroups: PanelNavGroup[],
|
|
@@ -102,23 +90,3 @@ export function shouldResyncPanelNavGroups(
|
|
|
102
90
|
countPanelNavItems(parsePanelNavGroups(groups)) > 0
|
|
103
91
|
);
|
|
104
92
|
}
|
|
105
|
-
|
|
106
|
-
let vtStyleInjected = false;
|
|
107
|
-
|
|
108
|
-
/** Inject view-transition suppress styles once per document (shared by PanelNav + hosts). */
|
|
109
|
-
export function ensurePanelNavVtStyle(): void {
|
|
110
|
-
if (vtStyleInjected) return;
|
|
111
|
-
const id = 'ds-panel-nav-vt-style';
|
|
112
|
-
if (document.getElementById(id)) {
|
|
113
|
-
vtStyleInjected = true;
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const style = document.createElement('style');
|
|
117
|
-
style.id = id;
|
|
118
|
-
style.textContent = [
|
|
119
|
-
'::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal}',
|
|
120
|
-
'::view-transition-new(root){clip-path:circle(0px at var(--vt-x,50%) var(--vt-y,50%))}',
|
|
121
|
-
].join('\n');
|
|
122
|
-
document.head.appendChild(style);
|
|
123
|
-
vtStyleInjected = true;
|
|
124
|
-
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type TabItemTab,
|
|
7
7
|
} from '../TabGroup/tab-item-utils';
|
|
8
8
|
|
|
9
|
-
export type TabGroupNavBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';
|
|
9
|
+
export type TabGroupNavBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark' | 'navigation';
|
|
10
10
|
|
|
11
11
|
@Component({
|
|
12
12
|
tag: 'ds-tab-group-nav',
|
|
@@ -119,18 +119,24 @@ export class TabGroupNav {
|
|
|
119
119
|
private getBgClass(): string {
|
|
120
120
|
if (!this.background || this.background === 'faint') return '';
|
|
121
121
|
if (this.background === 'always-dark') return 'on-always-dark';
|
|
122
|
+
if (this.background === 'navigation') return 'on-navigation';
|
|
122
123
|
return `on-${this.background}`;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
render() {
|
|
126
127
|
const bgClass = this.getBgClass();
|
|
127
128
|
const isVertical = this.orientation === 'vertical';
|
|
129
|
+
const isNavigation = this.background === 'navigation';
|
|
128
130
|
|
|
129
131
|
return (
|
|
130
132
|
<Host class="tab-group-nav-host">
|
|
131
133
|
<div
|
|
132
134
|
role="tablist"
|
|
133
|
-
class={{
|
|
135
|
+
class={{
|
|
136
|
+
'tab-list': true,
|
|
137
|
+
'tab-list--vertical': isVertical,
|
|
138
|
+
'tab-list--on-navigation': isNavigation,
|
|
139
|
+
}}
|
|
134
140
|
aria-label={this.ariaLabel}
|
|
135
141
|
aria-labelledby={this.ariaLabelledby}
|
|
136
142
|
aria-orientation={isVertical ? 'vertical' : undefined}
|