@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
272 lines (268 loc) • 11.5 kB
JavaScript
;
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useTreeItem = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _store = require("@mui/x-internals/store");
var _extractEventHandlers = _interopRequireDefault(require("@mui/utils/extractEventHandlers"));
var _useMergedRefs = require("@base-ui/utils/useMergedRefs");
var _TreeViewProvider = require("../internals/TreeViewProvider");
var _useTreeItemUtils = require("../hooks/useTreeItemUtils");
var _TreeViewItemDepthContext = require("../internals/TreeViewItemDepthContext");
var _tree = require("../internals/utils/tree");
var _focus = require("../internals/plugins/focus");
var _items = require("../internals/plugins/items");
var _id = require("../internals/plugins/id");
var _expansion = require("../internals/plugins/expansion");
var _selection = require("../internals/plugins/selection");
// TODO v8: Remove the lazy loading plugin from the typing on the community useTreeItem and ask users to pass the TStore generic.
const depthSelector = (state, itemId, depthContext) => {
if (typeof depthContext === 'function') {
return depthContext(state, itemId);
}
return depthContext;
};
const useTreeItem = parameters => {
const {
runItemPlugins,
publicAPI,
store
} = (0, _TreeViewProvider.useTreeViewContext)();
const depthContext = React.useContext(_TreeViewItemDepthContext.TreeViewItemDepthContext);
const depth = (0, _store.useStore)(store, depthSelector, parameters.itemId, depthContext);
const {
id,
itemId,
label,
children,
rootRef
} = parameters;
const {
rootRef: pluginRootRef,
contentRef,
propsEnhancers
} = runItemPlugins(parameters);
const {
interactions,
status
} = (0, _useTreeItemUtils.useTreeItemUtils)({
itemId,
children
});
const rootRefObject = React.useRef(null);
const contentRefObject = React.useRef(null);
const handleRootRef = (0, _useMergedRefs.useMergedRefs)(rootRef, pluginRootRef, rootRefObject);
const handleContentRef = (0, _useMergedRefs.useMergedRefs)(contentRef, contentRefObject);
const checkboxRef = React.useRef(null);
const isCheckboxSelectionEnabled = (0, _store.useStore)(store, _selection.selectionSelectors.isCheckboxSelectionEnabled);
const idAttribute = (0, _store.useStore)(store, _id.idSelectors.treeItemIdAttribute, itemId, id);
const shouldBeAccessibleWithTab = (0, _store.useStore)(store, _focus.focusSelectors.isItemTheDefaultFocusableItem, itemId);
const sharedPropsEnhancerParams = {
rootRefObject,
contentRefObject,
interactions
};
const createRootHandleFocus = otherHandlers => event => {
otherHandlers.onFocus?.(event);
if (event.defaultMuiPrevented) {
return;
}
if (!status.focused && _items.itemsSelectors.canItemBeFocused(store.state, itemId) && event.currentTarget === event.target) {
store.focus.focusItem(event, itemId);
}
};
const createRootHandleBlur = otherHandlers => event => {
otherHandlers.onBlur?.(event);
if (event.defaultMuiPrevented) {
return;
}
const rootElement = store.items.getItemDOMElement(itemId);
// Don't blur the root when switching to editing mode
// the input that triggers the root blur can be either the relatedTarget (when entering editing state) or the target (when exiting editing state)
// when we enter the editing state, we focus the input -> we don't want to remove the focused item from the state
if (status.editing ||
// we can exit the editing state by clicking outside the input (within the Tree Item) or by pressing Enter or Escape -> we don't want to remove the focused item from the state in these cases
// we can also exit the editing state by clicking on the root itself -> want to remove the focused item from the state in this case
event.relatedTarget && (0, _tree.isTargetInDescendants)(event.relatedTarget, rootElement) && (event.target && event.target?.dataset?.element === 'labelInput' && (0, _tree.isTargetInDescendants)(event.target, rootElement) || event.relatedTarget?.dataset?.element === 'labelInput')) {
return;
}
store.focus.removeFocusedItem();
};
const createRootHandleKeyDown = otherHandlers => event => {
otherHandlers.onKeyDown?.(event);
if (event.defaultMuiPrevented || event.target?.dataset?.element === 'labelInput') {
return;
}
store.keyboardNavigation.handleItemKeyDown(event, itemId);
};
const createLabelHandleDoubleClick = otherHandlers => event => {
otherHandlers.onDoubleClick?.(event);
if (event.defaultMuiPrevented) {
return;
}
interactions.toggleItemEditing();
};
const createContentHandleClick = otherHandlers => event => {
otherHandlers.onClick?.(event);
store.items.handleItemClick(event, itemId);
if (event.defaultMuiPrevented || checkboxRef.current?.contains(event.target)) {
return;
}
if (_expansion.expansionSelectors.triggerSlot(store.state) === 'content') {
interactions.handleExpansion(event);
}
if (!isCheckboxSelectionEnabled) {
interactions.handleSelection(event);
}
};
const createContentHandleMouseDown = otherHandlers => event => {
otherHandlers.onMouseDown?.(event);
if (event.defaultMuiPrevented) {
return;
}
// Prevent text selection
if (event.shiftKey || event.ctrlKey || event.metaKey || status.disabled) {
event.preventDefault();
}
};
const createIconContainerHandleClick = otherHandlers => event => {
otherHandlers.onClick?.(event);
if (event.defaultMuiPrevented) {
return;
}
if (_expansion.expansionSelectors.triggerSlot(store.state) === 'iconContainer') {
interactions.handleExpansion(event);
}
};
const getContextProviderProps = () => ({
itemId,
id
});
const getRootProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extends2.default)({}, (0, _extractEventHandlers.default)(parameters), (0, _extractEventHandlers.default)(externalProps));
const props = (0, _extends2.default)({}, externalEventHandlers, {
ref: handleRootRef,
role: 'treeitem',
tabIndex: shouldBeAccessibleWithTab ? 0 : -1,
id: idAttribute,
'aria-expanded': status.expandable ? status.expanded : undefined,
'aria-disabled': status.disabled || undefined
}, externalProps, {
style: (0, _extends2.default)({}, externalProps.style ?? {}, {
'--TreeView-itemDepth': depth
}),
onFocus: createRootHandleFocus(externalEventHandlers),
onBlur: createRootHandleBlur(externalEventHandlers),
onKeyDown: createRootHandleKeyDown(externalEventHandlers)
});
const enhancedRootProps = propsEnhancers.root?.((0, _extends2.default)({}, sharedPropsEnhancerParams, {
externalEventHandlers
})) ?? {};
return (0, _extends2.default)({}, props, enhancedRootProps);
};
const getContentProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
const props = (0, _extends2.default)({}, externalEventHandlers, externalProps, {
ref: handleContentRef,
onClick: createContentHandleClick(externalEventHandlers),
onMouseDown: createContentHandleMouseDown(externalEventHandlers),
status
});
['expanded', 'selected', 'focused', 'disabled', 'editing', 'editable'].forEach(key => {
if (status[key]) {
props[`data-${key}`] = '';
}
});
const enhancedContentProps = propsEnhancers.content?.((0, _extends2.default)({}, sharedPropsEnhancerParams, {
externalEventHandlers
})) ?? {};
return (0, _extends2.default)({}, props, enhancedContentProps);
};
const getCheckboxProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
const props = (0, _extends2.default)({}, externalEventHandlers, {
ref: checkboxRef,
'aria-hidden': true
}, externalProps);
const enhancedCheckboxProps = propsEnhancers.checkbox?.((0, _extends2.default)({}, sharedPropsEnhancerParams, {
externalEventHandlers
})) ?? {};
return (0, _extends2.default)({}, props, enhancedCheckboxProps);
};
const getLabelProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extends2.default)({}, (0, _extractEventHandlers.default)(externalProps));
const props = (0, _extends2.default)({}, externalEventHandlers, {
children: label
}, externalProps, {
onDoubleClick: createLabelHandleDoubleClick(externalEventHandlers)
});
const enhancedLabelProps = propsEnhancers.label?.((0, _extends2.default)({}, sharedPropsEnhancerParams, {
externalEventHandlers
})) ?? {};
return (0, _extends2.default)({}, enhancedLabelProps, props);
};
const getLabelInputProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
const enhancedLabelInputProps = propsEnhancers.labelInput?.((0, _extends2.default)({}, sharedPropsEnhancerParams, {
externalEventHandlers
})) ?? {};
return (0, _extends2.default)({}, externalProps, enhancedLabelInputProps);
};
const getIconContainerProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
return (0, _extends2.default)({}, externalEventHandlers, externalProps, {
onClick: createIconContainerHandleClick(externalEventHandlers)
});
};
const getErrorContainerProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
return (0, _extends2.default)({}, externalEventHandlers, externalProps);
};
const getLoadingContainerProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
return (0, _extends2.default)({
size: '12px',
thickness: 6
}, externalEventHandlers, externalProps);
};
const getGroupTransitionProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
const response = (0, _extends2.default)({}, externalEventHandlers, {
unmountOnExit: true,
component: 'ul',
role: 'group',
in: status.expanded,
children
}, externalProps);
return response;
};
const getDragAndDropOverlayProps = (externalProps = {}) => {
const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
const enhancedDragAndDropOverlayProps = propsEnhancers.dragAndDropOverlay?.((0, _extends2.default)({}, sharedPropsEnhancerParams, {
externalEventHandlers
})) ?? {};
return (0, _extends2.default)({}, externalProps, enhancedDragAndDropOverlayProps);
};
return {
getContextProviderProps,
getRootProps,
getContentProps,
getGroupTransitionProps,
getIconContainerProps,
getCheckboxProps,
getLabelProps,
getLabelInputProps,
getDragAndDropOverlayProps,
getErrorContainerProps,
getLoadingContainerProps,
rootRef: handleRootRef,
status,
publicAPI
};
};
exports.useTreeItem = useTreeItem;