@@ -12,21 +12,25 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
1212import { masterDetailLayoutStyles } from './styles/vaadin-master-detail-layout-base-styles.js' ;
1313
1414function parseTrackSizes ( gridTemplate ) {
15- return gridTemplate
15+ const sizes = gridTemplate
1616 . replace ( / \[ [ ^ \] ] + \] / gu, '' )
1717 . replace ( / \s + / gu, ' ' )
1818 . trim ( )
1919 . split ( ' ' )
2020 . map ( parseFloat ) ;
21+ return {
22+ masterSize : sizes [ 0 ] ,
23+ masterExtra : sizes [ 1 ] ,
24+ detailSize : sizes [ 2 ] ,
25+ detailExtra : sizes [ 3 ] ,
26+ } ;
2127}
2228
23- function detectOverflow ( hostSize , trackSizes ) {
24- const [ masterSize , masterExtra , detailSize ] = trackSizes ;
25-
26- if ( Math . floor ( masterSize + masterExtra + detailSize ) <= Math . floor ( hostSize ) ) {
29+ function detectOverflow ( { hostSize, masterSize, masterExtra, detailSize, detailExtra } ) {
30+ if ( Math . floor ( masterSize + masterExtra + detailSize + detailExtra ) <= Math . floor ( hostSize ) ) {
2731 return false ;
2832 }
29- if ( Math . floor ( masterExtra ) >= Math . floor ( detailSize ) ) {
33+ if ( Math . floor ( masterExtra ) >= Math . floor ( detailSize + detailExtra ) ) {
3034 return false ;
3135 }
3236 return true ;
@@ -217,13 +221,6 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
217221 type : Boolean ,
218222 sync : true ,
219223 } ,
220-
221- /** @private */
222- __detailCachedSize : {
223- type : String ,
224- observer : '__detailCachedSizeChanged' ,
225- sync : true ,
226- } ,
227224 } ;
228225 }
229226
@@ -282,19 +279,13 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
282279 /** @private */
283280 __detailSizeChanged ( size , oldSize ) {
284281 this . __updateStyleProperty ( 'detail-size' , size , oldSize ) ;
285- this . __detailCachedSize = null ;
286282 }
287283
288284 /** @private */
289285 __overlaySizeChanged ( size , oldSize ) {
290286 this . __updateStyleProperty ( 'overlay-size' , size , oldSize ) ;
291287 }
292288
293- /** @private */
294- __detailCachedSizeChanged ( size , oldSize ) {
295- this . __updateStyleProperty ( 'detail-cached-size' , size , oldSize ) ;
296- }
297-
298289 /** @private */
299290 __updateStyleProperty ( prop , size , oldSize ) {
300291 if ( size ) {
@@ -314,7 +305,7 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
314305 this . __resizeObserver = this . __resizeObserver || new ResizeObserver ( ( ) => this . __onResize ( ) ) ;
315306 this . __resizeObserver . disconnect ( ) ;
316307
317- const children = this . querySelectorAll ( ':scope > [slot="detail"], :scope >:not([slot])' ) ;
308+ const children = this . querySelectorAll ( ':scope > [slot="detail"], :scope > :not([slot])' ) ;
318309 [ this , this . $ . master , this . $ . detail , ...children ] . forEach ( ( node ) => {
319310 this . __resizeObserver . observe ( node ) ;
320311 } ) ;
@@ -340,7 +331,7 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
340331 __readLayoutState ( ) {
341332 const isVertical = this . orientation === 'vertical' ;
342333
343- const detailContent = this . querySelector ( '[slot="detail"]' ) ;
334+ const detailContent = this . querySelector ( ':scope > [slot="detail"]' ) ;
344335 const detailPlaceholder = this . querySelector ( ':scope > [slot="detail-placeholder"]' ) ;
345336
346337 const hadDetail = this . hasAttribute ( 'has-detail' ) ;
@@ -354,52 +345,52 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
354345 const trackSizesProp = isVertical ? 'gridTemplateRows' : 'gridTemplateColumns' ;
355346 const trackSizes = parseTrackSizes ( computedStyle [ trackSizesProp ] ) ;
356347
357- const hadOverflow = this . hasAttribute ( 'overlay' ) ;
358- const hasOverflow = ( hasDetail || hasDetailPlaceholder ) && detectOverflow ( hostSize , trackSizes ) ;
348+ let nestedLayoutSize = 0 ;
349+ if ( hasDetail && detailContent . matches ( this . constructor . is ) ) {
350+ const nestedLayout = detailContent . __readLayoutState ( ) ;
351+
352+ nestedLayoutSize += nestedLayout . trackSizes . masterSize ;
353+
354+ if ( nestedLayout . nestedLayoutSize > 0 ) {
355+ nestedLayoutSize += nestedLayout . nestedLayoutSize ;
356+ } else if ( nestedLayout . hasDetail ) {
357+ nestedLayoutSize += nestedLayout . trackSizes . detailSize ;
358+ }
359+ }
360+
361+ const hasOverflow =
362+ ( hasDetail || hasDetailPlaceholder ) &&
363+ detectOverflow ( {
364+ hostSize,
365+ masterSize : trackSizes . masterSize ,
366+ masterExtra : trackSizes . masterExtra ,
367+ detailSize : nestedLayoutSize > 0 ? nestedLayoutSize : trackSizes . detailSize ,
368+ detailExtra : trackSizes . detailExtra ,
369+ } ) ;
359370 const focusTarget = ! hadDetail && hasDetail && hasOverflow ? getFocusableElements ( detailContent ) [ 0 ] : null ;
360371
361372 return {
362373 hadDetail,
363374 hasDetail,
364375 hasDetailPlaceholder,
365- hadOverflow,
366376 hasOverflow,
367377 focusTarget,
368378 hostSize,
369379 trackSizes,
380+ nestedLayoutSize,
370381 } ;
371382 }
372383
373384 /**
374385 * Applies layout state to DOM attributes. Pure writes, no reads.
375386 * @private
376387 */
377- __writeLayoutState ( {
378- hadDetail,
379- hasDetail,
380- hasDetailPlaceholder,
381- hasOverflow,
382- hadOverflow,
383- focusTarget,
384- trackSizes,
385- } ) {
386- const [ _masterSize , _masterExtra , detailSize ] = trackSizes ;
387-
388- // If no detailSize is explicitily set, cache the intrinsic size (min-content) of
389- // the slotted detail content to use as a fallback for the detail column size
390- // while the detail content is rendered in an overlay.
391- if ( ! hadOverflow && hasOverflow && ! this . detailSize && ! this . __detailCachedSize ) {
392- this . __detailCachedSize = `${ Math . ceil ( detailSize ) } px` ;
393- }
394-
395- if ( ( hadOverflow && ! hasOverflow ) || ( ! hasDetail && ! hasDetailPlaceholder ) ) {
396- this . __detailCachedSize = null ;
388+ __writeLayoutState ( { hadDetail, hasDetail, hasDetailPlaceholder, hasOverflow, focusTarget, nestedLayoutSize } ) {
389+ if ( nestedLayoutSize > 0 ) {
390+ this . style . setProperty ( '--_nested-layout-size' , `${ nestedLayoutSize } px` ) ;
391+ } else {
392+ this . style . removeProperty ( '--_nested-layout-size' ) ;
397393 }
398- // if (!this.detailSize && !this.__detailCachedSize && hasDetail && detailSize > 0) {
399- // this.__detailCachedSize = `${Math.ceil(detailSize)}px`;
400- // } else if (hadDetail && !hasDetail) {
401- // this.__detailCachedSize = null;
402- // }
403394
404395 // Force the detail column offscreen when it first appears and overflow
405396 // is already detected. This prevents unnecessary master column shrinking,
@@ -423,17 +414,6 @@ class MasterDetailLayout extends ElementMixin(ThemableMixin(PolylitMixin(LitElem
423414 }
424415 }
425416
426- recalculateDetailSize ( ) {
427- this . __detailCachedSize = null ;
428- this . removeAttribute ( 'overlay' ) ;
429- this . toggleAttribute ( 'recalculating-detail-size' , true ) ;
430-
431- const { focusTarget, ...state } = this . __readLayoutState ( ) ;
432- this . __writeLayoutState ( state ) ;
433-
434- this . toggleAttribute ( 'recalculating-detail-size' , false ) ;
435- }
436-
437417 /** @private */
438418 __onBackdropClick ( ) {
439419 this . dispatchEvent ( new CustomEvent ( 'backdrop-click' ) ) ;
0 commit comments