@react-stately/layout 3.0.0-nightly-641446f65-240905

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.
@@ -0,0 +1,572 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {DropTarget, ItemDropTarget, Key} from '@react-types/shared';
14
+ import {getChildNodes} from '@react-stately/collections';
15
+ import {GridNode} from '@react-types/grid';
16
+ import {InvalidationContext, LayoutInfo, Point, Rect, Size} from '@react-stately/virtualizer';
17
+ import {LayoutNode, ListLayout, ListLayoutOptions} from './ListLayout';
18
+ import {TableCollection} from '@react-types/table';
19
+ import {TableColumnLayout} from '@react-stately/table';
20
+
21
+ export interface TableLayoutProps {
22
+ columnWidths?: Map<Key, number>
23
+ }
24
+
25
+ export class TableLayout<T, O extends TableLayoutProps = TableLayoutProps> extends ListLayout<T, O> {
26
+ protected collection: TableCollection<T>;
27
+ private columnWidths: Map<Key, number>;
28
+ private stickyColumnIndices: number[];
29
+ private lastPersistedKeys: Set<Key> = null;
30
+ private persistedIndices: Map<Key, number[]> = new Map();
31
+
32
+ constructor(options: ListLayoutOptions) {
33
+ super(options);
34
+ this.stickyColumnIndices = [];
35
+ }
36
+
37
+ private columnsChanged(newCollection: TableCollection<T>, oldCollection: TableCollection<T> | null) {
38
+ return !oldCollection ||
39
+ newCollection.columns !== oldCollection.columns &&
40
+ newCollection.columns.length !== oldCollection.columns.length ||
41
+ newCollection.columns.some((c, i) =>
42
+ c.key !== oldCollection.columns[i].key ||
43
+ c.props.width !== oldCollection.columns[i].props.width ||
44
+ c.props.minWidth !== oldCollection.columns[i].props.minWidth ||
45
+ c.props.maxWidth !== oldCollection.columns[i].props.maxWidth
46
+ );
47
+ }
48
+
49
+ update(invalidationContext: InvalidationContext<O>): void {
50
+ let newCollection = this.virtualizer.collection as TableCollection<T>;
51
+
52
+ // If columnWidths were provided via layoutOptions, update those.
53
+ // Otherwise, calculate column widths ourselves.
54
+ if (invalidationContext.layoutOptions?.columnWidths) {
55
+ if (invalidationContext.layoutOptions.columnWidths !== this.columnWidths) {
56
+ this.columnWidths = invalidationContext.layoutOptions.columnWidths;
57
+ invalidationContext.sizeChanged = true;
58
+ }
59
+ } else if (invalidationContext.sizeChanged || this.columnsChanged(newCollection, this.collection)) {
60
+ let columnLayout = new TableColumnLayout({});
61
+ this.columnWidths = columnLayout.buildColumnWidths(this.virtualizer.visibleRect.width, newCollection, new Map());
62
+ invalidationContext.sizeChanged = true;
63
+ }
64
+
65
+ super.update(invalidationContext);
66
+ }
67
+
68
+ protected buildCollection(): LayoutNode[] {
69
+ this.stickyColumnIndices = [];
70
+
71
+ for (let column of this.collection.columns) {
72
+ // The selection cell and any other sticky columns always need to be visible.
73
+ // In addition, row headers need to be in the DOM for accessibility labeling.
74
+ if (this.isStickyColumn(column) || this.collection.rowHeaderColumnKeys.has(column.key)) {
75
+ this.stickyColumnIndices.push(column.index);
76
+ }
77
+ }
78
+
79
+ let header = this.buildTableHeader();
80
+ this.layoutNodes.set(header.layoutInfo.key, header);
81
+ let body = this.buildBody(header.layoutInfo.rect.height);
82
+ this.lastPersistedKeys = null;
83
+
84
+ body.layoutInfo.rect.width = Math.max(header.layoutInfo.rect.width, body.layoutInfo.rect.width);
85
+ this.contentSize = new Size(body.layoutInfo.rect.width, body.layoutInfo.rect.maxY);
86
+ return [
87
+ header,
88
+ body
89
+ ];
90
+ }
91
+
92
+ protected buildTableHeader(): LayoutNode {
93
+ let rect = new Rect(0, 0, 0, 0);
94
+ let layoutInfo = new LayoutInfo('header', this.collection.head?.key ?? 'header', rect);
95
+ layoutInfo.isSticky = true;
96
+ layoutInfo.zIndex = 1;
97
+
98
+ let y = 0;
99
+ let width = 0;
100
+ let children: LayoutNode[] = [];
101
+ for (let headerRow of this.collection.headerRows) {
102
+ let layoutNode = this.buildChild(headerRow, 0, y, layoutInfo.key);
103
+ layoutNode.layoutInfo.parentKey = layoutInfo.key;
104
+ y = layoutNode.layoutInfo.rect.maxY;
105
+ width = Math.max(width, layoutNode.layoutInfo.rect.width);
106
+ layoutNode.index = children.length;
107
+ children.push(layoutNode);
108
+ }
109
+
110
+ rect.width = width;
111
+ rect.height = y;
112
+
113
+ return {
114
+ layoutInfo,
115
+ children,
116
+ validRect: layoutInfo.rect,
117
+ node: this.collection.head
118
+ };
119
+ }
120
+
121
+ protected buildHeaderRow(headerRow: GridNode<T>, x: number, y: number): LayoutNode {
122
+ let rect = new Rect(0, y, 0, 0);
123
+ let row = new LayoutInfo('headerrow', headerRow.key, rect);
124
+
125
+ let height = 0;
126
+ let columns: LayoutNode[] = [];
127
+ for (let cell of getChildNodes(headerRow, this.collection)) {
128
+ let layoutNode = this.buildChild(cell, x, y, row.key);
129
+ layoutNode.layoutInfo.parentKey = row.key;
130
+ x = layoutNode.layoutInfo.rect.maxX;
131
+ height = Math.max(height, layoutNode.layoutInfo.rect.height);
132
+ layoutNode.index = columns.length;
133
+ columns.push(layoutNode);
134
+ }
135
+ for (let [i, layout] of columns.entries()) {
136
+ layout.layoutInfo.zIndex = columns.length - i + 1;
137
+ }
138
+
139
+ this.setChildHeights(columns, height);
140
+
141
+ rect.height = height;
142
+ rect.width = x;
143
+
144
+ return {
145
+ layoutInfo: row,
146
+ children: columns,
147
+ validRect: rect,
148
+ node: headerRow
149
+ };
150
+ }
151
+
152
+ private setChildHeights(children: LayoutNode[], height: number) {
153
+ for (let child of children) {
154
+ if (child.layoutInfo.rect.height !== height) {
155
+ // Need to copy the layout info before we mutate it.
156
+ child.layoutInfo = child.layoutInfo.copy();
157
+ child.layoutInfo.rect.height = height;
158
+ }
159
+ }
160
+ }
161
+
162
+ // used to get the column widths when rendering to the DOM
163
+ private getRenderedColumnWidth(node: GridNode<T>) {
164
+ let colspan = node.colspan ?? 1;
165
+ let colIndex = node.colIndex ?? node.index;
166
+ let width = 0;
167
+ for (let i = colIndex; i < colIndex + colspan; i++) {
168
+ let column = this.collection.columns[i];
169
+ if (column?.key != null) {
170
+ width += this.columnWidths.get(column.key);
171
+ }
172
+ }
173
+
174
+ return width;
175
+ }
176
+
177
+ private getEstimatedHeight(node: GridNode<T>, width: number, height: number, estimatedHeight: number) {
178
+ let isEstimated = false;
179
+
180
+ // If no explicit height is available, use an estimated height.
181
+ if (height == null) {
182
+ // If a previous version of this layout info exists, reuse its height.
183
+ // Mark as estimated if the size of the overall collection view changed,
184
+ // or the content of the item changed.
185
+ let previousLayoutNode = this.layoutNodes.get(node.key);
186
+ if (previousLayoutNode) {
187
+ height = previousLayoutNode.layoutInfo.rect.height;
188
+ isEstimated = node !== previousLayoutNode.node || width !== previousLayoutNode.layoutInfo.rect.width || previousLayoutNode.layoutInfo.estimatedSize;
189
+ } else {
190
+ height = estimatedHeight;
191
+ isEstimated = true;
192
+ }
193
+ }
194
+
195
+ return {height, isEstimated};
196
+ }
197
+
198
+ protected getEstimatedRowHeight(): number {
199
+ return this.rowHeight ?? this.estimatedRowHeight;
200
+ }
201
+
202
+ protected buildColumn(node: GridNode<T>, x: number, y: number): LayoutNode {
203
+ let width = this.getRenderedColumnWidth(node);
204
+ let {height, isEstimated} = this.getEstimatedHeight(node, width, this.headingHeight, this.estimatedHeadingHeight);
205
+ let rect = new Rect(x, y, width, height);
206
+ let layoutInfo = new LayoutInfo(node.type, node.key, rect);
207
+ layoutInfo.isSticky = this.isStickyColumn(node);
208
+ layoutInfo.zIndex = layoutInfo.isSticky ? 2 : 1;
209
+ layoutInfo.estimatedSize = isEstimated;
210
+
211
+ return {
212
+ layoutInfo,
213
+ children: [],
214
+ validRect: layoutInfo.rect,
215
+ node
216
+ };
217
+ }
218
+
219
+ // For subclasses.
220
+ // eslint-disable-next-line
221
+ protected isStickyColumn(node: GridNode<T>) {
222
+ return false;
223
+ }
224
+
225
+ protected buildBody(y: number): LayoutNode {
226
+ let rect = new Rect(0, y, 0, 0);
227
+ let layoutInfo = new LayoutInfo('rowgroup', this.collection.body.key, rect);
228
+
229
+ let startY = y;
230
+ let skipped = 0;
231
+ let width = 0;
232
+ let children: LayoutNode[] = [];
233
+ let rowHeight = this.getEstimatedRowHeight();
234
+ for (let node of getChildNodes(this.collection.body, this.collection)) {
235
+ // Skip rows before the valid rectangle unless they are already cached.
236
+ if (y + rowHeight < this.requestedRect.y && !this.isValid(node, y)) {
237
+ y += rowHeight;
238
+ skipped++;
239
+ continue;
240
+ }
241
+
242
+ let layoutNode = this.buildChild(node, 0, y, layoutInfo.key);
243
+ layoutNode.layoutInfo.parentKey = layoutInfo.key;
244
+ layoutNode.index = children.length;
245
+ y = layoutNode.layoutInfo.rect.maxY;
246
+ width = Math.max(width, layoutNode.layoutInfo.rect.width);
247
+ children.push(layoutNode);
248
+
249
+ if (y > this.requestedRect.maxY) {
250
+ // Estimate the remaining height for rows that we don't need to layout right now.
251
+ y += (this.collection.size - (skipped + children.length)) * rowHeight;
252
+ break;
253
+ }
254
+ }
255
+
256
+ if (children.length === 0) {
257
+ y = this.virtualizer.visibleRect.maxY;
258
+ }
259
+
260
+ rect.width = width;
261
+ rect.height = y - startY;
262
+
263
+ return {
264
+ layoutInfo,
265
+ children,
266
+ validRect: layoutInfo.rect.intersection(this.requestedRect),
267
+ node: this.collection.body
268
+ };
269
+ }
270
+
271
+ protected buildNode(node: GridNode<T>, x: number, y: number): LayoutNode {
272
+ switch (node.type) {
273
+ case 'headerrow':
274
+ return this.buildHeaderRow(node, x, y);
275
+ case 'item':
276
+ return this.buildRow(node, x, y);
277
+ case 'column':
278
+ case 'placeholder':
279
+ return this.buildColumn(node, x, y);
280
+ case 'cell':
281
+ return this.buildCell(node, x, y);
282
+ case 'loader':
283
+ return this.buildLoader(node, x, y);
284
+ default:
285
+ throw new Error('Unknown node type ' + node.type);
286
+ }
287
+ }
288
+
289
+ protected buildRow(node: GridNode<T>, x: number, y: number): LayoutNode {
290
+ let rect = new Rect(x, y, 0, 0);
291
+ let layoutInfo = new LayoutInfo('row', node.key, rect);
292
+
293
+ let children: LayoutNode[] = [];
294
+ let height = 0;
295
+ for (let child of getChildNodes(node, this.collection)) {
296
+ if (child.type === 'cell') {
297
+ if (x > this.requestedRect.maxX) {
298
+ // Adjust existing cached layoutInfo to ensure that it is out of view.
299
+ // This can happen due to column resizing.
300
+ let layoutNode = this.layoutNodes.get(child.key);
301
+ if (layoutNode) {
302
+ layoutNode.layoutInfo.rect.x = x;
303
+ x += layoutNode.layoutInfo.rect.width;
304
+ } else {
305
+ break;
306
+ }
307
+ } else {
308
+ let layoutNode = this.buildChild(child, x, y, layoutInfo.key);
309
+ x = layoutNode.layoutInfo.rect.maxX;
310
+ height = Math.max(height, layoutNode.layoutInfo.rect.height);
311
+ layoutNode.index = children.length;
312
+ children.push(layoutNode);
313
+ }
314
+ }
315
+ }
316
+
317
+ this.setChildHeights(children, height);
318
+
319
+ rect.width = this.layoutNodes.get(this.collection.head?.key ?? 'header').layoutInfo.rect.width;
320
+ rect.height = height;
321
+
322
+ return {
323
+ layoutInfo,
324
+ children,
325
+ validRect: rect.intersection(this.requestedRect),
326
+ node
327
+ };
328
+ }
329
+
330
+ protected buildCell(node: GridNode<T>, x: number, y: number): LayoutNode {
331
+ let width = this.getRenderedColumnWidth(node);
332
+ let {height, isEstimated} = this.getEstimatedHeight(node, width, this.rowHeight, this.estimatedRowHeight);
333
+ let rect = new Rect(x, y, width, height);
334
+ let layoutInfo = new LayoutInfo(node.type, node.key, rect);
335
+ layoutInfo.isSticky = this.isStickyColumn(node);
336
+ layoutInfo.zIndex = layoutInfo.isSticky ? 2 : 1;
337
+ layoutInfo.estimatedSize = isEstimated;
338
+
339
+ return {
340
+ layoutInfo,
341
+ children: [],
342
+ validRect: rect,
343
+ node
344
+ };
345
+ }
346
+
347
+ getVisibleLayoutInfos(rect: Rect) {
348
+ // Adjust rect to keep number of visible rows consistent.
349
+ // (only if height > 1 for getDropTargetFromPoint)
350
+ if (rect.height > 1) {
351
+ let rowHeight = this.getEstimatedRowHeight();
352
+ rect.y = Math.floor(rect.y / rowHeight) * rowHeight;
353
+ rect.height = Math.ceil(rect.height / rowHeight) * rowHeight;
354
+ }
355
+
356
+ // If layout hasn't yet been done for the requested rect, union the
357
+ // new rect with the existing valid rect, and recompute.
358
+ this.layoutIfNeeded(rect);
359
+
360
+ let res: LayoutInfo[] = [];
361
+
362
+ this.buildPersistedIndices();
363
+ for (let node of this.rootNodes) {
364
+ res.push(node.layoutInfo);
365
+ this.addVisibleLayoutInfos(res, node, rect);
366
+ }
367
+
368
+ return res;
369
+ }
370
+
371
+ private addVisibleLayoutInfos(res: LayoutInfo[], node: LayoutNode, rect: Rect) {
372
+ if (!node.children || node.children.length === 0) {
373
+ return;
374
+ }
375
+
376
+ switch (node.layoutInfo.type) {
377
+ case 'header': {
378
+ for (let child of node.children) {
379
+ res.push(child.layoutInfo);
380
+ this.addVisibleLayoutInfos(res, child, rect);
381
+ }
382
+ break;
383
+ }
384
+ case 'rowgroup': {
385
+ let firstVisibleRow = this.binarySearch(node.children, rect.topLeft, 'y');
386
+ let lastVisibleRow = this.binarySearch(node.children, rect.bottomRight, 'y');
387
+
388
+ // Add persisted rows before the visible rows.
389
+ let persistedRowIndices = this.persistedIndices.get(node.layoutInfo.key);
390
+ let persistIndex = 0;
391
+ while (
392
+ persistedRowIndices &&
393
+ persistIndex < persistedRowIndices.length &&
394
+ persistedRowIndices[persistIndex] < firstVisibleRow
395
+ ) {
396
+ let idx = persistedRowIndices[persistIndex];
397
+ if (idx < node.children.length) {
398
+ res.push(node.children[idx].layoutInfo);
399
+ this.addVisibleLayoutInfos(res, node.children[idx], rect);
400
+ }
401
+ persistIndex++;
402
+ }
403
+
404
+ for (let i = firstVisibleRow; i <= lastVisibleRow; i++) {
405
+ // Skip persisted rows that overlap with visible cells.
406
+ while (persistedRowIndices && persistIndex < persistedRowIndices.length && persistedRowIndices[persistIndex] < i) {
407
+ persistIndex++;
408
+ }
409
+
410
+ res.push(node.children[i].layoutInfo);
411
+ this.addVisibleLayoutInfos(res, node.children[i], rect);
412
+ }
413
+
414
+ // Add persisted rows after the visible rows.
415
+ while (persistedRowIndices && persistIndex < persistedRowIndices.length) {
416
+ let idx = persistedRowIndices[persistIndex++];
417
+ if (idx < node.children.length) {
418
+ res.push(node.children[idx].layoutInfo);
419
+ this.addVisibleLayoutInfos(res, node.children[idx], rect);
420
+ }
421
+ }
422
+ break;
423
+ }
424
+ case 'headerrow':
425
+ case 'row': {
426
+ let firstVisibleCell = this.binarySearch(node.children, rect.topLeft, 'x');
427
+ let lastVisibleCell = this.binarySearch(node.children, rect.topRight, 'x');
428
+ let stickyIndex = 0;
429
+
430
+ // Add persisted/sticky cells before the visible cells.
431
+ let persistedCellIndices = this.persistedIndices.get(node.layoutInfo.key) || this.stickyColumnIndices;
432
+ while (stickyIndex < persistedCellIndices.length && persistedCellIndices[stickyIndex] < firstVisibleCell) {
433
+ let idx = persistedCellIndices[stickyIndex];
434
+ if (idx < node.children.length) {
435
+ res.push(node.children[idx].layoutInfo);
436
+ }
437
+ stickyIndex++;
438
+ }
439
+
440
+ for (let i = firstVisibleCell; i <= lastVisibleCell; i++) {
441
+ // Skip sticky cells that overlap with visible cells.
442
+ while (stickyIndex < persistedCellIndices.length && persistedCellIndices[stickyIndex] < i) {
443
+ stickyIndex++;
444
+ }
445
+
446
+ res.push(node.children[i].layoutInfo);
447
+ }
448
+
449
+ // Add any remaining sticky cells after the visible cells.
450
+ while (stickyIndex < persistedCellIndices.length) {
451
+ let idx = persistedCellIndices[stickyIndex++];
452
+ if (idx < node.children.length) {
453
+ res.push(node.children[idx].layoutInfo);
454
+ }
455
+ }
456
+ break;
457
+ }
458
+ default:
459
+ throw new Error('Unknown node type ' + node.layoutInfo.type);
460
+ }
461
+ }
462
+
463
+ private binarySearch(items: LayoutNode[], point: Point, axis: 'x' | 'y') {
464
+ let low = 0;
465
+ let high = items.length - 1;
466
+ while (low <= high) {
467
+ let mid = (low + high) >> 1;
468
+ let item = items[mid];
469
+
470
+ if ((axis === 'x' && item.layoutInfo.rect.maxX <= point.x) || (axis === 'y' && item.layoutInfo.rect.maxY <= point.y)) {
471
+ low = mid + 1;
472
+ } else if ((axis === 'x' && item.layoutInfo.rect.x > point.x) || (axis === 'y' && item.layoutInfo.rect.y > point.y)) {
473
+ high = mid - 1;
474
+ } else {
475
+ return mid;
476
+ }
477
+ }
478
+
479
+ return Math.max(0, Math.min(items.length - 1, low));
480
+ }
481
+
482
+ private buildPersistedIndices() {
483
+ if (this.virtualizer.persistedKeys === this.lastPersistedKeys) {
484
+ return;
485
+ }
486
+
487
+ this.lastPersistedKeys = this.virtualizer.persistedKeys;
488
+ this.persistedIndices.clear();
489
+
490
+ // Build a map of parentKey => indices of children to persist.
491
+ for (let key of this.virtualizer.persistedKeys) {
492
+ let layoutInfo = this.layoutNodes.get(key)?.layoutInfo;
493
+
494
+ // Walk up ancestors so parents are also persisted if children are.
495
+ while (layoutInfo && layoutInfo.parentKey) {
496
+ let collectionNode = this.collection.getItem(layoutInfo.key);
497
+ let indices = this.persistedIndices.get(layoutInfo.parentKey);
498
+ if (!indices) {
499
+ // stickyColumnIndices are always persisted along with any cells from persistedKeys.
500
+ indices = collectionNode?.type === 'cell' || collectionNode?.type === 'column' ? [...this.stickyColumnIndices] : [];
501
+ this.persistedIndices.set(layoutInfo.parentKey, indices);
502
+ }
503
+
504
+ let index = this.layoutNodes.get(layoutInfo.key).index;
505
+
506
+ if (!indices.includes(index)) {
507
+ indices.push(index);
508
+ }
509
+
510
+ layoutInfo = this.layoutNodes.get(layoutInfo.parentKey)?.layoutInfo;
511
+ }
512
+ }
513
+
514
+ for (let indices of this.persistedIndices.values()) {
515
+ indices.sort((a, b) => a - b);
516
+ }
517
+ }
518
+
519
+ getDropTargetFromPoint(x: number, y: number, isValidDropTarget: (target: DropTarget) => boolean): DropTarget {
520
+ x += this.virtualizer.visibleRect.x;
521
+ y += this.virtualizer.visibleRect.y;
522
+
523
+ // Custom variation of this.virtualizer.keyAtPoint that ignores body
524
+ let key: Key;
525
+ let point = new Point(x, y);
526
+ let rectAtPoint = new Rect(point.x, point.y, 1, 1);
527
+ let layoutInfos = this.virtualizer.layout.getVisibleLayoutInfos(rectAtPoint).filter(info => info.type === 'row');
528
+
529
+ // Layout may return multiple layout infos in the case of
530
+ // persisted keys, so find the first one that actually intersects.
531
+ for (let layoutInfo of layoutInfos) {
532
+ if (layoutInfo.rect.intersects(rectAtPoint)) {
533
+ key = layoutInfo.key;
534
+ }
535
+ }
536
+
537
+ if (key == null || this.collection.size === 0) {
538
+ return {type: 'root'};
539
+ }
540
+
541
+ let layoutInfo = this.getLayoutInfo(key);
542
+ let rect = layoutInfo.rect;
543
+ let target: DropTarget = {
544
+ type: 'item',
545
+ key: layoutInfo.key,
546
+ dropPosition: 'on'
547
+ };
548
+
549
+ // If dropping on the item isn't accepted, try the target before or after depending on the y position.
550
+ // Otherwise, if dropping on the item is accepted, still try the before/after positions if within 10px
551
+ // of the top or bottom of the item.
552
+ if (!isValidDropTarget(target)) {
553
+ if (y <= rect.y + rect.height / 2 && isValidDropTarget({...target, dropPosition: 'before'})) {
554
+ target.dropPosition = 'before';
555
+ } else if (isValidDropTarget({...target, dropPosition: 'after'})) {
556
+ target.dropPosition = 'after';
557
+ }
558
+ } else if (y <= rect.y + 10 && isValidDropTarget({...target, dropPosition: 'before'})) {
559
+ target.dropPosition = 'before';
560
+ } else if (y >= rect.maxY - 10 && isValidDropTarget({...target, dropPosition: 'after'})) {
561
+ target.dropPosition = 'after';
562
+ }
563
+
564
+ return target;
565
+ }
566
+
567
+ getDropTargetLayoutInfo(target: ItemDropTarget): LayoutInfo {
568
+ let layoutInfo = super.getDropTargetLayoutInfo(target);
569
+ layoutInfo.parentKey = this.collection.body.key;
570
+ return layoutInfo;
571
+ }
572
+ }
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ export type {GridLayoutOptions} from './GridLayout';
13
+ export type {ListLayoutOptions, LayoutNode} from './ListLayout';
14
+ export type {TableLayoutProps} from './TableLayout';
15
+ export {GridLayout} from './GridLayout';
16
+ export {ListLayout} from './ListLayout';
17
+ export {TableLayout} from './TableLayout';