UNPKG

@mui/lab

Version:
1,045 lines (865 loc) 29.7 kB
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import * as React from 'react'; import clsx from 'clsx'; import PropTypes from 'prop-types'; import { styled, useTheme, useThemeProps } from '@mui/material/styles'; import { unstable_composeClasses as composeClasses } from '@mui/base'; import { useControlled, useForkRef, ownerDocument, unstable_useId as useId } from '@mui/material/utils'; import TreeViewContext from './TreeViewContext'; import { DescendantProvider } from './descendants'; import { getTreeViewUtilityClass } from './treeViewClasses'; import { jsx as _jsx } from "react/jsx-runtime"; var useUtilityClasses = function useUtilityClasses(ownerState) { var classes = ownerState.classes; var slots = { root: ['root'] }; return composeClasses(slots, getTreeViewUtilityClass, classes); }; var TreeViewRoot = styled('ul', { name: 'MuiTreeView', slot: 'Root', overridesResolver: function overridesResolver(props, styles) { return styles.root; } })({ padding: 0, margin: 0, listStyle: 'none', outline: 0 }); function isPrintableCharacter(string) { return string && string.length === 1 && string.match(/\S/); } function findNextFirstChar(firstChars, startIndex, char) { for (var i = startIndex; i < firstChars.length; i += 1) { if (char === firstChars[i]) { return i; } } return -1; } function noopSelection() { return false; } var defaultDefaultExpanded = []; var defaultDefaultSelected = []; var TreeView = /*#__PURE__*/React.forwardRef(function TreeView(inProps, ref) { var props = useThemeProps({ props: inProps, name: 'MuiTreeView' }); var children = props.children, className = props.className, defaultCollapseIcon = props.defaultCollapseIcon, defaultEndIcon = props.defaultEndIcon, _props$defaultExpande = props.defaultExpanded, defaultExpanded = _props$defaultExpande === void 0 ? defaultDefaultExpanded : _props$defaultExpande, defaultExpandIcon = props.defaultExpandIcon, defaultParentIcon = props.defaultParentIcon, _props$defaultSelecte = props.defaultSelected, defaultSelected = _props$defaultSelecte === void 0 ? defaultDefaultSelected : _props$defaultSelecte, _props$disabledItemsF = props.disabledItemsFocusable, disabledItemsFocusable = _props$disabledItemsF === void 0 ? false : _props$disabledItemsF, _props$disableSelecti = props.disableSelection, disableSelection = _props$disableSelecti === void 0 ? false : _props$disableSelecti, expandedProp = props.expanded, idProp = props.id, _props$multiSelect = props.multiSelect, multiSelect = _props$multiSelect === void 0 ? false : _props$multiSelect, onBlur = props.onBlur, onFocus = props.onFocus, onKeyDown = props.onKeyDown, onNodeFocus = props.onNodeFocus, onNodeSelect = props.onNodeSelect, onNodeToggle = props.onNodeToggle, selectedProp = props.selected, other = _objectWithoutProperties(props, ["children", "className", "defaultCollapseIcon", "defaultEndIcon", "defaultExpanded", "defaultExpandIcon", "defaultParentIcon", "defaultSelected", "disabledItemsFocusable", "disableSelection", "expanded", "id", "multiSelect", "onBlur", "onFocus", "onKeyDown", "onNodeFocus", "onNodeSelect", "onNodeToggle", "selected"]); var theme = useTheme(); var isRtl = theme.direction === 'rtl'; var ownerState = _extends({}, props, { defaultExpanded: defaultExpanded, defaultSelected: defaultSelected, disabledItemsFocusable: disabledItemsFocusable, disableSelection: disableSelection, multiSelect: multiSelect }); var classes = useUtilityClasses(ownerState); var treeId = useId(idProp); var treeRef = React.useRef(null); var handleRef = useForkRef(treeRef, ref); var _React$useState = React.useState(null), focusedNodeId = _React$useState[0], setFocusedNodeId = _React$useState[1]; var nodeMap = React.useRef({}); var firstCharMap = React.useRef({}); var _useControlled = useControlled({ controlled: expandedProp, default: defaultExpanded, name: 'TreeView', state: 'expanded' }), _useControlled2 = _slicedToArray(_useControlled, 2), expanded = _useControlled2[0], setExpandedState = _useControlled2[1]; var _useControlled3 = useControlled({ controlled: selectedProp, default: defaultSelected, name: 'TreeView', state: 'selected' }), _useControlled4 = _slicedToArray(_useControlled3, 2), selected = _useControlled4[0], setSelectedState = _useControlled4[1]; /* * Status Helpers */ var isExpanded = React.useCallback(function (id) { return Array.isArray(expanded) ? expanded.indexOf(id) !== -1 : false; }, [expanded]); var isExpandable = React.useCallback(function (id) { return nodeMap.current[id] && nodeMap.current[id].expandable; }, []); var isSelected = React.useCallback(function (id) { return Array.isArray(selected) ? selected.indexOf(id) !== -1 : selected === id; }, [selected]); var isDisabled = React.useCallback(function (id) { var node = nodeMap.current[id]; // This can be called before the node has been added to the node map. if (!node) { return false; } if (node.disabled) { return true; } while (node.parentId != null) { node = nodeMap.current[node.parentId]; if (node.disabled) { return true; } } return false; }, []); var isFocused = function isFocused(id) { return focusedNodeId === id; }; /* * Child Helpers */ // Using Object.keys -> .map to mimic Object.values we should replace with Object.values() once we stop IE11 support. var getChildrenIds = function getChildrenIds(id) { return Object.keys(nodeMap.current).map(function (key) { return nodeMap.current[key]; }).filter(function (node) { return node.parentId === id; }).sort(function (a, b) { return a.index - b.index; }).map(function (child) { return child.id; }); }; var getNavigableChildrenIds = function getNavigableChildrenIds(id) { var childrenIds = getChildrenIds(id); if (!disabledItemsFocusable) { childrenIds = childrenIds.filter(function (node) { return !isDisabled(node); }); } return childrenIds; }; /* * Node Helpers */ var getNextNode = function getNextNode(id) { // If expanded get first child if (isExpanded(id) && getNavigableChildrenIds(id).length > 0) { return getNavigableChildrenIds(id)[0]; } var node = nodeMap.current[id]; while (node != null) { // Try to get next sibling var siblings = getNavigableChildrenIds(node.parentId); var nextSibling = siblings[siblings.indexOf(node.id) + 1]; if (nextSibling) { return nextSibling; } // If the sibling does not exist, go up a level to the parent and try again. node = nodeMap.current[node.parentId]; } return null; }; var getPreviousNode = function getPreviousNode(id) { var node = nodeMap.current[id]; var siblings = getNavigableChildrenIds(node.parentId); var nodeIndex = siblings.indexOf(id); if (nodeIndex === 0) { return node.parentId; } var currentNode = siblings[nodeIndex - 1]; while (isExpanded(currentNode) && getNavigableChildrenIds(currentNode).length > 0) { currentNode = getNavigableChildrenIds(currentNode).pop(); } return currentNode; }; var getLastNode = function getLastNode() { var lastNode = getNavigableChildrenIds(null).pop(); while (isExpanded(lastNode)) { lastNode = getNavigableChildrenIds(lastNode).pop(); } return lastNode; }; var getFirstNode = function getFirstNode() { return getNavigableChildrenIds(null)[0]; }; var getParent = function getParent(id) { return nodeMap.current[id].parentId; }; /** * This is used to determine the start and end of a selection range so * we can get the nodes between the two border nodes. * * It finds the nodes' common ancestor using * a naive implementation of a lowest common ancestor algorithm * (https://en.wikipedia.org/wiki/Lowest_common_ancestor). * Then compares the ancestor's 2 children that are ancestors of nodeA and NodeB * so we can compare their indexes to work out which node comes first in a depth first search. * (https://en.wikipedia.org/wiki/Depth-first_search) * * Another way to put it is which node is shallower in a trémaux tree * https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree */ var findOrderInTremauxTree = function findOrderInTremauxTree(nodeAId, nodeBId) { if (nodeAId === nodeBId) { return [nodeAId, nodeBId]; } var nodeA = nodeMap.current[nodeAId]; var nodeB = nodeMap.current[nodeBId]; if (nodeA.parentId === nodeB.id || nodeB.parentId === nodeA.id) { return nodeB.parentId === nodeA.id ? [nodeA.id, nodeB.id] : [nodeB.id, nodeA.id]; } var aFamily = [nodeA.id]; var bFamily = [nodeB.id]; var aAncestor = nodeA.parentId; var bAncestor = nodeB.parentId; var aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1; var bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1; var continueA = true; var continueB = true; while (!bAncestorIsCommon && !aAncestorIsCommon) { if (continueA) { aFamily.push(aAncestor); aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1; continueA = aAncestor !== null; if (!aAncestorIsCommon && continueA) { aAncestor = nodeMap.current[aAncestor].parentId; } } if (continueB && !aAncestorIsCommon) { bFamily.push(bAncestor); bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1; continueB = bAncestor !== null; if (!bAncestorIsCommon && continueB) { bAncestor = nodeMap.current[bAncestor].parentId; } } } var commonAncestor = aAncestorIsCommon ? aAncestor : bAncestor; var ancestorFamily = getChildrenIds(commonAncestor); var aSide = aFamily[aFamily.indexOf(commonAncestor) - 1]; var bSide = bFamily[bFamily.indexOf(commonAncestor) - 1]; return ancestorFamily.indexOf(aSide) < ancestorFamily.indexOf(bSide) ? [nodeAId, nodeBId] : [nodeBId, nodeAId]; }; var getNodesInRange = function getNodesInRange(nodeA, nodeB) { var _findOrderInTremauxTr = findOrderInTremauxTree(nodeA, nodeB), _findOrderInTremauxTr2 = _slicedToArray(_findOrderInTremauxTr, 2), first = _findOrderInTremauxTr2[0], last = _findOrderInTremauxTr2[1]; var nodes = [first]; var current = first; while (current !== last) { current = getNextNode(current); nodes.push(current); } return nodes; }; /* * Focus Helpers */ var focus = function focus(event, id) { if (id) { setFocusedNodeId(id); if (onNodeFocus) { onNodeFocus(event, id); } } }; var focusNextNode = function focusNextNode(event, id) { return focus(event, getNextNode(id)); }; var focusPreviousNode = function focusPreviousNode(event, id) { return focus(event, getPreviousNode(id)); }; var focusFirstNode = function focusFirstNode(event) { return focus(event, getFirstNode()); }; var focusLastNode = function focusLastNode(event) { return focus(event, getLastNode()); }; var focusByFirstCharacter = function focusByFirstCharacter(event, id, char) { var start; var index; var lowercaseChar = char.toLowerCase(); var firstCharIds = []; var firstChars = []; // This really only works since the ids are strings Object.keys(firstCharMap.current).forEach(function (nodeId) { var firstChar = firstCharMap.current[nodeId]; var map = nodeMap.current[nodeId]; var visible = map.parentId ? isExpanded(map.parentId) : true; var shouldBeSkipped = disabledItemsFocusable ? false : isDisabled(nodeId); if (visible && !shouldBeSkipped) { firstCharIds.push(nodeId); firstChars.push(firstChar); } }); // Get start index for search based on position of currentItem start = firstCharIds.indexOf(id) + 1; if (start >= firstCharIds.length) { start = 0; } // Check remaining slots in the menu index = findNextFirstChar(firstChars, start, lowercaseChar); // If not found in remaining slots, check from beginning if (index === -1) { index = findNextFirstChar(firstChars, 0, lowercaseChar); } // If match was found... if (index > -1) { focus(event, firstCharIds[index]); } }; /* * Expansion Helpers */ var toggleExpansion = function toggleExpansion(event) { var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : focusedNodeId; var newExpanded; if (expanded.indexOf(value) !== -1) { newExpanded = expanded.filter(function (id) { return id !== value; }); } else { newExpanded = [value].concat(expanded); } if (onNodeToggle) { onNodeToggle(event, newExpanded); } setExpandedState(newExpanded); }; var expandAllSiblings = function expandAllSiblings(event, id) { var map = nodeMap.current[id]; var siblings = getChildrenIds(map.parentId); var diff = siblings.filter(function (child) { return isExpandable(child) && !isExpanded(child); }); var newExpanded = expanded.concat(diff); if (diff.length > 0) { setExpandedState(newExpanded); if (onNodeToggle) { onNodeToggle(event, newExpanded); } } }; /* * Selection Helpers */ var lastSelectedNode = React.useRef(null); var lastSelectionWasRange = React.useRef(false); var currentRangeSelection = React.useRef([]); var handleRangeArrowSelect = function handleRangeArrowSelect(event, nodes) { var base = selected.slice(); var start = nodes.start, next = nodes.next, current = nodes.current; if (!next || !current) { return; } if (currentRangeSelection.current.indexOf(current) === -1) { currentRangeSelection.current = []; } if (lastSelectionWasRange.current) { if (currentRangeSelection.current.indexOf(next) !== -1) { base = base.filter(function (id) { return id === start || id !== current; }); currentRangeSelection.current = currentRangeSelection.current.filter(function (id) { return id === start || id !== current; }); } else { base.push(next); currentRangeSelection.current.push(next); } } else { base.push(next); currentRangeSelection.current.push(current, next); } if (onNodeSelect) { onNodeSelect(event, base); } setSelectedState(base); }; var handleRangeSelect = function handleRangeSelect(event, nodes) { var base = selected.slice(); var start = nodes.start, end = nodes.end; // If last selection was a range selection ignore nodes that were selected. if (lastSelectionWasRange.current) { base = base.filter(function (id) { return currentRangeSelection.current.indexOf(id) === -1; }); } var range = getNodesInRange(start, end); range = range.filter(function (node) { return !isDisabled(node); }); currentRangeSelection.current = range; var newSelected = base.concat(range); newSelected = newSelected.filter(function (id, i) { return newSelected.indexOf(id) === i; }); if (onNodeSelect) { onNodeSelect(event, newSelected); } setSelectedState(newSelected); }; var handleMultipleSelect = function handleMultipleSelect(event, value) { var newSelected; if (selected.indexOf(value) !== -1) { newSelected = selected.filter(function (id) { return id !== value; }); } else { newSelected = [value].concat(selected); } if (onNodeSelect) { onNodeSelect(event, newSelected); } setSelectedState(newSelected); }; var handleSingleSelect = function handleSingleSelect(event, value) { var newSelected = multiSelect ? [value] : value; if (onNodeSelect) { onNodeSelect(event, newSelected); } setSelectedState(newSelected); }; var selectNode = function selectNode(event, id) { var multiple = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (id) { if (multiple) { handleMultipleSelect(event, id); } else { handleSingleSelect(event, id); } lastSelectedNode.current = id; lastSelectionWasRange.current = false; currentRangeSelection.current = []; return true; } return false; }; var selectRange = function selectRange(event, nodes) { var stacked = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var _nodes$start = nodes.start, start = _nodes$start === void 0 ? lastSelectedNode.current : _nodes$start, end = nodes.end, current = nodes.current; if (stacked) { handleRangeArrowSelect(event, { start: start, next: end, current: current }); } else if (start != null && end != null) { handleRangeSelect(event, { start: start, end: end }); } lastSelectionWasRange.current = true; }; var rangeSelectToFirst = function rangeSelectToFirst(event, id) { if (!lastSelectedNode.current) { lastSelectedNode.current = id; } var start = lastSelectionWasRange.current ? lastSelectedNode.current : id; selectRange(event, { start: start, end: getFirstNode() }); }; var rangeSelectToLast = function rangeSelectToLast(event, id) { if (!lastSelectedNode.current) { lastSelectedNode.current = id; } var start = lastSelectionWasRange.current ? lastSelectedNode.current : id; selectRange(event, { start: start, end: getLastNode() }); }; var selectNextNode = function selectNextNode(event, id) { if (!isDisabled(getNextNode(id))) { selectRange(event, { end: getNextNode(id), current: id }, true); } }; var selectPreviousNode = function selectPreviousNode(event, id) { if (!isDisabled(getPreviousNode(id))) { selectRange(event, { end: getPreviousNode(id), current: id }, true); } }; var selectAllNodes = function selectAllNodes(event) { selectRange(event, { start: getFirstNode(), end: getLastNode() }); }; /* * Mapping Helpers */ var registerNode = React.useCallback(function (node) { var id = node.id, index = node.index, parentId = node.parentId, expandable = node.expandable, idAttribute = node.idAttribute, disabled = node.disabled; nodeMap.current[id] = { id: id, index: index, parentId: parentId, expandable: expandable, idAttribute: idAttribute, disabled: disabled }; }, []); var unregisterNode = React.useCallback(function (id) { var newMap = _extends({}, nodeMap.current); delete newMap[id]; nodeMap.current = newMap; setFocusedNodeId(function (oldFocusedNodeId) { if (oldFocusedNodeId === id && treeRef.current === ownerDocument(treeRef.current).activeElement) { return getChildrenIds(null)[0]; } return oldFocusedNodeId; }); }, []); var mapFirstChar = React.useCallback(function (id, firstChar) { firstCharMap.current[id] = firstChar; }, []); var unMapFirstChar = React.useCallback(function (id) { var newMap = _extends({}, firstCharMap.current); delete newMap[id]; firstCharMap.current = newMap; }, []); /** * Event handlers and Navigation */ var handleNextArrow = function handleNextArrow(event) { if (isExpandable(focusedNodeId)) { if (isExpanded(focusedNodeId)) { focusNextNode(event, focusedNodeId); } else if (!isDisabled(focusedNodeId)) { toggleExpansion(event); } } return true; }; var handlePreviousArrow = function handlePreviousArrow(event) { if (isExpanded(focusedNodeId) && !isDisabled(focusedNodeId)) { toggleExpansion(event, focusedNodeId); return true; } var parent = getParent(focusedNodeId); if (parent) { focus(event, parent); return true; } return false; }; var handleKeyDown = function handleKeyDown(event) { var flag = false; var key = event.key; // If the tree is empty there will be no focused node if (event.altKey || event.currentTarget !== event.target || !focusedNodeId) { return; } var ctrlPressed = event.ctrlKey || event.metaKey; switch (key) { case ' ': if (!disableSelection && !isDisabled(focusedNodeId)) { if (multiSelect && event.shiftKey) { selectRange(event, { end: focusedNodeId }); flag = true; } else if (multiSelect) { flag = selectNode(event, focusedNodeId, true); } else { flag = selectNode(event, focusedNodeId); } } event.stopPropagation(); break; case 'Enter': if (!isDisabled(focusedNodeId)) { if (isExpandable(focusedNodeId)) { toggleExpansion(event); flag = true; } else if (multiSelect) { flag = selectNode(event, focusedNodeId, true); } else { flag = selectNode(event, focusedNodeId); } } event.stopPropagation(); break; case 'ArrowDown': if (multiSelect && event.shiftKey && !disableSelection) { selectNextNode(event, focusedNodeId); } focusNextNode(event, focusedNodeId); flag = true; break; case 'ArrowUp': if (multiSelect && event.shiftKey && !disableSelection) { selectPreviousNode(event, focusedNodeId); } focusPreviousNode(event, focusedNodeId); flag = true; break; case 'ArrowRight': if (isRtl) { flag = handlePreviousArrow(event); } else { flag = handleNextArrow(event); } break; case 'ArrowLeft': if (isRtl) { flag = handleNextArrow(event); } else { flag = handlePreviousArrow(event); } break; case 'Home': if (multiSelect && ctrlPressed && event.shiftKey && !disableSelection && !isDisabled(focusedNodeId)) { rangeSelectToFirst(event, focusedNodeId); } focusFirstNode(event); flag = true; break; case 'End': if (multiSelect && ctrlPressed && event.shiftKey && !disableSelection && !isDisabled(focusedNodeId)) { rangeSelectToLast(event, focusedNodeId); } focusLastNode(event); flag = true; break; default: if (key === '*') { expandAllSiblings(event, focusedNodeId); flag = true; } else if (multiSelect && ctrlPressed && key.toLowerCase() === 'a' && !disableSelection) { selectAllNodes(event); flag = true; } else if (!ctrlPressed && !event.shiftKey && isPrintableCharacter(key)) { focusByFirstCharacter(event, focusedNodeId, key); flag = true; } } if (flag) { event.preventDefault(); event.stopPropagation(); } if (onKeyDown) { onKeyDown(event); } }; var handleFocus = function handleFocus(event) { // if the event bubbled (which is React specific) we don't want to steal focus if (event.target === event.currentTarget) { var firstSelected = Array.isArray(selected) ? selected[0] : selected; focus(event, firstSelected || getNavigableChildrenIds(null)[0]); } if (onFocus) { onFocus(event); } }; var handleBlur = function handleBlur(event) { setFocusedNodeId(null); if (onBlur) { onBlur(event); } }; var activeDescendant = nodeMap.current[focusedNodeId] ? nodeMap.current[focusedNodeId].idAttribute : null; return /*#__PURE__*/_jsx(TreeViewContext.Provider, { value: { icons: { defaultCollapseIcon: defaultCollapseIcon, defaultExpandIcon: defaultExpandIcon, defaultParentIcon: defaultParentIcon, defaultEndIcon: defaultEndIcon }, focus: focus, toggleExpansion: toggleExpansion, isExpanded: isExpanded, isExpandable: isExpandable, isFocused: isFocused, isSelected: isSelected, isDisabled: isDisabled, selectNode: disableSelection ? noopSelection : selectNode, selectRange: disableSelection ? noopSelection : selectRange, multiSelect: multiSelect, disabledItemsFocusable: disabledItemsFocusable, mapFirstChar: mapFirstChar, unMapFirstChar: unMapFirstChar, registerNode: registerNode, unregisterNode: unregisterNode, treeId: treeId }, children: /*#__PURE__*/_jsx(DescendantProvider, { children: /*#__PURE__*/_jsx(TreeViewRoot, _extends({ role: "tree", id: treeId, "aria-activedescendant": activeDescendant, "aria-multiselectable": multiSelect, className: clsx(classes.root, className), ref: handleRef, tabIndex: 0, onKeyDown: handleKeyDown, onFocus: handleFocus, onBlur: handleBlur, ownerState: ownerState }, other, { children: children })) }) }); }); process.env.NODE_ENV !== "production" ? TreeView.propTypes /* remove-proptypes */ = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the d.ts file and run "yarn proptypes" | // ---------------------------------------------------------------------- /** * The content of the component. */ children: PropTypes.node, /** * Override or extend the styles applied to the component. */ classes: PropTypes.object, /** * @ignore */ className: PropTypes.string, /** * The default icon used to collapse the node. */ defaultCollapseIcon: PropTypes.node, /** * The default icon displayed next to a end node. This is applied to all * tree nodes and can be overridden by the TreeItem `icon` prop. */ defaultEndIcon: PropTypes.node, /** * Expanded node ids. (Uncontrolled) * @default [] */ defaultExpanded: PropTypes.arrayOf(PropTypes.string), /** * The default icon used to expand the node. */ defaultExpandIcon: PropTypes.node, /** * The default icon displayed next to a parent node. This is applied to all * parent nodes and can be overridden by the TreeItem `icon` prop. */ defaultParentIcon: PropTypes.node, /** * Selected node ids. (Uncontrolled) * When `multiSelect` is true this takes an array of strings; when false (default) a string. * @default [] */ defaultSelected: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.string]), /** * If `true`, will allow focus on disabled items. * @default false */ disabledItemsFocusable: PropTypes.bool, /** * If `true` selection is disabled. * @default false */ disableSelection: PropTypes.bool, /** * Expanded node ids. (Controlled) */ expanded: PropTypes.arrayOf(PropTypes.string), /** * This prop is used to help implement the accessibility logic. * If you don't provide this prop. It falls back to a randomly generated id. */ id: PropTypes.string, /** * If true `ctrl` and `shift` will trigger multiselect. * @default false */ multiSelect: PropTypes.bool, /** * @ignore */ onBlur: PropTypes.func, /** * @ignore */ onFocus: PropTypes.func, /** * @ignore */ onKeyDown: PropTypes.func, /** * Callback fired when tree items are focused. * * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event. * @param {string} value of the focused node. */ onNodeFocus: PropTypes.func, /** * Callback fired when tree items are selected/unselected. * * @param {React.SyntheticEvent} event The event source of the callback * @param {string[] | string} nodeIds Ids of the selected nodes. When `multiSelect` is true * this is an array of strings; when false (default) a string. */ onNodeSelect: PropTypes.func, /** * Callback fired when tree items are expanded/collapsed. * * @param {React.SyntheticEvent} event The event source of the callback. * @param {array} nodeIds The ids of the expanded nodes. */ onNodeToggle: PropTypes.func, /** * Selected node ids. (Controlled) * When `multiSelect` is true this takes an array of strings; when false (default) a string. */ selected: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.string]), /** * The system prop that allows defining system overrides as well as additional CSS styles. */ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]) } : void 0; export default TreeView;