@ds-mo/ui 1.6.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/components/ds-app-shell.js +1 -1
  3. package/dist/components/ds-app-shell.js.map +1 -1
  4. package/dist/components/ds-badge.js +1 -1
  5. package/dist/components/ds-bar-nav-action.js +1 -1
  6. package/dist/components/ds-bar-nav.js +1 -1
  7. package/dist/components/ds-bar-nav.js.map +1 -1
  8. package/dist/components/ds-panel-nav.js +1 -1
  9. package/dist/components/ds-panel-nav.js.map +1 -1
  10. package/dist/components/ds-tab-group-nav.js +1 -1
  11. package/dist/components/ds-tab-group.js +1 -1
  12. package/dist/components/p--QMsZsaC.js +2 -0
  13. package/dist/components/p--QMsZsaC.js.map +1 -0
  14. package/dist/components/p-BdI4Wjw3.js +2 -0
  15. package/dist/components/p-BdI4Wjw3.js.map +1 -0
  16. package/dist/components/p-CXkDP-ct.js +2 -0
  17. package/dist/components/p-CXkDP-ct.js.map +1 -0
  18. package/dist/components/p-DmpLrzQp.js +2 -0
  19. package/dist/components/p-DmpLrzQp.js.map +1 -0
  20. package/dist/types/components/Badge/Badge.d.ts +13 -0
  21. package/dist/types/components/BarNav/BarNav.d.ts +1 -0
  22. package/dist/types/components/BarNavAction/BarNavAction.d.ts +1 -0
  23. package/dist/types/components.d.ts +11 -0
  24. package/dist/types/nav/badge-gradient-ring.d.ts +28 -0
  25. package/dist/types/nav/index.d.ts +2 -0
  26. package/package.json +2 -2
  27. package/src/angular/proxies.ts +2 -2
  28. package/src/wc/components/Badge/Badge.tsx +67 -1
  29. package/src/wc/components/BarNav/BarNav.tsx +5 -0
  30. package/src/wc/components/BarNavAction/BarNavAction.tsx +5 -1
  31. package/src/wc/components/PanelNav/PanelNav.tsx +2 -0
  32. package/src/wc/components/TabGroupNav/TabGroupNav.tsx +2 -0
  33. package/src/wc/components.d.ts +11 -0
  34. package/src/wc/nav/badge-gradient-ring.ts +109 -0
  35. package/src/wc/nav/index.ts +10 -0
  36. package/dist/components/p-B_enucPQ.js +0 -2
  37. package/dist/components/p-B_enucPQ.js.map +0 -1
  38. package/dist/components/p-DceSoh5V.js +0 -2
  39. package/dist/components/p-DceSoh5V.js.map +0 -1
  40. package/dist/components/p-_LI2ymhS.js +0 -2
  41. package/dist/components/p-_LI2ymhS.js.map +0 -1
@@ -2,6 +2,7 @@ import { EventEmitter } from '../../stencil-public-runtime';
2
2
  import type { NavChromeStyle } from '../../nav/nav-chrome';
3
3
  import type { BarNavActionItem, BarNavTab } from './bar-nav-types';
4
4
  export declare class BarNav {
5
+ el: HTMLElement;
5
6
  /**
6
7
  * Tab items for the left section.
7
8
  * Set via JS property: `el.tabs = [...]`. Replace the array reference to update.
@@ -1,6 +1,7 @@
1
1
  import { EventEmitter } from '../../stencil-public-runtime';
2
2
  export type BarNavActionBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark' | 'navigation';
3
3
  export declare class BarNavAction {
4
+ el: HTMLElement;
4
5
  /** Icon name passed to <ds-icon>. */
5
6
  icon: string;
6
7
  /** Controlled toggle/selected state. */
@@ -120,6 +120,11 @@ export namespace Components {
120
120
  * @default 0
121
121
  */
122
122
  "count": number;
123
+ /**
124
+ * Ring samples the shell gradient stack (base fill + wash) instead of a flat `box-shadow`. Use on badges over `ds-app-shell[gradient]` nav chrome.
125
+ * @default false
126
+ */
127
+ "gradientBackground": boolean;
123
128
  /**
124
129
  * Deprecated alias for selected counter styling. Prefer context-specific color in the parent.
125
130
  * @default false
@@ -1746,6 +1751,11 @@ declare namespace LocalJSX {
1746
1751
  * @default 0
1747
1752
  */
1748
1753
  "count"?: number;
1754
+ /**
1755
+ * Ring samples the shell gradient stack (base fill + wash) instead of a flat `box-shadow`. Use on badges over `ds-app-shell[gradient]` nav chrome.
1756
+ * @default false
1757
+ */
1758
+ "gradientBackground"?: boolean;
1749
1759
  /**
1750
1760
  * Deprecated alias for selected counter styling. Prefer context-specific color in the parent.
1751
1761
  * @default false
@@ -2775,6 +2785,7 @@ declare namespace LocalJSX {
2775
2785
  "max": number;
2776
2786
  "surface": BadgeSurface;
2777
2787
  "background": string | undefined;
2788
+ "gradientBackground": boolean;
2778
2789
  "isSelected": boolean;
2779
2790
  "label": string | undefined;
2780
2791
  }
@@ -0,0 +1,28 @@
1
+ /** Per-badge background-position for shell gradient ring sampling. */
2
+ export declare const BADGE_GRADIENT_POSITION_VAR = "--_badge-gradient-position";
3
+ export interface GradientSurface {
4
+ element: HTMLElement;
5
+ chromeHost: HTMLElement;
6
+ positionVar: string;
7
+ }
8
+ /** Whether the badge sits under `ds-app-shell[gradient]`. */
9
+ export declare function isShellGradientActive(from: HTMLElement): boolean;
10
+ /** Bar or panel chrome surface that owns the shell gradient stack. */
11
+ export declare function findGradientSurface(from: HTMLElement): GradientSurface | null;
12
+ interface ParsedPosition {
13
+ x: number;
14
+ y: number;
15
+ }
16
+ /** Parse a two-value CSS background-position (e.g. `-200px 0`). */
17
+ export declare function parseCssBackgroundPosition(value: string): ParsedPosition;
18
+ /**
19
+ * Background position for a badge ring so the shell gradient aligns with nav chrome.
20
+ * Uses badge center relative to the painted chrome surface.
21
+ */
22
+ export declare function badgeGradientPosition(badgeHost: HTMLElement, surface: GradientSurface, shellPosition: string): string;
23
+ /** Resolve shell gradient position from chrome host custom properties. */
24
+ export declare function readShellGradientPosition(surface: GradientSurface): string;
25
+ /** Stamp `--_badge-gradient-position` on the badge host. */
26
+ export declare function syncBadgeGradientPosition(badgeHost: HTMLElement): void;
27
+ export {};
28
+ //# sourceMappingURL=badge-gradient-ring.d.ts.map
@@ -4,4 +4,6 @@ export { SHELL_BAR_NAV_VT_NAME, parseCssTimeMs, ensureShellNavVtStyle, resolveSh
4
4
  export type { ShellNavRevealOrigin } from './shell-view-transition';
5
5
  export { SHELL_GRADIENT_IMAGE_VAR, SHELL_GRADIENT_SIZE_VAR, SHELL_GRADIENT_POSITION_PANEL_VAR, SHELL_GRADIENT_POSITION_BAR_VAR, SHELL_GRADIENT_OPACITY_VAR, SHELL_GRADIENT_OPACITY, buildShellRadialGradient, shellGradientImageForStyle, shellGradientSize, shellGradientPositionPanel, shellGradientPositionBar, } from './shell-gradient';
6
6
  export type { ShellGradientLayout } from './shell-gradient';
7
+ export { BADGE_GRADIENT_POSITION_VAR, badgeGradientPosition, findGradientSurface, isShellGradientActive, parseCssBackgroundPosition, readShellGradientPosition, syncBadgeGradientPosition, } from './badge-gradient-ring';
8
+ export type { GradientSurface } from './badge-gradient-ring';
7
9
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ds-mo/ui",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "description": "CompoMo — composable web components styled with TokoMo design tokens",
5
5
  "keywords": [
6
6
  "web-components",
@@ -69,7 +69,7 @@
69
69
  "pretest": "node scripts/generate-icon-catalog.mjs",
70
70
  "build": "stencil build && node scripts/patch-index-types.mjs && node scripts/verify-icons-externalized.mjs && node scripts/write-build-stamp.mjs",
71
71
  "verify:pack": "node scripts/verify-npm-pack.mjs && node scripts/verify-nav-import.mjs",
72
- "test": "node --import tsx/esm --test tests/panel-nav-utils.test.ts tests/shell-view-transition.test.ts tests/shell-gradient.test.ts tests/resolve-css-length-px.test.ts tests/resolve-css-time-ms.test.ts tests/overlay-positioning.test.ts tests/menu-position.test.ts tests/bar-nav-utils.test.ts tests/bar-nav-tabs-menu-utils.test.ts tests/bar-nav-dom-utils.test.ts tests/icon-catalog.test.ts",
72
+ "test": "node --import tsx/esm --test tests/panel-nav-utils.test.ts tests/shell-view-transition.test.ts tests/shell-gradient.test.ts tests/badge-gradient-ring.test.ts tests/resolve-css-length-px.test.ts tests/resolve-css-time-ms.test.ts tests/overlay-positioning.test.ts tests/menu-position.test.ts tests/bar-nav-utils.test.ts tests/bar-nav-tabs-menu-utils.test.ts tests/bar-nav-dom-utils.test.ts tests/icon-catalog.test.ts",
73
73
  "test:e2e": "npm run build && playwright test",
74
74
  "test:e2e:install": "playwright install chromium",
75
75
  "build:docs": "stencil build --docs",
@@ -59,14 +59,14 @@ export declare interface DsAppShell extends Components.DsAppShell {}
59
59
 
60
60
 
61
61
  @ProxyCmp({
62
- inputs: ['background', 'count', 'isSelected', 'label', 'max', 'surface', 'variant']
62
+ inputs: ['background', 'count', 'gradientBackground', 'isSelected', 'label', 'max', 'surface', 'variant']
63
63
  })
64
64
  @Component({
65
65
  selector: 'ds-badge',
66
66
  changeDetection: ChangeDetectionStrategy.OnPush,
67
67
  template: '<ng-content></ng-content>',
68
68
  // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
69
- inputs: ['background', 'count', 'isSelected', 'label', 'max', 'surface', 'variant'],
69
+ inputs: ['background', 'count', 'gradientBackground', 'isSelected', 'label', 'max', 'surface', 'variant'],
70
70
  standalone: false
71
71
  })
72
72
  export class DsBadge {
@@ -1,4 +1,8 @@
1
- import { Component, Prop, h, Host } from '@stencil/core';
1
+ import { Component, Prop, Element, Watch, h, Host } from '@stencil/core';
2
+ import {
3
+ BADGE_GRADIENT_POSITION_VAR,
4
+ syncBadgeGradientPosition,
5
+ } from '../../nav/badge-gradient-ring';
2
6
 
3
7
  export type BadgeVariant = 'counter' | 'dot';
4
8
  export type BadgeSurface =
@@ -28,6 +32,8 @@ const SURFACE_RING: Record<BadgeSurface, string> = {
28
32
  scoped: true,
29
33
  })
30
34
  export class Badge {
35
+ @Element() el!: HTMLElement;
36
+
31
37
  /** Render as a compact counter or notification dot. */
32
38
  @Prop() variant: BadgeVariant = 'counter';
33
39
 
@@ -43,12 +49,71 @@ export class Badge {
43
49
  /** Direct ring background override for component-local surfaces. */
44
50
  @Prop() background: string | undefined;
45
51
 
52
+ /**
53
+ * Ring samples the shell gradient stack (base fill + wash) instead of a flat
54
+ * `box-shadow`. Use on badges over `ds-app-shell[gradient]` nav chrome.
55
+ */
56
+ @Prop({ attribute: 'on-gradient-background', reflect: true }) gradientBackground: boolean = false;
57
+
46
58
  /** Deprecated alias for selected counter styling. Prefer context-specific color in the parent. */
47
59
  @Prop() isSelected: boolean = false;
48
60
 
49
61
  /** Accessible label. Defaults to the count as a string. */
50
62
  @Prop() label: string | undefined;
51
63
 
64
+ private gradientObserver: ResizeObserver | null = null;
65
+ private gradientWindowListener: (() => void) | null = null;
66
+
67
+ componentDidLoad() {
68
+ this.bindGradientRingSync();
69
+ }
70
+
71
+ disconnectedCallback() {
72
+ this.unbindGradientRingSync();
73
+ this.el.style.removeProperty(BADGE_GRADIENT_POSITION_VAR);
74
+ }
75
+
76
+ @Watch('gradientBackground')
77
+ gradientBackgroundChanged() {
78
+ this.bindGradientRingSync();
79
+ }
80
+
81
+ private bindGradientRingSync() {
82
+ this.unbindGradientRingSync();
83
+
84
+ if (!this.gradientBackground) return;
85
+
86
+ const update = () => syncBadgeGradientPosition(this.el);
87
+ update();
88
+
89
+ this.gradientWindowListener = update;
90
+ window.addEventListener('resize', update);
91
+
92
+ if (typeof ResizeObserver !== 'undefined') {
93
+ this.gradientObserver = new ResizeObserver(update);
94
+ this.gradientObserver.observe(this.el);
95
+
96
+ const shell = this.el.closest('ds-app-shell');
97
+ if (shell) this.gradientObserver.observe(shell);
98
+
99
+ const bar = this.el.closest('ds-bar-nav');
100
+ if (bar) this.gradientObserver.observe(bar);
101
+
102
+ const panel = this.el.closest('ds-panel-nav');
103
+ if (panel) this.gradientObserver.observe(panel);
104
+ }
105
+ }
106
+
107
+ private unbindGradientRingSync() {
108
+ if (this.gradientWindowListener) {
109
+ window.removeEventListener('resize', this.gradientWindowListener);
110
+ this.gradientWindowListener = null;
111
+ }
112
+
113
+ this.gradientObserver?.disconnect();
114
+ this.gradientObserver = null;
115
+ }
116
+
52
117
  render() {
53
118
  const isDot = this.variant === 'dot';
54
119
 
@@ -65,6 +130,7 @@ export class Badge {
65
130
  'badge--counter': !isDot,
66
131
  'badge--dot': isDot,
67
132
  'badge--selected': this.isSelected,
133
+ 'badge--on-gradient-background': this.gradientBackground,
68
134
  }}
69
135
  aria-label={ariaLabel}
70
136
  style={{ '--_badge-ring': ring }}
@@ -3,6 +3,7 @@ import {
3
3
  Prop,
4
4
  Event,
5
5
  EventEmitter,
6
+ Element,
6
7
  Watch,
7
8
  State,
8
9
  h,
@@ -11,6 +12,7 @@ import {
11
12
  import type { MenuItemData } from '../Menu/menu-types';
12
13
  import type { BarNavActionBackground } from '../BarNavAction/BarNavAction';
13
14
  import type { NavChromeStyle } from '../../nav/nav-chrome';
15
+ import { isShellGradientActive } from '../../nav/badge-gradient-ring';
14
16
  import { SHELL_BAR_NAV_VT_NAME } from '../../nav/shell-view-transition';
15
17
  import type { BarNavActionItem, BarNavTab } from './bar-nav-types';
16
18
  import {
@@ -36,6 +38,8 @@ import {
36
38
  scoped: true,
37
39
  })
38
40
  export class BarNav {
41
+ @Element() el!: HTMLElement;
42
+
39
43
  /**
40
44
  * Tab items for the left section.
41
45
  * Set via JS property: `el.tabs = [...]`. Replace the array reference to update.
@@ -547,6 +551,7 @@ export class BarNav {
547
551
  class="bar-nav__tab-trigger-dot"
548
552
  variant="dot"
549
553
  background="var(--_bar-nav-bg)"
554
+ on-gradient-background={isShellGradientActive(this.el)}
550
555
  label=""
551
556
  aria-hidden="true"
552
557
  />
@@ -1,4 +1,5 @@
1
- import { Component, Prop, Event, EventEmitter, h, Host } from '@stencil/core';
1
+ import { Component, Prop, Event, EventEmitter, Element, h, Host } from '@stencil/core';
2
+ import { isShellGradientActive } from '../../nav/badge-gradient-ring';
2
3
 
3
4
  export type BarNavActionBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark' | 'navigation';
4
5
 
@@ -8,6 +9,8 @@ export type BarNavActionBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'a
8
9
  scoped: true,
9
10
  })
10
11
  export class BarNavAction {
12
+ @Element() el!: HTMLElement;
13
+
11
14
  /** Icon name passed to <ds-icon>. */
12
15
  @Prop() icon: string = '';
13
16
 
@@ -64,6 +67,7 @@ export class BarNavAction {
64
67
  class="action-btn__dot"
65
68
  variant="dot"
66
69
  background="var(--_dot-ring)"
70
+ on-gradient-background={isShellGradientActive(this.el)}
67
71
  label=""
68
72
  aria-hidden="true"
69
73
  />
@@ -1,5 +1,6 @@
1
1
  import { Component, Prop, Event, EventEmitter, Watch, State, Element, h, Host } from '@stencil/core';
2
2
  import type { NavChromeStyle } from '../../nav/nav-chrome';
3
+ import { isShellGradientActive } from '../../nav/badge-gradient-ring';
3
4
  import {
4
5
  animateShellNavRadialReveal,
5
6
  ensureShellNavVtStyle,
@@ -482,6 +483,7 @@ export class PanelNav {
482
483
  class="panel-nav__item-dot"
483
484
  variant="dot"
484
485
  background="var(--_nav-bg)"
486
+ on-gradient-background={isShellGradientActive(this.el)}
485
487
  label=""
486
488
  aria-hidden="true"
487
489
  />
@@ -1,4 +1,5 @@
1
1
  import { Component, Prop, Event, EventEmitter, Element, Listen, Watch, h, Host } from '@stencil/core';
2
+ import { isShellGradientActive } from '../../nav/badge-gradient-ring';
2
3
  import {
3
4
  getSelectableTabs,
4
5
  isTabDivider,
@@ -187,6 +188,7 @@ export class TabGroupNav {
187
188
  class="tab__dot"
188
189
  variant="dot"
189
190
  background="var(--_dot-ring)"
191
+ on-gradient-background={isShellGradientActive(this.el)}
190
192
  label=""
191
193
  aria-hidden="true"
192
194
  />
@@ -120,6 +120,11 @@ export namespace Components {
120
120
  * @default 0
121
121
  */
122
122
  "count": number;
123
+ /**
124
+ * Ring samples the shell gradient stack (base fill + wash) instead of a flat `box-shadow`. Use on badges over `ds-app-shell[gradient]` nav chrome.
125
+ * @default false
126
+ */
127
+ "gradientBackground": boolean;
123
128
  /**
124
129
  * Deprecated alias for selected counter styling. Prefer context-specific color in the parent.
125
130
  * @default false
@@ -1746,6 +1751,11 @@ declare namespace LocalJSX {
1746
1751
  * @default 0
1747
1752
  */
1748
1753
  "count"?: number;
1754
+ /**
1755
+ * Ring samples the shell gradient stack (base fill + wash) instead of a flat `box-shadow`. Use on badges over `ds-app-shell[gradient]` nav chrome.
1756
+ * @default false
1757
+ */
1758
+ "gradientBackground"?: boolean;
1749
1759
  /**
1750
1760
  * Deprecated alias for selected counter styling. Prefer context-specific color in the parent.
1751
1761
  * @default false
@@ -2775,6 +2785,7 @@ declare namespace LocalJSX {
2775
2785
  "max": number;
2776
2786
  "surface": BadgeSurface;
2777
2787
  "background": string | undefined;
2788
+ "gradientBackground": boolean;
2778
2789
  "isSelected": boolean;
2779
2790
  "label": string | undefined;
2780
2791
  }
@@ -0,0 +1,109 @@
1
+ import {
2
+ SHELL_GRADIENT_POSITION_BAR_VAR,
3
+ SHELL_GRADIENT_POSITION_PANEL_VAR,
4
+ } from './shell-gradient';
5
+
6
+ /** Per-badge background-position for shell gradient ring sampling. */
7
+ export const BADGE_GRADIENT_POSITION_VAR = '--_badge-gradient-position';
8
+
9
+ export interface GradientSurface {
10
+ element: HTMLElement;
11
+ chromeHost: HTMLElement;
12
+ positionVar: string;
13
+ }
14
+
15
+ /** Whether the badge sits under `ds-app-shell[gradient]`. */
16
+ export function isShellGradientActive(from: HTMLElement): boolean {
17
+ const shell = from.closest('ds-app-shell');
18
+ return shell?.hasAttribute('gradient') === true;
19
+ }
20
+
21
+ /** Bar or panel chrome surface that owns the shell gradient stack. */
22
+ export function findGradientSurface(from: HTMLElement): GradientSurface | null {
23
+ const barHost = from.closest('ds-bar-nav');
24
+ if (barHost instanceof HTMLElement && barHost.shadowRoot) {
25
+ const element = barHost.shadowRoot.querySelector('.bar-nav');
26
+ if (element instanceof HTMLElement) {
27
+ return {
28
+ element,
29
+ chromeHost: barHost,
30
+ positionVar: SHELL_GRADIENT_POSITION_BAR_VAR,
31
+ };
32
+ }
33
+ }
34
+
35
+ const panelHost = from.closest('ds-panel-nav');
36
+ if (panelHost instanceof HTMLElement && panelHost.shadowRoot) {
37
+ const element = panelHost.shadowRoot.querySelector('.panel-nav');
38
+ if (element instanceof HTMLElement) {
39
+ return {
40
+ element,
41
+ chromeHost: panelHost,
42
+ positionVar: SHELL_GRADIENT_POSITION_PANEL_VAR,
43
+ };
44
+ }
45
+ }
46
+
47
+ return null;
48
+ }
49
+
50
+ interface ParsedPosition {
51
+ x: number;
52
+ y: number;
53
+ }
54
+
55
+ /** Parse a two-value CSS background-position (e.g. `-200px 0`). */
56
+ export function parseCssBackgroundPosition(value: string): ParsedPosition {
57
+ const trimmed = value.trim();
58
+ if (!trimmed) return { x: 0, y: 0 };
59
+
60
+ const parts = trimmed.split(/\s+/);
61
+ const x = parseLength(parts[0] ?? '0');
62
+ const y = parseLength(parts[1] ?? '0');
63
+ return { x, y };
64
+ }
65
+
66
+ function parseLength(token: string): number {
67
+ const px = token.match(/^(-?[\d.]+)px$/);
68
+ if (px) return Number(px[1]);
69
+ return 0;
70
+ }
71
+
72
+ /**
73
+ * Background position for a badge ring so the shell gradient aligns with nav chrome.
74
+ * Uses badge center relative to the painted chrome surface.
75
+ */
76
+ export function badgeGradientPosition(
77
+ badgeHost: HTMLElement,
78
+ surface: GradientSurface,
79
+ shellPosition: string,
80
+ ): string {
81
+ const badgeRect = badgeHost.getBoundingClientRect();
82
+ const surfaceRect = surface.element.getBoundingClientRect();
83
+ const anchorX = badgeRect.left + badgeRect.width / 2 - surfaceRect.left;
84
+ const anchorY = badgeRect.top + badgeRect.height / 2 - surfaceRect.top;
85
+ const { x, y } = parseCssBackgroundPosition(shellPosition);
86
+
87
+ return `${Math.round(x - anchorX)}px ${Math.round(y - anchorY)}px`;
88
+ }
89
+
90
+ /** Resolve shell gradient position from chrome host custom properties. */
91
+ export function readShellGradientPosition(surface: GradientSurface): string {
92
+ const styles = getComputedStyle(surface.chromeHost);
93
+ return styles.getPropertyValue(surface.positionVar).trim() || '0 0';
94
+ }
95
+
96
+ /** Stamp `--_badge-gradient-position` on the badge host. */
97
+ export function syncBadgeGradientPosition(badgeHost: HTMLElement): void {
98
+ const surface = findGradientSurface(badgeHost);
99
+ if (!surface) {
100
+ badgeHost.style.removeProperty(BADGE_GRADIENT_POSITION_VAR);
101
+ return;
102
+ }
103
+
104
+ const shellPosition = readShellGradientPosition(surface);
105
+ badgeHost.style.setProperty(
106
+ BADGE_GRADIENT_POSITION_VAR,
107
+ badgeGradientPosition(badgeHost, surface, shellPosition),
108
+ );
109
+ }
@@ -31,3 +31,13 @@ export {
31
31
  shellGradientPositionBar,
32
32
  } from './shell-gradient';
33
33
  export type { ShellGradientLayout } from './shell-gradient';
34
+ export {
35
+ BADGE_GRADIENT_POSITION_VAR,
36
+ badgeGradientPosition,
37
+ findGradientSurface,
38
+ isShellGradientActive,
39
+ parseCssBackgroundPosition,
40
+ readShellGradientPosition,
41
+ syncBadgeGradientPosition,
42
+ } from './badge-gradient-ring';
43
+ export type { GradientSurface } from './badge-gradient-ring';
@@ -1,2 +0,0 @@
1
- import{p as e,H as a,h as r,a as s,t as d}from"./index.js";const n=()=>`.sc-ds-badge-h{display:inline-flex;align-items:center;justify-content:center;pointer-events:none;vertical-align:middle;--_badge-bg:var(--color-background-bold-brand);--_badge-fg:var(--color-foreground-on-bold-background-primary);--_badge-ring:var(--color-background-secondary)}.badge__mark.sc-ds-badge{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;color:var(--_badge-fg);background:var(--_badge-bg);box-shadow:0 0 0 var(--dimension-stroke-width-018) var(--_badge-ring);white-space:nowrap}.badge--dot.sc-ds-badge-h .badge__mark.sc-ds-badge{width:var(--dimension-size-075);height:var(--dimension-size-075);border-radius:var(--dimension-radius-half)}.badge--counter.sc-ds-badge-h .badge__mark.sc-ds-badge{width:var(--dimension-size-150);height:var(--dimension-size-150);padding:0;border-radius:var(--dimension-radius-half);font-size:var(--typography-fontsize-xs);line-height:1}.badge--selected.sc-ds-badge-h{--_badge-bg:var(--color-foreground-primary)}`;const o={default:"var(--color-background-secondary)",primary:"var(--color-background-primary)",secondary:"var(--color-background-secondary)",medium:"var(--color-background-medium-neutral)",bold:"var(--color-background-bold-neutral)",strong:"var(--color-background-strong-neutral)",navigation:"var(--color-navigation-background)","always-dark":"var(--color-always-dark-background)"};const t=e(class e extends a{constructor(e){super();if(e!==false){this.__registerHost()}this.variant="counter";this.count=0;this.max=9;this.surface="default";this.isSelected=false}render(){const e=this.variant==="dot";if(!e&&this.count===0)return r(s,{style:{display:"none"}});const a=this.count>this.max?"+":String(this.count);const d=this.label??(e?"Notification":String(this.count));const n=this.background??o[this.surface];return r(s,{class:{badge:true,"badge--counter":!e,"badge--dot":e,"badge--selected":this.isSelected},"aria-label":d,style:{"--_badge-ring":n}},r("span",{class:{badge__mark:true,"text-caption-emphasis":!e},"aria-hidden":"true"},!e&&a))}static get style(){return n()}},[2,"ds-badge",{variant:[1],count:[2],max:[2],surface:[1],background:[1],isSelected:[4,"is-selected"],label:[1]}]);function i(){if(typeof customElements==="undefined"){return}const e=["ds-badge"];e.forEach((e=>{switch(e){case"ds-badge":if(!customElements.get(d(e))){customElements.define(d(e),t)}break}}))}i();export{t as B,i as d};
2
- //# sourceMappingURL=p-B_enucPQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["badgeCss","SURFACE_RING","default","primary","secondary","medium","bold","strong","navigation","Badge","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","variant","count","max","surface","isSelected","render","isDot","h","Host","style","display","String","ariaLabel","label","ring","background","class","badge","badge__mark"],"sources":["src/wc/components/Badge/Badge.css?tag=ds-badge&encapsulation=scoped","src/wc/components/Badge/Badge.tsx"],"sourcesContent":[":host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n vertical-align: middle;\n\n --_badge-bg: var(--color-background-bold-brand);\n --_badge-fg: var(--color-foreground-on-bold-background-primary);\n --_badge-ring: var(--color-background-secondary);\n}\n\n.badge__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-sizing: border-box;\n color: var(--_badge-fg);\n background: var(--_badge-bg);\n box-shadow: 0 0 0 var(--dimension-stroke-width-018) var(--_badge-ring);\n white-space: nowrap;\n}\n\n:host(.badge--dot) .badge__mark {\n width: var(--dimension-size-075);\n height: var(--dimension-size-075);\n border-radius: var(--dimension-radius-half);\n}\n\n:host(.badge--counter) .badge__mark {\n width: var(--dimension-size-150);\n height: var(--dimension-size-150);\n padding: 0;\n border-radius: var(--dimension-radius-half);\n font-size: var(--typography-fontsize-xs);\n line-height: 1;\n}\n\n:host(.badge--selected) {\n --_badge-bg: var(--color-foreground-primary);\n}\n","import { Component, Prop, h, Host } from '@stencil/core';\n\nexport type BadgeVariant = 'counter' | 'dot';\nexport type BadgeSurface =\n | 'default'\n | 'primary'\n | 'secondary'\n | 'medium'\n | 'bold'\n | 'strong'\n | 'navigation'\n | 'always-dark';\n\nconst SURFACE_RING: Record<BadgeSurface, string> = {\n default: 'var(--color-background-secondary)',\n primary: 'var(--color-background-primary)',\n secondary: 'var(--color-background-secondary)',\n medium: 'var(--color-background-medium-neutral)',\n bold: 'var(--color-background-bold-neutral)',\n strong: 'var(--color-background-strong-neutral)',\n navigation: 'var(--color-navigation-background)',\n 'always-dark': 'var(--color-always-dark-background)',\n};\n\n@Component({\n tag: 'ds-badge',\n styleUrl: 'Badge.css',\n scoped: true,\n})\nexport class Badge {\n /** Render as a compact counter or notification dot. */\n @Prop() variant: BadgeVariant = 'counter';\n\n /** Count shown for counter badges. Count 0 hides the badge. */\n @Prop() count: number = 0;\n\n /** Highest count shown before compacting to \"+\". */\n @Prop() max: number = 9;\n\n /** Surface context for the ring around dots. */\n @Prop() surface: BadgeSurface = 'default';\n\n /** Direct ring background override for component-local surfaces. */\n @Prop() background: string | undefined;\n\n /** Deprecated alias for selected counter styling. Prefer context-specific color in the parent. */\n @Prop() isSelected: boolean = false;\n\n /** Accessible label. Defaults to the count as a string. */\n @Prop() label: string | undefined;\n\n render() {\n const isDot = this.variant === 'dot';\n\n if (!isDot && this.count === 0) return <Host style={{ display: 'none' }} />;\n\n const display = this.count > this.max ? '+' : String(this.count);\n const ariaLabel = this.label ?? (isDot ? 'Notification' : String(this.count));\n const ring = this.background ?? SURFACE_RING[this.surface];\n\n return (\n <Host\n class={{\n badge: true,\n 'badge--counter': !isDot,\n 'badge--dot': isDot,\n 'badge--selected': this.isSelected,\n }}\n aria-label={ariaLabel}\n style={{ '--_badge-ring': ring }}\n >\n <span\n class={{\n 'badge__mark': true,\n 'text-caption-emphasis': !isDot,\n }}\n aria-hidden=\"true\"\n >\n {!isDot && display}\n </span>\n </Host>\n );\n }\n}\n"],"mappings":"2DAAA,MAAMA,EAAW,IAAM,4+BCavB,MAAMC,EAA6C,CACjDC,QAAS,oCACTC,QAAS,kCACTC,UAAW,oCACXC,OAAQ,yCACRC,KAAM,uCACNC,OAAQ,yCACRC,WAAY,qCACZ,cAAe,uC,MAQJC,EAAKC,EAAA,MAAAD,UAAAE,EALlB,WAAAC,CAAAC,G,4CAOUC,KAAAC,QAAwB,UAGxBD,KAAAE,MAAgB,EAGhBF,KAAAG,IAAc,EAGdH,KAAAI,QAAwB,UAMxBJ,KAAAK,WAAsB,KAqC/B,CAhCC,MAAAC,GACE,MAAMC,EAAQP,KAAKC,UAAY,MAE/B,IAAKM,GAASP,KAAKE,QAAU,EAAG,OAAOM,EAACC,EAAI,CAACC,MAAO,CAAEC,QAAS,UAE/D,MAAMA,EAAUX,KAAKE,MAAQF,KAAKG,IAAM,IAAMS,OAAOZ,KAAKE,OAC1D,MAAMW,EAAYb,KAAKc,QAAUP,EAAQ,eAAiBK,OAAOZ,KAAKE,QACtE,MAAMa,EAAOf,KAAKgB,YAAc7B,EAAaa,KAAKI,SAElD,OACEI,EAACC,EAAI,CACHQ,MAAO,CACLC,MAAO,KACP,kBAAmBX,EACnB,aAAcA,EACd,kBAAmBP,KAAKK,YACzB,aACWQ,EACZH,MAAO,CAAE,gBAAiBK,IAE1BP,EAAA,QACES,MAAO,CACLE,YAAe,KACf,yBAA0BZ,GAC3B,cACW,SAEVA,GAASI,G","ignoreList":[]}
@@ -1,2 +0,0 @@
1
- import{p as a,H as r,c as o,h as t,a as e,t as n}from"./index.js";import{g as i,i as s}from"./p-BQq26pt9.js";import{d}from"./p-B_enucPQ.js";const c=()=>`.sc-ds-tab-group-nav-h{display:block}.tab-list.sc-ds-tab-group-nav{display:flex;align-items:center;gap:var(--dimension-space-050);position:relative}.tab-list--vertical.sc-ds-tab-group-nav{flex-direction:column;align-items:stretch}.tab.sc-ds-tab-group-nav{display:flex;align-items:center;justify-content:center;gap:var(--dimension-space-050);padding:var(--dimension-space-075);background-color:transparent;border:none;border-radius:var(--dimension-radius-025);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--color-foreground-secondary);position:relative;transition:color var(--effect-motion-short-2);flex-shrink:0;height:var(--dimension-size-400);min-width:var(--dimension-size-400);box-sizing:border-box;--_hover-bg:var(--color-interaction-hover);--_pressed-bg:var(--color-interaction-pressed);--_dot:var(--color-foreground-bold-brand);--_dot-ring:var(--color-background-secondary)}.tab.sc-ds-tab-group-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025, 2px);background:transparent;pointer-events:none;transition:none}.tab.sc-ds-tab-group-nav:hover::after{background:var(--_hover-bg);transition:none}.tab.sc-ds-tab-group-nav:active::after{background:var(--_pressed-bg);transition:none}.tab.sc-ds-tab-group-nav:focus-visible:not(:hover):not(:active)::after{background:transparent}.tab--selected.sc-ds-tab-group-nav{color:var(--color-foreground-primary)}.tab.sc-ds-tab-group-nav:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.tab.sc-ds-tab-group-nav:disabled,.tab[aria-disabled="true"].sc-ds-tab-group-nav{opacity:0.5;cursor:not-allowed;pointer-events:none}.tab-list--vertical.sc-ds-tab-group-nav .tab.sc-ds-tab-group-nav{justify-content:flex-start}.tab__label.sc-ds-tab-group-nav{position:relative;display:inline-flex;align-items:center;padding:0 var(--dimension-space-025);white-space:nowrap}.tab__label--dot.sc-ds-tab-group-nav{padding-right:calc(var(--dimension-space-025) + var(--dimension-space-050))}.tab__dot.sc-ds-tab-group-nav{position:absolute;top:0;right:0;pointer-events:none}.on-medium.sc-ds-tab-group-nav{--_hover-bg:var(--color-interaction-on-medium-background-hover);--_pressed-bg:var(--color-interaction-on-medium-background-pressed);--_dot-ring:var(--color-background-medium-neutral)}.on-bold.sc-ds-tab-group-nav{--_hover-bg:var(--color-interaction-on-bold-background-hover);--_pressed-bg:var(--color-interaction-on-bold-background-pressed);--_dot-ring:var(--color-background-bold-neutral);color:var(--color-foreground-on-bold-background-secondary)}.on-bold.tab--selected.sc-ds-tab-group-nav{color:var(--color-foreground-on-bold-background-primary)}.on-strong.sc-ds-tab-group-nav{--_hover-bg:var(--color-interaction-on-strong-background-hover);--_pressed-bg:var(--color-interaction-on-strong-background-pressed);--_dot-ring:var(--color-background-strong-neutral);color:var(--color-foreground-on-bold-background-secondary)}.on-strong.tab--selected.sc-ds-tab-group-nav{color:var(--color-foreground-on-bold-background-primary)}.on-always-dark.sc-ds-tab-group-nav{--_hover-bg:var(--color-always-dark-interaction-hover);--_pressed-bg:var(--color-always-dark-interaction-pressed);--_dot-ring:var(--color-always-dark-background);color:var(--color-always-dark-foreground-secondary)}.on-always-dark.tab--selected.sc-ds-tab-group-nav{color:var(--color-always-dark-foreground-primary)}.on-navigation.sc-ds-tab-group-nav{color:var(--color-navigation-foreground-secondary);--_hover-bg:var(--color-navigation-interaction-hover);--_pressed-bg:var(--color-navigation-interaction-pressed);--_dot:var(--color-navigation-foreground-brand);--_dot-ring:var(--color-navigation-background)}.on-navigation.tab--selected.sc-ds-tab-group-nav{color:var(--color-navigation-foreground-primary)}.on-navigation.sc-ds-tab-group-nav:focus-visible{outline-color:var(--color-navigation-interaction-focus)}.tab-list--on-navigation.sc-ds-tab-group-nav .tab-divider__line.sc-ds-tab-group-nav{background-color:var(--color-navigation-border-tertiary)}.tab-divider.sc-ds-tab-group-nav{display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:var(--dimension-space-100);height:var(--dimension-size-400);padding-block:var(--dimension-space-075);flex-shrink:0;pointer-events:none}.tab-divider__line.sc-ds-tab-group-nav{width:var(--dimension-stroke-width-012);align-self:stretch;background-color:var(--color-border-secondary)}.tab-divider--vertical.sc-ds-tab-group-nav{width:auto;height:var(--dimension-space-100);align-self:stretch;padding-block:0;padding-inline:var(--dimension-space-075)}.tab-divider--vertical.sc-ds-tab-group-nav .tab-divider__line.sc-ds-tab-group-nav{width:auto;height:var(--dimension-stroke-width-012);align-self:stretch}`;const l=a(class a extends r{constructor(a){super();if(a!==false){this.__registerHost()}this.dsChange=o(this,"dsChange");this.value="";this.tabs=[];this.orientation="horizontal"}get selectableTabs(){return i(this.tabs)}selectTab(a,r){this.value=a;this.dsChange.emit(a);if(r?.focus!==false){this.focusTab(a)}}focusTab(a){const r=this.el.querySelector(`[data-tab-id="${a}"]`);r?.focus({preventScroll:true})}onValueChange(a,r){if(r===undefined||a===r)return;requestAnimationFrame((()=>{const r=document.activeElement;if(!r||!this.el.contains(r))return;const o=r.getAttribute("data-tab-id");if(o===a)return;const t=this.el.querySelector(`[data-tab-id="${a}"]`);if(t){t.focus({preventScroll:true})}else{r.blur()}}))}findEnabled(a,r){const o=this.selectableTabs;const t=o.length;for(let e=0;e<t;e++){const n=(a+r*(e+1)+t*(e+1))%t;if(!o[n]?.disabled)return n}return a}handleKeyDown(a){const r=this.selectableTabs;if(!r.length)return;const o=r.findIndex((a=>a.id===this.value));const t=this.orientation==="vertical";let e=null;if(!t){if(a.key==="ArrowRight"){e=this.findEnabled(o,1)}else if(a.key==="ArrowLeft"){e=this.findEnabled(o,-1)}}else{if(a.key==="ArrowDown"){e=this.findEnabled(o,1)}else if(a.key==="ArrowUp"){e=this.findEnabled(o,-1)}}if(a.key==="Home"){const a=r.findIndex((a=>!a.disabled));e=a===-1?null:a}else if(a.key==="End"){const a=[...r].reverse().findIndex((a=>!a.disabled));e=a===-1?null:r.length-1-a}if(e!==null){a.preventDefault();const o=r[e];this.selectTab(o.id)}}getBgClass(){if(!this.background||this.background==="faint")return"";if(this.background==="always-dark")return"on-always-dark";if(this.background==="navigation")return"on-navigation";return`on-${this.background}`}render(){const a=this.getBgClass();const r=this.orientation==="vertical";const o=this.background==="navigation";return t(e,{key:"c68d7a69a3c05c7e85e6ab4cf2be6d54351c55c1",class:"tab-group-nav-host"},t("div",{key:"4bf5c4ebc83ca93c0d7da6783f446de04a74854d",role:"tablist",class:{"tab-list":true,"tab-list--vertical":r,"tab-list--on-navigation":o},"aria-label":this.ariaLabel,"aria-labelledby":this.ariaLabelledby,"aria-orientation":r?"vertical":undefined},this.tabs.map(((o,e)=>{if(s(o)){return t("div",{key:`divider-${e}`,class:{"tab-divider":true,"tab-divider--vertical":r},"aria-hidden":"true"},t("div",{class:"tab-divider__line"}))}const n=o.id===this.value;return t("button",{key:o.id,type:"button",role:"tab","data-tab-id":o.id,class:{tab:true,"tab--selected":n,[a]:!!a},"aria-selected":n,"aria-disabled":o.disabled||undefined,"aria-controls":o.panelId??undefined,disabled:o.disabled,tabIndex:n?0:-1,onClick:()=>!o.disabled&&this.selectTab(o.id)},t("span",{class:{tab__label:true,"tab__label--dot":!!o.dot,[n?"text-body-medium-emphasis":"text-body-medium"]:true}},o.label,o.dot&&t("ds-badge",{class:"tab__dot",variant:"dot",background:"var(--_dot-ring)",label:"","aria-hidden":"true"})))}))))}get el(){return this}static get watchers(){return{value:[{onValueChange:0}]}}static get style(){return c()}},[2,"ds-tab-group-nav",{value:[1025],tabs:[16],background:[1],ariaLabel:[1,"aria-label"],ariaLabelledby:[1,"aria-labelledby"],orientation:[1]},[[0,"keydown","handleKeyDown"]],{value:[{onValueChange:0}]}]);function b(){if(typeof customElements==="undefined"){return}const a=["ds-tab-group-nav","ds-badge"];a.forEach((a=>{switch(a){case"ds-tab-group-nav":if(!customElements.get(n(a))){customElements.define(n(a),l)}break;case"ds-badge":if(!customElements.get(n(a))){d()}break}}))}b();export{l as T,b as d};
2
- //# sourceMappingURL=p-DceSoh5V.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["tabGroupNavCss","TabGroupNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","value","tabs","orientation","selectableTabs","getSelectableTabs","selectTab","id","options","dsChange","emit","focus","focusTab","btn","el","querySelector","preventScroll","onValueChange","next","prev","undefined","requestAnimationFrame","active","document","activeElement","contains","activeId","getAttribute","nextTab","blur","findEnabled","from","step","len","length","n","i","disabled","handleKeyDown","e","currentIdx","findIndex","t","isVertical","nextIdx","key","first","lastEnabled","reverse","preventDefault","getBgClass","background","render","bgClass","isNavigation","h","Host","class","role","ariaLabel","ariaLabelledby","map","tab","index","isTabDivider","isSelected","type","panelId","tabIndex","onClick","tab__label","dot","label","variant"],"sources":["src/wc/components/TabGroupNav/TabGroupNav.css?tag=ds-tab-group-nav&encapsulation=scoped","src/wc/components/TabGroupNav/TabGroupNav.tsx"],"sourcesContent":[":host {\n display: block;\n}\n\n.tab-list {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n position: relative;\n}\n\n/* Vertical orientation */\n.tab-list--vertical {\n flex-direction: column;\n align-items: stretch;\n}\n\n.tab {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-025);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n color: var(--color-foreground-secondary);\n position: relative;\n /* Only transition color — hover bg is instant (see ::after below) */\n transition: color var(--effect-motion-short-2);\n flex-shrink: 0;\n height: var(--dimension-size-400);\n min-width: var(--dimension-size-400);\n box-sizing: border-box;\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_dot: var(--color-foreground-bold-brand);\n --_dot-ring: var(--color-background-secondary);\n}\n\n/* Interaction layer — same pattern as PanelNav */\n.tab::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: var(--dimension-radius-025, 2px);\n background: transparent;\n pointer-events: none;\n transition: none;\n}\n\n.tab:hover::after { background: var(--_hover-bg); transition: none; }\n.tab:active::after { background: var(--_pressed-bg); transition: none; }\n\n/* Focus ring only — no persistent hover fill from keyboard focus */\n.tab:focus-visible:not(:hover):not(:active)::after {\n background: transparent;\n}\n\n.tab--selected { color: var(--color-foreground-primary); }\n\n.tab:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.tab:disabled,\n.tab[aria-disabled=\"true\"] {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* Vertical tabs read as a list — left-align the label */\n.tab-list--vertical .tab { justify-content: flex-start; }\n\n/* Label — dot anchors top-right like BarNav action icon zone */\n.tab__label {\n position: relative;\n display: inline-flex;\n align-items: center;\n padding: 0 var(--dimension-space-025);\n white-space: nowrap;\n}\n\n/* Clearance for top-right dot — slightly less than space-025 + space-075 */\n.tab__label--dot {\n padding-right: calc(var(--dimension-space-025) + var(--dimension-space-050));\n}\n\n/* Notification dot — top-right corner of the label zone */\n.tab__dot {\n position: absolute;\n top: 0;\n right: 0;\n pointer-events: none;\n}\n\n/* Background context */\n.on-medium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n --_dot-ring: var(--color-background-medium-neutral);\n}\n\n.on-bold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n --_dot-ring: var(--color-background-bold-neutral);\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n.on-bold.tab--selected { color: var(--color-foreground-on-bold-background-primary); }\n\n.on-strong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n --_dot-ring: var(--color-background-strong-neutral);\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n.on-strong.tab--selected { color: var(--color-foreground-on-bold-background-primary); }\n\n.on-always-dark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n --_dot-ring: var(--color-always-dark-background);\n color: var(--color-always-dark-foreground-secondary);\n}\n\n.on-always-dark.tab--selected { color: var(--color-always-dark-foreground-primary); }\n\n.on-navigation {\n color: var(--color-navigation-foreground-secondary);\n --_hover-bg: var(--color-navigation-interaction-hover);\n --_pressed-bg: var(--color-navigation-interaction-pressed);\n --_dot: var(--color-navigation-foreground-brand);\n --_dot-ring: var(--color-navigation-background);\n}\n\n.on-navigation.tab--selected { color: var(--color-navigation-foreground-primary); }\n\n.on-navigation:focus-visible {\n outline-color: var(--color-navigation-interaction-focus);\n}\n\n.tab-list--on-navigation .tab-divider__line {\n background-color: var(--color-navigation-border-tertiary);\n}\n\n/* In-tablist visual group separator — not focusable, skipped by keyboard nav */\n.tab-divider {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: var(--dimension-space-100);\n height: var(--dimension-size-400);\n padding-block: var(--dimension-space-075);\n flex-shrink: 0;\n pointer-events: none;\n}\n\n.tab-divider__line {\n width: var(--dimension-stroke-width-012);\n align-self: stretch;\n background-color: var(--color-border-secondary);\n}\n\n.tab-divider--vertical {\n width: auto;\n height: var(--dimension-space-100);\n align-self: stretch;\n padding-block: 0;\n padding-inline: var(--dimension-space-075);\n}\n\n.tab-divider--vertical .tab-divider__line {\n width: auto;\n height: var(--dimension-stroke-width-012);\n align-self: stretch;\n}\n","import { Component, Prop, Event, EventEmitter, Element, Listen, Watch, h, Host } from '@stencil/core';\nimport {\n getSelectableTabs,\n isTabDivider,\n type TabItem,\n type TabItemTab,\n} from '../TabGroup/tab-item-utils';\n\nexport type TabGroupNavBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark' | 'navigation';\n\n@Component({\n tag: 'ds-tab-group-nav',\n styleUrl: 'TabGroupNav.css',\n scoped: true,\n})\nexport class TabGroupNav {\n @Element() el!: HTMLElement;\n\n @Prop({ mutable: true }) value: string = '';\n @Prop() tabs: TabItem[] = [];\n @Prop() background: TabGroupNavBackground | undefined;\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | undefined;\n @Prop({ attribute: 'aria-labelledby' }) ariaLabelledby: string | undefined;\n @Prop() orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n @Event() dsChange!: EventEmitter<string>;\n\n private get selectableTabs(): TabItemTab[] {\n return getSelectableTabs(this.tabs);\n }\n\n private selectTab(id: string, options?: { focus?: boolean }) {\n this.value = id;\n this.dsChange.emit(id);\n if (options?.focus !== false) {\n this.focusTab(id);\n }\n }\n\n private focusTab(id: string) {\n const btn = this.el.querySelector(`[data-tab-id=\"${id}\"]`) as HTMLElement | null;\n btn?.focus({ preventScroll: true });\n }\n\n /** Keep focus on the selected tab when value changes externally (e.g. BarNav menu). */\n @Watch('value')\n onValueChange(next: string, prev: string | undefined) {\n if (prev === undefined || next === prev) return;\n\n requestAnimationFrame(() => {\n const active = document.activeElement as HTMLElement | null;\n if (!active || !this.el.contains(active)) return;\n\n const activeId = active.getAttribute('data-tab-id');\n if (activeId === next) return;\n\n const nextTab = this.el.querySelector(`[data-tab-id=\"${next}\"]`) as HTMLElement | null;\n if (nextTab) {\n nextTab.focus({ preventScroll: true });\n } else {\n active.blur();\n }\n });\n }\n\n /**\n * Find the next non-disabled tab index relative to `from`, stepping by `step`.\n * Returns `from` unchanged if no other enabled tab exists.\n */\n private findEnabled(from: number, step: 1 | -1): number {\n const tabs = this.selectableTabs;\n const len = tabs.length;\n for (let n = 0; n < len; n++) {\n const i = (from + step * (n + 1) + len * (n + 1)) % len;\n if (!tabs[i]?.disabled) return i;\n }\n return from;\n }\n\n @Listen('keydown')\n handleKeyDown(e: KeyboardEvent) {\n const tabs = this.selectableTabs;\n if (!tabs.length) return;\n\n const currentIdx = tabs.findIndex(t => t.id === this.value);\n const isVertical = this.orientation === 'vertical';\n\n let nextIdx: number | null = null;\n\n if (!isVertical) {\n if (e.key === 'ArrowRight') {\n nextIdx = this.findEnabled(currentIdx, 1);\n } else if (e.key === 'ArrowLeft') {\n nextIdx = this.findEnabled(currentIdx, -1);\n }\n } else {\n if (e.key === 'ArrowDown') {\n nextIdx = this.findEnabled(currentIdx, 1);\n } else if (e.key === 'ArrowUp') {\n nextIdx = this.findEnabled(currentIdx, -1);\n }\n }\n\n if (e.key === 'Home') {\n const first = tabs.findIndex(t => !t.disabled);\n nextIdx = first === -1 ? null : first;\n } else if (e.key === 'End') {\n const lastEnabled = [...tabs].reverse().findIndex(t => !t.disabled);\n nextIdx = lastEnabled === -1 ? null : tabs.length - 1 - lastEnabled;\n }\n\n if (nextIdx !== null) {\n e.preventDefault();\n const next = tabs[nextIdx];\n this.selectTab(next.id);\n }\n }\n\n private getBgClass(): string {\n if (!this.background || this.background === 'faint') return '';\n if (this.background === 'always-dark') return 'on-always-dark';\n if (this.background === 'navigation') return 'on-navigation';\n return `on-${this.background}`;\n }\n\n render() {\n const bgClass = this.getBgClass();\n const isVertical = this.orientation === 'vertical';\n const isNavigation = this.background === 'navigation';\n\n return (\n <Host class=\"tab-group-nav-host\">\n <div\n role=\"tablist\"\n class={{\n 'tab-list': true,\n 'tab-list--vertical': isVertical,\n 'tab-list--on-navigation': isNavigation,\n }}\n aria-label={this.ariaLabel}\n aria-labelledby={this.ariaLabelledby}\n aria-orientation={isVertical ? 'vertical' : undefined}\n >\n {this.tabs.map((tab, index) => {\n if (isTabDivider(tab)) {\n return (\n <div\n key={`divider-${index}`}\n class={{\n 'tab-divider': true,\n 'tab-divider--vertical': isVertical,\n }}\n aria-hidden=\"true\"\n >\n <div class=\"tab-divider__line\" />\n </div>\n );\n }\n\n const isSelected = tab.id === this.value;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n data-tab-id={tab.id}\n class={{\n tab: true,\n 'tab--selected': isSelected,\n [bgClass]: !!bgClass,\n }}\n aria-selected={isSelected}\n aria-disabled={tab.disabled || undefined}\n aria-controls={tab.panelId ?? undefined}\n disabled={tab.disabled}\n tabIndex={isSelected ? 0 : -1}\n onClick={() => !tab.disabled && this.selectTab(tab.id)}\n >\n <span class={{\n tab__label: true,\n 'tab__label--dot': !!tab.dot,\n [isSelected ? 'text-body-medium-emphasis' : 'text-body-medium']: true,\n }}>\n {tab.label}\n {tab.dot && (\n <ds-badge\n class=\"tab__dot\"\n variant=\"dot\"\n background=\"var(--_dot-ring)\"\n label=\"\"\n aria-hidden=\"true\"\n />\n )}\n </span>\n </button>\n );\n })}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,2 +0,0 @@
1
- import{p as o,H as n,c as a,h as r,a as e,t}from"./index.js";import{d as i}from"./p-B_enucPQ.js";import{d as s}from"./p-DqBCQRRd.js";const c=()=>`.action-btn.sc-ds-bar-nav-action{display:inline-flex;align-items:center;justify-content:center;width:var(--dimension-size-400);height:var(--dimension-size-400);padding:var(--dimension-space-075);background:transparent;border:none;border-radius:var(--dimension-radius-025);cursor:pointer;color:var(--color-foreground-secondary);box-sizing:border-box;-webkit-user-select:none;user-select:none;position:relative;transition:color var(--effect-motion-short-2);--_hover-bg:var(--color-interaction-hover);--_pressed-bg:var(--color-interaction-pressed);--_dot-ring:var(--color-background-secondary)}.action-btn.sc-ds-bar-nav-action::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025);background:transparent;pointer-events:none;transition:none}.action-btn.sc-ds-bar-nav-action:hover:not(.inactive)::after{background:var(--_hover-bg);transition:none}.action-btn.sc-ds-bar-nav-action:active:not(.inactive)::after{background:var(--_pressed-bg);transition:none}.action-btn.sc-ds-bar-nav-action:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.action-btn.selected.sc-ds-bar-nav-action{color:var(--color-foreground-primary)}.action-btn.inactive.sc-ds-bar-nav-action{opacity:0.5;cursor:not-allowed;pointer-events:none}.onMedium.sc-ds-bar-nav-action{--_hover-bg:var(--color-interaction-on-medium-background-hover);--_pressed-bg:var(--color-interaction-on-medium-background-pressed);--_dot-ring:var(--color-background-medium-neutral)}.onBold.sc-ds-bar-nav-action{color:var(--color-foreground-on-bold-background-secondary);--_hover-bg:var(--color-interaction-on-bold-background-hover);--_pressed-bg:var(--color-interaction-on-bold-background-pressed);--_dot-ring:var(--color-background-bold-neutral)}.onBold.selected.sc-ds-bar-nav-action{color:var(--color-foreground-on-bold-background-primary)}.onStrong.sc-ds-bar-nav-action{color:var(--color-foreground-on-bold-background-secondary);--_hover-bg:var(--color-interaction-on-strong-background-hover);--_pressed-bg:var(--color-interaction-on-strong-background-pressed);--_dot-ring:var(--color-background-strong-neutral)}.onStrong.selected.sc-ds-bar-nav-action{color:var(--color-foreground-on-bold-background-primary)}.onAlwaysDark.sc-ds-bar-nav-action{color:var(--color-always-dark-foreground-secondary);--_hover-bg:var(--color-always-dark-interaction-hover);--_pressed-bg:var(--color-always-dark-interaction-pressed);--_dot-ring:var(--color-always-dark-background)}.onAlwaysDark.selected.sc-ds-bar-nav-action{color:var(--color-always-dark-foreground-primary)}.onNavigation.sc-ds-bar-nav-action{color:var(--color-navigation-foreground-secondary);--_hover-bg:var(--color-navigation-interaction-hover);--_pressed-bg:var(--color-navigation-interaction-pressed);--_dot-ring:var(--color-navigation-background)}.onNavigation.selected.sc-ds-bar-nav-action{color:var(--color-navigation-foreground-primary)}.onNavigation.sc-ds-bar-nav-action:focus-visible{outline-color:var(--color-navigation-interaction-focus)}.action-btn__icon-wrap.sc-ds-bar-nav-action{position:relative;width:var(--dimension-iconography-md);height:var(--dimension-iconography-md);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.action-btn__dot.sc-ds-bar-nav-action{position:absolute;top:0;right:0;pointer-events:none}`;const d=o(class o extends n{constructor(o){super();if(o!==false){this.__registerHost()}this.dsChange=a(this,"dsChange");this.icon="";this.selected=false;this.dot=false;this.inactive=false;this.ariaLabel="action";this.handleClick=()=>{if(this.inactive)return;this.dsChange.emit(!this.selected)}}render(){const o=this.background;const n={"action-btn":true,selected:this.selected,inactive:this.inactive,onMedium:o==="medium",onBold:o==="bold",onStrong:o==="strong",onAlwaysDark:o==="always-dark",onNavigation:o==="navigation"};return r(e,{key:"2217e7e7b3db58d98eb3a4ce6ff3812412e3e69b"},r("button",{key:"db4db409c60aa9e0deda242d03b8ea85ab86f943",type:"button",class:n,disabled:this.inactive,"aria-pressed":this.selected,"aria-label":this.ariaLabel,onClick:this.handleClick},r("span",{key:"01fa2ef03a527b43da0cf84e049678b2ce762b67",class:"action-btn__icon-wrap"},r("ds-icon",{key:"735cfcf6032af6bda5d51e3b1e39e76310d9f04c",name:this.icon,size:"md",color:"inherit"}),this.dot&&r("ds-badge",{key:"f893cd3f15f45640d72e5a8d237b4d0166d3fa9d",class:"action-btn__dot",variant:"dot",background:"var(--_dot-ring)",label:"","aria-hidden":"true"}))))}static get style(){return c()}},[2,"ds-bar-nav-action",{icon:[1],selected:[4],dot:[4],inactive:[4],ariaLabel:[1,"aria-label"],background:[1]}]);function l(){if(typeof customElements==="undefined"){return}const o=["ds-bar-nav-action","ds-badge","ds-icon"];o.forEach((o=>{switch(o){case"ds-bar-nav-action":if(!customElements.get(t(o))){customElements.define(t(o),d)}break;case"ds-badge":if(!customElements.get(t(o))){i()}break;case"ds-icon":if(!customElements.get(t(o))){s()}break}}))}l();export{d as B,l as d};
2
- //# sourceMappingURL=p-_LI2ymhS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["barNavActionCss","BarNavAction","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","icon","selected","dot","inactive","ariaLabel","handleClick","dsChange","emit","render","bg","background","cls","onMedium","onBold","onStrong","onAlwaysDark","onNavigation","h","Host","key","type","class","disabled","onClick","name","size","color","variant","label"],"sources":["src/wc/components/BarNavAction/BarNavAction.css?tag=ds-bar-nav-action&encapsulation=scoped","src/wc/components/BarNavAction/BarNavAction.tsx"],"sourcesContent":[".action-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--dimension-size-400);\n height: var(--dimension-size-400);\n padding: var(--dimension-space-075);\n background: transparent;\n border: none;\n border-radius: var(--dimension-radius-025);\n cursor: pointer;\n color: var(--color-foreground-secondary);\n box-sizing: border-box;\n -webkit-user-select: none;\n user-select: none;\n position: relative;\n /* Only transition color — hover bg is instant (see ::after below) */\n transition: color var(--effect-motion-short-2);\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_dot-ring: var(--color-background-secondary);\n}\n\n/* Interaction layer — same pattern as PanelNav */\n.action-btn::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: var(--dimension-radius-025);\n background: transparent;\n pointer-events: none;\n transition: none;\n}\n\n.action-btn:hover:not(.inactive)::after { background: var(--_hover-bg); transition: none; }\n.action-btn:active:not(.inactive)::after { background: var(--_pressed-bg); transition: none; }\n\n.action-btn:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n/* Selected: icon turns primary — no background change */\n.action-btn.selected { color: var(--color-foreground-primary); }\n\n.action-btn.inactive { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n\n/* ==========================================================================\n Background context\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n --_dot-ring: var(--color-background-medium-neutral);\n}\n\n.onBold {\n color: var(--color-foreground-on-bold-background-secondary);\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n --_dot-ring: var(--color-background-bold-neutral);\n}\n\n.onBold.selected { color: var(--color-foreground-on-bold-background-primary); }\n\n.onStrong {\n color: var(--color-foreground-on-bold-background-secondary);\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n --_dot-ring: var(--color-background-strong-neutral);\n}\n\n.onStrong.selected { color: var(--color-foreground-on-bold-background-primary); }\n\n.onAlwaysDark {\n color: var(--color-always-dark-foreground-secondary);\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n --_dot-ring: var(--color-always-dark-background);\n}\n\n.onAlwaysDark.selected { color: var(--color-always-dark-foreground-primary); }\n\n.onNavigation {\n color: var(--color-navigation-foreground-secondary);\n --_hover-bg: var(--color-navigation-interaction-hover);\n --_pressed-bg: var(--color-navigation-interaction-pressed);\n --_dot-ring: var(--color-navigation-background);\n}\n\n.onNavigation.selected { color: var(--color-navigation-foreground-primary); }\n\n.onNavigation:focus-visible {\n outline-color: var(--color-navigation-interaction-focus);\n}\n\n/* ==========================================================================\n Inner layout — icon zone sits above the ::after overlay\n ========================================================================== */\n\n.action-btn__icon-wrap {\n position: relative;\n width: var(--dimension-iconography-md);\n height: var(--dimension-iconography-md);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n/* Notification dot — top-right corner of the icon zone */\n.action-btn__dot {\n position: absolute;\n top: 0;\n right: 0;\n pointer-events: none;\n}\n","import { Component, Prop, Event, EventEmitter, h, Host } from '@stencil/core';\n\nexport type BarNavActionBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark' | 'navigation';\n\n@Component({\n tag: 'ds-bar-nav-action',\n styleUrl: 'BarNavAction.css',\n scoped: true,\n})\nexport class BarNavAction {\n /** Icon name passed to <ds-icon>. */\n @Prop() icon: string = '';\n\n /** Controlled toggle/selected state. */\n @Prop() selected: boolean = false;\n\n /** Show a notification dot (brand colour) at the top-right of the icon. */\n @Prop() dot: boolean = false;\n\n /** Disables interaction. */\n @Prop() inactive: boolean = false;\n\n @Prop({ attribute: 'aria-label' }) ariaLabel: string = 'action';\n\n /** Parent surface context — adjusts hover/press colours for coloured backgrounds. */\n @Prop() background: BarNavActionBackground | undefined;\n\n /** Emits the new selected value (!selected) on click. */\n @Event() dsChange!: EventEmitter<boolean>;\n\n private handleClick = () => {\n if (this.inactive) return;\n this.dsChange.emit(!this.selected);\n };\n\n render() {\n const bg = this.background;\n\n const cls: Record<string, boolean> = {\n 'action-btn': true,\n selected: this.selected,\n inactive: this.inactive,\n onMedium: bg === 'medium',\n onBold: bg === 'bold',\n onStrong: bg === 'strong',\n onAlwaysDark: bg === 'always-dark',\n onNavigation: bg === 'navigation',\n };\n\n return (\n <Host>\n <button\n type=\"button\"\n class={cls}\n disabled={this.inactive}\n aria-pressed={this.selected}\n aria-label={this.ariaLabel}\n onClick={this.handleClick}\n >\n <span class=\"action-btn__icon-wrap\">\n <ds-icon name={this.icon} size=\"md\" color=\"inherit\" />\n {this.dot && (\n <ds-badge\n class=\"action-btn__dot\"\n variant=\"dot\"\n background=\"var(--_dot-ring)\"\n label=\"\"\n aria-hidden=\"true\"\n />\n )}\n </span>\n </button>\n </Host>\n );\n }\n}\n"],"mappings":"qIAAA,MAAMA,EAAkB,IAAM,iyG,MCSjBC,EAAYC,EAAA,MAAAD,UAAAE,EALzB,WAAAC,CAAAC,G,6EAOUC,KAAAC,KAAe,GAGfD,KAAAE,SAAoB,MAGpBF,KAAAG,IAAe,MAGfH,KAAAI,SAAoB,MAEOJ,KAAAK,UAAoB,SAQ/CL,KAAAM,YAAc,KACpB,GAAIN,KAAKI,SAAU,OACnBJ,KAAKO,SAASC,MAAMR,KAAKE,SAAS,CA2CrC,CAxCC,MAAAO,GACE,MAAMC,EAAKV,KAAKW,WAEhB,MAAMC,EAA+B,CACnC,aAAc,KACdV,SAAUF,KAAKE,SACfE,SAAUJ,KAAKI,SACfS,SAAUH,IAAO,SACjBI,OAAQJ,IAAO,OACfK,SAAUL,IAAO,SACjBM,aAAcN,IAAO,cACrBO,aAAcP,IAAO,cAGvB,OACEQ,EAACC,EAAI,CAAAC,IAAA,4CACHF,EAAA,UAAAE,IAAA,2CACEC,KAAK,SACLC,MAAOV,EACPW,SAAUvB,KAAKI,SAAQ,eACTJ,KAAKE,SAAQ,aACfF,KAAKK,UACjBmB,QAASxB,KAAKM,aAEdY,EAAA,QAAAE,IAAA,2CAAME,MAAM,yBACVJ,EAAA,WAAAE,IAAA,2CAASK,KAAMzB,KAAKC,KAAMyB,KAAK,KAAKC,MAAM,YACzC3B,KAAKG,KACJe,EAAA,YAAAE,IAAA,2CACEE,MAAM,kBACNM,QAAQ,MACRjB,WAAW,mBACXkB,MAAM,GAAE,cACI,W","ignoreList":[]}