UNPKG

@mui/x-data-grid-pro

Version:

The Pro plan edition of the MUI X Data Grid components.

177 lines (172 loc) 8.05 kB
"use strict"; 'use client'; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.MultiSelectChipsRoot = exports.GridMultiSelectChips = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var React = _interopRequireWildcard(require("react")); var _clsx = _interopRequireDefault(require("clsx")); var _styles = require("@mui/material/styles"); var _useForkRef = _interopRequireDefault(require("@mui/utils/useForkRef")); var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect")); var _xDataGrid = require("@mui/x-data-grid"); var _internals = require("@mui/x-data-grid/internals"); var _multiSelectCellUtils = require("../../utils/multiSelectCellUtils"); var _useGridPrivateApiContext = require("../../hooks/utils/useGridPrivateApiContext"); var _jsxRuntime = require("react/jsx-runtime"); const _excluded = ["values", "field", "columnWidth", "optionByValue", "getOptionLabel", "autoWrap", "classes", "slotProps"]; const MultiSelectChipsRoot = exports.MultiSelectChipsRoot = (0, _styles.styled)('div', { name: 'MuiDataGrid', slot: 'MultiSelectChips', shouldForwardProp: prop => prop !== 'ownerState' })({ display: 'flex', alignItems: 'center', width: '100%', height: '100%', gap: 4, overflow: 'hidden', position: 'relative' }); const Chip = (0, _styles.styled)(_internals.NotRendered, { name: 'MuiDataGrid', slot: 'MultiSelectChip' })({ [`&.${_xDataGrid.gridClasses['multiSelectCellChip--hidden']}`]: { display: 'none' } }); // Delay before revealing all chips on resize start, so a quick double-click (autosize) — which // toggles the resizing state in short bursts — doesn't flash every chip. const RESIZE_REVEAL_DELAY_MS = 150; function GridMultiSelectChipsImpl(props, ref) { const { values, field, columnWidth, optionByValue, getOptionLabel, autoWrap, classes, slotProps } = props, other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded); const rootProps = (0, _xDataGrid.useGridRootProps)(); const privateApiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)(); const ownerState = rootProps; const containerRef = React.useRef(null); const handleRef = (0, _useForkRef.default)(containerRef, ref); const chipsRef = React.useRef(new Map()); const chipWidthsRef = React.useRef(new Map()); const [measuredCount, setMeasuredCount] = React.useState(0); const [containerWidth, setContainerWidth] = React.useState(null); const subscribeMetrics = React.useCallback(notify => { const cache = privateApiRef.current.caches.multiSelect; if (!cache) { return () => {}; } return cache.subscribeOverflowMetrics(notify); }, [privateApiRef]); const getMetricsSnapshot = React.useCallback(() => privateApiRef.current.caches.multiSelect?.getOverflowMetrics() ?? null, [privateApiRef]); const overflowMetrics = (0, _internals.useSyncExternalStore)(subscribeMetrics, getMetricsSnapshot, getMetricsSnapshot); const arrayKey = React.useMemo(() => values.join('\0'), [values]); const [prevArrayKey, setPrevArrayKey] = React.useState(arrayKey); if (!autoWrap && prevArrayKey !== arrayKey) { setPrevArrayKey(arrayKey); chipWidthsRef.current.clear(); setMeasuredCount(0); setContainerWidth(null); } // Re-measure on committed column width changes (incl. when a resize finishes); we don't // track live drag, matching how other cells reflow only once the resize is committed. (0, _useEnhancedEffect.default)(() => { if (autoWrap || !containerRef.current) { return; } setContainerWidth(containerRef.current.getBoundingClientRect().width); }, [columnWidth, autoWrap]); // Measure chip and container widths after render. `getBoundingClientRect` is sub-pixel, // which keeps the chip-fit math aligned with the browser's actual layout. (0, _useEnhancedEffect.default)(() => { if (autoWrap) { return; } if (containerWidth === null && containerRef.current) { setContainerWidth(containerRef.current.getBoundingClientRect().width); } let newMeasurements = 0; chipsRef.current.forEach((chipEl, index) => { if (chipEl && !chipWidthsRef.current.has(index)) { chipWidthsRef.current.set(index, chipEl.getBoundingClientRect().width); newMeasurements += 1; } }); if (newMeasurements > 0) { setMeasuredCount(chipWidthsRef.current.size); } }, [containerWidth, autoWrap]); const overflowWidths = overflowMetrics?.overflowChipWidths ?? _multiSelectCellUtils.DEFAULT_OVERFLOW_CHIP_WIDTHS; const gap = overflowMetrics?.gap ?? _multiSelectCellUtils.DEFAULT_GAP; // While this column is being drag-resized, render every chip and let the cell clip them. // The `+N` overflow is recomputed once the resize is committed (see the `columnWidth` effect). const isResizingThisColumn = (0, _xDataGrid.useGridSelector)(privateApiRef, _xDataGrid.gridResizingColumnFieldSelector) === field; // Debounce the reveal so a quick double-click to autosize doesn't flash all chips. const revealTimeout = (0, _internals.useTimeout)(); const [revealWhileResizing, setRevealWhileResizing] = React.useState(false); React.useEffect(() => { if (!isResizingThisColumn) { revealTimeout.clear(); setRevealWhileResizing(false); return; } revealTimeout.start(RESIZE_REVEAL_DELAY_MS, () => setRevealWhileResizing(true)); }, [isResizingThisColumn, revealTimeout]); const visibleCount = React.useMemo(() => { if (autoWrap || revealWhileResizing || values.length === 0) { return values.length; } if (containerWidth === null || containerWidth === 0 || measuredCount < values.length) { return values.length; } return (0, _multiSelectCellUtils.calculateVisibleCount)(values.length, containerWidth, chipWidthsRef.current, overflowWidths, gap); }, [values.length, measuredCount, containerWidth, autoWrap, revealWhileResizing, overflowWidths, gap]); const hiddenCount = values.length - visibleCount; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(MultiSelectChipsRoot, (0, _extends2.default)({ ref: handleRef, ownerState: ownerState }, other, slotProps?.root, { className: (0, _clsx.default)(classes?.root, other?.className, slotProps?.root?.className), children: [values.map((v, index) => { const option = optionByValue.get(v) ?? v; const chipProps = typeof slotProps?.chip === 'function' ? slotProps.chip(option, index) : slotProps?.chip; return /*#__PURE__*/(0, _jsxRuntime.jsx)(Chip, (0, _extends2.default)({ as: rootProps.slots.baseChip, ownerState: ownerState, ref: el => { if (el) { chipsRef.current.set(index, el); } else { chipsRef.current.delete(index); } }, label: getOptionLabel(option), size: "small", variant: "outlined" }, chipProps, { className: (0, _clsx.default)(classes?.chip, chipProps?.className, index >= visibleCount && [_xDataGrid.gridClasses['multiSelectCellChip--hidden'], classes?.chipHidden]) }), index); }), hiddenCount > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.baseChip, (0, _extends2.default)({ label: `+${hiddenCount}`, size: "small", variant: "outlined" }, slotProps?.overflow, { className: (0, _clsx.default)(classes?.overflow, slotProps?.overflow?.className) }))] })); } const GridMultiSelectChips = exports.GridMultiSelectChips = /*#__PURE__*/React.forwardRef(GridMultiSelectChipsImpl); if (process.env.NODE_ENV !== "production") GridMultiSelectChips.displayName = "GridMultiSelectChips";