@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
121 lines (118 loc) • 4.2 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useTreeViewFocus = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _useEventCallback = require("@base-ui-components/utils/useEventCallback");
var _store = require("@mui/x-internals/store");
var _useTreeViewFocus = require("./useTreeViewFocus.selectors");
var _useTreeViewExpansion = require("../useTreeViewExpansion/useTreeViewExpansion.selectors");
var _useTreeViewItems = require("../useTreeViewItems/useTreeViewItems.selectors");
const useTreeViewFocus = ({
instance,
params,
store
}) => {
const setFocusedItemId = (0, _useEventCallback.useEventCallback)(itemId => {
const focusedItemId = _useTreeViewFocus.focusSelectors.focusedItemId(store.state);
if (focusedItemId === itemId) {
return;
}
store.set('focus', (0, _extends2.default)({}, store.state.focus, {
focusedItemId: itemId
}));
});
const isItemVisible = itemId => {
const itemMeta = _useTreeViewItems.itemsSelectors.itemMeta(store.state, itemId);
return itemMeta && (itemMeta.parentId == null || _useTreeViewExpansion.expansionSelectors.isItemExpanded(store.state, 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 = (0, _useEventCallback.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 = (0, _useEventCallback.useEventCallback)(() => {
const focusedItemId = _useTreeViewFocus.focusSelectors.focusedItemId(store.state);
if (focusedItemId == null) {
return;
}
const itemMeta = _useTreeViewItems.itemsSelectors.itemMeta(store.state, focusedItemId);
if (itemMeta) {
const itemElement = instance.getItemDOMElement(focusedItemId);
if (itemElement) {
itemElement.blur();
}
}
setFocusedItemId(null);
});
// Whenever the items change, we need to ensure the focused item is still present.
(0, _store.useStoreEffect)(store, _useTreeViewItems.itemsSelectors.itemMetaLookup, () => {
const focusedItemId = _useTreeViewFocus.focusSelectors.focusedItemId(store.state);
if (focusedItemId == null) {
return;
}
const hasItemBeenRemoved = !_useTreeViewItems.itemsSelectors.itemMeta(store.state, focusedItemId);
if (!hasItemBeenRemoved) {
return;
}
const defaultFocusableItemId = _useTreeViewFocus.focusSelectors.defaultFocusableItemId(store.state);
if (defaultFocusableItemId == null) {
setFocusedItemId(null);
return;
}
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 = _useTreeViewFocus.focusSelectors.defaultFocusableItemId(store.state);
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
}
};
};
exports.useTreeViewFocus = useTreeViewFocus;
useTreeViewFocus.getInitialState = () => ({
focus: {
focusedItemId: null
}
});
useTreeViewFocus.params = {
onItemFocus: true
};