@vaadin/dialog 24.0.0-alpha8 → 24.0.0-beta1
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 +11 -11
- package/src/vaadin-dialog-overlay.d.ts +43 -0
- package/src/vaadin-dialog-overlay.js +376 -0
- package/src/vaadin-dialog.d.ts +5 -23
- package/src/vaadin-dialog.js +18 -389
- package/web-types.json +24 -2
- package/web-types.lit.json +9 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/dialog",
|
|
3
|
-
"version": "24.0.0-
|
|
3
|
+
"version": "24.0.0-beta1",
|
|
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-
|
|
43
|
-
"@vaadin/lit-renderer": "24.0.0-
|
|
44
|
-
"@vaadin/overlay": "24.0.0-
|
|
45
|
-
"@vaadin/vaadin-lumo-styles": "24.0.0-
|
|
46
|
-
"@vaadin/vaadin-material-styles": "24.0.0-
|
|
47
|
-
"@vaadin/vaadin-themable-mixin": "24.0.0-
|
|
42
|
+
"@vaadin/component-base": "24.0.0-beta1",
|
|
43
|
+
"@vaadin/lit-renderer": "24.0.0-beta1",
|
|
44
|
+
"@vaadin/overlay": "24.0.0-beta1",
|
|
45
|
+
"@vaadin/vaadin-lumo-styles": "24.0.0-beta1",
|
|
46
|
+
"@vaadin/vaadin-material-styles": "24.0.0-beta1",
|
|
47
|
+
"@vaadin/vaadin-themable-mixin": "24.0.0-beta1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@esm-bundle/chai": "^4.3.4",
|
|
51
|
-
"@vaadin/polymer-legacy-adapter": "24.0.0-
|
|
52
|
-
"@vaadin/testing-helpers": "^0.
|
|
53
|
-
"@vaadin/text-area": "24.0.0-
|
|
51
|
+
"@vaadin/polymer-legacy-adapter": "24.0.0-beta1",
|
|
52
|
+
"@vaadin/testing-helpers": "^0.4.0",
|
|
53
|
+
"@vaadin/text-area": "24.0.0-beta1",
|
|
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": "
|
|
61
|
+
"gitHead": "c5b48921a62482746df8e46994b37e1490fec27e"
|
|
62
62
|
}
|
|
@@ -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);
|
package/src/vaadin-dialog.d.ts
CHANGED
|
@@ -4,15 +4,12 @@
|
|
|
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 {
|
|
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
14
|
export type DialogRenderer = (root: HTMLElement, dialog: Dialog) => void;
|
|
18
15
|
|
|
@@ -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
|
|
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
|
|
package/src/vaadin-dialog.js
CHANGED
|
@@ -3,397 +3,16 @@
|
|
|
3
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
|
-
|
|
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
|
|
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
|
-
|
|
608
|
-
this.$.overlay
|
|
609
|
-
|
|
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
|
|
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-
|
|
4
|
+
"version": "24.0.0-alpha12",
|
|
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-
|
|
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-alpha12/#/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.",
|
package/web-types.lit.json
CHANGED
|
@@ -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-
|
|
4
|
+
"version": "24.0.0-alpha12",
|
|
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-
|
|
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-alpha12/#/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.",
|