@ds-mo/ui 4.1.0 → 4.1.2

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 (46) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/agent.json +1 -1
  3. package/dist/components/ds-banner.js +1 -1
  4. package/dist/components/ds-bar-nav.js +1 -1
  5. package/dist/components/ds-button-filled.js +1 -1
  6. package/dist/components/ds-button-unfilled.js +1 -1
  7. package/dist/components/ds-card-data-viz-donut.js +1 -1
  8. package/dist/components/ds-card-setting.js +1 -1
  9. package/dist/components/ds-chart-legend.js +1 -1
  10. package/dist/components/ds-chart-legend.js.map +1 -1
  11. package/dist/components/ds-chip.js +1 -1
  12. package/dist/components/ds-chip.js.map +1 -1
  13. package/dist/components/ds-menu.js +1 -1
  14. package/dist/components/ds-modal.js +1 -1
  15. package/dist/components/ds-panel-nav.js +1 -1
  16. package/dist/components/ds-panel-nav.js.map +1 -1
  17. package/dist/components/ds-panel-tools.js +1 -1
  18. package/dist/components/ds-select.js +1 -1
  19. package/dist/components/ds-select.js.map +1 -1
  20. package/dist/components/ds-tag.js +1 -1
  21. package/dist/components/ds-tag.js.map +1 -1
  22. package/dist/components/ds-tooltip-data-viz.js +1 -1
  23. package/dist/components/ds-tooltip-data-viz.js.map +1 -1
  24. package/dist/components/ds-tooltip.js +1 -1
  25. package/dist/components/p-B2J0Kelv.js +2 -0
  26. package/dist/components/{p-DO7y9eZQ.js.map → p-B2J0Kelv.js.map} +1 -1
  27. package/dist/components/p-B_72yZ43.js +2 -0
  28. package/dist/components/{p-D7SoZNpD.js.map → p-B_72yZ43.js.map} +1 -1
  29. package/dist/components/{p-C1cBr-Ri.js → p-BvmooLHV.js} +2 -2
  30. package/dist/components/p-C2gX0ggG.js +2 -0
  31. package/dist/components/{p-CvjQuj6A.js.map → p-C2gX0ggG.js.map} +1 -1
  32. package/dist/components/p-DLcnbk3Z.js +2 -0
  33. package/dist/components/{p-BzIYKUGO.js.map → p-DLcnbk3Z.js.map} +1 -1
  34. package/dist/docs/components.json +1 -1
  35. package/dist/lib/utils/index.js +8 -6
  36. package/dist/lib/utils/index.js.map +2 -2
  37. package/dist/lib/utils/scroll-edge-fade.d.ts +7 -2
  38. package/dist/types/components/PanelNav/PanelNav.d.ts +3 -1
  39. package/dist/types/components/PanelNav/panel-nav-utils.d.ts +10 -0
  40. package/dist/types/utils/scroll-edge-fade.d.ts +7 -2
  41. package/package.json +1 -1
  42. package/dist/components/p-BzIYKUGO.js +0 -2
  43. package/dist/components/p-CvjQuj6A.js +0 -2
  44. package/dist/components/p-D7SoZNpD.js +0 -2
  45. package/dist/components/p-DO7y9eZQ.js +0 -2
  46. /package/dist/components/{p-C1cBr-Ri.js.map → p-BvmooLHV.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"names":["MODIFIER_GLYPHS","Set","MODIFIER_LABELS","alt","cmd","command","control","ctrl","option","shift","canonicalKeyLabel","label","toLowerCase","shortcutKeyLabels","shortcut","normalized","trim","includes","split","map","part","filter","Boolean","test","characters","Array","from","labels","length","has","push","join","tooltipCss","FALLBACK_HEIGHT","md","TOKEN_DEFAULTS","size400","sm","size300","xs","size200","lastDismissedAt","tooltipIdCounter","activeTooltip","createDsText","opts","el","document","createElement","as","variant","emphasis","color","wrap","textContent","text","styleTooltipLabel","style","flexShrink","minWidth","maxWidth","padding","Tooltip","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","size","side","align","sideOffset","TOKEN_CSS_LENGTHS","space050","alignOffset","delay","animationDelayMedium3","shortcutKeyPosition","tooltipId","delayTimer","closeTimer","anchor","popupEl","positionObserver","skipEnterAnimation","isOpen","mouseEnterHandler","show","mouseLeaveHandler","hide","focusHandler","blurHandler","e","next","relatedTarget","contains","componentDidLoad","bindAnchor","disconnectedCallback","unbindAnchor","clearTimers","destroyPopup","onContentOrPositionChange","hideInstant","renderPopupContent","schedulePosition","viewportPadPx","resolveCssLengthPx","sideOffsetPx","alignOffsetPx","hoverDelayMs","resolveCssTimeMs","instantReopenMs","animationDurationMedium1","fadeOutMs","motionShort3","animationDurationShort3","tooltipFallbackWidthPx","tooltipFallbackWidth","tooltipFallbackHeightPx","token","slot","querySelector","slotted","assignedElements","child","firstElementChild","setAttribute","addEventListener","removeAttribute","removeEventListener","clearTimeout","disconnect","remove","reapplyLabelStyles","requestAnimationFrame","calculatePosition","ResizeObserver","observe","Date","now","instant","mountPopup","setTimeout","classList","add","tip","id","className","Object","assign","position","left","top","zIndex","pointerEvents","body","appendChild","toggle","textVariant","CONTROL_TEXT_VARIANT","density","sc","inner","appendShortcut","shortcutKey","group","hint","wide","replaceChildren","a","getBoundingClientRect","tw","offsetWidth","th","offsetHeight","vpPad","x","y","right","width","bottom","height","nextX","Math","min","max","window","innerWidth","nextY","innerHeight","transform","round","render","h","Host","key","display"],"sources":["src/wc/utils/shortcut-key.ts","src/wc/components/Tooltip/Tooltip.css?tag=ds-tooltip&encapsulation=scoped","src/wc/components/Tooltip/Tooltip.tsx"],"sourcesContent":["const MODIFIER_GLYPHS = new Set(['⌘', '⇧', '⌥', '⌃']);\nconst MODIFIER_LABELS: Readonly<Record<string, string>> = {\n alt: '⌥',\n cmd: '⌘',\n command: '⌘',\n control: '⌃',\n ctrl: '⌃',\n option: '⌥',\n shift: '⇧',\n};\n\nfunction canonicalKeyLabel(label: string): string {\n return MODIFIER_LABELS[label.toLowerCase()] ?? label;\n}\n\n/** Split a shortcut chord into the labels rendered on individual keycaps. */\nexport function shortcutKeyLabels(shortcut: string): string[] {\n const normalized = shortcut.trim();\n if (!normalized) return [];\n\n if (normalized.includes('+')) {\n return normalized.split('+').map(part => part.trim()).filter(Boolean).map(canonicalKeyLabel);\n }\n\n if (/\\s/.test(normalized)) {\n return normalized.split(/\\s+/).filter(Boolean).map(canonicalKeyLabel);\n }\n\n const characters = Array.from(normalized);\n const labels: string[] = [];\n while (characters.length > 1 && MODIFIER_GLYPHS.has(characters[0])) {\n labels.push(characters.shift()!);\n }\n labels.push(characters.join(''));\n return labels;\n}\n","@import '../../utils/control-density.css';\n@import '../../utils/key-hint.css';\n\n.tooltip-popup {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n box-shadow: var(--effect-elevation-elevated-floating);\n white-space: nowrap;\n pointer-events: none;\n animation: tooltipFadeIn var(--effect-motion-short-2) forwards;\n will-change: transform;\n backface-visibility: hidden;\n}\n\n/* Warm handoff between nearby triggers — no enter fade (avoids 20–100ms lag). */\n.tooltip-popup--instant {\n animation: none;\n opacity: 1;\n}\n\n.tooltip-popup--closing {\n animation: tooltipFadeOut var(--effect-motion-short-3) forwards;\n}\n\n/* Density: md / sm / xs via `.ds-control--*` on `.tooltip-inner`. */\n.tooltip-inner {\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n display: flex;\n align-items: center;\n gap: var(--ds-control-gap, var(--dimension-space-050));\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n}\n\n/*\n * Label layout lives on ds-text (metric-box + control label-inset).\n * NOTE: Stencil scopes this to `ds-text.sc-ds-tooltip`, but portaled\n * createElement ds-text loses that class when Text's <Host class> renders.\n * `renderPopupContent` therefore also sets these as inline styles.\n */\n.tooltip-inner > ds-text {\n flex-shrink: 0;\n min-width: max-content;\n max-width: none;\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n color: var(--color-foreground-primary);\n}\n\n@keyframes tooltipFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes tooltipFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n","import { Component, Prop, Element, Watch, h, Host } from '@stencil/core';\nimport {\n CONTROL_TEXT_VARIANT,\n resolveCssLengthPx,\n resolveCssTimeMs,\n TOKEN_CSS_LENGTHS,\n TOKEN_DEFAULTS,\n} from '../../utils';\nimport type { TextVariant } from '../Text/text-types';\nimport { shortcutKeyLabels } from '../../utils/shortcut-key';\n// Side-effect: register `ds-text` — the portal builds it via createElement, not JSX.\nimport '../Text/Text';\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\nexport type TooltipAlign = 'start' | 'center' | 'end';\nexport type TooltipSize = 'md' | 'sm' | 'xs';\n\nconst FALLBACK_HEIGHT: Record<TooltipSize, string> = {\n md: TOKEN_DEFAULTS.size400,\n sm: TOKEN_DEFAULTS.size300,\n xs: TOKEN_DEFAULTS.size200,\n};\n\nlet lastDismissedAt = 0;\nlet tooltipIdCounter = 0;\n/** Currently open tooltip — force-cleared on warm handoff so tips don't cross-fade. */\nlet activeTooltip: Tooltip | null = null;\n\ntype DsTextEl = HTMLElement & {\n as: string;\n variant: TextVariant;\n emphasis: boolean;\n color: string;\n wrap: string;\n};\n\nfunction createDsText(opts: {\n variant: TextVariant;\n emphasis?: boolean;\n color?: string;\n wrap?: 'wrap' | 'nowrap' | 'balance' | 'pretty';\n text: string;\n}): DsTextEl {\n const el = document.createElement('ds-text') as DsTextEl;\n el.as = 'span';\n el.variant = opts.variant;\n el.emphasis = opts.emphasis ?? false;\n el.color = opts.color ?? 'inherit';\n if (opts.wrap) el.wrap = opts.wrap;\n el.textContent = opts.text;\n return el;\n}\n\n/**\n * Control-density label styles for portaled ds-text.\n * Scoped CSS requires `sc-ds-tooltip` on the host, but Text's `<Host class>`\n * overwrites imperative className — so these must be inline to stick.\n */\nfunction styleTooltipLabel(el: HTMLElement) {\n el.style.flexShrink = '0';\n el.style.minWidth = 'max-content';\n el.style.maxWidth = 'none';\n el.style.padding = '0 var(--ds-control-label-inset, var(--dimension-space-025))';\n el.style.color = 'var(--color-foreground-primary)';\n}\n\n/**\n * Imperative body portal for the popup.\n * Stencil must not own the portaled node — moving a VDOM child to `document.body`\n * causes recreate → re-portal → @State loops that freeze the page.\n */\n@Component({\n tag: 'ds-tooltip',\n styleUrl: 'Tooltip.css',\n scoped: true,\n})\nexport class Tooltip {\n @Element() el!: HTMLElement;\n\n /**\n * Tooltip text. Empty/whitespace skips show — useful when the wrapper must stay\n * mounted for layout/animation stability (e.g. PanelNav expand/collapse).\n */\n @Prop() label!: string;\n\n /** Control density (height, padding, type). */\n @Prop() size: TooltipSize = 'md';\n\n @Prop() side: TooltipSide = 'top';\n @Prop() align: TooltipAlign = 'center';\n /** Gap between anchor and tooltip — number (px) or TokoMo length. */\n @Prop() sideOffset: number | string = TOKEN_CSS_LENGTHS.space050;\n /** Cross-axis offset — number (px) or TokoMo length. */\n @Prop() alignOffset: number | string = 0;\n /**\n * Hover show delay before the tooltip appears.\n * Default: `--effect-animation-delay-medium-3` (1000ms). Accepts a number (ms)\n * or a TokoMo time token / `var(--effect-animation-delay-*)`. Applies to the\n * initial hover/focus show only — after a recent dismiss, reopen is instant.\n * Prefer the default; override only for denser chrome or rare/destructive actions.\n */\n @Prop() delay: number | string = TOKEN_DEFAULTS.animationDelayMedium3;\n @Prop() shortcutKey: string | undefined;\n @Prop() shortcutKeyPosition: 'start' | 'end' = 'end';\n\n private tooltipId = `ds-tooltip-${++tooltipIdCounter}`;\n private delayTimer: ReturnType<typeof setTimeout> | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private anchor: HTMLElement | null = null;\n private popupEl: HTMLElement | null = null;\n private positionObserver: ResizeObserver | null = null;\n private skipEnterAnimation = false;\n private isOpen = false;\n private mouseEnterHandler: () => void = () => this.show();\n private mouseLeaveHandler: () => void = () => this.hide();\n /** focusin/focusout so nested focus targets (e.g. ds-button-* inner button) still open the tip. */\n private focusHandler: () => void = () => this.show();\n private blurHandler: (e: FocusEvent) => void = (e) => {\n const next = e.relatedTarget as Node | null;\n if (next && this.anchor?.contains(next)) return;\n this.hide();\n };\n\n componentDidLoad() {\n this.bindAnchor();\n }\n\n disconnectedCallback() {\n if (activeTooltip === this) activeTooltip = null;\n this.unbindAnchor();\n this.clearTimers();\n this.destroyPopup();\n }\n\n @Watch('label')\n @Watch('size')\n @Watch('side')\n @Watch('align')\n @Watch('sideOffset')\n @Watch('alignOffset')\n @Watch('shortcutKey')\n @Watch('shortcutKeyPosition')\n onContentOrPositionChange() {\n if (!this.label?.trim()) {\n if (this.isOpen || this.popupEl) this.hideInstant();\n return;\n }\n if (!this.popupEl || !this.isOpen) return;\n this.renderPopupContent();\n this.schedulePosition();\n }\n\n private get viewportPadPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.space050, TOKEN_DEFAULTS.space050);\n }\n\n private get sideOffsetPx(): number {\n return resolveCssLengthPx(this.sideOffset, TOKEN_DEFAULTS.space050);\n }\n\n private get alignOffsetPx(): number {\n return resolveCssLengthPx(this.alignOffset, 0);\n }\n\n private get hoverDelayMs(): number {\n return resolveCssTimeMs(this.delay, TOKEN_DEFAULTS.animationDelayMedium3);\n }\n\n private get instantReopenMs(): number {\n return resolveCssTimeMs(\n TOKEN_DEFAULTS.animationDurationMedium1,\n TOKEN_DEFAULTS.animationDurationMedium1,\n );\n }\n\n private get fadeOutMs(): number {\n return resolveCssTimeMs(TOKEN_DEFAULTS.motionShort3, TOKEN_DEFAULTS.animationDurationShort3);\n }\n\n private get tooltipFallbackWidthPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.tooltipFallbackWidth, TOKEN_DEFAULTS.tooltipFallbackWidth);\n }\n\n private get tooltipFallbackHeightPx(): number {\n const token = FALLBACK_HEIGHT[this.size];\n return resolveCssLengthPx(token, token);\n }\n\n private bindAnchor() {\n const slot = this.el.querySelector('slot') as HTMLSlotElement | null;\n const slotted = slot?.assignedElements?.() ?? [];\n const child = (slotted[0] ?? this.el.firstElementChild) as HTMLElement | null;\n if (!child) return;\n this.anchor = child;\n child.setAttribute('aria-describedby', this.tooltipId);\n child.addEventListener('mouseenter', this.mouseEnterHandler);\n child.addEventListener('mouseleave', this.mouseLeaveHandler);\n child.addEventListener('focusin', this.focusHandler);\n child.addEventListener('focusout', this.blurHandler);\n }\n\n private unbindAnchor() {\n if (!this.anchor) return;\n this.anchor.removeAttribute('aria-describedby');\n this.anchor.removeEventListener('mouseenter', this.mouseEnterHandler);\n this.anchor.removeEventListener('mouseleave', this.mouseLeaveHandler);\n this.anchor.removeEventListener('focusin', this.focusHandler);\n this.anchor.removeEventListener('focusout', this.blurHandler);\n this.anchor = null;\n }\n\n private clearTimers() {\n if (this.delayTimer) { clearTimeout(this.delayTimer); this.delayTimer = null; }\n if (this.closeTimer) { clearTimeout(this.closeTimer); this.closeTimer = null; }\n }\n\n private destroyPopup() {\n this.positionObserver?.disconnect();\n this.positionObserver = null;\n if (!this.popupEl) return;\n this.popupEl.remove();\n this.popupEl = null;\n }\n\n /**\n * Position after `ds-text` upgrades and lays out. Measuring synchronously in\n * `mountPopup` reads a collapsed/fallback width and places left/right tips wrong.\n */\n private schedulePosition() {\n if (!this.popupEl) return;\n\n const reapplyLabelStyles = () => {\n const label = this.popupEl?.querySelector(':scope > .tooltip-inner > ds-text');\n if (label instanceof HTMLElement) styleTooltipLabel(label);\n };\n\n requestAnimationFrame(() => {\n reapplyLabelStyles();\n this.calculatePosition();\n requestAnimationFrame(() => {\n reapplyLabelStyles();\n this.calculatePosition();\n });\n });\n\n this.positionObserver?.disconnect();\n this.positionObserver = new ResizeObserver(() => this.calculatePosition());\n this.positionObserver.observe(this.popupEl);\n }\n\n /** Drop the open tip immediately (warm handoff to another tooltip). */\n private hideInstant() {\n this.clearTimers();\n lastDismissedAt = Date.now();\n if (activeTooltip === this) activeTooltip = null;\n this.destroyPopup();\n this.isOpen = false;\n this.skipEnterAnimation = false;\n }\n\n private show() {\n // Empty label = wrapper present for DOM stability (e.g. PanelNav expand/collapse)\n // but no tip should appear.\n if (!this.label?.trim()) return;\n this.clearTimers();\n let instant = Date.now() - lastDismissedAt < this.instantReopenMs;\n if (activeTooltip && activeTooltip !== this) {\n activeTooltip.hideInstant();\n instant = true;\n }\n // eslint-disable-next-line @typescript-eslint/no-this-alias -- module singleton tracks the active instance\n activeTooltip = this;\n this.skipEnterAnimation = instant;\n if (instant) {\n this.mountPopup();\n return;\n }\n this.delayTimer = setTimeout(() => {\n this.delayTimer = null;\n if (!this.label?.trim()) return;\n this.mountPopup();\n }, this.hoverDelayMs);\n }\n\n private hide() {\n this.clearTimers();\n if (!this.popupEl && !this.isOpen) return;\n lastDismissedAt = Date.now();\n if (activeTooltip === this) activeTooltip = null;\n if (!this.popupEl) {\n this.isOpen = false;\n return;\n }\n this.popupEl.classList.remove('tooltip-popup--instant');\n this.popupEl.classList.add('tooltip-popup--closing');\n this.closeTimer = setTimeout(() => {\n this.closeTimer = null;\n this.destroyPopup();\n this.isOpen = false;\n this.skipEnterAnimation = false;\n }, this.fadeOutMs);\n }\n\n private mountPopup() {\n if (!this.popupEl) {\n const tip = document.createElement('div');\n tip.id = this.tooltipId;\n tip.setAttribute('role', 'tooltip');\n // `sc-ds-tooltip` is required for Stencil scoped CSS to match outside the host.\n tip.className = 'tooltip-popup sc-ds-tooltip';\n Object.assign(tip.style, {\n position: 'fixed',\n left: '0',\n top: '0',\n zIndex: 'var(--dimension-z-index-tooltip)',\n pointerEvents: 'none',\n });\n document.body.appendChild(tip);\n this.popupEl = tip;\n }\n\n this.popupEl.classList.toggle('tooltip-popup--instant', this.skipEnterAnimation);\n this.popupEl.classList.remove('tooltip-popup--closing');\n this.renderPopupContent();\n this.schedulePosition();\n this.isOpen = true;\n }\n\n private renderPopupContent() {\n if (!this.popupEl) return;\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const density =\n this.size === 'md' ? 'ds-control--md' : this.size === 'sm' ? 'ds-control--sm' : 'ds-control--xs';\n // Every layout node needs `sc-ds-tooltip` so scoped selectors (`.foo.sc-ds-tooltip`) match.\n const sc = 'sc-ds-tooltip';\n\n const inner = document.createElement('div');\n inner.className = `tooltip-inner ${density} ${sc}`;\n\n const appendShortcut = (position: 'start' | 'end') => {\n if (!this.shortcutKey || this.shortcutKeyPosition !== position) return;\n const group = document.createElement('span');\n group.className = `key-hint-group ${sc}`;\n group.setAttribute('aria-hidden', 'true');\n\n for (const label of shortcutKeyLabels(this.shortcutKey)) {\n const hint = document.createElement('span');\n const wide = Array.from(label).length > 1 ? ' key-hint--wide' : '';\n hint.className = `key-hint${wide} ${sc}`;\n const text = document.createElement('span');\n text.className = `key-hint__label ${sc}`;\n text.textContent = label;\n hint.appendChild(text);\n group.appendChild(hint);\n }\n inner.appendChild(group);\n };\n\n appendShortcut('start');\n\n // ds-text is the layout box (metric-box + 2px control label-inset).\n // Inline styles required — see styleTooltipLabel.\n const label = createDsText({ variant: textVariant, wrap: 'nowrap', text: this.label });\n styleTooltipLabel(label);\n inner.appendChild(label);\n\n appendShortcut('end');\n\n this.popupEl.replaceChildren(inner);\n }\n\n private calculatePosition() {\n if (!this.anchor || !this.popupEl) return;\n const tip = this.popupEl;\n const a = this.anchor.getBoundingClientRect();\n const tw = tip.offsetWidth || this.tooltipFallbackWidthPx;\n const th = tip.offsetHeight || this.tooltipFallbackHeightPx;\n const sideOffset = this.sideOffsetPx;\n const alignOffset = this.alignOffsetPx;\n const vpPad = this.viewportPadPx;\n let x = 0, y = 0;\n\n switch (this.side) {\n case 'top':\n y = a.top - th - sideOffset;\n x = this.align === 'start' ? a.left + alignOffset\n : this.align === 'end' ? a.right - tw + alignOffset\n : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'bottom':\n y = a.bottom + sideOffset;\n x = this.align === 'start' ? a.left + alignOffset\n : this.align === 'end' ? a.right - tw + alignOffset\n : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'left':\n x = a.left - tw - sideOffset;\n y = this.align === 'start' ? a.top + alignOffset\n : this.align === 'end' ? a.bottom - th + alignOffset\n : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n case 'right':\n x = a.right + sideOffset;\n y = this.align === 'start' ? a.top + alignOffset\n : this.align === 'end' ? a.bottom - th + alignOffset\n : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n }\n\n const nextX = Math.min(Math.max(x, vpPad), window.innerWidth - tw - vpPad);\n const nextY = Math.min(Math.max(y, vpPad), window.innerHeight - th - vpPad);\n tip.style.transform = `translate(${Math.round(nextX)}px, ${Math.round(nextY)}px)`;\n }\n\n render() {\n return (\n <Host style={{ display: 'contents' }}>\n <slot />\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["MODIFIER_GLYPHS","Set","MODIFIER_LABELS","alt","cmd","command","control","ctrl","option","shift","canonicalKeyLabel","label","toLowerCase","shortcutKeyLabels","shortcut","normalized","trim","includes","split","map","part","filter","Boolean","test","characters","Array","from","labels","length","has","push","join","tooltipCss","FALLBACK_HEIGHT","md","TOKEN_DEFAULTS","size400","sm","size300","xs","size200","lastDismissedAt","tooltipIdCounter","activeTooltip","createDsText","opts","el","document","createElement","as","variant","emphasis","color","wrap","textContent","text","styleTooltipLabel","style","flexShrink","minWidth","maxWidth","padding","Tooltip","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","size","side","align","sideOffset","TOKEN_CSS_LENGTHS","space050","alignOffset","delay","animationDelayMedium3","shortcutKeyPosition","tooltipId","delayTimer","closeTimer","anchor","popupEl","positionObserver","skipEnterAnimation","isOpen","mouseEnterHandler","show","mouseLeaveHandler","hide","focusHandler","blurHandler","e","next","relatedTarget","contains","componentDidLoad","bindAnchor","disconnectedCallback","unbindAnchor","clearTimers","destroyPopup","onContentOrPositionChange","hideInstant","renderPopupContent","schedulePosition","viewportPadPx","resolveCssLengthPx","sideOffsetPx","alignOffsetPx","hoverDelayMs","resolveCssTimeMs","instantReopenMs","animationDurationMedium1","fadeOutMs","motionShort3","animationDurationShort3","tooltipFallbackWidthPx","tooltipFallbackWidth","tooltipFallbackHeightPx","token","slot","querySelector","slotted","assignedElements","child","firstElementChild","setAttribute","addEventListener","removeAttribute","removeEventListener","clearTimeout","disconnect","remove","reapplyLabelStyles","requestAnimationFrame","calculatePosition","ResizeObserver","observe","Date","now","instant","mountPopup","setTimeout","classList","add","tip","id","className","Object","assign","position","left","top","zIndex","pointerEvents","body","appendChild","toggle","textVariant","CONTROL_TEXT_VARIANT","density","sc","inner","appendShortcut","shortcutKey","group","hint","wide","replaceChildren","a","getBoundingClientRect","tw","offsetWidth","th","offsetHeight","vpPad","x","y","right","width","bottom","height","nextX","Math","min","max","window","innerWidth","nextY","innerHeight","transform","round","render","h","Host","key","display"],"sources":["src/wc/utils/shortcut-key.ts","src/wc/components/Tooltip/Tooltip.css?tag=ds-tooltip&encapsulation=scoped","src/wc/components/Tooltip/Tooltip.tsx"],"sourcesContent":["const MODIFIER_GLYPHS = new Set(['⌘', '⇧', '⌥', '⌃']);\nconst MODIFIER_LABELS: Readonly<Record<string, string>> = {\n alt: '⌥',\n cmd: '⌘',\n command: '⌘',\n control: '⌃',\n ctrl: '⌃',\n option: '⌥',\n shift: '⇧',\n};\n\nfunction canonicalKeyLabel(label: string): string {\n return MODIFIER_LABELS[label.toLowerCase()] ?? label;\n}\n\n/** Split a shortcut chord into the labels rendered on individual keycaps. */\nexport function shortcutKeyLabels(shortcut: string): string[] {\n const normalized = shortcut.trim();\n if (!normalized) return [];\n\n if (normalized.includes('+')) {\n return normalized.split('+').map(part => part.trim()).filter(Boolean).map(canonicalKeyLabel);\n }\n\n if (/\\s/.test(normalized)) {\n return normalized.split(/\\s+/).filter(Boolean).map(canonicalKeyLabel);\n }\n\n const characters = Array.from(normalized);\n const labels: string[] = [];\n while (characters.length > 1 && MODIFIER_GLYPHS.has(characters[0])) {\n labels.push(characters.shift()!);\n }\n labels.push(characters.join(''));\n return labels;\n}\n","@import '../../utils/control-density.css';\n@import '../../utils/key-hint.css';\n\n.tooltip-popup {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n box-shadow: var(--effect-elevation-elevated-floating);\n white-space: nowrap;\n pointer-events: none;\n animation: tooltipFadeIn var(--effect-motion-short-2) forwards;\n will-change: transform;\n backface-visibility: hidden;\n}\n\n/* Warm handoff between nearby triggers — no enter fade (avoids 20–100ms lag). */\n.tooltip-popup--instant {\n animation: none;\n opacity: 1;\n}\n\n.tooltip-popup--closing {\n animation: tooltipFadeOut var(--effect-motion-short-3) forwards;\n}\n\n/* Density: md / sm / xs via `.ds-control--*` on `.tooltip-inner`. */\n.tooltip-inner {\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n display: flex;\n align-items: center;\n gap: var(--ds-control-gap, var(--dimension-space-050));\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n}\n\n/*\n * Label layout lives on ds-text (metric-box + control label-inset).\n * NOTE: Stencil scopes this to `ds-text.sc-ds-tooltip`, but portaled\n * createElement ds-text loses that class when Text's <Host class> renders.\n * `renderPopupContent` therefore also sets these as inline styles.\n */\n.tooltip-inner > ds-text {\n flex-shrink: 0;\n min-width: max-content;\n max-width: none;\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n color: var(--color-foreground-primary);\n}\n\n@keyframes tooltipFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes tooltipFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n","import { Component, Prop, Element, Watch, h, Host } from '@stencil/core';\nimport {\n CONTROL_TEXT_VARIANT,\n resolveCssLengthPx,\n resolveCssTimeMs,\n TOKEN_CSS_LENGTHS,\n TOKEN_DEFAULTS,\n} from '../../utils';\nimport type { TextVariant } from '../Text/text-types';\nimport { shortcutKeyLabels } from '../../utils/shortcut-key';\n// Side-effect: register `ds-text` — the portal builds it via createElement, not JSX.\nimport '../Text/Text';\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\nexport type TooltipAlign = 'start' | 'center' | 'end';\nexport type TooltipSize = 'md' | 'sm' | 'xs';\n\nconst FALLBACK_HEIGHT: Record<TooltipSize, string> = {\n md: TOKEN_DEFAULTS.size400,\n sm: TOKEN_DEFAULTS.size300,\n xs: TOKEN_DEFAULTS.size200,\n};\n\nlet lastDismissedAt = 0;\nlet tooltipIdCounter = 0;\n/** Currently open tooltip — force-cleared on warm handoff so tips don't cross-fade. */\nlet activeTooltip: Tooltip | null = null;\n\ntype DsTextEl = HTMLElement & {\n as: string;\n variant: TextVariant;\n emphasis: boolean;\n color: string;\n wrap: string;\n};\n\nfunction createDsText(opts: {\n variant: TextVariant;\n emphasis?: boolean;\n color?: string;\n wrap?: 'wrap' | 'nowrap' | 'balance' | 'pretty';\n text: string;\n}): DsTextEl {\n const el = document.createElement('ds-text') as DsTextEl;\n el.as = 'span';\n el.variant = opts.variant;\n el.emphasis = opts.emphasis ?? false;\n el.color = opts.color ?? 'inherit';\n if (opts.wrap) el.wrap = opts.wrap;\n el.textContent = opts.text;\n return el;\n}\n\n/**\n * Control-density label styles for portaled ds-text.\n * Scoped CSS requires `sc-ds-tooltip` on the host, but Text's `<Host class>`\n * overwrites imperative className — so these must be inline to stick.\n */\nfunction styleTooltipLabel(el: HTMLElement) {\n el.style.flexShrink = '0';\n el.style.minWidth = 'max-content';\n el.style.maxWidth = 'none';\n el.style.padding = '0 var(--ds-control-label-inset, var(--dimension-space-025))';\n el.style.color = 'var(--color-foreground-primary)';\n}\n\n/**\n * Imperative body portal for the popup.\n * Stencil must not own the portaled node — moving a VDOM child to `document.body`\n * causes recreate → re-portal → @State loops that freeze the page.\n */\n@Component({\n tag: 'ds-tooltip',\n styleUrl: 'Tooltip.css',\n scoped: true,\n})\nexport class Tooltip {\n @Element() el!: HTMLElement;\n\n /**\n * Tooltip text. Empty/whitespace skips show — useful when the wrapper must stay\n * mounted for layout/animation stability (e.g. PanelNav expand/collapse).\n */\n @Prop() label!: string;\n\n /** Control density (height, padding, type). */\n @Prop() size: TooltipSize = 'md';\n\n @Prop() side: TooltipSide = 'top';\n @Prop() align: TooltipAlign = 'center';\n /** Gap between anchor and tooltip — number (px) or TokoMo length. */\n @Prop() sideOffset: number | string = TOKEN_CSS_LENGTHS.space050;\n /** Cross-axis offset — number (px) or TokoMo length. */\n @Prop() alignOffset: number | string = 0;\n /**\n * Hover show delay before the tooltip appears.\n * Default: `--effect-animation-delay-medium-3` (1000ms). Accepts a number (ms)\n * or a TokoMo time token / `var(--effect-animation-delay-*)`. Applies to the\n * initial hover/focus show only — after a recent dismiss, reopen is instant.\n * Prefer the default; override only for denser chrome or rare/destructive actions.\n */\n @Prop() delay: number | string = TOKEN_DEFAULTS.animationDelayMedium3;\n @Prop() shortcutKey: string | undefined;\n @Prop() shortcutKeyPosition: 'start' | 'end' = 'end';\n\n private tooltipId = `ds-tooltip-${++tooltipIdCounter}`;\n private delayTimer: ReturnType<typeof setTimeout> | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private anchor: HTMLElement | null = null;\n private popupEl: HTMLElement | null = null;\n private positionObserver: ResizeObserver | null = null;\n private skipEnterAnimation = false;\n private isOpen = false;\n private mouseEnterHandler: () => void = () => this.show();\n private mouseLeaveHandler: () => void = () => this.hide();\n /** focusin/focusout so nested focus targets (e.g. ds-button-* inner button) still open the tip. */\n private focusHandler: () => void = () => this.show();\n private blurHandler: (e: FocusEvent) => void = (e) => {\n const next = e.relatedTarget as Node | null;\n if (next && this.anchor?.contains(next)) return;\n this.hide();\n };\n\n componentDidLoad() {\n this.bindAnchor();\n }\n\n disconnectedCallback() {\n if (activeTooltip === this) activeTooltip = null;\n this.unbindAnchor();\n this.clearTimers();\n this.destroyPopup();\n }\n\n @Watch('label')\n @Watch('size')\n @Watch('side')\n @Watch('align')\n @Watch('sideOffset')\n @Watch('alignOffset')\n @Watch('shortcutKey')\n @Watch('shortcutKeyPosition')\n onContentOrPositionChange() {\n if (!this.label?.trim()) {\n if (this.isOpen || this.popupEl) this.hideInstant();\n return;\n }\n if (!this.popupEl || !this.isOpen) return;\n this.renderPopupContent();\n this.schedulePosition();\n }\n\n private get viewportPadPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.space050, TOKEN_DEFAULTS.space050);\n }\n\n private get sideOffsetPx(): number {\n return resolveCssLengthPx(this.sideOffset, TOKEN_DEFAULTS.space050);\n }\n\n private get alignOffsetPx(): number {\n return resolveCssLengthPx(this.alignOffset, 0);\n }\n\n private get hoverDelayMs(): number {\n return resolveCssTimeMs(this.delay, TOKEN_DEFAULTS.animationDelayMedium3);\n }\n\n private get instantReopenMs(): number {\n return resolveCssTimeMs(\n TOKEN_DEFAULTS.animationDurationMedium1,\n TOKEN_DEFAULTS.animationDurationMedium1,\n );\n }\n\n private get fadeOutMs(): number {\n return resolveCssTimeMs(TOKEN_DEFAULTS.motionShort3, TOKEN_DEFAULTS.animationDurationShort3);\n }\n\n private get tooltipFallbackWidthPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.tooltipFallbackWidth, TOKEN_DEFAULTS.tooltipFallbackWidth);\n }\n\n private get tooltipFallbackHeightPx(): number {\n const token = FALLBACK_HEIGHT[this.size];\n return resolveCssLengthPx(token, token);\n }\n\n private bindAnchor() {\n const slot = this.el.querySelector('slot') as HTMLSlotElement | null;\n const slotted = slot?.assignedElements?.() ?? [];\n const child = (slotted[0] ?? this.el.firstElementChild) as HTMLElement | null;\n if (!child) return;\n this.anchor = child;\n child.setAttribute('aria-describedby', this.tooltipId);\n child.addEventListener('mouseenter', this.mouseEnterHandler);\n child.addEventListener('mouseleave', this.mouseLeaveHandler);\n child.addEventListener('focusin', this.focusHandler);\n child.addEventListener('focusout', this.blurHandler);\n }\n\n private unbindAnchor() {\n if (!this.anchor) return;\n this.anchor.removeAttribute('aria-describedby');\n this.anchor.removeEventListener('mouseenter', this.mouseEnterHandler);\n this.anchor.removeEventListener('mouseleave', this.mouseLeaveHandler);\n this.anchor.removeEventListener('focusin', this.focusHandler);\n this.anchor.removeEventListener('focusout', this.blurHandler);\n this.anchor = null;\n }\n\n private clearTimers() {\n if (this.delayTimer) { clearTimeout(this.delayTimer); this.delayTimer = null; }\n if (this.closeTimer) { clearTimeout(this.closeTimer); this.closeTimer = null; }\n }\n\n private destroyPopup() {\n this.positionObserver?.disconnect();\n this.positionObserver = null;\n if (!this.popupEl) return;\n this.popupEl.remove();\n this.popupEl = null;\n }\n\n /**\n * Position after `ds-text` upgrades and lays out. Measuring synchronously in\n * `mountPopup` reads a collapsed/fallback width and places left/right tips wrong.\n */\n private schedulePosition() {\n if (!this.popupEl) return;\n\n const reapplyLabelStyles = () => {\n const label = this.popupEl?.querySelector(':scope > .tooltip-inner > ds-text');\n if (label instanceof HTMLElement) styleTooltipLabel(label);\n };\n\n requestAnimationFrame(() => {\n reapplyLabelStyles();\n this.calculatePosition();\n requestAnimationFrame(() => {\n reapplyLabelStyles();\n this.calculatePosition();\n });\n });\n\n this.positionObserver?.disconnect();\n this.positionObserver = new ResizeObserver(() => this.calculatePosition());\n this.positionObserver.observe(this.popupEl);\n }\n\n /** Drop the open tip immediately (warm handoff to another tooltip). */\n private hideInstant() {\n this.clearTimers();\n lastDismissedAt = Date.now();\n if (activeTooltip === this) activeTooltip = null;\n this.destroyPopup();\n this.isOpen = false;\n this.skipEnterAnimation = false;\n }\n\n private show() {\n // Empty label = wrapper present for DOM stability (e.g. PanelNav expand/collapse)\n // but no tip should appear.\n if (!this.label?.trim()) return;\n this.clearTimers();\n let instant = Date.now() - lastDismissedAt < this.instantReopenMs;\n if (activeTooltip && activeTooltip !== this) {\n activeTooltip.hideInstant();\n instant = true;\n }\n // eslint-disable-next-line @typescript-eslint/no-this-alias -- module singleton tracks the active instance\n activeTooltip = this;\n this.skipEnterAnimation = instant;\n if (instant) {\n this.mountPopup();\n return;\n }\n this.delayTimer = setTimeout(() => {\n this.delayTimer = null;\n if (!this.label?.trim()) return;\n this.mountPopup();\n }, this.hoverDelayMs);\n }\n\n private hide() {\n this.clearTimers();\n if (!this.popupEl && !this.isOpen) return;\n lastDismissedAt = Date.now();\n if (activeTooltip === this) activeTooltip = null;\n if (!this.popupEl) {\n this.isOpen = false;\n return;\n }\n this.popupEl.classList.remove('tooltip-popup--instant');\n this.popupEl.classList.add('tooltip-popup--closing');\n this.closeTimer = setTimeout(() => {\n this.closeTimer = null;\n this.destroyPopup();\n this.isOpen = false;\n this.skipEnterAnimation = false;\n }, this.fadeOutMs);\n }\n\n private mountPopup() {\n if (!this.popupEl) {\n const tip = document.createElement('div');\n tip.id = this.tooltipId;\n tip.setAttribute('role', 'tooltip');\n // `sc-ds-tooltip` is required for Stencil scoped CSS to match outside the host.\n tip.className = 'tooltip-popup sc-ds-tooltip';\n Object.assign(tip.style, {\n position: 'fixed',\n left: '0',\n top: '0',\n zIndex: 'var(--dimension-z-index-tooltip)',\n pointerEvents: 'none',\n });\n document.body.appendChild(tip);\n this.popupEl = tip;\n }\n\n this.popupEl.classList.toggle('tooltip-popup--instant', this.skipEnterAnimation);\n this.popupEl.classList.remove('tooltip-popup--closing');\n this.renderPopupContent();\n this.schedulePosition();\n this.isOpen = true;\n }\n\n private renderPopupContent() {\n if (!this.popupEl) return;\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const density =\n this.size === 'md' ? 'ds-control--md' : this.size === 'sm' ? 'ds-control--sm' : 'ds-control--xs';\n // Every layout node needs `sc-ds-tooltip` so scoped selectors (`.foo.sc-ds-tooltip`) match.\n const sc = 'sc-ds-tooltip';\n\n const inner = document.createElement('div');\n inner.className = `tooltip-inner ${density} ${sc}`;\n\n const appendShortcut = (position: 'start' | 'end') => {\n if (!this.shortcutKey || this.shortcutKeyPosition !== position) return;\n const group = document.createElement('span');\n group.className = `key-hint-group ${sc}`;\n group.setAttribute('aria-hidden', 'true');\n\n for (const label of shortcutKeyLabels(this.shortcutKey)) {\n const hint = document.createElement('span');\n const wide = Array.from(label).length > 1 ? ' key-hint--wide' : '';\n hint.className = `key-hint${wide} ${sc}`;\n const text = document.createElement('span');\n text.className = `key-hint__label ${sc}`;\n text.textContent = label;\n hint.appendChild(text);\n group.appendChild(hint);\n }\n inner.appendChild(group);\n };\n\n appendShortcut('start');\n\n // ds-text is the layout box (metric-box + 2px control label-inset).\n // Inline styles required — see styleTooltipLabel.\n const label = createDsText({ variant: textVariant, wrap: 'nowrap', text: this.label });\n styleTooltipLabel(label);\n inner.appendChild(label);\n\n appendShortcut('end');\n\n this.popupEl.replaceChildren(inner);\n }\n\n private calculatePosition() {\n if (!this.anchor || !this.popupEl) return;\n const tip = this.popupEl;\n const a = this.anchor.getBoundingClientRect();\n const tw = tip.offsetWidth || this.tooltipFallbackWidthPx;\n const th = tip.offsetHeight || this.tooltipFallbackHeightPx;\n const sideOffset = this.sideOffsetPx;\n const alignOffset = this.alignOffsetPx;\n const vpPad = this.viewportPadPx;\n let x = 0, y = 0;\n\n switch (this.side) {\n case 'top':\n y = a.top - th - sideOffset;\n x = this.align === 'start' ? a.left + alignOffset\n : this.align === 'end' ? a.right - tw + alignOffset\n : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'bottom':\n y = a.bottom + sideOffset;\n x = this.align === 'start' ? a.left + alignOffset\n : this.align === 'end' ? a.right - tw + alignOffset\n : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'left':\n x = a.left - tw - sideOffset;\n y = this.align === 'start' ? a.top + alignOffset\n : this.align === 'end' ? a.bottom - th + alignOffset\n : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n case 'right':\n x = a.right + sideOffset;\n y = this.align === 'start' ? a.top + alignOffset\n : this.align === 'end' ? a.bottom - th + alignOffset\n : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n }\n\n const nextX = Math.min(Math.max(x, vpPad), window.innerWidth - tw - vpPad);\n const nextY = Math.min(Math.max(y, vpPad), window.innerHeight - th - vpPad);\n tip.style.transform = `translate(${Math.round(nextX)}px, ${Math.round(nextY)}px)`;\n }\n\n render() {\n return (\n <Host style={{ display: 'contents' }}>\n <slot />\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- function n(n,t){const r=n.trim().split(/\s+/)[0]??"";const e=parseFloat(r);if(Number.isNaN(e))return t;if(/ms\s*$/.test(r))return e;if(/s\s*$/.test(r))return e*1e3;return e}function t(n){const t=n.match(/^var\(\s*(--[^),]+)/);if(t)return t[1].trim();if(n.startsWith("--"))return n.trim();return null}function r(r,e){if(typeof document==="undefined")return e;const u=t(r);if(!u)return n(r,e);const o=getComputedStyle(document.documentElement).getPropertyValue(u).trim();return n(o,e)}function e(e,u){if(typeof e==="number")return e;const o=typeof e==="string"&&e.trim()?e.trim():u;const f=t(o);if(f){return r(o,r(u,200))}return n(o,r(u,200))}export{e as r};
2
- //# sourceMappingURL=p-C1cBr-Ri.js.map
1
+ function n(n,t){const r=n.trim().split(/\s+/)[0]??"";const e=parseFloat(r);if(Number.isNaN(e))return t;if(/ms\s*$/.test(r))return e;if(/s\s*$/.test(r))return e*1e3;return e}function t(n){const t=n.match(/^var\(\s*(--[^),]+)/);if(t)return t[1].trim();if(n.startsWith("--"))return n.trim();return null}function r(r,e){if(typeof document==="undefined")return e;const u=t(r);if(!u)return n(r,e);const o=getComputedStyle(document.documentElement).getPropertyValue(u).trim();return n(o,e)}function e(e,u){if(typeof e==="number")return e;const o=typeof e==="string"&&e.trim()?e.trim():u;const f=t(o);if(f){return r(o,r(u,200))}return n(o,r(u,200))}export{n as p,e as r};
2
+ //# sourceMappingURL=p-BvmooLHV.js.map
@@ -0,0 +1,2 @@
1
+ import{p as t,H as o,c as n,h as i,a as d,t as l}from"./index.js";import{d as e}from"./p-9Qu1ls2y.js";import{d as r}from"./p-emacH2W5.js";import{C as s}from"./p-Cx-ywr1e.js";import{c as a}from"./p-DuFm-ieS.js";const c=()=>`.sc-ds-button-filled-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-button-filled: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-button-filled{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-button-filled:focus-visible{outline:none}.ds-focus-ring-inset.sc-ds-button-filled: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-button-filled{outline:none}.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-button-filled::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-button-filled-h,.ds-interaction-fill.sc-ds-button-filled{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);--ds-interaction-border-width:0px;--ds-interaction-border-color:transparent}.ds-interaction-fill.sc-ds-button-filled-h::before,.ds-interaction-fill.sc-ds-button-filled::before,.ds-interaction-fill.sc-ds-button-filled-h::after,.ds-interaction-fill.sc-ds-button-filled::after{content:'';position:absolute;inset:0;border-radius:inherit;background:transparent;pointer-events:none;transition:none}.ds-interaction-fill.sc-ds-button-filled-h::before,.ds-interaction-fill.sc-ds-button-filled::before{z-index:1}.ds-interaction-fill.sc-ds-button-filled-h::after,.ds-interaction-fill.sc-ds-button-filled::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-button-filled-h,.ds-interaction-fill--bordered.sc-ds-button-filled{--ds-interaction-border-width:var(--dimension-stroke-width-012);--ds-interaction-border-color:var(--color-border-secondary)}.ds-interaction-fill--selected.sc-ds-button-filled-h::before,.ds-interaction-fill--selected.sc-ds-button-filled::before{background:var(--ds-interaction-active)}.ds-interaction-fill--selected.sc-ds-button-filled-h,.ds-interaction-fill--selected.sc-ds-button-filled{--ds-interaction-dot-ring:var(--ds-interaction-active)}.ds-interaction-fill.sc-ds-button-filled-h:hover:not(:disabled)::after,.ds-interaction-fill.sc-ds-button-filled:hover:not(:disabled)::after{background:var(--ds-interaction-hover)}.ds-interaction-fill.sc-ds-button-filled-h:active:not(:disabled)::after,.ds-interaction-fill.sc-ds-button-filled:active:not(:disabled)::after{background:var(--ds-interaction-pressed)}.ds-interaction-fill.sc-ds-button-filled-h>.ds-interaction-fill__content.sc-ds-button-filled,.ds-interaction-fill.sc-ds-button-filled>.ds-interaction-fill__content.sc-ds-button-filled,.ds-interaction-fill__content.sc-ds-button-filled{position:relative;z-index:2}.ds-interaction-fill--on-medium.sc-ds-button-filled-h,.ds-interaction-fill--on-medium.sc-ds-button-filled{--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-button-filled-h,.ds-interaction-fill--on-bold.sc-ds-button-filled{--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-button-filled-h,.ds-interaction-fill--on-strong.sc-ds-button-filled{--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-always-dark.sc-ds-button-filled-h,.ds-interaction-fill--on-always-dark.sc-ds-button-filled{--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-button-filled-h,.ds-interaction-fill--on-navigation.sc-ds-button-filled{--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)}.ds-control-inactive.sc-ds-button-filled-h,.ds-control-inactive.sc-ds-button-filled{opacity:0.25;pointer-events:none;cursor:not-allowed}.ds-control--md.sc-ds-button-filled-h,.ds-control--md.sc-ds-button-filled{--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-button-filled-h,.ds-control--sm.sc-ds-button-filled{--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-button-filled-h,.ds-control--xs.sc-ds-button-filled{--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)}.ds-control-width--hug.sc-ds-button-filled-h,.ds-control-width--hug.sc-ds-button-filled{width:fit-content;max-width:100%;flex:0 0 auto;align-self:flex-start}.ds-control-width--fill.sc-ds-button-filled-h,.ds-control-width--fill.sc-ds-button-filled{width:100%;min-width:0;flex:1 1 auto;align-self:stretch}.sc-ds-button-filled-h{display:inline-flex;outline:none;--ds-button-filled-bg:var(--color-background-bold-brand);--ds-button-filled-fg:var(--color-foreground-faint-brand)}.button-filled-host--icon.ds-control-width--hug.sc-ds-button-filled-h{width:var(--ds-control-height, var(--dimension-size-400));height:var(--ds-control-height, var(--dimension-size-400));min-width:var(--ds-control-height, var(--dimension-size-400));min-height:var(--ds-control-height, var(--dimension-size-400))}.button-filled-host--icon.ds-control-width--fill.sc-ds-button-filled-h{height:var(--ds-control-height, var(--dimension-size-400));min-height:var(--ds-control-height, var(--dimension-size-400))}.ds-control-width--fill.sc-ds-button-filled-h .button-filled.sc-ds-button-filled{width:100%}.button-filled.sc-ds-button-filled{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;height:var(--ds-control-height, var(--dimension-size-400));padding:0 var(--ds-control-padding-inline, var(--dimension-space-075));gap:var(--ds-control-gap, var(--dimension-space-050));border:none;border-radius:var(--ds-control-radius, var(--dimension-radius-025));background-color:var(--ds-button-filled-bg);color:var(--ds-button-filled-fg);cursor:pointer;-webkit-user-select:none;user-select:none;overflow:hidden;transition:background-color var(--effect-motion-short-2), color var(--effect-motion-short-2), transform var(--effect-motion-short-2)}.button-filled--icon.sc-ds-button-filled{width:100%;height:100%;padding:0}.button-filled.sc-ds-button-filled:active:not(:disabled):not(.ds-control-inactive){transform:scale(var(--dimension-scale-subtle))}.button-filled__icon-wrap.sc-ds-button-filled{position:relative;width:var(--ds-control-icon, var(--dimension-iconography-md));height:var(--ds-control-icon, var(--dimension-iconography-md));display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;z-index:2}.button-filled__label.sc-ds-button-filled{position:relative;z-index:2;padding:0 var(--ds-control-label-inset, var(--dimension-space-025));white-space:nowrap;flex-shrink:0;min-width:0}.button-filled--intent-neutral.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-neutral);--ds-button-filled-fg:var(--color-foreground-faint-neutral)}.button-filled--intent-brand.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-brand);--ds-button-filled-fg:var(--color-foreground-faint-brand)}.button-filled--intent-ai.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-ai);--ds-button-filled-fg:var(--color-foreground-faint-ai)}.button-filled--intent-negative.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-negative);--ds-button-filled-fg:var(--color-foreground-faint-negative)}.button-filled--intent-warning.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-warning);--ds-button-filled-fg:var(--color-foreground-faint-warning)}.button-filled--intent-caution.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-caution);--ds-button-filled-fg:var(--color-foreground-faint-caution)}.button-filled--intent-positive.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-positive);--ds-button-filled-fg:var(--color-foreground-faint-positive)}.button-filled--intent-guide.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-guide);--ds-button-filled-fg:var(--color-foreground-faint-guide)}.button-filled--intent-walkthrough.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-bold-walkthrough);--ds-button-filled-fg:var(--color-foreground-faint-walkthrough)}.button-filled--contrast-strong.button-filled--intent-neutral.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-neutral);--ds-button-filled-fg:var(--color-foreground-medium-neutral)}.button-filled--contrast-strong.button-filled--intent-brand.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-brand);--ds-button-filled-fg:var(--color-foreground-medium-brand)}.button-filled--contrast-strong.button-filled--intent-ai.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-ai);--ds-button-filled-fg:var(--color-foreground-medium-ai)}.button-filled--contrast-strong.button-filled--intent-negative.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-negative);--ds-button-filled-fg:var(--color-foreground-medium-negative)}.button-filled--contrast-strong.button-filled--intent-warning.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-warning);--ds-button-filled-fg:var(--color-foreground-medium-warning)}.button-filled--contrast-strong.button-filled--intent-caution.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-caution);--ds-button-filled-fg:var(--color-foreground-medium-caution)}.button-filled--contrast-strong.button-filled--intent-positive.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-positive);--ds-button-filled-fg:var(--color-foreground-medium-positive)}.button-filled--contrast-strong.button-filled--intent-guide.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-guide);--ds-button-filled-fg:var(--color-foreground-medium-guide)}.button-filled--contrast-strong.button-filled--intent-walkthrough.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-strong-walkthrough);--ds-button-filled-fg:var(--color-foreground-medium-walkthrough)}.button-filled--contrast-medium.button-filled--intent-neutral.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-neutral);--ds-button-filled-fg:var(--color-foreground-strong-neutral)}.button-filled--contrast-medium.button-filled--intent-brand.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-brand);--ds-button-filled-fg:var(--color-foreground-strong-brand)}.button-filled--contrast-medium.button-filled--intent-ai.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-ai);--ds-button-filled-fg:var(--color-foreground-strong-ai)}.button-filled--contrast-medium.button-filled--intent-negative.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-negative);--ds-button-filled-fg:var(--color-foreground-strong-negative)}.button-filled--contrast-medium.button-filled--intent-warning.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-warning);--ds-button-filled-fg:var(--color-foreground-strong-warning)}.button-filled--contrast-medium.button-filled--intent-caution.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-caution);--ds-button-filled-fg:var(--color-foreground-strong-caution)}.button-filled--contrast-medium.button-filled--intent-positive.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-positive);--ds-button-filled-fg:var(--color-foreground-strong-positive)}.button-filled--contrast-medium.button-filled--intent-guide.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-guide);--ds-button-filled-fg:var(--color-foreground-strong-guide)}.button-filled--contrast-medium.button-filled--intent-walkthrough.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-medium-walkthrough);--ds-button-filled-fg:var(--color-foreground-strong-walkthrough)}.button-filled--contrast-faint.button-filled--intent-neutral.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-neutral);--ds-button-filled-fg:var(--color-foreground-bold-neutral)}.button-filled--contrast-faint.button-filled--intent-brand.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-brand);--ds-button-filled-fg:var(--color-foreground-bold-brand)}.button-filled--contrast-faint.button-filled--intent-ai.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-ai);--ds-button-filled-fg:var(--color-foreground-bold-ai)}.button-filled--contrast-faint.button-filled--intent-negative.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-negative);--ds-button-filled-fg:var(--color-foreground-bold-negative)}.button-filled--contrast-faint.button-filled--intent-warning.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-warning);--ds-button-filled-fg:var(--color-foreground-bold-warning)}.button-filled--contrast-faint.button-filled--intent-caution.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-caution);--ds-button-filled-fg:var(--color-foreground-bold-caution)}.button-filled--contrast-faint.button-filled--intent-positive.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-positive);--ds-button-filled-fg:var(--color-foreground-bold-positive)}.button-filled--contrast-faint.button-filled--intent-guide.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-guide);--ds-button-filled-fg:var(--color-foreground-bold-guide)}.button-filled--contrast-faint.button-filled--intent-walkthrough.sc-ds-button-filled{--ds-button-filled-bg:var(--color-background-faint-walkthrough);--ds-button-filled-fg:var(--color-foreground-bold-walkthrough)}`;const u={md:"md",sm:"sm",xs:"xs"};const f=t(class t extends o{constructor(t){super();if(t!==false){this.__registerHost()}this.dsClick=n(this,"dsClick");this.variant="label";this.size="md";this.width="hug";this.label="";this.icon="";this.intent="brand";this.contrast="bold";this.isInactive=false;this.type="button";this.ariaLabel=null;this.buttonEl=null;this.handleClick=t=>{if(this.isInactive)return;this.dsClick.emit(t)}}async setFocus(){this.buttonEl?.focus()}get showIcon(){return this.variant==="icon"||this.variant==="icon-label"}get showLabel(){return this.variant==="label"||this.variant==="icon-label"}get accessibleName(){if(this.ariaLabel)return this.ariaLabel;if(this.showLabel&&this.label)return undefined;if(this.variant==="icon")return this.icon||"action";return this.label||"action"}render(){const t=s[this.size];const o=u[this.size];const n={"button-filled":true,"ds-focus-ring-inset":true,"ds-interaction-fill":!this.isInactive,"ds-interaction-fill--on-bold":this.contrast==="bold","ds-interaction-fill--on-strong":this.contrast==="strong","ds-interaction-fill--on-medium":this.contrast==="medium","ds-control-inactive":this.isInactive,"ds-control--md":this.size==="md","ds-control--sm":this.size==="sm","ds-control--xs":this.size==="xs","button-filled--icon":this.variant==="icon","button-filled--label":this.variant==="label","button-filled--icon-label":this.variant==="icon-label",[`button-filled--intent-${this.intent}`]:true,[`button-filled--contrast-${this.contrast}`]:this.contrast!=="bold"};return i(d,{key:"618114abfee2b998f3426ab282928a1727ac1a67",class:{"button-filled-host":true,"button-filled-host--icon":this.variant==="icon","ds-control--md":this.size==="md","ds-control--sm":this.size==="sm","ds-control--xs":this.size==="xs",...a(this.width)},tabIndex:-1},i("button",{key:"a67a6a0b907879b53e5c6ba14bee49a5abbba8cc",ref:t=>{this.buttonEl=t??null},type:this.type,class:n,disabled:this.isInactive,"aria-label":this.accessibleName,onClick:this.handleClick},this.showIcon&&i("span",{key:"74682d9d33b26c0d2bf8946db979b30e05ce873b",class:"button-filled__icon-wrap ds-interaction-fill__content"},i("ds-icon",{key:"633eb6022d1efd850a3ea814c219fcf1cac2d640",name:this.icon,size:o,color:"inherit"})),this.showLabel&&i("ds-text",{key:"0d7c6b95a244aec87d5f52da3ee3251aa19242a5",class:"button-filled__label ds-interaction-fill__content",as:"span",variant:t,emphasis:true,color:"inherit"},this.label)))}get el(){return this}static get style(){return c()}},[2,"ds-button-filled",{variant:[1],size:[1],width:[1],label:[1],icon:[1],intent:[1],contrast:[1],isInactive:[4,"is-inactive"],type:[1],ariaLabel:[1,"aria-label"],setFocus:[64]}]);function b(){if(typeof customElements==="undefined"){return}const t=["ds-button-filled","ds-icon","ds-text"];t.forEach((t=>{switch(t){case"ds-button-filled":if(!customElements.get(l(t))){customElements.define(l(t),f)}break;case"ds-icon":if(!customElements.get(l(t))){e()}break;case"ds-text":if(!customElements.get(l(t))){r()}break}}))}b();export{f as B,b as d};
2
+ //# sourceMappingURL=p-C2gX0ggG.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["buttonFilledCss","ICON_SIZE","md","sm","xs","ButtonFilled","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","variant","size","width","label","icon","intent","contrast","isInactive","type","ariaLabel","buttonEl","handleClick","event","dsClick","emit","setFocus","focus","showIcon","showLabel","accessibleName","undefined","render","textVariant","CONTROL_TEXT_VARIANT","iconSize","cls","h","Host","key","class","controlWidthClass","tabIndex","ref","el","disabled","onClick","name","color","as","emphasis"],"sources":["src/wc/components/ButtonFilled/ButtonFilled.css?tag=ds-button-filled&encapsulation=scoped","src/wc/components/ButtonFilled/ButtonFilled.tsx"],"sourcesContent":["@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n@import '../../utils/control-width.css';\n\n:host {\n display: inline-flex;\n outline: none;\n --ds-button-filled-bg: var(--color-background-bold-brand);\n --ds-button-filled-fg: var(--color-foreground-faint-brand);\n}\n\n/* Icon-only: fixed square from density height (hug). Fill stretches the hit target. */\n:host(.button-filled-host--icon.ds-control-width--hug) {\n width: var(--ds-control-height, var(--dimension-size-400));\n height: var(--ds-control-height, var(--dimension-size-400));\n min-width: var(--ds-control-height, var(--dimension-size-400));\n min-height: var(--ds-control-height, var(--dimension-size-400));\n}\n\n:host(.button-filled-host--icon.ds-control-width--fill) {\n height: var(--ds-control-height, var(--dimension-size-400));\n min-height: var(--ds-control-height, var(--dimension-size-400));\n}\n\n:host(.ds-control-width--fill) .button-filled {\n width: 100%;\n}\n\n.button-filled {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n gap: var(--ds-control-gap, var(--dimension-space-050));\n border: none;\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n background-color: var(--ds-button-filled-bg);\n color: var(--ds-button-filled-fg);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n overflow: hidden;\n transition:\n background-color var(--effect-motion-short-2),\n color var(--effect-motion-short-2),\n transform var(--effect-motion-short-2);\n /* Hover/press: `.ds-interaction-fill` + contrast → `--on-*` (token overlay, not color-mix). */\n}\n\n.button-filled--icon {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n\n.button-filled:active:not(:disabled):not(.ds-control-inactive) {\n transform: scale(var(--dimension-scale-subtle));\n}\n\n/* Inactive: `.ds-control-inactive` (25% opacity). */\n\n.button-filled__icon-wrap {\n position: relative;\n width: var(--ds-control-icon, var(--dimension-iconography-md));\n height: var(--ds-control-icon, var(--dimension-iconography-md));\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n z-index: 2;\n}\n\n.button-filled__label {\n position: relative;\n z-index: 2;\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n white-space: nowrap;\n flex-shrink: 0;\n min-width: 0;\n}\n\n/* ── Intent + contrast (bold default) ─────────────────────────────────────── */\n\n.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-bold-neutral);\n --ds-button-filled-fg: var(--color-foreground-faint-neutral);\n}\n\n.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-bold-brand);\n --ds-button-filled-fg: var(--color-foreground-faint-brand);\n}\n\n.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-bold-ai);\n --ds-button-filled-fg: var(--color-foreground-faint-ai);\n}\n\n.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-bold-negative);\n --ds-button-filled-fg: var(--color-foreground-faint-negative);\n}\n\n.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-bold-warning);\n --ds-button-filled-fg: var(--color-foreground-faint-warning);\n}\n\n.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-bold-caution);\n --ds-button-filled-fg: var(--color-foreground-faint-caution);\n}\n\n.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-bold-positive);\n --ds-button-filled-fg: var(--color-foreground-faint-positive);\n}\n\n.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-bold-guide);\n --ds-button-filled-fg: var(--color-foreground-faint-guide);\n}\n\n.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-bold-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-faint-walkthrough);\n}\n\n/* strong → medium fg */\n.button-filled--contrast-strong.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-strong-neutral);\n --ds-button-filled-fg: var(--color-foreground-medium-neutral);\n}\n\n.button-filled--contrast-strong.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-strong-brand);\n --ds-button-filled-fg: var(--color-foreground-medium-brand);\n}\n\n.button-filled--contrast-strong.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-strong-ai);\n --ds-button-filled-fg: var(--color-foreground-medium-ai);\n}\n\n.button-filled--contrast-strong.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-strong-negative);\n --ds-button-filled-fg: var(--color-foreground-medium-negative);\n}\n\n.button-filled--contrast-strong.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-strong-warning);\n --ds-button-filled-fg: var(--color-foreground-medium-warning);\n}\n\n.button-filled--contrast-strong.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-strong-caution);\n --ds-button-filled-fg: var(--color-foreground-medium-caution);\n}\n\n.button-filled--contrast-strong.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-strong-positive);\n --ds-button-filled-fg: var(--color-foreground-medium-positive);\n}\n\n.button-filled--contrast-strong.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-strong-guide);\n --ds-button-filled-fg: var(--color-foreground-medium-guide);\n}\n\n.button-filled--contrast-strong.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-strong-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-medium-walkthrough);\n}\n\n/* medium → strong fg */\n.button-filled--contrast-medium.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-medium-neutral);\n --ds-button-filled-fg: var(--color-foreground-strong-neutral);\n}\n\n.button-filled--contrast-medium.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-medium-brand);\n --ds-button-filled-fg: var(--color-foreground-strong-brand);\n}\n\n.button-filled--contrast-medium.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-medium-ai);\n --ds-button-filled-fg: var(--color-foreground-strong-ai);\n}\n\n.button-filled--contrast-medium.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-medium-negative);\n --ds-button-filled-fg: var(--color-foreground-strong-negative);\n}\n\n.button-filled--contrast-medium.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-medium-warning);\n --ds-button-filled-fg: var(--color-foreground-strong-warning);\n}\n\n.button-filled--contrast-medium.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-medium-caution);\n --ds-button-filled-fg: var(--color-foreground-strong-caution);\n}\n\n.button-filled--contrast-medium.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-medium-positive);\n --ds-button-filled-fg: var(--color-foreground-strong-positive);\n}\n\n.button-filled--contrast-medium.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-medium-guide);\n --ds-button-filled-fg: var(--color-foreground-strong-guide);\n}\n\n.button-filled--contrast-medium.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-medium-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-strong-walkthrough);\n}\n\n/* faint → bold fg */\n.button-filled--contrast-faint.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-faint-neutral);\n --ds-button-filled-fg: var(--color-foreground-bold-neutral);\n}\n\n.button-filled--contrast-faint.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-faint-brand);\n --ds-button-filled-fg: var(--color-foreground-bold-brand);\n}\n\n.button-filled--contrast-faint.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-faint-ai);\n --ds-button-filled-fg: var(--color-foreground-bold-ai);\n}\n\n.button-filled--contrast-faint.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-faint-negative);\n --ds-button-filled-fg: var(--color-foreground-bold-negative);\n}\n\n.button-filled--contrast-faint.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-faint-warning);\n --ds-button-filled-fg: var(--color-foreground-bold-warning);\n}\n\n.button-filled--contrast-faint.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-faint-caution);\n --ds-button-filled-fg: var(--color-foreground-bold-caution);\n}\n\n.button-filled--contrast-faint.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-faint-positive);\n --ds-button-filled-fg: var(--color-foreground-bold-positive);\n}\n\n.button-filled--contrast-faint.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-faint-guide);\n --ds-button-filled-fg: var(--color-foreground-bold-guide);\n}\n\n.button-filled--contrast-faint.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-faint-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-bold-walkthrough);\n}\n","import { Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core';\nimport { controlWidthClass, CONTROL_TEXT_VARIANT, type ControlWidth } from '../../utils';\n\nexport type ButtonFilledIntent =\n | 'neutral'\n | 'brand'\n | 'ai'\n | 'negative'\n | 'warning'\n | 'caution'\n | 'positive'\n | 'guide'\n | 'walkthrough';\n\nexport type ButtonFilledContrast = 'bold' | 'strong' | 'medium' | 'faint';\n\nexport type ButtonFilledVariant = 'icon' | 'label' | 'icon-label';\n\nexport type ButtonFilledSize = 'md' | 'sm' | 'xs';\n\nexport type ButtonFilledWidth = ControlWidth;\n\n/**\n * `ds-icon` size prop matching control-density icon metrics\n * (md→20 / sm→16 / xs→12 via `--dimension-iconography-*`).\n */\nconst ICON_SIZE: Record<ButtonFilledSize, 'md' | 'sm' | 'xs'> = {\n md: 'md',\n sm: 'sm',\n xs: 'xs',\n};\n\n@Component({\n tag: 'ds-button-filled',\n styleUrl: 'ButtonFilled.css',\n scoped: true,\n})\nexport class ButtonFilled {\n @Element() el!: HTMLElement;\n\n /**\n * Content layout. Default is label-only; pass `icon` for icon-only chrome\n * (nav / tool rails) or `icon-label` for leading icon + text.\n */\n @Prop() variant: ButtonFilledVariant = 'label';\n\n /** Control density (height, padding, icon, type). */\n @Prop() size: ButtonFilledSize = 'md';\n\n /** Width fit — hug content (default) or fill the parent. */\n @Prop() width: ButtonFilledWidth = 'hug';\n\n /** Visible text for `label` / `icon-label` variants. */\n @Prop() label: string = '';\n\n /** Icon name passed to <ds-icon> for `icon` / `icon-label` variants. */\n @Prop() icon: string = '';\n\n /** Semantic colour intent. */\n @Prop() intent: ButtonFilledIntent = 'brand';\n\n /**\n * Background fill weight. Foreground uses the paired contrast token:\n * bold → faint, strong → medium, medium → strong, faint → bold.\n */\n @Prop() contrast: ButtonFilledContrast = 'bold';\n\n /** Disables interaction. */\n @Prop() isInactive: boolean = false;\n\n /** Native button type. */\n @Prop() type: 'button' | 'submit' | 'reset' = 'button';\n\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n\n @Event() dsClick!: EventEmitter<MouseEvent>;\n\n private buttonEl: HTMLButtonElement | null = null;\n\n @Method()\n async setFocus() {\n this.buttonEl?.focus();\n }\n\n private handleClick = (event: MouseEvent) => {\n if (this.isInactive) return;\n this.dsClick.emit(event);\n };\n\n private get showIcon(): boolean {\n return this.variant === 'icon' || this.variant === 'icon-label';\n }\n\n private get showLabel(): boolean {\n return this.variant === 'label' || this.variant === 'icon-label';\n }\n\n private get accessibleName(): string | undefined {\n if (this.ariaLabel) return this.ariaLabel;\n if (this.showLabel && this.label) return undefined;\n if (this.variant === 'icon') return this.icon || 'action';\n return this.label || 'action';\n }\n\n render() {\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const iconSize = ICON_SIZE[this.size];\n\n const cls: Record<string, boolean> = {\n 'button-filled': true,\n 'ds-focus-ring-inset': true,\n 'ds-interaction-fill': !this.isInactive,\n /* Bold is the default filled contrast — on-bold interaction tokens. */\n 'ds-interaction-fill--on-bold': this.contrast === 'bold',\n 'ds-interaction-fill--on-strong': this.contrast === 'strong',\n 'ds-interaction-fill--on-medium': this.contrast === 'medium',\n /* faint → default app interaction tokens (no --on-*). */\n 'ds-control-inactive': this.isInactive,\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n 'button-filled--icon': this.variant === 'icon',\n 'button-filled--label': this.variant === 'label',\n 'button-filled--icon-label': this.variant === 'icon-label',\n [`button-filled--intent-${this.intent}`]: true,\n [`button-filled--contrast-${this.contrast}`]: this.contrast !== 'bold',\n };\n\n return (\n <Host\n class={{\n 'button-filled-host': true,\n 'button-filled-host--icon': this.variant === 'icon',\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n ...controlWidthClass(this.width),\n }}\n tabIndex={-1}\n >\n <button\n ref={el => {\n this.buttonEl = el ?? null;\n }}\n type={this.type}\n class={cls}\n disabled={this.isInactive}\n aria-label={this.accessibleName}\n onClick={this.handleClick}\n >\n {this.showIcon && (\n <span class=\"button-filled__icon-wrap ds-interaction-fill__content\">\n <ds-icon name={this.icon} size={iconSize} color=\"inherit\" />\n </span>\n )}\n {this.showLabel && (\n <ds-text\n class=\"button-filled__label ds-interaction-fill__content\"\n as=\"span\"\n variant={textVariant}\n emphasis\n color=\"inherit\"\n >\n {this.label}\n </ds-text>\n )}\n </button>\n </Host>\n );\n }\n}\n"],"mappings":"kNAAA,MAAMA,EAAkB,IAAM,u7eC0B9B,MAAMC,EAA0D,CAC9DC,GAAI,KACJC,GAAI,KACJC,GAAI,M,MAQOC,EAAYC,EAAA,MAAAD,UAAAE,EALzB,WAAAC,CAAAC,G,2EAYUC,KAAAC,QAA+B,QAG/BD,KAAAE,KAAyB,KAGzBF,KAAAG,MAA2B,MAG3BH,KAAAI,MAAgB,GAGhBJ,KAAAK,KAAe,GAGfL,KAAAM,OAA6B,QAM7BN,KAAAO,SAAiC,OAGjCP,KAAAQ,WAAsB,MAGtBR,KAAAS,KAAsC,SAEXT,KAAAU,UAA2B,KAItDV,KAAAW,SAAqC,KAOrCX,KAAAY,YAAeC,IACrB,GAAIb,KAAKQ,WAAY,OACrBR,KAAKc,QAAQC,KAAKF,EAAM,CAoF3B,CA1FC,cAAMG,GACJhB,KAAKW,UAAUM,O,CAQjB,YAAYC,GACV,OAAOlB,KAAKC,UAAY,QAAUD,KAAKC,UAAY,Y,CAGrD,aAAYkB,GACV,OAAOnB,KAAKC,UAAY,SAAWD,KAAKC,UAAY,Y,CAGtD,kBAAYmB,GACV,GAAIpB,KAAKU,UAAW,OAAOV,KAAKU,UAChC,GAAIV,KAAKmB,WAAanB,KAAKI,MAAO,OAAOiB,UACzC,GAAIrB,KAAKC,UAAY,OAAQ,OAAOD,KAAKK,MAAQ,SACjD,OAAOL,KAAKI,OAAS,Q,CAGvB,MAAAkB,GACE,MAAMC,EAAcC,EAAqBxB,KAAKE,MAC9C,MAAMuB,EAAWlC,EAAUS,KAAKE,MAEhC,MAAMwB,EAA+B,CACnC,gBAAiB,KACjB,sBAAuB,KACvB,uBAAwB1B,KAAKQ,WAE7B,+BAAgCR,KAAKO,WAAa,OAClD,iCAAkCP,KAAKO,WAAa,SACpD,iCAAkCP,KAAKO,WAAa,SAEpD,sBAAuBP,KAAKQ,WAC5B,iBAAkBR,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,KAChC,sBAAuBF,KAAKC,UAAY,OACxC,uBAAwBD,KAAKC,UAAY,QACzC,4BAA6BD,KAAKC,UAAY,aAC9C,CAAC,yBAAyBD,KAAKM,UAAW,KAC1C,CAAC,2BAA2BN,KAAKO,YAAaP,KAAKO,WAAa,QAGlE,OACEoB,EAACC,EAAI,CAAAC,IAAA,2CACHC,MAAO,CACL,qBAAsB,KACtB,2BAA4B9B,KAAKC,UAAY,OAC7C,iBAAkBD,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,QAC7B6B,EAAkB/B,KAAKG,QAE5B6B,UAAU,GAEVL,EAAA,UAAAE,IAAA,2CACEI,IAAKC,IACHlC,KAAKW,SAAWuB,GAAM,IAAI,EAE5BzB,KAAMT,KAAKS,KACXqB,MAAOJ,EACPS,SAAUnC,KAAKQ,WAAU,aACbR,KAAKoB,eACjBgB,QAASpC,KAAKY,aAEbZ,KAAKkB,UACJS,EAAA,QAAAE,IAAA,2CAAMC,MAAM,yDACVH,EAAA,WAAAE,IAAA,2CAASQ,KAAMrC,KAAKK,KAAMH,KAAMuB,EAAUa,MAAM,aAGnDtC,KAAKmB,WACJQ,EAAA,WAAAE,IAAA,2CACEC,MAAM,oDACNS,GAAG,OACHtC,QAASsB,EACTiB,SAAQ,KACRF,MAAM,WAELtC,KAAKI,Q","ignoreList":[]}
1
+ {"version":3,"names":["buttonFilledCss","ICON_SIZE","md","sm","xs","ButtonFilled","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","variant","size","width","label","icon","intent","contrast","isInactive","type","ariaLabel","buttonEl","handleClick","event","dsClick","emit","setFocus","focus","showIcon","showLabel","accessibleName","undefined","render","textVariant","CONTROL_TEXT_VARIANT","iconSize","cls","h","Host","key","class","controlWidthClass","tabIndex","ref","el","disabled","onClick","name","color","as","emphasis"],"sources":["src/wc/components/ButtonFilled/ButtonFilled.css?tag=ds-button-filled&encapsulation=scoped","src/wc/components/ButtonFilled/ButtonFilled.tsx"],"sourcesContent":["@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n@import '../../utils/control-width.css';\n\n:host {\n display: inline-flex;\n outline: none;\n --ds-button-filled-bg: var(--color-background-bold-brand);\n --ds-button-filled-fg: var(--color-foreground-faint-brand);\n}\n\n/* Icon-only: fixed square from density height (hug). Fill stretches the hit target. */\n:host(.button-filled-host--icon.ds-control-width--hug) {\n width: var(--ds-control-height, var(--dimension-size-400));\n height: var(--ds-control-height, var(--dimension-size-400));\n min-width: var(--ds-control-height, var(--dimension-size-400));\n min-height: var(--ds-control-height, var(--dimension-size-400));\n}\n\n:host(.button-filled-host--icon.ds-control-width--fill) {\n height: var(--ds-control-height, var(--dimension-size-400));\n min-height: var(--ds-control-height, var(--dimension-size-400));\n}\n\n:host(.ds-control-width--fill) .button-filled {\n width: 100%;\n}\n\n.button-filled {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n gap: var(--ds-control-gap, var(--dimension-space-050));\n border: none;\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n background-color: var(--ds-button-filled-bg);\n color: var(--ds-button-filled-fg);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n overflow: hidden;\n transition:\n background-color var(--effect-motion-short-2),\n color var(--effect-motion-short-2),\n transform var(--effect-motion-short-2);\n /* Hover/press: `.ds-interaction-fill` + contrast → `--on-*` (token overlay, not color-mix). */\n}\n\n.button-filled--icon {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n\n.button-filled:active:not(:disabled):not(.ds-control-inactive) {\n transform: scale(var(--dimension-scale-subtle));\n}\n\n/* Inactive: `.ds-control-inactive` (25% opacity). */\n\n.button-filled__icon-wrap {\n position: relative;\n width: var(--ds-control-icon, var(--dimension-iconography-md));\n height: var(--ds-control-icon, var(--dimension-iconography-md));\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n z-index: 2;\n}\n\n.button-filled__label {\n position: relative;\n z-index: 2;\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n white-space: nowrap;\n flex-shrink: 0;\n min-width: 0;\n}\n\n/* ── Intent + contrast (bold default) ─────────────────────────────────────── */\n\n.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-bold-neutral);\n --ds-button-filled-fg: var(--color-foreground-faint-neutral);\n}\n\n.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-bold-brand);\n --ds-button-filled-fg: var(--color-foreground-faint-brand);\n}\n\n.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-bold-ai);\n --ds-button-filled-fg: var(--color-foreground-faint-ai);\n}\n\n.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-bold-negative);\n --ds-button-filled-fg: var(--color-foreground-faint-negative);\n}\n\n.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-bold-warning);\n --ds-button-filled-fg: var(--color-foreground-faint-warning);\n}\n\n.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-bold-caution);\n --ds-button-filled-fg: var(--color-foreground-faint-caution);\n}\n\n.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-bold-positive);\n --ds-button-filled-fg: var(--color-foreground-faint-positive);\n}\n\n.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-bold-guide);\n --ds-button-filled-fg: var(--color-foreground-faint-guide);\n}\n\n.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-bold-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-faint-walkthrough);\n}\n\n/* strong → medium fg */\n.button-filled--contrast-strong.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-strong-neutral);\n --ds-button-filled-fg: var(--color-foreground-medium-neutral);\n}\n\n.button-filled--contrast-strong.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-strong-brand);\n --ds-button-filled-fg: var(--color-foreground-medium-brand);\n}\n\n.button-filled--contrast-strong.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-strong-ai);\n --ds-button-filled-fg: var(--color-foreground-medium-ai);\n}\n\n.button-filled--contrast-strong.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-strong-negative);\n --ds-button-filled-fg: var(--color-foreground-medium-negative);\n}\n\n.button-filled--contrast-strong.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-strong-warning);\n --ds-button-filled-fg: var(--color-foreground-medium-warning);\n}\n\n.button-filled--contrast-strong.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-strong-caution);\n --ds-button-filled-fg: var(--color-foreground-medium-caution);\n}\n\n.button-filled--contrast-strong.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-strong-positive);\n --ds-button-filled-fg: var(--color-foreground-medium-positive);\n}\n\n.button-filled--contrast-strong.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-strong-guide);\n --ds-button-filled-fg: var(--color-foreground-medium-guide);\n}\n\n.button-filled--contrast-strong.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-strong-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-medium-walkthrough);\n}\n\n/* medium → strong fg */\n.button-filled--contrast-medium.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-medium-neutral);\n --ds-button-filled-fg: var(--color-foreground-strong-neutral);\n}\n\n.button-filled--contrast-medium.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-medium-brand);\n --ds-button-filled-fg: var(--color-foreground-strong-brand);\n}\n\n.button-filled--contrast-medium.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-medium-ai);\n --ds-button-filled-fg: var(--color-foreground-strong-ai);\n}\n\n.button-filled--contrast-medium.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-medium-negative);\n --ds-button-filled-fg: var(--color-foreground-strong-negative);\n}\n\n.button-filled--contrast-medium.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-medium-warning);\n --ds-button-filled-fg: var(--color-foreground-strong-warning);\n}\n\n.button-filled--contrast-medium.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-medium-caution);\n --ds-button-filled-fg: var(--color-foreground-strong-caution);\n}\n\n.button-filled--contrast-medium.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-medium-positive);\n --ds-button-filled-fg: var(--color-foreground-strong-positive);\n}\n\n.button-filled--contrast-medium.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-medium-guide);\n --ds-button-filled-fg: var(--color-foreground-strong-guide);\n}\n\n.button-filled--contrast-medium.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-medium-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-strong-walkthrough);\n}\n\n/* faint → bold fg */\n.button-filled--contrast-faint.button-filled--intent-neutral {\n --ds-button-filled-bg: var(--color-background-faint-neutral);\n --ds-button-filled-fg: var(--color-foreground-bold-neutral);\n}\n\n.button-filled--contrast-faint.button-filled--intent-brand {\n --ds-button-filled-bg: var(--color-background-faint-brand);\n --ds-button-filled-fg: var(--color-foreground-bold-brand);\n}\n\n.button-filled--contrast-faint.button-filled--intent-ai {\n --ds-button-filled-bg: var(--color-background-faint-ai);\n --ds-button-filled-fg: var(--color-foreground-bold-ai);\n}\n\n.button-filled--contrast-faint.button-filled--intent-negative {\n --ds-button-filled-bg: var(--color-background-faint-negative);\n --ds-button-filled-fg: var(--color-foreground-bold-negative);\n}\n\n.button-filled--contrast-faint.button-filled--intent-warning {\n --ds-button-filled-bg: var(--color-background-faint-warning);\n --ds-button-filled-fg: var(--color-foreground-bold-warning);\n}\n\n.button-filled--contrast-faint.button-filled--intent-caution {\n --ds-button-filled-bg: var(--color-background-faint-caution);\n --ds-button-filled-fg: var(--color-foreground-bold-caution);\n}\n\n.button-filled--contrast-faint.button-filled--intent-positive {\n --ds-button-filled-bg: var(--color-background-faint-positive);\n --ds-button-filled-fg: var(--color-foreground-bold-positive);\n}\n\n.button-filled--contrast-faint.button-filled--intent-guide {\n --ds-button-filled-bg: var(--color-background-faint-guide);\n --ds-button-filled-fg: var(--color-foreground-bold-guide);\n}\n\n.button-filled--contrast-faint.button-filled--intent-walkthrough {\n --ds-button-filled-bg: var(--color-background-faint-walkthrough);\n --ds-button-filled-fg: var(--color-foreground-bold-walkthrough);\n}\n","import { Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core';\nimport { controlWidthClass, CONTROL_TEXT_VARIANT, type ControlWidth } from '../../utils';\n\nexport type ButtonFilledIntent =\n | 'neutral'\n | 'brand'\n | 'ai'\n | 'negative'\n | 'warning'\n | 'caution'\n | 'positive'\n | 'guide'\n | 'walkthrough';\n\nexport type ButtonFilledContrast = 'bold' | 'strong' | 'medium' | 'faint';\n\nexport type ButtonFilledVariant = 'icon' | 'label' | 'icon-label';\n\nexport type ButtonFilledSize = 'md' | 'sm' | 'xs';\n\nexport type ButtonFilledWidth = ControlWidth;\n\n/**\n * `ds-icon` size prop matching control-density icon metrics\n * (md→20 / sm→16 / xs→12 via `--dimension-iconography-*`).\n */\nconst ICON_SIZE: Record<ButtonFilledSize, 'md' | 'sm' | 'xs'> = {\n md: 'md',\n sm: 'sm',\n xs: 'xs',\n};\n\n@Component({\n tag: 'ds-button-filled',\n styleUrl: 'ButtonFilled.css',\n scoped: true,\n})\nexport class ButtonFilled {\n @Element() el!: HTMLElement;\n\n /**\n * Content layout. Default is label-only; pass `icon` for icon-only chrome\n * (nav / tool rails) or `icon-label` for leading icon + text.\n */\n @Prop() variant: ButtonFilledVariant = 'label';\n\n /** Control density (height, padding, icon, type). */\n @Prop() size: ButtonFilledSize = 'md';\n\n /** Width fit — hug content (default) or fill the parent. */\n @Prop() width: ButtonFilledWidth = 'hug';\n\n /** Visible text for `label` / `icon-label` variants. */\n @Prop() label: string = '';\n\n /** Icon name passed to <ds-icon> for `icon` / `icon-label` variants. */\n @Prop() icon: string = '';\n\n /** Semantic colour intent. */\n @Prop() intent: ButtonFilledIntent = 'brand';\n\n /**\n * Background fill weight. Foreground uses the paired contrast token:\n * bold → faint, strong → medium, medium → strong, faint → bold.\n */\n @Prop() contrast: ButtonFilledContrast = 'bold';\n\n /** Disables interaction. */\n @Prop() isInactive: boolean = false;\n\n /** Native button type. */\n @Prop() type: 'button' | 'submit' | 'reset' = 'button';\n\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n\n @Event() dsClick!: EventEmitter<MouseEvent>;\n\n private buttonEl: HTMLButtonElement | null = null;\n\n @Method()\n async setFocus() {\n this.buttonEl?.focus();\n }\n\n private handleClick = (event: MouseEvent) => {\n if (this.isInactive) return;\n this.dsClick.emit(event);\n };\n\n private get showIcon(): boolean {\n return this.variant === 'icon' || this.variant === 'icon-label';\n }\n\n private get showLabel(): boolean {\n return this.variant === 'label' || this.variant === 'icon-label';\n }\n\n private get accessibleName(): string | undefined {\n if (this.ariaLabel) return this.ariaLabel;\n if (this.showLabel && this.label) return undefined;\n if (this.variant === 'icon') return this.icon || 'action';\n return this.label || 'action';\n }\n\n render() {\n const textVariant = CONTROL_TEXT_VARIANT[this.size];\n const iconSize = ICON_SIZE[this.size];\n\n const cls: Record<string, boolean> = {\n 'button-filled': true,\n 'ds-focus-ring-inset': true,\n 'ds-interaction-fill': !this.isInactive,\n /* Bold is the default filled contrast — on-bold interaction tokens. */\n 'ds-interaction-fill--on-bold': this.contrast === 'bold',\n 'ds-interaction-fill--on-strong': this.contrast === 'strong',\n 'ds-interaction-fill--on-medium': this.contrast === 'medium',\n /* faint → default app interaction tokens (no --on-*). */\n 'ds-control-inactive': this.isInactive,\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n 'button-filled--icon': this.variant === 'icon',\n 'button-filled--label': this.variant === 'label',\n 'button-filled--icon-label': this.variant === 'icon-label',\n [`button-filled--intent-${this.intent}`]: true,\n [`button-filled--contrast-${this.contrast}`]: this.contrast !== 'bold',\n };\n\n return (\n <Host\n class={{\n 'button-filled-host': true,\n 'button-filled-host--icon': this.variant === 'icon',\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n ...controlWidthClass(this.width),\n }}\n tabIndex={-1}\n >\n <button\n ref={el => {\n this.buttonEl = el ?? null;\n }}\n type={this.type}\n class={cls}\n disabled={this.isInactive}\n aria-label={this.accessibleName}\n onClick={this.handleClick}\n >\n {this.showIcon && (\n <span class=\"button-filled__icon-wrap ds-interaction-fill__content\">\n <ds-icon name={this.icon} size={iconSize} color=\"inherit\" />\n </span>\n )}\n {this.showLabel && (\n <ds-text\n class=\"button-filled__label ds-interaction-fill__content\"\n as=\"span\"\n variant={textVariant}\n emphasis\n color=\"inherit\"\n >\n {this.label}\n </ds-text>\n )}\n </button>\n </Host>\n );\n }\n}\n"],"mappings":"kNAAA,MAAMA,EAAkB,IAAM,85eC0B9B,MAAMC,EAA0D,CAC9DC,GAAI,KACJC,GAAI,KACJC,GAAI,M,MAQOC,EAAYC,EAAA,MAAAD,UAAAE,EALzB,WAAAC,CAAAC,G,2EAYUC,KAAAC,QAA+B,QAG/BD,KAAAE,KAAyB,KAGzBF,KAAAG,MAA2B,MAG3BH,KAAAI,MAAgB,GAGhBJ,KAAAK,KAAe,GAGfL,KAAAM,OAA6B,QAM7BN,KAAAO,SAAiC,OAGjCP,KAAAQ,WAAsB,MAGtBR,KAAAS,KAAsC,SAEXT,KAAAU,UAA2B,KAItDV,KAAAW,SAAqC,KAOrCX,KAAAY,YAAeC,IACrB,GAAIb,KAAKQ,WAAY,OACrBR,KAAKc,QAAQC,KAAKF,EAAM,CAoF3B,CA1FC,cAAMG,GACJhB,KAAKW,UAAUM,O,CAQjB,YAAYC,GACV,OAAOlB,KAAKC,UAAY,QAAUD,KAAKC,UAAY,Y,CAGrD,aAAYkB,GACV,OAAOnB,KAAKC,UAAY,SAAWD,KAAKC,UAAY,Y,CAGtD,kBAAYmB,GACV,GAAIpB,KAAKU,UAAW,OAAOV,KAAKU,UAChC,GAAIV,KAAKmB,WAAanB,KAAKI,MAAO,OAAOiB,UACzC,GAAIrB,KAAKC,UAAY,OAAQ,OAAOD,KAAKK,MAAQ,SACjD,OAAOL,KAAKI,OAAS,Q,CAGvB,MAAAkB,GACE,MAAMC,EAAcC,EAAqBxB,KAAKE,MAC9C,MAAMuB,EAAWlC,EAAUS,KAAKE,MAEhC,MAAMwB,EAA+B,CACnC,gBAAiB,KACjB,sBAAuB,KACvB,uBAAwB1B,KAAKQ,WAE7B,+BAAgCR,KAAKO,WAAa,OAClD,iCAAkCP,KAAKO,WAAa,SACpD,iCAAkCP,KAAKO,WAAa,SAEpD,sBAAuBP,KAAKQ,WAC5B,iBAAkBR,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,KAChC,sBAAuBF,KAAKC,UAAY,OACxC,uBAAwBD,KAAKC,UAAY,QACzC,4BAA6BD,KAAKC,UAAY,aAC9C,CAAC,yBAAyBD,KAAKM,UAAW,KAC1C,CAAC,2BAA2BN,KAAKO,YAAaP,KAAKO,WAAa,QAGlE,OACEoB,EAACC,EAAI,CAAAC,IAAA,2CACHC,MAAO,CACL,qBAAsB,KACtB,2BAA4B9B,KAAKC,UAAY,OAC7C,iBAAkBD,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,KAChC,iBAAkBF,KAAKE,OAAS,QAC7B6B,EAAkB/B,KAAKG,QAE5B6B,UAAU,GAEVL,EAAA,UAAAE,IAAA,2CACEI,IAAKC,IACHlC,KAAKW,SAAWuB,GAAM,IAAI,EAE5BzB,KAAMT,KAAKS,KACXqB,MAAOJ,EACPS,SAAUnC,KAAKQ,WAAU,aACbR,KAAKoB,eACjBgB,QAASpC,KAAKY,aAEbZ,KAAKkB,UACJS,EAAA,QAAAE,IAAA,2CAAMC,MAAM,yDACVH,EAAA,WAAAE,IAAA,2CAASQ,KAAMrC,KAAKK,KAAMH,KAAMuB,EAAUa,MAAM,aAGnDtC,KAAKmB,WACJQ,EAAA,WAAAE,IAAA,2CACEC,MAAM,oDACNS,GAAG,OACHtC,QAASsB,EACTiB,SAAQ,KACRF,MAAM,WAELtC,KAAKI,Q","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ import{p as i,H as e,c as s,h as n,a as t,t as o}from"./index.js";import{d as r}from"./p-CHcS6Z4V.js";import{d as a}from"./p-ORF34W29.js";import{d}from"./p-B4gGwfix.js";import{d as c}from"./p-emacH2W5.js";import{a as l,T as u}from"./p-drBA73M_.js";import{r as h}from"./p-BWUTr_XN.js";import{r as m}from"./p-BvmooLHV.js";function f(i){const{anchorRect:e,popupWidth:s,popupHeight:n,side:t,align:o,sideOffsetPx:r,alignOffsetPx:a,viewportPadPx:d,viewportWidth:c,viewportHeight:l}=i;let u=0;let h=0;switch(t){case"top":h=e.top-n-r;u=o==="start"?e.left+a:o==="end"?e.right-s+a:e.left+e.width/2-s/2+a;break;case"bottom":h=e.bottom+r;u=o==="start"?e.left+a:o==="end"?e.right-s+a:e.left+e.width/2-s/2+a;break;case"left":u=e.left-s-r;h=o==="start"?e.top+a:o==="end"?e.bottom-n+a:e.top+e.height/2-n/2+a;break;case"right":u=e.right+r;h=o==="start"?e.top+a:o==="end"?e.bottom-n+a:e.top+e.height/2-n/2+a;break}return{x:Math.min(Math.max(u,d),c-s-d),y:Math.min(Math.max(h,d),l-n-d)}}function g(i){return"variant"in i&&i.variant==="gradient-picker"}const v=()=>`.sc-ds-menu-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-menu: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-menu{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-menu:focus-visible{outline:none}.ds-focus-ring-inset.sc-ds-menu: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-menu{outline:none}.ds-focus-ring-inset.ds-focus-ring--visible.sc-ds-menu::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-menu-h,.ds-interaction-fill.sc-ds-menu{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);--ds-interaction-border-width:0px;--ds-interaction-border-color:transparent}.ds-interaction-fill.sc-ds-menu-h::before,.ds-interaction-fill.sc-ds-menu::before,.ds-interaction-fill.sc-ds-menu-h::after,.ds-interaction-fill.sc-ds-menu::after{content:'';position:absolute;inset:0;border-radius:inherit;background:transparent;pointer-events:none;transition:none}.ds-interaction-fill.sc-ds-menu-h::before,.ds-interaction-fill.sc-ds-menu::before{z-index:1}.ds-interaction-fill.sc-ds-menu-h::after,.ds-interaction-fill.sc-ds-menu::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-menu-h,.ds-interaction-fill--bordered.sc-ds-menu{--ds-interaction-border-width:var(--dimension-stroke-width-012);--ds-interaction-border-color:var(--color-border-secondary)}.ds-interaction-fill--selected.sc-ds-menu-h::before,.ds-interaction-fill--selected.sc-ds-menu::before{background:var(--ds-interaction-active)}.ds-interaction-fill--selected.sc-ds-menu-h,.ds-interaction-fill--selected.sc-ds-menu{--ds-interaction-dot-ring:var(--ds-interaction-active)}.ds-interaction-fill.sc-ds-menu-h:hover:not(:disabled)::after,.ds-interaction-fill.sc-ds-menu:hover:not(:disabled)::after{background:var(--ds-interaction-hover)}.ds-interaction-fill.sc-ds-menu-h:active:not(:disabled)::after,.ds-interaction-fill.sc-ds-menu:active:not(:disabled)::after{background:var(--ds-interaction-pressed)}.ds-interaction-fill.sc-ds-menu-h>.ds-interaction-fill__content.sc-ds-menu,.ds-interaction-fill.sc-ds-menu>.ds-interaction-fill__content.sc-ds-menu,.ds-interaction-fill__content.sc-ds-menu{position:relative;z-index:2}.ds-interaction-fill--on-medium.sc-ds-menu-h,.ds-interaction-fill--on-medium.sc-ds-menu{--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-menu-h,.ds-interaction-fill--on-bold.sc-ds-menu{--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-menu-h,.ds-interaction-fill--on-strong.sc-ds-menu{--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-always-dark.sc-ds-menu-h,.ds-interaction-fill--on-always-dark.sc-ds-menu{--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-menu-h,.ds-interaction-fill--on-navigation.sc-ds-menu{--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)}.ds-control-inactive.sc-ds-menu-h,.ds-control-inactive.sc-ds-menu{opacity:0.25;pointer-events:none;cursor:not-allowed}.ds-control--md.sc-ds-menu-h,.ds-control--md.sc-ds-menu{--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-menu-h,.ds-control--sm.sc-ds-menu{--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-menu-h,.ds-control--xs.sc-ds-menu{--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)}.menu-popup.sc-ds-menu{box-sizing:border-box;display:flex;flex-direction:column;min-width:var(--dimension-menu-width-xs);max-width:var(--dimension-panel-width-lg);overflow:hidden;background-color:var(--color-background-primary);border-radius:var(--dimension-radius-075);box-shadow:var(--effect-shadow-elevated-floating);animation:menuFadeIn var(--effect-motion-short-2) forwards;backface-visibility:hidden;will-change:transform;text-align:start}.menu-popup.sc-ds-menu::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;box-shadow:var(--effect-highlight-elevated-floating)}.menu-popup--closing.sc-ds-menu{animation:menuFadeOut var(--effect-motion-short-2) forwards}@keyframes menuFadeIn{from{opacity:0;transform:inherit scale(0.97)}to{opacity:1}}@keyframes menuFadeOut{from{opacity:1}to{opacity:0}}.menu-section.sc-ds-menu{display:flex;flex-direction:column;gap:var(--dimension-space-050);padding:var(--dimension-space-050)}.menu-section--divided.sc-ds-menu{border-bottom:var(--dimension-stroke-width-015) solid var(--color-border-tertiary)}ds-text.section-header.sc-ds-menu{display:flex;align-items:center;box-sizing:border-box;height:var(--ds-control-height, var(--dimension-size-400));padding:0 calc( var(--ds-control-padding-inline, var(--dimension-space-075)) + var(--ds-control-label-inset, var(--dimension-space-025)) );text-align:start;-webkit-user-select:none;user-select:none}.menu-item.sc-ds-menu{display:flex;align-items:center;gap:var(--ds-control-gap, var(--dimension-space-050));width:100%;height:var(--ds-control-height, var(--dimension-size-400));padding:0 var(--ds-control-padding-inline, var(--dimension-space-075));box-sizing:border-box;border:none;border-radius:var(--ds-control-radius, var(--dimension-radius-025));background:transparent;cursor:pointer;-webkit-user-select:none;user-select:none;text-align:left;color:inherit}.menu-item.sc-ds-menu:has(.menu-item__subtext){height:auto;min-height:var(--ds-control-height, var(--dimension-size-400));padding-block:var(--ds-control-padding-inline, var(--dimension-space-075));align-items:flex-start}.menu-item--destructive.sc-ds-menu .menu-item__label.sc-ds-menu{color:var(--color-foreground-bold-negative) !important}.menu-item__content.sc-ds-menu{display:flex;flex:1;flex-direction:column;gap:var(--dimension-space-025);min-width:0}ds-text.menu-item__label.sc-ds-menu{padding:0 var(--ds-control-label-inset, var(--dimension-space-025))}.menu-item__subtext.sc-ds-menu,ds-text.menu-item__subtext.sc-ds-menu{padding:0 var(--ds-control-label-inset, var(--dimension-space-025))}.menu-item__dot-box.sc-ds-menu{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ds-control-icon, var(--dimension-iconography-md));height:var(--ds-control-icon, var(--dimension-iconography-md));pointer-events:none}.menu-item__toggle.sc-ds-menu{position:relative;flex-shrink:0;width:calc(var(--dimension-size-400) + var(--dimension-size-050));height:var(--dimension-size-250);border-radius:var(--dimension-radius-125);background-color:var(--color-background-translucent);transition:background-color var(--effect-motion-short-2)}.menu-item__toggle--on.sc-ds-menu{background-color:var(--color-background-medium-brand)}.menu-item__toggle-thumb.sc-ds-menu{position:absolute;top:var(--dimension-space-025);left:var(--dimension-space-025);width:var(--dimension-size-200);height:var(--dimension-size-200);border-radius:50%;background-color:var(--color-foreground-on-bold-background-primary);transition:transform var(--effect-motion-short-2)}.menu-item__toggle--on.sc-ds-menu .menu-item__toggle-thumb.sc-ds-menu{transform:translateX(var(--dimension-offset-200, 16px))}`;const p=8;const b=i(class i extends e{constructor(i){super();if(i!==false){this.__registerHost()}this.dsClose=s(this,"dsClose");this.dsSelect=s(this,"dsSelect");this.dsGradientSelect=s(this,"dsGradientSelect");this.open=false;this.items=[];this.sections=[];this.side="bottom";this.align="start";this.sideOffset=l.space050;this.alignOffset=0;this.initialFocusVisible=false;this.menuLabel="Menu";this.shouldRender=false;this.closing=false;this.pos={x:0,y:0};this.focusedIndex=0;this.positionReady=false;this.focusRingVisible=false;this.clickOutsideHandler=null;this.scrollResizeHandler=null;this.closeTimer=null;this.itemEls=[];this.positionRetryRaf=null;this.listenersReady=false}componentDidLoad(){if(this.open)this.onOpenChange(true)}disconnectedCallback(){this.cancelPositionRetry();this.teardownListeners()}onOpenChange(i){if(i){this.teardownListeners();this.shouldRender=true;this.closing=false;this.positionReady=false;this.listenersReady=false;this.focusRingVisible=this.initialFocusVisible;this.listenersReady=true;this.setupListeners();this.schedulePositionUpdate((()=>{this.focusInitialItem()}))}else if(this.shouldRender){this.cancelPositionRetry();this.closing=true;this.teardownListeners();this.listenersReady=false;this.closeTimer=setTimeout((()=>{this.shouldRender=false;this.closing=false;this.closeTimer=null}),this.closeAnimationMs)}}onAnchorChange(){if(this.open)this.schedulePositionUpdate()}onPositionPropsChange(){if(this.open)this.schedulePositionUpdate()}get viewportPadPx(){return h(u.space050,u.space050)}get sideOffsetPx(){return h(this.sideOffset,u.space050)}get alignOffsetPx(){return h(this.alignOffset,0)}get popupFallbackWidthPx(){return h(u.menuWidthXs,u.menuWidthXs)}get popupFallbackHeightPx(){return h(u.menuFallbackHeight,u.menuFallbackHeight)}get closeAnimationMs(){return m(u.motionShort2,u.animationDurationShort3)}get resolvedAnchor(){if(this.anchor)return this.anchor;if(this.anchorId)return document.getElementById(this.anchorId);return null}get activeSections(){if(this.sections.length>0)return this.sections;if(this.items.length>0)return[{items:this.items}];return[]}get flatItems(){return this.activeSections.flatMap((i=>g(i)?[]:i.items))}cancelPositionRetry(){if(this.positionRetryRaf!==null){cancelAnimationFrame(this.positionRetryRaf);this.positionRetryRaf=null}}schedulePositionUpdate(i){if(!this.open)return;this.cancelPositionRetry();this.positionReady=false;let e=p;const s=()=>{this.positionRetryRaf=null;if(!this.open)return;if(this.calculatePosition()){this.positionReady=true;i?.();return}if(e>0){e-=1;this.positionRetryRaf=requestAnimationFrame(s)}};this.positionRetryRaf=requestAnimationFrame(s)}calculatePosition(){const i=this.resolvedAnchor;if(!i)return false;const e=this.el.querySelector(".menu-popup");if(!e)return false;this.pos=f({anchorRect:i.getBoundingClientRect(),popupWidth:e.offsetWidth||this.popupFallbackWidthPx,popupHeight:e.offsetHeight||this.popupFallbackHeightPx,side:this.side,align:this.align,sideOffsetPx:this.sideOffsetPx,alignOffsetPx:this.alignOffsetPx,viewportPadPx:this.viewportPadPx,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight});return true}focusInitialItem(){const i=this.flatItems;const e=i.findIndex((i=>i.isSelected&&!i.isInactive));const s=i.findIndex((i=>!i.isInactive));this.focusedIndex=e>=0?e:s>=0?s:0;requestAnimationFrame((()=>{const i=this.el.querySelectorAll(".menu-item");i[this.focusedIndex]?.focus()}))}setupListeners(){this.clickOutsideHandler=i=>{const e=i.target;const s=this.el.querySelector(".menu-popup");const n=this.resolvedAnchor;if(s?.contains(e)||n?.contains(e))return;this.close()};this.scrollResizeHandler=()=>{if(this.shouldRender&&!this.closing)this.calculatePosition()};document.addEventListener("mousedown",this.clickOutsideHandler,true);window.addEventListener("scroll",this.scrollResizeHandler,true);window.addEventListener("resize",this.scrollResizeHandler)}teardownListeners(){if(this.clickOutsideHandler){document.removeEventListener("mousedown",this.clickOutsideHandler,true);this.clickOutsideHandler=null}if(this.scrollResizeHandler){window.removeEventListener("scroll",this.scrollResizeHandler,true);window.removeEventListener("resize",this.scrollResizeHandler);this.scrollResizeHandler=null}if(this.closeTimer){clearTimeout(this.closeTimer);this.closeTimer=null}}close(){this.resolvedAnchor?.focus();this.dsClose.emit();this.open=false;this.onOpenChange(false)}handleKeyDown(i){if(!this.shouldRender||this.closing)return;const e=this.flatItems;const s=e.map(((i,e)=>({it:i,i:e}))).filter((({it:i})=>!i.isInactive)).map((({i})=>i));if(!s.length)return;const n=s.indexOf(this.focusedIndex);const t=n<0?0:n;switch(i.key){case"ArrowDown":i.preventDefault();i.stopPropagation();this.focusRingVisible=true;this.focusedIndex=s[(t+1)%s.length];this.focusItem(this.focusedIndex);break;case"ArrowUp":i.preventDefault();i.stopPropagation();this.focusRingVisible=true;this.focusedIndex=s[(t-1+s.length)%s.length];this.focusItem(this.focusedIndex);break;case"Home":i.preventDefault();i.stopPropagation();this.focusRingVisible=true;this.focusedIndex=s[0];this.focusItem(this.focusedIndex);break;case"End":i.preventDefault();i.stopPropagation();this.focusRingVisible=true;this.focusedIndex=s[s.length-1];this.focusItem(this.focusedIndex);break;case"Escape":i.preventDefault();this.close();break;case"Tab":i.preventDefault();this.close();break}}focusItem(i){const e=this.el.querySelectorAll(".menu-item");e[i]?.focus()}handleItemClick(i){if(i.isInactive)return;this.dsSelect.emit(i)}handleGradientSelect(i){this.dsGradientSelect.emit(i)}render(){if(!this.shouldRender)return n(t,{style:{display:"contents"}});const i=this.activeSections;let e=0;const s={position:"fixed",left:"0",top:"0",transform:`translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,zIndex:"9998",visibility:this.positionReady?"visible":"hidden"};if(this.menuWidth)s["width"]=this.menuWidth;if(this.minWidth)s["min-width"]=this.minWidth;return n(t,{style:{display:"contents"}},n("div",{class:{"menu-popup":true,"menu-popup--closing":this.closing},style:s,role:"menu","aria-label":this.menuLabel,"aria-orientation":"vertical"},i.map(((s,t)=>n("div",{key:t,class:{"menu-section":true,"menu-section--divided":t<i.length-1,"menu-section--gradient-picker":g(s)},role:s.header?"group":undefined,"aria-label":s.header},s.header&&n("ds-text",{class:"section-header ds-control--md",as:"span",variant:"text-body-small",emphasis:true,color:"primary","aria-hidden":"true"},s.header),g(s)?n("ds-shell-gradient-picker",{value:s.value,onDsChange:i=>{i.stopPropagation();this.handleGradientSelect(i.detail)}}):s.items.map((i=>{const s=e++;const t=this.focusedIndex===s;return n("button",{key:s,type:"button",class:{"menu-item":true,"ds-control--md":true,"ds-focus-ring-inset":true,"ds-focus-ring--visible":t&&this.focusRingVisible,"ds-interaction-fill":!i.isInactive,"ds-interaction-fill--selected":!!i.isSelected&&!i.isInactive,"menu-item--selected":!!i.isSelected,"ds-control-inactive":!!i.isInactive,"menu-item--destructive":!!i.isDestructive,"menu-item--focused":t},role:"menuitem","aria-current":i.isSelected?"true":undefined,disabled:i.isInactive,tabIndex:t?0:-1,onMouseDown:()=>{this.focusRingVisible=false},onClick:()=>this.handleItemClick(i),onFocus:()=>{this.focusedIndex=s}},n("div",{class:"menu-item__content ds-interaction-fill__content"},n("ds-text",{class:"menu-item__label",as:"span",variant:"text-body-medium",emphasis:!!i.isSelected,color:i.isSelected?"primary":"secondary"},i.label),i.subtext&&n("ds-text",{class:"menu-item__subtext",as:"span",variant:"text-body-small",color:"secondary"},i.subtext)),i.dot&&n("span",{class:"menu-item__dot-box ds-interaction-fill__content","aria-hidden":"true"},n("ds-badge",{class:"menu-item__dot",variant:"dot",background:i.isSelected&&!i.isInactive?"var(--ds-interaction-active)":"var(--color-background-primary)",label:""})),i.showToggle&&n("div",{class:{"menu-item__toggle":true,"menu-item__toggle--on":!!i.toggleValue,"ds-interaction-fill__content":true},"aria-hidden":"true"},n("div",{class:"menu-item__toggle-thumb"})))})))))))}get el(){return this}static get watchers(){return{open:[{onOpenChange:0}],anchor:[{onAnchorChange:0}],anchorId:[{onAnchorChange:0}],side:[{onPositionPropsChange:0}],align:[{onPositionPropsChange:0}],sideOffset:[{onPositionPropsChange:0}],alignOffset:[{onPositionPropsChange:0}]}}static get style(){return v()}},[2,"ds-menu",{open:[1028],items:[16],sections:[16],side:[1],align:[1],sideOffset:[8,"side-offset"],alignOffset:[8,"align-offset"],menuWidth:[1,"menu-width"],minWidth:[1,"min-width"],anchor:[16],anchorId:[1,"anchor-id"],initialFocusVisible:[4,"initial-focus-visible"],menuLabel:[1,"menu-label"],shouldRender:[32],closing:[32],pos:[32],focusedIndex:[32],positionReady:[32],focusRingVisible:[32]},[[0,"keydown","handleKeyDown"]],{open:[{onOpenChange:0}],anchor:[{onAnchorChange:0}],anchorId:[{onAnchorChange:0}],side:[{onPositionPropsChange:0}],align:[{onPositionPropsChange:0}],sideOffset:[{onPositionPropsChange:0}],alignOffset:[{onPositionPropsChange:0}]}]);function x(){if(typeof customElements==="undefined"){return}const i=["ds-menu","ds-badge","ds-shell-gradient-picker","ds-shell-gradient-swatch","ds-text"];i.forEach((i=>{switch(i){case"ds-menu":if(!customElements.get(o(i))){customElements.define(o(i),b)}break;case"ds-badge":if(!customElements.get(o(i))){r()}break;case"ds-shell-gradient-picker":if(!customElements.get(o(i))){a()}break;case"ds-shell-gradient-swatch":if(!customElements.get(o(i))){d()}break;case"ds-text":if(!customElements.get(o(i))){c()}break}}))}x();export{b as M,x as d};
2
+ //# sourceMappingURL=p-DLcnbk3Z.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["computeMenuPosition","input","anchorRect","a","popupWidth","pw","popupHeight","ph","side","align","sideOffsetPx","alignOffsetPx","viewportPadPx","vpPad","viewportWidth","viewportHeight","x","y","top","left","right","width","bottom","height","Math","min","max","isMenuGradientPickerSection","section","variant","menuCss","POSITION_RETRY_BUDGET","Menu","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","open","items","sections","sideOffset","TOKEN_CSS_LENGTHS","space050","alignOffset","initialFocusVisible","menuLabel","shouldRender","closing","pos","focusedIndex","positionReady","focusRingVisible","clickOutsideHandler","scrollResizeHandler","closeTimer","itemEls","positionRetryRaf","listenersReady","componentDidLoad","onOpenChange","disconnectedCallback","cancelPositionRetry","teardownListeners","isOpen","setupListeners","schedulePositionUpdate","focusInitialItem","setTimeout","closeAnimationMs","onAnchorChange","onPositionPropsChange","resolveCssLengthPx","TOKEN_DEFAULTS","popupFallbackWidthPx","menuWidthXs","popupFallbackHeightPx","menuFallbackHeight","resolveCssTimeMs","motionShort2","animationDurationShort3","resolvedAnchor","anchor","anchorId","document","getElementById","activeSections","length","flatItems","flatMap","cancelAnimationFrame","onReady","remaining","attempt","calculatePosition","requestAnimationFrame","anchorEl","popup","el","querySelector","getBoundingClientRect","offsetWidth","offsetHeight","window","innerWidth","innerHeight","flat","selectedIdx","findIndex","it","isSelected","isInactive","firstEnabledIdx","btns","querySelectorAll","focus","e","t","target","contains","close","addEventListener","removeEventListener","clearTimeout","dsClose","emit","handleKeyDown","enabled","map","i","filter","cur","indexOf","safe","key","preventDefault","stopPropagation","focusItem","idx","handleItemClick","item","dsSelect","handleGradientSelect","preset","dsGradientSelect","render","h","Host","style","display","flatIdx","popupStyle","position","transform","round","zIndex","visibility","menuWidth","minWidth","class","role","si","header","undefined","as","emphasis","color","value","onDsChange","detail","isFocused","type","isDestructive","disabled","tabIndex","onMouseDown","onClick","onFocus","label","subtext","dot","background","showToggle","toggleValue"],"sources":["src/wc/components/Menu/menu-position.ts","src/wc/components/Menu/menu-types.ts","src/wc/components/Menu/Menu.css?tag=ds-menu&encapsulation=scoped","src/wc/components/Menu/Menu.tsx"],"sourcesContent":["export type MenuSide = 'top' | 'right' | 'bottom' | 'left';\nexport type MenuAlign = 'start' | 'center' | 'end';\n\nexport interface MenuPositionInput {\n anchorRect: Pick<DOMRectReadOnly, 'top' | 'left' | 'right' | 'bottom' | 'width' | 'height'>;\n popupWidth: number;\n popupHeight: number;\n side: MenuSide;\n align: MenuAlign;\n sideOffsetPx: number;\n alignOffsetPx: number;\n viewportPadPx: number;\n viewportWidth: number;\n viewportHeight: number;\n}\n\n/** Pure layout math for ds-menu — anchor rect + placement props → viewport-fixed x/y. */\nexport function computeMenuPosition(input: MenuPositionInput): { x: number; y: number } {\n const {\n anchorRect: a,\n popupWidth: pw,\n popupHeight: ph,\n side,\n align,\n sideOffsetPx,\n alignOffsetPx,\n viewportPadPx: vpPad,\n viewportWidth,\n viewportHeight,\n } = input;\n\n let x = 0;\n let y = 0;\n\n switch (side) {\n case 'top':\n y = a.top - ph - sideOffsetPx;\n x =\n align === 'start'\n ? a.left + alignOffsetPx\n : align === 'end'\n ? a.right - pw + alignOffsetPx\n : a.left + a.width / 2 - pw / 2 + alignOffsetPx;\n break;\n case 'bottom':\n y = a.bottom + sideOffsetPx;\n x =\n align === 'start'\n ? a.left + alignOffsetPx\n : align === 'end'\n ? a.right - pw + alignOffsetPx\n : a.left + a.width / 2 - pw / 2 + alignOffsetPx;\n break;\n case 'left':\n x = a.left - pw - sideOffsetPx;\n y =\n align === 'start'\n ? a.top + alignOffsetPx\n : align === 'end'\n ? a.bottom - ph + alignOffsetPx\n : a.top + a.height / 2 - ph / 2 + alignOffsetPx;\n break;\n case 'right':\n x = a.right + sideOffsetPx;\n y =\n align === 'start'\n ? a.top + alignOffsetPx\n : align === 'end'\n ? a.bottom - ph + alignOffsetPx\n : a.top + a.height / 2 - ph / 2 + alignOffsetPx;\n break;\n }\n\n return {\n x: Math.min(Math.max(x, vpPad), viewportWidth - pw - vpPad),\n y: Math.min(Math.max(y, vpPad), viewportHeight - ph - vpPad),\n };\n}\n","import type { ShellGradientPreset } from '../../nav/shell-gradient-presets';\n\nexport type { MenuAlign, MenuSide } from './menu-position';\nexport {\n PANEL_NAV_USER_MENU_PLACEMENT,\n type MenuPlacement,\n} from './menu-placement';\n\nexport interface MenuItemData {\n label: string;\n value?: string;\n subtext?: string;\n /** Show a supplemental brand notification dot. */\n dot?: boolean;\n isSelected?: boolean;\n isInactive?: boolean;\n isDestructive?: boolean;\n showToggle?: boolean;\n toggleValue?: boolean;\n}\n\nexport interface MenuItemsSection {\n header?: string;\n items: MenuItemData[];\n}\n\nexport interface MenuGradientPickerSection {\n header?: string;\n variant: 'gradient-picker';\n value: ShellGradientPreset;\n}\n\nexport type MenuSection = MenuItemsSection | MenuGradientPickerSection;\n\nexport function isMenuGradientPickerSection(\n section: MenuSection,\n): section is MenuGradientPickerSection {\n return 'variant' in section && section.variant === 'gradient-picker';\n}\n\nexport type { ShellGradientPreset };\n","@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n\n/* ── Popup shell ─────────────────────────────────────────────────────────── */\n\n.menu-popup {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: var(--dimension-menu-width-xs);\n max-width: var(--dimension-panel-width-lg);\n overflow: hidden;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n /* Split elevation: shadow on shell, inset highlight on ::after (combined token clips with overflow:hidden). */\n box-shadow: var(--effect-shadow-elevated-floating);\n animation: menuFadeIn var(--effect-motion-short-2) forwards;\n backface-visibility: hidden;\n will-change: transform;\n /*\n * Neutralize the host `align` prop. Stencil reflects it as the legacy HTML\n * `align` attribute, which browsers map to `text-align` on ds-menu. Menu\n * items already force left; section headers / other content must not inherit\n * `end` once ds-text is the full-width layout box.\n */\n text-align: start;\n}\n\n.menu-popup::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n box-shadow: var(--effect-highlight-elevated-floating);\n}\n\n.menu-popup--closing {\n animation: menuFadeOut var(--effect-motion-short-2) forwards;\n}\n\n@keyframes menuFadeIn {\n from { opacity: 0; transform: inherit scale(0.97); }\n to { opacity: 1; }\n}\n\n@keyframes menuFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n/* ── Sections ────────────────────────────────────────────────────────────── */\n\n.menu-section {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-050);\n}\n\n.menu-section--divided {\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-tertiary);\n}\n\nds-text.section-header {\n display: flex;\n align-items: center;\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n /* Same inset as menu-item padding-inline + menu-item__label inset. */\n padding: 0 calc(\n var(--ds-control-padding-inline, var(--dimension-space-075)) +\n var(--ds-control-label-inset, var(--dimension-space-025))\n );\n text-align: start;\n -webkit-user-select: none;\n user-select: none;\n}\n\n/* ── Items (md control-density + interaction-fill + inset focus) ─────────── */\n\n.menu-item {\n display: flex;\n align-items: center;\n gap: var(--ds-control-gap, var(--dimension-space-050));\n width: 100%;\n height: var(--ds-control-height, var(--dimension-size-400));\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n box-sizing: border-box;\n border: none;\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n background: transparent;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n color: inherit;\n /* Hover/press/selected: `.ds-interaction-fill` (+ `--selected`). */\n}\n\n/* Subtext rows grow past the density height. */\n.menu-item:has(.menu-item__subtext) {\n height: auto;\n min-height: var(--ds-control-height, var(--dimension-size-400));\n padding-block: var(--ds-control-padding-inline, var(--dimension-space-075));\n align-items: flex-start;\n}\n\n/* Inactive: `.ds-control-inactive` (25% opacity). */\n\n.menu-item--destructive .menu-item__label {\n /* Beat ds-text color-* host classes for destructive rows. */\n color: var(--color-foreground-bold-negative) !important;\n}\n\n.menu-item__content {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n/* Colors come from ds-text color prop; keep padding on the metric box. */\nds-text.menu-item__label {\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n}\n\n.menu-item__subtext,\nds-text.menu-item__subtext {\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n}\n\n/* Standard md icon zone keeps the dot aligned with other control suffixes. */\n.menu-item__dot-box {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--ds-control-icon, var(--dimension-iconography-md));\n height: var(--ds-control-icon, var(--dimension-iconography-md));\n pointer-events: none;\n}\n\n/* ── Toggle suffix ───────────────────────────────────────────────────────── */\n\n.menu-item__toggle {\n position: relative;\n flex-shrink: 0;\n width: calc(var(--dimension-size-400) + var(--dimension-size-050));\n height: var(--dimension-size-250);\n border-radius: var(--dimension-radius-125);\n background-color: var(--color-background-translucent);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on {\n background-color: var(--color-background-medium-brand);\n}\n\n.menu-item__toggle-thumb {\n position: absolute;\n top: var(--dimension-space-025);\n left: var(--dimension-space-025);\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n border-radius: 50%;\n background-color: var(--color-foreground-on-bold-background-primary);\n transition: transform var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on .menu-item__toggle-thumb {\n transform: translateX(var(--dimension-offset-200, 16px));\n}\n","import { Component, Prop, State, Event, EventEmitter, Element, Watch, Listen, h, Host } from '@stencil/core';\nimport { resolveCssLengthPx, resolveCssTimeMs, TOKEN_CSS_LENGTHS, TOKEN_DEFAULTS } from '../../utils';\nimport { computeMenuPosition, type MenuAlign, type MenuSide } from './menu-position';\nimport type { MenuItemData, MenuSection } from './menu-types';\nimport { isMenuGradientPickerSection } from './menu-types';\nimport type { ShellGradientPreset } from '../../nav/shell-gradient-presets';\n\n/** rAF retries while the popup mounts or the anchor resolves. */\nconst POSITION_RETRY_BUDGET = 8;\n\n@Component({\n tag: 'ds-menu',\n styleUrl: 'Menu.css',\n scoped: true,\n})\nexport class Menu {\n @Element() el!: HTMLElement;\n\n @Prop({ mutable: true }) open: boolean = false;\n @Prop() items: MenuItemData[] = [];\n @Prop() sections: MenuSection[] = [];\n @Prop() side: MenuSide = 'bottom';\n @Prop() align: MenuAlign = 'start';\n /** Gap between anchor and menu — number (px) or TokoMo length (`var(--dimension-space-050)`, etc.). */\n @Prop() sideOffset: number | string = TOKEN_CSS_LENGTHS.space050;\n /** Cross-axis offset — number (px) or TokoMo length. */\n @Prop() alignOffset: number | string = 0;\n @Prop() menuWidth: string | undefined;\n @Prop() minWidth: string | undefined;\n /** External trigger element to position against. Set via JS: menuEl.anchor = buttonEl */\n @Prop() anchor: HTMLElement | undefined;\n /** ID of the external trigger element for positioning */\n @Prop() anchorId: string | undefined;\n /** Show a visible ring on the initially focused menu item. Use only when the opener was keyboard-driven. */\n @Prop() initialFocusVisible: boolean = false;\n /** Accessible name for the popup menu. */\n @Prop() menuLabel: string = 'Menu';\n\n @State() private shouldRender: boolean = false;\n @State() private closing: boolean = false;\n @State() private pos: { x: number; y: number } = { x: 0, y: 0 };\n @State() private focusedIndex: number = 0;\n @State() private positionReady: boolean = false;\n @State() private focusRingVisible: boolean = false;\n\n @Event() dsClose!: EventEmitter<void>;\n @Event() dsSelect!: EventEmitter<MenuItemData>;\n /** Emitted when a `gradient-picker` section swatch is chosen. */\n @Event() dsGradientSelect!: EventEmitter<ShellGradientPreset>;\n\n private clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private scrollResizeHandler: (() => void) | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private itemEls: HTMLElement[] = [];\n private positionRetryRaf: number | null = null;\n private listenersReady = false;\n\n componentDidLoad() {\n if (this.open) this.onOpenChange(true);\n }\n\n disconnectedCallback() {\n this.cancelPositionRetry();\n this.teardownListeners();\n }\n\n @Watch('open')\n onOpenChange(isOpen: boolean) {\n if (isOpen) {\n this.teardownListeners();\n this.shouldRender = true;\n this.closing = false;\n this.positionReady = false;\n this.listenersReady = false;\n this.focusRingVisible = this.initialFocusVisible;\n this.listenersReady = true;\n this.setupListeners();\n this.schedulePositionUpdate(() => {\n this.focusInitialItem();\n });\n } else if (this.shouldRender) {\n this.cancelPositionRetry();\n this.closing = true;\n this.teardownListeners();\n this.listenersReady = false;\n this.closeTimer = setTimeout(() => {\n this.shouldRender = false;\n this.closing = false;\n this.closeTimer = null;\n }, this.closeAnimationMs);\n }\n }\n\n @Watch('anchor')\n @Watch('anchorId')\n onAnchorChange() {\n if (this.open) this.schedulePositionUpdate();\n }\n\n @Watch('side')\n @Watch('align')\n @Watch('sideOffset')\n @Watch('alignOffset')\n onPositionPropsChange() {\n if (this.open) this.schedulePositionUpdate();\n }\n\n private get viewportPadPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.space050, TOKEN_DEFAULTS.space050);\n }\n\n private get sideOffsetPx(): number {\n return resolveCssLengthPx(this.sideOffset, TOKEN_DEFAULTS.space050);\n }\n\n private get alignOffsetPx(): number {\n return resolveCssLengthPx(this.alignOffset, 0);\n }\n\n private get popupFallbackWidthPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.menuWidthXs, TOKEN_DEFAULTS.menuWidthXs);\n }\n\n private get popupFallbackHeightPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.menuFallbackHeight, TOKEN_DEFAULTS.menuFallbackHeight);\n }\n\n private get closeAnimationMs(): number {\n return resolveCssTimeMs(TOKEN_DEFAULTS.motionShort2, TOKEN_DEFAULTS.animationDurationShort3);\n }\n\n private get resolvedAnchor(): HTMLElement | null {\n if (this.anchor) return this.anchor;\n if (this.anchorId) return document.getElementById(this.anchorId);\n return null;\n }\n\n private get activeSections(): MenuSection[] {\n if (this.sections.length > 0) return this.sections;\n if (this.items.length > 0) return [{ items: this.items }];\n return [];\n }\n\n private get flatItems(): MenuItemData[] {\n return this.activeSections.flatMap(section =>\n isMenuGradientPickerSection(section) ? [] : section.items,\n );\n }\n\n private cancelPositionRetry() {\n if (this.positionRetryRaf !== null) {\n cancelAnimationFrame(this.positionRetryRaf);\n this.positionRetryRaf = null;\n }\n }\n\n /** Retry until anchor + popup exist — do not reveal at 0,0 on a failed first pass. */\n private schedulePositionUpdate(onReady?: () => void) {\n if (!this.open) return;\n\n this.cancelPositionRetry();\n this.positionReady = false;\n\n let remaining = POSITION_RETRY_BUDGET;\n\n const attempt = () => {\n this.positionRetryRaf = null;\n if (!this.open) return;\n\n if (this.calculatePosition()) {\n this.positionReady = true;\n onReady?.();\n return;\n }\n\n if (remaining > 0) {\n remaining -= 1;\n this.positionRetryRaf = requestAnimationFrame(attempt);\n }\n };\n\n this.positionRetryRaf = requestAnimationFrame(attempt);\n }\n\n /** @returns `true` when anchor and popup were found and `pos` was updated. */\n private calculatePosition(): boolean {\n const anchorEl = this.resolvedAnchor;\n if (!anchorEl) return false;\n const popup = this.el.querySelector('.menu-popup') as HTMLElement | null;\n if (!popup) return false;\n\n this.pos = computeMenuPosition({\n anchorRect: anchorEl.getBoundingClientRect(),\n popupWidth: popup.offsetWidth || this.popupFallbackWidthPx,\n popupHeight: popup.offsetHeight || this.popupFallbackHeightPx,\n side: this.side,\n align: this.align,\n sideOffsetPx: this.sideOffsetPx,\n alignOffsetPx: this.alignOffsetPx,\n viewportPadPx: this.viewportPadPx,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n return true;\n }\n\n /** Focus the selected item when present, otherwise the first enabled item. */\n private focusInitialItem() {\n const flat = this.flatItems;\n const selectedIdx = flat.findIndex(it => it.isSelected && !it.isInactive);\n const firstEnabledIdx = flat.findIndex(it => !it.isInactive);\n this.focusedIndex = selectedIdx >= 0\n ? selectedIdx\n : (firstEnabledIdx >= 0 ? firstEnabledIdx : 0);\n\n requestAnimationFrame(() => {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[this.focusedIndex]?.focus();\n });\n }\n\n private setupListeners() {\n this.clickOutsideHandler = (e: MouseEvent) => {\n const t = e.target as Node;\n const popup = this.el.querySelector('.menu-popup');\n const anchorEl = this.resolvedAnchor;\n if (popup?.contains(t) || anchorEl?.contains(t)) return;\n this.close();\n };\n\n this.scrollResizeHandler = () => {\n if (this.shouldRender && !this.closing) this.calculatePosition();\n };\n\n document.addEventListener('mousedown', this.clickOutsideHandler, true);\n window.addEventListener('scroll', this.scrollResizeHandler, true);\n window.addEventListener('resize', this.scrollResizeHandler);\n }\n\n private teardownListeners() {\n if (this.clickOutsideHandler) {\n document.removeEventListener('mousedown', this.clickOutsideHandler, true);\n this.clickOutsideHandler = null;\n }\n if (this.scrollResizeHandler) {\n window.removeEventListener('scroll', this.scrollResizeHandler, true);\n window.removeEventListener('resize', this.scrollResizeHandler);\n this.scrollResizeHandler = null;\n }\n if (this.closeTimer) {\n clearTimeout(this.closeTimer);\n this.closeTimer = null;\n }\n }\n\n private close() {\n this.resolvedAnchor?.focus();\n this.dsClose.emit();\n this.open = false;\n this.onOpenChange(false);\n }\n\n @Listen('keydown')\n handleKeyDown(e: KeyboardEvent) {\n if (!this.shouldRender || this.closing) return;\n const flat = this.flatItems;\n const enabled = flat.map((it, i) => ({ it, i })).filter(({ it }) => !it.isInactive).map(({ i }) => i);\n if (!enabled.length) return;\n\n const cur = enabled.indexOf(this.focusedIndex);\n const safe = cur < 0 ? 0 : cur;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[(safe + 1) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'ArrowUp':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[(safe - 1 + enabled.length) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'Home':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[0];\n this.focusItem(this.focusedIndex);\n break;\n case 'End':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[enabled.length - 1];\n this.focusItem(this.focusedIndex);\n break;\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'Tab':\n e.preventDefault();\n this.close();\n break;\n }\n }\n\n private focusItem(idx: number) {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[idx]?.focus();\n }\n\n private handleItemClick(item: MenuItemData) {\n if (item.isInactive) return;\n this.dsSelect.emit(item);\n }\n\n private handleGradientSelect(preset: ShellGradientPreset) {\n this.dsGradientSelect.emit(preset);\n }\n\n render() {\n if (!this.shouldRender) return <Host style={{ display: 'contents' }} />;\n\n const sections = this.activeSections;\n let flatIdx = 0;\n\n const popupStyle: Record<string, string> = {\n position: 'fixed',\n left: '0',\n top: '0',\n transform: `translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,\n zIndex: '9998',\n visibility: this.positionReady ? 'visible' : 'hidden',\n };\n\n if (this.menuWidth) popupStyle['width'] = this.menuWidth;\n if (this.minWidth) popupStyle['min-width'] = this.minWidth;\n\n return (\n <Host style={{ display: 'contents' }}>\n <div\n class={{ 'menu-popup': true, 'menu-popup--closing': this.closing }}\n style={popupStyle}\n role=\"menu\"\n aria-label={this.menuLabel}\n aria-orientation=\"vertical\"\n >\n {sections.map((section, si) => (\n <div\n key={si}\n class={{\n 'menu-section': true,\n 'menu-section--divided': si < sections.length - 1,\n 'menu-section--gradient-picker': isMenuGradientPickerSection(section),\n }}\n role={section.header ? 'group' : undefined}\n aria-label={section.header}\n >\n {section.header && (\n <ds-text\n class=\"section-header ds-control--md\"\n as=\"span\"\n variant=\"text-body-small\"\n emphasis\n color=\"primary\"\n aria-hidden=\"true\"\n >\n {section.header}\n </ds-text>\n )}\n {isMenuGradientPickerSection(section) ? (\n <ds-shell-gradient-picker\n value={section.value}\n onDsChange={(e: CustomEvent<ShellGradientPreset>) => {\n e.stopPropagation();\n this.handleGradientSelect(e.detail);\n }}\n />\n ) : (\n section.items.map(item => {\n const idx = flatIdx++;\n const isFocused = this.focusedIndex === idx;\n return (\n <button\n key={idx}\n type=\"button\"\n class={{\n 'menu-item': true,\n 'ds-control--md': true,\n 'ds-focus-ring-inset': true,\n 'ds-focus-ring--visible': isFocused && this.focusRingVisible,\n 'ds-interaction-fill': !item.isInactive,\n 'ds-interaction-fill--selected': !!item.isSelected && !item.isInactive,\n 'menu-item--selected': !!item.isSelected,\n 'ds-control-inactive': !!item.isInactive,\n 'menu-item--destructive': !!item.isDestructive,\n 'menu-item--focused': isFocused,\n }}\n role=\"menuitem\"\n aria-current={item.isSelected ? 'true' : undefined}\n disabled={item.isInactive}\n tabIndex={isFocused ? 0 : -1}\n onMouseDown={() => { this.focusRingVisible = false; }}\n onClick={() => this.handleItemClick(item)}\n onFocus={() => { this.focusedIndex = idx; }}\n >\n <div class=\"menu-item__content ds-interaction-fill__content\">\n <ds-text\n class=\"menu-item__label\"\n as=\"span\"\n variant=\"text-body-medium\"\n emphasis={!!item.isSelected}\n color={item.isSelected ? 'primary' : 'secondary'}\n >\n {item.label}\n </ds-text>\n {item.subtext && (\n <ds-text class=\"menu-item__subtext\" as=\"span\" variant=\"text-body-small\" color=\"secondary\">\n {item.subtext}\n </ds-text>\n )}\n </div>\n {item.dot && (\n <span class=\"menu-item__dot-box ds-interaction-fill__content\" aria-hidden=\"true\">\n <ds-badge\n class=\"menu-item__dot\"\n variant=\"dot\"\n background={item.isSelected && !item.isInactive\n ? 'var(--ds-interaction-active)'\n : 'var(--color-background-primary)'}\n label=\"\"\n />\n </span>\n )}\n {item.showToggle && (\n <div class={{ 'menu-item__toggle': true, 'menu-item__toggle--on': !!item.toggleValue, 'ds-interaction-fill__content': true }} aria-hidden=\"true\">\n <div class=\"menu-item__toggle-thumb\" />\n </div>\n )}\n </button>\n );\n }))}\n </div>\n ))}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["computeMenuPosition","input","anchorRect","a","popupWidth","pw","popupHeight","ph","side","align","sideOffsetPx","alignOffsetPx","viewportPadPx","vpPad","viewportWidth","viewportHeight","x","y","top","left","right","width","bottom","height","Math","min","max","isMenuGradientPickerSection","section","variant","menuCss","POSITION_RETRY_BUDGET","Menu","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","open","items","sections","sideOffset","TOKEN_CSS_LENGTHS","space050","alignOffset","initialFocusVisible","menuLabel","shouldRender","closing","pos","focusedIndex","positionReady","focusRingVisible","clickOutsideHandler","scrollResizeHandler","closeTimer","itemEls","positionRetryRaf","listenersReady","componentDidLoad","onOpenChange","disconnectedCallback","cancelPositionRetry","teardownListeners","isOpen","setupListeners","schedulePositionUpdate","focusInitialItem","setTimeout","closeAnimationMs","onAnchorChange","onPositionPropsChange","resolveCssLengthPx","TOKEN_DEFAULTS","popupFallbackWidthPx","menuWidthXs","popupFallbackHeightPx","menuFallbackHeight","resolveCssTimeMs","motionShort2","animationDurationShort3","resolvedAnchor","anchor","anchorId","document","getElementById","activeSections","length","flatItems","flatMap","cancelAnimationFrame","onReady","remaining","attempt","calculatePosition","requestAnimationFrame","anchorEl","popup","el","querySelector","getBoundingClientRect","offsetWidth","offsetHeight","window","innerWidth","innerHeight","flat","selectedIdx","findIndex","it","isSelected","isInactive","firstEnabledIdx","btns","querySelectorAll","focus","e","t","target","contains","close","addEventListener","removeEventListener","clearTimeout","dsClose","emit","handleKeyDown","enabled","map","i","filter","cur","indexOf","safe","key","preventDefault","stopPropagation","focusItem","idx","handleItemClick","item","dsSelect","handleGradientSelect","preset","dsGradientSelect","render","h","Host","style","display","flatIdx","popupStyle","position","transform","round","zIndex","visibility","menuWidth","minWidth","class","role","si","header","undefined","as","emphasis","color","value","onDsChange","detail","isFocused","type","isDestructive","disabled","tabIndex","onMouseDown","onClick","onFocus","label","subtext","dot","background","showToggle","toggleValue"],"sources":["src/wc/components/Menu/menu-position.ts","src/wc/components/Menu/menu-types.ts","src/wc/components/Menu/Menu.css?tag=ds-menu&encapsulation=scoped","src/wc/components/Menu/Menu.tsx"],"sourcesContent":["export type MenuSide = 'top' | 'right' | 'bottom' | 'left';\nexport type MenuAlign = 'start' | 'center' | 'end';\n\nexport interface MenuPositionInput {\n anchorRect: Pick<DOMRectReadOnly, 'top' | 'left' | 'right' | 'bottom' | 'width' | 'height'>;\n popupWidth: number;\n popupHeight: number;\n side: MenuSide;\n align: MenuAlign;\n sideOffsetPx: number;\n alignOffsetPx: number;\n viewportPadPx: number;\n viewportWidth: number;\n viewportHeight: number;\n}\n\n/** Pure layout math for ds-menu — anchor rect + placement props → viewport-fixed x/y. */\nexport function computeMenuPosition(input: MenuPositionInput): { x: number; y: number } {\n const {\n anchorRect: a,\n popupWidth: pw,\n popupHeight: ph,\n side,\n align,\n sideOffsetPx,\n alignOffsetPx,\n viewportPadPx: vpPad,\n viewportWidth,\n viewportHeight,\n } = input;\n\n let x = 0;\n let y = 0;\n\n switch (side) {\n case 'top':\n y = a.top - ph - sideOffsetPx;\n x =\n align === 'start'\n ? a.left + alignOffsetPx\n : align === 'end'\n ? a.right - pw + alignOffsetPx\n : a.left + a.width / 2 - pw / 2 + alignOffsetPx;\n break;\n case 'bottom':\n y = a.bottom + sideOffsetPx;\n x =\n align === 'start'\n ? a.left + alignOffsetPx\n : align === 'end'\n ? a.right - pw + alignOffsetPx\n : a.left + a.width / 2 - pw / 2 + alignOffsetPx;\n break;\n case 'left':\n x = a.left - pw - sideOffsetPx;\n y =\n align === 'start'\n ? a.top + alignOffsetPx\n : align === 'end'\n ? a.bottom - ph + alignOffsetPx\n : a.top + a.height / 2 - ph / 2 + alignOffsetPx;\n break;\n case 'right':\n x = a.right + sideOffsetPx;\n y =\n align === 'start'\n ? a.top + alignOffsetPx\n : align === 'end'\n ? a.bottom - ph + alignOffsetPx\n : a.top + a.height / 2 - ph / 2 + alignOffsetPx;\n break;\n }\n\n return {\n x: Math.min(Math.max(x, vpPad), viewportWidth - pw - vpPad),\n y: Math.min(Math.max(y, vpPad), viewportHeight - ph - vpPad),\n };\n}\n","import type { ShellGradientPreset } from '../../nav/shell-gradient-presets';\n\nexport type { MenuAlign, MenuSide } from './menu-position';\nexport {\n PANEL_NAV_USER_MENU_PLACEMENT,\n type MenuPlacement,\n} from './menu-placement';\n\nexport interface MenuItemData {\n label: string;\n value?: string;\n subtext?: string;\n /** Show a supplemental brand notification dot. */\n dot?: boolean;\n isSelected?: boolean;\n isInactive?: boolean;\n isDestructive?: boolean;\n showToggle?: boolean;\n toggleValue?: boolean;\n}\n\nexport interface MenuItemsSection {\n header?: string;\n items: MenuItemData[];\n}\n\nexport interface MenuGradientPickerSection {\n header?: string;\n variant: 'gradient-picker';\n value: ShellGradientPreset;\n}\n\nexport type MenuSection = MenuItemsSection | MenuGradientPickerSection;\n\nexport function isMenuGradientPickerSection(\n section: MenuSection,\n): section is MenuGradientPickerSection {\n return 'variant' in section && section.variant === 'gradient-picker';\n}\n\nexport type { ShellGradientPreset };\n","@import '../../utils/focus-ring.css';\n@import '../../utils/interaction-fill.css';\n@import '../../utils/control-inactive.css';\n@import '../../utils/control-density.css';\n\n/* ── Popup shell ─────────────────────────────────────────────────────────── */\n\n.menu-popup {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: var(--dimension-menu-width-xs);\n max-width: var(--dimension-panel-width-lg);\n overflow: hidden;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n /* Split elevation: shadow on shell, inset highlight on ::after (combined token clips with overflow:hidden). */\n box-shadow: var(--effect-shadow-elevated-floating);\n animation: menuFadeIn var(--effect-motion-short-2) forwards;\n backface-visibility: hidden;\n will-change: transform;\n /*\n * Neutralize the host `align` prop. Stencil reflects it as the legacy HTML\n * `align` attribute, which browsers map to `text-align` on ds-menu. Menu\n * items already force left; section headers / other content must not inherit\n * `end` once ds-text is the full-width layout box.\n */\n text-align: start;\n}\n\n.menu-popup::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n box-shadow: var(--effect-highlight-elevated-floating);\n}\n\n.menu-popup--closing {\n animation: menuFadeOut var(--effect-motion-short-2) forwards;\n}\n\n@keyframes menuFadeIn {\n from { opacity: 0; transform: inherit scale(0.97); }\n to { opacity: 1; }\n}\n\n@keyframes menuFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n/* ── Sections ────────────────────────────────────────────────────────────── */\n\n.menu-section {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-050);\n}\n\n.menu-section--divided {\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-tertiary);\n}\n\nds-text.section-header {\n display: flex;\n align-items: center;\n box-sizing: border-box;\n height: var(--ds-control-height, var(--dimension-size-400));\n /* Same inset as menu-item padding-inline + menu-item__label inset. */\n padding: 0 calc(\n var(--ds-control-padding-inline, var(--dimension-space-075)) +\n var(--ds-control-label-inset, var(--dimension-space-025))\n );\n text-align: start;\n -webkit-user-select: none;\n user-select: none;\n}\n\n/* ── Items (md control-density + interaction-fill + inset focus) ─────────── */\n\n.menu-item {\n display: flex;\n align-items: center;\n gap: var(--ds-control-gap, var(--dimension-space-050));\n width: 100%;\n height: var(--ds-control-height, var(--dimension-size-400));\n padding: 0 var(--ds-control-padding-inline, var(--dimension-space-075));\n box-sizing: border-box;\n border: none;\n border-radius: var(--ds-control-radius, var(--dimension-radius-025));\n background: transparent;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n color: inherit;\n /* Hover/press/selected: `.ds-interaction-fill` (+ `--selected`). */\n}\n\n/* Subtext rows grow past the density height. */\n.menu-item:has(.menu-item__subtext) {\n height: auto;\n min-height: var(--ds-control-height, var(--dimension-size-400));\n padding-block: var(--ds-control-padding-inline, var(--dimension-space-075));\n align-items: flex-start;\n}\n\n/* Inactive: `.ds-control-inactive` (25% opacity). */\n\n.menu-item--destructive .menu-item__label {\n /* Beat ds-text color-* host classes for destructive rows. */\n color: var(--color-foreground-bold-negative) !important;\n}\n\n.menu-item__content {\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n/* Colors come from ds-text color prop; keep padding on the metric box. */\nds-text.menu-item__label {\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n}\n\n.menu-item__subtext,\nds-text.menu-item__subtext {\n padding: 0 var(--ds-control-label-inset, var(--dimension-space-025));\n}\n\n/* Standard md icon zone keeps the dot aligned with other control suffixes. */\n.menu-item__dot-box {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--ds-control-icon, var(--dimension-iconography-md));\n height: var(--ds-control-icon, var(--dimension-iconography-md));\n pointer-events: none;\n}\n\n/* ── Toggle suffix ───────────────────────────────────────────────────────── */\n\n.menu-item__toggle {\n position: relative;\n flex-shrink: 0;\n width: calc(var(--dimension-size-400) + var(--dimension-size-050));\n height: var(--dimension-size-250);\n border-radius: var(--dimension-radius-125);\n background-color: var(--color-background-translucent);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on {\n background-color: var(--color-background-medium-brand);\n}\n\n.menu-item__toggle-thumb {\n position: absolute;\n top: var(--dimension-space-025);\n left: var(--dimension-space-025);\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n border-radius: 50%;\n background-color: var(--color-foreground-on-bold-background-primary);\n transition: transform var(--effect-motion-short-2);\n}\n\n.menu-item__toggle--on .menu-item__toggle-thumb {\n transform: translateX(var(--dimension-offset-200, 16px));\n}\n","import { Component, Prop, State, Event, EventEmitter, Element, Watch, Listen, h, Host } from '@stencil/core';\nimport { resolveCssLengthPx, resolveCssTimeMs, TOKEN_CSS_LENGTHS, TOKEN_DEFAULTS } from '../../utils';\nimport { computeMenuPosition, type MenuAlign, type MenuSide } from './menu-position';\nimport type { MenuItemData, MenuSection } from './menu-types';\nimport { isMenuGradientPickerSection } from './menu-types';\nimport type { ShellGradientPreset } from '../../nav/shell-gradient-presets';\n\n/** rAF retries while the popup mounts or the anchor resolves. */\nconst POSITION_RETRY_BUDGET = 8;\n\n@Component({\n tag: 'ds-menu',\n styleUrl: 'Menu.css',\n scoped: true,\n})\nexport class Menu {\n @Element() el!: HTMLElement;\n\n @Prop({ mutable: true }) open: boolean = false;\n @Prop() items: MenuItemData[] = [];\n @Prop() sections: MenuSection[] = [];\n @Prop() side: MenuSide = 'bottom';\n @Prop() align: MenuAlign = 'start';\n /** Gap between anchor and menu — number (px) or TokoMo length (`var(--dimension-space-050)`, etc.). */\n @Prop() sideOffset: number | string = TOKEN_CSS_LENGTHS.space050;\n /** Cross-axis offset — number (px) or TokoMo length. */\n @Prop() alignOffset: number | string = 0;\n @Prop() menuWidth: string | undefined;\n @Prop() minWidth: string | undefined;\n /** External trigger element to position against. Set via JS: menuEl.anchor = buttonEl */\n @Prop() anchor: HTMLElement | undefined;\n /** ID of the external trigger element for positioning */\n @Prop() anchorId: string | undefined;\n /** Show a visible ring on the initially focused menu item. Use only when the opener was keyboard-driven. */\n @Prop() initialFocusVisible: boolean = false;\n /** Accessible name for the popup menu. */\n @Prop() menuLabel: string = 'Menu';\n\n @State() private shouldRender: boolean = false;\n @State() private closing: boolean = false;\n @State() private pos: { x: number; y: number } = { x: 0, y: 0 };\n @State() private focusedIndex: number = 0;\n @State() private positionReady: boolean = false;\n @State() private focusRingVisible: boolean = false;\n\n @Event() dsClose!: EventEmitter<void>;\n @Event() dsSelect!: EventEmitter<MenuItemData>;\n /** Emitted when a `gradient-picker` section swatch is chosen. */\n @Event() dsGradientSelect!: EventEmitter<ShellGradientPreset>;\n\n private clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private scrollResizeHandler: (() => void) | null = null;\n private closeTimer: ReturnType<typeof setTimeout> | null = null;\n private itemEls: HTMLElement[] = [];\n private positionRetryRaf: number | null = null;\n private listenersReady = false;\n\n componentDidLoad() {\n if (this.open) this.onOpenChange(true);\n }\n\n disconnectedCallback() {\n this.cancelPositionRetry();\n this.teardownListeners();\n }\n\n @Watch('open')\n onOpenChange(isOpen: boolean) {\n if (isOpen) {\n this.teardownListeners();\n this.shouldRender = true;\n this.closing = false;\n this.positionReady = false;\n this.listenersReady = false;\n this.focusRingVisible = this.initialFocusVisible;\n this.listenersReady = true;\n this.setupListeners();\n this.schedulePositionUpdate(() => {\n this.focusInitialItem();\n });\n } else if (this.shouldRender) {\n this.cancelPositionRetry();\n this.closing = true;\n this.teardownListeners();\n this.listenersReady = false;\n this.closeTimer = setTimeout(() => {\n this.shouldRender = false;\n this.closing = false;\n this.closeTimer = null;\n }, this.closeAnimationMs);\n }\n }\n\n @Watch('anchor')\n @Watch('anchorId')\n onAnchorChange() {\n if (this.open) this.schedulePositionUpdate();\n }\n\n @Watch('side')\n @Watch('align')\n @Watch('sideOffset')\n @Watch('alignOffset')\n onPositionPropsChange() {\n if (this.open) this.schedulePositionUpdate();\n }\n\n private get viewportPadPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.space050, TOKEN_DEFAULTS.space050);\n }\n\n private get sideOffsetPx(): number {\n return resolveCssLengthPx(this.sideOffset, TOKEN_DEFAULTS.space050);\n }\n\n private get alignOffsetPx(): number {\n return resolveCssLengthPx(this.alignOffset, 0);\n }\n\n private get popupFallbackWidthPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.menuWidthXs, TOKEN_DEFAULTS.menuWidthXs);\n }\n\n private get popupFallbackHeightPx(): number {\n return resolveCssLengthPx(TOKEN_DEFAULTS.menuFallbackHeight, TOKEN_DEFAULTS.menuFallbackHeight);\n }\n\n private get closeAnimationMs(): number {\n return resolveCssTimeMs(TOKEN_DEFAULTS.motionShort2, TOKEN_DEFAULTS.animationDurationShort3);\n }\n\n private get resolvedAnchor(): HTMLElement | null {\n if (this.anchor) return this.anchor;\n if (this.anchorId) return document.getElementById(this.anchorId);\n return null;\n }\n\n private get activeSections(): MenuSection[] {\n if (this.sections.length > 0) return this.sections;\n if (this.items.length > 0) return [{ items: this.items }];\n return [];\n }\n\n private get flatItems(): MenuItemData[] {\n return this.activeSections.flatMap(section =>\n isMenuGradientPickerSection(section) ? [] : section.items,\n );\n }\n\n private cancelPositionRetry() {\n if (this.positionRetryRaf !== null) {\n cancelAnimationFrame(this.positionRetryRaf);\n this.positionRetryRaf = null;\n }\n }\n\n /** Retry until anchor + popup exist — do not reveal at 0,0 on a failed first pass. */\n private schedulePositionUpdate(onReady?: () => void) {\n if (!this.open) return;\n\n this.cancelPositionRetry();\n this.positionReady = false;\n\n let remaining = POSITION_RETRY_BUDGET;\n\n const attempt = () => {\n this.positionRetryRaf = null;\n if (!this.open) return;\n\n if (this.calculatePosition()) {\n this.positionReady = true;\n onReady?.();\n return;\n }\n\n if (remaining > 0) {\n remaining -= 1;\n this.positionRetryRaf = requestAnimationFrame(attempt);\n }\n };\n\n this.positionRetryRaf = requestAnimationFrame(attempt);\n }\n\n /** @returns `true` when anchor and popup were found and `pos` was updated. */\n private calculatePosition(): boolean {\n const anchorEl = this.resolvedAnchor;\n if (!anchorEl) return false;\n const popup = this.el.querySelector('.menu-popup') as HTMLElement | null;\n if (!popup) return false;\n\n this.pos = computeMenuPosition({\n anchorRect: anchorEl.getBoundingClientRect(),\n popupWidth: popup.offsetWidth || this.popupFallbackWidthPx,\n popupHeight: popup.offsetHeight || this.popupFallbackHeightPx,\n side: this.side,\n align: this.align,\n sideOffsetPx: this.sideOffsetPx,\n alignOffsetPx: this.alignOffsetPx,\n viewportPadPx: this.viewportPadPx,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n return true;\n }\n\n /** Focus the selected item when present, otherwise the first enabled item. */\n private focusInitialItem() {\n const flat = this.flatItems;\n const selectedIdx = flat.findIndex(it => it.isSelected && !it.isInactive);\n const firstEnabledIdx = flat.findIndex(it => !it.isInactive);\n this.focusedIndex = selectedIdx >= 0\n ? selectedIdx\n : (firstEnabledIdx >= 0 ? firstEnabledIdx : 0);\n\n requestAnimationFrame(() => {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[this.focusedIndex]?.focus();\n });\n }\n\n private setupListeners() {\n this.clickOutsideHandler = (e: MouseEvent) => {\n const t = e.target as Node;\n const popup = this.el.querySelector('.menu-popup');\n const anchorEl = this.resolvedAnchor;\n if (popup?.contains(t) || anchorEl?.contains(t)) return;\n this.close();\n };\n\n this.scrollResizeHandler = () => {\n if (this.shouldRender && !this.closing) this.calculatePosition();\n };\n\n document.addEventListener('mousedown', this.clickOutsideHandler, true);\n window.addEventListener('scroll', this.scrollResizeHandler, true);\n window.addEventListener('resize', this.scrollResizeHandler);\n }\n\n private teardownListeners() {\n if (this.clickOutsideHandler) {\n document.removeEventListener('mousedown', this.clickOutsideHandler, true);\n this.clickOutsideHandler = null;\n }\n if (this.scrollResizeHandler) {\n window.removeEventListener('scroll', this.scrollResizeHandler, true);\n window.removeEventListener('resize', this.scrollResizeHandler);\n this.scrollResizeHandler = null;\n }\n if (this.closeTimer) {\n clearTimeout(this.closeTimer);\n this.closeTimer = null;\n }\n }\n\n private close() {\n this.resolvedAnchor?.focus();\n this.dsClose.emit();\n this.open = false;\n this.onOpenChange(false);\n }\n\n @Listen('keydown')\n handleKeyDown(e: KeyboardEvent) {\n if (!this.shouldRender || this.closing) return;\n const flat = this.flatItems;\n const enabled = flat.map((it, i) => ({ it, i })).filter(({ it }) => !it.isInactive).map(({ i }) => i);\n if (!enabled.length) return;\n\n const cur = enabled.indexOf(this.focusedIndex);\n const safe = cur < 0 ? 0 : cur;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[(safe + 1) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'ArrowUp':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[(safe - 1 + enabled.length) % enabled.length];\n this.focusItem(this.focusedIndex);\n break;\n case 'Home':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[0];\n this.focusItem(this.focusedIndex);\n break;\n case 'End':\n e.preventDefault(); e.stopPropagation();\n this.focusRingVisible = true;\n this.focusedIndex = enabled[enabled.length - 1];\n this.focusItem(this.focusedIndex);\n break;\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'Tab':\n e.preventDefault();\n this.close();\n break;\n }\n }\n\n private focusItem(idx: number) {\n const btns = this.el.querySelectorAll<HTMLElement>('.menu-item');\n btns[idx]?.focus();\n }\n\n private handleItemClick(item: MenuItemData) {\n if (item.isInactive) return;\n this.dsSelect.emit(item);\n }\n\n private handleGradientSelect(preset: ShellGradientPreset) {\n this.dsGradientSelect.emit(preset);\n }\n\n render() {\n if (!this.shouldRender) return <Host style={{ display: 'contents' }} />;\n\n const sections = this.activeSections;\n let flatIdx = 0;\n\n const popupStyle: Record<string, string> = {\n position: 'fixed',\n left: '0',\n top: '0',\n transform: `translate(${Math.round(this.pos.x)}px, ${Math.round(this.pos.y)}px)`,\n zIndex: '9998',\n visibility: this.positionReady ? 'visible' : 'hidden',\n };\n\n if (this.menuWidth) popupStyle['width'] = this.menuWidth;\n if (this.minWidth) popupStyle['min-width'] = this.minWidth;\n\n return (\n <Host style={{ display: 'contents' }}>\n <div\n class={{ 'menu-popup': true, 'menu-popup--closing': this.closing }}\n style={popupStyle}\n role=\"menu\"\n aria-label={this.menuLabel}\n aria-orientation=\"vertical\"\n >\n {sections.map((section, si) => (\n <div\n key={si}\n class={{\n 'menu-section': true,\n 'menu-section--divided': si < sections.length - 1,\n 'menu-section--gradient-picker': isMenuGradientPickerSection(section),\n }}\n role={section.header ? 'group' : undefined}\n aria-label={section.header}\n >\n {section.header && (\n <ds-text\n class=\"section-header ds-control--md\"\n as=\"span\"\n variant=\"text-body-small\"\n emphasis\n color=\"primary\"\n aria-hidden=\"true\"\n >\n {section.header}\n </ds-text>\n )}\n {isMenuGradientPickerSection(section) ? (\n <ds-shell-gradient-picker\n value={section.value}\n onDsChange={(e: CustomEvent<ShellGradientPreset>) => {\n e.stopPropagation();\n this.handleGradientSelect(e.detail);\n }}\n />\n ) : (\n section.items.map(item => {\n const idx = flatIdx++;\n const isFocused = this.focusedIndex === idx;\n return (\n <button\n key={idx}\n type=\"button\"\n class={{\n 'menu-item': true,\n 'ds-control--md': true,\n 'ds-focus-ring-inset': true,\n 'ds-focus-ring--visible': isFocused && this.focusRingVisible,\n 'ds-interaction-fill': !item.isInactive,\n 'ds-interaction-fill--selected': !!item.isSelected && !item.isInactive,\n 'menu-item--selected': !!item.isSelected,\n 'ds-control-inactive': !!item.isInactive,\n 'menu-item--destructive': !!item.isDestructive,\n 'menu-item--focused': isFocused,\n }}\n role=\"menuitem\"\n aria-current={item.isSelected ? 'true' : undefined}\n disabled={item.isInactive}\n tabIndex={isFocused ? 0 : -1}\n onMouseDown={() => { this.focusRingVisible = false; }}\n onClick={() => this.handleItemClick(item)}\n onFocus={() => { this.focusedIndex = idx; }}\n >\n <div class=\"menu-item__content ds-interaction-fill__content\">\n <ds-text\n class=\"menu-item__label\"\n as=\"span\"\n variant=\"text-body-medium\"\n emphasis={!!item.isSelected}\n color={item.isSelected ? 'primary' : 'secondary'}\n >\n {item.label}\n </ds-text>\n {item.subtext && (\n <ds-text class=\"menu-item__subtext\" as=\"span\" variant=\"text-body-small\" color=\"secondary\">\n {item.subtext}\n </ds-text>\n )}\n </div>\n {item.dot && (\n <span class=\"menu-item__dot-box ds-interaction-fill__content\" aria-hidden=\"true\">\n <ds-badge\n class=\"menu-item__dot\"\n variant=\"dot\"\n background={item.isSelected && !item.isInactive\n ? 'var(--ds-interaction-active)'\n : 'var(--color-background-primary)'}\n label=\"\"\n />\n </span>\n )}\n {item.showToggle && (\n <div class={{ 'menu-item__toggle': true, 'menu-item__toggle--on': !!item.toggleValue, 'ds-interaction-fill__content': true }} aria-hidden=\"true\">\n <div class=\"menu-item__toggle-thumb\" />\n </div>\n )}\n </button>\n );\n }))}\n </div>\n ))}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"gUAiBM,SAAUA,EAAoBC,GAClC,MACEC,WAAYC,EACZC,WAAYC,EACZC,YAAaC,EAAEC,KACfA,EAAIC,MACJA,EAAKC,aACLA,EAAYC,cACZA,EACAC,cAAeC,EAAKC,cACpBA,EAAaC,eACbA,GACEd,EAEJ,IAAIe,EAAI,EACR,IAAIC,EAAI,EAER,OAAQT,GACN,IAAK,MACHS,EAAId,EAAEe,IAAMX,EAAKG,EACjBM,EACEP,IAAU,QACNN,EAAEgB,KAAOR,EACTF,IAAU,MACRN,EAAEiB,MAAQf,EAAKM,EACfR,EAAEgB,KAAOhB,EAAEkB,MAAQ,EAAIhB,EAAK,EAAIM,EACxC,MACF,IAAK,SACHM,EAAId,EAAEmB,OAASZ,EACfM,EACEP,IAAU,QACNN,EAAEgB,KAAOR,EACTF,IAAU,MACRN,EAAEiB,MAAQf,EAAKM,EACfR,EAAEgB,KAAOhB,EAAEkB,MAAQ,EAAIhB,EAAK,EAAIM,EACxC,MACF,IAAK,OACHK,EAAIb,EAAEgB,KAAOd,EAAKK,EAClBO,EACER,IAAU,QACNN,EAAEe,IAAMP,EACRF,IAAU,MACRN,EAAEmB,OAASf,EAAKI,EAChBR,EAAEe,IAAMf,EAAEoB,OAAS,EAAIhB,EAAK,EAAII,EACxC,MACF,IAAK,QACHK,EAAIb,EAAEiB,MAAQV,EACdO,EACER,IAAU,QACNN,EAAEe,IAAMP,EACRF,IAAU,MACRN,EAAEmB,OAASf,EAAKI,EAChBR,EAAEe,IAAMf,EAAEoB,OAAS,EAAIhB,EAAK,EAAII,EACxC,MAGJ,MAAO,CACLK,EAAGQ,KAAKC,IAAID,KAAKE,IAAIV,EAAGH,GAAQC,EAAgBT,EAAKQ,GACrDI,EAAGO,KAAKC,IAAID,KAAKE,IAAIT,EAAGJ,GAAQE,EAAiBR,EAAKM,GAE1D,CC3CM,SAAUc,EACdC,GAEA,MAAO,YAAaA,GAAWA,EAAQC,UAAY,iBACrD,CCtCA,MAAMC,EAAU,IAAM,85SCQtB,MAAMC,EAAwB,E,MAOjBC,EAAIC,EAAA,MAAAD,UAAAE,EALjB,WAAAC,CAAAC,G,6JAQ2BC,KAAAC,KAAgB,MACjCD,KAAAE,MAAwB,GACxBF,KAAAG,SAA0B,GAC1BH,KAAA7B,KAAiB,SACjB6B,KAAA5B,MAAmB,QAEnB4B,KAAAI,WAA8BC,EAAkBC,SAEhDN,KAAAO,YAA+B,EAQ/BP,KAAAQ,oBAA+B,MAE/BR,KAAAS,UAAoB,OAEXT,KAAAU,aAAwB,MACxBV,KAAAW,QAAmB,MACnBX,KAAAY,IAAgC,CAAEjC,EAAG,EAAGC,EAAG,GAC3CoB,KAAAa,aAAuB,EACvBb,KAAAc,cAAyB,MACzBd,KAAAe,iBAA4B,MAOrCf,KAAAgB,oBAAwD,KACxDhB,KAAAiB,oBAA2C,KAC3CjB,KAAAkB,WAAmD,KACnDlB,KAAAmB,QAAyB,GACzBnB,KAAAoB,iBAAkC,KAClCpB,KAAAqB,eAAiB,KA2Y1B,CAzYC,gBAAAC,GACE,GAAItB,KAAKC,KAAMD,KAAKuB,aAAa,K,CAGnC,oBAAAC,GACExB,KAAKyB,sBACLzB,KAAK0B,mB,CAIP,YAAAH,CAAaI,GACX,GAAIA,EAAQ,CACV3B,KAAK0B,oBACL1B,KAAKU,aAAe,KACpBV,KAAKW,QAAU,MACfX,KAAKc,cAAgB,MACrBd,KAAKqB,eAAiB,MACtBrB,KAAKe,iBAAmBf,KAAKQ,oBAC7BR,KAAKqB,eAAiB,KACtBrB,KAAK4B,iBACL5B,KAAK6B,wBAAuB,KAC1B7B,KAAK8B,kBAAkB,G,MAEpB,GAAI9B,KAAKU,aAAc,CAC5BV,KAAKyB,sBACLzB,KAAKW,QAAU,KACfX,KAAK0B,oBACL1B,KAAKqB,eAAiB,MACtBrB,KAAKkB,WAAaa,YAAW,KAC3B/B,KAAKU,aAAe,MACpBV,KAAKW,QAAU,MACfX,KAAKkB,WAAa,IAAI,GACrBlB,KAAKgC,iB,EAMZ,cAAAC,GACE,GAAIjC,KAAKC,KAAMD,KAAK6B,wB,CAOtB,qBAAAK,GACE,GAAIlC,KAAKC,KAAMD,KAAK6B,wB,CAGtB,iBAAYtD,GACV,OAAO4D,EAAmBC,EAAe9B,SAAU8B,EAAe9B,S,CAGpE,gBAAYjC,GACV,OAAO8D,EAAmBnC,KAAKI,WAAYgC,EAAe9B,S,CAG5D,iBAAYhC,GACV,OAAO6D,EAAmBnC,KAAKO,YAAa,E,CAG9C,wBAAY8B,GACV,OAAOF,EAAmBC,EAAeE,YAAaF,EAAeE,Y,CAGvE,yBAAYC,GACV,OAAOJ,EAAmBC,EAAeI,mBAAoBJ,EAAeI,mB,CAG9E,oBAAYR,GACV,OAAOS,EAAiBL,EAAeM,aAAcN,EAAeO,wB,CAGtE,kBAAYC,GACV,GAAI5C,KAAK6C,OAAQ,OAAO7C,KAAK6C,OAC7B,GAAI7C,KAAK8C,SAAU,OAAOC,SAASC,eAAehD,KAAK8C,UACvD,OAAO,I,CAGT,kBAAYG,GACV,GAAIjD,KAAKG,SAAS+C,OAAS,EAAG,OAAOlD,KAAKG,SAC1C,GAAIH,KAAKE,MAAMgD,OAAS,EAAG,MAAO,CAAC,CAAEhD,MAAOF,KAAKE,QACjD,MAAO,E,CAGT,aAAYiD,GACV,OAAOnD,KAAKiD,eAAeG,SAAQ7D,GACjCD,EAA4BC,GAAW,GAAKA,EAAQW,O,CAIhD,mBAAAuB,GACN,GAAIzB,KAAKoB,mBAAqB,KAAM,CAClCiC,qBAAqBrD,KAAKoB,kBAC1BpB,KAAKoB,iBAAmB,I,EAKpB,sBAAAS,CAAuByB,GAC7B,IAAKtD,KAAKC,KAAM,OAEhBD,KAAKyB,sBACLzB,KAAKc,cAAgB,MAErB,IAAIyC,EAAY7D,EAEhB,MAAM8D,EAAU,KACdxD,KAAKoB,iBAAmB,KACxB,IAAKpB,KAAKC,KAAM,OAEhB,GAAID,KAAKyD,oBAAqB,CAC5BzD,KAAKc,cAAgB,KACrBwC,MACA,M,CAGF,GAAIC,EAAY,EAAG,CACjBA,GAAa,EACbvD,KAAKoB,iBAAmBsC,sBAAsBF,E,GAIlDxD,KAAKoB,iBAAmBsC,sBAAsBF,E,CAIxC,iBAAAC,GACN,MAAME,EAAW3D,KAAK4C,eACtB,IAAKe,EAAU,OAAO,MACtB,MAAMC,EAAQ5D,KAAK6D,GAAGC,cAAc,eACpC,IAAKF,EAAO,OAAO,MAEnB5D,KAAKY,IAAMjD,EAAoB,CAC7BE,WAAY8F,EAASI,wBACrBhG,WAAY6F,EAAMI,aAAehE,KAAKqC,qBACtCpE,YAAa2F,EAAMK,cAAgBjE,KAAKuC,sBACxCpE,KAAM6B,KAAK7B,KACXC,MAAO4B,KAAK5B,MACZC,aAAc2B,KAAK3B,aACnBC,cAAe0B,KAAK1B,cACpBC,cAAeyB,KAAKzB,cACpBE,cAAeyF,OAAOC,WACtBzF,eAAgBwF,OAAOE,cAEzB,OAAO,I,CAID,gBAAAtC,GACN,MAAMuC,EAAOrE,KAAKmD,UAClB,MAAMmB,EAAcD,EAAKE,WAAUC,GAAMA,EAAGC,aAAeD,EAAGE,aAC9D,MAAMC,EAAkBN,EAAKE,WAAUC,IAAOA,EAAGE,aACjD1E,KAAKa,aAAeyD,GAAe,EAC/BA,EACCK,GAAmB,EAAIA,EAAkB,EAE9CjB,uBAAsB,KACpB,MAAMkB,EAAO5E,KAAK6D,GAAGgB,iBAA8B,cACnDD,EAAK5E,KAAKa,eAAeiE,OAAO,G,CAI5B,cAAAlD,GACN5B,KAAKgB,oBAAuB+D,IAC1B,MAAMC,EAAID,EAAEE,OACZ,MAAMrB,EAAQ5D,KAAK6D,GAAGC,cAAc,eACpC,MAAMH,EAAW3D,KAAK4C,eACtB,GAAIgB,GAAOsB,SAASF,IAAMrB,GAAUuB,SAASF,GAAI,OACjDhF,KAAKmF,OAAO,EAGdnF,KAAKiB,oBAAsB,KACzB,GAAIjB,KAAKU,eAAiBV,KAAKW,QAASX,KAAKyD,mBAAmB,EAGlEV,SAASqC,iBAAiB,YAAapF,KAAKgB,oBAAqB,MACjEkD,OAAOkB,iBAAiB,SAAUpF,KAAKiB,oBAAqB,MAC5DiD,OAAOkB,iBAAiB,SAAUpF,KAAKiB,oB,CAGjC,iBAAAS,GACN,GAAI1B,KAAKgB,oBAAqB,CAC5B+B,SAASsC,oBAAoB,YAAarF,KAAKgB,oBAAqB,MACpEhB,KAAKgB,oBAAsB,I,CAE7B,GAAIhB,KAAKiB,oBAAqB,CAC5BiD,OAAOmB,oBAAoB,SAAUrF,KAAKiB,oBAAqB,MAC/DiD,OAAOmB,oBAAoB,SAAUrF,KAAKiB,qBAC1CjB,KAAKiB,oBAAsB,I,CAE7B,GAAIjB,KAAKkB,WAAY,CACnBoE,aAAatF,KAAKkB,YAClBlB,KAAKkB,WAAa,I,EAId,KAAAiE,GACNnF,KAAK4C,gBAAgBkC,QACrB9E,KAAKuF,QAAQC,OACbxF,KAAKC,KAAO,MACZD,KAAKuB,aAAa,M,CAIpB,aAAAkE,CAAcV,GACZ,IAAK/E,KAAKU,cAAgBV,KAAKW,QAAS,OACxC,MAAM0D,EAAOrE,KAAKmD,UAClB,MAAMuC,EAAUrB,EAAKsB,KAAI,CAACnB,EAAIoB,KAAC,CAAQpB,KAAIoB,QAAMC,QAAO,EAAGrB,SAAUA,EAAGE,aAAYiB,KAAI,EAAGC,KAAQA,IACnG,IAAKF,EAAQxC,OAAQ,OAErB,MAAM4C,EAAMJ,EAAQK,QAAQ/F,KAAKa,cACjC,MAAMmF,EAAOF,EAAM,EAAI,EAAIA,EAE3B,OAAQf,EAAEkB,KACR,IAAK,YACHlB,EAAEmB,iBAAkBnB,EAAEoB,kBACtBnG,KAAKe,iBAAmB,KACxBf,KAAKa,aAAe6E,GAASM,EAAO,GAAKN,EAAQxC,QACjDlD,KAAKoG,UAAUpG,KAAKa,cACpB,MACF,IAAK,UACHkE,EAAEmB,iBAAkBnB,EAAEoB,kBACtBnG,KAAKe,iBAAmB,KACxBf,KAAKa,aAAe6E,GAASM,EAAO,EAAIN,EAAQxC,QAAUwC,EAAQxC,QAClElD,KAAKoG,UAAUpG,KAAKa,cACpB,MACF,IAAK,OACHkE,EAAEmB,iBAAkBnB,EAAEoB,kBACtBnG,KAAKe,iBAAmB,KACxBf,KAAKa,aAAe6E,EAAQ,GAC5B1F,KAAKoG,UAAUpG,KAAKa,cACpB,MACF,IAAK,MACHkE,EAAEmB,iBAAkBnB,EAAEoB,kBACtBnG,KAAKe,iBAAmB,KACxBf,KAAKa,aAAe6E,EAAQA,EAAQxC,OAAS,GAC7ClD,KAAKoG,UAAUpG,KAAKa,cACpB,MACF,IAAK,SACHkE,EAAEmB,iBACFlG,KAAKmF,QACL,MACF,IAAK,MACHJ,EAAEmB,iBACFlG,KAAKmF,QACL,M,CAIE,SAAAiB,CAAUC,GAChB,MAAMzB,EAAO5E,KAAK6D,GAAGgB,iBAA8B,cACnDD,EAAKyB,IAAMvB,O,CAGL,eAAAwB,CAAgBC,GACtB,GAAIA,EAAK7B,WAAY,OACrB1E,KAAKwG,SAAShB,KAAKe,E,CAGb,oBAAAE,CAAqBC,GAC3B1G,KAAK2G,iBAAiBnB,KAAKkB,E,CAG7B,MAAAE,GACE,IAAK5G,KAAKU,aAAc,OAAOmG,EAACC,EAAI,CAACC,MAAO,CAAEC,QAAS,cAEvD,MAAM7G,EAAWH,KAAKiD,eACtB,IAAIgE,EAAU,EAEd,MAAMC,EAAqC,CACzCC,SAAU,QACVrI,KAAM,IACND,IAAK,IACLuI,UAAW,aAAajI,KAAKkI,MAAMrH,KAAKY,IAAIjC,SAASQ,KAAKkI,MAAMrH,KAAKY,IAAIhC,QACzE0I,OAAQ,OACRC,WAAYvH,KAAKc,cAAgB,UAAY,UAG/C,GAAId,KAAKwH,UAAWN,EAAW,SAAWlH,KAAKwH,UAC/C,GAAIxH,KAAKyH,SAAUP,EAAW,aAAelH,KAAKyH,SAElD,OACEZ,EAACC,EAAI,CAACC,MAAO,CAAEC,QAAS,aACtBH,EAAA,OACEa,MAAO,CAAE,aAAc,KAAM,sBAAuB1H,KAAKW,SACzDoG,MAAOG,EACPS,KAAK,OAAM,aACC3H,KAAKS,UAAS,mBACT,YAEhBN,EAASwF,KAAI,CAACpG,EAASqI,IACtBf,EAAA,OACEZ,IAAK2B,EACLF,MAAO,CACL,eAAgB,KAChB,wBAAyBE,EAAKzH,EAAS+C,OAAS,EAChD,gCAAiC5D,EAA4BC,IAE/DoI,KAAMpI,EAAQsI,OAAS,QAAUC,UAAS,aAC9BvI,EAAQsI,QAEnBtI,EAAQsI,QACPhB,EAAA,WACEa,MAAM,gCACNK,GAAG,OACHvI,QAAQ,kBACRwI,SAAQ,KACRC,MAAM,UAAS,cACH,QAEX1I,EAAQsI,QAGZvI,EAA4BC,GAC3BsH,EAAA,4BACEqB,MAAO3I,EAAQ2I,MACfC,WAAapD,IACXA,EAAEoB,kBACFnG,KAAKyG,qBAAqB1B,EAAEqD,OAAO,IAIvC7I,EAAQW,MAAMyF,KAAIY,IAClB,MAAMF,EAAMY,IACZ,MAAMoB,EAAYrI,KAAKa,eAAiBwF,EACxC,OACEQ,EAAA,UACEZ,IAAKI,EACLiC,KAAK,SACLZ,MAAO,CACL,YAAa,KACb,iBAAkB,KAClB,sBAAuB,KACvB,yBAA0BW,GAAarI,KAAKe,iBAC5C,uBAAwBwF,EAAK7B,WAC7B,kCAAmC6B,EAAK9B,aAAe8B,EAAK7B,WAC5D,wBAAyB6B,EAAK9B,WAC9B,wBAAyB8B,EAAK7B,WAC9B,2BAA4B6B,EAAKgC,cACjC,qBAAsBF,GAExBV,KAAK,WAAU,eACDpB,EAAK9B,WAAa,OAASqD,UACzCU,SAAUjC,EAAK7B,WACf+D,SAAUJ,EAAY,GAAI,EAC1BK,YAAa,KAAQ1I,KAAKe,iBAAmB,KAAK,EAClD4H,QAAS,IAAM3I,KAAKsG,gBAAgBC,GACpCqC,QAAS,KAAQ5I,KAAKa,aAAewF,CAAG,GAExCQ,EAAA,OAAKa,MAAM,mDACTb,EAAA,WACEa,MAAM,mBACNK,GAAG,OACHvI,QAAQ,mBACRwI,WAAYzB,EAAK9B,WACjBwD,MAAO1B,EAAK9B,WAAa,UAAY,aAEpC8B,EAAKsC,OAEPtC,EAAKuC,SACJjC,EAAA,WAASa,MAAM,qBAAqBK,GAAG,OAAOvI,QAAQ,kBAAkByI,MAAM,aAC3E1B,EAAKuC,UAIXvC,EAAKwC,KACJlC,EAAA,QAAMa,MAAM,kDAAiD,cAAa,QACxEb,EAAA,YACEa,MAAM,iBACNlI,QAAQ,MACRwJ,WAAYzC,EAAK9B,aAAe8B,EAAK7B,WACjC,+BACA,kCACJmE,MAAM,MAIXtC,EAAK0C,YACJpC,EAAA,OAAKa,MAAO,CAAE,oBAAqB,KAAM,0BAA2BnB,EAAK2C,YAAa,+BAAgC,MAAM,cAAc,QACxIrC,EAAA,OAAKa,MAAM,6BAGR,Q","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-07-12T20:41:52",
2
+ "timestamp": "2026-07-12T22:30:27",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.43.5",
@@ -172,13 +172,13 @@ function scrollEdgeFadeSizeStyle(size = "size-600", height) {
172
172
  function scrollEdgeFadeMaskImage(edge) {
173
173
  switch (edge) {
174
174
  case "top":
175
- return `linear-gradient(to bottom, #000 0, #000 50%, transparent 100%)`;
175
+ return `linear-gradient(to bottom, transparent 0, #000 ${SIZE_REF}, #000 100%)`;
176
176
  case "bottom":
177
177
  return `linear-gradient(to bottom, #000 0, #000 calc(100% - ${SIZE_REF}), transparent 100%)`;
178
178
  case "left":
179
- return `linear-gradient(to right, #000 0, #000 calc(100% - ${SIZE_REF}), transparent 100%)`;
179
+ return `linear-gradient(to right, transparent 0, #000 ${SIZE_REF}, #000 100%)`;
180
180
  case "right":
181
- return `linear-gradient(to left, #000 0, #000 calc(100% - ${SIZE_REF}), transparent 100%)`;
181
+ return `linear-gradient(to right, #000 0, #000 calc(100% - ${SIZE_REF}), transparent 100%)`;
182
182
  }
183
183
  }
184
184
  function scrollEdgeFadeMaskStyle(edge, size = "size-600", height) {
@@ -195,6 +195,7 @@ function scrollEdgeFadeClassMap(opts) {
195
195
  const edges = Array.isArray(opts.edges) ? opts.edges : [opts.edges];
196
196
  const classes = {
197
197
  "scroll-edge-fade": true,
198
+ "scroll-edge-fade--scroll-aware": opts.scrollAware === true,
198
199
  "scroll-edge-fade--hidden": opts.hidden === true
199
200
  };
200
201
  for (const edge of edges) {
@@ -204,9 +205,10 @@ function scrollEdgeFadeClassMap(opts) {
204
205
  if (atEnd === true) {
205
206
  classes["scroll-edge-fade--at-end"] = true;
206
207
  } else if (atEnd && typeof atEnd === "object") {
207
- const allAtEnd = edges.every((edge) => atEnd[edge]);
208
- if (allAtEnd) {
209
- classes["scroll-edge-fade--at-end"] = true;
208
+ for (const edge of edges) {
209
+ if (atEnd[edge]) {
210
+ classes[`scroll-edge-fade--${edge}-at-edge`] = true;
211
+ }
210
212
  }
211
213
  }
212
214
  return classes;