@vaadin/master-detail-layout 25.2.0-alpha3 → 25.2.0-alpha4

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.
@@ -33,7 +33,7 @@
33
33
  "type": {
34
34
  "text": "string"
35
35
  },
36
- "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. If there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay. Defaults to 15em.",
36
+ "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. When there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay.\n<p>\nIf not specified, the size is determined automatically by measuring\nthe detail content in a `min-content` CSS grid column when it first\nbecomes visible, and then caching the resulting intrinsic size. To\nrecalculate the cached intrinsic size, use the `recalculateLayout`\nmethod.",
37
37
  "attribute": "detail-size"
38
38
  },
39
39
  {
@@ -95,6 +95,11 @@
95
95
  },
96
96
  "description": "Size (in CSS length units) for the detail area when shown as an\noverlay. When not set, falls back to `detailSize`. Set to `100%`\nto make the detail cover the full layout.",
97
97
  "attribute": "overlay-size"
98
+ },
99
+ {
100
+ "kind": "method",
101
+ "name": "recalculateLayout",
102
+ "description": "When `detailSize` is not explicitly set, re-measures the cached intrinsic size of\nthe detail content by placing it in a min-content CSS grid column, then repeats\nthis process for ancestor master-detail layouts without an explicit `detailSize`,\nif any, so that their detail areas also adapt.\n\nCall this method after changing the detail content in a way that affects its intrinsic\nsize — for example, when opening a detail in a nested master-detail layout that was\nnot previously visible.\n\nNOTE: This method can be expensive in large layouts as it triggers consecutive\nsynchronous DOM reads and writes."
98
103
  }
99
104
  ],
100
105
  "events": [
@@ -119,7 +124,7 @@
119
124
  "type": {
120
125
  "text": "string"
121
126
  },
122
- "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. If there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay. Defaults to 15em.",
127
+ "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. When there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay.\n<p>\nIf not specified, the size is determined automatically by measuring\nthe detail content in a `min-content` CSS grid column when it first\nbecomes visible, and then caching the resulting intrinsic size. To\nrecalculate the cached intrinsic size, use the `recalculateLayout`\nmethod.",
123
128
  "fieldName": "detailSize"
124
129
  },
125
130
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/master-detail-layout",
3
- "version": "25.2.0-alpha3",
3
+ "version": "25.2.0-alpha4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,16 +34,16 @@
34
34
  "web-component"
35
35
  ],
36
36
  "dependencies": {
37
- "@vaadin/a11y-base": "25.2.0-alpha3",
38
- "@vaadin/component-base": "25.2.0-alpha3",
39
- "@vaadin/vaadin-themable-mixin": "25.2.0-alpha3",
37
+ "@vaadin/a11y-base": "25.2.0-alpha4",
38
+ "@vaadin/component-base": "25.2.0-alpha4",
39
+ "@vaadin/vaadin-themable-mixin": "25.2.0-alpha4",
40
40
  "lit": "^3.0.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@vaadin/aura": "25.2.0-alpha3",
44
- "@vaadin/chai-plugins": "25.2.0-alpha3",
43
+ "@vaadin/aura": "25.2.0-alpha4",
44
+ "@vaadin/chai-plugins": "25.2.0-alpha4",
45
45
  "@vaadin/testing-helpers": "^2.0.0",
46
- "@vaadin/vaadin-lumo-styles": "25.2.0-alpha3",
46
+ "@vaadin/vaadin-lumo-styles": "25.2.0-alpha4",
47
47
  "sinon": "^21.0.2"
48
48
  },
49
49
  "customElements": "custom-elements.json",
@@ -51,5 +51,5 @@
51
51
  "web-types.json",
52
52
  "web-types.lit.json"
53
53
  ],
54
- "gitHead": "6ba3d66b9eeb541945dc071e72e05dac2d4c3e0b"
54
+ "gitHead": "fc054a1bed540874ef3b5000828c191cc12044ec"
55
55
  }
@@ -8,10 +8,12 @@ import { css } from 'lit';
8
8
 
9
9
  export const masterDetailLayoutStyles = css`
10
10
  :host {
11
- --_master-size: 30em;
12
- --_detail-size: 15em;
13
- --_master-column: var(--_master-size) 0;
14
- --_detail-column: var(--_detail-size) 0;
11
+ --_master-size: 30rem;
12
+ --_master-extra: 0px;
13
+ --_detail-size: var(--_detail-cached-size);
14
+ --_detail-extra: 0px;
15
+ --_detail-cached-size: min-content;
16
+
15
17
  --_transition-duration: 0s;
16
18
  --_transition-easing: cubic-bezier(0.78, 0, 0.22, 1);
17
19
  --_rtl-multiplier: 1;
@@ -22,12 +24,16 @@ export const masterDetailLayoutStyles = css`
22
24
  height: 100%;
23
25
  position: relative;
24
26
  z-index: 0;
25
- overflow: hidden;
26
- grid-template-columns: [master-start] var(--_master-column) [detail-start] var(--_detail-column) [detail-end];
27
+ overflow: clip;
28
+ grid-template-columns:
29
+ [master-start] var(--_master-size) var(--_master-extra)
30
+ [detail-start] var(--_detail-size) var(--_detail-extra)
31
+ [detail-end];
27
32
  grid-template-rows: 100%;
28
33
  }
29
34
 
30
- :host([hidden]) {
35
+ :host([hidden]),
36
+ ::slotted([hidden]) {
31
37
  display: none !important;
32
38
  }
33
39
 
@@ -39,7 +45,10 @@ export const masterDetailLayoutStyles = css`
39
45
  --_detail-offscreen: 0 30px;
40
46
 
41
47
  grid-template-columns: 100%;
42
- grid-template-rows: [master-start] var(--_master-column) [detail-start] var(--_detail-column) [detail-end];
48
+ grid-template-rows:
49
+ [master-start] var(--_master-size) var(--_master-extra)
50
+ [detail-start] var(--_detail-size) var(--_detail-extra)
51
+ [detail-end];
43
52
  }
44
53
 
45
54
  :is(#master, #detail, #detail-placeholder, #outgoing) {
@@ -47,11 +56,11 @@ export const masterDetailLayoutStyles = css`
47
56
  }
48
57
 
49
58
  #detail-placeholder {
50
- display: none;
59
+ visibility: hidden;
51
60
  }
52
61
 
53
62
  :host([has-detail-placeholder]:not([has-detail], [overlay])) #detail-placeholder {
54
- display: block;
63
+ visibility: visible;
55
64
  }
56
65
 
57
66
  #master {
@@ -86,28 +95,32 @@ export const masterDetailLayoutStyles = css`
86
95
 
87
96
  :host([expand='both']),
88
97
  :host([expand='master']) {
89
- --_master-column: var(--_master-size) 1fr;
98
+ --_master-extra: 1fr;
99
+ }
100
+
101
+ :host([expand='both']:is([has-detail], [has-detail-placeholder])),
102
+ :host([expand='detail']:is([has-detail], [has-detail-placeholder])) {
103
+ --_detail-extra: 1fr;
104
+ }
105
+
106
+ :host([recalculating-detail-size]:is([has-detail], [has-detail-placeholder])) {
107
+ --_detail-extra: 0px;
90
108
  }
91
109
 
92
110
  :host([keep-detail-column-offscreen]),
93
111
  :host([has-detail-placeholder][overlay]),
94
112
  :host(:not([has-detail-placeholder], [has-detail])) {
95
- --_master-column: var(--_master-size) calc(100% - var(--_master-size));
96
- }
97
-
98
- :host([expand='both']),
99
- :host([expand='detail']) {
100
- --_detail-column: var(--_detail-size) 1fr;
113
+ --_master-extra: calc(100% - var(--_master-size));
101
114
  }
102
115
 
103
116
  :host([orientation='horizontal']) #detail-placeholder,
104
- :host([orientation='horizontal'][has-detail]:not([overlay])) #detail {
117
+ :host([orientation='horizontal']:not([overlay])) #detail {
105
118
  border-inline-start: var(--vaadin-master-detail-layout-border-width, 1px) solid
106
119
  var(--vaadin-master-detail-layout-border-color, var(--vaadin-border-color-secondary));
107
120
  }
108
121
 
109
122
  :host([orientation='vertical']) #detail-placeholder,
110
- :host([orientation='vertical'][has-detail]:not([overlay])) #detail {
123
+ :host([orientation='vertical']:not([overlay])) #detail {
111
124
  border-top: var(--vaadin-master-detail-layout-border-width, 1px) solid
112
125
  var(--vaadin-master-detail-layout-border-color, var(--vaadin-border-color-secondary));
113
126
  }
@@ -115,10 +128,12 @@ export const masterDetailLayoutStyles = css`
115
128
  /* Detail transition: off-screen by default, on-screen when has-detail */
116
129
  #detail {
117
130
  translate: var(--_detail-offscreen);
131
+ visibility: hidden;
118
132
  }
119
133
 
120
134
  :host([has-detail]) #detail {
121
135
  translate: none;
136
+ visibility: visible;
122
137
  }
123
138
 
124
139
  #outgoing:not([hidden]) {
@@ -150,13 +165,15 @@ export const masterDetailLayoutStyles = css`
150
165
  :host([has-detail][overlay]:not([orientation='vertical'])) :is(#detail, #outgoing) {
151
166
  inset-block: 0;
152
167
  inset-inline-end: 0;
153
- width: var(--_overlay-size, var(--_detail-size, min-content));
168
+ width: var(--_overlay-size, var(--_detail-size));
169
+ max-width: 100%;
154
170
  }
155
171
 
156
172
  :host([has-detail][overlay][orientation='vertical']) :is(#detail, #outgoing) {
157
173
  inset-inline: 0;
158
174
  inset-block-end: 0;
159
- height: var(--_overlay-size, var(--_detail-size, min-content));
175
+ height: var(--_overlay-size, var(--_detail-size));
176
+ max-height: 100%;
160
177
  }
161
178
 
162
179
  :host([has-detail][overlay][overlay-containment='viewport']) :is(#detail, #outgoing, #backdrop) {
@@ -84,9 +84,15 @@ export interface MasterDetailLayoutEventMap extends HTMLElementEventMap, MasterD
84
84
  declare class MasterDetailLayout extends ThemableMixin(ElementMixin(HTMLElement)) {
85
85
  /**
86
86
  * Size (in CSS length units) to be set on the detail area in
87
- * the CSS grid layout. If there is not enough space to show
87
+ * the CSS grid layout. When there is not enough space to show
88
88
  * master and detail areas next to each other, the detail area
89
- * is shown as an overlay. Defaults to 15em.
89
+ * is shown as an overlay.
90
+ * <p>
91
+ * If not specified, the size is determined automatically by measuring
92
+ * the detail content in a `min-content` CSS grid column when it first
93
+ * becomes visible, and then caching the resulting intrinsic size. To
94
+ * recalculate the cached intrinsic size, use the `recalculateLayout`
95
+ * method.
90
96
  *
91
97
  * @attr {string} detail-size
92
98
  */
@@ -143,6 +149,21 @@ declare class MasterDetailLayout extends ThemableMixin(ElementMixin(HTMLElement)
143
149
  */
144
150
  noAnimation: boolean;
145
151
 
152
+ /**
153
+ * When `detailSize` is not explicitly set, re-measures the cached intrinsic size of
154
+ * the detail content by placing it in a min-content CSS grid column, then repeats
155
+ * this process for ancestor master-detail layouts without an explicit `detailSize`,
156
+ * if any, so that their detail areas also adapt.
157
+ *
158
+ * Call this method after changing the detail content in a way that affects its intrinsic
159
+ * size — for example, when opening a detail in a nested master-detail layout that was
160
+ * not previously visible.
161
+ *
162
+ * NOTE: This method can be expensive in large layouts as it triggers consecutive
163
+ * synchronous DOM reads and writes.
164
+ */
165
+ recalculateLayout(): void;
166
+
146
167
  addEventListener<K extends keyof MasterDetailLayoutEventMap>(
147
168
  type: K,
148
169
  listener: (this: MasterDetailLayout, ev: MasterDetailLayoutEventMap[K]) => void,
@@ -6,6 +6,7 @@
6
6
  import { html, LitElement, nothing } from 'lit';
7
7
  import { getFocusableElements } from '@vaadin/a11y-base/src/focus-utils.js';
8
8
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
9
+ import { getClosestElement } from '@vaadin/component-base/src/dom-utils.js';
9
10
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
10
11
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
11
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
@@ -20,6 +21,18 @@ function parseTrackSizes(gridTemplate) {
20
21
  .map(parseFloat);
21
22
  }
22
23
 
24
+ function detectOverflow(hostSize, trackSizes) {
25
+ const [masterSize, masterExtra, detailSize] = trackSizes;
26
+
27
+ if (Math.floor(masterSize + masterExtra + detailSize) <= Math.floor(hostSize)) {
28
+ return false;
29
+ }
30
+ if (Math.floor(masterExtra) >= Math.floor(detailSize)) {
31
+ return false;
32
+ }
33
+ return true;
34
+ }
35
+
23
36
  /**
24
37
  * `<vaadin-master-detail-layout>` is a web component for building UIs with a master
25
38
  * (or primary) area and a detail (or secondary) area that is displayed next to, or
@@ -105,9 +118,15 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
105
118
  return {
106
119
  /**
107
120
  * Size (in CSS length units) to be set on the detail area in
108
- * the CSS grid layout. If there is not enough space to show
121
+ * the CSS grid layout. When there is not enough space to show
109
122
  * master and detail areas next to each other, the detail area
110
- * is shown as an overlay. Defaults to 15em.
123
+ * is shown as an overlay.
124
+ * <p>
125
+ * If not specified, the size is determined automatically by measuring
126
+ * the detail content in a `min-content` CSS grid column when it first
127
+ * becomes visible, and then caching the resulting intrinsic size. To
128
+ * recalculate the cached intrinsic size, use the `recalculateLayout`
129
+ * method.
111
130
  *
112
131
  * @attr {string} detail-size
113
132
  */
@@ -155,6 +174,7 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
155
174
  value: 'horizontal',
156
175
  reflectToAttribute: true,
157
176
  sync: true,
177
+ observer: '__orientationChanged',
158
178
  },
159
179
 
160
180
  /**
@@ -200,6 +220,13 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
200
220
  type: Boolean,
201
221
  sync: true,
202
222
  },
223
+
224
+ /** @private */
225
+ __detailCachedSize: {
226
+ type: String,
227
+ observer: '__detailCachedSizeChanged',
228
+ sync: true,
229
+ },
203
230
  };
204
231
  }
205
232
 
@@ -253,11 +280,26 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
253
280
  /** @private */
254
281
  __masterSizeChanged(size, oldSize) {
255
282
  this.__updateStyleProperty('master-size', size, oldSize);
283
+
284
+ if (oldSize != null) {
285
+ this.recalculateLayout();
286
+ }
256
287
  }
257
288
 
258
289
  /** @private */
259
290
  __detailSizeChanged(size, oldSize) {
260
291
  this.__updateStyleProperty('detail-size', size, oldSize);
292
+
293
+ if (oldSize != null) {
294
+ this.recalculateLayout();
295
+ }
296
+ }
297
+
298
+ /** @private */
299
+ __orientationChanged(_orientation, oldOrientation) {
300
+ if (oldOrientation != null) {
301
+ this.recalculateLayout();
302
+ }
261
303
  }
262
304
 
263
305
  /** @private */
@@ -265,6 +307,11 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
265
307
  this.__updateStyleProperty('overlay-size', size, oldSize);
266
308
  }
267
309
 
310
+ /** @private */
311
+ __detailCachedSizeChanged(size, oldSize) {
312
+ this.__updateStyleProperty('detail-cached-size', size, oldSize);
313
+ }
314
+
268
315
  /** @private */
269
316
  __updateStyleProperty(prop, size, oldSize) {
270
317
  if (size) {
@@ -297,9 +344,9 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
297
344
  * @private
298
345
  */
299
346
  __onResize() {
300
- const state = this.__computeLayoutState();
347
+ const state = this.__readLayoutState();
301
348
  cancelAnimationFrame(this.__resizeRaf);
302
- this.__resizeRaf = requestAnimationFrame(() => this.__applyLayoutState(state));
349
+ this.__resizeRaf = requestAnimationFrame(() => this.__writeLayoutState(state));
303
350
  }
304
351
 
305
352
  /**
@@ -307,26 +354,56 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
307
354
  * ResizeObserver callback where layout is already computed (no forced reflow).
308
355
  * @private
309
356
  */
310
- __computeLayoutState() {
357
+ __readLayoutState() {
358
+ const isVertical = this.orientation === 'vertical';
359
+
311
360
  const detailContent = this.querySelector(':scope > [slot="detail"]');
312
361
  const detailPlaceholder = this.querySelector(':scope > [slot="detail-placeholder"]');
313
362
 
314
363
  const hadDetail = this.hasAttribute('has-detail');
315
364
  const hasDetail = detailContent != null && detailContent.checkVisibility();
316
365
  const hasDetailPlaceholder = !!detailPlaceholder;
317
- const hasOverflow = (hasDetail || hasDetailPlaceholder) && this.__checkOverflow();
318
366
 
367
+ const computedStyle = getComputedStyle(this);
368
+ const hostSizeProp = isVertical ? 'height' : 'width';
369
+ const hostSize = parseFloat(computedStyle[hostSizeProp]);
370
+
371
+ const trackSizesProp = isVertical ? 'gridTemplateRows' : 'gridTemplateColumns';
372
+ const trackSizes = parseTrackSizes(computedStyle[trackSizesProp]);
373
+
374
+ const hasOverflow = (hasDetail || hasDetailPlaceholder) && detectOverflow(hostSize, trackSizes);
319
375
  const focusTarget = !hadDetail && hasDetail && hasOverflow ? getFocusableElements(detailContent)[0] : null;
320
- return { hadDetail, hasDetail, hasDetailPlaceholder, hasOverflow, focusTarget };
376
+
377
+ return {
378
+ hadDetail,
379
+ hasDetail,
380
+ hasDetailPlaceholder,
381
+ hasOverflow,
382
+ focusTarget,
383
+ hostSize,
384
+ trackSizes,
385
+ };
321
386
  }
322
387
 
323
388
  /**
324
389
  * Applies layout state to DOM attributes. Pure writes, no reads.
325
390
  * @private
326
391
  */
327
- __applyLayoutState({ hadDetail, hasDetail, hasDetailPlaceholder, hasOverflow, focusTarget }) {
328
- // Set keep-detail-column-offscreen when detail first appears with overlay
329
- // to prevent master width from jumping.
392
+ __writeLayoutState({ hadDetail, hasDetail, hasDetailPlaceholder, hasOverflow, focusTarget, trackSizes }) {
393
+ const [_masterSize, _masterExtra, detailSize] = trackSizes;
394
+
395
+ // If no detailSize is explicitily set, cache the intrinsic size (min-content) of
396
+ // the slotted detail content to use as a fallback for the detail column size
397
+ // while the detail content is rendered in an overlay.
398
+ if ((hasDetail || hasDetailPlaceholder) && this.__isDetailAutoSized && detailSize > 0) {
399
+ this.__detailCachedSize = this.__detailCachedSize || `${Math.ceil(detailSize)}px`;
400
+ } else {
401
+ this.__detailCachedSize = null;
402
+ }
403
+
404
+ // Force the detail column offscreen when it first appears and overflow
405
+ // is already detected. This prevents unnecessary master column shrinking,
406
+ // as the detail content is rendered in an overlay anyway.
330
407
  if (!hadDetail && hasDetail && hasOverflow) {
331
408
  this.setAttribute('keep-detail-column-offscreen', '');
332
409
  } else if (!hasDetail || !hasOverflow) {
@@ -346,23 +423,59 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
346
423
  }
347
424
  }
348
425
 
349
- /** @private */
350
- __checkOverflow() {
351
- const isVertical = this.orientation === 'vertical';
352
- const computedStyle = getComputedStyle(this);
426
+ /**
427
+ * When `detailSize` is not explicitly set, re-measures the cached intrinsic size of
428
+ * the detail content by placing it in a min-content CSS grid column, then repeats
429
+ * this process for ancestor master-detail layouts without an explicit `detailSize`,
430
+ * if any, so that their detail areas also adapt.
431
+ *
432
+ * Call this method after changing the detail content in a way that affects its intrinsic
433
+ * size — for example, when opening a detail in a nested master-detail layout that was
434
+ * not previously visible.
435
+ *
436
+ * NOTE: This method can be expensive in large layouts as it triggers consecutive
437
+ * synchronous DOM reads and writes.
438
+ */
439
+ recalculateLayout() {
440
+ // Cancel any pending ResizeObserver rAF to prevent it from potentially
441
+ // overriding the layout state with stale measurements.
442
+ cancelAnimationFrame(this.__resizeRaf);
353
443
 
354
- const hostSize = parseFloat(computedStyle[isVertical ? 'height' : 'width']);
355
- const [masterSize, masterExtra, detailSize] = parseTrackSizes(
356
- computedStyle[isVertical ? 'gridTemplateRows' : 'gridTemplateColumns'],
357
- );
444
+ const invalidatedLayouts = [...this.__ancestorLayouts.filter((layout) => layout.__isDetailAutoSized), this];
358
445
 
359
- if (Math.floor(masterSize + masterExtra + detailSize) <= Math.floor(hostSize)) {
360
- return false;
361
- }
362
- if (Math.floor(masterExtra) >= Math.floor(detailSize)) {
363
- return false;
364
- }
365
- return true;
446
+ // Write
447
+ invalidatedLayouts.forEach((layout) => {
448
+ layout.__detailCachedSize = null;
449
+
450
+ if (layout.__isDetailAutoSized) {
451
+ layout.removeAttribute('overlay');
452
+ layout.toggleAttribute('recalculating-detail-size', true);
453
+ }
454
+ });
455
+
456
+ // Read/Write
457
+ invalidatedLayouts.forEach((layout) => {
458
+ const state = layout.__readLayoutState();
459
+ layout.__writeLayoutState(state);
460
+ });
461
+
462
+ // Write
463
+ invalidatedLayouts.forEach((layout) => {
464
+ if (layout.__isDetailAutoSized) {
465
+ layout.toggleAttribute('recalculating-detail-size', false);
466
+ }
467
+ });
468
+ }
469
+
470
+ /** @private */
471
+ get __isDetailAutoSized() {
472
+ return this.detailSize == null;
473
+ }
474
+
475
+ /** @private */
476
+ get __ancestorLayouts() {
477
+ const parent = getClosestElement(this.constructor.is, this.parentNode);
478
+ return parent ? [...parent.__ancestorLayouts, parent] : [];
366
479
  }
367
480
 
368
481
  /** @private */
@@ -413,10 +526,7 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
413
526
 
414
527
  if (skipTransition || this.noAnimation) {
415
528
  updateSlot();
416
- queueMicrotask(() => {
417
- const state = this.__computeLayoutState();
418
- this.__applyLayoutState(state);
419
- });
529
+ queueMicrotask(() => this.recalculateLayout());
420
530
  return Promise.resolve();
421
531
  }
422
532
 
@@ -561,8 +671,7 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
561
671
  * @protected
562
672
  */
563
673
  _finishTransition() {
564
- const state = this.__computeLayoutState();
565
- this.__applyLayoutState(state);
674
+ queueMicrotask(() => this.recalculateLayout());
566
675
  }
567
676
 
568
677
  /**
@@ -670,10 +779,6 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
670
779
  }
671
780
  this.removeAttribute('transition');
672
781
  this.__clearOutgoing();
673
- // Cancel any pending ResizeObserver rAF that captured stale state
674
- // during the animation — _finishTransition already applied the
675
- // correct post-transition state synchronously.
676
- cancelAnimationFrame(this.__resizeRaf);
677
782
  if (this.__transitionResolve) {
678
783
  this.__transitionResolve();
679
784
  this.__transitionResolve = null;
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/master-detail-layout",
4
- "version": "25.2.0-alpha3",
4
+ "version": "25.2.0-alpha4",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -12,7 +12,7 @@
12
12
  "attributes": [
13
13
  {
14
14
  "name": "detail-size",
15
- "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. If there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay. Defaults to 15em.",
15
+ "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. When there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay.\n<p>\nIf not specified, the size is determined automatically by measuring\nthe detail content in a `min-content` CSS grid column when it first\nbecomes visible, and then caching the resulting intrinsic size. To\nrecalculate the cached intrinsic size, use the `recalculateLayout`\nmethod.",
16
16
  "value": {
17
17
  "type": [
18
18
  "string",
@@ -103,7 +103,7 @@
103
103
  "properties": [
104
104
  {
105
105
  "name": "detailSize",
106
- "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. If there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay. Defaults to 15em.",
106
+ "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. When there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay.\n<p>\nIf not specified, the size is determined automatically by measuring\nthe detail content in a `min-content` CSS grid column when it first\nbecomes visible, and then caching the resulting intrinsic size. To\nrecalculate the cached intrinsic size, use the `recalculateLayout`\nmethod.",
107
107
  "value": {
108
108
  "type": [
109
109
  "string",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/master-detail-layout",
4
- "version": "25.2.0-alpha3",
4
+ "version": "25.2.0-alpha4",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "name": ".detailSize",
31
- "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. If there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay. Defaults to 15em.",
31
+ "description": "Size (in CSS length units) to be set on the detail area in\nthe CSS grid layout. When there is not enough space to show\nmaster and detail areas next to each other, the detail area\nis shown as an overlay.\n<p>\nIf not specified, the size is determined automatically by measuring\nthe detail content in a `min-content` CSS grid column when it first\nbecomes visible, and then caching the resulting intrinsic size. To\nrecalculate the cached intrinsic size, use the `recalculateLayout`\nmethod.",
32
32
  "value": {
33
33
  "kind": "expression"
34
34
  }