@ds-mo/ui 0.10.3 → 0.11.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/components/ds-bar-nav.js +1 -1
- package/dist/components/ds-bar-nav.js.map +1 -1
- package/dist/components/ds-panel-nav.js +1 -1
- package/dist/components/ds-panel-nav.js.map +1 -1
- package/dist/components/index.d.ts +13 -0
- package/dist/types/.stencil/BarNav/BarNav.d.ts +20 -3
- package/dist/types/.stencil/BarNav/bar-nav-utils.d.ts +13 -0
- package/dist/types/.stencil/PanelNav/PanelNav.d.ts +15 -8
- package/dist/types/.stencil/PanelNav/index.d.ts +2 -1
- package/dist/types/.stencil/PanelNav/panel-nav-utils.d.ts +10 -0
- package/dist/types/components.d.ts +75 -15
- package/package.json +4 -2
- package/src/angular/proxies.ts +10 -5
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{p as
|
|
1
|
+
import{p as s,H as a,c as e,h as t,a as n,t as r}from"./index.js";import{d as i}from"./p-CdSPCP4g.js";import{d as o}from"./p-CkBXHj0e.js";import{d as c}from"./p-D1cpKdRU.js";function d(s,a,e){if(!s||!a){return{value:"",hideTabs:false}}if(s!==a&&!s.startsWith(`${a}/`)){return{value:"",hideTabs:false}}const t=s.slice(a.length);const n=t.startsWith("/")?t.slice(1).split("/")[0]:"";if(!n){return{value:e[0]?.id??"",hideTabs:false}}const r=e.find((s=>s.id===n));if(r){return{value:r.id,hideTabs:false}}return{value:"",hideTabs:true}}function h(s,a){if(Array.isArray(s))return s;if(typeof s==="string"&&s!==""){try{const e=JSON.parse(s);return Array.isArray(e)?e:a}catch{return a}}return a}const l=()=>`.sc-ds-bar-nav-h{display:block}.bar-nav.sc-ds-bar-nav{display:flex;align-items:center;height:var(--dimension-size-600);padding:var(--dimension-space-100);gap:var(--dimension-space-100);box-sizing:border-box;border-bottom:var(--dimension-stroke-width-012) solid var(--color-border-tertiary)}.bg-primary.sc-ds-bar-nav{background-color:var(--color-background-primary)}.bg-secondary.sc-ds-bar-nav{background-color:var(--color-background-secondary)}.bg-transparent.sc-ds-bar-nav{background-color:transparent}.bg-translucent.sc-ds-bar-nav{background-color:var(--color-background-translucent);backdrop-filter:blur(var(--effect-blur-md));-webkit-backdrop-filter:blur(var(--effect-blur-md))}.bar-nav__left.sc-ds-bar-nav{flex:1;min-width:0;display:flex;align-items:center}.bar-nav__left.sc-ds-bar-nav ds-tab-group.sc-ds-bar-nav{flex:1;min-width:0}.bar-nav__heading.sc-ds-bar-nav{display:inline-flex;align-items:center;height:var(--dimension-size-400);padding-inline:var(--dimension-space-100);color:var(--color-foreground-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bar-nav__actions.sc-ds-bar-nav{display:flex;align-items:center;gap:var(--dimension-space-050);flex-shrink:0}`;const b=s(class s extends a{constructor(s){super();if(s!==false){this.__registerHost()}this.dsTabChange=e(this,"dsTabChange");this.dsActionChange=e(this,"dsActionChange");this.tabs=[];this.tabsJson="";this.value="";this.actions=[];this.actionsJson="";this.background="secondary";this.basePath="";this.currentUrl="";this.resolvedTabs=[];this.resolvedActions=[];this.urlDerivedValue="";this.hideTabsForDetailRoute=false}get effectiveValue(){if(this.currentUrl&&this.basePath){return this.urlDerivedValue}return this.value}onPropsChange(){this.resolvedTabs=this.tabsJson?h(this.tabsJson,[]):this.tabs??[];this.resolvedActions=this.actionsJson?h(this.actionsJson,[]):this.actions??[];this.syncValueFromUrl()}onUrlChange(){this.syncValueFromUrl()}componentWillLoad(){this.onPropsChange()}syncValueFromUrl(){if(!this.currentUrl||!this.basePath){this.urlDerivedValue="";this.hideTabsForDetailRoute=false;return}const{value:s,hideTabs:a}=d(this.currentUrl,this.basePath,this.resolvedTabs);this.urlDerivedValue=s;this.hideTabsForDetailRoute=a}handleTabChange(s){const a=s.detail;this.value=a;this.dsTabChange.emit(a)}handleActionChange(s,a){const e=a.detail;this.dsActionChange.emit({id:s,selected:e})}render(){const s=this.resolvedTabs.length>0&&!this.hideTabsForDetailRoute;const a={};const e=a[this.background];return t(n,{key:"e824182c8658e29703dbea684775338477bba1db"},t("header",{key:"da442bde164d76254bbf570070d0c62f4b994e2d",class:{"bar-nav":true,[`bg-${this.background}`]:true}},t("div",{key:"f0db50dac4c2b354e335d2b264c82951e85601a5",class:"bar-nav__left"},s?t("ds-tab-group",{tabs:this.resolvedTabs,value:this.effectiveValue,onDsChange:s=>this.handleTabChange(s)}):this.heading&&t("span",{class:"bar-nav__heading text-body-medium-emphasis"},this.heading)),this.resolvedActions.length>0&&t("div",{key:"270c80cd552ea7182822c06bd76acc2fc1c7d992",class:"bar-nav__actions"},this.resolvedActions.map((s=>t("ds-bar-nav-action",{key:s.id,icon:s.icon,selected:s.selected??false,dot:s.dot??false,inactive:s.inactive,"aria-label":s.ariaLabel??s.id,background:e,onDsChange:a=>this.handleActionChange(s.id,a)}))))))}static get watchers(){return{tabs:[{onPropsChange:0}],tabsJson:[{onPropsChange:0}],actions:[{onPropsChange:0}],actionsJson:[{onPropsChange:0}],currentUrl:[{onUrlChange:0}],basePath:[{onUrlChange:0}]}}static get style(){return l()}},[2,"ds-bar-nav",{tabs:[16],tabsJson:[1,"tabs-json"],value:[1025],actions:[16],actionsJson:[1,"actions-json"],heading:[1],background:[1],basePath:[1,"base-path"],currentUrl:[1,"current-url"],resolvedTabs:[32],resolvedActions:[32],urlDerivedValue:[32],hideTabsForDetailRoute:[32]},undefined,{tabs:[{onPropsChange:0}],tabsJson:[{onPropsChange:0}],actions:[{onPropsChange:0}],actionsJson:[{onPropsChange:0}],currentUrl:[{onUrlChange:0}],basePath:[{onUrlChange:0}]}]);function u(){if(typeof customElements==="undefined"){return}const s=["ds-bar-nav","ds-bar-nav-action","ds-icon","ds-tab-group"];s.forEach((s=>{switch(s){case"ds-bar-nav":if(!customElements.get(r(s))){customElements.define(r(s),b)}break;case"ds-bar-nav-action":if(!customElements.get(r(s))){i()}break;case"ds-icon":if(!customElements.get(r(s))){o()}break;case"ds-tab-group":if(!customElements.get(r(s))){c()}break}}))}u();const f=b;const g=u;export{f as DsBarNav,g as defineCustomElement};
|
|
2
2
|
//# sourceMappingURL=ds-bar-nav.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["barNavCss","BarNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","tabs","value","actions","background","handleTabChange","e","id","detail","dsTabChange","emit","handleActionChange","actionId","selected","dsActionChange","render","hasTabs","length","bgToActionBg","actionBg","h","Host","key","class","onDsChange","heading","map","action","icon","dot","inactive","ariaLabel"],"sources":["src/wc/components/BarNav/BarNav.css?tag=ds-bar-nav&encapsulation=scoped","src/wc/components/BarNav/BarNav.tsx"],"sourcesContent":[":host {\n display: block;\n}\n\n.bar-nav {\n display: flex;\n align-items: center;\n height: var(--dimension-size-600);\n padding: var(--dimension-space-100);\n gap: var(--dimension-space-100);\n box-sizing: border-box;\n border-bottom: var(--dimension-stroke-width-012) solid var(--color-border-tertiary);\n}\n\n/* Background variants — mirrors ds-header pattern */\n.bg-primary { background-color: var(--color-background-primary); }\n.bg-secondary { background-color: var(--color-background-secondary); }\n.bg-transparent { background-color: transparent; }\n.bg-translucent {\n background-color: var(--color-background-translucent);\n backdrop-filter: blur(var(--effect-blur-md));\n -webkit-backdrop-filter: blur(var(--effect-blur-md));\n}\n\n/* Left zone — tabs fill available space */\n.bar-nav__left {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n\n.bar-nav__left ds-tab-group {\n flex: 1;\n min-width: 0;\n}\n\n/* Fallback heading when no tabs — matches a single (selected) tab so the area\n name shares the tab label's type token, color, height and horizontal inset.\n Inset = tab button padding (space-075, 6px) + label inset (space-025, 2px). */\n.bar-nav__heading {\n display: inline-flex;\n align-items: center;\n height: var(--dimension-size-400);\n padding-inline: var(--dimension-space-100);\n color: var(--color-foreground-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Right zone — action buttons, hugging right */\n.bar-nav__actions {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n flex-shrink: 0;\n}\n","import { Component, Prop, Event, EventEmitter, h, Host } from '@stencil/core';\nimport type { BarNavActionBackground } from '../BarNavAction/BarNavAction';\nimport type { TabItem } from '../TabGroup/TabGroup';\n\nexport type BarNavBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\nexport interface BarNavTab {\n id: string;\n label: string;\n disabled?: boolean;\n /** Notification dot on this tab. */\n dot?: boolean;\n}\n\nexport interface BarNavActionItem {\n id: string;\n /** Icon name for <ds-icon>. */\n icon: string;\n /** Whether this action button is currently pressed/active. */\n selected?: boolean;\n /** Show a notification dot. */\n dot?: boolean;\n inactive?: boolean;\n ariaLabel?: string;\n}\n\n@Component({\n tag: 'ds-bar-nav',\n styleUrl: 'BarNav.css',\n scoped: true,\n})\nexport class BarNav {\n /**\n * Tab items for the left section.\n * Set via JS property: `el.tabs = [...]`\n */\n @Prop() tabs: BarNavTab[] = [];\n\n /** ID of the currently active tab. */\n @Prop({ mutable: true }) value: string = '';\n\n /**\n * Action items rendered in the right section.\n * Set via JS property: `el.actions = [...]`\n */\n @Prop() actions: BarNavActionItem[] = [];\n\n /**\n * Fallback heading shown when no tabs are provided.\n * When tabs are present the heading is hidden.\n */\n @Prop() heading: string | undefined;\n\n /** Surface background variant. */\n @Prop() background: BarNavBackground = 'secondary';\n\n /** Emitted when the active tab changes. Detail = tab id. */\n @Event() dsTabChange!: EventEmitter<string>;\n\n /** Emitted when an action button is toggled. Detail = { id, selected }. */\n @Event() dsActionChange!: EventEmitter<{ id: string; selected: boolean }>;\n\n private handleTabChange(e: Event) {\n const id = (e as CustomEvent<string>).detail;\n this.value = id;\n this.dsTabChange.emit(id);\n }\n\n private handleActionChange(actionId: string, e: Event) {\n const selected = (e as CustomEvent<boolean>).detail;\n this.dsActionChange.emit({ id: actionId, selected });\n }\n\n render() {\n const hasTabs = this.tabs.length > 0;\n\n // Map BarNavBackground → BarNavActionBackground for context pass-through.\n // primary/secondary/transparent/translucent are all light — no override needed.\n const bgToActionBg: Partial<Record<BarNavBackground, BarNavActionBackground>> = {};\n const actionBg: BarNavActionBackground | undefined = bgToActionBg[this.background];\n\n return (\n <Host>\n <header class={{ 'bar-nav': true, [`bg-${this.background}`]: true }}>\n\n <div class=\"bar-nav__left\">\n {hasTabs\n ? (\n <ds-tab-group\n tabs={this.tabs as TabItem[]}\n value={this.value}\n onDsChange={(e: Event) => this.handleTabChange(e)}\n />\n )\n : this.heading && (\n <span class=\"bar-nav__heading text-body-medium-emphasis\">{this.heading}</span>\n )\n }\n </div>\n\n {this.actions.length > 0 && (\n <div class=\"bar-nav__actions\">\n {this.actions.map(action => (\n <ds-bar-nav-action\n key={action.id}\n icon={action.icon}\n selected={action.selected ?? false}\n dot={action.dot ?? false}\n inactive={action.inactive}\n aria-label={action.ariaLabel ?? action.id}\n background={actionBg}\n onDsChange={(e: Event) => this.handleActionChange(action.id, e)}\n />\n ))}\n </div>\n )}\n\n </header>\n </Host>\n );\n }\n}\n"],"mappings":"oKAAA,MAAMA,EAAY,IAAM,uqC,MC+BXC,EAAMC,EAAA,MAAAD,UAAAE,EALnB,WAAAC,CAAAC,G,gIAUUC,KAAAC,KAAoB,GAGHD,KAAAE,MAAgB,GAMjCF,KAAAG,QAA8B,GAS9BH,KAAAI,WAA+B,WAmExC,CA3DS,eAAAC,CAAgBC,GACtB,MAAMC,EAAMD,EAA0BE,OACtCR,KAAKE,MAAQK,EACbP,KAAKS,YAAYC,KAAKH,E,CAGhB,kBAAAI,CAAmBC,EAAkBN,GAC3C,MAAMO,EAAYP,EAA2BE,OAC7CR,KAAKc,eAAeJ,KAAK,CAAEH,GAAIK,EAAUC,Y,CAG3C,MAAAE,GACE,MAAMC,EAAUhB,KAAKC,KAAKgB,OAAS,EAInC,MAAMC,EAA0E,GAChF,MAAMC,EAA+CD,EAAalB,KAAKI,YAEvE,OACEgB,EAACC,EAAI,CAAAC,IAAA,4CACHF,EAAA,UAAAE,IAAA,2CAAQC,MAAO,CAAE,UAAW,KAAM,CAAC,MAAMvB,KAAKI,cAAe,OAE3DgB,EAAA,OAAAE,IAAA,2CAAKC,MAAM,iBACRP,EAEGI,EAAA,gBACEnB,KAAMD,KAAKC,KACXC,MAAOF,KAAKE,MACZsB,WAAalB,GAAaN,KAAKK,gBAAgBC,KAGjDN,KAAKyB,SACLL,EAAA,QAAMG,MAAM,8CAA8CvB,KAAKyB,UAKpEzB,KAAKG,QAAQc,OAAS,GACrBG,EAAA,OAAAE,IAAA,2CAAKC,MAAM,oBACRvB,KAAKG,QAAQuB,KAAIC,GAChBP,EAAA,qBACEE,IAAKK,EAAOpB,GACZqB,KAAMD,EAAOC,KACbf,SAAUc,EAAOd,UAAY,MAC7BgB,IAAKF,EAAOE,KAAO,MACnBC,SAAUH,EAAOG,SAAQ,aACbH,EAAOI,WAAaJ,EAAOpB,GACvCH,WAAYe,EACZK,WAAalB,GAAaN,KAAKW,mBAAmBgB,EAAOpB,GAAID,S","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["deriveBarNavValueFromUrl","path","basePath","tabs","value","hideTabs","startsWith","remainder","slice","length","seg","split","id","tab","find","t","parseJsonArrayProp","fallback","Array","isArray","parsed","JSON","parse","barNavCss","BarNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","tabsJson","actions","actionsJson","background","currentUrl","resolvedTabs","resolvedActions","urlDerivedValue","hideTabsForDetailRoute","effectiveValue","onPropsChange","syncValueFromUrl","onUrlChange","componentWillLoad","handleTabChange","e","detail","dsTabChange","emit","handleActionChange","actionId","selected","dsActionChange","render","hasTabs","bgToActionBg","actionBg","h","Host","key","class","onDsChange","heading","map","action","icon","dot","inactive","ariaLabel"],"sources":["src/wc/components/BarNav/bar-nav-utils.ts","src/wc/components/BarNav/BarNav.css?tag=ds-bar-nav&encapsulation=scoped","src/wc/components/BarNav/BarNav.tsx"],"sourcesContent":["import type { BarNavTab } from './BarNav';\n\nexport interface BarNavUrlState {\n /** Tab id derived from the URL, or empty when none applies. */\n value: string;\n /** When true, tabs should be hidden (e.g. non-tab child routes like detail pages). */\n hideTabs: boolean;\n}\n\n/** Derive BarNav tab selection from `currentUrl` relative to `basePath`.\n * Mirrors motive-webapp-lab `resolveBarNavState` tab-selection semantics. */\nexport function deriveBarNavValueFromUrl(\n path: string,\n basePath: string,\n tabs: BarNavTab[],\n): BarNavUrlState {\n if (!path || !basePath) {\n return { value: '', hideTabs: false };\n }\n\n if (path !== basePath && !path.startsWith(`${basePath}/`)) {\n return { value: '', hideTabs: false };\n }\n\n const remainder = path.slice(basePath.length);\n const seg = remainder.startsWith('/') ? remainder.slice(1).split('/')[0] : '';\n\n if (!seg) {\n return { value: tabs[0]?.id ?? '', hideTabs: false };\n }\n\n const tab = tabs.find(t => t.id === seg);\n if (tab) {\n return { value: tab.id, hideTabs: false };\n }\n\n return { value: '', hideTabs: true };\n}\n\n/** Parse tabs/actions from either a JSON attribute string or a JS property array. */\nexport function parseJsonArrayProp<T>(value: string | T[] | undefined, fallback: T[]): T[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string' && value !== '') {\n try {\n const parsed = JSON.parse(value);\n return Array.isArray(parsed) ? parsed : fallback;\n } catch {\n return fallback;\n }\n }\n return fallback;\n}\n",":host {\n display: block;\n}\n\n.bar-nav {\n display: flex;\n align-items: center;\n height: var(--dimension-size-600);\n padding: var(--dimension-space-100);\n gap: var(--dimension-space-100);\n box-sizing: border-box;\n border-bottom: var(--dimension-stroke-width-012) solid var(--color-border-tertiary);\n}\n\n/* Background variants — mirrors ds-header pattern */\n.bg-primary { background-color: var(--color-background-primary); }\n.bg-secondary { background-color: var(--color-background-secondary); }\n.bg-transparent { background-color: transparent; }\n.bg-translucent {\n background-color: var(--color-background-translucent);\n backdrop-filter: blur(var(--effect-blur-md));\n -webkit-backdrop-filter: blur(var(--effect-blur-md));\n}\n\n/* Left zone — tabs fill available space */\n.bar-nav__left {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n\n.bar-nav__left ds-tab-group {\n flex: 1;\n min-width: 0;\n}\n\n/* Fallback heading when no tabs — matches a single (selected) tab so the area\n name shares the tab label's type token, color, height and horizontal inset.\n Inset = tab button padding (space-075, 6px) + label inset (space-025, 2px). */\n.bar-nav__heading {\n display: inline-flex;\n align-items: center;\n height: var(--dimension-size-400);\n padding-inline: var(--dimension-space-100);\n color: var(--color-foreground-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Right zone — action buttons, hugging right */\n.bar-nav__actions {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n flex-shrink: 0;\n}\n","import { Component, Prop, Event, EventEmitter, Watch, State, h, Host } from '@stencil/core';\nimport type { BarNavActionBackground } from '../BarNavAction/BarNavAction';\nimport type { TabItem } from '../TabGroup/TabGroup';\nimport {\n deriveBarNavValueFromUrl,\n parseJsonArrayProp,\n} from './bar-nav-utils';\n\nexport type BarNavBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\nexport interface BarNavTab {\n id: string;\n label: string;\n disabled?: boolean;\n /** Notification dot on this tab. */\n dot?: boolean;\n}\n\nexport interface BarNavActionItem {\n id: string;\n /** Icon name for <ds-icon>. */\n icon: string;\n /** Whether this action button is currently pressed/active. */\n selected?: boolean;\n /** Show a notification dot. */\n dot?: boolean;\n inactive?: boolean;\n ariaLabel?: string;\n}\n\n@Component({\n tag: 'ds-bar-nav',\n styleUrl: 'BarNav.css',\n scoped: true,\n})\nexport class BarNav {\n /**\n * Tab items for the left section.\n * Set via JS property: `el.tabs = [...]`. Replace the array reference to update.\n */\n @Prop() tabs: BarNavTab[] = [];\n\n /** JSON fallback for `tabs` — useful when framework bindings don't propagate arrays. */\n @Prop({ attribute: 'tabs-json' }) tabsJson: string = '';\n\n /** ID of the currently active tab. Overridden when `currentUrl` + `basePath` are set. */\n @Prop({ mutable: true }) value: string = '';\n\n /**\n * Action items rendered in the right section.\n * Set via JS property: `el.actions = [...]`. Replace the array reference to update.\n */\n @Prop() actions: BarNavActionItem[] = [];\n\n /** JSON fallback for `actions` — useful when framework bindings don't propagate arrays. */\n @Prop({ attribute: 'actions-json' }) actionsJson: string = '';\n\n /**\n * Fallback heading shown when no tabs are provided.\n * When tabs are present the heading is hidden.\n */\n @Prop() heading: string | undefined;\n\n /** Surface background variant. */\n @Prop() background: BarNavBackground = 'secondary';\n\n /** Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`. */\n @Prop() basePath: string = '';\n\n /** Current route URL. When set with `basePath`, the active tab is derived automatically. */\n @Prop() currentUrl: string = '';\n\n /** Emitted when the active tab changes. Detail = tab id. */\n @Event() dsTabChange!: EventEmitter<string>;\n\n /** Emitted when an action button is toggled. Detail = { id, selected }. */\n @Event() dsActionChange!: EventEmitter<{ id: string; selected: boolean }>;\n\n @State() private resolvedTabs: BarNavTab[] = [];\n @State() private resolvedActions: BarNavActionItem[] = [];\n @State() private urlDerivedValue: string = '';\n @State() private hideTabsForDetailRoute = false;\n\n private get effectiveValue(): string {\n if (this.currentUrl && this.basePath) {\n return this.urlDerivedValue;\n }\n return this.value;\n }\n\n @Watch('tabs')\n @Watch('tabsJson')\n @Watch('actions')\n @Watch('actionsJson')\n onPropsChange() {\n this.resolvedTabs = this.tabsJson\n ? parseJsonArrayProp(this.tabsJson, [])\n : (this.tabs ?? []);\n this.resolvedActions = this.actionsJson\n ? parseJsonArrayProp(this.actionsJson, [])\n : (this.actions ?? []);\n this.syncValueFromUrl();\n }\n\n @Watch('currentUrl')\n @Watch('basePath')\n onUrlChange() {\n this.syncValueFromUrl();\n }\n\n componentWillLoad() {\n this.onPropsChange();\n }\n\n private syncValueFromUrl() {\n if (!this.currentUrl || !this.basePath) {\n this.urlDerivedValue = '';\n this.hideTabsForDetailRoute = false;\n return;\n }\n\n const { value, hideTabs } = deriveBarNavValueFromUrl(\n this.currentUrl,\n this.basePath,\n this.resolvedTabs,\n );\n this.urlDerivedValue = value;\n this.hideTabsForDetailRoute = hideTabs;\n }\n\n private handleTabChange(e: Event) {\n const id = (e as CustomEvent<string>).detail;\n this.value = id;\n this.dsTabChange.emit(id);\n }\n\n private handleActionChange(actionId: string, e: Event) {\n const selected = (e as CustomEvent<boolean>).detail;\n this.dsActionChange.emit({ id: actionId, selected });\n }\n\n render() {\n const hasTabs = this.resolvedTabs.length > 0 && !this.hideTabsForDetailRoute;\n\n // Map BarNavBackground → BarNavActionBackground for context pass-through.\n // primary/secondary/transparent/translucent are all light — no override needed.\n const bgToActionBg: Partial<Record<BarNavBackground, BarNavActionBackground>> = {};\n const actionBg: BarNavActionBackground | undefined = bgToActionBg[this.background];\n\n return (\n <Host>\n <header class={{ 'bar-nav': true, [`bg-${this.background}`]: true }}>\n\n <div class=\"bar-nav__left\">\n {hasTabs\n ? (\n <ds-tab-group\n tabs={this.resolvedTabs as TabItem[]}\n value={this.effectiveValue}\n onDsChange={(e: Event) => this.handleTabChange(e)}\n />\n )\n : this.heading && (\n <span class=\"bar-nav__heading text-body-medium-emphasis\">{this.heading}</span>\n )\n }\n </div>\n\n {this.resolvedActions.length > 0 && (\n <div class=\"bar-nav__actions\">\n {this.resolvedActions.map(action => (\n <ds-bar-nav-action\n key={action.id}\n icon={action.icon}\n selected={action.selected ?? false}\n dot={action.dot ?? false}\n inactive={action.inactive}\n aria-label={action.ariaLabel ?? action.id}\n background={actionBg}\n onDsChange={(e: Event) => this.handleActionChange(action.id, e)}\n />\n ))}\n </div>\n )}\n\n </header>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{p as a,H as e,c as n,h as t,a as i,t as o}from"./index.js";import{d as s}from"./p-CkBXHj0e.js";import{d as r}from"./p-C_mk7BoY.js";const l=()=>`.panel-nav.sc-ds-panel-nav{--_nav-width:200px;--_nav-width-collapsed:48px;--_nav-item-height:var(--dimension-size-400, 32px);--_nav-padding-x:var(--dimension-space-100, 8px);--_nav-padding-y:var(--dimension-space-100, 8px);--_nav-footer-btn-w:calc(var(--dimension-space-075, 6px) * 2 + var(--dimension-iconography-md, 20px));--_nav-speed:var(--ds-panel-nav-speed, 1);--_nav-expand-dur:calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));--_nav-expand-motion:var(--_nav-expand-dur) var(--effect-animation-easing-ease-in-out, ease);--_nav-label-fade-dur:calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));--_nav-label-fade-motion:var(--_nav-label-fade-dur) var(--effect-animation-easing-ease-in-out, ease);--_nav-label-fade-out-dur:calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));--_nav-label-fade-out-motion:var(--_nav-label-fade-out-dur) var(--effect-animation-easing-ease-in-out, ease);--_nav-bg:var(--color-navigation-background);--_nav-border:var(--color-navigation-border-tertiary);--_nav-divider:var(--color-navigation-divider);--_nav-fg-primary:var(--color-navigation-foreground-primary);--_nav-fg-secondary:var(--color-navigation-foreground-secondary);--_nav-fg-tertiary:var(--color-navigation-foreground-tertiary);--_nav-hover:var(--color-navigation-interaction-hover);--_nav-pressed:var(--color-navigation-interaction-pressed);--_nav-focus:var(--color-navigation-interaction-focus);--_nav-dot:var(--color-navigation-foreground-brand)}.panel-nav--settings.sc-ds-panel-nav{--_nav-bg:var(--color-background-secondary);--_nav-border:var(--color-border-tertiary);--_nav-divider:var(--color-border-tertiary);--_nav-fg-primary:var(--color-foreground-primary);--_nav-fg-secondary:var(--color-foreground-secondary);--_nav-fg-tertiary:var(--color-foreground-tertiary);--_nav-hover:var(--color-interaction-hover);--_nav-pressed:var(--color-interaction-pressed);--_nav-focus:var(--color-interaction-focus);--_nav-dot:var(--color-foreground-bold-brand)}.panel-nav.sc-ds-panel-nav{display:flex;flex-direction:column;width:var(--_nav-width);min-width:var(--_nav-width);height:100%;background:var(--_nav-bg);border-right:var(--dimension-stroke-width-012, 1px) solid var(--_nav-border);box-sizing:border-box;overflow:hidden;transition:width var(--_nav-expand-motion), min-width var(--_nav-expand-motion), background var(--effect-motion-short-3, 200ms ease), border-color var(--effect-motion-short-3, 200ms ease);font-family:var(--typography-font-family, system-ui)}.panel-nav--collapsed.sc-ds-panel-nav{width:var(--_nav-width-collapsed);min-width:var(--_nav-width-collapsed)}.panel-nav__header.sc-ds-panel-nav{display:flex;align-items:center;height:var(--dimension-size-600, 48px);padding:var(--dimension-space-100, 8px);flex-shrink:0;box-sizing:border-box;border-bottom:var(--dimension-stroke-width-012, 1px) solid var(--_nav-divider);transition:border-color var(--effect-motion-short-3, 200ms ease)}.panel-nav__header-btn.sc-ds-panel-nav{all:unset;display:flex;align-items:center;justify-content:center;padding:var(--dimension-space-075, 6px);border-radius:var(--dimension-radius-025, 2px);cursor:pointer;color:var(--_nav-fg-primary);position:relative;flex-shrink:0;box-sizing:border-box;transition:color var(--effect-motion-short-3, 200ms ease)}.panel-nav__header-btn.sc-ds-panel-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025, 2px);background:transparent;transition:background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);pointer-events:none}.panel-nav__header-btn.sc-ds-panel-nav:hover::after{background:var(--_nav-hover);transition:none}.panel-nav__header-btn.sc-ds-panel-nav:active::after{background:var(--_nav-pressed);transition:none}.panel-nav__header-btn.sc-ds-panel-nav:focus-visible{outline:none}.panel-nav__header-btn.sc-ds-panel-nav:focus-visible::after{outline:var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);outline-offset:calc(-1 * var(--dimension-stroke-width-025, 2px))}.panel-nav__header-logo.sc-ds-panel-nav{display:flex;align-items:center;justify-content:center;position:relative;z-index:1;transition:opacity var(--effect-motion-short-2, 100ms ease)}.panel-nav__m-mark.sc-ds-panel-nav{width:var(--dimension-iconography-md, 20px);height:var(--dimension-iconography-md, 20px);display:block}.panel-nav__header-toggle.sc-ds-panel-nav{display:none;align-items:center;justify-content:center;position:absolute;inset:0;z-index:1}.panel-nav__header-btn.sc-ds-panel-nav:hover .panel-nav__header-logo.sc-ds-panel-nav{opacity:0}.panel-nav__header-btn.sc-ds-panel-nav:hover .panel-nav__header-toggle.sc-ds-panel-nav{display:flex}.panel-nav__body.sc-ds-panel-nav{flex:1;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:var(--dimension-space-200, 16px);padding:var(--dimension-space-100, 8px);box-sizing:border-box;scrollbar-width:none}.panel-nav__body.sc-ds-panel-nav::-webkit-scrollbar{display:none}.panel-nav__group.sc-ds-panel-nav{display:flex;flex-direction:column;gap:var(--dimension-space-050, 4px)}.panel-nav__group-label.sc-ds-panel-nav{display:flex;align-items:center;text-transform:uppercase;color:var(--_nav-fg-secondary);user-select:none;height:var(--dimension-size-300, 24px);line-height:var(--typography-lineheight-xs, 12px);padding:0 var(--dimension-space-075, 6px);white-space:nowrap;overflow:hidden;max-height:var(--dimension-size-300, 24px);opacity:1;transition:opacity var(--_nav-label-fade-motion) 0ms, max-height var(--_nav-label-fade-motion) 0ms, padding var(--_nav-label-fade-motion) 0ms, color var(--effect-motion-short-3, 200ms ease)}.panel-nav__item.sc-ds-panel-nav{all:unset;display:flex;align-items:center;gap:var(--dimension-space-050, 4px);padding:0 var(--dimension-space-075, 6px);height:var(--dimension-size-400, 32px);border-radius:var(--dimension-radius-025, 2px);cursor:pointer;color:var(--_nav-fg-secondary);position:relative;box-sizing:border-box;width:100%;user-select:none;transition:color var(--effect-motion-short-1, 50ms ease-in-out)}.panel-nav__item.sc-ds-panel-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025, 2px);background:transparent;pointer-events:none;transition:background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease)}.panel-nav__item.sc-ds-panel-nav:hover::after{background:var(--_nav-hover);transition:none}.panel-nav__item.sc-ds-panel-nav:active::after{background:var(--_nav-pressed);transition:none}.panel-nav__item.sc-ds-panel-nav:focus-visible{outline:none}.panel-nav__item.sc-ds-panel-nav:focus-visible::after{outline:var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);outline-offset:calc(-1 * var(--dimension-stroke-width-025, 2px))}.panel-nav__item--active.sc-ds-panel-nav{color:var(--_nav-fg-primary)}.panel-nav__item-icon.sc-ds-panel-nav{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--dimension-iconography-md, 20px);height:var(--dimension-iconography-md, 20px);position:relative}.panel-nav__item-label.sc-ds-panel-nav{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;height:var(--typography-lineheight-md, 20px);line-height:var(--typography-lineheight-md, 20px);opacity:1;mask-image:linear-gradient(to right, black 50%, transparent 100%);-webkit-mask-image:linear-gradient(to right, black 50%, transparent 100%);mask-size:200% 100%;-webkit-mask-size:200% 100%;mask-position:0% 0;-webkit-mask-position:0% 0;transition:opacity var(--_nav-label-fade-motion) 0ms, mask-position var(--_nav-label-fade-motion) 0ms, -webkit-mask-position var(--_nav-label-fade-motion) 0ms}.panel-nav__item-label-text.sc-ds-panel-nav{padding:0 var(--dimension-space-025, 2px)}.panel-nav__item-dot.sc-ds-panel-nav{position:absolute;right:13px;top:13px;width:var(--dimension-space-075, 6px);height:var(--dimension-space-075, 6px);border-radius:var(--dimension-radius-full, 999px);background:var(--_nav-dot);box-shadow:0 0 0 var(--dimension-stroke-width-018, 1.5px) var(--_nav-bg);pointer-events:none;transition:right var(--_nav-expand-motion), top var(--_nav-expand-motion), background var(--effect-motion-short-3, 200ms ease), box-shadow var(--effect-motion-short-3, 200ms ease)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__item-dot.sc-ds-panel-nav{right:6px;top:6px}.panel-nav--animating.sc-ds-panel-nav .panel-nav__item-label.sc-ds-panel-nav{text-overflow:clip}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__item-label.sc-ds-panel-nav{opacity:0;pointer-events:none;text-overflow:clip;mask-position:100% 0;-webkit-mask-position:100% 0;transition:opacity var(--_nav-label-fade-out-motion) 0ms, mask-position var(--_nav-label-fade-out-motion) 0ms, -webkit-mask-position var(--_nav-label-fade-out-motion) 0ms}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__group-label.sc-ds-panel-nav{opacity:0;max-height:0;padding:0 var(--dimension-space-075, 6px);pointer-events:none;transition:opacity var(--_nav-label-fade-out-motion) 0ms, max-height var(--_nav-label-fade-out-motion) 0ms, padding var(--_nav-label-fade-out-motion) 0ms, color var(--effect-motion-short-3, 200ms ease)}.panel-nav__footer.sc-ds-panel-nav{position:relative;flex-shrink:0;height:calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height));transition:height var(--_nav-expand-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer.sc-ds-panel-nav{height:calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height) * 2 + var(--dimension-space-050, 4px))}.panel-nav__footer.sc-ds-panel-nav::before{content:'';position:absolute;bottom:100%;left:0;right:0;height:calc(var(--dimension-base, 8px) * 6);background:linear-gradient(to bottom, transparent, var(--_nav-bg));pointer-events:none;opacity:1;transition:opacity var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease)}.panel-nav--at-bottom.sc-ds-panel-nav .panel-nav__footer.sc-ds-panel-nav::before{opacity:0}.panel-nav__footer-btn.sc-ds-panel-nav{all:unset;display:flex;align-items:center;justify-content:center;position:absolute;left:var(--_nav-padding-x);top:var(--_nav-padding-y);padding:var(--dimension-space-075, 6px);border-radius:var(--dimension-radius-half, 9999px);cursor:pointer;color:var(--_nav-fg-secondary);box-sizing:border-box;background:transparent;transition:background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease), color var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease)}.panel-nav__footer-btn.sc-ds-panel-nav:focus-visible{outline:var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);outline-offset:calc(-1 * var(--dimension-stroke-width-025, 2px))}.panel-nav--dashboard.sc-ds-panel-nav .panel-nav__footer-btn.sc-ds-panel-nav:hover{background:var(--color-background-secondary);color:var(--color-foreground-secondary);transition:none}.panel-nav--settings.sc-ds-panel-nav .panel-nav__footer-btn.sc-ds-panel-nav:hover{background:var(--color-navigation-background);color:var(--color-navigation-foreground-secondary);transition:none}.panel-nav__footer-user.sc-ds-panel-nav{position:absolute;left:calc(var(--_nav-padding-x) + var(--_nav-footer-btn-w) + var(--dimension-space-050, 4px));right:var(--_nav-padding-x);top:var(--_nav-padding-y);width:auto;min-width:0;transition:left var(--_nav-expand-motion), right var(--_nav-expand-motion), top var(--_nav-expand-motion), color var(--effect-motion-short-3, 200ms ease)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-user.sc-ds-panel-nav{left:var(--_nav-padding-x);right:var(--_nav-padding-x);top:calc(var(--_nav-padding-y) + var(--_nav-item-height) + var(--dimension-space-050, 4px))}.panel-nav__footer-user-label.sc-ds-panel-nav{text-align:right;position:absolute;left:var(--dimension-space-075, 6px);right:calc(var(--dimension-space-075, 6px) + var(--dimension-iconography-md, 20px) + var(--dimension-space-050, 4px));top:50%;transform:translateY(-50%);flex:none;height:var(--typography-lineheight-md, 20px);mask-image:none;-webkit-mask-image:none;transition:opacity var(--_nav-label-fade-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-user-label.sc-ds-panel-nav{opacity:0;pointer-events:none;mask-position:0% 0;-webkit-mask-position:0% 0}.panel-nav__footer-user-icon.sc-ds-panel-nav{position:absolute;left:calc(100% - var(--dimension-iconography-md, 20px) - var(--dimension-space-075, 6px));top:0;bottom:0;height:auto;display:flex;align-items:center;justify-content:center;transition:left var(--_nav-expand-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-user-icon.sc-ds-panel-nav{left:var(--dimension-space-075, 6px)}.panel-nav__footer-icon-expanded.sc-ds-panel-nav,.panel-nav__footer-icon-collapsed.sc-ds-panel-nav{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.panel-nav__footer-icon-expanded.sc-ds-panel-nav{opacity:1;transition:opacity var(--_nav-label-fade-motion)}.panel-nav__footer-icon-collapsed.sc-ds-panel-nav{opacity:0;transition:opacity var(--_nav-label-fade-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-icon-expanded.sc-ds-panel-nav{opacity:0;transition:opacity var(--_nav-label-fade-out-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-icon-collapsed.sc-ds-panel-nav{opacity:1;transition:opacity var(--_nav-label-fade-out-motion)}.panel-nav__user-initial.sc-ds-panel-nav{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--_nav-fg-secondary);text-transform:uppercase;line-height:1;pointer-events:none;transition:color var(--effect-motion-short-3, 200ms ease)}.panel-nav__resize-handle.sc-ds-panel-nav{position:absolute;top:0;right:var(--dimension-space-n050, -4px);bottom:0;width:var(--dimension-space-100, 8px);z-index:10;cursor:ew-resize;touch-action:none;background:transparent}.panel-nav__resize-handle.sc-ds-panel-nav::before{content:'';position:absolute;inset:0;background:rgba(0, 0, 0, 0.001)}.panel-nav__resize-handle.sc-ds-panel-nav::after{content:'';position:absolute;top:0;bottom:0;left:50%;transform:translateX(-50%);width:var(--dimension-stroke-width-025, 2px);background:var(--color-background-bold-brand);opacity:0;pointer-events:none;transition:opacity var(--effect-motion-short-2, 100ms ease-in-out)}.panel-nav__resize-handle--overlay.sc-ds-panel-nav::after{opacity:1}@media (prefers-reduced-motion: reduce){.panel-nav.sc-ds-panel-nav,.panel-nav.sc-ds-panel-nav *.sc-ds-panel-nav,.panel-nav.sc-ds-panel-nav *.sc-ds-panel-nav::before,.panel-nav.sc-ds-panel-nav *.sc-ds-panel-nav::after,.panel-nav__resize-handle.sc-ds-panel-nav,.panel-nav__resize-handle.sc-ds-panel-nav::before,.panel-nav__resize-handle.sc-ds-panel-nav::after{transition-duration:0.01ms !important;animation-duration:0.01ms !important;transition-delay:0.01ms !important}}`;let d=false;const c=new WeakMap;const v=new WeakMap;function p(){if(d)return;const a="ds-panel-nav-vt-style";if(document.getElementById(a)){d=true;return}const e=document.createElement("style");e.id=a;e.textContent=["::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal}","::view-transition-new(root){clip-path:circle(0px at var(--vt-x,50%) var(--vt-y,50%))}"].join("\n");document.head.appendChild(e);d=true}function h(a,e){const n=a.trim();const t=parseFloat(n);if(Number.isNaN(t))return e;if(/ms\s*$/.test(n))return t;if(/s\s*$/.test(n))return t*1e3;return t}const f=a(class a extends e{constructor(a){super();if(a!==false){this.__registerHost()}this.dsNavSelect=n(this,"dsNavSelect");this.dsNavToggle=n(this,"dsNavToggle");this.dsNavFooterAction=n(this,"dsNavFooterAction");this.variant="dashboard";this.disableViewTransition=false;this.groups="[]";this.activeId="";this.collapsed=false;this.breakpoint=0;this.storageKey="";this.currentUrl="";this.userName="";this.userInitial="";this.renderedVariant="dashboard";this.parsedGroups=[];this.atBottom=false;this.isAnimating=false;this.rovingIndex=0;this.viewportNarrow=false;this.urlDerivedActiveId="";this.isDragging=false;this.dragStartX=0;this.didSnap=false;this.lastDeltaX=0;this.edgeOverlayTimer=null;this.showEdgeOverlay=false}get effectiveActiveId(){return this.urlDerivedActiveId||this.activeId}onCollapsedChange(){this.startCollapseAnimation()}onBreakpointChange(){this.disconnectResizeObserver();if(this.breakpoint>0)this.connectResizeObserver()}onGroupsChange(a){try{this.parsedGroups=JSON.parse(a)}catch{this.parsedGroups=[]}this.syncRovingIndex()}onActiveIdChange(){this.syncRovingIndex()}onCurrentUrlChange(){this.syncActiveFromUrl()}async onVariantChange(a){if(this.disableViewTransition){this.renderedVariant=a;return}c.get(this)?.skipTransition();c.delete(this);const e=document;if(typeof e.startViewTransition!=="function"){this.renderedVariant=a;return}p();const n=this.el.querySelector(".panel-nav__footer-btn");const t=n?.getBoundingClientRect();const i=t?Math.round(t.left+t.width/2):Math.round(window.innerWidth/2);const o=t?Math.round(t.top+t.height/2):Math.round(window.innerHeight/2);const s=Math.ceil(Math.hypot(Math.max(i,window.innerWidth-i),Math.max(o,window.innerHeight-o)));document.documentElement.style.setProperty("--vt-x",`${i}px`);document.documentElement.style.setProperty("--vt-y",`${o}px`);const r=e.startViewTransition((()=>new Promise((e=>{v.set(this,e);this.renderedVariant=a}))));c.set(this,r);r.finished.finally((()=>{if(c.get(this)===r)c.delete(this);v.delete(this)}));r.ready.then((()=>{const a=getComputedStyle(document.documentElement).getPropertyValue("--effect-animation-duration-long-1").trim();const e=h(a,750);document.documentElement.animate({clipPath:[`circle(0px at ${i}px ${o}px)`,`circle(${s}px at ${i}px ${o}px)`]},{duration:e,easing:"ease-in-out",fill:"forwards",pseudoElement:"::view-transition-new(root)"})})).catch((()=>{}))}componentWillLoad(){this.renderedVariant=this.variant;if(this.storageKey){try{const a=localStorage.getItem(this.storageKey);if(a!==null)this.collapsed=a==="true"}catch{}}this.onGroupsChange(this.groups);this.syncActiveFromUrl()}componentDidLoad(){this.checkScroll();if(this.breakpoint>0)this.connectResizeObserver();this.onGroupsChange(this.groups)}componentDidRender(){const a=v.get(this);if(a){v.delete(this);a()}}disconnectedCallback(){this.disconnectResizeObserver();this.clearEdgeOverlayTimer();if(this.globalMouseMoveHandler){window.removeEventListener("mousemove",this.globalMouseMoveHandler)}if(this.globalMouseUpHandler){window.removeEventListener("mouseup",this.globalMouseUpHandler)}}startCollapseAnimation(){this.isAnimating=true;const a=this.el.querySelector(".panel-nav");if(this.transitionEndHandler){a?.removeEventListener("transitionend",this.transitionEndHandler)}this.transitionEndHandler=e=>{if(e.propertyName==="width"){this.isAnimating=false;a?.removeEventListener("transitionend",this.transitionEndHandler)}};a?.addEventListener("transitionend",this.transitionEndHandler)}connectResizeObserver(){this.viewportNarrow=window.innerWidth<this.breakpoint;this.resizeObserver=new ResizeObserver((()=>{this.viewportNarrow=window.innerWidth<this.breakpoint}));this.resizeObserver.observe(document.documentElement)}disconnectResizeObserver(){this.resizeObserver?.disconnect();this.resizeObserver=undefined}syncActiveFromUrl(){if(!this.currentUrl){this.urlDerivedActiveId="";return}let a;let e=0;for(const n of this.getAllItems()){if(n.href&&this.currentUrl.startsWith(n.href)&&n.href.length>e){a=n;e=n.href.length}}this.urlDerivedActiveId=a?.id??""}applyToggle(a){this.dsNavToggle.emit(a);if(this.storageKey){this.collapsed=a;try{localStorage.setItem(this.storageKey,String(a))}catch{}}}getAllItems(){return this.parsedGroups.flatMap((a=>a.items))}syncRovingIndex(){const a=this.getAllItems().findIndex((a=>a.id===this.effectiveActiveId));this.rovingIndex=a>=0?a:0}handleItemKeyDown(a,e){const n=this.getAllItems().length;let t;switch(a.key){case"ArrowDown":a.preventDefault();t=(e+1)%n;break;case"ArrowUp":a.preventDefault();t=(e-1+n)%n;break;case"Home":a.preventDefault();t=0;break;case"End":a.preventDefault();t=n-1;break;default:return}this.rovingIndex=t;const i=Array.from(this.el.querySelectorAll(".panel-nav__body .panel-nav__item"));i[t]?.focus()}checkScroll(){const a=this.el.querySelector(".panel-nav__body");if(!a)return;const e=a.scrollHeight-a.scrollTop-a.clientHeight;this.atBottom=e<2}handleBodyScroll(a){const e=a.target;const n=e.scrollHeight-e.scrollTop-e.clientHeight;this.atBottom=n<2}handleItemClick(a){this.dsNavSelect.emit(a)}handleToggle(){this.applyToggle(!this.collapsed)}handleFooterAction(){this.dsNavFooterAction.emit()}clearEdgeOverlayTimer(){if(this.edgeOverlayTimer!==null){window.clearTimeout(this.edgeOverlayTimer);this.edgeOverlayTimer=null}}handleResizeHandleMouseEnter(){this.clearEdgeOverlayTimer();this.edgeOverlayTimer=window.setTimeout((()=>{this.showEdgeOverlay=true;this.edgeOverlayTimer=null}),500)}handleResizeHandleMouseLeave(){if(this.isDragging)return;this.clearEdgeOverlayTimer();this.showEdgeOverlay=false}handleResizeHandleMouseDown(a){a.preventDefault();a.stopPropagation();const e=this.collapsed||this.viewportNarrow;this.isDragging=true;this.dragStartX=a.clientX;this.didSnap=false;this.lastDeltaX=0;this.clearEdgeOverlayTimer();this.showEdgeOverlay=false;document.body.style.cursor="ew-resize";document.body.style.userSelect="none";const n=a=>{const n=a.clientX-this.dragStartX;this.lastDeltaX=Math.abs(n);if(this.didSnap)return;if(!e&&n<-8){this.applyToggle(true);this.didSnap=true}else if(e&&n>8){this.applyToggle(false);this.didSnap=true}};const t=()=>{if(!this.didSnap&&this.lastDeltaX<3){this.applyToggle(!e)}this.isDragging=false;this.showEdgeOverlay=false;document.body.style.cursor="";document.body.style.userSelect="";window.removeEventListener("mousemove",n);window.removeEventListener("mouseup",t);this.globalMouseMoveHandler=undefined;this.globalMouseUpHandler=undefined};this.globalMouseMoveHandler=n;this.globalMouseUpHandler=t;window.addEventListener("mousemove",n);window.addEventListener("mouseup",t)}renderNavItem(a,e,n){const i=a.id===this.effectiveActiveId;const o=[t("span",{class:"panel-nav__item-icon"},t("ds-icon",{name:a.icon,size:"md",color:"inherit",flag:a.flag})),t("span",{class:"panel-nav__item-label"},t("span",{class:"panel-nav__item-label-text"},t("ds-text",{as:"span",variant:i?"text-body-medium-emphasis":"text-body-medium",color:"inherit"},a.label))),a.dot&&t("span",{class:"panel-nav__item-dot","aria-hidden":"true"})];const s={class:{"panel-nav__item":true,"panel-nav__item--active":i},"aria-current":i?"page":undefined,title:n?a.label:undefined,tabIndex:e===this.rovingIndex?0:-1,onClick:()=>this.handleItemClick(a.id),onKeyDown:a=>this.handleItemKeyDown(a,e),onFocus:()=>{this.rovingIndex=e}};return a.href?t("a",{...s,href:a.href},o):t("button",{...s,type:"button"},o)}render(){const a=this.renderedVariant==="dashboard";const e=this.collapsed||this.viewportNarrow;const{userName:n,userInitial:o}=this;const s={"panel-nav":true,"panel-nav--dashboard":a,"panel-nav--settings":!a,"panel-nav--collapsed":e,"panel-nav--animating":this.isAnimating,"panel-nav--at-bottom":this.atBottom};return t(i,{key:"01d20359d9ca21960871752cc93e7925c120c58e",style:{display:"block",position:"relative"}},t("nav",{key:"d1955c92d0b0f2c588df18262a0fdbde32a9e803",class:s,"aria-label":a?"Main navigation":"Settings navigation"},t("div",{key:"c350bea0d242ca3cd7f093a43bed749469ca8a14",class:"panel-nav__header"},t("button",{key:"532ace0923570805395fa700243a03ef443b4d45",type:"button",class:"panel-nav__header-btn",onClick:()=>this.handleToggle(),"aria-label":e?"Expand navigation":"Collapse navigation","aria-expanded":e?"false":"true"},t("span",{key:"e85252b4ffb3795cf3ae5a69accb5a7339042647",class:"panel-nav__header-logo","aria-hidden":"true"},t("svg",{key:"1a5a9663fb7774edd0368d3fae375279e53c8b57",class:"panel-nav__m-mark",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",focusable:"false","aria-hidden":"true"},t("path",{key:"ceb229189fe603af6392a10eb0115baab4c17b03",d:"M11.1159 4.31537H7.67021L2.53401 13.0703H0V15.6875H4.02716L8.24319 8.49978V15.6846H11.6342L15.8289 8.47829V15.6846H18.7122V4.3125H15.2559L11.1159 11.3648V4.31537Z",fill:"currentColor"}))),t("span",{key:"28770da1bcc0970f82bfe7a8268c92d5b0c61d4e",class:"panel-nav__header-toggle","aria-hidden":"true"},t("ds-icon",{key:"5f28b2e6a25ddbded270984cf8ae48aba73d8a4b",name:e?"LeftExpandB":"LeftCollapseB",size:"md",color:"inherit"})))),t("div",{key:"7f33f2a66dc93237aa313a4df29a5418cc10dbb5",class:"panel-nav__body",onScroll:a=>this.handleBodyScroll(a)},(()=>{let a=0;return this.parsedGroups.map((n=>t("div",{class:"panel-nav__group"},n.label&&t("span",{class:"panel-nav__group-label"},t("span",{class:"panel-nav__item-label-text"},t("ds-text",{as:"span",variant:"text-caption-emphasis",color:"inherit"},n.label))),n.items.map((n=>this.renderNavItem(n,a++,e))))))})()),t("div",{key:"5dc95bc33b59cc4f5ee1e3178aea6905bbf6ebe3",class:"panel-nav__footer"},t("button",{key:"1b3b7c035aae20c5a0953de047c3aa876596a604",type:"button",class:"panel-nav__footer-btn",title:a?"Settings":"Dashboard","aria-label":a?"Open settings":"Go to dashboard",onClick:()=>this.handleFooterAction()},t("ds-icon",{key:"dd6eb0a8c7369979e22c9f78ec515fa14f601d24",name:a?"Gear":"Dashboard",size:"md",color:"inherit"})),t("button",{key:"08261a68c96d0f265ecce7d93635c5ae3bf1da6a",type:"button",class:"panel-nav__item panel-nav__footer-user","aria-label":e?`User: ${n}`:`User menu for ${n}`},t("span",{key:"5828cd9bd1da834f2e38e360cbcb8eb1b97bd688",class:"panel-nav__item-label panel-nav__footer-user-label"},t("span",{key:"2522dd79057da3b3b070ec6cc02f360ce50fcf5b",class:"panel-nav__item-label-text"},t("ds-text",{key:"ca7c2cc4bbe68e12ab9841e0da98c6caf83d53c1",as:"span",variant:"text-body-medium-emphasis",color:"inherit"},n))),t("span",{key:"0f86e95a3f57f0016f0919d089c866d37903b5fd",class:"panel-nav__item-icon panel-nav__footer-user-icon","aria-hidden":"true"},t("span",{key:"942b78ee6e48a12705ebb4f0974fa583d02c8cea",class:"panel-nav__footer-icon-expanded"},t("ds-icon",{key:"fb581ce5a349c5b1eb89dd581fcdbf6586661960",name:"ChevronUpDown",size:"md",color:"inherit"})),t("span",{key:"21ecc58857f2ec5efe4c1fcd5d7a9411fb77a9f1",class:"panel-nav__footer-icon-collapsed"},t("ds-icon",{key:"53862a063fb026cb6718ada3149b40ea0fbdaee8",name:"Circle",size:"md",color:"inherit"}),t("span",{key:"97446f68f7ba7acf1e3df871692c1f24867240a5",class:"panel-nav__user-initial"},t("ds-text",{key:"3c18372d8dee6570d01065e94eb247e420fa4012",as:"span",variant:"text-caption-emphasis",color:"inherit"},o))))))),!this.viewportNarrow&&t("div",{key:"189f63f36b385ad79b3b7b9b5fa783f711030d76",class:{"panel-nav__resize-handle":true,"panel-nav__resize-handle--overlay":this.showEdgeOverlay},onMouseEnter:()=>this.handleResizeHandleMouseEnter(),onMouseLeave:()=>this.handleResizeHandleMouseLeave(),onMouseDown:a=>this.handleResizeHandleMouseDown(a),"aria-hidden":"true"}))}get el(){return this}static get watchers(){return{collapsed:[{onCollapsedChange:0}],viewportNarrow:[{onCollapsedChange:0}],breakpoint:[{onBreakpointChange:0}],groups:[{onGroupsChange:0}],activeId:[{onActiveIdChange:0}],urlDerivedActiveId:[{onActiveIdChange:0}],currentUrl:[{onCurrentUrlChange:0}],variant:[{onVariantChange:0}]}}static get style(){return l()}},[2,"ds-panel-nav",{variant:[1],disableViewTransition:[4,"disable-view-transition"],groups:[1],activeId:[1,"active-id"],collapsed:[1028],breakpoint:[2],storageKey:[1,"storage-key"],currentUrl:[1,"current-url"],userName:[1,"user-name"],userInitial:[1,"user-initial"],renderedVariant:[32],parsedGroups:[32],atBottom:[32],isAnimating:[32],rovingIndex:[32],viewportNarrow:[32],urlDerivedActiveId:[32],showEdgeOverlay:[32]},undefined,{collapsed:[{onCollapsedChange:0}],viewportNarrow:[{onCollapsedChange:0}],breakpoint:[{onBreakpointChange:0}],groups:[{onGroupsChange:0}],activeId:[{onActiveIdChange:0}],urlDerivedActiveId:[{onActiveIdChange:0}],currentUrl:[{onCurrentUrlChange:0}],variant:[{onVariantChange:0}]}]);function m(){if(typeof customElements==="undefined"){return}const a=["ds-panel-nav","ds-icon","ds-text"];a.forEach((a=>{switch(a){case"ds-panel-nav":if(!customElements.get(o(a))){customElements.define(o(a),f)}break;case"ds-icon":if(!customElements.get(o(a))){s()}break;case"ds-text":if(!customElements.get(o(a))){r()}break}}))}m();const u=f;const _=m;export{u as DsPanelNav,_ as defineCustomElement};
|
|
1
|
+
import{p as a,H as e,c as n,h as t,a as i,t as o}from"./index.js";import{d as s}from"./p-CkBXHj0e.js";import{d as r}from"./p-C_mk7BoY.js";function d(a,e){return a===e||a.startsWith(`${e}/`)}function l(a,e){if(!a)return"";let n="";let t=0;for(const i of e){if(!i.href)continue;if(d(a,i.href)&&i.href.length>t){n=i.id;t=i.href.length}}return n}function c(a){if(Array.isArray(a))return a;if(typeof a==="string"){try{const e=JSON.parse(a);return Array.isArray(e)?e:[]}catch{return[]}}return[]}let v=false;function p(){if(v)return;const a="ds-panel-nav-vt-style";if(document.getElementById(a)){v=true;return}const e=document.createElement("style");e.id=a;e.textContent=["::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal}","::view-transition-new(root){clip-path:circle(0px at var(--vt-x,50%) var(--vt-y,50%))}"].join("\n");document.head.appendChild(e);v=true}const h=()=>`.panel-nav.sc-ds-panel-nav{--_nav-width:200px;--_nav-width-collapsed:48px;--_nav-item-height:var(--dimension-size-400, 32px);--_nav-padding-x:var(--dimension-space-100, 8px);--_nav-padding-y:var(--dimension-space-100, 8px);--_nav-footer-btn-w:calc(var(--dimension-space-075, 6px) * 2 + var(--dimension-iconography-md, 20px));--_nav-speed:var(--ds-panel-nav-speed, 1);--_nav-expand-dur:calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));--_nav-expand-motion:var(--_nav-expand-dur) var(--effect-animation-easing-ease-in-out, ease);--_nav-label-fade-dur:calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));--_nav-label-fade-motion:var(--_nav-label-fade-dur) var(--effect-animation-easing-ease-in-out, ease);--_nav-label-fade-out-dur:calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));--_nav-label-fade-out-motion:var(--_nav-label-fade-out-dur) var(--effect-animation-easing-ease-in-out, ease);--_nav-bg:var(--color-navigation-background);--_nav-border:var(--color-navigation-border-tertiary);--_nav-divider:var(--color-navigation-divider);--_nav-fg-primary:var(--color-navigation-foreground-primary);--_nav-fg-secondary:var(--color-navigation-foreground-secondary);--_nav-fg-tertiary:var(--color-navigation-foreground-tertiary);--_nav-hover:var(--color-navigation-interaction-hover);--_nav-pressed:var(--color-navigation-interaction-pressed);--_nav-focus:var(--color-navigation-interaction-focus);--_nav-dot:var(--color-navigation-foreground-brand)}.panel-nav--settings.sc-ds-panel-nav{--_nav-bg:var(--color-background-secondary);--_nav-border:var(--color-border-tertiary);--_nav-divider:var(--color-border-tertiary);--_nav-fg-primary:var(--color-foreground-primary);--_nav-fg-secondary:var(--color-foreground-secondary);--_nav-fg-tertiary:var(--color-foreground-tertiary);--_nav-hover:var(--color-interaction-hover);--_nav-pressed:var(--color-interaction-pressed);--_nav-focus:var(--color-interaction-focus);--_nav-dot:var(--color-foreground-bold-brand)}.panel-nav.sc-ds-panel-nav{display:flex;flex-direction:column;width:var(--_nav-width);min-width:var(--_nav-width);height:100%;background:var(--_nav-bg);border-right:var(--dimension-stroke-width-012, 1px) solid var(--_nav-border);box-sizing:border-box;overflow:hidden;transition:width var(--_nav-expand-motion), min-width var(--_nav-expand-motion), background var(--effect-motion-short-3, 200ms ease), border-color var(--effect-motion-short-3, 200ms ease);font-family:var(--typography-font-family, system-ui)}.panel-nav--collapsed.sc-ds-panel-nav{width:var(--_nav-width-collapsed);min-width:var(--_nav-width-collapsed)}.panel-nav__header.sc-ds-panel-nav{display:flex;align-items:center;height:var(--dimension-size-600, 48px);padding:var(--dimension-space-100, 8px);flex-shrink:0;box-sizing:border-box;border-bottom:var(--dimension-stroke-width-012, 1px) solid var(--_nav-divider);transition:border-color var(--effect-motion-short-3, 200ms ease)}.panel-nav__header-btn.sc-ds-panel-nav{all:unset;display:flex;align-items:center;justify-content:center;padding:var(--dimension-space-075, 6px);border-radius:var(--dimension-radius-025, 2px);cursor:pointer;color:var(--_nav-fg-primary);position:relative;flex-shrink:0;box-sizing:border-box;transition:color var(--effect-motion-short-3, 200ms ease)}.panel-nav__header-btn.sc-ds-panel-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025, 2px);background:transparent;transition:background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);pointer-events:none}.panel-nav__header-btn.sc-ds-panel-nav:hover::after{background:var(--_nav-hover);transition:none}.panel-nav__header-btn.sc-ds-panel-nav:active::after{background:var(--_nav-pressed);transition:none}.panel-nav__header-btn.sc-ds-panel-nav:focus-visible{outline:none}.panel-nav__header-btn.sc-ds-panel-nav:focus-visible::after{outline:var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);outline-offset:calc(-1 * var(--dimension-stroke-width-025, 2px))}.panel-nav__header-logo.sc-ds-panel-nav{display:flex;align-items:center;justify-content:center;position:relative;z-index:1;transition:opacity var(--effect-motion-short-2, 100ms ease)}.panel-nav__m-mark.sc-ds-panel-nav{width:var(--dimension-iconography-md, 20px);height:var(--dimension-iconography-md, 20px);display:block}.panel-nav__header-toggle.sc-ds-panel-nav{display:none;align-items:center;justify-content:center;position:absolute;inset:0;z-index:1}.panel-nav__header-btn.sc-ds-panel-nav:hover .panel-nav__header-logo.sc-ds-panel-nav{opacity:0}.panel-nav__header-btn.sc-ds-panel-nav:hover .panel-nav__header-toggle.sc-ds-panel-nav{display:flex}.panel-nav__body.sc-ds-panel-nav{flex:1;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:var(--dimension-space-200, 16px);padding:var(--dimension-space-100, 8px);box-sizing:border-box;scrollbar-width:none}.panel-nav__body.sc-ds-panel-nav::-webkit-scrollbar{display:none}.panel-nav__group.sc-ds-panel-nav{display:flex;flex-direction:column;gap:var(--dimension-space-050, 4px)}.panel-nav__group-label.sc-ds-panel-nav{display:flex;align-items:center;text-transform:uppercase;color:var(--_nav-fg-secondary);user-select:none;height:var(--dimension-size-300, 24px);line-height:var(--typography-lineheight-xs, 12px);padding:0 var(--dimension-space-075, 6px);white-space:nowrap;overflow:hidden;max-height:var(--dimension-size-300, 24px);opacity:1;transition:opacity var(--_nav-label-fade-motion) 0ms, max-height var(--_nav-label-fade-motion) 0ms, padding var(--_nav-label-fade-motion) 0ms, color var(--effect-motion-short-3, 200ms ease)}.panel-nav__item.sc-ds-panel-nav{all:unset;display:flex;align-items:center;gap:var(--dimension-space-050, 4px);padding:0 var(--dimension-space-075, 6px);height:var(--dimension-size-400, 32px);border-radius:var(--dimension-radius-025, 2px);cursor:pointer;color:var(--_nav-fg-secondary);position:relative;box-sizing:border-box;width:100%;user-select:none;transition:color var(--effect-motion-short-1, 50ms ease-in-out)}.panel-nav__item.sc-ds-panel-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025, 2px);background:transparent;pointer-events:none;transition:background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease)}.panel-nav__item.sc-ds-panel-nav:hover::after{background:var(--_nav-hover);transition:none}.panel-nav__item.sc-ds-panel-nav:active::after{background:var(--_nav-pressed);transition:none}.panel-nav__item.sc-ds-panel-nav:focus-visible{outline:none}.panel-nav__item.sc-ds-panel-nav:focus-visible::after{outline:var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);outline-offset:calc(-1 * var(--dimension-stroke-width-025, 2px))}.panel-nav__item--active.sc-ds-panel-nav{color:var(--_nav-fg-primary)}.panel-nav__item-icon.sc-ds-panel-nav{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--dimension-iconography-md, 20px);height:var(--dimension-iconography-md, 20px);position:relative}.panel-nav__item-label.sc-ds-panel-nav{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;height:var(--typography-lineheight-md, 20px);line-height:var(--typography-lineheight-md, 20px);opacity:1;mask-image:linear-gradient(to right, black 50%, transparent 100%);-webkit-mask-image:linear-gradient(to right, black 50%, transparent 100%);mask-size:200% 100%;-webkit-mask-size:200% 100%;mask-position:0% 0;-webkit-mask-position:0% 0;transition:opacity var(--_nav-label-fade-motion) 0ms, mask-position var(--_nav-label-fade-motion) 0ms, -webkit-mask-position var(--_nav-label-fade-motion) 0ms}.panel-nav__item-label-text.sc-ds-panel-nav{padding:0 var(--dimension-space-025, 2px)}.panel-nav__item-dot.sc-ds-panel-nav{position:absolute;right:13px;top:13px;width:var(--dimension-space-075, 6px);height:var(--dimension-space-075, 6px);border-radius:var(--dimension-radius-full, 999px);background:var(--_nav-dot);box-shadow:0 0 0 var(--dimension-stroke-width-018, 1.5px) var(--_nav-bg);pointer-events:none;transition:right var(--_nav-expand-motion), top var(--_nav-expand-motion), background var(--effect-motion-short-3, 200ms ease), box-shadow var(--effect-motion-short-3, 200ms ease)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__item-dot.sc-ds-panel-nav{right:6px;top:6px}.panel-nav--animating.sc-ds-panel-nav .panel-nav__item-label.sc-ds-panel-nav{text-overflow:clip}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__item-label.sc-ds-panel-nav{opacity:0;pointer-events:none;text-overflow:clip;mask-position:100% 0;-webkit-mask-position:100% 0;transition:opacity var(--_nav-label-fade-out-motion) 0ms, mask-position var(--_nav-label-fade-out-motion) 0ms, -webkit-mask-position var(--_nav-label-fade-out-motion) 0ms}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__group-label.sc-ds-panel-nav{opacity:0;max-height:0;padding:0 var(--dimension-space-075, 6px);pointer-events:none;transition:opacity var(--_nav-label-fade-out-motion) 0ms, max-height var(--_nav-label-fade-out-motion) 0ms, padding var(--_nav-label-fade-out-motion) 0ms, color var(--effect-motion-short-3, 200ms ease)}.panel-nav__footer.sc-ds-panel-nav{position:relative;flex-shrink:0;height:calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height));transition:height var(--_nav-expand-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer.sc-ds-panel-nav{height:calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height) * 2 + var(--dimension-space-050, 4px))}.panel-nav__footer.sc-ds-panel-nav::before{content:'';position:absolute;bottom:100%;left:0;right:0;height:calc(var(--dimension-base, 8px) * 6);background:linear-gradient(to bottom, transparent, var(--_nav-bg));pointer-events:none;opacity:1;transition:opacity var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease)}.panel-nav--at-bottom.sc-ds-panel-nav .panel-nav__footer.sc-ds-panel-nav::before{opacity:0}.panel-nav__footer-btn.sc-ds-panel-nav{all:unset;display:flex;align-items:center;justify-content:center;position:absolute;left:var(--_nav-padding-x);top:var(--_nav-padding-y);padding:var(--dimension-space-075, 6px);border-radius:var(--dimension-radius-half, 9999px);cursor:pointer;color:var(--_nav-fg-secondary);box-sizing:border-box;background:transparent;transition:background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease), color var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease)}.panel-nav__footer-btn.sc-ds-panel-nav:focus-visible{outline:var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);outline-offset:calc(-1 * var(--dimension-stroke-width-025, 2px))}.panel-nav--dashboard.sc-ds-panel-nav .panel-nav__footer-btn.sc-ds-panel-nav:hover{background:var(--color-background-secondary);color:var(--color-foreground-secondary);transition:none}.panel-nav--settings.sc-ds-panel-nav .panel-nav__footer-btn.sc-ds-panel-nav:hover{background:var(--color-navigation-background);color:var(--color-navigation-foreground-secondary);transition:none}.panel-nav__footer-user.sc-ds-panel-nav{position:absolute;left:calc(var(--_nav-padding-x) + var(--_nav-footer-btn-w) + var(--dimension-space-050, 4px));right:var(--_nav-padding-x);top:var(--_nav-padding-y);width:auto;min-width:0;transition:left var(--_nav-expand-motion), right var(--_nav-expand-motion), top var(--_nav-expand-motion), color var(--effect-motion-short-3, 200ms ease)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-user.sc-ds-panel-nav{left:var(--_nav-padding-x);right:var(--_nav-padding-x);top:calc(var(--_nav-padding-y) + var(--_nav-item-height) + var(--dimension-space-050, 4px))}.panel-nav__footer-user-label.sc-ds-panel-nav{text-align:right;position:absolute;left:var(--dimension-space-075, 6px);right:calc(var(--dimension-space-075, 6px) + var(--dimension-iconography-md, 20px) + var(--dimension-space-050, 4px));top:50%;transform:translateY(-50%);flex:none;height:var(--typography-lineheight-md, 20px);mask-image:none;-webkit-mask-image:none;transition:opacity var(--_nav-label-fade-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-user-label.sc-ds-panel-nav{opacity:0;pointer-events:none;mask-position:0% 0;-webkit-mask-position:0% 0}.panel-nav__footer-user-icon.sc-ds-panel-nav{position:absolute;left:calc(100% - var(--dimension-iconography-md, 20px) - var(--dimension-space-075, 6px));top:0;bottom:0;height:auto;display:flex;align-items:center;justify-content:center;transition:left var(--_nav-expand-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-user-icon.sc-ds-panel-nav{left:var(--dimension-space-075, 6px)}.panel-nav__footer-icon-expanded.sc-ds-panel-nav,.panel-nav__footer-icon-collapsed.sc-ds-panel-nav{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.panel-nav__footer-icon-expanded.sc-ds-panel-nav{opacity:1;transition:opacity var(--_nav-label-fade-motion)}.panel-nav__footer-icon-collapsed.sc-ds-panel-nav{opacity:0;transition:opacity var(--_nav-label-fade-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-icon-expanded.sc-ds-panel-nav{opacity:0;transition:opacity var(--_nav-label-fade-out-motion)}.panel-nav--collapsed.sc-ds-panel-nav .panel-nav__footer-icon-collapsed.sc-ds-panel-nav{opacity:1;transition:opacity var(--_nav-label-fade-out-motion)}.panel-nav__user-initial.sc-ds-panel-nav{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--_nav-fg-secondary);text-transform:uppercase;line-height:1;pointer-events:none;transition:color var(--effect-motion-short-3, 200ms ease)}.panel-nav__resize-handle.sc-ds-panel-nav{position:absolute;top:0;right:var(--dimension-space-n050, -4px);bottom:0;width:var(--dimension-space-100, 8px);z-index:10;cursor:ew-resize;touch-action:none;background:transparent}.panel-nav__resize-handle.sc-ds-panel-nav::before{content:'';position:absolute;inset:0;background:rgba(0, 0, 0, 0.001)}.panel-nav__resize-handle.sc-ds-panel-nav::after{content:'';position:absolute;top:0;bottom:0;left:50%;transform:translateX(-50%);width:var(--dimension-stroke-width-025, 2px);background:var(--color-background-bold-brand);opacity:0;pointer-events:none;transition:opacity var(--effect-motion-short-2, 100ms ease-in-out)}.panel-nav__resize-handle--overlay.sc-ds-panel-nav::after{opacity:1}@media (prefers-reduced-motion: reduce){.panel-nav.sc-ds-panel-nav,.panel-nav.sc-ds-panel-nav *.sc-ds-panel-nav,.panel-nav.sc-ds-panel-nav *.sc-ds-panel-nav::before,.panel-nav.sc-ds-panel-nav *.sc-ds-panel-nav::after,.panel-nav__resize-handle.sc-ds-panel-nav,.panel-nav__resize-handle.sc-ds-panel-nav::before,.panel-nav__resize-handle.sc-ds-panel-nav::after{transition-duration:0.01ms !important;animation-duration:0.01ms !important;transition-delay:0.01ms !important}}`;const f=new WeakMap;const m=new WeakMap;function u(a,e){const n=a.trim();const t=parseFloat(n);if(Number.isNaN(t))return e;if(/ms\s*$/.test(n))return t;if(/s\s*$/.test(n))return t*1e3;return t}const b=a(class a extends e{constructor(a){super();if(a!==false){this.__registerHost()}this.dsNavSelect=n(this,"dsNavSelect");this.dsNavToggle=n(this,"dsNavToggle");this.dsNavFooterAction=n(this,"dsNavFooterAction");this.dsNavUserAction=n(this,"dsNavUserAction");this.variant="dashboard";this.disableViewTransition=false;this.groups="[]";this.routerMode="anchor";this.activeId="";this.collapsed=false;this.breakpoint=0;this.storageKey="";this.currentUrl="";this.userName="";this.userInitial="";this.renderedVariant="dashboard";this.parsedGroups=[];this.atBottom=false;this.isAnimating=false;this.rovingIndex=0;this.viewportNarrow=false;this.urlDerivedActiveId="";this.isDragging=false;this.dragStartX=0;this.didSnap=false;this.lastDeltaX=0;this.edgeOverlayTimer=null;this.showEdgeOverlay=false}get effectiveActiveId(){return this.urlDerivedActiveId||this.activeId}onCollapsedChange(){this.startCollapseAnimation()}onBreakpointChange(){this.disconnectResizeObserver();if(this.breakpoint>0)this.connectResizeObserver()}onGroupsChange(a){this.parsedGroups=c(a);this.syncRovingIndex();this.syncActiveFromUrl()}onActiveIdChange(){this.syncRovingIndex()}onCurrentUrlChange(){this.syncActiveFromUrl()}async onVariantChange(a){if(this.disableViewTransition){this.renderedVariant=a;return}f.get(this)?.skipTransition();f.delete(this);const e=document;if(typeof e.startViewTransition!=="function"){this.renderedVariant=a;return}p();const n=this.el.querySelector(".panel-nav__footer-btn");const t=n?.getBoundingClientRect();const i=t?Math.round(t.left+t.width/2):Math.round(window.innerWidth/2);const o=t?Math.round(t.top+t.height/2):Math.round(window.innerHeight/2);const s=Math.ceil(Math.hypot(Math.max(i,window.innerWidth-i),Math.max(o,window.innerHeight-o)));document.documentElement.style.setProperty("--vt-x",`${i}px`);document.documentElement.style.setProperty("--vt-y",`${o}px`);const r=e.startViewTransition((()=>new Promise((e=>{m.set(this,e);this.renderedVariant=a}))));f.set(this,r);r.finished.finally((()=>{if(f.get(this)===r)f.delete(this);m.delete(this)}));r.ready.then((()=>{const a=getComputedStyle(document.documentElement).getPropertyValue("--effect-animation-duration-long-1").trim();const e=u(a,750);document.documentElement.animate({clipPath:[`circle(0px at ${i}px ${o}px)`,`circle(${s}px at ${i}px ${o}px)`]},{duration:e,easing:"ease-in-out",fill:"forwards",pseudoElement:"::view-transition-new(root)"})})).catch((()=>{}))}componentWillLoad(){this.renderedVariant=this.variant;if(this.storageKey){try{const a=localStorage.getItem(this.storageKey);if(a!==null)this.collapsed=a==="true"}catch{}}this.onGroupsChange(this.groups);this.syncActiveFromUrl()}componentDidLoad(){this.checkScroll();if(this.breakpoint>0)this.connectResizeObserver()}componentDidRender(){const a=m.get(this);if(a){m.delete(this);a()}}disconnectedCallback(){this.disconnectResizeObserver();this.clearEdgeOverlayTimer();if(this.globalMouseMoveHandler){window.removeEventListener("mousemove",this.globalMouseMoveHandler)}if(this.globalMouseUpHandler){window.removeEventListener("mouseup",this.globalMouseUpHandler)}}startCollapseAnimation(){this.isAnimating=true;const a=this.el.querySelector(".panel-nav");if(this.transitionEndHandler){a?.removeEventListener("transitionend",this.transitionEndHandler)}this.transitionEndHandler=e=>{if(e.propertyName==="width"){this.isAnimating=false;a?.removeEventListener("transitionend",this.transitionEndHandler)}};a?.addEventListener("transitionend",this.transitionEndHandler)}connectResizeObserver(){this.viewportNarrow=window.innerWidth<this.breakpoint;this.resizeObserver=new ResizeObserver((()=>{this.viewportNarrow=window.innerWidth<this.breakpoint}));this.resizeObserver.observe(document.documentElement)}disconnectResizeObserver(){this.resizeObserver?.disconnect();this.resizeObserver=undefined}syncActiveFromUrl(){if(!this.currentUrl){this.urlDerivedActiveId="";return}this.urlDerivedActiveId=l(this.currentUrl,this.getAllItems())}applyToggle(a){this.dsNavToggle.emit(a);if(this.storageKey){this.collapsed=a;try{localStorage.setItem(this.storageKey,String(a))}catch{}}}getAllItems(){return this.parsedGroups.flatMap((a=>a.items))}syncRovingIndex(){const a=this.getAllItems().findIndex((a=>a.id===this.effectiveActiveId));this.rovingIndex=a>=0?a:0}handleItemKeyDown(a,e){const n=this.getAllItems().length;let t;switch(a.key){case"ArrowDown":a.preventDefault();t=(e+1)%n;break;case"ArrowUp":a.preventDefault();t=(e-1+n)%n;break;case"Home":a.preventDefault();t=0;break;case"End":a.preventDefault();t=n-1;break;default:return}this.rovingIndex=t;const i=Array.from(this.el.querySelectorAll(".panel-nav__body .panel-nav__item"));i[t]?.focus()}checkScroll(){const a=this.el.querySelector(".panel-nav__body");if(!a)return;const e=a.scrollHeight-a.scrollTop-a.clientHeight;this.atBottom=e<2}handleBodyScroll(a){const e=a.target;const n=e.scrollHeight-e.scrollTop-e.clientHeight;this.atBottom=n<2}handleItemClick(a){this.dsNavSelect.emit(a)}handleToggle(){this.applyToggle(!this.collapsed)}handleFooterAction(){this.dsNavFooterAction.emit()}handleUserAction(){this.dsNavUserAction.emit()}clearEdgeOverlayTimer(){if(this.edgeOverlayTimer!==null){window.clearTimeout(this.edgeOverlayTimer);this.edgeOverlayTimer=null}}handleResizeHandleMouseEnter(){this.clearEdgeOverlayTimer();this.edgeOverlayTimer=window.setTimeout((()=>{this.showEdgeOverlay=true;this.edgeOverlayTimer=null}),500)}handleResizeHandleMouseLeave(){if(this.isDragging)return;this.clearEdgeOverlayTimer();this.showEdgeOverlay=false}handleResizeHandleMouseDown(a){a.preventDefault();a.stopPropagation();const e=this.collapsed||this.viewportNarrow;this.isDragging=true;this.dragStartX=a.clientX;this.didSnap=false;this.lastDeltaX=0;this.clearEdgeOverlayTimer();this.showEdgeOverlay=false;document.body.style.cursor="ew-resize";document.body.style.userSelect="none";const n=a=>{const n=a.clientX-this.dragStartX;this.lastDeltaX=Math.abs(n);if(this.didSnap)return;if(!e&&n<-8){this.applyToggle(true);this.didSnap=true}else if(e&&n>8){this.applyToggle(false);this.didSnap=true}};const t=()=>{if(!this.didSnap&&this.lastDeltaX<3){this.applyToggle(!e)}this.isDragging=false;this.showEdgeOverlay=false;document.body.style.cursor="";document.body.style.userSelect="";window.removeEventListener("mousemove",n);window.removeEventListener("mouseup",t);this.globalMouseMoveHandler=undefined;this.globalMouseUpHandler=undefined};this.globalMouseMoveHandler=n;this.globalMouseUpHandler=t;window.addEventListener("mousemove",n);window.addEventListener("mouseup",t)}renderNavItem(a,e,n){const i=a.id===this.effectiveActiveId;const o=[t("span",{class:"panel-nav__item-icon"},t("ds-icon",{name:a.icon,size:"md",color:"inherit",flag:a.flag})),t("span",{class:"panel-nav__item-label"},t("span",{class:"panel-nav__item-label-text"},t("ds-text",{as:"span",variant:i?"text-body-medium-emphasis":"text-body-medium",color:"inherit"},a.label))),a.dot&&t("span",{class:"panel-nav__item-dot","aria-hidden":"true"})];const s={class:{"panel-nav__item":true,"panel-nav__item--active":i},"aria-current":i?"page":undefined,title:n?a.label:undefined,tabIndex:e===this.rovingIndex?0:-1,onClick:()=>this.handleItemClick(a.id),onKeyDown:a=>this.handleItemKeyDown(a,e),onFocus:()=>{this.rovingIndex=e}};const r=this.routerMode==="anchor"&&a.href;return r?t("a",{...s,href:a.href},o):t("button",{...s,type:"button"},o)}render(){const a=this.renderedVariant==="dashboard";const e=this.collapsed||this.viewportNarrow;const{userName:n,userInitial:o}=this;const s={"panel-nav":true,"panel-nav--dashboard":a,"panel-nav--settings":!a,"panel-nav--collapsed":e,"panel-nav--animating":this.isAnimating,"panel-nav--at-bottom":this.atBottom};return t(i,{key:"75bb0d291cd86ec3eae2b9ccea8f793469b4be31",style:{display:"block",position:"relative"}},t("nav",{key:"ff8505395360bdbb7a9dbfd798da478d311c385c",class:s,"aria-label":a?"Main navigation":"Settings navigation"},t("div",{key:"acff3333081b70551dae34cd4f342fea13ab0e9b",class:"panel-nav__header"},t("button",{key:"625125b971d8b2f93af391a4838da27dc1c9f73d",type:"button",class:"panel-nav__header-btn",onClick:()=>this.handleToggle(),"aria-label":e?"Expand navigation":"Collapse navigation","aria-expanded":e?"false":"true"},t("span",{key:"7c65260ffe07903f988d27ee16a664ee27efabb6",class:"panel-nav__header-logo","aria-hidden":"true"},t("svg",{key:"92979f00985a081989ef6fc358105132216e2d62",class:"panel-nav__m-mark",viewBox:"0 0 20 20",fill:"none",xmlns:"http://www.w3.org/2000/svg",focusable:"false","aria-hidden":"true"},t("path",{key:"245c75d8bbd4635626c56c10652b2ef0f1422394",d:"M11.1159 4.31537H7.67021L2.53401 13.0703H0V15.6875H4.02716L8.24319 8.49978V15.6846H11.6342L15.8289 8.47829V15.6846H18.7122V4.3125H15.2559L11.1159 11.3648V4.31537Z",fill:"currentColor"}))),t("span",{key:"b4aee5f2b3bd518ebbdb8f77076c47ce3ec9eb2d",class:"panel-nav__header-toggle","aria-hidden":"true"},t("ds-icon",{key:"57866598644db254b503593c0e153506adb78f05",name:e?"LeftExpandB":"LeftCollapseB",size:"md",color:"inherit"})))),t("div",{key:"69bbbb451b9504bc6f75bef574fab34a2dc92ee2",class:"panel-nav__body",onScroll:a=>this.handleBodyScroll(a)},(()=>{let a=0;return this.parsedGroups.map((n=>t("div",{class:"panel-nav__group"},n.label&&t("span",{class:"panel-nav__group-label"},t("span",{class:"panel-nav__item-label-text"},t("ds-text",{as:"span",variant:"text-caption-emphasis",color:"inherit"},n.label))),n.items.map((n=>this.renderNavItem(n,a++,e))))))})()),t("div",{key:"586c6557c15251e1510106950ee1460149a20e6b",class:"panel-nav__footer"},t("button",{key:"48da25f162e689b66b97fb69cb51550226309c3f",type:"button",class:"panel-nav__footer-btn",title:a?"Settings":"Dashboard","aria-label":a?"Open settings":"Go to dashboard",onClick:()=>this.handleFooterAction()},t("ds-icon",{key:"b73353e1dd43d67b1733c94aab7bc83cbb004cfe",name:a?"Gear":"Dashboard",size:"md",color:"inherit"})),t("button",{key:"9bf1498f790784abc5c2e8c2c66e06f14e38b5ba",type:"button",class:"panel-nav__item panel-nav__footer-user","aria-label":e?`User: ${n}`:`User menu for ${n}`,onClick:()=>this.handleUserAction()},t("span",{key:"f2d084429e7e68dba7856739892335b3657bf64e",class:"panel-nav__item-label panel-nav__footer-user-label"},t("span",{key:"b94ac406ca7f0de5fa695c0c348cd06e4c56f6a4",class:"panel-nav__item-label-text"},t("ds-text",{key:"30f3f044f5f234fbe896f8e304c62e6d15f0967a",as:"span",variant:"text-body-medium-emphasis",color:"inherit"},n))),t("span",{key:"3fc742d82ee1f0478b8be976b6fbcad87d75d58b",class:"panel-nav__item-icon panel-nav__footer-user-icon","aria-hidden":"true"},t("span",{key:"94d16279915843a6d9664b6909cd50701f4175db",class:"panel-nav__footer-icon-expanded"},t("ds-icon",{key:"b3de58f2e93b7473efcefb2cfa1148c194594271",name:"ChevronUpDown",size:"md",color:"inherit"})),t("span",{key:"01b6c5720f4d97f01fd0ff738b709def6ba1c998",class:"panel-nav__footer-icon-collapsed"},t("ds-icon",{key:"1958490bb8c7b9d02b23759e4db00649b02716e7",name:"Circle",size:"md",color:"inherit"}),t("span",{key:"d70d6528f5ae27be803a7ead80f86e9ce48e2d5d",class:"panel-nav__user-initial"},t("ds-text",{key:"34a0616c5adad854873d79b6582c9ac97fe43eda",as:"span",variant:"text-caption-emphasis",color:"inherit"},o))))))),!this.viewportNarrow&&t("div",{key:"9b97c0b48d2c39e90dd02a09f8d58ac0dddd4979",class:{"panel-nav__resize-handle":true,"panel-nav__resize-handle--overlay":this.showEdgeOverlay},onMouseEnter:()=>this.handleResizeHandleMouseEnter(),onMouseLeave:()=>this.handleResizeHandleMouseLeave(),onMouseDown:a=>this.handleResizeHandleMouseDown(a),"aria-hidden":"true"}))}get el(){return this}static get watchers(){return{collapsed:[{onCollapsedChange:0}],viewportNarrow:[{onCollapsedChange:0}],breakpoint:[{onBreakpointChange:0}],groups:[{onGroupsChange:0}],activeId:[{onActiveIdChange:0}],urlDerivedActiveId:[{onActiveIdChange:0}],currentUrl:[{onCurrentUrlChange:0}],variant:[{onVariantChange:0}]}}static get style(){return h()}},[2,"ds-panel-nav",{variant:[1],disableViewTransition:[4,"disable-view-transition"],groups:[1],routerMode:[1,"router-mode"],activeId:[1,"active-id"],collapsed:[1028],breakpoint:[2],storageKey:[1,"storage-key"],currentUrl:[1,"current-url"],userName:[1,"user-name"],userInitial:[1,"user-initial"],renderedVariant:[32],parsedGroups:[32],atBottom:[32],isAnimating:[32],rovingIndex:[32],viewportNarrow:[32],urlDerivedActiveId:[32],showEdgeOverlay:[32]},undefined,{collapsed:[{onCollapsedChange:0}],viewportNarrow:[{onCollapsedChange:0}],breakpoint:[{onBreakpointChange:0}],groups:[{onGroupsChange:0}],activeId:[{onActiveIdChange:0}],urlDerivedActiveId:[{onActiveIdChange:0}],currentUrl:[{onCurrentUrlChange:0}],variant:[{onVariantChange:0}]}]);function _(){if(typeof customElements==="undefined"){return}const a=["ds-panel-nav","ds-icon","ds-text"];a.forEach((a=>{switch(a){case"ds-panel-nav":if(!customElements.get(o(a))){customElements.define(o(a),b)}break;case"ds-icon":if(!customElements.get(o(a))){s()}break;case"ds-text":if(!customElements.get(o(a))){r()}break}}))}_();const g=b;const x=_;export{g as DsPanelNav,x as defineCustomElement};
|
|
2
2
|
//# sourceMappingURL=ds-panel-nav.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["panelNavCss","vtStyleInjected","vtTransitions","WeakMap","vtResolvers","ensureVtStyle","id","document","getElementById","style","createElement","textContent","join","head","appendChild","parseCssTimeMs","value","fallback","v","trim","num","parseFloat","Number","isNaN","test","PanelNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","variant","disableViewTransition","groups","activeId","collapsed","breakpoint","storageKey","currentUrl","userName","userInitial","renderedVariant","parsedGroups","atBottom","isAnimating","rovingIndex","viewportNarrow","urlDerivedActiveId","isDragging","dragStartX","didSnap","lastDeltaX","edgeOverlayTimer","showEdgeOverlay","effectiveActiveId","onCollapsedChange","startCollapseAnimation","onBreakpointChange","disconnectResizeObserver","connectResizeObserver","onGroupsChange","val","JSON","parse","syncRovingIndex","onActiveIdChange","onCurrentUrlChange","syncActiveFromUrl","onVariantChange","newVal","get","skipTransition","delete","doc","startViewTransition","btn","el","querySelector","rect","getBoundingClientRect","x","Math","round","left","width","window","innerWidth","y","top","height","innerHeight","maxR","ceil","hypot","max","documentElement","setProperty","transition","Promise","resolve","set","finished","finally","ready","then","durToken","getComputedStyle","getPropertyValue","duration","animate","clipPath","easing","fill","pseudoElement","catch","componentWillLoad","stored","localStorage","getItem","componentDidLoad","checkScroll","componentDidRender","disconnectedCallback","clearEdgeOverlayTimer","globalMouseMoveHandler","removeEventListener","globalMouseUpHandler","panel","transitionEndHandler","e","propertyName","addEventListener","resizeObserver","ResizeObserver","observe","disconnect","undefined","best","bestLen","item","getAllItems","href","startsWith","length","applyToggle","next","dsNavToggle","emit","setItem","String","flatMap","g","items","idx","findIndex","i","handleItemKeyDown","index","total","key","preventDefault","Array","from","querySelectorAll","focus","body","remaining","scrollHeight","scrollTop","clientHeight","handleBodyScroll","target","handleItemClick","dsNavSelect","handleToggle","handleFooterAction","dsNavFooterAction","clearTimeout","handleResizeHandleMouseEnter","setTimeout","handleResizeHandleMouseLeave","handleResizeHandleMouseDown","stopPropagation","wasCollapsed","clientX","cursor","userSelect","onMove","ev","deltaX","abs","onUp","renderNavItem","isActive","itemContent","h","class","name","icon","size","color","flag","as","label","dot","sharedProps","title","tabIndex","onClick","onKeyDown","onFocus","type","render","isDashboard","navCls","Host","display","position","viewBox","xmlns","focusable","d","onScroll","flatIdx","map","group","onMouseEnter","onMouseLeave","onMouseDown"],"sources":["src/wc/components/PanelNav/PanelNav.css?tag=ds-panel-nav&encapsulation=scoped","src/wc/components/PanelNav/PanelNav.tsx"],"sourcesContent":["/* ── Theme variables ──────────────────────────────────────────────────────── */\n\n.panel-nav {\n /* ─ Sizes ─ */\n --_nav-width: 200px;\n --_nav-width-collapsed: 48px;\n --_nav-item-height: var(--dimension-size-400, 32px);\n --_nav-padding-x: var(--dimension-space-100, 8px);\n --_nav-padding-y: var(--dimension-space-100, 8px);\n /* gear button outer width = padding*2 + icon */\n --_nav-footer-btn-w: calc(var(--dimension-space-075, 6px) * 2 + var(--dimension-iconography-md, 20px));\n\n /* ─ Motion ─ */\n /* --ds-panel-nav-speed: unitless multiplier; override in Storybook to slow-mo (e.g. 10 = 10×).\n *-dur vars are duration-only (needed for calc); *-motion vars add easing for use in transitions. */\n --_nav-speed: var(--ds-panel-nav-speed, 1);\n --_nav-expand-dur: calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));\n --_nav-expand-motion: var(--_nav-expand-dur) var(--effect-animation-easing-ease-in-out, ease);\n --_nav-label-fade-dur: calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));\n --_nav-label-fade-motion: var(--_nav-label-fade-dur) var(--effect-animation-easing-ease-in-out, ease);\n --_nav-label-fade-out-dur: calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));\n --_nav-label-fade-out-motion: var(--_nav-label-fade-out-dur) var(--effect-animation-easing-ease-in-out, ease);\n\n /* ─ Colours – dashboard defaults ─ */\n --_nav-bg: var(--color-navigation-background);\n --_nav-border: var(--color-navigation-border-tertiary);\n --_nav-divider: var(--color-navigation-divider);\n --_nav-fg-primary: var(--color-navigation-foreground-primary);\n --_nav-fg-secondary: var(--color-navigation-foreground-secondary);\n --_nav-fg-tertiary: var(--color-navigation-foreground-tertiary);\n --_nav-hover: var(--color-navigation-interaction-hover);\n --_nav-pressed: var(--color-navigation-interaction-pressed);\n --_nav-focus: var(--color-navigation-interaction-focus);\n --_nav-dot: var(--color-navigation-foreground-brand);\n}\n\n/* ── Settings overrides ──────────────────────────────────────────────────── */\n\n.panel-nav--settings {\n --_nav-bg: var(--color-background-secondary);\n --_nav-border: var(--color-border-tertiary);\n --_nav-divider: var(--color-border-tertiary);\n --_nav-fg-primary: var(--color-foreground-primary);\n --_nav-fg-secondary: var(--color-foreground-secondary);\n --_nav-fg-tertiary: var(--color-foreground-tertiary);\n --_nav-hover: var(--color-interaction-hover);\n --_nav-pressed: var(--color-interaction-pressed);\n --_nav-focus: var(--color-interaction-focus);\n --_nav-dot: var(--color-foreground-bold-brand);\n}\n\n/* ── Shell ───────────────────────────────────────────────────────────────── */\n\n.panel-nav {\n display: flex;\n flex-direction: column;\n width: var(--_nav-width);\n min-width: var(--_nav-width);\n height: 100%;\n background: var(--_nav-bg);\n border-right: var(--dimension-stroke-width-012, 1px) solid var(--_nav-border);\n box-sizing: border-box;\n overflow: hidden;\n transition:\n width var(--_nav-expand-motion),\n min-width var(--_nav-expand-motion),\n background var(--effect-motion-short-3, 200ms ease),\n border-color var(--effect-motion-short-3, 200ms ease);\n font-family: var(--typography-font-family, system-ui);\n}\n\n.panel-nav--collapsed {\n width: var(--_nav-width-collapsed);\n min-width: var(--_nav-width-collapsed);\n}\n\n/* ── Header ──────────────────────────────────────────────────────────────── */\n\n.panel-nav__header {\n display: flex;\n align-items: center;\n height: var(--dimension-size-600, 48px);\n padding: var(--dimension-space-100, 8px);\n flex-shrink: 0;\n box-sizing: border-box;\n border-bottom: var(--dimension-stroke-width-012, 1px) solid var(--_nav-divider);\n transition: border-color var(--effect-motion-short-3, 200ms ease);\n}\n\n.panel-nav__header-btn {\n all: unset;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-075, 6px);\n border-radius: var(--dimension-radius-025, 2px);\n cursor: pointer;\n color: var(--_nav-fg-primary);\n position: relative;\n flex-shrink: 0;\n box-sizing: border-box;\n transition: color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* Interaction pseudo-element */\n.panel-nav__header-btn::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: var(--dimension-radius-025, 2px);\n background: transparent;\n transition: background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n pointer-events: none;\n}\n\n.panel-nav__header-btn:hover::after { background: var(--_nav-hover); transition: none; }\n.panel-nav__header-btn:active::after { background: var(--_nav-pressed); transition: none; }\n.panel-nav__header-btn:focus-visible { outline: none; }\n.panel-nav__header-btn:focus-visible::after {\n outline: var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);\n outline-offset: calc(-1 * var(--dimension-stroke-width-025, 2px));\n}\n\n/* Logo — visible by default, hidden on hover */\n.panel-nav__header-logo {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n z-index: 1;\n transition: opacity var(--effect-motion-short-2, 100ms ease);\n}\n\n.panel-nav__m-mark {\n width: var(--dimension-iconography-md, 20px);\n height: var(--dimension-iconography-md, 20px);\n display: block;\n}\n\n/* Toggle icon — hidden by default, revealed on hover */\n.panel-nav__header-toggle {\n display: none;\n align-items: center;\n justify-content: center;\n position: absolute;\n inset: 0;\n z-index: 1;\n}\n\n.panel-nav__header-btn:hover .panel-nav__header-logo { opacity: 0; }\n.panel-nav__header-btn:hover .panel-nav__header-toggle { display: flex; }\n\n/* ── Scrollable body ─────────────────────────────────────────────────────── */\n\n.panel-nav__body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-200, 16px);\n padding: var(--dimension-space-100, 8px);\n box-sizing: border-box;\n scrollbar-width: none;\n}\n\n.panel-nav__body::-webkit-scrollbar { display: none; }\n\n/* ── Group ───────────────────────────────────────────────────────────────── */\n\n.panel-nav__group {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050, 4px);\n}\n\n.panel-nav__group-label {\n /* Typography via ds-text (text-caption-emphasis) */\n display: flex;\n align-items: center;\n text-transform: uppercase;\n color: var(--_nav-fg-secondary);\n user-select: none;\n height: var(--dimension-size-300, 24px);\n line-height: var(--typography-lineheight-xs, 12px);\n padding: 0 var(--dimension-space-075, 6px);\n white-space: nowrap;\n overflow: hidden;\n max-height: var(--dimension-size-300, 24px);\n opacity: 1;\n transition:\n opacity var(--_nav-label-fade-motion) 0ms,\n max-height var(--_nav-label-fade-motion) 0ms,\n padding var(--_nav-label-fade-motion) 0ms,\n color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* ── Item ────────────────────────────────────────────────────────────────── */\n\n.panel-nav__item {\n all: unset;\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050, 4px);\n padding: 0 var(--dimension-space-075, 6px);\n height: var(--dimension-size-400, 32px);\n border-radius: var(--dimension-radius-025, 2px);\n cursor: pointer;\n color: var(--_nav-fg-secondary);\n position: relative;\n box-sizing: border-box;\n width: 100%;\n user-select: none;\n transition: color var(--effect-motion-short-1, 50ms ease-in-out);\n}\n\n/* Interaction layer */\n.panel-nav__item::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: background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n}\n\n.panel-nav__item:hover::after { background: var(--_nav-hover); transition: none; }\n.panel-nav__item:active::after { background: var(--_nav-pressed); transition: none; }\n.panel-nav__item:focus-visible { outline: none; }\n.panel-nav__item:focus-visible::after {\n outline: var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);\n outline-offset: calc(-1 * var(--dimension-stroke-width-025, 2px));\n}\n\n/* ── Active item ─────────────────────────────────────────────────────────── */\n\n.panel-nav__item--active {\n color: var(--_nav-fg-primary);\n /* Bold typography via ds-text (text-body-medium-emphasis) on the label */\n}\n\n/* ── Item icon ───────────────────────────────────────────────────────────── */\n\n.panel-nav__item-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--dimension-iconography-md, 20px);\n height: var(--dimension-iconography-md, 20px);\n position: relative;\n}\n\n/* ── Item label ──────────────────────────────────────────────────────────── */\n\n.panel-nav__item-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n height: var(--typography-lineheight-md, 20px);\n line-height: var(--typography-lineheight-md, 20px);\n opacity: 1;\n /* Gradient wipe: mask sweeps left-to-right on expand, right-to-left on collapse */\n mask-image: linear-gradient(to right, black 50%, transparent 100%);\n -webkit-mask-image: linear-gradient(to right, black 50%, transparent 100%);\n mask-size: 200% 100%;\n -webkit-mask-size: 200% 100%;\n mask-position: 0% 0;\n -webkit-mask-position: 0% 0;\n transition:\n opacity var(--_nav-label-fade-motion) 0ms,\n mask-position var(--_nav-label-fade-motion) 0ms,\n -webkit-mask-position var(--_nav-label-fade-motion) 0ms;\n}\n\n.panel-nav__item-label-text {\n padding: 0 var(--dimension-space-025, 2px);\n}\n\n/* ── Item notification dot — single element, moves between positions ──────── */\n\n.panel-nav__item-dot {\n position: absolute;\n right: 13px;\n top: 13px;\n width: var(--dimension-space-075, 6px);\n height: var(--dimension-space-075, 6px);\n border-radius: var(--dimension-radius-full, 999px);\n background: var(--_nav-dot);\n box-shadow: 0 0 0 var(--dimension-stroke-width-018, 1.5px) var(--_nav-bg);\n pointer-events: none;\n transition:\n right var(--_nav-expand-motion),\n top var(--_nav-expand-motion),\n background var(--effect-motion-short-3, 200ms ease),\n box-shadow var(--effect-motion-short-3, 200ms ease);\n}\n\n.panel-nav--collapsed .panel-nav__item-dot {\n right: 6px;\n top: 6px;\n}\n\n.panel-nav--animating .panel-nav__item-label {\n text-overflow: clip;\n}\n\n.panel-nav--collapsed .panel-nav__item-label {\n opacity: 0;\n pointer-events: none;\n text-overflow: clip;\n mask-position: 100% 0;\n -webkit-mask-position: 100% 0;\n transition:\n opacity var(--_nav-label-fade-out-motion) 0ms,\n mask-position var(--_nav-label-fade-out-motion) 0ms,\n -webkit-mask-position var(--_nav-label-fade-out-motion) 0ms;\n}\n\n.panel-nav--collapsed .panel-nav__group-label {\n opacity: 0;\n max-height: 0;\n padding: 0 var(--dimension-space-075, 6px);\n pointer-events: none;\n transition:\n opacity var(--_nav-label-fade-out-motion) 0ms,\n max-height var(--_nav-label-fade-out-motion) 0ms,\n padding var(--_nav-label-fade-out-motion) 0ms,\n color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* ── Footer ──────────────────────────────────────────────────────────────── */\n\n.panel-nav__footer {\n position: relative;\n flex-shrink: 0;\n /* single row: padding*2 + item */\n height: calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height));\n transition: height var(--_nav-expand-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer {\n /* two rows: padding*2 + item*2 + gap */\n height: calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height) * 2 + var(--dimension-space-050, 4px));\n}\n\n/* Gradient fade — floats above the footer, masks content scrolling under it */\n.panel-nav__footer::before {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 0;\n right: 0;\n height: calc(var(--dimension-base, 8px) * 6);\n background: linear-gradient(to bottom, transparent, var(--_nav-bg));\n pointer-events: none;\n opacity: 1;\n transition: opacity var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n}\n\n.panel-nav--at-bottom .panel-nav__footer::before {\n opacity: 0;\n}\n\n/* ── Footer icon button (gear / dashboard) ───────────────────────────────── */\n\n.panel-nav__footer-btn {\n all: unset;\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n left: var(--_nav-padding-x);\n top: var(--_nav-padding-y);\n padding: var(--dimension-space-075, 6px);\n border-radius: var(--dimension-radius-half, 9999px);\n cursor: pointer;\n color: var(--_nav-fg-secondary);\n box-sizing: border-box;\n background: transparent;\n transition:\n background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease),\n color var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n}\n\n.panel-nav__footer-btn:focus-visible {\n outline: var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);\n outline-offset: calc(-1 * var(--dimension-stroke-width-025, 2px));\n}\n\n/* Dashboard: hover previews settings surface */\n.panel-nav--dashboard .panel-nav__footer-btn:hover {\n background: var(--color-background-secondary);\n color: var(--color-foreground-secondary);\n transition: none;\n}\n\n/* Settings: hover previews dashboard nav surface */\n.panel-nav--settings .panel-nav__footer-btn:hover {\n background: var(--color-navigation-background);\n color: var(--color-navigation-foreground-secondary);\n transition: none;\n}\n\n/* ── Footer user — absolutely positioned, slides from row to below gear ───── */\n\n.panel-nav__footer-user {\n position: absolute;\n /* row position: right of gear button */\n left: calc(var(--_nav-padding-x) + var(--_nav-footer-btn-w) + var(--dimension-space-050, 4px));\n right: var(--_nav-padding-x);\n top: var(--_nav-padding-y);\n width: auto;\n min-width: 0;\n transition:\n left var(--_nav-expand-motion),\n right var(--_nav-expand-motion),\n top var(--_nav-expand-motion),\n color var(--effect-motion-short-3, 200ms ease);\n}\n\n.panel-nav--collapsed .panel-nav__footer-user {\n /* column position: full-width row below gear */\n left: var(--_nav-padding-x);\n right: var(--_nav-padding-x);\n top: calc(var(--_nav-padding-y) + var(--_nav-item-height) + var(--dimension-space-050, 4px));\n}\n\n/* Label: absolute so it stays in place and only fades — no mask slide */\n.panel-nav__footer-user-label {\n text-align: right;\n position: absolute;\n left: var(--dimension-space-075, 6px);\n right: calc(var(--dimension-space-075, 6px) + var(--dimension-iconography-md, 20px) + var(--dimension-space-050, 4px));\n top: 50%;\n transform: translateY(-50%);\n flex: none;\n height: var(--typography-lineheight-md, 20px);\n mask-image: none;\n -webkit-mask-image: none;\n transition: opacity var(--_nav-label-fade-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-user-label {\n opacity: 0;\n pointer-events: none;\n mask-position: 0% 0;\n -webkit-mask-position: 0% 0;\n}\n\n/* ── Footer user icon — cross-fades chevron ↔ circle+initial ────────────── */\n\n/* Absolute — right-anchored in expanded, left-anchored in collapsed to match regular item icon position */\n.panel-nav__footer-user-icon {\n position: absolute;\n left: calc(100% - var(--dimension-iconography-md, 20px) - var(--dimension-space-075, 6px));\n top: 0;\n bottom: 0;\n height: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: left var(--_nav-expand-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-user-icon {\n left: var(--dimension-space-075, 6px);\n}\n\n.panel-nav__footer-icon-expanded,\n.panel-nav__footer-icon-collapsed {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.panel-nav__footer-icon-expanded {\n opacity: 1;\n transition: opacity var(--_nav-label-fade-motion);\n}\n\n.panel-nav__footer-icon-collapsed {\n opacity: 0;\n transition: opacity var(--_nav-label-fade-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-icon-expanded {\n opacity: 0;\n transition: opacity var(--_nav-label-fade-out-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-icon-collapsed {\n opacity: 1;\n transition: opacity var(--_nav-label-fade-out-motion);\n}\n\n/* ── User initial — overlaid on the circle icon ─────────────────────────── */\n\n.panel-nav__user-initial {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--_nav-fg-secondary);\n text-transform: uppercase;\n line-height: 1;\n pointer-events: none;\n transition: color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* ── Drag-to-resize handle ───────────────────────────────────────────────── */\n\n.panel-nav__resize-handle {\n position: absolute;\n top: 0;\n /* Centered on the right edge: --dimension-space-050 outside + inside = --dimension-space-100 hit zone */\n right: var(--dimension-space-n050, -4px);\n bottom: 0;\n width: var(--dimension-space-100, 8px);\n z-index: 10;\n cursor: ew-resize;\n touch-action: none;\n /* Needs a real background for Safari hit-testing */\n background: transparent;\n}\n\n/* Safari requires non-transparent fill for hit testing */\n.panel-nav__resize-handle::before {\n content: '';\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.001);\n}\n\n/* The brand-bold overlay line */\n.panel-nav__resize-handle::after {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n width: var(--dimension-stroke-width-025, 2px);\n background: var(--color-background-bold-brand);\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--effect-motion-short-2, 100ms ease-in-out);\n}\n\n.panel-nav__resize-handle--overlay::after {\n opacity: 1;\n}\n\n/* ── Reduced motion ──────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .panel-nav,\n .panel-nav *,\n .panel-nav *::before,\n .panel-nav *::after,\n .panel-nav__resize-handle,\n .panel-nav__resize-handle::before,\n .panel-nav__resize-handle::after {\n transition-duration: 0.01ms !important;\n animation-duration: 0.01ms !important;\n transition-delay: 0.01ms !important;\n }\n}\n","import { Component, Prop, Event, EventEmitter, Watch, State, Element, h, Host } from '@stencil/core';\n\n// Injected once per document to suppress the browser default cross-fade and\n// pin the new-state snapshot to a 0px circle so the WAAPI reveal has no flash.\nlet vtStyleInjected = false;\n\n// Module-level WeakMaps for per-instance VT state. Using WeakMaps instead of\n// class fields avoids Stencil generating getter-only property descriptors on\n// the host element for private fields, which throws in strict environments.\n// Minimal typings for the View Transitions API, which isn't in our TS lib target.\ninterface ViewTransition {\n finished: Promise<void>;\n skipTransition: () => void;\n}\ntype DocumentWithViewTransition = Document & {\n startViewTransition?: (callback: () => void | Promise<void>) => ViewTransition;\n};\n\nconst vtTransitions = new WeakMap<object, ViewTransition>();\nconst vtResolvers = new WeakMap<object, () => void>();\nfunction ensureVtStyle() {\n if (vtStyleInjected) return;\n const id = 'ds-panel-nav-vt-style';\n if (document.getElementById(id)) { vtStyleInjected = true; return; }\n const style = document.createElement('style');\n style.id = id;\n style.textContent = [\n '::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal}',\n '::view-transition-new(root){clip-path:circle(0px at var(--vt-x,50%) var(--vt-y,50%))}',\n ].join('\\n');\n document.head.appendChild(style);\n vtStyleInjected = true;\n}\n\n/** Parse a CSS <time> value to milliseconds. Handles `s`, `ms`, and unitless\n * (assumed ms). Critically: `parseFloat('.75s')` is 0.75 — WAAPI treats that as\n * 0.75ms (instant/invisible), so the `s` unit must be scaled to ms. Design\n * tokens (e.g. `--effect-animation-duration-long-1`) are authored in seconds. */\nfunction parseCssTimeMs(value: string, fallback: number): number {\n const v = value.trim();\n const num = parseFloat(v);\n if (Number.isNaN(num)) return fallback;\n if (/ms\\s*$/.test(v)) return num;\n if (/s\\s*$/.test(v)) return num * 1000;\n return num;\n}\n\nexport type PanelNavVariant = 'dashboard' | 'settings';\n\nexport interface PanelNavItem {\n id: string;\n icon: string;\n label: string;\n /** Show a notification dot badge on the item */\n dot?: boolean;\n flag?: boolean;\n /** When set, the item renders as an `<a>` element so any router that\n * intercepts anchor clicks (Angular Router, React Router, etc.) handles\n * navigation automatically. `dsNavSelect` still fires on click. */\n href?: string;\n}\n\nexport interface PanelNavGroup {\n id?: string;\n label?: string;\n items: PanelNavItem[];\n}\n\n@Component({\n tag: 'ds-panel-nav',\n styleUrl: 'PanelNav.css',\n scoped: true,\n})\nexport class PanelNav {\n /** Visual variant: `dashboard` = always-dark surface, `settings` = light surface */\n @Prop() variant: PanelNavVariant = 'dashboard';\n\n /** When `true`, the component does not run its own View Transition on variant\n * change — it just updates the rendered surface synchronously. Use this when\n * the host app orchestrates the page transition itself (e.g. Angular Router's\n * `withViewTransitions`), so the two don't fight or nest. */\n @Prop() disableViewTransition: boolean = false;\n\n /** JSON string of `PanelNavGroup[]` */\n @Prop() groups: string = '[]';\n\n /** ID of the currently active/selected nav item. Overridden by `currentUrl` matching when set. */\n @Prop() activeId: string = '';\n\n /** Whether the nav is in collapsed (icon-only) state.\n * When `storageKey` is set the component manages this internally —\n * do not also bind it from outside in that mode. */\n @Prop({ mutable: true }) collapsed: boolean = false;\n\n /** Viewport width (px) below which the nav auto-collapses to icon-only mode. 0 = disabled. */\n @Prop() breakpoint: number = 0;\n\n /** `localStorage` key used to persist the collapsed state across page loads.\n * When set the component is self-managing for collapsed state; `dsNavToggle`\n * still fires for consumers that want to observe the change. */\n @Prop() storageKey: string = '';\n\n /** Current route URL (e.g. `window.location.pathname` or the router's active URL).\n * When set the component derives the active item by matching item `href` values\n * against this string (longest prefix wins), overriding `activeId`. */\n @Prop() currentUrl: string = '';\n\n /** Display name for the footer user section */\n @Prop() userName: string = '';\n\n /** Single character shown in the collapsed avatar */\n @Prop() userInitial: string = '';\n\n /** Emitted when a nav item is clicked. Detail = the item's `id`. */\n @Event() dsNavSelect!: EventEmitter<string>;\n\n /** Emitted when the collapse toggle is clicked. Detail = new collapsed state. */\n @Event() dsNavToggle!: EventEmitter<boolean>;\n\n /** Emitted when the footer left button (gear / dashboard) is clicked. */\n @Event() dsNavFooterAction!: EventEmitter<void>;\n\n @Element() el!: HTMLElement;\n\n /** Mirrors `variant` but is only updated inside the VT callback so the\n * View Transition captures a clean before/after snapshot. */\n @State() private renderedVariant: PanelNavVariant = 'dashboard';\n\n @State() private parsedGroups: PanelNavGroup[] = [];\n @State() private atBottom = false;\n @State() private isAnimating = false;\n @State() private rovingIndex: number = 0;\n @State() private viewportNarrow: boolean = false;\n @State() private urlDerivedActiveId: string = '';\n\n private transitionEndHandler?: (e: TransitionEvent) => void;\n private resizeObserver?: ResizeObserver;\n\n // Drag-to-resize state (not @State — no re-render needed)\n private isDragging = false;\n private dragStartX = 0;\n private didSnap = false;\n private lastDeltaX = 0;\n private edgeOverlayTimer: number | null = null;\n private globalMouseMoveHandler?: (e: MouseEvent) => void;\n private globalMouseUpHandler?: () => void;\n\n @State() private showEdgeOverlay = false;\n\n /** The ID that should be treated as active. `currentUrl` matching takes precedence\n * over `activeId` when both are present. */\n private get effectiveActiveId(): string {\n return this.urlDerivedActiveId || this.activeId;\n }\n\n @Watch('collapsed')\n @Watch('viewportNarrow')\n onCollapsedChange() {\n this.startCollapseAnimation();\n }\n\n @Watch('breakpoint')\n onBreakpointChange() {\n this.disconnectResizeObserver();\n if (this.breakpoint > 0) this.connectResizeObserver();\n }\n\n @Watch('groups')\n onGroupsChange(val: string) {\n try {\n this.parsedGroups = JSON.parse(val);\n } catch {\n this.parsedGroups = [];\n }\n this.syncRovingIndex();\n }\n\n @Watch('activeId')\n @Watch('urlDerivedActiveId')\n onActiveIdChange() {\n this.syncRovingIndex();\n }\n\n @Watch('currentUrl')\n onCurrentUrlChange() {\n this.syncActiveFromUrl();\n }\n\n @Watch('variant')\n async onVariantChange(newVal: PanelNavVariant) {\n // Host app drives the transition (e.g. Angular Router withViewTransitions):\n // just reflect the new surface so the app's transition captures it.\n if (this.disableViewTransition) {\n this.renderedVariant = newVal;\n return;\n }\n\n // Skip any in-progress transition immediately so rapid variant changes\n // (e.g. quick dashboard → settings → dashboard) never leave the nav stuck.\n vtTransitions.get(this)?.skipTransition();\n vtTransitions.delete(this);\n\n const doc = document as DocumentWithViewTransition;\n if (typeof doc.startViewTransition !== 'function') {\n this.renderedVariant = newVal;\n return;\n }\n\n ensureVtStyle();\n\n const btn = this.el.querySelector('.panel-nav__footer-btn') as HTMLElement | null;\n const rect = btn?.getBoundingClientRect();\n const x = rect ? Math.round(rect.left + rect.width / 2) : Math.round(window.innerWidth / 2);\n const y = rect ? Math.round(rect.top + rect.height / 2) : Math.round(window.innerHeight / 2);\n const maxR = Math.ceil(Math.hypot(\n Math.max(x, window.innerWidth - x),\n Math.max(y, window.innerHeight - y),\n ));\n\n document.documentElement.style.setProperty('--vt-x', `${x}px`);\n document.documentElement.style.setProperty('--vt-y', `${y}px`);\n\n const transition = doc.startViewTransition(() =>\n new Promise<void>(resolve => {\n vtResolvers.set(this, resolve);\n this.renderedVariant = newVal;\n })\n );\n\n vtTransitions.set(this, transition);\n transition.finished.finally(() => {\n if (vtTransitions.get(this) === transition) vtTransitions.delete(this);\n vtResolvers.delete(this);\n });\n\n transition.ready.then(() => {\n const durToken = getComputedStyle(document.documentElement)\n .getPropertyValue('--effect-animation-duration-long-1').trim();\n const duration = parseCssTimeMs(durToken, 750);\n document.documentElement.animate(\n { clipPath: [`circle(0px at ${x}px ${y}px)`, `circle(${maxR}px at ${x}px ${y}px)`] },\n { duration, easing: 'ease-in-out', fill: 'forwards', pseudoElement: '::view-transition-new(root)' },\n );\n }).catch(() => { /* transition was skipped or aborted */ });\n }\n\n componentWillLoad() {\n this.renderedVariant = this.variant;\n if (this.storageKey) {\n try {\n const stored = localStorage.getItem(this.storageKey);\n if (stored !== null) this.collapsed = stored === 'true';\n } catch { /* localStorage unavailable */ }\n }\n this.onGroupsChange(this.groups);\n this.syncActiveFromUrl();\n }\n\n componentDidLoad() {\n this.checkScroll();\n if (this.breakpoint > 0) this.connectResizeObserver();\n // Re-sync groups in case componentWillLoad ran before host bindings were applied\n // (common with Angular's property binding timing)\n this.onGroupsChange(this.groups);\n }\n\n componentDidRender() {\n // If a view transition callback is waiting for the render to complete,\n // resolve it now so the \"after\" snapshot is taken at exactly the right moment.\n const resolve = vtResolvers.get(this);\n if (resolve) {\n vtResolvers.delete(this);\n resolve();\n }\n }\n\n disconnectedCallback() {\n this.disconnectResizeObserver();\n this.clearEdgeOverlayTimer();\n if (this.globalMouseMoveHandler) {\n window.removeEventListener('mousemove', this.globalMouseMoveHandler);\n }\n if (this.globalMouseUpHandler) {\n window.removeEventListener('mouseup', this.globalMouseUpHandler);\n }\n }\n\n private startCollapseAnimation() {\n this.isAnimating = true;\n const panel = this.el.querySelector('.panel-nav') as HTMLElement | null;\n if (this.transitionEndHandler) {\n panel?.removeEventListener('transitionend', this.transitionEndHandler);\n }\n this.transitionEndHandler = (e: TransitionEvent) => {\n if (e.propertyName === 'width') {\n this.isAnimating = false;\n panel?.removeEventListener('transitionend', this.transitionEndHandler!);\n }\n };\n panel?.addEventListener('transitionend', this.transitionEndHandler);\n }\n\n private connectResizeObserver() {\n this.viewportNarrow = window.innerWidth < this.breakpoint;\n this.resizeObserver = new ResizeObserver(() => {\n this.viewportNarrow = window.innerWidth < this.breakpoint;\n });\n this.resizeObserver.observe(document.documentElement);\n }\n\n private disconnectResizeObserver() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = undefined;\n }\n\n /** Derive active ID from the current URL by matching item `href` values.\n * Uses longest-prefix match so `/fleet/detail` correctly activates `/fleet`. */\n private syncActiveFromUrl() {\n if (!this.currentUrl) {\n this.urlDerivedActiveId = '';\n return;\n }\n let best: PanelNavItem | undefined;\n let bestLen = 0;\n for (const item of this.getAllItems()) {\n if (item.href && this.currentUrl.startsWith(item.href) && item.href.length > bestLen) {\n best = item;\n bestLen = item.href.length;\n }\n }\n this.urlDerivedActiveId = best?.id ?? '';\n }\n\n /** Centralised toggle: always emits `dsNavToggle`; when `storageKey` is set\n * also mutates `collapsed` directly and persists to `localStorage`. */\n private applyToggle(next: boolean) {\n this.dsNavToggle.emit(next);\n if (this.storageKey) {\n this.collapsed = next;\n try { localStorage.setItem(this.storageKey, String(next)); } catch { /* unavailable */ }\n }\n }\n\n private getAllItems(): PanelNavItem[] {\n return this.parsedGroups.flatMap(g => g.items);\n }\n\n private syncRovingIndex() {\n const idx = this.getAllItems().findIndex(i => i.id === this.effectiveActiveId);\n this.rovingIndex = idx >= 0 ? idx : 0;\n }\n\n private handleItemKeyDown(e: KeyboardEvent, index: number) {\n const total = this.getAllItems().length;\n let next: number;\n switch (e.key) {\n case 'ArrowDown': e.preventDefault(); next = (index + 1) % total; break;\n case 'ArrowUp': e.preventDefault(); next = (index - 1 + total) % total; break;\n case 'Home': e.preventDefault(); next = 0; break;\n case 'End': e.preventDefault(); next = total - 1; break;\n default: return;\n }\n this.rovingIndex = next;\n const items = Array.from(\n this.el.querySelectorAll<HTMLElement>('.panel-nav__body .panel-nav__item')\n );\n items[next]?.focus();\n }\n\n private checkScroll() {\n const body = this.el.querySelector('.panel-nav__body') as HTMLElement | null;\n if (!body) return;\n const remaining = body.scrollHeight - body.scrollTop - body.clientHeight;\n this.atBottom = remaining < 2;\n }\n\n private handleBodyScroll(e: Event) {\n const body = e.target as HTMLElement;\n const remaining = body.scrollHeight - body.scrollTop - body.clientHeight;\n this.atBottom = remaining < 2;\n }\n\n private handleItemClick(id: string) {\n this.dsNavSelect.emit(id);\n }\n\n private handleToggle() {\n this.applyToggle(!this.collapsed);\n }\n\n private handleFooterAction() {\n this.dsNavFooterAction.emit();\n }\n\n private clearEdgeOverlayTimer() {\n if (this.edgeOverlayTimer !== null) {\n window.clearTimeout(this.edgeOverlayTimer);\n this.edgeOverlayTimer = null;\n }\n }\n\n private handleResizeHandleMouseEnter() {\n this.clearEdgeOverlayTimer();\n this.edgeOverlayTimer = window.setTimeout(() => {\n this.showEdgeOverlay = true;\n this.edgeOverlayTimer = null;\n }, 500);\n }\n\n private handleResizeHandleMouseLeave() {\n if (this.isDragging) return;\n this.clearEdgeOverlayTimer();\n this.showEdgeOverlay = false;\n }\n\n private handleResizeHandleMouseDown(e: MouseEvent) {\n e.preventDefault();\n e.stopPropagation();\n\n const wasCollapsed = this.collapsed || this.viewportNarrow;\n this.isDragging = true;\n this.dragStartX = e.clientX;\n this.didSnap = false;\n this.lastDeltaX = 0;\n this.clearEdgeOverlayTimer();\n this.showEdgeOverlay = false;\n\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n\n const onMove = (ev: MouseEvent) => {\n const deltaX = ev.clientX - this.dragStartX;\n this.lastDeltaX = Math.abs(deltaX);\n if (this.didSnap) return;\n if (!wasCollapsed && deltaX < -8) {\n this.applyToggle(true);\n this.didSnap = true;\n } else if (wasCollapsed && deltaX > 8) {\n this.applyToggle(false);\n this.didSnap = true;\n }\n };\n\n const onUp = () => {\n if (!this.didSnap && this.lastDeltaX < 3) {\n this.applyToggle(!wasCollapsed);\n }\n this.isDragging = false;\n this.showEdgeOverlay = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n this.globalMouseMoveHandler = undefined;\n this.globalMouseUpHandler = undefined;\n };\n\n this.globalMouseMoveHandler = onMove;\n this.globalMouseUpHandler = onUp;\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n }\n\n private renderNavItem(item: PanelNavItem, idx: number, collapsed: boolean) {\n const isActive = item.id === this.effectiveActiveId;\n\n const itemContent = [\n <span class=\"panel-nav__item-icon\">\n <ds-icon name={item.icon} size=\"md\" color=\"inherit\" flag={item.flag} />\n </span>,\n <span class=\"panel-nav__item-label\">\n <span class=\"panel-nav__item-label-text\">\n <ds-text\n as=\"span\"\n variant={isActive ? 'text-body-medium-emphasis' : 'text-body-medium'}\n color=\"inherit\"\n >\n {item.label}\n </ds-text>\n </span>\n </span>,\n item.dot && <span class=\"panel-nav__item-dot\" aria-hidden=\"true\" />,\n ];\n\n const sharedProps = {\n class: { 'panel-nav__item': true, 'panel-nav__item--active': isActive },\n 'aria-current': isActive ? ('page' as const) : undefined,\n title: collapsed ? item.label : undefined,\n tabIndex: idx === this.rovingIndex ? 0 : -1,\n onClick: () => this.handleItemClick(item.id),\n onKeyDown: (e: KeyboardEvent) => this.handleItemKeyDown(e, idx),\n onFocus: () => { this.rovingIndex = idx; },\n };\n\n return item.href\n ? <a {...sharedProps} href={item.href}>{itemContent}</a>\n : <button {...sharedProps} type=\"button\">{itemContent}</button>;\n }\n\n render() {\n const isDashboard = this.renderedVariant === 'dashboard';\n const collapsed = this.collapsed || this.viewportNarrow;\n const { userName, userInitial } = this;\n\n const navCls: Record<string, boolean> = {\n 'panel-nav': true,\n 'panel-nav--dashboard': isDashboard,\n 'panel-nav--settings': !isDashboard,\n 'panel-nav--collapsed': collapsed,\n 'panel-nav--animating': this.isAnimating,\n 'panel-nav--at-bottom': this.atBottom,\n };\n\n return (\n <Host style={{ display: 'block', position: 'relative' }}>\n <nav class={navCls} aria-label={isDashboard ? 'Main navigation' : 'Settings navigation'}>\n\n {/* ── Header: Motive logo, reveals collapse toggle on hover ── */}\n <div class=\"panel-nav__header\">\n <button\n type=\"button\"\n class=\"panel-nav__header-btn\"\n onClick={() => this.handleToggle()}\n aria-label={collapsed ? 'Expand navigation' : 'Collapse navigation'}\n aria-expanded={collapsed ? 'false' : 'true'}\n >\n {/* Motive M mark — fades out on hover to reveal collapse toggle */}\n <span class=\"panel-nav__header-logo\" aria-hidden=\"true\">\n <svg class=\"panel-nav__m-mark\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" focusable=\"false\" aria-hidden=\"true\">\n <path d=\"M11.1159 4.31537H7.67021L2.53401 13.0703H0V15.6875H4.02716L8.24319 8.49978V15.6846H11.6342L15.8289 8.47829V15.6846H18.7122V4.3125H15.2559L11.1159 11.3648V4.31537Z\" fill=\"currentColor\"/>\n </svg>\n </span>\n {/* Collapse / expand icon — revealed on hover via CSS */}\n <span class=\"panel-nav__header-toggle\" aria-hidden=\"true\">\n <ds-icon\n name={collapsed ? 'LeftExpandB' : 'LeftCollapseB'}\n size=\"md\"\n color=\"inherit\"\n />\n </span>\n </button>\n </div>\n\n {/* ── Scrollable body ── */}\n <div class=\"panel-nav__body\" onScroll={e => this.handleBodyScroll(e)}>\n {(() => {\n let flatIdx = 0;\n return this.parsedGroups.map(group => (\n <div class=\"panel-nav__group\">\n {group.label && (\n <span class=\"panel-nav__group-label\">\n <span class=\"panel-nav__item-label-text\">\n <ds-text as=\"span\" variant=\"text-caption-emphasis\" color=\"inherit\">\n {group.label}\n </ds-text>\n </span>\n </span>\n )}\n {group.items.map(item => this.renderNavItem(item, flatIdx++, collapsed))}\n </div>\n ));\n })()}\n </div>\n\n {/* ── Footer ── */}\n <div class=\"panel-nav__footer\">\n {/* Left icon button — Gear in dashboard, Dashboard in settings */}\n <button\n type=\"button\"\n class=\"panel-nav__footer-btn\"\n title={isDashboard ? 'Settings' : 'Dashboard'}\n aria-label={isDashboard ? 'Open settings' : 'Go to dashboard'}\n onClick={() => this.handleFooterAction()}\n >\n <ds-icon name={isDashboard ? 'Gear' : 'Dashboard'} size=\"md\" color=\"inherit\" />\n </button>\n\n {/* Right user — label fades like nav items; right icon cross-fades chevron ↔ circle+initial */}\n <button\n type=\"button\"\n class=\"panel-nav__item panel-nav__footer-user\"\n aria-label={collapsed ? `User: ${userName}` : `User menu for ${userName}`}\n >\n <span class=\"panel-nav__item-label panel-nav__footer-user-label\">\n <span class=\"panel-nav__item-label-text\">\n <ds-text as=\"span\" variant=\"text-body-medium-emphasis\" color=\"inherit\">\n {userName}\n </ds-text>\n </span>\n </span>\n <span class=\"panel-nav__item-icon panel-nav__footer-user-icon\" aria-hidden=\"true\">\n <span class=\"panel-nav__footer-icon-expanded\">\n <ds-icon name=\"ChevronUpDown\" size=\"md\" color=\"inherit\" />\n </span>\n <span class=\"panel-nav__footer-icon-collapsed\">\n <ds-icon name=\"Circle\" size=\"md\" color=\"inherit\" />\n <span class=\"panel-nav__user-initial\">\n <ds-text as=\"span\" variant=\"text-caption-emphasis\" color=\"inherit\">\n {userInitial}\n </ds-text>\n </span>\n </span>\n </span>\n </button>\n </div>\n\n </nav>\n\n {/* Drag-to-resize handle — always rendered, hidden only when auto-collapsed by breakpoint */}\n {!this.viewportNarrow && (\n <div\n class={{\n 'panel-nav__resize-handle': true,\n 'panel-nav__resize-handle--overlay': this.showEdgeOverlay,\n }}\n onMouseEnter={() => this.handleResizeHandleMouseEnter()}\n onMouseLeave={() => this.handleResizeHandleMouseLeave()}\n onMouseDown={(e: MouseEvent) => this.handleResizeHandleMouseDown(e)}\n aria-hidden=\"true\"\n />\n )}\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["hrefMatchesPath","path","href","startsWith","deriveActiveIdFromUrl","items","bestId","bestLen","item","length","id","parsePanelNavGroups","groups","Array","isArray","parsed","JSON","parse","vtStyleInjected","ensurePanelNavVtStyle","document","getElementById","style","createElement","textContent","join","head","appendChild","panelNavCss","vtTransitions","WeakMap","vtResolvers","parseCssTimeMs","value","fallback","v","trim","num","parseFloat","Number","isNaN","test","PanelNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","variant","disableViewTransition","routerMode","activeId","collapsed","breakpoint","storageKey","currentUrl","userName","userInitial","renderedVariant","parsedGroups","atBottom","isAnimating","rovingIndex","viewportNarrow","urlDerivedActiveId","isDragging","dragStartX","didSnap","lastDeltaX","edgeOverlayTimer","showEdgeOverlay","effectiveActiveId","onCollapsedChange","startCollapseAnimation","onBreakpointChange","disconnectResizeObserver","connectResizeObserver","onGroupsChange","val","syncRovingIndex","syncActiveFromUrl","onActiveIdChange","onCurrentUrlChange","onVariantChange","newVal","get","skipTransition","delete","doc","startViewTransition","btn","el","querySelector","rect","getBoundingClientRect","x","Math","round","left","width","window","innerWidth","y","top","height","innerHeight","maxR","ceil","hypot","max","documentElement","setProperty","transition","Promise","resolve","set","finished","finally","ready","then","durToken","getComputedStyle","getPropertyValue","duration","animate","clipPath","easing","fill","pseudoElement","catch","componentWillLoad","stored","localStorage","getItem","componentDidLoad","checkScroll","componentDidRender","disconnectedCallback","clearEdgeOverlayTimer","globalMouseMoveHandler","removeEventListener","globalMouseUpHandler","panel","transitionEndHandler","e","propertyName","addEventListener","resizeObserver","ResizeObserver","observe","disconnect","undefined","getAllItems","applyToggle","next","dsNavToggle","emit","setItem","String","flatMap","g","idx","findIndex","i","handleItemKeyDown","index","total","key","preventDefault","from","querySelectorAll","focus","body","remaining","scrollHeight","scrollTop","clientHeight","handleBodyScroll","target","handleItemClick","dsNavSelect","handleToggle","handleFooterAction","dsNavFooterAction","handleUserAction","dsNavUserAction","clearTimeout","handleResizeHandleMouseEnter","setTimeout","handleResizeHandleMouseLeave","handleResizeHandleMouseDown","stopPropagation","wasCollapsed","clientX","cursor","userSelect","onMove","ev","deltaX","abs","onUp","renderNavItem","isActive","itemContent","h","class","name","icon","size","color","flag","as","label","dot","sharedProps","title","tabIndex","onClick","onKeyDown","onFocus","useAnchor","type","render","isDashboard","navCls","Host","display","position","viewBox","xmlns","focusable","d","onScroll","flatIdx","map","group","onMouseEnter","onMouseLeave","onMouseDown"],"sources":["src/wc/components/PanelNav/panel-nav-utils.ts","src/wc/components/PanelNav/PanelNav.css?tag=ds-panel-nav&encapsulation=scoped","src/wc/components/PanelNav/PanelNav.tsx"],"sourcesContent":["import type { PanelNavGroup, PanelNavItem } from './PanelNav';\n\n/** Whether `path` matches `href` at a segment boundary (exact or child path). */\nexport function hrefMatchesPath(path: string, href: string): boolean {\n return path === href || path.startsWith(`${href}/`);\n}\n\n/** Derive the active nav item id from a URL using longest segment-boundary prefix match. */\nexport function deriveActiveIdFromUrl(path: string, items: PanelNavItem[]): string {\n if (!path) return '';\n\n let bestId = '';\n let bestLen = 0;\n\n for (const item of items) {\n if (!item.href) continue;\n if (hrefMatchesPath(path, item.href) && item.href.length > bestLen) {\n bestId = item.id;\n bestLen = item.href.length;\n }\n }\n\n return bestId;\n}\n\n/** Parse `groups` from either a JSON attribute string or a JS property array. */\nexport function parsePanelNavGroups(groups: string | unknown): PanelNavGroup[] {\n if (Array.isArray(groups)) return groups;\n if (typeof groups === 'string') {\n try {\n const parsed = JSON.parse(groups);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n return [];\n}\n\nlet vtStyleInjected = false;\n\n/** Inject view-transition suppress styles once per document (shared by PanelNav + hosts). */\nexport function ensurePanelNavVtStyle(): void {\n if (vtStyleInjected) return;\n const id = 'ds-panel-nav-vt-style';\n if (document.getElementById(id)) {\n vtStyleInjected = true;\n return;\n }\n const style = document.createElement('style');\n style.id = id;\n style.textContent = [\n '::view-transition-old(root),::view-transition-new(root){animation:none;mix-blend-mode:normal}',\n '::view-transition-new(root){clip-path:circle(0px at var(--vt-x,50%) var(--vt-y,50%))}',\n ].join('\\n');\n document.head.appendChild(style);\n vtStyleInjected = true;\n}\n","/* ── Theme variables ──────────────────────────────────────────────────────── */\n\n.panel-nav {\n /* ─ Sizes ─ */\n --_nav-width: 200px;\n --_nav-width-collapsed: 48px;\n --_nav-item-height: var(--dimension-size-400, 32px);\n --_nav-padding-x: var(--dimension-space-100, 8px);\n --_nav-padding-y: var(--dimension-space-100, 8px);\n /* gear button outer width = padding*2 + icon */\n --_nav-footer-btn-w: calc(var(--dimension-space-075, 6px) * 2 + var(--dimension-iconography-md, 20px));\n\n /* ─ Motion ─ */\n /* --ds-panel-nav-speed: unitless multiplier; override in Storybook to slow-mo (e.g. 10 = 10×).\n *-dur vars are duration-only (needed for calc); *-motion vars add easing for use in transitions. */\n --_nav-speed: var(--ds-panel-nav-speed, 1);\n --_nav-expand-dur: calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));\n --_nav-expand-motion: var(--_nav-expand-dur) var(--effect-animation-easing-ease-in-out, ease);\n --_nav-label-fade-dur: calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));\n --_nav-label-fade-motion: var(--_nav-label-fade-dur) var(--effect-animation-easing-ease-in-out, ease);\n --_nav-label-fade-out-dur: calc(var(--_nav-speed) * var(--effect-animation-duration-medium-1, 300ms));\n --_nav-label-fade-out-motion: var(--_nav-label-fade-out-dur) var(--effect-animation-easing-ease-in-out, ease);\n\n /* ─ Colours – dashboard defaults ─ */\n --_nav-bg: var(--color-navigation-background);\n --_nav-border: var(--color-navigation-border-tertiary);\n --_nav-divider: var(--color-navigation-divider);\n --_nav-fg-primary: var(--color-navigation-foreground-primary);\n --_nav-fg-secondary: var(--color-navigation-foreground-secondary);\n --_nav-fg-tertiary: var(--color-navigation-foreground-tertiary);\n --_nav-hover: var(--color-navigation-interaction-hover);\n --_nav-pressed: var(--color-navigation-interaction-pressed);\n --_nav-focus: var(--color-navigation-interaction-focus);\n --_nav-dot: var(--color-navigation-foreground-brand);\n}\n\n/* ── Settings overrides ──────────────────────────────────────────────────── */\n\n.panel-nav--settings {\n --_nav-bg: var(--color-background-secondary);\n --_nav-border: var(--color-border-tertiary);\n --_nav-divider: var(--color-border-tertiary);\n --_nav-fg-primary: var(--color-foreground-primary);\n --_nav-fg-secondary: var(--color-foreground-secondary);\n --_nav-fg-tertiary: var(--color-foreground-tertiary);\n --_nav-hover: var(--color-interaction-hover);\n --_nav-pressed: var(--color-interaction-pressed);\n --_nav-focus: var(--color-interaction-focus);\n --_nav-dot: var(--color-foreground-bold-brand);\n}\n\n/* ── Shell ───────────────────────────────────────────────────────────────── */\n\n.panel-nav {\n display: flex;\n flex-direction: column;\n width: var(--_nav-width);\n min-width: var(--_nav-width);\n height: 100%;\n background: var(--_nav-bg);\n border-right: var(--dimension-stroke-width-012, 1px) solid var(--_nav-border);\n box-sizing: border-box;\n overflow: hidden;\n transition:\n width var(--_nav-expand-motion),\n min-width var(--_nav-expand-motion),\n background var(--effect-motion-short-3, 200ms ease),\n border-color var(--effect-motion-short-3, 200ms ease);\n font-family: var(--typography-font-family, system-ui);\n}\n\n.panel-nav--collapsed {\n width: var(--_nav-width-collapsed);\n min-width: var(--_nav-width-collapsed);\n}\n\n/* ── Header ──────────────────────────────────────────────────────────────── */\n\n.panel-nav__header {\n display: flex;\n align-items: center;\n height: var(--dimension-size-600, 48px);\n padding: var(--dimension-space-100, 8px);\n flex-shrink: 0;\n box-sizing: border-box;\n border-bottom: var(--dimension-stroke-width-012, 1px) solid var(--_nav-divider);\n transition: border-color var(--effect-motion-short-3, 200ms ease);\n}\n\n.panel-nav__header-btn {\n all: unset;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-075, 6px);\n border-radius: var(--dimension-radius-025, 2px);\n cursor: pointer;\n color: var(--_nav-fg-primary);\n position: relative;\n flex-shrink: 0;\n box-sizing: border-box;\n transition: color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* Interaction pseudo-element */\n.panel-nav__header-btn::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: var(--dimension-radius-025, 2px);\n background: transparent;\n transition: background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n pointer-events: none;\n}\n\n.panel-nav__header-btn:hover::after { background: var(--_nav-hover); transition: none; }\n.panel-nav__header-btn:active::after { background: var(--_nav-pressed); transition: none; }\n.panel-nav__header-btn:focus-visible { outline: none; }\n.panel-nav__header-btn:focus-visible::after {\n outline: var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);\n outline-offset: calc(-1 * var(--dimension-stroke-width-025, 2px));\n}\n\n/* Logo — visible by default, hidden on hover */\n.panel-nav__header-logo {\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n z-index: 1;\n transition: opacity var(--effect-motion-short-2, 100ms ease);\n}\n\n.panel-nav__m-mark {\n width: var(--dimension-iconography-md, 20px);\n height: var(--dimension-iconography-md, 20px);\n display: block;\n}\n\n/* Toggle icon — hidden by default, revealed on hover */\n.panel-nav__header-toggle {\n display: none;\n align-items: center;\n justify-content: center;\n position: absolute;\n inset: 0;\n z-index: 1;\n}\n\n.panel-nav__header-btn:hover .panel-nav__header-logo { opacity: 0; }\n.panel-nav__header-btn:hover .panel-nav__header-toggle { display: flex; }\n\n/* ── Scrollable body ─────────────────────────────────────────────────────── */\n\n.panel-nav__body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-200, 16px);\n padding: var(--dimension-space-100, 8px);\n box-sizing: border-box;\n scrollbar-width: none;\n}\n\n.panel-nav__body::-webkit-scrollbar { display: none; }\n\n/* ── Group ───────────────────────────────────────────────────────────────── */\n\n.panel-nav__group {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050, 4px);\n}\n\n.panel-nav__group-label {\n /* Typography via ds-text (text-caption-emphasis) */\n display: flex;\n align-items: center;\n text-transform: uppercase;\n color: var(--_nav-fg-secondary);\n user-select: none;\n height: var(--dimension-size-300, 24px);\n line-height: var(--typography-lineheight-xs, 12px);\n padding: 0 var(--dimension-space-075, 6px);\n white-space: nowrap;\n overflow: hidden;\n max-height: var(--dimension-size-300, 24px);\n opacity: 1;\n transition:\n opacity var(--_nav-label-fade-motion) 0ms,\n max-height var(--_nav-label-fade-motion) 0ms,\n padding var(--_nav-label-fade-motion) 0ms,\n color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* ── Item ────────────────────────────────────────────────────────────────── */\n\n.panel-nav__item {\n all: unset;\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050, 4px);\n padding: 0 var(--dimension-space-075, 6px);\n height: var(--dimension-size-400, 32px);\n border-radius: var(--dimension-radius-025, 2px);\n cursor: pointer;\n color: var(--_nav-fg-secondary);\n position: relative;\n box-sizing: border-box;\n width: 100%;\n user-select: none;\n transition: color var(--effect-motion-short-1, 50ms ease-in-out);\n}\n\n/* Interaction layer */\n.panel-nav__item::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: background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n}\n\n.panel-nav__item:hover::after { background: var(--_nav-hover); transition: none; }\n.panel-nav__item:active::after { background: var(--_nav-pressed); transition: none; }\n.panel-nav__item:focus-visible { outline: none; }\n.panel-nav__item:focus-visible::after {\n outline: var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);\n outline-offset: calc(-1 * var(--dimension-stroke-width-025, 2px));\n}\n\n/* ── Active item ─────────────────────────────────────────────────────────── */\n\n.panel-nav__item--active {\n color: var(--_nav-fg-primary);\n /* Bold typography via ds-text (text-body-medium-emphasis) on the label */\n}\n\n/* ── Item icon ───────────────────────────────────────────────────────────── */\n\n.panel-nav__item-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--dimension-iconography-md, 20px);\n height: var(--dimension-iconography-md, 20px);\n position: relative;\n}\n\n/* ── Item label ──────────────────────────────────────────────────────────── */\n\n.panel-nav__item-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n height: var(--typography-lineheight-md, 20px);\n line-height: var(--typography-lineheight-md, 20px);\n opacity: 1;\n /* Gradient wipe: mask sweeps left-to-right on expand, right-to-left on collapse */\n mask-image: linear-gradient(to right, black 50%, transparent 100%);\n -webkit-mask-image: linear-gradient(to right, black 50%, transparent 100%);\n mask-size: 200% 100%;\n -webkit-mask-size: 200% 100%;\n mask-position: 0% 0;\n -webkit-mask-position: 0% 0;\n transition:\n opacity var(--_nav-label-fade-motion) 0ms,\n mask-position var(--_nav-label-fade-motion) 0ms,\n -webkit-mask-position var(--_nav-label-fade-motion) 0ms;\n}\n\n.panel-nav__item-label-text {\n padding: 0 var(--dimension-space-025, 2px);\n}\n\n/* ── Item notification dot — single element, moves between positions ──────── */\n\n.panel-nav__item-dot {\n position: absolute;\n right: 13px;\n top: 13px;\n width: var(--dimension-space-075, 6px);\n height: var(--dimension-space-075, 6px);\n border-radius: var(--dimension-radius-full, 999px);\n background: var(--_nav-dot);\n box-shadow: 0 0 0 var(--dimension-stroke-width-018, 1.5px) var(--_nav-bg);\n pointer-events: none;\n transition:\n right var(--_nav-expand-motion),\n top var(--_nav-expand-motion),\n background var(--effect-motion-short-3, 200ms ease),\n box-shadow var(--effect-motion-short-3, 200ms ease);\n}\n\n.panel-nav--collapsed .panel-nav__item-dot {\n right: 6px;\n top: 6px;\n}\n\n.panel-nav--animating .panel-nav__item-label {\n text-overflow: clip;\n}\n\n.panel-nav--collapsed .panel-nav__item-label {\n opacity: 0;\n pointer-events: none;\n text-overflow: clip;\n mask-position: 100% 0;\n -webkit-mask-position: 100% 0;\n transition:\n opacity var(--_nav-label-fade-out-motion) 0ms,\n mask-position var(--_nav-label-fade-out-motion) 0ms,\n -webkit-mask-position var(--_nav-label-fade-out-motion) 0ms;\n}\n\n.panel-nav--collapsed .panel-nav__group-label {\n opacity: 0;\n max-height: 0;\n padding: 0 var(--dimension-space-075, 6px);\n pointer-events: none;\n transition:\n opacity var(--_nav-label-fade-out-motion) 0ms,\n max-height var(--_nav-label-fade-out-motion) 0ms,\n padding var(--_nav-label-fade-out-motion) 0ms,\n color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* ── Footer ──────────────────────────────────────────────────────────────── */\n\n.panel-nav__footer {\n position: relative;\n flex-shrink: 0;\n /* single row: padding*2 + item */\n height: calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height));\n transition: height var(--_nav-expand-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer {\n /* two rows: padding*2 + item*2 + gap */\n height: calc(var(--_nav-padding-y) * 2 + var(--_nav-item-height) * 2 + var(--dimension-space-050, 4px));\n}\n\n/* Gradient fade — floats above the footer, masks content scrolling under it */\n.panel-nav__footer::before {\n content: '';\n position: absolute;\n bottom: 100%;\n left: 0;\n right: 0;\n height: calc(var(--dimension-base, 8px) * 6);\n background: linear-gradient(to bottom, transparent, var(--_nav-bg));\n pointer-events: none;\n opacity: 1;\n transition: opacity var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n}\n\n.panel-nav--at-bottom .panel-nav__footer::before {\n opacity: 0;\n}\n\n/* ── Footer icon button (gear / dashboard) ───────────────────────────────── */\n\n.panel-nav__footer-btn {\n all: unset;\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n left: var(--_nav-padding-x);\n top: var(--_nav-padding-y);\n padding: var(--dimension-space-075, 6px);\n border-radius: var(--dimension-radius-half, 9999px);\n cursor: pointer;\n color: var(--_nav-fg-secondary);\n box-sizing: border-box;\n background: transparent;\n transition:\n background var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease),\n color var(--effect-animation-duration-short-3, 200ms) var(--effect-animation-easing-ease-out, ease);\n}\n\n.panel-nav__footer-btn:focus-visible {\n outline: var(--dimension-stroke-width-025, 2px) solid var(--_nav-focus);\n outline-offset: calc(-1 * var(--dimension-stroke-width-025, 2px));\n}\n\n/* Dashboard: hover previews settings surface */\n.panel-nav--dashboard .panel-nav__footer-btn:hover {\n background: var(--color-background-secondary);\n color: var(--color-foreground-secondary);\n transition: none;\n}\n\n/* Settings: hover previews dashboard nav surface */\n.panel-nav--settings .panel-nav__footer-btn:hover {\n background: var(--color-navigation-background);\n color: var(--color-navigation-foreground-secondary);\n transition: none;\n}\n\n/* ── Footer user — absolutely positioned, slides from row to below gear ───── */\n\n.panel-nav__footer-user {\n position: absolute;\n /* row position: right of gear button */\n left: calc(var(--_nav-padding-x) + var(--_nav-footer-btn-w) + var(--dimension-space-050, 4px));\n right: var(--_nav-padding-x);\n top: var(--_nav-padding-y);\n width: auto;\n min-width: 0;\n transition:\n left var(--_nav-expand-motion),\n right var(--_nav-expand-motion),\n top var(--_nav-expand-motion),\n color var(--effect-motion-short-3, 200ms ease);\n}\n\n.panel-nav--collapsed .panel-nav__footer-user {\n /* column position: full-width row below gear */\n left: var(--_nav-padding-x);\n right: var(--_nav-padding-x);\n top: calc(var(--_nav-padding-y) + var(--_nav-item-height) + var(--dimension-space-050, 4px));\n}\n\n/* Label: absolute so it stays in place and only fades — no mask slide */\n.panel-nav__footer-user-label {\n text-align: right;\n position: absolute;\n left: var(--dimension-space-075, 6px);\n right: calc(var(--dimension-space-075, 6px) + var(--dimension-iconography-md, 20px) + var(--dimension-space-050, 4px));\n top: 50%;\n transform: translateY(-50%);\n flex: none;\n height: var(--typography-lineheight-md, 20px);\n mask-image: none;\n -webkit-mask-image: none;\n transition: opacity var(--_nav-label-fade-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-user-label {\n opacity: 0;\n pointer-events: none;\n mask-position: 0% 0;\n -webkit-mask-position: 0% 0;\n}\n\n/* ── Footer user icon — cross-fades chevron ↔ circle+initial ────────────── */\n\n/* Absolute — right-anchored in expanded, left-anchored in collapsed to match regular item icon position */\n.panel-nav__footer-user-icon {\n position: absolute;\n left: calc(100% - var(--dimension-iconography-md, 20px) - var(--dimension-space-075, 6px));\n top: 0;\n bottom: 0;\n height: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: left var(--_nav-expand-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-user-icon {\n left: var(--dimension-space-075, 6px);\n}\n\n.panel-nav__footer-icon-expanded,\n.panel-nav__footer-icon-collapsed {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.panel-nav__footer-icon-expanded {\n opacity: 1;\n transition: opacity var(--_nav-label-fade-motion);\n}\n\n.panel-nav__footer-icon-collapsed {\n opacity: 0;\n transition: opacity var(--_nav-label-fade-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-icon-expanded {\n opacity: 0;\n transition: opacity var(--_nav-label-fade-out-motion);\n}\n\n.panel-nav--collapsed .panel-nav__footer-icon-collapsed {\n opacity: 1;\n transition: opacity var(--_nav-label-fade-out-motion);\n}\n\n/* ── User initial — overlaid on the circle icon ─────────────────────────── */\n\n.panel-nav__user-initial {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--_nav-fg-secondary);\n text-transform: uppercase;\n line-height: 1;\n pointer-events: none;\n transition: color var(--effect-motion-short-3, 200ms ease);\n}\n\n/* ── Drag-to-resize handle ───────────────────────────────────────────────── */\n\n.panel-nav__resize-handle {\n position: absolute;\n top: 0;\n /* Centered on the right edge: --dimension-space-050 outside + inside = --dimension-space-100 hit zone */\n right: var(--dimension-space-n050, -4px);\n bottom: 0;\n width: var(--dimension-space-100, 8px);\n z-index: 10;\n cursor: ew-resize;\n touch-action: none;\n /* Needs a real background for Safari hit-testing */\n background: transparent;\n}\n\n/* Safari requires non-transparent fill for hit testing */\n.panel-nav__resize-handle::before {\n content: '';\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.001);\n}\n\n/* The brand-bold overlay line */\n.panel-nav__resize-handle::after {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n width: var(--dimension-stroke-width-025, 2px);\n background: var(--color-background-bold-brand);\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--effect-motion-short-2, 100ms ease-in-out);\n}\n\n.panel-nav__resize-handle--overlay::after {\n opacity: 1;\n}\n\n/* ── Reduced motion ──────────────────────────────────────────────────────── */\n\n@media (prefers-reduced-motion: reduce) {\n .panel-nav,\n .panel-nav *,\n .panel-nav *::before,\n .panel-nav *::after,\n .panel-nav__resize-handle,\n .panel-nav__resize-handle::before,\n .panel-nav__resize-handle::after {\n transition-duration: 0.01ms !important;\n animation-duration: 0.01ms !important;\n transition-delay: 0.01ms !important;\n }\n}\n","import { Component, Prop, Event, EventEmitter, Watch, State, Element, h, Host } from '@stencil/core';\nimport {\n deriveActiveIdFromUrl,\n ensurePanelNavVtStyle,\n parsePanelNavGroups,\n} from './panel-nav-utils';\n\n// Module-level WeakMaps for per-instance VT state. Using WeakMaps instead of\n// class fields avoids Stencil generating getter-only property descriptors on\n// the host element for private fields, which throws in strict environments.\n// Minimal typings for the View Transitions API, which isn't in our TS lib target.\ninterface ViewTransition {\n finished: Promise<void>;\n skipTransition: () => void;\n}\ntype DocumentWithViewTransition = Document & {\n startViewTransition?: (callback: () => void | Promise<void>) => ViewTransition;\n};\n\nconst vtTransitions = new WeakMap<object, ViewTransition>();\nconst vtResolvers = new WeakMap<object, () => void>();\n\n/** Parse a CSS <time> value to milliseconds. Handles `s`, `ms`, and unitless\n * (assumed ms). Critically: `parseFloat('.75s')` is 0.75 — WAAPI treats that as\n * 0.75ms (instant/invisible), so the `s` unit must be scaled to ms. Design\n * tokens (e.g. `--effect-animation-duration-long-1`) are authored in seconds. */\nfunction parseCssTimeMs(value: string, fallback: number): number {\n const v = value.trim();\n const num = parseFloat(v);\n if (Number.isNaN(num)) return fallback;\n if (/ms\\s*$/.test(v)) return num;\n if (/s\\s*$/.test(v)) return num * 1000;\n return num;\n}\n\nexport type PanelNavVariant = 'dashboard' | 'settings';\nexport type PanelNavRouterMode = 'anchor' | 'event';\n\nexport interface PanelNavItem {\n id: string;\n icon: string;\n label: string;\n /** Show a notification dot badge on the item */\n dot?: boolean;\n flag?: boolean;\n /** Route path used for `currentUrl` matching. In `anchor` mode also sets `<a href>`.\n * In `event` mode navigation is delegated to the host via `dsNavSelect`. */\n href?: string;\n}\n\nexport interface PanelNavGroup {\n id?: string;\n label?: string;\n items: PanelNavItem[];\n}\n\n@Component({\n tag: 'ds-panel-nav',\n styleUrl: 'PanelNav.css',\n scoped: true,\n})\nexport class PanelNav {\n /** Visual variant: `dashboard` = always-dark surface, `settings` = light surface */\n @Prop() variant: PanelNavVariant = 'dashboard';\n\n /** When `true`, the component does not run its own View Transition on variant\n * change — it just updates the rendered surface synchronously. Use this when\n * the host app orchestrates the page transition itself (e.g. Angular Router's\n * `withViewTransitions`), so the two don't fight or nest. */\n @Prop() disableViewTransition: boolean = false;\n\n /** Nav groups — set via JS property (`el.groups = [...]`) or JSON string attribute. */\n @Prop() groups: string | PanelNavGroup[] = '[]';\n\n /** How items with `href` render:\n * - `anchor` (default): native `<a href>` — works with routers that intercept anchors.\n * - `event`: always `<button>`; host handles navigation via `dsNavSelect`. */\n @Prop() routerMode: PanelNavRouterMode = 'anchor';\n\n /** ID of the currently active/selected nav item. Overridden by `currentUrl` matching when set. */\n @Prop() activeId: string = '';\n\n /** Whether the nav is in collapsed (icon-only) state.\n * When `storageKey` is set the component manages this internally —\n * do not also bind it from outside in that mode. */\n @Prop({ mutable: true }) collapsed: boolean = false;\n\n /** Viewport width (px) below which the nav auto-collapses to icon-only mode. 0 = disabled. */\n @Prop() breakpoint: number = 0;\n\n /** `localStorage` key used to persist the collapsed state across page loads.\n * When set the component is self-managing for collapsed state; `dsNavToggle`\n * still fires for consumers that want to observe the change. */\n @Prop() storageKey: string = '';\n\n /** Current route URL (e.g. `window.location.pathname` or the router's active URL).\n * When set the component derives the active item by matching item `href` values\n * against this string (longest segment-boundary prefix wins), overriding `activeId`. */\n @Prop() currentUrl: string = '';\n\n /** Display name for the footer user section */\n @Prop() userName: string = '';\n\n /** Single character shown in the collapsed avatar */\n @Prop() userInitial: string = '';\n\n /** Emitted when a nav item is clicked. Detail = the item's `id`. */\n @Event() dsNavSelect!: EventEmitter<string>;\n\n /** Emitted when the collapse toggle is clicked. Detail = new collapsed state. */\n @Event() dsNavToggle!: EventEmitter<boolean>;\n\n /** Emitted when the footer left button (gear / dashboard) is clicked. */\n @Event() dsNavFooterAction!: EventEmitter<void>;\n\n /** Emitted when the footer user button is clicked. */\n @Event() dsNavUserAction!: EventEmitter<void>;\n\n @Element() el!: HTMLElement;\n\n /** Mirrors `variant` but is only updated inside the VT callback so the\n * View Transition captures a clean before/after snapshot. */\n @State() private renderedVariant: PanelNavVariant = 'dashboard';\n\n @State() private parsedGroups: PanelNavGroup[] = [];\n @State() private atBottom = false;\n @State() private isAnimating = false;\n @State() private rovingIndex: number = 0;\n @State() private viewportNarrow: boolean = false;\n @State() private urlDerivedActiveId: string = '';\n\n private transitionEndHandler?: (e: TransitionEvent) => void;\n private resizeObserver?: ResizeObserver;\n\n // Drag-to-resize state (not @State — no re-render needed)\n private isDragging = false;\n private dragStartX = 0;\n private didSnap = false;\n private lastDeltaX = 0;\n private edgeOverlayTimer: number | null = null;\n private globalMouseMoveHandler?: (e: MouseEvent) => void;\n private globalMouseUpHandler?: () => void;\n\n @State() private showEdgeOverlay = false;\n\n /** The ID that should be treated as active. `currentUrl` matching takes precedence\n * over `activeId` when both are present. */\n private get effectiveActiveId(): string {\n return this.urlDerivedActiveId || this.activeId;\n }\n\n @Watch('collapsed')\n @Watch('viewportNarrow')\n onCollapsedChange() {\n this.startCollapseAnimation();\n }\n\n @Watch('breakpoint')\n onBreakpointChange() {\n this.disconnectResizeObserver();\n if (this.breakpoint > 0) this.connectResizeObserver();\n }\n\n @Watch('groups')\n onGroupsChange(val: string | PanelNavGroup[]) {\n this.parsedGroups = parsePanelNavGroups(val);\n this.syncRovingIndex();\n this.syncActiveFromUrl();\n }\n\n @Watch('activeId')\n @Watch('urlDerivedActiveId')\n onActiveIdChange() {\n this.syncRovingIndex();\n }\n\n @Watch('currentUrl')\n onCurrentUrlChange() {\n this.syncActiveFromUrl();\n }\n\n @Watch('variant')\n async onVariantChange(newVal: PanelNavVariant) {\n // Host app drives the transition (e.g. Angular Router withViewTransitions):\n // just reflect the new surface so the app's transition captures it.\n if (this.disableViewTransition) {\n this.renderedVariant = newVal;\n return;\n }\n\n // Skip any in-progress transition immediately so rapid variant changes\n // (e.g. quick dashboard → settings → dashboard) never leave the nav stuck.\n vtTransitions.get(this)?.skipTransition();\n vtTransitions.delete(this);\n\n const doc = document as DocumentWithViewTransition;\n if (typeof doc.startViewTransition !== 'function') {\n this.renderedVariant = newVal;\n return;\n }\n\n ensurePanelNavVtStyle();\n\n const btn = this.el.querySelector('.panel-nav__footer-btn') as HTMLElement | null;\n const rect = btn?.getBoundingClientRect();\n const x = rect ? Math.round(rect.left + rect.width / 2) : Math.round(window.innerWidth / 2);\n const y = rect ? Math.round(rect.top + rect.height / 2) : Math.round(window.innerHeight / 2);\n const maxR = Math.ceil(Math.hypot(\n Math.max(x, window.innerWidth - x),\n Math.max(y, window.innerHeight - y),\n ));\n\n document.documentElement.style.setProperty('--vt-x', `${x}px`);\n document.documentElement.style.setProperty('--vt-y', `${y}px`);\n\n const transition = doc.startViewTransition(() =>\n new Promise<void>(resolve => {\n vtResolvers.set(this, resolve);\n this.renderedVariant = newVal;\n })\n );\n\n vtTransitions.set(this, transition);\n transition.finished.finally(() => {\n if (vtTransitions.get(this) === transition) vtTransitions.delete(this);\n vtResolvers.delete(this);\n });\n\n transition.ready.then(() => {\n const durToken = getComputedStyle(document.documentElement)\n .getPropertyValue('--effect-animation-duration-long-1').trim();\n const duration = parseCssTimeMs(durToken, 750);\n document.documentElement.animate(\n { clipPath: [`circle(0px at ${x}px ${y}px)`, `circle(${maxR}px at ${x}px ${y}px)`] },\n { duration, easing: 'ease-in-out', fill: 'forwards', pseudoElement: '::view-transition-new(root)' },\n );\n }).catch(() => { /* transition was skipped or aborted */ });\n }\n\n componentWillLoad() {\n this.renderedVariant = this.variant;\n if (this.storageKey) {\n try {\n const stored = localStorage.getItem(this.storageKey);\n if (stored !== null) this.collapsed = stored === 'true';\n } catch { /* localStorage unavailable */ }\n }\n this.onGroupsChange(this.groups);\n this.syncActiveFromUrl();\n }\n\n componentDidLoad() {\n this.checkScroll();\n if (this.breakpoint > 0) this.connectResizeObserver();\n }\n\n componentDidRender() {\n // If a view transition callback is waiting for the render to complete,\n // resolve it now so the \"after\" snapshot is taken at exactly the right moment.\n const resolve = vtResolvers.get(this);\n if (resolve) {\n vtResolvers.delete(this);\n resolve();\n }\n }\n\n disconnectedCallback() {\n this.disconnectResizeObserver();\n this.clearEdgeOverlayTimer();\n if (this.globalMouseMoveHandler) {\n window.removeEventListener('mousemove', this.globalMouseMoveHandler);\n }\n if (this.globalMouseUpHandler) {\n window.removeEventListener('mouseup', this.globalMouseUpHandler);\n }\n }\n\n private startCollapseAnimation() {\n this.isAnimating = true;\n const panel = this.el.querySelector('.panel-nav') as HTMLElement | null;\n if (this.transitionEndHandler) {\n panel?.removeEventListener('transitionend', this.transitionEndHandler);\n }\n this.transitionEndHandler = (e: TransitionEvent) => {\n if (e.propertyName === 'width') {\n this.isAnimating = false;\n panel?.removeEventListener('transitionend', this.transitionEndHandler!);\n }\n };\n panel?.addEventListener('transitionend', this.transitionEndHandler);\n }\n\n private connectResizeObserver() {\n this.viewportNarrow = window.innerWidth < this.breakpoint;\n this.resizeObserver = new ResizeObserver(() => {\n this.viewportNarrow = window.innerWidth < this.breakpoint;\n });\n this.resizeObserver.observe(document.documentElement);\n }\n\n private disconnectResizeObserver() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = undefined;\n }\n\n /** Derive active ID from the current URL by matching item `href` values.\n * Uses longest segment-boundary prefix match. */\n private syncActiveFromUrl() {\n if (!this.currentUrl) {\n this.urlDerivedActiveId = '';\n return;\n }\n this.urlDerivedActiveId = deriveActiveIdFromUrl(this.currentUrl, this.getAllItems());\n }\n\n /** Centralised toggle: always emits `dsNavToggle`; when `storageKey` is set\n * also mutates `collapsed` directly and persists to `localStorage`. */\n private applyToggle(next: boolean) {\n this.dsNavToggle.emit(next);\n if (this.storageKey) {\n this.collapsed = next;\n try { localStorage.setItem(this.storageKey, String(next)); } catch { /* unavailable */ }\n }\n }\n\n private getAllItems(): PanelNavItem[] {\n return this.parsedGroups.flatMap(g => g.items);\n }\n\n private syncRovingIndex() {\n const idx = this.getAllItems().findIndex(i => i.id === this.effectiveActiveId);\n this.rovingIndex = idx >= 0 ? idx : 0;\n }\n\n private handleItemKeyDown(e: KeyboardEvent, index: number) {\n const total = this.getAllItems().length;\n let next: number;\n switch (e.key) {\n case 'ArrowDown': e.preventDefault(); next = (index + 1) % total; break;\n case 'ArrowUp': e.preventDefault(); next = (index - 1 + total) % total; break;\n case 'Home': e.preventDefault(); next = 0; break;\n case 'End': e.preventDefault(); next = total - 1; break;\n default: return;\n }\n this.rovingIndex = next;\n const items = Array.from(\n this.el.querySelectorAll<HTMLElement>('.panel-nav__body .panel-nav__item')\n );\n items[next]?.focus();\n }\n\n private checkScroll() {\n const body = this.el.querySelector('.panel-nav__body') as HTMLElement | null;\n if (!body) return;\n const remaining = body.scrollHeight - body.scrollTop - body.clientHeight;\n this.atBottom = remaining < 2;\n }\n\n private handleBodyScroll(e: Event) {\n const body = e.target as HTMLElement;\n const remaining = body.scrollHeight - body.scrollTop - body.clientHeight;\n this.atBottom = remaining < 2;\n }\n\n private handleItemClick(id: string) {\n this.dsNavSelect.emit(id);\n }\n\n private handleToggle() {\n this.applyToggle(!this.collapsed);\n }\n\n private handleFooterAction() {\n this.dsNavFooterAction.emit();\n }\n\n private handleUserAction() {\n this.dsNavUserAction.emit();\n }\n\n private clearEdgeOverlayTimer() {\n if (this.edgeOverlayTimer !== null) {\n window.clearTimeout(this.edgeOverlayTimer);\n this.edgeOverlayTimer = null;\n }\n }\n\n private handleResizeHandleMouseEnter() {\n this.clearEdgeOverlayTimer();\n this.edgeOverlayTimer = window.setTimeout(() => {\n this.showEdgeOverlay = true;\n this.edgeOverlayTimer = null;\n }, 500);\n }\n\n private handleResizeHandleMouseLeave() {\n if (this.isDragging) return;\n this.clearEdgeOverlayTimer();\n this.showEdgeOverlay = false;\n }\n\n private handleResizeHandleMouseDown(e: MouseEvent) {\n e.preventDefault();\n e.stopPropagation();\n\n const wasCollapsed = this.collapsed || this.viewportNarrow;\n this.isDragging = true;\n this.dragStartX = e.clientX;\n this.didSnap = false;\n this.lastDeltaX = 0;\n this.clearEdgeOverlayTimer();\n this.showEdgeOverlay = false;\n\n document.body.style.cursor = 'ew-resize';\n document.body.style.userSelect = 'none';\n\n const onMove = (ev: MouseEvent) => {\n const deltaX = ev.clientX - this.dragStartX;\n this.lastDeltaX = Math.abs(deltaX);\n if (this.didSnap) return;\n if (!wasCollapsed && deltaX < -8) {\n this.applyToggle(true);\n this.didSnap = true;\n } else if (wasCollapsed && deltaX > 8) {\n this.applyToggle(false);\n this.didSnap = true;\n }\n };\n\n const onUp = () => {\n if (!this.didSnap && this.lastDeltaX < 3) {\n this.applyToggle(!wasCollapsed);\n }\n this.isDragging = false;\n this.showEdgeOverlay = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n this.globalMouseMoveHandler = undefined;\n this.globalMouseUpHandler = undefined;\n };\n\n this.globalMouseMoveHandler = onMove;\n this.globalMouseUpHandler = onUp;\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n }\n\n private renderNavItem(item: PanelNavItem, idx: number, collapsed: boolean) {\n const isActive = item.id === this.effectiveActiveId;\n\n const itemContent = [\n <span class=\"panel-nav__item-icon\">\n <ds-icon name={item.icon} size=\"md\" color=\"inherit\" flag={item.flag} />\n </span>,\n <span class=\"panel-nav__item-label\">\n <span class=\"panel-nav__item-label-text\">\n <ds-text\n as=\"span\"\n variant={isActive ? 'text-body-medium-emphasis' : 'text-body-medium'}\n color=\"inherit\"\n >\n {item.label}\n </ds-text>\n </span>\n </span>,\n item.dot && <span class=\"panel-nav__item-dot\" aria-hidden=\"true\" />,\n ];\n\n const sharedProps = {\n class: { 'panel-nav__item': true, 'panel-nav__item--active': isActive },\n 'aria-current': isActive ? ('page' as const) : undefined,\n title: collapsed ? item.label : undefined,\n tabIndex: idx === this.rovingIndex ? 0 : -1,\n onClick: () => this.handleItemClick(item.id),\n onKeyDown: (e: KeyboardEvent) => this.handleItemKeyDown(e, idx),\n onFocus: () => { this.rovingIndex = idx; },\n };\n\n const useAnchor = this.routerMode === 'anchor' && item.href;\n\n return useAnchor\n ? <a {...sharedProps} href={item.href}>{itemContent}</a>\n : <button {...sharedProps} type=\"button\">{itemContent}</button>;\n }\n\n render() {\n const isDashboard = this.renderedVariant === 'dashboard';\n const collapsed = this.collapsed || this.viewportNarrow;\n const { userName, userInitial } = this;\n\n const navCls: Record<string, boolean> = {\n 'panel-nav': true,\n 'panel-nav--dashboard': isDashboard,\n 'panel-nav--settings': !isDashboard,\n 'panel-nav--collapsed': collapsed,\n 'panel-nav--animating': this.isAnimating,\n 'panel-nav--at-bottom': this.atBottom,\n };\n\n return (\n <Host style={{ display: 'block', position: 'relative' }}>\n <nav class={navCls} aria-label={isDashboard ? 'Main navigation' : 'Settings navigation'}>\n\n {/* ── Header: Motive logo, reveals collapse toggle on hover ── */}\n <div class=\"panel-nav__header\">\n <button\n type=\"button\"\n class=\"panel-nav__header-btn\"\n onClick={() => this.handleToggle()}\n aria-label={collapsed ? 'Expand navigation' : 'Collapse navigation'}\n aria-expanded={collapsed ? 'false' : 'true'}\n >\n {/* Motive M mark — fades out on hover to reveal collapse toggle */}\n <span class=\"panel-nav__header-logo\" aria-hidden=\"true\">\n <svg class=\"panel-nav__m-mark\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" focusable=\"false\" aria-hidden=\"true\">\n <path d=\"M11.1159 4.31537H7.67021L2.53401 13.0703H0V15.6875H4.02716L8.24319 8.49978V15.6846H11.6342L15.8289 8.47829V15.6846H18.7122V4.3125H15.2559L11.1159 11.3648V4.31537Z\" fill=\"currentColor\"/>\n </svg>\n </span>\n {/* Collapse / expand icon — revealed on hover via CSS */}\n <span class=\"panel-nav__header-toggle\" aria-hidden=\"true\">\n <ds-icon\n name={collapsed ? 'LeftExpandB' : 'LeftCollapseB'}\n size=\"md\"\n color=\"inherit\"\n />\n </span>\n </button>\n </div>\n\n {/* ── Scrollable body ── */}\n <div class=\"panel-nav__body\" onScroll={e => this.handleBodyScroll(e)}>\n {(() => {\n let flatIdx = 0;\n return this.parsedGroups.map(group => (\n <div class=\"panel-nav__group\">\n {group.label && (\n <span class=\"panel-nav__group-label\">\n <span class=\"panel-nav__item-label-text\">\n <ds-text as=\"span\" variant=\"text-caption-emphasis\" color=\"inherit\">\n {group.label}\n </ds-text>\n </span>\n </span>\n )}\n {group.items.map(item => this.renderNavItem(item, flatIdx++, collapsed))}\n </div>\n ));\n })()}\n </div>\n\n {/* ── Footer ── */}\n <div class=\"panel-nav__footer\">\n {/* Left icon button — Gear in dashboard, Dashboard in settings */}\n <button\n type=\"button\"\n class=\"panel-nav__footer-btn\"\n title={isDashboard ? 'Settings' : 'Dashboard'}\n aria-label={isDashboard ? 'Open settings' : 'Go to dashboard'}\n onClick={() => this.handleFooterAction()}\n >\n <ds-icon name={isDashboard ? 'Gear' : 'Dashboard'} size=\"md\" color=\"inherit\" />\n </button>\n\n {/* Right user — label fades like nav items; right icon cross-fades chevron ↔ circle+initial */}\n <button\n type=\"button\"\n class=\"panel-nav__item panel-nav__footer-user\"\n aria-label={collapsed ? `User: ${userName}` : `User menu for ${userName}`}\n onClick={() => this.handleUserAction()}\n >\n <span class=\"panel-nav__item-label panel-nav__footer-user-label\">\n <span class=\"panel-nav__item-label-text\">\n <ds-text as=\"span\" variant=\"text-body-medium-emphasis\" color=\"inherit\">\n {userName}\n </ds-text>\n </span>\n </span>\n <span class=\"panel-nav__item-icon panel-nav__footer-user-icon\" aria-hidden=\"true\">\n <span class=\"panel-nav__footer-icon-expanded\">\n <ds-icon name=\"ChevronUpDown\" size=\"md\" color=\"inherit\" />\n </span>\n <span class=\"panel-nav__footer-icon-collapsed\">\n <ds-icon name=\"Circle\" size=\"md\" color=\"inherit\" />\n <span class=\"panel-nav__user-initial\">\n <ds-text as=\"span\" variant=\"text-caption-emphasis\" color=\"inherit\">\n {userInitial}\n </ds-text>\n </span>\n </span>\n </span>\n </button>\n </div>\n\n </nav>\n\n {/* Drag-to-resize handle — always rendered, hidden only when auto-collapsed by breakpoint */}\n {!this.viewportNarrow && (\n <div\n class={{\n 'panel-nav__resize-handle': true,\n 'panel-nav__resize-handle--overlay': this.showEdgeOverlay,\n }}\n onMouseEnter={() => this.handleResizeHandleMouseEnter()}\n onMouseLeave={() => this.handleResizeHandleMouseLeave()}\n onMouseDown={(e: MouseEvent) => this.handleResizeHandleMouseDown(e)}\n aria-hidden=\"true\"\n />\n )}\n </Host>\n );\n }\n}\n"],"mappings":"0IAGM,SAAUA,EAAgBC,EAAcC,GAC5C,OAAOD,IAASC,GAAQD,EAAKE,WAAW,GAAGD,KAC7C,CAGM,SAAUE,EAAsBH,EAAcI,GAClD,IAAKJ,EAAM,MAAO,GAElB,IAAIK,EAAS,GACb,IAAIC,EAAU,EAEd,IAAK,MAAMC,KAAQH,EAAO,CACxB,IAAKG,EAAKN,KAAM,SAChB,GAAIF,EAAgBC,EAAMO,EAAKN,OAASM,EAAKN,KAAKO,OAASF,EAAS,CAClED,EAASE,EAAKE,GACdH,EAAUC,EAAKN,KAAKO,M,EAIxB,OAAOH,CACT,CAGM,SAAUK,EAAoBC,GAClC,GAAIC,MAAMC,QAAQF,GAAS,OAAOA,EAClC,UAAWA,IAAW,SAAU,CAC9B,IACE,MAAMG,EAASC,KAAKC,MAAML,GAC1B,OAAOC,MAAMC,QAAQC,GAAUA,EAAS,E,CACxC,MACA,MAAO,E,EAGX,MAAO,EACT,CAEA,IAAIG,EAAkB,M,SAGNC,IACd,GAAID,EAAiB,OACrB,MAAMR,EAAK,wBACX,GAAIU,SAASC,eAAeX,GAAK,CAC/BQ,EAAkB,KAClB,M,CAEF,MAAMI,EAAQF,SAASG,cAAc,SACrCD,EAAMZ,GAAKA,EACXY,EAAME,YAAc,CAClB,gGACA,yFACAC,KAAK,MACPL,SAASM,KAAKC,YAAYL,GAC1BJ,EAAkB,IACpB,CCzDA,MAAMU,EAAc,IAAM,smdCmB1B,MAAMC,EAAgB,IAAIC,QAC1B,MAAMC,EAAc,IAAID,QAMxB,SAASE,EAAeC,EAAeC,GACrC,MAAMC,EAAIF,EAAMG,OAChB,MAAMC,EAAMC,WAAWH,GACvB,GAAII,OAAOC,MAAMH,GAAM,OAAOH,EAC9B,GAAI,SAASO,KAAKN,GAAI,OAAOE,EAC7B,GAAI,QAAQI,KAAKN,GAAI,OAAOE,EAAM,IAClC,OAAOA,CACT,C,MA4BaK,EAAQC,EAAA,MAAAD,UAAAE,EALrB,WAAAC,CAAAC,G,4NAOUC,KAAAC,QAA2B,YAM3BD,KAAAE,sBAAiC,MAGjCF,KAAAnC,OAAmC,KAKnCmC,KAAAG,WAAiC,SAGjCH,KAAAI,SAAmB,GAKFJ,KAAAK,UAAqB,MAGtCL,KAAAM,WAAqB,EAKrBN,KAAAO,WAAqB,GAKrBP,KAAAQ,WAAqB,GAGrBR,KAAAS,SAAmB,GAGnBT,KAAAU,YAAsB,GAkBbV,KAAAW,gBAAmC,YAEnCX,KAAAY,aAAgC,GAChCZ,KAAAa,SAAW,MACXb,KAAAc,YAAc,MACdd,KAAAe,YAAsB,EACtBf,KAAAgB,eAA0B,MAC1BhB,KAAAiB,mBAA6B,GAMtCjB,KAAAkB,WAAa,MACblB,KAAAmB,WAAa,EACbnB,KAAAoB,QAAU,MACVpB,KAAAqB,WAAa,EACbrB,KAAAsB,iBAAkC,KAIzBtB,KAAAuB,gBAAkB,KAsdpC,CAldC,qBAAYC,GACV,OAAOxB,KAAKiB,oBAAsBjB,KAAKI,Q,CAKzC,iBAAAqB,GACEzB,KAAK0B,wB,CAIP,kBAAAC,GACE3B,KAAK4B,2BACL,GAAI5B,KAAKM,WAAa,EAAGN,KAAK6B,uB,CAIhC,cAAAC,CAAeC,GACb/B,KAAKY,aAAehD,EAAoBmE,GACxC/B,KAAKgC,kBACLhC,KAAKiC,mB,CAKP,gBAAAC,GACElC,KAAKgC,iB,CAIP,kBAAAG,GACEnC,KAAKiC,mB,CAIP,qBAAMG,CAAgBC,GAGpB,GAAIrC,KAAKE,sBAAuB,CAC9BF,KAAKW,gBAAkB0B,EACvB,M,CAKFvD,EAAcwD,IAAItC,OAAOuC,iBACzBzD,EAAc0D,OAAOxC,MAErB,MAAMyC,EAAMpE,SACZ,UAAWoE,EAAIC,sBAAwB,WAAY,CACjD1C,KAAKW,gBAAkB0B,EACvB,M,CAGFjE,IAEA,MAAMuE,EAAM3C,KAAK4C,GAAGC,cAAc,0BAClC,MAAMC,EAAOH,GAAKI,wBAClB,MAAMC,EAAIF,EAAOG,KAAKC,MAAMJ,EAAKK,KAAOL,EAAKM,MAAQ,GAAKH,KAAKC,MAAMG,OAAOC,WAAa,GACzF,MAAMC,EAAIT,EAAOG,KAAKC,MAAMJ,EAAKU,IAAMV,EAAKW,OAAS,GAAKR,KAAKC,MAAMG,OAAOK,YAAc,GAC1F,MAAMC,EAAOV,KAAKW,KAAKX,KAAKY,MAC1BZ,KAAKa,IAAId,EAAGK,OAAOC,WAAaN,GAChCC,KAAKa,IAAIP,EAAGF,OAAOK,YAAcH,KAGnClF,SAAS0F,gBAAgBxF,MAAMyF,YAAY,SAAU,GAAGhB,OACxD3E,SAAS0F,gBAAgBxF,MAAMyF,YAAY,SAAU,GAAGT,OAExD,MAAMU,EAAaxB,EAAIC,qBAAoB,IACzC,IAAIwB,SAAcC,IAChBnF,EAAYoF,IAAIpE,KAAMmE,GACtBnE,KAAKW,gBAAkB0B,CAAM,MAIjCvD,EAAcsF,IAAIpE,KAAMiE,GACxBA,EAAWI,SAASC,SAAQ,KAC1B,GAAIxF,EAAcwD,IAAItC,QAAUiE,EAAYnF,EAAc0D,OAAOxC,MACjEhB,EAAYwD,OAAOxC,KAAK,IAG1BiE,EAAWM,MAAMC,MAAK,KACpB,MAAMC,EAAWC,iBAAiBrG,SAAS0F,iBACxCY,iBAAiB,sCAAsCtF,OAC1D,MAAMuF,EAAW3F,EAAewF,EAAU,KAC1CpG,SAAS0F,gBAAgBc,QACvB,CAAEC,SAAU,CAAC,iBAAiB9B,OAAOO,OAAQ,UAAUI,UAAaX,OAAOO,SAC3E,CAAEqB,WAAUG,OAAQ,cAAeC,KAAM,WAAYC,cAAe,+BACrE,IACAC,OAAM,Q,CAGX,iBAAAC,GACEnF,KAAKW,gBAAkBX,KAAKC,QAC5B,GAAID,KAAKO,WAAY,CACnB,IACE,MAAM6E,EAASC,aAAaC,QAAQtF,KAAKO,YACzC,GAAI6E,IAAW,KAAMpF,KAAKK,UAAY+E,IAAW,M,CACjD,MAAM,C,CAEVpF,KAAK8B,eAAe9B,KAAKnC,QACzBmC,KAAKiC,mB,CAGP,gBAAAsD,GACEvF,KAAKwF,cACL,GAAIxF,KAAKM,WAAa,EAAGN,KAAK6B,uB,CAGhC,kBAAA4D,GAGE,MAAMtB,EAAUnF,EAAYsD,IAAItC,MAChC,GAAImE,EAAS,CACXnF,EAAYwD,OAAOxC,MACnBmE,G,EAIJ,oBAAAuB,GACE1F,KAAK4B,2BACL5B,KAAK2F,wBACL,GAAI3F,KAAK4F,uBAAwB,CAC/BvC,OAAOwC,oBAAoB,YAAa7F,KAAK4F,uB,CAE/C,GAAI5F,KAAK8F,qBAAsB,CAC7BzC,OAAOwC,oBAAoB,UAAW7F,KAAK8F,qB,EAIvC,sBAAApE,GACN1B,KAAKc,YAAc,KACnB,MAAMiF,EAAQ/F,KAAK4C,GAAGC,cAAc,cACpC,GAAI7C,KAAKgG,qBAAsB,CAC7BD,GAAOF,oBAAoB,gBAAiB7F,KAAKgG,qB,CAEnDhG,KAAKgG,qBAAwBC,IAC3B,GAAIA,EAAEC,eAAiB,QAAS,CAC9BlG,KAAKc,YAAc,MACnBiF,GAAOF,oBAAoB,gBAAiB7F,KAAKgG,qB,GAGrDD,GAAOI,iBAAiB,gBAAiBnG,KAAKgG,qB,CAGxC,qBAAAnE,GACN7B,KAAKgB,eAAiBqC,OAAOC,WAAatD,KAAKM,WAC/CN,KAAKoG,eAAiB,IAAIC,gBAAe,KACvCrG,KAAKgB,eAAiBqC,OAAOC,WAAatD,KAAKM,UAAU,IAE3DN,KAAKoG,eAAeE,QAAQjI,SAAS0F,gB,CAG/B,wBAAAnC,GACN5B,KAAKoG,gBAAgBG,aACrBvG,KAAKoG,eAAiBI,S,CAKhB,iBAAAvE,GACN,IAAKjC,KAAKQ,WAAY,CACpBR,KAAKiB,mBAAqB,GAC1B,M,CAEFjB,KAAKiB,mBAAqB5D,EAAsB2C,KAAKQ,WAAYR,KAAKyG,c,CAKhE,WAAAC,CAAYC,GAClB3G,KAAK4G,YAAYC,KAAKF,GACtB,GAAI3G,KAAKO,WAAY,CACnBP,KAAKK,UAAYsG,EACjB,IAAMtB,aAAayB,QAAQ9G,KAAKO,WAAYwG,OAAOJ,G,CAAU,MAAM,C,EAI/D,WAAAF,GACN,OAAOzG,KAAKY,aAAaoG,SAAQC,GAAKA,EAAE3J,O,CAGlC,eAAA0E,GACN,MAAMkF,EAAMlH,KAAKyG,cAAcU,WAAUC,GAAKA,EAAEzJ,KAAOqC,KAAKwB,oBAC5DxB,KAAKe,YAAcmG,GAAO,EAAIA,EAAM,C,CAG9B,iBAAAG,CAAkBpB,EAAkBqB,GAC1C,MAAMC,EAAQvH,KAAKyG,cAAc/I,OACjC,IAAIiJ,EACJ,OAAQV,EAAEuB,KACR,IAAK,YAAavB,EAAEwB,iBAAkBd,GAAQW,EAAQ,GAAKC,EAAO,MAClE,IAAK,UAAatB,EAAEwB,iBAAkBd,GAAQW,EAAQ,EAAIC,GAASA,EAAO,MAC1E,IAAK,OAAatB,EAAEwB,iBAAkBd,EAAO,EAAG,MAChD,IAAK,MAAaV,EAAEwB,iBAAkBd,EAAOY,EAAQ,EAAG,MACxD,QAAS,OAEXvH,KAAKe,YAAc4F,EACnB,MAAMrJ,EAAQQ,MAAM4J,KAClB1H,KAAK4C,GAAG+E,iBAA8B,sCAExCrK,EAAMqJ,IAAOiB,O,CAGP,WAAApC,GACN,MAAMqC,EAAO7H,KAAK4C,GAAGC,cAAc,oBACnC,IAAKgF,EAAM,OACX,MAAMC,EAAYD,EAAKE,aAAeF,EAAKG,UAAYH,EAAKI,aAC5DjI,KAAKa,SAAWiH,EAAY,C,CAGtB,gBAAAI,CAAiBjC,GACvB,MAAM4B,EAAO5B,EAAEkC,OACf,MAAML,EAAYD,EAAKE,aAAeF,EAAKG,UAAYH,EAAKI,aAC5DjI,KAAKa,SAAWiH,EAAY,C,CAGtB,eAAAM,CAAgBzK,GACtBqC,KAAKqI,YAAYxB,KAAKlJ,E,CAGhB,YAAA2K,GACNtI,KAAK0G,aAAa1G,KAAKK,U,CAGjB,kBAAAkI,GACNvI,KAAKwI,kBAAkB3B,M,CAGjB,gBAAA4B,GACNzI,KAAK0I,gBAAgB7B,M,CAGf,qBAAAlB,GACN,GAAI3F,KAAKsB,mBAAqB,KAAM,CAClC+B,OAAOsF,aAAa3I,KAAKsB,kBACzBtB,KAAKsB,iBAAmB,I,EAIpB,4BAAAsH,GACN5I,KAAK2F,wBACL3F,KAAKsB,iBAAmB+B,OAAOwF,YAAW,KACxC7I,KAAKuB,gBAAkB,KACvBvB,KAAKsB,iBAAmB,IAAI,GAC3B,I,CAGG,4BAAAwH,GACN,GAAI9I,KAAKkB,WAAY,OACrBlB,KAAK2F,wBACL3F,KAAKuB,gBAAkB,K,CAGjB,2BAAAwH,CAA4B9C,GAClCA,EAAEwB,iBACFxB,EAAE+C,kBAEF,MAAMC,EAAejJ,KAAKK,WAAaL,KAAKgB,eAC5ChB,KAAKkB,WAAa,KAClBlB,KAAKmB,WAAa8E,EAAEiD,QACpBlJ,KAAKoB,QAAU,MACfpB,KAAKqB,WAAa,EAClBrB,KAAK2F,wBACL3F,KAAKuB,gBAAkB,MAEvBlD,SAASwJ,KAAKtJ,MAAM4K,OAAS,YAC7B9K,SAASwJ,KAAKtJ,MAAM6K,WAAa,OAEjC,MAAMC,EAAUC,IACd,MAAMC,EAASD,EAAGJ,QAAUlJ,KAAKmB,WACjCnB,KAAKqB,WAAa4B,KAAKuG,IAAID,GAC3B,GAAIvJ,KAAKoB,QAAS,OAClB,IAAK6H,GAAgBM,GAAS,EAAI,CAChCvJ,KAAK0G,YAAY,MACjB1G,KAAKoB,QAAU,I,MACV,GAAI6H,GAAgBM,EAAS,EAAG,CACrCvJ,KAAK0G,YAAY,OACjB1G,KAAKoB,QAAU,I,GAInB,MAAMqI,EAAO,KACX,IAAKzJ,KAAKoB,SAAWpB,KAAKqB,WAAa,EAAG,CACxCrB,KAAK0G,aAAauC,E,CAEpBjJ,KAAKkB,WAAa,MAClBlB,KAAKuB,gBAAkB,MACvBlD,SAASwJ,KAAKtJ,MAAM4K,OAAS,GAC7B9K,SAASwJ,KAAKtJ,MAAM6K,WAAa,GACjC/F,OAAOwC,oBAAoB,YAAawD,GACxChG,OAAOwC,oBAAoB,UAAW4D,GACtCzJ,KAAK4F,uBAAyBY,UAC9BxG,KAAK8F,qBAAuBU,SAAS,EAGvCxG,KAAK4F,uBAAyByD,EAC9BrJ,KAAK8F,qBAAuB2D,EAC5BpG,OAAO8C,iBAAiB,YAAakD,GACrChG,OAAO8C,iBAAiB,UAAWsD,E,CAG7B,aAAAC,CAAcjM,EAAoByJ,EAAa7G,GACrD,MAAMsJ,EAAWlM,EAAKE,KAAOqC,KAAKwB,kBAElC,MAAMoI,EAAc,CAClBC,EAAA,QAAMC,MAAM,wBACVD,EAAA,WAASE,KAAMtM,EAAKuM,KAAMC,KAAK,KAAKC,MAAM,UAAUC,KAAM1M,EAAK0M,QAEjEN,EAAA,QAAMC,MAAM,yBACVD,EAAA,QAAMC,MAAM,8BACVD,EAAA,WACEO,GAAG,OACHnK,QAAS0J,EAAW,4BAA8B,mBAClDO,MAAM,WAELzM,EAAK4M,SAIZ5M,EAAK6M,KAAOT,EAAA,QAAMC,MAAM,sBAAqB,cAAa,UAG5D,MAAMS,EAAc,CAClBT,MAAO,CAAE,kBAAmB,KAAM,0BAA2BH,GAC7D,eAAgBA,EAAY,OAAmBnD,UAC/CgE,MAAOnK,EAAY5C,EAAK4M,MAAQ7D,UAChCiE,SAAUvD,IAAQlH,KAAKe,YAAc,GAAI,EACzC2J,QAAS,IAAM1K,KAAKoI,gBAAgB3K,EAAKE,IACzCgN,UAAY1E,GAAqBjG,KAAKqH,kBAAkBpB,EAAGiB,GAC3D0D,QAAS,KAAQ5K,KAAKe,YAAcmG,CAAG,GAGzC,MAAM2D,EAAY7K,KAAKG,aAAe,UAAY1C,EAAKN,KAEvD,OAAO0N,EACHhB,EAAA,QAAOU,EAAapN,KAAMM,EAAKN,MAAOyM,GACtCC,EAAA,aAAYU,EAAaO,KAAK,UAAUlB,E,CAG9C,MAAAmB,GACE,MAAMC,EAAchL,KAAKW,kBAAoB,YAC7C,MAAMN,EAAYL,KAAKK,WAAaL,KAAKgB,eACzC,MAAMP,SAAEA,EAAQC,YAAEA,GAAgBV,KAElC,MAAMiL,EAAkC,CACtC,YAAa,KACb,uBAAwBD,EACxB,uBAAwBA,EACxB,uBAAwB3K,EACxB,uBAAwBL,KAAKc,YAC7B,uBAAwBd,KAAKa,UAG/B,OACEgJ,EAACqB,EAAI,CAAA1D,IAAA,2CAACjJ,MAAO,CAAE4M,QAAS,QAASC,SAAU,aACzCvB,EAAA,OAAArC,IAAA,2CAAKsC,MAAOmB,EAAM,aAAcD,EAAc,kBAAoB,uBAGhEnB,EAAA,OAAArC,IAAA,2CAAKsC,MAAM,qBACTD,EAAA,UAAArC,IAAA,2CACEsD,KAAK,SACLhB,MAAM,wBACNY,QAAS,IAAM1K,KAAKsI,eAAc,aACtBjI,EAAY,oBAAsB,sBAAqB,gBACpDA,EAAY,QAAU,QAGrCwJ,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,yBAAwB,cAAa,QAC/CD,EAAA,OAAArC,IAAA,2CAAKsC,MAAM,oBAAoBuB,QAAQ,YAAYrG,KAAK,OAAOsG,MAAM,6BAA6BC,UAAU,QAAO,cAAa,QAC9H1B,EAAA,QAAArC,IAAA,2CAAMgE,EAAE,qKAAqKxG,KAAK,mBAItL6E,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,2BAA0B,cAAa,QACjDD,EAAA,WAAArC,IAAA,2CACEuC,KAAM1J,EAAY,cAAgB,gBAClC4J,KAAK,KACLC,MAAM,eAOdL,EAAA,OAAArC,IAAA,2CAAKsC,MAAM,kBAAkB2B,SAAUxF,GAAKjG,KAAKkI,iBAAiBjC,IAC/D,MACC,IAAIyF,EAAU,EACd,OAAO1L,KAAKY,aAAa+K,KAAIC,GAC3B/B,EAAA,OAAKC,MAAM,oBACR8B,EAAMvB,OACLR,EAAA,QAAMC,MAAM,0BACVD,EAAA,QAAMC,MAAM,8BACVD,EAAA,WAASO,GAAG,OAAOnK,QAAQ,wBAAwBiK,MAAM,WACtD0B,EAAMvB,SAKduB,EAAMtO,MAAMqO,KAAIlO,GAAQuC,KAAK0J,cAAcjM,EAAMiO,IAAWrL,OAGlE,EAhBA,IAoBHwJ,EAAA,OAAArC,IAAA,2CAAKsC,MAAM,qBAETD,EAAA,UAAArC,IAAA,2CACEsD,KAAK,SACLhB,MAAM,wBACNU,MAAOQ,EAAc,WAAa,YAAW,aACjCA,EAAc,gBAAkB,kBAC5CN,QAAS,IAAM1K,KAAKuI,sBAEpBsB,EAAA,WAAArC,IAAA,2CAASuC,KAAMiB,EAAc,OAAS,YAAaf,KAAK,KAAKC,MAAM,aAIrEL,EAAA,UAAArC,IAAA,2CACEsD,KAAK,SACLhB,MAAM,yCAAwC,aAClCzJ,EAAY,SAASI,IAAa,iBAAiBA,IAC/DiK,QAAS,IAAM1K,KAAKyI,oBAEpBoB,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,sDACVD,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,8BACVD,EAAA,WAAArC,IAAA,2CAAS4C,GAAG,OAAOnK,QAAQ,4BAA4BiK,MAAM,WAC1DzJ,KAIPoJ,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,mDAAkD,cAAa,QACzED,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,mCACVD,EAAA,WAAArC,IAAA,2CAASuC,KAAK,gBAAgBE,KAAK,KAAKC,MAAM,aAEhDL,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,oCACVD,EAAA,WAAArC,IAAA,2CAASuC,KAAK,SAASE,KAAK,KAAKC,MAAM,YACvCL,EAAA,QAAArC,IAAA,2CAAMsC,MAAM,2BACVD,EAAA,WAAArC,IAAA,2CAAS4C,GAAG,OAAOnK,QAAQ,wBAAwBiK,MAAM,WACtDxJ,UAWbV,KAAKgB,gBACL6I,EAAA,OAAArC,IAAA,2CACEsC,MAAO,CACL,2BAA4B,KAC5B,oCAAqC9J,KAAKuB,iBAE5CsK,aAAc,IAAM7L,KAAK4I,+BACzBkD,aAAc,IAAM9L,KAAK8I,+BACzBiD,YAAc9F,GAAkBjG,KAAK+I,4BAA4B9C,GAAE,cACvD,S","ignoreList":[]}
|
|
@@ -31,3 +31,16 @@ export interface SetPlatformOptions {
|
|
|
31
31
|
rel?: (el: EventTarget, eventName: string, listener: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions) => void;
|
|
32
32
|
}
|
|
33
33
|
export declare const setPlatformOptions: (opts: SetPlatformOptions) => void;
|
|
34
|
+
// --- nav type re-exports (patch-index-types.mjs) ---
|
|
35
|
+
export type {
|
|
36
|
+
PanelNavVariant,
|
|
37
|
+
PanelNavRouterMode,
|
|
38
|
+
PanelNavItem,
|
|
39
|
+
PanelNavGroup,
|
|
40
|
+
} from '../types/components/PanelNav/PanelNav';
|
|
41
|
+
export type {
|
|
42
|
+
BarNavBackground,
|
|
43
|
+
BarNavTab,
|
|
44
|
+
BarNavActionItem,
|
|
45
|
+
} from '../types/components/BarNav/BarNav';
|
|
46
|
+
|
|
@@ -21,16 +21,20 @@ export interface BarNavActionItem {
|
|
|
21
21
|
export declare class BarNav {
|
|
22
22
|
/**
|
|
23
23
|
* Tab items for the left section.
|
|
24
|
-
* Set via JS property: `el.tabs = [...]
|
|
24
|
+
* Set via JS property: `el.tabs = [...]`. Replace the array reference to update.
|
|
25
25
|
*/
|
|
26
26
|
tabs: BarNavTab[];
|
|
27
|
-
/**
|
|
27
|
+
/** JSON fallback for `tabs` — useful when framework bindings don't propagate arrays. */
|
|
28
|
+
tabsJson: string;
|
|
29
|
+
/** ID of the currently active tab. Overridden when `currentUrl` + `basePath` are set. */
|
|
28
30
|
value: string;
|
|
29
31
|
/**
|
|
30
32
|
* Action items rendered in the right section.
|
|
31
|
-
* Set via JS property: `el.actions = [...]
|
|
33
|
+
* Set via JS property: `el.actions = [...]`. Replace the array reference to update.
|
|
32
34
|
*/
|
|
33
35
|
actions: BarNavActionItem[];
|
|
36
|
+
/** JSON fallback for `actions` — useful when framework bindings don't propagate arrays. */
|
|
37
|
+
actionsJson: string;
|
|
34
38
|
/**
|
|
35
39
|
* Fallback heading shown when no tabs are provided.
|
|
36
40
|
* When tabs are present the heading is hidden.
|
|
@@ -38,6 +42,10 @@ export declare class BarNav {
|
|
|
38
42
|
heading: string | undefined;
|
|
39
43
|
/** Surface background variant. */
|
|
40
44
|
background: BarNavBackground;
|
|
45
|
+
/** Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`. */
|
|
46
|
+
basePath: string;
|
|
47
|
+
/** Current route URL. When set with `basePath`, the active tab is derived automatically. */
|
|
48
|
+
currentUrl: string;
|
|
41
49
|
/** Emitted when the active tab changes. Detail = tab id. */
|
|
42
50
|
dsTabChange: EventEmitter<string>;
|
|
43
51
|
/** Emitted when an action button is toggled. Detail = { id, selected }. */
|
|
@@ -45,6 +53,15 @@ export declare class BarNav {
|
|
|
45
53
|
id: string;
|
|
46
54
|
selected: boolean;
|
|
47
55
|
}>;
|
|
56
|
+
private resolvedTabs;
|
|
57
|
+
private resolvedActions;
|
|
58
|
+
private urlDerivedValue;
|
|
59
|
+
private hideTabsForDetailRoute;
|
|
60
|
+
private get effectiveValue();
|
|
61
|
+
onPropsChange(): void;
|
|
62
|
+
onUrlChange(): void;
|
|
63
|
+
componentWillLoad(): void;
|
|
64
|
+
private syncValueFromUrl;
|
|
48
65
|
private handleTabChange;
|
|
49
66
|
private handleActionChange;
|
|
50
67
|
render(): any;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BarNavTab } from './BarNav';
|
|
2
|
+
export interface BarNavUrlState {
|
|
3
|
+
/** Tab id derived from the URL, or empty when none applies. */
|
|
4
|
+
value: string;
|
|
5
|
+
/** When true, tabs should be hidden (e.g. non-tab child routes like detail pages). */
|
|
6
|
+
hideTabs: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** Derive BarNav tab selection from `currentUrl` relative to `basePath`.
|
|
9
|
+
* Mirrors motive-webapp-lab `resolveBarNavState` tab-selection semantics. */
|
|
10
|
+
export declare function deriveBarNavValueFromUrl(path: string, basePath: string, tabs: BarNavTab[]): BarNavUrlState;
|
|
11
|
+
/** Parse tabs/actions from either a JSON attribute string or a JS property array. */
|
|
12
|
+
export declare function parseJsonArrayProp<T>(value: string | T[] | undefined, fallback: T[]): T[];
|
|
13
|
+
//# sourceMappingURL=bar-nav-utils.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from '../../stencil-public-runtime';
|
|
2
2
|
export type PanelNavVariant = 'dashboard' | 'settings';
|
|
3
|
+
export type PanelNavRouterMode = 'anchor' | 'event';
|
|
3
4
|
export interface PanelNavItem {
|
|
4
5
|
id: string;
|
|
5
6
|
icon: string;
|
|
@@ -7,9 +8,8 @@ export interface PanelNavItem {
|
|
|
7
8
|
/** Show a notification dot badge on the item */
|
|
8
9
|
dot?: boolean;
|
|
9
10
|
flag?: boolean;
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* navigation automatically. `dsNavSelect` still fires on click. */
|
|
11
|
+
/** Route path used for `currentUrl` matching. In `anchor` mode also sets `<a href>`.
|
|
12
|
+
* In `event` mode navigation is delegated to the host via `dsNavSelect`. */
|
|
13
13
|
href?: string;
|
|
14
14
|
}
|
|
15
15
|
export interface PanelNavGroup {
|
|
@@ -25,8 +25,12 @@ export declare class PanelNav {
|
|
|
25
25
|
* the host app orchestrates the page transition itself (e.g. Angular Router's
|
|
26
26
|
* `withViewTransitions`), so the two don't fight or nest. */
|
|
27
27
|
disableViewTransition: boolean;
|
|
28
|
-
/**
|
|
29
|
-
groups: string;
|
|
28
|
+
/** Nav groups — set via JS property (`el.groups = [...]`) or JSON string attribute. */
|
|
29
|
+
groups: string | PanelNavGroup[];
|
|
30
|
+
/** How items with `href` render:
|
|
31
|
+
* - `anchor` (default): native `<a href>` — works with routers that intercept anchors.
|
|
32
|
+
* - `event`: always `<button>`; host handles navigation via `dsNavSelect`. */
|
|
33
|
+
routerMode: PanelNavRouterMode;
|
|
30
34
|
/** ID of the currently active/selected nav item. Overridden by `currentUrl` matching when set. */
|
|
31
35
|
activeId: string;
|
|
32
36
|
/** Whether the nav is in collapsed (icon-only) state.
|
|
@@ -41,7 +45,7 @@ export declare class PanelNav {
|
|
|
41
45
|
storageKey: string;
|
|
42
46
|
/** Current route URL (e.g. `window.location.pathname` or the router's active URL).
|
|
43
47
|
* When set the component derives the active item by matching item `href` values
|
|
44
|
-
* against this string (longest prefix wins), overriding `activeId`. */
|
|
48
|
+
* against this string (longest segment-boundary prefix wins), overriding `activeId`. */
|
|
45
49
|
currentUrl: string;
|
|
46
50
|
/** Display name for the footer user section */
|
|
47
51
|
userName: string;
|
|
@@ -53,6 +57,8 @@ export declare class PanelNav {
|
|
|
53
57
|
dsNavToggle: EventEmitter<boolean>;
|
|
54
58
|
/** Emitted when the footer left button (gear / dashboard) is clicked. */
|
|
55
59
|
dsNavFooterAction: EventEmitter<void>;
|
|
60
|
+
/** Emitted when the footer user button is clicked. */
|
|
61
|
+
dsNavUserAction: EventEmitter<void>;
|
|
56
62
|
el: HTMLElement;
|
|
57
63
|
/** Mirrors `variant` but is only updated inside the VT callback so the
|
|
58
64
|
* View Transition captures a clean before/after snapshot. */
|
|
@@ -78,7 +84,7 @@ export declare class PanelNav {
|
|
|
78
84
|
private get effectiveActiveId();
|
|
79
85
|
onCollapsedChange(): void;
|
|
80
86
|
onBreakpointChange(): void;
|
|
81
|
-
onGroupsChange(val: string): void;
|
|
87
|
+
onGroupsChange(val: string | PanelNavGroup[]): void;
|
|
82
88
|
onActiveIdChange(): void;
|
|
83
89
|
onCurrentUrlChange(): void;
|
|
84
90
|
onVariantChange(newVal: PanelNavVariant): Promise<void>;
|
|
@@ -90,7 +96,7 @@ export declare class PanelNav {
|
|
|
90
96
|
private connectResizeObserver;
|
|
91
97
|
private disconnectResizeObserver;
|
|
92
98
|
/** Derive active ID from the current URL by matching item `href` values.
|
|
93
|
-
* Uses longest-prefix match
|
|
99
|
+
* Uses longest segment-boundary prefix match. */
|
|
94
100
|
private syncActiveFromUrl;
|
|
95
101
|
/** Centralised toggle: always emits `dsNavToggle`; when `storageKey` is set
|
|
96
102
|
* also mutates `collapsed` directly and persists to `localStorage`. */
|
|
@@ -103,6 +109,7 @@ export declare class PanelNav {
|
|
|
103
109
|
private handleItemClick;
|
|
104
110
|
private handleToggle;
|
|
105
111
|
private handleFooterAction;
|
|
112
|
+
private handleUserAction;
|
|
106
113
|
private clearEdgeOverlayTimer;
|
|
107
114
|
private handleResizeHandleMouseEnter;
|
|
108
115
|
private handleResizeHandleMouseLeave;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export type { PanelNavVariant, PanelNavItem, PanelNavGroup } from './PanelNav';
|
|
1
|
+
export type { PanelNavVariant, PanelNavRouterMode, PanelNavItem, PanelNavGroup } from './PanelNav';
|
|
2
|
+
export { ensurePanelNavVtStyle } from './panel-nav-utils';
|
|
2
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PanelNavGroup, PanelNavItem } from './PanelNav';
|
|
2
|
+
/** Whether `path` matches `href` at a segment boundary (exact or child path). */
|
|
3
|
+
export declare function hrefMatchesPath(path: string, href: string): boolean;
|
|
4
|
+
/** Derive the active nav item id from a URL using longest segment-boundary prefix match. */
|
|
5
|
+
export declare function deriveActiveIdFromUrl(path: string, items: PanelNavItem[]): string;
|
|
6
|
+
/** Parse `groups` from either a JSON attribute string or a JS property array. */
|
|
7
|
+
export declare function parsePanelNavGroups(groups: string | unknown): PanelNavGroup[];
|
|
8
|
+
/** Inject view-transition suppress styles once per document (shared by PanelNav + hosts). */
|
|
9
|
+
export declare function ensurePanelNavVtStyle(): void;
|
|
10
|
+
//# sourceMappingURL=panel-nav-utils.d.ts.map
|
|
@@ -22,7 +22,7 @@ import { InputType } from "./components/Input/Input";
|
|
|
22
22
|
import { LabelWrapSize } from "./components/LabelWrap/LabelWrap";
|
|
23
23
|
import { MenuAlign, MenuItemData, MenuSection, MenuSide } from "./components/Menu/Menu";
|
|
24
24
|
import { ModalWidth } from "./components/Modal/Modal";
|
|
25
|
-
import { PanelNavVariant } from "./components/PanelNav/PanelNav";
|
|
25
|
+
import { PanelNavGroup, PanelNavRouterMode, PanelNavVariant } from "./components/PanelNav/PanelNav";
|
|
26
26
|
import { RadioOption } from "./components/RadioGroup/RadioGroup";
|
|
27
27
|
import { ScrollbarVariant } from "./components/Scrollbar/Scrollbar";
|
|
28
28
|
import { SelectOption } from "./components/Select/Select";
|
|
@@ -54,7 +54,7 @@ export { InputType } from "./components/Input/Input";
|
|
|
54
54
|
export { LabelWrapSize } from "./components/LabelWrap/LabelWrap";
|
|
55
55
|
export { MenuAlign, MenuItemData, MenuSection, MenuSide } from "./components/Menu/Menu";
|
|
56
56
|
export { ModalWidth } from "./components/Modal/Modal";
|
|
57
|
-
export { PanelNavVariant } from "./components/PanelNav/PanelNav";
|
|
57
|
+
export { PanelNavGroup, PanelNavRouterMode, PanelNavVariant } from "./components/PanelNav/PanelNav";
|
|
58
58
|
export { RadioOption } from "./components/RadioGroup/RadioGroup";
|
|
59
59
|
export { ScrollbarVariant } from "./components/Scrollbar/Scrollbar";
|
|
60
60
|
export { SelectOption } from "./components/Select/Select";
|
|
@@ -133,26 +133,46 @@ export namespace Components {
|
|
|
133
133
|
}
|
|
134
134
|
interface DsBarNav {
|
|
135
135
|
/**
|
|
136
|
-
* Action items rendered in the right section. Set via JS property: `el.actions = [...]
|
|
136
|
+
* Action items rendered in the right section. Set via JS property: `el.actions = [...]`. Replace the array reference to update.
|
|
137
137
|
* @default []
|
|
138
138
|
*/
|
|
139
139
|
"actions": BarNavActionItem[];
|
|
140
|
+
/**
|
|
141
|
+
* JSON fallback for `actions` — useful when framework bindings don't propagate arrays.
|
|
142
|
+
* @default ''
|
|
143
|
+
*/
|
|
144
|
+
"actionsJson": string;
|
|
140
145
|
/**
|
|
141
146
|
* Surface background variant.
|
|
142
147
|
* @default 'secondary'
|
|
143
148
|
*/
|
|
144
149
|
"background": BarNavBackground;
|
|
150
|
+
/**
|
|
151
|
+
* Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`.
|
|
152
|
+
* @default ''
|
|
153
|
+
*/
|
|
154
|
+
"basePath": string;
|
|
155
|
+
/**
|
|
156
|
+
* Current route URL. When set with `basePath`, the active tab is derived automatically.
|
|
157
|
+
* @default ''
|
|
158
|
+
*/
|
|
159
|
+
"currentUrl": string;
|
|
145
160
|
/**
|
|
146
161
|
* Fallback heading shown when no tabs are provided. When tabs are present the heading is hidden.
|
|
147
162
|
*/
|
|
148
163
|
"heading": string | undefined;
|
|
149
164
|
/**
|
|
150
|
-
* Tab items for the left section. Set via JS property: `el.tabs = [...]
|
|
165
|
+
* Tab items for the left section. Set via JS property: `el.tabs = [...]`. Replace the array reference to update.
|
|
151
166
|
* @default []
|
|
152
167
|
*/
|
|
153
168
|
"tabs": BarNavTab[];
|
|
154
169
|
/**
|
|
155
|
-
*
|
|
170
|
+
* JSON fallback for `tabs` — useful when framework bindings don't propagate arrays.
|
|
171
|
+
* @default ''
|
|
172
|
+
*/
|
|
173
|
+
"tabsJson": string;
|
|
174
|
+
/**
|
|
175
|
+
* ID of the currently active tab. Overridden when `currentUrl` + `basePath` are set.
|
|
156
176
|
* @default ''
|
|
157
177
|
*/
|
|
158
178
|
"value": string;
|
|
@@ -508,7 +528,7 @@ export namespace Components {
|
|
|
508
528
|
*/
|
|
509
529
|
"collapsed": boolean;
|
|
510
530
|
/**
|
|
511
|
-
* Current route URL (e.g. `window.location.pathname` or the router's active URL). When set the component derives the active item by matching item `href` values against this string (longest prefix wins), overriding `activeId`.
|
|
531
|
+
* Current route URL (e.g. `window.location.pathname` or the router's active URL). When set the component derives the active item by matching item `href` values against this string (longest segment-boundary prefix wins), overriding `activeId`.
|
|
512
532
|
* @default ''
|
|
513
533
|
*/
|
|
514
534
|
"currentUrl": string;
|
|
@@ -518,10 +538,15 @@ export namespace Components {
|
|
|
518
538
|
*/
|
|
519
539
|
"disableViewTransition": boolean;
|
|
520
540
|
/**
|
|
521
|
-
*
|
|
541
|
+
* Nav groups — set via JS property (`el.groups = [...]`) or JSON string attribute.
|
|
522
542
|
* @default '[]'
|
|
523
543
|
*/
|
|
524
|
-
"groups": string;
|
|
544
|
+
"groups": string | PanelNavGroup[];
|
|
545
|
+
/**
|
|
546
|
+
* How items with `href` render: - `anchor` (default): native `<a href>` — works with routers that intercept anchors. - `event`: always `<button>`; host handles navigation via `dsNavSelect`.
|
|
547
|
+
* @default 'anchor'
|
|
548
|
+
*/
|
|
549
|
+
"routerMode": PanelNavRouterMode;
|
|
525
550
|
/**
|
|
526
551
|
* `localStorage` key used to persist the collapsed state across page loads. When set the component is self-managing for collapsed state; `dsNavToggle` still fires for consumers that want to observe the change.
|
|
527
552
|
* @default ''
|
|
@@ -1310,6 +1335,7 @@ declare global {
|
|
|
1310
1335
|
"dsNavSelect": string;
|
|
1311
1336
|
"dsNavToggle": boolean;
|
|
1312
1337
|
"dsNavFooterAction": void;
|
|
1338
|
+
"dsNavUserAction": void;
|
|
1313
1339
|
}
|
|
1314
1340
|
interface HTMLDsPanelNavElement extends Components.DsPanelNav, HTMLStencilElement {
|
|
1315
1341
|
addEventListener<K extends keyof HTMLDsPanelNavElementEventMap>(type: K, listener: (this: HTMLDsPanelNavElement, ev: DsPanelNavCustomEvent<HTMLDsPanelNavElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -1646,15 +1672,30 @@ declare namespace LocalJSX {
|
|
|
1646
1672
|
}
|
|
1647
1673
|
interface DsBarNav {
|
|
1648
1674
|
/**
|
|
1649
|
-
* Action items rendered in the right section. Set via JS property: `el.actions = [...]
|
|
1675
|
+
* Action items rendered in the right section. Set via JS property: `el.actions = [...]`. Replace the array reference to update.
|
|
1650
1676
|
* @default []
|
|
1651
1677
|
*/
|
|
1652
1678
|
"actions"?: BarNavActionItem[];
|
|
1679
|
+
/**
|
|
1680
|
+
* JSON fallback for `actions` — useful when framework bindings don't propagate arrays.
|
|
1681
|
+
* @default ''
|
|
1682
|
+
*/
|
|
1683
|
+
"actionsJson"?: string;
|
|
1653
1684
|
/**
|
|
1654
1685
|
* Surface background variant.
|
|
1655
1686
|
* @default 'secondary'
|
|
1656
1687
|
*/
|
|
1657
1688
|
"background"?: BarNavBackground;
|
|
1689
|
+
/**
|
|
1690
|
+
* Section base path (e.g. `/dashboard/safety`). Used with `currentUrl` to derive `value`.
|
|
1691
|
+
* @default ''
|
|
1692
|
+
*/
|
|
1693
|
+
"basePath"?: string;
|
|
1694
|
+
/**
|
|
1695
|
+
* Current route URL. When set with `basePath`, the active tab is derived automatically.
|
|
1696
|
+
* @default ''
|
|
1697
|
+
*/
|
|
1698
|
+
"currentUrl"?: string;
|
|
1658
1699
|
/**
|
|
1659
1700
|
* Fallback heading shown when no tabs are provided. When tabs are present the heading is hidden.
|
|
1660
1701
|
*/
|
|
@@ -1668,12 +1709,17 @@ declare namespace LocalJSX {
|
|
|
1668
1709
|
*/
|
|
1669
1710
|
"onDsTabChange"?: (event: DsBarNavCustomEvent<string>) => void;
|
|
1670
1711
|
/**
|
|
1671
|
-
* Tab items for the left section. Set via JS property: `el.tabs = [...]
|
|
1712
|
+
* Tab items for the left section. Set via JS property: `el.tabs = [...]`. Replace the array reference to update.
|
|
1672
1713
|
* @default []
|
|
1673
1714
|
*/
|
|
1674
1715
|
"tabs"?: BarNavTab[];
|
|
1675
1716
|
/**
|
|
1676
|
-
*
|
|
1717
|
+
* JSON fallback for `tabs` — useful when framework bindings don't propagate arrays.
|
|
1718
|
+
* @default ''
|
|
1719
|
+
*/
|
|
1720
|
+
"tabsJson"?: string;
|
|
1721
|
+
/**
|
|
1722
|
+
* ID of the currently active tab. Overridden when `currentUrl` + `basePath` are set.
|
|
1677
1723
|
* @default ''
|
|
1678
1724
|
*/
|
|
1679
1725
|
"value"?: string;
|
|
@@ -2047,7 +2093,7 @@ declare namespace LocalJSX {
|
|
|
2047
2093
|
*/
|
|
2048
2094
|
"collapsed"?: boolean;
|
|
2049
2095
|
/**
|
|
2050
|
-
* Current route URL (e.g. `window.location.pathname` or the router's active URL). When set the component derives the active item by matching item `href` values against this string (longest prefix wins), overriding `activeId`.
|
|
2096
|
+
* Current route URL (e.g. `window.location.pathname` or the router's active URL). When set the component derives the active item by matching item `href` values against this string (longest segment-boundary prefix wins), overriding `activeId`.
|
|
2051
2097
|
* @default ''
|
|
2052
2098
|
*/
|
|
2053
2099
|
"currentUrl"?: string;
|
|
@@ -2057,10 +2103,10 @@ declare namespace LocalJSX {
|
|
|
2057
2103
|
*/
|
|
2058
2104
|
"disableViewTransition"?: boolean;
|
|
2059
2105
|
/**
|
|
2060
|
-
*
|
|
2106
|
+
* Nav groups — set via JS property (`el.groups = [...]`) or JSON string attribute.
|
|
2061
2107
|
* @default '[]'
|
|
2062
2108
|
*/
|
|
2063
|
-
"groups"?: string;
|
|
2109
|
+
"groups"?: string | PanelNavGroup[];
|
|
2064
2110
|
/**
|
|
2065
2111
|
* Emitted when the footer left button (gear / dashboard) is clicked.
|
|
2066
2112
|
*/
|
|
@@ -2073,6 +2119,15 @@ declare namespace LocalJSX {
|
|
|
2073
2119
|
* Emitted when the collapse toggle is clicked. Detail = new collapsed state.
|
|
2074
2120
|
*/
|
|
2075
2121
|
"onDsNavToggle"?: (event: DsPanelNavCustomEvent<boolean>) => void;
|
|
2122
|
+
/**
|
|
2123
|
+
* Emitted when the footer user button is clicked.
|
|
2124
|
+
*/
|
|
2125
|
+
"onDsNavUserAction"?: (event: DsPanelNavCustomEvent<void>) => void;
|
|
2126
|
+
/**
|
|
2127
|
+
* How items with `href` render: - `anchor` (default): native `<a href>` — works with routers that intercept anchors. - `event`: always `<button>`; host handles navigation via `dsNavSelect`.
|
|
2128
|
+
* @default 'anchor'
|
|
2129
|
+
*/
|
|
2130
|
+
"routerMode"?: PanelNavRouterMode;
|
|
2076
2131
|
/**
|
|
2077
2132
|
* `localStorage` key used to persist the collapsed state across page loads. When set the component is self-managing for collapsed state; `dsNavToggle` still fires for consumers that want to observe the change.
|
|
2078
2133
|
* @default ''
|
|
@@ -2542,9 +2597,13 @@ declare namespace LocalJSX {
|
|
|
2542
2597
|
"dismissLabel": string;
|
|
2543
2598
|
}
|
|
2544
2599
|
interface DsBarNavAttributes {
|
|
2600
|
+
"tabsJson": string;
|
|
2545
2601
|
"value": string;
|
|
2602
|
+
"actionsJson": string;
|
|
2546
2603
|
"heading": string | undefined;
|
|
2547
2604
|
"background": BarNavBackground;
|
|
2605
|
+
"basePath": string;
|
|
2606
|
+
"currentUrl": string;
|
|
2548
2607
|
}
|
|
2549
2608
|
interface DsBarNavActionAttributes {
|
|
2550
2609
|
"icon": string;
|
|
@@ -2666,7 +2725,8 @@ declare namespace LocalJSX {
|
|
|
2666
2725
|
interface DsPanelNavAttributes {
|
|
2667
2726
|
"variant": PanelNavVariant;
|
|
2668
2727
|
"disableViewTransition": boolean;
|
|
2669
|
-
"groups": string;
|
|
2728
|
+
"groups": string | PanelNavGroup[];
|
|
2729
|
+
"routerMode": PanelNavRouterMode;
|
|
2670
2730
|
"activeId": string;
|
|
2671
2731
|
"collapsed": boolean;
|
|
2672
2732
|
"breakpoint": number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ds-mo/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "CompoMo — composable web components styled with TokoMo design tokens",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"src/angular"
|
|
40
40
|
],
|
|
41
41
|
"scripts": {
|
|
42
|
-
"build": "stencil build",
|
|
42
|
+
"build": "stencil build && node scripts/patch-index-types.mjs",
|
|
43
|
+
"test": "node --import tsx/esm --test tests/panel-nav-utils.test.ts tests/bar-nav-utils.test.ts",
|
|
43
44
|
"build:docs": "stencil build --docs",
|
|
44
45
|
"dev": "stencil build --dev --watch",
|
|
45
46
|
"storybook": "stencil build && storybook dev -p 6006",
|
|
@@ -74,6 +75,7 @@
|
|
|
74
75
|
"globals": "^17.6.0",
|
|
75
76
|
"lit": "^3.3.3",
|
|
76
77
|
"storybook": "^10.4.2",
|
|
78
|
+
"tsx": "^4.20.3",
|
|
77
79
|
"typescript": "~5.8.3",
|
|
78
80
|
"typescript-eslint": "^8.59.1",
|
|
79
81
|
"vite": "^8.0.16",
|
package/src/angular/proxies.ts
CHANGED
|
@@ -87,14 +87,14 @@ export declare interface DsBanner extends Components.DsBanner {
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
@ProxyCmp({
|
|
90
|
-
inputs: ['actions', 'background', 'heading', 'tabs', 'value']
|
|
90
|
+
inputs: ['actions', 'actionsJson', 'background', 'basePath', 'currentUrl', 'heading', 'tabs', 'tabsJson', 'value']
|
|
91
91
|
})
|
|
92
92
|
@Component({
|
|
93
93
|
selector: 'ds-bar-nav',
|
|
94
94
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
95
95
|
template: '<ng-content></ng-content>',
|
|
96
96
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
|
97
|
-
inputs: ['actions', 'background', 'heading', 'tabs', 'value'],
|
|
97
|
+
inputs: ['actions', 'actionsJson', 'background', 'basePath', 'currentUrl', 'heading', 'tabs', 'tabsJson', 'value'],
|
|
98
98
|
outputs: ['dsTabChange', 'dsActionChange'],
|
|
99
99
|
standalone: false
|
|
100
100
|
})
|
|
@@ -602,15 +602,15 @@ export declare interface DsPagination extends Components.DsPagination {
|
|
|
602
602
|
|
|
603
603
|
|
|
604
604
|
@ProxyCmp({
|
|
605
|
-
inputs: ['activeId', 'breakpoint', 'collapsed', 'currentUrl', 'disableViewTransition', 'groups', 'storageKey', 'userInitial', 'userName', 'variant']
|
|
605
|
+
inputs: ['activeId', 'breakpoint', 'collapsed', 'currentUrl', 'disableViewTransition', 'groups', 'routerMode', 'storageKey', 'userInitial', 'userName', 'variant']
|
|
606
606
|
})
|
|
607
607
|
@Component({
|
|
608
608
|
selector: 'ds-panel-nav',
|
|
609
609
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
610
610
|
template: '<ng-content></ng-content>',
|
|
611
611
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
|
612
|
-
inputs: ['activeId', 'breakpoint', 'collapsed', 'currentUrl', 'disableViewTransition', 'groups', 'storageKey', 'userInitial', 'userName', 'variant'],
|
|
613
|
-
outputs: ['dsNavSelect', 'dsNavToggle', 'dsNavFooterAction'],
|
|
612
|
+
inputs: ['activeId', 'breakpoint', 'collapsed', 'currentUrl', 'disableViewTransition', 'groups', 'routerMode', 'storageKey', 'userInitial', 'userName', 'variant'],
|
|
613
|
+
outputs: ['dsNavSelect', 'dsNavToggle', 'dsNavFooterAction', 'dsNavUserAction'],
|
|
614
614
|
standalone: false
|
|
615
615
|
})
|
|
616
616
|
export class DsPanelNav {
|
|
@@ -618,6 +618,7 @@ export class DsPanelNav {
|
|
|
618
618
|
@Output() dsNavSelect = new EventEmitter<CustomEvent<string>>();
|
|
619
619
|
@Output() dsNavToggle = new EventEmitter<CustomEvent<boolean>>();
|
|
620
620
|
@Output() dsNavFooterAction = new EventEmitter<CustomEvent<void>>();
|
|
621
|
+
@Output() dsNavUserAction = new EventEmitter<CustomEvent<void>>();
|
|
621
622
|
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
|
622
623
|
c.detach();
|
|
623
624
|
this.el = r.nativeElement;
|
|
@@ -638,6 +639,10 @@ export declare interface DsPanelNav extends Components.DsPanelNav {
|
|
|
638
639
|
* Emitted when the footer left button (gear / dashboard) is clicked.
|
|
639
640
|
*/
|
|
640
641
|
dsNavFooterAction: EventEmitter<CustomEvent<void>>;
|
|
642
|
+
/**
|
|
643
|
+
* Emitted when the footer user button is clicked.
|
|
644
|
+
*/
|
|
645
|
+
dsNavUserAction: EventEmitter<CustomEvent<void>>;
|
|
641
646
|
}
|
|
642
647
|
|
|
643
648
|
|