Skip to content

Commit 0ddb394

Browse files
authored
fix(dnd): Virtualized Tree DnD fixes 2 (#8550)
* skip non-item nodes in useDndPersistedKeys * persist last descendant key for 'after' last key in collection
1 parent 0cdf701 commit 0ddb394

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

packages/react-aria-components/src/DragAndDrop.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export function useDndPersistedKeys(selectionManager: MultipleSelectionManager,
7676
if (dropState.target.dropPosition === 'after') {
7777
// Normalize to the "before" drop position since we only render those to the DOM.
7878
let nextKey = dropState.collection.getKeyAfter(dropTargetKey);
79+
let lastDescendantKey: Key | null = null;
7980
if (nextKey != null) {
8081
let targetLevel = dropState.collection.getItem(dropTargetKey)?.level ?? 0;
8182
// Skip over any rows that are descendants of the target ("after" position should be after all children)
@@ -85,16 +86,26 @@ export function useDndPersistedKeys(selectionManager: MultipleSelectionManager,
8586
if (!node) {
8687
break;
8788
}
88-
// Stop once we find a node at the same level or higher
89+
// Skip over non-item nodes (e.g., loaders) since they can't be drop targets.
90+
// eslint-disable-next-line max-depth
91+
if (node.type !== 'item') {
92+
nextKey = dropState.collection.getKeyAfter(nextKey);
93+
continue;
94+
}
95+
96+
// Stop once we find an item at the same level or higher
8997
// eslint-disable-next-line max-depth
9098
if ((node.level ?? 0) <= targetLevel) {
9199
break;
92100
}
101+
102+
lastDescendantKey = nextKey;
93103
nextKey = dropState.collection.getKeyAfter(nextKey);
94104
}
95105
}
96106

97-
dropTargetKey = nextKey ?? dropTargetKey;
107+
// If nextKey is null (end of collection), use the last descendant
108+
dropTargetKey = nextKey ?? lastDescendantKey ?? dropTargetKey;
98109
}
99110
}
100111

0 commit comments

Comments
 (0)