UNPKG

@mui/x-tree-view

Version:

The community edition of the MUI X Tree View components.

342 lines (339 loc) 13.4 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTreeViewItems = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback")); var _publishTreeViewEvent = require("../../utils/publishTreeViewEvent"); var _useTreeViewItems = require("./useTreeViewItems.utils"); var _TreeViewItemDepthContext = require("../../TreeViewItemDepthContext"); var _useTreeViewItems2 = require("./useTreeViewItems.selectors"); var _useTreeViewId = require("../../corePlugins/useTreeViewId/useTreeViewId.selectors"); var _useTreeViewId2 = require("../../corePlugins/useTreeViewId/useTreeViewId.utils"); var _jsxRuntime = require("react/jsx-runtime"); const checkId = (id, item, itemMetaLookup) => { if (id == null) { throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n')); } if (itemMetaLookup[id] != null) { throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Two items were provided with the same id in the \`items\` prop: "${id}"`].join('\n')); } }; const processItemsLookups = ({ disabledItemsFocusable, items, isItemDisabled, getItemLabel, getItemChildren, getItemId, initialDepth = 0, initialParentId = null, getChildrenCount, ignoreChildren = false }) => { const itemMetaLookup = {}; const itemModelLookup = {}; const itemOrderedChildrenIdsLookup = { [_useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID]: [] }; const processItem = (item, depth, parentId) => { const id = getItemId ? getItemId(item) : item.id; checkId(id, item, itemMetaLookup); const label = getItemLabel ? getItemLabel(item) : item.label; if (label == null) { throw new Error(['MUI X: The Tree View component requires all items to have a `label` property.', 'Alternatively, you can use the `getItemLabel` prop to specify a custom label for each item.', 'An item was provided without label in the `items` prop:', JSON.stringify(item)].join('\n')); } const children = getItemChildren ? getItemChildren(item) : item.children; itemMetaLookup[id] = { id, label, parentId, idAttribute: undefined, expandable: getChildrenCount ? getChildrenCount(item) > 0 : !!children?.length, disabled: isItemDisabled ? isItemDisabled(item) : false, depth }; itemModelLookup[id] = item; const parentIdWithDefault = parentId ?? _useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID; if (!itemOrderedChildrenIdsLookup[parentIdWithDefault]) { itemOrderedChildrenIdsLookup[parentIdWithDefault] = []; } itemOrderedChildrenIdsLookup[parentIdWithDefault].push(id); // if lazy loading is enabled, we don't want to process children passed through the `items` prop if (!ignoreChildren) { children?.forEach(child => processItem(child, depth + 1, id)); } }; items?.forEach(item => processItem(item, initialDepth, initialParentId)); const itemChildrenIndexesLookup = {}; Object.keys(itemOrderedChildrenIdsLookup).forEach(parentId => { itemChildrenIndexesLookup[parentId] = (0, _useTreeViewItems.buildSiblingIndexes)(itemOrderedChildrenIdsLookup[parentId]); }); return { disabledItemsFocusable, itemMetaLookup, itemModelLookup, itemOrderedChildrenIdsLookup, itemChildrenIndexesLookup }; }; const useTreeViewItems = ({ instance, params, store }) => { const getItem = React.useCallback(itemId => (0, _useTreeViewItems2.selectorItemModel)(store.value, itemId), [store]); const getParentId = React.useCallback(itemId => { const itemMeta = (0, _useTreeViewItems2.selectorItemMeta)(store.value, itemId); return itemMeta?.parentId || null; }, [store]); const setTreeViewLoading = (0, _useEventCallback.default)(isLoading => { store.update(prevState => (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, { loading: isLoading }) })); }); const setTreeViewError = (0, _useEventCallback.default)(error => { store.update(prevState => (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, { error }) })); }); const setIsItemDisabled = (0, _useEventCallback.default)(({ itemId, shouldBeDisabled }) => { store.update(prevState => { if (!prevState.items.itemMetaLookup[itemId]) { return prevState; } const itemMetaLookup = (0, _extends2.default)({}, prevState.items.itemMetaLookup); itemMetaLookup[itemId] = (0, _extends2.default)({}, itemMetaLookup[itemId], { disabled: shouldBeDisabled ?? !itemMetaLookup[itemId].disabled }); return (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, { itemMetaLookup }) }); }); }); const getItemTree = React.useCallback(() => { const getItemFromItemId = itemId => { const item = (0, _useTreeViewItems2.selectorItemModel)(store.value, itemId); const newChildren = (0, _useTreeViewItems2.selectorItemOrderedChildrenIds)(store.value, itemId); if (newChildren.length > 0) { item.children = newChildren.map(getItemFromItemId); } else { delete item.children; } return item; }; return (0, _useTreeViewItems2.selectorItemOrderedChildrenIds)(store.value, null).map(getItemFromItemId); }, [store]); const getItemOrderedChildrenIds = React.useCallback(itemId => (0, _useTreeViewItems2.selectorItemOrderedChildrenIds)(store.value, itemId), [store]); const getItemDOMElement = itemId => { const itemMeta = (0, _useTreeViewItems2.selectorItemMeta)(store.value, itemId); if (itemMeta == null) { return null; } const idAttribute = (0, _useTreeViewId2.generateTreeItemIdAttribute)({ treeId: (0, _useTreeViewId.selectorTreeViewId)(store.value), itemId, id: itemMeta.idAttribute }); return document.getElementById(idAttribute); }; const areItemUpdatesPreventedRef = React.useRef(false); const preventItemUpdates = React.useCallback(() => { areItemUpdatesPreventedRef.current = true; }, []); const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []); const addItems = ({ items, parentId, depth, getChildrenCount }) => { if (items) { const newState = processItemsLookups({ disabledItemsFocusable: params.disabledItemsFocusable, items, isItemDisabled: params.isItemDisabled, getItemId: params.getItemId, getItemLabel: params.getItemLabel, getItemChildren: params.getItemChildren, getChildrenCount, initialDepth: depth, initialParentId: parentId, ignoreChildren: true }); store.update(prevState => { let newItems; if (parentId) { newItems = { itemModelLookup: (0, _extends2.default)({}, prevState.items.itemModelLookup, newState.itemModelLookup), itemMetaLookup: (0, _extends2.default)({}, prevState.items.itemMetaLookup, newState.itemMetaLookup), itemOrderedChildrenIdsLookup: (0, _extends2.default)({}, newState.itemOrderedChildrenIdsLookup, prevState.items.itemOrderedChildrenIdsLookup), itemChildrenIndexesLookup: (0, _extends2.default)({}, newState.itemChildrenIndexesLookup, prevState.items.itemChildrenIndexesLookup) }; } else { newItems = { itemModelLookup: newState.itemModelLookup, itemMetaLookup: newState.itemMetaLookup, itemOrderedChildrenIdsLookup: newState.itemOrderedChildrenIdsLookup, itemChildrenIndexesLookup: newState.itemChildrenIndexesLookup }; } Object.values(prevState.items.itemMetaLookup).forEach(item => { if (!newItems.itemMetaLookup[item.id]) { (0, _publishTreeViewEvent.publishTreeViewEvent)(instance, 'removeItem', { id: item.id }); } }); return (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, newItems) }); }); } }; const removeChildren = parentId => { store.update(prevState => { if (!parentId) { return (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, { itemMetaLookup: {}, itemOrderedChildrenIdsLookup: {}, itemChildrenIndexesLookup: {} }) }); } const newMetaMap = Object.keys(prevState.items.itemMetaLookup).reduce((acc, key) => { const item = prevState.items.itemMetaLookup[key]; if (item.parentId === parentId) { (0, _publishTreeViewEvent.publishTreeViewEvent)(instance, 'removeItem', { id: item.id }); return acc; } return (0, _extends2.default)({}, acc, { [item.id]: item }); }, {}); const newItemOrderedChildrenIdsLookup = prevState.items.itemOrderedChildrenIdsLookup; const newItemChildrenIndexesLookup = prevState.items.itemChildrenIndexesLookup; delete newItemChildrenIndexesLookup[parentId]; delete newItemOrderedChildrenIdsLookup[parentId]; return (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, { itemMetaLookup: newMetaMap, itemOrderedChildrenIdsLookup: newItemOrderedChildrenIdsLookup, itemChildrenIndexesLookup: newItemChildrenIndexesLookup }) }); }); }; React.useEffect(() => { if (instance.areItemUpdatesPrevented()) { return; } store.update(prevState => { const newState = processItemsLookups({ disabledItemsFocusable: params.disabledItemsFocusable, items: params.items, isItemDisabled: params.isItemDisabled, getItemId: params.getItemId, getItemLabel: params.getItemLabel, getItemChildren: params.getItemChildren }); Object.values(prevState.items.itemMetaLookup).forEach(item => { if (!newState.itemMetaLookup[item.id]) { (0, _publishTreeViewEvent.publishTreeViewEvent)(instance, 'removeItem', { id: item.id }); } }); return (0, _extends2.default)({}, prevState, { items: (0, _extends2.default)({}, prevState.items, newState) }); }); }, [instance, store, params.items, params.disabledItemsFocusable, params.isItemDisabled, params.getItemId, params.getItemLabel, params.getItemChildren]); // Wrap `props.onItemClick` with `useEventCallback` to prevent unneeded context updates. const handleItemClick = (0, _useEventCallback.default)((event, itemId) => { if (params.onItemClick) { params.onItemClick(event, itemId); } }); return { getRootProps: () => ({ style: { '--TreeView-itemChildrenIndentation': typeof params.itemChildrenIndentation === 'number' ? `${params.itemChildrenIndentation}px` : params.itemChildrenIndentation } }), publicAPI: { getItem, getItemDOMElement, getItemTree, getItemOrderedChildrenIds, setIsItemDisabled, getParentId }, instance: { getItemDOMElement, preventItemUpdates, areItemUpdatesPrevented, addItems, setTreeViewLoading, setTreeViewError, removeChildren, handleItemClick } }; }; exports.useTreeViewItems = useTreeViewItems; useTreeViewItems.getInitialState = params => ({ items: (0, _extends2.default)({}, processItemsLookups({ disabledItemsFocusable: params.disabledItemsFocusable, items: params.items, isItemDisabled: params.isItemDisabled, getItemId: params.getItemId, getItemLabel: params.getItemLabel, getItemChildren: params.getItemChildren }), { loading: false, error: null }) }); useTreeViewItems.applyDefaultValuesToParams = ({ params }) => (0, _extends2.default)({}, params, { disabledItemsFocusable: params.disabledItemsFocusable ?? false, itemChildrenIndentation: params.itemChildrenIndentation ?? '12px' }); useTreeViewItems.wrapRoot = ({ children }) => { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_TreeViewItemDepthContext.TreeViewItemDepthContext.Provider, { value: _useTreeViewItems2.selectorItemDepth, children: children }); }; if (process.env.NODE_ENV !== "production") useTreeViewItems.wrapRoot.displayName = "useTreeViewItems.wrapRoot"; useTreeViewItems.params = { disabledItemsFocusable: true, items: true, isItemDisabled: true, getItemLabel: true, getItemChildren: true, getItemId: true, onItemClick: true, itemChildrenIndentation: true };