@@ -43,7 +43,13 @@ export interface WaterfallLayoutOptions {
4343 * The thickness of the drop indicator.
4444 * @default 2
4545 */
46- dropIndicatorThickness ?: number
46+ dropIndicatorThickness ?: number ,
47+ /**
48+ * The fixed height of a loader element in px. This loader is specifically for
49+ * "load more" elements rendered when loading more rows at the root level or inside nested row/sections.
50+ * @default 48
51+ */
52+ loaderHeight ?: number
4753}
4854
4955class WaterfallLayoutInfo extends LayoutInfo {
@@ -64,7 +70,8 @@ const DEFAULT_OPTIONS = {
6470 minSpace : new Size ( 18 , 18 ) ,
6571 maxSpace : Infinity ,
6672 maxColumns : Infinity ,
67- dropIndicatorThickness : 2
73+ dropIndicatorThickness : 2 ,
74+ loaderHeight : 48
6875} ;
6976
7077export class WaterfallLayout < T extends object , O extends WaterfallLayoutOptions = WaterfallLayoutOptions > extends Layout < Node < T > , O > implements LayoutDelegate , DropTargetDelegate {
@@ -80,7 +87,8 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
8087 || ( ! ( newOptions . minItemSize || DEFAULT_OPTIONS . minItemSize ) . equals ( oldOptions . minItemSize || DEFAULT_OPTIONS . minItemSize ) )
8188 || ( ! ( newOptions . maxItemSize || DEFAULT_OPTIONS . maxItemSize ) . equals ( oldOptions . maxItemSize || DEFAULT_OPTIONS . maxItemSize ) )
8289 || ( ! ( newOptions . minSpace || DEFAULT_OPTIONS . minSpace ) . equals ( oldOptions . minSpace || DEFAULT_OPTIONS . minSpace ) )
83- || ( newOptions . maxHorizontalSpace !== oldOptions . maxHorizontalSpace ) ;
90+ || ( newOptions . maxHorizontalSpace !== oldOptions . maxHorizontalSpace )
91+ || newOptions . loaderHeight !== oldOptions . loaderHeight ;
8492 }
8593
8694 update ( invalidationContext : InvalidationContext < O > ) : void {
@@ -90,7 +98,8 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
9098 minSpace = DEFAULT_OPTIONS . minSpace ,
9199 maxHorizontalSpace = DEFAULT_OPTIONS . maxSpace ,
92100 maxColumns = DEFAULT_OPTIONS . maxColumns ,
93- dropIndicatorThickness = DEFAULT_OPTIONS . dropIndicatorThickness
101+ dropIndicatorThickness = DEFAULT_OPTIONS . dropIndicatorThickness ,
102+ loaderHeight = DEFAULT_OPTIONS . loaderHeight
94103 } = invalidationContext . layoutOptions || { } ;
95104 this . dropIndicatorThickness = dropIndicatorThickness ;
96105 let visibleWidth = this . virtualizer ! . visibleRect . width ;
@@ -174,19 +183,27 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
174183 }
175184 }
176185
186+ // Reset all columns to the maximum for the next section. If loading, set to 0 so virtualizer doesn't render its body since there aren't items to render,
187+ // except if we are performing skeleton loading
188+ let isEmptyOrLoading = collection ?. size === 0 && collection . getItem ( collection . getFirstKey ( ) ! ) ?. type !== 'skeleton' ;
189+ let maxHeight = isEmptyOrLoading ? 0 : Math . max ( ...columnHeights ) ;
190+
177191 // Always add the loader sentinel if present in the collection so we can make sure it is never virtualized out.
178192 // Add it under the first column for simplicity
179193 let lastNode = collection . getItem ( collection . getLastKey ( ) ! ) ;
180194 if ( lastNode ?. type === 'loader' ) {
181- let rect = new Rect ( horizontalSpacing , columnHeights [ 0 ] , itemWidth , 0 ) ;
195+ if ( skeletonCount > 0 || ! lastNode . props . isLoading ) {
196+ loaderHeight = 0 ;
197+ }
198+ const loaderWidth = visibleWidth - horizontalSpacing * 2 ;
199+ // Note that if the user provides isLoading to their sentinel during a case where they only want to render the emptyState, this will reserve
200+ // room for the loader alongside rendering the emptyState
201+ let rect = new Rect ( horizontalSpacing , maxHeight , loaderWidth , loaderHeight ) ;
182202 let layoutInfo = new LayoutInfo ( 'loader' , lastNode . key , rect ) ;
183203 newLayoutInfos . set ( lastNode . key , layoutInfo ) ;
204+ maxHeight = layoutInfo . rect . maxY ;
184205 }
185206
186- // Reset all columns to the maximum for the next section. If loading, set to 0 so virtualizer doesn't render its body since there aren't items to render,
187- // except if we are performing skeleton loading
188- let isEmptyOrLoading = collection ?. size === 0 && collection . getItem ( collection . getFirstKey ( ) ! ) ?. type !== 'skeleton' ;
189- let maxHeight = isEmptyOrLoading ? 0 : Math . max ( ...columnHeights ) ;
190207 this . contentSize = new Size ( this . virtualizer ! . visibleRect . width , maxHeight ) ;
191208 this . layoutInfos = newLayoutInfos ;
192209 this . numColumns = numColumns ;
0 commit comments