@react-stately/layout 4.1.0 → 4.2.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 +98 -63
- package/dist/GridLayout.main.js.map +1 -1
- package/dist/GridLayout.mjs +99 -64
- package/dist/GridLayout.module.js +99 -64
- package/dist/GridLayout.module.js.map +1 -1
- package/dist/ListLayout.main.js +46 -20
- package/dist/ListLayout.main.js.map +1 -1
- package/dist/ListLayout.mjs +46 -20
- package/dist/ListLayout.module.js +46 -20
- package/dist/ListLayout.module.js.map +1 -1
- package/dist/TableLayout.main.js +20 -16
- package/dist/TableLayout.main.js.map +1 -1
- package/dist/TableLayout.mjs +20 -16
- package/dist/TableLayout.module.js +20 -16
- package/dist/TableLayout.module.js.map +1 -1
- package/dist/WaterfallLayout.main.js +212 -0
- package/dist/WaterfallLayout.main.js.map +1 -0
- package/dist/WaterfallLayout.mjs +207 -0
- package/dist/WaterfallLayout.module.js +207 -0
- package/dist/WaterfallLayout.module.js.map +1 -0
- package/dist/import.mjs +3 -1
- package/dist/main.js +3 -0
- package/dist/main.js.map +1 -1
- package/dist/module.js +3 -1
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +102 -29
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -9
- package/src/GridLayout.ts +154 -89
- package/src/ListLayout.ts +84 -34
- package/src/TableLayout.ts +28 -17
- package/src/WaterfallLayout.ts +302 -0
- package/src/index.ts +2 -0
package/src/ListLayout.ts
CHANGED
|
@@ -15,20 +15,41 @@ import {getChildNodes} from '@react-stately/collections';
|
|
|
15
15
|
import {InvalidationContext, Layout, LayoutInfo, Point, Rect, Size} from '@react-stately/virtualizer';
|
|
16
16
|
|
|
17
17
|
export interface ListLayoutOptions {
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The fixed height of a row in px.
|
|
20
|
+
* @default 48
|
|
21
|
+
*/
|
|
19
22
|
rowHeight?: number,
|
|
20
23
|
/** The estimated height of a row, when row heights are variable. */
|
|
21
24
|
estimatedRowHeight?: number,
|
|
22
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* The fixed height of a section header in px.
|
|
27
|
+
* @default 48
|
|
28
|
+
*/
|
|
23
29
|
headingHeight?: number,
|
|
24
30
|
/** The estimated height of a section header, when the height is variable. */
|
|
25
31
|
estimatedHeadingHeight?: number,
|
|
26
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* The fixed height of a loader element in px. This loader is specifically for
|
|
27
34
|
* "load more" elements rendered when loading more rows at the root level or inside nested row/sections.
|
|
35
|
+
* @default 48
|
|
28
36
|
*/
|
|
29
37
|
loaderHeight?: number,
|
|
30
|
-
/**
|
|
31
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The thickness of the drop indicator.
|
|
40
|
+
* @default 2
|
|
41
|
+
*/
|
|
42
|
+
dropIndicatorThickness?: number,
|
|
43
|
+
/**
|
|
44
|
+
* The gap between items.
|
|
45
|
+
* @default 0
|
|
46
|
+
*/
|
|
47
|
+
gap?: number,
|
|
48
|
+
/**
|
|
49
|
+
* The padding around the list.
|
|
50
|
+
* @default 0
|
|
51
|
+
*/
|
|
52
|
+
padding?: number
|
|
32
53
|
}
|
|
33
54
|
|
|
34
55
|
// A wrapper around LayoutInfo that supports hierarchy
|
|
@@ -43,24 +64,22 @@ export interface LayoutNode {
|
|
|
43
64
|
const DEFAULT_HEIGHT = 48;
|
|
44
65
|
|
|
45
66
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* The {@link ListKeyboardDelegate} extends the existing virtualizer
|
|
50
|
-
* delegate with an additional method to do this (it uses the same delegate object as
|
|
51
|
-
* the virtualizer itself).
|
|
67
|
+
* ListLayout is a virtualizer Layout implementation
|
|
68
|
+
* that arranges its items in a vertical stack. It supports both fixed
|
|
69
|
+
* and variable height items.
|
|
52
70
|
*/
|
|
53
|
-
export class ListLayout<T, O =
|
|
71
|
+
export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> extends Layout<Node<T>, O> implements DropTargetDelegate {
|
|
54
72
|
protected rowHeight: number | null;
|
|
55
73
|
protected estimatedRowHeight: number | null;
|
|
56
74
|
protected headingHeight: number | null;
|
|
57
75
|
protected estimatedHeadingHeight: number | null;
|
|
58
76
|
protected loaderHeight: number | null;
|
|
59
77
|
protected dropIndicatorThickness: number;
|
|
78
|
+
protected gap: number;
|
|
79
|
+
protected padding: number;
|
|
60
80
|
protected layoutNodes: Map<Key, LayoutNode>;
|
|
61
81
|
protected contentSize: Size;
|
|
62
82
|
protected lastCollection: Collection<Node<T>> | null;
|
|
63
|
-
private lastWidth: number;
|
|
64
83
|
protected rootNodes: LayoutNode[];
|
|
65
84
|
private invalidateEverything: boolean;
|
|
66
85
|
/** The rectangle containing currently valid layout infos. */
|
|
@@ -80,9 +99,10 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
80
99
|
this.estimatedHeadingHeight = options.estimatedHeadingHeight ?? null;
|
|
81
100
|
this.loaderHeight = options.loaderHeight ?? null;
|
|
82
101
|
this.dropIndicatorThickness = options.dropIndicatorThickness || 2;
|
|
102
|
+
this.gap = options.gap || 0;
|
|
103
|
+
this.padding = options.padding || 0;
|
|
83
104
|
this.layoutNodes = new Map();
|
|
84
105
|
this.rootNodes = [];
|
|
85
|
-
this.lastWidth = 0;
|
|
86
106
|
this.lastCollection = null;
|
|
87
107
|
this.invalidateEverything = false;
|
|
88
108
|
this.validRect = new Rect();
|
|
@@ -104,7 +124,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
104
124
|
// Adjust rect to keep number of visible rows consistent.
|
|
105
125
|
// (only if height > 1 for getDropTargetFromPoint)
|
|
106
126
|
if (rect.height > 1) {
|
|
107
|
-
let rowHeight = this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT;
|
|
127
|
+
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT) + this.gap;
|
|
108
128
|
rect.y = Math.floor(rect.y / rowHeight) * rowHeight;
|
|
109
129
|
rect.height = Math.ceil(rect.height / rowHeight) * rowHeight;
|
|
110
130
|
}
|
|
@@ -167,10 +187,28 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
167
187
|
return node.layoutInfo.rect.intersects(rect) || node.layoutInfo.isSticky || node.layoutInfo.type === 'header' || this.virtualizer!.isPersistedKey(node.layoutInfo.key);
|
|
168
188
|
}
|
|
169
189
|
|
|
170
|
-
protected shouldInvalidateEverything(invalidationContext: InvalidationContext<O>) {
|
|
190
|
+
protected shouldInvalidateEverything(invalidationContext: InvalidationContext<O>): boolean {
|
|
171
191
|
// Invalidate cache if the size of the collection changed.
|
|
172
192
|
// In this case, we need to recalculate the entire layout.
|
|
173
|
-
|
|
193
|
+
// Also invalidate if fixed sizes/gaps change.
|
|
194
|
+
let options = invalidationContext.layoutOptions;
|
|
195
|
+
return invalidationContext.sizeChanged
|
|
196
|
+
|| this.rowHeight !== (options?.rowHeight ?? this.rowHeight)
|
|
197
|
+
|| this.headingHeight !== (options?.headingHeight ?? this.headingHeight)
|
|
198
|
+
|| this.loaderHeight !== (options?.loaderHeight ?? this.loaderHeight)
|
|
199
|
+
|| this.gap !== (options?.gap ?? this.gap)
|
|
200
|
+
|| this.padding !== (options?.padding ?? this.padding);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean {
|
|
204
|
+
return newOptions.rowHeight !== oldOptions.rowHeight
|
|
205
|
+
|| newOptions.estimatedRowHeight !== oldOptions.estimatedRowHeight
|
|
206
|
+
|| newOptions.headingHeight !== oldOptions.headingHeight
|
|
207
|
+
|| newOptions.estimatedHeadingHeight !== oldOptions.estimatedHeadingHeight
|
|
208
|
+
|| newOptions.loaderHeight !== oldOptions.loaderHeight
|
|
209
|
+
|| newOptions.dropIndicatorThickness !== oldOptions.dropIndicatorThickness
|
|
210
|
+
|| newOptions.gap !== oldOptions.gap
|
|
211
|
+
|| newOptions.padding !== oldOptions.padding;
|
|
174
212
|
}
|
|
175
213
|
|
|
176
214
|
update(invalidationContext: InvalidationContext<O>) {
|
|
@@ -184,6 +222,16 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
184
222
|
this.layoutNodes.clear();
|
|
185
223
|
}
|
|
186
224
|
|
|
225
|
+
let options = invalidationContext.layoutOptions;
|
|
226
|
+
this.rowHeight = options?.rowHeight ?? this.rowHeight;
|
|
227
|
+
this.estimatedRowHeight = options?.estimatedRowHeight ?? this.estimatedRowHeight;
|
|
228
|
+
this.headingHeight = options?.headingHeight ?? this.headingHeight;
|
|
229
|
+
this.estimatedHeadingHeight = options?.estimatedHeadingHeight ?? this.estimatedHeadingHeight;
|
|
230
|
+
this.loaderHeight = options?.loaderHeight ?? this.loaderHeight;
|
|
231
|
+
this.dropIndicatorThickness = options?.dropIndicatorThickness ?? this.dropIndicatorThickness;
|
|
232
|
+
this.gap = options?.gap ?? this.gap;
|
|
233
|
+
this.padding = options?.padding ?? this.padding;
|
|
234
|
+
|
|
187
235
|
this.rootNodes = this.buildCollection();
|
|
188
236
|
|
|
189
237
|
// Remove deleted layout nodes
|
|
@@ -198,18 +246,17 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
198
246
|
}
|
|
199
247
|
}
|
|
200
248
|
|
|
201
|
-
this.lastWidth = this.virtualizer!.visibleRect.width;
|
|
202
249
|
this.lastCollection = collection;
|
|
203
250
|
this.invalidateEverything = false;
|
|
204
251
|
this.validRect = this.requestedRect.copy();
|
|
205
252
|
}
|
|
206
253
|
|
|
207
|
-
protected buildCollection(y =
|
|
254
|
+
protected buildCollection(y = this.padding): LayoutNode[] {
|
|
208
255
|
let collection = this.virtualizer!.collection;
|
|
209
256
|
let skipped = 0;
|
|
210
257
|
let nodes: LayoutNode[] = [];
|
|
211
258
|
for (let node of collection) {
|
|
212
|
-
let rowHeight = this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT;
|
|
259
|
+
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT) + this.gap;
|
|
213
260
|
|
|
214
261
|
// Skip rows before the valid rectangle unless they are already cached.
|
|
215
262
|
if (node.type === 'item' && y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
|
|
@@ -218,8 +265,8 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
218
265
|
continue;
|
|
219
266
|
}
|
|
220
267
|
|
|
221
|
-
let layoutNode = this.buildChild(node,
|
|
222
|
-
y = layoutNode.layoutInfo.rect.maxY;
|
|
268
|
+
let layoutNode = this.buildChild(node, this.padding, y, null);
|
|
269
|
+
y = layoutNode.layoutInfo.rect.maxY + this.gap;
|
|
223
270
|
nodes.push(layoutNode);
|
|
224
271
|
|
|
225
272
|
if (node.type === 'item' && y > this.requestedRect.maxY) {
|
|
@@ -228,6 +275,8 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
228
275
|
}
|
|
229
276
|
}
|
|
230
277
|
|
|
278
|
+
y -= this.gap;
|
|
279
|
+
y += this.padding;
|
|
231
280
|
this.contentSize = new Size(this.virtualizer!.visibleRect.width, y);
|
|
232
281
|
return nodes;
|
|
233
282
|
}
|
|
@@ -272,9 +321,9 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
272
321
|
}
|
|
273
322
|
|
|
274
323
|
protected buildLoader(node: Node<T>, x: number, y: number): LayoutNode {
|
|
275
|
-
let rect = new Rect(x, y,
|
|
324
|
+
let rect = new Rect(x, y, this.padding, 0);
|
|
276
325
|
let layoutInfo = new LayoutInfo('loader', node.key, rect);
|
|
277
|
-
rect.width = this.virtualizer!.contentSize.width;
|
|
326
|
+
rect.width = this.virtualizer!.contentSize.width - this.padding - x;
|
|
278
327
|
rect.height = this.loaderHeight || this.rowHeight || this.estimatedRowHeight || DEFAULT_HEIGHT;
|
|
279
328
|
|
|
280
329
|
return {
|
|
@@ -285,15 +334,15 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
285
334
|
|
|
286
335
|
protected buildSection(node: Node<T>, x: number, y: number): LayoutNode {
|
|
287
336
|
let collection = this.virtualizer!.collection;
|
|
288
|
-
let width = this.virtualizer!.visibleRect.width;
|
|
289
|
-
let rect = new Rect(
|
|
337
|
+
let width = this.virtualizer!.visibleRect.width - this.padding;
|
|
338
|
+
let rect = new Rect(x, y, width - x, 0);
|
|
290
339
|
let layoutInfo = new LayoutInfo(node.type, node.key, rect);
|
|
291
340
|
|
|
292
341
|
let startY = y;
|
|
293
342
|
let skipped = 0;
|
|
294
343
|
let children: LayoutNode[] = [];
|
|
295
344
|
for (let child of getChildNodes(node, collection)) {
|
|
296
|
-
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT);
|
|
345
|
+
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight ?? DEFAULT_HEIGHT) + this.gap;
|
|
297
346
|
|
|
298
347
|
// Skip rows before the valid rectangle unless they are already cached.
|
|
299
348
|
if (y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
|
|
@@ -303,7 +352,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
303
352
|
}
|
|
304
353
|
|
|
305
354
|
let layoutNode = this.buildChild(child, x, y, layoutInfo.key);
|
|
306
|
-
y = layoutNode.layoutInfo.rect.maxY;
|
|
355
|
+
y = layoutNode.layoutInfo.rect.maxY + this.gap;
|
|
307
356
|
children.push(layoutNode);
|
|
308
357
|
|
|
309
358
|
if (y > this.requestedRect.maxY) {
|
|
@@ -313,6 +362,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
313
362
|
}
|
|
314
363
|
}
|
|
315
364
|
|
|
365
|
+
y -= this.gap;
|
|
316
366
|
rect.height = y - startY;
|
|
317
367
|
|
|
318
368
|
return {
|
|
@@ -324,7 +374,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
324
374
|
}
|
|
325
375
|
|
|
326
376
|
protected buildSectionHeader(node: Node<T>, x: number, y: number): LayoutNode {
|
|
327
|
-
let width = this.virtualizer!.visibleRect.width;
|
|
377
|
+
let width = this.virtualizer!.visibleRect.width - this.padding;
|
|
328
378
|
let rectHeight = this.headingHeight;
|
|
329
379
|
let isEstimated = false;
|
|
330
380
|
|
|
@@ -339,7 +389,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
339
389
|
let curNode = this.virtualizer!.collection.getItem(node.key);
|
|
340
390
|
let lastNode = this.lastCollection ? this.lastCollection.getItem(node.key) : null;
|
|
341
391
|
rectHeight = previousLayoutInfo.rect.height;
|
|
342
|
-
isEstimated = width !==
|
|
392
|
+
isEstimated = width !== previousLayoutInfo.rect.width || curNode !== lastNode || previousLayoutInfo.estimatedSize;
|
|
343
393
|
} else {
|
|
344
394
|
rectHeight = (node.rendered ? this.estimatedHeadingHeight : 0);
|
|
345
395
|
isEstimated = true;
|
|
@@ -350,7 +400,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
350
400
|
rectHeight = DEFAULT_HEIGHT;
|
|
351
401
|
}
|
|
352
402
|
|
|
353
|
-
let headerRect = new Rect(
|
|
403
|
+
let headerRect = new Rect(x, y, width - x, rectHeight);
|
|
354
404
|
let header = new LayoutInfo('header', node.key, headerRect);
|
|
355
405
|
header.estimatedSize = isEstimated;
|
|
356
406
|
return {
|
|
@@ -362,7 +412,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
362
412
|
}
|
|
363
413
|
|
|
364
414
|
protected buildItem(node: Node<T>, x: number, y: number): LayoutNode {
|
|
365
|
-
let width = this.virtualizer!.visibleRect.width;
|
|
415
|
+
let width = this.virtualizer!.visibleRect.width - this.padding - x;
|
|
366
416
|
let rectHeight = this.rowHeight;
|
|
367
417
|
let isEstimated = false;
|
|
368
418
|
|
|
@@ -374,7 +424,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
374
424
|
let previousLayoutNode = this.layoutNodes.get(node.key);
|
|
375
425
|
if (previousLayoutNode) {
|
|
376
426
|
rectHeight = previousLayoutNode.layoutInfo.rect.height;
|
|
377
|
-
isEstimated = width !==
|
|
427
|
+
isEstimated = width !== previousLayoutNode.layoutInfo.rect.width || node !== previousLayoutNode.node || previousLayoutNode.layoutInfo.estimatedSize;
|
|
378
428
|
} else {
|
|
379
429
|
rectHeight = this.estimatedRowHeight;
|
|
380
430
|
isEstimated = true;
|
|
@@ -385,7 +435,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
|
|
|
385
435
|
rectHeight = DEFAULT_HEIGHT;
|
|
386
436
|
}
|
|
387
437
|
|
|
388
|
-
let rect = new Rect(x, y, width
|
|
438
|
+
let rect = new Rect(x, y, width, rectHeight);
|
|
389
439
|
let layoutInfo = new LayoutInfo(node.type, node.key, rect);
|
|
390
440
|
layoutInfo.estimatedSize = isEstimated;
|
|
391
441
|
return {
|
package/src/TableLayout.ts
CHANGED
|
@@ -18,12 +18,16 @@ import {LayoutNode, ListLayout, ListLayoutOptions} from './ListLayout';
|
|
|
18
18
|
import {TableCollection} from '@react-types/table';
|
|
19
19
|
import {TableColumnLayout} from '@react-stately/table';
|
|
20
20
|
|
|
21
|
-
export interface TableLayoutProps {
|
|
21
|
+
export interface TableLayoutProps extends ListLayoutOptions {
|
|
22
22
|
columnWidths?: Map<Key, number>
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const DEFAULT_ROW_HEIGHT = 48;
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* TableLayout is a virtualizer Layout implementation that arranges
|
|
29
|
+
* items in rows and columns.
|
|
30
|
+
*/
|
|
27
31
|
export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> extends ListLayout<T, O> {
|
|
28
32
|
protected lastCollection: TableCollection<T> | null = null;
|
|
29
33
|
private columnWidths: Map<Key, number> = new Map();
|
|
@@ -31,7 +35,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
31
35
|
private lastPersistedKeys: Set<Key> | null = null;
|
|
32
36
|
private persistedIndices: Map<Key, number[]> = new Map();
|
|
33
37
|
|
|
34
|
-
constructor(options
|
|
38
|
+
constructor(options?: ListLayoutOptions) {
|
|
35
39
|
super(options);
|
|
36
40
|
this.stickyColumnIndices = [];
|
|
37
41
|
}
|
|
@@ -53,6 +57,11 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
53
57
|
);
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean {
|
|
61
|
+
return newOptions.columnWidths !== oldOptions.columnWidths
|
|
62
|
+
|| super.shouldInvalidateLayoutOptions(newOptions, oldOptions);
|
|
63
|
+
}
|
|
64
|
+
|
|
56
65
|
update(invalidationContext: InvalidationContext<O>): void {
|
|
57
66
|
let newCollection = this.virtualizer!.collection as TableCollection<T>;
|
|
58
67
|
|
|
@@ -65,7 +74,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
65
74
|
}
|
|
66
75
|
} else if (invalidationContext.sizeChanged || this.columnsChanged(newCollection, this.lastCollection)) {
|
|
67
76
|
let columnLayout = new TableColumnLayout({});
|
|
68
|
-
this.columnWidths = columnLayout.buildColumnWidths(this.virtualizer!.visibleRect.width, newCollection, new Map());
|
|
77
|
+
this.columnWidths = columnLayout.buildColumnWidths(this.virtualizer!.visibleRect.width - this.padding * 2, newCollection, new Map());
|
|
69
78
|
invalidationContext.sizeChanged = true;
|
|
70
79
|
}
|
|
71
80
|
|
|
@@ -86,11 +95,11 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
86
95
|
|
|
87
96
|
let header = this.buildTableHeader();
|
|
88
97
|
this.layoutNodes.set(header.layoutInfo.key, header);
|
|
89
|
-
let body = this.buildBody(header.layoutInfo.rect.
|
|
98
|
+
let body = this.buildBody(header.layoutInfo.rect.maxY + this.gap);
|
|
90
99
|
this.lastPersistedKeys = null;
|
|
91
100
|
|
|
92
101
|
body.layoutInfo.rect.width = Math.max(header.layoutInfo.rect.width, body.layoutInfo.rect.width);
|
|
93
|
-
this.contentSize = new Size(body.layoutInfo.rect.width, body.layoutInfo.rect.maxY);
|
|
102
|
+
this.contentSize = new Size(body.layoutInfo.rect.width + this.padding * 2, body.layoutInfo.rect.maxY + this.padding);
|
|
94
103
|
return [
|
|
95
104
|
header,
|
|
96
105
|
body
|
|
@@ -99,16 +108,16 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
99
108
|
|
|
100
109
|
protected buildTableHeader(): LayoutNode {
|
|
101
110
|
let collection = this.virtualizer!.collection as TableCollection<T>;
|
|
102
|
-
let rect = new Rect(
|
|
111
|
+
let rect = new Rect(this.padding, this.padding, 0, 0);
|
|
103
112
|
let layoutInfo = new LayoutInfo('header', collection.head?.key ?? 'header', rect);
|
|
104
113
|
layoutInfo.isSticky = true;
|
|
105
114
|
layoutInfo.zIndex = 1;
|
|
106
115
|
|
|
107
|
-
let y =
|
|
116
|
+
let y = this.padding;
|
|
108
117
|
let width = 0;
|
|
109
118
|
let children: LayoutNode[] = [];
|
|
110
119
|
for (let headerRow of collection.headerRows) {
|
|
111
|
-
let layoutNode = this.buildChild(headerRow,
|
|
120
|
+
let layoutNode = this.buildChild(headerRow, this.padding, y, layoutInfo.key);
|
|
112
121
|
layoutNode.layoutInfo.parentKey = layoutInfo.key;
|
|
113
122
|
y = layoutNode.layoutInfo.rect.maxY;
|
|
114
123
|
width = Math.max(width, layoutNode.layoutInfo.rect.width);
|
|
@@ -117,7 +126,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
rect.width = width;
|
|
120
|
-
rect.height = y;
|
|
129
|
+
rect.height = y - this.padding;
|
|
121
130
|
|
|
122
131
|
return {
|
|
123
132
|
layoutInfo,
|
|
@@ -128,7 +137,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
protected buildHeaderRow(headerRow: GridNode<T>, x: number, y: number): LayoutNode {
|
|
131
|
-
let rect = new Rect(
|
|
140
|
+
let rect = new Rect(x, y, 0, 0);
|
|
132
141
|
let row = new LayoutInfo('headerrow', headerRow.key, rect);
|
|
133
142
|
|
|
134
143
|
let height = 0;
|
|
@@ -148,7 +157,7 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
148
157
|
this.setChildHeights(columns, height);
|
|
149
158
|
|
|
150
159
|
rect.height = height;
|
|
151
|
-
rect.width = x;
|
|
160
|
+
rect.width = x - rect.x;
|
|
152
161
|
|
|
153
162
|
return {
|
|
154
163
|
layoutInfo: row,
|
|
@@ -171,10 +180,10 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
171
180
|
// used to get the column widths when rendering to the DOM
|
|
172
181
|
private getRenderedColumnWidth(node: GridNode<T>) {
|
|
173
182
|
let collection = this.virtualizer!.collection as TableCollection<T>;
|
|
174
|
-
let
|
|
183
|
+
let colSpan = node.colSpan ?? 1;
|
|
175
184
|
let colIndex = node.colIndex ?? node.index;
|
|
176
185
|
let width = 0;
|
|
177
|
-
for (let i = colIndex; i < colIndex +
|
|
186
|
+
for (let i = colIndex; i < colIndex + colSpan; i++) {
|
|
178
187
|
let column = collection.columns[i];
|
|
179
188
|
if (column?.key != null) {
|
|
180
189
|
width += this.columnWidths.get(column.key) ?? 0;
|
|
@@ -234,14 +243,14 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
234
243
|
|
|
235
244
|
protected buildBody(y: number): LayoutNode {
|
|
236
245
|
let collection = this.virtualizer!.collection as TableCollection<T>;
|
|
237
|
-
let rect = new Rect(
|
|
246
|
+
let rect = new Rect(this.padding, y, 0, 0);
|
|
238
247
|
let layoutInfo = new LayoutInfo('rowgroup', collection.body.key, rect);
|
|
239
248
|
|
|
240
249
|
let startY = y;
|
|
241
250
|
let skipped = 0;
|
|
242
251
|
let width = 0;
|
|
243
252
|
let children: LayoutNode[] = [];
|
|
244
|
-
let rowHeight = this.getEstimatedRowHeight();
|
|
253
|
+
let rowHeight = this.getEstimatedRowHeight() + this.gap;
|
|
245
254
|
for (let node of getChildNodes(collection.body, collection)) {
|
|
246
255
|
// Skip rows before the valid rectangle unless they are already cached.
|
|
247
256
|
if (y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
|
|
@@ -250,10 +259,10 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
250
259
|
continue;
|
|
251
260
|
}
|
|
252
261
|
|
|
253
|
-
let layoutNode = this.buildChild(node,
|
|
262
|
+
let layoutNode = this.buildChild(node, this.padding, y, layoutInfo.key);
|
|
254
263
|
layoutNode.layoutInfo.parentKey = layoutInfo.key;
|
|
255
264
|
layoutNode.index = children.length;
|
|
256
|
-
y = layoutNode.layoutInfo.rect.maxY;
|
|
265
|
+
y = layoutNode.layoutInfo.rect.maxY + this.gap;
|
|
257
266
|
width = Math.max(width, layoutNode.layoutInfo.rect.width);
|
|
258
267
|
children.push(layoutNode);
|
|
259
268
|
|
|
@@ -266,6 +275,8 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
|
|
|
266
275
|
|
|
267
276
|
if (children.length === 0) {
|
|
268
277
|
y = this.virtualizer!.visibleRect.maxY;
|
|
278
|
+
} else {
|
|
279
|
+
y -= this.gap;
|
|
269
280
|
}
|
|
270
281
|
|
|
271
282
|
rect.width = width;
|