@mui/x-tree-view
Version:
The community edition of the MUI X Tree View components.
160 lines (154 loc) • 5.17 kB
JavaScript
'use client';
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import useSlotProps from '@mui/utils/useSlotProps';
import { useStore } from '@mui/x-internals/store';
import { warnOnce } from '@mui/x-internals/warning';
import { TreeItemLoader } from "../../TreeItemLoader/index.mjs";
import { TreeItemLoaderContext } from "../../TreeItemLoader/TreeItemLoaderContext.mjs";
import { useTreeViewRootProps } from "../hooks/useTreeViewRootProps.mjs";
import { itemsSelectors } from "../plugins/items/index.mjs";
import { selectionSelectors } from "../plugins/selection/index.mjs";
import { jsx as _jsx } from "react/jsx-runtime";
export const DEFAULT_LOADING_ITEMS_COUNT = 5;
export const MAX_LOADING_ITEMS_COUNT = 100;
export function getLoadingItemsCount(itemsCount) {
if (process.env.NODE_ENV !== 'production') {
if (itemsCount != null && (!Number.isFinite(itemsCount) || itemsCount < 0)) {
warnOnce([`MUI X: The \`itemsCount\` value in \`slotProps.loading\` received an invalid value (${itemsCount}).`, 'It must be a non-negative finite number.']);
}
}
const rawCount = itemsCount ?? DEFAULT_LOADING_ITEMS_COUNT;
return Number.isFinite(rawCount) ? Math.max(1, Math.min(MAX_LOADING_ITEMS_COUNT, Math.floor(rawCount))) : DEFAULT_LOADING_ITEMS_COUNT;
}
/**
* The owner state of the `loading` slot.
*/
function RichTreeViewItemLoaderRow(props) {
const {
classes,
slots,
slotProps,
ownerState
} = props;
const ItemLoader = slots.itemLoader ?? TreeItemLoader;
const itemLoaderProps = useSlotProps({
elementType: ItemLoader,
externalSlotProps: slotProps?.itemLoader,
className: classes.itemLoader,
additionalProps: {
role: 'treeitem',
'aria-disabled': true
},
ownerState
});
return /*#__PURE__*/_jsx(ItemLoader, _extends({}, itemLoaderProps));
}
/**
* Renders the default loading rows without any wrapper.
* Used by `RichTreeViewLoading` for the whole-tree loading state and by
* `RichTreeViewItem` for the children of an item that lazily loads them.
* It must render inside a `TreeItemLoaderContext` provider.
*/
export function RichTreeViewItemLoaders(props) {
const {
classes,
slots,
slotProps,
itemsCount
} = props;
const {
itemDepth,
isCheckboxSelectionEnabled
} = React.useContext(TreeItemLoaderContext);
return /*#__PURE__*/_jsx(React.Fragment, {
children: Array.from({
length: itemsCount
}, (_, index) => /*#__PURE__*/_jsx(RichTreeViewItemLoaderRow, {
classes: classes,
slots: slots,
slotProps: slotProps,
ownerState: {
index,
itemsCount,
itemDepth,
isCheckboxSelectionEnabled
}
}, index))
});
}
/**
* Provides the layout information the loading rows need to `TreeItemLoader`.
* Wraps both the default rows and a custom `loading` slot, so custom loading
* UIs composed with `TreeItemLoader` keep the correct depth and height.
*/
export function RichTreeViewLoadingContext(props) {
const {
store,
itemDepth = 0,
children
} = props;
const itemHeight = useStore(store, itemsSelectors.itemHeight);
const isCheckboxSelectionEnabled = useStore(store, selectionSelectors.isCheckboxSelectionEnabled);
const contextValue = React.useMemo(() => ({
itemDepth,
itemHeight,
isCheckboxSelectionEnabled
}), [itemDepth, itemHeight, isCheckboxSelectionEnabled]);
return /*#__PURE__*/_jsx(TreeItemLoaderContext.Provider, {
value: contextValue,
children: children
});
}
/**
* Renders the loading placeholder shared by `RichTreeView` and `RichTreeViewPro`.
* It reuses `useTreeViewRootProps` so the root element keeps the same `role="tree"`,
* `id`, `aria-multiselectable` and slot/className behavior as the non-loading tree.
*/
export function RichTreeViewLoading(props) {
const {
store,
slots,
slotProps,
ownerState,
forwardedProps,
rootRef,
classes
} = props;
const getRootProps = useTreeViewRootProps(store, forwardedProps, rootRef);
const Root = slots.root;
const Loading = slots.loading;
const loadingProps = useSlotProps({
elementType: Loading ?? 'div',
externalSlotProps: slotProps?.loading,
ownerState: {
itemId: null
}
});
const itemsCount = getLoadingItemsCount(loadingProps.itemsCount);
const rootProps = useSlotProps({
elementType: Root,
externalSlotProps: slotProps?.root,
className: classes.root,
getSlotProps: getRootProps,
additionalProps: _extends({
'aria-busy': true
}, forwardedProps['aria-label'] == null && forwardedProps['aria-labelledby'] == null ? {
'aria-label': 'Loading'
} : {}),
ownerState
});
return /*#__PURE__*/_jsx(Root, _extends({}, rootProps, {
children: /*#__PURE__*/_jsx(RichTreeViewLoadingContext, {
store: store,
children: Loading ? /*#__PURE__*/_jsx(Loading, _extends({}, loadingProps, {
itemsCount: itemsCount
})) : /*#__PURE__*/_jsx(RichTreeViewItemLoaders, {
classes: classes,
slots: slots,
slotProps: slotProps,
itemsCount: itemsCount
})
})
}));
}