@ds-mo/ui 0.14.2 → 0.14.3

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.
@@ -1,2 +1,2 @@
1
- import{p as e,H as s,c as t,h as i,a,t as n}from"./index.js";import{g as r,i as o,d as h}from"./p-DV8pmt1m.js";import{d as c}from"./p-BHwspdql.js";import{d}from"./p-CNhBzIIb.js";import{d as l}from"./p-CSIN3IaW.js";function b(e,s,t){if(!e||!s){return{value:"",hideTabs:false}}if(e!==s&&!e.startsWith(`${s}/`)){return{value:"",hideTabs:false}}const i=e.slice(s.length);const a=i.startsWith("/")?i.slice(1).split("/")[0]:"";const n=r(t);if(!a){return{value:n[0]?.id??"",hideTabs:false}}const o=n.find((e=>e.id===a));if(o){return{value:o.id,hideTabs:false}}return{value:"",hideTabs:true}}function u(e,s,t,i,a,n){const r=t?f(t,[]):s??[];const o=n?f(n,[]):a??[];return e.length===0&&r.length>0||i.length===0&&o.length>0}function f(e,s){if(Array.isArray(e))return e;if(typeof e==="string"&&e!==""){try{const t=JSON.parse(e);return Array.isArray(t)?t:s}catch{return s}}return s}function v(e,s){if(!e)return null;const t=e.shadowRoot??e;return t.querySelector(s)}function g(e){return v(e,'[role="tablist"]')}function p(e,s){const t=[];let i=[];for(const a of e){if(o(a)){if(i.length>0){t.push({items:i});i=[]}continue}i.push({label:a.label,value:a.id,isSelected:a.id===s,isInactive:a.disabled})}if(i.length>0){t.push({items:i})}return t}function m(e,s){const t=r(e);return t.find((e=>e.id===s))??t[0]}function _(e,s){return m(e,s)?.label??"Tabs"}function y(e,s,t,i=2){const a=e-s;if(t){return a>-i}return a>i}const k=()=>`.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{position:relative;flex:1 1 0%;min-width:0;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__tabs-probe.sc-ds-bar-nav{position:absolute;left:0;top:0;visibility:hidden;pointer-events:none;overflow:visible;width:max-content;max-width:none;z-index:-1}.bar-nav__tabs-probe.sc-ds-bar-nav ds-tab-group.sc-ds-bar-nav{width:max-content}.bar-nav__tabs-visible.sc-ds-bar-nav{width:100%;min-width:0}.bar-nav__tabs-pending.sc-ds-bar-nav{flex:1;min-width:0;height:var(--dimension-size-400);visibility:hidden;pointer-events:none}.bar-nav__tab-trigger.sc-ds-bar-nav{display:inline-flex;align-items:center;justify-content:center;gap:var(--dimension-space-050);max-width:100%;padding:var(--dimension-space-075);background-color:transparent;border:none;border-radius:var(--dimension-radius-025);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--color-foreground-primary);position:relative;transition:color var(--effect-motion-short-2);flex-shrink:1;min-width:0;height:var(--dimension-size-400);box-sizing:border-box;--_hover-bg:var(--color-interaction-hover);--_pressed-bg:var(--color-interaction-pressed);--_dot:var(--color-foreground-bold-brand);--_dot-ring:var(--color-background-secondary)}.bar-nav__tab-trigger.sc-ds-bar-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025);background:transparent;pointer-events:none;transition:none}.bar-nav__tab-trigger.sc-ds-bar-nav:hover::after{background:var(--_hover-bg);transition:none}.bar-nav__tab-trigger.sc-ds-bar-nav:active::after{background:var(--_pressed-bg);transition:none}.bar-nav__tab-trigger.sc-ds-bar-nav:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.bar-nav__tab-trigger--open.sc-ds-bar-nav::after{background:var(--_hover-bg)}.bar-nav__tab-trigger-label.sc-ds-bar-nav{position:relative;display:inline-flex;align-items:center;min-width:0;padding:0 var(--dimension-space-025);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bar-nav__tab-trigger-label--dot.sc-ds-bar-nav{padding-right:calc(var(--dimension-space-025) + var(--dimension-space-050))}.bar-nav__tab-trigger-dot.sc-ds-bar-nav{position:absolute;top:0;right:0;width:var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));height:var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));border-radius:var(--dimension-radius-half);background:var(--_dot);box-shadow:0 0 0 var(--dimension-stroke-width-018) var(--_dot-ring);pointer-events:none}.bar-nav__tab-trigger-chevron.sc-ds-bar-nav{flex-shrink: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 C=e(class e extends s{constructor(e){super();if(e!==false){this.__registerHost()}this.dsTabChange=t(this,"dsTabChange");this.dsActionChange=t(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;this.tabsCollapsed=false;this.menuOpen=false;this.tabLayoutCommitted=false;this.leftEl=null;this.triggerEl=null;this.menuEl=null;this.visibleTabGroupEl=null;this.probeTabGroupEl=null;this.resizeObserver=null;this.overflowCheckScheduled=false;this.intrinsicWidthRetryCount=0}get effectiveValue(){if(this.currentUrl&&this.basePath){return this.urlDerivedValue}return this.value}get activeTabLabel(){return _(this.resolvedTabs,this.effectiveValue)}get activeTabHasDot(){return!!m(this.resolvedTabs,this.effectiveValue)?.dot}onPropsChange(){this.resolvedTabs=this.tabsJson?f(this.tabsJson,[]):this.tabs??[];this.resolvedActions=this.actionsJson?f(this.actionsJson,[]):this.actions??[];this.syncValueFromUrl();this.intrinsicWidthRetryCount=0;this.scheduleOverflowCheck()}onUrlChange(){this.syncValueFromUrl();this.scheduleOverflowCheck()}onSelectionChange(){this.syncMenuSections();this.scheduleOverflowCheck()}onMenuOpenChange(e){if(this.menuEl){this.menuEl.open=e}}onTabsCollapsedChange(e,s){if(!e){this.menuOpen=false;this.menuEl=null}this.scheduleOverflowCheck();if(e||s===undefined||s===e)return;requestAnimationFrame((()=>this.scheduleOverflowCheck()));queueMicrotask((()=>this.focusVisibleSelectedTab()))}componentWillLoad(){this.onPropsChange()}componentDidLoad(){this.syncHostPropsIfNeeded();this.scheduleDeferredHostPropSync();this.setupOverflowObserver();this.scheduleOverflowCheck()}componentDidRender(){this.scheduleOverflowCheck();this.syncMenuAnchor()}disconnectedCallback(){this.resizeObserver?.disconnect();this.resizeObserver=null}syncHostPropsIfNeeded(){if(u(this.resolvedTabs,this.tabs,this.tabsJson,this.resolvedActions,this.actions,this.actionsJson)){this.onPropsChange()}else if(this.currentUrl&&this.basePath){this.syncValueFromUrl()}}scheduleDeferredHostPropSync(){let s=e.HOST_PROP_SYNC_BUDGET;const t=()=>{this.syncHostPropsIfNeeded();if(--s>0){requestAnimationFrame(t)}};queueMicrotask(t)}setupOverflowObserver(){if(typeof ResizeObserver==="undefined"||!this.leftEl)return;this.resizeObserver?.disconnect();this.resizeObserver=new ResizeObserver((()=>this.scheduleOverflowCheck()));this.resizeObserver.observe(this.leftEl);const e=this.leftEl.parentElement;if(e){this.resizeObserver.observe(e)}}scheduleOverflowCheck(){if(this.overflowCheckScheduled)return;this.overflowCheckScheduled=true;requestAnimationFrame((()=>{this.overflowCheckScheduled=false;this.updateTabsCollapsed()}))}getLeftZoneAvailableWidth(){if(!this.leftEl)return 0;const e=this.leftEl.parentElement;if(!e?.classList.contains("bar-nav")){return this.leftEl.clientWidth}const s=getComputedStyle(e);const t=parseFloat(s.columnGap||s.gap||"0")||0;const i=e.querySelector(".bar-nav__actions");const a=i?.offsetWidth??0;const n=(parseFloat(s.paddingLeft)||0)+(parseFloat(s.paddingRight)||0);const r=e.clientWidth-n-a-(i?t:0);return Math.max(0,r)}getTabsIntrinsicWidth(){const e=g(this.probeTabGroupEl);return e?.scrollWidth??0}scheduleIntrinsicWidthRetry(){if(this.intrinsicWidthRetryCount>=e.INTRINSIC_WIDTH_RETRY_MAX)return;this.intrinsicWidthRetryCount++;requestAnimationFrame((()=>this.scheduleOverflowCheck()))}updateTabsCollapsed(){if(!this.leftEl||this.resolvedTabs.length===0||this.hideTabsForDetailRoute){if(this.tabsCollapsed){this.tabsCollapsed=false;this.menuOpen=false}this.intrinsicWidthRetryCount=0;return}const e=this.getTabsIntrinsicWidth();if(e===0){this.scheduleIntrinsicWidthRetry();return}this.intrinsicWidthRetryCount=0;const s=y(e,this.getLeftZoneAvailableWidth(),this.tabsCollapsed);if(s!==this.tabsCollapsed){this.tabsCollapsed=s;if(!s){this.menuOpen=false}}}syncMenuAnchor(){if(!this.menuEl||!this.triggerEl||!this.tabsCollapsed)return;this.menuEl.anchor=this.triggerEl;this.syncMenuSections()}handleMenuSelect(e){const s=e.detail;if(s?.value!==undefined){this.selectTab(String(s.value))}this.menuOpen=false}handleMenuClose(){this.menuOpen=false}syncMenuSections(){if(!this.menuEl)return;this.menuEl.sections=p(this.resolvedTabs,this.effectiveValue)}syncValueFromUrl(){if(!this.currentUrl||!this.basePath){this.urlDerivedValue="";this.hideTabsForDetailRoute=false;return}const{value:e,hideTabs:s}=b(this.currentUrl,this.basePath,this.resolvedTabs);this.urlDerivedValue=e;this.hideTabsForDetailRoute=s}selectTab(e){this.value=e;this.dsTabChange.emit(e)}focusVisibleSelectedTab(){const e=v(this.visibleTabGroupEl,`[data-tab-id="${this.effectiveValue}"]`);e?.focus({preventScroll:true})}handleTabChange(e){this.selectTab(e.detail)}handleActionChange(e,s){const t=s.detail;this.dsActionChange.emit({id:e,selected:t})}toggleTabMenu(){if(this.menuOpen){this.menuOpen=false;return}if(this.menuEl&&this.triggerEl){this.menuEl.anchor=this.triggerEl;this.menuEl.minWidth=`${this.triggerEl.offsetWidth}px`;this.syncMenuSections()}this.menuOpen=true}handleTriggerKeyDown(e){if(!this.tabsCollapsed)return;if(!this.menuOpen){if(e.key==="ArrowDown"||e.key==="ArrowUp"||e.key==="Enter"||e.key===" "){e.preventDefault();this.toggleTabMenu()}return}if(e.key==="Escape"){e.preventDefault();this.menuOpen=false;this.triggerEl?.focus()}}render(){const e=this.resolvedTabs.length>0&&!this.hideTabsForDetailRoute;const s={};const t=s[this.background];return i(a,{key:"f61ba8038d5de9f4a82f4c6ea5bc364309cdda02"},i("header",{key:"bdcc95ad765f2029db92e479f0c1d1042860db40",class:{"bar-nav":true,[`bg-${this.background}`]:true}},i("div",{key:"85f14adc72765b5662cb650c2c719f6b254f8183",class:"bar-nav__left",ref:e=>{this.leftEl=e;if(e&&!this.resizeObserver){this.setupOverflowObserver()}}},e&&i("div",{key:"4f085a516d42824f3b549699f8f1e32ea6076bdc",class:"bar-nav__tabs-probe","aria-hidden":"true",inert:true},i("ds-tab-group",{key:"e28ce0c117e2d0c11bbd1d8aaec5a705bc084145",ref:e=>{this.probeTabGroupEl=e??null;if(e){this.intrinsicWidthRetryCount=0;this.scheduleOverflowCheck()}},tabs:this.resolvedTabs,value:this.effectiveValue})),e&&!this.tabsCollapsed&&i("ds-tab-group",{key:"ceea1d5c1d1e9f661a832e087eae075b037d1095",class:"bar-nav__tabs-visible",ref:e=>{this.visibleTabGroupEl=e},tabs:this.resolvedTabs,value:this.effectiveValue,onDsChange:e=>this.handleTabChange(e)}),!e&&this.heading&&i("span",{key:"7205f0a666d1f8f10f58caf4da23ea12a149429b",class:"bar-nav__heading text-body-medium-emphasis"},this.heading),e&&this.tabsCollapsed&&i("button",{key:"cdb5fba6d3ff04a9657105c1d174e41de3b3b0c3",type:"button",class:{"bar-nav__tab-trigger":true,"bar-nav__tab-trigger--open":this.menuOpen},ref:e=>{this.triggerEl=e},"aria-haspopup":"menu","aria-expanded":this.menuOpen,"aria-label":`${this.activeTabLabel} tabs`,onClick:()=>this.toggleTabMenu(),onKeyDown:e=>this.handleTriggerKeyDown(e)},i("span",{key:"e057760ebcefa4343aa075e1fe0c9a2c88aed55e",class:{"bar-nav__tab-trigger-label":true,"bar-nav__tab-trigger-label--dot":this.activeTabHasDot,"text-body-medium-emphasis":true}},this.activeTabLabel,this.activeTabHasDot&&i("span",{key:"73392b1254be46c78078d3902855125181d32dd5",class:"bar-nav__tab-trigger-dot","aria-hidden":"true"})),i("ds-icon",{key:"6591f7f874b8b21d0da9d6c3e4a70afb5e8c1b31",name:"ChevronDown",size:"sm",color:"inherit",class:"bar-nav__tab-trigger-chevron"}))),this.resolvedActions.length>0&&i("div",{key:"8875ac0ca60926a4bb14ec3429e9edc9cae65e67",class:"bar-nav__actions"},this.resolvedActions.map((e=>i("ds-bar-nav-action",{key:e.id,icon:e.icon,selected:e.selected??false,dot:e.dot??false,inactive:e.inactive,"aria-label":e.ariaLabel??e.id,background:t,onDsChange:s=>this.handleActionChange(e.id,s)}))))),e&&this.tabsCollapsed&&i("ds-menu",{key:"45043ee4b549c44977a2c9dd74012f1f115f4f7d",ref:e=>{this.menuEl=e??null},open:this.menuOpen,sections:p(this.resolvedTabs,this.effectiveValue),side:"bottom",align:"start",onDsSelect:e=>this.handleMenuSelect(e),onDsClose:()=>this.handleMenuClose()}))}static get watchers(){return{tabs:[{onPropsChange:0}],tabsJson:[{onPropsChange:0}],actions:[{onPropsChange:0}],actionsJson:[{onPropsChange:0}],currentUrl:[{onUrlChange:0}],basePath:[{onUrlChange:0}],value:[{onSelectionChange:0}],urlDerivedValue:[{onSelectionChange:0}],menuOpen:[{onMenuOpenChange:0}],tabsCollapsed:[{onTabsCollapsedChange:0}]}}static get style(){return k()}},[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],tabsCollapsed:[32],menuOpen:[32],tabLayoutCommitted:[32]},undefined,{tabs:[{onPropsChange:0}],tabsJson:[{onPropsChange:0}],actions:[{onPropsChange:0}],actionsJson:[{onPropsChange:0}],currentUrl:[{onUrlChange:0}],basePath:[{onUrlChange:0}],value:[{onSelectionChange:0}],urlDerivedValue:[{onSelectionChange:0}],menuOpen:[{onMenuOpenChange:0}],tabsCollapsed:[{onTabsCollapsedChange:0}]}]);C.HOST_PROP_SYNC_BUDGET=8;C.INTRINSIC_WIDTH_RETRY_MAX=3;function w(){if(typeof customElements==="undefined"){return}const e=["ds-bar-nav","ds-bar-nav-action","ds-icon","ds-menu","ds-tab-group"];e.forEach((e=>{switch(e){case"ds-bar-nav":if(!customElements.get(n(e))){customElements.define(n(e),C)}break;case"ds-bar-nav-action":if(!customElements.get(n(e))){c()}break;case"ds-icon":if(!customElements.get(n(e))){d()}break;case"ds-menu":if(!customElements.get(n(e))){l()}break;case"ds-tab-group":if(!customElements.get(n(e))){h()}break}}))}w();const x=C;const T=w;export{x as DsBarNav,T as defineCustomElement};
1
+ import{p as e,H as s,c as t,h as i,a,t as n}from"./index.js";import{g as r,i as o,d as h}from"./p-DV8pmt1m.js";import{d as c}from"./p-BHwspdql.js";import{d}from"./p-CNhBzIIb.js";import{d as l}from"./p-STnE_bmQ.js";function b(e,s,t){if(!e||!s){return{value:"",hideTabs:false}}if(e!==s&&!e.startsWith(`${s}/`)){return{value:"",hideTabs:false}}const i=e.slice(s.length);const a=i.startsWith("/")?i.slice(1).split("/")[0]:"";const n=r(t);if(!a){return{value:n[0]?.id??"",hideTabs:false}}const o=n.find((e=>e.id===a));if(o){return{value:o.id,hideTabs:false}}return{value:"",hideTabs:true}}function u(e,s,t,i,a,n){const r=t?f(t,[]):s??[];const o=n?f(n,[]):a??[];return e.length===0&&r.length>0||i.length===0&&o.length>0}function f(e,s){if(Array.isArray(e))return e;if(typeof e==="string"&&e!==""){try{const t=JSON.parse(e);return Array.isArray(t)?t:s}catch{return s}}return s}function v(e,s){if(!e)return null;const t=e.shadowRoot??e;return t.querySelector(s)}function g(e){return v(e,'[role="tablist"]')}function p(e,s){const t=[];let i=[];for(const a of e){if(o(a)){if(i.length>0){t.push({items:i});i=[]}continue}i.push({label:a.label,value:a.id,isSelected:a.id===s,isInactive:a.disabled})}if(i.length>0){t.push({items:i})}return t}function m(e,s){const t=r(e);return t.find((e=>e.id===s))??t[0]}function _(e,s){return m(e,s)?.label??"Tabs"}function y(e,s,t,i=2){const a=e-s;if(t){return a>-i}return a>i}const k=()=>`.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{position:relative;flex:1 1 0%;min-width:0;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__tabs-probe.sc-ds-bar-nav{position:absolute;left:0;top:0;visibility:hidden;pointer-events:none;overflow:visible;width:max-content;max-width:none;z-index:-1}.bar-nav__tabs-probe.sc-ds-bar-nav ds-tab-group.sc-ds-bar-nav{width:max-content}.bar-nav__tabs-visible.sc-ds-bar-nav{width:100%;min-width:0}.bar-nav__tabs-pending.sc-ds-bar-nav{flex:1;min-width:0;height:var(--dimension-size-400);visibility:hidden;pointer-events:none}.bar-nav__tab-trigger.sc-ds-bar-nav{display:inline-flex;align-items:center;justify-content:center;gap:var(--dimension-space-050);max-width:100%;padding:var(--dimension-space-075);background-color:transparent;border:none;border-radius:var(--dimension-radius-025);cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--color-foreground-primary);position:relative;transition:color var(--effect-motion-short-2);flex-shrink:1;min-width:0;height:var(--dimension-size-400);box-sizing:border-box;--_hover-bg:var(--color-interaction-hover);--_pressed-bg:var(--color-interaction-pressed);--_dot:var(--color-foreground-bold-brand);--_dot-ring:var(--color-background-secondary)}.bar-nav__tab-trigger.sc-ds-bar-nav::after{content:'';position:absolute;inset:0;border-radius:var(--dimension-radius-025);background:transparent;pointer-events:none;transition:none}.bar-nav__tab-trigger.sc-ds-bar-nav:hover::after{background:var(--_hover-bg);transition:none}.bar-nav__tab-trigger.sc-ds-bar-nav:active::after{background:var(--_pressed-bg);transition:none}.bar-nav__tab-trigger.sc-ds-bar-nav:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.bar-nav__tab-trigger--open.sc-ds-bar-nav::after{background:var(--_hover-bg)}.bar-nav__tab-trigger-label.sc-ds-bar-nav{position:relative;display:inline-flex;align-items:center;min-width:0;padding:0 var(--dimension-space-025);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.bar-nav__tab-trigger-label--dot.sc-ds-bar-nav{padding-right:calc(var(--dimension-space-025) + var(--dimension-space-050))}.bar-nav__tab-trigger-dot.sc-ds-bar-nav{position:absolute;top:0;right:0;width:var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));height:var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));border-radius:var(--dimension-radius-half);background:var(--_dot);box-shadow:0 0 0 var(--dimension-stroke-width-018) var(--_dot-ring);pointer-events:none}.bar-nav__tab-trigger-chevron.sc-ds-bar-nav{flex-shrink: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 C=e(class e extends s{constructor(e){super();if(e!==false){this.__registerHost()}this.dsTabChange=t(this,"dsTabChange");this.dsActionChange=t(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;this.tabsCollapsed=false;this.menuOpen=false;this.tabLayoutCommitted=false;this.leftEl=null;this.triggerEl=null;this.menuEl=null;this.visibleTabGroupEl=null;this.probeTabGroupEl=null;this.resizeObserver=null;this.overflowCheckScheduled=false;this.intrinsicWidthRetryCount=0}get effectiveValue(){if(this.currentUrl&&this.basePath){return this.urlDerivedValue}return this.value}get activeTabLabel(){return _(this.resolvedTabs,this.effectiveValue)}get activeTabHasDot(){return!!m(this.resolvedTabs,this.effectiveValue)?.dot}onPropsChange(){this.resolvedTabs=this.tabsJson?f(this.tabsJson,[]):this.tabs??[];this.resolvedActions=this.actionsJson?f(this.actionsJson,[]):this.actions??[];this.syncValueFromUrl();this.intrinsicWidthRetryCount=0;this.scheduleOverflowCheck()}onUrlChange(){this.syncValueFromUrl();this.scheduleOverflowCheck()}onSelectionChange(){this.syncMenuSections();this.scheduleOverflowCheck()}onMenuOpenChange(e){if(this.menuEl){this.menuEl.open=e}}onTabsCollapsedChange(e,s){if(!e){this.menuOpen=false;this.menuEl=null}this.scheduleOverflowCheck();if(e||s===undefined||s===e)return;requestAnimationFrame((()=>this.scheduleOverflowCheck()));queueMicrotask((()=>this.focusVisibleSelectedTab()))}componentWillLoad(){this.onPropsChange()}componentDidLoad(){this.syncHostPropsIfNeeded();this.scheduleDeferredHostPropSync();this.setupOverflowObserver();this.scheduleOverflowCheck()}componentDidRender(){this.scheduleOverflowCheck();this.syncMenuAnchor()}disconnectedCallback(){this.resizeObserver?.disconnect();this.resizeObserver=null}syncHostPropsIfNeeded(){if(u(this.resolvedTabs,this.tabs,this.tabsJson,this.resolvedActions,this.actions,this.actionsJson)){this.onPropsChange()}else if(this.currentUrl&&this.basePath){this.syncValueFromUrl()}}scheduleDeferredHostPropSync(){let s=e.HOST_PROP_SYNC_BUDGET;const t=()=>{this.syncHostPropsIfNeeded();if(--s>0){requestAnimationFrame(t)}};queueMicrotask(t)}setupOverflowObserver(){if(typeof ResizeObserver==="undefined"||!this.leftEl)return;this.resizeObserver?.disconnect();this.resizeObserver=new ResizeObserver((()=>this.scheduleOverflowCheck()));this.resizeObserver.observe(this.leftEl);const e=this.leftEl.parentElement;if(e){this.resizeObserver.observe(e)}}scheduleOverflowCheck(){if(this.overflowCheckScheduled)return;this.overflowCheckScheduled=true;requestAnimationFrame((()=>{this.overflowCheckScheduled=false;this.updateTabsCollapsed()}))}getLeftZoneAvailableWidth(){if(!this.leftEl)return 0;const e=this.leftEl.parentElement;if(!e?.classList.contains("bar-nav")){return this.leftEl.clientWidth}const s=getComputedStyle(e);const t=parseFloat(s.columnGap||s.gap||"0")||0;const i=e.querySelector(".bar-nav__actions");const a=i?.offsetWidth??0;const n=(parseFloat(s.paddingLeft)||0)+(parseFloat(s.paddingRight)||0);const r=e.clientWidth-n-a-(i?t:0);return Math.max(0,r)}getTabsIntrinsicWidth(){const e=g(this.probeTabGroupEl);return e?.scrollWidth??0}scheduleIntrinsicWidthRetry(){if(this.intrinsicWidthRetryCount>=e.INTRINSIC_WIDTH_RETRY_MAX)return;this.intrinsicWidthRetryCount++;requestAnimationFrame((()=>this.scheduleOverflowCheck()))}updateTabsCollapsed(){if(!this.leftEl||this.resolvedTabs.length===0||this.hideTabsForDetailRoute){if(this.tabsCollapsed){this.tabsCollapsed=false;this.menuOpen=false}this.intrinsicWidthRetryCount=0;return}const e=this.getTabsIntrinsicWidth();if(e===0){this.scheduleIntrinsicWidthRetry();return}this.intrinsicWidthRetryCount=0;const s=y(e,this.getLeftZoneAvailableWidth(),this.tabsCollapsed);if(s!==this.tabsCollapsed){this.tabsCollapsed=s;if(!s){this.menuOpen=false}}}syncMenuAnchor(){if(!this.menuEl||!this.triggerEl||!this.tabsCollapsed)return;this.menuEl.anchor=this.triggerEl;this.syncMenuSections()}handleMenuSelect(e){const s=e.detail;if(s?.value!==undefined){this.selectTab(String(s.value))}this.menuOpen=false}handleMenuClose(){this.menuOpen=false}syncMenuSections(){if(!this.menuEl)return;this.menuEl.sections=p(this.resolvedTabs,this.effectiveValue)}syncValueFromUrl(){if(!this.currentUrl||!this.basePath){this.urlDerivedValue="";this.hideTabsForDetailRoute=false;return}const{value:e,hideTabs:s}=b(this.currentUrl,this.basePath,this.resolvedTabs);this.urlDerivedValue=e;this.hideTabsForDetailRoute=s}selectTab(e){this.value=e;this.dsTabChange.emit(e)}focusVisibleSelectedTab(){const e=v(this.visibleTabGroupEl,`[data-tab-id="${this.effectiveValue}"]`);e?.focus({preventScroll:true})}handleTabChange(e){this.selectTab(e.detail)}handleActionChange(e,s){const t=s.detail;this.dsActionChange.emit({id:e,selected:t})}toggleTabMenu(){if(this.menuOpen){this.menuOpen=false;return}if(this.menuEl&&this.triggerEl){this.menuEl.anchor=this.triggerEl;this.menuEl.minWidth=`${this.triggerEl.offsetWidth}px`;this.syncMenuSections()}this.menuOpen=true}handleTriggerKeyDown(e){if(!this.tabsCollapsed)return;if(!this.menuOpen){if(e.key==="ArrowDown"||e.key==="ArrowUp"||e.key==="Enter"||e.key===" "){e.preventDefault();this.toggleTabMenu()}return}if(e.key==="Escape"){e.preventDefault();this.menuOpen=false;this.triggerEl?.focus()}}render(){const e=this.resolvedTabs.length>0&&!this.hideTabsForDetailRoute;const s={};const t=s[this.background];return i(a,{key:"f61ba8038d5de9f4a82f4c6ea5bc364309cdda02"},i("header",{key:"bdcc95ad765f2029db92e479f0c1d1042860db40",class:{"bar-nav":true,[`bg-${this.background}`]:true}},i("div",{key:"85f14adc72765b5662cb650c2c719f6b254f8183",class:"bar-nav__left",ref:e=>{this.leftEl=e;if(e&&!this.resizeObserver){this.setupOverflowObserver()}}},e&&i("div",{key:"4f085a516d42824f3b549699f8f1e32ea6076bdc",class:"bar-nav__tabs-probe","aria-hidden":"true",inert:true},i("ds-tab-group",{key:"e28ce0c117e2d0c11bbd1d8aaec5a705bc084145",ref:e=>{this.probeTabGroupEl=e??null;if(e){this.intrinsicWidthRetryCount=0;this.scheduleOverflowCheck()}},tabs:this.resolvedTabs,value:this.effectiveValue})),e&&!this.tabsCollapsed&&i("ds-tab-group",{key:"ceea1d5c1d1e9f661a832e087eae075b037d1095",class:"bar-nav__tabs-visible",ref:e=>{this.visibleTabGroupEl=e},tabs:this.resolvedTabs,value:this.effectiveValue,onDsChange:e=>this.handleTabChange(e)}),!e&&this.heading&&i("span",{key:"7205f0a666d1f8f10f58caf4da23ea12a149429b",class:"bar-nav__heading text-body-medium-emphasis"},this.heading),e&&this.tabsCollapsed&&i("button",{key:"cdb5fba6d3ff04a9657105c1d174e41de3b3b0c3",type:"button",class:{"bar-nav__tab-trigger":true,"bar-nav__tab-trigger--open":this.menuOpen},ref:e=>{this.triggerEl=e},"aria-haspopup":"menu","aria-expanded":this.menuOpen,"aria-label":`${this.activeTabLabel} tabs`,onClick:()=>this.toggleTabMenu(),onKeyDown:e=>this.handleTriggerKeyDown(e)},i("span",{key:"e057760ebcefa4343aa075e1fe0c9a2c88aed55e",class:{"bar-nav__tab-trigger-label":true,"bar-nav__tab-trigger-label--dot":this.activeTabHasDot,"text-body-medium-emphasis":true}},this.activeTabLabel,this.activeTabHasDot&&i("span",{key:"73392b1254be46c78078d3902855125181d32dd5",class:"bar-nav__tab-trigger-dot","aria-hidden":"true"})),i("ds-icon",{key:"6591f7f874b8b21d0da9d6c3e4a70afb5e8c1b31",name:"ChevronDown",size:"md",color:"inherit",class:"bar-nav__tab-trigger-chevron"}))),this.resolvedActions.length>0&&i("div",{key:"8875ac0ca60926a4bb14ec3429e9edc9cae65e67",class:"bar-nav__actions"},this.resolvedActions.map((e=>i("ds-bar-nav-action",{key:e.id,icon:e.icon,selected:e.selected??false,dot:e.dot??false,inactive:e.inactive,"aria-label":e.ariaLabel??e.id,background:t,onDsChange:s=>this.handleActionChange(e.id,s)}))))),e&&this.tabsCollapsed&&i("ds-menu",{key:"45043ee4b549c44977a2c9dd74012f1f115f4f7d",ref:e=>{this.menuEl=e??null},open:this.menuOpen,sections:p(this.resolvedTabs,this.effectiveValue),side:"bottom",align:"start",onDsSelect:e=>this.handleMenuSelect(e),onDsClose:()=>this.handleMenuClose()}))}static get watchers(){return{tabs:[{onPropsChange:0}],tabsJson:[{onPropsChange:0}],actions:[{onPropsChange:0}],actionsJson:[{onPropsChange:0}],currentUrl:[{onUrlChange:0}],basePath:[{onUrlChange:0}],value:[{onSelectionChange:0}],urlDerivedValue:[{onSelectionChange:0}],menuOpen:[{onMenuOpenChange:0}],tabsCollapsed:[{onTabsCollapsedChange:0}]}}static get style(){return k()}},[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],tabsCollapsed:[32],menuOpen:[32],tabLayoutCommitted:[32]},undefined,{tabs:[{onPropsChange:0}],tabsJson:[{onPropsChange:0}],actions:[{onPropsChange:0}],actionsJson:[{onPropsChange:0}],currentUrl:[{onUrlChange:0}],basePath:[{onUrlChange:0}],value:[{onSelectionChange:0}],urlDerivedValue:[{onSelectionChange:0}],menuOpen:[{onMenuOpenChange:0}],tabsCollapsed:[{onTabsCollapsedChange:0}]}]);C.HOST_PROP_SYNC_BUDGET=8;C.INTRINSIC_WIDTH_RETRY_MAX=3;function w(){if(typeof customElements==="undefined"){return}const e=["ds-bar-nav","ds-bar-nav-action","ds-icon","ds-menu","ds-tab-group"];e.forEach((e=>{switch(e){case"ds-bar-nav":if(!customElements.get(n(e))){customElements.define(n(e),C)}break;case"ds-bar-nav-action":if(!customElements.get(n(e))){c()}break;case"ds-icon":if(!customElements.get(n(e))){d()}break;case"ds-menu":if(!customElements.get(n(e))){l()}break;case"ds-tab-group":if(!customElements.get(n(e))){h()}break}}))}w();const x=C;const T=w;export{x as DsBarNav,T as defineCustomElement};
2
2
  //# sourceMappingURL=ds-bar-nav.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["deriveBarNavValueFromUrl","path","basePath","tabs","value","hideTabs","startsWith","remainder","slice","length","seg","split","selectableTabs","getSelectableTabs","id","tab","find","t","shouldResyncBarNavProps","resolvedTabs","tabsJson","resolvedActions","actions","actionsJson","tabsIncoming","parseJsonArrayProp","actionsIncoming","fallback","Array","isArray","parsed","JSON","parse","queryWithinComponentHost","host","selector","root","shadowRoot","querySelector","getTabListFromTabGroup","tabGroupEl","tabsToMenuSections","selectedId","sections","batch","item","isTabDivider","push","items","label","isSelected","isInactive","disabled","getActiveTab","selectable","getActiveTabLabel","tabsOverflowContainer","tabListScrollWidth","containerClientWidth","collapsed","hysteresis","diff","barNavCss","BarNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","background","currentUrl","urlDerivedValue","hideTabsForDetailRoute","tabsCollapsed","menuOpen","tabLayoutCommitted","leftEl","triggerEl","menuEl","visibleTabGroupEl","probeTabGroupEl","resizeObserver","overflowCheckScheduled","intrinsicWidthRetryCount","effectiveValue","activeTabLabel","activeTabHasDot","dot","onPropsChange","syncValueFromUrl","scheduleOverflowCheck","onUrlChange","onSelectionChange","syncMenuSections","onMenuOpenChange","open","onTabsCollapsedChange","prevCollapsed","undefined","requestAnimationFrame","queueMicrotask","focusVisibleSelectedTab","componentWillLoad","componentDidLoad","syncHostPropsIfNeeded","scheduleDeferredHostPropSync","setupOverflowObserver","componentDidRender","syncMenuAnchor","disconnectedCallback","disconnect","remaining","HOST_PROP_SYNC_BUDGET","tick","ResizeObserver","observe","header","parentElement","updateTabsCollapsed","getLeftZoneAvailableWidth","classList","contains","clientWidth","headerStyle","getComputedStyle","gap","parseFloat","columnGap","actionsEl","actionsWidth","offsetWidth","horizontalPadding","paddingLeft","paddingRight","available","Math","max","getTabsIntrinsicWidth","tabList","scrollWidth","scheduleIntrinsicWidthRetry","INTRINSIC_WIDTH_RETRY_MAX","intrinsicWidth","shouldCollapse","anchor","handleMenuSelect","e","detail","selectTab","String","handleMenuClose","dsTabChange","emit","focus","preventScroll","handleTabChange","handleActionChange","actionId","selected","dsActionChange","toggleTabMenu","minWidth","handleTriggerKeyDown","key","preventDefault","render","hasTabs","bgToActionBg","actionBg","h","Host","class","ref","el","inert","onDsChange","heading","type","onClick","onKeyDown","name","size","color","map","action","icon","inactive","ariaLabel","side","align","onDsSelect","onDsClose"],"sources":["src/wc/components/BarNav/bar-nav-utils.ts","src/wc/components/BarNav/bar-nav-dom-utils.ts","src/wc/components/BarNav/bar-nav-tabs-menu-utils.ts","src/wc/components/BarNav/BarNav.css?tag=ds-bar-nav&encapsulation=scoped","src/wc/components/BarNav/BarNav.tsx"],"sourcesContent":["import { getSelectableTabs } from '../TabGroup/tab-item-utils';\nimport type { BarNavActionItem, 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 const selectableTabs = getSelectableTabs(tabs);\n\n if (!seg) {\n return { value: selectableTabs[0]?.id ?? '', hideTabs: false };\n }\n\n const tab = selectableTabs.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/** True when host array/json props have data but resolved internal state is still empty. */\nexport function shouldResyncBarNavProps(\n resolvedTabs: BarNavTab[],\n tabs: BarNavTab[],\n tabsJson: string,\n resolvedActions: BarNavActionItem[],\n actions: BarNavActionItem[],\n actionsJson: string,\n): boolean {\n const tabsIncoming = tabsJson\n ? parseJsonArrayProp(tabsJson, [])\n : (tabs ?? []);\n const actionsIncoming = actionsJson\n ? parseJsonArrayProp(actionsJson, [])\n : (actions ?? []);\n\n return (\n (resolvedTabs.length === 0 && tabsIncoming.length > 0) ||\n (resolvedActions.length === 0 && actionsIncoming.length > 0)\n );\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","type QueryableHost = {\n shadowRoot?: ShadowRoot | null;\n querySelector: (selectors: string) => Element | null;\n};\n\n/**\n * Query within a Stencil custom-element host (light DOM today, shadow DOM–safe).\n * Use for child nodes owned by ds-tab-group and similar components.\n */\nexport function queryWithinComponentHost(\n host: QueryableHost | null | undefined,\n selector: string,\n): HTMLElement | null {\n if (!host) return null;\n const root = host.shadowRoot ?? host;\n return root.querySelector(selector) as HTMLElement | null;\n}\n\nexport function getTabListFromTabGroup(\n tabGroupEl: QueryableHost | null | undefined,\n): HTMLElement | null {\n return queryWithinComponentHost(tabGroupEl, '[role=\"tablist\"]');\n}\n","import type { MenuSection } from '../Menu/Menu';\nimport {\n getSelectableTabs,\n isTabDivider,\n type TabItem,\n type TabItemTab,\n} from '../TabGroup/tab-item-utils';\n\n/** Map BarNav tabs to menu sections, preserving `{ type: 'divider' }` as section breaks. */\nexport function tabsToMenuSections(tabs: TabItem[], selectedId: string): MenuSection[] {\n const sections: MenuSection[] = [];\n let batch: MenuSection['items'] = [];\n\n for (const item of tabs) {\n if (isTabDivider(item)) {\n if (batch.length > 0) {\n sections.push({ items: batch });\n batch = [];\n }\n continue;\n }\n\n batch.push({\n label: item.label,\n value: item.id,\n isSelected: item.id === selectedId,\n isInactive: item.disabled,\n });\n }\n\n if (batch.length > 0) {\n sections.push({ items: batch });\n }\n\n return sections;\n}\n\nexport function getActiveTab(tabs: TabItem[], selectedId: string): TabItemTab | undefined {\n const selectable = getSelectableTabs(tabs);\n return selectable.find(tab => tab.id === selectedId) ?? selectable[0];\n}\n\nexport function getActiveTabLabel(tabs: TabItem[], selectedId: string): string {\n return getActiveTab(tabs, selectedId)?.label ?? 'Tabs';\n}\n\n/** True when tablist content exceeds the available width (with optional hysteresis). */\nexport function tabsOverflowContainer(\n tabListScrollWidth: number,\n containerClientWidth: number,\n collapsed: boolean,\n hysteresis = 2,\n): boolean {\n const diff = tabListScrollWidth - containerClientWidth;\n if (collapsed) {\n return diff > -hysteresis;\n }\n return diff > hysteresis;\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 — always consume remaining header width (even when collapsed to a narrow trigger) */\n.bar-nav__left {\n position: relative;\n flex: 1 1 0%;\n min-width: 0;\n 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/* Unconstrained width so intrinsic tab row width is measurable while collapsed */\n.bar-nav__tabs-probe {\n position: absolute;\n left: 0;\n top: 0;\n visibility: hidden;\n pointer-events: none;\n overflow: visible;\n width: max-content;\n max-width: none;\n z-index: -1;\n}\n\n.bar-nav__tabs-probe ds-tab-group {\n width: max-content;\n}\n\n.bar-nav__tabs-visible {\n width: 100%;\n min-width: 0;\n}\n\n/* In-flow placeholder while measuring overflow — avoids layout jump; hidden from view/accessibility. */\n.bar-nav__tabs-pending {\n flex: 1;\n min-width: 0;\n height: var(--dimension-size-400);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* Collapsed tab trigger — tab interaction pattern, not ds-button */\n.bar-nav__tab-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-050);\n max-width: 100%;\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-025);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n color: var(--color-foreground-primary);\n position: relative;\n transition: color var(--effect-motion-short-2);\n flex-shrink: 1;\n min-width: 0;\n height: var(--dimension-size-400);\n box-sizing: border-box;\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_dot: var(--color-foreground-bold-brand);\n --_dot-ring: var(--color-background-secondary);\n}\n\n.bar-nav__tab-trigger::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: var(--dimension-radius-025);\n background: transparent;\n pointer-events: none;\n transition: none;\n}\n\n.bar-nav__tab-trigger:hover::after {\n background: var(--_hover-bg);\n transition: none;\n}\n\n.bar-nav__tab-trigger:active::after {\n background: var(--_pressed-bg);\n transition: none;\n}\n\n.bar-nav__tab-trigger:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.bar-nav__tab-trigger--open::after {\n background: var(--_hover-bg);\n}\n\n.bar-nav__tab-trigger-label {\n position: relative;\n display: inline-flex;\n align-items: center;\n min-width: 0;\n padding: 0 var(--dimension-space-025);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.bar-nav__tab-trigger-label--dot {\n padding-right: calc(var(--dimension-space-025) + var(--dimension-space-050));\n}\n\n.bar-nav__tab-trigger-dot {\n position: absolute;\n top: 0;\n right: 0;\n width: var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));\n height: var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));\n border-radius: var(--dimension-radius-half);\n background: var(--_dot);\n box-shadow: 0 0 0 var(--dimension-stroke-width-018) var(--_dot-ring);\n pointer-events: none;\n}\n\n.bar-nav__tab-trigger-chevron {\n flex-shrink: 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 {\n Component,\n Prop,\n Event,\n EventEmitter,\n Watch,\n State,\n h,\n Host,\n} from '@stencil/core';\nimport type { MenuItemData } from '../Menu/Menu';\nimport type { BarNavActionBackground } from '../BarNavAction/BarNavAction';\nimport type { TabItem } from '../TabGroup/tab-item-utils';\nimport {\n deriveBarNavValueFromUrl,\n parseJsonArrayProp,\n shouldResyncBarNavProps,\n} from './bar-nav-utils';\nimport {\n getTabListFromTabGroup,\n queryWithinComponentHost,\n} from './bar-nav-dom-utils';\nimport {\n getActiveTab,\n getActiveTabLabel,\n tabsOverflowContainer,\n tabsToMenuSections,\n} from './bar-nav-tabs-menu-utils';\n\nexport type BarNavBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\n/** Same shape as `TabItem` — supports `{ type: 'divider' }` between tab groups. */\nexport type BarNavTab = TabItem;\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 @State() private tabsCollapsed = false;\n @State() private menuOpen = false;\n /** When false, defer showing expanded tabs or the collapsed trigger until intrinsic width is measured (avoids a one-frame flash of the full tab row on narrow viewports). */\n @State() private tabLayoutCommitted = false;\n\n private static readonly HOST_PROP_SYNC_BUDGET = 8;\n private static readonly INTRINSIC_WIDTH_RETRY_MAX = 3;\n\n private leftEl: HTMLElement | null = null;\n private triggerEl: HTMLButtonElement | null = null;\n private menuEl: HTMLDsMenuElement | null = null;\n private visibleTabGroupEl: HTMLDsTabGroupElement | null = null;\n private probeTabGroupEl: HTMLDsTabGroupElement | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private overflowCheckScheduled = false;\n private intrinsicWidthRetryCount = 0;\n\n private get effectiveValue(): string {\n if (this.currentUrl && this.basePath) {\n return this.urlDerivedValue;\n }\n return this.value;\n }\n\n private get activeTabLabel(): string {\n return getActiveTabLabel(this.resolvedTabs, this.effectiveValue);\n }\n\n private get activeTabHasDot(): boolean {\n return !!getActiveTab(this.resolvedTabs, this.effectiveValue)?.dot;\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 this.intrinsicWidthRetryCount = 0;\n this.scheduleOverflowCheck();\n }\n\n @Watch('currentUrl')\n @Watch('basePath')\n onUrlChange() {\n this.syncValueFromUrl();\n this.scheduleOverflowCheck();\n }\n\n @Watch('value')\n @Watch('urlDerivedValue')\n onSelectionChange() {\n this.syncMenuSections();\n this.scheduleOverflowCheck();\n }\n\n @Watch('menuOpen')\n onMenuOpenChange(open: boolean) {\n if (this.menuEl) {\n this.menuEl.open = open;\n }\n }\n\n @Watch('tabsCollapsed')\n onTabsCollapsedChange(collapsed: boolean, prevCollapsed: boolean | undefined) {\n if (!collapsed) {\n this.menuOpen = false;\n this.menuEl = null;\n }\n this.scheduleOverflowCheck();\n if (collapsed || prevCollapsed === undefined || prevCollapsed === collapsed) return;\n requestAnimationFrame(() => this.scheduleOverflowCheck());\n queueMicrotask(() => this.focusVisibleSelectedTab());\n }\n\n componentWillLoad() {\n this.onPropsChange();\n }\n\n componentDidLoad() {\n this.syncHostPropsIfNeeded();\n this.scheduleDeferredHostPropSync();\n this.setupOverflowObserver();\n this.scheduleOverflowCheck();\n }\n\n componentDidRender() {\n this.scheduleOverflowCheck();\n this.syncMenuAnchor();\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n }\n\n /** Re-resolve props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */\n private syncHostPropsIfNeeded() {\n if (\n shouldResyncBarNavProps(\n this.resolvedTabs,\n this.tabs,\n this.tabsJson,\n this.resolvedActions,\n this.actions,\n this.actionsJson,\n )\n ) {\n this.onPropsChange();\n } else if (this.currentUrl && this.basePath) {\n this.syncValueFromUrl();\n }\n }\n\n /** Poll across animation frames — host props may land without triggering @Watch. */\n private scheduleDeferredHostPropSync() {\n let remaining = BarNav.HOST_PROP_SYNC_BUDGET;\n const tick = () => {\n this.syncHostPropsIfNeeded();\n if (--remaining > 0) {\n requestAnimationFrame(tick);\n }\n };\n queueMicrotask(tick);\n }\n\n private setupOverflowObserver() {\n if (typeof ResizeObserver === 'undefined' || !this.leftEl) return;\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => this.scheduleOverflowCheck());\n this.resizeObserver.observe(this.leftEl);\n const header = this.leftEl.parentElement;\n if (header) {\n this.resizeObserver.observe(header);\n }\n }\n\n private scheduleOverflowCheck() {\n if (this.overflowCheckScheduled) return;\n this.overflowCheckScheduled = true;\n requestAnimationFrame(() => {\n this.overflowCheckScheduled = false;\n this.updateTabsCollapsed();\n });\n }\n\n /** Width left for tabs after actions — stable while collapsed (unlike leftEl box when hugging the trigger). */\n private getLeftZoneAvailableWidth(): number {\n if (!this.leftEl) return 0;\n\n const header = this.leftEl.parentElement;\n if (!header?.classList.contains('bar-nav')) {\n return this.leftEl.clientWidth;\n }\n\n const headerStyle = getComputedStyle(header);\n const gap = parseFloat(headerStyle.columnGap || headerStyle.gap || '0') || 0;\n const actionsEl = header.querySelector('.bar-nav__actions') as HTMLElement | null;\n const actionsWidth = actionsEl?.offsetWidth ?? 0;\n const horizontalPadding =\n (parseFloat(headerStyle.paddingLeft) || 0) + (parseFloat(headerStyle.paddingRight) || 0);\n const available = header.clientWidth - horizontalPadding - actionsWidth - (actionsEl ? gap : 0);\n\n return Math.max(0, available);\n }\n\n private getTabsIntrinsicWidth(): number {\n const tabList = getTabListFromTabGroup(this.probeTabGroupEl);\n return tabList?.scrollWidth ?? 0;\n }\n\n private scheduleIntrinsicWidthRetry() {\n if (this.intrinsicWidthRetryCount >= BarNav.INTRINSIC_WIDTH_RETRY_MAX) return;\n this.intrinsicWidthRetryCount++;\n requestAnimationFrame(() => this.scheduleOverflowCheck());\n }\n\n private updateTabsCollapsed() {\n if (!this.leftEl || this.resolvedTabs.length === 0 || this.hideTabsForDetailRoute) {\n if (this.tabsCollapsed) {\n this.tabsCollapsed = false;\n this.menuOpen = false;\n }\n this.intrinsicWidthRetryCount = 0;\n return;\n }\n\n const intrinsicWidth = this.getTabsIntrinsicWidth();\n if (intrinsicWidth === 0) {\n this.scheduleIntrinsicWidthRetry();\n return;\n }\n this.intrinsicWidthRetryCount = 0;\n\n const shouldCollapse = tabsOverflowContainer(\n intrinsicWidth,\n this.getLeftZoneAvailableWidth(),\n this.tabsCollapsed,\n );\n\n if (shouldCollapse !== this.tabsCollapsed) {\n this.tabsCollapsed = shouldCollapse;\n if (!shouldCollapse) {\n this.menuOpen = false;\n }\n }\n }\n\n private syncMenuAnchor() {\n if (!this.menuEl || !this.triggerEl || !this.tabsCollapsed) return;\n this.menuEl.anchor = this.triggerEl;\n this.syncMenuSections();\n }\n\n private handleMenuSelect(e: Event) {\n const detail = (e as CustomEvent<MenuItemData>).detail;\n if (detail?.value !== undefined) {\n this.selectTab(String(detail.value));\n }\n this.menuOpen = false;\n }\n\n private handleMenuClose() {\n this.menuOpen = false;\n }\n\n private syncMenuSections() {\n if (!this.menuEl) return;\n this.menuEl.sections = tabsToMenuSections(this.resolvedTabs, this.effectiveValue);\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 selectTab(id: string) {\n this.value = id;\n this.dsTabChange.emit(id);\n }\n\n /** Move focus to the selected tab in the visible tab group (after expand). */\n private focusVisibleSelectedTab() {\n const tab = queryWithinComponentHost(\n this.visibleTabGroupEl,\n `[data-tab-id=\"${this.effectiveValue}\"]`,\n );\n tab?.focus({ preventScroll: true });\n }\n\n private handleTabChange(e: Event) {\n this.selectTab((e as CustomEvent<string>).detail);\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 private toggleTabMenu() {\n if (this.menuOpen) {\n this.menuOpen = false;\n return;\n }\n\n if (this.menuEl && this.triggerEl) {\n this.menuEl.anchor = this.triggerEl;\n this.menuEl.minWidth = `${this.triggerEl.offsetWidth}px`;\n this.syncMenuSections();\n }\n\n this.menuOpen = true;\n }\n\n private handleTriggerKeyDown(e: KeyboardEvent) {\n if (!this.tabsCollapsed) return;\n\n if (!this.menuOpen) {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.toggleTabMenu();\n }\n return;\n }\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.menuOpen = false;\n this.triggerEl?.focus();\n }\n }\n\n render() {\n const hasTabs = this.resolvedTabs.length > 0 && !this.hideTabsForDetailRoute;\n\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\n class=\"bar-nav__left\"\n ref={el => {\n this.leftEl = el as HTMLElement;\n if (el && !this.resizeObserver) {\n this.setupOverflowObserver();\n }\n }}\n >\n {hasTabs && (\n <div class=\"bar-nav__tabs-probe\" aria-hidden=\"true\" inert>\n <ds-tab-group\n ref={el => {\n this.probeTabGroupEl = (el as HTMLDsTabGroupElement) ?? null;\n if (el) {\n this.intrinsicWidthRetryCount = 0;\n this.scheduleOverflowCheck();\n }\n }}\n tabs={this.resolvedTabs}\n value={this.effectiveValue}\n />\n </div>\n )}\n\n {hasTabs && !this.tabsCollapsed && (\n <ds-tab-group\n class=\"bar-nav__tabs-visible\"\n ref={el => {\n this.visibleTabGroupEl = el as HTMLDsTabGroupElement;\n }}\n tabs={this.resolvedTabs}\n value={this.effectiveValue}\n onDsChange={(e: Event) => this.handleTabChange(e)}\n />\n )}\n\n {!hasTabs && this.heading && (\n <span class=\"bar-nav__heading text-body-medium-emphasis\">{this.heading}</span>\n )}\n\n {hasTabs && this.tabsCollapsed && (\n <button\n type=\"button\"\n class={{\n 'bar-nav__tab-trigger': true,\n 'bar-nav__tab-trigger--open': this.menuOpen,\n }}\n ref={el => {\n this.triggerEl = el as HTMLButtonElement;\n }}\n aria-haspopup=\"menu\"\n aria-expanded={this.menuOpen}\n aria-label={`${this.activeTabLabel} tabs`}\n onClick={() => this.toggleTabMenu()}\n onKeyDown={(e: KeyboardEvent) => this.handleTriggerKeyDown(e)}\n >\n <span class={{\n 'bar-nav__tab-trigger-label': true,\n 'bar-nav__tab-trigger-label--dot': this.activeTabHasDot,\n 'text-body-medium-emphasis': true,\n }}>\n {this.activeTabLabel}\n {this.activeTabHasDot && (\n <span class=\"bar-nav__tab-trigger-dot\" aria-hidden=\"true\" />\n )}\n </span>\n <ds-icon\n name=\"ChevronDown\"\n size=\"sm\"\n color=\"inherit\"\n class=\"bar-nav__tab-trigger-chevron\"\n />\n </button>\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\n {hasTabs && this.tabsCollapsed && (\n <ds-menu\n ref={el => {\n this.menuEl = (el as HTMLDsMenuElement) ?? null;\n }}\n open={this.menuOpen}\n sections={tabsToMenuSections(this.resolvedTabs, this.effectiveValue)}\n side=\"bottom\"\n align=\"start\"\n onDsSelect={(e: Event) => this.handleMenuSelect(e)}\n onDsClose={() => this.handleMenuClose()}\n />\n )}\n </Host>\n );\n }\n}\n"],"mappings":"+NAYgBA,EACdC,EACAC,EACAC,GAEA,IAAKF,IAASC,EAAU,CACtB,MAAO,CAAEE,MAAO,GAAIC,SAAU,M,CAGhC,GAAIJ,IAASC,IAAaD,EAAKK,WAAW,GAAGJ,MAAc,CACzD,MAAO,CAAEE,MAAO,GAAIC,SAAU,M,CAGhC,MAAME,EAAYN,EAAKO,MAAMN,EAASO,QACtC,MAAMC,EAAMH,EAAUD,WAAW,KAAOC,EAAUC,MAAM,GAAGG,MAAM,KAAK,GAAK,GAC3E,MAAMC,EAAiBC,EAAkBV,GAEzC,IAAKO,EAAK,CACR,MAAO,CAAEN,MAAOQ,EAAe,IAAIE,IAAM,GAAIT,SAAU,M,CAGzD,MAAMU,EAAMH,EAAeI,MAAKC,GAAKA,EAAEH,KAAOJ,IAC9C,GAAIK,EAAK,CACP,MAAO,CAAEX,MAAOW,EAAID,GAAIT,SAAU,M,CAGpC,MAAO,CAAED,MAAO,GAAIC,SAAU,KAChC,CAGM,SAAUa,EACdC,EACAhB,EACAiB,EACAC,EACAC,EACAC,GAEA,MAAMC,EAAeJ,EACjBK,EAAmBL,EAAU,IAC5BjB,GAAQ,GACb,MAAMuB,EAAkBH,EACpBE,EAAmBF,EAAa,IAC/BD,GAAW,GAEhB,OACGH,EAAaV,SAAW,GAAKe,EAAaf,OAAS,GACnDY,EAAgBZ,SAAW,GAAKiB,EAAgBjB,OAAS,CAE9D,CAGM,SAAUgB,EAAsBrB,EAAiCuB,GACrE,GAAIC,MAAMC,QAAQzB,GAAQ,OAAOA,EACjC,UAAWA,IAAU,UAAYA,IAAU,GAAI,CAC7C,IACE,MAAM0B,EAASC,KAAKC,MAAM5B,GAC1B,OAAOwB,MAAMC,QAAQC,GAAUA,EAASH,C,CACxC,MACA,OAAOA,C,EAGX,OAAOA,CACT,CClEM,SAAUM,EACdC,EACAC,GAEA,IAAKD,EAAM,OAAO,KAClB,MAAME,EAAOF,EAAKG,YAAcH,EAChC,OAAOE,EAAKE,cAAcH,EAC5B,CAEM,SAAUI,EACdC,GAEA,OAAOP,EAAyBO,EAAY,mBAC9C,CCbM,SAAUC,EAAmBtC,EAAiBuC,GAClD,MAAMC,EAA0B,GAChC,IAAIC,EAA8B,GAElC,IAAK,MAAMC,KAAQ1C,EAAM,CACvB,GAAI2C,EAAaD,GAAO,CACtB,GAAID,EAAMnC,OAAS,EAAG,CACpBkC,EAASI,KAAK,CAAEC,MAAOJ,IACvBA,EAAQ,E,CAEV,Q,CAGFA,EAAMG,KAAK,CACTE,MAAOJ,EAAKI,MACZ7C,MAAOyC,EAAK/B,GACZoC,WAAYL,EAAK/B,KAAO4B,EACxBS,WAAYN,EAAKO,U,CAIrB,GAAIR,EAAMnC,OAAS,EAAG,CACpBkC,EAASI,KAAK,CAAEC,MAAOJ,G,CAGzB,OAAOD,CACT,CAEM,SAAUU,EAAalD,EAAiBuC,GAC5C,MAAMY,EAAazC,EAAkBV,GACrC,OAAOmD,EAAWtC,MAAKD,GAAOA,EAAID,KAAO4B,KAAeY,EAAW,EACrE,CAEM,SAAUC,EAAkBpD,EAAiBuC,GACjD,OAAOW,EAAalD,EAAMuC,IAAaO,OAAS,MAClD,CAGM,SAAUO,EACdC,EACAC,EACAC,EACAC,EAAa,GAEb,MAAMC,EAAOJ,EAAqBC,EAClC,GAAIC,EAAW,CACb,OAAOE,GAAQD,C,CAEjB,OAAOC,EAAOD,CAChB,CC1DA,MAAME,EAAY,IAAM,koH,MCmDXC,EAAMC,EAAA,MAAAD,UAAAE,EALnB,WAAAC,CAAAC,G,gIAUUC,KAAAjE,KAAoB,GAGMiE,KAAAhD,SAAmB,GAG5BgD,KAAAhE,MAAgB,GAMjCgE,KAAA9C,QAA8B,GAGD8C,KAAA7C,YAAsB,GASnD6C,KAAAC,WAA+B,YAG/BD,KAAAlE,SAAmB,GAGnBkE,KAAAE,WAAqB,GAQZF,KAAAjD,aAA4B,GAC5BiD,KAAA/C,gBAAsC,GACtC+C,KAAAG,gBAA0B,GAC1BH,KAAAI,uBAAyB,MACzBJ,KAAAK,cAAgB,MAChBL,KAAAM,SAAW,MAEXN,KAAAO,mBAAqB,MAK9BP,KAAAQ,OAA6B,KAC7BR,KAAAS,UAAsC,KACtCT,KAAAU,OAAmC,KACnCV,KAAAW,kBAAkD,KAClDX,KAAAY,gBAAgD,KAChDZ,KAAAa,eAAwC,KACxCb,KAAAc,uBAAyB,MACzBd,KAAAe,yBAA2B,CAgapC,CA9ZC,kBAAYC,GACV,GAAIhB,KAAKE,YAAcF,KAAKlE,SAAU,CACpC,OAAOkE,KAAKG,e,CAEd,OAAOH,KAAKhE,K,CAGd,kBAAYiF,GACV,OAAO9B,EAAkBa,KAAKjD,aAAciD,KAAKgB,e,CAGnD,mBAAYE,GACV,QAASjC,EAAae,KAAKjD,aAAciD,KAAKgB,iBAAiBG,G,CAOjE,aAAAC,GACEpB,KAAKjD,aAAeiD,KAAKhD,SACrBK,EAAmB2C,KAAKhD,SAAU,IACjCgD,KAAKjE,MAAQ,GAClBiE,KAAK/C,gBAAkB+C,KAAK7C,YACxBE,EAAmB2C,KAAK7C,YAAa,IACpC6C,KAAK9C,SAAW,GACrB8C,KAAKqB,mBACLrB,KAAKe,yBAA2B,EAChCf,KAAKsB,uB,CAKP,WAAAC,GACEvB,KAAKqB,mBACLrB,KAAKsB,uB,CAKP,iBAAAE,GACExB,KAAKyB,mBACLzB,KAAKsB,uB,CAIP,gBAAAI,CAAiBC,GACf,GAAI3B,KAAKU,OAAQ,CACfV,KAAKU,OAAOiB,KAAOA,C,EAKvB,qBAAAC,CAAsBrC,EAAoBsC,GACxC,IAAKtC,EAAW,CACdS,KAAKM,SAAW,MAChBN,KAAKU,OAAS,I,CAEhBV,KAAKsB,wBACL,GAAI/B,GAAasC,IAAkBC,WAAaD,IAAkBtC,EAAW,OAC7EwC,uBAAsB,IAAM/B,KAAKsB,0BACjCU,gBAAe,IAAMhC,KAAKiC,2B,CAG5B,iBAAAC,GACElC,KAAKoB,e,CAGP,gBAAAe,GACEnC,KAAKoC,wBACLpC,KAAKqC,+BACLrC,KAAKsC,wBACLtC,KAAKsB,uB,CAGP,kBAAAiB,GACEvC,KAAKsB,wBACLtB,KAAKwC,gB,CAGP,oBAAAC,GACEzC,KAAKa,gBAAgB6B,aACrB1C,KAAKa,eAAiB,I,CAIhB,qBAAAuB,GACN,GACEtF,EACEkD,KAAKjD,aACLiD,KAAKjE,KACLiE,KAAKhD,SACLgD,KAAK/C,gBACL+C,KAAK9C,QACL8C,KAAK7C,aAEP,CACA6C,KAAKoB,e,MACA,GAAIpB,KAAKE,YAAcF,KAAKlE,SAAU,CAC3CkE,KAAKqB,kB,EAKD,4BAAAgB,GACN,IAAIM,EAAYhD,EAAOiD,sBACvB,MAAMC,EAAO,KACX7C,KAAKoC,wBACL,KAAMO,EAAY,EAAG,CACnBZ,sBAAsBc,E,GAG1Bb,eAAea,E,CAGT,qBAAAP,GACN,UAAWQ,iBAAmB,cAAgB9C,KAAKQ,OAAQ,OAC3DR,KAAKa,gBAAgB6B,aACrB1C,KAAKa,eAAiB,IAAIiC,gBAAe,IAAM9C,KAAKsB,0BACpDtB,KAAKa,eAAekC,QAAQ/C,KAAKQ,QACjC,MAAMwC,EAAShD,KAAKQ,OAAOyC,cAC3B,GAAID,EAAQ,CACVhD,KAAKa,eAAekC,QAAQC,E,EAIxB,qBAAA1B,GACN,GAAItB,KAAKc,uBAAwB,OACjCd,KAAKc,uBAAyB,KAC9BiB,uBAAsB,KACpB/B,KAAKc,uBAAyB,MAC9Bd,KAAKkD,qBAAqB,G,CAKtB,yBAAAC,GACN,IAAKnD,KAAKQ,OAAQ,OAAO,EAEzB,MAAMwC,EAAShD,KAAKQ,OAAOyC,cAC3B,IAAKD,GAAQI,UAAUC,SAAS,WAAY,CAC1C,OAAOrD,KAAKQ,OAAO8C,W,CAGrB,MAAMC,EAAcC,iBAAiBR,GACrC,MAAMS,EAAMC,WAAWH,EAAYI,WAAaJ,EAAYE,KAAO,MAAQ,EAC3E,MAAMG,EAAYZ,EAAO9E,cAAc,qBACvC,MAAM2F,EAAeD,GAAWE,aAAe,EAC/C,MAAMC,GACHL,WAAWH,EAAYS,cAAgB,IAAMN,WAAWH,EAAYU,eAAiB,GACxF,MAAMC,EAAYlB,EAAOM,YAAcS,EAAoBF,GAAgBD,EAAYH,EAAM,GAE7F,OAAOU,KAAKC,IAAI,EAAGF,E,CAGb,qBAAAG,GACN,MAAMC,EAAUnG,EAAuB6B,KAAKY,iBAC5C,OAAO0D,GAASC,aAAe,C,CAGzB,2BAAAC,GACN,GAAIxE,KAAKe,0BAA4BpB,EAAO8E,0BAA2B,OACvEzE,KAAKe,2BACLgB,uBAAsB,IAAM/B,KAAKsB,yB,CAG3B,mBAAA4B,GACN,IAAKlD,KAAKQ,QAAUR,KAAKjD,aAAaV,SAAW,GAAK2D,KAAKI,uBAAwB,CACjF,GAAIJ,KAAKK,cAAe,CACtBL,KAAKK,cAAgB,MACrBL,KAAKM,SAAW,K,CAElBN,KAAKe,yBAA2B,EAChC,M,CAGF,MAAM2D,EAAiB1E,KAAKqE,wBAC5B,GAAIK,IAAmB,EAAG,CACxB1E,KAAKwE,8BACL,M,CAEFxE,KAAKe,yBAA2B,EAEhC,MAAM4D,EAAiBvF,EACrBsF,EACA1E,KAAKmD,4BACLnD,KAAKK,eAGP,GAAIsE,IAAmB3E,KAAKK,cAAe,CACzCL,KAAKK,cAAgBsE,EACrB,IAAKA,EAAgB,CACnB3E,KAAKM,SAAW,K,GAKd,cAAAkC,GACN,IAAKxC,KAAKU,SAAWV,KAAKS,YAAcT,KAAKK,cAAe,OAC5DL,KAAKU,OAAOkE,OAAS5E,KAAKS,UAC1BT,KAAKyB,kB,CAGC,gBAAAoD,CAAiBC,GACvB,MAAMC,EAAUD,EAAgCC,OAChD,GAAIA,GAAQ/I,QAAU8F,UAAW,CAC/B9B,KAAKgF,UAAUC,OAAOF,EAAO/I,O,CAE/BgE,KAAKM,SAAW,K,CAGV,eAAA4E,GACNlF,KAAKM,SAAW,K,CAGV,gBAAAmB,GACN,IAAKzB,KAAKU,OAAQ,OAClBV,KAAKU,OAAOnC,SAAWF,EAAmB2B,KAAKjD,aAAciD,KAAKgB,e,CAG5D,gBAAAK,GACN,IAAKrB,KAAKE,aAAeF,KAAKlE,SAAU,CACtCkE,KAAKG,gBAAkB,GACvBH,KAAKI,uBAAyB,MAC9B,M,CAGF,MAAMpE,MAAEA,EAAKC,SAAEA,GAAaL,EAC1BoE,KAAKE,WACLF,KAAKlE,SACLkE,KAAKjD,cAEPiD,KAAKG,gBAAkBnE,EACvBgE,KAAKI,uBAAyBnE,C,CAGxB,SAAA+I,CAAUtI,GAChBsD,KAAKhE,MAAQU,EACbsD,KAAKmF,YAAYC,KAAK1I,E,CAIhB,uBAAAuF,GACN,MAAMtF,EAAMkB,EACVmC,KAAKW,kBACL,iBAAiBX,KAAKgB,oBAExBrE,GAAK0I,MAAM,CAAEC,cAAe,M,CAGtB,eAAAC,CAAgBT,GACtB9E,KAAKgF,UAAWF,EAA0BC,O,CAGpC,kBAAAS,CAAmBC,EAAkBX,GAC3C,MAAMY,EAAYZ,EAA2BC,OAC7C/E,KAAK2F,eAAeP,KAAK,CAAE1I,GAAI+I,EAAUC,Y,CAGnC,aAAAE,GACN,GAAI5F,KAAKM,SAAU,CACjBN,KAAKM,SAAW,MAChB,M,CAGF,GAAIN,KAAKU,QAAUV,KAAKS,UAAW,CACjCT,KAAKU,OAAOkE,OAAS5E,KAAKS,UAC1BT,KAAKU,OAAOmF,SAAW,GAAG7F,KAAKS,UAAUqD,gBACzC9D,KAAKyB,kB,CAGPzB,KAAKM,SAAW,I,CAGV,oBAAAwF,CAAqBhB,GAC3B,IAAK9E,KAAKK,cAAe,OAEzB,IAAKL,KAAKM,SAAU,CAClB,GAAIwE,EAAEiB,MAAQ,aAAejB,EAAEiB,MAAQ,WAAajB,EAAEiB,MAAQ,SAAWjB,EAAEiB,MAAQ,IAAK,CACtFjB,EAAEkB,iBACFhG,KAAK4F,e,CAEP,M,CAGF,GAAId,EAAEiB,MAAQ,SAAU,CACtBjB,EAAEkB,iBACFhG,KAAKM,SAAW,MAChBN,KAAKS,WAAW4E,O,EAIpB,MAAAY,GACE,MAAMC,EAAUlG,KAAKjD,aAAaV,OAAS,IAAM2D,KAAKI,uBAEtD,MAAM+F,EAA0E,GAChF,MAAMC,EAA+CD,EAAanG,KAAKC,YAEvE,OACEoG,EAACC,EAAI,CAAAP,IAAA,4CACHM,EAAA,UAAAN,IAAA,2CAAQQ,MAAO,CAAE,UAAW,KAAM,CAAC,MAAMvG,KAAKC,cAAe,OAE3DoG,EAAA,OAAAN,IAAA,2CACEQ,MAAM,gBACNC,IAAKC,IACHzG,KAAKQ,OAASiG,EACd,GAAIA,IAAOzG,KAAKa,eAAgB,CAC9Bb,KAAKsC,uB,IAIR4D,GACCG,EAAA,OAAAN,IAAA,2CAAKQ,MAAM,sBAAqB,cAAa,OAAOG,MAAK,MACvDL,EAAA,gBAAAN,IAAA,2CACES,IAAKC,IACHzG,KAAKY,gBAAmB6F,GAAgC,KACxD,GAAIA,EAAI,CACNzG,KAAKe,yBAA2B,EAChCf,KAAKsB,uB,GAGTvF,KAAMiE,KAAKjD,aACXf,MAAOgE,KAAKgB,kBAKjBkF,IAAYlG,KAAKK,eAChBgG,EAAA,gBAAAN,IAAA,2CACEQ,MAAM,wBACNC,IAAKC,IACHzG,KAAKW,kBAAoB8F,CAA2B,EAEtD1K,KAAMiE,KAAKjD,aACXf,MAAOgE,KAAKgB,eACZ2F,WAAa7B,GAAa9E,KAAKuF,gBAAgBT,MAIjDoB,GAAWlG,KAAK4G,SAChBP,EAAA,QAAAN,IAAA,2CAAMQ,MAAM,8CAA8CvG,KAAK4G,SAGhEV,GAAWlG,KAAKK,eACfgG,EAAA,UAAAN,IAAA,2CACEc,KAAK,SACLN,MAAO,CACL,uBAAwB,KACxB,6BAA8BvG,KAAKM,UAErCkG,IAAKC,IACHzG,KAAKS,UAAYgG,CAAuB,EACzC,gBACa,OAAM,gBACLzG,KAAKM,SAAQ,aAChB,GAAGN,KAAKiB,sBACpB6F,QAAS,IAAM9G,KAAK4F,gBACpBmB,UAAYjC,GAAqB9E,KAAK8F,qBAAqBhB,IAE3DuB,EAAA,QAAAN,IAAA,2CAAMQ,MAAO,CACX,6BAA8B,KAC9B,kCAAmCvG,KAAKkB,gBACxC,4BAA6B,OAE5BlB,KAAKiB,eACLjB,KAAKkB,iBACJmF,EAAA,QAAAN,IAAA,2CAAMQ,MAAM,2BAA0B,cAAa,UAGvDF,EAAA,WAAAN,IAAA,2CACEiB,KAAK,cACLC,KAAK,KACLC,MAAM,UACNX,MAAM,mCAMbvG,KAAK/C,gBAAgBZ,OAAS,GAC7BgK,EAAA,OAAAN,IAAA,2CAAKQ,MAAM,oBACRvG,KAAK/C,gBAAgBkK,KAAIC,GACxBf,EAAA,qBACEN,IAAKqB,EAAO1K,GACZ2K,KAAMD,EAAOC,KACb3B,SAAU0B,EAAO1B,UAAY,MAC7BvE,IAAKiG,EAAOjG,KAAO,MACnBmG,SAAUF,EAAOE,SAAQ,aACbF,EAAOG,WAAaH,EAAO1K,GACvCuD,WAAYmG,EACZO,WAAa7B,GAAa9E,KAAKwF,mBAAmB4B,EAAO1K,GAAIoI,SAQtEoB,GAAWlG,KAAKK,eACfgG,EAAA,WAAAN,IAAA,2CACES,IAAKC,IACHzG,KAAKU,OAAU+F,GAA4B,IAAI,EAEjD9E,KAAM3B,KAAKM,SACX/B,SAAUF,EAAmB2B,KAAKjD,aAAciD,KAAKgB,gBACrDwG,KAAK,SACLC,MAAM,QACNC,WAAa5C,GAAa9E,KAAK6E,iBAAiBC,GAChD6C,UAAW,IAAM3H,KAAKkF,oB,ihCApaRvF,EAAAiD,sBAAwB,EACxBjD,EAAA8E,0BAA4B,E","ignoreList":[]}
1
+ {"version":3,"names":["deriveBarNavValueFromUrl","path","basePath","tabs","value","hideTabs","startsWith","remainder","slice","length","seg","split","selectableTabs","getSelectableTabs","id","tab","find","t","shouldResyncBarNavProps","resolvedTabs","tabsJson","resolvedActions","actions","actionsJson","tabsIncoming","parseJsonArrayProp","actionsIncoming","fallback","Array","isArray","parsed","JSON","parse","queryWithinComponentHost","host","selector","root","shadowRoot","querySelector","getTabListFromTabGroup","tabGroupEl","tabsToMenuSections","selectedId","sections","batch","item","isTabDivider","push","items","label","isSelected","isInactive","disabled","getActiveTab","selectable","getActiveTabLabel","tabsOverflowContainer","tabListScrollWidth","containerClientWidth","collapsed","hysteresis","diff","barNavCss","BarNav","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","background","currentUrl","urlDerivedValue","hideTabsForDetailRoute","tabsCollapsed","menuOpen","tabLayoutCommitted","leftEl","triggerEl","menuEl","visibleTabGroupEl","probeTabGroupEl","resizeObserver","overflowCheckScheduled","intrinsicWidthRetryCount","effectiveValue","activeTabLabel","activeTabHasDot","dot","onPropsChange","syncValueFromUrl","scheduleOverflowCheck","onUrlChange","onSelectionChange","syncMenuSections","onMenuOpenChange","open","onTabsCollapsedChange","prevCollapsed","undefined","requestAnimationFrame","queueMicrotask","focusVisibleSelectedTab","componentWillLoad","componentDidLoad","syncHostPropsIfNeeded","scheduleDeferredHostPropSync","setupOverflowObserver","componentDidRender","syncMenuAnchor","disconnectedCallback","disconnect","remaining","HOST_PROP_SYNC_BUDGET","tick","ResizeObserver","observe","header","parentElement","updateTabsCollapsed","getLeftZoneAvailableWidth","classList","contains","clientWidth","headerStyle","getComputedStyle","gap","parseFloat","columnGap","actionsEl","actionsWidth","offsetWidth","horizontalPadding","paddingLeft","paddingRight","available","Math","max","getTabsIntrinsicWidth","tabList","scrollWidth","scheduleIntrinsicWidthRetry","INTRINSIC_WIDTH_RETRY_MAX","intrinsicWidth","shouldCollapse","anchor","handleMenuSelect","e","detail","selectTab","String","handleMenuClose","dsTabChange","emit","focus","preventScroll","handleTabChange","handleActionChange","actionId","selected","dsActionChange","toggleTabMenu","minWidth","handleTriggerKeyDown","key","preventDefault","render","hasTabs","bgToActionBg","actionBg","h","Host","class","ref","el","inert","onDsChange","heading","type","onClick","onKeyDown","name","size","color","map","action","icon","inactive","ariaLabel","side","align","onDsSelect","onDsClose"],"sources":["src/wc/components/BarNav/bar-nav-utils.ts","src/wc/components/BarNav/bar-nav-dom-utils.ts","src/wc/components/BarNav/bar-nav-tabs-menu-utils.ts","src/wc/components/BarNav/BarNav.css?tag=ds-bar-nav&encapsulation=scoped","src/wc/components/BarNav/BarNav.tsx"],"sourcesContent":["import { getSelectableTabs } from '../TabGroup/tab-item-utils';\nimport type { BarNavActionItem, 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 const selectableTabs = getSelectableTabs(tabs);\n\n if (!seg) {\n return { value: selectableTabs[0]?.id ?? '', hideTabs: false };\n }\n\n const tab = selectableTabs.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/** True when host array/json props have data but resolved internal state is still empty. */\nexport function shouldResyncBarNavProps(\n resolvedTabs: BarNavTab[],\n tabs: BarNavTab[],\n tabsJson: string,\n resolvedActions: BarNavActionItem[],\n actions: BarNavActionItem[],\n actionsJson: string,\n): boolean {\n const tabsIncoming = tabsJson\n ? parseJsonArrayProp(tabsJson, [])\n : (tabs ?? []);\n const actionsIncoming = actionsJson\n ? parseJsonArrayProp(actionsJson, [])\n : (actions ?? []);\n\n return (\n (resolvedTabs.length === 0 && tabsIncoming.length > 0) ||\n (resolvedActions.length === 0 && actionsIncoming.length > 0)\n );\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","type QueryableHost = {\n shadowRoot?: ShadowRoot | null;\n querySelector: (selectors: string) => Element | null;\n};\n\n/**\n * Query within a Stencil custom-element host (light DOM today, shadow DOM–safe).\n * Use for child nodes owned by ds-tab-group and similar components.\n */\nexport function queryWithinComponentHost(\n host: QueryableHost | null | undefined,\n selector: string,\n): HTMLElement | null {\n if (!host) return null;\n const root = host.shadowRoot ?? host;\n return root.querySelector(selector) as HTMLElement | null;\n}\n\nexport function getTabListFromTabGroup(\n tabGroupEl: QueryableHost | null | undefined,\n): HTMLElement | null {\n return queryWithinComponentHost(tabGroupEl, '[role=\"tablist\"]');\n}\n","import type { MenuSection } from '../Menu/Menu';\nimport {\n getSelectableTabs,\n isTabDivider,\n type TabItem,\n type TabItemTab,\n} from '../TabGroup/tab-item-utils';\n\n/** Map BarNav tabs to menu sections, preserving `{ type: 'divider' }` as section breaks. */\nexport function tabsToMenuSections(tabs: TabItem[], selectedId: string): MenuSection[] {\n const sections: MenuSection[] = [];\n let batch: MenuSection['items'] = [];\n\n for (const item of tabs) {\n if (isTabDivider(item)) {\n if (batch.length > 0) {\n sections.push({ items: batch });\n batch = [];\n }\n continue;\n }\n\n batch.push({\n label: item.label,\n value: item.id,\n isSelected: item.id === selectedId,\n isInactive: item.disabled,\n });\n }\n\n if (batch.length > 0) {\n sections.push({ items: batch });\n }\n\n return sections;\n}\n\nexport function getActiveTab(tabs: TabItem[], selectedId: string): TabItemTab | undefined {\n const selectable = getSelectableTabs(tabs);\n return selectable.find(tab => tab.id === selectedId) ?? selectable[0];\n}\n\nexport function getActiveTabLabel(tabs: TabItem[], selectedId: string): string {\n return getActiveTab(tabs, selectedId)?.label ?? 'Tabs';\n}\n\n/** True when tablist content exceeds the available width (with optional hysteresis). */\nexport function tabsOverflowContainer(\n tabListScrollWidth: number,\n containerClientWidth: number,\n collapsed: boolean,\n hysteresis = 2,\n): boolean {\n const diff = tabListScrollWidth - containerClientWidth;\n if (collapsed) {\n return diff > -hysteresis;\n }\n return diff > hysteresis;\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 — always consume remaining header width (even when collapsed to a narrow trigger) */\n.bar-nav__left {\n position: relative;\n flex: 1 1 0%;\n min-width: 0;\n 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/* Unconstrained width so intrinsic tab row width is measurable while collapsed */\n.bar-nav__tabs-probe {\n position: absolute;\n left: 0;\n top: 0;\n visibility: hidden;\n pointer-events: none;\n overflow: visible;\n width: max-content;\n max-width: none;\n z-index: -1;\n}\n\n.bar-nav__tabs-probe ds-tab-group {\n width: max-content;\n}\n\n.bar-nav__tabs-visible {\n width: 100%;\n min-width: 0;\n}\n\n/* In-flow placeholder while measuring overflow — avoids layout jump; hidden from view/accessibility. */\n.bar-nav__tabs-pending {\n flex: 1;\n min-width: 0;\n height: var(--dimension-size-400);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* Collapsed tab trigger — tab interaction pattern, not ds-button */\n.bar-nav__tab-trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-050);\n max-width: 100%;\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-025);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n color: var(--color-foreground-primary);\n position: relative;\n transition: color var(--effect-motion-short-2);\n flex-shrink: 1;\n min-width: 0;\n height: var(--dimension-size-400);\n box-sizing: border-box;\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_dot: var(--color-foreground-bold-brand);\n --_dot-ring: var(--color-background-secondary);\n}\n\n.bar-nav__tab-trigger::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: var(--dimension-radius-025);\n background: transparent;\n pointer-events: none;\n transition: none;\n}\n\n.bar-nav__tab-trigger:hover::after {\n background: var(--_hover-bg);\n transition: none;\n}\n\n.bar-nav__tab-trigger:active::after {\n background: var(--_pressed-bg);\n transition: none;\n}\n\n.bar-nav__tab-trigger:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.bar-nav__tab-trigger--open::after {\n background: var(--_hover-bg);\n}\n\n.bar-nav__tab-trigger-label {\n position: relative;\n display: inline-flex;\n align-items: center;\n min-width: 0;\n padding: 0 var(--dimension-space-025);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.bar-nav__tab-trigger-label--dot {\n padding-right: calc(var(--dimension-space-025) + var(--dimension-space-050));\n}\n\n.bar-nav__tab-trigger-dot {\n position: absolute;\n top: 0;\n right: 0;\n width: var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));\n height: var(--dimension-size-075, calc(var(--dimension-size-base) * 3 / 4));\n border-radius: var(--dimension-radius-half);\n background: var(--_dot);\n box-shadow: 0 0 0 var(--dimension-stroke-width-018) var(--_dot-ring);\n pointer-events: none;\n}\n\n.bar-nav__tab-trigger-chevron {\n flex-shrink: 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 {\n Component,\n Prop,\n Event,\n EventEmitter,\n Watch,\n State,\n h,\n Host,\n} from '@stencil/core';\nimport type { MenuItemData } from '../Menu/Menu';\nimport type { BarNavActionBackground } from '../BarNavAction/BarNavAction';\nimport type { TabItem } from '../TabGroup/tab-item-utils';\nimport {\n deriveBarNavValueFromUrl,\n parseJsonArrayProp,\n shouldResyncBarNavProps,\n} from './bar-nav-utils';\nimport {\n getTabListFromTabGroup,\n queryWithinComponentHost,\n} from './bar-nav-dom-utils';\nimport {\n getActiveTab,\n getActiveTabLabel,\n tabsOverflowContainer,\n tabsToMenuSections,\n} from './bar-nav-tabs-menu-utils';\n\nexport type BarNavBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\n/** Same shape as `TabItem` — supports `{ type: 'divider' }` between tab groups. */\nexport type BarNavTab = TabItem;\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 @State() private tabsCollapsed = false;\n @State() private menuOpen = false;\n /** When false, defer showing expanded tabs or the collapsed trigger until intrinsic width is measured (avoids a one-frame flash of the full tab row on narrow viewports). */\n @State() private tabLayoutCommitted = false;\n\n private static readonly HOST_PROP_SYNC_BUDGET = 8;\n private static readonly INTRINSIC_WIDTH_RETRY_MAX = 3;\n\n private leftEl: HTMLElement | null = null;\n private triggerEl: HTMLButtonElement | null = null;\n private menuEl: HTMLDsMenuElement | null = null;\n private visibleTabGroupEl: HTMLDsTabGroupElement | null = null;\n private probeTabGroupEl: HTMLDsTabGroupElement | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private overflowCheckScheduled = false;\n private intrinsicWidthRetryCount = 0;\n\n private get effectiveValue(): string {\n if (this.currentUrl && this.basePath) {\n return this.urlDerivedValue;\n }\n return this.value;\n }\n\n private get activeTabLabel(): string {\n return getActiveTabLabel(this.resolvedTabs, this.effectiveValue);\n }\n\n private get activeTabHasDot(): boolean {\n return !!getActiveTab(this.resolvedTabs, this.effectiveValue)?.dot;\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 this.intrinsicWidthRetryCount = 0;\n this.scheduleOverflowCheck();\n }\n\n @Watch('currentUrl')\n @Watch('basePath')\n onUrlChange() {\n this.syncValueFromUrl();\n this.scheduleOverflowCheck();\n }\n\n @Watch('value')\n @Watch('urlDerivedValue')\n onSelectionChange() {\n this.syncMenuSections();\n this.scheduleOverflowCheck();\n }\n\n @Watch('menuOpen')\n onMenuOpenChange(open: boolean) {\n if (this.menuEl) {\n this.menuEl.open = open;\n }\n }\n\n @Watch('tabsCollapsed')\n onTabsCollapsedChange(collapsed: boolean, prevCollapsed: boolean | undefined) {\n if (!collapsed) {\n this.menuOpen = false;\n this.menuEl = null;\n }\n this.scheduleOverflowCheck();\n if (collapsed || prevCollapsed === undefined || prevCollapsed === collapsed) return;\n requestAnimationFrame(() => this.scheduleOverflowCheck());\n queueMicrotask(() => this.focusVisibleSelectedTab());\n }\n\n componentWillLoad() {\n this.onPropsChange();\n }\n\n componentDidLoad() {\n this.syncHostPropsIfNeeded();\n this.scheduleDeferredHostPropSync();\n this.setupOverflowObserver();\n this.scheduleOverflowCheck();\n }\n\n componentDidRender() {\n this.scheduleOverflowCheck();\n this.syncMenuAnchor();\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n }\n\n /** Re-resolve props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */\n private syncHostPropsIfNeeded() {\n if (\n shouldResyncBarNavProps(\n this.resolvedTabs,\n this.tabs,\n this.tabsJson,\n this.resolvedActions,\n this.actions,\n this.actionsJson,\n )\n ) {\n this.onPropsChange();\n } else if (this.currentUrl && this.basePath) {\n this.syncValueFromUrl();\n }\n }\n\n /** Poll across animation frames — host props may land without triggering @Watch. */\n private scheduleDeferredHostPropSync() {\n let remaining = BarNav.HOST_PROP_SYNC_BUDGET;\n const tick = () => {\n this.syncHostPropsIfNeeded();\n if (--remaining > 0) {\n requestAnimationFrame(tick);\n }\n };\n queueMicrotask(tick);\n }\n\n private setupOverflowObserver() {\n if (typeof ResizeObserver === 'undefined' || !this.leftEl) return;\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => this.scheduleOverflowCheck());\n this.resizeObserver.observe(this.leftEl);\n const header = this.leftEl.parentElement;\n if (header) {\n this.resizeObserver.observe(header);\n }\n }\n\n private scheduleOverflowCheck() {\n if (this.overflowCheckScheduled) return;\n this.overflowCheckScheduled = true;\n requestAnimationFrame(() => {\n this.overflowCheckScheduled = false;\n this.updateTabsCollapsed();\n });\n }\n\n /** Width left for tabs after actions — stable while collapsed (unlike leftEl box when hugging the trigger). */\n private getLeftZoneAvailableWidth(): number {\n if (!this.leftEl) return 0;\n\n const header = this.leftEl.parentElement;\n if (!header?.classList.contains('bar-nav')) {\n return this.leftEl.clientWidth;\n }\n\n const headerStyle = getComputedStyle(header);\n const gap = parseFloat(headerStyle.columnGap || headerStyle.gap || '0') || 0;\n const actionsEl = header.querySelector('.bar-nav__actions') as HTMLElement | null;\n const actionsWidth = actionsEl?.offsetWidth ?? 0;\n const horizontalPadding =\n (parseFloat(headerStyle.paddingLeft) || 0) + (parseFloat(headerStyle.paddingRight) || 0);\n const available = header.clientWidth - horizontalPadding - actionsWidth - (actionsEl ? gap : 0);\n\n return Math.max(0, available);\n }\n\n private getTabsIntrinsicWidth(): number {\n const tabList = getTabListFromTabGroup(this.probeTabGroupEl);\n return tabList?.scrollWidth ?? 0;\n }\n\n private scheduleIntrinsicWidthRetry() {\n if (this.intrinsicWidthRetryCount >= BarNav.INTRINSIC_WIDTH_RETRY_MAX) return;\n this.intrinsicWidthRetryCount++;\n requestAnimationFrame(() => this.scheduleOverflowCheck());\n }\n\n private updateTabsCollapsed() {\n if (!this.leftEl || this.resolvedTabs.length === 0 || this.hideTabsForDetailRoute) {\n if (this.tabsCollapsed) {\n this.tabsCollapsed = false;\n this.menuOpen = false;\n }\n this.intrinsicWidthRetryCount = 0;\n return;\n }\n\n const intrinsicWidth = this.getTabsIntrinsicWidth();\n if (intrinsicWidth === 0) {\n this.scheduleIntrinsicWidthRetry();\n return;\n }\n this.intrinsicWidthRetryCount = 0;\n\n const shouldCollapse = tabsOverflowContainer(\n intrinsicWidth,\n this.getLeftZoneAvailableWidth(),\n this.tabsCollapsed,\n );\n\n if (shouldCollapse !== this.tabsCollapsed) {\n this.tabsCollapsed = shouldCollapse;\n if (!shouldCollapse) {\n this.menuOpen = false;\n }\n }\n }\n\n private syncMenuAnchor() {\n if (!this.menuEl || !this.triggerEl || !this.tabsCollapsed) return;\n this.menuEl.anchor = this.triggerEl;\n this.syncMenuSections();\n }\n\n private handleMenuSelect(e: Event) {\n const detail = (e as CustomEvent<MenuItemData>).detail;\n if (detail?.value !== undefined) {\n this.selectTab(String(detail.value));\n }\n this.menuOpen = false;\n }\n\n private handleMenuClose() {\n this.menuOpen = false;\n }\n\n private syncMenuSections() {\n if (!this.menuEl) return;\n this.menuEl.sections = tabsToMenuSections(this.resolvedTabs, this.effectiveValue);\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 selectTab(id: string) {\n this.value = id;\n this.dsTabChange.emit(id);\n }\n\n /** Move focus to the selected tab in the visible tab group (after expand). */\n private focusVisibleSelectedTab() {\n const tab = queryWithinComponentHost(\n this.visibleTabGroupEl,\n `[data-tab-id=\"${this.effectiveValue}\"]`,\n );\n tab?.focus({ preventScroll: true });\n }\n\n private handleTabChange(e: Event) {\n this.selectTab((e as CustomEvent<string>).detail);\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 private toggleTabMenu() {\n if (this.menuOpen) {\n this.menuOpen = false;\n return;\n }\n\n if (this.menuEl && this.triggerEl) {\n this.menuEl.anchor = this.triggerEl;\n this.menuEl.minWidth = `${this.triggerEl.offsetWidth}px`;\n this.syncMenuSections();\n }\n\n this.menuOpen = true;\n }\n\n private handleTriggerKeyDown(e: KeyboardEvent) {\n if (!this.tabsCollapsed) return;\n\n if (!this.menuOpen) {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.toggleTabMenu();\n }\n return;\n }\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.menuOpen = false;\n this.triggerEl?.focus();\n }\n }\n\n render() {\n const hasTabs = this.resolvedTabs.length > 0 && !this.hideTabsForDetailRoute;\n\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\n class=\"bar-nav__left\"\n ref={el => {\n this.leftEl = el as HTMLElement;\n if (el && !this.resizeObserver) {\n this.setupOverflowObserver();\n }\n }}\n >\n {hasTabs && (\n <div class=\"bar-nav__tabs-probe\" aria-hidden=\"true\" inert>\n <ds-tab-group\n ref={el => {\n this.probeTabGroupEl = (el as HTMLDsTabGroupElement) ?? null;\n if (el) {\n this.intrinsicWidthRetryCount = 0;\n this.scheduleOverflowCheck();\n }\n }}\n tabs={this.resolvedTabs}\n value={this.effectiveValue}\n />\n </div>\n )}\n\n {hasTabs && !this.tabsCollapsed && (\n <ds-tab-group\n class=\"bar-nav__tabs-visible\"\n ref={el => {\n this.visibleTabGroupEl = el as HTMLDsTabGroupElement;\n }}\n tabs={this.resolvedTabs}\n value={this.effectiveValue}\n onDsChange={(e: Event) => this.handleTabChange(e)}\n />\n )}\n\n {!hasTabs && this.heading && (\n <span class=\"bar-nav__heading text-body-medium-emphasis\">{this.heading}</span>\n )}\n\n {hasTabs && this.tabsCollapsed && (\n <button\n type=\"button\"\n class={{\n 'bar-nav__tab-trigger': true,\n 'bar-nav__tab-trigger--open': this.menuOpen,\n }}\n ref={el => {\n this.triggerEl = el as HTMLButtonElement;\n }}\n aria-haspopup=\"menu\"\n aria-expanded={this.menuOpen}\n aria-label={`${this.activeTabLabel} tabs`}\n onClick={() => this.toggleTabMenu()}\n onKeyDown={(e: KeyboardEvent) => this.handleTriggerKeyDown(e)}\n >\n <span class={{\n 'bar-nav__tab-trigger-label': true,\n 'bar-nav__tab-trigger-label--dot': this.activeTabHasDot,\n 'text-body-medium-emphasis': true,\n }}>\n {this.activeTabLabel}\n {this.activeTabHasDot && (\n <span class=\"bar-nav__tab-trigger-dot\" aria-hidden=\"true\" />\n )}\n </span>\n <ds-icon\n name=\"ChevronDown\"\n size=\"md\"\n color=\"inherit\"\n class=\"bar-nav__tab-trigger-chevron\"\n />\n </button>\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\n {hasTabs && this.tabsCollapsed && (\n <ds-menu\n ref={el => {\n this.menuEl = (el as HTMLDsMenuElement) ?? null;\n }}\n open={this.menuOpen}\n sections={tabsToMenuSections(this.resolvedTabs, this.effectiveValue)}\n side=\"bottom\"\n align=\"start\"\n onDsSelect={(e: Event) => this.handleMenuSelect(e)}\n onDsClose={() => this.handleMenuClose()}\n />\n )}\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- import{M as o,d as s}from"./p-CSIN3IaW.js";const t=o;const a=s;export{t as DsMenu,a as defineCustomElement};
1
+ import{M as o,d as s}from"./p-STnE_bmQ.js";const t=o;const m=s;export{t as DsMenu,m as defineCustomElement};
2
2
  //# sourceMappingURL=ds-menu.js.map
@@ -1,2 +1,2 @@
1
- import{p as e,H as s,c as t,h as i,a as r,t as o}from"./index.js";import{d as n}from"./p-CSIN3IaW.js";const a=()=>`.select-host.sc-ds-select-h{display:inline-block;width:100%;position:relative}.inactive.sc-ds-select-h{opacity:0.5;pointer-events:none}.trigger.sc-ds-select{display:inline-flex;align-items:center;justify-content:space-between;width:100%;height:var(--dimension-size-400);padding:0 var(--dimension-space-075) 0 var(--dimension-space-100);border:none;border-radius:var(--dimension-radius-050);background-color:var(--color-background-primary);box-shadow:var(--effect-elevation-elevated-sm);cursor:pointer;box-sizing:border-box;gap:var(--dimension-space-050);font-family:inherit;outline:none;--_hover-bg:color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));--_pressed-bg:color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary))}.trigger.sc-ds-select:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.trigger.sc-ds-select:hover:not(:disabled){background-color:var(--_hover-bg)}.trigger.sc-ds-select:active:not(:disabled){background-color:var(--_pressed-bg)}.trigger--open.sc-ds-select{background-color:var(--_pressed-bg)}.trigger__label.sc-ds-select{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;font-size:var(--typography-fontsize-md);line-height:var(--typography-lineheight-md);font-weight:var(--typography-weight-regular);color:var(--color-foreground-primary)}.trigger__label--placeholder.sc-ds-select{color:var(--color-foreground-secondary)}.trigger__chevron.sc-ds-select{flex-shrink:0;color:var(--color-foreground-secondary);transition:transform var(--effect-motion-short-2)}.trigger--open.sc-ds-select .trigger__chevron.sc-ds-select{transform:rotate(180deg)}`;const l=e(class e extends s{constructor(e){super();if(e!==false){this.__registerHost()}this.dsChange=t(this,"dsChange");this.options=[];this.value="";this.placeholder="Select option";this.inactive=false;this.isOpen=false;this.triggerEl=null;this.menuEl=null}componentDidLoad(){if(this.menuEl&&this.triggerEl){this.menuEl.anchor=this.triggerEl}this.menuEl?.addEventListener("dsSelect",(e=>{const s=e.detail;if(s?.value!==undefined){this.value=String(s.value);this.dsChange.emit(this.value)}this.isOpen=false}));this.menuEl?.addEventListener("dsClose",(()=>{this.isOpen=false}))}onIsOpenChange(e){if(this.menuEl){this.menuEl.open=e}}onOptionsChange(){this.syncMenuItems()}onValueChange(){this.syncMenuItems()}syncMenuItems(){if(!this.menuEl)return;this.menuEl.items=this.options.map((e=>({label:e.label,value:e.value,isSelected:e.value===this.value})))}open(){if(this.inactive||!this.options.length)return;if(this.menuEl&&this.triggerEl){this.menuEl.menuWidth=`${this.triggerEl.offsetWidth}px`;this.menuEl.anchor=this.triggerEl}this.syncMenuItems();this.isOpen=true}close(){this.isOpen=false}toggle(){if(this.isOpen){this.close()}else{this.open()}}handleKeyDown(e){if(document.activeElement!==this.triggerEl)return;if(!this.isOpen){switch(e.key){case"ArrowDown":case"ArrowUp":case"Enter":case" ":e.preventDefault();this.open();break}}else{if(e.key==="Escape"){e.preventDefault();this.close();this.triggerEl?.focus()}}}get selectedLabel(){const e=this.options.find((e=>e.value===this.value));return e?.label??""}get hasSelection(){return!!this.options.find((e=>e.value===this.value))}render(){const e=this.hasSelection?this.selectedLabel:this.placeholder;const s=!this.hasSelection;return i(r,{key:"fcffba37b8dcf974c2d74117d25e0380e356167e",class:{"select-host":true,inactive:this.inactive}},i("button",{key:"ed79b817bf6868792eac46ed999412afe7424d5f",ref:e=>{this.triggerEl=e??null},type:"button",class:{trigger:true,"trigger--open":this.isOpen},disabled:this.inactive,role:"combobox","aria-haspopup":"listbox","aria-expanded":this.isOpen,"aria-label":this.ariaLabel,"aria-labelledby":this.ariaLabelledby,onClick:()=>this.toggle()},i("span",{key:"0aec501ac7aed7b585ebb4e82e4012756bcd0568",class:{trigger__label:true,"trigger__label--placeholder":s}},e),i("svg",{key:"571234fad53285d8d9178154df802950f5f71d80",class:"trigger__chevron",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true"},i("path",{key:"f7024025bdadde316a71dcec5822ba0de2ef0781",d:"M4 6L8 10L12 6",stroke:"currentColor","stroke-width":"1.25","stroke-linecap":"round","stroke-linejoin":"round"}))),i("ds-menu",{key:"cbcb053228fee25d5e6823db842967dbda5b7214",ref:e=>{this.menuEl=e??null},side:"bottom",align:"start"}))}get el(){return this}static get watchers(){return{isOpen:[{onIsOpenChange:0}],options:[{onOptionsChange:0}],value:[{onValueChange:0}]}}static get style(){return a()}},[2,"ds-select",{options:[16],value:[1025],placeholder:[1],inactive:[4],ariaLabel:[1,"aria-label"],ariaLabelledby:[1,"aria-labelledby"],isOpen:[32]},[[0,"keydown","handleKeyDown"]],{isOpen:[{onIsOpenChange:0}],options:[{onOptionsChange:0}],value:[{onValueChange:0}]}]);function c(){if(typeof customElements==="undefined"){return}const e=["ds-select","ds-menu"];e.forEach((e=>{switch(e){case"ds-select":if(!customElements.get(o(e))){customElements.define(o(e),l)}break;case"ds-menu":if(!customElements.get(o(e))){n()}break}}))}c();const d=l;const h=c;export{d as DsSelect,h as defineCustomElement};
1
+ import{p as e,H as s,c as t,h as i,a as r,t as o}from"./index.js";import{d as n}from"./p-STnE_bmQ.js";const a=()=>`.select-host.sc-ds-select-h{display:inline-block;width:100%;position:relative}.inactive.sc-ds-select-h{opacity:0.5;pointer-events:none}.trigger.sc-ds-select{display:inline-flex;align-items:center;justify-content:space-between;width:100%;height:var(--dimension-size-400);padding:0 var(--dimension-space-075) 0 var(--dimension-space-100);border:none;border-radius:var(--dimension-radius-050);background-color:var(--color-background-primary);box-shadow:var(--effect-elevation-elevated-sm);cursor:pointer;box-sizing:border-box;gap:var(--dimension-space-050);font-family:inherit;outline:none;--_hover-bg:color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));--_pressed-bg:color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary))}.trigger.sc-ds-select:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.trigger.sc-ds-select:hover:not(:disabled){background-color:var(--_hover-bg)}.trigger.sc-ds-select:active:not(:disabled){background-color:var(--_pressed-bg)}.trigger--open.sc-ds-select{background-color:var(--_pressed-bg)}.trigger__label.sc-ds-select{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;font-size:var(--typography-fontsize-md);line-height:var(--typography-lineheight-md);font-weight:var(--typography-weight-regular);color:var(--color-foreground-primary)}.trigger__label--placeholder.sc-ds-select{color:var(--color-foreground-secondary)}.trigger__chevron.sc-ds-select{flex-shrink:0;color:var(--color-foreground-secondary);transition:transform var(--effect-motion-short-2)}.trigger--open.sc-ds-select .trigger__chevron.sc-ds-select{transform:rotate(180deg)}`;const l=e(class e extends s{constructor(e){super();if(e!==false){this.__registerHost()}this.dsChange=t(this,"dsChange");this.options=[];this.value="";this.placeholder="Select option";this.inactive=false;this.isOpen=false;this.triggerEl=null;this.menuEl=null}componentDidLoad(){if(this.menuEl&&this.triggerEl){this.menuEl.anchor=this.triggerEl}this.menuEl?.addEventListener("dsSelect",(e=>{const s=e.detail;if(s?.value!==undefined){this.value=String(s.value);this.dsChange.emit(this.value)}this.isOpen=false}));this.menuEl?.addEventListener("dsClose",(()=>{this.isOpen=false}))}onIsOpenChange(e){if(this.menuEl){this.menuEl.open=e}}onOptionsChange(){this.syncMenuItems()}onValueChange(){this.syncMenuItems()}syncMenuItems(){if(!this.menuEl)return;this.menuEl.items=this.options.map((e=>({label:e.label,value:e.value,isSelected:e.value===this.value})))}open(){if(this.inactive||!this.options.length)return;if(this.menuEl&&this.triggerEl){this.menuEl.menuWidth=`${this.triggerEl.offsetWidth}px`;this.menuEl.anchor=this.triggerEl}this.syncMenuItems();this.isOpen=true}close(){this.isOpen=false}toggle(){if(this.isOpen){this.close()}else{this.open()}}handleKeyDown(e){if(document.activeElement!==this.triggerEl)return;if(!this.isOpen){switch(e.key){case"ArrowDown":case"ArrowUp":case"Enter":case" ":e.preventDefault();this.open();break}}else{if(e.key==="Escape"){e.preventDefault();this.close();this.triggerEl?.focus()}}}get selectedLabel(){const e=this.options.find((e=>e.value===this.value));return e?.label??""}get hasSelection(){return!!this.options.find((e=>e.value===this.value))}render(){const e=this.hasSelection?this.selectedLabel:this.placeholder;const s=!this.hasSelection;return i(r,{key:"fcffba37b8dcf974c2d74117d25e0380e356167e",class:{"select-host":true,inactive:this.inactive}},i("button",{key:"ed79b817bf6868792eac46ed999412afe7424d5f",ref:e=>{this.triggerEl=e??null},type:"button",class:{trigger:true,"trigger--open":this.isOpen},disabled:this.inactive,role:"combobox","aria-haspopup":"listbox","aria-expanded":this.isOpen,"aria-label":this.ariaLabel,"aria-labelledby":this.ariaLabelledby,onClick:()=>this.toggle()},i("span",{key:"0aec501ac7aed7b585ebb4e82e4012756bcd0568",class:{trigger__label:true,"trigger__label--placeholder":s}},e),i("svg",{key:"571234fad53285d8d9178154df802950f5f71d80",class:"trigger__chevron",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true"},i("path",{key:"f7024025bdadde316a71dcec5822ba0de2ef0781",d:"M4 6L8 10L12 6",stroke:"currentColor","stroke-width":"1.25","stroke-linecap":"round","stroke-linejoin":"round"}))),i("ds-menu",{key:"cbcb053228fee25d5e6823db842967dbda5b7214",ref:e=>{this.menuEl=e??null},side:"bottom",align:"start"}))}get el(){return this}static get watchers(){return{isOpen:[{onIsOpenChange:0}],options:[{onOptionsChange:0}],value:[{onValueChange:0}]}}static get style(){return a()}},[2,"ds-select",{options:[16],value:[1025],placeholder:[1],inactive:[4],ariaLabel:[1,"aria-label"],ariaLabelledby:[1,"aria-labelledby"],isOpen:[32]},[[0,"keydown","handleKeyDown"]],{isOpen:[{onIsOpenChange:0}],options:[{onOptionsChange:0}],value:[{onValueChange:0}]}]);function c(){if(typeof customElements==="undefined"){return}const e=["ds-select","ds-menu"];e.forEach((e=>{switch(e){case"ds-select":if(!customElements.get(o(e))){customElements.define(o(e),l)}break;case"ds-menu":if(!customElements.get(o(e))){n()}break}}))}c();const d=l;const h=c;export{d as DsSelect,h as defineCustomElement};
2
2
  //# sourceMappingURL=ds-select.js.map
@@ -1,2 +1,2 @@
1
- import{p as e,H as t,c as s,h as i,a as n,t as o}from"./index.js";const r=()=>`.menu-popup.sc-ds-menu{box-sizing:border-box;display:flex;flex-direction:column;min-width:200px;max-width:600px;overflow:hidden;background-color:var(--color-background-primary);border-radius:var(--dimension-radius-075);box-shadow:var(--effect-elevation-elevated-floating);animation:menuFadeIn var(--effect-motion-short-2) forwards;backface-visibility:hidden;will-change:transform}.menu-popup--closing.sc-ds-menu{animation:menuFadeOut var(--effect-motion-short-3) forwards}@keyframes menuFadeIn{from{opacity:0;transform:inherit scale(0.97)}to{opacity:1}}@keyframes menuFadeOut{from{opacity:1}to{opacity:0}}.menu-section.sc-ds-menu{display:flex;flex-direction:column;gap:var(--dimension-space-050);padding:var(--dimension-space-100)}.menu-section--divided.sc-ds-menu{border-bottom:var(--dimension-stroke-width-015) solid var(--color-border-tertiary)}.section-header.sc-ds-menu{display:flex;align-items:center;height:var(--dimension-size-400);padding:var(--dimension-space-050) var(--dimension-space-075);-webkit-user-select:none;user-select:none}.section-label.sc-ds-menu{color:var(--color-foreground-secondary)}.menu-item.sc-ds-menu{display:flex;align-items:center;gap:var(--dimension-space-050);position:relative;width:100%;min-height:var(--dimension-size-400);padding:var(--dimension-space-075);box-sizing:border-box;border:none;border-radius:var(--dimension-radius-025);background:transparent;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:left;color:inherit;--_hover-bg:var(--color-interaction-hover);--_pressed-bg:var(--color-interaction-pressed);--_selected-bg:var(--color-interaction-active)}.menu-item.sc-ds-menu:has(.menu-item__subtext){align-items:flex-start}.menu-item.sc-ds-menu::after{content:'';position:absolute;inset:0;border-radius:inherit;background:transparent;pointer-events:none;transition:none}.menu-item--selected.sc-ds-menu::after{background:var(--_selected-bg);transition:none}.menu-item.sc-ds-menu:hover:not(:disabled):not(.menu-item--selected)::after,.menu-item--focused.sc-ds-menu:not(:disabled):not(.menu-item--selected)::after{background:var(--_hover-bg);transition:none}.menu-item.sc-ds-menu:active:not(:disabled)::after{background:var(--_pressed-bg);transition:none}.menu-item.sc-ds-menu:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.menu-item--inactive.sc-ds-menu{opacity:0.5;cursor:not-allowed;pointer-events:none}.menu-item--destructive.sc-ds-menu .menu-item__label.sc-ds-menu{color:var(--color-foreground-bold-negative) !important}.menu-item__content.sc-ds-menu{position:relative;z-index:1;display:flex;flex:1;flex-direction:column;gap:var(--dimension-space-025);min-width:0}.menu-item__label.sc-ds-menu{color:var(--color-foreground-secondary)}.menu-item.sc-ds-menu:has(.menu-item__subtext) .menu-item__label.sc-ds-menu,.menu-item--selected.sc-ds-menu .menu-item__label.sc-ds-menu{color:var(--color-foreground-primary)}.menu-item__subtext.sc-ds-menu{color:var(--color-foreground-secondary);line-height:1.4}.menu-item__toggle.sc-ds-menu{position:relative;z-index:1;flex-shrink:0;width:calc(var(--dimension-size-400) + var(--dimension-size-050));height:var(--dimension-size-250);border-radius:var(--dimension-radius-125);background-color:var(--color-background-translucent);transition:background-color var(--effect-motion-short-2)}.menu-item__toggle--on.sc-ds-menu{background-color:var(--color-background-medium-brand)}.menu-item__toggle-thumb.sc-ds-menu{position:absolute;top:var(--dimension-space-025);left:var(--dimension-space-025);width:var(--dimension-size-200);height:var(--dimension-size-200);border-radius:50%;background-color:var(--color-foreground-on-bold-background-primary);transition:transform var(--effect-motion-short-2)}.menu-item__toggle--on.sc-ds-menu .menu-item__toggle-thumb.sc-ds-menu{transform:translateX(var(--dimension-offset-200, 16px))}`;const a=220;const d=4;const c=e(class e extends t{constructor(e){super();if(e!==false){this.__registerHost()}this.dsClose=s(this,"dsClose");this.dsSelect=s(this,"dsSelect");this.open=false;this.items=[];this.sections=[];this.side="bottom";this.align="start";this.sideOffset=4;this.alignOffset=0;this.shouldRender=false;this.closing=false;this.pos={x:0,y:0};this.focusedIndex=0;this.positionReady=false;this.clickOutsideHandler=null;this.scrollResizeHandler=null;this.closeTimer=null;this.itemEls=[]}componentDidLoad(){if(this.open)this.onOpenChange(true)}disconnectedCallback(){this.teardownListeners()}onOpenChange(e){if(e){this.shouldRender=true;this.closing=false;this.positionReady=false;requestAnimationFrame((()=>{this.calculatePosition();this.positionReady=true;this.focusInitialItem();this.setupListeners()}))}else if(this.shouldRender){this.closing=true;this.teardownListeners();this.closeTimer=setTimeout((()=>{this.shouldRender=false;this.closing=false;this.closeTimer=null}),a)}}get resolvedAnchor(){if(this.anchor)return this.anchor;if(this.anchorId)return document.getElementById(this.anchorId);return null}get activeSections(){if(this.sections.length>0)return this.sections;if(this.items.length>0)return[{items:this.items}];return[]}get flatItems(){return this.activeSections.flatMap((e=>e.items))}calculatePosition(){const e=this.resolvedAnchor;if(!e)return;const t=this.el.querySelector(".menu-popup");if(!t)return;const s=e.getBoundingClientRect();const i=t.offsetWidth||200;const n=t.offsetHeight||160;let o=0,r=0;switch(this.side){case"top":r=s.top-n-this.sideOffset;o=this.align==="start"?s.left+this.alignOffset:this.align==="end"?s.right-i+this.alignOffset:s.left+s.width/2-i/2+this.alignOffset;break;case"bottom":r=s.bottom+this.sideOffset;o=this.align==="start"?s.left+this.alignOffset:this.align==="end"?s.right-i+this.alignOffset:s.left+s.width/2-i/2+this.alignOffset;break;case"left":o=s.left-i-this.sideOffset;r=this.align==="start"?s.top+this.alignOffset:this.align==="end"?s.bottom-n+this.alignOffset:s.top+s.height/2-n/2+this.alignOffset;break;case"right":o=s.right+this.sideOffset;r=this.align==="start"?s.top+this.alignOffset:this.align==="end"?s.bottom-n+this.alignOffset:s.top+s.height/2-n/2+this.alignOffset;break}this.pos={x:Math.min(Math.max(o,d),window.innerWidth-i-d),y:Math.min(Math.max(r,d),window.innerHeight-n-d)}}focusInitialItem(){const e=this.flatItems;const t=e.findIndex((e=>e.isSelected&&!e.isInactive));const s=e.findIndex((e=>!e.isInactive));this.focusedIndex=t>=0?t:s>=0?s:0;requestAnimationFrame((()=>{const e=this.el.querySelectorAll(".menu-item");e[this.focusedIndex]?.focus()}))}setupListeners(){this.clickOutsideHandler=e=>{const t=e.target;const s=this.el.querySelector(".menu-popup");const i=this.resolvedAnchor;if(s?.contains(t)||i?.contains(t))return;this.close()};this.scrollResizeHandler=()=>this.calculatePosition();document.addEventListener("mousedown",this.clickOutsideHandler,true);window.addEventListener("scroll",this.scrollResizeHandler,true);window.addEventListener("resize",this.scrollResizeHandler)}teardownListeners(){if(this.clickOutsideHandler){document.removeEventListener("mousedown",this.clickOutsideHandler,true);this.clickOutsideHandler=null}if(this.scrollResizeHandler){window.removeEventListener("scroll",this.scrollResizeHandler,true);window.removeEventListener("resize",this.scrollResizeHandler);this.scrollResizeHandler=null}if(this.closeTimer){clearTimeout(this.closeTimer);this.closeTimer=null}}close(){this.resolvedAnchor?.focus();this.dsClose.emit();this.open=false}handleKeyDown(e){if(!this.open)return;const t=this.flatItems;const s=t.map(((e,t)=>({it:e,i:t}))).filter((({it:e})=>!e.isInactive)).map((({i:e})=>e));if(!s.length)return;const i=s.indexOf(this.focusedIndex);const n=i<0?0:i;switch(e.key){case"ArrowDown":e.preventDefault();e.stopPropagation();this.focusedIndex=s[(n+1)%s.length];this.focusItem(this.focusedIndex);break;case"ArrowUp":e.preventDefault();e.stopPropagation();this.focusedIndex=s[(n-1+s.length)%s.length];this.focusItem(this.focusedIndex);break;case"Home":e.preventDefault();e.stopPropagation();this.focusedIndex=s[0];this.focusItem(this.focusedIndex);break;case"End":e.preventDefault();e.stopPropagation();this.focusedIndex=s[s.length-1];this.focusItem(this.focusedIndex);break;case"Escape":e.preventDefault();this.close();break;case"Tab":e.preventDefault();this.close();break}}focusItem(e){const t=this.el.querySelectorAll(".menu-item");t[e]?.focus()}handleItemClick(e){if(e.isInactive)return;this.dsSelect.emit(e);this.close()}render(){if(!this.shouldRender)return i(n,{style:{display:"contents"}});const e=this.activeSections;let t=0;const s={position:"fixed",left:"0",top:"0",transform:`translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,zIndex:"9998",visibility:this.positionReady?"visible":"hidden"};if(this.menuWidth)s["width"]=this.menuWidth;if(this.minWidth)s["min-width"]=this.minWidth;return i(n,{style:{display:"contents"}},i("div",{class:{"menu-popup":true,"menu-popup--closing":this.closing},style:s,role:"menu","aria-label":"Menu","aria-orientation":"vertical"},e.map(((s,n)=>i("div",{key:n,class:{"menu-section":true,"menu-section--divided":n<e.length-1},role:s.header?"group":undefined,"aria-label":s.header},s.header&&i("div",{class:"section-header","aria-hidden":"true"},i("span",{class:"text-body-small-emphasis section-label"},s.header)),s.items.map((e=>{const s=t++;const n=this.focusedIndex===s;return i("button",{key:s,type:"button",class:{"menu-item":true,"menu-item--selected":!!e.isSelected,"menu-item--inactive":!!e.isInactive,"menu-item--destructive":!!e.isDestructive,"menu-item--focused":n},role:"menuitem","aria-current":e.isSelected?"true":undefined,disabled:e.isInactive,tabIndex:n?0:-1,onClick:()=>this.handleItemClick(e),onFocus:()=>{this.focusedIndex=s}},i("div",{class:"menu-item__content"},i("span",{class:e.isSelected?"text-body-medium-emphasis menu-item__label":"text-body-medium menu-item__label"},e.label),e.subtext&&i("span",{class:"text-body-small menu-item__subtext"},e.subtext)),e.showToggle&&i("div",{class:{"menu-item__toggle":true,"menu-item__toggle--on":!!e.toggleValue},"aria-hidden":"true"},i("div",{class:"menu-item__toggle-thumb"})))})))))))}get el(){return this}static get watchers(){return{open:[{onOpenChange:0}]}}static get style(){return r()}},[2,"ds-menu",{open:[1028],items:[16],sections:[16],side:[1],align:[1],sideOffset:[2,"side-offset"],alignOffset:[2,"align-offset"],menuWidth:[1,"menu-width"],minWidth:[1,"min-width"],anchor:[16],anchorId:[1,"anchor-id"],shouldRender:[32],closing:[32],pos:[32],focusedIndex:[32],positionReady:[32]},[[0,"keydown","handleKeyDown"]],{open:[{onOpenChange:0}]}]);function m(){if(typeof customElements==="undefined"){return}const e=["ds-menu"];e.forEach((e=>{switch(e){case"ds-menu":if(!customElements.get(o(e))){customElements.define(o(e),c)}break}}))}m();export{c as M,m as d};
2
- //# sourceMappingURL=p-CSIN3IaW.js.map
1
+ import{p as e,H as t,c as s,h as i,a as n,t as o}from"./index.js";const r=()=>`.menu-popup.sc-ds-menu{box-sizing:border-box;display:flex;flex-direction:column;min-width:200px;max-width:600px;overflow:hidden;background-color:var(--color-background-primary);border-radius:var(--dimension-radius-075);box-shadow:var(--effect-elevation-elevated-floating);animation:menuFadeIn var(--effect-motion-short-2) forwards;backface-visibility:hidden;will-change:transform}.menu-popup--closing.sc-ds-menu{animation:menuFadeOut var(--effect-motion-short-3) forwards}@keyframes menuFadeIn{from{opacity:0;transform:inherit scale(0.97)}to{opacity:1}}@keyframes menuFadeOut{from{opacity:1}to{opacity:0}}.menu-section.sc-ds-menu{display:flex;flex-direction:column;gap:var(--dimension-space-050);padding:var(--dimension-space-050)}.menu-section--divided.sc-ds-menu{border-bottom:var(--dimension-stroke-width-015) solid var(--color-border-tertiary)}.section-header.sc-ds-menu{display:flex;align-items:center;height:var(--dimension-size-400);padding:var(--dimension-space-050) var(--dimension-space-075);-webkit-user-select:none;user-select:none}.section-label.sc-ds-menu{color:var(--color-foreground-secondary)}.menu-item.sc-ds-menu{display:flex;align-items:center;gap:var(--dimension-space-050);position:relative;width:100%;min-height:var(--dimension-size-400);padding:var(--dimension-space-075);box-sizing:border-box;border:none;border-radius:var(--dimension-radius-025);background:transparent;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:left;color:inherit;--_hover-bg:var(--color-interaction-hover);--_pressed-bg:var(--color-interaction-pressed);--_selected-bg:var(--color-interaction-active)}.menu-item.sc-ds-menu:has(.menu-item__subtext){align-items:flex-start}.menu-item.sc-ds-menu::after{content:'';position:absolute;inset:0;border-radius:inherit;background:transparent;pointer-events:none;transition:none}.menu-item--selected.sc-ds-menu::after{background:var(--_selected-bg);transition:none}.menu-item.sc-ds-menu:hover:not(:disabled):not(.menu-item--selected)::after,.menu-item--focused.sc-ds-menu:not(:disabled):not(.menu-item--selected)::after{background:var(--_hover-bg);transition:none}.menu-item.sc-ds-menu:active:not(:disabled)::after{background:var(--_pressed-bg);transition:none}.menu-item.sc-ds-menu:focus-visible{outline:var(--dimension-stroke-width-025) solid var(--color-interaction-focus);outline-offset:var(--dimension-space-025)}.menu-item--inactive.sc-ds-menu{opacity:0.5;cursor:not-allowed;pointer-events:none}.menu-item--destructive.sc-ds-menu .menu-item__label.sc-ds-menu{color:var(--color-foreground-bold-negative) !important}.menu-item__content.sc-ds-menu{position:relative;z-index:1;display:flex;flex:1;flex-direction:column;gap:var(--dimension-space-025);min-width:0}.menu-item__label.sc-ds-menu{color:var(--color-foreground-secondary)}.menu-item.sc-ds-menu:has(.menu-item__subtext) .menu-item__label.sc-ds-menu,.menu-item--selected.sc-ds-menu .menu-item__label.sc-ds-menu{color:var(--color-foreground-primary)}.menu-item__subtext.sc-ds-menu{color:var(--color-foreground-secondary);line-height:1.4}.menu-item__toggle.sc-ds-menu{position:relative;z-index:1;flex-shrink:0;width:calc(var(--dimension-size-400) + var(--dimension-size-050));height:var(--dimension-size-250);border-radius:var(--dimension-radius-125);background-color:var(--color-background-translucent);transition:background-color var(--effect-motion-short-2)}.menu-item__toggle--on.sc-ds-menu{background-color:var(--color-background-medium-brand)}.menu-item__toggle-thumb.sc-ds-menu{position:absolute;top:var(--dimension-space-025);left:var(--dimension-space-025);width:var(--dimension-size-200);height:var(--dimension-size-200);border-radius:50%;background-color:var(--color-foreground-on-bold-background-primary);transition:transform var(--effect-motion-short-2)}.menu-item__toggle--on.sc-ds-menu .menu-item__toggle-thumb.sc-ds-menu{transform:translateX(var(--dimension-offset-200, 16px))}`;const a=220;const d=4;const c=e(class e extends t{constructor(e){super();if(e!==false){this.__registerHost()}this.dsClose=s(this,"dsClose");this.dsSelect=s(this,"dsSelect");this.open=false;this.items=[];this.sections=[];this.side="bottom";this.align="start";this.sideOffset=4;this.alignOffset=0;this.shouldRender=false;this.closing=false;this.pos={x:0,y:0};this.focusedIndex=0;this.positionReady=false;this.clickOutsideHandler=null;this.scrollResizeHandler=null;this.closeTimer=null;this.itemEls=[]}componentDidLoad(){if(this.open)this.onOpenChange(true)}disconnectedCallback(){this.teardownListeners()}onOpenChange(e){if(e){this.shouldRender=true;this.closing=false;this.positionReady=false;requestAnimationFrame((()=>{this.calculatePosition();this.positionReady=true;this.focusInitialItem();this.setupListeners()}))}else if(this.shouldRender){this.closing=true;this.teardownListeners();this.closeTimer=setTimeout((()=>{this.shouldRender=false;this.closing=false;this.closeTimer=null}),a)}}get resolvedAnchor(){if(this.anchor)return this.anchor;if(this.anchorId)return document.getElementById(this.anchorId);return null}get activeSections(){if(this.sections.length>0)return this.sections;if(this.items.length>0)return[{items:this.items}];return[]}get flatItems(){return this.activeSections.flatMap((e=>e.items))}calculatePosition(){const e=this.resolvedAnchor;if(!e)return;const t=this.el.querySelector(".menu-popup");if(!t)return;const s=e.getBoundingClientRect();const i=t.offsetWidth||200;const n=t.offsetHeight||160;let o=0,r=0;switch(this.side){case"top":r=s.top-n-this.sideOffset;o=this.align==="start"?s.left+this.alignOffset:this.align==="end"?s.right-i+this.alignOffset:s.left+s.width/2-i/2+this.alignOffset;break;case"bottom":r=s.bottom+this.sideOffset;o=this.align==="start"?s.left+this.alignOffset:this.align==="end"?s.right-i+this.alignOffset:s.left+s.width/2-i/2+this.alignOffset;break;case"left":o=s.left-i-this.sideOffset;r=this.align==="start"?s.top+this.alignOffset:this.align==="end"?s.bottom-n+this.alignOffset:s.top+s.height/2-n/2+this.alignOffset;break;case"right":o=s.right+this.sideOffset;r=this.align==="start"?s.top+this.alignOffset:this.align==="end"?s.bottom-n+this.alignOffset:s.top+s.height/2-n/2+this.alignOffset;break}this.pos={x:Math.min(Math.max(o,d),window.innerWidth-i-d),y:Math.min(Math.max(r,d),window.innerHeight-n-d)}}focusInitialItem(){const e=this.flatItems;const t=e.findIndex((e=>e.isSelected&&!e.isInactive));const s=e.findIndex((e=>!e.isInactive));this.focusedIndex=t>=0?t:s>=0?s:0;requestAnimationFrame((()=>{const e=this.el.querySelectorAll(".menu-item");e[this.focusedIndex]?.focus()}))}setupListeners(){this.clickOutsideHandler=e=>{const t=e.target;const s=this.el.querySelector(".menu-popup");const i=this.resolvedAnchor;if(s?.contains(t)||i?.contains(t))return;this.close()};this.scrollResizeHandler=()=>this.calculatePosition();document.addEventListener("mousedown",this.clickOutsideHandler,true);window.addEventListener("scroll",this.scrollResizeHandler,true);window.addEventListener("resize",this.scrollResizeHandler)}teardownListeners(){if(this.clickOutsideHandler){document.removeEventListener("mousedown",this.clickOutsideHandler,true);this.clickOutsideHandler=null}if(this.scrollResizeHandler){window.removeEventListener("scroll",this.scrollResizeHandler,true);window.removeEventListener("resize",this.scrollResizeHandler);this.scrollResizeHandler=null}if(this.closeTimer){clearTimeout(this.closeTimer);this.closeTimer=null}}close(){this.resolvedAnchor?.focus();this.dsClose.emit();this.open=false}handleKeyDown(e){if(!this.open)return;const t=this.flatItems;const s=t.map(((e,t)=>({it:e,i:t}))).filter((({it:e})=>!e.isInactive)).map((({i:e})=>e));if(!s.length)return;const i=s.indexOf(this.focusedIndex);const n=i<0?0:i;switch(e.key){case"ArrowDown":e.preventDefault();e.stopPropagation();this.focusedIndex=s[(n+1)%s.length];this.focusItem(this.focusedIndex);break;case"ArrowUp":e.preventDefault();e.stopPropagation();this.focusedIndex=s[(n-1+s.length)%s.length];this.focusItem(this.focusedIndex);break;case"Home":e.preventDefault();e.stopPropagation();this.focusedIndex=s[0];this.focusItem(this.focusedIndex);break;case"End":e.preventDefault();e.stopPropagation();this.focusedIndex=s[s.length-1];this.focusItem(this.focusedIndex);break;case"Escape":e.preventDefault();this.close();break;case"Tab":e.preventDefault();this.close();break}}focusItem(e){const t=this.el.querySelectorAll(".menu-item");t[e]?.focus()}handleItemClick(e){if(e.isInactive)return;this.dsSelect.emit(e);this.close()}render(){if(!this.shouldRender)return i(n,{style:{display:"contents"}});const e=this.activeSections;let t=0;const s={position:"fixed",left:"0",top:"0",transform:`translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,zIndex:"9998",visibility:this.positionReady?"visible":"hidden"};if(this.menuWidth)s["width"]=this.menuWidth;if(this.minWidth)s["min-width"]=this.minWidth;return i(n,{style:{display:"contents"}},i("div",{class:{"menu-popup":true,"menu-popup--closing":this.closing},style:s,role:"menu","aria-label":"Menu","aria-orientation":"vertical"},e.map(((s,n)=>i("div",{key:n,class:{"menu-section":true,"menu-section--divided":n<e.length-1},role:s.header?"group":undefined,"aria-label":s.header},s.header&&i("div",{class:"section-header","aria-hidden":"true"},i("span",{class:"text-body-small-emphasis section-label"},s.header)),s.items.map((e=>{const s=t++;const n=this.focusedIndex===s;return i("button",{key:s,type:"button",class:{"menu-item":true,"menu-item--selected":!!e.isSelected,"menu-item--inactive":!!e.isInactive,"menu-item--destructive":!!e.isDestructive,"menu-item--focused":n},role:"menuitem","aria-current":e.isSelected?"true":undefined,disabled:e.isInactive,tabIndex:n?0:-1,onClick:()=>this.handleItemClick(e),onFocus:()=>{this.focusedIndex=s}},i("div",{class:"menu-item__content"},i("span",{class:e.isSelected?"text-body-medium-emphasis menu-item__label":"text-body-medium menu-item__label"},e.label),e.subtext&&i("span",{class:"text-body-small menu-item__subtext"},e.subtext)),e.showToggle&&i("div",{class:{"menu-item__toggle":true,"menu-item__toggle--on":!!e.toggleValue},"aria-hidden":"true"},i("div",{class:"menu-item__toggle-thumb"})))})))))))}get el(){return this}static get watchers(){return{open:[{onOpenChange:0}]}}static get style(){return r()}},[2,"ds-menu",{open:[1028],items:[16],sections:[16],side:[1],align:[1],sideOffset:[2,"side-offset"],alignOffset:[2,"align-offset"],menuWidth:[1,"menu-width"],minWidth:[1,"min-width"],anchor:[16],anchorId:[1,"anchor-id"],shouldRender:[32],closing:[32],pos:[32],focusedIndex:[32],positionReady:[32]},[[0,"keydown","handleKeyDown"]],{open:[{onOpenChange:0}]}]);function m(){if(typeof customElements==="undefined"){return}const e=["ds-menu"];e.forEach((e=>{switch(e){case"ds-menu":if(!customElements.get(o(e))){customElements.define(o(e),c)}break}}))}m();export{c as M,m as d};
2
+ //# sourceMappingURL=p-STnE_bmQ.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["menuCss","CLOSE_ANIMATION_MS","VP_PAD","Menu","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","open","items","sections","side","align","sideOffset","alignOffset","shouldRender","closing","pos","x","y","focusedIndex","positionReady","clickOutsideHandler","scrollResizeHandler","closeTimer","itemEls","componentDidLoad","onOpenChange","disconnectedCallback","teardownListeners","isOpen","requestAnimationFrame","calculatePosition","focusInitialItem","setupListeners","setTimeout","resolvedAnchor","anchor","anchorId","document","getElementById","activeSections","length","flatItems","flatMap","s","anchorEl","popup","el","querySelector","a","getBoundingClientRect","pw","offsetWidth","ph","offsetHeight","top","left","right","width","bottom","height","Math","min","max","window","innerWidth","innerHeight","flat","selectedIdx","findIndex","it","isSelected","isInactive","firstEnabledIdx","btns","querySelectorAll","focus","e","t","target","contains","close","addEventListener","removeEventListener","clearTimeout","dsClose","emit","handleKeyDown","enabled","map","i","filter","cur","indexOf","safe","key","preventDefault","stopPropagation","focusItem","idx","handleItemClick","item","dsSelect","render","h","Host","style","display","flatIdx","popupStyle","position","transform","round","zIndex","visibility","menuWidth","minWidth","class","role","section","si","header","undefined","isFocused","type","isDestructive","disabled","tabIndex","onClick","onFocus","label","subtext","showToggle","toggleValue"],"sources":["src/wc/components/Menu/Menu.css?tag=ds-menu&encapsulation=scoped","src/wc/components/Menu/Menu.tsx"],"sourcesContent":["/* ── Popup shell ─────────────────────────────────────────────────────────── */\n\n.menu-popup {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: 200px;\n max-width: 600px;\n overflow: hidden;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n box-shadow: var(--effect-elevation-elevated-floating);\n animation: menuFadeIn var(--effect-motion-short-2) forwards;\n backface-visibility: hidden;\n will-change: transform;\n}\n\n.menu-popup--closing {\n animation: menuFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes menuFadeIn {\n from { opacity: 0; transform: inherit scale(0.97); }\n to { opacity: 1; }\n}\n\n@keyframes menuFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n/* ── Sections ────────────────────────────────────────────────────────────── */\n\n.menu-section {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-100);\n}\n\n.menu-section--divided {\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-tertiary);\n}\n\n.section-header {\n display: flex;\n align-items: center;\n height: var(--dimension-size-400);\n padding: var(--dimension-space-050) var(--dimension-space-075);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.section-label {\n color: var(--color-foreground-secondary);\n}\n\n/* ── Items ───────────────────────────────────────────────────────────────── */\n\n.menu-item {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n position: relative;\n width: 100%;\n min-height: var(--dimension-size-400);\n padding: var(--dimension-space-075);\n box-sizing: border-box;\n border: none;\n border-radius: var(--dimension-radius-025);\n background: transparent;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n color: inherit;\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_selected-bg: var(--color-interaction-active);\n}\n\n.menu-item:has(.menu-item__subtext) {\n align-items: flex-start;\n}\n\n/* Interaction layer — same ::after pattern as tabs / BarNav trigger */\n.menu-item::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background: transparent;\n pointer-events: none;\n transition: none;\n}\n\n.menu-item--selected::after {\n background: var(--_selected-bg);\n transition: none;\n}\n\n.menu-item:hover:not(:disabled):not(.menu-item--selected)::after,\n.menu-item--focused:not(:disabled):not(.menu-item--selected)::after {\n background: var(--_hover-bg);\n transition: none;\n}\n\n.menu-item:active:not(:disabled)::after {\n background: var(--_pressed-bg);\n transition: none;\n}\n\n.menu-item:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.menu-item--inactive {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.menu-item--destructive .menu-item__label {\n color: var(--color-foreground-bold-negative) !important;\n}\n\n.menu-item__content {\n position: relative;\n z-index: 1;\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n.menu-item__label {\n color: var(--color-foreground-secondary);\n}\n\n.menu-item:has(.menu-item__subtext) .menu-item__label,\n.menu-item--selected .menu-item__label {\n color: var(--color-foreground-primary);\n}\n\n.menu-item__subtext {\n color: var(--color-foreground-secondary);\n line-height: 1.4;\n}\n\n/* ── Toggle suffix ───────────────────────────────────────────────────────── */\n\n.menu-item__toggle {\n position: relative;\n z-index: 1;\n flex-shrink: 0;\n width: calc(var(--dimension-size-400) + var(--dimension-size-050));\n height: var(--dimension-size-250);\n border-radius: var(--dimension-radius-125);\n background-color: var(--color-background-translucent);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on {\n background-color: var(--color-background-medium-brand);\n}\n\n.menu-item__toggle-thumb {\n position: absolute;\n top: var(--dimension-space-025);\n left: var(--dimension-space-025);\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n border-radius: 50%;\n background-color: var(--color-foreground-on-bold-background-primary);\n transition: transform var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on .menu-item__toggle-thumb {\n transform: translateX(var(--dimension-offset-200, 16px));\n}\n","import { Component, Prop, State, Event, EventEmitter, Element, Watch, Listen, h, Host } from '@stencil/core';\n\nexport type MenuSide = 'top' | 'right' | 'bottom' | 'left';\nexport type MenuAlign = 'start' | 'center' | 'end';\n\nexport interface MenuItemData {\n label: string;\n value?: string;\n subtext?: string;\n isSelected?: boolean;\n isInactive?: boolean;\n isDestructive?: boolean;\n showToggle?: boolean;\n toggleValue?: boolean;\n}\n\nexport interface MenuSection {\n header?: string;\n items: MenuItemData[];\n}\n\nconst CLOSE_ANIMATION_MS = 220;\nconst VP_PAD = 4;\n\n@Component({\n tag: 'ds-menu',\n styleUrl: 'Menu.css',\n scoped: true,\n})\nexport class Menu {\n @Element() el!: HTMLElement;\n\n @Prop({ mutable: true }) open: boolean = false;\n @Prop() items: MenuItemData[] = [];\n @Prop() sections: MenuSection[] = [];\n @Prop() side: MenuSide = 'bottom';\n @Prop() align: MenuAlign = 'start';\n @Prop() sideOffset: number = 4;\n @Prop() alignOffset: number = 0;\n @Prop() menuWidth: string | undefined;\n @Prop() minWidth: string | undefined;\n /** External trigger element to position against. Set via JS: menuEl.anchor = buttonEl */\n @Prop() anchor: HTMLElement | undefined;\n /** ID of the external trigger element for positioning */\n @Prop() anchorId: string | undefined;\n\n @State() private shouldRender: boolean = false;\n @State() private closing: boolean = false;\n @State() private pos: { x: number; y: number } = { x: 0, y: 0 };\n @State() private focusedIndex: number = 0;\n @State() private positionReady: boolean = false;\n\n @Event() dsClose!: EventEmitter<void>;\n @Event() dsSelect!: EventEmitter<MenuItemData>;\n\n private clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private scrollResizeHandler: (() => void) | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private itemEls: HTMLElement[] = [];\n\n componentDidLoad() {\n if (this.open) this.onOpenChange(true);\n }\n\n disconnectedCallback() {\n this.teardownListeners();\n }\n\n @Watch('open')\n onOpenChange(isOpen: boolean) {\n if (isOpen) {\n this.shouldRender = true;\n this.closing = false;\n this.positionReady = false;\n requestAnimationFrame(() => {\n this.calculatePosition();\n this.positionReady = true;\n this.focusInitialItem();\n this.setupListeners();\n });\n } else if (this.shouldRender) {\n this.closing = true;\n this.teardownListeners();\n this.closeTimer = setTimeout(() => {\n this.shouldRender = false;\n this.closing = false;\n this.closeTimer = null;\n }, CLOSE_ANIMATION_MS);\n }\n }\n\n private get resolvedAnchor(): HTMLElement | null {\n if (this.anchor) return this.anchor;\n if (this.anchorId) return document.getElementById(this.anchorId);\n return null;\n }\n\n private get activeSections(): MenuSection[] {\n if (this.sections.length > 0) return this.sections;\n if (this.items.length > 0) return [{ items: this.items }];\n return [];\n }\n\n private get flatItems(): MenuItemData[] {\n return this.activeSections.flatMap(s => s.items);\n }\n\n private calculatePosition() {\n const anchorEl = this.resolvedAnchor;\n if (!anchorEl) return;\n const popup = this.el.querySelector('.menu-popup') as HTMLElement | null;\n if (!popup) return;\n\n const a = anchorEl.getBoundingClientRect();\n const pw = popup.offsetWidth || 200;\n const ph = popup.offsetHeight || 160;\n let x = 0, y = 0;\n\n switch (this.side) {\n case 'top':\n y = a.top - ph - this.sideOffset;\n x = this.align === 'start' ? a.left + this.alignOffset\n : this.align === 'end' ? a.right - pw + this.alignOffset\n : a.left + a.width / 2 - pw / 2 + this.alignOffset;\n break;\n case 'bottom':\n y = a.bottom + this.sideOffset;\n x = this.align === 'start' ? a.left + this.alignOffset\n : this.align === 'end' ? a.right - pw + this.alignOffset\n : a.left + a.width / 2 - pw / 2 + this.alignOffset;\n break;\n case 'left':\n x = a.left - pw - this.sideOffset;\n y = this.align === 'start' ? a.top + this.alignOffset\n : this.align === 'end' ? a.bottom - ph + this.alignOffset\n : a.top + a.height / 2 - ph / 2 + this.alignOffset;\n break;\n case 'right':\n x = a.right + this.sideOffset;\n y = this.align === 'start' ? a.top + this.alignOffset\n : this.align === 'end' ? a.bottom - ph + this.alignOffset\n : a.top + a.height / 2 - ph / 2 + this.alignOffset;\n break;\n }\n\n this.pos = {\n x: Math.min(Math.max(x, VP_PAD), window.innerWidth - pw - VP_PAD),\n y: Math.min(Math.max(y, VP_PAD), window.innerHeight - ph - VP_PAD),\n };\n }\n\n /** Focus the selected item when present, otherwise the first enabled item. */\n private focusInitialItem() {\n const flat = this.flatItems;\n const selectedIdx = flat.findIndex(it => it.isSelected && !it.isInactive);\n const firstEnabledIdx = flat.findIndex(it => !it.isInactive);\n this.focusedIndex = selectedIdx >= 0\n ? selectedIdx\n : (firstEnabledIdx >= 0 ? firstEnabledIdx : 0);\n\n requestAnimationFrame(() => {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[this.focusedIndex]?.focus();\n });\n }\n\n private setupListeners() {\n this.clickOutsideHandler = (e: MouseEvent) => {\n const t = e.target as Node;\n const popup = this.el.querySelector('.menu-popup');\n const anchorEl = this.resolvedAnchor;\n if (popup?.contains(t) || anchorEl?.contains(t)) return;\n this.close();\n };\n\n this.scrollResizeHandler = () => this.calculatePosition();\n\n document.addEventListener('mousedown', this.clickOutsideHandler, true);\n window.addEventListener('scroll', this.scrollResizeHandler, true);\n window.addEventListener('resize', this.scrollResizeHandler);\n }\n\n private teardownListeners() {\n if (this.clickOutsideHandler) {\n document.removeEventListener('mousedown', this.clickOutsideHandler, true);\n this.clickOutsideHandler = null;\n }\n if (this.scrollResizeHandler) {\n window.removeEventListener('scroll', this.scrollResizeHandler, true);\n window.removeEventListener('resize', this.scrollResizeHandler);\n this.scrollResizeHandler = null;\n }\n if (this.closeTimer) {\n clearTimeout(this.closeTimer);\n this.closeTimer = null;\n }\n }\n\n private close() {\n this.resolvedAnchor?.focus();\n this.dsClose.emit();\n this.open = false;\n }\n\n @Listen('keydown')\n handleKeyDown(e: KeyboardEvent) {\n if (!this.open) return;\n const flat = this.flatItems;\n const enabled = flat.map((it, i) => ({ it, i })).filter(({ it }) => !it.isInactive).map(({ i }) => i);\n if (!enabled.length) return;\n\n const cur = enabled.indexOf(this.focusedIndex);\n const safe = cur < 0 ? 0 : cur;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[(safe + 1) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'ArrowUp':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[(safe - 1 + enabled.length) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'Home':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[0];\n this.focusItem(this.focusedIndex);\n break;\n case 'End':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[enabled.length - 1];\n this.focusItem(this.focusedIndex);\n break;\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'Tab':\n e.preventDefault();\n this.close();\n break;\n }\n }\n\n private focusItem(idx: number) {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[idx]?.focus();\n }\n\n private handleItemClick(item: MenuItemData) {\n if (item.isInactive) return;\n this.dsSelect.emit(item);\n this.close();\n }\n\n render() {\n if (!this.shouldRender) return <Host style={{ display: 'contents' }} />;\n\n const sections = this.activeSections;\n let flatIdx = 0;\n\n const popupStyle: Record<string, string> = {\n position: 'fixed',\n left: '0',\n top: '0',\n transform: `translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,\n zIndex: '9998',\n visibility: this.positionReady ? 'visible' : 'hidden',\n };\n\n if (this.menuWidth) popupStyle['width'] = this.menuWidth;\n if (this.minWidth) popupStyle['min-width'] = this.minWidth;\n\n return (\n <Host style={{ display: 'contents' }}>\n <div\n class={{ 'menu-popup': true, 'menu-popup--closing': this.closing }}\n style={popupStyle}\n role=\"menu\"\n aria-label=\"Menu\"\n aria-orientation=\"vertical\"\n >\n {sections.map((section, si) => (\n <div\n key={si}\n class={{ 'menu-section': true, 'menu-section--divided': si < sections.length - 1 }}\n role={section.header ? 'group' : undefined}\n aria-label={section.header}\n >\n {section.header && (\n <div class=\"section-header\" aria-hidden=\"true\">\n <span class=\"text-body-small-emphasis section-label\">{section.header}</span>\n </div>\n )}\n {section.items.map(item => {\n const idx = flatIdx++;\n const isFocused = this.focusedIndex === idx;\n return (\n <button\n key={idx}\n type=\"button\"\n class={{\n 'menu-item': true,\n 'menu-item--selected': !!item.isSelected,\n 'menu-item--inactive': !!item.isInactive,\n 'menu-item--destructive': !!item.isDestructive,\n 'menu-item--focused': isFocused,\n }}\n role=\"menuitem\"\n aria-current={item.isSelected ? 'true' : undefined}\n disabled={item.isInactive}\n tabIndex={isFocused ? 0 : -1}\n onClick={() => this.handleItemClick(item)}\n onFocus={() => { this.focusedIndex = idx; }}\n >\n <div class=\"menu-item__content\">\n <span class={item.isSelected ? 'text-body-medium-emphasis menu-item__label' : 'text-body-medium menu-item__label'}>\n {item.label}\n </span>\n {item.subtext && (\n <span class=\"text-body-small menu-item__subtext\">{item.subtext}</span>\n )}\n </div>\n {item.showToggle && (\n <div class={{ 'menu-item__toggle': true, 'menu-item__toggle--on': !!item.toggleValue }} aria-hidden=\"true\">\n <div class=\"menu-item__toggle-thumb\" />\n </div>\n )}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["menuCss","CLOSE_ANIMATION_MS","VP_PAD","Menu","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","open","items","sections","side","align","sideOffset","alignOffset","shouldRender","closing","pos","x","y","focusedIndex","positionReady","clickOutsideHandler","scrollResizeHandler","closeTimer","itemEls","componentDidLoad","onOpenChange","disconnectedCallback","teardownListeners","isOpen","requestAnimationFrame","calculatePosition","focusInitialItem","setupListeners","setTimeout","resolvedAnchor","anchor","anchorId","document","getElementById","activeSections","length","flatItems","flatMap","s","anchorEl","popup","el","querySelector","a","getBoundingClientRect","pw","offsetWidth","ph","offsetHeight","top","left","right","width","bottom","height","Math","min","max","window","innerWidth","innerHeight","flat","selectedIdx","findIndex","it","isSelected","isInactive","firstEnabledIdx","btns","querySelectorAll","focus","e","t","target","contains","close","addEventListener","removeEventListener","clearTimeout","dsClose","emit","handleKeyDown","enabled","map","i","filter","cur","indexOf","safe","key","preventDefault","stopPropagation","focusItem","idx","handleItemClick","item","dsSelect","render","h","Host","style","display","flatIdx","popupStyle","position","transform","round","zIndex","visibility","menuWidth","minWidth","class","role","section","si","header","undefined","isFocused","type","isDestructive","disabled","tabIndex","onClick","onFocus","label","subtext","showToggle","toggleValue"],"sources":["src/wc/components/Menu/Menu.css?tag=ds-menu&encapsulation=scoped","src/wc/components/Menu/Menu.tsx"],"sourcesContent":["/* ── Popup shell ─────────────────────────────────────────────────────────── */\n\n.menu-popup {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: 200px;\n max-width: 600px;\n overflow: hidden;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n box-shadow: var(--effect-elevation-elevated-floating);\n animation: menuFadeIn var(--effect-motion-short-2) forwards;\n backface-visibility: hidden;\n will-change: transform;\n}\n\n.menu-popup--closing {\n animation: menuFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes menuFadeIn {\n from { opacity: 0; transform: inherit scale(0.97); }\n to { opacity: 1; }\n}\n\n@keyframes menuFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n/* ── Sections ────────────────────────────────────────────────────────────── */\n\n.menu-section {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-050);\n}\n\n.menu-section--divided {\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-tertiary);\n}\n\n.section-header {\n display: flex;\n align-items: center;\n height: var(--dimension-size-400);\n padding: var(--dimension-space-050) var(--dimension-space-075);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.section-label {\n color: var(--color-foreground-secondary);\n}\n\n/* ── Items ───────────────────────────────────────────────────────────────── */\n\n.menu-item {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n position: relative;\n width: 100%;\n min-height: var(--dimension-size-400);\n padding: var(--dimension-space-075);\n box-sizing: border-box;\n border: none;\n border-radius: var(--dimension-radius-025);\n background: transparent;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n color: inherit;\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_selected-bg: var(--color-interaction-active);\n}\n\n.menu-item:has(.menu-item__subtext) {\n align-items: flex-start;\n}\n\n/* Interaction layer — same ::after pattern as tabs / BarNav trigger */\n.menu-item::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background: transparent;\n pointer-events: none;\n transition: none;\n}\n\n.menu-item--selected::after {\n background: var(--_selected-bg);\n transition: none;\n}\n\n.menu-item:hover:not(:disabled):not(.menu-item--selected)::after,\n.menu-item--focused:not(:disabled):not(.menu-item--selected)::after {\n background: var(--_hover-bg);\n transition: none;\n}\n\n.menu-item:active:not(:disabled)::after {\n background: var(--_pressed-bg);\n transition: none;\n}\n\n.menu-item:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.menu-item--inactive {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.menu-item--destructive .menu-item__label {\n color: var(--color-foreground-bold-negative) !important;\n}\n\n.menu-item__content {\n position: relative;\n z-index: 1;\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n.menu-item__label {\n color: var(--color-foreground-secondary);\n}\n\n.menu-item:has(.menu-item__subtext) .menu-item__label,\n.menu-item--selected .menu-item__label {\n color: var(--color-foreground-primary);\n}\n\n.menu-item__subtext {\n color: var(--color-foreground-secondary);\n line-height: 1.4;\n}\n\n/* ── Toggle suffix ───────────────────────────────────────────────────────── */\n\n.menu-item__toggle {\n position: relative;\n z-index: 1;\n flex-shrink: 0;\n width: calc(var(--dimension-size-400) + var(--dimension-size-050));\n height: var(--dimension-size-250);\n border-radius: var(--dimension-radius-125);\n background-color: var(--color-background-translucent);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on {\n background-color: var(--color-background-medium-brand);\n}\n\n.menu-item__toggle-thumb {\n position: absolute;\n top: var(--dimension-space-025);\n left: var(--dimension-space-025);\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n border-radius: 50%;\n background-color: var(--color-foreground-on-bold-background-primary);\n transition: transform var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on .menu-item__toggle-thumb {\n transform: translateX(var(--dimension-offset-200, 16px));\n}\n","import { Component, Prop, State, Event, EventEmitter, Element, Watch, Listen, h, Host } from '@stencil/core';\n\nexport type MenuSide = 'top' | 'right' | 'bottom' | 'left';\nexport type MenuAlign = 'start' | 'center' | 'end';\n\nexport interface MenuItemData {\n label: string;\n value?: string;\n subtext?: string;\n isSelected?: boolean;\n isInactive?: boolean;\n isDestructive?: boolean;\n showToggle?: boolean;\n toggleValue?: boolean;\n}\n\nexport interface MenuSection {\n header?: string;\n items: MenuItemData[];\n}\n\nconst CLOSE_ANIMATION_MS = 220;\nconst VP_PAD = 4;\n\n@Component({\n tag: 'ds-menu',\n styleUrl: 'Menu.css',\n scoped: true,\n})\nexport class Menu {\n @Element() el!: HTMLElement;\n\n @Prop({ mutable: true }) open: boolean = false;\n @Prop() items: MenuItemData[] = [];\n @Prop() sections: MenuSection[] = [];\n @Prop() side: MenuSide = 'bottom';\n @Prop() align: MenuAlign = 'start';\n @Prop() sideOffset: number = 4;\n @Prop() alignOffset: number = 0;\n @Prop() menuWidth: string | undefined;\n @Prop() minWidth: string | undefined;\n /** External trigger element to position against. Set via JS: menuEl.anchor = buttonEl */\n @Prop() anchor: HTMLElement | undefined;\n /** ID of the external trigger element for positioning */\n @Prop() anchorId: string | undefined;\n\n @State() private shouldRender: boolean = false;\n @State() private closing: boolean = false;\n @State() private pos: { x: number; y: number } = { x: 0, y: 0 };\n @State() private focusedIndex: number = 0;\n @State() private positionReady: boolean = false;\n\n @Event() dsClose!: EventEmitter<void>;\n @Event() dsSelect!: EventEmitter<MenuItemData>;\n\n private clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private scrollResizeHandler: (() => void) | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private itemEls: HTMLElement[] = [];\n\n componentDidLoad() {\n if (this.open) this.onOpenChange(true);\n }\n\n disconnectedCallback() {\n this.teardownListeners();\n }\n\n @Watch('open')\n onOpenChange(isOpen: boolean) {\n if (isOpen) {\n this.shouldRender = true;\n this.closing = false;\n this.positionReady = false;\n requestAnimationFrame(() => {\n this.calculatePosition();\n this.positionReady = true;\n this.focusInitialItem();\n this.setupListeners();\n });\n } else if (this.shouldRender) {\n this.closing = true;\n this.teardownListeners();\n this.closeTimer = setTimeout(() => {\n this.shouldRender = false;\n this.closing = false;\n this.closeTimer = null;\n }, CLOSE_ANIMATION_MS);\n }\n }\n\n private get resolvedAnchor(): HTMLElement | null {\n if (this.anchor) return this.anchor;\n if (this.anchorId) return document.getElementById(this.anchorId);\n return null;\n }\n\n private get activeSections(): MenuSection[] {\n if (this.sections.length > 0) return this.sections;\n if (this.items.length > 0) return [{ items: this.items }];\n return [];\n }\n\n private get flatItems(): MenuItemData[] {\n return this.activeSections.flatMap(s => s.items);\n }\n\n private calculatePosition() {\n const anchorEl = this.resolvedAnchor;\n if (!anchorEl) return;\n const popup = this.el.querySelector('.menu-popup') as HTMLElement | null;\n if (!popup) return;\n\n const a = anchorEl.getBoundingClientRect();\n const pw = popup.offsetWidth || 200;\n const ph = popup.offsetHeight || 160;\n let x = 0, y = 0;\n\n switch (this.side) {\n case 'top':\n y = a.top - ph - this.sideOffset;\n x = this.align === 'start' ? a.left + this.alignOffset\n : this.align === 'end' ? a.right - pw + this.alignOffset\n : a.left + a.width / 2 - pw / 2 + this.alignOffset;\n break;\n case 'bottom':\n y = a.bottom + this.sideOffset;\n x = this.align === 'start' ? a.left + this.alignOffset\n : this.align === 'end' ? a.right - pw + this.alignOffset\n : a.left + a.width / 2 - pw / 2 + this.alignOffset;\n break;\n case 'left':\n x = a.left - pw - this.sideOffset;\n y = this.align === 'start' ? a.top + this.alignOffset\n : this.align === 'end' ? a.bottom - ph + this.alignOffset\n : a.top + a.height / 2 - ph / 2 + this.alignOffset;\n break;\n case 'right':\n x = a.right + this.sideOffset;\n y = this.align === 'start' ? a.top + this.alignOffset\n : this.align === 'end' ? a.bottom - ph + this.alignOffset\n : a.top + a.height / 2 - ph / 2 + this.alignOffset;\n break;\n }\n\n this.pos = {\n x: Math.min(Math.max(x, VP_PAD), window.innerWidth - pw - VP_PAD),\n y: Math.min(Math.max(y, VP_PAD), window.innerHeight - ph - VP_PAD),\n };\n }\n\n /** Focus the selected item when present, otherwise the first enabled item. */\n private focusInitialItem() {\n const flat = this.flatItems;\n const selectedIdx = flat.findIndex(it => it.isSelected && !it.isInactive);\n const firstEnabledIdx = flat.findIndex(it => !it.isInactive);\n this.focusedIndex = selectedIdx >= 0\n ? selectedIdx\n : (firstEnabledIdx >= 0 ? firstEnabledIdx : 0);\n\n requestAnimationFrame(() => {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[this.focusedIndex]?.focus();\n });\n }\n\n private setupListeners() {\n this.clickOutsideHandler = (e: MouseEvent) => {\n const t = e.target as Node;\n const popup = this.el.querySelector('.menu-popup');\n const anchorEl = this.resolvedAnchor;\n if (popup?.contains(t) || anchorEl?.contains(t)) return;\n this.close();\n };\n\n this.scrollResizeHandler = () => this.calculatePosition();\n\n document.addEventListener('mousedown', this.clickOutsideHandler, true);\n window.addEventListener('scroll', this.scrollResizeHandler, true);\n window.addEventListener('resize', this.scrollResizeHandler);\n }\n\n private teardownListeners() {\n if (this.clickOutsideHandler) {\n document.removeEventListener('mousedown', this.clickOutsideHandler, true);\n this.clickOutsideHandler = null;\n }\n if (this.scrollResizeHandler) {\n window.removeEventListener('scroll', this.scrollResizeHandler, true);\n window.removeEventListener('resize', this.scrollResizeHandler);\n this.scrollResizeHandler = null;\n }\n if (this.closeTimer) {\n clearTimeout(this.closeTimer);\n this.closeTimer = null;\n }\n }\n\n private close() {\n this.resolvedAnchor?.focus();\n this.dsClose.emit();\n this.open = false;\n }\n\n @Listen('keydown')\n handleKeyDown(e: KeyboardEvent) {\n if (!this.open) return;\n const flat = this.flatItems;\n const enabled = flat.map((it, i) => ({ it, i })).filter(({ it }) => !it.isInactive).map(({ i }) => i);\n if (!enabled.length) return;\n\n const cur = enabled.indexOf(this.focusedIndex);\n const safe = cur < 0 ? 0 : cur;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[(safe + 1) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'ArrowUp':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[(safe - 1 + enabled.length) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'Home':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[0];\n this.focusItem(this.focusedIndex);\n break;\n case 'End':\n e.preventDefault(); e.stopPropagation();\n this.focusedIndex = enabled[enabled.length - 1];\n this.focusItem(this.focusedIndex);\n break;\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'Tab':\n e.preventDefault();\n this.close();\n break;\n }\n }\n\n private focusItem(idx: number) {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[idx]?.focus();\n }\n\n private handleItemClick(item: MenuItemData) {\n if (item.isInactive) return;\n this.dsSelect.emit(item);\n this.close();\n }\n\n render() {\n if (!this.shouldRender) return <Host style={{ display: 'contents' }} />;\n\n const sections = this.activeSections;\n let flatIdx = 0;\n\n const popupStyle: Record<string, string> = {\n position: 'fixed',\n left: '0',\n top: '0',\n transform: `translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,\n zIndex: '9998',\n visibility: this.positionReady ? 'visible' : 'hidden',\n };\n\n if (this.menuWidth) popupStyle['width'] = this.menuWidth;\n if (this.minWidth) popupStyle['min-width'] = this.minWidth;\n\n return (\n <Host style={{ display: 'contents' }}>\n <div\n class={{ 'menu-popup': true, 'menu-popup--closing': this.closing }}\n style={popupStyle}\n role=\"menu\"\n aria-label=\"Menu\"\n aria-orientation=\"vertical\"\n >\n {sections.map((section, si) => (\n <div\n key={si}\n class={{ 'menu-section': true, 'menu-section--divided': si < sections.length - 1 }}\n role={section.header ? 'group' : undefined}\n aria-label={section.header}\n >\n {section.header && (\n <div class=\"section-header\" aria-hidden=\"true\">\n <span class=\"text-body-small-emphasis section-label\">{section.header}</span>\n </div>\n )}\n {section.items.map(item => {\n const idx = flatIdx++;\n const isFocused = this.focusedIndex === idx;\n return (\n <button\n key={idx}\n type=\"button\"\n class={{\n 'menu-item': true,\n 'menu-item--selected': !!item.isSelected,\n 'menu-item--inactive': !!item.isInactive,\n 'menu-item--destructive': !!item.isDestructive,\n 'menu-item--focused': isFocused,\n }}\n role=\"menuitem\"\n aria-current={item.isSelected ? 'true' : undefined}\n disabled={item.isInactive}\n tabIndex={isFocused ? 0 : -1}\n onClick={() => this.handleItemClick(item)}\n onFocus={() => { this.focusedIndex = idx; }}\n >\n <div class=\"menu-item__content\">\n <span class={item.isSelected ? 'text-body-medium-emphasis menu-item__label' : 'text-body-medium menu-item__label'}>\n {item.label}\n </span>\n {item.subtext && (\n <span class=\"text-body-small menu-item__subtext\">{item.subtext}</span>\n )}\n </div>\n {item.showToggle && (\n <div class={{ 'menu-item__toggle': true, 'menu-item__toggle--on': !!item.toggleValue }} aria-hidden=\"true\">\n <div class=\"menu-item__toggle-thumb\" />\n </div>\n )}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ds-mo/ui",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "description": "CompoMo — composable web components styled with TokoMo design tokens",
5
5
  "keywords": [
6
6
  "web-components",
@@ -62,7 +62,7 @@
62
62
  }
63
63
  },
64
64
  "devDependencies": {
65
- "@ds-mo/icons": "^4.3.1",
65
+ "@ds-mo/icons": "^4.4.0",
66
66
  "@ds-mo/tokens": "^2.9.0",
67
67
  "@playwright/test": "^1.55.0",
68
68
  "@eslint/js": "^10.0.1",