Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
473d209
initial tree stuff
yihuiliao Sep 23, 2025
e896397
fix virtualized tree section expanding, update methods to remove flat…
yihuiliao Oct 6, 2025
c3385c1
cleanup
yihuiliao Oct 6, 2025
fb17656
more cleanup
yihuiliao Oct 6, 2025
a1c8b17
Merge branch 'main' into tree-section
yihuiliao Oct 6, 2025
89df42f
update key after if its content node
yihuiliao Oct 7, 2025
8491826
fix types when checking content node
yihuiliao Oct 7, 2025
6f78fe7
fix spacing
yihuiliao Oct 7, 2025
43f2895
update dynamic story
yihuiliao Oct 9, 2025
99d4169
update setSize with added getDirectChildren function
yihuiliao Oct 9, 2025
049f2a5
fix types, update at method
yihuiliao Oct 9, 2025
fce9dce
remove console logs
yihuiliao Oct 9, 2025
f138f6a
add collection dependency to gridlist
yihuiliao Oct 9, 2025
900d69e
fix lint
yihuiliao Oct 10, 2025
ae36ec5
update yarn lock
yihuiliao Oct 10, 2025
cff1b4c
rename dynamic row section array
yihuiliao Oct 10, 2025
e6752ca
add tests, fix setSize for top level nodes inside a section
yihuiliao Oct 10, 2025
fb703b2
fix lint
yihuiliao Oct 10, 2025
98289ce
remove comments
yihuiliao Oct 10, 2025
ed55388
more cleanup
yihuiliao Oct 10, 2025
3facc4a
comments and stuff
yihuiliao Oct 10, 2025
2674d5b
Merge branch 'main' into tree-section
yihuiliao Oct 21, 2025
19151b4
Merge branch 'main' into tree-section
yihuiliao Jan 29, 2026
91cb778
fix tests
yihuiliao Jan 29, 2026
49cb60c
these changes were made in oct and it's now jan so...
yihuiliao Jan 29, 2026
13baafd
lots of comments regarding skipping content nodes in tree
yihuiliao Feb 6, 2026
100befa
skip content nodes is listlayout and collections, update keyboard del…
yihuiliao Feb 7, 2026
2d98707
Merge branch 'main' into tree-section
yihuiliao Feb 7, 2026
fa3da98
update yarn lock
yihuiliao Feb 7, 2026
2410143
update direct children function
yihuiliao Feb 8, 2026
92e1840
comments
yihuiliao Feb 9, 2026
8191e58
update direct children functiona and remove collectionode type from g…
yihuiliao Feb 9, 2026
229092c
update comments
yihuiliao Feb 9, 2026
bee7804
Merge branch 'main' into tree-section
yihuiliao Feb 11, 2026
46d3c76
updates
yihuiliao Feb 11, 2026
8f668a2
simplify logic for visible/non disabled item
yihuiliao Feb 11, 2026
29e729d
comments, small fixes
yihuiliao Feb 12, 2026
564646d
make guarding against content node more robust
yihuiliao Feb 12, 2026
3d8b288
optimize filtering content nodes in list layout
yihuiliao Feb 12, 2026
d209f52
optimize getting child array
yihuiliao Feb 12, 2026
f1088a1
add helper function for cloning
yihuiliao Feb 12, 2026
421f22f
add comments
yihuiliao Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/@react-aria/collections/src/useCachedChildren.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export function useCachedChildren<T extends object>(props: CachedChildrenOptions
rendered = children(item);
// @ts-ignore
let key = rendered.props.id ?? item.key ?? item.id;

if (key == null) {
throw new Error('Could not determine key for item');
}

if (idScope) {
key = idScope + ':' + key;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/@react-aria/dnd/src/DropTargetKeyboardNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ function nextDropTarget(
nextKey = keyboardDelegate.getKeyBelow?.(target.key);
}
let nextCollectionKey = collection.getKeyAfter(target.key);
let nextCollectionNode = nextCollectionKey && collection.getItem(nextCollectionKey);
if (nextCollectionNode && nextCollectionNode.type === 'content') {
nextCollectionKey = nextCollectionKey ? collection.getKeyAfter(nextCollectionKey) : null;
}

// If the keyboard delegate did not move to the next key in the collection,
// jump to that key with the same drop position. Otherwise, try the other
Expand Down Expand Up @@ -100,7 +104,7 @@ function nextDropTarget(
}
case 'after': {
// If this is the last sibling in a level, traverse to the parent.
let targetNode = collection.getItem(target.key);
let targetNode = collection.getItem(target.key);
if (targetNode && targetNode.nextKey == null && targetNode.parentKey != null) {
// If the parent item has an item after it, use the "before" position.
let parentNode = collection.getItem(targetNode.parentKey);
Expand Down
1 change: 1 addition & 0 deletions packages/@react-aria/gridlist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"url": "https://github.com/adobe/react-spectrum"
},
"dependencies": {
"@react-aria/collections": "^3.0.0",
"@react-aria/focus": "^3.21.2",
"@react-aria/grid": "^3.14.5",
"@react-aria/i18n": "^3.12.13",
Expand Down
17 changes: 14 additions & 3 deletions packages/@react-aria/gridlist/src/useGridListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
*/

import {chain, getScrollParent, mergeProps, scrollIntoViewport, useSlotId, useSyntheticLinkProps} from '@react-aria/utils';
import {DOMAttributes, FocusableElement, Key, RefObject, Node as RSNode} from '@react-types/shared';
import {Collection, DOMAttributes, FocusableElement, Key, RefObject, Node as RSNode} from '@react-types/shared';
import {CollectionNode} from '@react-aria/collections';
import {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';
import {getRowId, listMap} from './utils';
import {HTMLAttributes, KeyboardEvent as ReactKeyboardEvent, useRef} from 'react';
Expand Down Expand Up @@ -100,11 +101,11 @@ export function useGridListItem<T>(props: AriaGridListItemOptions, state: ListSt

let isExpanded = hasChildRows ? state.expandedKeys.has(node.key) : undefined;
let setSize = 1;
if (node.level > 0 && node?.parentKey != null) {
if (node.level >= 0 && node?.parentKey != null) {
let parent = state.collection.getItem(node.parentKey);
if (parent) {
// siblings must exist because our original node exists
let siblings = state.collection.getChildren?.(parent.key)!;
let siblings = getDirectChildren(parent as CollectionNode<T>, state.collection as Collection<CollectionNode<T>>);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we used to use the getChildren method from TreeCollection but now that we've changed it to get ALL the descendants of a parent node instead of its immediate descendants, we can't use that anymore. i decided to make a new function called getDirectChildren which is essentially the same code as what getChildren was before

setSize = [...siblings].filter(row => row.type === 'item').length;
}
} else {
Expand Down Expand Up @@ -324,3 +325,13 @@ function last(walker: TreeWalker) {
} while (last);
return next;
}

function getDirectChildren<T>(parent: CollectionNode<T>, collection: Collection<CollectionNode<T>>) {
let node = parent?.firstChildKey != null ? collection.getItem(parent.firstChildKey) : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this only works with new collections (that's why it required a type cast above)? Maybe ok because we currently only implement Tree in RAC, not directly via hooks, but if someone did that this wouldn't work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh true. i guess i could maybe do some type guarding and have some different logic if it's Node and not a CollectionNode? kinda unfortunate that we can't use getChildren here anymore tho

let siblings: CollectionNode<T>[] = [];
while (node) {
siblings.push(node);
node = node.nextKey != null ? collection.getItem(node.nextKey) : null;
}
return siblings;
}
2 changes: 1 addition & 1 deletion packages/@react-stately/data/src/useTreeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ function moveItems<T extends object>(
// decrement the index if the child being removed is in the target parent and before the target index
// the root node is special, it is null, and will not have a key, however, a parentKey can still point to it
if ((child.parentKey === toParent
|| child.parentKey === toParent?.key)
|| child.parentKey === toParent?.key)
&& keyArray.includes(child.key)
&& (toParent?.children ? toParent.children.indexOf(child) : items.indexOf(child)) < originalToIndex) {
toIndex--;
Expand Down
2 changes: 1 addition & 1 deletion packages/react-aria-components/src/GridList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ export const GridListSection = /*#__PURE__*/ createBranchComponent(SectionNode,
});

export const GridListHeaderContext = createContext<ContextValue<HTMLAttributes<HTMLDivElement>, HTMLDivElement>>({});
const GridListHeaderInnerContext = createContext<HTMLAttributes<HTMLElement> | null>(null);
export const GridListHeaderInnerContext = createContext<HTMLAttributes<HTMLElement> | null>(null);

export const GridListHeader = /*#__PURE__*/ createLeafComponent(HeaderNode, function Header(props: HTMLAttributes<HTMLElement>, ref: ForwardedRef<HTMLDivElement>) {
[props, ref] = useContextProps(props, ref, GridListHeaderContext);
Expand Down
Loading