@vaadin/vaadin-overlay 21.0.1 → 22.0.0-alpha10

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,10 +1,29 @@
1
1
  {
2
2
  "name": "@vaadin/vaadin-overlay",
3
- "version": "21.0.1",
3
+ "version": "22.0.0-alpha10",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
4
7
  "description": "vaadin-overlay",
8
+ "license": "Apache-2.0",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/vaadin/web-components.git",
12
+ "directory": "packages/vaadin-overlay"
13
+ },
14
+ "author": "Vaadin Ltd",
15
+ "homepage": "https://vaadin.com/components",
16
+ "bugs": {
17
+ "url": "https://github.com/vaadin/vaadin-overlay/issues"
18
+ },
5
19
  "main": "vaadin-overlay.js",
6
20
  "module": "vaadin-overlay.js",
7
- "repository": "vaadin/vaadin-overlay",
21
+ "files": [
22
+ "src",
23
+ "theme",
24
+ "vaadin-*.d.ts",
25
+ "vaadin-*.js"
26
+ ],
8
27
  "keywords": [
9
28
  "Vaadin",
10
29
  "vaadin-overlay",
@@ -13,37 +32,22 @@
13
32
  "web-component",
14
33
  "polymer"
15
34
  ],
16
- "author": "Vaadin Ltd",
17
- "license": "Apache-2.0",
18
- "bugs": {
19
- "url": "https://github.com/vaadin/vaadin-overlay/issues"
20
- },
21
- "homepage": "https://vaadin.com/components",
22
- "files": [
23
- "vaadin-*.d.ts",
24
- "vaadin-*.js",
25
- "src",
26
- "theme"
27
- ],
28
35
  "dependencies": {
29
36
  "@polymer/polymer": "^3.0.0",
30
- "@vaadin/vaadin-element-mixin": "^21.0.1",
31
- "@vaadin/vaadin-lumo-styles": "^21.0.1",
32
- "@vaadin/vaadin-material-styles": "^21.0.1",
33
- "@vaadin/vaadin-themable-mixin": "^21.0.1"
37
+ "@vaadin/component-base": "22.0.0-alpha10",
38
+ "@vaadin/vaadin-lumo-styles": "22.0.0-alpha10",
39
+ "@vaadin/vaadin-material-styles": "22.0.0-alpha10",
40
+ "@vaadin/vaadin-themable-mixin": "22.0.0-alpha10"
34
41
  },
35
42
  "devDependencies": {
36
- "@esm-bundle/chai": "^4.1.5",
43
+ "@esm-bundle/chai": "^4.3.4",
37
44
  "@polymer/iron-overlay-behavior": "^3.0.0",
38
- "@vaadin/testing-helpers": "^0.2.1",
39
- "@vaadin/vaadin-button": "^21.0.1",
40
- "@vaadin/vaadin-radio-button": "^21.0.1",
41
- "@vaadin/vaadin-text-field": "^21.0.1",
42
- "lit": "^2.0.0-rc.1",
45
+ "@vaadin/button": "22.0.0-alpha10",
46
+ "@vaadin/radio-group": "22.0.0-alpha10",
47
+ "@vaadin/testing-helpers": "^0.3.0",
48
+ "@vaadin/text-field": "22.0.0-alpha10",
49
+ "lit": "^2.0.0",
43
50
  "sinon": "^9.2.1"
44
51
  },
45
- "publishConfig": {
46
- "access": "public"
47
- },
48
- "gitHead": "91e44dcfa63dc5e30e1e8d18be499b3e1e17b1c4"
52
+ "gitHead": "6d3055383b9c3c8306ea34c6f2e2087e63c49348"
49
53
  }
@@ -3,10 +3,21 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+
7
+ const PROP_NAMES_VERTICAL = {
8
+ start: 'top',
9
+ end: 'bottom'
10
+ };
11
+
12
+ const PROP_NAMES_HORIZONTAL = {
13
+ start: 'left',
14
+ end: 'right'
15
+ };
16
+
6
17
  /**
7
18
  * @polymerMixin
8
19
  */
9
- export const _PositionMixin = (superClass) =>
20
+ export const PositionMixin = (superClass) =>
10
21
  class PositionMixin extends superClass {
11
22
  static get properties() {
12
23
  return {
@@ -67,31 +78,45 @@ export const _PositionMixin = (superClass) =>
67
78
  }
68
79
  static get observers() {
69
80
  return [
70
- `__positionSettingsChanged(positionTarget, horizontalAlign, verticalAlign,
71
- noHorizontalOverlap, noVerticalOverlap)`
81
+ '__positionSettingsChanged(positionTarget, horizontalAlign, verticalAlign, noHorizontalOverlap, noVerticalOverlap)',
82
+ '__overlayOpenedChanged(opened)'
72
83
  ];
73
84
  }
74
85
 
75
86
  constructor() {
76
87
  super();
77
88
 
78
- const boundUpdatePosition = this._updatePosition.bind(this);
79
-
80
- this.addEventListener('opened-changed', (e) => {
81
- const func = e.detail.value ? 'addEventListener' : 'removeEventListener';
82
- window[func]('scroll', boundUpdatePosition);
83
- window[func]('resize', boundUpdatePosition);
89
+ this.__boundUpdatePosition = this._updatePosition.bind(this);
90
+ }
84
91
 
85
- if (e.detail.value) {
86
- this._updatePosition();
92
+ __overlayOpenedChanged(opened) {
93
+ // Toggle the event listeners that cause the overlay to update its position
94
+ ['scroll', 'resize'].forEach((eventName) => {
95
+ if (opened) {
96
+ window.addEventListener(eventName, this.__boundUpdatePosition);
97
+ } else {
98
+ window.removeEventListener(eventName, this.__boundUpdatePosition);
87
99
  }
88
100
  });
89
- }
90
101
 
91
- ready() {
92
- super.ready();
102
+ if (opened) {
103
+ const computedStyle = getComputedStyle(this);
104
+ if (!this.__margins) {
105
+ this.__margins = {};
106
+ ['top', 'bottom', 'left', 'right'].forEach((propName) => {
107
+ this.__margins[propName] = parseInt(computedStyle[propName], 10);
108
+ });
109
+ }
110
+ this.setAttribute('dir', computedStyle.direction);
93
111
 
94
- console.warn('PositionMixin is not considered stable and might change any time');
112
+ this._updatePosition();
113
+ // Schedule another position update (to cover virtual keyboard opening for example)
114
+ requestAnimationFrame(() => this._updatePosition());
115
+ }
116
+ }
117
+
118
+ get __isRTL() {
119
+ return this.getAttribute('dir') === 'rtl';
95
120
  }
96
121
 
97
122
  __positionSettingsChanged() {
@@ -99,33 +124,55 @@ export const _PositionMixin = (superClass) =>
99
124
  }
100
125
 
101
126
  _updatePosition() {
102
- if (!this.positionTarget) {
127
+ if (!this.positionTarget || !this.opened) {
103
128
  return;
104
129
  }
105
- const computedStyle = getComputedStyle(this);
106
- if (!this.__margins) {
107
- this.__margins = {};
108
- ['top', 'bottom', 'left', 'right'].forEach((propName) => {
109
- this.__margins[propName] = parseInt(computedStyle[propName], 10);
110
- });
111
- }
112
- const rtl = computedStyle.direction === 'rtl';
113
130
 
114
131
  const targetRect = this.positionTarget.getBoundingClientRect();
115
132
 
116
- const horizontalProps = this.__calculateHorizontalPosition(targetRect, rtl);
117
- const verticalProps = this.__calculateVerticalPosition(targetRect);
133
+ // Detect the desired alignment and update the layout accordingly
134
+ const shouldAlignStartVertically = this.__shouldAlignStartVertically(targetRect);
135
+ this.style.justifyContent = shouldAlignStartVertically ? 'flex-start' : 'flex-end';
118
136
 
119
- const positionProps = Object.assign({}, horizontalProps, verticalProps);
120
- this.__doSetPosition(positionProps, rtl);
121
- }
137
+ const shouldAlignStartHorizontally = this.__shouldAlignStartHorizontally(targetRect, this.__isRTL);
138
+ const flexStart =
139
+ (!this.__isRTL && shouldAlignStartHorizontally) || (this.__isRTL && !shouldAlignStartHorizontally);
140
+ this.style.alignItems = flexStart ? 'flex-start' : 'flex-end';
122
141
 
123
- __calculateHorizontalPosition(targetRect, rtl) {
124
- const propNames = {
125
- start: 'left',
126
- end: 'right'
127
- };
142
+ // Get the overlay rect after possible overlay alignment changes
143
+ const overlayRect = this.getBoundingClientRect();
144
+
145
+ // Obtain vertical positioning properties
146
+ const verticalProps = this.__calculatePositionInOneDimension(
147
+ targetRect,
148
+ overlayRect,
149
+ this.noVerticalOverlap,
150
+ PROP_NAMES_VERTICAL,
151
+ this,
152
+ shouldAlignStartVertically
153
+ );
154
+
155
+ // Obtain horizontal positioning properties
156
+ const horizontalProps = this.__calculatePositionInOneDimension(
157
+ targetRect,
158
+ overlayRect,
159
+ this.noHorizontalOverlap,
160
+ PROP_NAMES_HORIZONTAL,
161
+ this,
162
+ shouldAlignStartHorizontally
163
+ );
164
+
165
+ // Apply the positioning properties to the overlay
166
+ Object.assign(this.style, verticalProps, horizontalProps);
128
167
 
168
+ this.toggleAttribute('bottom-aligned', !shouldAlignStartVertically);
169
+ this.toggleAttribute('top-aligned', shouldAlignStartVertically);
170
+
171
+ this.toggleAttribute('end-aligned', !flexStart);
172
+ this.toggleAttribute('start-aligned', flexStart);
173
+ }
174
+
175
+ __shouldAlignStartHorizontally(targetRect, rtl) {
129
176
  // Using previous size to fix a case where window resize may cause the overlay to be squeezed
130
177
  // smaller than its current space before the fit-calculations.
131
178
  const contentWidth = Math.max(this.__oldContentWidth || 0, this.$.overlay.offsetWidth);
@@ -133,25 +180,19 @@ export const _PositionMixin = (superClass) =>
133
180
 
134
181
  const viewportWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
135
182
  const defaultAlignLeft = (!rtl && this.horizontalAlign === 'start') || (rtl && this.horizontalAlign === 'end');
136
- const currentAlignLeft = !!this.style.left;
137
- return PositionMixin.__calculatePositionInOneDimension(
183
+
184
+ return this.__shouldAlignStart(
138
185
  targetRect,
139
186
  contentWidth,
140
187
  viewportWidth,
141
188
  this.__margins,
142
189
  defaultAlignLeft,
143
- currentAlignLeft,
144
190
  this.noHorizontalOverlap,
145
- propNames
191
+ PROP_NAMES_HORIZONTAL
146
192
  );
147
193
  }
148
194
 
149
- __calculateVerticalPosition(targetRect) {
150
- const propNames = {
151
- start: 'top',
152
- end: 'bottom'
153
- };
154
-
195
+ __shouldAlignStartVertically(targetRect) {
155
196
  // Using previous size to fix a case where window resize may cause the overlay to be squeezed
156
197
  // smaller than its current space before the fit-calculations.
157
198
  const contentHeight = Math.max(this.__oldContentHeight || 0, this.$.overlay.offsetHeight);
@@ -159,33 +200,19 @@ export const _PositionMixin = (superClass) =>
159
200
 
160
201
  const viewportHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
161
202
  const defaultAlignTop = this.verticalAlign === 'top';
162
- const currentAlignTop = !!this.style.top;
163
- return PositionMixin.__calculatePositionInOneDimension(
203
+
204
+ return this.__shouldAlignStart(
164
205
  targetRect,
165
206
  contentHeight,
166
207
  viewportHeight,
167
208
  this.__margins,
168
209
  defaultAlignTop,
169
- currentAlignTop,
170
210
  this.noVerticalOverlap,
171
- propNames
211
+ PROP_NAMES_VERTICAL
172
212
  );
173
213
  }
174
214
 
175
- /**
176
- * Returns an object with CSS position properties to set,
177
- * e.g. { top: "100px", bottom: "" }
178
- */
179
- static __calculatePositionInOneDimension(
180
- targetRect,
181
- contentSize,
182
- viewportSize,
183
- margins,
184
- defaultAlignStart,
185
- currentAlignStart,
186
- noOverlap,
187
- propNames
188
- ) {
215
+ __shouldAlignStart(targetRect, contentSize, viewportSize, margins, defaultAlignStart, noOverlap, propNames) {
189
216
  const spaceForStartAlignment =
190
217
  viewportSize - targetRect[noOverlap ? propNames.end : propNames.start] - margins[propNames.end];
191
218
  const spaceForEndAlignment = targetRect[noOverlap ? propNames.start : propNames.end] - margins[propNames.start];
@@ -196,28 +223,26 @@ export const _PositionMixin = (superClass) =>
196
223
  const shouldGoToDefaultSide =
197
224
  spaceForDefaultAlignment > spaceForOtherAlignment || spaceForDefaultAlignment > contentSize;
198
225
 
199
- const shouldAlignStart = defaultAlignStart === shouldGoToDefaultSide;
226
+ return defaultAlignStart === shouldGoToDefaultSide;
227
+ }
200
228
 
229
+ /**
230
+ * Returns an object with CSS position properties to set,
231
+ * e.g. { top: "100px", bottom: "" }
232
+ */
233
+ __calculatePositionInOneDimension(targetRect, overlayRect, noOverlap, propNames, overlay, shouldAlignStart) {
201
234
  const cssPropNameToSet = shouldAlignStart ? propNames.start : propNames.end;
202
235
  const cssPropNameToClear = shouldAlignStart ? propNames.end : propNames.start;
203
236
 
204
- const cssPropValueToSet =
205
- (shouldAlignStart
206
- ? targetRect[noOverlap ? propNames.end : propNames.start]
207
- : viewportSize - targetRect[noOverlap ? propNames.start : propNames.end]) + 'px';
237
+ const currentValue = parseFloat(overlay.style[cssPropNameToSet] || getComputedStyle(overlay)[cssPropNameToSet]);
208
238
 
209
- const props = {};
210
- props[cssPropNameToSet] = cssPropValueToSet;
211
- props[cssPropNameToClear] = '';
212
- return props;
213
- }
214
-
215
- __doSetPosition(cssProps, rtl) {
216
- Object.assign(this.style, cssProps);
217
-
218
- const alignStart = (!rtl && cssProps.left) || (rtl && cssProps.right);
219
- this.style.alignItems = alignStart ? 'flex-start' : 'flex-end';
239
+ const diff =
240
+ overlayRect[shouldAlignStart ? propNames.start : propNames.end] -
241
+ targetRect[noOverlap === shouldAlignStart ? propNames.end : propNames.start];
220
242
 
221
- this.style.justifyContent = cssProps.top ? 'flex-start' : 'flex-end';
243
+ return {
244
+ [cssPropNameToSet]: currentValue + diff * (shouldAlignStart ? -1 : 1) + 'px',
245
+ [cssPropNameToClear]: ''
246
+ };
222
247
  }
223
248
  };
@@ -1,8 +1,23 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
1
7
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
2
8
 
3
- import { DirMixin } from '@vaadin/vaadin-element-mixin/vaadin-dir-mixin.js';
9
+ export type OverlayRenderer = (root: HTMLElement, owner: HTMLElement, model?: object) => void;
10
+
11
+ /**
12
+ * Fired when the `opened` property changes.
13
+ */
14
+ export type OverlayOpenedChangedEvent = CustomEvent<{ value: boolean }>;
4
15
 
5
- import { OverlayEventMap, OverlayRenderer } from './interfaces';
16
+ export interface OverlayElementEventMap {
17
+ 'opened-changed': OverlayOpenedChangedEvent;
18
+ }
19
+
20
+ export type OverlayEventMap = HTMLElementEventMap & OverlayElementEventMap;
6
21
 
7
22
  /**
8
23
  * `<vaadin-overlay>` is a Web Component for creating overlays. The content of the overlay
@@ -209,13 +224,6 @@ declare class OverlayElement extends ThemableMixin(DirMixin(HTMLElement)) {
209
224
  */
210
225
  requestContentUpdate(): void;
211
226
 
212
- /**
213
- * Manually invoke existing renderer.
214
- *
215
- * @deprecated Since Vaadin 21, `render()` is deprecated. Please use `requestContentUpdate()` instead.
216
- */
217
- render(): void;
218
-
219
227
  _isFocused(element: Element | null): boolean;
220
228
 
221
229
  _focusedIndex(elements: Array<Element | null> | null): number;
@@ -7,8 +7,8 @@ import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
7
7
  import { templatize } from '@polymer/polymer/lib/utils/templatize.js';
8
8
  import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
9
9
  import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
10
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
10
11
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
- import { DirMixin } from '@vaadin/vaadin-element-mixin/vaadin-dir-mixin.js';
12
12
  import { FocusablesHelper } from './vaadin-focusables-helper.js';
13
13
 
14
14
  /**
@@ -457,17 +457,6 @@ class OverlayElement extends ThemableMixin(DirMixin(PolymerElement)) {
457
457
  }
458
458
  }
459
459
 
460
- /**
461
- * Manually invoke existing renderer.
462
- *
463
- * @deprecated Since Vaadin 21, `render()` is deprecated. Please use `requestContentUpdate()` instead.
464
- */
465
- render() {
466
- console.warn('WARNING: Since Vaadin 21, render() is deprecated. Please use requestContentUpdate() instead.');
467
-
468
- this.requestContentUpdate();
469
- }
470
-
471
460
  /** @private */
472
461
  _ironOverlayCanceled(event) {
473
462
  event.preventDefault();
@@ -1,4 +1,4 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
- import '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
1
+ import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
+ import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
3
3
 
4
- registerStyles('vaadin-overlay', css``, { include: ['lumo-overlay'], moduleId: 'lumo-vaadin-overlay' });
4
+ registerStyles('vaadin-overlay', overlay, { moduleId: 'lumo-vaadin-overlay' });
@@ -1,4 +1,4 @@
1
- import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
- import '@vaadin/vaadin-material-styles/mixins/overlay.js';
1
+ import { registerStyles } from '@vaadin/vaadin-themable-mixin/register-styles.js';
2
+ import { overlay } from '@vaadin/vaadin-material-styles/mixins/overlay.js';
3
3
 
4
- registerStyles('vaadin-overlay', css``, { include: ['material-overlay'], moduleId: 'material-vaadin-overlay' });
4
+ registerStyles('vaadin-overlay', overlay, { moduleId: 'material-vaadin-overlay' });
@@ -1,2 +1 @@
1
1
  export * from './src/vaadin-overlay.js';
2
- export * from './src/interfaces';
@@ -1,12 +0,0 @@
1
- export type OverlayRenderer = (root: HTMLElement, owner: HTMLElement, model?: object) => void;
2
-
3
- /**
4
- * Fired when the `opened` property changes.
5
- */
6
- export type OverlayOpenedChangedEvent = CustomEvent<{ value: boolean }>;
7
-
8
- export interface OverlayElementEventMap {
9
- 'opened-changed': OverlayOpenedChangedEvent;
10
- }
11
-
12
- export type OverlayEventMap = HTMLElementEventMap & OverlayElementEventMap;