@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
96 lines • 3.37 kB
JavaScript
import { createSelector, useStore } from '@mui/x-internals/store';
import { useTreeViewContext } from "../../TreeViewProvider/index.js";
import { itemsSelectors } from "../items/selectors.js";
import { selectionSelectors } from "./selectors.js";
const selectorCheckboxSelectionStatus = createSelector((state, itemId) => {
if (selectionSelectors.isItemSelected(state, itemId)) {
return 'checked';
}
let hasSelectedDescendant = false;
let hasUnSelectedDescendant = false;
const traverseDescendants = itemToTraverseId => {
if (itemToTraverseId !== itemId) {
if (selectionSelectors.isItemSelected(state, itemToTraverseId)) {
hasSelectedDescendant = true;
} else {
hasUnSelectedDescendant = true;
}
}
itemsSelectors.itemOrderedChildrenIds(state, itemToTraverseId).forEach(traverseDescendants);
};
traverseDescendants(itemId);
const shouldSelectBasedOnDescendants = selectionSelectors.propagationRules(state).parents;
if (shouldSelectBasedOnDescendants) {
if (hasSelectedDescendant && hasUnSelectedDescendant) {
return 'indeterminate';
}
if (hasSelectedDescendant && !hasUnSelectedDescendant) {
return 'checked';
}
return 'empty';
}
if (hasSelectedDescendant) {
return 'indeterminate';
}
return 'empty';
});
export const useSelectionItemPlugin = ({
props
}) => {
const {
itemId
} = props;
const {
store
} = useTreeViewContext();
const isCheckboxSelectionEnabled = useStore(store, selectionSelectors.isCheckboxSelectionEnabled);
const isFeatureEnabledForItem = useStore(store, selectionSelectors.isFeatureEnabledForItem, itemId);
const canItemBeSelected = useStore(store, selectionSelectors.canItemBeSelected, itemId);
const selectionStatus = useStore(store, selectorCheckboxSelectionStatus, itemId);
return {
propsEnhancers: {
root: () => {
// https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
let ariaChecked;
if (selectionStatus === 'checked') {
// - each selected node has aria-checked set to true.
ariaChecked = true;
} else if (selectionStatus === 'indeterminate') {
ariaChecked = 'mixed';
} else if (!canItemBeSelected) {
// - if the tree contains nodes that are not selectable, aria-checked is not present on those nodes.
ariaChecked = undefined;
} else {
// - all nodes that are selectable but not selected have aria-checked set to false.
ariaChecked = false;
}
return {
'aria-checked': ariaChecked
};
},
checkbox: ({
externalEventHandlers,
interactions
}) => {
const handleChange = event => {
externalEventHandlers.onChange?.(event);
if (event.defaultMuiPrevented) {
return;
}
if (!selectionSelectors.canItemBeSelected(store.state, itemId)) {
return;
}
interactions.handleCheckboxSelection(event);
};
return {
tabIndex: -1,
onChange: handleChange,
visible: isCheckboxSelectionEnabled && isFeatureEnabledForItem,
disabled: !canItemBeSelected,
checked: selectionStatus === 'checked',
indeterminate: selectionStatus === 'indeterminate'
};
}
}
};
};