UNPKG

@mui/x-tree-view

Version:

The community edition of the MUI X Tree View components.

239 lines (236 loc) 10.2 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTreeViewSelection = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _useAssertModelConsistency = require("@mui/x-internals/useAssertModelConsistency"); var _useIsoLayoutEffect = require("@base-ui-components/utils/useIsoLayoutEffect"); var _tree = require("../../utils/tree"); var _useTreeViewSelection = require("./useTreeViewSelection.utils"); var _useTreeViewSelection2 = require("./useTreeViewSelection.selectors"); var _useTreeViewSelection3 = require("./useTreeViewSelection.itemPlugin"); const useTreeViewSelection = ({ store, params }) => { (0, _useAssertModelConsistency.useAssertModelConsistency)({ componentName: 'Tree View', propName: 'selectedItems', controlled: params.selectedItems, defaultValue: params.defaultSelectedItems }); const lastSelectedItem = React.useRef(null); const lastSelectedRange = React.useRef({}); const setSelectedItems = (event, newModel, additionalItemsToPropagate) => { const oldModel = _useTreeViewSelection2.selectionSelectors.selectedItemsRaw(store.state); let cleanModel; const isMultiSelectEnabled = _useTreeViewSelection2.selectionSelectors.isMultiSelectEnabled(store.state); if (isMultiSelectEnabled && (params.selectionPropagation.descendants || params.selectionPropagation.parents)) { cleanModel = (0, _useTreeViewSelection.propagateSelection)({ store, selectionPropagation: params.selectionPropagation, newModel: newModel, oldModel: oldModel, additionalItemsToPropagate }); } else { cleanModel = newModel; } if (params.onItemSelectionToggle) { if (isMultiSelectEnabled) { const changes = (0, _useTreeViewSelection.getAddedAndRemovedItems)({ store, newModel: cleanModel, oldModel: oldModel }); if (params.onItemSelectionToggle) { changes.added.forEach(itemId => { params.onItemSelectionToggle(event, itemId, true); }); changes.removed.forEach(itemId => { params.onItemSelectionToggle(event, itemId, false); }); } } else if (params.onItemSelectionToggle && cleanModel !== oldModel) { if (oldModel != null) { params.onItemSelectionToggle(event, oldModel, false); } if (cleanModel != null) { params.onItemSelectionToggle(event, cleanModel, true); } } } if (params.selectedItems === undefined) { store.set('selection', (0, _extends2.default)({}, store.state.selection, { selectedItems: cleanModel })); } params.onSelectedItemsChange?.(event, cleanModel); }; const setItemSelection = ({ itemId, event = null, keepExistingSelection = false, shouldBeSelected }) => { if (!_useTreeViewSelection2.selectionSelectors.enabled(store.state)) { return; } let newSelected; const isMultiSelectEnabled = _useTreeViewSelection2.selectionSelectors.isMultiSelectEnabled(store.state); if (keepExistingSelection) { const oldSelected = _useTreeViewSelection2.selectionSelectors.selectedItems(store.state); const isSelectedBefore = _useTreeViewSelection2.selectionSelectors.isItemSelected(store.state, itemId); if (isSelectedBefore && (shouldBeSelected === false || shouldBeSelected == null)) { newSelected = oldSelected.filter(id => id !== itemId); } else if (!isSelectedBefore && (shouldBeSelected === true || shouldBeSelected == null)) { newSelected = [itemId].concat(oldSelected); } else { newSelected = oldSelected; } } else { // eslint-disable-next-line no-lonely-if if (shouldBeSelected === false || shouldBeSelected == null && _useTreeViewSelection2.selectionSelectors.isItemSelected(store.state, itemId)) { newSelected = isMultiSelectEnabled ? [] : null; } else { newSelected = isMultiSelectEnabled ? [itemId] : itemId; } } setSelectedItems(event, newSelected, // If shouldBeSelected === selectionSelectors.isItemSelected(store, itemId), we still want to propagate the select. // This is useful when the element is in an indeterminate state. [itemId]); lastSelectedItem.current = itemId; lastSelectedRange.current = {}; }; const selectRange = (event, [start, end]) => { const isMultiSelectEnabled = _useTreeViewSelection2.selectionSelectors.isMultiSelectEnabled(store.state); if (!isMultiSelectEnabled) { return; } let newSelectedItems = _useTreeViewSelection2.selectionSelectors.selectedItems(store.state).slice(); // If the last selection was a range selection, // remove the items that were part of the last range from the model if (Object.keys(lastSelectedRange.current).length > 0) { newSelectedItems = newSelectedItems.filter(id => !lastSelectedRange.current[id]); } // Add to the model the items that are part of the new range and not already part of the model. const selectedItemsLookup = (0, _useTreeViewSelection.getLookupFromArray)(newSelectedItems); const range = (0, _tree.getNonDisabledItemsInRange)(store.state, start, end); const itemsToAddToModel = range.filter(id => !selectedItemsLookup[id]); newSelectedItems = newSelectedItems.concat(itemsToAddToModel); setSelectedItems(event, newSelectedItems); lastSelectedRange.current = (0, _useTreeViewSelection.getLookupFromArray)(range); }; const expandSelectionRange = (event, itemId) => { if (lastSelectedItem.current != null) { const [start, end] = (0, _tree.findOrderInTremauxTree)(store.state, itemId, lastSelectedItem.current); selectRange(event, [start, end]); } }; const selectRangeFromStartToItem = (event, itemId) => { selectRange(event, [(0, _tree.getFirstNavigableItem)(store.state), itemId]); }; const selectRangeFromItemToEnd = (event, itemId) => { selectRange(event, [itemId, (0, _tree.getLastNavigableItem)(store.state)]); }; const selectAllNavigableItems = event => { const isMultiSelectEnabled = _useTreeViewSelection2.selectionSelectors.isMultiSelectEnabled(store.state); if (!isMultiSelectEnabled) { return; } const navigableItems = (0, _tree.getAllNavigableItems)(store.state); setSelectedItems(event, navigableItems); lastSelectedRange.current = (0, _useTreeViewSelection.getLookupFromArray)(navigableItems); }; const selectItemFromArrowNavigation = (event, currentItem, nextItem) => { const isMultiSelectEnabled = _useTreeViewSelection2.selectionSelectors.isMultiSelectEnabled(store.state); if (!isMultiSelectEnabled) { return; } let newSelectedItems = _useTreeViewSelection2.selectionSelectors.selectedItems(store.state).slice(); if (Object.keys(lastSelectedRange.current).length === 0) { newSelectedItems.push(nextItem); lastSelectedRange.current = { [currentItem]: true, [nextItem]: true }; } else { if (!lastSelectedRange.current[currentItem]) { lastSelectedRange.current = {}; } if (lastSelectedRange.current[nextItem]) { newSelectedItems = newSelectedItems.filter(id => id !== currentItem); delete lastSelectedRange.current[currentItem]; } else { newSelectedItems.push(nextItem); lastSelectedRange.current[nextItem] = true; } } setSelectedItems(event, newSelectedItems); }; (0, _useIsoLayoutEffect.useIsoLayoutEffect)(() => { store.set('selection', { selectedItems: params.selectedItems === undefined ? store.state.selection.selectedItems : params.selectedItems, isEnabled: !params.disableSelection, isMultiSelectEnabled: params.multiSelect, isCheckboxSelectionEnabled: params.checkboxSelection, selectionPropagation: { descendants: params.selectionPropagation.descendants, parents: params.selectionPropagation.parents } }); }, [store, params.selectedItems, params.multiSelect, params.checkboxSelection, params.disableSelection, params.selectionPropagation.descendants, params.selectionPropagation.parents]); return { getRootProps: () => ({ 'aria-multiselectable': params.multiSelect }), publicAPI: { setItemSelection }, instance: { setItemSelection, selectAllNavigableItems, expandSelectionRange, selectRangeFromStartToItem, selectRangeFromItemToEnd, selectItemFromArrowNavigation } }; }; exports.useTreeViewSelection = useTreeViewSelection; useTreeViewSelection.itemPlugin = _useTreeViewSelection3.useTreeViewSelectionItemPlugin; const DEFAULT_SELECTED_ITEMS = []; const EMPTY_SELECTION_PROPAGATION = {}; useTreeViewSelection.applyDefaultValuesToParams = ({ params }) => (0, _extends2.default)({}, params, { disableSelection: params.disableSelection ?? false, multiSelect: params.multiSelect ?? false, checkboxSelection: params.checkboxSelection ?? false, defaultSelectedItems: params.defaultSelectedItems ?? (params.multiSelect ? DEFAULT_SELECTED_ITEMS : null), selectionPropagation: params.selectionPropagation ?? EMPTY_SELECTION_PROPAGATION }); useTreeViewSelection.getInitialState = params => ({ selection: { selectedItems: params.selectedItems === undefined ? params.defaultSelectedItems : params.selectedItems, isEnabled: !params.disableSelection, isMultiSelectEnabled: params.multiSelect, isCheckboxSelectionEnabled: params.checkboxSelection, selectionPropagation: params.selectionPropagation } }); useTreeViewSelection.params = { disableSelection: true, multiSelect: true, checkboxSelection: true, defaultSelectedItems: true, selectedItems: true, onSelectedItemsChange: true, onItemSelectionToggle: true, selectionPropagation: true };