@vaadin/overlay 24.0.0-alpha9 → 24.0.0-beta2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/overlay",
3
- "version": "24.0.0-alpha9",
3
+ "version": "24.0.0-beta2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -36,16 +36,16 @@
36
36
  "dependencies": {
37
37
  "@open-wc/dedupe-mixin": "^1.3.0",
38
38
  "@polymer/polymer": "^3.0.0",
39
- "@vaadin/component-base": "24.0.0-alpha9",
40
- "@vaadin/vaadin-lumo-styles": "24.0.0-alpha9",
41
- "@vaadin/vaadin-material-styles": "24.0.0-alpha9",
42
- "@vaadin/vaadin-themable-mixin": "24.0.0-alpha9"
39
+ "@vaadin/component-base": "24.0.0-beta2",
40
+ "@vaadin/vaadin-lumo-styles": "24.0.0-beta2",
41
+ "@vaadin/vaadin-material-styles": "24.0.0-beta2",
42
+ "@vaadin/vaadin-themable-mixin": "24.0.0-beta2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@esm-bundle/chai": "^4.3.4",
46
- "@vaadin/testing-helpers": "^0.3.2",
46
+ "@vaadin/testing-helpers": "^0.4.0",
47
47
  "lit": "^2.0.0",
48
48
  "sinon": "^13.0.2"
49
49
  },
50
- "gitHead": "cc3f747164041566b300bde4b105d2475649e93f"
50
+ "gitHead": "00086f1f6d487f042f189c9b9ecd7ba736960888"
51
51
  }
@@ -54,4 +54,14 @@ export declare class PositionMixinClass {
54
54
  * @attr {boolean} no-vertical-overlap
55
55
  */
56
56
  noVerticalOverlap: boolean;
57
+
58
+ /**
59
+ * If the overlay content has no intrinsic height, this property can be used to set
60
+ * the minimum vertical space (in pixels) required by the overlay. Setting a value to
61
+ * the property effectively disables the content measurement in favor of using this
62
+ * fixed value for determining the open direction.
63
+ *
64
+ * @attr {number} required-vertical-space
65
+ */
66
+ requiredVerticalSpace: number;
57
67
  }
@@ -93,12 +93,25 @@ export const PositionMixin = (superClass) =>
93
93
  type: Boolean,
94
94
  value: false,
95
95
  },
96
+
97
+ /**
98
+ * If the overlay content has no intrinsic height, this property can be used to set
99
+ * the minimum vertical space (in pixels) required by the overlay. Setting a value to
100
+ * the property effectively disables the content measurement in favor of using this
101
+ * fixed value for determining the open direction.
102
+ *
103
+ * @attr {number} required-vertical-space
104
+ */
105
+ requiredVerticalSpace: {
106
+ type: Number,
107
+ value: 0,
108
+ },
96
109
  };
97
110
  }
98
111
 
99
112
  static get observers() {
100
113
  return [
101
- '__positionSettingsChanged(horizontalAlign, verticalAlign, noHorizontalOverlap, noVerticalOverlap)',
114
+ '__positionSettingsChanged(horizontalAlign, verticalAlign, noHorizontalOverlap, noVerticalOverlap, requiredVerticalSpace)',
102
115
  '__overlayOpenedChanged(opened, positionTarget)',
103
116
  ];
104
117
  }
@@ -262,7 +275,8 @@ export const PositionMixin = (superClass) =>
262
275
  __shouldAlignStartVertically(targetRect) {
263
276
  // Using previous size to fix a case where window resize may cause the overlay to be squeezed
264
277
  // smaller than its current space before the fit-calculations.
265
- const contentHeight = Math.max(this.__oldContentHeight || 0, this.$.overlay.offsetHeight);
278
+ const contentHeight =
279
+ this.requiredVerticalSpace || Math.max(this.__oldContentHeight || 0, this.$.overlay.offsetHeight);
266
280
  this.__oldContentHeight = this.$.overlay.offsetHeight;
267
281
 
268
282
  const viewportHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
@@ -20,25 +20,31 @@ export type OverlayOpenedChangedEvent = CustomEvent<{ value: boolean }>;
20
20
  export type OverlayOpenEvent = CustomEvent;
21
21
 
22
22
  /**
23
- * Fired before the overlay will be closed.
24
- * If canceled the closing of the overlay is canceled as well.
23
+ * Fired when the opened overlay is about to be closed.
24
+ * Calling `preventDefault()` on the event cancels the closing.
25
25
  */
26
26
  export type OverlayCloseEvent = CustomEvent;
27
27
 
28
28
  /**
29
- * Fired when the overlay will be closed.
29
+ * Fired after the overlay is closed.
30
+ */
31
+ export type OverlayClosedEvent = CustomEvent;
32
+
33
+ /**
34
+ * Fired when the overlay starts to close.
35
+ * Closing the overlay can be asynchronous depending on the animation.
30
36
  */
31
37
  export type OverlayClosingEvent = CustomEvent;
32
38
 
33
39
  /**
34
- * Fired before the overlay will be closed on outside click.
35
- * If canceled the closing of the overlay is canceled as well.
40
+ * Fired before the overlay is closed on outside click.
41
+ * Calling `preventDefault()` on the event cancels the closing.
36
42
  */
37
43
  export type OverlayOutsideClickEvent = CustomEvent<{ sourceEvent: MouseEvent }>;
38
44
 
39
45
  /**
40
- * Fired before the overlay will be closed on ESC button press.
41
- * If canceled the closing of the overlay is canceled as well.
46
+ * Fired before the overlay is closed on Escape key press.
47
+ * Calling `preventDefault()` on the event cancels the closing.
42
48
  */
43
49
  export type OverlayEscapePressEvent = CustomEvent<{ sourceEvent: KeyboardEvent }>;
44
50
 
@@ -46,6 +52,7 @@ export interface OverlayCustomEventMap {
46
52
  'opened-changed': OverlayOpenedChangedEvent;
47
53
  'vaadin-overlay-open': OverlayOpenEvent;
48
54
  'vaadin-overlay-close': OverlayCloseEvent;
55
+ 'vaadin-overlay-closed': OverlayClosedEvent;
49
56
  'vaadin-overlay-closing': OverlayClosingEvent;
50
57
  'vaadin-overlay-outside-click': OverlayOutsideClickEvent;
51
58
  'vaadin-overlay-escape-press': OverlayEscapePressEvent;
@@ -106,10 +113,11 @@ export type OverlayEventMap = HTMLElementEventMap & OverlayCustomEventMap;
106
113
  *
107
114
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
108
115
  * @fires {CustomEvent} vaadin-overlay-open - Fired after the overlay is opened.
109
- * @fires {CustomEvent} vaadin-overlay-close - Fired before the overlay will be closed. If canceled the closing of the overlay is canceled as well.
110
- * @fires {CustomEvent} vaadin-overlay-closing - Fired when the overlay will be closed.
111
- * @fires {CustomEvent} vaadin-overlay-outside-click - Fired before the overlay will be closed on outside click. If canceled the closing of the overlay is canceled as well.
112
- * @fires {CustomEvent} vaadin-overlay-escape-press - Fired before the overlay will be closed on ESC button press. If canceled the closing of the overlay is canceled as well.
116
+ * @fires {CustomEvent} vaadin-overlay-close - Fired when the opened overlay is about to be closed. Calling `preventDefault()` on the event cancels the closing.
117
+ * @fires {CustomEvent} vaadin-overlay-closing - Fired when the overlay starts to close. Closing the overlay can be asynchronous depending on the animation.
118
+ * @fires {CustomEvent} vaadin-overlay-closed - Fired after the overlay is closed.
119
+ * @fires {CustomEvent} vaadin-overlay-outside-click - Fired before the overlay is closed on outside click. Calling `preventDefault()` on the event cancels the closing.
120
+ * @fires {CustomEvent} vaadin-overlay-escape-press - Fired before the overlay is closed on Escape key press. Calling `preventDefault()` on the event cancels the closing.
113
121
  */
114
122
  declare class Overlay extends ThemableMixin(DirMixin(ControllerMixin(HTMLElement))) {
115
123
  /**
@@ -144,7 +152,7 @@ declare class Overlay extends ThemableMixin(DirMixin(ControllerMixin(HTMLElement
144
152
 
145
153
  /**
146
154
  * When true the overlay won't disable the main content, showing
147
- * it doesnt change the functionality of the user interface.
155
+ * it doesn't change the functionality of the user interface.
148
156
  */
149
157
  modeless: boolean;
150
158
 
@@ -171,6 +179,11 @@ declare class Overlay extends ThemableMixin(DirMixin(ControllerMixin(HTMLElement
171
179
  */
172
180
  restoreFocusNode?: HTMLElement;
173
181
 
182
+ /**
183
+ * Returns true if this is the last one in the opened overlays stack.
184
+ */
185
+ protected readonly _last: boolean;
186
+
174
187
  close(sourceEvent?: Event | null): void;
175
188
 
176
189
  /**
@@ -197,6 +210,14 @@ declare class Overlay extends ThemableMixin(DirMixin(ControllerMixin(HTMLElement
197
210
  listener: (this: Overlay, ev: OverlayEventMap[K]) => void,
198
211
  options?: EventListenerOptions | boolean,
199
212
  ): void;
213
+
214
+ protected _flushAnimation(type: 'closing' | 'opening'): void;
215
+
216
+ /**
217
+ * Whether to close the overlay on outside click or not.
218
+ * Override this method to customize the closing logic.
219
+ */
220
+ protected _shouldCloseOnOutsideClick(event: Event): boolean;
200
221
  }
201
222
 
202
223
  declare global {
@@ -65,10 +65,11 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
65
65
  *
66
66
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
67
67
  * @fires {CustomEvent} vaadin-overlay-open - Fired after the overlay is opened.
68
- * @fires {CustomEvent} vaadin-overlay-close - Fired before the overlay will be closed. If canceled the closing of the overlay is canceled as well.
69
- * @fires {CustomEvent} vaadin-overlay-closing - Fired when the overlay will be closed.
70
- * @fires {CustomEvent} vaadin-overlay-outside-click - Fired before the overlay will be closed on outside click. If canceled the closing of the overlay is canceled as well.
71
- * @fires {CustomEvent} vaadin-overlay-escape-press - Fired before the overlay will be closed on ESC button press. If canceled the closing of the overlay is canceled as well.
68
+ * @fires {CustomEvent} vaadin-overlay-close - Fired when the opened overlay is about to be closed. Calling `preventDefault()` on the event cancels the closing.
69
+ * @fires {CustomEvent} vaadin-overlay-closing - Fired when the overlay starts to close. Closing the overlay can be asynchronous depending on the animation.
70
+ * @fires {CustomEvent} vaadin-overlay-closed - Fired after the overlay is closed.
71
+ * @fires {CustomEvent} vaadin-overlay-outside-click - Fired before the overlay is closed on outside click. Calling `preventDefault()` on the event cancels the closing.
72
+ * @fires {CustomEvent} vaadin-overlay-escape-press - Fired before the overlay is closed on Escape key press. Calling `preventDefault()` on the event cancels the closing.
72
73
  *
73
74
  * @extends HTMLElement
74
75
  * @mixes ThemableMixin
@@ -202,7 +203,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
202
203
 
203
204
  /**
204
205
  * When true the overlay won't disable the main content, showing
205
- * it doesnt change the functionality of the user interface.
206
+ * it doesn't change the functionality of the user interface.
206
207
  * @type {boolean}
207
208
  */
208
209
  modeless: {
@@ -279,6 +280,16 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
279
280
  return ['_rendererOrDataChanged(renderer, owner, model, opened)'];
280
281
  }
281
282
 
283
+ /**
284
+ * Returns all attached overlays in visual stacking order.
285
+ * @private
286
+ */
287
+ static get __attachedInstances() {
288
+ return Array.from(document.body.children)
289
+ .filter((el) => el instanceof Overlay && !el.hasAttribute('closing'))
290
+ .sort((a, b) => a.__zIndex - b.__zIndex || 0);
291
+ }
292
+
282
293
  constructor() {
283
294
  super();
284
295
  this._boundMouseDownListener = this._mouseDownListener.bind(this);
@@ -294,6 +305,15 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
294
305
  this.__focusTrapController = new FocusTrapController(this);
295
306
  }
296
307
 
308
+ /**
309
+ * Returns true if this is the last one in the opened overlays stack
310
+ * @return {boolean}
311
+ * @protected
312
+ */
313
+ get _last() {
314
+ return this === Overlay.__attachedInstances.pop();
315
+ }
316
+
297
317
  /** @protected */
298
318
  ready() {
299
319
  super.ready();
@@ -333,8 +353,6 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
333
353
 
334
354
  /**
335
355
  * @param {Event=} sourceEvent
336
- * @event vaadin-overlay-close
337
- * fired before the `vaadin-overlay` will be closed. If canceled the closing of the overlay is canceled as well.
338
356
  */
339
357
  close(sourceEvent) {
340
358
  const evt = new CustomEvent('vaadin-overlay-close', {
@@ -392,12 +410,21 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
392
410
  }
393
411
 
394
412
  /**
395
- * We need to listen on 'click' / 'tap' event and capture it and close the overlay before
396
- * propagating the event to the listener in the button. Otherwise, if the clicked button would call
397
- * open(), this would happen: https://www.youtube.com/watch?v=Z86V_ICUCD4
413
+ * Whether to close the overlay on outside click or not.
414
+ * Override this method to customize the closing logic.
398
415
  *
399
- * @event vaadin-overlay-outside-click
400
- * fired before the `vaadin-overlay` will be closed on outside click. If canceled the closing of the overlay is canceled as well.
416
+ * @param {Event} _event
417
+ * @return {boolean}
418
+ * @protected
419
+ */
420
+ _shouldCloseOnOutsideClick(_event) {
421
+ return this._last;
422
+ }
423
+
424
+ /**
425
+ * Outside click listener used in capture phase to close the overlay before
426
+ * propagating the event to the listener on the element that triggered it.
427
+ * Otherwise, calling `open()` would result in closing and re-opening.
401
428
  *
402
429
  * @private
403
430
  */
@@ -407,7 +434,8 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
407
434
  this._mouseUpInside = false;
408
435
  return;
409
436
  }
410
- if (!this._last) {
437
+
438
+ if (!this._shouldCloseOnOutsideClick(event)) {
411
439
  return;
412
440
  }
413
441
 
@@ -424,9 +452,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
424
452
  }
425
453
 
426
454
  /**
427
- * @event vaadin-overlay-escape-press
428
- * fired before the `vaadin-overlay` will be closed on ESC button press. If canceled the closing of the overlay is canceled as well.
429
- *
455
+ * Listener used to close whe overlay on Escape press, if it is the last one.
430
456
  * @private
431
457
  */
432
458
  _keydownListener(event) {
@@ -453,12 +479,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
453
479
  }
454
480
  }
455
481
 
456
- /**
457
- * @event vaadin-overlay-open
458
- * fired after the `vaadin-overlay` is opened.
459
- *
460
- * @private
461
- */
482
+ /** @private */
462
483
  _openedChanged(opened, wasOpened) {
463
484
  if (opened) {
464
485
  // Store focused node.
@@ -503,18 +524,19 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
503
524
 
504
525
  /**
505
526
  * @return {boolean}
506
- * @protected
527
+ * @private
507
528
  */
508
529
  _shouldAnimate() {
509
- const name = getComputedStyle(this).getPropertyValue('animation-name');
510
- const hidden = getComputedStyle(this).getPropertyValue('display') === 'none';
530
+ const style = getComputedStyle(this);
531
+ const name = style.getPropertyValue('animation-name');
532
+ const hidden = style.getPropertyValue('display') === 'none';
511
533
  return !hidden && name && name !== 'none';
512
534
  }
513
535
 
514
536
  /**
515
537
  * @param {string} type
516
538
  * @param {Function} callback
517
- * @protected
539
+ * @private
518
540
  */
519
541
  _enqueueAnimation(type, callback) {
520
542
  const handler = `__${type}Handler`;
@@ -541,7 +563,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
541
563
  }
542
564
  }
543
565
 
544
- /** @protected */
566
+ /** @private */
545
567
  _animatedOpening() {
546
568
  if (this.parentNode === document.body && this.hasAttribute('closing')) {
547
569
  this._flushAnimation('closing');
@@ -561,7 +583,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
561
583
  }
562
584
  }
563
585
 
564
- /** @protected */
586
+ /** @private */
565
587
  _attachOverlay() {
566
588
  this._placeholder = document.createComment('vaadin-overlay-placeholder');
567
589
  this.parentNode.insertBefore(this._placeholder, this);
@@ -569,24 +591,20 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
569
591
  this.bringToFront();
570
592
  }
571
593
 
572
- /** @protected */
594
+ /** @private */
573
595
  _finishOpening() {
574
596
  this.removeAttribute('opening');
575
597
  }
576
598
 
577
- /** @protected */
599
+ /** @private */
578
600
  _finishClosing() {
579
601
  this._detachOverlay();
580
602
  this.$.overlay.style.removeProperty('pointer-events');
581
603
  this.removeAttribute('closing');
604
+ this.dispatchEvent(new CustomEvent('vaadin-overlay-closed'));
582
605
  }
583
606
 
584
- /**
585
- * @event vaadin-overlay-closing
586
- * Fired when the overlay will be closed.
587
- *
588
- * @protected
589
- */
607
+ /** @private */
590
608
  _animatedClosing() {
591
609
  if (this.hasAttribute('opening')) {
592
610
  this._flushAnimation('opening');
@@ -627,31 +645,12 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
627
645
  }
628
646
  }
629
647
 
630
- /** @protected */
648
+ /** @private */
631
649
  _detachOverlay() {
632
650
  this._placeholder.parentNode.insertBefore(this, this._placeholder);
633
651
  this._placeholder.parentNode.removeChild(this._placeholder);
634
652
  }
635
653
 
636
- /**
637
- * Returns all attached overlays in visual stacking order.
638
- * @private
639
- */
640
- static get __attachedInstances() {
641
- return Array.from(document.body.children)
642
- .filter((el) => el instanceof Overlay && !el.hasAttribute('closing'))
643
- .sort((a, b) => a.__zIndex - b.__zIndex || 0);
644
- }
645
-
646
- /**
647
- * Returns true if this is the last one in the opened overlays stack
648
- * @return {boolean}
649
- * @protected
650
- */
651
- get _last() {
652
- return this === Overlay.__attachedInstances.pop();
653
- }
654
-
655
654
  /** @private */
656
655
  _modelessChanged(modeless) {
657
656
  if (!modeless) {
@@ -665,7 +664,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
665
664
  }
666
665
  }
667
666
 
668
- /** @protected */
667
+ /** @private */
669
668
  _addGlobalListeners() {
670
669
  document.addEventListener('mousedown', this._boundMouseDownListener);
671
670
  document.addEventListener('mouseup', this._boundMouseUpListener);
@@ -674,7 +673,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
674
673
  document.documentElement.addEventListener('click', this._boundOutsideClickListener, true);
675
674
  }
676
675
 
677
- /** @protected */
676
+ /** @private */
678
677
  _enterModalState() {
679
678
  if (document.body.style.pointerEvents !== 'none') {
680
679
  // Set body pointer-events to 'none' to disable mouse interactions with
@@ -691,14 +690,14 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
691
690
  });
692
691
  }
693
692
 
694
- /** @protected */
693
+ /** @private */
695
694
  _removeGlobalListeners() {
696
695
  document.removeEventListener('mousedown', this._boundMouseDownListener);
697
696
  document.removeEventListener('mouseup', this._boundMouseUpListener);
698
697
  document.documentElement.removeEventListener('click', this._boundOutsideClickListener, true);
699
698
  }
700
699
 
701
- /** @protected */
700
+ /** @private */
702
701
  _exitModalState() {
703
702
  if (this._previousDocumentPointerEvents !== undefined) {
704
703
  // Restore body pointer-events
@@ -750,7 +749,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
750
749
 
751
750
  /**
752
751
  * @return {!Element}
753
- * @protected
752
+ * @private
754
753
  */
755
754
  _getActiveElement() {
756
755
  // Document.activeElement can be null
@@ -765,7 +764,7 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
765
764
  /**
766
765
  * @param {!Node} node
767
766
  * @return {boolean}
768
- * @protected
767
+ * @private
769
768
  */
770
769
  _deepContains(node) {
771
770
  if (this.contains(node)) {
@@ -793,6 +792,40 @@ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
793
792
  this.style.zIndex = zIndex;
794
793
  this.__zIndex = zIndex || parseFloat(getComputedStyle(this).zIndex);
795
794
  }
795
+
796
+ /**
797
+ * @event vaadin-overlay-open
798
+ * Fired after the overlay is opened.
799
+ */
800
+
801
+ /**
802
+ * @event vaadin-overlay-close
803
+ * Fired when the opened overlay is about to be closed.
804
+ * Calling `preventDefault()` on the event cancels the closing.
805
+ */
806
+
807
+ /**
808
+ * @event vaadin-overlay-closing
809
+ * Fired when the overlay starts to close.
810
+ * Closing the overlay can be asynchronous depending on the animation.
811
+ */
812
+
813
+ /**
814
+ * @event vaadin-overlay-closed
815
+ * Fired after the overlay is closed.
816
+ */
817
+
818
+ /**
819
+ * @event vaadin-overlay-escape-press
820
+ * Fired before the overlay is closed on Escape key press.
821
+ * Calling `preventDefault()` on the event cancels the closing.
822
+ */
823
+
824
+ /**
825
+ * @event vaadin-overlay-outside-click
826
+ * Fired before the overlay is closed on outside click.
827
+ * Calling `preventDefault()` on the event cancels the closing.
828
+ */
796
829
  }
797
830
 
798
831
  customElements.define(Overlay.is, Overlay);