@awc-ui/core 1.0.0-beta → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/components/p-6wZSqm_2.js +2 -0
  2. package/dist/components/{p-Bx5sxRqa.js.map → p-6wZSqm_2.js.map} +1 -1
  3. package/dist/components/p-7fN_yCXW.js +2 -0
  4. package/dist/components/{p-CJdqKSuf.js.map → p-7fN_yCXW.js.map} +1 -1
  5. package/dist/components/{p-G5m2pHZ2.js → p-B0Opn6dK.js} +2 -2
  6. package/dist/components/{p-pDrTJmeT.js → p-B3MWYEEJ.js} +2 -2
  7. package/dist/components/{p-DGGkdSZk.js → p-BwXpiUsu.js} +2 -2
  8. package/dist/{md3/p-B0NLeNWu.js → components/p-Bx6--dQF.js} +2 -2
  9. package/dist/components/{p-BIIp3Qod.js → p-C8EP4S21.js} +2 -2
  10. package/dist/components/{p-CWM3KSti.js → p-C_ogF68H.js} +2 -2
  11. package/dist/components/{p-BlwGYUkt.js → p-Ch2-tttM.js} +2 -2
  12. package/dist/components/p-DXXUoRSH.js +2 -0
  13. package/dist/components/{p-DWUCvzfU.js.map → p-DXXUoRSH.js.map} +1 -1
  14. package/dist/components/p-Dp-w93ot.js +2 -0
  15. package/dist/components/{p-BUYYCrGa.js.map → p-Dp-w93ot.js.map} +1 -1
  16. package/dist/{md3/p-CGStn3Iq.js → components/p-DvOKnoqK.js} +2 -2
  17. package/dist/components/{p-B7yMxWo-.js → p-DzPKu-Ma.js} +2 -2
  18. package/dist/components/{p-CXpXrhQH.js → p-RLxbNqRv.js} +2 -2
  19. package/dist/components/p-UdGDg2oJ.js +2 -0
  20. package/dist/components/{p-BujtL9xW.js.map → p-UdGDg2oJ.js.map} +1 -1
  21. package/dist/components/p-e2HRV63Y.js +2 -0
  22. package/dist/components/{p-CrlkPxeB.js.map → p-e2HRV63Y.js.map} +1 -1
  23. package/dist/components/p-stybaFzj.js +2 -0
  24. package/dist/components/{p-JbwZ84YK.js.map → p-stybaFzj.js.map} +1 -1
  25. package/dist/components/p-uTEkf0sE.js +2 -0
  26. package/dist/components/{p-BXwh1zjF.js.map → p-uTEkf0sE.js.map} +1 -1
  27. package/dist/esm/{a11y-C9_cZAF_.js → a11y-C6CRqodW.js} +3 -3
  28. package/dist/esm/{a11y-C9_cZAF_.js.map → a11y-C6CRqodW.js.map} +1 -1
  29. package/dist/esm/{bar-chart-IvBgAmmF.js → bar-chart-ZZrajEkM.js} +4 -4
  30. package/dist/esm/{bar-chart-IvBgAmmF.js.map → bar-chart-ZZrajEkM.js.map} +1 -1
  31. package/dist/esm/{chart-D1kP9gfW.js → chart-32olae06.js} +4 -4
  32. package/dist/esm/{chart-D1kP9gfW.js.map → chart-32olae06.js.map} +1 -1
  33. package/dist/esm/{hit-test-DFfwlMb9.js → hit-test-DHldf5Lm.js} +3 -3
  34. package/dist/esm/{hit-test-DFfwlMb9.js.map → hit-test-DHldf5Lm.js.map} +1 -1
  35. package/dist/esm/{rtl-CGStn3Iq.js → rtl-DvOKnoqK.js} +3 -3
  36. package/dist/esm/{rtl-CGStn3Iq.js.map → rtl-DvOKnoqK.js.map} +1 -1
  37. package/dist/md3/p-04e97f5d.entry.js +2 -0
  38. package/dist/md3/{p-ec14eaca.entry.js.map → p-04e97f5d.entry.js.map} +1 -1
  39. package/dist/md3/p-3cce1de3.entry.js +2 -0
  40. package/dist/md3/{p-2121c939.entry.js.map → p-3cce1de3.entry.js.map} +1 -1
  41. package/dist/md3/p-4d82132d.entry.js +2 -0
  42. package/dist/md3/{p-fe78659d.entry.js.map → p-4d82132d.entry.js.map} +1 -1
  43. package/dist/{components/p-Bu-m4Gm2.js → md3/p-Bx6--dQF.js} +2 -2
  44. package/dist/md3/{p-B0NLeNWu.js.map → p-Bx6--dQF.js.map} +1 -1
  45. package/dist/md3/{p-CWM3KSti.js → p-C_ogF68H.js} +2 -2
  46. package/dist/md3/{p-CWM3KSti.js.map → p-C_ogF68H.js.map} +1 -1
  47. package/dist/{components/p-CGStn3Iq.js → md3/p-DvOKnoqK.js} +2 -2
  48. package/dist/md3/{p-CGStn3Iq.js.map → p-DvOKnoqK.js.map} +1 -1
  49. package/dist/md3/{p-B7yMxWo-.js → p-DzPKu-Ma.js} +2 -2
  50. package/dist/md3/{p-B7yMxWo-.js.map → p-DzPKu-Ma.js.map} +1 -1
  51. package/dist/md3/{p-CXpXrhQH.js → p-RLxbNqRv.js} +2 -2
  52. package/dist/md3/{p-CXpXrhQH.js.map → p-RLxbNqRv.js.map} +1 -1
  53. package/dist/md3/{p-f6373c6c.entry.js → p-aaec2698.entry.js} +2 -2
  54. package/dist/md3/{p-9ff2d5d1.entry.js → p-c063c823.entry.js} +2 -2
  55. package/main-llm.md +2 -2
  56. package/package.json +24 -3
  57. package/dist/components/p-BUYYCrGa.js +0 -2
  58. package/dist/components/p-BXwh1zjF.js +0 -2
  59. package/dist/components/p-BujtL9xW.js +0 -2
  60. package/dist/components/p-Bx5sxRqa.js +0 -2
  61. package/dist/components/p-CJdqKSuf.js +0 -2
  62. package/dist/components/p-CrlkPxeB.js +0 -2
  63. package/dist/components/p-DWUCvzfU.js +0 -2
  64. package/dist/components/p-JbwZ84YK.js +0 -2
  65. package/dist/md3/p-2121c939.entry.js +0 -2
  66. package/dist/md3/p-ec14eaca.entry.js +0 -2
  67. package/dist/md3/p-fe78659d.entry.js +0 -2
  68. /package/dist/components/{p-G5m2pHZ2.js.map → p-B0Opn6dK.js.map} +0 -0
  69. /package/dist/components/{p-pDrTJmeT.js.map → p-B3MWYEEJ.js.map} +0 -0
  70. /package/dist/components/{p-DGGkdSZk.js.map → p-BwXpiUsu.js.map} +0 -0
  71. /package/dist/components/{p-Bu-m4Gm2.js.map → p-Bx6--dQF.js.map} +0 -0
  72. /package/dist/components/{p-BIIp3Qod.js.map → p-C8EP4S21.js.map} +0 -0
  73. /package/dist/components/{p-CWM3KSti.js.map → p-C_ogF68H.js.map} +0 -0
  74. /package/dist/components/{p-BlwGYUkt.js.map → p-Ch2-tttM.js.map} +0 -0
  75. /package/dist/components/{p-CGStn3Iq.js.map → p-DvOKnoqK.js.map} +0 -0
  76. /package/dist/components/{p-B7yMxWo-.js.map → p-DzPKu-Ma.js.map} +0 -0
  77. /package/dist/components/{p-CXpXrhQH.js.map → p-RLxbNqRv.js.map} +0 -0
  78. /package/dist/md3/{p-f6373c6c.entry.js.map → p-aaec2698.entry.js.map} +0 -0
  79. /package/dist/md3/{p-9ff2d5d1.entry.js.map → p-c063c823.entry.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"names":["mdTooltipCss","TOOLTIP_VIEWPORT_MARGIN","MdTooltip","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","text","subhead","variant","position","autoPosition","offset","crossOffset","open","showDelay","hideDelay","disabled","density","isVisible","resolvedPlacement","hasSlottedActions","hasSlottedSubhead","tooltipId","Math","random","toString","slice","scrollListenerBound","escapeListenerBound","hostHoverBound","hasLoaded","suppressed","onTriggerSlotChange","els","triggerSlot","assignedElements","length","bindTrigger","handleTriggerEnter","scheduleShow","handleTriggerLeave","scheduleHide","handleTriggerFocus","handleTriggerBlur","e","relatedTarget","el","contains","handleHostFocusOut","handlePopupEnter","clearTimers","handlePopupLeave","handleGlobalEscape","key","preventDefault","active","getDeepActiveElement","focusInside","triggerEl","focus","lastGeom","at","al","aw","ah","pw","ph","vw","vh","ex","ey","watchdogFrame","handleScroll","updatePosition","componentWillLoad","syncSlotFlags","componentDidLoad","setup","showTooltip","connectedCallback","addScrollListener","addEscapeListener","schedulePositionUpdate","startPositionWatchdog","shadow","shadowRoot","querySelector","undefined","addEventListener","MutationObserver","slotObserver","updateTriggerAria","observe","childList","subtree","characterData","first","children","Array","from","some","c","getAttribute","disconnectedCallback","stopPositionWatchdog","unbindTrigger","removeScrollListener","removeEscapeListener","removeEventListener","disconnect","onOpenChange","val","hideTooltip","onDisabledChange","removeAttribute","onDescriptionChange","show","hide","useHostHover","tag","tagName","toLowerCase","hasAttribute","tabIndex","startsWith","desc","computeDescription","setAttribute","parts","child","slot","t","textContent","trim","push","join","showTimer","setTimeout","hideTimer","document","a","activeElement","isConnected","mdOpen","emit","attempt","requestAnimationFrame","positioned","tick","popup","popupEl","offsetWidth","offsetHeight","getAnchorRect","p","getBoundingClientRect","g","drifted","top","left","width","height","abs","window","innerWidth","innerHeight","cancelAnimationFrame","mdClose","clearTimeout","capture","passive","anchorRect","popupW","popupH","placement","physicalPlacement","findBestPlacement","coords","calcCoords","isVertical","M","absLeft","maxLeft","clampedLeft","min","max","absTop","maxTop","clampedTop","fixedCoords","toFixedCoords","style","insetBlockStart","insetInlineStart","triggerRect","viewportTop","viewportLeft","containingBlock","getFixedContainingBlock","cbRect","createsFixedContainingBlock","s","transform","filter","perspective","translate","rotate","scale","backdropFilter","test","willChange","contain","contentVisibility","containerType","node","getComputedStyle","parentElement","parentNode","ShadowRoot","host","isRTL","direction","axis","align","split","flippedAxis","flippedAlign","hostW","hostH","o","fitsMainAxis","hostRect","relTop","relLeft","getOppositePlacement","opp","bottom","right","preferred","check","opposite","axes","candidate","render","isRich","hasSubhead","hasActions","h","Host","class","id","role","part","ref","onMouseEnter","onMouseLeave","name"],"sources":["src/components/md-tooltip/md-tooltip.css?tag=md-tooltip&encapsulation=shadow","src/components/md-tooltip/md-tooltip.tsx"],"sourcesContent":["/* ==========================================================\n md-tooltip — Material Design 3 Tooltip\n Spec: https://m3.material.io/components/tooltips/specs\n\n PUBLIC CSS CUSTOM PROPERTIES (override per-instance):\n --md-tooltip-plain-container-color Plain tooltip background\n --md-tooltip-plain-text-color Plain tooltip text color\n --md-tooltip-rich-container-color Rich tooltip background\n --md-tooltip-rich-subhead-color Rich subhead text color\n --md-tooltip-rich-text-color Rich supporting text color\n --md-tooltip-rich-action-color Rich action button color\n --md-tooltip-container-shape Border-radius (plain)\n --md-tooltip-plain-max-inline-size Plain tooltip max width\n --md-tooltip-rich-container-shape Border-radius (rich)\n --md-tooltip-rich-min-inline-size Rich tooltip min width\n --md-tooltip-rich-max-inline-size Rich tooltip max width\n\n CSS PARTS:\n popup Tooltip popup container\n subhead Rich tooltip subhead wrapper\n supporting-text Rich tooltip supporting text wrapper\n actions Rich tooltip action button wrapper\n text Plain tooltip text wrapper\n\n SLOTS:\n (default) Trigger element\n content Rich tooltip supporting text\n subhead Rich tooltip subhead\n actions Rich tooltip action buttons\n ========================================================== */\n\n/* ==========================================================\n 1. HOST\n ========================================================== */\n\n:host {\n display: inline-block;\n position: relative;\n}\n\n/* ==========================================================\n 2. POPUP — shared base\n ========================================================== */\n\n.md-tooltip__popup {\n /* Fixed + viewport coords (set in JS) so popups escape overflow:hidden ancestors. */\n position: fixed;\n z-index: var(--md-sys-z-index-tooltip, 1500);\n pointer-events: none;\n box-sizing: border-box;\n /* CRITICAL: width must not depend on the popup's own offsets. With width:auto, a\n fixed element shrink-to-fits into (containing block − left), so writing `left`\n changes the width, which re-wraps the text, which the position watchdog sees as\n drift and repositions — an animated wrap/slide feedback loop that crawls the\n popup across the screen one frame at a time. max-content sizes from the CONTENT\n only (the variant max-inline-size caps still bound it), decoupling measurement\n from position: one measure, one placement, no loop. */\n width: max-content;\n\n opacity: 0;\n visibility: hidden;\n transform: scale(0.9);\n\n transition:\n opacity var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n transform var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n visibility 0ms linear var(--md-sys-motion-duration-short2, 100ms);\n}\n\n.md-tooltip__popup--visible {\n opacity: 1;\n visibility: visible;\n transform: scale(1);\n pointer-events: auto;\n transition:\n opacity var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n transform var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n visibility 0ms linear 0ms;\n}\n\n/* ==========================================================\n 3. PLAIN TOOLTIP\n Spec: height 24px (via padding), padding 8px, body-small\n ========================================================== */\n\n.md-tooltip__popup--plain {\n --_container-color: var(--md-tooltip-plain-container-color, var(--md-sys-color-inverse-surface, #313033));\n --_text-color: var(--md-tooltip-plain-text-color, var(--md-sys-color-inverse-on-surface, #F4EFF4));\n --_shape: var(--md-tooltip-container-shape, var(--md-sys-shape-corner-extra-small, 4px));\n\n background-color: var(--_container-color);\n color: var(--_text-color);\n border-radius: var(--_shape);\n\n /* Global density: on-grid padding tracks --md-sys-spacing-* (4/8 = inset-xs/sm);\n defaults resolve byte-for-byte at density 0. min-block-size stays the 24px\n spec height floor. */\n padding-block: var(--md-sys-spacing-inset-xs, 4px);\n padding-inline: var(--md-sys-spacing-inset-sm, 8px);\n\n min-block-size: max(20px, calc(24px + var(--md-sys-density-scale, 0) * 1px));\n max-inline-size: min(var(--md-tooltip-plain-max-inline-size, 280px), calc(100vw - 16px));\n\n font-family: var(--md-sys-typescale-body-small-font-family, Roboto, sans-serif);\n font-size: max(10px, calc(12px + var(--md-sys-density-scale, 0) * 0.5px));\n font-weight: var(--md-sys-typescale-body-small-font-weight, 400);\n line-height: max(14px, calc(16px + var(--md-sys-density-scale, 0) * 0.5px));\n letter-spacing: var(--md-sys-typescale-body-small-letter-spacing, 0.4px);\n\n /* Wrap long content over multiple lines instead of clipping it. The plain\n tooltip is the overflow tooltip used by md-list-item, so it must reveal\n the FULL text. `max-inline-size` caps the line length (280px default here,\n overridable per-instance) and the content wraps below it rather than\n truncating with an ellipsis. */\n white-space: normal;\n display: flex;\n align-items: center;\n}\n\n.md-tooltip__text {\n /* No ellipsis / overflow clipping — let the popup grow vertically and wrap.\n `overflow-wrap: anywhere` keeps an unbroken long word (URLs, IDs) from\n forcing the popup wider than its max-inline-size. */\n overflow-wrap: anywhere;\n}\n\n/* ==========================================================\n 4. RICH TOOLTIP\n Spec: top padding 12px, bottom 8px, left/right 16px\n ========================================================== */\n\n.md-tooltip__popup--rich {\n --_container-color: var(--md-tooltip-rich-container-color, var(--md-sys-color-surface-container, #F3EDF7));\n --_subhead-color: var(--md-tooltip-rich-subhead-color, var(--md-sys-color-on-surface-variant, #49454F));\n --_text-color: var(--md-tooltip-rich-text-color, var(--md-sys-color-on-surface-variant, #49454F));\n --_action-color: var(--md-tooltip-rich-action-color, var(--md-sys-color-primary, #6750A4));\n --_shape: var(--md-tooltip-rich-container-shape, var(--md-sys-shape-corner-medium, 12px));\n\n background-color: var(--_container-color);\n color: var(--_text-color);\n border-radius: var(--_shape);\n\n /* Global density: on-grid rich padding tracks --md-sys-spacing-*\n (12/8/16 = inset-md/sm/lg); defaults resolve byte-for-byte at density 0. */\n padding-block-start: var(--md-sys-spacing-inset-md, 12px);\n padding-block-end: var(--md-sys-spacing-inset-sm, 8px);\n padding-inline: var(--md-sys-spacing-inset-lg, 16px);\n\n min-inline-size: var(--md-tooltip-rich-min-inline-size, 120px);\n max-inline-size: min(var(--md-tooltip-rich-max-inline-size, 320px), calc(100vw - 16px));\n\n white-space: normal;\n box-shadow: var(--md-sys-elevation-2, 0 1px 3px 1px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.3));\n}\n\n/* Subhead */\n.md-tooltip__subhead {\n font-family: var(--md-sys-typescale-title-small-font-family, Roboto, sans-serif);\n font-size: max(11px, calc(14px + var(--md-sys-density-scale, 0) * 0.5px));\n font-weight: var(--md-sys-typescale-title-small-font-weight, 500);\n line-height: max(16px, calc(20px + var(--md-sys-density-scale, 0) * 1px));\n letter-spacing: var(--md-sys-typescale-title-small-letter-spacing, 0.1px);\n color: var(--_subhead-color);\n margin-block-end: var(--md-sys-spacing-gap-xs, 4px);\n}\n\n/* Supporting text */\n.md-tooltip__supporting-text {\n font-family: var(--md-sys-typescale-body-medium-font-family, Roboto, sans-serif);\n font-size: max(11px, calc(14px + var(--md-sys-density-scale, 0) * 0.5px));\n font-weight: var(--md-sys-typescale-body-medium-font-weight, 400);\n line-height: max(16px, calc(20px + var(--md-sys-density-scale, 0) * 1px));\n letter-spacing: var(--md-sys-typescale-body-medium-letter-spacing, 0.25px);\n color: var(--_text-color);\n}\n\n/* Actions */\n.md-tooltip__actions {\n display: flex;\n gap: var(--md-sys-spacing-gap-sm, 8px);\n justify-content: flex-end;\n margin-block-start: var(--md-sys-spacing-gap-md, 12px);\n color: var(--_action-color);\n}\n\n.md-tooltip__actions--empty {\n display: none;\n}\n\n/* Slotted action buttons */\n::slotted([slot=\"actions\"]) {\n color: var(--_action-color);\n}\n\n/* ==========================================================\n 5. PLACEMENT — transform-origin for enter animation\n Position is set inline via JS; these handle animation origin.\n ========================================================== */\n\n.md-tooltip__popup--top,\n.md-tooltip__popup--top-start,\n.md-tooltip__popup--top-end {\n transform-origin: bottom center;\n}\n\n.md-tooltip__popup--bottom,\n.md-tooltip__popup--bottom-start,\n.md-tooltip__popup--bottom-end {\n transform-origin: top center;\n}\n\n.md-tooltip__popup--left,\n.md-tooltip__popup--left-start,\n.md-tooltip__popup--left-end {\n transform-origin: center right;\n}\n\n.md-tooltip__popup--right,\n.md-tooltip__popup--right-start,\n.md-tooltip__popup--right-end {\n transform-origin: center left;\n}\n\n/* ==========================================================\n 6. RTL\n NB: no transform-origin overrides here. The placement classes are already\n PHYSICAL — JS (physicalPlacement) maps logical placements per direction\n before resolving the class — so the base origins in section 5 always face\n the trigger. The old :host-context([dir=rtl]) re-flip double-flipped them,\n making the entrance scale grow from the edge facing AWAY from the trigger.\n ========================================================== */\n\n:host-context([dir=\"rtl\"]) .md-tooltip__actions {\n justify-content: flex-start;\n}\n\n/* ==========================================================\n 7. FORCED COLORS (Windows High Contrast)\n The popup is a background + elevation surface — both are dropped in\n forced-colors mode, leaving the tooltip text floating with no boundary\n over the page. Give it a system-color border so the region stays\n perceivable (matches the md-toolbar hardened convention).\n ========================================================== */\n\n@media (forced-colors: active) {\n .md-tooltip__popup {\n border: 1px solid CanvasText;\n }\n}\n\n/* ==========================================================\n 8. REDUCED MOTION\n Honor a reduced-motion preference by dropping the scale/opacity\n entrance so the tooltip appears/disappears instantly instead of\n animating on every hover (md-list-item mounts a tooltip per row).\n ========================================================== */\n\n@media (prefers-reduced-motion: reduce) {\n .md-tooltip__popup,\n .md-tooltip__popup--visible {\n transition: none;\n transform: none;\n }\n}\n\n/* ==========================================================\n DENSITY (local override)\n Maps the local `density` prop onto the same --md-sys-density-scale signal a\n global `data-density` ancestor sets. Declared on :host, so a local rung wins\n over the inherited global one. Every density-sensitive value in this file\n derives from that single signal by calc — never add a fixed per-rung ladder.\n ========================================================== */\n:host([density='-1']) { --md-sys-density-scale: -1; }\n:host([density='-2']) { --md-sys-density-scale: -2; }\n:host([density='-3']) { --md-sys-density-scale: -3; }\n:host([density='-4']) { --md-sys-density-scale: -4; }\n","import { Component, Host, h, Prop, State, Event, EventEmitter, Element, Method, Watch } from '@stencil/core';\n\nexport type Placement =\n | 'top' | 'top-start' | 'top-end'\n | 'bottom' | 'bottom-start' | 'bottom-end'\n | 'left' | 'left-start' | 'left-end'\n | 'right' | 'right-start' | 'right-end';\n\n/** Minimum gap kept between a popup and the viewport edge when cross-axis clamping. */\nconst TOOLTIP_VIEWPORT_MARGIN = 8;\n\n/**\n * @slot - Trigger element the tooltip is anchored to\n * @slot content - Rich tooltip supporting text (overrides `text` prop)\n * @slot subhead - Rich tooltip subhead (overrides `subhead` prop)\n * @slot actions - Rich tooltip action buttons\n *\n * @part popup - Tooltip popup container\n * @part subhead - Rich tooltip subhead wrapper\n * @part supporting-text - Rich tooltip supporting text wrapper\n * @part actions - Rich tooltip action button wrapper\n * @part text - Plain tooltip text wrapper\n */\n@Component({\n tag: 'md-tooltip',\n styleUrl: 'md-tooltip.css',\n shadow: true,\n})\nexport class MdTooltip {\n @Element() el!: HTMLElement;\n\n /** Plain tooltip text, or rich tooltip supporting text */\n @Prop() text: string = '';\n\n /** Rich tooltip subhead (headline) */\n @Prop() subhead: string = '';\n\n /** Visual variant */\n @Prop({ reflect: true }) variant: 'plain' | 'rich' = 'plain';\n\n /** Preferred placement relative to the trigger */\n @Prop() position: Placement = 'top';\n\n /** Automatically reposition if overflowing the viewport */\n @Prop() autoPosition: boolean = true;\n\n /** Distance from the trigger in pixels */\n @Prop() offset: number = 8;\n\n /** Cross-axis offset in pixels */\n @Prop() crossOffset: number = 0;\n\n /** Programmatic open state */\n @Prop({ mutable: true, reflect: true }) open: boolean = false;\n\n /** Delay before showing (ms) */\n @Prop() showDelay: number = 500;\n\n /** Delay before hiding (ms) — for rich variant hover-out grace period */\n @Prop() hideDelay: number = 200;\n\n /** When true, hover/focus handlers are ignored and any open tooltip is dismissed. */\n @Prop({ reflect: true }) disabled: boolean = false;\n\n /**\n * Local density rung. Drives the same `--md-sys-density-scale` signal that a\n * global `data-density` ancestor sets, so a local value simply overrides the\n * inherited one. 0 = default, -4 = ultra-compact.\n */\n @Prop({ reflect: true }) density: 0 | -1 | -2 | -3 | -4 = 0;\n\n /**\n * Emits when the tooltip becomes visible. `bubbles:false` + `composed:false` keep it\n * from crossing the shadow boundary and retargeting onto an embedding host (the repo's\n * documented composed-event-leak class — see md-date-picker's swallow guards).\n */\n @Event({ bubbles: false, composed: false }) mdOpen: EventEmitter<void>;\n\n /** Emits when the tooltip is dismissed (does not bubble or cross shadow boundaries). */\n @Event({ bubbles: false, composed: false }) mdClose: EventEmitter<void>;\n\n @State() private isVisible = false;\n @State() private resolvedPlacement: Placement = 'top';\n @State() private hasSlottedActions = false;\n @State() private hasSlottedSubhead = false;\n\n private popupEl?: HTMLElement;\n private triggerEl?: HTMLElement;\n private triggerSlot?: HTMLSlotElement;\n private slotObserver?: MutationObserver;\n private showTimer?: ReturnType<typeof setTimeout>;\n private hideTimer?: ReturnType<typeof setTimeout>;\n private tooltipId = `md-tooltip-${Math.random().toString(36).slice(2, 9)}`;\n private scrollListenerBound = false;\n private escapeListenerBound = false;\n private hostHoverBound = false;\n private hasLoaded = false;\n /** Set on Escape dismissal; blocks re-show until the pointer/focus leaves the trigger. */\n private suppressed = false;\n\n // ─── Lifecycle ───────────────────────────────────────────\n\n componentWillLoad() {\n // Seed slot flags + visible state BEFORE the first render so the didLoad setup()\n // re-computes them to the same values — a no-op write rather than a state change\n // during componentDidLoad (which triggers Stencil's extra-re-render warning).\n // Honor `disabled`: a disabled tooltip must never render visible, and seeding\n // isVisible while disabled would also leak an unbalanced mdClose on the next hide.\n this.syncSlotFlags();\n if (this.open && !this.disabled) this.isVisible = true;\n }\n\n componentDidLoad() {\n this.hasLoaded = true;\n this.setup();\n if (this.open) this.showTooltip();\n }\n\n connectedCallback() {\n // On a REPARENT (disconnect→connect after first load), re-establish bindings —\n // componentDidLoad runs only once, so without this a moved tooltip goes dead.\n if (!this.hasLoaded) return;\n this.setup();\n // If the tooltip was still visible when it was moved, disconnectedCallback tore\n // down its scroll/Escape listeners without hiding it — restore them and reposition\n // against the moved trigger so it isn't stranded open, undismissable and detached.\n if (this.isVisible && !this.disabled) {\n this.addScrollListener();\n this.addEscapeListener();\n this.schedulePositionUpdate();\n this.startPositionWatchdog();\n } else if (this.open && !this.isVisible && !this.disabled) {\n // `open` was set while the element was DETACHED (showTooltip refuses to bind\n // global listeners there) — honor it now that we are connected again.\n this.showTooltip();\n }\n }\n\n /** (Re)attach trigger binding, slot detection and the host focusout listener. */\n private setup() {\n const shadow = this.el.shadowRoot;\n if (!shadow) return;\n\n this.triggerSlot = (shadow.querySelector('slot:not([name])') as HTMLSlotElement | null) ?? undefined;\n // addEventListener dedupes identical (fn, capture) pairs, so a re-setup is safe.\n this.triggerSlot?.addEventListener('slotchange', this.onTriggerSlotChange);\n this.el.addEventListener('focusout', this.handleHostFocusOut);\n\n // Rich content is authored in light DOM regardless of variant, so detect it there —\n // the shadow content/subhead/actions slots only exist while variant=\"rich\" renders,\n // which is why shadow-slot detection missed a runtime plain→rich switch.\n this.syncSlotFlags();\n if (typeof MutationObserver !== 'undefined' && !this.slotObserver) {\n // childList catches slotted content add/remove; subtree+characterData catches\n // edits to slotted text so a slot-only rich tooltip's aria-description stays fresh.\n this.slotObserver = new MutationObserver(() => {\n this.syncSlotFlags();\n if (this.triggerEl) this.updateTriggerAria(this.triggerEl);\n });\n this.slotObserver.observe(this.el, { childList: true, subtree: true, characterData: true });\n }\n\n const first = this.triggerSlot?.assignedElements()[0] as HTMLElement | undefined;\n if (first) this.bindTrigger(first);\n }\n\n private onTriggerSlotChange = () => {\n const els = this.triggerSlot?.assignedElements();\n if (els && els.length > 0) this.bindTrigger(els[0] as HTMLElement);\n };\n\n private syncSlotFlags() {\n // Direct-child scan (not `:scope >`, which Stencil's mock-doc can't parse).\n const children = Array.from(this.el.children);\n this.hasSlottedActions = children.some((c) => c.getAttribute('slot') === 'actions');\n this.hasSlottedSubhead = children.some((c) => c.getAttribute('slot') === 'subhead');\n }\n\n disconnectedCallback() {\n this.clearTimers();\n this.stopPositionWatchdog();\n this.unbindTrigger();\n this.removeScrollListener();\n this.removeEscapeListener();\n this.el.removeEventListener('focusout', this.handleHostFocusOut);\n this.triggerSlot?.removeEventListener('slotchange', this.onTriggerSlotChange);\n this.triggerSlot = undefined;\n this.slotObserver?.disconnect();\n this.slotObserver = undefined;\n }\n\n // ─── Watchers ────────────────────────────────────────────\n\n @Watch('open')\n onOpenChange(val: boolean) {\n if (val) {\n this.showTooltip();\n } else {\n this.hideTooltip();\n }\n }\n\n @Watch('disabled')\n onDisabledChange(disabled: boolean) {\n if (disabled) {\n this.clearTimers();\n if (this.open) this.open = false;\n this.triggerEl?.removeAttribute('aria-description');\n } else if (this.triggerEl) {\n this.updateTriggerAria(this.triggerEl);\n }\n }\n\n /** Keep the trigger's aria-description in sync when the tooltip's text changes\n * after binding (bindTrigger and the disabled watcher were the only refreshers). */\n @Watch('text')\n @Watch('subhead')\n onDescriptionChange() {\n if (this.triggerEl) this.updateTriggerAria(this.triggerEl);\n }\n\n // ─── Public Methods ──────────────────────────────────────\n\n /** Show the tooltip programmatically (no-op while `disabled`). */\n @Method()\n async show() {\n // Don't flip `open` (a reflected attribute) true while disabled — showTooltip\n // would early-return, leaving open=true with nothing visible (a state desync).\n if (this.disabled) return;\n this.open = true;\n }\n\n /** Dismiss the tooltip programmatically. */\n @Method()\n async hide() {\n this.open = false;\n }\n\n // ─── Trigger Binding ─────────────────────────────────────\n\n private bindTrigger(el: HTMLElement) {\n this.unbindTrigger();\n this.triggerEl = el;\n\n // Presentational triggers (e.g. weekday spans) are not focusable; hover the host instead.\n if (this.useHostHover(el)) {\n this.el.addEventListener('mouseenter', this.handleTriggerEnter);\n this.el.addEventListener('mouseleave', this.handleTriggerLeave);\n this.hostHoverBound = true;\n } else {\n el.addEventListener('mouseenter', this.handleTriggerEnter);\n el.addEventListener('mouseleave', this.handleTriggerLeave);\n }\n\n el.addEventListener('focus', this.handleTriggerFocus);\n el.addEventListener('blur', this.handleTriggerBlur);\n this.updateTriggerAria(el);\n }\n\n private unbindTrigger() {\n if (this.hostHoverBound) {\n this.el.removeEventListener('mouseenter', this.handleTriggerEnter);\n this.el.removeEventListener('mouseleave', this.handleTriggerLeave);\n this.hostHoverBound = false;\n } else if (this.triggerEl) {\n this.triggerEl.removeEventListener('mouseenter', this.handleTriggerEnter);\n this.triggerEl.removeEventListener('mouseleave', this.handleTriggerLeave);\n }\n\n if (!this.triggerEl) return;\n\n this.triggerEl.removeEventListener('focus', this.handleTriggerFocus);\n this.triggerEl.removeEventListener('blur', this.handleTriggerBlur);\n this.triggerEl.removeAttribute('aria-description');\n this.triggerEl = undefined;\n }\n\n /** True when hover should be tracked on the tooltip host (non-interactive triggers). */\n private useHostHover(el: HTMLElement): boolean {\n const tag = el.tagName.toLowerCase();\n if (tag === 'button' || tag === 'a' || tag === 'input' || tag === 'select' || tag === 'textarea') {\n return false;\n }\n if (el.hasAttribute('tabindex') && el.tabIndex >= 0) return false;\n if (tag.startsWith('md-')) return false;\n return true;\n }\n\n /** aria-description works across shadow DOM (unlike aria-describedby IDREFs) */\n private updateTriggerAria(el: HTMLElement) {\n if (this.disabled) {\n el.removeAttribute('aria-description');\n return;\n }\n const desc = this.computeDescription();\n if (desc) {\n el.setAttribute('aria-description', desc);\n } else {\n el.removeAttribute('aria-description');\n }\n }\n\n /**\n * The trigger's accessible description: `text`/`subhead` props first, then a\n * fallback to slotted rich content (subhead + supporting text) so a slot-only\n * rich tooltip is still announced to screen readers. Action buttons are excluded\n * — they are not description text and carry their own accessible names.\n */\n private computeDescription(): string {\n if (this.text) return this.text;\n if (this.subhead) return this.subhead;\n const parts: string[] = [];\n for (const child of Array.from(this.el.children)) {\n const slot = child.getAttribute('slot');\n if (slot === 'subhead' || slot === 'content') {\n const t = (child.textContent || '').trim();\n if (t) parts.push(t);\n }\n }\n return parts.join('. ');\n }\n\n // ─── Event Handlers ──────────────────────────────────────\n\n /** Arm the show timer, unless disabled or Escape-suppressed until re-entry. */\n private scheduleShow() {\n if (this.disabled || this.suppressed) return;\n this.clearTimers();\n this.showTimer = setTimeout(() => {\n this.open = true;\n }, this.showDelay);\n }\n\n /** Arm the hide grace timer (both variants) so the pointer can travel from the\n * trigger onto the popup without it vanishing — WCAG 1.4.13 \"hoverable\". */\n private scheduleHide() {\n this.clearTimers();\n this.hideTimer = setTimeout(() => {\n this.open = false;\n }, this.hideDelay);\n }\n\n private handleTriggerEnter = () => this.scheduleShow();\n\n private handleTriggerLeave = () => {\n // A fresh hover may re-show after an Escape dismissal.\n this.suppressed = false;\n this.scheduleHide();\n };\n\n private handleTriggerFocus = () => this.scheduleShow();\n\n private handleTriggerBlur = (e: FocusEvent) => {\n // Focus moving into the popup (rich action buttons) keeps the tooltip open.\n if (e.relatedTarget && this.el.contains(e.relatedTarget as Node)) return;\n this.suppressed = false;\n this.scheduleHide();\n };\n\n /**\n * Handles focusout at the host level — covers focus leaving\n * both the trigger AND slotted rich-tooltip action buttons.\n */\n private handleHostFocusOut = (e: FocusEvent) => {\n if (this.variant !== 'rich' || !this.isVisible) return;\n if (e.relatedTarget && this.el.contains(e.relatedTarget as Node)) return;\n this.scheduleHide();\n };\n\n /** Pointer over the popup keeps it open (hoverable) — both variants. */\n private handlePopupEnter = () => {\n this.clearTimers();\n };\n\n private handlePopupLeave = () => {\n this.scheduleHide();\n };\n\n // ─── Show / Hide ─────────────────────────────────────────\n\n /** Document-level Escape handler — dismisses from any focused descendant */\n private handleGlobalEscape = (e: KeyboardEvent) => {\n if (e.key !== 'Escape' || !this.isVisible) return;\n e.preventDefault();\n this.clearTimers();\n // Suppress re-show until the pointer/focus leaves and returns, so refocusing\n // the trigger (below) or a lingering hover can't immediately reopen it.\n this.suppressed = true;\n // WCAG 1.4.13: dismissal must NOT move focus. Only return focus to the trigger\n // when focus is currently inside the tooltip (popup/actions) or on the trigger —\n // never yank it from an unrelated element the user is interacting with.\n const active = this.getDeepActiveElement();\n const focusInside = !!active && (this.el.contains(active) || active === this.triggerEl);\n this.open = false;\n if (focusInside && this.triggerEl) this.triggerEl.focus();\n };\n\n /** Deepest focused element, piercing shadow roots. */\n private getDeepActiveElement(): Element | null {\n if (typeof document === 'undefined') return null;\n let a: Element | null = document.activeElement;\n while (a && a.shadowRoot && a.shadowRoot.activeElement) a = a.shadowRoot.activeElement;\n return a;\n }\n\n private addEscapeListener() {\n if (!this.escapeListenerBound) {\n document.addEventListener('keydown', this.handleGlobalEscape, true);\n this.escapeListenerBound = true;\n }\n }\n\n private removeEscapeListener() {\n if (this.escapeListenerBound) {\n document.removeEventListener('keydown', this.handleGlobalEscape, true);\n this.escapeListenerBound = false;\n }\n }\n\n private showTooltip() {\n if (this.disabled) return;\n // A DETACHED element must not bind global listeners or start the rAF loop —\n // disconnectedCallback can never fire again to clean them up (a stale ref\n // toggling `open` after removal would otherwise leak a 60fps loop plus a\n // document-level Escape handler forever). connectedCallback re-shows on\n // reconnect via the open/isVisible checks.\n if (!this.el.isConnected) return;\n this.isVisible = true;\n this.mdOpen.emit();\n this.addScrollListener();\n this.addEscapeListener();\n // Measure after layout so fixed coords are accurate (retry if popup not yet sized).\n this.schedulePositionUpdate();\n this.startPositionWatchdog();\n }\n\n private schedulePositionUpdate(attempt = 0) {\n requestAnimationFrame(() => {\n const positioned = this.updatePosition();\n if (!positioned && attempt < 3) {\n this.schedulePositionUpdate(attempt + 1);\n }\n });\n }\n\n // ─── Position Watchdog ──────────────────────────────────\n //\n // The scroll listener only repairs staleness that arrives as a light-DOM scroll.\n // Everything else that moves the anchor or resizes the popup after positioning is\n // invisible to it: window resize reflow, scrollers inside OTHER shadow roots\n // (scroll is composed:false), sibling layout shift, web-font/text growth, and a\n // containing-block appearing/vanishing at rest (md-list's --shifting adds\n // will-change:transform to rows that haven't moved; md-date-picker's entrance\n // transform settles back to none). Rather than plumbing per-ancestor listeners +\n // ResizeObservers + animation hooks (large lifecycle surface), a single rAF\n // watchdog runs ONLY while the tooltip is visible and repositions when the anchor\n // rect, popup size, the popup's ACTUAL viewport position (which shifts when a\n // containing block reinterprets the stored coords), or the viewport changes.\n // Cost: two getBoundingClientRect calls (anchor + popup) and two offset reads per\n // frame, per visible tooltip (tooltips are transient, effectively one at a time).\n\n /** Geometry snapshot from the last successful updatePosition. ex/ey are the popup's\n * EXPECTED viewport coords — if a containing-block change reinterprets the stored\n * style.top/left, the popup's real rect drifts from these and we reposition. */\n private lastGeom = { at: 0, al: 0, aw: 0, ah: 0, pw: 0, ph: 0, vw: 0, vh: 0, ex: 0, ey: 0 };\n private watchdogFrame = 0;\n\n private startPositionWatchdog() {\n if (typeof requestAnimationFrame !== 'function') return;\n this.stopPositionWatchdog();\n const tick = () => {\n if (!this.isVisible || !this.el.isConnected) {\n this.watchdogFrame = 0;\n return;\n }\n const popup = this.popupEl;\n if (popup && this.triggerEl) {\n const pw = popup.offsetWidth;\n const ph = popup.offsetHeight;\n // A 0x0 popup means a hidden ancestor — positioning would fail without\n // refreshing the snapshot, so skip until it has a box again (the size\n // delta versus the snapshot triggers the reposition on reveal).\n if (pw !== 0 || ph !== 0) {\n const a = this.getAnchorRect();\n const p = popup.getBoundingClientRect();\n const g = this.lastGeom;\n const drifted =\n a.top !== g.at || a.left !== g.al || a.width !== g.aw || a.height !== g.ah ||\n pw !== g.pw || ph !== g.ph ||\n // 0.5px tolerance absorbs subpixel churn; the entrance scale animation\n // exceeds it for a few frames, which just re-writes the same coords.\n Math.abs(p.top - g.ey) > 0.5 || Math.abs(p.left - g.ex) > 0.5 ||\n window.innerWidth !== g.vw || window.innerHeight !== g.vh;\n if (drifted) this.updatePosition();\n }\n }\n this.watchdogFrame = requestAnimationFrame(tick);\n };\n this.watchdogFrame = requestAnimationFrame(tick);\n }\n\n private stopPositionWatchdog() {\n if (this.watchdogFrame && typeof cancelAnimationFrame === 'function') {\n cancelAnimationFrame(this.watchdogFrame);\n }\n this.watchdogFrame = 0;\n }\n\n private hideTooltip() {\n // No spurious mdClose if it was never actually shown (e.g. hide() after a\n // show() that was suppressed by `disabled`) — keep open/close events balanced.\n if (!this.isVisible) return;\n this.isVisible = false;\n this.mdClose.emit();\n this.removeScrollListener();\n this.removeEscapeListener();\n this.stopPositionWatchdog();\n }\n\n private clearTimers() {\n if (this.showTimer != null) {\n clearTimeout(this.showTimer);\n this.showTimer = undefined;\n }\n if (this.hideTimer != null) {\n clearTimeout(this.hideTimer);\n this.hideTimer = undefined;\n }\n }\n\n // ─── Scroll Listener ────────────────────────────────────\n\n private addScrollListener() {\n if (!this.scrollListenerBound) {\n window.addEventListener('scroll', this.handleScroll, { capture: true, passive: true });\n this.scrollListenerBound = true;\n }\n }\n\n private removeScrollListener() {\n if (this.scrollListenerBound) {\n window.removeEventListener('scroll', this.handleScroll, true);\n this.scrollListenerBound = false;\n }\n }\n\n private handleScroll = () => {\n if (this.isVisible) this.updatePosition();\n };\n\n // ─── Positioning ─────────────────────────────────────────\n\n private updatePosition(): boolean {\n if (!this.popupEl || !this.triggerEl) return false;\n\n const anchorRect = this.getAnchorRect();\n const popupW = this.popupEl.offsetWidth;\n const popupH = this.popupEl.offsetHeight;\n\n if (popupW === 0 && popupH === 0) return false;\n\n let placement = this.physicalPlacement(this.position);\n\n if (this.autoPosition) {\n placement = this.findBestPlacement(anchorRect, popupW, popupH, placement);\n }\n\n const coords = this.calcCoords(anchorRect.width, anchorRect.height, popupW, popupH, placement);\n\n // crossOffset shifts the popup along the axis PERPENDICULAR to the placement:\n // horizontal for top/bottom, vertical for left/right. Applying it to `left`\n // unconditionally moved it along the MAIN axis for left/right placements.\n if (placement.startsWith('top') || placement.startsWith('bottom')) {\n coords.left += this.crossOffset;\n } else {\n coords.top += this.crossOffset;\n }\n\n // Cross-axis clamp: nudge the popup along the axis perpendicular to the\n // placement so it stays in the viewport, instead of flipping. A centered\n // top/bottom tooltip on an edge trigger (e.g. the first/last nav chevron in\n // a docked md-date-picker) would otherwise overflow horizontally — keep the\n // requested side and shift it inward so it stays bottom and fully visible.\n if (this.autoPosition) {\n const isVertical = placement.startsWith('top') || placement.startsWith('bottom');\n const M = TOOLTIP_VIEWPORT_MARGIN;\n if (isVertical) {\n const absLeft = anchorRect.left + coords.left;\n const maxLeft = window.innerWidth - popupW - M;\n const clampedLeft = Math.min(Math.max(absLeft, M), Math.max(M, maxLeft));\n coords.left += clampedLeft - absLeft;\n } else {\n const absTop = anchorRect.top + coords.top;\n const maxTop = window.innerHeight - popupH - M;\n const clampedTop = Math.min(Math.max(absTop, M), Math.max(M, maxTop));\n coords.top += clampedTop - absTop;\n }\n }\n\n const fixedCoords = this.toFixedCoords(anchorRect.top + coords.top, anchorRect.left + coords.left);\n\n // position:fixed — use physical top/left; getBoundingClientRect is viewport-physical.\n // Logical inset-inline-start would misplace popups in RTL (inline-start is on the right).\n this.popupEl.style.top = `${fixedCoords.top}px`;\n this.popupEl.style.left = `${fixedCoords.left}px`;\n this.popupEl.style.insetBlockStart = '';\n this.popupEl.style.insetInlineStart = '';\n this.resolvedPlacement = placement as Placement;\n // Snapshot the geometry this position was computed FROM — the watchdog\n // repositions when any of it drifts. ex/ey are the intended VIEWPORT position\n // (pre containing-block conversion): if a CB later appears/vanishes at rest,\n // the popup's real rect diverges from these with no other signal.\n this.lastGeom = {\n at: anchorRect.top, al: anchorRect.left, aw: anchorRect.width, ah: anchorRect.height,\n pw: popupW, ph: popupH,\n vw: window.innerWidth, vh: window.innerHeight,\n ex: anchorRect.left + coords.left, ey: anchorRect.top + coords.top,\n };\n return true;\n }\n\n /** Prefer the slotted trigger; fall back to the tooltip host when the trigger has\n * no box. Reads the trigger rect FIRST so the common case costs one rect read —\n * this runs every watchdog frame. */\n private getAnchorRect(): DOMRect {\n if (this.triggerEl) {\n const triggerRect = this.triggerEl.getBoundingClientRect();\n if (triggerRect.width > 0 || triggerRect.height > 0) return triggerRect;\n }\n return this.el.getBoundingClientRect();\n }\n\n /**\n * `position:fixed` is viewport-relative unless an ancestor has transform/filter/perspective,\n * in which case fixed is relative to that ancestor. Convert viewport coords accordingly.\n */\n private toFixedCoords(viewportTop: number, viewportLeft: number): { top: number; left: number } {\n const containingBlock = this.getFixedContainingBlock();\n if (!containingBlock) {\n return { top: viewportTop, left: viewportLeft };\n }\n\n const cbRect = containingBlock.getBoundingClientRect();\n return {\n top: viewportTop - cbRect.top,\n left: viewportLeft - cbRect.left,\n };\n }\n\n /** Whether this element's computed style makes it a containing block for\n * position:fixed descendants. Beyond transform/filter/perspective/backdrop-filter,\n * this includes will-change of those properties (md-list-item's --shifting uses\n * will-change: transform), layout/paint containment (incl. the contain shorthands\n * and container-type, which md-app-bar uses), and content-visibility. */\n private createsFixedContainingBlock(style: CSSStyleDeclaration): boolean {\n const s = style as CSSStyleDeclaration & {\n backdropFilter?: string;\n contain?: string;\n contentVisibility?: string;\n containerType?: string;\n translate?: string;\n rotate?: string;\n scale?: string;\n };\n // NB: check truthiness too — mock-doc (spec env) returns '' for unset\n // properties, and '' !== 'none' would make every element a containing block.\n if (\n (style.transform && style.transform !== 'none') ||\n (style.filter && style.filter !== 'none') ||\n (style.perspective && style.perspective !== 'none')\n ) return true;\n // The individual transform properties create containing blocks too.\n if (\n (s.translate && s.translate !== 'none') ||\n (s.rotate && s.rotate !== 'none') ||\n (s.scale && s.scale !== 'none')\n ) return true;\n if (s.backdropFilter && s.backdropFilter !== 'none') return true;\n if (/\\b(transform|perspective|filter|translate|rotate|scale)\\b/.test(style.willChange || '')) return true;\n if (/(layout|paint|strict|content)\\b/.test(s.contain || '')) return true;\n if (s.contentVisibility === 'auto' || s.contentVisibility === 'hidden') return true;\n // Only size containment creates a containing block — `scroll-state` query\n // containers apply no containment at all.\n if (s.containerType && /\\bsize\\b/.test(s.containerType)) return true;\n return false;\n }\n\n private getFixedContainingBlock(): HTMLElement | null {\n // Start at the HOST itself — a transformed md-tooltip is the popup's containing\n // block too (the popup lives inside its shadow root).\n let node: HTMLElement | null = this.el;\n\n while (node) {\n if (this.createsFixedContainingBlock(getComputedStyle(node))) {\n return node;\n }\n\n if (node.parentElement) {\n node = node.parentElement;\n } else if (node.parentNode instanceof ShadowRoot) {\n node = node.parentNode.host as HTMLElement;\n } else {\n node = null;\n }\n }\n\n return null;\n }\n\n private physicalPlacement(placement: string): string {\n if (typeof window === 'undefined') return placement;\n const isRTL = getComputedStyle(this.el).direction === 'rtl';\n if (!isRTL) return placement;\n\n const [axis, align = ''] = [placement.split('-')[0], placement.split('-').slice(1).join('-')];\n // The placement SIDE mirrors in RTL for left/right (inline axis).\n const flippedAxis = axis === 'left' ? 'right' : axis === 'right' ? 'left' : axis;\n // The -start/-end SUFFIX is inline-axis alignment only for top/bottom placements —\n // for left/right it aligns on the BLOCK (vertical) axis, which does not mirror\n // in RTL. Flipping it there swapped top-aligned to bottom-aligned.\n const flippedAlign =\n axis === 'top' || axis === 'bottom'\n ? align === 'start' ? 'end' : align === 'end' ? 'start' : align\n : align;\n return flippedAlign ? `${flippedAxis}-${flippedAlign}` : flippedAxis;\n }\n\n private calcCoords(\n hostW: number, hostH: number,\n popupW: number, popupH: number,\n placement: string,\n ): { top: number; left: number } {\n const o = this.offset;\n\n switch (placement) {\n case 'top': return { top: -(popupH + o), left: (hostW - popupW) / 2 };\n case 'top-start': return { top: -(popupH + o), left: 0 };\n case 'top-end': return { top: -(popupH + o), left: hostW - popupW };\n case 'bottom': return { top: hostH + o, left: (hostW - popupW) / 2 };\n case 'bottom-start': return { top: hostH + o, left: 0 };\n case 'bottom-end': return { top: hostH + o, left: hostW - popupW };\n case 'left': return { top: (hostH - popupH) / 2, left: -(popupW + o) };\n case 'left-start': return { top: 0, left: -(popupW + o) };\n case 'left-end': return { top: hostH - popupH, left: -(popupW + o) };\n case 'right': return { top: (hostH - popupH) / 2, left: hostW + o };\n case 'right-start': return { top: 0, left: hostW + o };\n case 'right-end': return { top: hostH - popupH, left: hostW + o };\n default: return { top: -(popupH + o), left: (hostW - popupW) / 2 };\n }\n }\n\n /**\n * Whether the placement fits the viewport along its MAIN axis only — the axis\n * the popup is pushed along (vertical for top/bottom, horizontal for left/right).\n * Cross-axis overflow is handled by clamping in `updatePosition`, not flipping,\n * so an edge-anchored centered tooltip keeps its requested side.\n */\n private fitsMainAxis(\n hostRect: DOMRect,\n popupW: number,\n popupH: number,\n relTop: number,\n relLeft: number,\n placement: string,\n ): boolean {\n const isVertical = placement.startsWith('top') || placement.startsWith('bottom');\n if (isVertical) {\n const absTop = hostRect.top + relTop;\n return absTop >= 0 && absTop + popupH <= window.innerHeight;\n }\n const absLeft = hostRect.left + relLeft;\n return absLeft >= 0 && absLeft + popupW <= window.innerWidth;\n }\n\n private getOppositePlacement(p: string): string {\n const [axis, align] = [p.split('-')[0], p.split('-').slice(1).join('-')];\n const opp: Record<string, string> = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };\n return align ? `${opp[axis]}-${align}` : opp[axis];\n }\n\n private findBestPlacement(\n hostRect: DOMRect,\n popupW: number,\n popupH: number,\n preferred: string,\n ): string {\n const check = (p: string) => {\n const c = this.calcCoords(hostRect.width, hostRect.height, popupW, popupH, p);\n return this.fitsMainAxis(hostRect, popupW, popupH, c.top, c.left, p);\n };\n\n if (check(preferred)) return preferred;\n\n const opposite = this.getOppositePlacement(preferred);\n if (check(opposite)) return opposite;\n\n const align = preferred.split('-')[1] || '';\n const axes = ['top', 'bottom', 'right', 'left'];\n for (const axis of axes) {\n const candidate = align ? `${axis}-${align}` : axis;\n if (candidate !== preferred && candidate !== opposite && check(candidate)) {\n return candidate;\n }\n }\n\n return preferred;\n }\n\n // ─── Render ──────────────────────────────────────────────\n\n render() {\n const isRich = this.variant === 'rich';\n const hasSubhead = !!this.subhead || this.hasSlottedSubhead;\n const hasActions = this.hasSlottedActions;\n\n return (\n <Host class=\"md-tooltip-wrapper\">\n <slot></slot>\n <div\n class={{\n 'md-tooltip__popup': true,\n 'md-tooltip__popup--plain': !isRich,\n 'md-tooltip__popup--rich': isRich,\n 'md-tooltip__popup--visible': this.isVisible,\n [`md-tooltip__popup--${this.resolvedPlacement}`]: true,\n }}\n id={this.tooltipId}\n role=\"tooltip\"\n part=\"popup\"\n aria-hidden={this.isVisible ? 'false' : 'true'}\n ref={el => (this.popupEl = el)}\n onMouseEnter={this.handlePopupEnter}\n onMouseLeave={this.handlePopupLeave}\n >\n {isRich ? ([\n hasSubhead && (\n <div class=\"md-tooltip__subhead\" part=\"subhead\" key=\"subhead\">\n <slot name=\"subhead\">{this.subhead}</slot>\n </div>\n ),\n <div class=\"md-tooltip__supporting-text\" part=\"supporting-text\" key=\"text\">\n <slot name=\"content\">{this.text}</slot>\n </div>,\n <div class={{ 'md-tooltip__actions': true, 'md-tooltip__actions--empty': !hasActions }} part=\"actions\" key=\"actions\">\n <slot name=\"actions\"></slot>\n </div>,\n ]) : (\n <span class=\"md-tooltip__text\" part=\"text\">{this.text}</span>\n )}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["mdTooltipCss","TOOLTIP_VIEWPORT_MARGIN","MdTooltip","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","text","subhead","variant","position","autoPosition","offset","crossOffset","open","showDelay","hideDelay","disabled","density","isVisible","resolvedPlacement","hasSlottedActions","hasSlottedSubhead","tooltipId","Math","random","toString","slice","scrollListenerBound","escapeListenerBound","hostHoverBound","hasLoaded","suppressed","onTriggerSlotChange","els","triggerSlot","assignedElements","length","bindTrigger","handleTriggerEnter","scheduleShow","handleTriggerLeave","scheduleHide","handleTriggerFocus","handleTriggerBlur","e","relatedTarget","el","contains","handleHostFocusOut","handlePopupEnter","clearTimers","handlePopupLeave","handleGlobalEscape","key","preventDefault","active","getDeepActiveElement","focusInside","triggerEl","focus","lastGeom","at","al","aw","ah","pw","ph","vw","vh","ex","ey","watchdogFrame","handleScroll","updatePosition","componentWillLoad","syncSlotFlags","componentDidLoad","setup","showTooltip","connectedCallback","addScrollListener","addEscapeListener","schedulePositionUpdate","startPositionWatchdog","shadow","shadowRoot","querySelector","undefined","addEventListener","MutationObserver","slotObserver","updateTriggerAria","observe","childList","subtree","characterData","first","children","Array","from","some","c","getAttribute","disconnectedCallback","stopPositionWatchdog","unbindTrigger","removeScrollListener","removeEscapeListener","removeEventListener","disconnect","onOpenChange","val","hideTooltip","onDisabledChange","removeAttribute","onDescriptionChange","show","hide","useHostHover","tag","tagName","toLowerCase","hasAttribute","tabIndex","startsWith","desc","computeDescription","setAttribute","parts","child","slot","t","textContent","trim","push","join","showTimer","setTimeout","hideTimer","document","a","activeElement","isConnected","mdOpen","emit","attempt","requestAnimationFrame","positioned","tick","popup","popupEl","offsetWidth","offsetHeight","getAnchorRect","p","getBoundingClientRect","g","drifted","top","left","width","height","abs","window","innerWidth","innerHeight","cancelAnimationFrame","mdClose","clearTimeout","capture","passive","anchorRect","popupW","popupH","placement","physicalPlacement","findBestPlacement","coords","calcCoords","isVertical","M","absLeft","maxLeft","clampedLeft","min","max","absTop","maxTop","clampedTop","fixedCoords","toFixedCoords","style","insetBlockStart","insetInlineStart","triggerRect","viewportTop","viewportLeft","containingBlock","getFixedContainingBlock","cbRect","createsFixedContainingBlock","s","transform","filter","perspective","translate","rotate","scale","backdropFilter","test","willChange","contain","contentVisibility","containerType","node","getComputedStyle","parentElement","parentNode","ShadowRoot","host","isRTL","direction","axis","align","split","flippedAxis","flippedAlign","hostW","hostH","o","fitsMainAxis","hostRect","relTop","relLeft","getOppositePlacement","opp","bottom","right","preferred","check","opposite","axes","candidate","render","isRich","hasSubhead","hasActions","h","Host","class","id","role","part","ref","onMouseEnter","onMouseLeave","name"],"sources":["src/components/md-tooltip/md-tooltip.css?tag=md-tooltip&encapsulation=shadow","src/components/md-tooltip/md-tooltip.tsx"],"sourcesContent":["/* ==========================================================\n md-tooltip — Material Design 3 Tooltip\n Spec: https://m3.material.io/components/tooltips/specs\n\n PUBLIC CSS CUSTOM PROPERTIES (override per-instance):\n --md-tooltip-plain-container-color Plain tooltip background\n --md-tooltip-plain-text-color Plain tooltip text color\n --md-tooltip-rich-container-color Rich tooltip background\n --md-tooltip-rich-subhead-color Rich subhead text color\n --md-tooltip-rich-text-color Rich supporting text color\n --md-tooltip-rich-action-color Rich action button color\n --md-tooltip-container-shape Border-radius (plain)\n --md-tooltip-plain-max-inline-size Plain tooltip max width\n --md-tooltip-rich-container-shape Border-radius (rich)\n --md-tooltip-rich-min-inline-size Rich tooltip min width\n --md-tooltip-rich-max-inline-size Rich tooltip max width\n\n CSS PARTS:\n popup Tooltip popup container\n subhead Rich tooltip subhead wrapper\n supporting-text Rich tooltip supporting text wrapper\n actions Rich tooltip action button wrapper\n text Plain tooltip text wrapper\n\n SLOTS:\n (default) Trigger element\n content Rich tooltip supporting text\n subhead Rich tooltip subhead\n actions Rich tooltip action buttons\n ========================================================== */\n\n/* ==========================================================\n 1. HOST\n ========================================================== */\n\n:host {\n display: inline-block;\n position: relative;\n}\n\n/* ==========================================================\n 2. POPUP — shared base\n ========================================================== */\n\n.md-tooltip__popup {\n /* Fixed + viewport coords (set in JS) so popups escape overflow:hidden ancestors. */\n position: fixed;\n z-index: var(--md-sys-z-index-tooltip, 1500);\n pointer-events: none;\n box-sizing: border-box;\n /* CRITICAL: width must not depend on the popup's own offsets. With width:auto, a\n fixed element shrink-to-fits into (containing block − left), so writing `left`\n changes the width, which re-wraps the text, which the position watchdog sees as\n drift and repositions — an animated wrap/slide feedback loop that crawls the\n popup across the screen one frame at a time. max-content sizes from the CONTENT\n only (the variant max-inline-size caps still bound it), decoupling measurement\n from position: one measure, one placement, no loop. */\n width: max-content;\n\n opacity: 0;\n visibility: hidden;\n transform: scale(0.9);\n\n transition:\n opacity var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n transform var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n visibility 0ms linear var(--md-sys-motion-duration-short2, 100ms);\n}\n\n.md-tooltip__popup--visible {\n opacity: 1;\n visibility: visible;\n transform: scale(1);\n pointer-events: auto;\n transition:\n opacity var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n transform var(--md-sys-motion-duration-short2, 100ms) var(--md-sys-motion-easing-standard, ease),\n visibility 0ms linear 0ms;\n}\n\n/* ==========================================================\n 3. PLAIN TOOLTIP\n Spec: height 24px (via padding), padding 8px, body-small\n ========================================================== */\n\n.md-tooltip__popup--plain {\n --_container-color: var(--md-tooltip-plain-container-color, var(--md-sys-color-inverse-surface, #313033));\n --_text-color: var(--md-tooltip-plain-text-color, var(--md-sys-color-inverse-on-surface, #F4EFF4));\n --_shape: var(--md-tooltip-container-shape, var(--md-sys-shape-corner-extra-small, 4px));\n\n background-color: var(--_container-color);\n color: var(--_text-color);\n border-radius: var(--_shape);\n\n /* Global density: on-grid padding tracks --md-sys-spacing-* (4/8 = inset-xs/sm);\n defaults resolve byte-for-byte at density 0. min-block-size stays the 24px\n spec height floor. */\n padding-block: var(--md-sys-spacing-inset-xs, 4px);\n padding-inline: var(--md-sys-spacing-inset-sm, 8px);\n\n min-block-size: max(20px, calc(24px + var(--md-sys-density-scale, 0) * 1px));\n max-inline-size: min(var(--md-tooltip-plain-max-inline-size, 280px), calc(100vw - 16px));\n\n font-family: var(--md-sys-typescale-body-small-font-family, Roboto, sans-serif);\n font-size: max(10px, calc(12px + var(--md-sys-density-scale, 0) * 0.5px));\n font-weight: var(--md-sys-typescale-body-small-font-weight, 400);\n line-height: max(14px, calc(16px + var(--md-sys-density-scale, 0) * 0.5px));\n letter-spacing: var(--md-sys-typescale-body-small-letter-spacing, 0.4px);\n\n /* Wrap long content over multiple lines instead of clipping it. The plain\n tooltip is the overflow tooltip used by md-list-item, so it must reveal\n the FULL text. `max-inline-size` caps the line length (280px default here,\n overridable per-instance) and the content wraps below it rather than\n truncating with an ellipsis. */\n white-space: normal;\n display: flex;\n align-items: center;\n}\n\n.md-tooltip__text {\n /* No ellipsis / overflow clipping — let the popup grow vertically and wrap.\n `overflow-wrap: anywhere` keeps an unbroken long word (URLs, IDs) from\n forcing the popup wider than its max-inline-size. */\n overflow-wrap: anywhere;\n}\n\n/* ==========================================================\n 4. RICH TOOLTIP\n Spec: top padding 12px, bottom 8px, left/right 16px\n ========================================================== */\n\n.md-tooltip__popup--rich {\n --_container-color: var(--md-tooltip-rich-container-color, var(--md-sys-color-surface-container, #F3EDF7));\n --_subhead-color: var(--md-tooltip-rich-subhead-color, var(--md-sys-color-on-surface-variant, #49454F));\n --_text-color: var(--md-tooltip-rich-text-color, var(--md-sys-color-on-surface-variant, #49454F));\n --_action-color: var(--md-tooltip-rich-action-color, var(--md-sys-color-primary, #6750A4));\n --_shape: var(--md-tooltip-rich-container-shape, var(--md-sys-shape-corner-medium, 12px));\n\n background-color: var(--_container-color);\n color: var(--_text-color);\n border-radius: var(--_shape);\n\n /* Global density: on-grid rich padding tracks --md-sys-spacing-*\n (12/8/16 = inset-md/sm/lg); defaults resolve byte-for-byte at density 0. */\n padding-block-start: var(--md-sys-spacing-inset-md, 12px);\n padding-block-end: var(--md-sys-spacing-inset-sm, 8px);\n padding-inline: var(--md-sys-spacing-inset-lg, 16px);\n\n min-inline-size: var(--md-tooltip-rich-min-inline-size, 120px);\n max-inline-size: min(var(--md-tooltip-rich-max-inline-size, 320px), calc(100vw - 16px));\n\n white-space: normal;\n box-shadow: var(--md-sys-elevation-2, 0 1px 3px 1px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.3));\n}\n\n/* Subhead */\n.md-tooltip__subhead {\n font-family: var(--md-sys-typescale-title-small-font-family, Roboto, sans-serif);\n font-size: max(11px, calc(14px + var(--md-sys-density-scale, 0) * 0.5px));\n font-weight: var(--md-sys-typescale-title-small-font-weight, 500);\n line-height: max(16px, calc(20px + var(--md-sys-density-scale, 0) * 1px));\n letter-spacing: var(--md-sys-typescale-title-small-letter-spacing, 0.1px);\n color: var(--_subhead-color);\n margin-block-end: var(--md-sys-spacing-gap-xs, 4px);\n}\n\n/* Supporting text */\n.md-tooltip__supporting-text {\n font-family: var(--md-sys-typescale-body-medium-font-family, Roboto, sans-serif);\n font-size: max(11px, calc(14px + var(--md-sys-density-scale, 0) * 0.5px));\n font-weight: var(--md-sys-typescale-body-medium-font-weight, 400);\n line-height: max(16px, calc(20px + var(--md-sys-density-scale, 0) * 1px));\n letter-spacing: var(--md-sys-typescale-body-medium-letter-spacing, 0.25px);\n color: var(--_text-color);\n}\n\n/* Actions */\n.md-tooltip__actions {\n display: flex;\n gap: var(--md-sys-spacing-gap-sm, 8px);\n justify-content: flex-end;\n margin-block-start: var(--md-sys-spacing-gap-md, 12px);\n color: var(--_action-color);\n}\n\n.md-tooltip__actions--empty {\n display: none;\n}\n\n/* Slotted action buttons */\n::slotted([slot=\"actions\"]) {\n color: var(--_action-color);\n}\n\n/* ==========================================================\n 5. PLACEMENT — transform-origin for enter animation\n Position is set inline via JS; these handle animation origin.\n ========================================================== */\n\n.md-tooltip__popup--top,\n.md-tooltip__popup--top-start,\n.md-tooltip__popup--top-end {\n transform-origin: bottom center;\n}\n\n.md-tooltip__popup--bottom,\n.md-tooltip__popup--bottom-start,\n.md-tooltip__popup--bottom-end {\n transform-origin: top center;\n}\n\n.md-tooltip__popup--left,\n.md-tooltip__popup--left-start,\n.md-tooltip__popup--left-end {\n transform-origin: center right;\n}\n\n.md-tooltip__popup--right,\n.md-tooltip__popup--right-start,\n.md-tooltip__popup--right-end {\n transform-origin: center left;\n}\n\n/* ==========================================================\n 6. RTL\n NB: no transform-origin overrides here. The placement classes are already\n PHYSICAL — JS (physicalPlacement) maps logical placements per direction\n before resolving the class — so the base origins in section 5 always face\n the trigger. The old :host-context([dir=rtl]) re-flip double-flipped them,\n making the entrance scale grow from the edge facing AWAY from the trigger.\n ========================================================== */\n\n:host-context([dir=\"rtl\"]) .md-tooltip__actions {\n justify-content: flex-start;\n}\n\n/* ==========================================================\n 7. FORCED COLORS (Windows High Contrast)\n The popup is a background + elevation surface — both are dropped in\n forced-colors mode, leaving the tooltip text floating with no boundary\n over the page. Give it a system-color border so the region stays\n perceivable (matches the md-toolbar hardened convention).\n ========================================================== */\n\n@media (forced-colors: active) {\n .md-tooltip__popup {\n border: 1px solid CanvasText;\n }\n}\n\n/* ==========================================================\n 8. REDUCED MOTION\n Honor a reduced-motion preference by dropping the scale/opacity\n entrance so the tooltip appears/disappears instantly instead of\n animating on every hover (md-list-item mounts a tooltip per row).\n ========================================================== */\n\n@media (prefers-reduced-motion: reduce) {\n .md-tooltip__popup,\n .md-tooltip__popup--visible {\n transition: none;\n transform: none;\n }\n}\n\n/* ==========================================================\n DENSITY (local override)\n Maps the local `density` prop onto the same --md-sys-density-scale signal a\n global `data-density` ancestor sets. Declared on :host, so a local rung wins\n over the inherited global one. Every density-sensitive value in this file\n derives from that single signal by calc — never add a fixed per-rung ladder.\n ========================================================== */\n:host([density='-1']) { --md-sys-density-scale: -1; }\n:host([density='-2']) { --md-sys-density-scale: -2; }\n:host([density='-3']) { --md-sys-density-scale: -3; }\n:host([density='-4']) { --md-sys-density-scale: -4; }\n","import { Component, Host, h, Prop, State, Event, EventEmitter, Element, Method, Watch } from '@stencil/core';\n\nexport type Placement =\n | 'top' | 'top-start' | 'top-end'\n | 'bottom' | 'bottom-start' | 'bottom-end'\n | 'left' | 'left-start' | 'left-end'\n | 'right' | 'right-start' | 'right-end';\n\n/** Minimum gap kept between a popup and the viewport edge when cross-axis clamping. */\nconst TOOLTIP_VIEWPORT_MARGIN = 8;\n\n/**\n * @slot - Trigger element the tooltip is anchored to\n * @slot content - Rich tooltip supporting text (overrides `text` prop)\n * @slot subhead - Rich tooltip subhead (overrides `subhead` prop)\n * @slot actions - Rich tooltip action buttons\n *\n * @part popup - Tooltip popup container\n * @part subhead - Rich tooltip subhead wrapper\n * @part supporting-text - Rich tooltip supporting text wrapper\n * @part actions - Rich tooltip action button wrapper\n * @part text - Plain tooltip text wrapper\n */\n@Component({\n tag: 'md-tooltip',\n styleUrl: 'md-tooltip.css',\n shadow: true,\n})\nexport class MdTooltip {\n @Element() el!: HTMLElement;\n\n /** Plain tooltip text, or rich tooltip supporting text */\n @Prop() text: string = '';\n\n /** Rich tooltip subhead (headline) */\n @Prop() subhead: string = '';\n\n /** Visual variant */\n @Prop({ reflect: true }) variant: 'plain' | 'rich' = 'plain';\n\n /** Preferred placement relative to the trigger */\n @Prop() position: Placement = 'top';\n\n /** Automatically reposition if overflowing the viewport */\n @Prop() autoPosition: boolean = true;\n\n /** Distance from the trigger in pixels */\n @Prop() offset: number = 8;\n\n /** Cross-axis offset in pixels */\n @Prop() crossOffset: number = 0;\n\n /** Programmatic open state */\n @Prop({ mutable: true, reflect: true }) open: boolean = false;\n\n /** Delay before showing (ms) */\n @Prop() showDelay: number = 500;\n\n /** Delay before hiding (ms) — for rich variant hover-out grace period */\n @Prop() hideDelay: number = 200;\n\n /** When true, hover/focus handlers are ignored and any open tooltip is dismissed. */\n @Prop({ reflect: true }) disabled: boolean = false;\n\n /**\n * Local density rung. Drives the same `--md-sys-density-scale` signal that a\n * global `data-density` ancestor sets, so a local value simply overrides the\n * inherited one. 0 = default, -4 = ultra-compact.\n */\n @Prop({ reflect: true }) density: 0 | -1 | -2 | -3 | -4 = 0;\n\n /**\n * Emits when the tooltip becomes visible. `bubbles:false` + `composed:false` keep it\n * from crossing the shadow boundary and retargeting onto an embedding host (the repo's\n * documented composed-event-leak class — see md-date-picker's swallow guards).\n */\n @Event({ bubbles: false, composed: false }) mdOpen: EventEmitter<void>;\n\n /** Emits when the tooltip is dismissed (does not bubble or cross shadow boundaries). */\n @Event({ bubbles: false, composed: false }) mdClose: EventEmitter<void>;\n\n @State() private isVisible = false;\n @State() private resolvedPlacement: Placement = 'top';\n @State() private hasSlottedActions = false;\n @State() private hasSlottedSubhead = false;\n\n private popupEl?: HTMLElement;\n private triggerEl?: HTMLElement;\n private triggerSlot?: HTMLSlotElement;\n private slotObserver?: MutationObserver;\n private showTimer?: ReturnType<typeof setTimeout>;\n private hideTimer?: ReturnType<typeof setTimeout>;\n private tooltipId = `md-tooltip-${Math.random().toString(36).slice(2, 9)}`;\n private scrollListenerBound = false;\n private escapeListenerBound = false;\n private hostHoverBound = false;\n private hasLoaded = false;\n /** Set on Escape dismissal; blocks re-show until the pointer/focus leaves the trigger. */\n private suppressed = false;\n\n // ─── Lifecycle ───────────────────────────────────────────\n\n componentWillLoad() {\n // Seed slot flags + visible state BEFORE the first render so the didLoad setup()\n // re-computes them to the same values — a no-op write rather than a state change\n // during componentDidLoad (which triggers Stencil's extra-re-render warning).\n // Honor `disabled`: a disabled tooltip must never render visible, and seeding\n // isVisible while disabled would also leak an unbalanced mdClose on the next hide.\n this.syncSlotFlags();\n if (this.open && !this.disabled) this.isVisible = true;\n }\n\n componentDidLoad() {\n this.hasLoaded = true;\n this.setup();\n if (this.open) this.showTooltip();\n }\n\n connectedCallback() {\n // On a REPARENT (disconnect→connect after first load), re-establish bindings —\n // componentDidLoad runs only once, so without this a moved tooltip goes dead.\n if (!this.hasLoaded) return;\n this.setup();\n // If the tooltip was still visible when it was moved, disconnectedCallback tore\n // down its scroll/Escape listeners without hiding it — restore them and reposition\n // against the moved trigger so it isn't stranded open, undismissable and detached.\n if (this.isVisible && !this.disabled) {\n this.addScrollListener();\n this.addEscapeListener();\n this.schedulePositionUpdate();\n this.startPositionWatchdog();\n } else if (this.open && !this.isVisible && !this.disabled) {\n // `open` was set while the element was DETACHED (showTooltip refuses to bind\n // global listeners there) — honor it now that we are connected again.\n this.showTooltip();\n }\n }\n\n /** (Re)attach trigger binding, slot detection and the host focusout listener. */\n private setup() {\n const shadow = this.el.shadowRoot;\n if (!shadow) return;\n\n this.triggerSlot = (shadow.querySelector('slot:not([name])') as HTMLSlotElement | null) ?? undefined;\n // addEventListener dedupes identical (fn, capture) pairs, so a re-setup is safe.\n this.triggerSlot?.addEventListener('slotchange', this.onTriggerSlotChange);\n this.el.addEventListener('focusout', this.handleHostFocusOut);\n\n // Rich content is authored in light DOM regardless of variant, so detect it there —\n // the shadow content/subhead/actions slots only exist while variant=\"rich\" renders,\n // which is why shadow-slot detection missed a runtime plain→rich switch.\n this.syncSlotFlags();\n if (typeof MutationObserver !== 'undefined' && !this.slotObserver) {\n // childList catches slotted content add/remove; subtree+characterData catches\n // edits to slotted text so a slot-only rich tooltip's aria-description stays fresh.\n this.slotObserver = new MutationObserver(() => {\n this.syncSlotFlags();\n if (this.triggerEl) this.updateTriggerAria(this.triggerEl);\n });\n this.slotObserver.observe(this.el, { childList: true, subtree: true, characterData: true });\n }\n\n const first = this.triggerSlot?.assignedElements()[0] as HTMLElement | undefined;\n if (first) this.bindTrigger(first);\n }\n\n private onTriggerSlotChange = () => {\n const els = this.triggerSlot?.assignedElements();\n if (els && els.length > 0) this.bindTrigger(els[0] as HTMLElement);\n };\n\n private syncSlotFlags() {\n // Direct-child scan (not `:scope >`, which Stencil's mock-doc can't parse).\n const children = Array.from(this.el.children);\n this.hasSlottedActions = children.some((c) => c.getAttribute('slot') === 'actions');\n this.hasSlottedSubhead = children.some((c) => c.getAttribute('slot') === 'subhead');\n }\n\n disconnectedCallback() {\n this.clearTimers();\n this.stopPositionWatchdog();\n this.unbindTrigger();\n this.removeScrollListener();\n this.removeEscapeListener();\n this.el.removeEventListener('focusout', this.handleHostFocusOut);\n this.triggerSlot?.removeEventListener('slotchange', this.onTriggerSlotChange);\n this.triggerSlot = undefined;\n this.slotObserver?.disconnect();\n this.slotObserver = undefined;\n }\n\n // ─── Watchers ────────────────────────────────────────────\n\n @Watch('open')\n onOpenChange(val: boolean) {\n if (val) {\n this.showTooltip();\n } else {\n this.hideTooltip();\n }\n }\n\n @Watch('disabled')\n onDisabledChange(disabled: boolean) {\n if (disabled) {\n this.clearTimers();\n if (this.open) this.open = false;\n this.triggerEl?.removeAttribute('aria-description');\n } else if (this.triggerEl) {\n this.updateTriggerAria(this.triggerEl);\n }\n }\n\n /** Keep the trigger's aria-description in sync when the tooltip's text changes\n * after binding (bindTrigger and the disabled watcher were the only refreshers). */\n @Watch('text')\n @Watch('subhead')\n onDescriptionChange() {\n if (this.triggerEl) this.updateTriggerAria(this.triggerEl);\n }\n\n // ─── Public Methods ──────────────────────────────────────\n\n /** Show the tooltip programmatically (no-op while `disabled`). */\n @Method()\n async show() {\n // Don't flip `open` (a reflected attribute) true while disabled — showTooltip\n // would early-return, leaving open=true with nothing visible (a state desync).\n if (this.disabled) return;\n this.open = true;\n }\n\n /** Dismiss the tooltip programmatically. */\n @Method()\n async hide() {\n this.open = false;\n }\n\n // ─── Trigger Binding ─────────────────────────────────────\n\n private bindTrigger(el: HTMLElement) {\n this.unbindTrigger();\n this.triggerEl = el;\n\n // Presentational triggers (e.g. weekday spans) are not focusable; hover the host instead.\n if (this.useHostHover(el)) {\n this.el.addEventListener('mouseenter', this.handleTriggerEnter);\n this.el.addEventListener('mouseleave', this.handleTriggerLeave);\n this.hostHoverBound = true;\n } else {\n el.addEventListener('mouseenter', this.handleTriggerEnter);\n el.addEventListener('mouseleave', this.handleTriggerLeave);\n }\n\n el.addEventListener('focus', this.handleTriggerFocus);\n el.addEventListener('blur', this.handleTriggerBlur);\n this.updateTriggerAria(el);\n }\n\n private unbindTrigger() {\n if (this.hostHoverBound) {\n this.el.removeEventListener('mouseenter', this.handleTriggerEnter);\n this.el.removeEventListener('mouseleave', this.handleTriggerLeave);\n this.hostHoverBound = false;\n } else if (this.triggerEl) {\n this.triggerEl.removeEventListener('mouseenter', this.handleTriggerEnter);\n this.triggerEl.removeEventListener('mouseleave', this.handleTriggerLeave);\n }\n\n if (!this.triggerEl) return;\n\n this.triggerEl.removeEventListener('focus', this.handleTriggerFocus);\n this.triggerEl.removeEventListener('blur', this.handleTriggerBlur);\n this.triggerEl.removeAttribute('aria-description');\n this.triggerEl = undefined;\n }\n\n /** True when hover should be tracked on the tooltip host (non-interactive triggers). */\n private useHostHover(el: HTMLElement): boolean {\n const tag = el.tagName.toLowerCase();\n if (tag === 'button' || tag === 'a' || tag === 'input' || tag === 'select' || tag === 'textarea') {\n return false;\n }\n if (el.hasAttribute('tabindex') && el.tabIndex >= 0) return false;\n if (tag.startsWith('md-')) return false;\n return true;\n }\n\n /** aria-description works across shadow DOM (unlike aria-describedby IDREFs) */\n private updateTriggerAria(el: HTMLElement) {\n if (this.disabled) {\n el.removeAttribute('aria-description');\n return;\n }\n const desc = this.computeDescription();\n if (desc) {\n el.setAttribute('aria-description', desc);\n } else {\n el.removeAttribute('aria-description');\n }\n }\n\n /**\n * The trigger's accessible description: `text`/`subhead` props first, then a\n * fallback to slotted rich content (subhead + supporting text) so a slot-only\n * rich tooltip is still announced to screen readers. Action buttons are excluded\n * — they are not description text and carry their own accessible names.\n */\n private computeDescription(): string {\n if (this.text) return this.text;\n if (this.subhead) return this.subhead;\n const parts: string[] = [];\n for (const child of Array.from(this.el.children)) {\n const slot = child.getAttribute('slot');\n if (slot === 'subhead' || slot === 'content') {\n const t = (child.textContent || '').trim();\n if (t) parts.push(t);\n }\n }\n return parts.join('. ');\n }\n\n // ─── Event Handlers ──────────────────────────────────────\n\n /** Arm the show timer, unless disabled or Escape-suppressed until re-entry. */\n private scheduleShow() {\n if (this.disabled || this.suppressed) return;\n this.clearTimers();\n this.showTimer = setTimeout(() => {\n this.open = true;\n }, this.showDelay);\n }\n\n /** Arm the hide grace timer (both variants) so the pointer can travel from the\n * trigger onto the popup without it vanishing — WCAG 1.4.13 \"hoverable\". */\n private scheduleHide() {\n this.clearTimers();\n this.hideTimer = setTimeout(() => {\n this.open = false;\n }, this.hideDelay);\n }\n\n private handleTriggerEnter = () => this.scheduleShow();\n\n private handleTriggerLeave = () => {\n // A fresh hover may re-show after an Escape dismissal.\n this.suppressed = false;\n this.scheduleHide();\n };\n\n private handleTriggerFocus = () => this.scheduleShow();\n\n private handleTriggerBlur = (e: FocusEvent) => {\n // Focus moving into the popup (rich action buttons) keeps the tooltip open.\n if (e.relatedTarget && this.el.contains(e.relatedTarget as Node)) return;\n this.suppressed = false;\n this.scheduleHide();\n };\n\n /**\n * Handles focusout at the host level — covers focus leaving\n * both the trigger AND slotted rich-tooltip action buttons.\n */\n private handleHostFocusOut = (e: FocusEvent) => {\n if (this.variant !== 'rich' || !this.isVisible) return;\n if (e.relatedTarget && this.el.contains(e.relatedTarget as Node)) return;\n this.scheduleHide();\n };\n\n /** Pointer over the popup keeps it open (hoverable) — both variants. */\n private handlePopupEnter = () => {\n this.clearTimers();\n };\n\n private handlePopupLeave = () => {\n this.scheduleHide();\n };\n\n // ─── Show / Hide ─────────────────────────────────────────\n\n /** Document-level Escape handler — dismisses from any focused descendant */\n private handleGlobalEscape = (e: KeyboardEvent) => {\n if (e.key !== 'Escape' || !this.isVisible) return;\n e.preventDefault();\n this.clearTimers();\n // Suppress re-show until the pointer/focus leaves and returns, so refocusing\n // the trigger (below) or a lingering hover can't immediately reopen it.\n this.suppressed = true;\n // WCAG 1.4.13: dismissal must NOT move focus. Only return focus to the trigger\n // when focus is currently inside the tooltip (popup/actions) or on the trigger —\n // never yank it from an unrelated element the user is interacting with.\n const active = this.getDeepActiveElement();\n const focusInside = !!active && (this.el.contains(active) || active === this.triggerEl);\n this.open = false;\n if (focusInside && this.triggerEl) this.triggerEl.focus();\n };\n\n /** Deepest focused element, piercing shadow roots. */\n private getDeepActiveElement(): Element | null {\n if (typeof document === 'undefined') return null;\n let a: Element | null = document.activeElement;\n while (a && a.shadowRoot && a.shadowRoot.activeElement) a = a.shadowRoot.activeElement;\n return a;\n }\n\n private addEscapeListener() {\n if (!this.escapeListenerBound) {\n document.addEventListener('keydown', this.handleGlobalEscape, true);\n this.escapeListenerBound = true;\n }\n }\n\n private removeEscapeListener() {\n if (this.escapeListenerBound) {\n document.removeEventListener('keydown', this.handleGlobalEscape, true);\n this.escapeListenerBound = false;\n }\n }\n\n private showTooltip() {\n if (this.disabled) return;\n // A DETACHED element must not bind global listeners or start the rAF loop —\n // disconnectedCallback can never fire again to clean them up (a stale ref\n // toggling `open` after removal would otherwise leak a 60fps loop plus a\n // document-level Escape handler forever). connectedCallback re-shows on\n // reconnect via the open/isVisible checks.\n if (!this.el.isConnected) return;\n this.isVisible = true;\n this.mdOpen.emit();\n this.addScrollListener();\n this.addEscapeListener();\n // Measure after layout so fixed coords are accurate (retry if popup not yet sized).\n this.schedulePositionUpdate();\n this.startPositionWatchdog();\n }\n\n private schedulePositionUpdate(attempt = 0) {\n requestAnimationFrame(() => {\n const positioned = this.updatePosition();\n if (!positioned && attempt < 3) {\n this.schedulePositionUpdate(attempt + 1);\n }\n });\n }\n\n // ─── Position Watchdog ──────────────────────────────────\n //\n // The scroll listener only repairs staleness that arrives as a light-DOM scroll.\n // Everything else that moves the anchor or resizes the popup after positioning is\n // invisible to it: window resize reflow, scrollers inside OTHER shadow roots\n // (scroll is composed:false), sibling layout shift, web-font/text growth, and a\n // containing-block appearing/vanishing at rest (md-list's --shifting adds\n // will-change:transform to rows that haven't moved; md-date-picker's entrance\n // transform settles back to none). Rather than plumbing per-ancestor listeners +\n // ResizeObservers + animation hooks (large lifecycle surface), a single rAF\n // watchdog runs ONLY while the tooltip is visible and repositions when the anchor\n // rect, popup size, the popup's ACTUAL viewport position (which shifts when a\n // containing block reinterprets the stored coords), or the viewport changes.\n // Cost: two getBoundingClientRect calls (anchor + popup) and two offset reads per\n // frame, per visible tooltip (tooltips are transient, effectively one at a time).\n\n /** Geometry snapshot from the last successful updatePosition. ex/ey are the popup's\n * EXPECTED viewport coords — if a containing-block change reinterprets the stored\n * style.top/left, the popup's real rect drifts from these and we reposition. */\n private lastGeom = { at: 0, al: 0, aw: 0, ah: 0, pw: 0, ph: 0, vw: 0, vh: 0, ex: 0, ey: 0 };\n private watchdogFrame = 0;\n\n private startPositionWatchdog() {\n if (typeof requestAnimationFrame !== 'function') return;\n this.stopPositionWatchdog();\n const tick = () => {\n if (!this.isVisible || !this.el.isConnected) {\n this.watchdogFrame = 0;\n return;\n }\n const popup = this.popupEl;\n if (popup && this.triggerEl) {\n const pw = popup.offsetWidth;\n const ph = popup.offsetHeight;\n // A 0x0 popup means a hidden ancestor — positioning would fail without\n // refreshing the snapshot, so skip until it has a box again (the size\n // delta versus the snapshot triggers the reposition on reveal).\n if (pw !== 0 || ph !== 0) {\n const a = this.getAnchorRect();\n const p = popup.getBoundingClientRect();\n const g = this.lastGeom;\n const drifted =\n a.top !== g.at || a.left !== g.al || a.width !== g.aw || a.height !== g.ah ||\n pw !== g.pw || ph !== g.ph ||\n // 0.5px tolerance absorbs subpixel churn; the entrance scale animation\n // exceeds it for a few frames, which just re-writes the same coords.\n Math.abs(p.top - g.ey) > 0.5 || Math.abs(p.left - g.ex) > 0.5 ||\n window.innerWidth !== g.vw || window.innerHeight !== g.vh;\n if (drifted) this.updatePosition();\n }\n }\n this.watchdogFrame = requestAnimationFrame(tick);\n };\n this.watchdogFrame = requestAnimationFrame(tick);\n }\n\n private stopPositionWatchdog() {\n if (this.watchdogFrame && typeof cancelAnimationFrame === 'function') {\n cancelAnimationFrame(this.watchdogFrame);\n }\n this.watchdogFrame = 0;\n }\n\n private hideTooltip() {\n // No spurious mdClose if it was never actually shown (e.g. hide() after a\n // show() that was suppressed by `disabled`) — keep open/close events balanced.\n if (!this.isVisible) return;\n this.isVisible = false;\n this.mdClose.emit();\n this.removeScrollListener();\n this.removeEscapeListener();\n this.stopPositionWatchdog();\n }\n\n private clearTimers() {\n if (this.showTimer != null) {\n clearTimeout(this.showTimer);\n this.showTimer = undefined;\n }\n if (this.hideTimer != null) {\n clearTimeout(this.hideTimer);\n this.hideTimer = undefined;\n }\n }\n\n // ─── Scroll Listener ────────────────────────────────────\n\n private addScrollListener() {\n if (!this.scrollListenerBound) {\n window.addEventListener('scroll', this.handleScroll, { capture: true, passive: true });\n this.scrollListenerBound = true;\n }\n }\n\n private removeScrollListener() {\n if (this.scrollListenerBound) {\n window.removeEventListener('scroll', this.handleScroll, true);\n this.scrollListenerBound = false;\n }\n }\n\n private handleScroll = () => {\n if (this.isVisible) this.updatePosition();\n };\n\n // ─── Positioning ─────────────────────────────────────────\n\n private updatePosition(): boolean {\n if (!this.popupEl || !this.triggerEl) return false;\n\n const anchorRect = this.getAnchorRect();\n const popupW = this.popupEl.offsetWidth;\n const popupH = this.popupEl.offsetHeight;\n\n if (popupW === 0 && popupH === 0) return false;\n\n let placement = this.physicalPlacement(this.position);\n\n if (this.autoPosition) {\n placement = this.findBestPlacement(anchorRect, popupW, popupH, placement);\n }\n\n const coords = this.calcCoords(anchorRect.width, anchorRect.height, popupW, popupH, placement);\n\n // crossOffset shifts the popup along the axis PERPENDICULAR to the placement:\n // horizontal for top/bottom, vertical for left/right. Applying it to `left`\n // unconditionally moved it along the MAIN axis for left/right placements.\n if (placement.startsWith('top') || placement.startsWith('bottom')) {\n coords.left += this.crossOffset;\n } else {\n coords.top += this.crossOffset;\n }\n\n // Cross-axis clamp: nudge the popup along the axis perpendicular to the\n // placement so it stays in the viewport, instead of flipping. A centered\n // top/bottom tooltip on an edge trigger (e.g. the first/last nav chevron in\n // a docked md-date-picker) would otherwise overflow horizontally — keep the\n // requested side and shift it inward so it stays bottom and fully visible.\n if (this.autoPosition) {\n const isVertical = placement.startsWith('top') || placement.startsWith('bottom');\n const M = TOOLTIP_VIEWPORT_MARGIN;\n if (isVertical) {\n const absLeft = anchorRect.left + coords.left;\n const maxLeft = window.innerWidth - popupW - M;\n const clampedLeft = Math.min(Math.max(absLeft, M), Math.max(M, maxLeft));\n coords.left += clampedLeft - absLeft;\n } else {\n const absTop = anchorRect.top + coords.top;\n const maxTop = window.innerHeight - popupH - M;\n const clampedTop = Math.min(Math.max(absTop, M), Math.max(M, maxTop));\n coords.top += clampedTop - absTop;\n }\n }\n\n const fixedCoords = this.toFixedCoords(anchorRect.top + coords.top, anchorRect.left + coords.left);\n\n // position:fixed — use physical top/left; getBoundingClientRect is viewport-physical.\n // Logical inset-inline-start would misplace popups in RTL (inline-start is on the right).\n this.popupEl.style.top = `${fixedCoords.top}px`;\n this.popupEl.style.left = `${fixedCoords.left}px`;\n this.popupEl.style.insetBlockStart = '';\n this.popupEl.style.insetInlineStart = '';\n this.resolvedPlacement = placement as Placement;\n // Snapshot the geometry this position was computed FROM — the watchdog\n // repositions when any of it drifts. ex/ey are the intended VIEWPORT position\n // (pre containing-block conversion): if a CB later appears/vanishes at rest,\n // the popup's real rect diverges from these with no other signal.\n this.lastGeom = {\n at: anchorRect.top, al: anchorRect.left, aw: anchorRect.width, ah: anchorRect.height,\n pw: popupW, ph: popupH,\n vw: window.innerWidth, vh: window.innerHeight,\n ex: anchorRect.left + coords.left, ey: anchorRect.top + coords.top,\n };\n return true;\n }\n\n /** Prefer the slotted trigger; fall back to the tooltip host when the trigger has\n * no box. Reads the trigger rect FIRST so the common case costs one rect read —\n * this runs every watchdog frame. */\n private getAnchorRect(): DOMRect {\n if (this.triggerEl) {\n const triggerRect = this.triggerEl.getBoundingClientRect();\n if (triggerRect.width > 0 || triggerRect.height > 0) return triggerRect;\n }\n return this.el.getBoundingClientRect();\n }\n\n /**\n * `position:fixed` is viewport-relative unless an ancestor has transform/filter/perspective,\n * in which case fixed is relative to that ancestor. Convert viewport coords accordingly.\n */\n private toFixedCoords(viewportTop: number, viewportLeft: number): { top: number; left: number } {\n const containingBlock = this.getFixedContainingBlock();\n if (!containingBlock) {\n return { top: viewportTop, left: viewportLeft };\n }\n\n const cbRect = containingBlock.getBoundingClientRect();\n return {\n top: viewportTop - cbRect.top,\n left: viewportLeft - cbRect.left,\n };\n }\n\n /** Whether this element's computed style makes it a containing block for\n * position:fixed descendants. Beyond transform/filter/perspective/backdrop-filter,\n * this includes will-change of those properties (md-list-item's --shifting uses\n * will-change: transform), layout/paint containment (incl. the contain shorthands\n * and container-type, which md-app-bar uses), and content-visibility. */\n private createsFixedContainingBlock(style: CSSStyleDeclaration): boolean {\n const s = style as CSSStyleDeclaration & {\n backdropFilter?: string;\n contain?: string;\n contentVisibility?: string;\n containerType?: string;\n translate?: string;\n rotate?: string;\n scale?: string;\n };\n // NB: check truthiness too — mock-doc (spec env) returns '' for unset\n // properties, and '' !== 'none' would make every element a containing block.\n if (\n (style.transform && style.transform !== 'none') ||\n (style.filter && style.filter !== 'none') ||\n (style.perspective && style.perspective !== 'none')\n ) return true;\n // The individual transform properties create containing blocks too.\n if (\n (s.translate && s.translate !== 'none') ||\n (s.rotate && s.rotate !== 'none') ||\n (s.scale && s.scale !== 'none')\n ) return true;\n if (s.backdropFilter && s.backdropFilter !== 'none') return true;\n if (/\\b(transform|perspective|filter|translate|rotate|scale)\\b/.test(style.willChange || '')) return true;\n if (/(layout|paint|strict|content)\\b/.test(s.contain || '')) return true;\n if (s.contentVisibility === 'auto' || s.contentVisibility === 'hidden') return true;\n // Only size containment creates a containing block — `scroll-state` query\n // containers apply no containment at all.\n if (s.containerType && /\\bsize\\b/.test(s.containerType)) return true;\n return false;\n }\n\n private getFixedContainingBlock(): HTMLElement | null {\n // Start at the HOST itself — a transformed md-tooltip is the popup's containing\n // block too (the popup lives inside its shadow root).\n let node: HTMLElement | null = this.el;\n\n while (node) {\n if (this.createsFixedContainingBlock(getComputedStyle(node))) {\n return node;\n }\n\n if (node.parentElement) {\n node = node.parentElement;\n } else if (node.parentNode instanceof ShadowRoot) {\n node = node.parentNode.host as HTMLElement;\n } else {\n node = null;\n }\n }\n\n return null;\n }\n\n private physicalPlacement(placement: string): string {\n if (typeof window === 'undefined') return placement;\n const isRTL = getComputedStyle(this.el).direction === 'rtl';\n if (!isRTL) return placement;\n\n const [axis, align = ''] = [placement.split('-')[0], placement.split('-').slice(1).join('-')];\n // The placement SIDE mirrors in RTL for left/right (inline axis).\n const flippedAxis = axis === 'left' ? 'right' : axis === 'right' ? 'left' : axis;\n // The -start/-end SUFFIX is inline-axis alignment only for top/bottom placements —\n // for left/right it aligns on the BLOCK (vertical) axis, which does not mirror\n // in RTL. Flipping it there swapped top-aligned to bottom-aligned.\n const flippedAlign =\n axis === 'top' || axis === 'bottom'\n ? align === 'start' ? 'end' : align === 'end' ? 'start' : align\n : align;\n return flippedAlign ? `${flippedAxis}-${flippedAlign}` : flippedAxis;\n }\n\n private calcCoords(\n hostW: number, hostH: number,\n popupW: number, popupH: number,\n placement: string,\n ): { top: number; left: number } {\n const o = this.offset;\n\n switch (placement) {\n case 'top': return { top: -(popupH + o), left: (hostW - popupW) / 2 };\n case 'top-start': return { top: -(popupH + o), left: 0 };\n case 'top-end': return { top: -(popupH + o), left: hostW - popupW };\n case 'bottom': return { top: hostH + o, left: (hostW - popupW) / 2 };\n case 'bottom-start': return { top: hostH + o, left: 0 };\n case 'bottom-end': return { top: hostH + o, left: hostW - popupW };\n case 'left': return { top: (hostH - popupH) / 2, left: -(popupW + o) };\n case 'left-start': return { top: 0, left: -(popupW + o) };\n case 'left-end': return { top: hostH - popupH, left: -(popupW + o) };\n case 'right': return { top: (hostH - popupH) / 2, left: hostW + o };\n case 'right-start': return { top: 0, left: hostW + o };\n case 'right-end': return { top: hostH - popupH, left: hostW + o };\n default: return { top: -(popupH + o), left: (hostW - popupW) / 2 };\n }\n }\n\n /**\n * Whether the placement fits the viewport along its MAIN axis only — the axis\n * the popup is pushed along (vertical for top/bottom, horizontal for left/right).\n * Cross-axis overflow is handled by clamping in `updatePosition`, not flipping,\n * so an edge-anchored centered tooltip keeps its requested side.\n */\n private fitsMainAxis(\n hostRect: DOMRect,\n popupW: number,\n popupH: number,\n relTop: number,\n relLeft: number,\n placement: string,\n ): boolean {\n const isVertical = placement.startsWith('top') || placement.startsWith('bottom');\n if (isVertical) {\n const absTop = hostRect.top + relTop;\n return absTop >= 0 && absTop + popupH <= window.innerHeight;\n }\n const absLeft = hostRect.left + relLeft;\n return absLeft >= 0 && absLeft + popupW <= window.innerWidth;\n }\n\n private getOppositePlacement(p: string): string {\n const [axis, align] = [p.split('-')[0], p.split('-').slice(1).join('-')];\n const opp: Record<string, string> = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };\n return align ? `${opp[axis]}-${align}` : opp[axis];\n }\n\n private findBestPlacement(\n hostRect: DOMRect,\n popupW: number,\n popupH: number,\n preferred: string,\n ): string {\n const check = (p: string) => {\n const c = this.calcCoords(hostRect.width, hostRect.height, popupW, popupH, p);\n return this.fitsMainAxis(hostRect, popupW, popupH, c.top, c.left, p);\n };\n\n if (check(preferred)) return preferred;\n\n const opposite = this.getOppositePlacement(preferred);\n if (check(opposite)) return opposite;\n\n const align = preferred.split('-')[1] || '';\n const axes = ['top', 'bottom', 'right', 'left'];\n for (const axis of axes) {\n const candidate = align ? `${axis}-${align}` : axis;\n if (candidate !== preferred && candidate !== opposite && check(candidate)) {\n return candidate;\n }\n }\n\n return preferred;\n }\n\n // ─── Render ──────────────────────────────────────────────\n\n render() {\n const isRich = this.variant === 'rich';\n const hasSubhead = !!this.subhead || this.hasSlottedSubhead;\n const hasActions = this.hasSlottedActions;\n\n return (\n <Host class=\"md-tooltip-wrapper\">\n <slot></slot>\n <div\n class={{\n 'md-tooltip__popup': true,\n 'md-tooltip__popup--plain': !isRich,\n 'md-tooltip__popup--rich': isRich,\n 'md-tooltip__popup--visible': this.isVisible,\n [`md-tooltip__popup--${this.resolvedPlacement}`]: true,\n }}\n id={this.tooltipId}\n role=\"tooltip\"\n part=\"popup\"\n aria-hidden={this.isVisible ? 'false' : 'true'}\n ref={el => (this.popupEl = el)}\n onMouseEnter={this.handlePopupEnter}\n onMouseLeave={this.handlePopupLeave}\n >\n {isRich ? ([\n hasSubhead && (\n <div class=\"md-tooltip__subhead\" part=\"subhead\" key=\"subhead\">\n <slot name=\"subhead\">{this.subhead}</slot>\n </div>\n ),\n <div class=\"md-tooltip__supporting-text\" part=\"supporting-text\" key=\"text\">\n <slot name=\"content\">{this.text}</slot>\n </div>,\n <div class={{ 'md-tooltip__actions': true, 'md-tooltip__actions--empty': !hasActions }} part=\"actions\" key=\"actions\">\n <slot name=\"actions\"></slot>\n </div>,\n ]) : (\n <span class=\"md-tooltip__text\" part=\"text\">{this.text}</span>\n )}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}