@spectrum-web-components/tooltip 1.12.0-testing.20260223092154 → 2.0.0-next.20260512072922
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 +21 -7
- package/package.json +5 -5
- package/src/Tooltip.d.ts +11 -1
- package/src/Tooltip.dev.js +18 -1
- package/src/Tooltip.dev.js.map +2 -2
- package/src/Tooltip.js +2 -2
- package/src/Tooltip.js.map +3 -3
package/custom-elements.json
CHANGED
|
@@ -219,6 +219,24 @@
|
|
|
219
219
|
"privacy": "public",
|
|
220
220
|
"attribute": "tipPadding"
|
|
221
221
|
},
|
|
222
|
+
{
|
|
223
|
+
"kind": "field",
|
|
224
|
+
"name": "_triggerElement",
|
|
225
|
+
"type": {
|
|
226
|
+
"text": "HTMLElement | null"
|
|
227
|
+
},
|
|
228
|
+
"privacy": "private",
|
|
229
|
+
"default": "null"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"kind": "field",
|
|
233
|
+
"name": "triggerElement",
|
|
234
|
+
"privacy": "public",
|
|
235
|
+
"description": "Explicit trigger element override for self-managed tooltip usage.\n\nThis is useful when the intended trigger is not an ancestor of the tooltip\nin the composed tree (for example, tooltips slotted into components that\nrender their interactive trigger internally).",
|
|
236
|
+
"type": {
|
|
237
|
+
"text": "HTMLElement | null"
|
|
238
|
+
}
|
|
239
|
+
},
|
|
222
240
|
{
|
|
223
241
|
"kind": "field",
|
|
224
242
|
"name": "_variant",
|
|
@@ -266,19 +284,15 @@
|
|
|
266
284
|
]
|
|
267
285
|
},
|
|
268
286
|
{
|
|
269
|
-
"kind": "
|
|
270
|
-
"name": "
|
|
271
|
-
"type": {
|
|
272
|
-
"text": "HTMLElement | null"
|
|
273
|
-
},
|
|
287
|
+
"kind": "method",
|
|
288
|
+
"name": "resolveSelfManagedTriggerElement",
|
|
274
289
|
"privacy": "private",
|
|
275
|
-
"description": "Finds the trigger element for a self-managed tooltip by traversing up the composed DOM tree.\n\nSelf-managed tooltips automatically bind to their first focusable ancestor element.\nThis method walks up through shadow DOM boundaries to find a suitable trigger element.\n\nA 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\nCommon scenarios where no trigger element is found:\n1. Tooltip is placed directly in document body without a focusable parent\n2. Tooltip is nested in non-interactive elements (divs, spans) without focusable ancestors\n3. All ancestor elements have tabindex=\"-1\" or are otherwise non-focusable\n\nExpected usage: <sp-action-button><sp-tooltip self-managed>...</sp-tooltip></sp-action-button>",
|
|
276
290
|
"return": {
|
|
277
291
|
"type": {
|
|
278
292
|
"text": ""
|
|
279
293
|
}
|
|
280
294
|
},
|
|
281
|
-
"
|
|
295
|
+
"description": "Finds the trigger element for a self-managed tooltip by traversing up the composed DOM tree.\n\nSelf-managed tooltips automatically bind to their first focusable ancestor element.\nThis method walks up through shadow DOM boundaries to find a suitable trigger element.\n\nA 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\nCommon scenarios where no trigger element is found:\n1. Tooltip is placed directly in document body without a focusable parent\n2. Tooltip is nested in non-interactive elements (divs, spans) without focusable ancestors\n3. All ancestor elements have tabindex=\"-1\" or are otherwise non-focusable\n\nExpected usage: <sp-action-button><sp-tooltip self-managed>...</sp-tooltip></sp-action-button>"
|
|
282
296
|
}
|
|
283
297
|
],
|
|
284
298
|
"events": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/tooltip",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-next.20260512072922",
|
|
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": "
|
|
62
|
-
"@spectrum-web-components/overlay": "
|
|
63
|
-
"@spectrum-web-components/reactive-controllers": "
|
|
64
|
-
"@spectrum-web-components/shared": "
|
|
61
|
+
"@spectrum-web-components/base": "2.0.0-next.20260512072922",
|
|
62
|
+
"@spectrum-web-components/overlay": "2.0.0-next.20260512072922",
|
|
63
|
+
"@spectrum-web-components/reactive-controllers": "2.0.0-next.20260512072922",
|
|
64
|
+
"@spectrum-web-components/shared": "2.0.0-next.20260512072922"
|
|
65
65
|
},
|
|
66
66
|
"keywords": [
|
|
67
67
|
"design-system",
|
package/src/Tooltip.d.ts
CHANGED
|
@@ -47,6 +47,16 @@ export declare class Tooltip extends SpectrumElement {
|
|
|
47
47
|
placement?: Placement;
|
|
48
48
|
tipElement: HTMLSpanElement;
|
|
49
49
|
tipPadding?: number;
|
|
50
|
+
private _triggerElement;
|
|
51
|
+
/**
|
|
52
|
+
* Explicit trigger element override for self-managed tooltip usage.
|
|
53
|
+
*
|
|
54
|
+
* This is useful when the intended trigger is not an ancestor of the tooltip
|
|
55
|
+
* in the composed tree (for example, tooltips slotted into components that
|
|
56
|
+
* render their interactive trigger internally).
|
|
57
|
+
*/
|
|
58
|
+
set triggerElement(triggerElement: HTMLElement | null);
|
|
59
|
+
get triggerElement(): HTMLElement | null;
|
|
50
60
|
private _variant;
|
|
51
61
|
get variant(): string;
|
|
52
62
|
set variant(variant: string);
|
|
@@ -73,7 +83,7 @@ export declare class Tooltip extends SpectrumElement {
|
|
|
73
83
|
*
|
|
74
84
|
* @returns The first focusable ancestor element, or null if none found
|
|
75
85
|
*/
|
|
76
|
-
private
|
|
86
|
+
private resolveSelfManagedTriggerElement;
|
|
77
87
|
render(): TemplateResult;
|
|
78
88
|
connectedCallback(): void;
|
|
79
89
|
}
|
package/src/Tooltip.dev.js
CHANGED
|
@@ -99,6 +99,7 @@ export class Tooltip extends SpectrumElement {
|
|
|
99
99
|
this.selfManaged = false;
|
|
100
100
|
this.offset = 0;
|
|
101
101
|
this.open = false;
|
|
102
|
+
this._triggerElement = null;
|
|
102
103
|
/* Ensure that a '' value for `variant` removes the attribute instead of a blank value */
|
|
103
104
|
this._variant = "";
|
|
104
105
|
this.handleOpenOverlay = () => {
|
|
@@ -111,6 +112,22 @@ export class Tooltip extends SpectrumElement {
|
|
|
111
112
|
static get styles() {
|
|
112
113
|
return [tooltipStyles];
|
|
113
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Explicit trigger element override for self-managed tooltip usage.
|
|
117
|
+
*
|
|
118
|
+
* This is useful when the intended trigger is not an ancestor of the tooltip
|
|
119
|
+
* in the composed tree (for example, tooltips slotted into components that
|
|
120
|
+
* render their interactive trigger internally).
|
|
121
|
+
*/
|
|
122
|
+
set triggerElement(triggerElement) {
|
|
123
|
+
this._triggerElement = triggerElement;
|
|
124
|
+
if (this.overlayElement) {
|
|
125
|
+
this.overlayElement.triggerElement = triggerElement;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
get triggerElement() {
|
|
129
|
+
return this._triggerElement || this.resolveSelfManagedTriggerElement();
|
|
130
|
+
}
|
|
114
131
|
get variant() {
|
|
115
132
|
return this._variant;
|
|
116
133
|
}
|
|
@@ -155,7 +172,7 @@ export class Tooltip extends SpectrumElement {
|
|
|
155
172
|
*
|
|
156
173
|
* @returns The first focusable ancestor element, or null if none found
|
|
157
174
|
*/
|
|
158
|
-
|
|
175
|
+
resolveSelfManagedTriggerElement() {
|
|
159
176
|
var _a;
|
|
160
177
|
let start = this.assignedSlot || this;
|
|
161
178
|
let root = start.getRootNode();
|
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 /* 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 get triggerElement(): 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;AAOX,SAAO,cAAc;AAGrB,SAAO,SAAS;AAGhB,SAAO,OAAO;
|
|
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": "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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 m=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var i=(s,l,e,t)=>{for(var n=t>1?void 0:t?c(l,e):l,o=s.length-1,r;o>=0;o--)(r=s[o])&&(n=(t?r(l,e,n):r(n))||n);return t&&n&&m(l,e,n),n};import{html as p,SpectrumElement as u}from"@spectrum-web-components/base";import{property as a,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 b}from"@spectrum-web-components/reactive-controllers/src/DependencyManger.js";import{focusableSelector as v}from"@spectrum-web-components/shared/src/focusable-selectors.js";import g from"./tooltip.css.js";class f 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",f);export class Tooltip extends u{constructor(){super(...arguments);this.delayed=!1;this.dependencyManager=new b(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[g]}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 o;let e=this.assignedSlot||this,t=e.getRootNode();if(t===document)return null;let n=e.parentElement||t.host||t;for(;!((o=n==null?void 0:n.matches)!=null&&o.call(n,v));){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}})}}i([a({type:Boolean})],Tooltip.prototype,"delayed",2),i([a({type:Boolean})],Tooltip.prototype,"disabled",2),i([a({type:Boolean,attribute:"self-managed"})],Tooltip.prototype,"selfManaged",2),i([a({type:Number})],Tooltip.prototype,"offset",2),i([a({type:Boolean,reflect:!0})],Tooltip.prototype,"open",2),i([d("sp-overlay")],Tooltip.prototype,"overlayElement",2),i([a({reflect:!0})],Tooltip.prototype,"placement",2),i([d("#tip")],Tooltip.prototype,"tipElement",2),i([a({type:Number})],Tooltip.prototype,"tipPadding",2),i([a({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 /* 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 get triggerElement(): 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,GAOX,KAAO,YAAc,GAGrB,KAAO,OAAS,EAGhB,KAAO,KAAO,
|
|
6
|
-
"names": ["html", "SpectrumElement", "property", "query", "ifDefined", "DependencyManagerController", "focusableSelector", "tooltipStyles", "TooltipOpenable", "event", "name", "_oldValue", "newValue", "open", "tooltip", "placement", "variant", "_a", "start", "root", "
|
|
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": "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",
|
|
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
|
}
|