@spectrum-web-components/overlay 0.42.0 → 0.42.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +14 -6
- package/package.json +7 -7
- package/src/Overlay.d.ts +6 -0
- package/src/Overlay.dev.js +9 -0
- package/src/Overlay.dev.js.map +2 -2
- package/src/Overlay.js +2 -2
- package/src/Overlay.js.map +2 -2
- package/test/overlay-trigger-hover.test.js +6 -1
- package/test/overlay-trigger-hover.test.js.map +2 -2
package/custom-elements.json
CHANGED
|
@@ -1654,6 +1654,16 @@
|
|
|
1654
1654
|
"description": "Instruct the Overlay where to place itself in\nrelationship to the trigger element.",
|
|
1655
1655
|
"attribute": "placement"
|
|
1656
1656
|
},
|
|
1657
|
+
{
|
|
1658
|
+
"kind": "field",
|
|
1659
|
+
"name": "lastRequestSlottableState",
|
|
1660
|
+
"type": {
|
|
1661
|
+
"text": "boolean"
|
|
1662
|
+
},
|
|
1663
|
+
"privacy": "private",
|
|
1664
|
+
"default": "false",
|
|
1665
|
+
"description": "The state in which the last `request-slottable` event was dispatched.\nDo not allow overlays from dispatching the same state twice in a row."
|
|
1666
|
+
},
|
|
1657
1667
|
{
|
|
1658
1668
|
"kind": "field",
|
|
1659
1669
|
"name": "receivesFocus",
|
|
@@ -1979,12 +1989,6 @@
|
|
|
1979
1989
|
}
|
|
1980
1990
|
],
|
|
1981
1991
|
"events": [
|
|
1982
|
-
{
|
|
1983
|
-
"name": "overlay-content",
|
|
1984
|
-
"type": {
|
|
1985
|
-
"text": "SlottableRequestEvent"
|
|
1986
|
-
}
|
|
1987
|
-
},
|
|
1988
1992
|
{
|
|
1989
1993
|
"description": "announces that an overlay has completed any entry animations",
|
|
1990
1994
|
"name": "sp-opened"
|
|
@@ -1992,6 +1996,10 @@
|
|
|
1992
1996
|
{
|
|
1993
1997
|
"description": "announce that an overlay has compelted any exit animations",
|
|
1994
1998
|
"name": "sp-closed"
|
|
1999
|
+
},
|
|
2000
|
+
{
|
|
2001
|
+
"description": "requests to add or remove slottable content",
|
|
2002
|
+
"name": "slottable-request"
|
|
1995
2003
|
}
|
|
1996
2004
|
],
|
|
1997
2005
|
"attributes": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spectrum-web-components/overlay",
|
|
3
|
-
"version": "0.42.
|
|
3
|
+
"version": "0.42.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -152,11 +152,11 @@
|
|
|
152
152
|
"dependencies": {
|
|
153
153
|
"@floating-ui/dom": "^1.6.1",
|
|
154
154
|
"@floating-ui/utils": "^0.2.1",
|
|
155
|
-
"@spectrum-web-components/action-button": "^0.42.
|
|
156
|
-
"@spectrum-web-components/base": "^0.42.
|
|
157
|
-
"@spectrum-web-components/reactive-controllers": "^0.42.
|
|
158
|
-
"@spectrum-web-components/shared": "^0.42.
|
|
159
|
-
"@spectrum-web-components/theme": "^0.42.
|
|
155
|
+
"@spectrum-web-components/action-button": "^0.42.2",
|
|
156
|
+
"@spectrum-web-components/base": "^0.42.2",
|
|
157
|
+
"@spectrum-web-components/reactive-controllers": "^0.42.2",
|
|
158
|
+
"@spectrum-web-components/shared": "^0.42.2",
|
|
159
|
+
"@spectrum-web-components/theme": "^0.42.2"
|
|
160
160
|
},
|
|
161
161
|
"types": "./src/index.d.ts",
|
|
162
162
|
"customElements": "custom-elements.json",
|
|
@@ -168,5 +168,5 @@
|
|
|
168
168
|
"./stories/overlay-story-components.js",
|
|
169
169
|
"./**/*.dev.js"
|
|
170
170
|
],
|
|
171
|
-
"gitHead": "
|
|
171
|
+
"gitHead": "e19af30387032608baaa88c6a17c2ee50103a7c5"
|
|
172
172
|
}
|
package/src/Overlay.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare const strategies: {
|
|
|
19
19
|
*
|
|
20
20
|
* @fires sp-opened - announces that an overlay has completed any entry animations
|
|
21
21
|
* @fires sp-closed - announce that an overlay has compelted any exit animations
|
|
22
|
+
* @fires slottable-request - requests to add or remove slottable content
|
|
22
23
|
*/
|
|
23
24
|
export declare class Overlay extends OverlayFeatures {
|
|
24
25
|
static styles: import("@spectrum-web-components/base").CSSResult[];
|
|
@@ -68,6 +69,11 @@ export declare class Overlay extends OverlayFeatures {
|
|
|
68
69
|
* @type {"top" | "top-start" | "top-end" | "right" | "right-start" | "right-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end"}
|
|
69
70
|
*/
|
|
70
71
|
placement?: Placement;
|
|
72
|
+
/**
|
|
73
|
+
* The state in which the last `request-slottable` event was dispatched.
|
|
74
|
+
* Do not allow overlays from dispatching the same state twice in a row.
|
|
75
|
+
*/
|
|
76
|
+
private lastRequestSlottableState;
|
|
71
77
|
/**
|
|
72
78
|
* Whether to pass focus to the overlay once opened, or
|
|
73
79
|
* to the appropriate value based on the "type" of the overlay
|
package/src/Overlay.dev.js
CHANGED
|
@@ -63,6 +63,11 @@ const _Overlay = class _Overlay extends OverlayFeatures {
|
|
|
63
63
|
this._disabled = false;
|
|
64
64
|
this.offset = 0;
|
|
65
65
|
this._open = false;
|
|
66
|
+
/**
|
|
67
|
+
* The state in which the last `request-slottable` event was dispatched.
|
|
68
|
+
* Do not allow overlays from dispatching the same state twice in a row.
|
|
69
|
+
*/
|
|
70
|
+
this.lastRequestSlottableState = false;
|
|
66
71
|
this.receivesFocus = "auto";
|
|
67
72
|
this._state = "closed";
|
|
68
73
|
this.triggerElement = null;
|
|
@@ -363,6 +368,9 @@ const _Overlay = class _Overlay extends OverlayFeatures {
|
|
|
363
368
|
return shouldPreventClose;
|
|
364
369
|
}
|
|
365
370
|
requestSlottable() {
|
|
371
|
+
if (this.lastRequestSlottableState === this.open) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
366
374
|
if (!this.open) {
|
|
367
375
|
document.body.offsetHeight;
|
|
368
376
|
}
|
|
@@ -372,6 +380,7 @@ const _Overlay = class _Overlay extends OverlayFeatures {
|
|
|
372
380
|
this.open ? {} : removeSlottableRequest
|
|
373
381
|
)
|
|
374
382
|
);
|
|
383
|
+
this.lastRequestSlottableState = this.open;
|
|
375
384
|
}
|
|
376
385
|
willUpdate(changes) {
|
|
377
386
|
var _a;
|
package/src/Overlay.dev.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Overlay.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2023 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n html,\n PropertyValues,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n ElementResolutionController,\n elementResolverUpdatedSymbol,\n} from '@spectrum-web-components/reactive-controllers/src/ElementResolution.js';\nimport {\n ifDefined,\n StyleInfo,\n styleMap,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport type {\n OpenableElement,\n OverlayState,\n OverlayTypes,\n Placement,\n TriggerInteraction,\n} from './overlay-types.dev.js'\nimport { AbstractOverlay, nextFrame } from './AbstractOverlay.dev.js'\nimport { OverlayDialog } from './OverlayDialog.dev.js'\nimport { OverlayPopover } from './OverlayPopover.dev.js'\nimport { OverlayNoPopover } from './OverlayNoPopover.dev.js'\nimport { overlayStack } from './OverlayStack.dev.js'\nimport { VirtualTrigger } from './VirtualTrigger.dev.js'\nimport { PlacementController } from './PlacementController.dev.js'\nimport { ClickController } from './ClickController.dev.js'\nimport { HoverController } from './HoverController.dev.js'\nimport { LongpressController } from './LongpressController.dev.js'\nexport { LONGPRESS_INSTRUCTIONS } from './LongpressController.dev.js'\nimport {\n removeSlottableRequest,\n SlottableRequestEvent,\n} from './slottable-request-event.dev.js'\n\nimport styles from './overlay.css.js';\n\nconst supportsPopover = 'showPopover' in document.createElement('div');\n\nlet OverlayFeatures = OverlayDialog(AbstractOverlay);\n/* c8 ignore next 2 */\nif (supportsPopover) {\n OverlayFeatures = OverlayPopover(OverlayFeatures);\n} else {\n OverlayFeatures = OverlayNoPopover(OverlayFeatures);\n}\n\nexport const strategies = {\n click: ClickController,\n longpress: LongpressController,\n hover: HoverController,\n};\n\n/**\n * @element sp-overlay\n *\n * @fires sp-opened - announces that an overlay has completed any entry animations\n * @fires sp-closed - announce that an overlay has compelted any exit animations\n */\nexport class Overlay extends OverlayFeatures {\n static override styles = [styles];\n\n /**\n * An Overlay that is `delayed` will wait until a warm-up period of 1000ms\n * has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened,\n * a cooldown period of 1000ms will begin. Once the cooldown has completed,\n * the next Overlay to be opened will be subject to the warm-up period if\n * provided that option.\n */\n @property({ type: Boolean })\n override get delayed(): boolean {\n return this.elements.at(-1)?.hasAttribute('delayed') || this._delayed;\n }\n\n override set delayed(delayed: boolean) {\n this._delayed = delayed;\n }\n\n private _delayed = false;\n\n @query('.dialog')\n override dialogEl!: HTMLDialogElement & {\n showPopover(): void;\n hidePopover(): void;\n };\n\n /**\n * Whether the overlay is currently functional or not\n */\n @property({ type: Boolean })\n override get disabled(): boolean {\n return this._disabled;\n }\n\n override set disabled(disabled: boolean) {\n this._disabled = disabled;\n if (disabled) {\n this.strategy?.abort();\n this.wasOpen = this.open;\n this.open = false;\n } else {\n this.bindEvents();\n this.open = this.open || this.wasOpen;\n this.wasOpen = false;\n }\n }\n\n private _disabled = false;\n\n @queryAssignedElements({\n flatten: true,\n selector: ':not([slot=\"longpress-describedby-descriptor\"], slot)', // gather only elements slotted into the default slot\n })\n override elements!: OpenableElement[];\n\n public parentOverlayToForceClose?: Overlay;\n\n private get hasNonVirtualTrigger(): boolean {\n return (\n !!this.triggerElement &&\n !(this.triggerElement instanceof VirtualTrigger)\n );\n }\n\n /**\n * The `offset` property accepts either a single number, to\n * define the offset of the Overlay along the main axis from\n * the trigger, or 2-tuple, to define the offset along the\n * main axis and the cross axis. This option has no effect\n * when there is no trigger element.\n */\n @property({ type: Number })\n override offset: number | [number, number] = 0;\n\n protected override get placementController(): PlacementController {\n if (!this._placementController) {\n this._placementController = new PlacementController(this);\n }\n return this._placementController;\n }\n\n /**\n * Whether the Overlay is projected onto the \"top layer\" or not.\n */\n @property({ type: Boolean, reflect: true })\n override get open(): boolean {\n return this._open;\n }\n\n override set open(open: boolean) {\n // Don't respond when disabled.\n if (open && this.disabled) return;\n // Don't respond when state not dirty\n if (open === this.open) return;\n // Don't respond when you're in the shadow on a longpress\n // Shadow occurs when the first \"click\" would normally close the popover\n if (this.strategy?.activelyOpening && !open) return;\n this._open = open;\n if (this.open) {\n Overlay.openCount += 1;\n }\n this.requestUpdate('open', !this.open);\n if (this.open) {\n this.requestSlottable();\n }\n }\n\n private _open = false;\n\n static openCount = 1;\n\n /**\n * Instruct the Overlay where to place itself in\n * relationship to the trigger element.\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n */\n @property()\n override placement?: Placement;\n\n /**\n * Whether to pass focus to the overlay once opened, or\n * to the appropriate value based on the \"type\" of the overlay\n * when set to `\"auto\"`.\n *\n */\n @property({ attribute: 'receives-focus' })\n override receivesFocus: 'true' | 'false' | 'auto' = 'auto';\n\n @query('slot')\n slotEl!: HTMLSlotElement;\n\n @state()\n override get state(): OverlayState {\n return this._state;\n }\n\n override set state(state) {\n if (state === this.state) return;\n const oldState = this.state;\n this._state = state;\n if (this.state === 'opened' || this.state === 'closed') {\n this.strategy?.shouldCompleteOpen();\n }\n this.requestUpdate('state', oldState);\n }\n\n override _state: OverlayState = 'closed';\n\n public strategy?: ClickController | HoverController | LongpressController;\n\n @property({ type: Number, attribute: 'tip-padding' })\n tipPadding?: number;\n\n /**\n * An optional ID reference for the trigger element combined with the optional\n * interaction (click | hover | longpress) by which the overlay shold open\n * the overlay with an `@`: e.g. `trigger@click` opens the overlay when an\n * element with the ID \"trigger\" is clicked.\n */\n @property()\n trigger?: string;\n\n /**\n * An element reference for the trigger element that the overlay should relate to.\n */\n @property({ attribute: false })\n override triggerElement: HTMLElement | VirtualTrigger | null = null;\n\n /**\n * The specific interaction to listen for on the `triggerElement` to open the overlay.\n */\n @property({ attribute: false })\n triggerInteraction?: TriggerInteraction;\n\n /**\n * Configures the open/close heuristics of the Overlay.\n * @type {\"auto\" | \"hint\" | \"manual\" | \"modal\" | \"page\"}\n */\n @property()\n override type: OverlayTypes = 'auto';\n\n protected wasOpen = false;\n\n protected override get elementResolver(): ElementResolutionController {\n if (!this._elementResolver) {\n this._elementResolver = new ElementResolutionController(this);\n }\n return this._elementResolver;\n }\n\n private get usesDialog(): boolean {\n return this.type === 'modal' || this.type === 'page';\n }\n\n private get popoverValue(): 'auto' | 'manual' | undefined {\n const hasPopoverAttribute = 'popover' in this;\n if (!hasPopoverAttribute) {\n return undefined;\n }\n /* c8 ignore next 9 */\n switch (this.type) {\n case 'modal':\n case 'page':\n return undefined;\n case 'hint':\n return 'manual';\n default:\n return this.type;\n }\n }\n\n protected get requiresPosition(): boolean {\n // Do not position \"page\" overlays as they should block the entire UI.\n if (this.type === 'page' || !this.open) return false;\n // Do not position content without a trigger element, what would you position it in relation to?\n // Do not automatically position content, unless it is a \"hint\".\n if (!this.triggerElement || (!this.placement && this.type !== 'hint'))\n return false;\n return true;\n }\n\n protected override managePosition(): void {\n if (!this.requiresPosition || !this.open) return;\n\n const offset = this.offset || 0;\n const trigger = this.triggerElement as HTMLElement;\n const placement = (this.placement as Placement) || 'right';\n const tipPadding = this.tipPadding;\n\n this.placementController.placeOverlay(this.dialogEl, {\n offset,\n placement,\n tipPadding,\n trigger,\n type: this.type,\n });\n }\n\n protected override async managePopoverOpen(): Promise<void> {\n super.managePopoverOpen();\n const targetOpenState = this.open;\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n await this.manageDelay(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.ensureOnDOM(targetOpenState);\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n const focusEl = await this.makeTransition(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.applyFocus(targetOpenState, focusEl);\n }\n\n protected override async applyFocus(\n targetOpenState: boolean,\n focusEl: HTMLElement | null\n ): Promise<void> {\n // Do not move focus when explicitly told not to\n // and when the Overlay is a \"hint\"\n if (this.receivesFocus === 'false' || this.type === 'hint') {\n return;\n }\n\n await nextFrame();\n await nextFrame();\n if (targetOpenState === this.open && !this.open) {\n if (\n this.hasNonVirtualTrigger &&\n this.contains((this.getRootNode() as Document).activeElement)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n return;\n }\n focusEl?.focus();\n }\n\n protected override returnFocus(): void {\n if (this.open || this.type === 'hint') return;\n\n // If the focus remains inside of the overlay or\n // a slotted descendent of the overlay you need to return\n // focus back to the trigger.\n const getAncestors = (): HTMLElement[] => {\n const ancestors: HTMLElement[] = [];\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n let currentNode = document.activeElement;\n while (currentNode?.shadowRoot?.activeElement) {\n currentNode = currentNode.shadowRoot.activeElement;\n }\n while (currentNode) {\n const ancestor =\n currentNode.assignedSlot ||\n currentNode.parentElement ||\n (currentNode.getRootNode() as ShadowRoot)?.host;\n if (ancestor) {\n ancestors.push(ancestor as HTMLElement);\n }\n currentNode = ancestor;\n }\n return ancestors;\n };\n if (\n (this.triggerElement as HTMLElement)?.focus &&\n (this.contains((this.getRootNode() as Document).activeElement) ||\n getAncestors().includes(this) ||\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n document.activeElement === document.body)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n }\n\n private closeOnFocusOut = (event: FocusEvent): void => {\n // If you don't know where the focus went, we can't do anyting here.\n if (!event.relatedTarget) {\n // this.open = false;\n return;\n }\n const relationEvent = new Event('overlay-relation-query', {\n bubbles: true,\n composed: true,\n });\n event.relatedTarget.addEventListener(\n relationEvent.type,\n (event: Event) => {\n if (!event.composedPath().includes(this)) {\n this.open = false;\n }\n }\n );\n event.relatedTarget.dispatchEvent(relationEvent);\n };\n\n protected async manageOpen(oldOpen: boolean): Promise<void> {\n // The `.showPopover()` and `.showModal()` events will error on content that is not connected to the DOM.\n // Prevent from entering the manage workflow in order to avoid this.\n if (!this.isConnected && this.open) return;\n\n if (!this.hasUpdated) {\n await this.updateComplete;\n }\n\n if (this.open) {\n overlayStack.add(this);\n if (this.willPreventClose) {\n document.addEventListener(\n 'pointerup',\n () => {\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n false\n );\n this.willPreventClose = false;\n },\n { once: true }\n );\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n true\n );\n }\n } else {\n if (oldOpen) {\n this.dispose();\n }\n overlayStack.remove(this);\n }\n if (this.open && this.state !== 'opened') {\n this.state = 'opening';\n } else if (!this.open && this.state !== 'closed') {\n this.state = 'closing';\n }\n\n if (this.usesDialog) {\n this.manageDialogOpen();\n } else {\n this.managePopoverOpen();\n }\n if (this.type === 'auto') {\n const listenerRoot = this.getRootNode() as Document;\n if (this.open) {\n listenerRoot.addEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n } else {\n listenerRoot.removeEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n }\n }\n }\n\n protected bindEvents(): void {\n this.strategy?.abort();\n this.strategy = undefined;\n if (!this.hasNonVirtualTrigger) return;\n if (!this.triggerInteraction) return;\n this.strategy = new strategies[this.triggerInteraction](\n this,\n this.triggerElement as HTMLElement\n );\n }\n\n protected handleBeforetoggle(event: Event & { newState: string }): void {\n if (event.newState !== 'open') {\n this.handleBrowserClose();\n }\n }\n\n protected handleBrowserClose(): void {\n if (!this.strategy?.activelyOpening) {\n this.open = false;\n return;\n }\n this.manuallyKeepOpen();\n }\n\n public override manuallyKeepOpen(): void {\n this.open = true;\n this.placementController.allowPlacementUpdate = true;\n this.manageOpen(false);\n }\n\n protected handleSlotchange(): void {\n if (!this.elements.length) {\n this.strategy?.releaseDescription();\n } else if (this.hasNonVirtualTrigger) {\n this.strategy?.prepareDescription(\n this.triggerElement as HTMLElement\n );\n }\n }\n\n public shouldPreventClose(): boolean {\n const shouldPreventClose = this.willPreventClose;\n this.willPreventClose = false;\n return shouldPreventClose;\n }\n\n protected override requestSlottable(): void {\n if (!this.open) {\n document.body.offsetHeight;\n }\n this.dispatchEvent(\n new SlottableRequestEvent(\n 'overlay-content',\n this.open ? {} : removeSlottableRequest\n )\n );\n }\n\n override willUpdate(changes: PropertyValues): void {\n if (!this.hasAttribute('id')) {\n this.setAttribute(\n 'id',\n `${this.tagName.toLowerCase()}-${randomID()}`\n );\n }\n if (\n changes.has('open') &&\n (typeof changes.get('open') !== 'undefined' || this.open)\n ) {\n this.manageOpen(changes.get('open'));\n }\n if (changes.has('trigger')) {\n const [id, interaction] = this.trigger?.split('@') || [];\n this.elementResolver.selector = id ? `#${id}` : '';\n this.triggerInteraction = interaction as\n | 'click'\n | 'longpress'\n | 'hover'\n | undefined;\n }\n // Merge multiple possible calls to `bindEvents()`.\n let oldTrigger: HTMLElement | false | undefined = false;\n if (changes.has(elementResolverUpdatedSymbol)) {\n oldTrigger = this.triggerElement as HTMLElement;\n this.triggerElement = this.elementResolver.element;\n }\n if (changes.has('triggerElement')) {\n oldTrigger = changes.get('triggerElement');\n }\n if (oldTrigger !== false) {\n this.bindEvents();\n }\n }\n\n protected override updated(changes: PropertyValues): void {\n super.updated(changes);\n if (changes.has('placement')) {\n if (this.placement) {\n this.dialogEl.setAttribute('actual-placement', this.placement);\n } else {\n this.dialogEl.removeAttribute('actual-placement');\n }\n if (this.open && typeof changes.get('placement') !== 'undefined') {\n this.placementController.resetOverlayPosition();\n }\n }\n if (\n changes.has('state') &&\n this.state === 'closed' &&\n typeof changes.get('state') !== 'undefined'\n ) {\n this.placementController.clearOverlayPosition();\n }\n }\n\n protected renderContent(): TemplateResult {\n return html`\n <slot @slotchange=${this.handleSlotchange}></slot>\n `;\n }\n\n private get dialogStyleMap(): StyleInfo {\n return {\n '--swc-overlay-open-count': Overlay.openCount.toString(),\n };\n }\n\n protected renderDialog(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <dialog\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n style=${styleMap(this.dialogStyleMap)}\n @close=${this.handleBrowserClose}\n @cancel=${this.handleBrowserClose}\n @beforetoggle=${this.handleBeforetoggle}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </dialog>\n `;\n }\n\n protected renderPopover(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <div\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n popover=${ifDefined(this.popoverValue)}\n style=${styleMap(this.dialogStyleMap)}\n @beforetoggle=${this.handleBeforetoggle}\n @close=${this.handleBrowserClose}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </div>\n `;\n }\n\n public override render(): TemplateResult {\n const isDialog = this.type === 'modal' || this.type === 'page';\n return html`\n ${isDialog ? this.renderDialog() : this.renderPopover()}\n <slot name=\"longpress-describedby-descriptor\"></slot>\n `;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('close', () => {\n this.open = false;\n });\n if (this.hasUpdated) {\n this.bindEvents();\n }\n }\n\n override disconnectedCallback(): void {\n this.strategy?.releaseDescription();\n this.open = false;\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAWA;AAAA,EACI;AAAA,OAGG;AACP;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP;AAAA,EACI;AAAA,EACA;AAAA,OACG;AACP;AAAA,EACI;AAAA,EAEA;AAAA,OACG;AACP,SAAS,gBAAgB;AASzB,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAC/B,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAChC,SAAS,2BAA2B;AACpC,SAAS,8BAA8B;AACvC;AAAA,EACI;AAAA,EACA;AAAA,OACG;AAEP,OAAO,YAAY;AAEnB,MAAM,kBAAkB,iBAAiB,SAAS,cAAc,KAAK;AAErE,IAAI,kBAAkB,cAAc,eAAe;AAEnD,IAAI,iBAAiB;AACjB,oBAAkB,eAAe,eAAe;AACpD,OAAO;AACH,oBAAkB,iBAAiB,eAAe;AACtD;AAEO,aAAM,aAAa;AAAA,EACtB,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AACX;
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2023 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n html,\n PropertyValues,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n ElementResolutionController,\n elementResolverUpdatedSymbol,\n} from '@spectrum-web-components/reactive-controllers/src/ElementResolution.js';\nimport {\n ifDefined,\n StyleInfo,\n styleMap,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport type {\n OpenableElement,\n OverlayState,\n OverlayTypes,\n Placement,\n TriggerInteraction,\n} from './overlay-types.dev.js'\nimport { AbstractOverlay, nextFrame } from './AbstractOverlay.dev.js'\nimport { OverlayDialog } from './OverlayDialog.dev.js'\nimport { OverlayPopover } from './OverlayPopover.dev.js'\nimport { OverlayNoPopover } from './OverlayNoPopover.dev.js'\nimport { overlayStack } from './OverlayStack.dev.js'\nimport { VirtualTrigger } from './VirtualTrigger.dev.js'\nimport { PlacementController } from './PlacementController.dev.js'\nimport { ClickController } from './ClickController.dev.js'\nimport { HoverController } from './HoverController.dev.js'\nimport { LongpressController } from './LongpressController.dev.js'\nexport { LONGPRESS_INSTRUCTIONS } from './LongpressController.dev.js'\nimport {\n removeSlottableRequest,\n SlottableRequestEvent,\n} from './slottable-request-event.dev.js'\n\nimport styles from './overlay.css.js';\n\nconst supportsPopover = 'showPopover' in document.createElement('div');\n\nlet OverlayFeatures = OverlayDialog(AbstractOverlay);\n/* c8 ignore next 2 */\nif (supportsPopover) {\n OverlayFeatures = OverlayPopover(OverlayFeatures);\n} else {\n OverlayFeatures = OverlayNoPopover(OverlayFeatures);\n}\n\nexport const strategies = {\n click: ClickController,\n longpress: LongpressController,\n hover: HoverController,\n};\n\n/**\n * @element sp-overlay\n *\n * @fires sp-opened - announces that an overlay has completed any entry animations\n * @fires sp-closed - announce that an overlay has compelted any exit animations\n * @fires slottable-request - requests to add or remove slottable content\n */\nexport class Overlay extends OverlayFeatures {\n static override styles = [styles];\n\n /**\n * An Overlay that is `delayed` will wait until a warm-up period of 1000ms\n * has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened,\n * a cooldown period of 1000ms will begin. Once the cooldown has completed,\n * the next Overlay to be opened will be subject to the warm-up period if\n * provided that option.\n */\n @property({ type: Boolean })\n override get delayed(): boolean {\n return this.elements.at(-1)?.hasAttribute('delayed') || this._delayed;\n }\n\n override set delayed(delayed: boolean) {\n this._delayed = delayed;\n }\n\n private _delayed = false;\n\n @query('.dialog')\n override dialogEl!: HTMLDialogElement & {\n showPopover(): void;\n hidePopover(): void;\n };\n\n /**\n * Whether the overlay is currently functional or not\n */\n @property({ type: Boolean })\n override get disabled(): boolean {\n return this._disabled;\n }\n\n override set disabled(disabled: boolean) {\n this._disabled = disabled;\n if (disabled) {\n this.strategy?.abort();\n this.wasOpen = this.open;\n this.open = false;\n } else {\n this.bindEvents();\n this.open = this.open || this.wasOpen;\n this.wasOpen = false;\n }\n }\n\n private _disabled = false;\n\n @queryAssignedElements({\n flatten: true,\n selector: ':not([slot=\"longpress-describedby-descriptor\"], slot)', // gather only elements slotted into the default slot\n })\n override elements!: OpenableElement[];\n\n public parentOverlayToForceClose?: Overlay;\n\n private get hasNonVirtualTrigger(): boolean {\n return (\n !!this.triggerElement &&\n !(this.triggerElement instanceof VirtualTrigger)\n );\n }\n\n /**\n * The `offset` property accepts either a single number, to\n * define the offset of the Overlay along the main axis from\n * the trigger, or 2-tuple, to define the offset along the\n * main axis and the cross axis. This option has no effect\n * when there is no trigger element.\n */\n @property({ type: Number })\n override offset: number | [number, number] = 0;\n\n protected override get placementController(): PlacementController {\n if (!this._placementController) {\n this._placementController = new PlacementController(this);\n }\n return this._placementController;\n }\n\n /**\n * Whether the Overlay is projected onto the \"top layer\" or not.\n */\n @property({ type: Boolean, reflect: true })\n override get open(): boolean {\n return this._open;\n }\n\n override set open(open: boolean) {\n // Don't respond when disabled.\n if (open && this.disabled) return;\n // Don't respond when state not dirty\n if (open === this.open) return;\n // Don't respond when you're in the shadow on a longpress\n // Shadow occurs when the first \"click\" would normally close the popover\n if (this.strategy?.activelyOpening && !open) return;\n this._open = open;\n if (this.open) {\n Overlay.openCount += 1;\n }\n this.requestUpdate('open', !this.open);\n if (this.open) {\n this.requestSlottable();\n }\n }\n\n private _open = false;\n\n static openCount = 1;\n\n /**\n * Instruct the Overlay where to place itself in\n * relationship to the trigger element.\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n */\n @property()\n override placement?: Placement;\n\n /**\n * The state in which the last `request-slottable` event was dispatched.\n * Do not allow overlays from dispatching the same state twice in a row.\n */\n private lastRequestSlottableState = false;\n\n /**\n * Whether to pass focus to the overlay once opened, or\n * to the appropriate value based on the \"type\" of the overlay\n * when set to `\"auto\"`.\n *\n */\n @property({ attribute: 'receives-focus' })\n override receivesFocus: 'true' | 'false' | 'auto' = 'auto';\n\n @query('slot')\n slotEl!: HTMLSlotElement;\n\n @state()\n override get state(): OverlayState {\n return this._state;\n }\n\n override set state(state) {\n if (state === this.state) return;\n const oldState = this.state;\n this._state = state;\n if (this.state === 'opened' || this.state === 'closed') {\n this.strategy?.shouldCompleteOpen();\n }\n this.requestUpdate('state', oldState);\n }\n\n override _state: OverlayState = 'closed';\n\n public strategy?: ClickController | HoverController | LongpressController;\n\n @property({ type: Number, attribute: 'tip-padding' })\n tipPadding?: number;\n\n /**\n * An optional ID reference for the trigger element combined with the optional\n * interaction (click | hover | longpress) by which the overlay shold open\n * the overlay with an `@`: e.g. `trigger@click` opens the overlay when an\n * element with the ID \"trigger\" is clicked.\n */\n @property()\n trigger?: string;\n\n /**\n * An element reference for the trigger element that the overlay should relate to.\n */\n @property({ attribute: false })\n override triggerElement: HTMLElement | VirtualTrigger | null = null;\n\n /**\n * The specific interaction to listen for on the `triggerElement` to open the overlay.\n */\n @property({ attribute: false })\n triggerInteraction?: TriggerInteraction;\n\n /**\n * Configures the open/close heuristics of the Overlay.\n * @type {\"auto\" | \"hint\" | \"manual\" | \"modal\" | \"page\"}\n */\n @property()\n override type: OverlayTypes = 'auto';\n\n protected wasOpen = false;\n\n protected override get elementResolver(): ElementResolutionController {\n if (!this._elementResolver) {\n this._elementResolver = new ElementResolutionController(this);\n }\n return this._elementResolver;\n }\n\n private get usesDialog(): boolean {\n return this.type === 'modal' || this.type === 'page';\n }\n\n private get popoverValue(): 'auto' | 'manual' | undefined {\n const hasPopoverAttribute = 'popover' in this;\n if (!hasPopoverAttribute) {\n return undefined;\n }\n /* c8 ignore next 9 */\n switch (this.type) {\n case 'modal':\n case 'page':\n return undefined;\n case 'hint':\n return 'manual';\n default:\n return this.type;\n }\n }\n\n protected get requiresPosition(): boolean {\n // Do not position \"page\" overlays as they should block the entire UI.\n if (this.type === 'page' || !this.open) return false;\n // Do not position content without a trigger element, what would you position it in relation to?\n // Do not automatically position content, unless it is a \"hint\".\n if (!this.triggerElement || (!this.placement && this.type !== 'hint'))\n return false;\n return true;\n }\n\n protected override managePosition(): void {\n if (!this.requiresPosition || !this.open) return;\n\n const offset = this.offset || 0;\n const trigger = this.triggerElement as HTMLElement;\n const placement = (this.placement as Placement) || 'right';\n const tipPadding = this.tipPadding;\n\n this.placementController.placeOverlay(this.dialogEl, {\n offset,\n placement,\n tipPadding,\n trigger,\n type: this.type,\n });\n }\n\n protected override async managePopoverOpen(): Promise<void> {\n super.managePopoverOpen();\n const targetOpenState = this.open;\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n await this.manageDelay(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.ensureOnDOM(targetOpenState);\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n const focusEl = await this.makeTransition(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.applyFocus(targetOpenState, focusEl);\n }\n\n protected override async applyFocus(\n targetOpenState: boolean,\n focusEl: HTMLElement | null\n ): Promise<void> {\n // Do not move focus when explicitly told not to\n // and when the Overlay is a \"hint\"\n if (this.receivesFocus === 'false' || this.type === 'hint') {\n return;\n }\n\n await nextFrame();\n await nextFrame();\n if (targetOpenState === this.open && !this.open) {\n if (\n this.hasNonVirtualTrigger &&\n this.contains((this.getRootNode() as Document).activeElement)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n return;\n }\n focusEl?.focus();\n }\n\n protected override returnFocus(): void {\n if (this.open || this.type === 'hint') return;\n\n // If the focus remains inside of the overlay or\n // a slotted descendent of the overlay you need to return\n // focus back to the trigger.\n const getAncestors = (): HTMLElement[] => {\n const ancestors: HTMLElement[] = [];\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n let currentNode = document.activeElement;\n while (currentNode?.shadowRoot?.activeElement) {\n currentNode = currentNode.shadowRoot.activeElement;\n }\n while (currentNode) {\n const ancestor =\n currentNode.assignedSlot ||\n currentNode.parentElement ||\n (currentNode.getRootNode() as ShadowRoot)?.host;\n if (ancestor) {\n ancestors.push(ancestor as HTMLElement);\n }\n currentNode = ancestor;\n }\n return ancestors;\n };\n if (\n (this.triggerElement as HTMLElement)?.focus &&\n (this.contains((this.getRootNode() as Document).activeElement) ||\n getAncestors().includes(this) ||\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n document.activeElement === document.body)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n }\n\n private closeOnFocusOut = (event: FocusEvent): void => {\n // If you don't know where the focus went, we can't do anyting here.\n if (!event.relatedTarget) {\n // this.open = false;\n return;\n }\n const relationEvent = new Event('overlay-relation-query', {\n bubbles: true,\n composed: true,\n });\n event.relatedTarget.addEventListener(\n relationEvent.type,\n (event: Event) => {\n if (!event.composedPath().includes(this)) {\n this.open = false;\n }\n }\n );\n event.relatedTarget.dispatchEvent(relationEvent);\n };\n\n protected async manageOpen(oldOpen: boolean): Promise<void> {\n // The `.showPopover()` and `.showModal()` events will error on content that is not connected to the DOM.\n // Prevent from entering the manage workflow in order to avoid this.\n if (!this.isConnected && this.open) return;\n\n if (!this.hasUpdated) {\n await this.updateComplete;\n }\n\n if (this.open) {\n overlayStack.add(this);\n if (this.willPreventClose) {\n document.addEventListener(\n 'pointerup',\n () => {\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n false\n );\n this.willPreventClose = false;\n },\n { once: true }\n );\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n true\n );\n }\n } else {\n if (oldOpen) {\n this.dispose();\n }\n overlayStack.remove(this);\n }\n if (this.open && this.state !== 'opened') {\n this.state = 'opening';\n } else if (!this.open && this.state !== 'closed') {\n this.state = 'closing';\n }\n\n if (this.usesDialog) {\n this.manageDialogOpen();\n } else {\n this.managePopoverOpen();\n }\n if (this.type === 'auto') {\n const listenerRoot = this.getRootNode() as Document;\n if (this.open) {\n listenerRoot.addEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n } else {\n listenerRoot.removeEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n }\n }\n }\n\n protected bindEvents(): void {\n this.strategy?.abort();\n this.strategy = undefined;\n if (!this.hasNonVirtualTrigger) return;\n if (!this.triggerInteraction) return;\n this.strategy = new strategies[this.triggerInteraction](\n this,\n this.triggerElement as HTMLElement\n );\n }\n\n protected handleBeforetoggle(event: Event & { newState: string }): void {\n if (event.newState !== 'open') {\n this.handleBrowserClose();\n }\n }\n\n protected handleBrowserClose(): void {\n if (!this.strategy?.activelyOpening) {\n this.open = false;\n return;\n }\n this.manuallyKeepOpen();\n }\n\n public override manuallyKeepOpen(): void {\n this.open = true;\n this.placementController.allowPlacementUpdate = true;\n this.manageOpen(false);\n }\n\n protected handleSlotchange(): void {\n if (!this.elements.length) {\n this.strategy?.releaseDescription();\n } else if (this.hasNonVirtualTrigger) {\n this.strategy?.prepareDescription(\n this.triggerElement as HTMLElement\n );\n }\n }\n\n public shouldPreventClose(): boolean {\n const shouldPreventClose = this.willPreventClose;\n this.willPreventClose = false;\n return shouldPreventClose;\n }\n\n protected override requestSlottable(): void {\n if (this.lastRequestSlottableState === this.open) {\n return;\n }\n if (!this.open) {\n document.body.offsetHeight;\n }\n /**\n * @ignore\n */\n this.dispatchEvent(\n new SlottableRequestEvent(\n 'overlay-content',\n this.open ? {} : removeSlottableRequest\n )\n );\n this.lastRequestSlottableState = this.open;\n }\n\n override willUpdate(changes: PropertyValues): void {\n if (!this.hasAttribute('id')) {\n this.setAttribute(\n 'id',\n `${this.tagName.toLowerCase()}-${randomID()}`\n );\n }\n if (\n changes.has('open') &&\n (typeof changes.get('open') !== 'undefined' || this.open)\n ) {\n this.manageOpen(changes.get('open'));\n }\n if (changes.has('trigger')) {\n const [id, interaction] = this.trigger?.split('@') || [];\n this.elementResolver.selector = id ? `#${id}` : '';\n this.triggerInteraction = interaction as\n | 'click'\n | 'longpress'\n | 'hover'\n | undefined;\n }\n // Merge multiple possible calls to `bindEvents()`.\n let oldTrigger: HTMLElement | false | undefined = false;\n if (changes.has(elementResolverUpdatedSymbol)) {\n oldTrigger = this.triggerElement as HTMLElement;\n this.triggerElement = this.elementResolver.element;\n }\n if (changes.has('triggerElement')) {\n oldTrigger = changes.get('triggerElement');\n }\n if (oldTrigger !== false) {\n this.bindEvents();\n }\n }\n\n protected override updated(changes: PropertyValues): void {\n super.updated(changes);\n if (changes.has('placement')) {\n if (this.placement) {\n this.dialogEl.setAttribute('actual-placement', this.placement);\n } else {\n this.dialogEl.removeAttribute('actual-placement');\n }\n if (this.open && typeof changes.get('placement') !== 'undefined') {\n this.placementController.resetOverlayPosition();\n }\n }\n if (\n changes.has('state') &&\n this.state === 'closed' &&\n typeof changes.get('state') !== 'undefined'\n ) {\n this.placementController.clearOverlayPosition();\n }\n }\n\n protected renderContent(): TemplateResult {\n return html`\n <slot @slotchange=${this.handleSlotchange}></slot>\n `;\n }\n\n private get dialogStyleMap(): StyleInfo {\n return {\n '--swc-overlay-open-count': Overlay.openCount.toString(),\n };\n }\n\n protected renderDialog(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <dialog\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n style=${styleMap(this.dialogStyleMap)}\n @close=${this.handleBrowserClose}\n @cancel=${this.handleBrowserClose}\n @beforetoggle=${this.handleBeforetoggle}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </dialog>\n `;\n }\n\n protected renderPopover(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <div\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n popover=${ifDefined(this.popoverValue)}\n style=${styleMap(this.dialogStyleMap)}\n @beforetoggle=${this.handleBeforetoggle}\n @close=${this.handleBrowserClose}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </div>\n `;\n }\n\n public override render(): TemplateResult {\n const isDialog = this.type === 'modal' || this.type === 'page';\n return html`\n ${isDialog ? this.renderDialog() : this.renderPopover()}\n <slot name=\"longpress-describedby-descriptor\"></slot>\n `;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('close', () => {\n this.open = false;\n });\n if (this.hasUpdated) {\n this.bindEvents();\n }\n }\n\n override disconnectedCallback(): void {\n this.strategy?.releaseDescription();\n this.open = false;\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["event", "state", "_a"]
|
|
7
7
|
}
|
package/src/Overlay.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var b=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var b=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var r=(u,a,e,t)=>{for(var o=t>1?void 0:t?E(a,e):a,s=u.length-1,l;s>=0;s--)(l=u[s])&&(o=(t?l(a,e,o):l(o))||o);return t&&o&&b(a,e,o),o};import{html as d}from"@spectrum-web-components/base";import{property as n,query as g,queryAssignedElements as C,state as P}from"@spectrum-web-components/base/src/decorators.js";import{ElementResolutionController as w,elementResolverUpdatedSymbol as T}from"@spectrum-web-components/reactive-controllers/src/ElementResolution.js";import{ifDefined as c,styleMap as f}from"@spectrum-web-components/base/src/directives.js";import{randomID as S}from"@spectrum-web-components/shared/src/random-id.js";import{AbstractOverlay as R,nextFrame as v}from"./AbstractOverlay.js";import{OverlayDialog as L}from"./OverlayDialog.js";import{OverlayPopover as O}from"./OverlayPopover.js";import{OverlayNoPopover as M}from"./OverlayNoPopover.js";import{overlayStack as y}from"./OverlayStack.js";import{VirtualTrigger as $}from"./VirtualTrigger.js";import{PlacementController as D}from"./PlacementController.js";import{ClickController as H}from"./ClickController.js";import{HoverController as q}from"./HoverController.js";import{LongpressController as N}from"./LongpressController.js";export{LONGPRESS_INSTRUCTIONS}from"./LongpressController.js";import{removeSlottableRequest as F,SlottableRequestEvent as B}from"./slottable-request-event.js";import I from"./overlay.css.js";const V="showPopover"in document.createElement("div");let p=L(R);V?p=O(p):p=M(p);export const strategies={click:H,longpress:N,hover:q};const i=class i extends p{constructor(){super(...arguments);this._delayed=!1;this._disabled=!1;this.offset=0;this._open=!1;this.lastRequestSlottableState=!1;this.receivesFocus="auto";this._state="closed";this.triggerElement=null;this.type="auto";this.wasOpen=!1;this.closeOnFocusOut=e=>{if(!e.relatedTarget)return;const t=new Event("overlay-relation-query",{bubbles:!0,composed:!0});e.relatedTarget.addEventListener(t.type,o=>{o.composedPath().includes(this)||(this.open=!1)}),e.relatedTarget.dispatchEvent(t)}}get delayed(){var e;return((e=this.elements.at(-1))==null?void 0:e.hasAttribute("delayed"))||this._delayed}set delayed(e){this._delayed=e}get disabled(){return this._disabled}set disabled(e){var t;this._disabled=e,e?((t=this.strategy)==null||t.abort(),this.wasOpen=this.open,this.open=!1):(this.bindEvents(),this.open=this.open||this.wasOpen,this.wasOpen=!1)}get hasNonVirtualTrigger(){return!!this.triggerElement&&!(this.triggerElement instanceof $)}get placementController(){return this._placementController||(this._placementController=new D(this)),this._placementController}get open(){return this._open}set open(e){var t;e&&this.disabled||e!==this.open&&((t=this.strategy)!=null&&t.activelyOpening&&!e||(this._open=e,this.open&&(i.openCount+=1),this.requestUpdate("open",!this.open),this.open&&this.requestSlottable()))}get state(){return this._state}set state(e){var o;if(e===this.state)return;const t=this.state;this._state=e,(this.state==="opened"||this.state==="closed")&&((o=this.strategy)==null||o.shouldCompleteOpen()),this.requestUpdate("state",t)}get elementResolver(){return this._elementResolver||(this._elementResolver=new w(this)),this._elementResolver}get usesDialog(){return this.type==="modal"||this.type==="page"}get popoverValue(){if("popover"in this)switch(this.type){case"modal":case"page":return;case"hint":return"manual";default:return this.type}}get requiresPosition(){return!(this.type==="page"||!this.open||!this.triggerElement||!this.placement&&this.type!=="hint")}managePosition(){if(!this.requiresPosition||!this.open)return;const e=this.offset||0,t=this.triggerElement,o=this.placement||"right",s=this.tipPadding;this.placementController.placeOverlay(this.dialogEl,{offset:e,placement:o,tipPadding:s,trigger:t,type:this.type})}async managePopoverOpen(){super.managePopoverOpen();const e=this.open;if(this.open!==e||(await this.manageDelay(e),this.open!==e)||(await this.ensureOnDOM(e),this.open!==e))return;const t=await this.makeTransition(e);this.open===e&&await this.applyFocus(e,t)}async applyFocus(e,t){if(!(this.receivesFocus==="false"||this.type==="hint")){if(await v(),await v(),e===this.open&&!this.open){this.hasNonVirtualTrigger&&this.contains(this.getRootNode().activeElement)&&this.triggerElement.focus();return}t==null||t.focus()}}returnFocus(){var t;if(this.open||this.type==="hint")return;const e=()=>{var l,m;const o=[];let s=document.activeElement;for(;(l=s==null?void 0:s.shadowRoot)!=null&&l.activeElement;)s=s.shadowRoot.activeElement;for(;s;){const h=s.assignedSlot||s.parentElement||((m=s.getRootNode())==null?void 0:m.host);h&&o.push(h),s=h}return o};(t=this.triggerElement)!=null&&t.focus&&(this.contains(this.getRootNode().activeElement)||e().includes(this)||document.activeElement===document.body)&&this.triggerElement.focus()}async manageOpen(e){if(!(!this.isConnected&&this.open)&&(this.hasUpdated||await this.updateComplete,this.open?(y.add(this),this.willPreventClose&&(document.addEventListener("pointerup",()=>{this.dialogEl.classList.toggle("not-immediately-closable",!1),this.willPreventClose=!1},{once:!0}),this.dialogEl.classList.toggle("not-immediately-closable",!0))):(e&&this.dispose(),y.remove(this)),this.open&&this.state!=="opened"?this.state="opening":!this.open&&this.state!=="closed"&&(this.state="closing"),this.usesDialog?this.manageDialogOpen():this.managePopoverOpen(),this.type==="auto")){const t=this.getRootNode();this.open?t.addEventListener("focusout",this.closeOnFocusOut,{capture:!0}):t.removeEventListener("focusout",this.closeOnFocusOut,{capture:!0})}}bindEvents(){var e;(e=this.strategy)==null||e.abort(),this.strategy=void 0,this.hasNonVirtualTrigger&&this.triggerInteraction&&(this.strategy=new strategies[this.triggerInteraction](this,this.triggerElement))}handleBeforetoggle(e){e.newState!=="open"&&this.handleBrowserClose()}handleBrowserClose(){var e;if(!((e=this.strategy)!=null&&e.activelyOpening)){this.open=!1;return}this.manuallyKeepOpen()}manuallyKeepOpen(){this.open=!0,this.placementController.allowPlacementUpdate=!0,this.manageOpen(!1)}handleSlotchange(){var e,t;this.elements.length?this.hasNonVirtualTrigger&&((t=this.strategy)==null||t.prepareDescription(this.triggerElement)):(e=this.strategy)==null||e.releaseDescription()}shouldPreventClose(){const e=this.willPreventClose;return this.willPreventClose=!1,e}requestSlottable(){this.lastRequestSlottableState!==this.open&&(this.open||document.body.offsetHeight,this.dispatchEvent(new B("overlay-content",this.open?{}:F)),this.lastRequestSlottableState=this.open)}willUpdate(e){var o;if(this.hasAttribute("id")||this.setAttribute("id",`${this.tagName.toLowerCase()}-${S()}`),e.has("open")&&(typeof e.get("open")!="undefined"||this.open)&&this.manageOpen(e.get("open")),e.has("trigger")){const[s,l]=((o=this.trigger)==null?void 0:o.split("@"))||[];this.elementResolver.selector=s?`#${s}`:"",this.triggerInteraction=l}let t=!1;e.has(T)&&(t=this.triggerElement,this.triggerElement=this.elementResolver.element),e.has("triggerElement")&&(t=e.get("triggerElement")),t!==!1&&this.bindEvents()}updated(e){super.updated(e),e.has("placement")&&(this.placement?this.dialogEl.setAttribute("actual-placement",this.placement):this.dialogEl.removeAttribute("actual-placement"),this.open&&typeof e.get("placement")!="undefined"&&this.placementController.resetOverlayPosition()),e.has("state")&&this.state==="closed"&&typeof e.get("state")!="undefined"&&this.placementController.clearOverlayPosition()}renderContent(){return d`
|
|
2
2
|
<slot @slotchange=${this.handleSlotchange}></slot>
|
|
3
3
|
`}get dialogStyleMap(){return{"--swc-overlay-open-count":i.openCount.toString()}}renderDialog(){return d`
|
|
4
4
|
<dialog
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
`}render(){const e=this.type==="modal"||this.type==="page";return d`
|
|
30
30
|
${e?this.renderDialog():this.renderPopover()}
|
|
31
31
|
<slot name="longpress-describedby-descriptor"></slot>
|
|
32
|
-
`}connectedCallback(){super.connectedCallback(),this.addEventListener("close",()=>{this.open=!1}),this.hasUpdated&&this.bindEvents()}disconnectedCallback(){var e;(e=this.strategy)==null||e.releaseDescription(),this.open=!1,super.disconnectedCallback()}};i.styles=[I],i.openCount=1,
|
|
32
|
+
`}connectedCallback(){super.connectedCallback(),this.addEventListener("close",()=>{this.open=!1}),this.hasUpdated&&this.bindEvents()}disconnectedCallback(){var e;(e=this.strategy)==null||e.releaseDescription(),this.open=!1,super.disconnectedCallback()}};i.styles=[I],i.openCount=1,r([n({type:Boolean})],i.prototype,"delayed",1),r([g(".dialog")],i.prototype,"dialogEl",2),r([n({type:Boolean})],i.prototype,"disabled",1),r([C({flatten:!0,selector:':not([slot="longpress-describedby-descriptor"], slot)'})],i.prototype,"elements",2),r([n({type:Number})],i.prototype,"offset",2),r([n({type:Boolean,reflect:!0})],i.prototype,"open",1),r([n()],i.prototype,"placement",2),r([n({attribute:"receives-focus"})],i.prototype,"receivesFocus",2),r([g("slot")],i.prototype,"slotEl",2),r([P()],i.prototype,"state",1),r([n({type:Number,attribute:"tip-padding"})],i.prototype,"tipPadding",2),r([n()],i.prototype,"trigger",2),r([n({attribute:!1})],i.prototype,"triggerElement",2),r([n({attribute:!1})],i.prototype,"triggerInteraction",2),r([n()],i.prototype,"type",2);export let Overlay=i;
|
|
33
33
|
//# sourceMappingURL=Overlay.js.map
|
package/src/Overlay.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["Overlay.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2023 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n html,\n PropertyValues,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n ElementResolutionController,\n elementResolverUpdatedSymbol,\n} from '@spectrum-web-components/reactive-controllers/src/ElementResolution.js';\nimport {\n ifDefined,\n StyleInfo,\n styleMap,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport type {\n OpenableElement,\n OverlayState,\n OverlayTypes,\n Placement,\n TriggerInteraction,\n} from './overlay-types.js';\nimport { AbstractOverlay, nextFrame } from './AbstractOverlay.js';\nimport { OverlayDialog } from './OverlayDialog.js';\nimport { OverlayPopover } from './OverlayPopover.js';\nimport { OverlayNoPopover } from './OverlayNoPopover.js';\nimport { overlayStack } from './OverlayStack.js';\nimport { VirtualTrigger } from './VirtualTrigger.js';\nimport { PlacementController } from './PlacementController.js';\nimport { ClickController } from './ClickController.js';\nimport { HoverController } from './HoverController.js';\nimport { LongpressController } from './LongpressController.js';\nexport { LONGPRESS_INSTRUCTIONS } from './LongpressController.js';\nimport {\n removeSlottableRequest,\n SlottableRequestEvent,\n} from './slottable-request-event.js';\n\nimport styles from './overlay.css.js';\n\nconst supportsPopover = 'showPopover' in document.createElement('div');\n\nlet OverlayFeatures = OverlayDialog(AbstractOverlay);\n/* c8 ignore next 2 */\nif (supportsPopover) {\n OverlayFeatures = OverlayPopover(OverlayFeatures);\n} else {\n OverlayFeatures = OverlayNoPopover(OverlayFeatures);\n}\n\nexport const strategies = {\n click: ClickController,\n longpress: LongpressController,\n hover: HoverController,\n};\n\n/**\n * @element sp-overlay\n *\n * @fires sp-opened - announces that an overlay has completed any entry animations\n * @fires sp-closed - announce that an overlay has compelted any exit animations\n */\nexport class Overlay extends OverlayFeatures {\n static override styles = [styles];\n\n /**\n * An Overlay that is `delayed` will wait until a warm-up period of 1000ms\n * has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened,\n * a cooldown period of 1000ms will begin. Once the cooldown has completed,\n * the next Overlay to be opened will be subject to the warm-up period if\n * provided that option.\n */\n @property({ type: Boolean })\n override get delayed(): boolean {\n return this.elements.at(-1)?.hasAttribute('delayed') || this._delayed;\n }\n\n override set delayed(delayed: boolean) {\n this._delayed = delayed;\n }\n\n private _delayed = false;\n\n @query('.dialog')\n override dialogEl!: HTMLDialogElement & {\n showPopover(): void;\n hidePopover(): void;\n };\n\n /**\n * Whether the overlay is currently functional or not\n */\n @property({ type: Boolean })\n override get disabled(): boolean {\n return this._disabled;\n }\n\n override set disabled(disabled: boolean) {\n this._disabled = disabled;\n if (disabled) {\n this.strategy?.abort();\n this.wasOpen = this.open;\n this.open = false;\n } else {\n this.bindEvents();\n this.open = this.open || this.wasOpen;\n this.wasOpen = false;\n }\n }\n\n private _disabled = false;\n\n @queryAssignedElements({\n flatten: true,\n selector: ':not([slot=\"longpress-describedby-descriptor\"], slot)', // gather only elements slotted into the default slot\n })\n override elements!: OpenableElement[];\n\n public parentOverlayToForceClose?: Overlay;\n\n private get hasNonVirtualTrigger(): boolean {\n return (\n !!this.triggerElement &&\n !(this.triggerElement instanceof VirtualTrigger)\n );\n }\n\n /**\n * The `offset` property accepts either a single number, to\n * define the offset of the Overlay along the main axis from\n * the trigger, or 2-tuple, to define the offset along the\n * main axis and the cross axis. This option has no effect\n * when there is no trigger element.\n */\n @property({ type: Number })\n override offset: number | [number, number] = 0;\n\n protected override get placementController(): PlacementController {\n if (!this._placementController) {\n this._placementController = new PlacementController(this);\n }\n return this._placementController;\n }\n\n /**\n * Whether the Overlay is projected onto the \"top layer\" or not.\n */\n @property({ type: Boolean, reflect: true })\n override get open(): boolean {\n return this._open;\n }\n\n override set open(open: boolean) {\n // Don't respond when disabled.\n if (open && this.disabled) return;\n // Don't respond when state not dirty\n if (open === this.open) return;\n // Don't respond when you're in the shadow on a longpress\n // Shadow occurs when the first \"click\" would normally close the popover\n if (this.strategy?.activelyOpening && !open) return;\n this._open = open;\n if (this.open) {\n Overlay.openCount += 1;\n }\n this.requestUpdate('open', !this.open);\n if (this.open) {\n this.requestSlottable();\n }\n }\n\n private _open = false;\n\n static openCount = 1;\n\n /**\n * Instruct the Overlay where to place itself in\n * relationship to the trigger element.\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n */\n @property()\n override placement?: Placement;\n\n /**\n * Whether to pass focus to the overlay once opened, or\n * to the appropriate value based on the \"type\" of the overlay\n * when set to `\"auto\"`.\n *\n */\n @property({ attribute: 'receives-focus' })\n override receivesFocus: 'true' | 'false' | 'auto' = 'auto';\n\n @query('slot')\n slotEl!: HTMLSlotElement;\n\n @state()\n override get state(): OverlayState {\n return this._state;\n }\n\n override set state(state) {\n if (state === this.state) return;\n const oldState = this.state;\n this._state = state;\n if (this.state === 'opened' || this.state === 'closed') {\n this.strategy?.shouldCompleteOpen();\n }\n this.requestUpdate('state', oldState);\n }\n\n override _state: OverlayState = 'closed';\n\n public strategy?: ClickController | HoverController | LongpressController;\n\n @property({ type: Number, attribute: 'tip-padding' })\n tipPadding?: number;\n\n /**\n * An optional ID reference for the trigger element combined with the optional\n * interaction (click | hover | longpress) by which the overlay shold open\n * the overlay with an `@`: e.g. `trigger@click` opens the overlay when an\n * element with the ID \"trigger\" is clicked.\n */\n @property()\n trigger?: string;\n\n /**\n * An element reference for the trigger element that the overlay should relate to.\n */\n @property({ attribute: false })\n override triggerElement: HTMLElement | VirtualTrigger | null = null;\n\n /**\n * The specific interaction to listen for on the `triggerElement` to open the overlay.\n */\n @property({ attribute: false })\n triggerInteraction?: TriggerInteraction;\n\n /**\n * Configures the open/close heuristics of the Overlay.\n * @type {\"auto\" | \"hint\" | \"manual\" | \"modal\" | \"page\"}\n */\n @property()\n override type: OverlayTypes = 'auto';\n\n protected wasOpen = false;\n\n protected override get elementResolver(): ElementResolutionController {\n if (!this._elementResolver) {\n this._elementResolver = new ElementResolutionController(this);\n }\n return this._elementResolver;\n }\n\n private get usesDialog(): boolean {\n return this.type === 'modal' || this.type === 'page';\n }\n\n private get popoverValue(): 'auto' | 'manual' | undefined {\n const hasPopoverAttribute = 'popover' in this;\n if (!hasPopoverAttribute) {\n return undefined;\n }\n /* c8 ignore next 9 */\n switch (this.type) {\n case 'modal':\n case 'page':\n return undefined;\n case 'hint':\n return 'manual';\n default:\n return this.type;\n }\n }\n\n protected get requiresPosition(): boolean {\n // Do not position \"page\" overlays as they should block the entire UI.\n if (this.type === 'page' || !this.open) return false;\n // Do not position content without a trigger element, what would you position it in relation to?\n // Do not automatically position content, unless it is a \"hint\".\n if (!this.triggerElement || (!this.placement && this.type !== 'hint'))\n return false;\n return true;\n }\n\n protected override managePosition(): void {\n if (!this.requiresPosition || !this.open) return;\n\n const offset = this.offset || 0;\n const trigger = this.triggerElement as HTMLElement;\n const placement = (this.placement as Placement) || 'right';\n const tipPadding = this.tipPadding;\n\n this.placementController.placeOverlay(this.dialogEl, {\n offset,\n placement,\n tipPadding,\n trigger,\n type: this.type,\n });\n }\n\n protected override async managePopoverOpen(): Promise<void> {\n super.managePopoverOpen();\n const targetOpenState = this.open;\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n await this.manageDelay(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.ensureOnDOM(targetOpenState);\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n const focusEl = await this.makeTransition(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.applyFocus(targetOpenState, focusEl);\n }\n\n protected override async applyFocus(\n targetOpenState: boolean,\n focusEl: HTMLElement | null\n ): Promise<void> {\n // Do not move focus when explicitly told not to\n // and when the Overlay is a \"hint\"\n if (this.receivesFocus === 'false' || this.type === 'hint') {\n return;\n }\n\n await nextFrame();\n await nextFrame();\n if (targetOpenState === this.open && !this.open) {\n if (\n this.hasNonVirtualTrigger &&\n this.contains((this.getRootNode() as Document).activeElement)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n return;\n }\n focusEl?.focus();\n }\n\n protected override returnFocus(): void {\n if (this.open || this.type === 'hint') return;\n\n // If the focus remains inside of the overlay or\n // a slotted descendent of the overlay you need to return\n // focus back to the trigger.\n const getAncestors = (): HTMLElement[] => {\n const ancestors: HTMLElement[] = [];\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n let currentNode = document.activeElement;\n while (currentNode?.shadowRoot?.activeElement) {\n currentNode = currentNode.shadowRoot.activeElement;\n }\n while (currentNode) {\n const ancestor =\n currentNode.assignedSlot ||\n currentNode.parentElement ||\n (currentNode.getRootNode() as ShadowRoot)?.host;\n if (ancestor) {\n ancestors.push(ancestor as HTMLElement);\n }\n currentNode = ancestor;\n }\n return ancestors;\n };\n if (\n (this.triggerElement as HTMLElement)?.focus &&\n (this.contains((this.getRootNode() as Document).activeElement) ||\n getAncestors().includes(this) ||\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n document.activeElement === document.body)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n }\n\n private closeOnFocusOut = (event: FocusEvent): void => {\n // If you don't know where the focus went, we can't do anyting here.\n if (!event.relatedTarget) {\n // this.open = false;\n return;\n }\n const relationEvent = new Event('overlay-relation-query', {\n bubbles: true,\n composed: true,\n });\n event.relatedTarget.addEventListener(\n relationEvent.type,\n (event: Event) => {\n if (!event.composedPath().includes(this)) {\n this.open = false;\n }\n }\n );\n event.relatedTarget.dispatchEvent(relationEvent);\n };\n\n protected async manageOpen(oldOpen: boolean): Promise<void> {\n // The `.showPopover()` and `.showModal()` events will error on content that is not connected to the DOM.\n // Prevent from entering the manage workflow in order to avoid this.\n if (!this.isConnected && this.open) return;\n\n if (!this.hasUpdated) {\n await this.updateComplete;\n }\n\n if (this.open) {\n overlayStack.add(this);\n if (this.willPreventClose) {\n document.addEventListener(\n 'pointerup',\n () => {\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n false\n );\n this.willPreventClose = false;\n },\n { once: true }\n );\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n true\n );\n }\n } else {\n if (oldOpen) {\n this.dispose();\n }\n overlayStack.remove(this);\n }\n if (this.open && this.state !== 'opened') {\n this.state = 'opening';\n } else if (!this.open && this.state !== 'closed') {\n this.state = 'closing';\n }\n\n if (this.usesDialog) {\n this.manageDialogOpen();\n } else {\n this.managePopoverOpen();\n }\n if (this.type === 'auto') {\n const listenerRoot = this.getRootNode() as Document;\n if (this.open) {\n listenerRoot.addEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n } else {\n listenerRoot.removeEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n }\n }\n }\n\n protected bindEvents(): void {\n this.strategy?.abort();\n this.strategy = undefined;\n if (!this.hasNonVirtualTrigger) return;\n if (!this.triggerInteraction) return;\n this.strategy = new strategies[this.triggerInteraction](\n this,\n this.triggerElement as HTMLElement\n );\n }\n\n protected handleBeforetoggle(event: Event & { newState: string }): void {\n if (event.newState !== 'open') {\n this.handleBrowserClose();\n }\n }\n\n protected handleBrowserClose(): void {\n if (!this.strategy?.activelyOpening) {\n this.open = false;\n return;\n }\n this.manuallyKeepOpen();\n }\n\n public override manuallyKeepOpen(): void {\n this.open = true;\n this.placementController.allowPlacementUpdate = true;\n this.manageOpen(false);\n }\n\n protected handleSlotchange(): void {\n if (!this.elements.length) {\n this.strategy?.releaseDescription();\n } else if (this.hasNonVirtualTrigger) {\n this.strategy?.prepareDescription(\n this.triggerElement as HTMLElement\n );\n }\n }\n\n public shouldPreventClose(): boolean {\n const shouldPreventClose = this.willPreventClose;\n this.willPreventClose = false;\n return shouldPreventClose;\n }\n\n protected override requestSlottable(): void {\n if (!this.open) {\n document.body.offsetHeight;\n }\n this.dispatchEvent(\n new SlottableRequestEvent(\n 'overlay-content',\n this.open ? {} : removeSlottableRequest\n )\n );\n }\n\n override willUpdate(changes: PropertyValues): void {\n if (!this.hasAttribute('id')) {\n this.setAttribute(\n 'id',\n `${this.tagName.toLowerCase()}-${randomID()}`\n );\n }\n if (\n changes.has('open') &&\n (typeof changes.get('open') !== 'undefined' || this.open)\n ) {\n this.manageOpen(changes.get('open'));\n }\n if (changes.has('trigger')) {\n const [id, interaction] = this.trigger?.split('@') || [];\n this.elementResolver.selector = id ? `#${id}` : '';\n this.triggerInteraction = interaction as\n | 'click'\n | 'longpress'\n | 'hover'\n | undefined;\n }\n // Merge multiple possible calls to `bindEvents()`.\n let oldTrigger: HTMLElement | false | undefined = false;\n if (changes.has(elementResolverUpdatedSymbol)) {\n oldTrigger = this.triggerElement as HTMLElement;\n this.triggerElement = this.elementResolver.element;\n }\n if (changes.has('triggerElement')) {\n oldTrigger = changes.get('triggerElement');\n }\n if (oldTrigger !== false) {\n this.bindEvents();\n }\n }\n\n protected override updated(changes: PropertyValues): void {\n super.updated(changes);\n if (changes.has('placement')) {\n if (this.placement) {\n this.dialogEl.setAttribute('actual-placement', this.placement);\n } else {\n this.dialogEl.removeAttribute('actual-placement');\n }\n if (this.open && typeof changes.get('placement') !== 'undefined') {\n this.placementController.resetOverlayPosition();\n }\n }\n if (\n changes.has('state') &&\n this.state === 'closed' &&\n typeof changes.get('state') !== 'undefined'\n ) {\n this.placementController.clearOverlayPosition();\n }\n }\n\n protected renderContent(): TemplateResult {\n return html`\n <slot @slotchange=${this.handleSlotchange}></slot>\n `;\n }\n\n private get dialogStyleMap(): StyleInfo {\n return {\n '--swc-overlay-open-count': Overlay.openCount.toString(),\n };\n }\n\n protected renderDialog(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <dialog\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n style=${styleMap(this.dialogStyleMap)}\n @close=${this.handleBrowserClose}\n @cancel=${this.handleBrowserClose}\n @beforetoggle=${this.handleBeforetoggle}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </dialog>\n `;\n }\n\n protected renderPopover(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <div\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n popover=${ifDefined(this.popoverValue)}\n style=${styleMap(this.dialogStyleMap)}\n @beforetoggle=${this.handleBeforetoggle}\n @close=${this.handleBrowserClose}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </div>\n `;\n }\n\n public override render(): TemplateResult {\n const isDialog = this.type === 'modal' || this.type === 'page';\n return html`\n ${isDialog ? this.renderDialog() : this.renderPopover()}\n <slot name=\"longpress-describedby-descriptor\"></slot>\n `;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('close', () => {\n this.open = false;\n });\n if (this.hasUpdated) {\n this.bindEvents();\n }\n }\n\n override disconnectedCallback(): void {\n this.strategy?.releaseDescription();\n this.open = false;\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
-
"mappings": "qNAWA,OACI,QAAAA,MAGG,gCACP,OACI,YAAAC,EACA,SAAAC,EACA,yBAAAC,EACA,SAAAC,MACG,kDACP,OACI,+BAAAC,EACA,gCAAAC,MACG,yEACP,OACI,aAAAC,EAEA,YAAAC,MACG,kDACP,OAAS,YAAAC,MAAgB,mDASzB,OAAS,mBAAAC,EAAiB,aAAAC,MAAiB,uBAC3C,OAAS,iBAAAC,MAAqB,qBAC9B,OAAS,kBAAAC,MAAsB,sBAC/B,OAAS,oBAAAC,MAAwB,wBACjC,OAAS,gBAAAC,MAAoB,oBAC7B,OAAS,kBAAAC,MAAsB,sBAC/B,OAAS,uBAAAC,MAA2B,2BACpC,OAAS,mBAAAC,MAAuB,uBAChC,OAAS,mBAAAC,MAAuB,uBAChC,OAAS,uBAAAC,MAA2B,2BACpC,OAAS,2BAA8B,2BACvC,OACI,0BAAAC,EACA,yBAAAC,MACG,+BAEP,OAAOC,MAAY,mBAEnB,MAAMC,EAAkB,gBAAiB,SAAS,cAAc,KAAK,EAErE,IAAIC,EAAkBb,EAAcF,CAAe,EAE/Cc,EACAC,EAAkBZ,EAAeY,CAAe,EAEhDA,EAAkBX,EAAiBW,CAAe,EAG/C,aAAM,WAAa,CACtB,MAAOP,EACP,UAAWE,EACX,MAAOD,CACX,
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2023 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n html,\n PropertyValues,\n TemplateResult,\n} from '@spectrum-web-components/base';\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from '@spectrum-web-components/base/src/decorators.js';\nimport {\n ElementResolutionController,\n elementResolverUpdatedSymbol,\n} from '@spectrum-web-components/reactive-controllers/src/ElementResolution.js';\nimport {\n ifDefined,\n StyleInfo,\n styleMap,\n} from '@spectrum-web-components/base/src/directives.js';\nimport { randomID } from '@spectrum-web-components/shared/src/random-id.js';\n\nimport type {\n OpenableElement,\n OverlayState,\n OverlayTypes,\n Placement,\n TriggerInteraction,\n} from './overlay-types.js';\nimport { AbstractOverlay, nextFrame } from './AbstractOverlay.js';\nimport { OverlayDialog } from './OverlayDialog.js';\nimport { OverlayPopover } from './OverlayPopover.js';\nimport { OverlayNoPopover } from './OverlayNoPopover.js';\nimport { overlayStack } from './OverlayStack.js';\nimport { VirtualTrigger } from './VirtualTrigger.js';\nimport { PlacementController } from './PlacementController.js';\nimport { ClickController } from './ClickController.js';\nimport { HoverController } from './HoverController.js';\nimport { LongpressController } from './LongpressController.js';\nexport { LONGPRESS_INSTRUCTIONS } from './LongpressController.js';\nimport {\n removeSlottableRequest,\n SlottableRequestEvent,\n} from './slottable-request-event.js';\n\nimport styles from './overlay.css.js';\n\nconst supportsPopover = 'showPopover' in document.createElement('div');\n\nlet OverlayFeatures = OverlayDialog(AbstractOverlay);\n/* c8 ignore next 2 */\nif (supportsPopover) {\n OverlayFeatures = OverlayPopover(OverlayFeatures);\n} else {\n OverlayFeatures = OverlayNoPopover(OverlayFeatures);\n}\n\nexport const strategies = {\n click: ClickController,\n longpress: LongpressController,\n hover: HoverController,\n};\n\n/**\n * @element sp-overlay\n *\n * @fires sp-opened - announces that an overlay has completed any entry animations\n * @fires sp-closed - announce that an overlay has compelted any exit animations\n * @fires slottable-request - requests to add or remove slottable content\n */\nexport class Overlay extends OverlayFeatures {\n static override styles = [styles];\n\n /**\n * An Overlay that is `delayed` will wait until a warm-up period of 1000ms\n * has completed before opening. Once the warmup period has completed, all\n * subsequent Overlays will open immediately. When no Overlays are opened,\n * a cooldown period of 1000ms will begin. Once the cooldown has completed,\n * the next Overlay to be opened will be subject to the warm-up period if\n * provided that option.\n */\n @property({ type: Boolean })\n override get delayed(): boolean {\n return this.elements.at(-1)?.hasAttribute('delayed') || this._delayed;\n }\n\n override set delayed(delayed: boolean) {\n this._delayed = delayed;\n }\n\n private _delayed = false;\n\n @query('.dialog')\n override dialogEl!: HTMLDialogElement & {\n showPopover(): void;\n hidePopover(): void;\n };\n\n /**\n * Whether the overlay is currently functional or not\n */\n @property({ type: Boolean })\n override get disabled(): boolean {\n return this._disabled;\n }\n\n override set disabled(disabled: boolean) {\n this._disabled = disabled;\n if (disabled) {\n this.strategy?.abort();\n this.wasOpen = this.open;\n this.open = false;\n } else {\n this.bindEvents();\n this.open = this.open || this.wasOpen;\n this.wasOpen = false;\n }\n }\n\n private _disabled = false;\n\n @queryAssignedElements({\n flatten: true,\n selector: ':not([slot=\"longpress-describedby-descriptor\"], slot)', // gather only elements slotted into the default slot\n })\n override elements!: OpenableElement[];\n\n public parentOverlayToForceClose?: Overlay;\n\n private get hasNonVirtualTrigger(): boolean {\n return (\n !!this.triggerElement &&\n !(this.triggerElement instanceof VirtualTrigger)\n );\n }\n\n /**\n * The `offset` property accepts either a single number, to\n * define the offset of the Overlay along the main axis from\n * the trigger, or 2-tuple, to define the offset along the\n * main axis and the cross axis. This option has no effect\n * when there is no trigger element.\n */\n @property({ type: Number })\n override offset: number | [number, number] = 0;\n\n protected override get placementController(): PlacementController {\n if (!this._placementController) {\n this._placementController = new PlacementController(this);\n }\n return this._placementController;\n }\n\n /**\n * Whether the Overlay is projected onto the \"top layer\" or not.\n */\n @property({ type: Boolean, reflect: true })\n override get open(): boolean {\n return this._open;\n }\n\n override set open(open: boolean) {\n // Don't respond when disabled.\n if (open && this.disabled) return;\n // Don't respond when state not dirty\n if (open === this.open) return;\n // Don't respond when you're in the shadow on a longpress\n // Shadow occurs when the first \"click\" would normally close the popover\n if (this.strategy?.activelyOpening && !open) return;\n this._open = open;\n if (this.open) {\n Overlay.openCount += 1;\n }\n this.requestUpdate('open', !this.open);\n if (this.open) {\n this.requestSlottable();\n }\n }\n\n private _open = false;\n\n static openCount = 1;\n\n /**\n * Instruct the Overlay where to place itself in\n * relationship to the trigger element.\n * @type {\"top\" | \"top-start\" | \"top-end\" | \"right\" | \"right-start\" | \"right-end\" | \"bottom\" | \"bottom-start\" | \"bottom-end\" | \"left\" | \"left-start\" | \"left-end\"}\n */\n @property()\n override placement?: Placement;\n\n /**\n * The state in which the last `request-slottable` event was dispatched.\n * Do not allow overlays from dispatching the same state twice in a row.\n */\n private lastRequestSlottableState = false;\n\n /**\n * Whether to pass focus to the overlay once opened, or\n * to the appropriate value based on the \"type\" of the overlay\n * when set to `\"auto\"`.\n *\n */\n @property({ attribute: 'receives-focus' })\n override receivesFocus: 'true' | 'false' | 'auto' = 'auto';\n\n @query('slot')\n slotEl!: HTMLSlotElement;\n\n @state()\n override get state(): OverlayState {\n return this._state;\n }\n\n override set state(state) {\n if (state === this.state) return;\n const oldState = this.state;\n this._state = state;\n if (this.state === 'opened' || this.state === 'closed') {\n this.strategy?.shouldCompleteOpen();\n }\n this.requestUpdate('state', oldState);\n }\n\n override _state: OverlayState = 'closed';\n\n public strategy?: ClickController | HoverController | LongpressController;\n\n @property({ type: Number, attribute: 'tip-padding' })\n tipPadding?: number;\n\n /**\n * An optional ID reference for the trigger element combined with the optional\n * interaction (click | hover | longpress) by which the overlay shold open\n * the overlay with an `@`: e.g. `trigger@click` opens the overlay when an\n * element with the ID \"trigger\" is clicked.\n */\n @property()\n trigger?: string;\n\n /**\n * An element reference for the trigger element that the overlay should relate to.\n */\n @property({ attribute: false })\n override triggerElement: HTMLElement | VirtualTrigger | null = null;\n\n /**\n * The specific interaction to listen for on the `triggerElement` to open the overlay.\n */\n @property({ attribute: false })\n triggerInteraction?: TriggerInteraction;\n\n /**\n * Configures the open/close heuristics of the Overlay.\n * @type {\"auto\" | \"hint\" | \"manual\" | \"modal\" | \"page\"}\n */\n @property()\n override type: OverlayTypes = 'auto';\n\n protected wasOpen = false;\n\n protected override get elementResolver(): ElementResolutionController {\n if (!this._elementResolver) {\n this._elementResolver = new ElementResolutionController(this);\n }\n return this._elementResolver;\n }\n\n private get usesDialog(): boolean {\n return this.type === 'modal' || this.type === 'page';\n }\n\n private get popoverValue(): 'auto' | 'manual' | undefined {\n const hasPopoverAttribute = 'popover' in this;\n if (!hasPopoverAttribute) {\n return undefined;\n }\n /* c8 ignore next 9 */\n switch (this.type) {\n case 'modal':\n case 'page':\n return undefined;\n case 'hint':\n return 'manual';\n default:\n return this.type;\n }\n }\n\n protected get requiresPosition(): boolean {\n // Do not position \"page\" overlays as they should block the entire UI.\n if (this.type === 'page' || !this.open) return false;\n // Do not position content without a trigger element, what would you position it in relation to?\n // Do not automatically position content, unless it is a \"hint\".\n if (!this.triggerElement || (!this.placement && this.type !== 'hint'))\n return false;\n return true;\n }\n\n protected override managePosition(): void {\n if (!this.requiresPosition || !this.open) return;\n\n const offset = this.offset || 0;\n const trigger = this.triggerElement as HTMLElement;\n const placement = (this.placement as Placement) || 'right';\n const tipPadding = this.tipPadding;\n\n this.placementController.placeOverlay(this.dialogEl, {\n offset,\n placement,\n tipPadding,\n trigger,\n type: this.type,\n });\n }\n\n protected override async managePopoverOpen(): Promise<void> {\n super.managePopoverOpen();\n const targetOpenState = this.open;\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n await this.manageDelay(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.ensureOnDOM(targetOpenState);\n /* c8 ignore next 3 */\n if (this.open !== targetOpenState) {\n return;\n }\n const focusEl = await this.makeTransition(targetOpenState);\n if (this.open !== targetOpenState) {\n return;\n }\n await this.applyFocus(targetOpenState, focusEl);\n }\n\n protected override async applyFocus(\n targetOpenState: boolean,\n focusEl: HTMLElement | null\n ): Promise<void> {\n // Do not move focus when explicitly told not to\n // and when the Overlay is a \"hint\"\n if (this.receivesFocus === 'false' || this.type === 'hint') {\n return;\n }\n\n await nextFrame();\n await nextFrame();\n if (targetOpenState === this.open && !this.open) {\n if (\n this.hasNonVirtualTrigger &&\n this.contains((this.getRootNode() as Document).activeElement)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n return;\n }\n focusEl?.focus();\n }\n\n protected override returnFocus(): void {\n if (this.open || this.type === 'hint') return;\n\n // If the focus remains inside of the overlay or\n // a slotted descendent of the overlay you need to return\n // focus back to the trigger.\n const getAncestors = (): HTMLElement[] => {\n const ancestors: HTMLElement[] = [];\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n let currentNode = document.activeElement;\n while (currentNode?.shadowRoot?.activeElement) {\n currentNode = currentNode.shadowRoot.activeElement;\n }\n while (currentNode) {\n const ancestor =\n currentNode.assignedSlot ||\n currentNode.parentElement ||\n (currentNode.getRootNode() as ShadowRoot)?.host;\n if (ancestor) {\n ancestors.push(ancestor as HTMLElement);\n }\n currentNode = ancestor;\n }\n return ancestors;\n };\n if (\n (this.triggerElement as HTMLElement)?.focus &&\n (this.contains((this.getRootNode() as Document).activeElement) ||\n getAncestors().includes(this) ||\n // eslint-disable-next-line @spectrum-web-components/document-active-element\n document.activeElement === document.body)\n ) {\n (this.triggerElement as HTMLElement).focus();\n }\n }\n\n private closeOnFocusOut = (event: FocusEvent): void => {\n // If you don't know where the focus went, we can't do anyting here.\n if (!event.relatedTarget) {\n // this.open = false;\n return;\n }\n const relationEvent = new Event('overlay-relation-query', {\n bubbles: true,\n composed: true,\n });\n event.relatedTarget.addEventListener(\n relationEvent.type,\n (event: Event) => {\n if (!event.composedPath().includes(this)) {\n this.open = false;\n }\n }\n );\n event.relatedTarget.dispatchEvent(relationEvent);\n };\n\n protected async manageOpen(oldOpen: boolean): Promise<void> {\n // The `.showPopover()` and `.showModal()` events will error on content that is not connected to the DOM.\n // Prevent from entering the manage workflow in order to avoid this.\n if (!this.isConnected && this.open) return;\n\n if (!this.hasUpdated) {\n await this.updateComplete;\n }\n\n if (this.open) {\n overlayStack.add(this);\n if (this.willPreventClose) {\n document.addEventListener(\n 'pointerup',\n () => {\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n false\n );\n this.willPreventClose = false;\n },\n { once: true }\n );\n this.dialogEl.classList.toggle(\n 'not-immediately-closable',\n true\n );\n }\n } else {\n if (oldOpen) {\n this.dispose();\n }\n overlayStack.remove(this);\n }\n if (this.open && this.state !== 'opened') {\n this.state = 'opening';\n } else if (!this.open && this.state !== 'closed') {\n this.state = 'closing';\n }\n\n if (this.usesDialog) {\n this.manageDialogOpen();\n } else {\n this.managePopoverOpen();\n }\n if (this.type === 'auto') {\n const listenerRoot = this.getRootNode() as Document;\n if (this.open) {\n listenerRoot.addEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n } else {\n listenerRoot.removeEventListener(\n 'focusout',\n this.closeOnFocusOut,\n { capture: true }\n );\n }\n }\n }\n\n protected bindEvents(): void {\n this.strategy?.abort();\n this.strategy = undefined;\n if (!this.hasNonVirtualTrigger) return;\n if (!this.triggerInteraction) return;\n this.strategy = new strategies[this.triggerInteraction](\n this,\n this.triggerElement as HTMLElement\n );\n }\n\n protected handleBeforetoggle(event: Event & { newState: string }): void {\n if (event.newState !== 'open') {\n this.handleBrowserClose();\n }\n }\n\n protected handleBrowserClose(): void {\n if (!this.strategy?.activelyOpening) {\n this.open = false;\n return;\n }\n this.manuallyKeepOpen();\n }\n\n public override manuallyKeepOpen(): void {\n this.open = true;\n this.placementController.allowPlacementUpdate = true;\n this.manageOpen(false);\n }\n\n protected handleSlotchange(): void {\n if (!this.elements.length) {\n this.strategy?.releaseDescription();\n } else if (this.hasNonVirtualTrigger) {\n this.strategy?.prepareDescription(\n this.triggerElement as HTMLElement\n );\n }\n }\n\n public shouldPreventClose(): boolean {\n const shouldPreventClose = this.willPreventClose;\n this.willPreventClose = false;\n return shouldPreventClose;\n }\n\n protected override requestSlottable(): void {\n if (this.lastRequestSlottableState === this.open) {\n return;\n }\n if (!this.open) {\n document.body.offsetHeight;\n }\n /**\n * @ignore\n */\n this.dispatchEvent(\n new SlottableRequestEvent(\n 'overlay-content',\n this.open ? {} : removeSlottableRequest\n )\n );\n this.lastRequestSlottableState = this.open;\n }\n\n override willUpdate(changes: PropertyValues): void {\n if (!this.hasAttribute('id')) {\n this.setAttribute(\n 'id',\n `${this.tagName.toLowerCase()}-${randomID()}`\n );\n }\n if (\n changes.has('open') &&\n (typeof changes.get('open') !== 'undefined' || this.open)\n ) {\n this.manageOpen(changes.get('open'));\n }\n if (changes.has('trigger')) {\n const [id, interaction] = this.trigger?.split('@') || [];\n this.elementResolver.selector = id ? `#${id}` : '';\n this.triggerInteraction = interaction as\n | 'click'\n | 'longpress'\n | 'hover'\n | undefined;\n }\n // Merge multiple possible calls to `bindEvents()`.\n let oldTrigger: HTMLElement | false | undefined = false;\n if (changes.has(elementResolverUpdatedSymbol)) {\n oldTrigger = this.triggerElement as HTMLElement;\n this.triggerElement = this.elementResolver.element;\n }\n if (changes.has('triggerElement')) {\n oldTrigger = changes.get('triggerElement');\n }\n if (oldTrigger !== false) {\n this.bindEvents();\n }\n }\n\n protected override updated(changes: PropertyValues): void {\n super.updated(changes);\n if (changes.has('placement')) {\n if (this.placement) {\n this.dialogEl.setAttribute('actual-placement', this.placement);\n } else {\n this.dialogEl.removeAttribute('actual-placement');\n }\n if (this.open && typeof changes.get('placement') !== 'undefined') {\n this.placementController.resetOverlayPosition();\n }\n }\n if (\n changes.has('state') &&\n this.state === 'closed' &&\n typeof changes.get('state') !== 'undefined'\n ) {\n this.placementController.clearOverlayPosition();\n }\n }\n\n protected renderContent(): TemplateResult {\n return html`\n <slot @slotchange=${this.handleSlotchange}></slot>\n `;\n }\n\n private get dialogStyleMap(): StyleInfo {\n return {\n '--swc-overlay-open-count': Overlay.openCount.toString(),\n };\n }\n\n protected renderDialog(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <dialog\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n style=${styleMap(this.dialogStyleMap)}\n @close=${this.handleBrowserClose}\n @cancel=${this.handleBrowserClose}\n @beforetoggle=${this.handleBeforetoggle}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </dialog>\n `;\n }\n\n protected renderPopover(): TemplateResult {\n /**\n * `--swc-overlay-open-count` is applied to mimic the single stack\n * nature of the top layer in browsers that do not yet support it.\n *\n * The value should always be the full number of overlays ever opened\n * which will be added to `--swc-overlay-z-index-base` which can be\n * provided by a consuming developer but defaults to 1000 to beat as\n * much stacking as possible durring fallback delivery.\n **/\n return html`\n <div\n class=\"dialog\"\n part=\"dialog\"\n placement=${ifDefined(\n this.requiresPosition\n ? this.placement || 'right'\n : undefined\n )}\n popover=${ifDefined(this.popoverValue)}\n style=${styleMap(this.dialogStyleMap)}\n @beforetoggle=${this.handleBeforetoggle}\n @close=${this.handleBrowserClose}\n ?is-visible=${this.state !== 'closed'}\n >\n ${this.renderContent()}\n </div>\n `;\n }\n\n public override render(): TemplateResult {\n const isDialog = this.type === 'modal' || this.type === 'page';\n return html`\n ${isDialog ? this.renderDialog() : this.renderPopover()}\n <slot name=\"longpress-describedby-descriptor\"></slot>\n `;\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('close', () => {\n this.open = false;\n });\n if (this.hasUpdated) {\n this.bindEvents();\n }\n }\n\n override disconnectedCallback(): void {\n this.strategy?.releaseDescription();\n this.open = false;\n super.disconnectedCallback();\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["html", "property", "query", "queryAssignedElements", "state", "ElementResolutionController", "elementResolverUpdatedSymbol", "ifDefined", "styleMap", "randomID", "AbstractOverlay", "nextFrame", "OverlayDialog", "OverlayPopover", "OverlayNoPopover", "overlayStack", "VirtualTrigger", "PlacementController", "ClickController", "HoverController", "LongpressController", "removeSlottableRequest", "SlottableRequestEvent", "styles", "supportsPopover", "OverlayFeatures", "_Overlay", "event", "relationEvent", "_a", "delayed", "disabled", "open", "oldState", "offset", "trigger", "placement", "tipPadding", "targetOpenState", "focusEl", "getAncestors", "_b", "ancestors", "currentNode", "ancestor", "oldOpen", "listenerRoot", "shouldPreventClose", "changes", "id", "interaction", "oldTrigger", "isDialog", "__decorateClass"]
|
|
7
7
|
}
|
|
@@ -237,10 +237,15 @@ describe("Overlay Trigger - Hover", () => {
|
|
|
237
237
|
`)()
|
|
238
238
|
);
|
|
239
239
|
await elementUpdated(el);
|
|
240
|
+
const input = document.createElement("input");
|
|
241
|
+
el.insertAdjacentElement("beforebegin", input);
|
|
240
242
|
expect(el.open).to.be.undefined;
|
|
241
243
|
const trigger = el.querySelector('[slot="trigger"]');
|
|
242
244
|
const opened = oneEvent(el, "sp-opened");
|
|
243
|
-
|
|
245
|
+
input.focus();
|
|
246
|
+
await sendKeys({
|
|
247
|
+
press: "Tab"
|
|
248
|
+
});
|
|
244
249
|
await opened;
|
|
245
250
|
expect(el.open).to.equal("hover");
|
|
246
251
|
const closed = oneEvent(el, "sp-closed");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["overlay-trigger-hover.test.ts"],
|
|
4
|
-
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n elementUpdated,\n expect,\n html,\n nextFrame,\n oneEvent,\n waitUntil,\n} from '@open-wc/testing';\nimport '@spectrum-web-components/overlay/overlay-trigger.js';\nimport '@spectrum-web-components/popover/sp-popover.js';\nimport '@spectrum-web-components/button/sp-button.js';\nimport '@spectrum-web-components/tooltip/sp-tooltip.js';\nimport '@spectrum-web-components/dialog/sp-dialog-wrapper.js';\nimport '@spectrum-web-components/action-button/sp-action-button.js';\nimport '@spectrum-web-components/icons-workflow/icons/sp-icon-magnify.js';\nimport { OverlayTrigger } from '@spectrum-web-components/overlay';\nimport { spy } from 'sinon';\nimport { ActionButton } from '@spectrum-web-components/action-button';\nimport { sendKeys } from '@web/test-runner-commands';\nimport { Button } from '@spectrum-web-components/button';\nimport '@spectrum-web-components/theme/sp-theme.js';\nimport '@spectrum-web-components/theme/src/themes.js';\nimport { TemplateResult } from '@spectrum-web-components/base';\nimport { Theme } from '@spectrum-web-components/theme';\nimport { Tooltip } from '@spectrum-web-components/tooltip';\nimport {\n fixture,\n ignoreResizeObserverLoopError,\n} from '../../../test/testing-helpers.js';\n\nignoreResizeObserverLoopError(before, after);\n\nasync function styledFixture<T extends Element>(\n story: TemplateResult\n): Promise<T> {\n const test = await fixture<Theme>(html`\n <sp-theme theme=\"spectrum\" scale=\"medium\" color=\"light\">\n ${story}\n </sp-theme>\n `);\n return test.children[0] as T;\n}\n\ndescribe('Overlay Trigger - Hover', () => {\n it('displays `hover` declaratively', async () => {\n const openedSpy = spy();\n const closedSpy = spy();\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger\n placement=\"right-start\"\n open=\"hover\"\n @sp-opened=${() => openedSpy()}\n @sp-closed=${() => closedSpy()}\n >\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n await waitUntil(\n () => openedSpy.calledOnce,\n 'hover content projected to overlay',\n { timeout: 2000 }\n );\n\n el.removeAttribute('open');\n await elementUpdated(el);\n\n await waitUntil(() => closedSpy.calledOnce, 'hover content returned', {\n timeout: 2000,\n });\n });\n describe('\"tooltip\" mouse interactions', () => {\n let el: OverlayTrigger;\n let button: ActionButton;\n let tooltip: Tooltip;\n beforeEach(async () => {\n el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-tooltip slot=\"hover-content\" tip>\n Magnify\n </sp-tooltip>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n button = el.querySelector('sp-action-button') as ActionButton;\n tooltip = el.querySelector('sp-tooltip') as Tooltip;\n });\n it('allows pointer to enter the \"tooltip\" without closing the \"tooltip\"', async () => {\n const opened = oneEvent(button, 'sp-opened');\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n await nextFrame();\n await nextFrame();\n await nextFrame();\n expect(tooltip.open).to.be.true;\n\n button.dispatchEvent(\n new MouseEvent('pointerleave', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n\n tooltip.dispatchEvent(\n new MouseEvent('pointerleave', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n const closed = oneEvent(button, 'sp-closed');\n button.dispatchEvent(\n new MouseEvent('pointerleave', {\n relatedTarget: null,\n bubbles: true,\n composed: true,\n })\n );\n await closed;\n\n expect(el.open).to.be.undefined;\n });\n it('closes the \"tooltip\" when leaving the \"tooltip\"', async () => {\n const opened = oneEvent(button, 'sp-opened');\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n button.dispatchEvent(\n new MouseEvent('pointerleave', {\n relatedTarget: tooltip,\n bubbles: true,\n composed: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n const closed = oneEvent(button, 'sp-closed');\n tooltip.dispatchEvent(\n new MouseEvent('pointerleave', {\n relatedTarget: null,\n bubbles: true,\n composed: true,\n })\n );\n await closed;\n\n expect(el.open).to.be.undefined;\n });\n });\n it('persists hover content', async () => {\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n expect(el.open).to.be.undefined;\n\n const trigger = el.querySelector('[slot=\"trigger\"]') as ActionButton;\n const opened = oneEvent(trigger, 'sp-opened');\n trigger.dispatchEvent(\n new Event('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n trigger.click();\n\n await elementUpdated(el);\n\n expect(el.open).to.equal('hover');\n });\n it('closes persistent hover content on `longpress`', async () => {\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n <sp-popover slot=\"longpress-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n expect(el.open).to.be.undefined;\n\n const trigger = el.querySelector('[slot=\"trigger\"]') as ActionButton;\n let opened = oneEvent(trigger, 'sp-opened');\n trigger.dispatchEvent(\n new Event('pointerenter', {\n bubbles: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n opened = oneEvent(trigger, 'sp-opened');\n trigger.dispatchEvent(\n new Event('longpress', {\n bubbles: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('longpress');\n });\n it('closes `hover` overlay when [type=\"modal\"]', async () => {\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\" type=\"modal\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n expect(el.open).to.be.undefined;\n\n const trigger = el.querySelector('[slot=\"trigger\"]') as ActionButton;\n const opened = oneEvent(el, 'sp-opened');\n trigger.focus();\n await opened;\n\n expect(el.open).to.equal('hover');\n\n const closed = oneEvent(el, 'sp-closed');\n trigger.blur();\n await closed;\n\n expect(el.open).to.be.undefined;\n });\n it('will not return focus to a \"modal\" parent', async () => {\n const el = await styledFixture<OverlayTrigger>(html`\n <overlay-trigger type=\"modal\">\n <sp-button slot=\"trigger\">Toggle Dialog</sp-button>\n <sp-dialog-wrapper\n slot=\"click-content\"\n headline=\"Dialog title\"\n size=\"s\"\n >\n ${[1, 2, 3, 4].map(\n (index) => html`\n <overlay-trigger>\n <sp-button slot=\"trigger\" id=\"button-${index}\">\n Button with Tooltip ${index}\n </sp-button>\n <sp-tooltip slot=\"hover-content\">\n Tooltip ${index}\n </sp-tooltip>\n </overlay-trigger>\n `\n )}\n </sp-dialog-wrapper>\n </overlay-trigger>\n `);\n await elementUpdated(el);\n\n const button = el.querySelector('sp-button') as Button;\n const dialog = el.querySelector('sp-dialog-wrapper') as HTMLElement;\n const button1 = dialog.querySelector('#button-1') as Button;\n const button2 = dialog.querySelector('#button-2') as Button;\n const button3 = dialog.querySelector('#button-3') as Button;\n await elementUpdated(button);\n await elementUpdated(dialog);\n\n let opened = oneEvent(button, 'sp-opened');\n const openedHint = oneEvent(button1, 'sp-opened');\n button.dispatchEvent(new Event('click', { bubbles: true }));\n await opened;\n await openedHint;\n\n expect(button1 === document.activeElement).to.be.true;\n\n opened = oneEvent(button2, 'sp-opened');\n sendKeys({\n press: 'Tab',\n });\n await opened;\n\n expect(button2 === document.activeElement).to.be.true;\n\n opened = oneEvent(button3, 'sp-opened');\n sendKeys({\n press: 'Tab',\n });\n await opened;\n\n expect(button3 === document.activeElement).to.be.true;\n });\n});\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/*\nCopyright 2020 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\nimport {\n elementUpdated,\n expect,\n html,\n nextFrame,\n oneEvent,\n waitUntil,\n} from '@open-wc/testing';\nimport '@spectrum-web-components/overlay/overlay-trigger.js';\nimport '@spectrum-web-components/popover/sp-popover.js';\nimport '@spectrum-web-components/button/sp-button.js';\nimport '@spectrum-web-components/tooltip/sp-tooltip.js';\nimport '@spectrum-web-components/dialog/sp-dialog-wrapper.js';\nimport '@spectrum-web-components/action-button/sp-action-button.js';\nimport '@spectrum-web-components/icons-workflow/icons/sp-icon-magnify.js';\nimport { OverlayTrigger } from '@spectrum-web-components/overlay';\nimport { spy } from 'sinon';\nimport { ActionButton } from '@spectrum-web-components/action-button';\nimport { sendKeys } from '@web/test-runner-commands';\nimport { Button } from '@spectrum-web-components/button';\nimport '@spectrum-web-components/theme/sp-theme.js';\nimport '@spectrum-web-components/theme/src/themes.js';\nimport { TemplateResult } from '@spectrum-web-components/base';\nimport { Theme } from '@spectrum-web-components/theme';\nimport { Tooltip } from '@spectrum-web-components/tooltip';\nimport {\n fixture,\n ignoreResizeObserverLoopError,\n} from '../../../test/testing-helpers.js';\n\nignoreResizeObserverLoopError(before, after);\n\nasync function styledFixture<T extends Element>(\n story: TemplateResult\n): Promise<T> {\n const test = await fixture<Theme>(html`\n <sp-theme theme=\"spectrum\" scale=\"medium\" color=\"light\">\n ${story}\n </sp-theme>\n `);\n return test.children[0] as T;\n}\n\ndescribe('Overlay Trigger - Hover', () => {\n it('displays `hover` declaratively', async () => {\n const openedSpy = spy();\n const closedSpy = spy();\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger\n placement=\"right-start\"\n open=\"hover\"\n @sp-opened=${() => openedSpy()}\n @sp-closed=${() => closedSpy()}\n >\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n await waitUntil(\n () => openedSpy.calledOnce,\n 'hover content projected to overlay',\n { timeout: 2000 }\n );\n\n el.removeAttribute('open');\n await elementUpdated(el);\n\n await waitUntil(() => closedSpy.calledOnce, 'hover content returned', {\n timeout: 2000,\n });\n });\n describe('\"tooltip\" mouse interactions', () => {\n let el: OverlayTrigger;\n let button: ActionButton;\n let tooltip: Tooltip;\n beforeEach(async () => {\n el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-tooltip slot=\"hover-content\" tip>\n Magnify\n </sp-tooltip>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n button = el.querySelector('sp-action-button') as ActionButton;\n tooltip = el.querySelector('sp-tooltip') as Tooltip;\n });\n it('allows pointer to enter the \"tooltip\" without closing the \"tooltip\"', async () => {\n const opened = oneEvent(button, 'sp-opened');\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n await nextFrame();\n await nextFrame();\n await nextFrame();\n expect(tooltip.open).to.be.true;\n\n button.dispatchEvent(\n new MouseEvent('pointerleave', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n\n tooltip.dispatchEvent(\n new MouseEvent('pointerleave', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n const closed = oneEvent(button, 'sp-closed');\n button.dispatchEvent(\n new MouseEvent('pointerleave', {\n relatedTarget: null,\n bubbles: true,\n composed: true,\n })\n );\n await closed;\n\n expect(el.open).to.be.undefined;\n });\n it('closes the \"tooltip\" when leaving the \"tooltip\"', async () => {\n const opened = oneEvent(button, 'sp-opened');\n button.dispatchEvent(\n new MouseEvent('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await nextFrame();\n button.dispatchEvent(\n new MouseEvent('pointerleave', {\n relatedTarget: tooltip,\n bubbles: true,\n composed: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n const closed = oneEvent(button, 'sp-closed');\n tooltip.dispatchEvent(\n new MouseEvent('pointerleave', {\n relatedTarget: null,\n bubbles: true,\n composed: true,\n })\n );\n await closed;\n\n expect(el.open).to.be.undefined;\n });\n });\n it('persists hover content', async () => {\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n expect(el.open).to.be.undefined;\n\n const trigger = el.querySelector('[slot=\"trigger\"]') as ActionButton;\n const opened = oneEvent(trigger, 'sp-opened');\n trigger.dispatchEvent(\n new Event('pointerenter', {\n bubbles: true,\n composed: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n trigger.click();\n\n await elementUpdated(el);\n\n expect(el.open).to.equal('hover');\n });\n it('closes persistent hover content on `longpress`', async () => {\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n <sp-popover slot=\"longpress-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n\n expect(el.open).to.be.undefined;\n\n const trigger = el.querySelector('[slot=\"trigger\"]') as ActionButton;\n let opened = oneEvent(trigger, 'sp-opened');\n trigger.dispatchEvent(\n new Event('pointerenter', {\n bubbles: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('hover');\n\n opened = oneEvent(trigger, 'sp-opened');\n trigger.dispatchEvent(\n new Event('longpress', {\n bubbles: true,\n })\n );\n await opened;\n\n expect(el.open).to.equal('longpress');\n });\n it('closes `hover` overlay when [type=\"modal\"]', async () => {\n const el = await fixture<OverlayTrigger>(\n (() => html`\n <overlay-trigger placement=\"right-start\" type=\"modal\">\n <sp-action-button slot=\"trigger\">\n <sp-icon-magnify slot=\"icon\"></sp-icon-magnify>\n </sp-action-button>\n <sp-popover slot=\"hover-content\" tip></sp-popover>\n </overlay-trigger>\n `)()\n );\n await elementUpdated(el);\n const input = document.createElement('input');\n el.insertAdjacentElement('beforebegin', input);\n\n expect(el.open).to.be.undefined;\n\n const trigger = el.querySelector('[slot=\"trigger\"]') as ActionButton;\n const opened = oneEvent(el, 'sp-opened');\n input.focus();\n await sendKeys({\n press: 'Tab',\n });\n await opened;\n\n expect(el.open).to.equal('hover');\n\n const closed = oneEvent(el, 'sp-closed');\n trigger.blur();\n await closed;\n\n expect(el.open).to.be.undefined;\n });\n it('will not return focus to a \"modal\" parent', async () => {\n const el = await styledFixture<OverlayTrigger>(html`\n <overlay-trigger type=\"modal\">\n <sp-button slot=\"trigger\">Toggle Dialog</sp-button>\n <sp-dialog-wrapper\n slot=\"click-content\"\n headline=\"Dialog title\"\n size=\"s\"\n >\n ${[1, 2, 3, 4].map(\n (index) => html`\n <overlay-trigger>\n <sp-button slot=\"trigger\" id=\"button-${index}\">\n Button with Tooltip ${index}\n </sp-button>\n <sp-tooltip slot=\"hover-content\">\n Tooltip ${index}\n </sp-tooltip>\n </overlay-trigger>\n `\n )}\n </sp-dialog-wrapper>\n </overlay-trigger>\n `);\n await elementUpdated(el);\n\n const button = el.querySelector('sp-button') as Button;\n const dialog = el.querySelector('sp-dialog-wrapper') as HTMLElement;\n const button1 = dialog.querySelector('#button-1') as Button;\n const button2 = dialog.querySelector('#button-2') as Button;\n const button3 = dialog.querySelector('#button-3') as Button;\n await elementUpdated(button);\n await elementUpdated(dialog);\n\n let opened = oneEvent(button, 'sp-opened');\n const openedHint = oneEvent(button1, 'sp-opened');\n button.dispatchEvent(new Event('click', { bubbles: true }));\n await opened;\n await openedHint;\n\n expect(button1 === document.activeElement).to.be.true;\n\n opened = oneEvent(button2, 'sp-opened');\n sendKeys({\n press: 'Tab',\n });\n await opened;\n\n expect(button2 === document.activeElement).to.be.true;\n\n opened = oneEvent(button3, 'sp-opened');\n sendKeys({\n press: 'Tab',\n });\n await opened;\n\n expect(button3 === document.activeElement).to.be.true;\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|