@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
149 lines (148 loc) • 5.01 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { useAssertModelConsistency } from '@mui/x-internals/useAssertModelConsistency';
import { useStableCallback } from '@base-ui/utils/useStableCallback';
import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
import { expansionSelectors } from "./useTreeViewExpansion.selectors.js";
import { getExpansionTrigger } from "./useTreeViewExpansion.utils.js";
import { itemsSelectors } from "../useTreeViewItems/useTreeViewItems.selectors.js";
import { publishTreeViewEvent } from "../../utils/publishTreeViewEvent.js";
export const useTreeViewExpansion = ({
instance,
store,
params
}) => {
useAssertModelConsistency({
componentName: 'Tree View',
propName: 'expandedItems',
controlled: params.expandedItems,
defaultValue: params.defaultExpandedItems
});
useIsoLayoutEffect(() => {
const newExpansionTrigger = getExpansionTrigger({
isItemEditable: params.isItemEditable,
expansionTrigger: params.expansionTrigger
});
if (store.state.expansion.expansionTrigger === newExpansionTrigger) {
return;
}
store.set('expansion', _extends({}, store.state.expansion, {
expansionTrigger: newExpansionTrigger
}));
}, [store, params.isItemEditable, params.expansionTrigger]);
const setExpandedItems = (event, value) => {
if (params.expandedItems === undefined) {
store.set('expansion', _extends({}, store.state.expansion, {
expandedItems: value
}));
}
params.onExpandedItemsChange?.(event, value);
};
const resetItemExpansion = useStableCallback(() => {
setExpandedItems(null, []);
});
const applyItemExpansion = useStableCallback(({
itemId,
event,
shouldBeExpanded
}) => {
const oldExpanded = expansionSelectors.expandedItemsRaw(store.state);
let newExpanded;
if (shouldBeExpanded) {
newExpanded = [itemId].concat(oldExpanded);
} else {
newExpanded = oldExpanded.filter(id => id !== itemId);
}
if (params.onItemExpansionToggle) {
params.onItemExpansionToggle(event, itemId, shouldBeExpanded);
}
setExpandedItems(event, newExpanded);
});
const setItemExpansion = useStableCallback(({
itemId,
event = null,
shouldBeExpanded
}) => {
const isExpandedBefore = expansionSelectors.isItemExpanded(store.state, itemId);
const cleanShouldBeExpanded = shouldBeExpanded ?? !isExpandedBefore;
if (isExpandedBefore === cleanShouldBeExpanded) {
return;
}
const eventParameters = {
isExpansionPrevented: false,
shouldBeExpanded: cleanShouldBeExpanded,
event,
itemId
};
publishTreeViewEvent(instance, 'beforeItemToggleExpansion', eventParameters);
if (eventParameters.isExpansionPrevented) {
return;
}
instance.applyItemExpansion({
itemId,
event,
shouldBeExpanded: cleanShouldBeExpanded
});
});
const isItemExpanded = useStableCallback(itemId => {
return expansionSelectors.isItemExpanded(store.state, itemId);
});
const expandAllSiblings = (event, itemId) => {
const itemMeta = itemsSelectors.itemMeta(store.state, itemId);
if (itemMeta == null) {
return;
}
const siblings = itemsSelectors.itemOrderedChildrenIds(store.state, itemMeta.parentId);
const diff = siblings.filter(child => expansionSelectors.isItemExpandable(store.state, child) && !expansionSelectors.isItemExpanded(store.state, child));
const newExpanded = expansionSelectors.expandedItemsRaw(store.state).concat(diff);
if (diff.length > 0) {
if (params.onItemExpansionToggle) {
diff.forEach(newlyExpandedItemId => {
params.onItemExpansionToggle(event, newlyExpandedItemId, true);
});
}
setExpandedItems(event, newExpanded);
}
};
/**
* Update the controlled model when the `expandedItems` prop changes.
*/
useIsoLayoutEffect(() => {
const expandedItems = params.expandedItems;
if (expandedItems !== undefined) {
store.set('expansion', _extends({}, store.state.expansion, {
expandedItems
}));
}
}, [store, params.expandedItems]);
return {
publicAPI: {
setItemExpansion,
isItemExpanded
},
instance: {
setItemExpansion,
applyItemExpansion,
expandAllSiblings,
resetItemExpansion
}
};
};
const DEFAULT_EXPANDED_ITEMS = [];
useTreeViewExpansion.applyDefaultValuesToParams = ({
params
}) => _extends({}, params, {
defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_ITEMS
});
useTreeViewExpansion.getInitialState = params => ({
expansion: {
expandedItems: params.expandedItems === undefined ? params.defaultExpandedItems : params.expandedItems,
expansionTrigger: getExpansionTrigger(params)
}
});
useTreeViewExpansion.params = {
expandedItems: true,
defaultExpandedItems: true,
onExpandedItemsChange: true,
onItemExpansionToggle: true,
expansionTrigger: true
};