@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
159 lines (155 loc) • 5.52 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _formatErrorMessage from "@mui/x-internals/formatErrorMessage";
export const TREE_VIEW_ROOT_PARENT_ID = '__TREE_VIEW_ROOT_PARENT_ID__';
export const buildSiblingIndexes = siblings => {
const siblingsIndexLookup = {};
siblings.forEach((childId, index) => {
siblingsIndexLookup[childId] = index;
});
return siblingsIndexLookup;
};
/**
* Check if an item is disabled.
* This method should only be used in selectors that are checking if several items are disabled.
* Otherwise, use the `itemsSelector.isItemDisabled` selector.
* @returns
*/
export const isItemDisabled = (itemMetaLookup, itemId) => {
if (itemId == null) {
return false;
}
let itemMeta = itemMetaLookup[itemId];
// This can be called before the item has been added to the item map.
if (!itemMeta) {
return false;
}
if (itemMeta.disabled) {
return true;
}
while (itemMeta.parentId != null) {
itemMeta = itemMetaLookup[itemMeta.parentId];
if (!itemMeta) {
return false;
}
if (itemMeta.disabled) {
return true;
}
}
return false;
};
export function buildItemsLookups(parameters) {
const {
storeParameters,
items,
parentId,
depth,
isItemExpandable,
otherItemsMetaLookup
} = parameters;
const metaLookup = {};
const modelLookup = {};
const orderedChildrenIds = [];
const itemsChildren = [];
const processItem = item => {
const id = storeParameters.getItemId ? storeParameters.getItemId(item) : item.id;
checkId({
id,
parentId,
item,
itemMetaLookup: otherItemsMetaLookup,
siblingsMetaLookup: metaLookup
});
const label = storeParameters.getItemLabel ? storeParameters.getItemLabel(item) : item.label;
if (label == null) {
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X Tree View: All items must have a `label` property. ' + 'You can use the `getItemLabel` prop to specify a custom label for each item. ' + `An item was provided without a label: ${JSON.stringify(item)}` : _formatErrorMessage(192, JSON.stringify(item)));
}
const children = (storeParameters.getItemChildren ? storeParameters.getItemChildren(item) : item.children) || [];
itemsChildren.push({
id,
children
});
modelLookup[id] = item;
metaLookup[id] = {
id,
label,
parentId,
idAttribute: undefined,
expandable: isItemExpandable(item, children),
disabled: storeParameters.isItemDisabled ? storeParameters.isItemDisabled(item) : false,
selectable: storeParameters.isItemSelectionDisabled ? !storeParameters.isItemSelectionDisabled(item) : true,
depth
};
orderedChildrenIds.push(id);
};
for (const item of items) {
processItem(item);
}
return {
metaLookup,
modelLookup,
orderedChildrenIds,
childrenIndexes: buildSiblingIndexes(orderedChildrenIds),
itemsChildren
};
}
/**
* Builds the items lookups for a tree of items, recursing into the children of each item.
* The returned lookups only contain the items passed to this method.
*/
export function buildItemsLookupsRecursively(parameters) {
const {
storeParameters,
items,
parentId,
depth,
isItemExpandable,
existingItemMetaLookup
} = parameters;
const itemMetaLookup = {};
const itemModelLookup = {};
const itemOrderedChildrenIdsLookup = {};
const itemChildrenIndexesLookup = {};
// Both the existing items and the ones processed here, to detect duplicated ids.
const otherItemsMetaLookup = _extends({}, existingItemMetaLookup);
const processSiblings = (siblings, siblingsParentId, siblingsDepth) => {
const lookups = buildItemsLookups({
storeParameters,
items: siblings,
parentId: siblingsParentId,
depth: siblingsDepth,
isItemExpandable,
otherItemsMetaLookup
});
Object.assign(itemMetaLookup, lookups.metaLookup);
Object.assign(otherItemsMetaLookup, lookups.metaLookup);
Object.assign(itemModelLookup, lookups.modelLookup);
itemOrderedChildrenIdsLookup[siblingsParentId ?? TREE_VIEW_ROOT_PARENT_ID] = lookups.orderedChildrenIds;
itemChildrenIndexesLookup[siblingsParentId ?? TREE_VIEW_ROOT_PARENT_ID] = lookups.childrenIndexes;
for (const item of lookups.itemsChildren) {
processSiblings(item.children, item.id, siblingsDepth + 1);
}
};
processSiblings(items, parentId, depth);
return {
itemMetaLookup,
itemModelLookup,
itemOrderedChildrenIdsLookup,
itemChildrenIndexesLookup
};
}
function checkId({
id,
parentId,
item,
itemMetaLookup,
siblingsMetaLookup
}) {
if (id == null) {
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X Tree View: All items must have a unique `id` property. ' + 'You can use the `getItemId` prop to specify a custom id for each item. ' + `An item was provided without an id: ${JSON.stringify(item)}` : _formatErrorMessage(193, JSON.stringify(item)));
}
if (siblingsMetaLookup[id] != null ||
// Ignore items with the same parent id, because it's the same item from the previous generation.
itemMetaLookup[id] != null && itemMetaLookup[id].parentId !== parentId) {
throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Tree View: All items must have a unique \`id\` property. ` + `The id "${id}" is used by multiple items. ` + 'Use the `getItemId` prop to specify a custom id for each item if needed.' : _formatErrorMessage(194, id));
}
}