@react-stately/layout 3.13.10-nightly.4674 → 3.13.10-nightly.4683
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/ListLayout.main.js +33 -108
- package/dist/ListLayout.main.js.map +1 -1
- package/dist/ListLayout.mjs +33 -108
- package/dist/ListLayout.module.js +33 -108
- package/dist/ListLayout.module.js.map +1 -1
- package/dist/TableLayout.main.js +63 -99
- package/dist/TableLayout.main.js.map +1 -1
- package/dist/TableLayout.mjs +63 -99
- package/dist/TableLayout.module.js +63 -99
- package/dist/TableLayout.module.js.map +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +30 -70
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/ListLayout.ts +59 -166
- package/src/TableLayout.ts +86 -130
- package/src/index.ts +2 -1
package/src/ListLayout.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {Collection, DropTarget, DropTargetDelegate, Key,
|
|
13
|
+
import {Collection, DropTarget, DropTargetDelegate, Key, Node} from '@react-types/shared';
|
|
14
14
|
import {getChildNodes} from '@react-stately/collections';
|
|
15
15
|
import {InvalidationContext, Layout, LayoutInfo, Point, Rect, Size} from '@react-stately/virtualizer';
|
|
16
16
|
|
|
@@ -22,11 +22,10 @@ export type ListLayoutOptions<T> = {
|
|
|
22
22
|
estimatedHeadingHeight?: number,
|
|
23
23
|
padding?: number,
|
|
24
24
|
indentationForItem?: (collection: Collection<Node<T>>, key: Key) => number,
|
|
25
|
-
collator?: Intl.Collator,
|
|
26
25
|
loaderHeight?: number,
|
|
27
26
|
placeholderHeight?: number,
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
forceSectionHeaders?: boolean,
|
|
28
|
+
enableEmptyState?: boolean
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
// A wrapper around LayoutInfo that supports hierarchy
|
|
@@ -39,23 +38,23 @@ export interface LayoutNode {
|
|
|
39
38
|
index?: number
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
interface ListLayoutProps {
|
|
41
|
+
export interface ListLayoutProps {
|
|
43
42
|
isLoading?: boolean
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
const DEFAULT_HEIGHT = 48;
|
|
47
46
|
|
|
48
47
|
/**
|
|
49
|
-
* The ListLayout class is an implementation of a
|
|
48
|
+
* The ListLayout class is an implementation of a virtualizer {@link Layout}
|
|
50
49
|
* it is used for creating lists and lists with indented sub-lists.
|
|
51
50
|
*
|
|
52
51
|
* To configure a ListLayout, you can use the properties to define the
|
|
53
52
|
* layouts and/or use the method for defining indentation.
|
|
54
|
-
* The {@link ListKeyboardDelegate} extends the existing
|
|
53
|
+
* The {@link ListKeyboardDelegate} extends the existing virtualizer
|
|
55
54
|
* delegate with an additional method to do this (it uses the same delegate object as
|
|
56
|
-
* the
|
|
55
|
+
* the virtualizer itself).
|
|
57
56
|
*/
|
|
58
|
-
export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements
|
|
57
|
+
export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements DropTargetDelegate {
|
|
59
58
|
protected rowHeight: number;
|
|
60
59
|
protected estimatedRowHeight: number;
|
|
61
60
|
protected headingHeight: number;
|
|
@@ -66,19 +65,19 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
66
65
|
protected layoutInfos: Map<Key, LayoutInfo>;
|
|
67
66
|
protected layoutNodes: Map<Key, LayoutNode>;
|
|
68
67
|
protected contentSize: Size;
|
|
69
|
-
collection: Collection<Node<T>>;
|
|
70
|
-
|
|
71
|
-
allowDisabledKeyFocus: boolean = false;
|
|
72
|
-
isLoading: boolean;
|
|
68
|
+
protected collection: Collection<Node<T>>;
|
|
69
|
+
protected isLoading: boolean;
|
|
73
70
|
protected lastWidth: number;
|
|
74
71
|
protected lastCollection: Collection<Node<T>>;
|
|
75
72
|
protected rootNodes: LayoutNode[];
|
|
76
|
-
protected collator: Intl.Collator;
|
|
77
73
|
protected invalidateEverything: boolean;
|
|
78
74
|
protected loaderHeight: number;
|
|
79
75
|
protected placeholderHeight: number;
|
|
80
|
-
protected
|
|
76
|
+
protected enableEmptyState: boolean;
|
|
77
|
+
/** The rectangle containing currently valid layout infos. */
|
|
81
78
|
protected validRect: Rect;
|
|
79
|
+
/** The rectangle of requested layout infos so far. */
|
|
80
|
+
protected requestedRect: Rect;
|
|
82
81
|
|
|
83
82
|
/**
|
|
84
83
|
* Creates a new ListLayout with options. See the list of properties below for a description
|
|
@@ -93,17 +92,16 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
93
92
|
this.forceSectionHeaders = options.forceSectionHeaders;
|
|
94
93
|
this.padding = options.padding || 0;
|
|
95
94
|
this.indentationForItem = options.indentationForItem;
|
|
96
|
-
this.collator = options.collator;
|
|
97
95
|
this.loaderHeight = options.loaderHeight;
|
|
98
96
|
this.placeholderHeight = options.placeholderHeight;
|
|
97
|
+
this.enableEmptyState = options.enableEmptyState || false;
|
|
99
98
|
this.layoutInfos = new Map();
|
|
100
99
|
this.layoutNodes = new Map();
|
|
101
100
|
this.rootNodes = [];
|
|
102
101
|
this.lastWidth = 0;
|
|
103
102
|
this.lastCollection = null;
|
|
104
|
-
this.allowDisabledKeyFocus = options.allowDisabledKeyFocus;
|
|
105
|
-
this.lastValidRect = new Rect();
|
|
106
103
|
this.validRect = new Rect();
|
|
104
|
+
this.requestedRect = new Rect();
|
|
107
105
|
this.contentSize = new Size();
|
|
108
106
|
}
|
|
109
107
|
|
|
@@ -146,14 +144,13 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
146
144
|
return res;
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
layoutIfNeeded(rect: Rect) {
|
|
147
|
+
protected layoutIfNeeded(rect: Rect) {
|
|
150
148
|
if (!this.lastCollection) {
|
|
151
149
|
return;
|
|
152
150
|
}
|
|
153
151
|
|
|
154
|
-
if (!this.
|
|
155
|
-
this.
|
|
156
|
-
this.validRect = this.validRect.union(rect);
|
|
152
|
+
if (!this.requestedRect.containsRect(rect)) {
|
|
153
|
+
this.requestedRect = this.requestedRect.union(rect);
|
|
157
154
|
this.rootNodes = this.buildCollection();
|
|
158
155
|
} else {
|
|
159
156
|
// Ensure all of the persisted keys are available.
|
|
@@ -165,22 +162,21 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
165
162
|
}
|
|
166
163
|
}
|
|
167
164
|
|
|
168
|
-
ensureLayoutInfo(key: Key) {
|
|
165
|
+
private ensureLayoutInfo(key: Key) {
|
|
169
166
|
// If the layout info wasn't found, it might be outside the bounds of the area that we've
|
|
170
167
|
// computed layout for so far. This can happen when accessing a random key, e.g pressing Home/End.
|
|
171
168
|
// Compute the full layout and try again.
|
|
172
|
-
if (!this.layoutInfos.has(key) && this.
|
|
173
|
-
this.
|
|
174
|
-
this.validRect = new Rect(0, 0, Infinity, Infinity);
|
|
169
|
+
if (!this.layoutInfos.has(key) && this.requestedRect.area < this.contentSize.area && this.lastCollection) {
|
|
170
|
+
this.requestedRect = new Rect(0, 0, Infinity, Infinity);
|
|
175
171
|
this.rootNodes = this.buildCollection();
|
|
176
|
-
this.
|
|
172
|
+
this.requestedRect = new Rect(0, 0, this.contentSize.width, this.contentSize.height);
|
|
177
173
|
return true;
|
|
178
174
|
}
|
|
179
175
|
|
|
180
176
|
return false;
|
|
181
177
|
}
|
|
182
178
|
|
|
183
|
-
isVisible(node: LayoutNode, rect: Rect) {
|
|
179
|
+
private isVisible(node: LayoutNode, rect: Rect) {
|
|
184
180
|
return node.layoutInfo.rect.intersects(rect) || node.layoutInfo.isSticky || this.virtualizer.isPersistedKey(node.layoutInfo.key);
|
|
185
181
|
}
|
|
186
182
|
|
|
@@ -198,8 +194,7 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
198
194
|
// Otherwise we can reuse cached layout infos outside the current visible rect.
|
|
199
195
|
this.invalidateEverything = this.shouldInvalidateEverything(invalidationContext);
|
|
200
196
|
if (this.invalidateEverything) {
|
|
201
|
-
this.
|
|
202
|
-
this.validRect = this.virtualizer.visibleRect.copy();
|
|
197
|
+
this.requestedRect = this.virtualizer.visibleRect.copy();
|
|
203
198
|
}
|
|
204
199
|
|
|
205
200
|
this.rootNodes = this.buildCollection();
|
|
@@ -221,9 +216,10 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
221
216
|
this.lastWidth = this.virtualizer.visibleRect.width;
|
|
222
217
|
this.lastCollection = this.collection;
|
|
223
218
|
this.invalidateEverything = false;
|
|
219
|
+
this.validRect = this.requestedRect.copy();
|
|
224
220
|
}
|
|
225
221
|
|
|
226
|
-
buildCollection(): LayoutNode[] {
|
|
222
|
+
protected buildCollection(): LayoutNode[] {
|
|
227
223
|
let y = this.padding;
|
|
228
224
|
let skipped = 0;
|
|
229
225
|
let nodes = [];
|
|
@@ -231,17 +227,17 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
231
227
|
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight);
|
|
232
228
|
|
|
233
229
|
// Skip rows before the valid rectangle unless they are already cached.
|
|
234
|
-
if (node.type === 'item' && y + rowHeight < this.
|
|
230
|
+
if (node.type === 'item' && y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
|
|
235
231
|
y += rowHeight;
|
|
236
232
|
skipped++;
|
|
237
233
|
continue;
|
|
238
234
|
}
|
|
239
235
|
|
|
240
|
-
let layoutNode = this.buildChild(node, 0, y);
|
|
236
|
+
let layoutNode = this.buildChild(node, 0, y, null);
|
|
241
237
|
y = layoutNode.layoutInfo.rect.maxY;
|
|
242
238
|
nodes.push(layoutNode);
|
|
243
239
|
|
|
244
|
-
if (node.type === 'item' && y > this.
|
|
240
|
+
if (node.type === 'item' && y > this.requestedRect.maxY) {
|
|
245
241
|
y += (this.collection.size - (nodes.length + skipped)) * rowHeight;
|
|
246
242
|
break;
|
|
247
243
|
}
|
|
@@ -256,7 +252,7 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
256
252
|
y = loader.rect.maxY;
|
|
257
253
|
}
|
|
258
254
|
|
|
259
|
-
if (nodes.length === 0) {
|
|
255
|
+
if (nodes.length === 0 && this.enableEmptyState) {
|
|
260
256
|
let rect = new Rect(0, y, this.virtualizer.visibleRect.width,
|
|
261
257
|
this.placeholderHeight ?? this.virtualizer.visibleRect.height);
|
|
262
258
|
let placeholder = new LayoutInfo('placeholder', 'placeholder', rect);
|
|
@@ -269,19 +265,19 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
269
265
|
return nodes;
|
|
270
266
|
}
|
|
271
267
|
|
|
272
|
-
isValid(node: Node<T>, y: number) {
|
|
268
|
+
protected isValid(node: Node<T>, y: number) {
|
|
273
269
|
let cached = this.layoutNodes.get(node.key);
|
|
274
270
|
return (
|
|
275
271
|
!this.invalidateEverything &&
|
|
276
272
|
cached &&
|
|
277
273
|
cached.node === node &&
|
|
278
274
|
y === (cached.header || cached.layoutInfo).rect.y &&
|
|
279
|
-
cached.layoutInfo.rect.intersects(this.
|
|
280
|
-
cached.validRect.containsRect(cached.layoutInfo.rect.intersection(this.
|
|
275
|
+
cached.layoutInfo.rect.intersects(this.validRect) &&
|
|
276
|
+
cached.validRect.containsRect(cached.layoutInfo.rect.intersection(this.requestedRect))
|
|
281
277
|
);
|
|
282
278
|
}
|
|
283
279
|
|
|
284
|
-
buildChild(node: Node<T>, x: number, y: number): LayoutNode {
|
|
280
|
+
protected buildChild(node: Node<T>, x: number, y: number, parentKey: Key | null): LayoutNode {
|
|
285
281
|
if (this.isValid(node, y)) {
|
|
286
282
|
return this.layoutNodes.get(node.key);
|
|
287
283
|
}
|
|
@@ -289,7 +285,7 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
289
285
|
let layoutNode = this.buildNode(node, x, y);
|
|
290
286
|
layoutNode.node = node;
|
|
291
287
|
|
|
292
|
-
layoutNode.layoutInfo.parentKey =
|
|
288
|
+
layoutNode.layoutInfo.parentKey = parentKey ?? null;
|
|
293
289
|
this.layoutInfos.set(layoutNode.layoutInfo.key, layoutNode.layoutInfo);
|
|
294
290
|
if (layoutNode.header) {
|
|
295
291
|
this.layoutInfos.set(layoutNode.header.key, layoutNode.header);
|
|
@@ -299,22 +295,22 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
299
295
|
return layoutNode;
|
|
300
296
|
}
|
|
301
297
|
|
|
302
|
-
buildNode(node: Node<T>, x: number, y: number): LayoutNode {
|
|
298
|
+
protected buildNode(node: Node<T>, x: number, y: number): LayoutNode {
|
|
303
299
|
switch (node.type) {
|
|
304
300
|
case 'section':
|
|
305
301
|
return this.buildSection(node, x, y);
|
|
306
302
|
case 'item':
|
|
307
303
|
return this.buildItem(node, x, y);
|
|
308
304
|
case 'header':
|
|
309
|
-
return this.
|
|
305
|
+
return this.buildSectionHeader(node, x, y);
|
|
310
306
|
}
|
|
311
307
|
}
|
|
312
308
|
|
|
313
|
-
buildSection(node: Node<T>, x: number, y: number): LayoutNode {
|
|
309
|
+
private buildSection(node: Node<T>, x: number, y: number): LayoutNode {
|
|
314
310
|
let width = this.virtualizer.visibleRect.width;
|
|
315
311
|
let header = null;
|
|
316
312
|
if (node.rendered || this.forceSectionHeaders) {
|
|
317
|
-
let headerNode = this.
|
|
313
|
+
let headerNode = this.buildSectionHeader(node, x, y);
|
|
318
314
|
header = headerNode.layoutInfo;
|
|
319
315
|
header.key += ':header';
|
|
320
316
|
header.parentKey = node.key;
|
|
@@ -331,17 +327,17 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
331
327
|
let rowHeight = (this.rowHeight ?? this.estimatedRowHeight);
|
|
332
328
|
|
|
333
329
|
// Skip rows before the valid rectangle unless they are already cached.
|
|
334
|
-
if (y + rowHeight < this.
|
|
330
|
+
if (y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
|
|
335
331
|
y += rowHeight;
|
|
336
332
|
skipped++;
|
|
337
333
|
continue;
|
|
338
334
|
}
|
|
339
335
|
|
|
340
|
-
let layoutNode = this.buildChild(child, x, y);
|
|
336
|
+
let layoutNode = this.buildChild(child, x, y, layoutInfo.key);
|
|
341
337
|
y = layoutNode.layoutInfo.rect.maxY;
|
|
342
338
|
children.push(layoutNode);
|
|
343
339
|
|
|
344
|
-
if (y > this.
|
|
340
|
+
if (y > this.requestedRect.maxY) {
|
|
345
341
|
// Estimate the remaining height for rows that we don't need to layout right now.
|
|
346
342
|
y += ([...getChildNodes(node, this.collection)].length - (children.length + skipped)) * rowHeight;
|
|
347
343
|
break;
|
|
@@ -354,11 +350,11 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
354
350
|
header,
|
|
355
351
|
layoutInfo,
|
|
356
352
|
children,
|
|
357
|
-
validRect: layoutInfo.rect.intersection(this.
|
|
353
|
+
validRect: layoutInfo.rect.intersection(this.requestedRect)
|
|
358
354
|
};
|
|
359
355
|
}
|
|
360
356
|
|
|
361
|
-
|
|
357
|
+
private buildSectionHeader(node: Node<T>, x: number, y: number): LayoutNode {
|
|
362
358
|
let width = this.virtualizer.visibleRect.width;
|
|
363
359
|
let rectHeight = this.headingHeight;
|
|
364
360
|
let isEstimated = false;
|
|
@@ -366,7 +362,7 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
366
362
|
// If no explicit height is available, use an estimated height.
|
|
367
363
|
if (rectHeight == null) {
|
|
368
364
|
// If a previous version of this layout info exists, reuse its height.
|
|
369
|
-
// Mark as estimated if the size of the overall
|
|
365
|
+
// Mark as estimated if the size of the overall virtualizer changed,
|
|
370
366
|
// or the content of the item changed.
|
|
371
367
|
let previousLayoutNode = this.layoutNodes.get(node.key);
|
|
372
368
|
let previousLayoutInfo = previousLayoutNode?.header || previousLayoutNode?.layoutInfo;
|
|
@@ -391,11 +387,11 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
391
387
|
return {
|
|
392
388
|
layoutInfo: header,
|
|
393
389
|
children: [],
|
|
394
|
-
validRect: header.rect.intersection(this.
|
|
390
|
+
validRect: header.rect.intersection(this.requestedRect)
|
|
395
391
|
};
|
|
396
392
|
}
|
|
397
393
|
|
|
398
|
-
buildItem(node: Node<T>, x: number, y: number): LayoutNode {
|
|
394
|
+
private buildItem(node: Node<T>, x: number, y: number): LayoutNode {
|
|
399
395
|
let width = this.virtualizer.visibleRect.width;
|
|
400
396
|
let rectHeight = this.rowHeight;
|
|
401
397
|
let isEstimated = false;
|
|
@@ -403,7 +399,7 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
403
399
|
// If no explicit height is available, use an estimated height.
|
|
404
400
|
if (rectHeight == null) {
|
|
405
401
|
// If a previous version of this layout info exists, reuse its height.
|
|
406
|
-
// Mark as estimated if the size of the overall
|
|
402
|
+
// Mark as estimated if the size of the overall virtualizer changed,
|
|
407
403
|
// or the content of the item changed.
|
|
408
404
|
let previousLayoutNode = this.layoutNodes.get(node.key);
|
|
409
405
|
if (previousLayoutNode) {
|
|
@@ -448,6 +444,13 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
448
444
|
newLayoutInfo.rect.height = size.height;
|
|
449
445
|
this.layoutInfos.set(key, newLayoutInfo);
|
|
450
446
|
|
|
447
|
+
// Items after this layoutInfo will need to be repositioned to account for the new height.
|
|
448
|
+
// Adjust the validRect so that only items above remain valid.
|
|
449
|
+
this.validRect.height = Math.min(this.validRect.height, layoutInfo.rect.y - this.validRect.y);
|
|
450
|
+
|
|
451
|
+
// The requestedRect also needs to be adjusted to account for the height difference.
|
|
452
|
+
this.requestedRect.height += newLayoutInfo.rect.height - layoutInfo.rect.height;
|
|
453
|
+
|
|
451
454
|
// Invalidate layout for this layout node and all parents
|
|
452
455
|
this.updateLayoutNode(key, layoutInfo, newLayoutInfo);
|
|
453
456
|
|
|
@@ -463,11 +466,11 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
463
466
|
return false;
|
|
464
467
|
}
|
|
465
468
|
|
|
466
|
-
updateLayoutNode(key: Key, oldLayoutInfo: LayoutInfo, newLayoutInfo: LayoutInfo) {
|
|
469
|
+
private updateLayoutNode(key: Key, oldLayoutInfo: LayoutInfo, newLayoutInfo: LayoutInfo) {
|
|
467
470
|
let n = this.layoutNodes.get(key);
|
|
468
471
|
if (n) {
|
|
469
|
-
// Invalidate by
|
|
470
|
-
n.validRect =
|
|
472
|
+
// Invalidate by intersecting the validRect of this node with the overall validRect.
|
|
473
|
+
n.validRect = n.validRect.intersection(this.validRect);
|
|
471
474
|
|
|
472
475
|
// Replace layout info in LayoutNode
|
|
473
476
|
if (n.header === oldLayoutInfo) {
|
|
@@ -482,116 +485,6 @@ export class ListLayout<T> extends Layout<Node<T>, ListLayoutProps> implements K
|
|
|
482
485
|
return this.contentSize;
|
|
483
486
|
}
|
|
484
487
|
|
|
485
|
-
getKeyAbove(key: Key): Key | null {
|
|
486
|
-
let collection = this.collection;
|
|
487
|
-
|
|
488
|
-
key = collection.getKeyBefore(key);
|
|
489
|
-
while (key != null) {
|
|
490
|
-
let item = collection.getItem(key);
|
|
491
|
-
if (item.type === 'item' && (this.allowDisabledKeyFocus || !this.disabledKeys.has(item.key))) {
|
|
492
|
-
return key;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
key = collection.getKeyBefore(key);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
getKeyBelow(key: Key): Key | null {
|
|
500
|
-
let collection = this.collection;
|
|
501
|
-
|
|
502
|
-
key = collection.getKeyAfter(key);
|
|
503
|
-
while (key != null) {
|
|
504
|
-
let item = collection.getItem(key);
|
|
505
|
-
if (item.type === 'item' && (this.allowDisabledKeyFocus || !this.disabledKeys.has(item.key))) {
|
|
506
|
-
return key;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
key = collection.getKeyAfter(key);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
getKeyPageAbove(key: Key): Key | null {
|
|
514
|
-
let layoutInfo = this.getLayoutInfo(key);
|
|
515
|
-
|
|
516
|
-
if (layoutInfo) {
|
|
517
|
-
let pageY = Math.max(0, layoutInfo.rect.y + layoutInfo.rect.height - this.virtualizer.visibleRect.height);
|
|
518
|
-
while (layoutInfo && layoutInfo.rect.y > pageY) {
|
|
519
|
-
let keyAbove = this.getKeyAbove(layoutInfo.key);
|
|
520
|
-
layoutInfo = this.getLayoutInfo(keyAbove);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
if (layoutInfo) {
|
|
524
|
-
return layoutInfo.key;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
return this.getFirstKey();
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
getKeyPageBelow(key: Key): Key | null {
|
|
532
|
-
let layoutInfo = this.getLayoutInfo(key != null ? key : this.getFirstKey());
|
|
533
|
-
|
|
534
|
-
if (layoutInfo) {
|
|
535
|
-
let pageY = Math.min(this.virtualizer.contentSize.height, layoutInfo.rect.y - layoutInfo.rect.height + this.virtualizer.visibleRect.height);
|
|
536
|
-
while (layoutInfo && layoutInfo.rect.y < pageY) {
|
|
537
|
-
let keyBelow = this.getKeyBelow(layoutInfo.key);
|
|
538
|
-
layoutInfo = this.getLayoutInfo(keyBelow);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
if (layoutInfo) {
|
|
542
|
-
return layoutInfo.key;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
return this.getLastKey();
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
getFirstKey(): Key | null {
|
|
550
|
-
let collection = this.collection;
|
|
551
|
-
let key = collection.getFirstKey();
|
|
552
|
-
while (key != null) {
|
|
553
|
-
let item = collection.getItem(key);
|
|
554
|
-
if (item.type === 'item' && (this.allowDisabledKeyFocus || !this.disabledKeys.has(item.key))) {
|
|
555
|
-
return key;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
key = collection.getKeyAfter(key);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
getLastKey(): Key | null {
|
|
563
|
-
let collection = this.collection;
|
|
564
|
-
let key = collection.getLastKey();
|
|
565
|
-
while (key != null) {
|
|
566
|
-
let item = collection.getItem(key);
|
|
567
|
-
if (item.type === 'item' && (this.allowDisabledKeyFocus || !this.disabledKeys.has(item.key))) {
|
|
568
|
-
return key;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
key = collection.getKeyBefore(key);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
getKeyForSearch(search: string, fromKey?: Key): Key | null {
|
|
576
|
-
if (!this.collator) {
|
|
577
|
-
return null;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
let collection = this.collection;
|
|
581
|
-
let key = fromKey || this.getFirstKey();
|
|
582
|
-
while (key != null) {
|
|
583
|
-
let item = collection.getItem(key);
|
|
584
|
-
let substring = item.textValue.slice(0, search.length);
|
|
585
|
-
if (item.textValue && this.collator.compare(substring, search) === 0) {
|
|
586
|
-
return key;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
key = this.getKeyBelow(key);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
return null;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
488
|
getDropTargetFromPoint(x: number, y: number, isValidDropTarget: (target: DropTarget) => boolean): DropTarget {
|
|
596
489
|
x += this.virtualizer.visibleRect.x;
|
|
597
490
|
y += this.virtualizer.visibleRect.y;
|