@spectrum-web-components/tooltip 1.12.1 → 1.12.2-next.20260706135249
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +4 -2
- package/package.json +5 -5
- package/src/Tooltip.d.ts +5 -0
- package/src/Tooltip.dev.js +25 -0
- package/src/Tooltip.dev.js.map +2 -2
- package/src/Tooltip.js +2 -2
- package/src/Tooltip.js.map +2 -2
package/custom-elements.json
CHANGED
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
},
|
|
161
161
|
"privacy": "public",
|
|
162
162
|
"default": "false",
|
|
163
|
-
"
|
|
163
|
+
"deprecated": "The `self-managed` attribute will be removed in a future release in favor of an updated binding method.\n\nAutomatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.\nWithout this, you must provide your own `overlay-trigger`.",
|
|
164
164
|
"attribute": "self-managed"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
@@ -217,6 +217,7 @@
|
|
|
217
217
|
"text": "number | undefined"
|
|
218
218
|
},
|
|
219
219
|
"privacy": "public",
|
|
220
|
+
"deprecated": "The `tip-padding` attribute will be removed in a future release.",
|
|
220
221
|
"attribute": "tipPadding"
|
|
221
222
|
},
|
|
222
223
|
{
|
|
@@ -335,7 +336,7 @@
|
|
|
335
336
|
"text": "boolean"
|
|
336
337
|
},
|
|
337
338
|
"default": "false",
|
|
338
|
-
"
|
|
339
|
+
"deprecated": "The `self-managed` attribute will be removed in a future release in favor of an updated binding method.\n\nAutomatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.\nWithout this, you must provide your own `overlay-trigger`.",
|
|
339
340
|
"fieldName": "selfManaged"
|
|
340
341
|
},
|
|
341
342
|
{
|
|
@@ -359,6 +360,7 @@
|
|
|
359
360
|
"type": {
|
|
360
361
|
"text": "number | undefined"
|
|
361
362
|
},
|
|
363
|
+
"deprecated": "The `tip-padding` attribute will be removed in a future release.",
|
|
362
364
|
"fieldName": "tipPadding"
|
|
363
365
|
},
|
|
364
366
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/tooltip",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.2-next.20260706135249",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Adobe",
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
],
|
|
59
59
|
"types": "./src/index.d.ts",
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@spectrum-web-components/base": "1.12.
|
|
62
|
-
"@spectrum-web-components/overlay": "1.12.
|
|
63
|
-
"@spectrum-web-components/reactive-controllers": "1.12.
|
|
64
|
-
"@spectrum-web-components/shared": "1.12.
|
|
61
|
+
"@spectrum-web-components/base": "1.12.2-next.20260706135249",
|
|
62
|
+
"@spectrum-web-components/overlay": "1.12.2-next.20260706135249",
|
|
63
|
+
"@spectrum-web-components/reactive-controllers": "1.12.2-next.20260706135249",
|
|
64
|
+
"@spectrum-web-components/shared": "1.12.2-next.20260706135249"
|
|
65
65
|
},
|
|
66
66
|
"keywords": [
|
|
67
67
|
"design-system",
|
package/src/Tooltip.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export declare class Tooltip extends SpectrumElement {
|
|
|
33
33
|
*/
|
|
34
34
|
disabled: boolean;
|
|
35
35
|
/**
|
|
36
|
+
* @deprecated The `self-managed` attribute will be removed in a future release in favor of an updated binding method.
|
|
37
|
+
*
|
|
36
38
|
* Automatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.
|
|
37
39
|
* Without this, you must provide your own `overlay-trigger`.
|
|
38
40
|
*/
|
|
@@ -46,6 +48,9 @@ export declare class Tooltip extends SpectrumElement {
|
|
|
46
48
|
*/
|
|
47
49
|
placement?: Placement;
|
|
48
50
|
tipElement: HTMLSpanElement;
|
|
51
|
+
/**
|
|
52
|
+
* @deprecated The `tip-padding` attribute will be removed in a future release.
|
|
53
|
+
*/
|
|
49
54
|
tipPadding?: number;
|
|
50
55
|
private _triggerElement;
|
|
51
56
|
/**
|
package/src/Tooltip.dev.js
CHANGED
|
@@ -136,6 +136,23 @@ export class Tooltip extends SpectrumElement {
|
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
138
|
if (["info", "positive", "negative"].includes(variant)) {
|
|
139
|
+
if (true) {
|
|
140
|
+
if (variant === "info") {
|
|
141
|
+
window.__swc.warn(
|
|
142
|
+
this,
|
|
143
|
+
`The "info" variant on <${this.localName}> is deprecated and will be removed in a future release. Use "informative" instead.`,
|
|
144
|
+
"https://opensource.adobe.com/spectrum-web-components/components/tooltip",
|
|
145
|
+
{ level: "deprecation" }
|
|
146
|
+
);
|
|
147
|
+
} else if (variant === "positive") {
|
|
148
|
+
window.__swc.warn(
|
|
149
|
+
this,
|
|
150
|
+
`The "positive" variant on <${this.localName}> is deprecated and will be removed in a future release.`,
|
|
151
|
+
"https://opensource.adobe.com/spectrum-web-components/components/tooltip",
|
|
152
|
+
{ level: "deprecation" }
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
139
156
|
this.setAttribute("variant", variant);
|
|
140
157
|
this._variant = variant;
|
|
141
158
|
return;
|
|
@@ -254,6 +271,14 @@ export class Tooltip extends SpectrumElement {
|
|
|
254
271
|
if (!this.selfManaged) {
|
|
255
272
|
return;
|
|
256
273
|
}
|
|
274
|
+
if (true) {
|
|
275
|
+
window.__swc.warn(
|
|
276
|
+
this,
|
|
277
|
+
`The "self-managed" attribute on <${this.localName}> is deprecated and will be removed in a future release in favor of an updated binding method.`,
|
|
278
|
+
"https://opensource.adobe.com/spectrum-web-components/components/tooltip",
|
|
279
|
+
{ level: "deprecation" }
|
|
280
|
+
);
|
|
281
|
+
}
|
|
257
282
|
const overlayElement = this.overlayElement;
|
|
258
283
|
if (overlayElement) {
|
|
259
284
|
const triggerElement = this.triggerElement;
|
package/src/Tooltip.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tooltip.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport { ifDefined } from '@spectrum-web-components/base/src/directives.js';\nimport type {\n Overlay,\n OverlayOpenCloseDetail,\n Placement,\n} from '@spectrum-web-components/overlay';\nimport { DependencyManagerController } from '@spectrum-web-components/reactive-controllers/src/DependencyManger.js';\nimport { focusableSelector } from '@spectrum-web-components/shared/src/focusable-selectors.js';\n\nimport tooltipStyles from './tooltip.css.js';\n\nclass TooltipOpenable extends HTMLElement {\n constructor() {\n super();\n this.addEventListener('sp-opened', this.redispatchEvent);\n this.addEventListener('sp-closed', this.redispatchEvent);\n }\n redispatchEvent(event: Event): void {\n event.stopPropagation();\n this.tooltip.dispatchEvent(\n new CustomEvent<OverlayOpenCloseDetail>(event.type, {\n bubbles: event.bubbles,\n composed: event.composed,\n detail: (event as CustomEvent<OverlayOpenCloseDetail>).detail,\n })\n );\n }\n get tooltip(): Tooltip {\n return (this.getRootNode() as ShadowRoot).host as Tooltip;\n }\n static get observedAttributes(): string[] {\n return ['open', 'placement'];\n }\n attributeChangedCallback(\n name: 'open' | 'placement',\n _oldValue: string,\n newValue: 'string'\n ): void {\n switch (name) {\n // API generally sets `open` as a property\n /* c8 ignore next 3 */\n case 'open':\n this.open = newValue !== null;\n break;\n case 'placement':\n this.placement = newValue as Placement;\n break;\n }\n }\n set open(open: boolean) {\n this._open = open;\n const { tooltip } = this;\n /* c8 ignore next 3 */\n if (!tooltip) {\n return;\n }\n tooltip.open = open;\n }\n /* c8 ignore next 3 */\n get open(): boolean {\n return this._open;\n }\n private _open = false;\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n set placement(placement: Placement) {\n this._placement = placement;\n const { tooltip } = this;\n if (!tooltip) {\n return;\n }\n tooltip.placement = placement;\n }\n /* c8 ignore next 3 */\n get placement(): Placement {\n return this._placement;\n }\n private _placement: Placement = 'top';\n get tipElement(): HTMLElement {\n return this.tooltip.tipElement;\n }\n}\n\nif (!customElements.get('sp-tooltip-openable')) {\n customElements.define('sp-tooltip-openable', TooltipOpenable);\n}\n\n/**\n * @element sp-tooltip\n *\n * @slot icon - the icon element appearing at the start of the label\n * @slot - the text label of the Tooltip\n */\nexport class Tooltip extends SpectrumElement {\n public static override get styles(): CSSResultArray {\n return [tooltipStyles];\n }\n\n /**\n * A Tooltip that is `delayed` will its Overlay wait until a warm-up period of\n * 1000ms has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened, a\n * cooldown period of 1000ms will begin. Once the cooldown has completed, the next\n * Overlay to be opened will be subject to the warm-up period if provided that option.\n */\n @property({ type: Boolean })\n delayed = false;\n\n private dependencyManager = new DependencyManagerController(this);\n\n /**\n * Whether to prevent a self-managed Tooltip from responding to user input.\n */\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * Automatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.\n * Without this, you must provide your own `overlay-trigger`.\n */\n @property({ type: Boolean, attribute: 'self-managed' })\n public selfManaged = false;\n\n @property({ type: Number })\n public offset = 0;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @query('sp-overlay')\n public overlayElement?: Overlay;\n\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n @property({ reflect: true })\n public placement?: Placement;\n\n @query('#tip')\n public tipElement!: HTMLSpanElement;\n\n @property({ type: Number })\n public tipPadding?: number;\n\n private _triggerElement: HTMLElement | null = null;\n\n /**\n * Explicit trigger element override for self-managed tooltip usage.\n *\n * This is useful when the intended trigger is not an ancestor of the tooltip\n * in the composed tree (for example, tooltips slotted into components that\n * render their interactive trigger internally).\n */\n public set triggerElement(triggerElement: HTMLElement | null) {\n this._triggerElement = triggerElement;\n if (this.overlayElement) {\n this.overlayElement.triggerElement = triggerElement;\n }\n }\n\n public get triggerElement(): HTMLElement | null {\n return this._triggerElement || this.resolveSelfManagedTriggerElement();\n }\n\n /* Ensure that a '' value for `variant` removes the attribute instead of a blank value */\n private _variant = '';\n\n @property({ type: String })\n public get variant(): string {\n return this._variant;\n }\n public set variant(variant: string) {\n if (variant === this.variant) {\n return;\n }\n if (['info', 'positive', 'negative'].includes(variant)) {\n this.setAttribute('variant', variant);\n this._variant = variant;\n return;\n }\n this.removeAttribute('variant');\n this._variant = '';\n }\n\n private handleOpenOverlay = (): void => {\n this.open = true;\n };\n\n protected handleCloseOverlay = (): void => {\n this.open = false;\n };\n\n protected forwardTransitionEvent(event: TransitionEvent): void {\n this.dispatchEvent(\n new TransitionEvent(event.type, {\n bubbles: true,\n composed: true,\n propertyName: event.propertyName,\n })\n );\n }\n\n /**\n * Finds the trigger element for a self-managed tooltip by traversing up the composed DOM tree.\n *\n * Self-managed tooltips automatically bind to their first focusable ancestor element.\n * This method walks up through shadow DOM boundaries to find a suitable trigger element.\n *\n * A trigger element must match the focusableSelector, which includes:\n * - Interactive elements like buttons, inputs, links, etc.\n * - Elements with tabindex (except -1)\n * - Elements with focusable=\"true\"\n *\n * Common scenarios where no trigger element is found:\n * 1. Tooltip is placed directly in document body without a focusable parent\n * 2. Tooltip is nested in non-interactive elements (divs, spans) without focusable ancestors\n * 3. All ancestor elements have tabindex=\"-1\" or are otherwise non-focusable\n *\n * Expected usage: <sp-action-button><sp-tooltip self-managed>...</sp-tooltip></sp-action-button>\n *\n * @returns The first focusable ancestor element, or null if none found\n */\n private resolveSelfManagedTriggerElement(): HTMLElement | null {\n // Start from the assigned slot (if tooltip is slotted) or the tooltip itself\n let start: HTMLElement = this.assignedSlot || this;\n let root = start.getRootNode();\n\n // Check if we've reached the document root without finding a parent\n // This happens when the tooltip is at the top level without a container\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[INITIAL_TRAVERSAL] Self-managed <${this.localName}> is at document root without a parent element. Self-managed tooltips must be nested inside focusable elements like <sp-action-button>, <sp-button>, or elements with tabindex.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Get the initial candidate trigger element:\n // 1. Direct parent element in the same document/shadow root\n // 2. Shadow host if we're in a shadow root\n // 3. The root itself as fallback\n let triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n root) as HTMLElement;\n\n // Walk up the composed tree until we find a focusable element\n // The focusableSelector matches interactive elements that can receive focus\n while (!triggerElement?.matches?.(focusableSelector)) {\n // Move to the next level up in the composed tree\n // This handles both regular DOM and shadow DOM traversal\n start = triggerElement.assignedSlot || (triggerElement as HTMLElement);\n root = start.getRootNode();\n\n /* c8 ignore next 13 */\n // Check if we've reached the document root during traversal\n // This happens when no focusable ancestor is found\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[TRAVERSAL_EXHAUSTED] Self-managed <${this.localName}> could not find a focusable trigger element. All ancestor elements are non-focusable. Ensure the tooltip is nested inside an interactive element like <sp-action-button>, <sp-button>, or add tabindex=\"0\" to a parent element.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Continue traversing up to find the next candidate\n triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n /* c8 ignore next 1 */\n root) as HTMLElement;\n }\n\n return triggerElement;\n }\n\n override render(): TemplateResult {\n const tooltip = html`\n <sp-tooltip-openable\n id=\"tooltip\"\n placement=${ifDefined(this.placement)}\n @transitionrun=${this.forwardTransitionEvent}\n @transitionend=${this.forwardTransitionEvent}\n @transitioncancel=${this.forwardTransitionEvent}\n >\n <slot name=\"icon\"></slot>\n <span id=\"label\"><slot></slot></span>\n <span id=\"tip\" aria-hidden=\"true\"></span>\n </sp-tooltip-openable>\n `;\n if (this.selfManaged) {\n this.dependencyManager.add('sp-overlay');\n import('@spectrum-web-components/overlay/sp-overlay.js');\n return html`\n <sp-overlay\n ?open=${this.open && !this.disabled && this.dependencyManager.loaded}\n ?delayed=${this.delayed}\n ?disabled=${this.disabled}\n offset=${this.offset}\n .placement=${this.placement}\n type=\"hint\"\n .tipPadding=${this.tipPadding}\n .triggerInteraction=${'hover'}\n @sp-opened=${this.handleOpenOverlay}\n @sp-closed=${this.handleCloseOverlay}\n >\n ${tooltip}\n </sp-overlay>\n `;\n } else {\n return tooltip;\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n\n this.updateComplete.then(() => {\n if (!this.selfManaged) {\n return;\n }\n const overlayElement = this.overlayElement;\n if (overlayElement) {\n const triggerElement = this.triggerElement;\n overlayElement.triggerElement = triggerElement;\n }\n });\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;AAYA;AAAA,EAEE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAM1B,SAAS,mCAAmC;AAC5C,SAAS,yBAAyB;AAElC,OAAO,mBAAmB;AAE1B,MAAM,wBAAwB,YAAY;AAAA,EACxC,cAAc;AACZ,UAAM;AAiDR,SAAQ,QAAQ;AAiBhB,SAAQ,aAAwB;AAjE9B,SAAK,iBAAiB,aAAa,KAAK,eAAe;AACvD,SAAK,iBAAiB,aAAa,KAAK,eAAe;AAAA,EACzD;AAAA,EACA,gBAAgB,OAAoB;AAClC,UAAM,gBAAgB;AACtB,SAAK,QAAQ;AAAA,MACX,IAAI,YAAoC,MAAM,MAAM;AAAA,QAClD,SAAS,MAAM;AAAA,QACf,UAAU,MAAM;AAAA,QAChB,QAAS,MAA8C;AAAA,MACzD,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EACA,IAAI,UAAmB;AACrB,WAAQ,KAAK,YAAY,EAAiB;AAAA,EAC5C;AAAA,EACA,WAAW,qBAA+B;AACxC,WAAO,CAAC,QAAQ,WAAW;AAAA,EAC7B;AAAA,EACA,yBACE,MACA,WACA,UACM;AACN,YAAQ,MAAM;AAAA,MAGZ,KAAK;AACH,aAAK,OAAO,aAAa;AACzB;AAAA,MACF,KAAK;AACH,aAAK,YAAY;AACjB;AAAA,IACJ;AAAA,EACF;AAAA,EACA,IAAI,KAAK,MAAe;AACtB,SAAK,QAAQ;AACb,UAAM,EAAE,QAAQ,IAAI;AAEpB,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,YAAQ,OAAO;AAAA,EACjB;AAAA;AAAA,EAEA,IAAI,OAAgB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAU,WAAsB;AAClC,SAAK,aAAa;AAClB,UAAM,EAAE,QAAQ,IAAI;AACpB,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,YAAQ,YAAY;AAAA,EACtB;AAAA;AAAA,EAEA,IAAI,YAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAA0B;AAC5B,WAAO,KAAK,QAAQ;AAAA,EACtB;AACF;AAEA,IAAI,CAAC,eAAe,IAAI,qBAAqB,GAAG;AAC9C,iBAAe,OAAO,uBAAuB,eAAe;AAC9D;AAQO,aAAM,gBAAgB,gBAAgB;AAAA,EAAtC;AAAA;AAaL,mBAAU;AAEV,SAAQ,oBAAoB,IAAI,4BAA4B,IAAI;AAMhE,oBAAW;
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport { ifDefined } from '@spectrum-web-components/base/src/directives.js';\nimport type {\n Overlay,\n OverlayOpenCloseDetail,\n Placement,\n} from '@spectrum-web-components/overlay';\nimport { DependencyManagerController } from '@spectrum-web-components/reactive-controllers/src/DependencyManger.js';\nimport { focusableSelector } from '@spectrum-web-components/shared/src/focusable-selectors.js';\n\nimport tooltipStyles from './tooltip.css.js';\n\nclass TooltipOpenable extends HTMLElement {\n constructor() {\n super();\n this.addEventListener('sp-opened', this.redispatchEvent);\n this.addEventListener('sp-closed', this.redispatchEvent);\n }\n redispatchEvent(event: Event): void {\n event.stopPropagation();\n this.tooltip.dispatchEvent(\n new CustomEvent<OverlayOpenCloseDetail>(event.type, {\n bubbles: event.bubbles,\n composed: event.composed,\n detail: (event as CustomEvent<OverlayOpenCloseDetail>).detail,\n })\n );\n }\n get tooltip(): Tooltip {\n return (this.getRootNode() as ShadowRoot).host as Tooltip;\n }\n static get observedAttributes(): string[] {\n return ['open', 'placement'];\n }\n attributeChangedCallback(\n name: 'open' | 'placement',\n _oldValue: string,\n newValue: 'string'\n ): void {\n switch (name) {\n // API generally sets `open` as a property\n /* c8 ignore next 3 */\n case 'open':\n this.open = newValue !== null;\n break;\n case 'placement':\n this.placement = newValue as Placement;\n break;\n }\n }\n set open(open: boolean) {\n this._open = open;\n const { tooltip } = this;\n /* c8 ignore next 3 */\n if (!tooltip) {\n return;\n }\n tooltip.open = open;\n }\n /* c8 ignore next 3 */\n get open(): boolean {\n return this._open;\n }\n private _open = false;\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n set placement(placement: Placement) {\n this._placement = placement;\n const { tooltip } = this;\n if (!tooltip) {\n return;\n }\n tooltip.placement = placement;\n }\n /* c8 ignore next 3 */\n get placement(): Placement {\n return this._placement;\n }\n private _placement: Placement = 'top';\n get tipElement(): HTMLElement {\n return this.tooltip.tipElement;\n }\n}\n\nif (!customElements.get('sp-tooltip-openable')) {\n customElements.define('sp-tooltip-openable', TooltipOpenable);\n}\n\n/**\n * @element sp-tooltip\n *\n * @slot icon - the icon element appearing at the start of the label\n * @slot - the text label of the Tooltip\n */\nexport class Tooltip extends SpectrumElement {\n public static override get styles(): CSSResultArray {\n return [tooltipStyles];\n }\n\n /**\n * A Tooltip that is `delayed` will its Overlay wait until a warm-up period of\n * 1000ms has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened, a\n * cooldown period of 1000ms will begin. Once the cooldown has completed, the next\n * Overlay to be opened will be subject to the warm-up period if provided that option.\n */\n @property({ type: Boolean })\n delayed = false;\n\n private dependencyManager = new DependencyManagerController(this);\n\n /**\n * Whether to prevent a self-managed Tooltip from responding to user input.\n */\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * @deprecated The `self-managed` attribute will be removed in a future release in favor of an updated binding method.\n *\n * Automatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.\n * Without this, you must provide your own `overlay-trigger`.\n */\n @property({ type: Boolean, attribute: 'self-managed' })\n public selfManaged = false;\n\n @property({ type: Number })\n public offset = 0;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @query('sp-overlay')\n public overlayElement?: Overlay;\n\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n @property({ reflect: true })\n public placement?: Placement;\n\n @query('#tip')\n public tipElement!: HTMLSpanElement;\n\n /**\n * @deprecated The `tip-padding` attribute will be removed in a future release.\n */\n @property({ type: Number })\n public tipPadding?: number;\n\n private _triggerElement: HTMLElement | null = null;\n\n /**\n * Explicit trigger element override for self-managed tooltip usage.\n *\n * This is useful when the intended trigger is not an ancestor of the tooltip\n * in the composed tree (for example, tooltips slotted into components that\n * render their interactive trigger internally).\n */\n public set triggerElement(triggerElement: HTMLElement | null) {\n this._triggerElement = triggerElement;\n if (this.overlayElement) {\n this.overlayElement.triggerElement = triggerElement;\n }\n }\n\n public get triggerElement(): HTMLElement | null {\n return this._triggerElement || this.resolveSelfManagedTriggerElement();\n }\n\n /* Ensure that a '' value for `variant` removes the attribute instead of a blank value */\n private _variant = '';\n\n @property({ type: String })\n public get variant(): string {\n return this._variant;\n }\n public set variant(variant: string) {\n if (variant === this.variant) {\n return;\n }\n if (['info', 'positive', 'negative'].includes(variant)) {\n if (window.__swc?.DEBUG) {\n if (variant === 'info') {\n window.__swc.warn(\n this,\n `The \"info\" variant on <${this.localName}> is deprecated and will be removed in a future release. Use \"informative\" instead.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip',\n { level: 'deprecation' }\n );\n } else if (variant === 'positive') {\n window.__swc.warn(\n this,\n `The \"positive\" variant on <${this.localName}> is deprecated and will be removed in a future release.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip',\n { level: 'deprecation' }\n );\n }\n }\n this.setAttribute('variant', variant);\n this._variant = variant;\n return;\n }\n this.removeAttribute('variant');\n this._variant = '';\n }\n\n private handleOpenOverlay = (): void => {\n this.open = true;\n };\n\n protected handleCloseOverlay = (): void => {\n this.open = false;\n };\n\n protected forwardTransitionEvent(event: TransitionEvent): void {\n this.dispatchEvent(\n new TransitionEvent(event.type, {\n bubbles: true,\n composed: true,\n propertyName: event.propertyName,\n })\n );\n }\n\n /**\n * Finds the trigger element for a self-managed tooltip by traversing up the composed DOM tree.\n *\n * Self-managed tooltips automatically bind to their first focusable ancestor element.\n * This method walks up through shadow DOM boundaries to find a suitable trigger element.\n *\n * A trigger element must match the focusableSelector, which includes:\n * - Interactive elements like buttons, inputs, links, etc.\n * - Elements with tabindex (except -1)\n * - Elements with focusable=\"true\"\n *\n * Common scenarios where no trigger element is found:\n * 1. Tooltip is placed directly in document body without a focusable parent\n * 2. Tooltip is nested in non-interactive elements (divs, spans) without focusable ancestors\n * 3. All ancestor elements have tabindex=\"-1\" or are otherwise non-focusable\n *\n * Expected usage: <sp-action-button><sp-tooltip self-managed>...</sp-tooltip></sp-action-button>\n *\n * @returns The first focusable ancestor element, or null if none found\n */\n private resolveSelfManagedTriggerElement(): HTMLElement | null {\n // Start from the assigned slot (if tooltip is slotted) or the tooltip itself\n let start: HTMLElement = this.assignedSlot || this;\n let root = start.getRootNode();\n\n // Check if we've reached the document root without finding a parent\n // This happens when the tooltip is at the top level without a container\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[INITIAL_TRAVERSAL] Self-managed <${this.localName}> is at document root without a parent element. Self-managed tooltips must be nested inside focusable elements like <sp-action-button>, <sp-button>, or elements with tabindex.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Get the initial candidate trigger element:\n // 1. Direct parent element in the same document/shadow root\n // 2. Shadow host if we're in a shadow root\n // 3. The root itself as fallback\n let triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n root) as HTMLElement;\n\n // Walk up the composed tree until we find a focusable element\n // The focusableSelector matches interactive elements that can receive focus\n while (!triggerElement?.matches?.(focusableSelector)) {\n // Move to the next level up in the composed tree\n // This handles both regular DOM and shadow DOM traversal\n start = triggerElement.assignedSlot || (triggerElement as HTMLElement);\n root = start.getRootNode();\n\n /* c8 ignore next 13 */\n // Check if we've reached the document root during traversal\n // This happens when no focusable ancestor is found\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[TRAVERSAL_EXHAUSTED] Self-managed <${this.localName}> could not find a focusable trigger element. All ancestor elements are non-focusable. Ensure the tooltip is nested inside an interactive element like <sp-action-button>, <sp-button>, or add tabindex=\"0\" to a parent element.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Continue traversing up to find the next candidate\n triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n /* c8 ignore next 1 */\n root) as HTMLElement;\n }\n\n return triggerElement;\n }\n\n override render(): TemplateResult {\n const tooltip = html`\n <sp-tooltip-openable\n id=\"tooltip\"\n placement=${ifDefined(this.placement)}\n @transitionrun=${this.forwardTransitionEvent}\n @transitionend=${this.forwardTransitionEvent}\n @transitioncancel=${this.forwardTransitionEvent}\n >\n <slot name=\"icon\"></slot>\n <span id=\"label\"><slot></slot></span>\n <span id=\"tip\" aria-hidden=\"true\"></span>\n </sp-tooltip-openable>\n `;\n if (this.selfManaged) {\n this.dependencyManager.add('sp-overlay');\n import('@spectrum-web-components/overlay/sp-overlay.js');\n return html`\n <sp-overlay\n ?open=${this.open && !this.disabled && this.dependencyManager.loaded}\n ?delayed=${this.delayed}\n ?disabled=${this.disabled}\n offset=${this.offset}\n .placement=${this.placement}\n type=\"hint\"\n .tipPadding=${this.tipPadding}\n .triggerInteraction=${'hover'}\n @sp-opened=${this.handleOpenOverlay}\n @sp-closed=${this.handleCloseOverlay}\n >\n ${tooltip}\n </sp-overlay>\n `;\n } else {\n return tooltip;\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n\n this.updateComplete.then(() => {\n if (!this.selfManaged) {\n return;\n }\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `The \"self-managed\" attribute on <${this.localName}> is deprecated and will be removed in a future release in favor of an updated binding method.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip',\n { level: 'deprecation' }\n );\n }\n const overlayElement = this.overlayElement;\n if (overlayElement) {\n const triggerElement = this.triggerElement;\n overlayElement.triggerElement = triggerElement;\n }\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/src/Tooltip.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var c=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var o=(l,a,e,t)=>{for(var n=t>1?void 0:t?m(a,e):a,s=l.length-1,r;s>=0;s--)(r=l[s])&&(n=(t?r(a,e,n):r(n))||n);return t&&n&&c(a,e,n),n};import{html as p,SpectrumElement as u}from"@spectrum-web-components/base";import{property as i,query as d}from"@spectrum-web-components/base/src/decorators.js";import{ifDefined as h}from"@spectrum-web-components/base/src/directives.js";import{DependencyManagerController as v}from"@spectrum-web-components/reactive-controllers/src/DependencyManger.js";import{focusableSelector as b}from"@spectrum-web-components/shared/src/focusable-selectors.js";import f from"./tooltip.css.js";class g extends HTMLElement{constructor(){super();this._open=!1;this._placement="top";this.addEventListener("sp-opened",this.redispatchEvent),this.addEventListener("sp-closed",this.redispatchEvent)}redispatchEvent(e){e.stopPropagation(),this.tooltip.dispatchEvent(new CustomEvent(e.type,{bubbles:e.bubbles,composed:e.composed,detail:e.detail}))}get tooltip(){return this.getRootNode().host}static get observedAttributes(){return["open","placement"]}attributeChangedCallback(e,t,n){switch(e){case"open":this.open=n!==null;break;case"placement":this.placement=n;break}}set open(e){this._open=e;const{tooltip:t}=this;t&&(t.open=e)}get open(){return this._open}set placement(e){this._placement=e;const{tooltip:t}=this;t&&(t.placement=e)}get placement(){return this._placement}get tipElement(){return this.tooltip.tipElement}}customElements.get("sp-tooltip-openable")||customElements.define("sp-tooltip-openable",g);export class Tooltip extends u{constructor(){super(...arguments);this.delayed=!1;this.dependencyManager=new v(this);this.disabled=!1;this.selfManaged=!1;this.offset=0;this.open=!1;this._triggerElement=null;this._variant="";this.handleOpenOverlay=()=>{this.open=!0};this.handleCloseOverlay=()=>{this.open=!1}}static get styles(){return[f]}set triggerElement(e){this._triggerElement=e,this.overlayElement&&(this.overlayElement.triggerElement=e)}get triggerElement(){return this._triggerElement||this.resolveSelfManagedTriggerElement()}get variant(){return this._variant}set variant(e){if(e!==this.variant){if(["info","positive","negative"].includes(e)){this.setAttribute("variant",e),this._variant=e;return}this.removeAttribute("variant"),this._variant=""}}forwardTransitionEvent(e){this.dispatchEvent(new TransitionEvent(e.type,{bubbles:!0,composed:!0,propertyName:e.propertyName}))}resolveSelfManagedTriggerElement(){var s;let e=this.assignedSlot||this,t=e.getRootNode();if(t===document)return null;let n=e.parentElement||t.host||t;for(;!((s=n==null?void 0:n.matches)!=null&&s.call(n,b));){if(e=n.assignedSlot||n,t=e.getRootNode(),t===document)return null;n=e.parentElement||t.host||t}return n}render(){const e=p`
|
|
2
2
|
<sp-tooltip-openable
|
|
3
3
|
id="tooltip"
|
|
4
4
|
placement=${h(this.placement)}
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
>
|
|
26
26
|
${e}
|
|
27
27
|
</sp-overlay>
|
|
28
|
-
`):e}connectedCallback(){super.connectedCallback(),this.updateComplete.then(()=>{if(!this.selfManaged)return;const e=this.overlayElement;if(e){const t=this.triggerElement;e.triggerElement=t}})}}
|
|
28
|
+
`):e}connectedCallback(){super.connectedCallback(),this.updateComplete.then(()=>{if(!this.selfManaged)return;const e=this.overlayElement;if(e){const t=this.triggerElement;e.triggerElement=t}})}}o([i({type:Boolean})],Tooltip.prototype,"delayed",2),o([i({type:Boolean})],Tooltip.prototype,"disabled",2),o([i({type:Boolean,attribute:"self-managed"})],Tooltip.prototype,"selfManaged",2),o([i({type:Number})],Tooltip.prototype,"offset",2),o([i({type:Boolean,reflect:!0})],Tooltip.prototype,"open",2),o([d("sp-overlay")],Tooltip.prototype,"overlayElement",2),o([i({reflect:!0})],Tooltip.prototype,"placement",2),o([d("#tip")],Tooltip.prototype,"tipElement",2),o([i({type:Number})],Tooltip.prototype,"tipPadding",2),o([i({type:String})],Tooltip.prototype,"variant",1);
|
|
29
29
|
//# sourceMappingURL=Tooltip.js.map
|
package/src/Tooltip.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Tooltip.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport { ifDefined } from '@spectrum-web-components/base/src/directives.js';\nimport type {\n Overlay,\n OverlayOpenCloseDetail,\n Placement,\n} from '@spectrum-web-components/overlay';\nimport { DependencyManagerController } from '@spectrum-web-components/reactive-controllers/src/DependencyManger.js';\nimport { focusableSelector } from '@spectrum-web-components/shared/src/focusable-selectors.js';\n\nimport tooltipStyles from './tooltip.css.js';\n\nclass TooltipOpenable extends HTMLElement {\n constructor() {\n super();\n this.addEventListener('sp-opened', this.redispatchEvent);\n this.addEventListener('sp-closed', this.redispatchEvent);\n }\n redispatchEvent(event: Event): void {\n event.stopPropagation();\n this.tooltip.dispatchEvent(\n new CustomEvent<OverlayOpenCloseDetail>(event.type, {\n bubbles: event.bubbles,\n composed: event.composed,\n detail: (event as CustomEvent<OverlayOpenCloseDetail>).detail,\n })\n );\n }\n get tooltip(): Tooltip {\n return (this.getRootNode() as ShadowRoot).host as Tooltip;\n }\n static get observedAttributes(): string[] {\n return ['open', 'placement'];\n }\n attributeChangedCallback(\n name: 'open' | 'placement',\n _oldValue: string,\n newValue: 'string'\n ): void {\n switch (name) {\n // API generally sets `open` as a property\n /* c8 ignore next 3 */\n case 'open':\n this.open = newValue !== null;\n break;\n case 'placement':\n this.placement = newValue as Placement;\n break;\n }\n }\n set open(open: boolean) {\n this._open = open;\n const { tooltip } = this;\n /* c8 ignore next 3 */\n if (!tooltip) {\n return;\n }\n tooltip.open = open;\n }\n /* c8 ignore next 3 */\n get open(): boolean {\n return this._open;\n }\n private _open = false;\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n set placement(placement: Placement) {\n this._placement = placement;\n const { tooltip } = this;\n if (!tooltip) {\n return;\n }\n tooltip.placement = placement;\n }\n /* c8 ignore next 3 */\n get placement(): Placement {\n return this._placement;\n }\n private _placement: Placement = 'top';\n get tipElement(): HTMLElement {\n return this.tooltip.tipElement;\n }\n}\n\nif (!customElements.get('sp-tooltip-openable')) {\n customElements.define('sp-tooltip-openable', TooltipOpenable);\n}\n\n/**\n * @element sp-tooltip\n *\n * @slot icon - the icon element appearing at the start of the label\n * @slot - the text label of the Tooltip\n */\nexport class Tooltip extends SpectrumElement {\n public static override get styles(): CSSResultArray {\n return [tooltipStyles];\n }\n\n /**\n * A Tooltip that is `delayed` will its Overlay wait until a warm-up period of\n * 1000ms has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened, a\n * cooldown period of 1000ms will begin. Once the cooldown has completed, the next\n * Overlay to be opened will be subject to the warm-up period if provided that option.\n */\n @property({ type: Boolean })\n delayed = false;\n\n private dependencyManager = new DependencyManagerController(this);\n\n /**\n * Whether to prevent a self-managed Tooltip from responding to user input.\n */\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * Automatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.\n * Without this, you must provide your own `overlay-trigger`.\n */\n @property({ type: Boolean, attribute: 'self-managed' })\n public selfManaged = false;\n\n @property({ type: Number })\n public offset = 0;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @query('sp-overlay')\n public overlayElement?: Overlay;\n\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n @property({ reflect: true })\n public placement?: Placement;\n\n @query('#tip')\n public tipElement!: HTMLSpanElement;\n\n @property({ type: Number })\n public tipPadding?: number;\n\n private _triggerElement: HTMLElement | null = null;\n\n /**\n * Explicit trigger element override for self-managed tooltip usage.\n *\n * This is useful when the intended trigger is not an ancestor of the tooltip\n * in the composed tree (for example, tooltips slotted into components that\n * render their interactive trigger internally).\n */\n public set triggerElement(triggerElement: HTMLElement | null) {\n this._triggerElement = triggerElement;\n if (this.overlayElement) {\n this.overlayElement.triggerElement = triggerElement;\n }\n }\n\n public get triggerElement(): HTMLElement | null {\n return this._triggerElement || this.resolveSelfManagedTriggerElement();\n }\n\n /* Ensure that a '' value for `variant` removes the attribute instead of a blank value */\n private _variant = '';\n\n @property({ type: String })\n public get variant(): string {\n return this._variant;\n }\n public set variant(variant: string) {\n if (variant === this.variant) {\n return;\n }\n if (['info', 'positive', 'negative'].includes(variant)) {\n this.setAttribute('variant', variant);\n this._variant = variant;\n return;\n }\n this.removeAttribute('variant');\n this._variant = '';\n }\n\n private handleOpenOverlay = (): void => {\n this.open = true;\n };\n\n protected handleCloseOverlay = (): void => {\n this.open = false;\n };\n\n protected forwardTransitionEvent(event: TransitionEvent): void {\n this.dispatchEvent(\n new TransitionEvent(event.type, {\n bubbles: true,\n composed: true,\n propertyName: event.propertyName,\n })\n );\n }\n\n /**\n * Finds the trigger element for a self-managed tooltip by traversing up the composed DOM tree.\n *\n * Self-managed tooltips automatically bind to their first focusable ancestor element.\n * This method walks up through shadow DOM boundaries to find a suitable trigger element.\n *\n * A trigger element must match the focusableSelector, which includes:\n * - Interactive elements like buttons, inputs, links, etc.\n * - Elements with tabindex (except -1)\n * - Elements with focusable=\"true\"\n *\n * Common scenarios where no trigger element is found:\n * 1. Tooltip is placed directly in document body without a focusable parent\n * 2. Tooltip is nested in non-interactive elements (divs, spans) without focusable ancestors\n * 3. All ancestor elements have tabindex=\"-1\" or are otherwise non-focusable\n *\n * Expected usage: <sp-action-button><sp-tooltip self-managed>...</sp-tooltip></sp-action-button>\n *\n * @returns The first focusable ancestor element, or null if none found\n */\n private resolveSelfManagedTriggerElement(): HTMLElement | null {\n // Start from the assigned slot (if tooltip is slotted) or the tooltip itself\n let start: HTMLElement = this.assignedSlot || this;\n let root = start.getRootNode();\n\n // Check if we've reached the document root without finding a parent\n // This happens when the tooltip is at the top level without a container\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[INITIAL_TRAVERSAL] Self-managed <${this.localName}> is at document root without a parent element. Self-managed tooltips must be nested inside focusable elements like <sp-action-button>, <sp-button>, or elements with tabindex.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Get the initial candidate trigger element:\n // 1. Direct parent element in the same document/shadow root\n // 2. Shadow host if we're in a shadow root\n // 3. The root itself as fallback\n let triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n root) as HTMLElement;\n\n // Walk up the composed tree until we find a focusable element\n // The focusableSelector matches interactive elements that can receive focus\n while (!triggerElement?.matches?.(focusableSelector)) {\n // Move to the next level up in the composed tree\n // This handles both regular DOM and shadow DOM traversal\n start = triggerElement.assignedSlot || (triggerElement as HTMLElement);\n root = start.getRootNode();\n\n /* c8 ignore next 13 */\n // Check if we've reached the document root during traversal\n // This happens when no focusable ancestor is found\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[TRAVERSAL_EXHAUSTED] Self-managed <${this.localName}> could not find a focusable trigger element. All ancestor elements are non-focusable. Ensure the tooltip is nested inside an interactive element like <sp-action-button>, <sp-button>, or add tabindex=\"0\" to a parent element.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Continue traversing up to find the next candidate\n triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n /* c8 ignore next 1 */\n root) as HTMLElement;\n }\n\n return triggerElement;\n }\n\n override render(): TemplateResult {\n const tooltip = html`\n <sp-tooltip-openable\n id=\"tooltip\"\n placement=${ifDefined(this.placement)}\n @transitionrun=${this.forwardTransitionEvent}\n @transitionend=${this.forwardTransitionEvent}\n @transitioncancel=${this.forwardTransitionEvent}\n >\n <slot name=\"icon\"></slot>\n <span id=\"label\"><slot></slot></span>\n <span id=\"tip\" aria-hidden=\"true\"></span>\n </sp-tooltip-openable>\n `;\n if (this.selfManaged) {\n this.dependencyManager.add('sp-overlay');\n import('@spectrum-web-components/overlay/sp-overlay.js');\n return html`\n <sp-overlay\n ?open=${this.open && !this.disabled && this.dependencyManager.loaded}\n ?delayed=${this.delayed}\n ?disabled=${this.disabled}\n offset=${this.offset}\n .placement=${this.placement}\n type=\"hint\"\n .tipPadding=${this.tipPadding}\n .triggerInteraction=${'hover'}\n @sp-opened=${this.handleOpenOverlay}\n @sp-closed=${this.handleCloseOverlay}\n >\n ${tooltip}\n </sp-overlay>\n `;\n } else {\n return tooltip;\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n\n this.updateComplete.then(() => {\n if (!this.selfManaged) {\n return;\n }\n const overlayElement = this.overlayElement;\n if (overlayElement) {\n const triggerElement = this.triggerElement;\n overlayElement.triggerElement = triggerElement;\n }\n });\n }\n}\n"],
|
|
5
|
-
"mappings": "qNAYA,OAEE,QAAAA,EACA,mBAAAC,MAEK,gCACP,OACE,YAAAC,EACA,SAAAC,MACK,kDACP,OAAS,aAAAC,MAAiB,kDAM1B,OAAS,+BAAAC,MAAmC,wEAC5C,OAAS,qBAAAC,MAAyB,6DAElC,OAAOC,MAAmB,mBAE1B,MAAMC,UAAwB,WAAY,CACxC,aAAc,CACZ,MAAM,EAiDR,KAAQ,MAAQ,GAiBhB,KAAQ,WAAwB,MAjE9B,KAAK,iBAAiB,YAAa,KAAK,eAAe,EACvD,KAAK,iBAAiB,YAAa,KAAK,eAAe,CACzD,CACA,gBAAgBC,EAAoB,CAClCA,EAAM,gBAAgB,EACtB,KAAK,QAAQ,cACX,IAAI,YAAoCA,EAAM,KAAM,CAClD,QAASA,EAAM,QACf,SAAUA,EAAM,SAChB,OAASA,EAA8C,MACzD,CAAC,CACH,CACF,CACA,IAAI,SAAmB,CACrB,OAAQ,KAAK,YAAY,EAAiB,IAC5C,CACA,WAAW,oBAA+B,CACxC,MAAO,CAAC,OAAQ,WAAW,CAC7B,CACA,yBACEC,EACAC,EACAC,EACM,CACN,OAAQF,EAAM,CAGZ,IAAK,OACH,KAAK,KAAOE,IAAa,KACzB,MACF,IAAK,YACH,KAAK,UAAYA,EACjB,KACJ,CACF,CACA,IAAI,KAAKC,EAAe,CACtB,KAAK,MAAQA,EACb,KAAM,CAAE,QAAAC,CAAQ,EAAI,KAEfA,IAGLA,EAAQ,KAAOD,EACjB,CAEA,IAAI,MAAgB,CAClB,OAAO,KAAK,KACd,CAMA,IAAI,UAAUE,EAAsB,CAClC,KAAK,WAAaA,EAClB,KAAM,CAAE,QAAAD,CAAQ,EAAI,KACfA,IAGLA,EAAQ,UAAYC,EACtB,CAEA,IAAI,WAAuB,CACzB,OAAO,KAAK,UACd,CAEA,IAAI,YAA0B,CAC5B,OAAO,KAAK,QAAQ,UACtB,CACF,CAEK,eAAe,IAAI,qBAAqB,GAC3C,eAAe,OAAO,sBAAuBP,CAAe,EASvD,aAAM,gBAAgBP,CAAgB,CAAtC,kCAaL,aAAU,GAEV,KAAQ,kBAAoB,IAAII,EAA4B,IAAI,EAMhE,cAAW,
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n CSSResultArray,\n html,\n SpectrumElement,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport { ifDefined } from '@spectrum-web-components/base/src/directives.js';\nimport type {\n Overlay,\n OverlayOpenCloseDetail,\n Placement,\n} from '@spectrum-web-components/overlay';\nimport { DependencyManagerController } from '@spectrum-web-components/reactive-controllers/src/DependencyManger.js';\nimport { focusableSelector } from '@spectrum-web-components/shared/src/focusable-selectors.js';\n\nimport tooltipStyles from './tooltip.css.js';\n\nclass TooltipOpenable extends HTMLElement {\n constructor() {\n super();\n this.addEventListener('sp-opened', this.redispatchEvent);\n this.addEventListener('sp-closed', this.redispatchEvent);\n }\n redispatchEvent(event: Event): void {\n event.stopPropagation();\n this.tooltip.dispatchEvent(\n new CustomEvent<OverlayOpenCloseDetail>(event.type, {\n bubbles: event.bubbles,\n composed: event.composed,\n detail: (event as CustomEvent<OverlayOpenCloseDetail>).detail,\n })\n );\n }\n get tooltip(): Tooltip {\n return (this.getRootNode() as ShadowRoot).host as Tooltip;\n }\n static get observedAttributes(): string[] {\n return ['open', 'placement'];\n }\n attributeChangedCallback(\n name: 'open' | 'placement',\n _oldValue: string,\n newValue: 'string'\n ): void {\n switch (name) {\n // API generally sets `open` as a property\n /* c8 ignore next 3 */\n case 'open':\n this.open = newValue !== null;\n break;\n case 'placement':\n this.placement = newValue as Placement;\n break;\n }\n }\n set open(open: boolean) {\n this._open = open;\n const { tooltip } = this;\n /* c8 ignore next 3 */\n if (!tooltip) {\n return;\n }\n tooltip.open = open;\n }\n /* c8 ignore next 3 */\n get open(): boolean {\n return this._open;\n }\n private _open = false;\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n set placement(placement: Placement) {\n this._placement = placement;\n const { tooltip } = this;\n if (!tooltip) {\n return;\n }\n tooltip.placement = placement;\n }\n /* c8 ignore next 3 */\n get placement(): Placement {\n return this._placement;\n }\n private _placement: Placement = 'top';\n get tipElement(): HTMLElement {\n return this.tooltip.tipElement;\n }\n}\n\nif (!customElements.get('sp-tooltip-openable')) {\n customElements.define('sp-tooltip-openable', TooltipOpenable);\n}\n\n/**\n * @element sp-tooltip\n *\n * @slot icon - the icon element appearing at the start of the label\n * @slot - the text label of the Tooltip\n */\nexport class Tooltip extends SpectrumElement {\n public static override get styles(): CSSResultArray {\n return [tooltipStyles];\n }\n\n /**\n * A Tooltip that is `delayed` will its Overlay wait until a warm-up period of\n * 1000ms has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened, a\n * cooldown period of 1000ms will begin. Once the cooldown has completed, the next\n * Overlay to be opened will be subject to the warm-up period if provided that option.\n */\n @property({ type: Boolean })\n delayed = false;\n\n private dependencyManager = new DependencyManagerController(this);\n\n /**\n * Whether to prevent a self-managed Tooltip from responding to user input.\n */\n @property({ type: Boolean })\n disabled = false;\n\n /**\n * @deprecated The `self-managed` attribute will be removed in a future release in favor of an updated binding method.\n *\n * Automatically bind to the parent element of the assigned `slot` or the parent element of the `sp-tooltip`.\n * Without this, you must provide your own `overlay-trigger`.\n */\n @property({ type: Boolean, attribute: 'self-managed' })\n public selfManaged = false;\n\n @property({ type: Number })\n public offset = 0;\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @query('sp-overlay')\n public overlayElement?: Overlay;\n\n /**\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n * @attr\n */\n @property({ reflect: true })\n public placement?: Placement;\n\n @query('#tip')\n public tipElement!: HTMLSpanElement;\n\n /**\n * @deprecated The `tip-padding` attribute will be removed in a future release.\n */\n @property({ type: Number })\n public tipPadding?: number;\n\n private _triggerElement: HTMLElement | null = null;\n\n /**\n * Explicit trigger element override for self-managed tooltip usage.\n *\n * This is useful when the intended trigger is not an ancestor of the tooltip\n * in the composed tree (for example, tooltips slotted into components that\n * render their interactive trigger internally).\n */\n public set triggerElement(triggerElement: HTMLElement | null) {\n this._triggerElement = triggerElement;\n if (this.overlayElement) {\n this.overlayElement.triggerElement = triggerElement;\n }\n }\n\n public get triggerElement(): HTMLElement | null {\n return this._triggerElement || this.resolveSelfManagedTriggerElement();\n }\n\n /* Ensure that a '' value for `variant` removes the attribute instead of a blank value */\n private _variant = '';\n\n @property({ type: String })\n public get variant(): string {\n return this._variant;\n }\n public set variant(variant: string) {\n if (variant === this.variant) {\n return;\n }\n if (['info', 'positive', 'negative'].includes(variant)) {\n if (window.__swc?.DEBUG) {\n if (variant === 'info') {\n window.__swc.warn(\n this,\n `The \"info\" variant on <${this.localName}> is deprecated and will be removed in a future release. Use \"informative\" instead.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip',\n { level: 'deprecation' }\n );\n } else if (variant === 'positive') {\n window.__swc.warn(\n this,\n `The \"positive\" variant on <${this.localName}> is deprecated and will be removed in a future release.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip',\n { level: 'deprecation' }\n );\n }\n }\n this.setAttribute('variant', variant);\n this._variant = variant;\n return;\n }\n this.removeAttribute('variant');\n this._variant = '';\n }\n\n private handleOpenOverlay = (): void => {\n this.open = true;\n };\n\n protected handleCloseOverlay = (): void => {\n this.open = false;\n };\n\n protected forwardTransitionEvent(event: TransitionEvent): void {\n this.dispatchEvent(\n new TransitionEvent(event.type, {\n bubbles: true,\n composed: true,\n propertyName: event.propertyName,\n })\n );\n }\n\n /**\n * Finds the trigger element for a self-managed tooltip by traversing up the composed DOM tree.\n *\n * Self-managed tooltips automatically bind to their first focusable ancestor element.\n * This method walks up through shadow DOM boundaries to find a suitable trigger element.\n *\n * A trigger element must match the focusableSelector, which includes:\n * - Interactive elements like buttons, inputs, links, etc.\n * - Elements with tabindex (except -1)\n * - Elements with focusable=\"true\"\n *\n * Common scenarios where no trigger element is found:\n * 1. Tooltip is placed directly in document body without a focusable parent\n * 2. Tooltip is nested in non-interactive elements (divs, spans) without focusable ancestors\n * 3. All ancestor elements have tabindex=\"-1\" or are otherwise non-focusable\n *\n * Expected usage: <sp-action-button><sp-tooltip self-managed>...</sp-tooltip></sp-action-button>\n *\n * @returns The first focusable ancestor element, or null if none found\n */\n private resolveSelfManagedTriggerElement(): HTMLElement | null {\n // Start from the assigned slot (if tooltip is slotted) or the tooltip itself\n let start: HTMLElement = this.assignedSlot || this;\n let root = start.getRootNode();\n\n // Check if we've reached the document root without finding a parent\n // This happens when the tooltip is at the top level without a container\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[INITIAL_TRAVERSAL] Self-managed <${this.localName}> is at document root without a parent element. Self-managed tooltips must be nested inside focusable elements like <sp-action-button>, <sp-button>, or elements with tabindex.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Get the initial candidate trigger element:\n // 1. Direct parent element in the same document/shadow root\n // 2. Shadow host if we're in a shadow root\n // 3. The root itself as fallback\n let triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n root) as HTMLElement;\n\n // Walk up the composed tree until we find a focusable element\n // The focusableSelector matches interactive elements that can receive focus\n while (!triggerElement?.matches?.(focusableSelector)) {\n // Move to the next level up in the composed tree\n // This handles both regular DOM and shadow DOM traversal\n start = triggerElement.assignedSlot || (triggerElement as HTMLElement);\n root = start.getRootNode();\n\n /* c8 ignore next 13 */\n // Check if we've reached the document root during traversal\n // This happens when no focusable ancestor is found\n if (root === document) {\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `[TRAVERSAL_EXHAUSTED] Self-managed <${this.localName}> could not find a focusable trigger element. All ancestor elements are non-focusable. Ensure the tooltip is nested inside an interactive element like <sp-action-button>, <sp-button>, or add tabindex=\"0\" to a parent element.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip#self-managed-overlays',\n {\n level: 'high',\n }\n );\n }\n return null;\n }\n\n // Continue traversing up to find the next candidate\n triggerElement = (start.parentElement ||\n (root as ShadowRoot).host ||\n /* c8 ignore next 1 */\n root) as HTMLElement;\n }\n\n return triggerElement;\n }\n\n override render(): TemplateResult {\n const tooltip = html`\n <sp-tooltip-openable\n id=\"tooltip\"\n placement=${ifDefined(this.placement)}\n @transitionrun=${this.forwardTransitionEvent}\n @transitionend=${this.forwardTransitionEvent}\n @transitioncancel=${this.forwardTransitionEvent}\n >\n <slot name=\"icon\"></slot>\n <span id=\"label\"><slot></slot></span>\n <span id=\"tip\" aria-hidden=\"true\"></span>\n </sp-tooltip-openable>\n `;\n if (this.selfManaged) {\n this.dependencyManager.add('sp-overlay');\n import('@spectrum-web-components/overlay/sp-overlay.js');\n return html`\n <sp-overlay\n ?open=${this.open && !this.disabled && this.dependencyManager.loaded}\n ?delayed=${this.delayed}\n ?disabled=${this.disabled}\n offset=${this.offset}\n .placement=${this.placement}\n type=\"hint\"\n .tipPadding=${this.tipPadding}\n .triggerInteraction=${'hover'}\n @sp-opened=${this.handleOpenOverlay}\n @sp-closed=${this.handleCloseOverlay}\n >\n ${tooltip}\n </sp-overlay>\n `;\n } else {\n return tooltip;\n }\n }\n\n public override connectedCallback(): void {\n super.connectedCallback();\n\n this.updateComplete.then(() => {\n if (!this.selfManaged) {\n return;\n }\n if (window.__swc?.DEBUG) {\n window.__swc.warn(\n this,\n `The \"self-managed\" attribute on <${this.localName}> is deprecated and will be removed in a future release in favor of an updated binding method.`,\n 'https://opensource.adobe.com/spectrum-web-components/components/tooltip',\n { level: 'deprecation' }\n );\n }\n const overlayElement = this.overlayElement;\n if (overlayElement) {\n const triggerElement = this.triggerElement;\n overlayElement.triggerElement = triggerElement;\n }\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["html", "SpectrumElement", "property", "query", "ifDefined", "DependencyManagerController", "focusableSelector", "tooltipStyles", "TooltipOpenable", "event", "name", "_oldValue", "newValue", "open", "tooltip", "placement", "triggerElement", "variant", "_a", "start", "root", "overlayElement", "__decorateClass"]
|
|
7
7
|
}
|