( props: GridStateOptions<T, C> )
| 38 | * focusable child if applicable. |
| 39 | */ |
| 40 | export function useGridState<T extends object, C extends IGridCollection<T>>( |
| 41 | props: GridStateOptions<T, C> |
| 42 | ): GridState<T, C> { |
| 43 | let {collection, focusMode} = props; |
| 44 | // eslint-disable-next-line react-hooks/rules-of-hooks |
| 45 | let selectionState = props.UNSAFE_selectionState || useMultipleSelectionState(props); |
| 46 | let disabledKeys = useMemo( |
| 47 | () => (props.disabledKeys ? new Set(props.disabledKeys) : new Set<Key>()), |
| 48 | [props.disabledKeys] |
| 49 | ); |
| 50 | |
| 51 | let setFocusedKey = selectionState.setFocusedKey; |
| 52 | selectionState.setFocusedKey = (key, child) => { |
| 53 | // If focusMode is cell and an item is focused, focus a child cell instead. |
| 54 | if (focusMode === 'cell' && key != null) { |
| 55 | let item = collection.getItem(key); |
| 56 | if (item?.type === 'item') { |
| 57 | let children = getChildNodes(item, collection); |
| 58 | if (child === 'last') { |
| 59 | key = getLastItem(children)?.key ?? null; |
| 60 | } else { |
| 61 | key = getFirstItem(children)?.key ?? null; |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | setFocusedKey(key, child); |
| 67 | }; |
| 68 | |
| 69 | let selectionManager = useMemo( |
| 70 | () => new SelectionManager(collection, selectionState), |
| 71 | [collection, selectionState] |
| 72 | ); |
| 73 | |
| 74 | // Reset focused key if that item is deleted from the collection. |
| 75 | const cachedCollection = useRef<C | null>(null); |
| 76 | useEffect(() => { |
| 77 | if ( |
| 78 | selectionState.focusedKey != null && |
| 79 | cachedCollection.current && |
| 80 | !collection.getItem(selectionState.focusedKey) |
| 81 | ) { |
| 82 | const node = cachedCollection.current.getItem(selectionState.focusedKey); |
| 83 | const parentNode = |
| 84 | node?.parentKey != null && |
| 85 | (node.type === 'cell' || node.type === 'rowheader' || node.type === 'column') |
| 86 | ? cachedCollection.current.getItem(node.parentKey) |
| 87 | : node; |
| 88 | if (!parentNode) { |
| 89 | selectionState.setFocusedKey(null); |
| 90 | return; |
| 91 | } |
| 92 | const cachedRows = cachedCollection.current.rows; |
| 93 | const rows = collection.rows; |
| 94 | const diff = cachedRows.length - rows.length; |
| 95 | let index = Math.min( |
| 96 | diff > 1 ? Math.max(parentNode.index - diff + 1, 0) : parentNode.index, |
| 97 | rows.length - 1 |
no test coverage detected