@react-stately/layout 4.3.1 → 4.4.0
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/dist/GridLayout.main.js +13 -4
- package/dist/GridLayout.main.js.map +1 -1
- package/dist/GridLayout.mjs +13 -4
- package/dist/GridLayout.module.js +13 -4
- package/dist/GridLayout.module.js.map +1 -1
- package/dist/ListLayout.main.js +40 -17
- package/dist/ListLayout.main.js.map +1 -1
- package/dist/ListLayout.mjs +40 -17
- package/dist/ListLayout.module.js +40 -17
- package/dist/ListLayout.module.js.map +1 -1
- package/dist/TableLayout.main.js +3 -3
- package/dist/TableLayout.main.js.map +1 -1
- package/dist/TableLayout.mjs +3 -3
- package/dist/TableLayout.module.js +3 -3
- package/dist/TableLayout.module.js.map +1 -1
- package/dist/WaterfallLayout.main.js +4 -2
- package/dist/WaterfallLayout.main.js.map +1 -1
- package/dist/WaterfallLayout.mjs +4 -2
- package/dist/WaterfallLayout.module.js +4 -2
- package/dist/WaterfallLayout.module.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/GridLayout.ts +14 -4
- package/src/ListLayout.ts +40 -18
- package/src/TableLayout.ts +7 -7
- package/src/WaterfallLayout.ts +3 -2
package/src/GridLayout.ts
CHANGED
|
@@ -120,11 +120,21 @@ export class GridLayout<T, O extends GridLayoutOptions = GridLayoutOptions> exte
|
|
|
120
120
|
let horizontalSpacing = Math.floor((visibleWidth - numColumns * itemWidth) / (numColumns + 1));
|
|
121
121
|
this.gap = new Size(horizontalSpacing, minSpace.height);
|
|
122
122
|
|
|
123
|
+
// If there is a skeleton loader within the last 2 items in the collection, increment the collection size
|
|
124
|
+
// so that an additional row is added for the skeletons.
|
|
123
125
|
let collection = this.virtualizer!.collection;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let
|
|
127
|
-
|
|
126
|
+
let collectionSize = collection.size;
|
|
127
|
+
let lastKey = collection.getLastKey();
|
|
128
|
+
for (let i = 0; i < 2 && lastKey != null; i++) {
|
|
129
|
+
let item = collection.getItem(lastKey);
|
|
130
|
+
if (item?.type === 'skeleton') {
|
|
131
|
+
collectionSize++;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
lastKey = collection.getKeyBefore(lastKey);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let rows = Math.ceil(collectionSize / numColumns);
|
|
128
138
|
let iterator = collection[Symbol.iterator]();
|
|
129
139
|
let y = rows > 0 ? minSpace.height : 0;
|
|
130
140
|
let newLayoutInfos = new Map();
|
package/src/ListLayout.ts
CHANGED
|
@@ -251,43 +251,49 @@ export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> exte
|
|
|
251
251
|
this.validRect = this.requestedRect.copy();
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
-
protected buildCollection(y = this.padding): LayoutNode[] {
|
|
254
|
+
protected buildCollection(y: number = this.padding): LayoutNode[] {
|
|
255
255
|
let collection = this.virtualizer!.collection;
|
|
256
|
-
let
|
|
256
|
+
let collectionNodes = [...collection];
|
|
257
|
+
let loaderNodes = collectionNodes.filter(node => node.type === 'loader');
|
|
257
258
|
let nodes: LayoutNode[] = [];
|
|
258
|
-
let isEmptyOrLoading = collection?.size === 0
|
|
259
|
+
let isEmptyOrLoading = collection?.size === 0;
|
|
259
260
|
if (isEmptyOrLoading) {
|
|
260
261
|
y = 0;
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
for (let node of
|
|
264
|
+
for (let node of collectionNodes) {
|
|
264
265
|
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT) + this.gap;
|
|
265
266
|
// Skip rows before the valid rectangle unless they are already cached.
|
|
266
267
|
if (node.type === 'item' && y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
|
|
267
268
|
y += rowHeight;
|
|
268
|
-
skipped++;
|
|
269
269
|
continue;
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
let layoutNode = this.buildChild(node, this.padding, y, null);
|
|
273
273
|
y = layoutNode.layoutInfo.rect.maxY + this.gap;
|
|
274
274
|
nodes.push(layoutNode);
|
|
275
|
-
if (node.type === '
|
|
276
|
-
let
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
itemsAfterRect--;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
y += itemsAfterRect * rowHeight;
|
|
275
|
+
if (node.type === 'loader') {
|
|
276
|
+
let index = loaderNodes.indexOf(node);
|
|
277
|
+
loaderNodes.splice(index, 1);
|
|
278
|
+
}
|
|
283
279
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
280
|
+
// Build each loader that exists in the collection that is outside the visible rect so that they are persisted
|
|
281
|
+
// at the proper estimated location. If the node.type is "section" then we don't do this shortcut since we have to
|
|
282
|
+
// build the sections to see how tall they are.
|
|
283
|
+
if ((node.type === 'item' || node.type === 'loader') && y > this.requestedRect.maxY) {
|
|
284
|
+
let lastProcessedIndex = collectionNodes.indexOf(node);
|
|
285
|
+
for (let loaderNode of loaderNodes) {
|
|
286
|
+
let loaderNodeIndex = collectionNodes.indexOf(loaderNode);
|
|
287
|
+
// Subtract by an additional 1 since we've already added the current item's height to y
|
|
288
|
+
y += (loaderNodeIndex - lastProcessedIndex - 1) * rowHeight;
|
|
289
|
+
let loader = this.buildChild(loaderNode, this.padding, y, null);
|
|
288
290
|
nodes.push(loader);
|
|
289
291
|
y = loader.layoutInfo.rect.maxY;
|
|
292
|
+
lastProcessedIndex = loaderNodeIndex;
|
|
290
293
|
}
|
|
294
|
+
|
|
295
|
+
// Account for the rest of the items after the last loader spinner, subtract by 1 since we've processed the current node's height already
|
|
296
|
+
y += (collectionNodes.length - lastProcessedIndex - 1) * rowHeight;
|
|
291
297
|
break;
|
|
292
298
|
}
|
|
293
299
|
}
|
|
@@ -585,8 +591,24 @@ export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> exte
|
|
|
585
591
|
let layoutInfo = this.getLayoutInfo(target.key)!;
|
|
586
592
|
let rect: Rect;
|
|
587
593
|
if (target.dropPosition === 'before') {
|
|
588
|
-
rect = new Rect(layoutInfo.rect.x, layoutInfo.rect.y - this.dropIndicatorThickness / 2, layoutInfo.rect.width, this.dropIndicatorThickness);
|
|
594
|
+
rect = new Rect(layoutInfo.rect.x, Math.max(0, layoutInfo.rect.y - this.dropIndicatorThickness / 2), layoutInfo.rect.width, this.dropIndicatorThickness);
|
|
589
595
|
} else if (target.dropPosition === 'after') {
|
|
596
|
+
// Render after last visible descendant of the drop target.
|
|
597
|
+
let targetNode = this.collection.getItem(target.key);
|
|
598
|
+
if (targetNode) {
|
|
599
|
+
let targetLevel = targetNode.level ?? 0;
|
|
600
|
+
let currentKey = this.collection.getKeyAfter(target.key);
|
|
601
|
+
|
|
602
|
+
while (currentKey != null) {
|
|
603
|
+
let node = this.collection.getItem(currentKey);
|
|
604
|
+
if (!node || node.level <= targetLevel) {
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
layoutInfo = this.getLayoutInfo(currentKey) || layoutInfo;
|
|
609
|
+
currentKey = this.collection.getKeyAfter(currentKey);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
590
612
|
rect = new Rect(layoutInfo.rect.x, layoutInfo.rect.maxY - this.dropIndicatorThickness / 2, layoutInfo.rect.width, this.dropIndicatorThickness);
|
|
591
613
|
} else {
|
|
592
614
|
rect = layoutInfo.rect;
|
package/src/TableLayout.ts
CHANGED
|
@@ -68,9 +68,12 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
68
68
|
// If columnWidths were provided via layoutOptions, update those.
|
|
69
69
|
// Otherwise, calculate column widths ourselves.
|
|
70
70
|
if (invalidationContext.layoutOptions?.columnWidths) {
|
|
71
|
-
|
|
72
|
-
this.columnWidths
|
|
73
|
-
|
|
71
|
+
for (const [key, val] of invalidationContext.layoutOptions.columnWidths) {
|
|
72
|
+
if (this.columnWidths.get(key) !== val) {
|
|
73
|
+
this.columnWidths = invalidationContext.layoutOptions.columnWidths;
|
|
74
|
+
invalidationContext.sizeChanged = true;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
74
77
|
}
|
|
75
78
|
} else if (invalidationContext.sizeChanged || this.columnsChanged(newCollection, this.lastCollection)) {
|
|
76
79
|
let columnLayout = new TableColumnLayout({});
|
|
@@ -274,9 +277,6 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
274
277
|
if (y > this.requestedRect.maxY) {
|
|
275
278
|
let rowsAfterRect = collection.size - (children.length + skipped);
|
|
276
279
|
let lastNode = getLastItem(childNodes);
|
|
277
|
-
if (lastNode?.type === 'loader') {
|
|
278
|
-
rowsAfterRect--;
|
|
279
|
-
}
|
|
280
280
|
|
|
281
281
|
// Estimate the remaining height for rows that we don't need to layout right now.
|
|
282
282
|
y += rowsAfterRect * rowHeight;
|
|
@@ -296,7 +296,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
// Make sure that the table body gets a height if empty or performing initial load
|
|
299
|
-
let isEmptyOrLoading = collection?.size === 0
|
|
299
|
+
let isEmptyOrLoading = collection?.size === 0;
|
|
300
300
|
if (isEmptyOrLoading) {
|
|
301
301
|
y = this.virtualizer!.visibleRect.maxY;
|
|
302
302
|
} else {
|
package/src/WaterfallLayout.ts
CHANGED
|
@@ -169,8 +169,9 @@ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions
|
|
|
169
169
|
newLayoutInfos.set(lastNode.key, layoutInfo);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// 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
|
|
173
|
-
|
|
172
|
+
// 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,
|
|
173
|
+
// except if we are performing skeleton loading
|
|
174
|
+
let isEmptyOrLoading = collection?.size === 0 && collection.getItem(collection.getFirstKey()!)?.type !== 'skeleton';
|
|
174
175
|
let maxHeight = isEmptyOrLoading ? 0 : Math.max(...columnHeights);
|
|
175
176
|
this.contentSize = new Size(this.virtualizer!.visibleRect.width, maxHeight);
|
|
176
177
|
this.layoutInfos = newLayoutInfos;
|