@vaadin/dialog 24.0.0-alpha1 → 24.0.0-alpha11

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/dialog",
3
- "version": "24.0.0-alpha1",
3
+ "version": "24.0.0-alpha11",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -39,18 +39,18 @@
39
39
  "dependencies": {
40
40
  "@open-wc/dedupe-mixin": "^1.3.0",
41
41
  "@polymer/polymer": "^3.0.0",
42
- "@vaadin/component-base": "24.0.0-alpha1",
43
- "@vaadin/lit-renderer": "24.0.0-alpha1",
44
- "@vaadin/overlay": "24.0.0-alpha1",
45
- "@vaadin/vaadin-lumo-styles": "24.0.0-alpha1",
46
- "@vaadin/vaadin-material-styles": "24.0.0-alpha1",
47
- "@vaadin/vaadin-themable-mixin": "24.0.0-alpha1"
42
+ "@vaadin/component-base": "24.0.0-alpha11",
43
+ "@vaadin/lit-renderer": "24.0.0-alpha11",
44
+ "@vaadin/overlay": "24.0.0-alpha11",
45
+ "@vaadin/vaadin-lumo-styles": "24.0.0-alpha11",
46
+ "@vaadin/vaadin-material-styles": "24.0.0-alpha11",
47
+ "@vaadin/vaadin-themable-mixin": "24.0.0-alpha11"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@esm-bundle/chai": "^4.3.4",
51
- "@vaadin/polymer-legacy-adapter": "24.0.0-alpha1",
51
+ "@vaadin/polymer-legacy-adapter": "24.0.0-alpha11",
52
52
  "@vaadin/testing-helpers": "^0.3.2",
53
- "@vaadin/text-area": "24.0.0-alpha1",
53
+ "@vaadin/text-area": "24.0.0-alpha11",
54
54
  "lit": "^2.0.0",
55
55
  "sinon": "^13.0.2"
56
56
  },
@@ -58,5 +58,5 @@
58
58
  "web-types.json",
59
59
  "web-types.lit.json"
60
60
  ],
61
- "gitHead": "427527c27c4b27822d61fd41d38d7b170134770b"
61
+ "gitHead": "641b3d96ceeb3e503a093682ebe686afdd8c3a68"
62
62
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  /* eslint-disable max-classes-per-file */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  /* eslint-disable max-classes-per-file */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
7
+
8
+ export type DialogOverlayBounds = {
9
+ top: number;
10
+ left: number;
11
+ width: number;
12
+ height: number;
13
+ };
14
+
15
+ export type DialogOverlayBoundsParam =
16
+ | DialogOverlayBounds
17
+ | {
18
+ top?: number | string;
19
+ left?: number | string;
20
+ width?: number | string;
21
+ height?: number | string;
22
+ };
23
+
24
+ /**
25
+ * An element used internally by `<vaadin-dialog>`. Not intended to be used separately.
26
+ */
27
+ export class DialogOverlay extends Overlay {
28
+ /**
29
+ * Retrieves the coordinates of the overlay.
30
+ */
31
+ getBounds(): DialogOverlayBounds;
32
+
33
+ /**
34
+ * Updates the coordinates of the overlay.
35
+ */
36
+ setBounds(bounds: DialogOverlayBoundsParam): void;
37
+ }
38
+
39
+ declare global {
40
+ interface HTMLElementTagNameMap {
41
+ 'vaadin-dialog-overlay': DialogOverlay;
42
+ }
43
+ }
@@ -0,0 +1,376 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
7
+ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
+
9
+ registerStyles(
10
+ 'vaadin-dialog-overlay',
11
+ css`
12
+ [part='header'],
13
+ [part='header-content'],
14
+ [part='footer'] {
15
+ display: flex;
16
+ align-items: center;
17
+ flex-wrap: wrap;
18
+ flex: none;
19
+ pointer-events: none;
20
+ z-index: 1;
21
+ }
22
+
23
+ [part='header'] {
24
+ flex-wrap: nowrap;
25
+ }
26
+
27
+ ::slotted([slot='header-content']),
28
+ ::slotted([slot='title']),
29
+ ::slotted([slot='footer']) {
30
+ display: contents;
31
+ pointer-events: auto;
32
+ }
33
+
34
+ ::slotted([slot='title']) {
35
+ font: inherit !important;
36
+ overflow-wrap: anywhere;
37
+ }
38
+
39
+ [part='header-content'] {
40
+ flex: 1;
41
+ }
42
+
43
+ :host([has-title]) [part='header-content'],
44
+ [part='footer'] {
45
+ justify-content: flex-end;
46
+ }
47
+
48
+ :host(:not([has-title]):not([has-header])) [part='header'],
49
+ :host(:not([has-header])) [part='header-content'],
50
+ :host(:not([has-title])) [part='title'],
51
+ :host(:not([has-footer])) [part='footer'] {
52
+ display: none !important;
53
+ }
54
+
55
+ :host(:is([has-title], [has-header], [has-footer])) [part='content'] {
56
+ height: auto;
57
+ }
58
+
59
+ @media (min-height: 320px) {
60
+ :host(:is([has-title], [has-header], [has-footer])) .resizer-container {
61
+ overflow: hidden;
62
+ display: flex;
63
+ flex-direction: column;
64
+ }
65
+
66
+ :host(:is([has-title], [has-header], [has-footer])) [part='content'] {
67
+ flex: 1;
68
+ overflow: auto;
69
+ }
70
+ }
71
+
72
+ /*
73
+ NOTE(platosha): Make some min-width to prevent collapsing of the content
74
+ taking the parent width, e. g., <vaadin-grid> and such.
75
+ */
76
+ [part='content'] {
77
+ min-width: 12em; /* matches the default <vaadin-text-field> width */
78
+ }
79
+
80
+ :host([has-bounds-set]) [part='overlay'] {
81
+ max-width: none;
82
+ }
83
+ `,
84
+ { moduleId: 'vaadin-dialog-overlay-styles' },
85
+ );
86
+
87
+ let memoizedTemplate;
88
+
89
+ /**
90
+ * An element used internally by `<vaadin-dialog>`. Not intended to be used separately.
91
+ *
92
+ * @extends Overlay
93
+ * @private
94
+ */
95
+ export class DialogOverlay extends Overlay {
96
+ static get is() {
97
+ return 'vaadin-dialog-overlay';
98
+ }
99
+
100
+ static get template() {
101
+ if (!memoizedTemplate) {
102
+ memoizedTemplate = super.template.cloneNode(true);
103
+ const contentPart = memoizedTemplate.content.querySelector('[part="content"]');
104
+ const overlayPart = memoizedTemplate.content.querySelector('[part="overlay"]');
105
+ const resizerContainer = document.createElement('section');
106
+ resizerContainer.id = 'resizerContainer';
107
+ resizerContainer.classList.add('resizer-container');
108
+ resizerContainer.appendChild(contentPart);
109
+ overlayPart.appendChild(resizerContainer);
110
+
111
+ const headerContainer = document.createElement('header');
112
+ headerContainer.setAttribute('part', 'header');
113
+ resizerContainer.insertBefore(headerContainer, contentPart);
114
+
115
+ const titleContainer = document.createElement('div');
116
+ titleContainer.setAttribute('part', 'title');
117
+ headerContainer.appendChild(titleContainer);
118
+
119
+ const titleSlot = document.createElement('slot');
120
+ titleSlot.setAttribute('name', 'title');
121
+ titleContainer.appendChild(titleSlot);
122
+
123
+ const headerContentContainer = document.createElement('div');
124
+ headerContentContainer.setAttribute('part', 'header-content');
125
+ headerContainer.appendChild(headerContentContainer);
126
+
127
+ const headerSlot = document.createElement('slot');
128
+ headerSlot.setAttribute('name', 'header-content');
129
+ headerContentContainer.appendChild(headerSlot);
130
+
131
+ const footerContainer = document.createElement('footer');
132
+ footerContainer.setAttribute('part', 'footer');
133
+ resizerContainer.appendChild(footerContainer);
134
+
135
+ const footerSlot = document.createElement('slot');
136
+ footerSlot.setAttribute('name', 'footer');
137
+ footerContainer.appendChild(footerSlot);
138
+ }
139
+ return memoizedTemplate;
140
+ }
141
+
142
+ static get observers() {
143
+ return [
144
+ '_headerFooterRendererChange(headerRenderer, footerRenderer, opened)',
145
+ '_headerTitleChanged(headerTitle, opened)',
146
+ ];
147
+ }
148
+
149
+ static get properties() {
150
+ return {
151
+ modeless: Boolean,
152
+
153
+ withBackdrop: Boolean,
154
+
155
+ headerTitle: String,
156
+
157
+ headerRenderer: Function,
158
+
159
+ footerRenderer: Function,
160
+ };
161
+ }
162
+
163
+ /** @protected */
164
+ ready() {
165
+ super.ready();
166
+
167
+ // Update overflow attribute on resize
168
+ this.__resizeObserver = new ResizeObserver(() => {
169
+ this.__updateOverflow();
170
+ });
171
+ this.__resizeObserver.observe(this.$.resizerContainer);
172
+
173
+ // Update overflow attribute on scroll
174
+ this.$.content.addEventListener('scroll', () => {
175
+ this.__updateOverflow();
176
+ });
177
+ }
178
+
179
+ /** @private */
180
+ __createContainer(slot) {
181
+ const container = document.createElement('div');
182
+ container.setAttribute('slot', slot);
183
+ return container;
184
+ }
185
+
186
+ /** @private */
187
+ __clearContainer(container) {
188
+ container.innerHTML = '';
189
+ // Whenever a Lit-based renderer is used, it assigns a Lit part to the node it was rendered into.
190
+ // When clearing the rendered content, this part needs to be manually disposed of.
191
+ // Otherwise, using a Lit-based renderer on the same node will throw an exception or render nothing afterward.
192
+ delete container._$litPart$;
193
+ }
194
+
195
+ /** @private */
196
+ __initContainer(container, slot) {
197
+ if (container) {
198
+ // Reset existing container in case if a new renderer is set.
199
+ this.__clearContainer(container);
200
+ } else {
201
+ // Create the container, but wait to append it until requestContentUpdate is called.
202
+ container = this.__createContainer(slot);
203
+ }
204
+ return container;
205
+ }
206
+
207
+ /** @private */
208
+ _headerFooterRendererChange(headerRenderer, footerRenderer, opened) {
209
+ const headerRendererChanged = this.__oldHeaderRenderer !== headerRenderer;
210
+ this.__oldHeaderRenderer = headerRenderer;
211
+
212
+ const footerRendererChanged = this.__oldFooterRenderer !== footerRenderer;
213
+ this.__oldFooterRenderer = footerRenderer;
214
+
215
+ const openedChanged = this._oldOpenedFooterHeader !== opened;
216
+ this._oldOpenedFooterHeader = opened;
217
+
218
+ // Set attributes here to update styles before detecting content overflow
219
+ this.toggleAttribute('has-header', !!headerRenderer);
220
+ this.toggleAttribute('has-footer', !!footerRenderer);
221
+
222
+ if (headerRendererChanged) {
223
+ if (headerRenderer) {
224
+ this.headerContainer = this.__initContainer(this.headerContainer, 'header-content');
225
+ } else if (this.headerContainer) {
226
+ this.headerContainer.remove();
227
+ this.headerContainer = null;
228
+ this.__updateOverflow();
229
+ }
230
+ }
231
+
232
+ if (footerRendererChanged) {
233
+ if (footerRenderer) {
234
+ this.footerContainer = this.__initContainer(this.footerContainer, 'footer');
235
+ } else if (this.footerContainer) {
236
+ this.footerContainer.remove();
237
+ this.footerContainer = null;
238
+ this.__updateOverflow();
239
+ }
240
+ }
241
+
242
+ if (
243
+ (headerRenderer && (headerRendererChanged || openedChanged)) ||
244
+ (footerRenderer && (footerRendererChanged || openedChanged))
245
+ ) {
246
+ if (opened) {
247
+ this.requestContentUpdate();
248
+ }
249
+ }
250
+ }
251
+
252
+ /** @private */
253
+ _headerTitleChanged(headerTitle, opened) {
254
+ this.toggleAttribute('has-title', !!headerTitle);
255
+
256
+ if (opened && (headerTitle || this._oldHeaderTitle)) {
257
+ this.requestContentUpdate();
258
+ }
259
+ this._oldHeaderTitle = headerTitle;
260
+ }
261
+
262
+ /** @private */
263
+ _headerTitleRenderer() {
264
+ if (this.headerTitle) {
265
+ if (!this.headerTitleElement) {
266
+ this.headerTitleElement = document.createElement('h2');
267
+ this.headerTitleElement.setAttribute('slot', 'title');
268
+ this.headerTitleElement.classList.add('draggable');
269
+ }
270
+ this.appendChild(this.headerTitleElement);
271
+ this.headerTitleElement.textContent = this.headerTitle;
272
+ } else if (this.headerTitleElement) {
273
+ this.headerTitleElement.remove();
274
+ this.headerTitleElement = null;
275
+ }
276
+ }
277
+
278
+ /**
279
+ * @override
280
+ */
281
+ requestContentUpdate() {
282
+ super.requestContentUpdate();
283
+
284
+ if (this.headerContainer) {
285
+ // If a new renderer has been set, make sure to reattach the container
286
+ if (!this.headerContainer.parentElement) {
287
+ this.appendChild(this.headerContainer);
288
+ }
289
+
290
+ if (this.headerRenderer) {
291
+ // Only call header renderer after the container has been initialized
292
+ this.headerRenderer.call(this.owner, this.headerContainer, this.owner);
293
+ }
294
+ }
295
+
296
+ if (this.footerContainer) {
297
+ // If a new renderer has been set, make sure to reattach the container
298
+ if (!this.footerContainer.parentElement) {
299
+ this.appendChild(this.footerContainer);
300
+ }
301
+
302
+ if (this.footerRenderer) {
303
+ // Only call header renderer after the container has been initialized
304
+ this.footerRenderer.call(this.owner, this.footerContainer, this.owner);
305
+ }
306
+ }
307
+
308
+ this._headerTitleRenderer();
309
+
310
+ this.__updateOverflow();
311
+ }
312
+
313
+ /**
314
+ * Updates the coordinates of the overlay.
315
+ * @param {!DialogOverlayBoundsParam} bounds
316
+ */
317
+ setBounds(bounds) {
318
+ const overlay = this.$.overlay;
319
+ const parsedBounds = { ...bounds };
320
+
321
+ if (overlay.style.position !== 'absolute') {
322
+ overlay.style.position = 'absolute';
323
+ this.setAttribute('has-bounds-set', '');
324
+ }
325
+
326
+ Object.keys(parsedBounds).forEach((arg) => {
327
+ if (typeof parsedBounds[arg] === 'number') {
328
+ parsedBounds[arg] = `${parsedBounds[arg]}px`;
329
+ }
330
+ });
331
+
332
+ Object.assign(overlay.style, parsedBounds);
333
+ }
334
+
335
+ /**
336
+ * Retrieves the coordinates of the overlay.
337
+ * @return {!DialogOverlayBounds}
338
+ */
339
+ getBounds() {
340
+ const overlayBounds = this.$.overlay.getBoundingClientRect();
341
+ const containerBounds = this.getBoundingClientRect();
342
+ const top = overlayBounds.top - containerBounds.top;
343
+ const left = overlayBounds.left - containerBounds.left;
344
+ const width = overlayBounds.width;
345
+ const height = overlayBounds.height;
346
+ return { top, left, width, height };
347
+ }
348
+
349
+ /** @private */
350
+ __updateOverflow() {
351
+ let overflow = '';
352
+
353
+ // Only set "overflow" attribute if the dialog has a header, title or footer.
354
+ // Check for state attributes as extending components might not use renderers.
355
+ if (this.hasAttribute('has-header') || this.hasAttribute('has-footer') || this.headerTitle) {
356
+ const content = this.$.content;
357
+
358
+ if (content.scrollTop > 0) {
359
+ overflow += ' top';
360
+ }
361
+
362
+ if (content.scrollTop < content.scrollHeight - content.clientHeight) {
363
+ overflow += ' bottom';
364
+ }
365
+ }
366
+
367
+ const value = overflow.trim();
368
+ if (value.length > 0 && this.getAttribute('overflow') !== value) {
369
+ this.setAttribute('overflow', value);
370
+ } else if (value.length === 0 && this.hasAttribute('overflow')) {
371
+ this.removeAttribute('overflow');
372
+ }
373
+ }
374
+ }
375
+
376
+ customElements.define(DialogOverlay.is, DialogOverlay);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
 
@@ -1,20 +1,17 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
7
- import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
7
+ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
8
8
  import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
9
9
  import { DialogDraggableMixin } from './vaadin-dialog-draggable-mixin.js';
10
10
  import { DialogResizableMixin } from './vaadin-dialog-resizable-mixin.js';
11
11
 
12
- /**
13
- * An element used internally by `<vaadin-dialog>`. Not intended to be used separately.
14
- */
15
- export class DialogOverlay extends Overlay {}
12
+ export { DialogOverlay, DialogOverlayBounds, DialogOverlayBoundsParam } from './vaadin-dialog-overlay.js';
16
13
 
17
- export type DialogRenderer = (root: HTMLElement, dialog?: Dialog) => void;
14
+ export type DialogRenderer = (root: HTMLElement, dialog: Dialog) => void;
18
15
 
19
16
  export type DialogResizableDirection = 'e' | 'n' | 'ne' | 'nw' | 's' | 'se' | 'sw' | 'w';
20
17
 
@@ -25,22 +22,6 @@ export type DialogResizeDimensions = {
25
22
  contentHeight: string;
26
23
  };
27
24
 
28
- export type DialogOverlayBounds = {
29
- top: number;
30
- left: number;
31
- width: number;
32
- height: number;
33
- };
34
-
35
- export type DialogOverlayBoundsParam =
36
- | DialogOverlayBounds
37
- | {
38
- top?: number | string;
39
- left?: number | string;
40
- width?: number | string;
41
- height?: number | string;
42
- };
43
-
44
25
  /**
45
26
  * Fired when the `opened` property changes.
46
27
  */
@@ -120,7 +101,9 @@ export type DialogEventMap = DialogCustomEventMap & HTMLElementEventMap;
120
101
  * @fires {CustomEvent} resize - Fired when the dialog resize is finished.
121
102
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
122
103
  */
123
- declare class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(DialogResizableMixin(HTMLElement)))) {
104
+ declare class Dialog extends OverlayClassMixin(
105
+ ThemePropertyMixin(ElementMixin(DialogDraggableMixin(DialogResizableMixin(HTMLElement)))),
106
+ ) {
124
107
  /**
125
108
  * True if the overlay is currently displayed.
126
109
  */
@@ -221,7 +204,6 @@ declare class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixi
221
204
  declare global {
222
205
  interface HTMLElementTagNameMap {
223
206
  'vaadin-dialog': Dialog;
224
- 'vaadin-dialog-overlay': DialogOverlay;
225
207
  }
226
208
  }
227
209
 
@@ -1,399 +1,18 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import './vaadin-dialog-overlay.js';
6
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
8
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
9
+ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
8
10
  import { processTemplates } from '@vaadin/component-base/src/templates.js';
9
- import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
10
- import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
11
  import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
12
12
  import { DialogDraggableMixin } from './vaadin-dialog-draggable-mixin.js';
13
13
  import { DialogResizableMixin } from './vaadin-dialog-resizable-mixin.js';
14
14
 
15
- registerStyles(
16
- 'vaadin-dialog-overlay',
17
- css`
18
- [part='header'],
19
- [part='header-content'],
20
- [part='footer'] {
21
- display: flex;
22
- align-items: center;
23
- flex-wrap: wrap;
24
- flex: none;
25
- pointer-events: none;
26
- z-index: 1;
27
- }
28
-
29
- [part='header'] {
30
- flex-wrap: nowrap;
31
- }
32
-
33
- ::slotted([slot='header-content']),
34
- ::slotted([slot='title']),
35
- ::slotted([slot='footer']) {
36
- display: contents;
37
- pointer-events: auto;
38
- }
39
-
40
- ::slotted([slot='title']) {
41
- font: inherit !important;
42
- overflow-wrap: anywhere;
43
- }
44
-
45
- [part='header-content'] {
46
- flex: 1;
47
- }
48
-
49
- :host([has-title]) [part='header-content'],
50
- [part='footer'] {
51
- justify-content: flex-end;
52
- }
53
-
54
- :host(:not([has-title]):not([has-header])) [part='header'],
55
- :host(:not([has-header])) [part='header-content'],
56
- :host(:not([has-title])) [part='title'],
57
- :host(:not([has-footer])) [part='footer'] {
58
- display: none !important;
59
- }
60
-
61
- :host(:is([has-title], [has-header], [has-footer])) [part='content'] {
62
- height: auto;
63
- }
64
-
65
- @media (min-height: 320px) {
66
- :host(:is([has-title], [has-header], [has-footer])) .resizer-container {
67
- overflow: hidden;
68
- display: flex;
69
- flex-direction: column;
70
- }
71
-
72
- :host(:is([has-title], [has-header], [has-footer])) [part='content'] {
73
- flex: 1;
74
- overflow: auto;
75
- }
76
- }
77
-
78
- /*
79
- NOTE(platosha): Make some min-width to prevent collapsing of the content
80
- taking the parent width, e. g., <vaadin-grid> and such.
81
- */
82
- [part='content'] {
83
- min-width: 12em; /* matches the default <vaadin-text-field> width */
84
- }
85
-
86
- :host([has-bounds-set]) [part='overlay'] {
87
- max-width: none;
88
- }
89
- `,
90
- { moduleId: 'vaadin-dialog-overlay-styles' },
91
- );
92
-
93
- let memoizedTemplate;
94
-
95
- /**
96
- * An element used internally by `<vaadin-dialog>`. Not intended to be used separately.
97
- *
98
- * @extends Overlay
99
- * @private
100
- */
101
- export class DialogOverlay extends Overlay {
102
- static get is() {
103
- return 'vaadin-dialog-overlay';
104
- }
105
-
106
- static get template() {
107
- if (!memoizedTemplate) {
108
- memoizedTemplate = super.template.cloneNode(true);
109
- const contentPart = memoizedTemplate.content.querySelector('[part="content"]');
110
- const overlayPart = memoizedTemplate.content.querySelector('[part="overlay"]');
111
- const resizerContainer = document.createElement('section');
112
- resizerContainer.id = 'resizerContainer';
113
- resizerContainer.classList.add('resizer-container');
114
- resizerContainer.appendChild(contentPart);
115
- overlayPart.appendChild(resizerContainer);
116
-
117
- const headerContainer = document.createElement('header');
118
- headerContainer.setAttribute('part', 'header');
119
- resizerContainer.insertBefore(headerContainer, contentPart);
120
-
121
- const titleContainer = document.createElement('div');
122
- titleContainer.setAttribute('part', 'title');
123
- headerContainer.appendChild(titleContainer);
124
-
125
- const titleSlot = document.createElement('slot');
126
- titleSlot.setAttribute('name', 'title');
127
- titleContainer.appendChild(titleSlot);
128
-
129
- const headerContentContainer = document.createElement('div');
130
- headerContentContainer.setAttribute('part', 'header-content');
131
- headerContainer.appendChild(headerContentContainer);
132
-
133
- const headerSlot = document.createElement('slot');
134
- headerSlot.setAttribute('name', 'header-content');
135
- headerContentContainer.appendChild(headerSlot);
136
-
137
- const footerContainer = document.createElement('footer');
138
- footerContainer.setAttribute('part', 'footer');
139
- resizerContainer.appendChild(footerContainer);
140
-
141
- const footerSlot = document.createElement('slot');
142
- footerSlot.setAttribute('name', 'footer');
143
- footerContainer.appendChild(footerSlot);
144
- }
145
- return memoizedTemplate;
146
- }
147
-
148
- static get observers() {
149
- return [
150
- '_headerFooterRendererChange(headerRenderer, footerRenderer, opened)',
151
- '_headerTitleChanged(headerTitle, opened)',
152
- ];
153
- }
154
-
155
- static get properties() {
156
- return {
157
- modeless: Boolean,
158
-
159
- withBackdrop: Boolean,
160
-
161
- headerTitle: String,
162
-
163
- headerRenderer: Function,
164
-
165
- footerRenderer: Function,
166
- };
167
- }
168
-
169
- /** @protected */
170
- ready() {
171
- super.ready();
172
-
173
- // Update overflow attribute on resize
174
- this.__resizeObserver = new ResizeObserver(() => {
175
- this.__updateOverflow();
176
- });
177
- this.__resizeObserver.observe(this.$.resizerContainer);
178
-
179
- // Update overflow attribute on scroll
180
- this.$.content.addEventListener('scroll', () => {
181
- this.__updateOverflow();
182
- });
183
- }
184
-
185
- /** @private */
186
- __createContainer(slot) {
187
- const container = document.createElement('div');
188
- container.setAttribute('slot', slot);
189
- return container;
190
- }
191
-
192
- /** @private */
193
- __clearContainer(container) {
194
- container.innerHTML = '';
195
- // Whenever a Lit-based renderer is used, it assigns a Lit part to the node it was rendered into.
196
- // When clearing the rendered content, this part needs to be manually disposed of.
197
- // Otherwise, using a Lit-based renderer on the same node will throw an exception or render nothing afterward.
198
- delete container._$litPart$;
199
- }
200
-
201
- /** @private */
202
- __initContainer(container, slot) {
203
- if (container) {
204
- // Reset existing container in case if a new renderer is set.
205
- this.__clearContainer(container);
206
- } else {
207
- // Create the container, but wait to append it until requestContentUpdate is called.
208
- container = this.__createContainer(slot);
209
- }
210
- return container;
211
- }
212
-
213
- /** @private */
214
- _headerFooterRendererChange(headerRenderer, footerRenderer, opened) {
215
- const headerRendererChanged = this.__oldHeaderRenderer !== headerRenderer;
216
- this.__oldHeaderRenderer = headerRenderer;
217
-
218
- const footerRendererChanged = this.__oldFooterRenderer !== footerRenderer;
219
- this.__oldFooterRenderer = footerRenderer;
220
-
221
- const openedChanged = this._oldOpenedFooterHeader !== opened;
222
- this._oldOpenedFooterHeader = opened;
223
-
224
- // Set attributes here to update styles before detecting content overflow
225
- this.toggleAttribute('has-header', !!headerRenderer);
226
- this.toggleAttribute('has-footer', !!footerRenderer);
227
-
228
- if (headerRendererChanged) {
229
- if (headerRenderer) {
230
- this.headerContainer = this.__initContainer(this.headerContainer, 'header-content');
231
- } else if (this.headerContainer) {
232
- this.headerContainer.remove();
233
- this.headerContainer = null;
234
- this.__updateOverflow();
235
- }
236
- }
237
-
238
- if (footerRendererChanged) {
239
- if (footerRenderer) {
240
- this.footerContainer = this.__initContainer(this.footerContainer, 'footer');
241
- } else if (this.footerContainer) {
242
- this.footerContainer.remove();
243
- this.footerContainer = null;
244
- this.__updateOverflow();
245
- }
246
- }
247
-
248
- if (
249
- (headerRenderer && (headerRendererChanged || openedChanged)) ||
250
- (footerRenderer && (footerRendererChanged || openedChanged))
251
- ) {
252
- if (opened) {
253
- this.requestContentUpdate();
254
- }
255
- }
256
- }
257
-
258
- /** @private */
259
- _headerTitleChanged(headerTitle, opened) {
260
- this.toggleAttribute('has-title', !!headerTitle);
261
-
262
- if (opened && (headerTitle || this._oldHeaderTitle)) {
263
- this.requestContentUpdate();
264
- }
265
- this._oldHeaderTitle = headerTitle;
266
- }
267
-
268
- /** @private */
269
- _headerTitleRenderer() {
270
- if (this.headerTitle) {
271
- if (!this.headerTitleElement) {
272
- this.headerTitleElement = document.createElement('h2');
273
- this.headerTitleElement.setAttribute('slot', 'title');
274
- this.headerTitleElement.classList.add('draggable');
275
- }
276
- this.appendChild(this.headerTitleElement);
277
- this.headerTitleElement.textContent = this.headerTitle;
278
- } else if (this.headerTitleElement) {
279
- this.headerTitleElement.remove();
280
- this.headerTitleElement = null;
281
- }
282
- }
283
-
284
- requestContentUpdate() {
285
- super.requestContentUpdate();
286
-
287
- if (this.headerContainer) {
288
- // If a new renderer has been set, make sure to reattach the container
289
- if (!this.headerContainer.parentElement) {
290
- this.appendChild(this.headerContainer);
291
- }
292
-
293
- if (this.headerRenderer) {
294
- // Only call header renderer after the container has been initialized
295
- this.headerRenderer.call(this.owner, this.headerContainer, this.owner);
296
- }
297
- }
298
-
299
- if (this.footerContainer) {
300
- // If a new renderer has been set, make sure to reattach the container
301
- if (!this.footerContainer.parentElement) {
302
- this.appendChild(this.footerContainer);
303
- }
304
-
305
- if (this.footerRenderer) {
306
- // Only call header renderer after the container has been initialized
307
- this.footerRenderer.call(this.owner, this.footerContainer, this.owner);
308
- }
309
- }
310
-
311
- this._headerTitleRenderer();
312
-
313
- this.__updateOverflow();
314
- }
315
-
316
- /**
317
- * Updates the coordinates of the overlay.
318
- * @param {!DialogOverlayBoundsParam} bounds
319
- */
320
- setBounds(bounds) {
321
- const overlay = this.$.overlay;
322
- const parsedBounds = { ...bounds };
323
-
324
- if (overlay.style.position !== 'absolute') {
325
- overlay.style.position = 'absolute';
326
- this.setAttribute('has-bounds-set', '');
327
- this.__forceSafariReflow();
328
- }
329
-
330
- Object.keys(parsedBounds).forEach((arg) => {
331
- if (typeof parsedBounds[arg] === 'number') {
332
- parsedBounds[arg] = `${parsedBounds[arg]}px`;
333
- }
334
- });
335
-
336
- Object.assign(overlay.style, parsedBounds);
337
- }
338
-
339
- /**
340
- * Retrieves the coordinates of the overlay.
341
- * @return {!DialogOverlayBounds}
342
- */
343
- getBounds() {
344
- const overlayBounds = this.$.overlay.getBoundingClientRect();
345
- const containerBounds = this.getBoundingClientRect();
346
- const top = overlayBounds.top - containerBounds.top;
347
- const left = overlayBounds.left - containerBounds.left;
348
- const width = overlayBounds.width;
349
- const height = overlayBounds.height;
350
- return { top, left, width, height };
351
- }
352
-
353
- /**
354
- * Safari 13 renders overflowing elements incorrectly.
355
- * This forces it to recalculate height.
356
- * @private
357
- */
358
- __forceSafariReflow() {
359
- const scrollPosition = this.$.resizerContainer.scrollTop;
360
- const overlay = this.$.overlay;
361
- overlay.style.display = 'block';
362
-
363
- requestAnimationFrame(() => {
364
- overlay.style.display = '';
365
- this.$.resizerContainer.scrollTop = scrollPosition;
366
- });
367
- }
368
-
369
- /** @private */
370
- __updateOverflow() {
371
- let overflow = '';
372
-
373
- // Only set "overflow" attribute if the dialog has a header, title or footer.
374
- // Check for state attributes as extending components might not use renderers.
375
- if (this.hasAttribute('has-header') || this.hasAttribute('has-footer') || this.headerTitle) {
376
- const content = this.$.content;
377
-
378
- if (content.scrollTop > 0) {
379
- overflow += ' top';
380
- }
381
-
382
- if (content.scrollTop < content.scrollHeight - content.clientHeight) {
383
- overflow += ' bottom';
384
- }
385
- }
386
-
387
- const value = overflow.trim();
388
- if (value.length > 0 && this.getAttribute('overflow') !== value) {
389
- this.setAttribute('overflow', value);
390
- } else if (value.length === 0 && this.hasAttribute('overflow')) {
391
- this.removeAttribute('overflow');
392
- }
393
- }
394
- }
395
-
396
- customElements.define(DialogOverlay.is, DialogOverlay);
15
+ export { DialogOverlay } from './vaadin-dialog-overlay.js';
397
16
 
398
17
  /**
399
18
  * `<vaadin-dialog>` is a Web Component for creating customized modal dialogs.
@@ -461,8 +80,11 @@ customElements.define(DialogOverlay.is, DialogOverlay);
461
80
  * @mixes ElementMixin
462
81
  * @mixes DialogDraggableMixin
463
82
  * @mixes DialogResizableMixin
83
+ * @mixes OverlayClassMixin
464
84
  */
465
- class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(DialogResizableMixin(PolymerElement)))) {
85
+ class Dialog extends OverlayClassMixin(
86
+ ThemePropertyMixin(ElementMixin(DialogDraggableMixin(DialogResizableMixin(PolymerElement)))),
87
+ ) {
466
88
  static get template() {
467
89
  return html`
468
90
  <style>
@@ -604,9 +226,14 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
604
226
  /** @protected */
605
227
  ready() {
606
228
  super.ready();
607
- this.$.overlay.setAttribute('role', 'dialog');
608
- this.$.overlay.addEventListener('vaadin-overlay-outside-click', this._handleOutsideClick.bind(this));
609
- this.$.overlay.addEventListener('vaadin-overlay-escape-press', this._handleEscPress.bind(this));
229
+
230
+ const overlay = this.$.overlay;
231
+ overlay.setAttribute('role', 'dialog');
232
+
233
+ overlay.addEventListener('vaadin-overlay-outside-click', this._handleOutsideClick.bind(this));
234
+ overlay.addEventListener('vaadin-overlay-escape-press', this._handleEscPress.bind(this));
235
+
236
+ this._overlayElement = overlay;
610
237
 
611
238
  processTemplates(this);
612
239
  }
@@ -619,7 +246,9 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
619
246
  * It is not guaranteed that the update happens immediately (synchronously) after it is requested.
620
247
  */
621
248
  requestContentUpdate() {
622
- this.$.overlay.requestContentUpdate();
249
+ if (this.$) {
250
+ this.$.overlay.requestContentUpdate();
251
+ }
623
252
  }
624
253
 
625
254
  /** @private */
package/web-types.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/dialog",
4
- "version": "24.0.0-alpha1",
4
+ "version": "24.0.0-alpha11",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-dialog",
11
- "description": "`<vaadin-dialog>` is a Web Component for creating customized modal dialogs.\n\n### Rendering\n\nThe content of the dialog can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `dialog` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `dialog`. Before generating new content,\nusers are able to check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-dialog id=\"dialog\"></vaadin-dialog>\n```\n```js\nconst dialog = document.querySelector('#dialog');\ndialog.renderer = function(root, dialog) {\n root.textContent = \"Sample dialog\";\n};\n```\n\nRenderer is called on the opening of the dialog.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### Styling\n\n`<vaadin-dialog>` uses `<vaadin-dialog-overlay>` internal\nthemable component as the actual visible dialog overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha1/#/elements/vaadin-overlay) documentation.\nfor `<vaadin-dialog-overlay>` parts.\n\nIn addition to `<vaadin-overlay>` parts, the following parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`header` | Element wrapping title and header content\n`header-content` | Element wrapping the header content slot\n`title` | Element wrapping the title slot\n`footer` | Element wrapping the footer slot\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|--------------------------------------------\n`has-title` | Set when the element has a title\n`has-header` | Set when the element has header renderer\n`has-footer` | Set when the element has footer renderer\n`overflow` | Set to `top`, `bottom`, none or both\n\nNote: the `theme` attribute value set on `<vaadin-dialog>` is\npropagated to the internal `<vaadin-dialog-overlay>` component.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
11
+ "description": "`<vaadin-dialog>` is a Web Component for creating customized modal dialogs.\n\n### Rendering\n\nThe content of the dialog can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `dialog` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `dialog`. Before generating new content,\nusers are able to check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-dialog id=\"dialog\"></vaadin-dialog>\n```\n```js\nconst dialog = document.querySelector('#dialog');\ndialog.renderer = function(root, dialog) {\n root.textContent = \"Sample dialog\";\n};\n```\n\nRenderer is called on the opening of the dialog.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### Styling\n\n`<vaadin-dialog>` uses `<vaadin-dialog-overlay>` internal\nthemable component as the actual visible dialog overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha11/#/elements/vaadin-overlay) documentation.\nfor `<vaadin-dialog-overlay>` parts.\n\nIn addition to `<vaadin-overlay>` parts, the following parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`header` | Element wrapping title and header content\n`header-content` | Element wrapping the header content slot\n`title` | Element wrapping the title slot\n`footer` | Element wrapping the footer slot\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|--------------------------------------------\n`has-title` | Set when the element has a title\n`has-header` | Set when the element has header renderer\n`has-footer` | Set when the element has footer renderer\n`overflow` | Set to `top`, `bottom`, none or both\n\nNote: the `theme` attribute value set on `<vaadin-dialog>` is\npropagated to the internal `<vaadin-dialog-overlay>` component.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "draggable",
@@ -28,6 +28,17 @@
28
28
  ]
29
29
  }
30
30
  },
31
+ {
32
+ "name": "overlay-class",
33
+ "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
34
+ "value": {
35
+ "type": [
36
+ "string",
37
+ "null",
38
+ "undefined"
39
+ ]
40
+ }
41
+ },
31
42
  {
32
43
  "name": "opened",
33
44
  "description": "True if the overlay is currently displayed.",
@@ -118,6 +129,17 @@
118
129
  ]
119
130
  }
120
131
  },
132
+ {
133
+ "name": "overlayClass",
134
+ "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
135
+ "value": {
136
+ "type": [
137
+ "string",
138
+ "null",
139
+ "undefined"
140
+ ]
141
+ }
142
+ },
121
143
  {
122
144
  "name": "opened",
123
145
  "description": "True if the overlay is currently displayed.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/dialog",
4
- "version": "24.0.0-alpha1",
4
+ "version": "24.0.0-alpha11",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -16,7 +16,7 @@
16
16
  "elements": [
17
17
  {
18
18
  "name": "vaadin-dialog",
19
- "description": "`<vaadin-dialog>` is a Web Component for creating customized modal dialogs.\n\n### Rendering\n\nThe content of the dialog can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `dialog` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `dialog`. Before generating new content,\nusers are able to check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-dialog id=\"dialog\"></vaadin-dialog>\n```\n```js\nconst dialog = document.querySelector('#dialog');\ndialog.renderer = function(root, dialog) {\n root.textContent = \"Sample dialog\";\n};\n```\n\nRenderer is called on the opening of the dialog.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### Styling\n\n`<vaadin-dialog>` uses `<vaadin-dialog-overlay>` internal\nthemable component as the actual visible dialog overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha1/#/elements/vaadin-overlay) documentation.\nfor `<vaadin-dialog-overlay>` parts.\n\nIn addition to `<vaadin-overlay>` parts, the following parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`header` | Element wrapping title and header content\n`header-content` | Element wrapping the header content slot\n`title` | Element wrapping the title slot\n`footer` | Element wrapping the footer slot\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|--------------------------------------------\n`has-title` | Set when the element has a title\n`has-header` | Set when the element has header renderer\n`has-footer` | Set when the element has footer renderer\n`overflow` | Set to `top`, `bottom`, none or both\n\nNote: the `theme` attribute value set on `<vaadin-dialog>` is\npropagated to the internal `<vaadin-dialog-overlay>` component.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
19
+ "description": "`<vaadin-dialog>` is a Web Component for creating customized modal dialogs.\n\n### Rendering\n\nThe content of the dialog can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `dialog` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `dialog`. Before generating new content,\nusers are able to check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-dialog id=\"dialog\"></vaadin-dialog>\n```\n```js\nconst dialog = document.querySelector('#dialog');\ndialog.renderer = function(root, dialog) {\n root.textContent = \"Sample dialog\";\n};\n```\n\nRenderer is called on the opening of the dialog.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### Styling\n\n`<vaadin-dialog>` uses `<vaadin-dialog-overlay>` internal\nthemable component as the actual visible dialog overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha11/#/elements/vaadin-overlay) documentation.\nfor `<vaadin-dialog-overlay>` parts.\n\nIn addition to `<vaadin-overlay>` parts, the following parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`header` | Element wrapping title and header content\n`header-content` | Element wrapping the header content slot\n`title` | Element wrapping the title slot\n`footer` | Element wrapping the footer slot\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|--------------------------------------------\n`has-title` | Set when the element has a title\n`has-header` | Set when the element has header renderer\n`has-footer` | Set when the element has footer renderer\n`overflow` | Set to `top`, `bottom`, none or both\n\nNote: the `theme` attribute value set on `<vaadin-dialog>` is\npropagated to the internal `<vaadin-dialog-overlay>` component.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -61,6 +61,13 @@
61
61
  "kind": "expression"
62
62
  }
63
63
  },
64
+ {
65
+ "name": ".overlayClass",
66
+ "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
67
+ "value": {
68
+ "kind": "expression"
69
+ }
70
+ },
64
71
  {
65
72
  "name": ".ariaLabel",
66
73
  "description": "Set the `aria-label` attribute for assistive technologies like\nscreen readers. An empty string value for this property (the\ndefault) means that the `aria-label` attribute is not present.",