| 55 | * of items from props, item expanded state, and manages multiple selection state. |
| 56 | */ |
| 57 | export function useTreeState<T>(props: TreeProps<T>): TreeState<T> { |
| 58 | let {onExpandedChange} = props; |
| 59 | |
| 60 | let [expandedKeys, setExpandedKeys] = useControlledState( |
| 61 | props.expandedKeys ? new Set(props.expandedKeys) : undefined, |
| 62 | props.defaultExpandedKeys ? new Set(props.defaultExpandedKeys) : new Set(), |
| 63 | onExpandedChange |
| 64 | ); |
| 65 | |
| 66 | let selectionState = useMultipleSelectionState(props); |
| 67 | let disabledKeys = useMemo( |
| 68 | () => (props.disabledKeys ? new Set(props.disabledKeys) : new Set<Key>()), |
| 69 | [props.disabledKeys] |
| 70 | ); |
| 71 | |
| 72 | let tree = useCollection( |
| 73 | props, |
| 74 | useCallback(nodes => new TreeCollection(nodes, {expandedKeys}), [expandedKeys]), |
| 75 | null |
| 76 | ); |
| 77 | |
| 78 | // Reset focused key if that item is deleted from the collection. |
| 79 | useEffect(() => { |
| 80 | if (selectionState.focusedKey != null && !tree.getItem(selectionState.focusedKey)) { |
| 81 | selectionState.setFocusedKey(null); |
| 82 | } |
| 83 | // eslint-disable-next-line react-hooks/exhaustive-deps |
| 84 | }, [tree, selectionState.focusedKey]); |
| 85 | |
| 86 | let onToggle = (key: Key) => { |
| 87 | setExpandedKeys(toggleKey(expandedKeys, key)); |
| 88 | }; |
| 89 | |
| 90 | return { |
| 91 | collection: tree, |
| 92 | expandedKeys, |
| 93 | disabledKeys, |
| 94 | toggleKey: onToggle, |
| 95 | setExpandedKeys, |
| 96 | selectionManager: new SelectionManager(tree, selectionState) |
| 97 | }; |
| 98 | } |
| 99 | |
| 100 | function toggleKey(set: Set<Key>, key: Key): Set<Key> { |
| 101 | let res = new Set(set); |