@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/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { DropTarget, DropTargetDelegate, ItemDropTarget, Key, Node, Collection } from "@react-types/shared";
2
- import { Layout, LayoutInfo, Rect, Size, InvalidationContext } from "@react-stately/virtualizer";
1
+ import { DropTarget, DropTargetDelegate, ItemDropTarget, Key, Node, Collection, LayoutDelegate } from "@react-types/shared";
2
+ import { InvalidationContext, Layout, LayoutInfo, Rect, Size } from "@react-stately/virtualizer";
3
3
  import { GridNode } from "@react-types/grid";
4
4
  import { TableCollection } from "@react-types/table";
5
5
  export interface GridLayoutOptions {
@@ -13,6 +13,13 @@ export interface GridLayoutOptions {
13
13
  * @default Infinity
14
14
  */
15
15
  maxItemSize?: Size;
16
+ /**
17
+ * Whether to preserve the aspect ratio of the `minItemSize`.
18
+ * By default, grid rows may have variable heights. When `preserveAspectRatio`
19
+ * is true, all rows will have equal heights.
20
+ * @default false
21
+ */
22
+ preserveAspectRatio?: boolean;
16
23
  /**
17
24
  * The minimum space required between items.
18
25
  * @default 18 x 18
@@ -29,41 +36,61 @@ export interface GridLayoutOptions {
29
36
  */
30
37
  dropIndicatorThickness?: number;
31
38
  }
32
- export class GridLayout<T, O = any> extends Layout<Node<T>, O> implements DropTargetDelegate {
33
- protected minItemSize: Size;
34
- protected maxItemSize: Size;
35
- protected minSpace: Size;
36
- protected maxColumns: number;
39
+ /**
40
+ * GridLayout is a virtualizer Layout implementation
41
+ * that arranges its items in a grid.
42
+ * The items are sized between a minimum and maximum size
43
+ * depending on the width of the container.
44
+ */
45
+ export class GridLayout<T, O extends GridLayoutOptions = GridLayoutOptions> extends Layout<Node<T>, O> implements DropTargetDelegate {
46
+ protected gap: Size;
37
47
  protected dropIndicatorThickness: number;
38
- protected itemSize: Size;
39
48
  protected numColumns: number;
40
- protected horizontalSpacing: number;
41
- protected layoutInfos: LayoutInfo[];
42
- constructor(options: GridLayoutOptions);
43
- update(): void;
44
- getVisibleLayoutInfos(rect: Rect): LayoutInfo[];
45
- protected getIndexAtPoint(x: number, y: number): number;
46
- getLayoutInfo(key: Key): LayoutInfo | null;
47
- protected getLayoutInfoForNode(node: Node<T>): LayoutInfo;
49
+ shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean;
50
+ update(invalidationContext: InvalidationContext<O>): void;
51
+ getLayoutInfo(key: Key): LayoutInfo;
48
52
  getContentSize(): Size;
53
+ getVisibleLayoutInfos(rect: Rect): LayoutInfo[];
54
+ updateItemSize(key: Key, size: Size): boolean;
49
55
  getDropTargetFromPoint(x: number, y: number, isValidDropTarget: (target: DropTarget) => boolean): DropTarget;
50
56
  getDropTargetLayoutInfo(target: ItemDropTarget): LayoutInfo;
51
57
  }
52
58
  export interface ListLayoutOptions {
53
- /** The fixed height of a row in px. */
59
+ /**
60
+ * The fixed height of a row in px.
61
+ * @default 48
62
+ */
54
63
  rowHeight?: number;
55
64
  /** The estimated height of a row, when row heights are variable. */
56
65
  estimatedRowHeight?: number;
57
- /** The fixed height of a section header in px. */
66
+ /**
67
+ * The fixed height of a section header in px.
68
+ * @default 48
69
+ */
58
70
  headingHeight?: number;
59
71
  /** The estimated height of a section header, when the height is variable. */
60
72
  estimatedHeadingHeight?: number;
61
- /** The fixed height of a loader element in px. This loader is specifically for
73
+ /**
74
+ * The fixed height of a loader element in px. This loader is specifically for
62
75
  * "load more" elements rendered when loading more rows at the root level or inside nested row/sections.
76
+ * @default 48
63
77
  */
64
78
  loaderHeight?: number;
65
- /** The thickness of the drop indicator. */
79
+ /**
80
+ * The thickness of the drop indicator.
81
+ * @default 2
82
+ */
66
83
  dropIndicatorThickness?: number;
84
+ /**
85
+ * The gap between items.
86
+ * @default 0
87
+ */
88
+ gap?: number;
89
+ /**
90
+ * The padding around the list.
91
+ * @default 0
92
+ */
93
+ padding?: number;
67
94
  }
68
95
  export interface LayoutNode {
69
96
  node?: Node<unknown>;
@@ -73,20 +100,19 @@ export interface LayoutNode {
73
100
  index?: number;
74
101
  }
75
102
  /**
76
- * The ListLayout class is an implementation of a virtualizer {@link Layout}.
77
- * To configure a ListLayout, you can use the properties to define the
78
- * layouts and/or use the method for defining indentation.
79
- * The {@link ListKeyboardDelegate} extends the existing virtualizer
80
- * delegate with an additional method to do this (it uses the same delegate object as
81
- * the virtualizer itself).
103
+ * ListLayout is a virtualizer Layout implementation
104
+ * that arranges its items in a vertical stack. It supports both fixed
105
+ * and variable height items.
82
106
  */
83
- export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTargetDelegate {
107
+ export class ListLayout<T, O extends ListLayoutOptions = ListLayoutOptions> extends Layout<Node<T>, O> implements DropTargetDelegate {
84
108
  protected rowHeight: number | null;
85
109
  protected estimatedRowHeight: number | null;
86
110
  protected headingHeight: number | null;
87
111
  protected estimatedHeadingHeight: number | null;
88
112
  protected loaderHeight: number | null;
89
113
  protected dropIndicatorThickness: number;
114
+ protected gap: number;
115
+ protected padding: number;
90
116
  protected layoutNodes: Map<Key, LayoutNode>;
91
117
  protected contentSize: Size;
92
118
  protected lastCollection: Collection<Node<T>> | null;
@@ -106,6 +132,7 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
106
132
  protected layoutIfNeeded(rect: Rect): void;
107
133
  protected isVisible(node: LayoutNode, rect: Rect): boolean;
108
134
  protected shouldInvalidateEverything(invalidationContext: InvalidationContext<O>): boolean;
135
+ shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean;
109
136
  update(invalidationContext: InvalidationContext<O>): void;
110
137
  protected buildCollection(y?: number): LayoutNode[];
111
138
  protected isValid(node: Node<T>, y: number): boolean | undefined;
@@ -120,13 +147,18 @@ export class ListLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
120
147
  getDropTargetFromPoint(x: number, y: number, isValidDropTarget: (target: DropTarget) => boolean): DropTarget | null;
121
148
  getDropTargetLayoutInfo(target: ItemDropTarget): LayoutInfo;
122
149
  }
123
- export interface TableLayoutProps {
150
+ export interface TableLayoutProps extends ListLayoutOptions {
124
151
  columnWidths?: Map<Key, number>;
125
152
  }
153
+ /**
154
+ * TableLayout is a virtualizer Layout implementation that arranges
155
+ * items in rows and columns.
156
+ */
126
157
  export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> extends ListLayout<T, O> {
127
158
  protected lastCollection: TableCollection<T> | null;
128
- constructor(options: ListLayoutOptions);
159
+ constructor(options?: ListLayoutOptions);
129
160
  protected get collection(): TableCollection<T>;
161
+ shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean;
130
162
  update(invalidationContext: InvalidationContext<O>): void;
131
163
  protected buildCollection(): LayoutNode[];
132
164
  protected buildTableHeader(): LayoutNode;
@@ -142,5 +174,46 @@ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> exten
142
174
  getDropTargetFromPoint(x: number, y: number, isValidDropTarget: (target: DropTarget) => boolean): DropTarget | null;
143
175
  getDropTargetLayoutInfo(target: ItemDropTarget): LayoutInfo;
144
176
  }
177
+ export interface WaterfallLayoutOptions {
178
+ /**
179
+ * The minimum item size.
180
+ * @default 200 x 200
181
+ */
182
+ minItemSize?: Size;
183
+ /**
184
+ * The maximum item size.
185
+ * @default Infinity
186
+ */
187
+ maxItemSize?: Size;
188
+ /**
189
+ * The minimum space required between items.
190
+ * @default 18 x 18
191
+ */
192
+ minSpace?: Size;
193
+ /**
194
+ * The maximum number of columns.
195
+ * @default Infinity
196
+ */
197
+ maxColumns?: number;
198
+ /**
199
+ * The thickness of the drop indicator.
200
+ * @default 2
201
+ */
202
+ dropIndicatorThickness?: number;
203
+ }
204
+ export class WaterfallLayout<T extends object, O extends WaterfallLayoutOptions = WaterfallLayoutOptions> extends Layout<Node<T>, O> implements LayoutDelegate, DropTargetDelegate {
205
+ protected numColumns: number;
206
+ protected dropIndicatorThickness: number;
207
+ shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean;
208
+ update(invalidationContext: InvalidationContext<O>): void;
209
+ getLayoutInfo(key: Key): LayoutInfo;
210
+ getContentSize(): Size;
211
+ getVisibleLayoutInfos(rect: Rect): LayoutInfo[];
212
+ updateItemSize(key: Key, size: Size): boolean;
213
+ getKeyRightOf(key: Key): Key | null;
214
+ getKeyLeftOf(key: Key): Key | null;
215
+ getKeyRange(from: Key, to: Key): Key[];
216
+ getDropTargetFromPoint(x: number, y: number): DropTarget;
217
+ }
145
218
 
146
219
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-stately/layout/src/packages/@react-stately/layout/src/GridLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/ListLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/TableLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/index.ts","packages/@react-stately/layout/src/index.ts"],"sourcesContent":[null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport type {GridLayoutOptions} from './GridLayout';\nexport type {ListLayoutOptions, LayoutNode} from './ListLayout';\nexport type {TableLayoutProps} from './TableLayout';\nexport {GridLayout} from './GridLayout';\nexport {ListLayout} from './ListLayout';\nexport {TableLayout} from './TableLayout';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
1
+ {"mappings":"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","sources":["packages/@react-stately/layout/src/packages/@react-stately/layout/src/GridLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/ListLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/TableLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/WaterfallLayout.ts","packages/@react-stately/layout/src/packages/@react-stately/layout/src/index.ts","packages/@react-stately/layout/src/index.ts"],"sourcesContent":[null,null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport type {GridLayoutOptions} from './GridLayout';\nexport type {ListLayoutOptions, LayoutNode} from './ListLayout';\nexport type {TableLayoutProps} from './TableLayout';\nexport type {WaterfallLayoutOptions} from './WaterfallLayout';\nexport {GridLayout} from './GridLayout';\nexport {ListLayout} from './ListLayout';\nexport {TableLayout} from './TableLayout';\nexport {WaterfallLayout} from './WaterfallLayout';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-stately/layout",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,19 +22,20 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@react-stately/collections": "^3.12.0",
26
- "@react-stately/table": "^3.13.0",
27
- "@react-stately/virtualizer": "^4.2.0",
28
- "@react-types/grid": "^3.2.10",
29
- "@react-types/shared": "^3.26.0",
30
- "@react-types/table": "^3.10.3",
25
+ "@react-stately/collections": "^3.12.2",
26
+ "@react-stately/table": "^3.14.0",
27
+ "@react-stately/virtualizer": "^4.3.0",
28
+ "@react-types/grid": "^3.3.0",
29
+ "@react-types/shared": "^3.28.0",
30
+ "@react-types/table": "^3.11.0",
31
31
  "@swc/helpers": "^0.5.0"
32
32
  },
33
33
  "peerDependencies": {
34
- "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
34
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
35
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
35
36
  },
36
37
  "publishConfig": {
37
38
  "access": "public"
38
39
  },
39
- "gitHead": "71f0ef23053f9e03ee7e97df736e8b083e006849"
40
+ "gitHead": "4d3c72c94eea2d72eb3a0e7d56000c6ef7e39726"
40
41
  }
package/src/GridLayout.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import {DropTarget, DropTargetDelegate, ItemDropTarget, Key, Node} from '@react-types/shared';
14
- import {Layout, LayoutInfo, Rect, Size} from '@react-stately/virtualizer';
14
+ import {InvalidationContext, Layout, LayoutInfo, Point, Rect, Size} from '@react-stately/virtualizer';
15
15
 
16
16
  export interface GridLayoutOptions {
17
17
  /**
@@ -24,6 +24,13 @@ export interface GridLayoutOptions {
24
24
  * @default Infinity
25
25
  */
26
26
  maxItemSize?: Size,
27
+ /**
28
+ * Whether to preserve the aspect ratio of the `minItemSize`.
29
+ * By default, grid rows may have variable heights. When `preserveAspectRatio`
30
+ * is true, all rows will have equal heights.
31
+ * @default false
32
+ */
33
+ preserveAspectRatio?: boolean,
27
34
  /**
28
35
  * The minimum space required between items.
29
36
  * @default 18 x 18
@@ -41,129 +48,187 @@ export interface GridLayoutOptions {
41
48
  dropIndicatorThickness?: number
42
49
  }
43
50
 
44
- export class GridLayout<T, O = any> extends Layout<Node<T>, O> implements DropTargetDelegate {
45
- protected minItemSize: Size;
46
- protected maxItemSize: Size;
47
- protected minSpace: Size;
48
- protected maxColumns: number;
49
- protected dropIndicatorThickness: number;
50
- protected itemSize: Size = new Size();
51
+ const DEFAULT_OPTIONS = {
52
+ minItemSize: new Size(200, 200),
53
+ maxItemSize: new Size(Infinity, Infinity),
54
+ preserveAspectRatio: false,
55
+ minSpace: new Size(18, 18),
56
+ maxColumns: Infinity,
57
+ dropIndicatorThickness: 2
58
+ };
59
+
60
+ /**
61
+ * GridLayout is a virtualizer Layout implementation
62
+ * that arranges its items in a grid.
63
+ * The items are sized between a minimum and maximum size
64
+ * depending on the width of the container.
65
+ */
66
+ export class GridLayout<T, O extends GridLayoutOptions = GridLayoutOptions> extends Layout<Node<T>, O> implements DropTargetDelegate {
67
+ protected gap: Size = DEFAULT_OPTIONS.minSpace;
68
+ protected dropIndicatorThickness = 2;
51
69
  protected numColumns: number = 0;
52
- protected horizontalSpacing: number = 0;
53
- protected layoutInfos: LayoutInfo[] = [];
54
-
55
- constructor(options: GridLayoutOptions) {
56
- super();
57
- this.minItemSize = options.minItemSize || new Size(200, 200);
58
- this.maxItemSize = options.maxItemSize || new Size(Infinity, Infinity);
59
- this.minSpace = options.minSpace || new Size(18, 18);
60
- this.maxColumns = options.maxColumns || Infinity;
61
- this.dropIndicatorThickness = options.dropIndicatorThickness || 2;
70
+ private contentSize: Size = new Size();
71
+ private layoutInfos: Map<Key, LayoutInfo> = new Map();
72
+
73
+ shouldInvalidateLayoutOptions(newOptions: O, oldOptions: O): boolean {
74
+ return newOptions.maxColumns !== oldOptions.maxColumns
75
+ || newOptions.dropIndicatorThickness !== oldOptions.dropIndicatorThickness
76
+ || newOptions.preserveAspectRatio !== oldOptions.preserveAspectRatio
77
+ || (!(newOptions.minItemSize || DEFAULT_OPTIONS.minItemSize).equals(oldOptions.minItemSize || DEFAULT_OPTIONS.minItemSize))
78
+ || (!(newOptions.maxItemSize || DEFAULT_OPTIONS.maxItemSize).equals(oldOptions.maxItemSize || DEFAULT_OPTIONS.maxItemSize))
79
+ || (!(newOptions.minSpace || DEFAULT_OPTIONS.minSpace).equals(oldOptions.minSpace || DEFAULT_OPTIONS.minSpace));
62
80
  }
63
81
 
64
- update(): void {
82
+ update(invalidationContext: InvalidationContext<O>): void {
83
+ let {
84
+ minItemSize = DEFAULT_OPTIONS.minItemSize,
85
+ maxItemSize = DEFAULT_OPTIONS.maxItemSize,
86
+ preserveAspectRatio = DEFAULT_OPTIONS.preserveAspectRatio,
87
+ minSpace = DEFAULT_OPTIONS.minSpace,
88
+ maxColumns = DEFAULT_OPTIONS.maxColumns,
89
+ dropIndicatorThickness = DEFAULT_OPTIONS.dropIndicatorThickness
90
+ } = invalidationContext.layoutOptions || {};
91
+ this.dropIndicatorThickness = dropIndicatorThickness;
92
+
65
93
  let visibleWidth = this.virtualizer!.visibleRect.width;
66
94
 
67
95
  // The max item width is always the entire viewport.
68
96
  // If the max item height is infinity, scale in proportion to the max width.
69
- let maxItemWidth = Math.min(this.maxItemSize.width, visibleWidth);
70
- let maxItemHeight = Number.isFinite(this.maxItemSize.height)
71
- ? this.maxItemSize.height
72
- : Math.floor((this.minItemSize.height / this.minItemSize.width) * maxItemWidth);
97
+ let maxItemWidth = Math.min(maxItemSize.width, visibleWidth);
98
+ let maxItemHeight = Number.isFinite(maxItemSize.height)
99
+ ? maxItemSize.height
100
+ : Math.floor((minItemSize.height / minItemSize.width) * maxItemWidth);
73
101
 
74
102
  // Compute the number of rows and columns needed to display the content
75
- let columns = Math.floor(visibleWidth / (this.minItemSize.width + this.minSpace.width));
76
- this.numColumns = Math.max(1, Math.min(this.maxColumns, columns));
103
+ let columns = Math.floor(visibleWidth / (minItemSize.width + minSpace.width));
104
+ let numColumns = Math.max(1, Math.min(maxColumns, columns));
77
105
 
78
106
  // Compute the available width (minus the space between items)
79
- let width = visibleWidth - (this.minSpace.width * Math.max(0, this.numColumns));
107
+ let width = visibleWidth - (minSpace.width * Math.max(0, numColumns));
80
108
 
81
109
  // Compute the item width based on the space available
82
- let itemWidth = Math.floor(width / this.numColumns);
83
- itemWidth = Math.max(this.minItemSize.width, Math.min(maxItemWidth, itemWidth));
110
+ let itemWidth = Math.floor(width / numColumns);
111
+ itemWidth = Math.max(minItemSize.width, Math.min(maxItemWidth, itemWidth));
84
112
 
85
113
  // Compute the item height, which is proportional to the item width
86
- let t = ((itemWidth - this.minItemSize.width) / Math.max(1, maxItemWidth - this.minItemSize.width));
87
- let itemHeight = this.minItemSize.height + Math.floor((maxItemHeight - this.minItemSize.height) * t);
88
- itemHeight = Math.max(this.minItemSize.height, Math.min(maxItemHeight, itemHeight));
89
- this.itemSize = new Size(itemWidth, itemHeight);
114
+ let t = ((itemWidth - minItemSize.width) / Math.max(1, maxItemWidth - minItemSize.width));
115
+ let itemHeight = minItemSize.height + Math.floor((maxItemHeight - minItemSize.height) * t);
116
+ itemHeight = Math.max(minItemSize.height, Math.min(maxItemHeight, itemHeight));
90
117
 
91
118
  // Compute the horizontal spacing and content height
92
- this.horizontalSpacing = Math.floor((visibleWidth - this.numColumns * this.itemSize.width) / (this.numColumns + 1));
119
+ let horizontalSpacing = Math.floor((visibleWidth - numColumns * itemWidth) / (numColumns + 1));
120
+ this.gap = new Size(horizontalSpacing, minSpace.height);
93
121
 
94
- this.layoutInfos = [];
95
- for (let node of this.virtualizer!.collection) {
96
- this.layoutInfos.push(this.getLayoutInfoForNode(node));
97
- }
98
- }
122
+ let rows = Math.ceil(this.virtualizer!.collection.size / numColumns);
123
+ let iterator = this.virtualizer!.collection[Symbol.iterator]();
124
+ let y = rows > 0 ? minSpace.height : 0;
125
+ let newLayoutInfos = new Map();
126
+ let skeleton: Node<T> | null = null;
127
+ let skeletonCount = 0;
128
+ for (let row = 0; row < rows; row++) {
129
+ let maxHeight = 0;
130
+ let rowLayoutInfos: LayoutInfo[] = [];
131
+ for (let col = 0; col < numColumns; col++) {
132
+ // Repeat skeleton until the end of the current row.
133
+ let node = skeleton || iterator.next().value;
134
+ if (!node) {
135
+ break;
136
+ }
99
137
 
100
- getVisibleLayoutInfos(rect: Rect): LayoutInfo[] {
101
- let firstVisibleItem = this.getIndexAtPoint(rect.x, rect.y);
102
- let lastVisibleItem = this.getIndexAtPoint(rect.maxX, rect.maxY);
103
- let result = this.layoutInfos.slice(firstVisibleItem, lastVisibleItem + 1);
104
- let persistedIndices: number[] = [];
105
- for (let key of this.virtualizer!.persistedKeys) {
106
- let item = this.virtualizer!.collection.getItem(key);
107
- if (item?.index != null) {
108
- persistedIndices.push(item.index);
138
+ if (node.type === 'skeleton') {
139
+ skeleton = node;
140
+ }
141
+
142
+ let key = skeleton ? `${skeleton.key}-${skeletonCount++}` : node.key;
143
+ let oldLayoutInfo = this.layoutInfos.get(key);
144
+ let content = node;
145
+ if (skeleton) {
146
+ content = oldLayoutInfo && oldLayoutInfo.content.key === key ? oldLayoutInfo.content : {...skeleton, key};
147
+ }
148
+ let x = horizontalSpacing + col * (itemWidth + horizontalSpacing);
149
+ let height = itemHeight;
150
+ let estimatedSize = !preserveAspectRatio;
151
+ if (oldLayoutInfo && estimatedSize) {
152
+ height = oldLayoutInfo.rect.height;
153
+ estimatedSize = invalidationContext.layoutOptionsChanged || invalidationContext.sizeChanged || oldLayoutInfo.estimatedSize || (oldLayoutInfo.content !== content);
154
+ }
155
+
156
+ let rect = new Rect(x, y, itemWidth, height);
157
+ let layoutInfo = new LayoutInfo(node.type, key, rect);
158
+ layoutInfo.estimatedSize = estimatedSize;
159
+ layoutInfo.allowOverflow = true;
160
+ layoutInfo.content = content;
161
+ newLayoutInfos.set(key, layoutInfo);
162
+ rowLayoutInfos.push(layoutInfo);
163
+
164
+ maxHeight = Math.max(maxHeight, layoutInfo.rect.height);
109
165
  }
110
- }
111
- persistedIndices.sort((a, b) => a - b);
112
-
113
- let persistedBefore: LayoutInfo[] = [];
114
- for (let index of persistedIndices) {
115
- if (index < firstVisibleItem) {
116
- persistedBefore.push(this.layoutInfos[index]);
117
- } else if (index > lastVisibleItem) {
118
- result.push(this.layoutInfos[index]);
166
+
167
+ for (let layoutInfo of rowLayoutInfos) {
168
+ layoutInfo.rect.height = maxHeight;
169
+ }
170
+
171
+ y += maxHeight + minSpace.height;
172
+
173
+ // Keep adding skeleton rows until we fill the viewport
174
+ if (skeleton && row === rows - 1 && y < this.virtualizer!.visibleRect.height) {
175
+ rows++;
119
176
  }
120
177
  }
121
- result.unshift(...persistedBefore);
122
- return result;
178
+
179
+ this.layoutInfos = newLayoutInfos;
180
+ this.contentSize = new Size(this.virtualizer!.visibleRect.width, y);
123
181
  }
124
182
 
125
- protected getIndexAtPoint(x: number, y: number) {
126
- let itemHeight = this.itemSize.height + this.minSpace.height;
127
- let itemWidth = this.itemSize.width + this.horizontalSpacing;
128
- return Math.max(0,
129
- Math.min(
130
- this.virtualizer!.collection.size - 1,
131
- Math.floor(y / itemHeight) * this.numColumns + Math.floor((x - this.horizontalSpacing) / itemWidth)
132
- )
133
- );
183
+ getLayoutInfo(key: Key): LayoutInfo {
184
+ return this.layoutInfos.get(key)!;
134
185
  }
135
186
 
136
- getLayoutInfo(key: Key): LayoutInfo | null {
137
- let node = this.virtualizer!.collection.getItem(key);
138
- return node ? this.layoutInfos[node.index] : null;
187
+ getContentSize(): Size {
188
+ return this.contentSize;
139
189
  }
140
190
 
141
- protected getLayoutInfoForNode(node: Node<T>): LayoutInfo {
142
- let idx = node.index;
143
- let row = Math.floor(idx / this.numColumns);
144
- let column = idx % this.numColumns;
145
- let x = this.horizontalSpacing + column * (this.itemSize.width + this.horizontalSpacing);
146
- let y = this.minSpace.height + row * (this.itemSize.height + this.minSpace.height);
147
- let rect = new Rect(x, y, this.itemSize.width, this.itemSize.height);
148
- return new LayoutInfo(node.type, node.key, rect);
191
+ getVisibleLayoutInfos(rect: Rect): LayoutInfo[] {
192
+ let layoutInfos: LayoutInfo[] = [];
193
+ for (let layoutInfo of this.layoutInfos.values()) {
194
+ if (layoutInfo.rect.intersects(rect) || this.virtualizer!.isPersistedKey(layoutInfo.key)) {
195
+ layoutInfos.push(layoutInfo);
196
+ }
197
+ }
198
+ return layoutInfos;
149
199
  }
150
200
 
151
- getContentSize(): Size {
152
- let numRows = Math.ceil(this.virtualizer!.collection.size / this.numColumns);
153
- let contentHeight = this.minSpace.height + numRows * (this.itemSize.height + this.minSpace.height);
154
- return new Size(this.virtualizer!.visibleRect.width, contentHeight);
201
+ updateItemSize(key: Key, size: Size) {
202
+ let layoutInfo = this.layoutInfos.get(key);
203
+ if (!size || !layoutInfo) {
204
+ return false;
205
+ }
206
+
207
+ if (size.height !== layoutInfo.rect.height) {
208
+ let newLayoutInfo = layoutInfo.copy();
209
+ newLayoutInfo.rect.height = size.height;
210
+ newLayoutInfo.estimatedSize = false;
211
+ this.layoutInfos.set(key, newLayoutInfo);
212
+ return true;
213
+ }
214
+
215
+ return false;
155
216
  }
156
217
 
157
218
  getDropTargetFromPoint(x: number, y: number, isValidDropTarget: (target: DropTarget) => boolean): DropTarget {
158
- if (this.layoutInfos.length === 0) {
219
+ if (this.layoutInfos.size === 0) {
159
220
  return {type: 'root'};
160
221
  }
161
222
 
162
223
  x += this.virtualizer!.visibleRect.x;
163
224
  y += this.virtualizer!.visibleRect.y;
164
- let index = this.getIndexAtPoint(x, y);
165
225
 
166
- let layoutInfo = this.layoutInfos[index];
226
+ let key = this.virtualizer!.keyAtPoint(new Point(x, y));
227
+ let layoutInfo = key != null ? this.getLayoutInfo(key) : null;
228
+ if (!layoutInfo) {
229
+ return {type: 'root'};
230
+ }
231
+
167
232
  let target: DropTarget = {
168
233
  type: 'item',
169
234
  key: layoutInfo.key,
@@ -202,16 +267,16 @@ export class GridLayout<T, O = any> extends Layout<Node<T>, O> implements DropTa
202
267
  rect = new Rect(
203
268
  layoutInfo.rect.x,
204
269
  target.dropPosition === 'before'
205
- ? layoutInfo.rect.y - this.minSpace.height / 2 - this.dropIndicatorThickness / 2
206
- : layoutInfo.rect.maxY + this.minSpace.height / 2 - this.dropIndicatorThickness / 2,
270
+ ? layoutInfo.rect.y - this.gap.height / 2 - this.dropIndicatorThickness / 2
271
+ : layoutInfo.rect.maxY + this.gap.height / 2 - this.dropIndicatorThickness / 2,
207
272
  layoutInfo.rect.width,
208
273
  this.dropIndicatorThickness
209
274
  );
210
275
  } else {
211
276
  rect = new Rect(
212
277
  target.dropPosition === 'before'
213
- ? layoutInfo.rect.x - this.horizontalSpacing / 2 - this.dropIndicatorThickness / 2
214
- : layoutInfo.rect.maxX + this.horizontalSpacing / 2 - this.dropIndicatorThickness / 2,
278
+ ? layoutInfo.rect.x - this.gap.width / 2 - this.dropIndicatorThickness / 2
279
+ : layoutInfo.rect.maxX + this.gap.width / 2 - this.dropIndicatorThickness / 2,
215
280
  layoutInfo.rect.y,
216
281
  this.dropIndicatorThickness,
217
282
  layoutInfo.rect.height