UNPKG

@mui/x-data-grid-pro

Version:

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

289 lines (287 loc) 13.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.GridHeaderFilterCell = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var React = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _clsx = _interopRequireDefault(require("clsx")); var _utils = require("@mui/utils"); var _fastMemo = require("@mui/x-internals/fastMemo"); var _xDataGrid = require("@mui/x-data-grid"); var _internals = require("@mui/x-data-grid/internals"); var _RtlProvider = require("@mui/system/RtlProvider"); var _forwardRef = require("@mui/x-internals/forwardRef"); var _useGridRootProps = require("../../hooks/utils/useGridRootProps"); var _GridHeaderFilterMenuContainer = require("./GridHeaderFilterMenuContainer"); var _GridHeaderFilterClearButton = require("./GridHeaderFilterClearButton"); var _jsxRuntime = require("react/jsx-runtime"); const _excluded = ["colIndex", "height", "hasFocus", "width", "headerClassName", "colDef", "item", "headerFilterMenuRef", "InputComponentProps", "showClearIcon", "pinnedPosition", "pinnedOffset", "style", "showLeftBorder", "showRightBorder"]; const useUtilityClasses = ownerState => { const { colDef, classes, showRightBorder, showLeftBorder, pinnedPosition } = ownerState; const slots = { root: ['columnHeader', colDef.headerAlign === 'left' && 'columnHeader--alignLeft', colDef.headerAlign === 'center' && 'columnHeader--alignCenter', colDef.headerAlign === 'right' && 'columnHeader--alignRight', 'withBorderColor', showRightBorder && 'columnHeader--withRightBorder', showLeftBorder && 'columnHeader--withLeftBorder', pinnedPosition === _internals.PinnedColumnPosition.LEFT && 'columnHeader--pinnedLeft', pinnedPosition === _internals.PinnedColumnPosition.RIGHT && 'columnHeader--pinnedRight'] }; return (0, _utils.unstable_composeClasses)(slots, _xDataGrid.getDataGridUtilityClass, classes); }; const emptyFieldSx = { [`& input[value=""]:not(:focus)`]: { color: 'transparent' } }; const defaultInputComponents = { string: _xDataGrid.GridFilterInputValue, number: _xDataGrid.GridFilterInputValue, date: _xDataGrid.GridFilterInputDate, dateTime: _xDataGrid.GridFilterInputDate, boolean: _xDataGrid.GridFilterInputBoolean, singleSelect: _xDataGrid.GridFilterInputSingleSelect, actions: null, custom: null }; const GridHeaderFilterCell = (0, _forwardRef.forwardRef)((props, ref) => { const { colIndex, height, hasFocus, width, headerClassName, colDef, item, headerFilterMenuRef, InputComponentProps, showClearIcon = true, pinnedPosition, pinnedOffset, style: styleProp, showLeftBorder, showRightBorder } = props, other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded); const apiRef = (0, _internals.useGridPrivateApiContext)(); const isRtl = (0, _RtlProvider.useRtl)(); const columnFields = (0, _xDataGrid.useGridSelector)(apiRef, _xDataGrid.gridVisibleColumnFieldsSelector); const rootProps = (0, _useGridRootProps.useGridRootProps)(); const cellRef = React.useRef(null); const handleRef = (0, _utils.unstable_useForkRef)(ref, cellRef); const inputRef = React.useRef(null); const buttonRef = React.useRef(null); const editingField = (0, _xDataGrid.useGridSelector)(apiRef, _internals.gridHeaderFilteringEditFieldSelector); const isEditing = editingField === colDef.field; const menuOpenField = (0, _xDataGrid.useGridSelector)(apiRef, _internals.gridHeaderFilteringMenuSelector); const isMenuOpen = menuOpenField === colDef.field; // TODO: Support for `isAnyOf` operator const filterOperators = React.useMemo(() => { if (!colDef.filterOperators) { return []; } return colDef.filterOperators.filter(operator => operator.value !== 'isAnyOf'); }, [colDef.filterOperators]); const filterModel = (0, _xDataGrid.useGridSelector)(apiRef, _xDataGrid.gridFilterModelSelector); const filterableColumnsLookup = (0, _xDataGrid.useGridSelector)(apiRef, _xDataGrid.gridFilterableColumnLookupSelector); const isFilterReadOnly = React.useMemo(() => { if (!filterModel?.items.length) { return false; } const filterModelItem = filterModel.items.find(it => it.field === colDef.field); return filterModelItem ? !filterableColumnsLookup[filterModelItem.field] : false; }, [colDef.field, filterModel, filterableColumnsLookup]); const currentOperator = React.useMemo(() => filterOperators.find(operator => operator.value === item.operator) ?? filterOperators[0], [item.operator, filterOperators]); const InputComponent = colDef.filterable || isFilterReadOnly ? currentOperator.InputComponent ?? defaultInputComponents[colDef.type] : null; const clearFilterItem = React.useCallback(() => { apiRef.current.deleteFilterItem(item); }, [apiRef, item]); let headerFilterComponent; if (colDef.renderHeaderFilter) { headerFilterComponent = colDef.renderHeaderFilter((0, _extends2.default)({}, props, { inputRef })); } React.useLayoutEffect(() => { if (hasFocus && !isMenuOpen) { let focusableElement = cellRef.current.querySelector('[tabindex="0"]'); if (isEditing && InputComponent) { focusableElement = inputRef.current; } const elementToFocus = focusableElement || cellRef.current; elementToFocus?.focus(); if (apiRef.current.columnHeadersContainerRef.current) { apiRef.current.columnHeadersContainerRef.current.scrollLeft = 0; } } }, [InputComponent, apiRef, hasFocus, isEditing, isMenuOpen]); const onKeyDown = React.useCallback(event => { if (isMenuOpen || (0, _internals.isNavigationKey)(event.key) || isFilterReadOnly) { return; } switch (event.key) { case 'Escape': if (isEditing) { apiRef.current.stopHeaderFilterEditMode(); } break; case 'Enter': if (isEditing) { if (!event.defaultPrevented) { apiRef.current.stopHeaderFilterEditMode(); break; } } if (event.metaKey || event.ctrlKey) { headerFilterMenuRef.current = buttonRef.current; apiRef.current.showHeaderFilterMenu(colDef.field); break; } apiRef.current.startHeaderFilterEditMode(colDef.field); break; case 'Tab': { if (isEditing) { const fieldToFocus = columnFields[colIndex + (event.shiftKey ? -1 : 1)] ?? null; if (fieldToFocus) { apiRef.current.startHeaderFilterEditMode(fieldToFocus); apiRef.current.setColumnHeaderFilterFocus(fieldToFocus, event); } } break; } default: if (isEditing || event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) { break; } apiRef.current.startHeaderFilterEditMode(colDef.field); break; } }, [apiRef, colDef.field, colIndex, columnFields, headerFilterMenuRef, isEditing, isFilterReadOnly, isMenuOpen]); const publish = React.useCallback((eventName, propHandler) => event => { apiRef.current.publishEvent(eventName, apiRef.current.getColumnHeaderParams(colDef.field), event); if (propHandler) { propHandler(event); } }, [apiRef, colDef.field]); const onMouseDown = React.useCallback(event => { if (!hasFocus) { if (inputRef.current?.contains?.(event.target)) { inputRef.current.focus(); } apiRef.current.setColumnHeaderFilterFocus(colDef.field, event); } }, [apiRef, colDef.field, hasFocus]); const mouseEventsHandlers = React.useMemo(() => ({ onKeyDown: publish('headerFilterKeyDown', onKeyDown), onClick: publish('headerFilterClick'), onMouseDown: publish('headerFilterMouseDown', onMouseDown), onBlur: publish('headerFilterBlur') }), [onMouseDown, onKeyDown, publish]); const ownerState = (0, _extends2.default)({}, rootProps, { pinnedPosition, colDef, showLeftBorder, showRightBorder }); const classes = useUtilityClasses(ownerState); const isNoInputOperator = currentOperator.requiresFilterValue === false; const isApplied = item?.value !== undefined || isNoInputOperator; const label = currentOperator.headerLabel ?? apiRef.current.getLocaleText(`headerFilterOperator${(0, _utils.unstable_capitalize)(item.operator)}`); const isFilterActive = isApplied || hasFocus; return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", (0, _extends2.default)({ className: (0, _clsx.default)(classes.root, headerClassName), style: (0, _internals.attachPinnedStyle)((0, _extends2.default)({ height, width }, styleProp), isRtl, pinnedPosition, pinnedOffset), role: "columnheader", "aria-colindex": colIndex + 1, "aria-label": headerFilterComponent == null ? colDef.headerName ?? colDef.field : undefined }, other, mouseEventsHandlers, { ref: handleRef, children: [headerFilterComponent, InputComponent && headerFilterComponent === undefined ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(React.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(InputComponent, (0, _extends2.default)({ apiRef: apiRef, item: item, inputRef: inputRef, applyValue: apiRef.current.upsertFilterItem, onFocus: () => apiRef.current.startHeaderFilterEditMode(colDef.field), onBlur: event => { apiRef.current.stopHeaderFilterEditMode(); // Blurring an input element should reset focus state only if `relatedTarget` is not the header filter cell if (!event.relatedTarget?.className.includes('columnHeader')) { apiRef.current.setState(state => (0, _extends2.default)({}, state, { focus: { cell: null, columnHeader: null, columnHeaderFilter: null, columnGroupHeader: null } })); } }, label: (0, _utils.unstable_capitalize)(label), placeholder: "", isFilterActive: isFilterActive, clearButton: showClearIcon && isApplied ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridHeaderFilterClearButton.GridHeaderFilterClearButton, { onClick: clearFilterItem, disabled: isFilterReadOnly }) : null, disabled: isFilterReadOnly || isNoInputOperator, tabIndex: -1, InputLabelProps: null, sx: colDef.type === 'date' || colDef.type === 'dateTime' || colDef.type === 'number' ? emptyFieldSx : undefined }, isNoInputOperator ? { value: '' } : {}, currentOperator?.InputComponentProps, InputComponentProps)), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridHeaderFilterMenuContainer.GridHeaderFilterMenuContainer, { operators: filterOperators, item: item, field: colDef.field, disabled: isFilterReadOnly, applyFilterChanges: apiRef.current.upsertFilterItem, headerFilterMenuRef: headerFilterMenuRef, buttonRef: buttonRef })] }) : null] })); }); process.env.NODE_ENV !== "production" ? GridHeaderFilterCell.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- colDef: _propTypes.default.object.isRequired, colIndex: _propTypes.default.number.isRequired, hasFocus: _propTypes.default.bool, /** * Class name added to the column header cell. */ headerClassName: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.string]), headerFilterMenuRef: _propTypes.default.shape({ current: _propTypes.default.object }).isRequired, height: _propTypes.default.number.isRequired, InputComponentProps: _propTypes.default.object, item: _propTypes.default.shape({ field: _propTypes.default.string.isRequired, id: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]), operator: _propTypes.default.string.isRequired, value: _propTypes.default.any }).isRequired, pinnedOffset: _propTypes.default.number, pinnedPosition: _propTypes.default.oneOf([0, 1, 2, 3]), showClearIcon: _propTypes.default.bool, showLeftBorder: _propTypes.default.bool.isRequired, showRightBorder: _propTypes.default.bool.isRequired, sortIndex: _propTypes.default.number, style: _propTypes.default.object, tabIndex: _propTypes.default.oneOf([-1, 0]).isRequired, width: _propTypes.default.number.isRequired } : void 0; const Memoized = exports.GridHeaderFilterCell = (0, _fastMemo.fastMemo)(GridHeaderFilterCell);