@mui/x-data-grid
Version:
The Community plan edition of the Data Grid components (MUI X).
196 lines (192 loc) • 8.38 kB
JavaScript
"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.QuickFilter = QuickFilter;
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 _utils = require("@mui/utils");
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
var _useId = _interopRequireDefault(require("@mui/utils/useId"));
var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
var _QuickFilterContext = require("./QuickFilterContext");
var _useGridComponentRenderer = require("../../hooks/utils/useGridComponentRenderer");
var _useGridApiContext = require("../../hooks/utils/useGridApiContext");
var _useGridSelector = require("../../hooks/utils/useGridSelector");
var _filter = require("../../hooks/features/filter");
var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
var _jsxRuntime = require("react/jsx-runtime");
const _excluded = ["render", "className", "parser", "formatter", "debounceMs", "defaultExpanded", "expanded", "onExpandedChange"];
const DEFAULT_PARSER = searchText => searchText.split(' ').filter(word => word !== '');
const DEFAULT_FORMATTER = values => values.join(' ');
/**
* The top level Quick Filter component that provides context to child components.
* It renders a `<div />` element.
*
* Demos:
*
* - [Quick Filter](https://mui.com/x/react-data-grid/components/quick-filter/)
*
* API:
*
* - [QuickFilter API](https://mui.com/x/api/data-grid/quick-filter/)
*/
function QuickFilter(props) {
const rootProps = (0, _useGridRootProps.useGridRootProps)();
const {
render,
className,
parser = DEFAULT_PARSER,
formatter = DEFAULT_FORMATTER,
debounceMs = rootProps.filterDebounceMs,
defaultExpanded,
expanded,
onExpandedChange
} = props,
other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
const apiRef = (0, _useGridApiContext.useGridApiContext)();
const controlRef = React.useRef(null);
const triggerRef = React.useRef(null);
const quickFilterValues = (0, _useGridSelector.useGridSelector)(apiRef, _filter.gridQuickFilterValuesSelector);
const [value, setValue] = React.useState(formatter(quickFilterValues ?? []));
const [internalExpanded, setInternalExpanded] = React.useState(defaultExpanded ?? value.length > 0);
const expandedValue = expanded ?? internalExpanded;
const state = React.useMemo(() => ({
value,
expanded: expandedValue
}), [value, expandedValue]);
const resolvedClassName = typeof className === 'function' ? className(state) : className;
const ref = React.useRef(null);
const controlId = (0, _useId.default)();
const handleExpandedChange = React.useCallback(newExpanded => {
if (onExpandedChange) {
onExpandedChange(newExpanded);
}
if (expanded === undefined) {
setInternalExpanded(newExpanded);
}
}, [onExpandedChange, expanded]);
const prevQuickFilterValuesRef = React.useRef(quickFilterValues);
React.useEffect(() => {
if (!(0, _isDeepEqual.isDeepEqual)(prevQuickFilterValuesRef.current, quickFilterValues)) {
// The model of quick filter value has been updated
prevQuickFilterValuesRef.current = quickFilterValues;
// Update the input value if needed to match the new model
setValue(prevSearchValue => (0, _isDeepEqual.isDeepEqual)(parser(prevSearchValue), quickFilterValues) ? prevSearchValue : formatter(quickFilterValues ?? []));
}
}, [quickFilterValues, formatter, parser]);
const isFirstRender = React.useRef(true);
const previousExpandedValue = React.useRef(expandedValue);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
// Ensure the expanded state has actually changed before focusing
if (previousExpandedValue.current !== expandedValue) {
if (expandedValue) {
// Ensures the focus does not interupt CSS transitions and animations on the control
requestAnimationFrame(() => {
controlRef.current?.focus({
preventScroll: true
});
});
} else {
triggerRef.current?.focus({
preventScroll: true
});
}
previousExpandedValue.current = expandedValue;
}
}, [expandedValue]);
const setQuickFilterValueDebounced = React.useMemo(() => (0, _utils.unstable_debounce)(newValue => {
const newQuickFilterValues = parser(newValue);
prevQuickFilterValuesRef.current = newQuickFilterValues;
apiRef.current.setQuickFilterValues(newQuickFilterValues);
}, debounceMs), [apiRef, debounceMs, parser]);
React.useEffect(() => setQuickFilterValueDebounced.clear, [setQuickFilterValueDebounced]);
const handleValueChange = React.useCallback(event => {
const newValue = event.target.value;
setValue(newValue);
setQuickFilterValueDebounced(newValue);
}, [setQuickFilterValueDebounced]);
const handleClearValue = React.useCallback(() => {
setValue('');
apiRef.current.setQuickFilterValues([]);
controlRef.current?.focus();
}, [apiRef, controlRef]);
const contextValue = React.useMemo(() => ({
controlRef,
triggerRef,
state,
controlId,
clearValue: handleClearValue,
onValueChange: handleValueChange,
onExpandedChange: handleExpandedChange
}), [controlId, state, handleValueChange, handleClearValue, handleExpandedChange]);
(0, _useEnhancedEffect.default)(() => {
if (ref.current && triggerRef.current) {
ref.current.style.setProperty('--trigger-width', `${triggerRef.current?.offsetWidth}px`);
}
}, []);
const element = (0, _useGridComponentRenderer.useGridComponentRenderer)('div', render, (0, _extends2.default)({
className: resolvedClassName
}, other, {
ref
}), state);
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_QuickFilterContext.QuickFilterContext.Provider, {
value: contextValue,
children: element
});
}
process.env.NODE_ENV !== "production" ? QuickFilter.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "pnpm proptypes" |
// ----------------------------------------------------------------------
/**
* Override or extend the styles applied to the component.
*/
className: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.string]),
/**
* The debounce time in milliseconds.
* @default 150
*/
debounceMs: _propTypes.default.number,
/**
* The default expanded state of the quick filter control.
* @default false
*/
defaultExpanded: _propTypes.default.bool,
/**
* The expanded state of the quick filter control.
*/
expanded: _propTypes.default.bool,
/**
* Function responsible for formatting values of quick filter in a string when the model is modified
* @param {any[]} values The new values passed to the quick filter model
* @returns {string} The string to display in the text field
* @default (values: string[]) => values.join(' ')
*/
formatter: _propTypes.default.func,
/**
* Callback function that is called when the quick filter input is expanded or collapsed.
* @param {boolean} expanded The new expanded state of the quick filter control
*/
onExpandedChange: _propTypes.default.func,
/**
* Function responsible for parsing text input in an array of independent values for quick filtering.
* @param {string} input The value entered by the user
* @returns {any[]} The array of value on which quick filter is applied
* @default (searchText: string) => searchText.split(' ').filter((word) => word !== '')
*/
parser: _propTypes.default.func,
/**
* A function to customize rendering of the component.
*/
render: _propTypes.default.oneOfType([_propTypes.default.element, _propTypes.default.func])
} : void 0;