@vaadin/dialog 23.0.4 → 23.1.0-alpha2
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": "23.0
|
|
3
|
+
"version": "23.1.0-alpha2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -35,18 +35,18 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
37
37
|
"@polymer/polymer": "^3.0.0",
|
|
38
|
-
"@vaadin/component-base": "
|
|
39
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
40
|
-
"@vaadin/vaadin-material-styles": "
|
|
41
|
-
"@vaadin/vaadin-overlay": "
|
|
42
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
38
|
+
"@vaadin/component-base": "23.1.0-alpha2",
|
|
39
|
+
"@vaadin/vaadin-lumo-styles": "23.1.0-alpha2",
|
|
40
|
+
"@vaadin/vaadin-material-styles": "23.1.0-alpha2",
|
|
41
|
+
"@vaadin/vaadin-overlay": "23.1.0-alpha2",
|
|
42
|
+
"@vaadin/vaadin-themable-mixin": "23.1.0-alpha2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@esm-bundle/chai": "^4.3.4",
|
|
46
|
-
"@vaadin/polymer-legacy-adapter": "
|
|
46
|
+
"@vaadin/polymer-legacy-adapter": "23.1.0-alpha2",
|
|
47
47
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
48
|
-
"@vaadin/text-area": "
|
|
48
|
+
"@vaadin/text-area": "23.1.0-alpha2",
|
|
49
49
|
"sinon": "^9.2.1"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "6842dcb8b163d4512fae8d3d12a6559077a4aee6"
|
|
52
52
|
}
|
|
@@ -24,6 +24,7 @@ registerStyles(
|
|
|
24
24
|
.resizer-container {
|
|
25
25
|
overflow: auto;
|
|
26
26
|
flex-grow: 1;
|
|
27
|
+
border-radius: inherit; /* prevent child elements being drawn outside part=overlay */
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
[part='overlay'][style] .resizer-container {
|
|
@@ -35,6 +36,12 @@ registerStyles(
|
|
|
35
36
|
display: none;
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
:host([resizable]) [part='title'] {
|
|
40
|
+
cursor: move;
|
|
41
|
+
-webkit-user-select: none;
|
|
42
|
+
user-select: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
.resizer {
|
|
39
46
|
position: absolute;
|
|
40
47
|
height: 16px;
|
package/src/vaadin-dialog.d.ts
CHANGED
|
@@ -94,6 +94,24 @@ export type DialogEventMap = HTMLElementEventMap & DialogCustomEventMap;
|
|
|
94
94
|
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation.
|
|
95
95
|
* for `<vaadin-dialog-overlay>` parts.
|
|
96
96
|
*
|
|
97
|
+
* In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
|
|
98
|
+
*
|
|
99
|
+
* Part name | Description
|
|
100
|
+
* -----------------|-------------------------------------------
|
|
101
|
+
* `header` | Element wrapping title and header content
|
|
102
|
+
* `header-content` | Element wrapping the header content slot
|
|
103
|
+
* `title` | Element wrapping the title slot
|
|
104
|
+
* `footer` | Element wrapping the footer slot
|
|
105
|
+
*
|
|
106
|
+
* The following state attributes are available for styling:
|
|
107
|
+
*
|
|
108
|
+
* Attribute | Description
|
|
109
|
+
* -----------------|--------------------------------------------
|
|
110
|
+
* `has-title` | Set when the element has a title
|
|
111
|
+
* `has-header` | Set when the element has header renderer
|
|
112
|
+
* `has-footer` | Set when the element has footer renderer
|
|
113
|
+
* `overflow` | Set to `top`, `bottom`, none or both
|
|
114
|
+
*
|
|
97
115
|
* Note: the `theme` attribute value set on `<vaadin-dialog>` is
|
|
98
116
|
* propagated to the internal `<vaadin-dialog-overlay>` component.
|
|
99
117
|
*
|
|
@@ -136,14 +154,52 @@ declare class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixi
|
|
|
136
154
|
*/
|
|
137
155
|
renderer: DialogRenderer | null | undefined;
|
|
138
156
|
|
|
157
|
+
/**
|
|
158
|
+
* String used for rendering a dialog title.
|
|
159
|
+
*
|
|
160
|
+
* If both `headerTitle` and `headerRenderer` are defined, the title
|
|
161
|
+
* and the elements created by the renderer will be placed next to
|
|
162
|
+
* each other, with the title coming first.
|
|
163
|
+
*
|
|
164
|
+
* When `headerTitle` is set, the attribute `has-title` is added to the overlay element.
|
|
165
|
+
* @attr {string} header-title
|
|
166
|
+
*/
|
|
167
|
+
headerTitle: string | null | undefined;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Custom function for rendering the dialog header.
|
|
171
|
+
* Receives two arguments:
|
|
172
|
+
*
|
|
173
|
+
* - `root` The root container DOM element. Append your content to it.
|
|
174
|
+
* - `dialog` The reference to the `<vaadin-dialog>` element.
|
|
175
|
+
*
|
|
176
|
+
* If both `headerTitle` and `headerRenderer` are defined, the title
|
|
177
|
+
* and the elements created by the renderer will be placed next to
|
|
178
|
+
* each other, with the title coming first.
|
|
179
|
+
*
|
|
180
|
+
* When `headerRenderer` is set, the attribute `has-header` is added to the overlay element.
|
|
181
|
+
*/
|
|
182
|
+
headerRenderer: DialogRenderer | null | undefined;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Custom function for rendering the dialog footer.
|
|
186
|
+
* Receives two arguments:
|
|
187
|
+
*
|
|
188
|
+
* - `root` The root container DOM element. Append your content to it.
|
|
189
|
+
* - `dialog` The reference to the `<vaadin-dialog>` element.
|
|
190
|
+
*
|
|
191
|
+
* When `footerRenderer` is set, the attribute `has-footer` is added to the overlay element.
|
|
192
|
+
*/
|
|
193
|
+
footerRenderer: DialogRenderer | null | undefined;
|
|
194
|
+
|
|
139
195
|
/**
|
|
140
196
|
* Set to true to remove backdrop and allow click events on background elements.
|
|
141
197
|
*/
|
|
142
198
|
modeless: boolean;
|
|
143
199
|
|
|
144
200
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
201
|
+
* While performing the update, it invokes the renderer passed in the `renderer` property,
|
|
202
|
+
* as well as `headerRender` and `footerRenderer` properties, if these are defined.
|
|
147
203
|
*
|
|
148
204
|
* It is not guaranteed that the update happens immediately (synchronously) after it is requested.
|
|
149
205
|
*/
|
package/src/vaadin-dialog.js
CHANGED
|
@@ -15,6 +15,62 @@ import { DialogResizableMixin } from './vaadin-dialog-resizable-mixin.js';
|
|
|
15
15
|
registerStyles(
|
|
16
16
|
'vaadin-dialog-overlay',
|
|
17
17
|
css`
|
|
18
|
+
/* prefixing with the element tags to avoid styling confirm-dialog header part */
|
|
19
|
+
header[part='header'],
|
|
20
|
+
[part='header-content'],
|
|
21
|
+
footer[part='footer'] {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
flex-wrap: wrap;
|
|
25
|
+
flex: none;
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
z-index: 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:host(:is([has-title], [has-header])) ::slotted([slot='header']),
|
|
31
|
+
::slotted([slot='header-content']),
|
|
32
|
+
::slotted([slot='title']),
|
|
33
|
+
:host([has-footer]) ::slotted([slot='footer']) {
|
|
34
|
+
display: contents;
|
|
35
|
+
pointer-events: auto;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
[part='header-content'] {
|
|
39
|
+
flex: 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* prefixing with the element tag to avoid styling confirm-dialog footer part */
|
|
43
|
+
[part='header-content'],
|
|
44
|
+
footer[part='footer'] {
|
|
45
|
+
justify-content: flex-end;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host(:not([has-title]):not([has-header])) header[part='header'],
|
|
49
|
+
:host(:not([has-title])) [part='title'] {
|
|
50
|
+
display: none;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:host(:not([has-footer])) footer[part='footer'] {
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:host(:is([has-title], [has-header], [has-footer])) [part='content'] {
|
|
58
|
+
height: auto;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@media (min-height: 320px) {
|
|
62
|
+
:host(:is([has-title], [has-header], [has-footer])) .resizer-container {
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:host(:is([has-title], [has-header], [has-footer])) [part='content'] {
|
|
69
|
+
flex: 1;
|
|
70
|
+
overflow: auto;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
18
74
|
/*
|
|
19
75
|
NOTE(platosha): Make some min-width to prevent collapsing of the content
|
|
20
76
|
taking the parent width, e. g., <vaadin-grid> and such.
|
|
@@ -53,18 +109,213 @@ export class DialogOverlay extends OverlayElement {
|
|
|
53
109
|
resizerContainer.classList.add('resizer-container');
|
|
54
110
|
resizerContainer.appendChild(contentPart);
|
|
55
111
|
overlayPart.appendChild(resizerContainer);
|
|
112
|
+
|
|
113
|
+
const headerContainer = document.createElement('header');
|
|
114
|
+
headerContainer.setAttribute('part', 'header');
|
|
115
|
+
resizerContainer.insertBefore(headerContainer, contentPart);
|
|
116
|
+
|
|
117
|
+
const titleContainer = document.createElement('div');
|
|
118
|
+
titleContainer.setAttribute('part', 'title');
|
|
119
|
+
headerContainer.appendChild(titleContainer);
|
|
120
|
+
|
|
121
|
+
const titleSlot = document.createElement('slot');
|
|
122
|
+
titleSlot.setAttribute('name', 'title');
|
|
123
|
+
titleContainer.appendChild(titleSlot);
|
|
124
|
+
|
|
125
|
+
const headerContentContainer = document.createElement('div');
|
|
126
|
+
headerContentContainer.setAttribute('part', 'header-content');
|
|
127
|
+
headerContainer.appendChild(headerContentContainer);
|
|
128
|
+
|
|
129
|
+
const headerSlot = document.createElement('slot');
|
|
130
|
+
headerSlot.setAttribute('name', 'header-content');
|
|
131
|
+
headerContentContainer.appendChild(headerSlot);
|
|
132
|
+
|
|
133
|
+
const footerContainer = document.createElement('footer');
|
|
134
|
+
footerContainer.setAttribute('part', 'footer');
|
|
135
|
+
resizerContainer.appendChild(footerContainer);
|
|
136
|
+
|
|
137
|
+
const footerSlot = document.createElement('slot');
|
|
138
|
+
footerSlot.setAttribute('name', 'footer');
|
|
139
|
+
footerContainer.appendChild(footerSlot);
|
|
56
140
|
}
|
|
57
141
|
return memoizedTemplate;
|
|
58
142
|
}
|
|
59
143
|
|
|
144
|
+
static get observers() {
|
|
145
|
+
return [
|
|
146
|
+
'_headerFooterRendererChange(headerRenderer, footerRenderer, opened)',
|
|
147
|
+
'_headerTitleChanged(headerTitle, opened)'
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
|
|
60
151
|
static get properties() {
|
|
61
152
|
return {
|
|
62
153
|
modeless: Boolean,
|
|
63
154
|
|
|
64
|
-
withBackdrop: Boolean
|
|
155
|
+
withBackdrop: Boolean,
|
|
156
|
+
|
|
157
|
+
headerTitle: String,
|
|
158
|
+
|
|
159
|
+
headerRenderer: Function,
|
|
160
|
+
|
|
161
|
+
footerRenderer: Function
|
|
65
162
|
};
|
|
66
163
|
}
|
|
67
164
|
|
|
165
|
+
/** @protected */
|
|
166
|
+
ready() {
|
|
167
|
+
super.ready();
|
|
168
|
+
|
|
169
|
+
const uniqueId = (DialogOverlay._uniqueId = 1 + DialogOverlay._uniqueId || 0);
|
|
170
|
+
this._titleId = `${this.constructor.is}-title-${uniqueId}`;
|
|
171
|
+
|
|
172
|
+
// Update overflow attribute on resize
|
|
173
|
+
this.__resizeObserver = new ResizeObserver(() => {
|
|
174
|
+
this.__updateOverflow();
|
|
175
|
+
});
|
|
176
|
+
this.__resizeObserver.observe(this.$.resizerContainer);
|
|
177
|
+
|
|
178
|
+
// Update overflow attribute on scroll
|
|
179
|
+
this.$.content.addEventListener('scroll', () => {
|
|
180
|
+
this.__updateOverflow();
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** @private */
|
|
185
|
+
__createContainer(slot) {
|
|
186
|
+
const container = document.createElement('div');
|
|
187
|
+
container.setAttribute('slot', slot);
|
|
188
|
+
return container;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** @private */
|
|
192
|
+
__clearContainer(container) {
|
|
193
|
+
container.innerHTML = '';
|
|
194
|
+
// Whenever a Lit-based renderer is used, it assigns a Lit part to the node it was rendered into.
|
|
195
|
+
// When clearing the rendered content, this part needs to be manually disposed of.
|
|
196
|
+
// Otherwise, using a Lit-based renderer on the same node will throw an exception or render nothing afterward.
|
|
197
|
+
delete container._$litPart$;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** @private */
|
|
201
|
+
__initContainer(container, slot) {
|
|
202
|
+
if (container) {
|
|
203
|
+
// Reset existing container in case if a new renderer is set.
|
|
204
|
+
this.__clearContainer(container);
|
|
205
|
+
} else {
|
|
206
|
+
// Create the container, but wait to append it until requestContentUpdate is called.
|
|
207
|
+
container = this.__createContainer(slot);
|
|
208
|
+
}
|
|
209
|
+
return container;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** @private */
|
|
213
|
+
_headerFooterRendererChange(headerRenderer, footerRenderer, opened) {
|
|
214
|
+
const headerRendererChanged = this.__oldHeaderRenderer !== headerRenderer;
|
|
215
|
+
this.__oldHeaderRenderer = headerRenderer;
|
|
216
|
+
|
|
217
|
+
const footerRendererChanged = this.__oldFooterRenderer !== footerRenderer;
|
|
218
|
+
this.__oldFooterRenderer = footerRenderer;
|
|
219
|
+
|
|
220
|
+
const openedChanged = this._oldOpenedFooterHeader !== opened;
|
|
221
|
+
this._oldOpenedFooterHeader = opened;
|
|
222
|
+
|
|
223
|
+
// Set attributes here to update styles before detecting content overflow
|
|
224
|
+
this.toggleAttribute('has-header', !!headerRenderer);
|
|
225
|
+
this.toggleAttribute('has-footer', !!footerRenderer);
|
|
226
|
+
|
|
227
|
+
if (headerRendererChanged) {
|
|
228
|
+
if (headerRenderer) {
|
|
229
|
+
this.headerContainer = this.__initContainer(this.headerContainer, 'header-content');
|
|
230
|
+
} else if (this.headerContainer) {
|
|
231
|
+
this.headerContainer.remove();
|
|
232
|
+
this.headerContainer = null;
|
|
233
|
+
this.__updateOverflow();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (footerRendererChanged) {
|
|
238
|
+
if (footerRenderer) {
|
|
239
|
+
this.footerContainer = this.__initContainer(this.footerContainer, 'footer');
|
|
240
|
+
} else if (this.footerContainer) {
|
|
241
|
+
this.footerContainer.remove();
|
|
242
|
+
this.footerContainer = null;
|
|
243
|
+
this.__updateOverflow();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (
|
|
248
|
+
(headerRenderer && (headerRendererChanged || openedChanged)) ||
|
|
249
|
+
(footerRenderer && (footerRendererChanged || openedChanged))
|
|
250
|
+
) {
|
|
251
|
+
if (opened) {
|
|
252
|
+
this.requestContentUpdate();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** @private */
|
|
258
|
+
_headerTitleChanged(headerTitle, opened) {
|
|
259
|
+
this.toggleAttribute('has-title', !!headerTitle);
|
|
260
|
+
|
|
261
|
+
if (opened && (headerTitle || this._oldHeaderTitle)) {
|
|
262
|
+
this.requestContentUpdate();
|
|
263
|
+
}
|
|
264
|
+
this._oldHeaderTitle = headerTitle;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** @private */
|
|
268
|
+
_headerTitleRenderer() {
|
|
269
|
+
if (this.headerTitle) {
|
|
270
|
+
if (!this.headerTitleElement) {
|
|
271
|
+
this.headerTitleElement = document.createElement('span');
|
|
272
|
+
this.headerTitleElement.id = this._titleId;
|
|
273
|
+
this.headerTitleElement.setAttribute('slot', 'title');
|
|
274
|
+
this.headerTitleElement.classList.add('draggable');
|
|
275
|
+
|
|
276
|
+
this.setAttribute('aria-labelledby', this._titleId);
|
|
277
|
+
}
|
|
278
|
+
this.appendChild(this.headerTitleElement);
|
|
279
|
+
this.headerTitleElement.textContent = this.headerTitle;
|
|
280
|
+
} else if (this.headerTitleElement) {
|
|
281
|
+
this.headerTitleElement.remove();
|
|
282
|
+
this.headerTitleElement = null;
|
|
283
|
+
this.removeAttribute('aria-labelledby');
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
requestContentUpdate() {
|
|
288
|
+
super.requestContentUpdate();
|
|
289
|
+
|
|
290
|
+
if (this.headerContainer) {
|
|
291
|
+
// If a new renderer has been set, make sure to reattach the container
|
|
292
|
+
if (!this.headerContainer.parentElement) {
|
|
293
|
+
this.appendChild(this.headerContainer);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (this.headerRenderer) {
|
|
297
|
+
// Only call header renderer after the container has been initialized
|
|
298
|
+
this.headerRenderer.call(this.owner, this.headerContainer, this.owner);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (this.footerContainer) {
|
|
303
|
+
// If a new renderer has been set, make sure to reattach the container
|
|
304
|
+
if (!this.footerContainer.parentElement) {
|
|
305
|
+
this.appendChild(this.footerContainer);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (this.footerRenderer) {
|
|
309
|
+
// Only call header renderer after the container has been initialized
|
|
310
|
+
this.footerRenderer.call(this.owner, this.footerContainer, this.owner);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
this._headerTitleRenderer();
|
|
315
|
+
|
|
316
|
+
this.__updateOverflow();
|
|
317
|
+
}
|
|
318
|
+
|
|
68
319
|
/**
|
|
69
320
|
* Updates the coordinates of the overlay.
|
|
70
321
|
* @param {!DialogOverlayBoundsParam} bounds
|
|
@@ -117,6 +368,32 @@ export class DialogOverlay extends OverlayElement {
|
|
|
117
368
|
this.$.resizerContainer.scrollTop = scrollPosition;
|
|
118
369
|
});
|
|
119
370
|
}
|
|
371
|
+
|
|
372
|
+
/** @private */
|
|
373
|
+
__updateOverflow() {
|
|
374
|
+
let overflow = '';
|
|
375
|
+
|
|
376
|
+
// Only set "overflow" attribute if the dialog has a header, title or footer.
|
|
377
|
+
// Check for state attributes as extending components might not use renderers.
|
|
378
|
+
if (this.hasAttribute('has-header') || this.hasAttribute('has-footer') || this.headerTitle) {
|
|
379
|
+
const content = this.$.content;
|
|
380
|
+
|
|
381
|
+
if (content.scrollTop > 0) {
|
|
382
|
+
overflow += ' top';
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (content.scrollTop < content.scrollHeight - content.clientHeight) {
|
|
386
|
+
overflow += ' bottom';
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const value = overflow.trim();
|
|
391
|
+
if (value.length > 0 && this.getAttribute('overflow') !== value) {
|
|
392
|
+
this.setAttribute('overflow', value);
|
|
393
|
+
} else if (value.length === 0 && this.hasAttribute('overflow')) {
|
|
394
|
+
this.removeAttribute('overflow');
|
|
395
|
+
}
|
|
396
|
+
}
|
|
120
397
|
}
|
|
121
398
|
|
|
122
399
|
customElements.define(DialogOverlay.is, DialogOverlay);
|
|
@@ -156,6 +433,24 @@ customElements.define(DialogOverlay.is, DialogOverlay);
|
|
|
156
433
|
* See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation.
|
|
157
434
|
* for `<vaadin-dialog-overlay>` parts.
|
|
158
435
|
*
|
|
436
|
+
* In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
|
|
437
|
+
*
|
|
438
|
+
* Part name | Description
|
|
439
|
+
* -----------------|-------------------------------------------
|
|
440
|
+
* `header` | Element wrapping title and header content
|
|
441
|
+
* `header-content` | Element wrapping the header content slot
|
|
442
|
+
* `title` | Element wrapping the title slot
|
|
443
|
+
* `footer` | Element wrapping the footer slot
|
|
444
|
+
*
|
|
445
|
+
* The following state attributes are available for styling:
|
|
446
|
+
*
|
|
447
|
+
* Attribute | Description
|
|
448
|
+
* -----------------|--------------------------------------------
|
|
449
|
+
* `has-title` | Set when the element has a title
|
|
450
|
+
* `has-header` | Set when the element has header renderer
|
|
451
|
+
* `has-footer` | Set when the element has footer renderer
|
|
452
|
+
* `overflow` | Set to `top`, `bottom`, none or both
|
|
453
|
+
*
|
|
159
454
|
* Note: the `theme` attribute value set on `<vaadin-dialog>` is
|
|
160
455
|
* propagated to the internal `<vaadin-dialog-overlay>` component.
|
|
161
456
|
*
|
|
@@ -175,16 +470,17 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
|
|
|
175
470
|
return html`
|
|
176
471
|
<style>
|
|
177
472
|
:host {
|
|
178
|
-
display: none;
|
|
473
|
+
display: none !important;
|
|
179
474
|
}
|
|
180
475
|
</style>
|
|
181
476
|
|
|
182
477
|
<vaadin-dialog-overlay
|
|
183
478
|
id="overlay"
|
|
479
|
+
header-title="[[headerTitle]]"
|
|
184
480
|
on-opened-changed="_onOverlayOpened"
|
|
185
481
|
on-mousedown="_bringOverlayToFront"
|
|
186
482
|
on-touchstart="_bringOverlayToFront"
|
|
187
|
-
theme$="[[
|
|
483
|
+
theme$="[[_theme]]"
|
|
188
484
|
modeless="[[modeless]]"
|
|
189
485
|
with-backdrop="[[!modeless]]"
|
|
190
486
|
resizable$="[[resizable]]"
|
|
@@ -249,6 +545,46 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
|
|
|
249
545
|
*/
|
|
250
546
|
renderer: Function,
|
|
251
547
|
|
|
548
|
+
/**
|
|
549
|
+
* String used for rendering a dialog title.
|
|
550
|
+
*
|
|
551
|
+
* If both `headerTitle` and `headerRenderer` are defined, the title
|
|
552
|
+
* and the elements created by the renderer will be placed next to
|
|
553
|
+
* each other, with the title coming first.
|
|
554
|
+
*
|
|
555
|
+
* When `headerTitle` is set, the attribute `has-title` is added to the overlay element.
|
|
556
|
+
* @attr {string} header-title
|
|
557
|
+
*/
|
|
558
|
+
headerTitle: String,
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Custom function for rendering the dialog header.
|
|
562
|
+
* Receives two arguments:
|
|
563
|
+
*
|
|
564
|
+
* - `root` The root container DOM element. Append your content to it.
|
|
565
|
+
* - `dialog` The reference to the `<vaadin-dialog>` element.
|
|
566
|
+
*
|
|
567
|
+
* If both `headerTitle` and `headerRenderer` are defined, the title
|
|
568
|
+
* and the elements created by the renderer will be placed next to
|
|
569
|
+
* each other, with the title coming first.
|
|
570
|
+
*
|
|
571
|
+
* When `headerRenderer` is set, the attribute `has-header` is added to the overlay element.
|
|
572
|
+
* @type {DialogRenderer | undefined}
|
|
573
|
+
*/
|
|
574
|
+
headerRenderer: Function,
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Custom function for rendering the dialog footer.
|
|
578
|
+
* Receives two arguments:
|
|
579
|
+
*
|
|
580
|
+
* - `root` The root container DOM element. Append your content to it.
|
|
581
|
+
* - `dialog` The reference to the `<vaadin-dialog>` element.
|
|
582
|
+
*
|
|
583
|
+
* When `footerRenderer` is set, the attribute `has-footer` is added to the overlay element.
|
|
584
|
+
* @type {DialogRenderer | undefined}
|
|
585
|
+
*/
|
|
586
|
+
footerRenderer: Function,
|
|
587
|
+
|
|
252
588
|
/**
|
|
253
589
|
* Set to true to remove backdrop and allow click events on background elements.
|
|
254
590
|
* @type {boolean}
|
|
@@ -261,7 +597,11 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
|
|
|
261
597
|
}
|
|
262
598
|
|
|
263
599
|
static get observers() {
|
|
264
|
-
return [
|
|
600
|
+
return [
|
|
601
|
+
'_openedChanged(opened)',
|
|
602
|
+
'_ariaLabelChanged(ariaLabel)',
|
|
603
|
+
'_rendererChanged(renderer, headerRenderer, footerRenderer)'
|
|
604
|
+
];
|
|
265
605
|
}
|
|
266
606
|
|
|
267
607
|
/** @protected */
|
|
@@ -276,7 +616,8 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
|
|
|
276
616
|
|
|
277
617
|
/**
|
|
278
618
|
* Requests an update for the content of the dialog.
|
|
279
|
-
* While performing the update, it invokes the renderer passed in the `renderer` property
|
|
619
|
+
* While performing the update, it invokes the renderer passed in the `renderer` property,
|
|
620
|
+
* as well as `headerRender` and `footerRenderer` properties, if these are defined.
|
|
280
621
|
*
|
|
281
622
|
* It is not guaranteed that the update happens immediately (synchronously) after it is requested.
|
|
282
623
|
*/
|
|
@@ -285,13 +626,24 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
|
|
|
285
626
|
}
|
|
286
627
|
|
|
287
628
|
/** @private */
|
|
288
|
-
_rendererChanged(renderer) {
|
|
289
|
-
this.$.overlay.setProperties({ owner: this, renderer });
|
|
629
|
+
_rendererChanged(renderer, headerRenderer, footerRenderer) {
|
|
630
|
+
this.$.overlay.setProperties({ owner: this, renderer, headerRenderer, footerRenderer });
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/** @protected */
|
|
634
|
+
connectedCallback() {
|
|
635
|
+
super.connectedCallback();
|
|
636
|
+
// Restore opened state if overlay was opened when disconnecting
|
|
637
|
+
if (this.__restoreOpened) {
|
|
638
|
+
this.opened = true;
|
|
639
|
+
}
|
|
290
640
|
}
|
|
291
641
|
|
|
292
642
|
/** @protected */
|
|
293
643
|
disconnectedCallback() {
|
|
294
644
|
super.disconnectedCallback();
|
|
645
|
+
// Close overlay and memorize opened state
|
|
646
|
+
this.__restoreOpened = this.opened;
|
|
295
647
|
this.opened = false;
|
|
296
648
|
}
|
|
297
649
|
|
|
@@ -27,11 +27,59 @@ const dialogOverlay = css`
|
|
|
27
27
|
padding: var(--lumo-space-l);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
:host(:is([has-header], [has-title])) [part='header'] + [part='content'] {
|
|
31
|
+
padding-top: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
:host(:is([has-header], [has-title])) [part='header'],
|
|
35
|
+
:host([has-header]) [part='header-content'],
|
|
36
|
+
:host([has-footer]) [part='footer'] {
|
|
37
|
+
gap: var(--lumo-space-xs) var(--lumo-space-s);
|
|
38
|
+
line-height: var(--lumo-line-height-s);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
:host(:is([has-header], [has-title])) [part='header'] {
|
|
42
|
+
padding: var(--lumo-space-s) var(--lumo-space-m);
|
|
43
|
+
min-height: var(--lumo-size-xl);
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
background-color: var(--lumo-base-color);
|
|
46
|
+
border-radius: var(--lumo-border-radius-l) var(--lumo-border-radius-l) 0 0; /* Needed for Safari */
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:host([has-footer]) [part='footer'] {
|
|
50
|
+
padding: var(--lumo-space-s) var(--lumo-space-m);
|
|
51
|
+
min-height: var(--lumo-size-l);
|
|
52
|
+
box-sizing: border-box;
|
|
53
|
+
background-color: var(--lumo-contrast-5pct);
|
|
54
|
+
border-radius: 0 0 var(--lumo-border-radius-l) var(--lumo-border-radius-l); /* Needed for Safari */
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
[part='title'] {
|
|
58
|
+
font-size: var(--lumo-font-size-xl);
|
|
59
|
+
font-weight: 600;
|
|
60
|
+
color: var(--lumo-header-text-color);
|
|
61
|
+
margin-inline-start: calc(var(--lumo-space-l) - var(--lumo-space-m));
|
|
62
|
+
}
|
|
63
|
+
|
|
30
64
|
/* No padding */
|
|
31
65
|
:host([theme~='no-padding']) [part='content'] {
|
|
32
66
|
padding: 0;
|
|
33
67
|
}
|
|
34
68
|
|
|
69
|
+
:host([theme~='no-padding']:is([has-header], [has-title])) [part='header'] {
|
|
70
|
+
padding: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
:host([theme~='no-padding'][has-footer]) [part='footer'] {
|
|
74
|
+
padding: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@media (min-height: 320px) {
|
|
78
|
+
:host(:is([has-header], [has-title])[overflow~='top']) [part='header'] {
|
|
79
|
+
box-shadow: 0 1px 0 0 var(--lumo-contrast-10pct);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
35
83
|
/* Animations */
|
|
36
84
|
|
|
37
85
|
:host([opening]),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import '@vaadin/vaadin-material-styles/shadow.js';
|
|
2
|
+
import '@vaadin/vaadin-material-styles/color.js';
|
|
2
3
|
import { overlay } from '@vaadin/vaadin-material-styles/mixins/overlay.js';
|
|
3
4
|
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
4
5
|
|
|
@@ -15,6 +16,41 @@ const dialogOverlay = css`
|
|
|
15
16
|
padding: 24px;
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
:host(:is([has-header], [has-title])) [part='header'] {
|
|
20
|
+
padding: 16px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:host(:is([has-header], [has-title])) [part='header'] + [part='content'] {
|
|
24
|
+
padding-top: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:host(:is([has-header], [has-title])) [part='header'],
|
|
28
|
+
:host([has-header]) [part='header-content'],
|
|
29
|
+
:host([has-footer]) [part='footer'] {
|
|
30
|
+
gap: 8px;
|
|
31
|
+
line-height: 1.2;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
[part='title'] {
|
|
35
|
+
font-size: var(--material-h5-font-size);
|
|
36
|
+
font-weight: 500;
|
|
37
|
+
margin-inline-start: 8px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
:host([has-footer]) [part='footer'] {
|
|
41
|
+
padding: 8px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media (min-height: 320px) {
|
|
45
|
+
:host(:is([has-header], [has-title])[overflow~='top']) [part='header'] {
|
|
46
|
+
box-shadow: 0 1px 0 0 var(--material-divider-color);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:host([has-footer][overflow~='bottom']) [part='footer'] {
|
|
50
|
+
box-shadow: 0 -1px 0 0 var(--material-divider-color);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
18
54
|
/* No padding */
|
|
19
55
|
:host([theme~='no-padding']) [part='content'] {
|
|
20
56
|
padding: 0;
|