@ds-mo/ui 9.2.0 → 9.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/README.md +0 -79
  2. package/dist/.build-stamp +1 -1
  3. package/dist/agent-patterns.json +1 -1
  4. package/dist/agent.json +17 -1
  5. package/dist/angular/ds-avatar.d.ts +1 -1
  6. package/dist/angular/ds-avatar.js +3 -3
  7. package/dist/angular/ds-conversation-list-item.d.ts +1 -1
  8. package/dist/angular/ds-conversation-list-item.js +3 -3
  9. package/dist/angular/ds-menu.d.ts +6 -1
  10. package/dist/angular/ds-menu.js +5 -2
  11. package/dist/angular/ds-panel-nav.d.ts +1 -1
  12. package/dist/angular/ds-panel-nav.js +3 -3
  13. package/dist/components/ds-agent-activity.js +1 -1
  14. package/dist/components/ds-agent-response.js +1 -1
  15. package/dist/components/ds-agent-response.js.map +1 -1
  16. package/dist/components/ds-agent-source-list.js +1 -1
  17. package/dist/components/ds-agent-tool-call.js +1 -1
  18. package/dist/components/ds-attachment-list.js +1 -1
  19. package/dist/components/ds-avatar.js +1 -1
  20. package/dist/components/ds-avatar.js.map +1 -1
  21. package/dist/components/ds-bar-nav.js +1 -1
  22. package/dist/components/ds-bar-nav.js.map +1 -1
  23. package/dist/components/ds-button-filled.js +1 -1
  24. package/dist/components/ds-button-unfilled.js +1 -1
  25. package/dist/components/ds-card-data-viz-donut.js +1 -1
  26. package/dist/components/ds-card-setting.js +1 -1
  27. package/dist/components/ds-card-shell-data-viz.js +1 -1
  28. package/dist/components/ds-card.js +1 -1
  29. package/dist/components/ds-chart-legend.js +1 -1
  30. package/dist/components/ds-checkbox.js +1 -1
  31. package/dist/components/ds-chip.js +1 -1
  32. package/dist/components/ds-code-block.js +1 -1
  33. package/dist/components/ds-conversation-list-item.js +1 -1
  34. package/dist/components/ds-conversation-list-item.js.map +1 -1
  35. package/dist/components/ds-conversation-list-section.js +1 -1
  36. package/dist/components/ds-conversation-list-section.js.map +1 -1
  37. package/dist/components/ds-conversation-list.js +1 -1
  38. package/dist/components/ds-conversation-list.js.map +1 -1
  39. package/dist/components/ds-divider.js +1 -1
  40. package/dist/components/ds-empty-state.js +1 -1
  41. package/dist/components/ds-icon.js +1 -1
  42. package/dist/components/ds-input.js +1 -1
  43. package/dist/components/ds-markdown.js +1 -1
  44. package/dist/components/ds-menu.js +1 -1
  45. package/dist/components/ds-message-bubble.js +1 -1
  46. package/dist/components/ds-message-composer.js +1 -1
  47. package/dist/components/ds-message-composer.js.map +1 -1
  48. package/dist/components/ds-message-scroller.js +1 -1
  49. package/dist/components/ds-message-scroller.js.map +1 -1
  50. package/dist/components/ds-message.js +1 -1
  51. package/dist/components/ds-panel-nav.js +1 -1
  52. package/dist/components/ds-panel-nav.js.map +1 -1
  53. package/dist/components/ds-panel-tool-header.js +1 -1
  54. package/dist/components/ds-panel-tool-search.js +1 -1
  55. package/dist/components/ds-panel-tools.js +1 -1
  56. package/dist/components/ds-panel-tools.js.map +1 -1
  57. package/dist/components/ds-select-multi.js +1 -1
  58. package/dist/components/ds-select.js +1 -1
  59. package/dist/components/ds-slider.js +1 -1
  60. package/dist/components/ds-slider.js.map +1 -1
  61. package/dist/components/ds-switch.js +1 -1
  62. package/dist/components/ds-tab-group.js +1 -1
  63. package/dist/components/ds-tag.js +1 -1
  64. package/dist/components/ds-tag.js.map +1 -1
  65. package/dist/components/{p-Di-ThR90.js → p-BHpWYKtP.js} +2 -2
  66. package/dist/components/p-BHpWYKtP.js.map +1 -0
  67. package/dist/components/p-BRfOCc_h.js +2 -0
  68. package/dist/components/p-BRfOCc_h.js.map +1 -0
  69. package/dist/components/{p-BEQB8EnB.js → p-CBYuvZKM.js} +2 -2
  70. package/dist/components/{p-BFWC17em.js → p-CJlgONwR.js} +2 -2
  71. package/dist/components/p-CWNdl52Y.js +2 -0
  72. package/dist/components/p-CWNdl52Y.js.map +1 -0
  73. package/dist/components/{p-BZAEZENv.js → p-CblAABEo.js} +2 -2
  74. package/dist/components/{p--KbMQblZ.js → p-CeFBA7Dx.js} +2 -2
  75. package/dist/components/p-CiKGqsA2.js +2 -0
  76. package/dist/components/{p-CnM9SW_8.js.map → p-CiKGqsA2.js.map} +1 -1
  77. package/dist/components/{p-2br9YDbG.js → p-Ci_nVk5P.js} +2 -2
  78. package/dist/components/p-Cijzn3YQ.js +2 -0
  79. package/dist/components/p-Cijzn3YQ.js.map +1 -0
  80. package/dist/components/p-DFxqk71w.js +2 -0
  81. package/dist/components/p-DFxqk71w.js.map +1 -0
  82. package/dist/components/{p-C0sq948W.js → p-DaQ0ZE_V.js} +2 -2
  83. package/dist/components/{p-t9Ei1kHP.js → p-DiooIO2B.js} +2 -2
  84. package/dist/components/{p-DIsDiGcp.js → p-Dj5MejHv.js} +2 -2
  85. package/dist/components/p-Dj5MejHv.js.map +1 -0
  86. package/dist/components/{p-Bo5wikia.js → p-DnMCRAwx.js} +2 -2
  87. package/dist/components/{p-CZMEhdlA.js → p-Dst-OliP.js} +2 -2
  88. package/dist/components/p-Dst-OliP.js.map +1 -0
  89. package/dist/components/p-T0Mzhv3-.js +2 -0
  90. package/dist/components/p-T0Mzhv3-.js.map +1 -0
  91. package/dist/components/{p-Bx1G7P6W.js → p-kezp2_Xu.js} +2 -2
  92. package/dist/components/{p-Di4HBckb.js → p-xB0GPG3-.js} +2 -2
  93. package/dist/docs/components.json +291 -11
  94. package/dist/mcp-data/registry/agent-response.json +1 -1
  95. package/dist/mcp-data/registry/avatar.json +19 -1
  96. package/dist/mcp-data/registry/bar-nav.json +1 -1
  97. package/dist/mcp-data/registry/button-unfilled.json +2 -2
  98. package/dist/mcp-data/registry/code-block.json +1 -1
  99. package/dist/mcp-data/registry/conversation-list-item.json +20 -2
  100. package/dist/mcp-data/registry/conversation-list-section.json +1 -1
  101. package/dist/mcp-data/registry/conversation-list.json +1 -1
  102. package/dist/mcp-data/registry/markdown.json +1 -1
  103. package/dist/mcp-data/registry/menu.json +17 -1
  104. package/dist/mcp-data/registry/message-bubble.json +1 -1
  105. package/dist/mcp-data/registry/message-composer.json +1 -1
  106. package/dist/mcp-data/registry/message-scroller.json +2 -2
  107. package/dist/mcp-data/registry/message.json +2 -2
  108. package/dist/mcp-data/registry/panel-nav.json +20 -2
  109. package/dist/mcp-data/registry/panel-tool-header.json +1 -1
  110. package/dist/mcp-data/registry/panel-tools.json +1 -1
  111. package/dist/mcp-data/registry/registry.json +16 -0
  112. package/dist/mcp-data/registry/slider.json +1 -1
  113. package/dist/mcp-data/registry/switch.json +1 -1
  114. package/dist/mcp-data/registry/tag.json +2 -2
  115. package/dist/react/ds-menu.d.ts +1 -0
  116. package/dist/react/ds-menu.js +1 -0
  117. package/dist/types/components/Avatar/Avatar.d.ts +3 -0
  118. package/dist/types/components/BarNav/BarNav.d.ts +2 -0
  119. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +2 -0
  120. package/dist/types/components/ConversationListItem/ConversationListItem.d.ts +2 -0
  121. package/dist/types/components/Menu/Menu.d.ts +6 -0
  122. package/dist/types/components/MessageScroller/MessageScroller.d.ts +4 -0
  123. package/dist/types/components/PanelNav/PanelNav.d.ts +2 -0
  124. package/dist/types/components.d.ts +44 -6
  125. package/package.json +8 -11
  126. package/dist/components/p-41UAx2eq.js +0 -2
  127. package/dist/components/p-41UAx2eq.js.map +0 -1
  128. package/dist/components/p-B7NbIYjS.js +0 -2
  129. package/dist/components/p-B7NbIYjS.js.map +0 -1
  130. package/dist/components/p-CC1C8s6m.js +0 -2
  131. package/dist/components/p-CC1C8s6m.js.map +0 -1
  132. package/dist/components/p-CZMEhdlA.js.map +0 -1
  133. package/dist/components/p-CnM9SW_8.js +0 -2
  134. package/dist/components/p-CuKn9I5f.js +0 -2
  135. package/dist/components/p-CuKn9I5f.js.map +0 -1
  136. package/dist/components/p-DFMM60My.js +0 -2
  137. package/dist/components/p-DFMM60My.js.map +0 -1
  138. package/dist/components/p-DIsDiGcp.js.map +0 -1
  139. package/dist/components/p-Di-ThR90.js.map +0 -1
  140. /package/dist/components/{p-BEQB8EnB.js.map → p-CBYuvZKM.js.map} +0 -0
  141. /package/dist/components/{p-BFWC17em.js.map → p-CJlgONwR.js.map} +0 -0
  142. /package/dist/components/{p-BZAEZENv.js.map → p-CblAABEo.js.map} +0 -0
  143. /package/dist/components/{p--KbMQblZ.js.map → p-CeFBA7Dx.js.map} +0 -0
  144. /package/dist/components/{p-2br9YDbG.js.map → p-Ci_nVk5P.js.map} +0 -0
  145. /package/dist/components/{p-C0sq948W.js.map → p-DaQ0ZE_V.js.map} +0 -0
  146. /package/dist/components/{p-t9Ei1kHP.js.map → p-DiooIO2B.js.map} +0 -0
  147. /package/dist/components/{p-Bo5wikia.js.map → p-DnMCRAwx.js.map} +0 -0
  148. /package/dist/components/{p-Bx1G7P6W.js.map → p-kezp2_Xu.js.map} +0 -0
  149. /package/dist/components/{p-Di4HBckb.js.map → p-xB0GPG3-.js.map} +0 -0
@@ -1,2 +1,2 @@
1
- import{p as o,H as i,c as e,h as s,a as c,t as n}from"./index.js";import{d as t}from"./p-BSOZXagj.js";const r=()=>`.ds-control-inactive.sc-ds-checkbox-h,.ds-control-inactive.sc-ds-checkbox{opacity:0.25;pointer-events:none;cursor:not-allowed}.ds-control--md.sc-ds-checkbox-h,.ds-control--md.sc-ds-checkbox{--ds-control-height:var(--dimension-size-400);--ds-control-icon:var(--dimension-iconography-md);--ds-control-padding-inline:var(--dimension-space-075);--ds-control-label-inset:var(--dimension-space-025);--ds-control-gap:var(--dimension-space-050);--ds-control-radius:var(--dimension-radius-025)}.ds-control--sm.sc-ds-checkbox-h,.ds-control--sm.sc-ds-checkbox{--ds-control-height:var(--dimension-size-300);--ds-control-icon:var(--dimension-iconography-sm);--ds-control-padding-inline:var(--dimension-space-050);--ds-control-label-inset:var(--dimension-space-025);--ds-control-gap:var(--dimension-space-025);--ds-control-radius:var(--dimension-radius-025)}.ds-control--xs.sc-ds-checkbox-h,.ds-control--xs.sc-ds-checkbox{--ds-control-height:var(--dimension-size-200);--ds-control-icon:var(--dimension-iconography-xs);--ds-control-padding-inline:var(--dimension-space-025);--ds-control-label-inset:var(--dimension-space-025);--ds-control-gap:0;--ds-control-radius:var(--dimension-radius-025)}.sc-ds-checkbox-h{--ds-focus-ring-width:var(--dimension-stroke-width-025, 2px);--ds-focus-ring-offset:var(--dimension-space-025, 2px);--ds-focus-ring-color:var(--color-interaction-focus)}.ds-focus-ring.sc-ds-checkbox-h:focus-visible,.ds-focus-ring.sc-ds-checkbox:focus-visible{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:var(--ds-focus-ring-offset)}.ds-focus-ring.ds-focus-ring--visible.sc-ds-checkbox-h,.ds-focus-ring.ds-focus-ring--visible.sc-ds-checkbox{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:var(--ds-focus-ring-offset)}.ds-focus-ring-inset.sc-ds-checkbox-h:focus-visible,.ds-focus-ring-inset.sc-ds-checkbox:focus-visible{outline:none}.ds-focus-ring-inset.sc-ds-checkbox-h:focus-visible::after,.ds-focus-ring-inset.sc-ds-checkbox:focus-visible::after{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:calc(-1 * var(--ds-focus-ring-width))}.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox-h,.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox{outline:none}.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox-h::after,.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox::after{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:calc(-1 * var(--ds-focus-ring-width))}.ds-interaction-fill.sc-ds-checkbox-h,.ds-interaction-fill.sc-ds-checkbox{position:relative;z-index:0;--ds-interaction-hover:var(--color-interaction-hover);--ds-interaction-pressed:var(--color-interaction-pressed);--ds-interaction-active:var(--color-interaction-active-brand);--ds-interaction-border-width:0px;--ds-interaction-border-color:transparent}.ds-interaction-fill.sc-ds-checkbox-h::before,.ds-interaction-fill.sc-ds-checkbox::before,.ds-interaction-fill.sc-ds-checkbox-h::after,.ds-interaction-fill.sc-ds-checkbox::after{content:'';position:absolute;inset:0;border-radius:inherit;background:transparent;pointer-events:none;transition:none}.ds-interaction-fill.sc-ds-checkbox-h::before,.ds-interaction-fill.sc-ds-checkbox::before{z-index:1}.ds-interaction-fill.sc-ds-checkbox-h::after,.ds-interaction-fill.sc-ds-checkbox::after{z-index:3;box-shadow:inset 0 0 0 var(--ds-interaction-border-width) var(--ds-interaction-border-color)}.ds-interaction-fill--bordered.sc-ds-checkbox-h,.ds-interaction-fill--bordered.sc-ds-checkbox{--ds-interaction-border-width:var(--dimension-stroke-width-012);--ds-interaction-border-color:var(--color-border-secondary)}.ds-interaction-fill--selected.sc-ds-checkbox-h::before,.ds-interaction-fill--selected.sc-ds-checkbox::before{background:var(--ds-interaction-active)}.ds-interaction-fill--selected.sc-ds-checkbox-h,.ds-interaction-fill--selected.sc-ds-checkbox{--ds-interaction-dot-ring:var(--ds-interaction-active)}.ds-interaction-fill.sc-ds-checkbox-h:hover:not(:disabled)::after,.ds-interaction-fill.sc-ds-checkbox:hover:not(:disabled)::after{background:var(--ds-interaction-hover)}.ds-interaction-fill.sc-ds-checkbox-h:active:not(:disabled)::after,.ds-interaction-fill.sc-ds-checkbox:active:not(:disabled)::after{background:var(--ds-interaction-pressed)}.ds-interaction-fill.sc-ds-checkbox-h>.ds-interaction-fill__content.sc-ds-checkbox,.ds-interaction-fill.sc-ds-checkbox>.ds-interaction-fill__content.sc-ds-checkbox,.ds-interaction-fill__content.sc-ds-checkbox{position:relative;z-index:2}.ds-interaction-fill--on-faint.sc-ds-checkbox-h,.ds-interaction-fill--on-faint.sc-ds-checkbox{--ds-interaction-active:var(--color-interaction-active)}.ds-interaction-fill--on-medium.sc-ds-checkbox-h,.ds-interaction-fill--on-medium.sc-ds-checkbox{--ds-interaction-hover:var(--color-interaction-on-medium-background-hover);--ds-interaction-pressed:var(--color-interaction-on-medium-background-pressed);--ds-interaction-active:var(--color-interaction-on-medium-background-active);--ds-focus-ring-color:var(--color-interaction-on-medium-background-focus)}.ds-interaction-fill--on-bold.sc-ds-checkbox-h,.ds-interaction-fill--on-bold.sc-ds-checkbox{--ds-interaction-hover:var(--color-interaction-on-bold-background-hover);--ds-interaction-pressed:var(--color-interaction-on-bold-background-pressed);--ds-interaction-active:var(--color-interaction-on-bold-background-active);--ds-focus-ring-color:var(--color-interaction-on-bold-background-focus)}.ds-interaction-fill--on-strong.sc-ds-checkbox-h,.ds-interaction-fill--on-strong.sc-ds-checkbox{--ds-interaction-hover:var(--color-interaction-on-strong-background-hover);--ds-interaction-pressed:var(--color-interaction-on-strong-background-pressed);--ds-interaction-active:var(--color-interaction-on-strong-background-active);--ds-focus-ring-color:var(--color-interaction-on-strong-background-focus)}.ds-interaction-fill--on-translucent.sc-ds-checkbox-h,.ds-interaction-fill--on-translucent.sc-ds-checkbox{--ds-interaction-hover:var(--color-translucent-interaction-hover);--ds-interaction-pressed:var(--color-translucent-interaction-pressed);--ds-interaction-active:var(--color-translucent-interaction-active);--ds-focus-ring-color:var(--color-translucent-interaction-focus)}.ds-interaction-fill--on-inverted.sc-ds-checkbox-h,.ds-interaction-fill--on-inverted.sc-ds-checkbox{--ds-interaction-hover:var(--color-inverted-interaction-hover);--ds-interaction-pressed:var(--color-inverted-interaction-pressed);--ds-interaction-active:var(--color-inverted-interaction-active);--ds-focus-ring-color:var(--color-inverted-interaction-focus)}.ds-interaction-fill--on-media.sc-ds-checkbox-h,.ds-interaction-fill--on-media.sc-ds-checkbox{--ds-interaction-hover:var(--color-media-interaction-hover);--ds-interaction-pressed:var(--color-media-interaction-pressed);--ds-interaction-active:var(--color-media-interaction-active);--ds-focus-ring-color:var(--color-media-interaction-focus)}.ds-interaction-fill--on-always-dark.sc-ds-checkbox-h,.ds-interaction-fill--on-always-dark.sc-ds-checkbox{--ds-interaction-hover:var(--color-always-dark-interaction-hover);--ds-interaction-pressed:var(--color-always-dark-interaction-pressed);--ds-interaction-active:var(--color-always-dark-interaction-active);--ds-focus-ring-color:var(--color-always-dark-interaction-focus)}.ds-interaction-fill--on-navigation.sc-ds-checkbox-h,.ds-interaction-fill--on-navigation.sc-ds-checkbox{--ds-interaction-hover:var(--color-navigation-interaction-hover);--ds-interaction-pressed:var(--color-navigation-interaction-pressed);--ds-interaction-active:var(--color-navigation-interaction-active);--ds-focus-ring-color:var(--color-navigation-interaction-focus)}.sc-ds-checkbox-h{display:inline-flex;align-items:center;box-sizing:border-box;gap:var(--ds-control-gap);height:var(--ds-control-height);padding:0 var(--ds-control-padding-inline);border-radius:var(--ds-control-radius);cursor:pointer;user-select:none}.checkbox--presentation.sc-ds-checkbox-h{width:var(--ds-control-icon);height:var(--ds-control-icon);padding:0;gap:0;pointer-events:none}.checkbox--md.sc-ds-checkbox-h{--_checkbox-box:var(--dimension-iconography-sm);--_checkbox-stroke:var(--dimension-stroke-width-015)}.checkbox--sm.sc-ds-checkbox-h{--_checkbox-box:var(--dimension-iconography-xs);--_checkbox-stroke:var(--dimension-stroke-width-012)}.checkbox--xs.sc-ds-checkbox-h{--_checkbox-box:var(--dimension-size-100);--_checkbox-stroke:calc(var(--dimension-stroke-width-base) * 3 / 32)}.checkbox__placement.sc-ds-checkbox{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ds-control-icon);height:var(--ds-control-icon)}.box.sc-ds-checkbox{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:var(--_checkbox-box);height:var(--_checkbox-box);border:0;border-radius:var(--dimension-radius-025);box-shadow:inset 0 0 0 var(--_checkbox-stroke) var(--color-foreground-tertiary);transition:background-color var(--effect-motion-short-2), box-shadow var(--effect-motion-short-2)}.box--marked.sc-ds-checkbox{color:var(--color-foreground-on-bold-background-primary);background-color:var(--color-background-bold-brand);box-shadow:none}.checkbox__mark.sc-ds-checkbox{width:100%;height:100%;flex-shrink:0;stroke:currentColor;stroke-width:var(--_checkbox-stroke);stroke-linecap:butt;stroke-linejoin:round}.checkbox__mark--checked.sc-ds-checkbox{transform:translateY(-0.5px)}.checkbox__label.sc-ds-checkbox{flex:1;min-width:0;padding:0 var(--ds-control-label-inset)}`;const a={md:"text-body-medium",sm:"text-body-small",xs:"text-caption"};let d=0;const l=o(class o extends i{constructor(o){super();if(o!==false){this.__registerHost()}this.dsChange=e(this,"dsChange");this.internals=this.attachInternals();this.labelId=`ds-checkbox-label-${++d}`;this.checked=false;this.size="md";this.value="on";this.disabled=false;this.required=false;this.requiredMessage="This field is required.";this.indeterminate=false;this.isInactive=false;this.presentation=false;this.initialChecked=false;this.initialIndeterminate=false;this.formDisabled=false;this.handleActivate=()=>{if(this.isInactive||this.disabled||this.formDisabled||this.presentation)return;if(this.indeterminate)this.indeterminate=false;this.checked=!this.checked;this.dsChange.emit(this.checked)};this.handleKeyDown=o=>{if(o.key==="Enter"||o.key===" "){o.preventDefault();this.handleActivate()}}}componentWillLoad(){this.initialChecked=this.checked;this.initialIndeterminate=this.indeterminate;this.syncFormValue()}syncFormValue(){const o=this.isInactive||this.disabled||this.formDisabled||this.presentation;this.internals.setFormValue(!o&&this.checked?this.value:null);const i=this.required&&!o&&!this.checked;this.internals.setValidity(i?{valueMissing:true}:{},i?this.requiredMessage:"")}formDisabledCallback(o){this.formDisabled=o;this.syncFormValue()}formResetCallback(){this.checked=this.initialChecked;this.indeterminate=this.initialIndeterminate}render(){const o=this.isInactive||this.disabled||this.formDisabled;const i=this.checked||this.indeterminate;const e=this.required&&!o&&!this.checked;return s(c,{key:"11d6885b8c76677bad4d7c833f2f45ea5605afca",role:this.presentation?undefined:"checkbox","aria-checked":this.presentation?undefined:this.indeterminate?"mixed":String(this.checked),"aria-disabled":!this.presentation&&o?"true":undefined,"aria-required":!this.presentation&&this.required?"true":undefined,"aria-invalid":!this.presentation&&e?"true":undefined,"aria-labelledby":this.presentation?undefined:this.labelId,"aria-hidden":this.presentation?"true":undefined,tabIndex:this.presentation||o?-1:0,class:{checkbox:true,"checkbox--presentation":this.presentation,[`checkbox--${this.size}`]:true,[`ds-control--${this.size}`]:true,"ds-control-inactive":o&&!this.presentation,"ds-focus-ring-inset":!this.presentation,"ds-interaction-fill":!o&&!this.presentation},onClick:this.presentation?undefined:this.handleActivate,onKeyDown:this.presentation?undefined:this.handleKeyDown},s("span",{key:"e9c917d309aca6157ff4d6bca9b5dd0029e8718c",class:"checkbox__placement ds-interaction-fill__content","aria-hidden":"true"},s("span",{key:"2ee9449509a9f0be534fa78c7724228fb163dd55",class:{box:true,"box--marked":i}},i&&s("svg",{key:"912bc367d37c602fa826d5731190907b5357261d",class:{checkbox__mark:true,"checkbox__mark--checked":!this.indeterminate},viewBox:"0 0 16 16",fill:"none",focusable:"false"},s("path",{key:"960a209b215d181dedf6c7ed1be9d1a3f9bc37af",d:this.indeterminate?"M4 8H12":"M3.5 8.25L6.75 11.5L12.5 4.75","vector-effect":"non-scaling-stroke"})))),!this.presentation&&s("ds-text",{key:"492fe4b6fcb64f88e7ea5ae070d2e307933b6519",class:"checkbox__label ds-interaction-fill__content",as:"span",variant:a[this.size],textId:this.labelId},this.label))}static get formAssociated(){return true}static get watchers(){return{checked:[{syncFormValue:0}],value:[{syncFormValue:0}],disabled:[{syncFormValue:0}],isInactive:[{syncFormValue:0}],required:[{syncFormValue:0}],presentation:[{syncFormValue:0}]}}static get style(){return r()}},[66,"ds-checkbox",{label:[1],checked:[1028],size:[1],name:[513],value:[1],disabled:[516],required:[516],requiredMessage:[1,"required-message"],indeterminate:[1028],isInactive:[4,"is-inactive"],presentation:[4],formDisabled:[32]},undefined,{checked:[{syncFormValue:0}],value:[{syncFormValue:0}],disabled:[{syncFormValue:0}],isInactive:[{syncFormValue:0}],required:[{syncFormValue:0}],presentation:[{syncFormValue:0}]}]);function h(){if(typeof customElements==="undefined"){return}const o=["ds-checkbox","ds-text"];o.forEach((o=>{switch(o){case"ds-checkbox":if(!customElements.get(n(o))){customElements.define(n(o),l)}break;case"ds-text":if(!customElements.get(n(o))){t()}break}}))}h();export{l as C,h as d};
2
- //# sourceMappingURL=p-Di4HBckb.js.map
1
+ import{p as o,H as e,c as i,h as s,a as c,t as n}from"./index.js";import{d as t}from"./p-BSOZXagj.js";const r=()=>`.ds-control-inactive.sc-ds-checkbox-h,.ds-control-inactive.sc-ds-checkbox{opacity:0.25;pointer-events:none;cursor:not-allowed}.ds-control--md.sc-ds-checkbox-h,.ds-control--md.sc-ds-checkbox{--ds-control-height:var(--dimension-size-400);--ds-control-icon:var(--dimension-iconography-md);--ds-control-padding-inline:var(--dimension-space-075);--ds-control-label-inset:var(--dimension-space-025);--ds-control-gap:var(--dimension-space-050);--ds-control-radius:var(--dimension-radius-025)}.ds-control--sm.sc-ds-checkbox-h,.ds-control--sm.sc-ds-checkbox{--ds-control-height:var(--dimension-size-300);--ds-control-icon:var(--dimension-iconography-sm);--ds-control-padding-inline:var(--dimension-space-050);--ds-control-label-inset:var(--dimension-space-025);--ds-control-gap:var(--dimension-space-025);--ds-control-radius:var(--dimension-radius-025)}.ds-control--xs.sc-ds-checkbox-h,.ds-control--xs.sc-ds-checkbox{--ds-control-height:var(--dimension-size-200);--ds-control-icon:var(--dimension-iconography-xs);--ds-control-padding-inline:var(--dimension-space-025);--ds-control-label-inset:var(--dimension-space-025);--ds-control-gap:0;--ds-control-radius:var(--dimension-radius-025)}.sc-ds-checkbox-h{--ds-focus-ring-width:var(--dimension-stroke-width-025, 2px);--ds-focus-ring-offset:var(--dimension-space-025, 2px);--ds-focus-ring-color:var(--color-interaction-focus)}.ds-focus-ring.sc-ds-checkbox-h:focus-visible,.ds-focus-ring.sc-ds-checkbox:focus-visible{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:var(--ds-focus-ring-offset)}.ds-focus-ring.ds-focus-ring--visible.sc-ds-checkbox-h,.ds-focus-ring.ds-focus-ring--visible.sc-ds-checkbox{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:var(--ds-focus-ring-offset)}.ds-focus-ring-inset.sc-ds-checkbox-h:focus-visible,.ds-focus-ring-inset.sc-ds-checkbox:focus-visible{outline:none}.ds-focus-ring-inset.sc-ds-checkbox-h:focus-visible::after,.ds-focus-ring-inset.sc-ds-checkbox:focus-visible::after{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:calc(-1 * var(--ds-focus-ring-width))}.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox-h,.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox{outline:none}.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox-h::after,.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-checkbox::after{outline:var(--ds-focus-ring-width) solid var(--ds-focus-ring-color);outline-offset:calc(-1 * var(--ds-focus-ring-width))}.ds-interaction-fill.sc-ds-checkbox-h,.ds-interaction-fill.sc-ds-checkbox{position:relative;z-index:0;--ds-interaction-hover:var(--color-interaction-hover);--ds-interaction-pressed:var(--color-interaction-pressed);--ds-interaction-active:var(--color-interaction-active-brand);--ds-interaction-border-width:0px;--ds-interaction-border-color:transparent}.ds-interaction-fill.sc-ds-checkbox-h::before,.ds-interaction-fill.sc-ds-checkbox::before,.ds-interaction-fill.sc-ds-checkbox-h::after,.ds-interaction-fill.sc-ds-checkbox::after{content:'';position:absolute;inset:0;border-radius:inherit;background:transparent;pointer-events:none;transition:none}.ds-interaction-fill.sc-ds-checkbox-h::before,.ds-interaction-fill.sc-ds-checkbox::before{z-index:1}.ds-interaction-fill.sc-ds-checkbox-h::after,.ds-interaction-fill.sc-ds-checkbox::after{z-index:3;box-shadow:inset 0 0 0 var(--ds-interaction-border-width) var(--ds-interaction-border-color)}.ds-interaction-fill--bordered.sc-ds-checkbox-h,.ds-interaction-fill--bordered.sc-ds-checkbox{--ds-interaction-border-width:var(--dimension-stroke-width-012);--ds-interaction-border-color:var(--color-border-secondary)}.ds-interaction-fill--selected.sc-ds-checkbox-h::before,.ds-interaction-fill--selected.sc-ds-checkbox::before{background:var(--ds-interaction-active)}.ds-interaction-fill--selected.sc-ds-checkbox-h,.ds-interaction-fill--selected.sc-ds-checkbox{--ds-interaction-dot-ring:var(--ds-interaction-active)}.ds-interaction-fill.sc-ds-checkbox-h:hover:not(:disabled)::after,.ds-interaction-fill.sc-ds-checkbox:hover:not(:disabled)::after{background:var(--ds-interaction-hover)}.ds-interaction-fill.sc-ds-checkbox-h:active:not(:disabled)::after,.ds-interaction-fill.sc-ds-checkbox:active:not(:disabled)::after{background:var(--ds-interaction-pressed)}.ds-interaction-fill.sc-ds-checkbox-h>.ds-interaction-fill__content.sc-ds-checkbox,.ds-interaction-fill.sc-ds-checkbox>.ds-interaction-fill__content.sc-ds-checkbox,.ds-interaction-fill__content.sc-ds-checkbox{position:relative;z-index:2}.ds-interaction-fill--on-faint.sc-ds-checkbox-h,.ds-interaction-fill--on-faint.sc-ds-checkbox{--ds-interaction-active:var(--color-interaction-active)}.ds-interaction-fill--on-medium.sc-ds-checkbox-h,.ds-interaction-fill--on-medium.sc-ds-checkbox{--ds-interaction-hover:var(--color-interaction-on-medium-background-hover);--ds-interaction-pressed:var(--color-interaction-on-medium-background-pressed);--ds-interaction-active:var(--color-interaction-on-medium-background-active);--ds-focus-ring-color:var(--color-interaction-on-medium-background-focus)}.ds-interaction-fill--on-bold.sc-ds-checkbox-h,.ds-interaction-fill--on-bold.sc-ds-checkbox{--ds-interaction-hover:var(--color-interaction-on-bold-background-hover);--ds-interaction-pressed:var(--color-interaction-on-bold-background-pressed);--ds-interaction-active:var(--color-interaction-on-bold-background-active);--ds-focus-ring-color:var(--color-interaction-on-bold-background-focus)}.ds-interaction-fill--on-strong.sc-ds-checkbox-h,.ds-interaction-fill--on-strong.sc-ds-checkbox{--ds-interaction-hover:var(--color-interaction-on-strong-background-hover);--ds-interaction-pressed:var(--color-interaction-on-strong-background-pressed);--ds-interaction-active:var(--color-interaction-on-strong-background-active);--ds-focus-ring-color:var(--color-interaction-on-strong-background-focus)}.ds-interaction-fill--on-translucent.sc-ds-checkbox-h,.ds-interaction-fill--on-translucent.sc-ds-checkbox{--ds-interaction-hover:var(--color-translucent-interaction-hover);--ds-interaction-pressed:var(--color-translucent-interaction-pressed);--ds-interaction-active:var(--color-translucent-interaction-active);--ds-focus-ring-color:var(--color-translucent-interaction-focus)}.ds-interaction-fill--on-inverted.sc-ds-checkbox-h,.ds-interaction-fill--on-inverted.sc-ds-checkbox{--ds-interaction-hover:var(--color-inverted-interaction-hover);--ds-interaction-pressed:var(--color-inverted-interaction-pressed);--ds-interaction-active:var(--color-inverted-interaction-active);--ds-focus-ring-color:var(--color-inverted-interaction-focus)}.ds-interaction-fill--on-media.sc-ds-checkbox-h,.ds-interaction-fill--on-media.sc-ds-checkbox{--ds-interaction-hover:var(--color-media-interaction-hover);--ds-interaction-pressed:var(--color-media-interaction-pressed);--ds-interaction-active:var(--color-media-interaction-active);--ds-focus-ring-color:var(--color-media-interaction-focus)}.ds-interaction-fill--on-always-dark.sc-ds-checkbox-h,.ds-interaction-fill--on-always-dark.sc-ds-checkbox{--ds-interaction-hover:var(--color-always-dark-interaction-hover);--ds-interaction-pressed:var(--color-always-dark-interaction-pressed);--ds-interaction-active:var(--color-always-dark-interaction-active);--ds-focus-ring-color:var(--color-always-dark-interaction-focus)}.ds-interaction-fill--on-navigation.sc-ds-checkbox-h,.ds-interaction-fill--on-navigation.sc-ds-checkbox{--ds-interaction-hover:var(--color-navigation-interaction-hover);--ds-interaction-pressed:var(--color-navigation-interaction-pressed);--ds-interaction-active:var(--color-navigation-interaction-active);--ds-focus-ring-color:var(--color-navigation-interaction-focus)}.sc-ds-checkbox-h{display:inline-flex;align-items:center;box-sizing:border-box;gap:var(--ds-control-gap);height:var(--ds-control-height);padding:0 var(--ds-control-padding-inline);border-radius:var(--ds-control-radius);cursor:pointer;user-select:none}.checkbox--presentation.sc-ds-checkbox-h{width:var(--ds-control-icon);height:var(--ds-control-icon);padding:0;gap:0;pointer-events:none}.checkbox--md.sc-ds-checkbox-h{--_checkbox-box:var(--dimension-iconography-sm);--_checkbox-stroke:var(--dimension-stroke-width-015)}.checkbox--sm.sc-ds-checkbox-h{--_checkbox-box:var(--dimension-iconography-xs);--_checkbox-stroke:var(--dimension-stroke-width-012)}.checkbox--xs.sc-ds-checkbox-h{--_checkbox-box:var(--dimension-size-100);--_checkbox-stroke:calc(var(--dimension-stroke-width-base) * 3 / 32)}.checkbox__placement.sc-ds-checkbox{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ds-control-icon);height:var(--ds-control-icon)}.box.sc-ds-checkbox{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;width:var(--_checkbox-box);height:var(--_checkbox-box);border:0;border-radius:var(--dimension-radius-025);box-shadow:inset 0 0 0 var(--_checkbox-stroke) var(--color-foreground-tertiary);transition:background-color var(--effect-motion-short-2), box-shadow var(--effect-motion-short-2)}.box--marked.sc-ds-checkbox{color:var(--color-foreground-on-bold-background-primary);background-color:var(--color-background-bold-brand);box-shadow:none}.checkbox__mark.sc-ds-checkbox{width:100%;height:100%;flex-shrink:0;stroke:currentColor;stroke-width:var(--_checkbox-stroke);stroke-linecap:butt;stroke-linejoin:round}.checkbox__mark--checked.sc-ds-checkbox{transform:translateY(-0.5px)}.checkbox__label.sc-ds-checkbox{flex:1;min-width:0;padding:0 var(--ds-control-label-inset)}`;const a={md:"text-body-medium",sm:"text-body-small",xs:"text-caption"};let d=0;const l=o(class o extends e{constructor(o){super();if(o!==false){this.__registerHost()}this.dsChange=i(this,"dsChange");this.internals=this.attachInternals();this.labelId=`ds-checkbox-label-${++d}`;this.checked=false;this.size="md";this.value="on";this.disabled=false;this.required=false;this.requiredMessage="This field is required.";this.indeterminate=false;this.isInactive=false;this.presentation=false;this.initialChecked=false;this.initialIndeterminate=false;this.formDisabled=false;this.handleActivate=()=>{if(this.isInactive||this.disabled||this.formDisabled||this.presentation)return;if(this.indeterminate)this.indeterminate=false;this.checked=!this.checked;this.dsChange.emit(this.checked)};this.handleKeyDown=o=>{if(o.key==="Enter"||o.key===" "){o.preventDefault();this.handleActivate()}}}componentWillLoad(){this.initialChecked=this.checked;this.initialIndeterminate=this.indeterminate;this.syncFormValue()}syncFormValue(){const o=this.isInactive||this.disabled||this.formDisabled||this.presentation;this.internals.setFormValue(!o&&this.checked?this.value:null);const e=this.required&&!o&&!this.checked;this.internals.setValidity(e?{valueMissing:true}:{},e?this.requiredMessage:"")}formDisabledCallback(o){this.formDisabled=o;this.syncFormValue()}formResetCallback(){this.checked=this.initialChecked;this.indeterminate=this.initialIndeterminate}render(){const o=this.isInactive||this.disabled||this.formDisabled;const e=this.checked||this.indeterminate;const i=this.required&&!o&&!this.checked;return s(c,{key:"94e08c7e3d60041f460d9a668be08f57f0cde351",role:this.presentation?undefined:"checkbox","aria-checked":this.presentation?undefined:this.indeterminate?"mixed":String(this.checked),"aria-disabled":!this.presentation&&o?"true":undefined,"aria-required":!this.presentation&&this.required?"true":undefined,"aria-invalid":!this.presentation&&i?"true":undefined,"aria-labelledby":this.presentation?undefined:this.labelId,"aria-hidden":this.presentation?"true":undefined,tabIndex:this.presentation||o?-1:0,class:{checkbox:true,"checkbox--presentation":this.presentation,[`checkbox--${this.size}`]:true,[`ds-control--${this.size}`]:true,"ds-control-inactive":o&&!this.presentation,"ds-focus-ring-inset":!this.presentation,"ds-interaction-fill":!o&&!this.presentation},onClick:this.presentation?undefined:this.handleActivate,onKeyDown:this.presentation?undefined:this.handleKeyDown},s("span",{key:"190afbb7ed68a43a0744547bea789bc2e958cb7a",class:"checkbox__placement ds-interaction-fill__content","aria-hidden":"true"},s("span",{key:"177079a6d598eec30ad79263c13d3f3283065015",class:{box:true,"box--marked":e}},e&&s("svg",{key:"5afd2f4b573db84441fd91e48807683d9ecc0ee6",class:{checkbox__mark:true,"checkbox__mark--checked":!this.indeterminate},viewBox:"0 0 16 16",fill:"none",focusable:"false"},s("path",{key:"88a50952387b378297a4cc4c9db74a05b4d706a4",d:this.indeterminate?"M4 8H12":"M3.5 8.25L6.75 11.5L12.5 4.75","vector-effect":"non-scaling-stroke"})))),!this.presentation&&s("ds-text",{key:"5204a014040030faa6e762e803fd32ce2a60e0f3",class:"checkbox__label ds-interaction-fill__content",as:"span",variant:a[this.size],textId:this.labelId},this.label))}static get formAssociated(){return true}static get watchers(){return{checked:[{syncFormValue:0}],value:[{syncFormValue:0}],disabled:[{syncFormValue:0}],isInactive:[{syncFormValue:0}],required:[{syncFormValue:0}],presentation:[{syncFormValue:0}]}}static get style(){return r()}},[66,"ds-checkbox",{label:[1],checked:[1028],size:[1],name:[513],value:[1],disabled:[516],required:[516],requiredMessage:[1,"required-message"],indeterminate:[1028],isInactive:[4,"is-inactive"],presentation:[4],formDisabled:[32]},undefined,{checked:[{syncFormValue:0}],value:[{syncFormValue:0}],disabled:[{syncFormValue:0}],isInactive:[{syncFormValue:0}],required:[{syncFormValue:0}],presentation:[{syncFormValue:0}]}]);function h(){if(typeof customElements==="undefined"){return}const o=["ds-checkbox","ds-text"];o.forEach((o=>{switch(o){case"ds-checkbox":if(!customElements.get(n(o))){customElements.define(n(o),l)}break;case"ds-text":if(!customElements.get(n(o))){t()}break}}))}h();export{l as C,h as d};
2
+ //# sourceMappingURL=p-xB0GPG3-.js.map
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-19T23:20:16",
2
+ "timestamp": "2026-07-20T03:10:58",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.43.5",
@@ -1049,6 +1049,214 @@
1049
1049
  "getter": false,
1050
1050
  "setter": false
1051
1051
  },
1052
+ {
1053
+ "name": "iconColor",
1054
+ "type": "\"ai\" | \"bold-ai\" | \"bold-brand\" | \"bold-caution\" | \"bold-negative\" | \"bold-neutral\" | \"bold-positive\" | \"bold-warning\" | \"brand\" | \"caution\" | \"faint-ai\" | \"faint-brand\" | \"faint-caution\" | \"faint-negative\" | \"faint-neutral\" | \"faint-positive\" | \"faint-warning\" | \"guide\" | \"inherit\" | \"medium-ai\" | \"medium-brand\" | \"medium-caution\" | \"medium-negative\" | \"medium-neutral\" | \"medium-positive\" | \"medium-warning\" | \"negative\" | \"neutral\" | \"on-bold\" | \"on-strong\" | \"positive\" | \"primary\" | \"quaternary\" | \"secondary\" | \"strong-ai\" | \"strong-brand\" | \"strong-caution\" | \"strong-negative\" | \"strong-neutral\" | \"strong-positive\" | \"strong-warning\" | \"tertiary\" | \"warning\" | `var(--${string})`",
1055
+ "complexType": {
1056
+ "original": "IconColor",
1057
+ "resolved": "\"ai\" | \"bold-ai\" | \"bold-brand\" | \"bold-caution\" | \"bold-negative\" | \"bold-neutral\" | \"bold-positive\" | \"bold-warning\" | \"brand\" | \"caution\" | \"faint-ai\" | \"faint-brand\" | \"faint-caution\" | \"faint-negative\" | \"faint-neutral\" | \"faint-positive\" | \"faint-warning\" | \"guide\" | \"inherit\" | \"medium-ai\" | \"medium-brand\" | \"medium-caution\" | \"medium-negative\" | \"medium-neutral\" | \"medium-positive\" | \"medium-warning\" | \"negative\" | \"neutral\" | \"on-bold\" | \"on-strong\" | \"positive\" | \"primary\" | \"quaternary\" | \"secondary\" | \"strong-ai\" | \"strong-brand\" | \"strong-caution\" | \"strong-negative\" | \"strong-neutral\" | \"strong-positive\" | \"strong-warning\" | \"tertiary\" | \"warning\" | `var(--${string})`",
1058
+ "references": {
1059
+ "IconColor": {
1060
+ "location": "import",
1061
+ "path": "../Icon/Icon",
1062
+ "id": "src/wc/components/Icon/Icon.tsx::IconColor",
1063
+ "referenceLocation": "IconColor"
1064
+ }
1065
+ }
1066
+ },
1067
+ "mutable": false,
1068
+ "attr": "icon-color",
1069
+ "reflectToAttr": false,
1070
+ "docs": "Semantic color for the icon. Use primary to surface unread or current identity state.",
1071
+ "docsTags": [
1072
+ {
1073
+ "name": "default",
1074
+ "text": "'secondary'"
1075
+ }
1076
+ ],
1077
+ "default": "'secondary'",
1078
+ "values": [
1079
+ {
1080
+ "value": "ai",
1081
+ "type": "string"
1082
+ },
1083
+ {
1084
+ "value": "bold-ai",
1085
+ "type": "string"
1086
+ },
1087
+ {
1088
+ "value": "bold-brand",
1089
+ "type": "string"
1090
+ },
1091
+ {
1092
+ "value": "bold-caution",
1093
+ "type": "string"
1094
+ },
1095
+ {
1096
+ "value": "bold-negative",
1097
+ "type": "string"
1098
+ },
1099
+ {
1100
+ "value": "bold-neutral",
1101
+ "type": "string"
1102
+ },
1103
+ {
1104
+ "value": "bold-positive",
1105
+ "type": "string"
1106
+ },
1107
+ {
1108
+ "value": "bold-warning",
1109
+ "type": "string"
1110
+ },
1111
+ {
1112
+ "value": "brand",
1113
+ "type": "string"
1114
+ },
1115
+ {
1116
+ "value": "caution",
1117
+ "type": "string"
1118
+ },
1119
+ {
1120
+ "value": "faint-ai",
1121
+ "type": "string"
1122
+ },
1123
+ {
1124
+ "value": "faint-brand",
1125
+ "type": "string"
1126
+ },
1127
+ {
1128
+ "value": "faint-caution",
1129
+ "type": "string"
1130
+ },
1131
+ {
1132
+ "value": "faint-negative",
1133
+ "type": "string"
1134
+ },
1135
+ {
1136
+ "value": "faint-neutral",
1137
+ "type": "string"
1138
+ },
1139
+ {
1140
+ "value": "faint-positive",
1141
+ "type": "string"
1142
+ },
1143
+ {
1144
+ "value": "faint-warning",
1145
+ "type": "string"
1146
+ },
1147
+ {
1148
+ "value": "guide",
1149
+ "type": "string"
1150
+ },
1151
+ {
1152
+ "value": "inherit",
1153
+ "type": "string"
1154
+ },
1155
+ {
1156
+ "value": "medium-ai",
1157
+ "type": "string"
1158
+ },
1159
+ {
1160
+ "value": "medium-brand",
1161
+ "type": "string"
1162
+ },
1163
+ {
1164
+ "value": "medium-caution",
1165
+ "type": "string"
1166
+ },
1167
+ {
1168
+ "value": "medium-negative",
1169
+ "type": "string"
1170
+ },
1171
+ {
1172
+ "value": "medium-neutral",
1173
+ "type": "string"
1174
+ },
1175
+ {
1176
+ "value": "medium-positive",
1177
+ "type": "string"
1178
+ },
1179
+ {
1180
+ "value": "medium-warning",
1181
+ "type": "string"
1182
+ },
1183
+ {
1184
+ "value": "negative",
1185
+ "type": "string"
1186
+ },
1187
+ {
1188
+ "value": "neutral",
1189
+ "type": "string"
1190
+ },
1191
+ {
1192
+ "value": "on-bold",
1193
+ "type": "string"
1194
+ },
1195
+ {
1196
+ "value": "on-strong",
1197
+ "type": "string"
1198
+ },
1199
+ {
1200
+ "value": "positive",
1201
+ "type": "string"
1202
+ },
1203
+ {
1204
+ "value": "primary",
1205
+ "type": "string"
1206
+ },
1207
+ {
1208
+ "value": "quaternary",
1209
+ "type": "string"
1210
+ },
1211
+ {
1212
+ "value": "secondary",
1213
+ "type": "string"
1214
+ },
1215
+ {
1216
+ "value": "strong-ai",
1217
+ "type": "string"
1218
+ },
1219
+ {
1220
+ "value": "strong-brand",
1221
+ "type": "string"
1222
+ },
1223
+ {
1224
+ "value": "strong-caution",
1225
+ "type": "string"
1226
+ },
1227
+ {
1228
+ "value": "strong-negative",
1229
+ "type": "string"
1230
+ },
1231
+ {
1232
+ "value": "strong-neutral",
1233
+ "type": "string"
1234
+ },
1235
+ {
1236
+ "value": "strong-positive",
1237
+ "type": "string"
1238
+ },
1239
+ {
1240
+ "value": "strong-warning",
1241
+ "type": "string"
1242
+ },
1243
+ {
1244
+ "value": "tertiary",
1245
+ "type": "string"
1246
+ },
1247
+ {
1248
+ "value": "warning",
1249
+ "type": "string"
1250
+ },
1251
+ {
1252
+ "type": "`var(--${string})`"
1253
+ }
1254
+ ],
1255
+ "optional": false,
1256
+ "required": false,
1257
+ "getter": false,
1258
+ "setter": false
1259
+ },
1052
1260
  {
1053
1261
  "name": "label",
1054
1262
  "type": "string | undefined",
@@ -5724,6 +5932,35 @@
5724
5932
  "docsTags": [],
5725
5933
  "usage": {},
5726
5934
  "props": [
5935
+ {
5936
+ "name": "actionsOpen",
5937
+ "type": "boolean",
5938
+ "complexType": {
5939
+ "original": "boolean",
5940
+ "resolved": "boolean",
5941
+ "references": {}
5942
+ },
5943
+ "mutable": false,
5944
+ "attr": "actions-open",
5945
+ "reflectToAttr": true,
5946
+ "docs": "Keep the contextual-actions surface visible while its popup is open or closing.",
5947
+ "docsTags": [
5948
+ {
5949
+ "name": "default",
5950
+ "text": "false"
5951
+ }
5952
+ ],
5953
+ "default": "false",
5954
+ "values": [
5955
+ {
5956
+ "type": "boolean"
5957
+ }
5958
+ ],
5959
+ "optional": false,
5960
+ "required": false,
5961
+ "getter": false,
5962
+ "setter": false
5963
+ },
5727
5964
  {
5728
5965
  "name": "conversationId",
5729
5966
  "type": "string",
@@ -8885,6 +9122,20 @@
8885
9122
  ],
8886
9123
  "methods": [],
8887
9124
  "events": [
9125
+ {
9126
+ "event": "dsAfterClose",
9127
+ "detail": "void",
9128
+ "bubbles": true,
9129
+ "complexType": {
9130
+ "original": "void",
9131
+ "resolved": "void",
9132
+ "references": {}
9133
+ },
9134
+ "cancelable": true,
9135
+ "composed": true,
9136
+ "docs": "Emitted after the popup's exit motion is complete and its rendered content is removed.",
9137
+ "docsTags": []
9138
+ },
8888
9139
  {
8889
9140
  "event": "dsClose",
8890
9141
  "detail": "void",
@@ -10201,6 +10452,35 @@
10201
10452
  "getter": false,
10202
10453
  "setter": false
10203
10454
  },
10455
+ {
10456
+ "name": "accountMenuExpanded",
10457
+ "type": "boolean",
10458
+ "complexType": {
10459
+ "original": "boolean",
10460
+ "resolved": "boolean",
10461
+ "references": {}
10462
+ },
10463
+ "mutable": false,
10464
+ "attr": "account-menu-expanded",
10465
+ "reflectToAttr": false,
10466
+ "docs": "Keep the account-menu trigger visually active while its popup is open or closing.",
10467
+ "docsTags": [
10468
+ {
10469
+ "name": "default",
10470
+ "text": "false"
10471
+ }
10472
+ ],
10473
+ "default": "false",
10474
+ "values": [
10475
+ {
10476
+ "type": "boolean"
10477
+ }
10478
+ ],
10479
+ "optional": false,
10480
+ "required": false,
10481
+ "getter": false,
10482
+ "setter": false
10483
+ },
10204
10484
  {
10205
10485
  "name": "activeId",
10206
10486
  "type": "string",
@@ -19358,6 +19638,16 @@
19358
19638
  }
19359
19639
  ],
19360
19640
  "typeLibrary": {
19641
+ "src/wc/components/Icon/Icon.tsx::IconSize": {
19642
+ "declaration": "export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';",
19643
+ "docstring": "",
19644
+ "path": "src/wc/components/Icon/Icon.tsx"
19645
+ },
19646
+ "src/wc/components/Icon/Icon.tsx::IconColor": {
19647
+ "declaration": "export type IconColor = IconColorToken | `var(--${string})`;",
19648
+ "docstring": "",
19649
+ "path": "src/wc/components/Icon/Icon.tsx"
19650
+ },
19361
19651
  "src/wc/components/Badge/Badge.tsx::BadgeVariant": {
19362
19652
  "declaration": "export type BadgeVariant = 'counter' | 'dot';",
19363
19653
  "docstring": "",
@@ -19503,16 +19793,6 @@
19503
19793
  "docstring": "",
19504
19794
  "path": "src/wc/components/Divider/Divider.tsx"
19505
19795
  },
19506
- "src/wc/components/Icon/Icon.tsx::IconSize": {
19507
- "declaration": "export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';",
19508
- "docstring": "",
19509
- "path": "src/wc/components/Icon/Icon.tsx"
19510
- },
19511
- "src/wc/components/Icon/Icon.tsx::IconColor": {
19512
- "declaration": "export type IconColor = IconColorToken | `var(--${string})`;",
19513
- "docstring": "",
19514
- "path": "src/wc/components/Icon/Icon.tsx"
19515
- },
19516
19796
  "src/wc/components/Input/Input.tsx::InputType": {
19517
19797
  "declaration": "export type InputType = 'text' | 'email' | 'tel' | 'url' | 'search' | 'password';",
19518
19798
  "docstring": "",
@@ -199,7 +199,7 @@
199
199
  "files": [
200
200
  {
201
201
  "path": "src/wc/components/AgentResponse/AgentResponse.css",
202
- "content": ":host {\n display: block;\n width: 100%;\n}\n.agent-response {\n display: grid;\n gap: var(--dimension-space-150);\n min-width: 0;\n width: 100%;\n}\n",
202
+ "content": ":host {\n display: block;\n width: 100%;\n -webkit-user-select: none;\n user-select: none;\n}\n.agent-response {\n display: grid;\n gap: var(--dimension-space-150);\n min-width: 0;\n width: 100%;\n -webkit-user-select: none;\n user-select: none;\n}\n",
203
203
  "type": "registry:ui"
204
204
  },
205
205
  {
@@ -49,6 +49,15 @@
49
49
  "mutable": false,
50
50
  "description": "Canonical IcoMo icon name displayed inside the avatar."
51
51
  },
52
+ "iconColor": {
53
+ "type": "IconColor",
54
+ "resolvedType": "\"ai\" | \"bold-ai\" | \"bold-brand\" | \"bold-caution\" | \"bold-negative\" | \"bold-neutral\" | \"bold-positive\" | \"bold-warning\" | \"brand\" | \"caution\" | \"faint-ai\" | \"faint-brand\" | \"faint-caution\" | \"faint-negative\" | \"faint-neutral\" | \"faint-positive\" | \"faint-warning\" | \"guide\" | \"inherit\" | \"medium-ai\" | \"medium-brand\" | \"medium-caution\" | \"medium-negative\" | \"medium-neutral\" | \"medium-positive\" | \"medium-warning\" | \"negative\" | \"neutral\" | \"on-bold\" | \"on-strong\" | \"positive\" | \"primary\" | \"quaternary\" | \"secondary\" | \"strong-ai\" | \"strong-brand\" | \"strong-caution\" | \"strong-negative\" | \"strong-neutral\" | \"strong-positive\" | \"strong-warning\" | \"tertiary\" | \"warning\" | `var(--${string})`",
55
+ "attribute": "icon-color",
56
+ "default": "'secondary'",
57
+ "required": false,
58
+ "mutable": false,
59
+ "description": "Semantic color for the icon. Use primary to surface unread or current identity state."
60
+ },
52
61
  "label": {
53
62
  "type": "string | undefined",
54
63
  "resolvedType": "string | undefined",
@@ -72,6 +81,15 @@
72
81
  "mutable": false,
73
82
  "description": "Canonical IcoMo icon name displayed inside the avatar."
74
83
  },
84
+ "iconColor": {
85
+ "type": "IconColor",
86
+ "resolvedType": "\"ai\" | \"bold-ai\" | \"bold-brand\" | \"bold-caution\" | \"bold-negative\" | \"bold-neutral\" | \"bold-positive\" | \"bold-warning\" | \"brand\" | \"caution\" | \"faint-ai\" | \"faint-brand\" | \"faint-caution\" | \"faint-negative\" | \"faint-neutral\" | \"faint-positive\" | \"faint-warning\" | \"guide\" | \"inherit\" | \"medium-ai\" | \"medium-brand\" | \"medium-caution\" | \"medium-negative\" | \"medium-neutral\" | \"medium-positive\" | \"medium-warning\" | \"negative\" | \"neutral\" | \"on-bold\" | \"on-strong\" | \"positive\" | \"primary\" | \"quaternary\" | \"secondary\" | \"strong-ai\" | \"strong-brand\" | \"strong-caution\" | \"strong-negative\" | \"strong-neutral\" | \"strong-positive\" | \"strong-warning\" | \"tertiary\" | \"warning\" | `var(--${string})`",
87
+ "attribute": "icon-color",
88
+ "default": "'secondary'",
89
+ "required": false,
90
+ "mutable": false,
91
+ "description": "Semantic color for the icon. Use primary to surface unread or current identity state."
92
+ },
75
93
  "label": {
76
94
  "type": "string | undefined",
77
95
  "resolvedType": "string | undefined",
@@ -129,7 +147,7 @@
129
147
  },
130
148
  {
131
149
  "path": "src/wc/components/Avatar/Avatar.tsx",
132
- "content": "import { Component, h, Host, Prop } from '@stencil/core';\n\n@Component({\n tag: 'ds-avatar',\n styleUrl: 'Avatar.css',\n scoped: true,\n})\nexport class Avatar {\n /** Canonical IcoMo icon name displayed inside the avatar. */\n @Prop() icon: string = '';\n\n /** Optional accessible label. Omit when the surrounding content already conveys the meaning. */\n @Prop() label: string | undefined;\n\n render() {\n return (\n <Host>\n <span\n class=\"avatar\"\n role={this.label ? 'img' : 'presentation'}\n aria-label={this.label}\n aria-hidden={!this.label ? 'true' : undefined}\n >\n <ds-icon name={this.icon} size=\"md\" color=\"secondary\" />\n </span>\n </Host>\n );\n }\n}\n",
150
+ "content": "import { Component, h, Host, Prop } from '@stencil/core';\nimport type { IconColor } from '../Icon/Icon';\n\n@Component({\n tag: 'ds-avatar',\n styleUrl: 'Avatar.css',\n scoped: true,\n})\nexport class Avatar {\n /** Canonical IcoMo icon name displayed inside the avatar. */\n @Prop() icon: string = '';\n\n /** Semantic color for the icon. Use primary to surface unread or current identity state. */\n @Prop() iconColor: IconColor = 'secondary';\n\n /** Optional accessible label. Omit when the surrounding content already conveys the meaning. */\n @Prop() label: string | undefined;\n\n render() {\n return (\n <Host>\n <span\n class=\"avatar\"\n role={this.label ? 'img' : 'presentation'}\n aria-label={this.label}\n aria-hidden={!this.label ? 'true' : undefined}\n >\n <ds-icon name={this.icon} size=\"md\" color={this.iconColor} />\n </span>\n </Host>\n );\n }\n}\n",
133
151
  "type": "registry:ui"
134
152
  }
135
153
  ]
@@ -319,7 +319,7 @@
319
319
  },
320
320
  {
321
321
  "path": "src/wc/components/BarNav/BarNav.tsx",
322
- "content": "import {\n Component,\n Prop,\n Event,\n EventEmitter,\n Element,\n Watch,\n State,\n h,\n Host,\n} from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport type { MenuItemData } from '../Menu/menu-types';\nimport { getSelectableTabs, isTabDivider, type TabItemTab } from '../TabGroup/tab-item-utils';\nimport type { BarNavTab } from './bar-nav-types';\nimport {\n deriveBarNavValueFromUrl,\n parseJsonArrayProp,\n shouldResyncBarNavProps,\n} from './bar-nav-utils';\nimport {\n tabsOverflowContainer,\n tabsToOverflowMenuSections,\n trimTrailingDividers,\n visibleTabCountForWidth,\n} from './bar-nav-tabs-menu-utils';\nimport {\n CHROME_TRANSITION_END,\n CHROME_TRANSITION_START,\n ChromeTransitionGate,\n createRafCoalescer,\n readChromeTransitionSource,\n readChromeTransitionPhase,\n} from '../../shell/chrome-transition';\n\n@Component({\n tag: 'ds-bar-nav',\n styleUrl: 'BarNav.css',\n scoped: true,\n})\nexport class BarNav {\n /** Style slot: `dashboard` or `settings`. Colors match for now. */\n @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';\n\n @Element() el!: HTMLElement;\n\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 * 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 /** 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 @Prop() moreTabsLabel: string = 'More tabs';\n\n /** Emitted when the active tab changes. Detail = tab id. */\n @Event() dsTabChange!: EventEmitter<string>;\n\n @State() private resolvedTabs: BarNavTab[] = [];\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 @State() private visibleTabs: BarNavTab[] = [];\n @State() private overflowTabs: BarNavTab[] = [];\n @State() private menuInitialFocusVisible = false;\n @State() private overflowRovingFocused = false;\n @State() private focusedTabId = '';\n\n private static readonly HOST_PROP_SYNC_BUDGET = 8;\n private static readonly INTRINSIC_WIDTH_RETRY_MAX = 3;\n private static readonly TAB_LAYOUT_COMMIT_MAX_FRAMES = 16;\n private static readonly OVERFLOW_HYSTERESIS_PX = 8;\n\n private headerEl: HTMLElement | null = null;\n private triggerEl: (HTMLElement & { setFocus?: () => Promise<void> }) | null = null;\n private menuEl: HTMLDsMenuElement | null = null;\n private visibleTabListEl: HTMLElement | null = null;\n private probeTabListEl: HTMLElement | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private intrinsicWidthRetryCount = 0;\n private tabLayoutPendingFrames = 0;\n private readonly panelNavTransition = new ChromeTransitionGate();\n private readonly panelToolsTransition = new ChromeTransitionGate();\n private readonly overflowCoalescer = createRafCoalescer(() => {\n this.updateTabsCollapsed();\n });\n private chromeTransitionShell: HTMLElement | null = null;\n /** Matches `basePath` once tabs + URL are reconciled for the active section. */\n @State() private committedSection = '';\n /** Section waiting for URL + tabs to catch up after a cross-area navigation. */\n @State() private pendingSection = '';\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 renderedSelectableTabs(): TabItemTab[] {\n const tabs = this.hasOverflowTabs ? this.visibleTabs : this.resolvedTabs;\n return getSelectableTabs(tabs);\n }\n\n private get hasOverflowTabs(): boolean {\n return this.tabLayoutCommitted && this.tabsCollapsed && this.overflowTabs.length > 0;\n }\n\n private syncFocusedTabId(preferred: string, tabs: TabItemTab[]) {\n if (tabs.some(tab => tab.id === preferred && !tab.isInactive)) {\n this.focusedTabId = preferred;\n return;\n }\n const first = tabs.find(tab => !tab.isInactive);\n this.focusedTabId = first?.id ?? '';\n }\n\n private digestTabsConfig(tabs: BarNavTab[]): string {\n return tabs.map(t => (isTabDivider(t) ? '|' : t.id)).join(',');\n }\n\n private resetTabOverflowLayout() {\n this.tabLayoutCommitted = false;\n this.tabsCollapsed = false;\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.visibleTabs = [];\n this.overflowTabs = [];\n }\n\n @Watch('tabs')\n @Watch('tabsJson')\n @Watch('currentUrl')\n @Watch('basePath')\n onHostPropsChange() {\n this.applyHostProps();\n }\n\n @Watch('value')\n @Watch('urlDerivedValue')\n onSelectionChange() {\n this.syncFocusedTabId(this.effectiveValue, this.renderedSelectableTabs);\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.menuInitialFocusVisible = false;\n this.menuEl = null;\n }\n this.scheduleOverflowCheck();\n if (collapsed) {\n requestAnimationFrame(() => {\n this.scheduleOverflowCheck();\n });\n }\n if (collapsed || prevCollapsed === undefined || prevCollapsed === collapsed) return;\n requestAnimationFrame(() => this.scheduleOverflowCheck());\n queueMicrotask(() => this.focusVisibleSelectedTab());\n }\n\n componentWillLoad() {\n this.applyHostProps();\n this.syncFocusedTabId(this.effectiveValue, getSelectableTabs(this.resolvedTabs));\n }\n\n componentDidLoad() {\n this.syncHostPropsIfNeeded();\n this.scheduleDeferredHostPropSync();\n this.setupOverflowObserver();\n this.bindChromeTransitionListeners();\n this.scheduleOverflowCheck();\n }\n\n componentDidRender() {\n if (this.chromeOverflowPaused()) {\n this.syncMenuAnchor();\n return;\n }\n this.scheduleOverflowCheck();\n this.syncMenuAnchor();\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.overflowCoalescer.cancel();\n this.unbindChromeTransitionListeners();\n }\n\n private bindChromeTransitionListeners() {\n const shell = this.el.closest('ds-app-shell');\n if (!shell) return;\n this.chromeTransitionShell = shell;\n shell.addEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n shell.addEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n }\n\n private unbindChromeTransitionListeners() {\n if (!this.chromeTransitionShell) return;\n this.chromeTransitionShell.removeEventListener(\n CHROME_TRANSITION_START,\n this.onChromeTransitionStart,\n );\n this.chromeTransitionShell.removeEventListener(\n CHROME_TRANSITION_END,\n this.onChromeTransitionEnd,\n );\n this.chromeTransitionShell = null;\n }\n\n private onChromeTransitionStart = (event: Event) => {\n const source = readChromeTransitionSource(event);\n if (source === 'panel-nav') {\n this.panelNavTransition.enter();\n return;\n }\n if (source === 'panel-tools') {\n const phase = readChromeTransitionPhase(event) ?? 'opening';\n if (phase === 'closing') {\n this.panelToolsTransition.enter();\n }\n }\n };\n\n private chromeOverflowPaused(): boolean {\n return this.panelNavTransition.isActive || this.panelToolsTransition.isActive;\n }\n\n private onChromeTransitionEnd = (event: Event) => {\n const source = readChromeTransitionSource(event);\n if (source === 'panel-nav') {\n this.panelNavTransition.exit();\n if (!this.panelNavTransition.isActive) {\n this.scheduleOverflowCheck();\n }\n return;\n }\n if (source === 'panel-tools') {\n this.panelToolsTransition.exit();\n this.scheduleOverflowCheck();\n }\n };\n\n /** Re-resolve props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */\n private syncHostPropsIfNeeded() {\n if (shouldResyncBarNavProps(this.resolvedTabs, this.tabs, this.tabsJson)) {\n this.applyHostProps();\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.headerEl) return;\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => {\n if (this.chromeOverflowPaused()) return;\n this.scheduleOverflowCheck();\n });\n this.resizeObserver.observe(this.headerEl);\n }\n\n private scheduleOverflowCheck() {\n if (this.chromeOverflowPaused()) return;\n this.overflowCoalescer.schedule();\n }\n\n /** Width available for the tab row or collapsed trigger. */\n private getLeftZoneAvailableWidth(): number {\n if (!this.headerEl) return 0;\n\n const headerStyle = getComputedStyle(this.headerEl);\n const horizontalPadding =\n (parseFloat(headerStyle.paddingLeft) || 0) + (parseFloat(headerStyle.paddingRight) || 0);\n\n return Math.max(0, this.headerEl.clientWidth - horizontalPadding);\n }\n\n private getTabsIntrinsicWidth(): number {\n return this.probeTabListEl?.scrollWidth ?? 0;\n }\n\n private getHeaderGap(): number {\n if (!this.headerEl) return 0;\n const style = getComputedStyle(this.headerEl);\n return parseFloat(style.columnGap || style.gap) || 0;\n }\n\n private getOverflowTriggerReserveWidth(): number {\n if (!this.triggerEl) {\n return 40;\n }\n return this.triggerEl.getBoundingClientRect().width + this.getHeaderGap();\n }\n\n private getProbeTabMetrics():\n | {\n itemWidths: number[];\n itemGap: number;\n listExtraWidth: number;\n }\n | null {\n const tabList = this.probeTabListEl;\n if (!tabList) return null;\n\n const children = Array.from(tabList.children) as HTMLElement[];\n const itemWidths = children.map(child => child.getBoundingClientRect().width);\n if (itemWidths.length === 0 || itemWidths.some(width => width === 0)) return null;\n\n const style = getComputedStyle(tabList);\n const itemGap = parseFloat(style.columnGap || style.gap) || 0;\n const childrenWidth = itemWidths.reduce((sum, width) => sum + width, 0);\n const gapWidth = itemGap * Math.max(0, itemWidths.length - 1);\n const listExtraWidth = Math.max(0, tabList.scrollWidth - childrenWidth - gapWidth);\n\n return { itemWidths, itemGap, listExtraWidth };\n }\n\n private setOverflowTabLayout(visibleTabs: BarNavTab[], overflowTabs: BarNavTab[]) {\n const nextCollapsed = overflowTabs.length > 0;\n const visibleChanged =\n this.digestTabsConfig(visibleTabs) !== this.digestTabsConfig(this.visibleTabs);\n const overflowChanged =\n this.digestTabsConfig(overflowTabs) !== this.digestTabsConfig(this.overflowTabs);\n\n if (visibleChanged) {\n this.visibleTabs = visibleTabs;\n }\n if (overflowChanged) {\n this.overflowTabs = overflowTabs;\n }\n if (nextCollapsed !== this.tabsCollapsed) {\n this.tabsCollapsed = nextCollapsed;\n if (!nextCollapsed) {\n this.menuOpen = false;\n }\n }\n this.syncFocusedTabId(\n this.effectiveValue,\n getSelectableTabs(nextCollapsed ? visibleTabs : this.resolvedTabs),\n );\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 forceTabLayoutCommit(fallbackCollapsed: boolean) {\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.setOverflowTabLayout(\n fallbackCollapsed ? [] : this.resolvedTabs,\n fallbackCollapsed ? this.resolvedTabs : [],\n );\n this.tabLayoutCommitted = true;\n }\n\n private updateTabsCollapsed() {\n if (!this.headerEl || this.resolvedTabs.length === 0 || this.hideTabsForDetailRoute) {\n if (this.tabsCollapsed) {\n this.setOverflowTabLayout([], []);\n }\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.tabLayoutCommitted = true;\n return;\n }\n\n const metrics = this.getProbeTabMetrics();\n const intrinsicWidth = this.getTabsIntrinsicWidth();\n if (!metrics || intrinsicWidth === 0) {\n this.tabLayoutPendingFrames += 1;\n if (this.intrinsicWidthRetryCount >= BarNav.INTRINSIC_WIDTH_RETRY_MAX) {\n this.forceTabLayoutCommit(false);\n } else if (this.tabLayoutPendingFrames >= BarNav.TAB_LAYOUT_COMMIT_MAX_FRAMES) {\n this.forceTabLayoutCommit(false);\n } else {\n this.scheduleIntrinsicWidthRetry();\n }\n return;\n }\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n\n const shouldCollapse = tabsOverflowContainer(\n intrinsicWidth,\n this.getLeftZoneAvailableWidth(),\n this.tabsCollapsed,\n BarNav.OVERFLOW_HYSTERESIS_PX,\n );\n\n if (!shouldCollapse) {\n this.setOverflowTabLayout(this.resolvedTabs, []);\n this.tabLayoutCommitted = true;\n return;\n }\n\n const visibleCount = visibleTabCountForWidth(\n metrics.itemWidths,\n this.getLeftZoneAvailableWidth(),\n this.getOverflowTriggerReserveWidth(),\n metrics.itemGap,\n metrics.listExtraWidth,\n );\n const visibleTabs = trimTrailingDividers(this.resolvedTabs.slice(0, visibleCount));\n const overflowTabs = this.resolvedTabs.slice(visibleTabs.length);\n this.setOverflowTabLayout(visibleTabs, overflowTabs);\n this.tabLayoutCommitted = true;\n }\n\n private syncMenuAnchor() {\n if (!this.menuEl || !this.triggerEl || !this.hasOverflowTabs) 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 this.menuInitialFocusVisible = false;\n }\n\n private handleMenuClose() {\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n }\n\n /** Batch tabs/basePath/currentUrl updates so URL derivation never runs with a mixed section. */\n private incomingTabs(): BarNavTab[] {\n return this.tabsJson\n ? parseJsonArrayProp(this.tabsJson, [])\n : (this.tabs ?? []);\n }\n\n private applyHostProps() {\n const nextBasePath = this.basePath;\n const sectionChanged =\n nextBasePath !== '' &&\n this.committedSection !== '' &&\n nextBasePath !== this.committedSection;\n\n if (sectionChanged) {\n this.urlDerivedValue = '';\n this.committedSection = '';\n this.pendingSection = nextBasePath;\n this.resolvedTabs = [];\n this.resetTabOverflowLayout();\n return;\n }\n\n if (this.pendingSection) {\n if (!nextBasePath || nextBasePath !== this.pendingSection) {\n return;\n }\n if (!this.currentUrl.startsWith(this.pendingSection)) {\n return;\n }\n const tabs = this.incomingTabs();\n if (tabs.length === 0) {\n return;\n }\n this.pendingSection = '';\n }\n\n const tabs = this.incomingTabs();\n const tabsConfigChanged =\n this.digestTabsConfig(tabs) !== this.digestTabsConfig(this.resolvedTabs);\n\n this.resolvedTabs = tabs;\n this.syncValueFromUrl();\n this.committedSection = nextBasePath;\n if (tabsConfigChanged) {\n this.resetTabOverflowLayout();\n }\n this.scheduleOverflowCheck();\n }\n\n private syncMenuSections() {\n if (!this.menuEl) return;\n this.menuEl.sections = tabsToOverflowMenuSections(this.overflowTabs, this.effectiveValue);\n }\n\n private syncValueFromUrl() {\n const tabs = this.incomingTabs();\n\n if (!this.currentUrl || !this.basePath) {\n this.urlDerivedValue = '';\n this.hideTabsForDetailRoute = false;\n return;\n }\n\n if (!this.currentUrl.startsWith(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 tabs,\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 = this.visibleTabListEl?.querySelector(\n `[data-tab-id=\"${this.effectiveValue}\"]`,\n ) as HTMLElement | null;\n tab?.focus({ preventScroll: true });\n }\n\n private focusVisibleTab(id: string) {\n this.focusedTabId = id;\n const tab = this.visibleTabListEl?.querySelector(\n `[data-tab-id=\"${id}\"]`,\n ) as HTMLElement | null;\n tab?.focus({ preventScroll: true });\n }\n\n private focusLastVisibleTab() {\n const last = [...this.renderedSelectableTabs].reverse().find(tab => !tab.isInactive);\n if (last) this.focusVisibleTab(last.id);\n }\n\n private findEnabledVisibleTab(from: number, step: 1 | -1): number | null {\n const tabs = this.renderedSelectableTabs;\n for (let index = from + step; index >= 0 && index < tabs.length; index += step) {\n if (!tabs[index]?.isInactive) return index;\n }\n return null;\n }\n\n private handleTabKeyDown(e: KeyboardEvent) {\n const tabs = this.renderedSelectableTabs;\n if (!tabs.length) return;\n const targetId = (e.target as HTMLElement | null)?.getAttribute('data-tab-id');\n const focusedId = targetId ?? this.focusedTabId;\n\n if (e.key === 'Enter' || e.key === ' ') {\n const focused = tabs.find(tab => tab.id === focusedId);\n if (!focused || focused.isInactive) return;\n e.preventDefault();\n this.selectTab(focused.id);\n return;\n }\n\n const currentIndex = tabs.findIndex(tab => tab.id === focusedId);\n if (currentIndex < 0) return;\n\n let nextIndex: number | null;\n if (e.key === 'ArrowRight') {\n nextIndex = this.findEnabledVisibleTab(currentIndex, 1);\n if (nextIndex === null && this.hasOverflowTabs) {\n e.preventDefault();\n this.overflowRovingFocused = true;\n void this.triggerEl?.setFocus?.();\n return;\n }\n } else if (e.key === 'ArrowLeft') {\n nextIndex = this.findEnabledVisibleTab(currentIndex, -1);\n } else if (e.key === 'Home') {\n nextIndex = tabs.findIndex(tab => !tab.isInactive);\n } else if (e.key === 'End') {\n const reversedIndex = [...tabs].reverse().findIndex(tab => !tab.isInactive);\n nextIndex = reversedIndex < 0 ? null : tabs.length - 1 - reversedIndex;\n } else {\n return;\n }\n\n if (nextIndex === null || nextIndex < 0 || nextIndex === currentIndex) return;\n e.preventDefault();\n this.focusVisibleTab(tabs[nextIndex].id);\n }\n\n private toggleTabMenu(options?: { focusVisible?: boolean }) {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n return;\n }\n\n if (this.menuEl && this.triggerEl) {\n this.menuEl.anchor = this.triggerEl;\n this.menuEl.minWidth = '';\n this.syncMenuSections();\n }\n\n this.menuInitialFocusVisible = options?.focusVisible ?? false;\n this.menuOpen = true;\n }\n\n private handleOverflowFocus = () => {\n this.overflowRovingFocused = true;\n };\n\n private handleOverflowBlur = () => {\n this.overflowRovingFocused = false;\n };\n\n private handleTriggerKeyDown(e: KeyboardEvent) {\n if (!this.hasOverflowTabs) return;\n\n if (!this.menuOpen) {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n this.overflowRovingFocused = false;\n this.focusLastVisibleTab();\n return;\n }\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.toggleTabMenu({ focusVisible: true });\n }\n return;\n }\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n void this.triggerEl?.setFocus?.();\n }\n }\n\n private renderTabList(tabs: BarNavTab[], probe: boolean) {\n return (\n <div\n role=\"tablist\"\n class=\"bar-nav__tab-list\"\n aria-label={this.heading}\n ref={el => {\n if (probe) {\n const next = (el as HTMLElement) ?? null;\n if (next === this.probeTabListEl) return;\n this.probeTabListEl = next;\n if (next) {\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.scheduleOverflowCheck();\n }\n } else {\n this.visibleTabListEl = (el as HTMLElement) ?? null;\n }\n }}\n onKeyDown={probe ? undefined : (e: KeyboardEvent) => this.handleTabKeyDown(e)}\n onFocusin={probe ? undefined : () => {\n this.overflowRovingFocused = false;\n }}\n >\n {tabs.map((tab, index) => {\n if (isTabDivider(tab)) {\n return (\n <div class=\"bar-nav__tab-divider\" key={`divider-${index}`} aria-hidden=\"true\">\n <div class=\"bar-nav__tab-divider-line\" />\n </div>\n );\n }\n\n const isSelected = tab.id === this.effectiveValue;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n data-tab-id={tab.id}\n class={{\n 'bar-nav__tab': true,\n 'bar-nav__tab--selected': isSelected,\n 'ds-control--md': true,\n 'ds-focus-ring-inset': true,\n 'ds-control-inactive': !!tab.isInactive,\n }}\n aria-selected={isSelected ? 'true' : 'false'}\n aria-disabled={tab.isInactive ? 'true' : undefined}\n aria-controls={tab.panelId ?? undefined}\n disabled={tab.isInactive}\n tabIndex={\n !probe && !this.overflowRovingFocused && tab.id === this.focusedTabId\n ? 0\n : -1\n }\n onClick={() => !probe && !tab.isInactive && this.selectTab(tab.id)}\n onFocus={() => {\n if (!probe) this.focusedTabId = tab.id;\n }}\n >\n <span\n class={{\n 'bar-nav__tab-label': true,\n 'bar-nav__tab-label--dot': !!tab.dot,\n }}\n >\n <ds-text as=\"span\" variant=\"text-body-medium\" emphasis={isSelected} color=\"inherit\">\n {tab.label}\n </ds-text>\n {tab.dot && (\n <ds-badge\n class=\"bar-nav__tab-dot\"\n variant=\"dot\"\n hasRing={false}\n label=\"\"\n aria-hidden=\"true\"\n />\n )}\n </span>\n </button>\n );\n })}\n </div>\n );\n }\n\n render() {\n // Section gating only applies when `basePath` is set (SPA section sync).\n // Tabs without a base path must still render — otherwise a single-tab bar\n // (or any non-routed tabs) silently falls through to an empty header.\n const sectionReady =\n this.basePath === '' || this.committedSection === this.basePath;\n const hasTabs =\n sectionReady && this.resolvedTabs.length > 0 && !this.hideTabsForDetailRoute;\n const tabGroupKey = this.basePath || 'no-section';\n const renderedTabs = this.hasOverflowTabs ? this.visibleTabs : this.resolvedTabs;\n\n return (\n <Host>\n <header\n class={{\n 'bar-nav': true,\n 'ds-control--md': true,\n 'bar-nav--dashboard': this.navStyle === 'dashboard',\n 'bar-nav--settings': this.navStyle === 'settings',\n 'bar-nav--tabs-collapsed':\n hasTabs && this.hasOverflowTabs,\n }}\n ref={el => {\n this.headerEl = 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 <div key={`probe-${tabGroupKey}`}>\n {this.renderTabList(this.resolvedTabs, true)}\n </div>\n </div>\n )}\n\n {hasTabs && this.tabLayoutCommitted && renderedTabs.length > 0 && (\n <div class=\"bar-nav__left\">\n <div key={`visible-${tabGroupKey}`} class=\"bar-nav__tabs-visible\">\n {this.renderTabList(renderedTabs, false)}\n </div>\n </div>\n )}\n\n {hasTabs && !this.tabLayoutCommitted && (\n <div class=\"bar-nav__tabs-pending\" aria-hidden=\"true\" />\n )}\n\n {!hasTabs && this.heading && (\n <ds-text\n class=\"bar-nav__heading\"\n as=\"span\"\n variant=\"text-body-medium\"\n emphasis\n color=\"primary\"\n wrap=\"nowrap\"\n >\n {this.heading}\n </ds-text>\n )}\n\n {hasTabs && this.hasOverflowTabs && (\n <ds-button-unfilled variant=\"icon\"\n class={{\n 'bar-nav__overflow-trigger': true,\n }}\n icon=\"Ellipses\"\n isActive={this.menuOpen}\n activeFill={false}\n hasBorder={false}\n focusTabIndex={this.overflowRovingFocused ? 0 : -1}\n ref={(el?: HTMLDsButtonUnfilledElement) => {\n this.triggerEl = (el as (HTMLElement & { setFocus?: () => Promise<void> })) ?? null;\n }}\n haspopup=\"menu\"\n expanded={this.menuOpen}\n aria-label={this.moreTabsLabel}\n onDsClick={() => this.toggleTabMenu({ focusVisible: false })}\n onFocusin={this.handleOverflowFocus}\n onFocusout={this.handleOverflowBlur}\n onKeyDown={(e: KeyboardEvent) => this.handleTriggerKeyDown(e)}\n />\n )}\n\n </header>\n\n {hasTabs && this.hasOverflowTabs && (\n <ds-menu\n ref={el => {\n this.menuEl = (el as HTMLDsMenuElement) ?? null;\n }}\n open={this.menuOpen}\n sections={tabsToOverflowMenuSections(this.overflowTabs, this.effectiveValue)}\n side=\"bottom\"\n align=\"end\"\n sideOffset=\"calc(var(--dimension-space-100) + var(--dimension-space-050))\"\n initialFocusVisible={this.menuInitialFocusVisible}\n onDsSelect={(e: Event) => this.handleMenuSelect(e)}\n onDsClose={() => this.handleMenuClose()}\n />\n )}\n </Host>\n );\n }\n}\n",
322
+ "content": "import {\n Component,\n Prop,\n Event,\n EventEmitter,\n Element,\n Watch,\n State,\n h,\n Host,\n} from '@stencil/core';\nimport type { NavChromeStyle } from '../../shell/nav-chrome';\nimport type { MenuItemData } from '../Menu/menu-types';\nimport { getSelectableTabs, isTabDivider, type TabItemTab } from '../TabGroup/tab-item-utils';\nimport type { BarNavTab } from './bar-nav-types';\nimport {\n deriveBarNavValueFromUrl,\n parseJsonArrayProp,\n shouldResyncBarNavProps,\n} from './bar-nav-utils';\nimport {\n tabsOverflowContainer,\n tabsToOverflowMenuSections,\n trimTrailingDividers,\n visibleTabCountForWidth,\n} from './bar-nav-tabs-menu-utils';\nimport {\n CHROME_TRANSITION_END,\n CHROME_TRANSITION_START,\n ChromeTransitionGate,\n createRafCoalescer,\n readChromeTransitionSource,\n readChromeTransitionPhase,\n} from '../../shell/chrome-transition';\n\n@Component({\n tag: 'ds-bar-nav',\n styleUrl: 'BarNav.css',\n scoped: true,\n})\nexport class BarNav {\n /** Style slot: `dashboard` or `settings`. Colors match for now. */\n @Prop({ attribute: 'nav-style', reflect: true }) navStyle: NavChromeStyle = 'dashboard';\n\n @Element() el!: HTMLElement;\n\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 * 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 /** 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 @Prop() moreTabsLabel: string = 'More tabs';\n\n /** Emitted when the active tab changes. Detail = tab id. */\n @Event() dsTabChange!: EventEmitter<string>;\n\n @State() private resolvedTabs: BarNavTab[] = [];\n @State() private urlDerivedValue: string = '';\n @State() private hideTabsForDetailRoute = false;\n @State() private tabsCollapsed = false;\n @State() private menuOpen = false;\n @State() private menuTriggerActive = 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 @State() private visibleTabs: BarNavTab[] = [];\n @State() private overflowTabs: BarNavTab[] = [];\n @State() private menuInitialFocusVisible = false;\n @State() private overflowRovingFocused = false;\n @State() private focusedTabId = '';\n\n private static readonly HOST_PROP_SYNC_BUDGET = 8;\n private static readonly INTRINSIC_WIDTH_RETRY_MAX = 3;\n private static readonly TAB_LAYOUT_COMMIT_MAX_FRAMES = 16;\n private static readonly OVERFLOW_HYSTERESIS_PX = 8;\n\n private headerEl: HTMLElement | null = null;\n private triggerEl: (HTMLElement & { setFocus?: () => Promise<void> }) | null = null;\n private menuEl: HTMLDsMenuElement | null = null;\n private visibleTabListEl: HTMLElement | null = null;\n private probeTabListEl: HTMLElement | null = null;\n private resizeObserver: ResizeObserver | null = null;\n private intrinsicWidthRetryCount = 0;\n private tabLayoutPendingFrames = 0;\n private readonly panelNavTransition = new ChromeTransitionGate();\n private readonly panelToolsTransition = new ChromeTransitionGate();\n private readonly overflowCoalescer = createRafCoalescer(() => {\n this.updateTabsCollapsed();\n });\n private chromeTransitionShell: HTMLElement | null = null;\n /** Matches `basePath` once tabs + URL are reconciled for the active section. */\n @State() private committedSection = '';\n /** Section waiting for URL + tabs to catch up after a cross-area navigation. */\n @State() private pendingSection = '';\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 renderedSelectableTabs(): TabItemTab[] {\n const tabs = this.hasOverflowTabs ? this.visibleTabs : this.resolvedTabs;\n return getSelectableTabs(tabs);\n }\n\n private get hasOverflowTabs(): boolean {\n return this.tabLayoutCommitted && this.tabsCollapsed && this.overflowTabs.length > 0;\n }\n\n private syncFocusedTabId(preferred: string, tabs: TabItemTab[]) {\n if (tabs.some(tab => tab.id === preferred && !tab.isInactive)) {\n this.focusedTabId = preferred;\n return;\n }\n const first = tabs.find(tab => !tab.isInactive);\n this.focusedTabId = first?.id ?? '';\n }\n\n private digestTabsConfig(tabs: BarNavTab[]): string {\n return tabs.map(t => (isTabDivider(t) ? '|' : t.id)).join(',');\n }\n\n private resetTabOverflowLayout() {\n this.tabLayoutCommitted = false;\n this.tabsCollapsed = false;\n this.menuOpen = false;\n this.menuTriggerActive = false;\n this.menuInitialFocusVisible = false;\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.visibleTabs = [];\n this.overflowTabs = [];\n }\n\n @Watch('tabs')\n @Watch('tabsJson')\n @Watch('currentUrl')\n @Watch('basePath')\n onHostPropsChange() {\n this.applyHostProps();\n }\n\n @Watch('value')\n @Watch('urlDerivedValue')\n onSelectionChange() {\n this.syncFocusedTabId(this.effectiveValue, this.renderedSelectableTabs);\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.menuTriggerActive = false;\n this.menuInitialFocusVisible = false;\n this.menuEl = null;\n }\n this.scheduleOverflowCheck();\n if (collapsed) {\n requestAnimationFrame(() => {\n this.scheduleOverflowCheck();\n });\n }\n if (collapsed || prevCollapsed === undefined || prevCollapsed === collapsed) return;\n requestAnimationFrame(() => this.scheduleOverflowCheck());\n queueMicrotask(() => this.focusVisibleSelectedTab());\n }\n\n componentWillLoad() {\n this.applyHostProps();\n this.syncFocusedTabId(this.effectiveValue, getSelectableTabs(this.resolvedTabs));\n }\n\n componentDidLoad() {\n this.syncHostPropsIfNeeded();\n this.scheduleDeferredHostPropSync();\n this.setupOverflowObserver();\n this.bindChromeTransitionListeners();\n this.scheduleOverflowCheck();\n }\n\n componentDidRender() {\n if (this.chromeOverflowPaused()) {\n this.syncMenuAnchor();\n return;\n }\n this.scheduleOverflowCheck();\n this.syncMenuAnchor();\n }\n\n disconnectedCallback() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.overflowCoalescer.cancel();\n this.unbindChromeTransitionListeners();\n }\n\n private bindChromeTransitionListeners() {\n const shell = this.el.closest('ds-app-shell');\n if (!shell) return;\n this.chromeTransitionShell = shell;\n shell.addEventListener(CHROME_TRANSITION_START, this.onChromeTransitionStart);\n shell.addEventListener(CHROME_TRANSITION_END, this.onChromeTransitionEnd);\n }\n\n private unbindChromeTransitionListeners() {\n if (!this.chromeTransitionShell) return;\n this.chromeTransitionShell.removeEventListener(\n CHROME_TRANSITION_START,\n this.onChromeTransitionStart,\n );\n this.chromeTransitionShell.removeEventListener(\n CHROME_TRANSITION_END,\n this.onChromeTransitionEnd,\n );\n this.chromeTransitionShell = null;\n }\n\n private onChromeTransitionStart = (event: Event) => {\n const source = readChromeTransitionSource(event);\n if (source === 'panel-nav') {\n this.panelNavTransition.enter();\n return;\n }\n if (source === 'panel-tools') {\n const phase = readChromeTransitionPhase(event) ?? 'opening';\n if (phase === 'closing') {\n this.panelToolsTransition.enter();\n }\n }\n };\n\n private chromeOverflowPaused(): boolean {\n return this.panelNavTransition.isActive || this.panelToolsTransition.isActive;\n }\n\n private onChromeTransitionEnd = (event: Event) => {\n const source = readChromeTransitionSource(event);\n if (source === 'panel-nav') {\n this.panelNavTransition.exit();\n if (!this.panelNavTransition.isActive) {\n this.scheduleOverflowCheck();\n }\n return;\n }\n if (source === 'panel-tools') {\n this.panelToolsTransition.exit();\n this.scheduleOverflowCheck();\n }\n };\n\n /** Re-resolve props assigned by the host after componentWillLoad (Angular ngAfterViewInit). */\n private syncHostPropsIfNeeded() {\n if (shouldResyncBarNavProps(this.resolvedTabs, this.tabs, this.tabsJson)) {\n this.applyHostProps();\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.headerEl) return;\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => {\n if (this.chromeOverflowPaused()) return;\n this.scheduleOverflowCheck();\n });\n this.resizeObserver.observe(this.headerEl);\n }\n\n private scheduleOverflowCheck() {\n if (this.chromeOverflowPaused()) return;\n this.overflowCoalescer.schedule();\n }\n\n /** Width available for the tab row or collapsed trigger. */\n private getLeftZoneAvailableWidth(): number {\n if (!this.headerEl) return 0;\n\n const headerStyle = getComputedStyle(this.headerEl);\n const horizontalPadding =\n (parseFloat(headerStyle.paddingLeft) || 0) + (parseFloat(headerStyle.paddingRight) || 0);\n\n return Math.max(0, this.headerEl.clientWidth - horizontalPadding);\n }\n\n private getTabsIntrinsicWidth(): number {\n return this.probeTabListEl?.scrollWidth ?? 0;\n }\n\n private getHeaderGap(): number {\n if (!this.headerEl) return 0;\n const style = getComputedStyle(this.headerEl);\n return parseFloat(style.columnGap || style.gap) || 0;\n }\n\n private getOverflowTriggerReserveWidth(): number {\n if (!this.triggerEl) {\n return 40;\n }\n return this.triggerEl.getBoundingClientRect().width + this.getHeaderGap();\n }\n\n private getProbeTabMetrics():\n | {\n itemWidths: number[];\n itemGap: number;\n listExtraWidth: number;\n }\n | null {\n const tabList = this.probeTabListEl;\n if (!tabList) return null;\n\n const children = Array.from(tabList.children) as HTMLElement[];\n const itemWidths = children.map(child => child.getBoundingClientRect().width);\n if (itemWidths.length === 0 || itemWidths.some(width => width === 0)) return null;\n\n const style = getComputedStyle(tabList);\n const itemGap = parseFloat(style.columnGap || style.gap) || 0;\n const childrenWidth = itemWidths.reduce((sum, width) => sum + width, 0);\n const gapWidth = itemGap * Math.max(0, itemWidths.length - 1);\n const listExtraWidth = Math.max(0, tabList.scrollWidth - childrenWidth - gapWidth);\n\n return { itemWidths, itemGap, listExtraWidth };\n }\n\n private setOverflowTabLayout(visibleTabs: BarNavTab[], overflowTabs: BarNavTab[]) {\n const nextCollapsed = overflowTabs.length > 0;\n const visibleChanged =\n this.digestTabsConfig(visibleTabs) !== this.digestTabsConfig(this.visibleTabs);\n const overflowChanged =\n this.digestTabsConfig(overflowTabs) !== this.digestTabsConfig(this.overflowTabs);\n\n if (visibleChanged) {\n this.visibleTabs = visibleTabs;\n }\n if (overflowChanged) {\n this.overflowTabs = overflowTabs;\n }\n if (nextCollapsed !== this.tabsCollapsed) {\n this.tabsCollapsed = nextCollapsed;\n if (!nextCollapsed) {\n this.menuOpen = false;\n this.menuTriggerActive = false;\n }\n }\n this.syncFocusedTabId(\n this.effectiveValue,\n getSelectableTabs(nextCollapsed ? visibleTabs : this.resolvedTabs),\n );\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 forceTabLayoutCommit(fallbackCollapsed: boolean) {\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.setOverflowTabLayout(\n fallbackCollapsed ? [] : this.resolvedTabs,\n fallbackCollapsed ? this.resolvedTabs : [],\n );\n this.tabLayoutCommitted = true;\n }\n\n private updateTabsCollapsed() {\n if (!this.headerEl || this.resolvedTabs.length === 0 || this.hideTabsForDetailRoute) {\n if (this.tabsCollapsed) {\n this.setOverflowTabLayout([], []);\n }\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.tabLayoutCommitted = true;\n return;\n }\n\n const metrics = this.getProbeTabMetrics();\n const intrinsicWidth = this.getTabsIntrinsicWidth();\n if (!metrics || intrinsicWidth === 0) {\n this.tabLayoutPendingFrames += 1;\n if (this.intrinsicWidthRetryCount >= BarNav.INTRINSIC_WIDTH_RETRY_MAX) {\n this.forceTabLayoutCommit(false);\n } else if (this.tabLayoutPendingFrames >= BarNav.TAB_LAYOUT_COMMIT_MAX_FRAMES) {\n this.forceTabLayoutCommit(false);\n } else {\n this.scheduleIntrinsicWidthRetry();\n }\n return;\n }\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n\n const shouldCollapse = tabsOverflowContainer(\n intrinsicWidth,\n this.getLeftZoneAvailableWidth(),\n this.tabsCollapsed,\n BarNav.OVERFLOW_HYSTERESIS_PX,\n );\n\n if (!shouldCollapse) {\n this.setOverflowTabLayout(this.resolvedTabs, []);\n this.tabLayoutCommitted = true;\n return;\n }\n\n const visibleCount = visibleTabCountForWidth(\n metrics.itemWidths,\n this.getLeftZoneAvailableWidth(),\n this.getOverflowTriggerReserveWidth(),\n metrics.itemGap,\n metrics.listExtraWidth,\n );\n const visibleTabs = trimTrailingDividers(this.resolvedTabs.slice(0, visibleCount));\n const overflowTabs = this.resolvedTabs.slice(visibleTabs.length);\n this.setOverflowTabLayout(visibleTabs, overflowTabs);\n this.tabLayoutCommitted = true;\n }\n\n private syncMenuAnchor() {\n if (!this.menuEl || !this.triggerEl || !this.hasOverflowTabs) 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 this.menuInitialFocusVisible = false;\n }\n\n private handleMenuClose() {\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n }\n\n private handleMenuAfterClose() {\n if (!this.menuOpen) this.menuTriggerActive = false;\n }\n\n /** Batch tabs/basePath/currentUrl updates so URL derivation never runs with a mixed section. */\n private incomingTabs(): BarNavTab[] {\n return this.tabsJson\n ? parseJsonArrayProp(this.tabsJson, [])\n : (this.tabs ?? []);\n }\n\n private applyHostProps() {\n const nextBasePath = this.basePath;\n const sectionChanged =\n nextBasePath !== '' &&\n this.committedSection !== '' &&\n nextBasePath !== this.committedSection;\n\n if (sectionChanged) {\n this.urlDerivedValue = '';\n this.committedSection = '';\n this.pendingSection = nextBasePath;\n this.resolvedTabs = [];\n this.resetTabOverflowLayout();\n return;\n }\n\n if (this.pendingSection) {\n if (!nextBasePath || nextBasePath !== this.pendingSection) {\n return;\n }\n if (!this.currentUrl.startsWith(this.pendingSection)) {\n return;\n }\n const tabs = this.incomingTabs();\n if (tabs.length === 0) {\n return;\n }\n this.pendingSection = '';\n }\n\n const tabs = this.incomingTabs();\n const tabsConfigChanged =\n this.digestTabsConfig(tabs) !== this.digestTabsConfig(this.resolvedTabs);\n\n this.resolvedTabs = tabs;\n this.syncValueFromUrl();\n this.committedSection = nextBasePath;\n if (tabsConfigChanged) {\n this.resetTabOverflowLayout();\n }\n this.scheduleOverflowCheck();\n }\n\n private syncMenuSections() {\n if (!this.menuEl) return;\n this.menuEl.sections = tabsToOverflowMenuSections(this.overflowTabs, this.effectiveValue);\n }\n\n private syncValueFromUrl() {\n const tabs = this.incomingTabs();\n\n if (!this.currentUrl || !this.basePath) {\n this.urlDerivedValue = '';\n this.hideTabsForDetailRoute = false;\n return;\n }\n\n if (!this.currentUrl.startsWith(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 tabs,\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 = this.visibleTabListEl?.querySelector(\n `[data-tab-id=\"${this.effectiveValue}\"]`,\n ) as HTMLElement | null;\n tab?.focus({ preventScroll: true });\n }\n\n private focusVisibleTab(id: string) {\n this.focusedTabId = id;\n const tab = this.visibleTabListEl?.querySelector(\n `[data-tab-id=\"${id}\"]`,\n ) as HTMLElement | null;\n tab?.focus({ preventScroll: true });\n }\n\n private focusLastVisibleTab() {\n const last = [...this.renderedSelectableTabs].reverse().find(tab => !tab.isInactive);\n if (last) this.focusVisibleTab(last.id);\n }\n\n private findEnabledVisibleTab(from: number, step: 1 | -1): number | null {\n const tabs = this.renderedSelectableTabs;\n for (let index = from + step; index >= 0 && index < tabs.length; index += step) {\n if (!tabs[index]?.isInactive) return index;\n }\n return null;\n }\n\n private handleTabKeyDown(e: KeyboardEvent) {\n const tabs = this.renderedSelectableTabs;\n if (!tabs.length) return;\n const targetId = (e.target as HTMLElement | null)?.getAttribute('data-tab-id');\n const focusedId = targetId ?? this.focusedTabId;\n\n if (e.key === 'Enter' || e.key === ' ') {\n const focused = tabs.find(tab => tab.id === focusedId);\n if (!focused || focused.isInactive) return;\n e.preventDefault();\n this.selectTab(focused.id);\n return;\n }\n\n const currentIndex = tabs.findIndex(tab => tab.id === focusedId);\n if (currentIndex < 0) return;\n\n let nextIndex: number | null;\n if (e.key === 'ArrowRight') {\n nextIndex = this.findEnabledVisibleTab(currentIndex, 1);\n if (nextIndex === null && this.hasOverflowTabs) {\n e.preventDefault();\n this.overflowRovingFocused = true;\n void this.triggerEl?.setFocus?.();\n return;\n }\n } else if (e.key === 'ArrowLeft') {\n nextIndex = this.findEnabledVisibleTab(currentIndex, -1);\n } else if (e.key === 'Home') {\n nextIndex = tabs.findIndex(tab => !tab.isInactive);\n } else if (e.key === 'End') {\n const reversedIndex = [...tabs].reverse().findIndex(tab => !tab.isInactive);\n nextIndex = reversedIndex < 0 ? null : tabs.length - 1 - reversedIndex;\n } else {\n return;\n }\n\n if (nextIndex === null || nextIndex < 0 || nextIndex === currentIndex) return;\n e.preventDefault();\n this.focusVisibleTab(tabs[nextIndex].id);\n }\n\n private toggleTabMenu(options?: { focusVisible?: boolean }) {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n return;\n }\n\n if (this.menuEl && this.triggerEl) {\n this.menuEl.anchor = this.triggerEl;\n this.menuEl.minWidth = '';\n this.syncMenuSections();\n }\n\n this.menuInitialFocusVisible = options?.focusVisible ?? false;\n this.menuTriggerActive = true;\n this.menuOpen = true;\n }\n\n private handleOverflowFocus = () => {\n this.overflowRovingFocused = true;\n };\n\n private handleOverflowBlur = () => {\n this.overflowRovingFocused = false;\n };\n\n private handleTriggerKeyDown(e: KeyboardEvent) {\n if (!this.hasOverflowTabs) return;\n\n if (!this.menuOpen) {\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n this.overflowRovingFocused = false;\n this.focusLastVisibleTab();\n return;\n }\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.toggleTabMenu({ focusVisible: true });\n }\n return;\n }\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.menuOpen = false;\n this.menuInitialFocusVisible = false;\n void this.triggerEl?.setFocus?.();\n }\n }\n\n private renderTabList(tabs: BarNavTab[], probe: boolean) {\n return (\n <div\n role=\"tablist\"\n class=\"bar-nav__tab-list\"\n aria-label={this.heading}\n ref={el => {\n if (probe) {\n const next = (el as HTMLElement) ?? null;\n if (next === this.probeTabListEl) return;\n this.probeTabListEl = next;\n if (next) {\n this.intrinsicWidthRetryCount = 0;\n this.tabLayoutPendingFrames = 0;\n this.scheduleOverflowCheck();\n }\n } else {\n this.visibleTabListEl = (el as HTMLElement) ?? null;\n }\n }}\n onKeyDown={probe ? undefined : (e: KeyboardEvent) => this.handleTabKeyDown(e)}\n onFocusin={probe ? undefined : () => {\n this.overflowRovingFocused = false;\n }}\n >\n {tabs.map((tab, index) => {\n if (isTabDivider(tab)) {\n return (\n <div class=\"bar-nav__tab-divider\" key={`divider-${index}`} aria-hidden=\"true\">\n <div class=\"bar-nav__tab-divider-line\" />\n </div>\n );\n }\n\n const isSelected = tab.id === this.effectiveValue;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n data-tab-id={tab.id}\n class={{\n 'bar-nav__tab': true,\n 'bar-nav__tab--selected': isSelected,\n 'ds-control--md': true,\n 'ds-focus-ring-inset': true,\n 'ds-control-inactive': !!tab.isInactive,\n }}\n aria-selected={isSelected ? 'true' : 'false'}\n aria-disabled={tab.isInactive ? 'true' : undefined}\n aria-controls={tab.panelId ?? undefined}\n disabled={tab.isInactive}\n tabIndex={\n !probe && !this.overflowRovingFocused && tab.id === this.focusedTabId\n ? 0\n : -1\n }\n onClick={() => !probe && !tab.isInactive && this.selectTab(tab.id)}\n onFocus={() => {\n if (!probe) this.focusedTabId = tab.id;\n }}\n >\n <span\n class={{\n 'bar-nav__tab-label': true,\n 'bar-nav__tab-label--dot': !!tab.dot,\n }}\n >\n <ds-text as=\"span\" variant=\"text-body-medium\" emphasis={isSelected} color=\"inherit\">\n {tab.label}\n </ds-text>\n {tab.dot && (\n <ds-badge\n class=\"bar-nav__tab-dot\"\n variant=\"dot\"\n hasRing={false}\n label=\"\"\n aria-hidden=\"true\"\n />\n )}\n </span>\n </button>\n );\n })}\n </div>\n );\n }\n\n render() {\n // Section gating only applies when `basePath` is set (SPA section sync).\n // Tabs without a base path must still render — otherwise a single-tab bar\n // (or any non-routed tabs) silently falls through to an empty header.\n const sectionReady =\n this.basePath === '' || this.committedSection === this.basePath;\n const hasTabs =\n sectionReady && this.resolvedTabs.length > 0 && !this.hideTabsForDetailRoute;\n const tabGroupKey = this.basePath || 'no-section';\n const renderedTabs = this.hasOverflowTabs ? this.visibleTabs : this.resolvedTabs;\n\n return (\n <Host>\n <header\n class={{\n 'bar-nav': true,\n 'ds-control--md': true,\n 'bar-nav--dashboard': this.navStyle === 'dashboard',\n 'bar-nav--settings': this.navStyle === 'settings',\n 'bar-nav--tabs-collapsed':\n hasTabs && this.hasOverflowTabs,\n }}\n ref={el => {\n this.headerEl = 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 <div key={`probe-${tabGroupKey}`}>\n {this.renderTabList(this.resolvedTabs, true)}\n </div>\n </div>\n )}\n\n {hasTabs && this.tabLayoutCommitted && renderedTabs.length > 0 && (\n <div class=\"bar-nav__left\">\n <div key={`visible-${tabGroupKey}`} class=\"bar-nav__tabs-visible\">\n {this.renderTabList(renderedTabs, false)}\n </div>\n </div>\n )}\n\n {hasTabs && !this.tabLayoutCommitted && (\n <div class=\"bar-nav__tabs-pending\" aria-hidden=\"true\" />\n )}\n\n {!hasTabs && this.heading && (\n <ds-text\n class=\"bar-nav__heading\"\n as=\"span\"\n variant=\"text-body-medium\"\n emphasis\n color=\"primary\"\n wrap=\"nowrap\"\n >\n {this.heading}\n </ds-text>\n )}\n\n {hasTabs && this.hasOverflowTabs && (\n <ds-button-unfilled variant=\"icon\"\n class={{\n 'bar-nav__overflow-trigger': true,\n }}\n icon=\"Ellipses\"\n activeFill={false}\n hasBorder={false}\n focusTabIndex={this.overflowRovingFocused ? 0 : -1}\n ref={(el?: HTMLDsButtonUnfilledElement) => {\n this.triggerEl = (el as (HTMLElement & { setFocus?: () => Promise<void> })) ?? null;\n }}\n haspopup=\"menu\"\n expanded={this.menuTriggerActive}\n aria-label={this.moreTabsLabel}\n onDsClick={() => this.toggleTabMenu({ focusVisible: false })}\n onFocusin={this.handleOverflowFocus}\n onFocusout={this.handleOverflowBlur}\n onKeyDown={(e: KeyboardEvent) => this.handleTriggerKeyDown(e)}\n />\n )}\n\n </header>\n\n {hasTabs && this.hasOverflowTabs && (\n <ds-menu\n ref={el => {\n this.menuEl = (el as HTMLDsMenuElement) ?? null;\n }}\n open={this.menuOpen}\n sections={tabsToOverflowMenuSections(this.overflowTabs, this.effectiveValue)}\n side=\"bottom\"\n align=\"end\"\n sideOffset=\"calc(var(--dimension-space-100) + var(--dimension-space-050))\"\n initialFocusVisible={this.menuInitialFocusVisible}\n onDsSelect={(e: Event) => this.handleMenuSelect(e)}\n onDsClose={() => this.handleMenuClose()}\n onDsAfterClose={() => this.handleMenuAfterClose()}\n />\n )}\n </Host>\n );\n }\n}\n",
323
323
  "type": "registry:ui"
324
324
  },
325
325
  {