UNPKG

@mui/x-tree-view

Version:

The community edition of the MUI X Tree View components.

108 lines (107 loc) 3.47 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import useEventCallback from '@mui/utils/useEventCallback'; import { useInstanceEventHandler } from "../../hooks/useInstanceEventHandler.js"; import { selectorDefaultFocusableItemId, selectorFocusedItemId } from "./useTreeViewFocus.selectors.js"; import { selectorIsItemExpanded } from "../useTreeViewExpansion/useTreeViewExpansion.selectors.js"; import { selectorItemMeta } from "../useTreeViewItems/useTreeViewItems.selectors.js"; export const useTreeViewFocus = ({ instance, params, store }) => { const setFocusedItemId = useEventCallback(itemId => { store.update(prevState => { const focusedItemId = selectorFocusedItemId(prevState); if (focusedItemId === itemId) { return prevState; } return _extends({}, prevState, { focus: _extends({}, prevState.focus, { focusedItemId: itemId }) }); }); }); const isItemVisible = itemId => { const itemMeta = selectorItemMeta(store.value, itemId); return itemMeta && (itemMeta.parentId == null || selectorIsItemExpanded(store.value, itemMeta.parentId)); }; const innerFocusItem = (event, itemId) => { const itemElement = instance.getItemDOMElement(itemId); if (itemElement) { itemElement.focus(); } setFocusedItemId(itemId); if (params.onItemFocus) { params.onItemFocus(event, itemId); } }; const focusItem = useEventCallback((event, itemId) => { // If we receive an itemId, and it is visible, the focus will be set to it if (isItemVisible(itemId)) { innerFocusItem(event, itemId); } }); const removeFocusedItem = useEventCallback(() => { const focusedItemId = selectorFocusedItemId(store.value); if (focusedItemId == null) { return; } const itemMeta = selectorItemMeta(store.value, focusedItemId); if (itemMeta) { const itemElement = instance.getItemDOMElement(focusedItemId); if (itemElement) { itemElement.blur(); } } setFocusedItemId(null); }); useInstanceEventHandler(instance, 'removeItem', ({ id }) => { const focusedItemId = selectorFocusedItemId(store.value); const defaultFocusableItemId = selectorDefaultFocusableItemId(store.value); if (focusedItemId === id && defaultFocusableItemId != null) { innerFocusItem(null, defaultFocusableItemId); } }); const createRootHandleFocus = otherHandlers => event => { otherHandlers.onFocus?.(event); if (event.defaultMuiPrevented) { return; } // if the event bubbled (which is React specific) we don't want to steal focus const defaultFocusableItemId = selectorDefaultFocusableItemId(store.value); if (event.target === event.currentTarget && defaultFocusableItemId != null) { innerFocusItem(event, defaultFocusableItemId); } }; const createRootHandleBlur = otherHandlers => event => { otherHandlers.onBlur?.(event); if (event.defaultMuiPrevented) { return; } setFocusedItemId(null); }; return { getRootProps: otherHandlers => ({ onFocus: createRootHandleFocus(otherHandlers), onBlur: createRootHandleBlur(otherHandlers) }), publicAPI: { focusItem }, instance: { focusItem, removeFocusedItem } }; }; useTreeViewFocus.getInitialState = () => ({ focus: { focusedItemId: null } }); useTreeViewFocus.params = { onItemFocus: true };