@vaadin/dialog 23.1.0-alpha1 → 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.1.0-alpha1",
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": "23.1.0-alpha1",
39
- "@vaadin/vaadin-lumo-styles": "23.1.0-alpha1",
40
- "@vaadin/vaadin-material-styles": "23.1.0-alpha1",
41
- "@vaadin/vaadin-overlay": "23.1.0-alpha1",
42
- "@vaadin/vaadin-themable-mixin": "23.1.0-alpha1"
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": "23.1.0-alpha1",
46
+ "@vaadin/polymer-legacy-adapter": "23.1.0-alpha2",
47
47
  "@vaadin/testing-helpers": "^0.3.2",
48
- "@vaadin/text-area": "23.1.0-alpha1",
48
+ "@vaadin/text-area": "23.1.0-alpha2",
49
49
  "sinon": "^9.2.1"
50
50
  },
51
- "gitHead": "5d0cdee069f866037c507265fafb4d0476795333"
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;
@@ -110,6 +110,7 @@ export type DialogEventMap = HTMLElementEventMap & DialogCustomEventMap;
110
110
  * `has-title` | Set when the element has a title
111
111
  * `has-header` | Set when the element has header renderer
112
112
  * `has-footer` | Set when the element has footer renderer
113
+ * `overflow` | Set to `top`, `bottom`, none or both
113
114
  *
114
115
  * Note: the `theme` attribute value set on `<vaadin-dialog>` is
115
116
  * propagated to the internal `<vaadin-dialog-overlay>` component.
@@ -15,9 +15,24 @@ import { DialogResizableMixin } from './vaadin-dialog-resizable-mixin.js';
15
15
  registerStyles(
16
16
  'vaadin-dialog-overlay',
17
17
  css`
18
- /* prefixing with the element tag to avoid styling confirm-dialog header part */
19
- header[part='header'] {
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'] {
20
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;
21
36
  }
22
37
 
23
38
  [part='header-content'] {
@@ -25,8 +40,8 @@ registerStyles(
25
40
  }
26
41
 
27
42
  /* prefixing with the element tag to avoid styling confirm-dialog footer part */
43
+ [part='header-content'],
28
44
  footer[part='footer'] {
29
- display: flex;
30
45
  justify-content: flex-end;
31
46
  }
32
47
 
@@ -40,7 +55,6 @@ registerStyles(
40
55
  }
41
56
 
42
57
  :host(:is([has-title], [has-header], [has-footer])) [part='content'] {
43
- min-height: 100%;
44
58
  height: auto;
45
59
  }
46
60
 
@@ -54,8 +68,6 @@ registerStyles(
54
68
  :host(:is([has-title], [has-header], [has-footer])) [part='content'] {
55
69
  flex: 1;
56
70
  overflow: auto;
57
- min-height: auto;
58
- height: 100%;
59
71
  }
60
72
  }
61
73
 
@@ -150,11 +162,23 @@ export class DialogOverlay extends OverlayElement {
150
162
  };
151
163
  }
152
164
 
165
+ /** @protected */
153
166
  ready() {
154
167
  super.ready();
155
168
 
156
169
  const uniqueId = (DialogOverlay._uniqueId = 1 + DialogOverlay._uniqueId || 0);
157
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
+ });
158
182
  }
159
183
 
160
184
  /** @private */
@@ -196,12 +220,17 @@ export class DialogOverlay extends OverlayElement {
196
220
  const openedChanged = this._oldOpenedFooterHeader !== opened;
197
221
  this._oldOpenedFooterHeader = opened;
198
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
+
199
227
  if (headerRendererChanged) {
200
228
  if (headerRenderer) {
201
229
  this.headerContainer = this.__initContainer(this.headerContainer, 'header-content');
202
230
  } else if (this.headerContainer) {
203
231
  this.headerContainer.remove();
204
232
  this.headerContainer = null;
233
+ this.__updateOverflow();
205
234
  }
206
235
  }
207
236
 
@@ -211,6 +240,7 @@ export class DialogOverlay extends OverlayElement {
211
240
  } else if (this.footerContainer) {
212
241
  this.footerContainer.remove();
213
242
  this.footerContainer = null;
243
+ this.__updateOverflow();
214
244
  }
215
245
  }
216
246
 
@@ -222,18 +252,16 @@ export class DialogOverlay extends OverlayElement {
222
252
  this.requestContentUpdate();
223
253
  }
224
254
  }
225
-
226
- this.toggleAttribute('has-header', !!headerRenderer);
227
- this.toggleAttribute('has-footer', !!footerRenderer);
228
255
  }
229
256
 
230
257
  /** @private */
231
258
  _headerTitleChanged(headerTitle, opened) {
259
+ this.toggleAttribute('has-title', !!headerTitle);
260
+
232
261
  if (opened && (headerTitle || this._oldHeaderTitle)) {
233
262
  this.requestContentUpdate();
234
263
  }
235
264
  this._oldHeaderTitle = headerTitle;
236
- this.toggleAttribute('has-title', !!headerTitle);
237
265
  }
238
266
 
239
267
  /** @private */
@@ -259,24 +287,33 @@ export class DialogOverlay extends OverlayElement {
259
287
  requestContentUpdate() {
260
288
  super.requestContentUpdate();
261
289
 
262
- // If a new renderer has been set, make sure to reattach the header/footer roots
263
- if (this.headerContainer && !this.headerContainer.parentElement) {
264
- this.appendChild(this.headerContainer);
265
- }
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
+ }
266
295
 
267
- if (this.footerContainer && !this.footerContainer.parentElement) {
268
- this.appendChild(this.footerContainer);
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
+ }
269
300
  }
270
301
 
271
- if (this.headerRenderer) {
272
- this.headerRenderer.call(this.owner, this.headerContainer, this.owner);
273
- }
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
+ }
274
307
 
275
- if (this.footerRenderer) {
276
- this.footerRenderer.call(this.owner, this.footerContainer, this.owner);
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
+ }
277
312
  }
278
313
 
279
314
  this._headerTitleRenderer();
315
+
316
+ this.__updateOverflow();
280
317
  }
281
318
 
282
319
  /**
@@ -331,6 +368,32 @@ export class DialogOverlay extends OverlayElement {
331
368
  this.$.resizerContainer.scrollTop = scrollPosition;
332
369
  });
333
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
+ }
334
397
  }
335
398
 
336
399
  customElements.define(DialogOverlay.is, DialogOverlay);
@@ -386,6 +449,7 @@ customElements.define(DialogOverlay.is, DialogOverlay);
386
449
  * `has-title` | Set when the element has a title
387
450
  * `has-header` | Set when the element has header renderer
388
451
  * `has-footer` | Set when the element has footer renderer
452
+ * `overflow` | Set to `top`, `bottom`, none or both
389
453
  *
390
454
  * Note: the `theme` attribute value set on `<vaadin-dialog>` is
391
455
  * propagated to the internal `<vaadin-dialog-overlay>` component.
@@ -566,9 +630,20 @@ class Dialog extends ThemePropertyMixin(ElementMixin(DialogDraggableMixin(Dialog
566
630
  this.$.overlay.setProperties({ owner: this, renderer, headerRenderer, footerRenderer });
567
631
  }
568
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
+ }
640
+ }
641
+
569
642
  /** @protected */
570
643
  disconnectedCallback() {
571
644
  super.disconnectedCallback();
645
+ // Close overlay and memorize opened state
646
+ this.__restoreOpened = this.opened;
572
647
  this.opened = false;
573
648
  }
574
649
 
@@ -27,19 +27,38 @@ const dialogOverlay = css`
27
27
  padding: var(--lumo-space-l);
28
28
  }
29
29
 
30
- [part='header'] {
31
- gap: var(--lumo-space-s);
30
+ :host(:is([has-header], [has-title])) [part='header'] + [part='content'] {
31
+ padding-top: 0;
32
32
  }
33
33
 
34
- :host([has-header]) [part='header'],
35
- :host([has-title]) [part='header'] {
36
- padding: var(--lumo-space-m) var(--lumo-space-l);
37
- border-bottom: 1px solid var(--lumo-contrast-10pct);
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 */
38
47
  }
39
48
 
40
49
  :host([has-footer]) [part='footer'] {
41
50
  padding: var(--lumo-space-s) var(--lumo-space-m);
42
- border-top: 1px solid var(--lumo-contrast-10pct);
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));
43
62
  }
44
63
 
45
64
  /* No padding */
@@ -47,8 +66,7 @@ const dialogOverlay = css`
47
66
  padding: 0;
48
67
  }
49
68
 
50
- :host([theme~='no-padding'][has-header]) [part='header'],
51
- :host([theme~='no-padding'][has-title]) [part='header'] {
69
+ :host([theme~='no-padding']:is([has-header], [has-title])) [part='header'] {
52
70
  padding: 0;
53
71
  }
54
72
 
@@ -56,6 +74,12 @@ const dialogOverlay = css`
56
74
  padding: 0;
57
75
  }
58
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
+
59
83
  /* Animations */
60
84
 
61
85
  :host([opening]),
@@ -16,17 +16,39 @@ const dialogOverlay = css`
16
16
  padding: 24px;
17
17
  }
18
18
 
19
- :host([has-header]) [part='header'],
20
- :host([has-title]) [part='header'] {
21
- padding: 9px 24px;
22
- font-weight: 500;
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'] {
23
30
  gap: 8px;
24
- border-bottom: 1px solid var(--material-divider-color);
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;
25
38
  }
26
39
 
27
40
  :host([has-footer]) [part='footer'] {
28
41
  padding: 8px;
29
- border-top: 1px solid var(--material-divider-color);
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
+ }
30
52
  }
31
53
 
32
54
  /* No padding */