@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
124 lines (119 loc) • 4.98 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { expansionSelectors } from "./selectors.js";
import { itemsSelectors } from "../items/selectors.js";
export class TreeViewExpansionPlugin {
// We can't type `store`, otherwise we get the following TS error:
// 'expansion' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
constructor(store) {
this.store = store;
}
setExpandedItems = (event, value) => {
if (this.store.parameters.expandedItems === undefined) {
this.store.set('expandedItems', value);
}
this.store.parameters.onExpandedItemsChange?.(event, value);
};
/**
* Check if an item is expanded.
* @param {TreeViewItemId} itemId The id of the item to check.
* @returns {boolean} `true` if the item is expanded, `false` otherwise.
*/
isItemExpanded = itemId => expansionSelectors.isItemExpanded(this.store.state, itemId);
buildPublicAPI = () => {
return {
isItemExpanded: this.isItemExpanded,
setItemExpansion: this.setItemExpansion
};
};
/**
* Change the expansion status of a given item.
* @param {object} parameters The parameters of the method.
* @param {TreeViewItemId} parameters.itemId The id of the item to expand of collapse.
* @param {React.SyntheticEvent} parameters.event The DOM event that triggered the change.
* @param {boolean} parameters.shouldBeExpanded If `true` the item will be expanded. If `false` the item will be collapsed. If not defined, the item's expansion status will be the toggled.
*/
setItemExpansion = ({
itemId,
event = null,
shouldBeExpanded
}) => {
const isExpandedBefore = expansionSelectors.isItemExpanded(this.store.state, itemId);
const cleanShouldBeExpanded = shouldBeExpanded ?? !isExpandedBefore;
if (isExpandedBefore === cleanShouldBeExpanded) {
return;
}
const eventParameters = {
isExpansionPrevented: false,
shouldBeExpanded: cleanShouldBeExpanded,
itemId
};
this.store.publishEvent('beforeItemToggleExpansion', eventParameters, event);
if (eventParameters.isExpansionPrevented) {
return;
}
this.applyItemExpansion({
itemId,
event,
shouldBeExpanded: cleanShouldBeExpanded
});
};
/**
* Apply the new expansion status of a given item.
* Is used by the `setItemExpansion` method and by the `useTreeViewLazyLoading` plugin.
* Unlike `setItemExpansion`, this method does not trigger the lazy loading.
* @param {object} parameters The parameters of the method.
* @param {TreeViewItemId} parameters.itemId The id of the item to expand of collapse.
* @param {React.SyntheticEvent | null} parameters.event The DOM event that triggered the change.
* @param {boolean} parameters.shouldBeExpanded If `true` the item will be expanded. If `false` the item will be collapsed.
*/
applyItemExpansion = ({
itemId,
event,
shouldBeExpanded
}) => {
const oldExpanded = expansionSelectors.expandedItemsRaw(this.store.state);
let newExpanded;
if (shouldBeExpanded) {
newExpanded = [itemId].concat(oldExpanded);
} else {
newExpanded = oldExpanded.filter(id => id !== itemId);
}
this.store.parameters.onItemExpansionToggle?.(event, itemId, shouldBeExpanded);
this.setExpandedItems(event, newExpanded);
};
/**
* Expand all the siblings (i.e.: the items that have the same parent) of a given item.
* @param {React.SyntheticEvent} event The DOM event that triggered the change.
* @param {TreeViewItemId} itemId The id of the item whose siblings will be expanded.
*/
expandAllSiblings = (event, itemId) => {
const itemMeta = itemsSelectors.itemMeta(this.store.state, itemId);
if (itemMeta == null) {
return;
}
const siblings = itemsSelectors.itemOrderedChildrenIds(this.store.state, itemMeta.parentId);
const diff = siblings.filter(child => expansionSelectors.isItemExpandable(this.store.state, child) && !expansionSelectors.isItemExpanded(this.store.state, child));
const newExpanded = expansionSelectors.expandedItemsRaw(this.store.state).concat(diff);
if (diff.length > 0) {
if (this.store.parameters.onItemExpansionToggle) {
diff.forEach(newlyExpandedItemId => {
this.store.parameters.onItemExpansionToggle(event, newlyExpandedItemId, true);
});
}
this.setExpandedItems(event, newExpanded);
}
};
/**
* Mark a list of items as expandable.
* @param {TreeViewItemId[]} items The ids of the items to mark as expandable.
*/
addExpandableItems = items => {
const newItemMetaLookup = _extends({}, this.store.state.itemMetaLookup);
for (const itemId of items) {
newItemMetaLookup[itemId] = _extends({}, newItemMetaLookup[itemId], {
expandable: true
});
}
this.store.set('itemMetaLookup', newItemMetaLookup);
};
}