@spectrum-web-components/overlay 0.36.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +266 -149
  2. package/custom-elements.json +1678 -553
  3. package/package.json +49 -22
  4. package/sp-overlay.d.ts +6 -0
  5. package/sp-overlay.dev.js +5 -0
  6. package/{active-overlay.dev.js.map → sp-overlay.dev.js.map} +3 -3
  7. package/sp-overlay.js +2 -0
  8. package/{active-overlay.js.map → sp-overlay.js.map} +4 -4
  9. package/src/AbstractOverlay.d.ts +58 -0
  10. package/src/AbstractOverlay.dev.js +211 -0
  11. package/src/AbstractOverlay.dev.js.map +7 -0
  12. package/src/AbstractOverlay.js +2 -0
  13. package/src/AbstractOverlay.js.map +7 -0
  14. package/src/Overlay.d.ts +163 -0
  15. package/src/Overlay.dev.js +792 -0
  16. package/src/Overlay.dev.js.map +7 -0
  17. package/src/Overlay.js +33 -0
  18. package/src/Overlay.js.map +7 -0
  19. package/src/OverlayDialog.d.ts +4 -0
  20. package/src/OverlayDialog.dev.js +135 -0
  21. package/src/OverlayDialog.dev.js.map +7 -0
  22. package/src/OverlayDialog.js +2 -0
  23. package/src/OverlayDialog.js.map +7 -0
  24. package/src/OverlayNoPopover.d.ts +4 -0
  25. package/src/OverlayNoPopover.dev.js +109 -0
  26. package/src/OverlayNoPopover.dev.js.map +7 -0
  27. package/src/OverlayNoPopover.js +2 -0
  28. package/src/OverlayNoPopover.js.map +7 -0
  29. package/src/OverlayPopover.d.ts +4 -0
  30. package/src/OverlayPopover.dev.js +169 -0
  31. package/src/OverlayPopover.dev.js.map +7 -0
  32. package/src/OverlayPopover.js +2 -0
  33. package/src/OverlayPopover.js.map +7 -0
  34. package/src/OverlayStack.d.ts +43 -0
  35. package/src/OverlayStack.dev.js +150 -0
  36. package/src/OverlayStack.dev.js.map +7 -0
  37. package/src/OverlayStack.js +2 -0
  38. package/src/OverlayStack.js.map +7 -0
  39. package/src/OverlayTrigger.d.ts +26 -42
  40. package/src/OverlayTrigger.dev.js +172 -296
  41. package/src/OverlayTrigger.dev.js.map +3 -3
  42. package/src/OverlayTrigger.js +49 -25
  43. package/src/OverlayTrigger.js.map +3 -3
  44. package/src/PlacementController.d.ts +38 -0
  45. package/src/PlacementController.dev.js +199 -0
  46. package/src/PlacementController.dev.js.map +7 -0
  47. package/src/PlacementController.js +2 -0
  48. package/src/PlacementController.js.map +7 -0
  49. package/src/VirtualTrigger.dev.js +2 -1
  50. package/src/VirtualTrigger.dev.js.map +2 -2
  51. package/src/VirtualTrigger.js +1 -1
  52. package/src/VirtualTrigger.js.map +2 -2
  53. package/src/fullSizePlugin.d.ts +12 -0
  54. package/src/fullSizePlugin.dev.js +39 -0
  55. package/src/fullSizePlugin.dev.js.map +7 -0
  56. package/src/fullSizePlugin.js +2 -0
  57. package/src/fullSizePlugin.js.map +7 -0
  58. package/src/index.d.ts +2 -3
  59. package/src/index.dev.js +2 -3
  60. package/src/index.dev.js.map +2 -2
  61. package/src/index.js +1 -1
  62. package/src/index.js.map +2 -2
  63. package/src/loader.d.ts +1 -2
  64. package/src/loader.dev.js +2 -19
  65. package/src/loader.dev.js.map +2 -2
  66. package/src/loader.js +1 -1
  67. package/src/loader.js.map +3 -3
  68. package/src/overlay-timer.dev.js.map +2 -2
  69. package/src/overlay-timer.js.map +2 -2
  70. package/src/overlay-trigger.css.dev.js +1 -1
  71. package/src/overlay-trigger.css.dev.js.map +1 -1
  72. package/src/overlay-trigger.css.js +3 -3
  73. package/src/overlay-trigger.css.js.map +1 -1
  74. package/src/overlay-types.d.ts +25 -31
  75. package/src/overlay-types.dev.js +1 -0
  76. package/src/overlay-types.dev.js.map +3 -3
  77. package/src/overlay-types.js +1 -1
  78. package/src/overlay-types.js.map +3 -3
  79. package/src/overlay.css.dev.js +9 -0
  80. package/src/overlay.css.dev.js.map +7 -0
  81. package/src/overlay.css.js +6 -0
  82. package/src/overlay.css.js.map +7 -0
  83. package/src/topLayerOverTransforms.d.ts +2 -0
  84. package/src/topLayerOverTransforms.dev.js +91 -0
  85. package/src/topLayerOverTransforms.dev.js.map +7 -0
  86. package/src/topLayerOverTransforms.js +2 -0
  87. package/src/topLayerOverTransforms.js.map +7 -0
  88. package/stories/overlay-element.stories.js +476 -0
  89. package/stories/overlay-element.stories.js.map +7 -0
  90. package/stories/overlay-story-components.js +9 -8
  91. package/stories/overlay-story-components.js.map +2 -2
  92. package/stories/overlay.stories.js +824 -680
  93. package/stories/overlay.stories.js.map +2 -2
  94. package/sync/overlay-trigger.d.ts +5 -0
  95. package/sync/overlay-trigger.dev.js +2 -4
  96. package/sync/overlay-trigger.dev.js.map +2 -2
  97. package/sync/overlay-trigger.js +1 -1
  98. package/sync/overlay-trigger.js.map +3 -3
  99. package/test/benchmark/basic-test.js +2 -2
  100. package/test/benchmark/basic-test.js.map +1 -1
  101. package/test/index.js +414 -377
  102. package/test/index.js.map +3 -3
  103. package/test/overlay-element.test-vrt.js +5 -0
  104. package/test/overlay-element.test-vrt.js.map +7 -0
  105. package/test/overlay-element.test.js +682 -0
  106. package/test/overlay-element.test.js.map +7 -0
  107. package/test/overlay-lifecycle.test.js +36 -106
  108. package/test/overlay-lifecycle.test.js.map +2 -2
  109. package/test/overlay-trigger-click.test.js +11 -5
  110. package/test/overlay-trigger-click.test.js.map +2 -2
  111. package/test/overlay-trigger-extended.test.js +46 -36
  112. package/test/overlay-trigger-extended.test.js.map +2 -2
  113. package/test/overlay-trigger-hover-click.test.js +38 -25
  114. package/test/overlay-trigger-hover-click.test.js.map +2 -2
  115. package/test/overlay-trigger-hover.test.js +41 -35
  116. package/test/overlay-trigger-hover.test.js.map +2 -2
  117. package/test/overlay-trigger-longpress.test.js +211 -82
  118. package/test/overlay-trigger-longpress.test.js.map +2 -2
  119. package/test/overlay-trigger-sync.test.js +1 -1
  120. package/test/overlay-trigger-sync.test.js.map +2 -2
  121. package/test/overlay-trigger.test.js +1 -1
  122. package/test/overlay-trigger.test.js.map +2 -2
  123. package/test/overlay-update.test.js +5 -5
  124. package/test/overlay-update.test.js.map +2 -2
  125. package/test/overlay-v1.test.js +547 -0
  126. package/test/overlay-v1.test.js.map +7 -0
  127. package/test/overlay.test.js +385 -269
  128. package/test/overlay.test.js.map +3 -3
  129. package/active-overlay.d.ts +0 -6
  130. package/active-overlay.dev.js +0 -5
  131. package/active-overlay.js +0 -2
  132. package/src/ActiveOverlay.d.ts +0 -84
  133. package/src/ActiveOverlay.dev.js +0 -517
  134. package/src/ActiveOverlay.dev.js.map +0 -7
  135. package/src/ActiveOverlay.js +0 -16
  136. package/src/ActiveOverlay.js.map +0 -7
  137. package/src/active-overlay.css.dev.js +0 -13
  138. package/src/active-overlay.css.dev.js.map +0 -7
  139. package/src/active-overlay.css.js +0 -10
  140. package/src/active-overlay.css.js.map +0 -7
  141. package/src/overlay-stack.d.ts +0 -50
  142. package/src/overlay-stack.dev.js +0 -515
  143. package/src/overlay-stack.dev.js.map +0 -7
  144. package/src/overlay-stack.js +0 -34
  145. package/src/overlay-stack.js.map +0 -7
  146. package/src/overlay-utils.d.ts +0 -3
  147. package/src/overlay-utils.dev.js +0 -31
  148. package/src/overlay-utils.dev.js.map +0 -7
  149. package/src/overlay-utils.js +0 -2
  150. package/src/overlay-utils.js.map +0 -7
  151. package/src/overlay.d.ts +0 -59
  152. package/src/overlay.dev.js +0 -127
  153. package/src/overlay.dev.js.map +0 -7
  154. package/src/overlay.js +0 -2
  155. package/src/overlay.js.map +0 -7
  156. /package/src/{active-overlay.css.d.ts → overlay.css.d.ts} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["OverlayStack.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\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*/\n\nimport { Overlay } from './Overlay.js';\n\nconst supportsPopover = 'showPopover' in document.createElement('div');\n\nclass OverlayStack {\n private get document(): Document {\n return this.root.ownerDocument /* c8 ignore next */ || document;\n }\n\n private pointerdownPath?: EventTarget[];\n\n private root: HTMLElement = document.body;\n\n stack: Overlay[] = [];\n\n constructor() {\n this.bindEvents();\n }\n\n bindEvents(): void {\n this.document.addEventListener('pointerdown', this.handlePointerdown);\n this.document.addEventListener('pointerup', this.handlePointerup);\n this.document.addEventListener('keydown', this.handleKeydown);\n }\n\n private closeOverlay(overlay: Overlay): void {\n const overlayIndex = this.stack.indexOf(overlay);\n if (overlayIndex > -1) {\n this.stack.splice(overlayIndex, 1);\n }\n overlay.open = false;\n }\n\n /**\n * Cach the `pointerdownTarget` for later testing\n *\n * @param event {ClickEvent}\n */\n handlePointerdown = (event: Event): void => {\n this.pointerdownPath = event.composedPath();\n };\n\n /**\n * Close all overlays that are not ancestors of this click event\n *\n * @param event {ClickEvent}\n */\n handlePointerup = (): void => {\n if (!this.stack.length) return;\n if (!this.pointerdownPath?.length) return;\n\n // Test against the composed path in `pointerdown` in case the visitor moved their\n // pointer during the course of the interaction.\n const composedPath = this.pointerdownPath;\n this.pointerdownPath = undefined;\n const nonAncestorOverlays = this.stack.filter((overlay) => {\n const inStack = composedPath.find(\n (el) => el === overlay || el === overlay?.triggerElement\n );\n return !inStack && !overlay.shouldPreventClose();\n }) as Overlay[];\n nonAncestorOverlays.reverse();\n nonAncestorOverlays.forEach((overlay) => {\n this.closeOverlay(overlay);\n let parentToClose = overlay.parentOverlayToForceClose;\n while (parentToClose) {\n this.closeOverlay(parentToClose);\n parentToClose = parentToClose.parentOverlayToForceClose;\n }\n });\n };\n\n handleBeforetoggle = (event: Event): void => {\n const { target, newState: open } = event as Event & {\n newState: string;\n };\n if (open === 'open') return;\n this.closeOverlay(target as Overlay);\n };\n\n private handleKeydown = (event: KeyboardEvent): void => {\n if (event.code !== 'Escape') return;\n const last = this.stack.at(-1);\n if (last?.type === 'page') {\n event.preventDefault();\n return;\n }\n if (supportsPopover) return;\n if (!this.stack.length) return;\n\n if (!last) return;\n this.closeOverlay(last);\n };\n\n /**\n * Get an array of Overlays that all share the same trigger element.\n *\n * @param triggerElement {HTMLELement}\n * @returns {Overlay[]}\n */\n overlaysByTriggerElement(triggerElement: HTMLElement): Overlay[] {\n return this.stack.filter(\n (overlay) => overlay.triggerElement === triggerElement\n );\n }\n\n /**\n * When overlays are added manage the open state of exisiting overlays appropriately:\n * - 'modal': should close other overlays\n * - 'page': should close other overlays\n * - 'hint': shouldn't close other overlays\n * - 'auto': should close other 'auto' overlays and other 'hint' overlays, but not 'manual' overlays\n * - 'manual': shouldn't close other overlays\n */\n add(overlay: Overlay): void {\n if (this.stack.includes(overlay)) {\n const overlayIndex = this.stack.indexOf(overlay);\n if (overlayIndex > -1) {\n this.stack.splice(overlayIndex, 1);\n this.stack.push(overlay);\n }\n return;\n }\n if (\n overlay.type === 'auto' ||\n overlay.type === 'modal' ||\n overlay.type === 'page'\n ) {\n // manage closing open overlays\n const queryPathEventName = 'sp-overlay-query-path';\n const queryPathEvent = new Event(queryPathEventName, {\n composed: true,\n bubbles: true,\n });\n overlay.addEventListener(\n queryPathEventName,\n (event: Event) => {\n const path = event.composedPath();\n this.stack.forEach((overlayEl) => {\n const inPath = path.find((el) => el === overlayEl);\n if (!inPath && overlayEl.type !== 'manual') {\n this.closeOverlay(overlayEl);\n }\n });\n },\n { once: true }\n );\n overlay.dispatchEvent(queryPathEvent);\n } else if (overlay.type === 'hint') {\n this.stack.forEach((overlayEl) => {\n if (overlayEl.type === 'hint') {\n this.closeOverlay(overlayEl);\n }\n });\n }\n requestAnimationFrame(() => {\n this.stack.push(overlay);\n overlay.addEventListener('beforetoggle', this.handleBeforetoggle, {\n once: true,\n });\n });\n }\n\n remove(overlay: Overlay): void {\n this.closeOverlay(overlay);\n }\n}\n\nexport const overlayStack = new OverlayStack();\n"],
5
+ "mappings": "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",
6
+ "names": ["supportsPopover", "OverlayStack", "event", "_a", "composedPath", "nonAncestorOverlays", "overlay", "el", "parentToClose", "target", "open", "last", "overlayIndex", "triggerElement", "queryPathEventName", "queryPathEvent", "path", "overlayEl"]
7
+ }
@@ -1,11 +1,8 @@
1
1
  import { CSSResultArray, PropertyValues, SpectrumElement, TemplateResult } from '@spectrum-web-components/base';
2
- import { OverlayOptions, OverlayTriggerInteractions, Placement, TriggerInteractions } from './overlay-types';
2
+ import type { Placement } from '@floating-ui/dom';
3
+ import type { Overlay } from './Overlay.js';
4
+ import type { OverlayTriggerInteractions } from './overlay-types';
3
5
  export declare type OverlayContentTypes = 'click' | 'hover' | 'longpress';
4
- export declare const LONGPRESS_INSTRUCTIONS: {
5
- touch: string;
6
- keyboard: string;
7
- mouse: string;
8
- };
9
6
  /**
10
7
  * @element overlay-trigger
11
8
  *
@@ -18,50 +15,37 @@ export declare const LONGPRESS_INSTRUCTIONS: {
18
15
  * @fires sp-closed - Announces that the overlay has been closed
19
16
  */
20
17
  export declare class OverlayTrigger extends SpectrumElement {
21
- private closeClickOverlay?;
22
- private closeLongpressOverlay?;
23
- private closeHoverOverlay?;
24
18
  static get styles(): CSSResultArray;
19
+ content: string;
25
20
  /**
26
- * @type {"auto" | "auto-start" | "auto-end" | "top" | "bottom" | "right" | "left" | "top-start" | "top-end" | "bottom-start" | "bottom-end" | "right-start" | "right-end" | "left-start" | "left-end" | "none"}
21
+ * @type {"top" | "top-start" | "top-end" | "right" | "right-start" | "right-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end"}
27
22
  * @attr
28
23
  */
29
- placement: Placement;
24
+ placement?: Placement;
30
25
  type?: OverlayTriggerInteractions;
31
26
  offset: number;
32
27
  open?: OverlayContentTypes;
33
28
  disabled: boolean;
34
- hasLongpressContent: boolean;
35
- private longpressDescriptor?;
36
- private clickContent?;
37
- private longpressContent?;
38
- private hoverContent?;
39
- private targetContent?;
40
- private overlaidContent?;
41
- private _longpressId;
42
- private handleClose;
29
+ private clickContent;
30
+ private clickPlacement?;
31
+ private longpressContent;
32
+ private longpressPlacement?;
33
+ private hoverContent;
34
+ private hoverPlacement?;
35
+ private targetContent;
36
+ clickOverlayElement: Overlay;
37
+ longpressOverlayElement: Overlay;
38
+ hoverOverlayElement: Overlay;
39
+ private getAssignedElementsFromSlot;
40
+ private handleTriggerContent;
41
+ private handleSlotContent;
42
+ private handleBeforetoggle;
43
+ protected update(changes: PropertyValues): void;
44
+ protected renderSlot(name: string): TemplateResult;
45
+ protected renderClickOverlay(): TemplateResult;
46
+ protected renderHoverOverlay(): TemplateResult;
47
+ protected renderLongpressOverlay(): TemplateResult;
43
48
  protected render(): TemplateResult;
44
- protected updated(changes: PropertyValues<this>): void;
45
- protected manageLongpressDescriptor(): void;
46
- private closeAllOverlays;
47
- private manageOpen;
48
- private openOverlay;
49
- static openOverlay: (target: HTMLElement, interaction: TriggerInteractions, content: HTMLElement, options: OverlayOptions) => Promise<() => void>;
50
- private get overlayOptions();
51
- private onTrigger;
52
- private prepareToFocusOverlayContent;
53
- onTriggerClick(): Promise<void>;
54
- private _longpressEvent?;
55
- private onTriggerLongpress;
56
- private abortOverlay;
57
- onTriggerMouseEnter(): Promise<void>;
58
- private onClickSlotChange;
59
- private onLongpressSlotChange;
60
- private onHoverSlotChange;
61
- private onTargetSlotChange;
62
- private extractSlotContentFromEvent;
63
- private openStatePromise;
64
- private openStateResolver;
49
+ protected updated(changes: PropertyValues): void;
65
50
  protected getUpdateComplete(): Promise<boolean>;
66
- disconnectedCallback(): void;
67
51
  }
@@ -16,346 +16,222 @@ import {
16
16
  } from "@spectrum-web-components/base";
17
17
  import {
18
18
  property,
19
+ query,
19
20
  state
20
21
  } from "@spectrum-web-components/base/src/decorators.js";
21
- import { firstFocusableIn } from "@spectrum-web-components/shared/src/first-focusable-in.js";
22
- import {
23
- isAndroid,
24
- isIOS
25
- } from "@spectrum-web-components/shared/src/platform.js";
26
- import { openOverlay } from "./loader.dev.js";
27
22
  import overlayTriggerStyles from "./overlay-trigger.css.js";
28
- export const LONGPRESS_INSTRUCTIONS = {
29
- touch: "Double tap and long press for additional options",
30
- keyboard: "Press Space or Alt+Down Arrow for additional options",
31
- mouse: "Click and hold for additional options"
32
- };
33
- const _OverlayTrigger = class _OverlayTrigger extends SpectrumElement {
23
+ export class OverlayTrigger extends SpectrumElement {
34
24
  constructor() {
35
25
  super(...arguments);
36
- this.placement = "bottom";
26
+ this.content = "click hover longpress";
37
27
  this.offset = 6;
38
28
  this.disabled = false;
39
- this.hasLongpressContent = false;
40
- this._longpressId = `longpress-describedby-descriptor`;
41
- this.abortOverlay = () => {
42
- return;
43
- };
44
- this.openStatePromise = Promise.resolve();
29
+ this.clickContent = [];
30
+ this.longpressContent = [];
31
+ this.hoverContent = [];
32
+ this.targetContent = [];
45
33
  }
46
34
  static get styles() {
47
35
  return [overlayTriggerStyles];
48
36
  }
49
- handleClose(event) {
50
- if (event && event.detail.interaction !== this.open && event.detail.interaction !== this.type) {
51
- return;
52
- }
53
- this.removeAttribute("open");
37
+ getAssignedElementsFromSlot(slot) {
38
+ return slot.assignedElements({ flatten: true });
54
39
  }
55
- render() {
56
- return html`
57
- <slot
58
- id="trigger"
59
- @click=${this.onTrigger}
60
- @longpress=${this.onTrigger}
61
- @mouseenter=${this.onTrigger}
62
- @mouseleave=${this.onTrigger}
63
- @focusin=${this.onTrigger}
64
- @focusout=${this.onTrigger}
65
- @sp-closed=${this.handleClose}
66
- @slotchange=${this.onTargetSlotChange}
67
- name="trigger"
68
- ></slot>
69
- <div id="overlay-content">
70
- <slot
71
- @slotchange=${this.onClickSlotChange}
72
- name="click-content"
73
- ></slot>
74
- <slot
75
- @slotchange=${this.onLongpressSlotChange}
76
- name="longpress-content"
77
- ></slot>
78
- <slot
79
- @slotchange=${this.onHoverSlotChange}
80
- name="hover-content"
81
- ></slot>
82
- <slot name=${this._longpressId}></slot>
83
- </div>
84
- `;
40
+ handleTriggerContent(event) {
41
+ this.targetContent = this.getAssignedElementsFromSlot(event.target);
85
42
  }
86
- updated(changes) {
87
- super.updated(changes);
88
- if (this.disabled && changes.has("disabled")) {
89
- this.closeAllOverlays();
43
+ handleSlotContent(event) {
44
+ switch (event.target.name) {
45
+ case "click-content":
46
+ this.clickContent = this.getAssignedElementsFromSlot(
47
+ event.target
48
+ );
49
+ break;
50
+ case "longpress-content":
51
+ this.longpressContent = this.getAssignedElementsFromSlot(
52
+ event.target
53
+ );
54
+ break;
55
+ case "hover-content":
56
+ this.hoverContent = this.getAssignedElementsFromSlot(
57
+ event.target
58
+ );
59
+ break;
60
+ }
61
+ }
62
+ handleBeforetoggle(event) {
63
+ const { target } = event;
64
+ let type;
65
+ if (target === this.clickOverlayElement) {
66
+ type = "click";
67
+ } else if (target === this.longpressOverlayElement) {
68
+ type = "longpress";
69
+ } else if (target === this.hoverOverlayElement) {
70
+ type = "hover";
71
+ } else {
90
72
  return;
91
73
  }
92
- if (changes.has("open")) {
93
- this.manageOpen();
94
- }
95
- if (changes.has("hasLongpressContent")) {
96
- this.manageLongpressDescriptor();
74
+ if (event.newState === "open") {
75
+ this.open = type;
76
+ } else if (this.open === type) {
77
+ this.open = void 0;
97
78
  }
98
79
  }
99
- manageLongpressDescriptor() {
100
- const trigger = this.querySelector(
101
- '[slot="trigger"]'
102
- );
103
- const ariaDescribedby = trigger.getAttribute("aria-describedby");
104
- let descriptors = ariaDescribedby ? ariaDescribedby.split(/\s+/) : [];
105
- if (this.hasLongpressContent) {
106
- if (!this.longpressDescriptor) {
107
- this.longpressDescriptor = document.createElement(
108
- "div"
109
- );
110
- this.longpressDescriptor.id = this._longpressId;
111
- this.longpressDescriptor.slot = this._longpressId;
112
- }
113
- const messageType = isIOS() || isAndroid() ? "touch" : "keyboard";
114
- this.longpressDescriptor.textContent = LONGPRESS_INSTRUCTIONS[messageType];
115
- this.appendChild(this.longpressDescriptor);
116
- descriptors.push(this._longpressId);
117
- } else {
118
- if (this.longpressDescriptor)
119
- this.longpressDescriptor.remove();
120
- descriptors = descriptors.filter(
121
- (descriptor) => descriptor !== this._longpressId
122
- );
80
+ update(changes) {
81
+ var _a, _b, _c, _d, _e, _f;
82
+ if (changes.has("clickContent")) {
83
+ this.clickPlacement = ((_a = this.clickContent[0]) == null ? void 0 : _a.getAttribute("placement")) || ((_b = this.clickContent[0]) == null ? void 0 : _b.getAttribute(
84
+ "direction"
85
+ )) || void 0;
123
86
  }
124
- if (descriptors.length) {
125
- trigger.setAttribute("aria-describedby", descriptors.join(" "));
126
- } else {
127
- trigger.removeAttribute("aria-describedby");
87
+ if (changes.has("hoverContent")) {
88
+ this.hoverPlacement = ((_c = this.hoverContent[0]) == null ? void 0 : _c.getAttribute("placement")) || ((_d = this.hoverContent[0]) == null ? void 0 : _d.getAttribute(
89
+ "direction"
90
+ )) || void 0;
128
91
  }
92
+ if (changes.has("longpressContent")) {
93
+ this.longpressPlacement = ((_e = this.longpressContent[0]) == null ? void 0 : _e.getAttribute("placement")) || ((_f = this.longpressContent[0]) == null ? void 0 : _f.getAttribute(
94
+ "direction"
95
+ )) || void 0;
96
+ }
97
+ super.update(changes);
129
98
  }
130
- closeAllOverlays() {
131
- if (this.abortOverlay)
132
- this.abortOverlay(true);
133
- [
134
- "closeClickOverlay",
135
- "closeHoverOverlay",
136
- "closeLongpressOverlay"
137
- ].forEach(async (name) => {
138
- const canClose = this[name];
139
- if (canClose == null)
140
- return;
141
- delete this[name];
142
- (await canClose)();
143
- });
144
- this.overlaidContent = void 0;
145
- }
146
- manageOpen() {
147
- var _a;
148
- const openHandlers = {
149
- click: () => this.onTriggerClick(),
150
- hover: () => this.onTriggerMouseEnter(),
151
- longpress: () => this.onTriggerLongpress(),
152
- none: () => this.closeAllOverlays()
153
- };
154
- openHandlers[(_a = this.open) != null ? _a : "none"]();
155
- }
156
- async openOverlay(target, interaction, content, options) {
157
- this.openStatePromise = new Promise(
158
- (res) => this.openStateResolver = res
159
- );
160
- this.addEventListener(
161
- "sp-opened",
162
- () => {
163
- this.openStateResolver();
164
- },
165
- { once: true }
166
- );
167
- this.overlaidContent = content;
168
- return _OverlayTrigger.openOverlay(
169
- target,
170
- interaction,
171
- content,
172
- options
173
- );
174
- }
175
- get overlayOptions() {
176
- return {
177
- offset: this.offset,
178
- placement: this.placement,
179
- receivesFocus: !this.type || this.type === "inline" || this.open === "hover" ? void 0 : "auto"
180
- };
99
+ renderSlot(name) {
100
+ return html`
101
+ <slot name=${name} @slotchange=${this.handleSlotContent}></slot>
102
+ `;
181
103
  }
182
- onTrigger(event) {
183
- const mouseIsEnteringHoverContent = event.type === "mouseleave" && this.open === "hover" && event.relatedTarget === this.overlaidContent;
184
- if (mouseIsEnteringHoverContent && this.overlaidContent) {
185
- this.overlaidContent.addEventListener(
186
- "mouseleave",
187
- (event2) => {
188
- const mouseIsEnteringTrigger = event2.relatedTarget === this.targetContent;
189
- if (mouseIsEnteringTrigger) {
190
- return;
191
- }
192
- this.onTrigger(
193
- event2
194
- );
195
- },
196
- { once: true }
197
- );
198
- return;
199
- }
200
- if (this.disabled)
201
- return;
202
- switch (event.type) {
203
- case "mouseenter":
204
- case "focusin":
205
- if (!this.open && this.hoverContent) {
206
- this.open = "hover";
207
- }
208
- return;
209
- case "mouseleave":
210
- case "focusout":
211
- if (this.open === "hover") {
212
- this.handleClose();
213
- }
214
- return;
215
- case "click":
216
- if (this.clickContent) {
217
- this.open = event.type;
218
- }
219
- return;
220
- case "longpress":
221
- if (this.longpressContent) {
222
- this._longpressEvent = event;
223
- this.open = event.type;
224
- }
225
- return;
104
+ renderClickOverlay() {
105
+ import("@spectrum-web-components/overlay/sp-overlay.js");
106
+ const slot = this.renderSlot("click-content");
107
+ if (!this.clickContent.length) {
108
+ return slot;
226
109
  }
110
+ return html`
111
+ <sp-overlay
112
+ id="click-overlay"
113
+ ?disabled=${this.disabled || !this.clickContent.length}
114
+ ?open=${this.open === "click" && !!this.clickContent.length}
115
+ .offset=${this.offset}
116
+ .placement=${this.clickPlacement || this.placement}
117
+ .triggerElement=${this.targetContent[0]}
118
+ .triggerInteraction=${"click"}
119
+ .type=${this.type !== "modal" ? "auto" : "modal"}
120
+ @beforetoggle=${this.handleBeforetoggle}
121
+ >
122
+ ${slot}
123
+ </sp-overlay>
124
+ `;
227
125
  }
228
- prepareToFocusOverlayContent(overlayContent) {
229
- if (this.type !== "modal") {
230
- return;
231
- }
232
- const firstFocusable = firstFocusableIn(overlayContent);
233
- if (!firstFocusable) {
234
- overlayContent.tabIndex = 0;
126
+ renderHoverOverlay() {
127
+ import("@spectrum-web-components/overlay/sp-overlay.js");
128
+ const slot = this.renderSlot("hover-content");
129
+ if (!this.hoverContent.length) {
130
+ return slot;
235
131
  }
132
+ return html`
133
+ <sp-overlay
134
+ id="hover-overlay"
135
+ ?disabled=${this.disabled || !this.hoverContent.length || !!this.open && this.open !== "hover"}
136
+ ?open=${this.open === "hover" && !!this.hoverContent.length}
137
+ .offset=${this.offset}
138
+ .placement=${this.hoverPlacement || this.placement}
139
+ .triggerElement=${this.targetContent[0]}
140
+ .triggerInteraction=${"hover"}
141
+ .type=${"hint"}
142
+ @beforetoggle=${this.handleBeforetoggle}
143
+ >
144
+ ${slot}
145
+ </sp-overlay>
146
+ `;
236
147
  }
237
- async onTriggerClick() {
238
- if (!this.targetContent || !this.clickContent || this.closeClickOverlay) {
239
- return;
240
- }
241
- const { targetContent, clickContent } = this;
242
- this.closeAllOverlays();
243
- this.prepareToFocusOverlayContent(clickContent);
244
- if (true) {
245
- window.__swc.ignoreWarningLevels.deprecation = true;
246
- }
247
- this.closeClickOverlay = this.openOverlay(
248
- targetContent,
249
- this.type ? this.type : "click",
250
- clickContent,
251
- this.overlayOptions
252
- );
253
- if (true) {
254
- window.__swc.ignoreWarningLevels.deprecation = false;
148
+ renderLongpressOverlay() {
149
+ import("@spectrum-web-components/overlay/sp-overlay.js");
150
+ const slot = this.renderSlot("longpress-content");
151
+ if (!this.longpressContent.length) {
152
+ return slot;
255
153
  }
154
+ return html`
155
+ <sp-overlay
156
+ id="longpress-overlay"
157
+ ?disabled=${this.disabled || !this.longpressContent.length}
158
+ ?open=${this.open === "longpress" && !!this.longpressContent.length}
159
+ .offset=${this.offset}
160
+ .placement=${this.longpressPlacement || this.placement}
161
+ .triggerElement=${this.targetContent[0]}
162
+ .triggerInteraction=${"longpress"}
163
+ .type=${"auto"}
164
+ @beforetoggle=${this.handleBeforetoggle}
165
+ >
166
+ ${slot}
167
+ </sp-overlay>
168
+ <slot name="longpress-describedby-descriptor"></slot>
169
+ `;
256
170
  }
257
- async onTriggerLongpress() {
258
- var _a, _b;
259
- if (!this.targetContent || !this.longpressContent || this.closeLongpressOverlay) {
260
- return;
261
- }
262
- const { targetContent, longpressContent } = this;
263
- this.closeAllOverlays();
264
- this.prepareToFocusOverlayContent(longpressContent);
265
- const notImmediatelyClosable = ((_b = (_a = this._longpressEvent) == null ? void 0 : _a.detail) == null ? void 0 : _b.source) !== "keyboard";
266
- if (true) {
267
- window.__swc.ignoreWarningLevels.deprecation = true;
268
- }
269
- this.closeLongpressOverlay = this.openOverlay(
270
- targetContent,
271
- this.type ? this.type : "longpress",
272
- longpressContent,
273
- {
274
- ...this.overlayOptions,
275
- receivesFocus: "auto",
276
- notImmediatelyClosable
277
- }
278
- );
279
- if (true) {
280
- window.__swc.ignoreWarningLevels.deprecation = false;
281
- }
282
- this._longpressEvent = void 0;
171
+ render() {
172
+ const content = this.content.split(" ");
173
+ return html`
174
+ <slot
175
+ id="trigger"
176
+ name="trigger"
177
+ @slotchange=${this.handleTriggerContent}
178
+ ></slot>
179
+ ${[
180
+ content.includes("click") ? this.renderClickOverlay() : html``,
181
+ content.includes("hover") ? this.renderHoverOverlay() : html``,
182
+ content.includes("longpress") ? this.renderLongpressOverlay() : html``
183
+ ]}
184
+ `;
283
185
  }
284
- async onTriggerMouseEnter() {
285
- if (!this.targetContent || !this.hoverContent || this.closeHoverOverlay) {
186
+ updated(changes) {
187
+ super.updated(changes);
188
+ if (this.disabled && changes.has("disabled")) {
189
+ this.open = void 0;
286
190
  return;
287
191
  }
288
- const abortPromise = new Promise((res) => {
289
- this.abortOverlay = res;
290
- });
291
- const { targetContent, hoverContent } = this;
292
- if (true) {
293
- window.__swc.ignoreWarningLevels.deprecation = true;
294
- }
295
- this.closeHoverOverlay = this.openOverlay(
296
- targetContent,
297
- "hover",
298
- hoverContent,
299
- {
300
- abortPromise,
301
- ...this.overlayOptions
302
- }
303
- );
304
- if (true) {
305
- window.__swc.ignoreWarningLevels.deprecation = false;
306
- }
307
- }
308
- onClickSlotChange(event) {
309
- this.clickContent = this.extractSlotContentFromEvent(event);
310
- this.manageOpen();
311
- }
312
- onLongpressSlotChange(event) {
313
- this.longpressContent = this.extractSlotContentFromEvent(event);
314
- this.hasLongpressContent = !!this.longpressContent || !!this.closeLongpressOverlay;
315
- this.manageOpen();
316
- }
317
- onHoverSlotChange(event) {
318
- this.hoverContent = this.extractSlotContentFromEvent(event);
319
- this.manageOpen();
320
- }
321
- onTargetSlotChange(event) {
322
- this.targetContent = this.extractSlotContentFromEvent(event);
323
- }
324
- extractSlotContentFromEvent(event) {
325
- const slot = event.target;
326
- const nodes = slot.assignedNodes({ flatten: true });
327
- return nodes.find((node) => node instanceof HTMLElement);
328
192
  }
329
193
  async getUpdateComplete() {
330
194
  const complete = await super.getUpdateComplete();
331
- await this.openStatePromise;
332
195
  return complete;
333
196
  }
334
- disconnectedCallback() {
335
- this.closeAllOverlays();
336
- super.disconnectedCallback();
337
- }
338
- };
339
- _OverlayTrigger.openOverlay = async (target, interaction, content, options) => {
340
- return openOverlay(target, interaction, content, options);
341
- };
197
+ }
198
+ __decorateClass([
199
+ property()
200
+ ], OverlayTrigger.prototype, "content", 2);
342
201
  __decorateClass([
343
202
  property({ reflect: true })
344
- ], _OverlayTrigger.prototype, "placement", 2);
203
+ ], OverlayTrigger.prototype, "placement", 2);
345
204
  __decorateClass([
346
205
  property()
347
- ], _OverlayTrigger.prototype, "type", 2);
206
+ ], OverlayTrigger.prototype, "type", 2);
348
207
  __decorateClass([
349
- property({ type: Number, reflect: true })
350
- ], _OverlayTrigger.prototype, "offset", 2);
208
+ property({ type: Number })
209
+ ], OverlayTrigger.prototype, "offset", 2);
351
210
  __decorateClass([
352
211
  property({ reflect: true })
353
- ], _OverlayTrigger.prototype, "open", 2);
212
+ ], OverlayTrigger.prototype, "open", 2);
354
213
  __decorateClass([
355
214
  property({ type: Boolean, reflect: true })
356
- ], _OverlayTrigger.prototype, "disabled", 2);
215
+ ], OverlayTrigger.prototype, "disabled", 2);
357
216
  __decorateClass([
358
217
  state()
359
- ], _OverlayTrigger.prototype, "hasLongpressContent", 2);
360
- export let OverlayTrigger = _OverlayTrigger;
218
+ ], OverlayTrigger.prototype, "clickContent", 2);
219
+ __decorateClass([
220
+ state()
221
+ ], OverlayTrigger.prototype, "longpressContent", 2);
222
+ __decorateClass([
223
+ state()
224
+ ], OverlayTrigger.prototype, "hoverContent", 2);
225
+ __decorateClass([
226
+ state()
227
+ ], OverlayTrigger.prototype, "targetContent", 2);
228
+ __decorateClass([
229
+ query("#click-overlay", true)
230
+ ], OverlayTrigger.prototype, "clickOverlayElement", 2);
231
+ __decorateClass([
232
+ query("#longpress-overlay", true)
233
+ ], OverlayTrigger.prototype, "longpressOverlayElement", 2);
234
+ __decorateClass([
235
+ query("#hover-overlay", true)
236
+ ], OverlayTrigger.prototype, "hoverOverlayElement", 2);
361
237
  //# sourceMappingURL=OverlayTrigger.dev.js.map