@momentum-design/components 0.27.6 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/browser/index.js +314 -131
  2. package/dist/browser/index.js.map +4 -4
  3. package/dist/components/button/button.styles.js +1 -0
  4. package/dist/components/buttonsimple/buttonsimple.component.d.ts +5 -0
  5. package/dist/components/buttonsimple/buttonsimple.component.js +10 -0
  6. package/dist/components/modalcontainer/modalcontainer.component.d.ts +9 -3
  7. package/dist/components/modalcontainer/modalcontainer.component.js +26 -15
  8. package/dist/components/modalcontainer/modalcontainer.constants.d.ts +2 -5
  9. package/dist/components/modalcontainer/modalcontainer.constants.js +3 -6
  10. package/dist/components/modalcontainer/modalcontainer.styles.js +6 -6
  11. package/dist/components/modalcontainer/modalcontainer.types.d.ts +1 -2
  12. package/dist/components/popover/index.d.ts +9 -0
  13. package/dist/components/popover/index.js +6 -0
  14. package/dist/components/popover/popover.component.d.ts +256 -0
  15. package/dist/components/popover/popover.component.js +675 -0
  16. package/dist/components/popover/popover.constants.d.ts +44 -0
  17. package/dist/components/popover/popover.constants.js +46 -0
  18. package/dist/components/popover/popover.events.d.ts +34 -0
  19. package/dist/components/popover/popover.events.js +47 -0
  20. package/dist/components/popover/popover.stack.d.ts +45 -0
  21. package/dist/components/popover/popover.stack.js +55 -0
  22. package/dist/components/popover/popover.styles.d.ts +2 -0
  23. package/dist/components/popover/popover.styles.js +109 -0
  24. package/dist/components/popover/popover.types.d.ts +4 -0
  25. package/dist/components/popover/popover.types.js +1 -0
  26. package/dist/components/popover/popover.utils.d.ts +48 -0
  27. package/dist/components/popover/popover.utils.js +156 -0
  28. package/dist/custom-elements.json +4135 -2187
  29. package/dist/index.d.ts +2 -1
  30. package/dist/index.js +2 -1
  31. package/dist/react/index.d.ts +2 -1
  32. package/dist/react/index.js +2 -1
  33. package/dist/react/popover/index.d.ts +24 -0
  34. package/dist/react/popover/index.js +33 -0
  35. package/dist/utils/mixins/DataAriaDescribedbyMixin.d.ts +6 -0
  36. package/dist/utils/mixins/DataAriaDescribedbyMixin.js +30 -0
  37. package/dist/utils/mixins/DataAriaLabelledbyMixin.d.ts +6 -0
  38. package/dist/utils/mixins/DataAriaLabelledbyMixin.js +29 -0
  39. package/dist/utils/mixins/FocusTrapMixin.d.ts +9 -0
  40. package/dist/utils/mixins/FocusTrapMixin.js +323 -0
  41. package/package.json +2 -1
@@ -0,0 +1,675 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { html, nothing } from 'lit';
11
+ import { ifDefined } from 'lit/directives/if-defined.js';
12
+ import { property } from 'lit/decorators.js';
13
+ import { computePosition, autoUpdate, offset, flip, shift, arrow, size } from '@floating-ui/dom';
14
+ import styles from './popover.styles';
15
+ import { Component } from '../../models';
16
+ import { FocusTrapMixin } from '../../utils/mixins/FocusTrapMixin';
17
+ import { popoverStack } from './popover.stack';
18
+ import { COLOR } from '../modalcontainer/modalcontainer.constants';
19
+ import { DEFAULTS, POPOVER_PLACEMENT, TRIGGER } from './popover.constants';
20
+ import { DataAriaLabelMixin } from '../../utils/mixins/DataAriaLabelMixin';
21
+ import { DataAriaDescribedbyMixin } from '../../utils/mixins/DataAriaDescribedbyMixin';
22
+ import { DataAriaLabelledbyMixin } from '../../utils/mixins/DataAriaLabelledbyMixin';
23
+ import { PopoverEventManager } from './popover.events';
24
+ import { PopoverUtils } from './popover.utils';
25
+ /**
26
+ * Popover component is a lightweight floating UI element that displays additional content when triggered.
27
+ * It can be used for tooltips, dropdowns, or contextual menus.
28
+ * The popover automatically positions itself based on available space and
29
+ * supports dynamic height adjustments with scrollable content when needed。
30
+ *
31
+ * @dependency mdc-button
32
+ * @dependency mdc-modalcontainer
33
+ *
34
+ * @tagname mdc-popover
35
+ *
36
+ * @cssproperty --mdc-popover-arrow-border-radius - radius of the arrow border
37
+ * @cssproperty --mdc-popover-arrow-border - border of the arrow
38
+ * @cssproperty --mdc-popover-primary-background-color - primary background color of the popover
39
+ * @cssproperty --mdc-popover-inverted-background-color - inverted background color of the popover
40
+ * @cssproperty --mdc-popover-inverted-border-color - inverted border color of the popover
41
+ * @cssproperty --mdc-popover-inverted-text-color - inverted text color of the popover
42
+ *
43
+ * @slot - Default slot for modal container
44
+ *
45
+ */
46
+ class Popover extends DataAriaLabelMixin(DataAriaLabelledbyMixin(DataAriaDescribedbyMixin(FocusTrapMixin(Component)))) {
47
+ constructor() {
48
+ super();
49
+ /**
50
+ * The unique ID of the popover.
51
+ */
52
+ this.id = '';
53
+ /**
54
+ * The ID of the element that triggers the popover.
55
+ * This attribute is required for the popover to work.
56
+ */
57
+ this.triggerID = '';
58
+ /**
59
+ * Determines the events that cause the Popover to show.
60
+ * Multiple event names should be separated by spaces.
61
+ * For example to allow both click and hover, use 'click mouseenter' as the trigger.
62
+ * - **click**
63
+ * - **mouseenter**
64
+ * - **focusin**
65
+ * - **manual**
66
+ * @default click
67
+ */
68
+ this.trigger = DEFAULTS.TRIGGER;
69
+ /**
70
+ * The placement of the popover.
71
+ * - **top**
72
+ * - **top-start**
73
+ * - **top-end**
74
+ * - **bottom**
75
+ * - **bottom-start**
76
+ * - **bottom-end**
77
+ * - **left**
78
+ * - **left-start**
79
+ * - **left-end**
80
+ * - **right**
81
+ * - **right-start**
82
+ * - **right-end**
83
+ * @default bottom
84
+ */
85
+ this.placement = DEFAULTS.PLACEMENT;
86
+ /**
87
+ * Color of the popover
88
+ * - **tonal**
89
+ * - **contrast**
90
+ * @default tonal
91
+ */
92
+ this.color = DEFAULTS.COLOR;
93
+ /**
94
+ * The visibility of the popover.
95
+ * @default false
96
+ */
97
+ this.visible = DEFAULTS.VISIBLE;
98
+ /**
99
+ * The offset of the popover.
100
+ * @default 4
101
+ */
102
+ this.offset = DEFAULTS.OFFSET;
103
+ /**
104
+ * Determines whether the focus trap is enabled.
105
+ * If true, focus will be restricted to the content within this component.
106
+ * @default false
107
+ */
108
+ this.focusTrap = DEFAULTS.FOCUS_TRAP;
109
+ /**
110
+ * Prevent outside scrolling when popover show.
111
+ * @default false
112
+ */
113
+ this.preventScroll = DEFAULTS.PREVENT_SCROLL;
114
+ /**
115
+ * The arrow visibility of the popover.
116
+ * @default false
117
+ */
118
+ this.showArrow = DEFAULTS.ARROW;
119
+ /**
120
+ * The close button visibility of the popover.
121
+ * @default false
122
+ */
123
+ this.closeButton = DEFAULTS.CLOSE_BUTTON;
124
+ /**
125
+ * Determines whether the popover is interactive。
126
+ * @default false
127
+ */
128
+ this.interactive = DEFAULTS.INTERACTIVE;
129
+ /**
130
+ * The delay of the show/hide popover.
131
+ * @default 0,0
132
+ */
133
+ this.delay = DEFAULTS.DELAY;
134
+ /**
135
+ * Hide popover on escape key press.
136
+ * @default false
137
+ */
138
+ this.hideOnEscape = DEFAULTS.HIDE_ON_ESCAPE;
139
+ /**
140
+ * Hide popover on blur.
141
+ * @default false
142
+ */
143
+ this.hideOnBlur = DEFAULTS.HIDE_ON_BLUR;
144
+ /**
145
+ * Hide on outside click of the popover.
146
+ * @default false
147
+ */
148
+ this.hideOnOutsideClick = DEFAULTS.HIDE_ON_CLICK_OUTSIDE;
149
+ /**
150
+ * The focus back to trigger after the popover hide.
151
+ * @default false
152
+ */
153
+ this.focusBackToTrigger = DEFAULTS.FOCUS_BACK;
154
+ /**
155
+ * Determines whether the popover with backdrop.
156
+ * Other than popover and trigger element, the rest of the screen will be covered with a backdrop.
157
+ * @default false
158
+ */
159
+ this.backdrop = DEFAULTS.BACKDROP;
160
+ /**
161
+ * Changes the placement of popover to keep it in view when scrolling.
162
+ * @default true
163
+ */
164
+ this.flip = DEFAULTS.FLIP;
165
+ /**
166
+ * Changes the size of popover to keep it in view when scrolling.
167
+ * @default false
168
+ */
169
+ this.size = DEFAULTS.SIZE;
170
+ /**
171
+ * The z-index of the popover.
172
+ * @default 1000
173
+ */
174
+ this.zIndex = DEFAULTS.Z_INDEX;
175
+ /**
176
+ * Element ID that the popover append to.
177
+ * @default ''
178
+ */
179
+ this.appendTo = '';
180
+ /**
181
+ * aria-label attribute to be set for close button accessibility.
182
+ * @default null
183
+ */
184
+ this.closeButtonAriaLabel = null;
185
+ /**
186
+ * Role of the popover
187
+ * @default dialog
188
+ */
189
+ this.dataRole = DEFAULTS.ROLE;
190
+ this.arrowElement = null;
191
+ /** @internal */
192
+ this.triggerElement = null;
193
+ /** @internal */
194
+ this.containerElement = null;
195
+ /** @internal */
196
+ this.hoverTimer = null;
197
+ /** @internal */
198
+ this.isTriggerClicked = false;
199
+ /** @internal */
200
+ this.openDelay = 0;
201
+ /** @internal */
202
+ this.closeDelay = 0;
203
+ /**
204
+ * Handles the outside click event to close the popover.
205
+ *
206
+ * @param event - The mouse event.
207
+ */
208
+ this.onOutsidePopoverClick = (event) => {
209
+ if (popoverStack.peek() !== this)
210
+ return;
211
+ let insidePopoverClick = false;
212
+ const path = event.composedPath();
213
+ insidePopoverClick = this.contains(event.target) || path.includes(this.triggerElement);
214
+ const backdropElement = this.renderRoot.querySelector('.popover-backdrop');
215
+ const clickedOnBackdrop = backdropElement ? path.includes(backdropElement) : false;
216
+ if (!insidePopoverClick || clickedOnBackdrop) {
217
+ this.hidePopover();
218
+ }
219
+ };
220
+ /**
221
+ * Handles the escape keydown event to close the popover.
222
+ *
223
+ * @param event - The keyboard event.
224
+ */
225
+ this.onEscapeKeydown = (event) => {
226
+ if (!this.visible || event.code !== 'Escape') {
227
+ return;
228
+ }
229
+ event.preventDefault();
230
+ this.hidePopover();
231
+ };
232
+ /**
233
+ * Handles the popover focus out event.
234
+ *
235
+ * @param event - The focus event.
236
+ */
237
+ this.onPopoverFocusOut = (event) => {
238
+ if (!this.contains(event.relatedTarget)) {
239
+ this.hidePopover();
240
+ }
241
+ };
242
+ /**
243
+ * Starts the close delay timer.
244
+ * If the popover is not interactive, it will close the popover after the delay.
245
+ */
246
+ this.startCloseDelay = () => {
247
+ if (!this.interactive) {
248
+ this.hidePopover();
249
+ }
250
+ else {
251
+ if (this.isTriggerClicked)
252
+ return;
253
+ this.hoverTimer = window.setTimeout(() => {
254
+ this.visible = false;
255
+ }, this.closeDelay);
256
+ }
257
+ };
258
+ /**
259
+ * Cancels the close delay timer.
260
+ */
261
+ this.cancelCloseDelay = () => {
262
+ if (this.hoverTimer) {
263
+ clearTimeout(this.hoverTimer);
264
+ this.hoverTimer = null;
265
+ }
266
+ };
267
+ /**
268
+ * Shows the popover.
269
+ */
270
+ this.showPopover = () => {
271
+ this.cancelCloseDelay();
272
+ setTimeout(() => {
273
+ this.visible = true;
274
+ PopoverEventManager.onShowPopover(this);
275
+ }, this.openDelay);
276
+ if (popoverStack.peek() !== this) {
277
+ popoverStack.push(this);
278
+ }
279
+ };
280
+ /**
281
+ * Hides the popover.
282
+ */
283
+ this.hidePopover = () => {
284
+ if (popoverStack.peek() === this) {
285
+ setTimeout(() => {
286
+ this.visible = false;
287
+ PopoverEventManager.onHidePopover(this);
288
+ this.isTriggerClicked = false;
289
+ }, this.closeDelay);
290
+ popoverStack.pop();
291
+ }
292
+ };
293
+ /**
294
+ * Toggles the popover visibility.
295
+ */
296
+ this.togglePopoverVisible = () => {
297
+ if (this.isTriggerClicked) {
298
+ this.hidePopover();
299
+ }
300
+ else {
301
+ this.showPopover();
302
+ this.isTriggerClicked = true;
303
+ }
304
+ };
305
+ this.utils = new PopoverUtils(this);
306
+ }
307
+ async firstUpdated(changedProperties) {
308
+ super.firstUpdated(changedProperties);
309
+ this.containerElement = this.renderRoot.querySelector('.popover-container');
310
+ this.utils.setupAppendTo();
311
+ [this.openDelay, this.closeDelay] = this.utils.setupDelay();
312
+ this.setupTriggerListener();
313
+ this.utils.setupAccessibility();
314
+ PopoverEventManager.onCreatedPopover(this);
315
+ if (this.visible) {
316
+ await this.positionPopover();
317
+ await this.handleCreatePopoverFirstUpdate();
318
+ }
319
+ }
320
+ async disconnectedCallback() {
321
+ super.disconnectedCallback();
322
+ await this.removeEventListeners();
323
+ PopoverEventManager.onDestroyedPopover(this);
324
+ popoverStack.remove(this);
325
+ }
326
+ /**
327
+ * Sets up the trigger event listeners based on the trigger type.
328
+ */
329
+ setupTriggerListener() {
330
+ var _a, _b;
331
+ if (!this.triggerID)
332
+ return;
333
+ this.triggerElement = document.getElementById(this.triggerID);
334
+ if (!this.triggerElement)
335
+ return;
336
+ if (this.trigger === 'mouseenter') {
337
+ if (this.interactive) {
338
+ // if the popover is interactive, there is interactive content inside the popover
339
+ // so we can't use the focusin trigger, since after closing with escape key, the
340
+ // popover keeps opening. So we need to use the click trigger instead.
341
+ this.trigger = 'mouseenter click';
342
+ }
343
+ else {
344
+ // non-interactive popovers with trigger mouseenter (like a tooltip) should also open
345
+ // when focusing to the trigger element
346
+ this.trigger = 'mouseenter focusin';
347
+ }
348
+ }
349
+ if (this.trigger.includes('click')) {
350
+ this.triggerElement.addEventListener('click', this.togglePopoverVisible);
351
+ }
352
+ if (this.trigger.includes('mouseenter')) {
353
+ const hoverBridge = this.renderRoot.querySelector('.popover-hover-bridge');
354
+ this.triggerElement.addEventListener('mouseenter', this.showPopover);
355
+ this.triggerElement.addEventListener('mouseleave', this.startCloseDelay);
356
+ (_a = this.containerElement) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', this.cancelCloseDelay);
357
+ (_b = this.containerElement) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', this.startCloseDelay);
358
+ hoverBridge === null || hoverBridge === void 0 ? void 0 : hoverBridge.addEventListener('mouseenter', this.cancelCloseDelay);
359
+ }
360
+ if (this.trigger.includes('focusin')) {
361
+ this.triggerElement.addEventListener('focusin', this.showPopover);
362
+ if (!this.interactive) {
363
+ this.triggerElement.addEventListener('focusout', this.hidePopover);
364
+ }
365
+ }
366
+ this.addEventListener('focus-trap-exit', this.hidePopover);
367
+ }
368
+ /**
369
+ * Removes the trigger event listeners.
370
+ */
371
+ removeEventListeners() {
372
+ var _a, _b;
373
+ if (!this.triggerElement)
374
+ return;
375
+ const hoverBridge = this.renderRoot.querySelector('.popover-hover-bridge');
376
+ this.triggerElement.removeEventListener('click', this.togglePopoverVisible);
377
+ this.triggerElement.removeEventListener('mouseenter', this.showPopover);
378
+ this.triggerElement.removeEventListener('mouseleave', this.hidePopover);
379
+ (_a = this.containerElement) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', this.cancelCloseDelay);
380
+ (_b = this.containerElement) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', this.startCloseDelay);
381
+ this.triggerElement.removeEventListener('focusin', this.showPopover);
382
+ this.triggerElement.removeEventListener('focusout', this.hidePopover);
383
+ hoverBridge === null || hoverBridge === void 0 ? void 0 : hoverBridge.removeEventListener('mouseenter', this.cancelCloseDelay);
384
+ this.removeEventListener('focus-trap-exit', this.hidePopover);
385
+ }
386
+ async updated(changedProperties) {
387
+ super.updated(changedProperties);
388
+ if (changedProperties.has('visible')) {
389
+ const oldValue = changedProperties.get('visible');
390
+ await this.isOpenUpdated(oldValue, this.visible);
391
+ }
392
+ if (changedProperties.has('placement')) {
393
+ this.setAttribute('placement', Object.values(POPOVER_PLACEMENT).includes(this.placement) ? this.placement : DEFAULTS.PLACEMENT);
394
+ }
395
+ if (changedProperties.has('delay')) {
396
+ [this.openDelay, this.closeDelay] = this.utils.setupDelay();
397
+ }
398
+ if (changedProperties.has('trigger')) {
399
+ const triggers = this.trigger.split(' ');
400
+ const validTriggers = triggers.filter((trigger) => Object.values(TRIGGER).includes(trigger));
401
+ this.setAttribute('trigger', validTriggers.length > 0 ? this.trigger : DEFAULTS.TRIGGER);
402
+ this.removeEventListeners();
403
+ this.setupTriggerListener();
404
+ }
405
+ if (changedProperties.has('color')) {
406
+ this.setAttribute('color', Object.values(COLOR).includes(this.color) ? this.color : DEFAULTS.COLOR);
407
+ }
408
+ if (changedProperties.has('zIndex')) {
409
+ this.setAttribute('z-index', `${this.zIndex}`);
410
+ }
411
+ if (changedProperties.has('append-to')) {
412
+ this.utils.setupAppendTo();
413
+ }
414
+ if (changedProperties.has('interactive')
415
+ || changedProperties.has('data-aria-label')
416
+ || changedProperties.has('data-aria-labelledby')) {
417
+ this.utils.setupAccessibility();
418
+ }
419
+ }
420
+ /**
421
+ * Handles the popover visibility change and position the popover.
422
+ * Handles the exit event to close the popover.
423
+ *
424
+ * @param oldValue - The old value of the visible property.
425
+ * @param newValue - The new value of the visible property.
426
+ */
427
+ async isOpenUpdated(oldValue, newValue) {
428
+ var _a, _b, _c, _d;
429
+ if (oldValue === newValue || !this.triggerElement) {
430
+ return;
431
+ }
432
+ if (newValue) {
433
+ this.enabledFocusTrap = this.focusTrap;
434
+ this.enabledPreventScroll = this.preventScroll;
435
+ if (this.backdrop) {
436
+ const popoverBackdrop = this.renderRoot.querySelector('.popover-backdrop');
437
+ popoverBackdrop.style.zIndex = `${this.zIndex - 1}`;
438
+ this.triggerElement.style.zIndex = `${this.zIndex}`;
439
+ }
440
+ this.positionPopover();
441
+ await this.handleCreatePopoverFirstUpdate();
442
+ if (this.hideOnBlur) {
443
+ (_a = this.containerElement) === null || _a === void 0 ? void 0 : _a.addEventListener('focusout', this.onPopoverFocusOut);
444
+ if (this.trigger === 'click') {
445
+ this.triggerElement.style.pointerEvents = 'none';
446
+ }
447
+ }
448
+ if (this.hideOnOutsideClick) {
449
+ document.addEventListener('click', this.onOutsidePopoverClick);
450
+ }
451
+ if (this.hideOnEscape) {
452
+ document.addEventListener('keydown', this.onEscapeKeydown);
453
+ }
454
+ this.triggerElement.setAttribute('aria-expanded', 'true');
455
+ if (this.interactive) {
456
+ this.triggerElement.setAttribute('aria-haspopup', this.triggerElement.getAttribute('aria-haspopup') || 'dialog');
457
+ }
458
+ }
459
+ else {
460
+ if (this.hideOnBlur) {
461
+ (_b = this.containerElement) === null || _b === void 0 ? void 0 : _b.removeEventListener('focusout', this.onPopoverFocusOut);
462
+ if (this.trigger === 'click') {
463
+ this.triggerElement.style.pointerEvents = '';
464
+ }
465
+ }
466
+ if (this.hideOnOutsideClick) {
467
+ document.removeEventListener('click', this.onOutsidePopoverClick);
468
+ }
469
+ if (this.hideOnEscape) {
470
+ document.removeEventListener('keydown', this.onEscapeKeydown);
471
+ }
472
+ (_c = this.deactivateFocusTrap) === null || _c === void 0 ? void 0 : _c.call(this);
473
+ this.triggerElement.removeAttribute('aria-expanded');
474
+ if (this.interactive) {
475
+ this.triggerElement.removeAttribute('aria-haspopup');
476
+ }
477
+ if (this.focusBackToTrigger) {
478
+ (_d = this.triggerElement) === null || _d === void 0 ? void 0 : _d.focus();
479
+ }
480
+ }
481
+ }
482
+ /**
483
+ * Sets the focusable elements inside the popover.
484
+ */
485
+ async handleCreatePopoverFirstUpdate() {
486
+ var _a, _b;
487
+ if (this.visible && this.interactive) {
488
+ (_a = this.setFocusableElements) === null || _a === void 0 ? void 0 : _a.call(this);
489
+ await this.updateComplete;
490
+ (_b = this.setInitialFocus) === null || _b === void 0 ? void 0 : _b.call(this);
491
+ }
492
+ }
493
+ /**
494
+ * Positions the popover based on the trigger element.
495
+ * It also handles the flip, size and arrow placement.
496
+ * It uses the floating-ui/dom library to calculate the position.
497
+ */
498
+ positionPopover() {
499
+ if (!this.triggerElement || !this.containerElement)
500
+ return;
501
+ const middleware = [shift()];
502
+ let popoverOffset = this.offset;
503
+ if (this.flip) {
504
+ middleware.push(flip());
505
+ }
506
+ if (this.size) {
507
+ const popoverContent = this.containerElement.querySelector('[part="popover-content"]');
508
+ middleware.push(size({
509
+ apply({ availableHeight }) {
510
+ if (!popoverContent)
511
+ return;
512
+ Object.assign(popoverContent.style, {
513
+ maxHeight: `${availableHeight}px`,
514
+ });
515
+ },
516
+ padding: 50,
517
+ }));
518
+ }
519
+ if (this.showArrow) {
520
+ this.arrowElement = this.renderRoot.querySelector('.popover-arrow');
521
+ if (this.arrowElement) {
522
+ const arrowLen = this.arrowElement.offsetHeight;
523
+ const arrowOffset = Math.sqrt(2 * arrowLen ** 2) / 2;
524
+ popoverOffset = arrowOffset + this.offset;
525
+ middleware.push(arrow({ element: this.arrowElement, padding: 12 }));
526
+ }
527
+ }
528
+ middleware.push(offset(popoverOffset));
529
+ autoUpdate(this.triggerElement, this.containerElement, async () => {
530
+ if (!this.triggerElement || !this.containerElement)
531
+ return;
532
+ const { x, y, middlewareData, placement } = await computePosition(this.triggerElement, this.containerElement, {
533
+ placement: this.placement,
534
+ middleware,
535
+ });
536
+ this.utils.updatePopoverStyle(x, y);
537
+ if (middlewareData.arrow && this.arrowElement) {
538
+ this.utils.updateArrowStyle(middlewareData.arrow, placement);
539
+ }
540
+ if (this.trigger.includes('mouseenter')) {
541
+ this.utils.setupHoverBridge(placement);
542
+ }
543
+ });
544
+ }
545
+ render() {
546
+ return html `
547
+ ${this.backdrop && this.visible ? html `<div class="popover-backdrop"></div>` : nothing}
548
+ <mdc-modalcontainer
549
+ class="popover-container"
550
+ elevation="3"
551
+ color=${this.color}
552
+ ?data-aria-modal=${this.interactive}
553
+ data-role="${ifDefined(this.dataRole)}"
554
+ data-aria-label="${ifDefined(this.interactive ? this.dataAriaLabel : undefined)}"
555
+ data-aria-labelledby="${ifDefined(this.interactive ? this.dataAriaLabelledby : undefined)}"
556
+ data-aria-describedby="${ifDefined(this.interactive ? this.dataAriaDescribedby : undefined)}"
557
+ style="z-index: ${this.zIndex};"
558
+ >
559
+ <div class="popover-hover-bridge"></div>
560
+ ${this.closeButton
561
+ ? html ` <mdc-button
562
+ class="popover-close"
563
+ prefix-icon="cancel-bold"
564
+ variant="tertiary"
565
+ size="20"
566
+ aria-label=${ifDefined(this.closeButtonAriaLabel)}
567
+ @click="${this.hidePopover}"
568
+ ></mdc-button>`
569
+ : nothing}
570
+ ${this.showArrow ? html `<div class="popover-arrow"></div>` : nothing}
571
+ <div part="popover-content">
572
+ <slot></slot>
573
+ </div>
574
+ </mdc-modalcontainer>
575
+ `;
576
+ }
577
+ }
578
+ Popover.styles = [...Component.styles, ...styles];
579
+ __decorate([
580
+ property({ type: String }),
581
+ __metadata("design:type", String)
582
+ ], Popover.prototype, "id", void 0);
583
+ __decorate([
584
+ property({ type: String }),
585
+ __metadata("design:type", String)
586
+ ], Popover.prototype, "triggerID", void 0);
587
+ __decorate([
588
+ property({ type: String, reflect: true }),
589
+ __metadata("design:type", String)
590
+ ], Popover.prototype, "trigger", void 0);
591
+ __decorate([
592
+ property({ type: String, reflect: true }),
593
+ __metadata("design:type", String)
594
+ ], Popover.prototype, "placement", void 0);
595
+ __decorate([
596
+ property({ type: String, reflect: true }),
597
+ __metadata("design:type", String)
598
+ ], Popover.prototype, "color", void 0);
599
+ __decorate([
600
+ property({ type: Boolean, reflect: true }),
601
+ __metadata("design:type", Boolean)
602
+ ], Popover.prototype, "visible", void 0);
603
+ __decorate([
604
+ property({ type: Number, reflect: true }),
605
+ __metadata("design:type", Number)
606
+ ], Popover.prototype, "offset", void 0);
607
+ __decorate([
608
+ property({ type: Boolean, reflect: true, attribute: 'focus-trap' }),
609
+ __metadata("design:type", Boolean)
610
+ ], Popover.prototype, "focusTrap", void 0);
611
+ __decorate([
612
+ property({ type: Boolean, reflect: true, attribute: 'prevent-scroll' }),
613
+ __metadata("design:type", Boolean)
614
+ ], Popover.prototype, "preventScroll", void 0);
615
+ __decorate([
616
+ property({ type: Boolean, attribute: 'show-arrow' }),
617
+ __metadata("design:type", Boolean)
618
+ ], Popover.prototype, "showArrow", void 0);
619
+ __decorate([
620
+ property({ type: Boolean, reflect: true, attribute: 'close-button' }),
621
+ __metadata("design:type", Boolean)
622
+ ], Popover.prototype, "closeButton", void 0);
623
+ __decorate([
624
+ property({ type: Boolean, reflect: true }),
625
+ __metadata("design:type", Boolean)
626
+ ], Popover.prototype, "interactive", void 0);
627
+ __decorate([
628
+ property({ type: String, reflect: true }),
629
+ __metadata("design:type", String)
630
+ ], Popover.prototype, "delay", void 0);
631
+ __decorate([
632
+ property({ type: Boolean, reflect: true, attribute: 'hide-on-escape' }),
633
+ __metadata("design:type", Boolean)
634
+ ], Popover.prototype, "hideOnEscape", void 0);
635
+ __decorate([
636
+ property({ type: Boolean, reflect: true, attribute: 'hide-on-blur' }),
637
+ __metadata("design:type", Boolean)
638
+ ], Popover.prototype, "hideOnBlur", void 0);
639
+ __decorate([
640
+ property({ type: Boolean, reflect: true, attribute: 'hide-on-outside-click' }),
641
+ __metadata("design:type", Boolean)
642
+ ], Popover.prototype, "hideOnOutsideClick", void 0);
643
+ __decorate([
644
+ property({ type: Boolean, reflect: true, attribute: 'focus-back-to-trigger' }),
645
+ __metadata("design:type", Boolean)
646
+ ], Popover.prototype, "focusBackToTrigger", void 0);
647
+ __decorate([
648
+ property({ type: Boolean, reflect: true }),
649
+ __metadata("design:type", Boolean)
650
+ ], Popover.prototype, "backdrop", void 0);
651
+ __decorate([
652
+ property({ type: Boolean, reflect: true }),
653
+ __metadata("design:type", Boolean)
654
+ ], Popover.prototype, "flip", void 0);
655
+ __decorate([
656
+ property({ type: Boolean, reflect: true }),
657
+ __metadata("design:type", Boolean)
658
+ ], Popover.prototype, "size", void 0);
659
+ __decorate([
660
+ property({ type: Number, reflect: true, attribute: 'z-index' }),
661
+ __metadata("design:type", Number)
662
+ ], Popover.prototype, "zIndex", void 0);
663
+ __decorate([
664
+ property({ type: String, reflect: true, attribute: 'append-to' }),
665
+ __metadata("design:type", String)
666
+ ], Popover.prototype, "appendTo", void 0);
667
+ __decorate([
668
+ property({ type: String, attribute: 'close-button-aria-label' }),
669
+ __metadata("design:type", Object)
670
+ ], Popover.prototype, "closeButtonAriaLabel", void 0);
671
+ __decorate([
672
+ property({ type: String, reflect: true, attribute: 'data-role' }),
673
+ __metadata("design:type", Object)
674
+ ], Popover.prototype, "dataRole", void 0);
675
+ export default Popover;