wip:milestone 0 fixes
Some checks failed
CI/CD Pipeline / unit-tests (push) Failing after 1m16s
CI/CD Pipeline / integration-tests (push) Failing after 2m32s
CI/CD Pipeline / lint (push) Successful in 5m22s
CI/CD Pipeline / e2e-tests (push) Has been skipped
CI/CD Pipeline / build (push) Has been skipped

This commit is contained in:
2026-03-15 12:35:42 +02:00
parent 6708cf28a7
commit cffdf8af86
61266 changed files with 4511646 additions and 1938 deletions

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridPipeProcessingApi = require("./gridPipeProcessingApi");
Object.keys(_gridPipeProcessingApi).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridPipeProcessingApi[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridPipeProcessingApi[key];
}
});
});
var _useGridPipeProcessing = require("./useGridPipeProcessing");
Object.keys(_useGridPipeProcessing).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _useGridPipeProcessing[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _useGridPipeProcessing[key];
}
});
});
var _useGridRegisterPipeProcessor = require("./useGridRegisterPipeProcessor");
Object.keys(_useGridRegisterPipeProcessor).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _useGridRegisterPipeProcessor[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _useGridRegisterPipeProcessor[key];
}
});
});
var _useGridRegisterPipeApplier = require("./useGridRegisterPipeApplier");
Object.keys(_useGridRegisterPipeApplier).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _useGridRegisterPipeApplier[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _useGridRegisterPipeApplier[key];
}
});
});

View File

@@ -0,0 +1,115 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridPipeProcessing = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _toPropertyKey2 = _interopRequireDefault(require("@babel/runtime/helpers/toPropertyKey"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* Implement the Pipeline Pattern
*
* More information and detailed example in (TODO add link to technical doc when ready)
*
* Some plugins contains custom logic to enrich data provided by other plugins or components.
* For instance, the row grouping plugin needs to add / remove the grouping columns when the grid columns are updated.
*
* =====================================================================================================================
*
* The plugin containing the custom logic must use:
*
* - `useGridRegisterPipeProcessor` to register their processor.
*
* - `apiRef.current.requestPipeProcessorsApplication` to imperatively re-apply a group.
* This method should be used in last resort.
* Most of the time, the application should be triggered by an update on the deps of the processor.
*
* =====================================================================================================================
*
* The plugin or component that needs to enrich its data must use:
*
* - `apiRef.current.unstable_applyPipeProcessors` to run in chain all the processors of a given group.
*
* - `useGridRegisterPipeApplier` to re-apply the whole pipe when requested.
* The applier will be called when:
* * a processor is registered.
* * `apiRef.current.requestPipeProcessorsApplication` is called for the given group.
*/
const useGridPipeProcessing = apiRef => {
const processorsCache = React.useRef({});
const isRunning = React.useRef(false);
const runAppliers = React.useCallback(groupCache => {
if (isRunning.current || !groupCache) {
return;
}
isRunning.current = true;
Object.values(groupCache.appliers).forEach(callback => {
callback();
});
isRunning.current = false;
}, []);
const registerPipeProcessor = React.useCallback((group, id, processor) => {
if (!processorsCache.current[group]) {
processorsCache.current[group] = {
processors: new Map(),
appliers: {}
};
}
const groupCache = processorsCache.current[group];
const oldProcessor = groupCache.processors.get(id);
if (oldProcessor !== processor) {
groupCache.processors.set(id, processor);
runAppliers(groupCache);
}
return () => {
processorsCache.current[group].processors.set(id, null);
};
}, [runAppliers]);
const registerPipeApplier = React.useCallback((group, id, applier) => {
if (!processorsCache.current[group]) {
processorsCache.current[group] = {
processors: new Map(),
appliers: {}
};
}
processorsCache.current[group].appliers[id] = applier;
return () => {
const _appliers = processorsCache.current[group].appliers,
otherAppliers = (0, _objectWithoutPropertiesLoose2.default)(_appliers, [id].map(_toPropertyKey2.default));
processorsCache.current[group].appliers = otherAppliers;
};
}, []);
const requestPipeProcessorsApplication = React.useCallback(group => {
const groupCache = processorsCache.current[group];
runAppliers(groupCache);
}, [runAppliers]);
const applyPipeProcessors = React.useCallback((...args) => {
const [group, value, context] = args;
if (!processorsCache.current[group]) {
return value;
}
const preProcessors = Array.from(processorsCache.current[group].processors.values());
return preProcessors.reduce((acc, preProcessor) => {
if (!preProcessor) {
return acc;
}
return preProcessor(acc, context);
}, value);
}, []);
const preProcessingPrivateApi = {
registerPipeProcessor,
registerPipeApplier,
requestPipeProcessorsApplication
};
const preProcessingPublicApi = {
unstable_applyPipeProcessors: applyPipeProcessors
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, preProcessingPrivateApi, 'private');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, preProcessingPublicApi, 'public');
};
exports.useGridPipeProcessing = useGridPipeProcessing;

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRegisterPipeApplier = void 0;
var React = _interopRequireWildcard(require("react"));
var _useFirstRender = require("../../utils/useFirstRender");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridRegisterPipeApplier = (apiRef, group, callback) => {
const cleanup = React.useRef();
const id = React.useRef(`mui-${Math.round(Math.random() * 1e9)}`);
const registerPreProcessor = React.useCallback(() => {
cleanup.current = apiRef.current.registerPipeApplier(group, id.current, callback);
}, [apiRef, callback, group]);
(0, _useFirstRender.useFirstRender)(() => {
registerPreProcessor();
});
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
} else {
registerPreProcessor();
}
return () => {
if (cleanup.current) {
cleanup.current();
cleanup.current = null;
}
};
}, [registerPreProcessor]);
};
exports.useGridRegisterPipeApplier = useGridRegisterPipeApplier;

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRegisterPipeProcessor = void 0;
var React = _interopRequireWildcard(require("react"));
var _useFirstRender = require("../../utils/useFirstRender");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridRegisterPipeProcessor = (apiRef, group, callback) => {
const cleanup = React.useRef();
const id = React.useRef(`mui-${Math.round(Math.random() * 1e9)}`);
const registerPreProcessor = React.useCallback(() => {
cleanup.current = apiRef.current.registerPipeProcessor(group, id.current, callback);
}, [apiRef, callback, group]);
(0, _useFirstRender.useFirstRender)(() => {
registerPreProcessor();
});
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
} else {
registerPreProcessor();
}
return () => {
if (cleanup.current) {
cleanup.current();
cleanup.current = null;
}
};
}, [registerPreProcessor]);
};
exports.useGridRegisterPipeProcessor = useGridRegisterPipeProcessor;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridStrategyProcessingApi = require("./gridStrategyProcessingApi");
Object.keys(_gridStrategyProcessingApi).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridStrategyProcessingApi[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridStrategyProcessingApi[key];
}
});
});
var _useGridRegisterStrategyProcessor = require("./useGridRegisterStrategyProcessor");
Object.keys(_useGridRegisterStrategyProcessor).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _useGridRegisterStrategyProcessor[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _useGridRegisterStrategyProcessor[key];
}
});
});
var _useGridStrategyProcessing = require("./useGridStrategyProcessing");
Object.keys(_useGridStrategyProcessing).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _useGridStrategyProcessing[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _useGridStrategyProcessing[key];
}
});
});

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRegisterStrategyProcessor = void 0;
var React = _interopRequireWildcard(require("react"));
var _useFirstRender = require("../../utils/useFirstRender");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridRegisterStrategyProcessor = (apiRef, strategyName, group, processor) => {
const registerPreProcessor = React.useCallback(() => {
apiRef.current.registerStrategyProcessor(strategyName, group, processor);
}, [apiRef, processor, group, strategyName]);
(0, _useFirstRender.useFirstRender)(() => {
registerPreProcessor();
});
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
} else {
registerPreProcessor();
}
}, [registerPreProcessor]);
};
exports.useGridRegisterStrategyProcessor = useGridRegisterStrategyProcessor;

View File

@@ -0,0 +1,121 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridStrategyProcessing = exports.GRID_STRATEGIES_PROCESSORS = exports.GRID_DEFAULT_STRATEGY = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _toPropertyKey2 = _interopRequireDefault(require("@babel/runtime/helpers/toPropertyKey"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const GRID_DEFAULT_STRATEGY = exports.GRID_DEFAULT_STRATEGY = 'none';
const GRID_STRATEGIES_PROCESSORS = exports.GRID_STRATEGIES_PROCESSORS = {
rowTreeCreation: 'rowTree',
filtering: 'rowTree',
sorting: 'rowTree',
visibleRowsLookupCreation: 'rowTree'
};
/**
* Implements a variant of the Strategy Pattern (see https://en.wikipedia.org/wiki/Strategy_pattern)
*
* More information and detailed example in (TODO add link to technical doc when ready)
*
* Some plugins contains custom logic that must only be applied if the right strategy is active.
* For instance, the row grouping plugin has a custom filtering algorithm.
* This algorithm must be applied by the filtering plugin if the row grouping is the current way of grouping rows,
* but not if the tree data is the current way of grouping rows.
*
* =====================================================================================================================
*
* The plugin containing the custom logic must use:
*
* - `useGridRegisterStrategyProcessor` to register their processor.
* When the processor of the active strategy changes, it will fire `"activeStrategyProcessorChange"` to re-apply the processor.
*
* - `apiRef.current.setStrategyAvailability` to tell if their strategy can be used.
*
* =====================================================================================================================
*
* The plugin or component that needs to apply the custom logic of the current strategy must use:
*
* - `apiRef.current.applyStrategyProcessor` to run the processor of the active strategy for a given processor name.
*
* - the "strategyAvailabilityChange" event to update something when the active strategy changes.
* Warning: Be careful not to apply the processor several times.
* For instance "rowsSet" is fired by `useGridRows` whenever the active strategy changes.
* So listening to both would most likely run your logic twice.
*
* - The "activeStrategyProcessorChange" event to update something when the processor of the active strategy changes.
*
* =====================================================================================================================
*
* Each processor name is part of a strategy group which can only have one active strategy at the time.
* For now, there is only one strategy group named `rowTree` which customize
* - row tree creation algorithm.
* - sorting algorithm.
* - filtering algorithm.
*/
const useGridStrategyProcessing = apiRef => {
const availableStrategies = React.useRef(new Map());
const strategiesCache = React.useRef({});
const registerStrategyProcessor = React.useCallback((strategyName, processorName, processor) => {
const cleanup = () => {
const _ref = strategiesCache.current[processorName],
otherProcessors = (0, _objectWithoutPropertiesLoose2.default)(_ref, [strategyName].map(_toPropertyKey2.default));
strategiesCache.current[processorName] = otherProcessors;
};
if (!strategiesCache.current[processorName]) {
strategiesCache.current[processorName] = {};
}
const groupPreProcessors = strategiesCache.current[processorName];
const previousProcessor = groupPreProcessors[strategyName];
groupPreProcessors[strategyName] = processor;
if (!previousProcessor || previousProcessor === processor) {
return cleanup;
}
if (strategyName === apiRef.current.getActiveStrategy(GRID_STRATEGIES_PROCESSORS[processorName])) {
apiRef.current.publishEvent('activeStrategyProcessorChange', processorName);
}
return cleanup;
}, [apiRef]);
const applyStrategyProcessor = React.useCallback((processorName, params) => {
const activeStrategy = apiRef.current.getActiveStrategy(GRID_STRATEGIES_PROCESSORS[processorName]);
if (activeStrategy == null) {
throw new Error("Can't apply a strategy processor before defining an active strategy");
}
const groupCache = strategiesCache.current[processorName];
if (!groupCache || !groupCache[activeStrategy]) {
throw new Error(`No processor found for processor "${processorName}" on strategy "${activeStrategy}"`);
}
const processor = groupCache[activeStrategy];
return processor(params);
}, [apiRef]);
const getActiveStrategy = React.useCallback(strategyGroup => {
const strategyEntries = Array.from(availableStrategies.current.entries());
const availableStrategyEntry = strategyEntries.find(([, strategy]) => {
if (strategy.group !== strategyGroup) {
return false;
}
return strategy.isAvailable();
});
return availableStrategyEntry?.[0] ?? GRID_DEFAULT_STRATEGY;
}, []);
const setStrategyAvailability = React.useCallback((strategyGroup, strategyName, isAvailable) => {
availableStrategies.current.set(strategyName, {
group: strategyGroup,
isAvailable
});
apiRef.current.publishEvent('strategyAvailabilityChange');
}, [apiRef]);
const strategyProcessingApi = {
registerStrategyProcessor,
applyStrategyProcessor,
getActiveStrategy,
setStrategyAvailability
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, strategyProcessingApi, 'private');
};
exports.useGridStrategyProcessing = useGridStrategyProcessing;

View File

@@ -0,0 +1,118 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.unwrapPrivateAPI = unwrapPrivateAPI;
exports.useGridApiInitialization = useGridApiInitialization;
var React = _interopRequireWildcard(require("react"));
var _Store = require("../../utils/Store");
var _useGridApiMethod = require("../utils/useGridApiMethod");
var _useGridApiEventHandler = require("../utils/useGridApiEventHandler");
var _EventManager = require("../../utils/EventManager");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const SYMBOL_API_PRIVATE = Symbol('mui.api_private');
const isSyntheticEvent = event => {
return event.isPropagationStopped !== undefined;
};
function unwrapPrivateAPI(publicApi) {
return publicApi[SYMBOL_API_PRIVATE];
}
let globalId = 0;
function createPrivateAPI(publicApiRef) {
const existingPrivateApi = publicApiRef.current?.[SYMBOL_API_PRIVATE];
if (existingPrivateApi) {
return existingPrivateApi;
}
const state = {};
const privateApi = {
state,
store: _Store.Store.create(state),
instanceId: {
id: globalId
}
};
globalId += 1;
privateApi.getPublicApi = () => publicApiRef.current;
privateApi.register = (visibility, methods) => {
Object.keys(methods).forEach(methodName => {
const method = methods[methodName];
const currentPrivateMethod = privateApi[methodName];
if (currentPrivateMethod?.spying === true) {
currentPrivateMethod.target = method;
} else {
privateApi[methodName] = method;
}
if (visibility === 'public') {
const publicApi = publicApiRef.current;
const currentPublicMethod = publicApi[methodName];
if (currentPublicMethod?.spying === true) {
currentPublicMethod.target = method;
} else {
publicApi[methodName] = method;
}
}
});
};
privateApi.register('private', {
caches: {},
eventManager: new _EventManager.EventManager()
});
return privateApi;
}
function createPublicAPI(privateApiRef) {
const publicApi = {
get state() {
return privateApiRef.current.state;
},
get store() {
return privateApiRef.current.store;
},
get instanceId() {
return privateApiRef.current.instanceId;
},
[SYMBOL_API_PRIVATE]: privateApiRef.current
};
return publicApi;
}
function useGridApiInitialization(inputApiRef, props) {
const publicApiRef = React.useRef();
const privateApiRef = React.useRef();
if (!privateApiRef.current) {
privateApiRef.current = createPrivateAPI(publicApiRef);
}
if (!publicApiRef.current) {
publicApiRef.current = createPublicAPI(privateApiRef);
}
const publishEvent = React.useCallback((...args) => {
const [name, params, event = {}] = args;
event.defaultMuiPrevented = false;
if (isSyntheticEvent(event) && event.isPropagationStopped()) {
return;
}
const details = props.signature === _useGridApiEventHandler.GridSignature.DataGridPro ? {
api: privateApiRef.current.getPublicApi()
} : {};
privateApiRef.current.eventManager.emit(name, params, event, details);
}, [privateApiRef, props.signature]);
const subscribeEvent = React.useCallback((event, handler, options) => {
privateApiRef.current.eventManager.on(event, handler, options);
const api = privateApiRef.current;
return () => {
api.eventManager.removeListener(event, handler);
};
}, [privateApiRef]);
(0, _useGridApiMethod.useGridApiMethod)(privateApiRef, {
subscribeEvent,
publishEvent
}, 'public');
React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
React.useEffect(() => {
const api = privateApiRef.current;
return () => {
api.publishEvent('unmount');
};
}, [privateApiRef]);
return privateApiRef;
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridInitialization = void 0;
var _useGridLoggerFactory = require("./useGridLoggerFactory");
var _useGridApiInitialization = require("./useGridApiInitialization");
var _useGridLocaleText = require("./useGridLocaleText");
var _pipeProcessing = require("./pipeProcessing");
var _strategyProcessing = require("./strategyProcessing");
var _useGridStateInitialization = require("./useGridStateInitialization");
/**
* Initialize the technical pieces of the DataGrid (logger, state, ...) that any DataGrid implementation needs
*/
const useGridInitialization = (inputApiRef, props) => {
const privateApiRef = (0, _useGridApiInitialization.useGridApiInitialization)(inputApiRef, props);
(0, _useGridLoggerFactory.useGridLoggerFactory)(privateApiRef, props);
(0, _useGridStateInitialization.useGridStateInitialization)(privateApiRef, props);
(0, _pipeProcessing.useGridPipeProcessing)(privateApiRef);
(0, _strategyProcessing.useGridStrategyProcessing)(privateApiRef);
(0, _useGridLocaleText.useGridLocaleText)(privateApiRef, props);
privateApiRef.current.register('private', {
rootProps: props
});
return privateApiRef;
};
exports.useGridInitialization = useGridInitialization;

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridLocaleText = void 0;
var React = _interopRequireWildcard(require("react"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridLocaleText = (apiRef, props) => {
const getLocaleText = React.useCallback(key => {
if (props.localeText[key] == null) {
throw new Error(`Missing translation for key ${key}.`);
}
return props.localeText[key];
}, [props.localeText]);
apiRef.current.register('public', {
getLocaleText
});
};
exports.useGridLocaleText = useGridLocaleText;

View File

@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridLoggerFactory = void 0;
var React = _interopRequireWildcard(require("react"));
var _utils = require("../../utils/utils");
var _utils2 = require("../utils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const forceDebug = (0, _utils.localStorageAvailable)() && window.localStorage.getItem('DEBUG') != null;
const noop = () => {};
const noopLogger = {
debug: noop,
info: noop,
warn: noop,
error: noop
};
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
function getAppender(name, logLevel, appender = console) {
const minLogLevelIdx = LOG_LEVELS.indexOf(logLevel);
if (minLogLevelIdx === -1) {
throw new Error(`MUI: Log level ${logLevel} not recognized.`);
}
const logger = LOG_LEVELS.reduce((loggerObj, method, idx) => {
if (idx >= minLogLevelIdx) {
loggerObj[method] = (...args) => {
const [message, ...other] = args;
appender[method](`MUI: ${name} - ${message}`, ...other);
};
} else {
loggerObj[method] = noop;
}
return loggerObj;
}, {});
return logger;
}
const useGridLoggerFactory = (apiRef, props) => {
const getLogger = React.useCallback(name => {
if (forceDebug) {
return getAppender(name, 'debug', props.logger);
}
if (!props.logLevel) {
return noopLogger;
}
return getAppender(name, props.logLevel.toString(), props.logger);
}, [props.logLevel, props.logger]);
(0, _utils2.useGridApiMethod)(apiRef, {
getLogger
}, 'private');
};
exports.useGridLoggerFactory = useGridLoggerFactory;

View File

@@ -0,0 +1,109 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridStateInitialization = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiEventHandler = require("../utils/useGridApiEventHandler");
var _utils = require("../utils");
var _utils2 = require("../../utils/utils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridStateInitialization = (apiRef, props) => {
const controlStateMapRef = React.useRef({});
const [, rawForceUpdate] = React.useState();
const registerControlState = React.useCallback(controlStateItem => {
controlStateMapRef.current[controlStateItem.stateId] = controlStateItem;
}, []);
const setState = React.useCallback((state, reason) => {
let newState;
if ((0, _utils2.isFunction)(state)) {
newState = state(apiRef.current.state);
} else {
newState = state;
}
if (apiRef.current.state === newState) {
return false;
}
let ignoreSetState = false;
// Apply the control state constraints
const updatedControlStateIds = [];
Object.keys(controlStateMapRef.current).forEach(stateId => {
const controlState = controlStateMapRef.current[stateId];
const oldSubState = controlState.stateSelector(apiRef.current.state, apiRef.current.instanceId);
const newSubState = controlState.stateSelector(newState, apiRef.current.instanceId);
if (newSubState === oldSubState) {
return;
}
updatedControlStateIds.push({
stateId: controlState.stateId,
hasPropChanged: newSubState !== controlState.propModel
});
// The state is controlled, the prop should always win
if (controlState.propModel !== undefined && newSubState !== controlState.propModel) {
ignoreSetState = true;
}
});
if (updatedControlStateIds.length > 1) {
// Each hook modify its own state, and it should not leak
// Events are here to forward to other hooks and apply changes.
// You are trying to update several states in a no isolated way.
throw new Error(`You're not allowed to update several sub-state in one transaction. You already updated ${updatedControlStateIds[0].stateId}, therefore, you're not allowed to update ${updatedControlStateIds.map(el => el.stateId).join(', ')} in the same transaction.`);
}
if (!ignoreSetState) {
// We always assign it as we mutate rows for perf reason.
apiRef.current.state = newState;
if (apiRef.current.publishEvent) {
apiRef.current.publishEvent('stateChange', newState);
}
apiRef.current.store.update(newState);
}
if (updatedControlStateIds.length === 1) {
const {
stateId,
hasPropChanged
} = updatedControlStateIds[0];
const controlState = controlStateMapRef.current[stateId];
const model = controlState.stateSelector(newState, apiRef.current.instanceId);
if (controlState.propOnChange && hasPropChanged) {
const details = props.signature === _useGridApiEventHandler.GridSignature.DataGridPro ? {
api: apiRef.current,
reason
} : {
reason
};
controlState.propOnChange(model, details);
}
if (!ignoreSetState) {
apiRef.current.publishEvent(controlState.changeEvent, model, {
reason
});
}
}
return !ignoreSetState;
}, [apiRef, props.signature]);
const updateControlState = React.useCallback((key, state, reason) => {
return apiRef.current.setState(previousState => {
return (0, _extends2.default)({}, previousState, {
[key]: state(previousState[key])
});
}, reason);
}, [apiRef]);
const forceUpdate = React.useCallback(() => rawForceUpdate(() => apiRef.current.state), [apiRef]);
const publicStateApi = {
setState,
forceUpdate
};
const privateStateApi = {
updateControlState,
registerControlState
};
(0, _utils.useGridApiMethod)(apiRef, publicStateApi, 'public');
(0, _utils.useGridApiMethod)(apiRef, privateStateApi, 'private');
};
exports.useGridStateInitialization = useGridStateInitialization;

View File

@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridClipboard = void 0;
var React = _interopRequireWildcard(require("react"));
var _utils = require("../../utils");
var _gridFocusStateSelector = require("../focus/gridFocusStateSelector");
var _csvSerializer = require("../export/serializers/csvSerializer");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function writeToClipboardPolyfill(data) {
const span = document.createElement('span');
span.style.whiteSpace = 'pre';
span.style.userSelect = 'all';
span.style.opacity = '0px';
span.textContent = data;
document.body.appendChild(span);
const range = document.createRange();
range.selectNode(span);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
try {
document.execCommand('copy');
} finally {
document.body.removeChild(span);
}
}
function copyToClipboard(data) {
if (navigator.clipboard) {
navigator.clipboard.writeText(data).catch(() => {
writeToClipboardPolyfill(data);
});
} else {
writeToClipboardPolyfill(data);
}
}
function hasNativeSelection(element) {
// When getSelection is called on an <iframe> that is not displayed Firefox will return null.
if (window.getSelection()?.toString()) {
return true;
}
// window.getSelection() returns an empty string in Firefox for selections inside a form element.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=85686.
// Instead, we can use element.selectionStart that is only defined on form elements.
if (element && (element.selectionEnd || 0) - (element.selectionStart || 0) > 0) {
return true;
}
return false;
}
/**
* @requires useGridCsvExport (method)
* @requires useGridSelection (method)
*/
const useGridClipboard = (apiRef, props) => {
const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp?.clipboardExport : ignoreValueFormatterProp) || false;
const clipboardCopyCellDelimiter = props.clipboardCopyCellDelimiter;
const handleCopy = React.useCallback(event => {
if (!((event.ctrlKey || event.metaKey) && event.key === 'c')) {
return;
}
// Do nothing if there's a native selection
if (hasNativeSelection(event.target)) {
return;
}
let textToCopy = '';
const selectedRows = apiRef.current.getSelectedRows();
if (selectedRows.size > 0) {
textToCopy = apiRef.current.getDataAsCsv({
includeHeaders: false,
delimiter: clipboardCopyCellDelimiter,
shouldAppendQuotes: false,
escapeFormulas: false
});
} else {
const focusedCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (focusedCell) {
const cellParams = apiRef.current.getCellParams(focusedCell.id, focusedCell.field);
textToCopy = (0, _csvSerializer.serializeCellValue)(cellParams, {
csvOptions: {
delimiter: clipboardCopyCellDelimiter,
shouldAppendQuotes: false,
escapeFormulas: false
},
ignoreValueFormatter
});
}
}
textToCopy = apiRef.current.unstable_applyPipeProcessors('clipboardCopy', textToCopy);
if (textToCopy) {
copyToClipboard(textToCopy);
apiRef.current.publishEvent('clipboardCopy', textToCopy);
}
}, [apiRef, ignoreValueFormatter, clipboardCopyCellDelimiter]);
(0, _utils.useGridNativeEventListener)(apiRef, apiRef.current.rootElementRef, 'keydown', handleCopy);
(0, _utils.useGridApiOptionHandler)(apiRef, 'clipboardCopy', props.onClipboardCopy);
};
exports.useGridClipboard = useGridClipboard;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridColumnGroupsUnwrappedModelSelector = exports.gridColumnGroupsLookupSelector = exports.gridColumnGroupsHeaderStructureSelector = exports.gridColumnGroupsHeaderMaxDepthSelector = exports.gridColumnGroupingSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
/**
* @category ColumnGrouping
* @ignore - do not document.
*/
const gridColumnGroupingSelector = state => state.columnGrouping;
exports.gridColumnGroupingSelector = gridColumnGroupingSelector;
const gridColumnGroupsUnwrappedModelSelector = exports.gridColumnGroupsUnwrappedModelSelector = (0, _createSelector.createSelectorMemoized)(gridColumnGroupingSelector, columnGrouping => columnGrouping?.unwrappedGroupingModel ?? {});
const gridColumnGroupsLookupSelector = exports.gridColumnGroupsLookupSelector = (0, _createSelector.createSelectorMemoized)(gridColumnGroupingSelector, columnGrouping => columnGrouping?.lookup ?? {});
const gridColumnGroupsHeaderStructureSelector = exports.gridColumnGroupsHeaderStructureSelector = (0, _createSelector.createSelectorMemoized)(gridColumnGroupingSelector, columnGrouping => columnGrouping?.headerStructure ?? []);
const gridColumnGroupsHeaderMaxDepthSelector = exports.gridColumnGroupsHeaderMaxDepthSelector = (0, _createSelector.createSelector)(gridColumnGroupingSelector, columnGrouping => columnGrouping?.maxDepth ?? 0);

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.unwrapGroupingColumnModel = exports.getColumnGroupsHeaderStructure = void 0;
var _gridColumnGrouping = require("../../../models/gridColumnGrouping");
var _utils = require("../../../utils/utils");
// This is the recurrence function that help writing `unwrapGroupingColumnModel()`
const recurrentUnwrapGroupingColumnModel = (columnGroupNode, parents, unwrappedGroupingModelToComplete) => {
if ((0, _gridColumnGrouping.isLeaf)(columnGroupNode)) {
if (unwrappedGroupingModelToComplete[columnGroupNode.field] !== undefined) {
throw new Error([`MUI: columnGroupingModel contains duplicated field`, `column field ${columnGroupNode.field} occurs two times in the grouping model:`, `- ${unwrappedGroupingModelToComplete[columnGroupNode.field].join(' > ')}`, `- ${parents.join(' > ')}`].join('\n'));
}
unwrappedGroupingModelToComplete[columnGroupNode.field] = parents;
return;
}
const {
groupId,
children
} = columnGroupNode;
children.forEach(child => {
recurrentUnwrapGroupingColumnModel(child, [...parents, groupId], unwrappedGroupingModelToComplete);
});
};
/**
* This is a function that provide for each column the array of its parents.
* Parents are ordered from the root to the leaf.
* @param columnGroupingModel The model such as provided in DataGrid props
* @returns An object `{[field]: groupIds}` where `groupIds` is the parents of the column `field`
*/
const unwrapGroupingColumnModel = columnGroupingModel => {
if (!columnGroupingModel) {
return {};
}
const unwrappedSubTree = {};
columnGroupingModel.forEach(columnGroupNode => {
recurrentUnwrapGroupingColumnModel(columnGroupNode, [], unwrappedSubTree);
});
return unwrappedSubTree;
};
exports.unwrapGroupingColumnModel = unwrapGroupingColumnModel;
const getColumnGroupsHeaderStructure = (orderedColumns, unwrappedGroupingModel, pinnedFields) => {
const getParents = field => unwrappedGroupingModel[field] ?? [];
const groupingHeaderStructure = [];
const maxDepth = Math.max(...orderedColumns.map(field => getParents(field).length));
const haveSameParents = (field1, field2, depth) => (0, _utils.isDeepEqual)(getParents(field1).slice(0, depth + 1), getParents(field2).slice(0, depth + 1));
const haveDifferentContainers = (field1, field2) => {
if (pinnedFields?.left && pinnedFields.left.includes(field1) && !pinnedFields.left.includes(field2)) {
return true;
}
if (pinnedFields?.right && !pinnedFields.right.includes(field1) && pinnedFields.right.includes(field2)) {
return true;
}
return false;
};
for (let depth = 0; depth < maxDepth; depth += 1) {
const depthStructure = orderedColumns.reduce((structure, newField) => {
const groupId = getParents(newField)[depth] ?? null;
if (structure.length === 0) {
return [{
columnFields: [newField],
groupId
}];
}
const lastGroup = structure[structure.length - 1];
const prevField = lastGroup.columnFields[lastGroup.columnFields.length - 1];
const prevGroupId = lastGroup.groupId;
if (prevGroupId !== groupId || !haveSameParents(prevField, newField, depth) ||
// Fix for https://github.com/mui/mui-x/issues/7041
haveDifferentContainers(prevField, newField)) {
// It's a new group
return [...structure, {
columnFields: [newField],
groupId
}];
}
// It extends the previous group
return [...structure.slice(0, structure.length - 1), {
columnFields: [...lastGroup.columnFields, newField],
groupId
}];
}, []);
groupingHeaderStructure.push(depthStructure);
}
return groupingHeaderStructure;
};
exports.getColumnGroupsHeaderStructure = getColumnGroupsHeaderStructure;

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridColumnGroupsSelector = require("./gridColumnGroupsSelector");
Object.keys(_gridColumnGroupsSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridColumnGroupsSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridColumnGroupsSelector[key];
}
});
});

View File

@@ -0,0 +1,147 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnGrouping = exports.columnGroupsStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var React = _interopRequireWildcard(require("react"));
var _gridColumnGrouping = require("../../../models/gridColumnGrouping");
var _gridColumnGroupsSelector = require("./gridColumnGroupsSelector");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridColumnGroupsUtils = require("./gridColumnGroupsUtils");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _columns = require("../columns");
const _excluded = ["groupId", "children"];
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const createGroupLookup = columnGroupingModel => {
let groupLookup = {};
columnGroupingModel.forEach(node => {
if ((0, _gridColumnGrouping.isLeaf)(node)) {
return;
}
const {
groupId,
children
} = node,
other = (0, _objectWithoutPropertiesLoose2.default)(node, _excluded);
if (!groupId) {
throw new Error('MUI: An element of the columnGroupingModel does not have either `field` or `groupId`.');
}
if (!children) {
console.warn(`MUI: group groupId=${groupId} has no children.`);
}
const groupParam = (0, _extends2.default)({}, other, {
groupId
});
const subTreeLookup = createGroupLookup(children);
if (subTreeLookup[groupId] !== undefined || groupLookup[groupId] !== undefined) {
throw new Error(`MUI: The groupId ${groupId} is used multiple times in the columnGroupingModel.`);
}
groupLookup = (0, _extends2.default)({}, groupLookup, subTreeLookup, {
[groupId]: groupParam
});
});
return (0, _extends2.default)({}, groupLookup);
};
const columnGroupsStateInitializer = (state, props, apiRef) => {
if (!props.experimentalFeatures?.columnGrouping) {
return state;
}
const columnFields = (0, _columns.gridColumnFieldsSelector)(apiRef);
const visibleColumnFields = (0, _columns.gridVisibleColumnFieldsSelector)(apiRef);
const groupLookup = createGroupLookup(props.columnGroupingModel ?? []);
const unwrappedGroupingModel = (0, _gridColumnGroupsUtils.unwrapGroupingColumnModel)(props.columnGroupingModel ?? []);
const columnGroupsHeaderStructure = (0, _gridColumnGroupsUtils.getColumnGroupsHeaderStructure)(columnFields, unwrappedGroupingModel,
// @ts-expect-error Move this part to `Pro` package
apiRef.current.state.pinnedColumns ?? {});
const maxDepth = visibleColumnFields.length === 0 ? 0 : Math.max(...visibleColumnFields.map(field => unwrappedGroupingModel[field]?.length ?? 0));
return (0, _extends2.default)({}, state, {
columnGrouping: {
lookup: groupLookup,
unwrappedGroupingModel,
headerStructure: columnGroupsHeaderStructure,
maxDepth
}
});
};
/**
* @requires useGridColumns (method, event)
* @requires useGridParamsApi (method)
*/
exports.columnGroupsStateInitializer = columnGroupsStateInitializer;
const useGridColumnGrouping = (apiRef, props) => {
/**
* API METHODS
*/
const getColumnGroupPath = React.useCallback(field => {
const unwrappedGroupingModel = (0, _gridColumnGroupsSelector.gridColumnGroupsUnwrappedModelSelector)(apiRef);
return unwrappedGroupingModel[field] ?? [];
}, [apiRef]);
const getAllGroupDetails = React.useCallback(() => {
const columnGroupLookup = (0, _gridColumnGroupsSelector.gridColumnGroupsLookupSelector)(apiRef);
return columnGroupLookup;
}, [apiRef]);
const columnGroupingApi = {
unstable_getColumnGroupPath: getColumnGroupPath,
unstable_getAllGroupDetails: getAllGroupDetails
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, columnGroupingApi, 'public');
const handleColumnIndexChange = React.useCallback(() => {
const unwrappedGroupingModel = (0, _gridColumnGroupsUtils.unwrapGroupingColumnModel)(props.columnGroupingModel ?? []);
apiRef.current.setState(state => {
const orderedFields = state.columns?.orderedFields ?? [];
// @ts-expect-error Move this logic to `Pro` package
const pinnedColumns = state.pinnedColumns ?? {};
const columnGroupsHeaderStructure = (0, _gridColumnGroupsUtils.getColumnGroupsHeaderStructure)(orderedFields, unwrappedGroupingModel, pinnedColumns);
return (0, _extends2.default)({}, state, {
columnGrouping: (0, _extends2.default)({}, state.columnGrouping, {
headerStructure: columnGroupsHeaderStructure
})
});
});
}, [apiRef, props.columnGroupingModel]);
const updateColumnGroupingState = React.useCallback(columnGroupingModel => {
if (!props.experimentalFeatures?.columnGrouping) {
return;
}
// @ts-expect-error Move this logic to `Pro` package
const pinnedColumns = apiRef.current.getPinnedColumns?.() ?? {};
const columnFields = (0, _columns.gridColumnFieldsSelector)(apiRef);
const visibleColumnFields = (0, _columns.gridVisibleColumnFieldsSelector)(apiRef);
const groupLookup = createGroupLookup(columnGroupingModel ?? []);
const unwrappedGroupingModel = (0, _gridColumnGroupsUtils.unwrapGroupingColumnModel)(columnGroupingModel ?? []);
const columnGroupsHeaderStructure = (0, _gridColumnGroupsUtils.getColumnGroupsHeaderStructure)(columnFields, unwrappedGroupingModel, pinnedColumns);
const maxDepth = visibleColumnFields.length === 0 ? 0 : Math.max(...visibleColumnFields.map(field => unwrappedGroupingModel[field]?.length ?? 0));
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
columnGrouping: {
lookup: groupLookup,
unwrappedGroupingModel,
headerStructure: columnGroupsHeaderStructure,
maxDepth
}
});
});
}, [apiRef, props.experimentalFeatures?.columnGrouping]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnIndexChange', handleColumnIndexChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnsChange', () => {
updateColumnGroupingState(props.columnGroupingModel);
});
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnVisibilityModelChange', () => {
updateColumnGroupingState(props.columnGroupingModel);
});
/**
* EFFECTS
*/
React.useEffect(() => {
updateColumnGroupingState(props.columnGroupingModel);
}, [updateColumnGroupingState, props.columnGroupingModel]);
};
exports.useGridColumnGrouping = useGridColumnGrouping;

View File

@@ -0,0 +1,352 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnHeaders = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var ReactDOM = _interopRequireWildcard(require("react-dom"));
var _utils = require("@mui/utils");
var _styles = require("@mui/material/styles");
var _reselect = require("reselect");
var _utils2 = require("../../utils");
var _useGridPrivateApiContext = require("../../utils/useGridPrivateApiContext");
var _useGridRootProps = require("../../utils/useGridRootProps");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _GridColumnHeaderItem = require("../../../components/columnHeaders/GridColumnHeaderItem");
var _gridColumnsUtils = require("../columns/gridColumnsUtils");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _useGridVirtualScroller = require("../virtualization/useGridVirtualScroller");
var _virtualization = require("../virtualization");
var _GridColumnGroupHeader = require("../../../components/columnHeaders/GridColumnGroupHeader");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const GridColumnHeaderRow = (0, _styles.styled)('div', {
name: 'MuiDataGrid',
slot: 'ColumnHeaderRow',
overridesResolver: (props, styles) => styles.columnHeaderRow
})(() => ({
display: 'flex'
}));
function isUIEvent(event) {
return !!event.target;
}
const useGridColumnHeaders = props => {
const {
innerRef: innerRefProp,
minColumnIndex = 0,
visibleColumns,
sortColumnLookup,
filterColumnLookup,
columnPositions,
columnHeaderTabIndexState,
columnGroupHeaderTabIndexState,
columnHeaderFocus,
columnGroupHeaderFocus,
densityFactor,
headerGroupingMaxDepth,
columnMenuState,
columnVisibility,
columnGroupsHeaderStructure,
hasOtherElementInTabSequence
} = props;
const theme = (0, _styles.useTheme)();
const [dragCol, setDragCol] = React.useState('');
const [resizeCol, setResizeCol] = React.useState('');
const apiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)();
const hasVirtualization = (0, _utils2.useGridSelector)(apiRef, _virtualization.gridVirtualizationColumnEnabledSelector);
const rootProps = (0, _useGridRootProps.useGridRootProps)();
const innerRef = React.useRef(null);
const handleInnerRef = (0, _utils.unstable_useForkRef)(innerRefProp, innerRef);
const [renderContext, setRenderContextRaw] = React.useState(null);
const prevRenderContext = React.useRef(renderContext);
const prevScrollLeft = React.useRef(0);
const currentPage = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, rootProps);
const totalHeaderHeight = (0, _gridColumnsUtils.getTotalHeaderHeight)(apiRef, rootProps.columnHeaderHeight);
const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
const setRenderContext = React.useCallback(nextRenderContext => {
if (renderContext && nextRenderContext && (0, _useGridVirtualScroller.areRenderContextsEqual)(renderContext, nextRenderContext)) {
return;
}
setRenderContextRaw(nextRenderContext);
}, [renderContext]);
React.useEffect(() => {
if (apiRef.current.columnHeadersContainerElementRef?.current) {
apiRef.current.columnHeadersContainerElementRef.current.scrollLeft = 0;
}
}, [apiRef]);
// memoize `getFirstColumnIndexToRender`, since it's called on scroll
const getFirstColumnIndexToRenderRef = React.useRef((0, _reselect.defaultMemoize)(_gridColumnsUtils.getFirstColumnIndexToRender, {
equalityCheck: (a, b) => ['firstColumnIndex', 'minColumnIndex', 'columnBuffer'].every(key => a[key] === b[key])
}));
const updateInnerPosition = React.useCallback(nextRenderContext => {
const [firstRowToRender, lastRowToRender] = (0, _useGridVirtualScroller.getRenderableIndexes)({
firstIndex: nextRenderContext.firstRowIndex,
lastIndex: nextRenderContext.lastRowIndex,
minFirstIndex: 0,
maxLastIndex: currentPage.rows.length,
buffer: rootProps.rowBuffer
});
const firstColumnToRender = getFirstColumnIndexToRenderRef.current({
firstColumnIndex: nextRenderContext.firstColumnIndex,
minColumnIndex,
columnBuffer: rootProps.columnBuffer,
firstRowToRender,
lastRowToRender,
apiRef,
visibleRows: currentPage.rows
});
const direction = theme.direction === 'ltr' ? 1 : -1;
const offset = firstColumnToRender > 0 ? prevScrollLeft.current - direction * columnPositions[firstColumnToRender] : prevScrollLeft.current;
innerRef.current.style.transform = `translate3d(${-offset}px, 0px, 0px)`;
}, [columnPositions, minColumnIndex, rootProps.columnBuffer, apiRef, currentPage.rows, rootProps.rowBuffer, theme.direction]);
React.useLayoutEffect(() => {
if (renderContext) {
updateInnerPosition(renderContext);
}
}, [renderContext, updateInnerPosition]);
const handleScroll = React.useCallback(({
left,
renderContext: nextRenderContext = null
}, event) => {
if (!innerRef.current) {
return;
}
// Ignore vertical scroll.
// Excepts the first event which sets the previous render context.
if (prevScrollLeft.current === left && prevRenderContext.current?.firstColumnIndex === nextRenderContext?.firstColumnIndex && prevRenderContext.current?.lastColumnIndex === nextRenderContext?.lastColumnIndex) {
return;
}
prevScrollLeft.current = left;
// We can only update the position when we guarantee that the render context has been
// rendered. This is achieved using ReactDOM.flushSync or when the context doesn't change.
let canUpdateInnerPosition = false;
if (nextRenderContext !== prevRenderContext.current || !prevRenderContext.current) {
// ReactDOM.flushSync cannot be called on `scroll` events fired inside effects
if (isUIEvent(event)) {
// To prevent flickering, the inner position can only be updated after the new context has
// been rendered. ReactDOM.flushSync ensures that the state changes will happen before
// updating the position.
ReactDOM.flushSync(() => {
setRenderContext(nextRenderContext);
});
canUpdateInnerPosition = true;
} else {
setRenderContext(nextRenderContext);
}
prevRenderContext.current = nextRenderContext;
} else {
canUpdateInnerPosition = true;
}
// Pass directly the render context to avoid waiting for the next render
if (nextRenderContext && canUpdateInnerPosition) {
updateInnerPosition(nextRenderContext);
}
}, [updateInnerPosition, setRenderContext]);
const handleColumnResizeStart = React.useCallback(params => setResizeCol(params.field), []);
const handleColumnResizeStop = React.useCallback(() => setResizeCol(''), []);
const handleColumnReorderStart = React.useCallback(params => setDragCol(params.field), []);
const handleColumnReorderStop = React.useCallback(() => setDragCol(''), []);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnResizeStart', handleColumnResizeStart);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnResizeStop', handleColumnResizeStop);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragStart', handleColumnReorderStart);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragEnd', handleColumnReorderStop);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'scrollPositionChange', handleScroll);
// Helper for computation common between getColumnHeaders and getColumnGroupHeaders
const getColumnsToRender = params => {
const {
renderContext: nextRenderContext = renderContext,
minFirstColumn = minColumnIndex,
maxLastColumn = visibleColumns.length
} = params || {};
if (!nextRenderContext) {
return null;
}
const [firstRowToRender, lastRowToRender] = (0, _useGridVirtualScroller.getRenderableIndexes)({
firstIndex: nextRenderContext.firstRowIndex,
lastIndex: nextRenderContext.lastRowIndex,
minFirstIndex: 0,
maxLastIndex: currentPage.rows.length,
buffer: rootProps.rowBuffer
});
const firstColumnToRender = !hasVirtualization ? 0 : getFirstColumnIndexToRenderRef.current({
firstColumnIndex: nextRenderContext.firstColumnIndex,
minColumnIndex: minFirstColumn,
columnBuffer: rootProps.columnBuffer,
apiRef,
firstRowToRender,
lastRowToRender,
visibleRows: currentPage.rows
});
const lastColumnToRender = !hasVirtualization ? maxLastColumn : Math.min(nextRenderContext.lastColumnIndex + rootProps.columnBuffer, maxLastColumn);
const renderedColumns = visibleColumns.slice(firstColumnToRender, lastColumnToRender);
return {
renderedColumns,
firstColumnToRender,
lastColumnToRender,
minFirstColumn,
maxLastColumn
};
};
const getColumnHeaders = (params, other = {}) => {
const columnsToRender = getColumnsToRender(params);
if (columnsToRender == null) {
return null;
}
const {
renderedColumns,
firstColumnToRender
} = columnsToRender;
const columns = [];
for (let i = 0; i < renderedColumns.length; i += 1) {
const colDef = renderedColumns[i];
const columnIndex = firstColumnToRender + i;
const isFirstColumn = columnIndex === 0;
const tabIndex = columnHeaderTabIndexState !== null && columnHeaderTabIndexState.field === colDef.field || isFirstColumn && !hasOtherElementInTabSequence ? 0 : -1;
const hasFocus = columnHeaderFocus !== null && columnHeaderFocus.field === colDef.field;
const open = columnMenuState.open && columnMenuState.field === colDef.field;
columns.push( /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridColumnHeaderItem.GridColumnHeaderItem, (0, _extends2.default)({}, sortColumnLookup[colDef.field], {
columnMenuOpen: open,
filterItemsCounter: filterColumnLookup[colDef.field] && filterColumnLookup[colDef.field].length,
headerHeight: headerHeight,
isDragging: colDef.field === dragCol,
colDef: colDef,
colIndex: columnIndex,
isResizing: resizeCol === colDef.field,
hasFocus: hasFocus,
tabIndex: tabIndex
}, other), colDef.field));
}
return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridColumnHeaderRow, {
role: "row",
"aria-rowindex": headerGroupingMaxDepth + 1,
ownerState: rootProps,
children: columns
});
};
const getColumnGroupHeaders = params => {
if (headerGroupingMaxDepth === 0) {
return null;
}
const columnsToRender = getColumnsToRender(params);
if (columnsToRender == null || columnsToRender.renderedColumns.length === 0) {
return null;
}
const {
firstColumnToRender,
lastColumnToRender
} = columnsToRender;
const columns = [];
const headerToRender = [];
for (let depth = 0; depth < headerGroupingMaxDepth; depth += 1) {
const rowStructure = columnGroupsHeaderStructure[depth];
const firstColumnFieldToRender = visibleColumns[firstColumnToRender].field;
const firstGroupToRender = apiRef.current.unstable_getColumnGroupPath(firstColumnFieldToRender)[depth] ?? null;
const firstGroupIndex = rowStructure.findIndex(({
groupId,
columnFields
}) => groupId === firstGroupToRender && columnFields.includes(firstColumnFieldToRender));
const lastColumnFieldToRender = visibleColumns[lastColumnToRender - 1].field;
const lastGroupToRender = apiRef.current.unstable_getColumnGroupPath(lastColumnFieldToRender)[depth] ?? null;
const lastGroupIndex = rowStructure.findIndex(({
groupId,
columnFields
}) => groupId === lastGroupToRender && columnFields.includes(lastColumnFieldToRender));
const visibleColumnGroupHeader = rowStructure.slice(firstGroupIndex, lastGroupIndex + 1).map(groupStructure => {
return (0, _extends2.default)({}, groupStructure, {
columnFields: groupStructure.columnFields.filter(field => columnVisibility[field] !== false)
});
}).filter(groupStructure => groupStructure.columnFields.length > 0);
const firstVisibleColumnIndex = visibleColumnGroupHeader[0].columnFields.indexOf(firstColumnFieldToRender);
const hiddenGroupColumns = visibleColumnGroupHeader[0].columnFields.slice(0, firstVisibleColumnIndex);
const leftOverflow = hiddenGroupColumns.reduce((acc, field) => {
const column = apiRef.current.getColumn(field);
return acc + (column.computedWidth ?? 0);
}, 0);
let columnIndex = firstColumnToRender;
const elements = visibleColumnGroupHeader.map(({
groupId,
columnFields
}) => {
const hasFocus = columnGroupHeaderFocus !== null && columnGroupHeaderFocus.depth === depth && columnFields.includes(columnGroupHeaderFocus.field);
const tabIndex = columnGroupHeaderTabIndexState !== null && columnGroupHeaderTabIndexState.depth === depth && columnFields.includes(columnGroupHeaderTabIndexState.field) ? 0 : -1;
const headerInfo = {
groupId,
width: columnFields.reduce((acc, field) => acc + apiRef.current.getColumn(field).computedWidth, 0),
fields: columnFields,
colIndex: columnIndex,
hasFocus,
tabIndex
};
columnIndex += columnFields.length;
return headerInfo;
});
headerToRender.push({
leftOverflow,
elements
});
}
headerToRender.forEach((depthInfo, depthIndex) => {
columns.push( /*#__PURE__*/(0, _jsxRuntime.jsx)(GridColumnHeaderRow, {
style: {
height: `${headerHeight}px`,
transform: `translateX(-${depthInfo.leftOverflow}px)`
},
role: "row",
"aria-rowindex": depthIndex + 1,
ownerState: rootProps,
children: depthInfo.elements.map(({
groupId,
width,
fields,
colIndex,
hasFocus,
tabIndex
}, groupIndex) => {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridColumnGroupHeader.GridColumnGroupHeader, {
groupId: groupId,
width: width,
fields: fields,
colIndex: colIndex,
depth: depthIndex,
isLastColumn: colIndex === visibleColumns.length - fields.length,
maxDepth: headerToRender.length,
height: headerHeight,
hasFocus: hasFocus,
tabIndex: tabIndex
}, groupIndex);
})
}, depthIndex));
});
return columns;
};
const rootStyle = {
minHeight: totalHeaderHeight,
maxHeight: totalHeaderHeight,
lineHeight: `${headerHeight}px`
};
return {
renderContext,
getColumnHeaders,
getColumnsToRender,
getColumnGroupHeaders,
isDragging: !!dragCol,
getRootProps: (other = {}) => (0, _extends2.default)({
style: rootStyle
}, other),
getInnerProps: () => ({
ref: handleInnerRef,
role: 'rowgroup'
}),
headerHeight
};
};
exports.useGridColumnHeaders = useGridColumnHeaders;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridColumnMenuSelector = void 0;
const gridColumnMenuSelector = state => state.columnMenu;
exports.gridColumnMenuSelector = gridColumnMenuSelector;

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _columnMenuInterfaces = require("./columnMenuInterfaces");
Object.keys(_columnMenuInterfaces).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _columnMenuInterfaces[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _columnMenuInterfaces[key];
}
});
});
var _columnMenuSelector = require("./columnMenuSelector");
Object.keys(_columnMenuSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _columnMenuSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _columnMenuSelector[key];
}
});
});

View File

@@ -0,0 +1,112 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnMenu = exports.columnMenuStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("../../utils");
var _columnMenuSelector = require("./columnMenuSelector");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const columnMenuStateInitializer = state => (0, _extends2.default)({}, state, {
columnMenu: {
open: false
}
});
/**
* @requires useGridColumnResize (event)
* @requires useGridInfiniteLoader (event)
*/
exports.columnMenuStateInitializer = columnMenuStateInitializer;
const useGridColumnMenu = apiRef => {
const logger = (0, _utils.useGridLogger)(apiRef, 'useGridColumnMenu');
/**
* API METHODS
*/
const showColumnMenu = React.useCallback(field => {
const shouldUpdate = apiRef.current.setState(state => {
if (state.columnMenu.open && state.columnMenu.field === field) {
return state;
}
logger.debug('Opening Column Menu');
return (0, _extends2.default)({}, state, {
columnMenu: {
open: true,
field
}
});
});
if (shouldUpdate) {
apiRef.current.hidePreferences();
apiRef.current.forceUpdate();
}
}, [apiRef, logger]);
const hideColumnMenu = React.useCallback(() => {
const columnMenuState = (0, _columnMenuSelector.gridColumnMenuSelector)(apiRef.current.state);
if (columnMenuState.field) {
const columnLookup = (0, _gridColumnsSelector.gridColumnLookupSelector)(apiRef);
const columnVisibilityModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const orderedFields = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
let fieldToFocus = columnMenuState.field;
// If the column was removed from the grid, we need to find the closest visible field
if (!columnLookup[fieldToFocus]) {
fieldToFocus = orderedFields[0];
}
// If the field to focus is hidden, we need to find the closest visible field
if (columnVisibilityModel[fieldToFocus] === false) {
// contains visible column fields + the field that was just hidden
const visibleOrderedFields = orderedFields.filter(field => {
if (field === fieldToFocus) {
return true;
}
return columnVisibilityModel[field] !== false;
});
const fieldIndex = visibleOrderedFields.indexOf(fieldToFocus);
fieldToFocus = visibleOrderedFields[fieldIndex + 1] || visibleOrderedFields[fieldIndex - 1];
}
apiRef.current.setColumnHeaderFocus(fieldToFocus);
}
const shouldUpdate = apiRef.current.setState(state => {
if (!state.columnMenu.open && state.columnMenu.field === undefined) {
return state;
}
logger.debug('Hiding Column Menu');
return (0, _extends2.default)({}, state, {
columnMenu: (0, _extends2.default)({}, state.columnMenu, {
open: false,
field: undefined
})
});
});
if (shouldUpdate) {
apiRef.current.forceUpdate();
}
}, [apiRef, logger]);
const toggleColumnMenu = React.useCallback(field => {
logger.debug('Toggle Column Menu');
const columnMenu = (0, _columnMenuSelector.gridColumnMenuSelector)(apiRef.current.state);
if (!columnMenu.open || columnMenu.field !== field) {
showColumnMenu(field);
} else {
hideColumnMenu();
}
}, [apiRef, logger, showColumnMenu, hideColumnMenu]);
const columnMenuApi = {
showColumnMenu,
hideColumnMenu,
toggleColumnMenu
};
(0, _utils.useGridApiMethod)(apiRef, columnMenuApi, 'public');
(0, _utils.useGridApiEventHandler)(apiRef, 'columnResizeStart', hideColumnMenu);
(0, _utils.useGridApiEventHandler)(apiRef, 'virtualScrollerWheel', apiRef.current.hideColumnMenu);
(0, _utils.useGridApiEventHandler)(apiRef, 'virtualScrollerTouchMove', apiRef.current.hideColumnMenu);
};
exports.useGridColumnMenu = useGridColumnMenu;

View File

@@ -0,0 +1,67 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnMenuSlots = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _Divider = _interopRequireDefault(require("@mui/material/Divider"));
var _useGridPrivateApiContext = require("../../utils/useGridPrivateApiContext");
const _excluded = ["displayOrder"];
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridColumnMenuSlots = props => {
const apiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)();
const {
defaultSlots,
defaultSlotProps,
slots = {},
slotProps = {},
hideMenu,
colDef,
addDividers = true
} = props;
const processedComponents = React.useMemo(() => (0, _extends2.default)({}, defaultSlots, slots), [defaultSlots, slots]);
const processedSlotProps = React.useMemo(() => {
if (!slotProps || Object.keys(slotProps).length === 0) {
return defaultSlotProps;
}
const mergedProps = (0, _extends2.default)({}, slotProps);
Object.entries(defaultSlotProps).forEach(([key, currentSlotProps]) => {
mergedProps[key] = (0, _extends2.default)({}, currentSlotProps, slotProps[key] || {});
});
return mergedProps;
}, [defaultSlotProps, slotProps]);
const defaultItems = apiRef.current.unstable_applyPipeProcessors('columnMenu', [], props.colDef);
const userItems = React.useMemo(() => {
const defaultComponentKeys = Object.keys(defaultSlots);
return Object.keys(slots).filter(key => !defaultComponentKeys.includes(key));
}, [slots, defaultSlots]);
return React.useMemo(() => {
const uniqueItems = Array.from(new Set([...defaultItems, ...userItems]));
const cleansedItems = uniqueItems.filter(key => processedComponents[key] != null);
const sorted = cleansedItems.sort((a, b) => {
const leftItemProps = processedSlotProps[a];
const rightItemProps = processedSlotProps[b];
const leftDisplayOrder = Number.isFinite(leftItemProps?.displayOrder) ? leftItemProps.displayOrder : 100;
const rightDisplayOrder = Number.isFinite(rightItemProps?.displayOrder) ? rightItemProps.displayOrder : 100;
return leftDisplayOrder - rightDisplayOrder;
});
return sorted.reduce((acc, key, index) => {
let itemProps = {
colDef,
onClick: hideMenu
};
const processedComponentProps = processedSlotProps[key];
if (processedComponentProps) {
const customProps = (0, _objectWithoutPropertiesLoose2.default)(processedComponentProps, _excluded);
itemProps = (0, _extends2.default)({}, itemProps, customProps);
}
return addDividers && index !== sorted.length - 1 ? [...acc, [processedComponents[key], itemProps], [_Divider.default, {}]] : [...acc, [processedComponents[key], itemProps]];
}, []);
}, [addDividers, colDef, defaultItems, hideMenu, processedComponents, processedSlotProps, userItems]);
};
exports.useGridColumnMenuSlots = useGridColumnMenuSlots;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,93 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridVisibleColumnFieldsSelector = exports.gridVisibleColumnDefinitionsSelector = exports.gridFilterableColumnLookupSelector = exports.gridFilterableColumnDefinitionsSelector = exports.gridColumnsTotalWidthSelector = exports.gridColumnsStateSelector = exports.gridColumnVisibilityModelSelector = exports.gridColumnPositionsSelector = exports.gridColumnLookupSelector = exports.gridColumnFieldsSelector = exports.gridColumnDefinitionsSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
/**
* Get the columns state
* @category Columns
*/
const gridColumnsStateSelector = state => state.columns;
/**
* Get an array of column fields in the order rendered on screen.
* @category Columns
*/
exports.gridColumnsStateSelector = gridColumnsStateSelector;
const gridColumnFieldsSelector = exports.gridColumnFieldsSelector = (0, _createSelector.createSelector)(gridColumnsStateSelector, columnsState => columnsState.orderedFields);
/**
* Get the columns as a lookup (an object containing the field for keys and the definition for values).
* @category Columns
*/
const gridColumnLookupSelector = exports.gridColumnLookupSelector = (0, _createSelector.createSelector)(gridColumnsStateSelector, columnsState => columnsState.lookup);
/**
* Get an array of column definitions in the order rendered on screen..
* @category Columns
*/
const gridColumnDefinitionsSelector = exports.gridColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnFieldsSelector, gridColumnLookupSelector, (allFields, lookup) => allFields.map(field => lookup[field]));
/**
* Get the column visibility model, containing the visibility status of each column.
* If a column is not registered in the model, it is visible.
* @category Visible Columns
*/
const gridColumnVisibilityModelSelector = exports.gridColumnVisibilityModelSelector = (0, _createSelector.createSelector)(gridColumnsStateSelector, columnsState => columnsState.columnVisibilityModel);
/**
* Get the visible columns as a lookup (an object containing the field for keys and the definition for values).
* @category Visible Columns
*/
const gridVisibleColumnDefinitionsSelector = exports.gridVisibleColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, (columns, columnVisibilityModel) => columns.filter(column => columnVisibilityModel[column.field] !== false));
/**
* Get the field of each visible column.
* @category Visible Columns
*/
const gridVisibleColumnFieldsSelector = exports.gridVisibleColumnFieldsSelector = (0, _createSelector.createSelectorMemoized)(gridVisibleColumnDefinitionsSelector, visibleColumns => visibleColumns.map(column => column.field));
/**
* Get the left position in pixel of each visible columns relative to the left of the first column.
* @category Visible Columns
*/
const gridColumnPositionsSelector = exports.gridColumnPositionsSelector = (0, _createSelector.createSelectorMemoized)(gridVisibleColumnDefinitionsSelector, visibleColumns => {
const positions = [];
let currentPosition = 0;
for (let i = 0; i < visibleColumns.length; i += 1) {
positions.push(currentPosition);
currentPosition += visibleColumns[i].computedWidth;
}
return positions;
});
/**
* Get the summed width of all the visible columns.
* @category Visible Columns
*/
const gridColumnsTotalWidthSelector = exports.gridColumnsTotalWidthSelector = (0, _createSelector.createSelector)(gridVisibleColumnDefinitionsSelector, gridColumnPositionsSelector, (visibleColumns, positions) => {
const colCount = visibleColumns.length;
if (colCount === 0) {
return 0;
}
return positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth;
});
/**
* Get the filterable columns as an array.
* @category Columns
*/
const gridFilterableColumnDefinitionsSelector = exports.gridFilterableColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnDefinitionsSelector, columns => columns.filter(col => col.filterable));
/**
* Get the filterable columns as a lookup (an object containing the field for keys and the definition for values).
* @category Columns
*/
const gridFilterableColumnLookupSelector = exports.gridFilterableColumnLookupSelector = (0, _createSelector.createSelectorMemoized)(gridColumnDefinitionsSelector, columns => columns.reduce((acc, col) => {
if (col.filterable) {
acc[col.field] = col;
}
return acc;
}, {}));

View File

@@ -0,0 +1,348 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.applyInitialState = exports.COLUMNS_DIMENSION_PROPERTIES = void 0;
exports.computeFlexColumnsWidth = computeFlexColumnsWidth;
exports.createColumnsState = void 0;
exports.getFirstColumnIndexToRender = getFirstColumnIndexToRender;
exports.getFirstNonSpannedColumnToRender = getFirstNonSpannedColumnToRender;
exports.getTotalHeaderHeight = getTotalHeaderHeight;
exports.mergeColumnsState = exports.hydrateColumnsWidth = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _colDef = require("../../../colDef");
var _gridColumnsSelector = require("./gridColumnsSelector");
var _utils = require("../../../utils/utils");
var _densitySelector = require("../density/densitySelector");
var _gridColumnGroupsSelector = require("../columnGrouping/gridColumnGroupsSelector");
const COLUMNS_DIMENSION_PROPERTIES = exports.COLUMNS_DIMENSION_PROPERTIES = ['maxWidth', 'minWidth', 'width', 'flex'];
/**
* Computes width for flex columns.
* Based on CSS Flexbox specification:
* https://drafts.csswg.org/css-flexbox-1/#resolve-flexible-lengths
*/
function computeFlexColumnsWidth({
initialFreeSpace,
totalFlexUnits,
flexColumns
}) {
const uniqueFlexColumns = new Set(flexColumns.map(col => col.field));
const flexColumnsLookup = {
all: {},
frozenFields: [],
freeze: field => {
const value = flexColumnsLookup.all[field];
if (value && value.frozen !== true) {
flexColumnsLookup.all[field].frozen = true;
flexColumnsLookup.frozenFields.push(field);
}
}
};
// Step 5 of https://drafts.csswg.org/css-flexbox-1/#resolve-flexible-lengths
function loopOverFlexItems() {
// 5a: If all the flex items on the line are frozen, free space has been distributed.
if (flexColumnsLookup.frozenFields.length === uniqueFlexColumns.size) {
return;
}
const violationsLookup = {
min: {},
max: {}
};
let remainingFreeSpace = initialFreeSpace;
let flexUnits = totalFlexUnits;
let totalViolation = 0;
// 5b: Calculate the remaining free space
flexColumnsLookup.frozenFields.forEach(field => {
remainingFreeSpace -= flexColumnsLookup.all[field].computedWidth;
flexUnits -= flexColumnsLookup.all[field].flex;
});
for (let i = 0; i < flexColumns.length; i += 1) {
const column = flexColumns[i];
if (flexColumnsLookup.all[column.field] && flexColumnsLookup.all[column.field].frozen === true) {
continue;
}
// 5c: Distribute remaining free space proportional to the flex factors
const widthPerFlexUnit = remainingFreeSpace / flexUnits;
let computedWidth = widthPerFlexUnit * column.flex;
// 5d: Fix min/max violations
if (computedWidth < column.minWidth) {
totalViolation += column.minWidth - computedWidth;
computedWidth = column.minWidth;
violationsLookup.min[column.field] = true;
} else if (computedWidth > column.maxWidth) {
totalViolation += column.maxWidth - computedWidth;
computedWidth = column.maxWidth;
violationsLookup.max[column.field] = true;
}
flexColumnsLookup.all[column.field] = {
frozen: false,
computedWidth,
flex: column.flex
};
}
// 5e: Freeze over-flexed items
if (totalViolation < 0) {
// Freeze all the items with max violations
Object.keys(violationsLookup.max).forEach(field => {
flexColumnsLookup.freeze(field);
});
} else if (totalViolation > 0) {
// Freeze all the items with min violations
Object.keys(violationsLookup.min).forEach(field => {
flexColumnsLookup.freeze(field);
});
} else {
// Freeze all items
flexColumns.forEach(({
field
}) => {
flexColumnsLookup.freeze(field);
});
}
// 5f: Return to the start of this loop
loopOverFlexItems();
}
loopOverFlexItems();
return flexColumnsLookup.all;
}
/**
* Compute the `computedWidth` (ie: the width the column should have during rendering) based on the `width` / `flex` / `minWidth` / `maxWidth` properties of `GridColDef`.
* The columns already have been merged with there `type` default values for `minWidth`, `maxWidth` and `width`, thus the `!` for those properties below.
* TODO: Unit test this function in depth and only keep basic cases for the whole grid testing.
* TODO: Improve the `GridColDef` typing to reflect the fact that `minWidth` / `maxWidth` and `width` can't be null after the merge with the `type` default values.
*/
const hydrateColumnsWidth = (rawState, viewportInnerWidth) => {
const columnsLookup = {};
let totalFlexUnits = 0;
let widthAllocatedBeforeFlex = 0;
const flexColumns = [];
// For the non-flex columns, compute their width
// For the flex columns, compute there minimum width and how much width must be allocated during the flex allocation
rawState.orderedFields.forEach(columnField => {
const newColumn = (0, _extends2.default)({}, rawState.lookup[columnField]);
if (rawState.columnVisibilityModel[columnField] === false) {
newColumn.computedWidth = 0;
} else {
let computedWidth;
if (newColumn.flex && newColumn.flex > 0) {
totalFlexUnits += newColumn.flex;
computedWidth = 0;
flexColumns.push(newColumn);
} else {
computedWidth = (0, _utils.clamp)(newColumn.width || _colDef.GRID_STRING_COL_DEF.width, newColumn.minWidth || _colDef.GRID_STRING_COL_DEF.minWidth, newColumn.maxWidth || _colDef.GRID_STRING_COL_DEF.maxWidth);
}
widthAllocatedBeforeFlex += computedWidth;
newColumn.computedWidth = computedWidth;
}
columnsLookup[columnField] = newColumn;
});
const initialFreeSpace = Math.max(viewportInnerWidth - widthAllocatedBeforeFlex, 0);
// Allocate the remaining space to the flex columns
if (totalFlexUnits > 0 && viewportInnerWidth > 0) {
const computedColumnWidths = computeFlexColumnsWidth({
initialFreeSpace,
totalFlexUnits,
flexColumns
});
Object.keys(computedColumnWidths).forEach(field => {
columnsLookup[field].computedWidth = computedColumnWidths[field].computedWidth;
});
}
return (0, _extends2.default)({}, rawState, {
lookup: columnsLookup
});
};
/**
* Apply the order and the dimensions of the initial state.
* The columns not registered in `orderedFields` will be placed after the imported columns.
*/
exports.hydrateColumnsWidth = hydrateColumnsWidth;
const applyInitialState = (columnsState, initialState) => {
if (!initialState) {
return columnsState;
}
const {
orderedFields = [],
dimensions = {}
} = initialState;
const columnsWithUpdatedDimensions = Object.keys(dimensions);
if (columnsWithUpdatedDimensions.length === 0 && orderedFields.length === 0) {
return columnsState;
}
const orderedFieldsLookup = {};
const cleanOrderedFields = [];
for (let i = 0; i < orderedFields.length; i += 1) {
const field = orderedFields[i];
// Ignores the fields in the initialState that matches no field on the current column state
if (columnsState.lookup[field]) {
orderedFieldsLookup[field] = true;
cleanOrderedFields.push(field);
}
}
const newOrderedFields = cleanOrderedFields.length === 0 ? columnsState.orderedFields : [...cleanOrderedFields, ...columnsState.orderedFields.filter(field => !orderedFieldsLookup[field])];
const newColumnLookup = (0, _extends2.default)({}, columnsState.lookup);
for (let i = 0; i < columnsWithUpdatedDimensions.length; i += 1) {
const field = columnsWithUpdatedDimensions[i];
const newColDef = (0, _extends2.default)({}, newColumnLookup[field], {
hasBeenResized: true
});
Object.entries(dimensions[field]).forEach(([key, value]) => {
newColDef[key] = value === -1 ? Infinity : value;
});
newColumnLookup[field] = newColDef;
}
const newColumnsState = (0, _extends2.default)({}, columnsState, {
orderedFields: newOrderedFields,
lookup: newColumnLookup
});
return newColumnsState;
};
exports.applyInitialState = applyInitialState;
function getDefaultColTypeDef(columnTypes, type) {
let colDef = columnTypes[_colDef.DEFAULT_GRID_COL_TYPE_KEY];
if (type && columnTypes[type]) {
colDef = columnTypes[type];
}
return colDef;
}
const createColumnsState = ({
apiRef,
columnsToUpsert,
initialState,
columnTypes,
columnVisibilityModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef),
keepOnlyColumnsToUpsert = false
}) => {
const isInsideStateInitializer = !apiRef.current.state.columns;
let columnsState;
if (isInsideStateInitializer) {
columnsState = {
orderedFields: [],
lookup: {},
columnVisibilityModel
};
} else {
const currentState = (0, _gridColumnsSelector.gridColumnsStateSelector)(apiRef.current.state);
columnsState = {
orderedFields: keepOnlyColumnsToUpsert ? [] : [...currentState.orderedFields],
lookup: (0, _extends2.default)({}, currentState.lookup),
// Will be cleaned later if keepOnlyColumnsToUpsert=true
columnVisibilityModel
};
}
let columnsToKeep = {};
if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
columnsToKeep = Object.keys(columnsState.lookup).reduce((acc, key) => (0, _extends2.default)({}, acc, {
[key]: false
}), {});
}
const columnsToUpsertLookup = {};
columnsToUpsert.forEach(newColumn => {
const {
field
} = newColumn;
columnsToUpsertLookup[field] = true;
columnsToKeep[field] = true;
let existingState = columnsState.lookup[field];
if (existingState == null) {
existingState = (0, _extends2.default)({}, getDefaultColTypeDef(columnTypes, newColumn.type), {
field,
hasBeenResized: false
});
columnsState.orderedFields.push(field);
} else if (keepOnlyColumnsToUpsert) {
columnsState.orderedFields.push(field);
}
// If the column type has changed - merge the existing state with the default column type definition
if (existingState && existingState.type !== newColumn.type) {
existingState = (0, _extends2.default)({}, getDefaultColTypeDef(columnTypes, newColumn.type), {
field
});
}
let hasBeenResized = existingState.hasBeenResized;
COLUMNS_DIMENSION_PROPERTIES.forEach(key => {
if (newColumn[key] !== undefined) {
hasBeenResized = true;
if (newColumn[key] === -1) {
newColumn[key] = Infinity;
}
}
});
columnsState.lookup[field] = (0, _extends2.default)({}, existingState, newColumn, {
hasBeenResized
});
});
if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
Object.keys(columnsState.lookup).forEach(field => {
if (!columnsToKeep[field]) {
delete columnsState.lookup[field];
}
});
}
const columnsStateWithPreProcessing = apiRef.current.unstable_applyPipeProcessors('hydrateColumns', columnsState);
const columnsStateWithPortableColumns = applyInitialState(columnsStateWithPreProcessing, initialState);
return hydrateColumnsWidth(columnsStateWithPortableColumns, apiRef.current.getRootDimensions?.()?.viewportInnerSize.width ?? 0);
};
exports.createColumnsState = createColumnsState;
const mergeColumnsState = columnsState => state => (0, _extends2.default)({}, state, {
columns: columnsState
});
exports.mergeColumnsState = mergeColumnsState;
function getFirstNonSpannedColumnToRender({
firstColumnToRender,
apiRef,
firstRowToRender,
lastRowToRender,
visibleRows
}) {
let firstNonSpannedColumnToRender = firstColumnToRender;
for (let i = firstRowToRender; i < lastRowToRender; i += 1) {
const row = visibleRows[i];
if (row) {
const rowId = visibleRows[i].id;
const cellColSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowId, firstColumnToRender);
if (cellColSpanInfo && cellColSpanInfo.spannedByColSpan) {
firstNonSpannedColumnToRender = cellColSpanInfo.leftVisibleCellIndex;
}
}
}
return firstNonSpannedColumnToRender;
}
function getFirstColumnIndexToRender({
firstColumnIndex,
minColumnIndex,
columnBuffer,
firstRowToRender,
lastRowToRender,
apiRef,
visibleRows
}) {
const initialFirstColumnToRender = Math.max(firstColumnIndex - columnBuffer, minColumnIndex);
const firstColumnToRender = getFirstNonSpannedColumnToRender({
firstColumnToRender: initialFirstColumnToRender,
apiRef,
firstRowToRender,
lastRowToRender,
visibleRows
});
return firstColumnToRender;
}
function getTotalHeaderHeight(apiRef, headerHeight) {
const densityFactor = (0, _densitySelector.gridDensityFactorSelector)(apiRef);
const maxDepth = (0, _gridColumnGroupsSelector.gridColumnGroupsHeaderMaxDepthSelector)(apiRef);
return Math.floor(headerHeight * densityFactor) * ((maxDepth ?? 0) + 1);
}

View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "gridColumnDefinitionsSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridColumnDefinitionsSelector;
}
});
Object.defineProperty(exports, "gridColumnFieldsSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridColumnFieldsSelector;
}
});
Object.defineProperty(exports, "gridColumnLookupSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridColumnLookupSelector;
}
});
Object.defineProperty(exports, "gridColumnPositionsSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridColumnPositionsSelector;
}
});
Object.defineProperty(exports, "gridColumnVisibilityModelSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridColumnVisibilityModelSelector;
}
});
Object.defineProperty(exports, "gridColumnsTotalWidthSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridColumnsTotalWidthSelector;
}
});
Object.defineProperty(exports, "gridFilterableColumnDefinitionsSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridFilterableColumnDefinitionsSelector;
}
});
Object.defineProperty(exports, "gridFilterableColumnLookupSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridFilterableColumnLookupSelector;
}
});
Object.defineProperty(exports, "gridVisibleColumnDefinitionsSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridVisibleColumnDefinitionsSelector;
}
});
Object.defineProperty(exports, "gridVisibleColumnFieldsSelector", {
enumerable: true,
get: function () {
return _gridColumnsSelector.gridVisibleColumnFieldsSelector;
}
});
var _gridColumnsSelector = require("./gridColumnsSelector");

View File

@@ -0,0 +1,113 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnSpanning = void 0;
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* @requires useGridColumns (method, event)
* @requires useGridParamsApi (method)
*/
const useGridColumnSpanning = apiRef => {
const lookup = React.useRef({});
const setCellColSpanInfo = React.useCallback((rowId, columnIndex, cellColSpanInfo) => {
const sizes = lookup.current;
if (!sizes[rowId]) {
sizes[rowId] = {};
}
sizes[rowId][columnIndex] = cellColSpanInfo;
}, []);
const getCellColSpanInfo = React.useCallback((rowId, columnIndex) => {
return lookup.current[rowId]?.[columnIndex];
}, []);
// Calculate `colSpan` for the cell.
const calculateCellColSpan = React.useCallback(params => {
const {
columnIndex,
rowId,
minFirstColumnIndex,
maxLastColumnIndex,
columns
} = params;
const columnsLength = columns.length;
const column = columns[columnIndex];
const colSpan = typeof column.colSpan === 'function' ? column.colSpan(apiRef.current.getCellParams(rowId, column.field)) : column.colSpan;
if (!colSpan || colSpan === 1) {
setCellColSpanInfo(rowId, columnIndex, {
spannedByColSpan: false,
cellProps: {
colSpan: 1,
width: column.computedWidth
}
});
return {
colSpan: 1
};
}
let width = column.computedWidth;
for (let j = 1; j < colSpan; j += 1) {
const nextColumnIndex = columnIndex + j;
// Cells should be spanned only within their column section (left-pinned, right-pinned and unpinned).
if (nextColumnIndex >= minFirstColumnIndex && nextColumnIndex < maxLastColumnIndex) {
const nextColumn = columns[nextColumnIndex];
width += nextColumn.computedWidth;
setCellColSpanInfo(rowId, columnIndex + j, {
spannedByColSpan: true,
rightVisibleCellIndex: Math.min(columnIndex + colSpan, columnsLength - 1),
leftVisibleCellIndex: columnIndex
});
}
setCellColSpanInfo(rowId, columnIndex, {
spannedByColSpan: false,
cellProps: {
colSpan,
width
}
});
}
return {
colSpan
};
}, [apiRef, setCellColSpanInfo]);
// Calculate `colSpan` for each cell in the row
const calculateColSpan = React.useCallback(({
rowId,
minFirstColumn,
maxLastColumn,
columns
}) => {
for (let i = minFirstColumn; i < maxLastColumn; i += 1) {
const cellProps = calculateCellColSpan({
columnIndex: i,
rowId,
minFirstColumnIndex: minFirstColumn,
maxLastColumnIndex: maxLastColumn,
columns
});
if (cellProps.colSpan > 1) {
i += cellProps.colSpan - 1;
}
}
}, [calculateCellColSpan]);
const columnSpanningPublicApi = {
unstable_getCellColSpanInfo: getCellColSpanInfo
};
const columnSpanningPrivateApi = {
calculateColSpan
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, columnSpanningPublicApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, columnSpanningPrivateApi, 'private');
const handleColumnReorderChange = React.useCallback(() => {
// `colSpan` needs to be recalculated after column reordering
lookup.current = {};
}, []);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnOrderChange', handleColumnReorderChange);
};
exports.useGridColumnSpanning = useGridColumnSpanning;

View File

@@ -0,0 +1,313 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.columnsStateInitializer = void 0;
exports.useGridColumns = useGridColumns;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridColumnsSelector = require("./gridColumnsSelector");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridColumnsUtils = require("./gridColumnsUtils");
var _preferencesPanel = require("../preferencesPanel");
var _colDef = require("../../../colDef");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const defaultColumnTypes = (0, _colDef.getGridDefaultColumnTypes)();
const columnsStateInitializer = (state, props, apiRef) => {
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes: defaultColumnTypes,
columnsToUpsert: props.columns,
initialState: props.initialState?.columns,
columnVisibilityModel: props.columnVisibilityModel ?? props.initialState?.columns?.columnVisibilityModel ?? {},
keepOnlyColumnsToUpsert: true
});
return (0, _extends2.default)({}, state, {
columns: columnsState
});
};
/**
* @requires useGridParamsApi (method)
* @requires useGridDimensions (method, event) - can be after
* TODO: Impossible priority - useGridParamsApi also needs to be after useGridColumns
*/
exports.columnsStateInitializer = columnsStateInitializer;
function useGridColumns(apiRef, props) {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridColumns');
const columnTypes = defaultColumnTypes;
const previousColumnsProp = React.useRef(props.columns);
const previousColumnTypesProp = React.useRef(columnTypes);
apiRef.current.registerControlState({
stateId: 'visibleColumns',
propModel: props.columnVisibilityModel,
propOnChange: props.onColumnVisibilityModelChange,
stateSelector: _gridColumnsSelector.gridColumnVisibilityModelSelector,
changeEvent: 'columnVisibilityModelChange'
});
const setGridColumnsState = React.useCallback(columnsState => {
logger.debug('Updating columns state.');
apiRef.current.setState((0, _gridColumnsUtils.mergeColumnsState)(columnsState));
apiRef.current.forceUpdate();
apiRef.current.publishEvent('columnsChange', columnsState.orderedFields);
}, [logger, apiRef]);
/**
* API METHODS
*/
const getColumn = React.useCallback(field => (0, _gridColumnsSelector.gridColumnLookupSelector)(apiRef)[field], [apiRef]);
const getAllColumns = React.useCallback(() => (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef), [apiRef]);
const getVisibleColumns = React.useCallback(() => (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef), [apiRef]);
const getColumnIndex = React.useCallback((field, useVisibleColumns = true) => {
const columns = useVisibleColumns ? (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef) : (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef);
return columns.findIndex(col => col.field === field);
}, [apiRef]);
const getColumnPosition = React.useCallback(field => {
const index = getColumnIndex(field);
return (0, _gridColumnsSelector.gridColumnPositionsSelector)(apiRef)[index];
}, [apiRef, getColumnIndex]);
const setColumnVisibilityModel = React.useCallback(model => {
const currentModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
if (currentModel !== model) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
columns: (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: [],
initialState: undefined,
columnVisibilityModel: model,
keepOnlyColumnsToUpsert: false
})
}));
apiRef.current.forceUpdate();
}
}, [apiRef, columnTypes]);
const updateColumns = React.useCallback(columns => {
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: columns,
initialState: undefined,
keepOnlyColumnsToUpsert: false
});
setGridColumnsState(columnsState);
}, [apiRef, setGridColumnsState, columnTypes]);
const setColumnVisibility = React.useCallback((field, isVisible) => {
const columnVisibilityModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const isCurrentlyVisible = columnVisibilityModel[field] ?? true;
if (isVisible !== isCurrentlyVisible) {
const newModel = (0, _extends2.default)({}, columnVisibilityModel, {
[field]: isVisible
});
apiRef.current.setColumnVisibilityModel(newModel);
}
}, [apiRef]);
const getColumnIndexRelativeToVisibleColumns = React.useCallback(field => {
const allColumns = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
return allColumns.findIndex(col => col === field);
}, [apiRef]);
const setColumnIndex = React.useCallback((field, targetIndexPosition) => {
const allColumns = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
const oldIndexPosition = getColumnIndexRelativeToVisibleColumns(field);
if (oldIndexPosition === targetIndexPosition) {
return;
}
logger.debug(`Moving column ${field} to index ${targetIndexPosition}`);
const updatedColumns = [...allColumns];
const fieldRemoved = updatedColumns.splice(oldIndexPosition, 1)[0];
updatedColumns.splice(targetIndexPosition, 0, fieldRemoved);
setGridColumnsState((0, _extends2.default)({}, (0, _gridColumnsSelector.gridColumnsStateSelector)(apiRef.current.state), {
orderedFields: updatedColumns
}));
const params = {
column: apiRef.current.getColumn(field),
targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(field),
oldIndex: oldIndexPosition
};
apiRef.current.publishEvent('columnIndexChange', params);
}, [apiRef, logger, setGridColumnsState, getColumnIndexRelativeToVisibleColumns]);
const setColumnWidth = React.useCallback((field, width) => {
logger.debug(`Updating column ${field} width to ${width}`);
const columnsState = (0, _gridColumnsSelector.gridColumnsStateSelector)(apiRef.current.state);
const column = columnsState.lookup[field];
const newColumn = (0, _extends2.default)({}, column, {
width,
hasBeenResized: true
});
setGridColumnsState((0, _gridColumnsUtils.hydrateColumnsWidth)((0, _extends2.default)({}, columnsState, {
lookup: (0, _extends2.default)({}, columnsState.lookup, {
[field]: newColumn
})
}), apiRef.current.getRootDimensions()?.viewportInnerSize.width ?? 0));
apiRef.current.publishEvent('columnWidthChange', {
element: apiRef.current.getColumnHeaderElement(field),
colDef: newColumn,
width
});
}, [apiRef, logger, setGridColumnsState]);
const columnApi = {
getColumn,
getAllColumns,
getColumnIndex,
getColumnPosition,
getVisibleColumns,
getColumnIndexRelativeToVisibleColumns,
updateColumns,
setColumnVisibilityModel,
setColumnVisibility,
setColumnWidth
};
const columnReorderApi = {
setColumnIndex
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, columnApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, columnReorderApi, props.signature === _useGridApiEventHandler.GridSignature.DataGrid ? 'private' : 'public');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const columnsStateToExport = {};
const columnVisibilityModelToExport = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const shouldExportColumnVisibilityModel =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the model is controlled
props.columnVisibilityModel != null ||
// Always export if the model has been initialized
// TODO v6 Do a nullish check instead to export even if the initial model equals "{}"
Object.keys(props.initialState?.columns?.columnVisibilityModel ?? {}).length > 0 ||
// Always export if the model is not empty
Object.keys(columnVisibilityModelToExport).length > 0;
if (shouldExportColumnVisibilityModel) {
columnsStateToExport.columnVisibilityModel = columnVisibilityModelToExport;
}
columnsStateToExport.orderedFields = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
const columns = (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef);
const dimensions = {};
columns.forEach(colDef => {
if (colDef.hasBeenResized) {
const colDefDimensions = {};
_gridColumnsUtils.COLUMNS_DIMENSION_PROPERTIES.forEach(propertyName => {
let propertyValue = colDef[propertyName];
if (propertyValue === Infinity) {
propertyValue = -1;
}
colDefDimensions[propertyName] = propertyValue;
});
dimensions[colDef.field] = colDefDimensions;
}
});
if (Object.keys(dimensions).length > 0) {
columnsStateToExport.dimensions = dimensions;
}
return (0, _extends2.default)({}, prevState, {
columns: columnsStateToExport
});
}, [apiRef, props.columnVisibilityModel, props.initialState?.columns]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const columnVisibilityModelToImport = context.stateToRestore.columns?.columnVisibilityModel;
const initialState = context.stateToRestore.columns;
if (columnVisibilityModelToImport == null && initialState == null) {
return params;
}
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: [],
initialState,
columnVisibilityModel: columnVisibilityModelToImport,
keepOnlyColumnsToUpsert: false
});
apiRef.current.setState((0, _gridColumnsUtils.mergeColumnsState)(columnsState));
if (initialState != null) {
apiRef.current.publishEvent('columnsChange', columnsState.orderedFields);
}
return params;
}, [apiRef, columnTypes]);
const preferencePanelPreProcessing = React.useCallback((initialValue, value) => {
if (value === _preferencesPanel.GridPreferencePanelsValue.columns) {
const ColumnsPanel = props.slots.columnsPanel;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ColumnsPanel, (0, _extends2.default)({}, props.slotProps?.columnsPanel));
}
return initialValue;
}, [props.slots.columnsPanel, props.slotProps?.columnsPanel]);
const addColumnMenuItems = React.useCallback(columnMenuItems => {
if (props.disableColumnSelector) {
return columnMenuItems;
}
return [...columnMenuItems, 'columnMenuColumnsItem'];
}, [props.disableColumnSelector]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'columnMenu', addColumnMenuItems);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'preferencePanel', preferencePanelPreProcessing);
/**
* EVENTS
*/
const prevInnerWidth = React.useRef(null);
const handleGridSizeChange = viewportInnerSize => {
if (prevInnerWidth.current !== viewportInnerSize.width) {
prevInnerWidth.current = viewportInnerSize.width;
setGridColumnsState((0, _gridColumnsUtils.hydrateColumnsWidth)((0, _gridColumnsSelector.gridColumnsStateSelector)(apiRef.current.state), viewportInnerSize.width));
}
};
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'viewportInnerSizeChange', handleGridSizeChange);
/**
* APPLIERS
*/
const hydrateColumns = React.useCallback(() => {
logger.info(`Columns pipe processing have changed, regenerating the columns`);
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: [],
initialState: undefined,
keepOnlyColumnsToUpsert: false
});
setGridColumnsState(columnsState);
}, [apiRef, logger, setGridColumnsState, columnTypes]);
(0, _pipeProcessing.useGridRegisterPipeApplier)(apiRef, 'hydrateColumns', hydrateColumns);
/**
* EFFECTS
*/
// The effect do not track any value defined synchronously during the 1st render by hooks called after `useGridColumns`
// As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
logger.info(`GridColumns have changed, new length ${props.columns.length}`);
if (previousColumnsProp.current === props.columns && previousColumnTypesProp.current === columnTypes) {
return;
}
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
initialState: undefined,
// If the user provides a model, we don't want to set it in the state here because it has it's dedicated `useEffect` which calls `setColumnVisibilityModel`
columnsToUpsert: props.columns,
keepOnlyColumnsToUpsert: true
});
previousColumnsProp.current = props.columns;
previousColumnTypesProp.current = columnTypes;
setGridColumnsState(columnsState);
}, [logger, apiRef, setGridColumnsState, props.columns, columnTypes]);
React.useEffect(() => {
if (props.columnVisibilityModel !== undefined) {
apiRef.current.setColumnVisibilityModel(props.columnVisibilityModel);
}
}, [apiRef, logger, props.columnVisibilityModel]);
}

View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridDensityValueSelector = exports.gridDensitySelector = exports.gridDensityFactorSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
const gridDensitySelector = state => state.density;
exports.gridDensitySelector = gridDensitySelector;
const gridDensityValueSelector = exports.gridDensityValueSelector = (0, _createSelector.createSelector)(gridDensitySelector, density => density.value);
const gridDensityFactorSelector = exports.gridDensityFactorSelector = (0, _createSelector.createSelector)(gridDensitySelector, density => density.factor);

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _densityState = require("./densityState");
Object.keys(_densityState).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _densityState[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _densityState[key];
}
});
});
var _densitySelector = require("./densitySelector");
Object.keys(_densitySelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _densitySelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _densitySelector[key];
}
});
});

View File

@@ -0,0 +1,57 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridDensity = exports.densityStateInitializer = exports.COMPACT_DENSITY_FACTOR = exports.COMFORTABLE_DENSITY_FACTOR = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridLogger = require("../../utils/useGridLogger");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _densitySelector = require("./densitySelector");
var _utils = require("../../../utils/utils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const COMPACT_DENSITY_FACTOR = exports.COMPACT_DENSITY_FACTOR = 0.7;
const COMFORTABLE_DENSITY_FACTOR = exports.COMFORTABLE_DENSITY_FACTOR = 1.3;
const DENSITY_FACTORS = {
compact: COMPACT_DENSITY_FACTOR,
comfortable: COMFORTABLE_DENSITY_FACTOR,
standard: 1
};
const densityStateInitializer = (state, props) => (0, _extends2.default)({}, state, {
density: {
value: props.density,
factor: DENSITY_FACTORS[props.density]
}
});
exports.densityStateInitializer = densityStateInitializer;
const useGridDensity = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useDensity');
const setDensity = React.useCallback(newDensity => {
logger.debug(`Set grid density to ${newDensity}`);
apiRef.current.setState(state => {
const currentDensityState = (0, _densitySelector.gridDensitySelector)(state);
const newDensityState = {
value: newDensity,
factor: DENSITY_FACTORS[newDensity]
};
if ((0, _utils.isDeepEqual)(currentDensityState, newDensityState)) {
return state;
}
return (0, _extends2.default)({}, state, {
density: newDensityState
});
});
apiRef.current.forceUpdate();
}, [logger, apiRef]);
React.useEffect(() => {
apiRef.current.setDensity(props.density);
}, [apiRef, props.density]);
const densityApi = {
setDensity
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, densityApi, 'public');
};
exports.useGridDensity = useGridDensity;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,224 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridDimensions = useGridDimensions;
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _columns = require("../columns");
var _density = require("../density");
var _utils2 = require("../../utils");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _gridRowsMetaSelector = require("../rows/gridRowsMetaSelector");
var _gridRowsUtils = require("../rows/gridRowsUtils");
var _gridColumnsUtils = require("../columns/gridColumnsUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const isTestEnvironment = process.env.NODE_ENV === 'test';
const hasScroll = ({
content,
container,
scrollBarSize
}) => {
const hasScrollXIfNoYScrollBar = content.width > container.width;
const hasScrollYIfNoXScrollBar = content.height > container.height;
let hasScrollX = false;
let hasScrollY = false;
if (hasScrollXIfNoYScrollBar || hasScrollYIfNoXScrollBar) {
hasScrollX = hasScrollXIfNoYScrollBar;
hasScrollY = content.height + (hasScrollX ? scrollBarSize : 0) > container.height;
// We recalculate the scroll x to consider the size of the y scrollbar.
if (hasScrollY) {
hasScrollX = content.width + scrollBarSize > container.width;
}
}
return {
hasScrollX,
hasScrollY
};
};
function useGridDimensions(apiRef, props) {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useResizeContainer');
const errorShown = React.useRef(false);
const rootDimensionsRef = React.useRef(null);
const fullDimensionsRef = React.useRef(null);
const rowsMeta = (0, _utils2.useGridSelector)(apiRef, _gridRowsMetaSelector.gridRowsMetaSelector);
const densityFactor = (0, _utils2.useGridSelector)(apiRef, _density.gridDensityFactorSelector);
const rowHeight = Math.floor(props.rowHeight * densityFactor);
const totalHeaderHeight = (0, _gridColumnsUtils.getTotalHeaderHeight)(apiRef, props.columnHeaderHeight);
const updateGridDimensionsRef = React.useCallback(() => {
const rootElement = apiRef.current.rootElementRef?.current;
const columnsTotalWidth = (0, _columns.gridColumnsTotalWidthSelector)(apiRef);
const pinnedRowsHeight = (0, _gridRowsUtils.calculatePinnedRowsHeight)(apiRef);
if (!rootDimensionsRef.current) {
return;
}
let scrollBarSize;
if (props.scrollbarSize != null) {
scrollBarSize = props.scrollbarSize;
} else if (!columnsTotalWidth || !rootElement) {
scrollBarSize = 0;
} else {
const doc = (0, _utils.unstable_ownerDocument)(rootElement);
const scrollDiv = doc.createElement('div');
scrollDiv.style.width = '99px';
scrollDiv.style.height = '99px';
scrollDiv.style.position = 'absolute';
scrollDiv.style.overflow = 'scroll';
scrollDiv.className = 'scrollDiv';
rootElement.appendChild(scrollDiv);
scrollBarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
rootElement.removeChild(scrollDiv);
}
let viewportOuterSize;
let hasScrollX;
let hasScrollY;
if (props.autoHeight) {
hasScrollY = false;
hasScrollX = Math.round(columnsTotalWidth) > Math.round(rootDimensionsRef.current.width);
viewportOuterSize = {
width: rootDimensionsRef.current.width,
height: rowsMeta.currentPageTotalHeight + (hasScrollX ? scrollBarSize : 0)
};
} else {
viewportOuterSize = {
width: rootDimensionsRef.current.width,
height: Math.max(rootDimensionsRef.current.height - totalHeaderHeight, 0)
};
const scrollInformation = hasScroll({
content: {
width: Math.round(columnsTotalWidth),
height: rowsMeta.currentPageTotalHeight
},
container: {
width: Math.round(viewportOuterSize.width),
height: viewportOuterSize.height - pinnedRowsHeight.top - pinnedRowsHeight.bottom
},
scrollBarSize
});
hasScrollY = scrollInformation.hasScrollY;
hasScrollX = scrollInformation.hasScrollX;
}
const viewportInnerSize = {
width: viewportOuterSize.width - (hasScrollY ? scrollBarSize : 0),
height: viewportOuterSize.height - (hasScrollX ? scrollBarSize : 0)
};
const newFullDimensions = {
viewportOuterSize,
viewportInnerSize,
hasScrollX,
hasScrollY,
scrollBarSize
};
const prevDimensions = fullDimensionsRef.current;
fullDimensionsRef.current = newFullDimensions;
if (newFullDimensions.viewportInnerSize.width !== prevDimensions?.viewportInnerSize.width || newFullDimensions.viewportInnerSize.height !== prevDimensions?.viewportInnerSize.height) {
apiRef.current.publishEvent('viewportInnerSizeChange', newFullDimensions.viewportInnerSize);
}
}, [apiRef, props.scrollbarSize, props.autoHeight, rowsMeta.currentPageTotalHeight, totalHeaderHeight]);
const [savedSize, setSavedSize] = React.useState();
const debouncedSetSavedSize = React.useMemo(() => (0, _utils.unstable_debounce)(setSavedSize, 60), []);
const previousSize = React.useRef();
(0, _utils.unstable_useEnhancedEffect)(() => {
if (savedSize) {
updateGridDimensionsRef();
apiRef.current.publishEvent('debouncedResize', rootDimensionsRef.current);
}
}, [apiRef, savedSize, updateGridDimensionsRef]);
// This is the function called by apiRef.current.resize()
const resize = React.useCallback(() => {
apiRef.current.computeSizeAndPublishResizeEvent();
}, [apiRef]);
const getRootDimensions = React.useCallback(() => fullDimensionsRef.current, []);
const getViewportPageSize = React.useCallback(() => {
const dimensions = apiRef.current.getRootDimensions();
if (!dimensions) {
return 0;
}
const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef, {
pagination: props.pagination,
paginationMode: props.paginationMode
});
// TODO: Use a combination of scrollTop, dimensions.viewportInnerSize.height and rowsMeta.possitions
// to find out the maximum number of rows that can fit in the visible part of the grid
if (props.getRowHeight) {
const renderContext = apiRef.current.getRenderContext();
const viewportPageSize = renderContext.lastRowIndex - renderContext.firstRowIndex;
return Math.min(viewportPageSize - 1, currentPage.rows.length);
}
const maximumPageSizeWithoutScrollBar = Math.floor(dimensions.viewportInnerSize.height / rowHeight);
return Math.min(maximumPageSizeWithoutScrollBar, currentPage.rows.length);
}, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]);
const computeSizeAndPublishResizeEvent = React.useCallback(() => {
const mainEl = apiRef.current.mainElementRef?.current;
if (!mainEl) {
return;
}
const win = (0, _utils.unstable_ownerWindow)(mainEl);
const computedStyle = win.getComputedStyle(mainEl);
const height = parseFloat(computedStyle.height) || 0;
const width = parseFloat(computedStyle.width) || 0;
const hasHeightChanged = height !== previousSize.current?.height;
const hasWidthChanged = width !== previousSize.current?.width;
if (!previousSize.current || hasHeightChanged || hasWidthChanged) {
const size = {
width,
height
};
apiRef.current.publishEvent('resize', size);
previousSize.current = size;
}
}, [apiRef]);
const dimensionsApi = {
resize,
getRootDimensions
};
const dimensionsPrivateApi = {
getViewportPageSize,
updateGridDimensionsRef,
computeSizeAndPublishResizeEvent
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, dimensionsApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, dimensionsPrivateApi, 'private');
const isFirstSizing = React.useRef(true);
const handleResize = React.useCallback(size => {
rootDimensionsRef.current = size;
// jsdom has no layout capabilities
const isJSDOM = /jsdom/.test(window.navigator.userAgent);
if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) {
logger.error(['The parent DOM element of the data grid has an empty height.', 'Please make sure that this element has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
errorShown.current = true;
}
if (size.width === 0 && !errorShown.current && !isJSDOM) {
logger.error(['The parent DOM element of the data grid has an empty width.', 'Please make sure that this element has an intrinsic width.', 'The grid displays with a width of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
errorShown.current = true;
}
if (isTestEnvironment) {
// We don't need to debounce the resize for tests.
setSavedSize(size);
isFirstSizing.current = false;
return;
}
if (isFirstSizing.current) {
// We want to initialize the grid dimensions as soon as possible to avoid flickering
setSavedSize(size);
isFirstSizing.current = false;
return;
}
debouncedSetSavedSize(size);
}, [props.autoHeight, debouncedSetSavedSize, logger]);
(0, _utils.unstable_useEnhancedEffect)(() => updateGridDimensionsRef(), [updateGridDimensionsRef]);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'sortedRowsSet', updateGridDimensionsRef);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'paginationModelChange', updateGridDimensionsRef);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnsChange', updateGridDimensionsRef);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'resize', handleResize);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'debouncedResize', props.onResize);
}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridEditRowsStateSelector = void 0;
// TODO v6: rename to gridEditingStateSelector
const gridEditRowsStateSelector = state => state.editRows;
exports.gridEditRowsStateSelector = gridEditRowsStateSelector;

View File

@@ -0,0 +1,445 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridCellEditing = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _toPropertyKey2 = _interopRequireDefault(require("@babel/runtime/helpers/toPropertyKey"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridEditingSelectors = require("./gridEditingSelectors");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _warning = require("../../../utils/warning");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _utils2 = require("../../../utils/utils");
var _gridEditCellParams = require("../../../models/params/gridEditCellParams");
const _excluded = ["id", "field"],
_excluded2 = ["id", "field"];
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const missingOnProcessRowUpdateErrorWarning = (0, _warning.buildWarning)(['MUI: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see http://mui.com/components/data-grid/editing/#server-side-persistence.'], 'error');
const useGridCellEditing = (apiRef, props) => {
const [cellModesModel, setCellModesModel] = React.useState({});
const cellModesModelRef = React.useRef(cellModesModel);
const prevCellModesModel = React.useRef({});
const {
processRowUpdate,
onProcessRowUpdateError,
cellModesModel: cellModesModelProp,
onCellModesModelChange
} = props;
const runIfEditModeIsCell = callback => (...args) => {
if (props.editMode === _gridEditRowModel.GridEditModes.Cell) {
callback(...args);
}
};
const throwIfNotEditable = React.useCallback((id, field) => {
const params = apiRef.current.getCellParams(id, field);
if (!apiRef.current.isCellEditable(params)) {
throw new Error(`MUI: The cell with id=${id} and field=${field} is not editable.`);
}
}, [apiRef]);
const throwIfNotInMode = React.useCallback((id, field, mode) => {
if (apiRef.current.getCellMode(id, field) !== mode) {
throw new Error(`MUI: The cell with id=${id} and field=${field} is not in ${mode} mode.`);
}
}, [apiRef]);
const handleCellDoubleClick = React.useCallback((params, event) => {
if (!params.isEditable) {
return;
}
if (params.cellMode === _gridEditRowModel.GridCellModes.Edit) {
return;
}
const newParams = (0, _extends2.default)({}, params, {
reason: _gridEditCellParams.GridCellEditStartReasons.cellDoubleClick
});
apiRef.current.publishEvent('cellEditStart', newParams, event);
}, [apiRef]);
const handleCellFocusOut = React.useCallback((params, event) => {
if (params.cellMode === _gridEditRowModel.GridCellModes.View) {
return;
}
if (apiRef.current.getCellMode(params.id, params.field) === _gridEditRowModel.GridCellModes.View) {
return;
}
const newParams = (0, _extends2.default)({}, params, {
reason: _gridEditCellParams.GridCellEditStopReasons.cellFocusOut
});
apiRef.current.publishEvent('cellEditStop', newParams, event);
}, [apiRef]);
const handleCellKeyDown = React.useCallback((params, event) => {
if (params.cellMode === _gridEditRowModel.GridCellModes.Edit) {
// Wait until IME is settled for Asian languages like Japanese and Chinese
// TODO: `event.which` is deprecated but this is a temporary workaround
if (event.which === 229) {
return;
}
let reason;
if (event.key === 'Escape') {
reason = _gridEditCellParams.GridCellEditStopReasons.escapeKeyDown;
} else if (event.key === 'Enter') {
reason = _gridEditCellParams.GridCellEditStopReasons.enterKeyDown;
} else if (event.key === 'Tab') {
reason = event.shiftKey ? _gridEditCellParams.GridCellEditStopReasons.shiftTabKeyDown : _gridEditCellParams.GridCellEditStopReasons.tabKeyDown;
event.preventDefault(); // Prevent going to the next element in the tab sequence
}
if (reason) {
const newParams = (0, _extends2.default)({}, params, {
reason
});
apiRef.current.publishEvent('cellEditStop', newParams, event);
}
} else if (params.isEditable) {
let reason;
const canStartEditing = apiRef.current.unstable_applyPipeProcessors('canStartEditing', true, {
event,
cellParams: params,
editMode: 'cell'
});
if (!canStartEditing) {
return;
}
if ((0, _keyboardUtils.isPrintableKey)(event)) {
reason = _gridEditCellParams.GridCellEditStartReasons.printableKeyDown;
} else if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
reason = _gridEditCellParams.GridCellEditStartReasons.pasteKeyDown;
} else if (event.key === 'Enter') {
reason = _gridEditCellParams.GridCellEditStartReasons.enterKeyDown;
} else if (event.key === 'Delete' || event.key === 'Backspace') {
// Delete on Windows, Backspace on macOS
reason = _gridEditCellParams.GridCellEditStartReasons.deleteKeyDown;
}
if (reason) {
const newParams = (0, _extends2.default)({}, params, {
reason,
key: event.key
});
apiRef.current.publishEvent('cellEditStart', newParams, event);
}
}
}, [apiRef]);
const handleCellEditStart = React.useCallback(params => {
const {
id,
field,
reason
} = params;
const startCellEditModeParams = {
id,
field
};
if (reason === _gridEditCellParams.GridCellEditStartReasons.printableKeyDown || reason === _gridEditCellParams.GridCellEditStartReasons.deleteKeyDown || reason === _gridEditCellParams.GridCellEditStartReasons.pasteKeyDown) {
startCellEditModeParams.deleteValue = true;
}
apiRef.current.startCellEditMode(startCellEditModeParams);
}, [apiRef]);
const handleCellEditStop = React.useCallback(params => {
const {
id,
field,
reason
} = params;
apiRef.current.runPendingEditCellValueMutation(id, field);
let cellToFocusAfter;
if (reason === _gridEditCellParams.GridCellEditStopReasons.enterKeyDown) {
cellToFocusAfter = 'below';
} else if (reason === _gridEditCellParams.GridCellEditStopReasons.tabKeyDown) {
cellToFocusAfter = 'right';
} else if (reason === _gridEditCellParams.GridCellEditStopReasons.shiftTabKeyDown) {
cellToFocusAfter = 'left';
}
const ignoreModifications = reason === 'escapeKeyDown';
apiRef.current.stopCellEditMode({
id,
field,
ignoreModifications,
cellToFocusAfter
});
}, [apiRef]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', runIfEditModeIsCell(handleCellDoubleClick));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusOut', runIfEditModeIsCell(handleCellFocusOut));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', runIfEditModeIsCell(handleCellKeyDown));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellEditStart', runIfEditModeIsCell(handleCellEditStart));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellEditStop', runIfEditModeIsCell(handleCellEditStop));
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellEditStart', props.onCellEditStart);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellEditStop', props.onCellEditStop);
const getCellMode = React.useCallback((id, field) => {
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const isEditing = editingState[id] && editingState[id][field];
return isEditing ? _gridEditRowModel.GridCellModes.Edit : _gridEditRowModel.GridCellModes.View;
}, [apiRef]);
const updateCellModesModel = (0, _utils.unstable_useEventCallback)(newModel => {
const isNewModelDifferentFromProp = newModel !== props.cellModesModel;
if (onCellModesModelChange && isNewModelDifferentFromProp) {
onCellModesModelChange(newModel, {});
}
if (props.cellModesModel && isNewModelDifferentFromProp) {
return; // The prop always win
}
setCellModesModel(newModel);
cellModesModelRef.current = newModel;
apiRef.current.publishEvent('cellModesModelChange', newModel);
});
const updateFieldInCellModesModel = React.useCallback((id, field, newProps) => {
// We use the ref because it always contain the up-to-date value, different from the state
// that needs a rerender to reflect the new value
const newModel = (0, _extends2.default)({}, cellModesModelRef.current);
if (newProps !== null) {
newModel[id] = (0, _extends2.default)({}, newModel[id], {
[field]: (0, _extends2.default)({}, newProps)
});
} else {
const _newModel$id = newModel[id],
otherFields = (0, _objectWithoutPropertiesLoose2.default)(_newModel$id, [field].map(_toPropertyKey2.default)); // Ensure that we have a new object, not a reference
newModel[id] = otherFields;
if (Object.keys(newModel[id]).length === 0) {
delete newModel[id];
}
}
updateCellModesModel(newModel);
}, [updateCellModesModel]);
const updateOrDeleteFieldState = React.useCallback((id, field, newProps) => {
apiRef.current.setState(state => {
const newEditingState = (0, _extends2.default)({}, state.editRows);
if (newProps !== null) {
newEditingState[id] = (0, _extends2.default)({}, newEditingState[id], {
[field]: (0, _extends2.default)({}, newProps)
});
} else {
delete newEditingState[id][field];
if (Object.keys(newEditingState[id]).length === 0) {
delete newEditingState[id];
}
}
return (0, _extends2.default)({}, state, {
editRows: newEditingState
});
});
apiRef.current.forceUpdate();
}, [apiRef]);
const startCellEditMode = React.useCallback(params => {
const {
id,
field
} = params,
other = (0, _objectWithoutPropertiesLoose2.default)(params, _excluded);
throwIfNotEditable(id, field);
throwIfNotInMode(id, field, _gridEditRowModel.GridCellModes.View);
updateFieldInCellModesModel(id, field, (0, _extends2.default)({
mode: _gridEditRowModel.GridCellModes.Edit
}, other));
}, [throwIfNotEditable, throwIfNotInMode, updateFieldInCellModesModel]);
const updateStateToStartCellEditMode = (0, _utils.unstable_useEventCallback)(params => {
const {
id,
field,
deleteValue,
initialValue
} = params;
let newValue = apiRef.current.getCellValue(id, field);
if (deleteValue || initialValue) {
newValue = deleteValue ? '' : initialValue;
}
const newProps = {
value: newValue,
error: false,
isProcessingProps: false
};
updateOrDeleteFieldState(id, field, newProps);
apiRef.current.setCellFocus(id, field);
});
const stopCellEditMode = React.useCallback(params => {
const {
id,
field
} = params,
other = (0, _objectWithoutPropertiesLoose2.default)(params, _excluded2);
throwIfNotInMode(id, field, _gridEditRowModel.GridCellModes.Edit);
updateFieldInCellModesModel(id, field, (0, _extends2.default)({
mode: _gridEditRowModel.GridCellModes.View
}, other));
}, [throwIfNotInMode, updateFieldInCellModesModel]);
const updateStateToStopCellEditMode = (0, _utils.unstable_useEventCallback)(async params => {
const {
id,
field,
ignoreModifications,
cellToFocusAfter = 'none'
} = params;
throwIfNotInMode(id, field, _gridEditRowModel.GridCellModes.Edit);
apiRef.current.runPendingEditCellValueMutation(id, field);
const finishCellEditMode = () => {
updateOrDeleteFieldState(id, field, null);
updateFieldInCellModesModel(id, field, null);
if (cellToFocusAfter !== 'none') {
apiRef.current.moveFocusToRelativeCell(id, field, cellToFocusAfter);
}
};
if (ignoreModifications) {
finishCellEditMode();
return;
}
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const {
error,
isProcessingProps
} = editingState[id][field];
if (error || isProcessingProps) {
// Attempt to change cell mode to "view" was not successful
// Update previous mode to allow another attempt
prevCellModesModel.current[id][field].mode = _gridEditRowModel.GridCellModes.Edit;
// Revert the mode in the cellModesModel prop back to "edit"
updateFieldInCellModesModel(id, field, {
mode: _gridEditRowModel.GridCellModes.Edit
});
return;
}
const rowUpdate = apiRef.current.getRowWithUpdatedValuesFromCellEditing(id, field);
if (processRowUpdate) {
const handleError = errorThrown => {
prevCellModesModel.current[id][field].mode = _gridEditRowModel.GridCellModes.Edit;
// Revert the mode in the cellModesModel prop back to "edit"
updateFieldInCellModesModel(id, field, {
mode: _gridEditRowModel.GridCellModes.Edit
});
if (onProcessRowUpdateError) {
onProcessRowUpdateError(errorThrown);
} else {
missingOnProcessRowUpdateErrorWarning();
}
};
try {
const row = apiRef.current.getRow(id);
Promise.resolve(processRowUpdate(rowUpdate, row)).then(finalRowUpdate => {
apiRef.current.updateRows([finalRowUpdate]);
finishCellEditMode();
}).catch(handleError);
} catch (errorThrown) {
handleError(errorThrown);
}
} else {
apiRef.current.updateRows([rowUpdate]);
finishCellEditMode();
}
});
const setCellEditingEditCellValue = React.useCallback(async params => {
const {
id,
field,
value,
debounceMs,
unstable_skipValueParser: skipValueParser
} = params;
throwIfNotEditable(id, field);
throwIfNotInMode(id, field, _gridEditRowModel.GridCellModes.Edit);
const column = apiRef.current.getColumn(field);
const row = apiRef.current.getRow(id);
let parsedValue = value;
if (column.valueParser && !skipValueParser) {
parsedValue = column.valueParser(value, apiRef.current.getCellParams(id, field));
}
let editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
let newProps = (0, _extends2.default)({}, editingState[id][field], {
value: parsedValue,
changeReason: debounceMs ? 'debouncedSetEditCellValue' : 'setEditCellValue'
});
if (column.preProcessEditCellProps) {
const hasChanged = value !== editingState[id][field].value;
newProps = (0, _extends2.default)({}, newProps, {
isProcessingProps: true
});
updateOrDeleteFieldState(id, field, newProps);
newProps = await Promise.resolve(column.preProcessEditCellProps({
id,
row,
props: newProps,
hasChanged
}));
}
// Check again if the cell is in edit mode because the user may have
// discarded the changes while the props were being processed.
if (apiRef.current.getCellMode(id, field) === _gridEditRowModel.GridCellModes.View) {
return false;
}
editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
newProps = (0, _extends2.default)({}, newProps, {
isProcessingProps: false
});
// We don't update the value with the one coming from the props pre-processing
// because when the promise resolves it may be already outdated. The only
// exception to this rule is when there's no pre-processing.
newProps.value = column.preProcessEditCellProps ? editingState[id][field].value : parsedValue;
updateOrDeleteFieldState(id, field, newProps);
editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
return !editingState[id]?.[field]?.error;
}, [apiRef, throwIfNotEditable, throwIfNotInMode, updateOrDeleteFieldState]);
const getRowWithUpdatedValuesFromCellEditing = React.useCallback((id, field) => {
const column = apiRef.current.getColumn(field);
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const row = apiRef.current.getRow(id);
if (!editingState[id] || !editingState[id][field]) {
return apiRef.current.getRow(id);
}
const {
value
} = editingState[id][field];
return column.valueSetter ? column.valueSetter({
value,
row
}) : (0, _extends2.default)({}, row, {
[field]: value
});
}, [apiRef]);
const editingApi = {
getCellMode,
startCellEditMode,
stopCellEditMode
};
const editingPrivateApi = {
setCellEditingEditCellValue,
getRowWithUpdatedValuesFromCellEditing
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, editingApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, editingPrivateApi, 'private');
React.useEffect(() => {
if (cellModesModelProp) {
updateCellModesModel(cellModesModelProp);
}
}, [cellModesModelProp, updateCellModesModel]);
// Run this effect synchronously so that the keyboard event can impact the yet-to-be-rendered input.
(0, _utils.unstable_useEnhancedEffect)(() => {
const idToIdLookup = (0, _gridRowsSelector.gridRowsDataRowIdToIdLookupSelector)(apiRef);
// Update the ref here because updateStateToStopCellEditMode may change it later
const copyOfPrevCellModes = prevCellModesModel.current;
prevCellModesModel.current = (0, _utils2.deepClone)(cellModesModel); // Do a deep-clone because the attributes might be changed later
Object.entries(cellModesModel).forEach(([id, fields]) => {
Object.entries(fields).forEach(([field, params]) => {
const prevMode = copyOfPrevCellModes[id]?.[field]?.mode || _gridEditRowModel.GridCellModes.View;
const originalId = idToIdLookup[id] ?? id;
if (params.mode === _gridEditRowModel.GridCellModes.Edit && prevMode === _gridEditRowModel.GridCellModes.View) {
updateStateToStartCellEditMode((0, _extends2.default)({
id: originalId,
field
}, params));
} else if (params.mode === _gridEditRowModel.GridCellModes.View && prevMode === _gridEditRowModel.GridCellModes.Edit) {
updateStateToStopCellEditMode((0, _extends2.default)({
id: originalId,
field
}, params));
}
});
});
}, [apiRef, cellModesModel, updateStateToStartCellEditMode, updateStateToStopCellEditMode]);
};
exports.useGridCellEditing = useGridCellEditing;

View File

@@ -0,0 +1,134 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridEditing = exports.editingStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridCellEditing = require("./useGridCellEditing");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _useGridRowEditing = require("./useGridRowEditing");
var _gridEditingSelectors = require("./gridEditingSelectors");
var _gridRowsUtils = require("../rows/gridRowsUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const editingStateInitializer = state => (0, _extends2.default)({}, state, {
editRows: {}
});
exports.editingStateInitializer = editingStateInitializer;
const useGridEditing = (apiRef, props) => {
(0, _useGridCellEditing.useGridCellEditing)(apiRef, props);
(0, _useGridRowEditing.useGridRowEditing)(apiRef, props);
const debounceMap = React.useRef({});
const {
isCellEditable: isCellEditableProp
} = props;
const isCellEditable = React.useCallback(params => {
if ((0, _gridRowsUtils.isAutoGeneratedRow)(params.rowNode)) {
return false;
}
if (!params.colDef.editable) {
return false;
}
if (!params.colDef.renderEditCell) {
return false;
}
if (isCellEditableProp) {
return isCellEditableProp(params);
}
return true;
}, [isCellEditableProp]);
const maybeDebounce = (id, field, debounceMs, callback) => {
if (!debounceMs) {
callback();
return;
}
if (!debounceMap.current[id]) {
debounceMap.current[id] = {};
}
if (debounceMap.current[id][field]) {
const [timeout] = debounceMap.current[id][field];
clearTimeout(timeout);
}
// To run the callback immediately without waiting the timeout
const runImmediately = () => {
const [timeout] = debounceMap.current[id][field];
clearTimeout(timeout);
callback();
delete debounceMap.current[id][field];
};
const timeout = setTimeout(() => {
callback();
delete debounceMap.current[id][field];
}, debounceMs);
debounceMap.current[id][field] = [timeout, runImmediately];
};
React.useEffect(() => {
const debounces = debounceMap.current;
return () => {
Object.entries(debounces).forEach(([id, fields]) => {
Object.keys(fields).forEach(field => {
const [timeout] = debounces[id][field];
clearTimeout(timeout);
delete debounces[id][field];
});
});
};
}, []);
const runPendingEditCellValueMutation = React.useCallback((id, field) => {
if (!debounceMap.current[id]) {
return;
}
if (!field) {
Object.keys(debounceMap.current[id]).forEach(debouncedField => {
const [, runCallback] = debounceMap.current[id][debouncedField];
runCallback();
});
} else if (debounceMap.current[id][field]) {
const [, runCallback] = debounceMap.current[id][field];
runCallback();
}
}, []);
const setEditCellValue = React.useCallback(params => {
const {
id,
field,
debounceMs
} = params;
return new Promise(resolve => {
maybeDebounce(id, field, debounceMs, async () => {
const setEditCellValueToCall = props.editMode === _gridEditRowModel.GridEditModes.Row ? apiRef.current.setRowEditingEditCellValue : apiRef.current.setCellEditingEditCellValue;
// Check if the cell is in edit mode
// By the time this callback runs the user may have cancelled the editing
if (apiRef.current.getCellMode(id, field) === _gridEditRowModel.GridCellModes.Edit) {
const result = await setEditCellValueToCall(params);
resolve(result);
}
});
});
}, [apiRef, props.editMode]);
const getRowWithUpdatedValues = React.useCallback((id, field) => {
return props.editMode === _gridEditRowModel.GridEditModes.Cell ? apiRef.current.getRowWithUpdatedValuesFromCellEditing(id, field) : apiRef.current.getRowWithUpdatedValuesFromRowEditing(id);
}, [apiRef, props.editMode]);
const getEditCellMeta = React.useCallback((id, field) => {
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
return editingState[id]?.[field] ?? null;
}, [apiRef]);
const editingSharedApi = {
isCellEditable,
setEditCellValue,
getRowWithUpdatedValues,
unstable_getEditCellMeta: getEditCellMeta
};
const editingSharedPrivateApi = {
runPendingEditCellValueMutation
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, editingSharedApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, editingSharedPrivateApi, 'private');
};
exports.useGridEditing = useGridEditing;

View File

@@ -0,0 +1,571 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRowEditing = void 0;
var _toPropertyKey2 = _interopRequireDefault(require("@babel/runtime/helpers/toPropertyKey"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridEditingSelectors = require("./gridEditingSelectors");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _warning = require("../../../utils/warning");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _utils2 = require("../../../utils/utils");
var _gridRowParams = require("../../../models/params/gridRowParams");
var _colDef = require("../../../colDef");
const _excluded = ["id"],
_excluded2 = ["id"];
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const missingOnProcessRowUpdateErrorWarning = (0, _warning.buildWarning)(['MUI: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see http://mui.com/components/data-grid/editing/#server-side-persistence.'], 'error');
const useGridRowEditing = (apiRef, props) => {
const [rowModesModel, setRowModesModel] = React.useState({});
const rowModesModelRef = React.useRef(rowModesModel);
const prevRowModesModel = React.useRef({});
const focusTimeout = React.useRef(null);
const nextFocusedCell = React.useRef(null);
const {
processRowUpdate,
onProcessRowUpdateError,
rowModesModel: rowModesModelProp,
onRowModesModelChange
} = props;
const runIfEditModeIsRow = callback => (...args) => {
if (props.editMode === _gridEditRowModel.GridEditModes.Row) {
callback(...args);
}
};
const throwIfNotEditable = React.useCallback((id, field) => {
const params = apiRef.current.getCellParams(id, field);
if (!apiRef.current.isCellEditable(params)) {
throw new Error(`MUI: The cell with id=${id} and field=${field} is not editable.`);
}
}, [apiRef]);
const throwIfNotInMode = React.useCallback((id, mode) => {
if (apiRef.current.getRowMode(id) !== mode) {
throw new Error(`MUI: The row with id=${id} is not in ${mode} mode.`);
}
}, [apiRef]);
const handleCellDoubleClick = React.useCallback((params, event) => {
if (!params.isEditable) {
return;
}
if (apiRef.current.getRowMode(params.id) === _gridEditRowModel.GridRowModes.Edit) {
return;
}
const rowParams = apiRef.current.getRowParams(params.id);
const newParams = (0, _extends2.default)({}, rowParams, {
field: params.field,
reason: _gridRowParams.GridRowEditStartReasons.cellDoubleClick
});
apiRef.current.publishEvent('rowEditStart', newParams, event);
}, [apiRef]);
const handleCellFocusIn = React.useCallback(params => {
nextFocusedCell.current = params;
}, []);
const handleCellFocusOut = React.useCallback((params, event) => {
if (!params.isEditable) {
return;
}
if (apiRef.current.getRowMode(params.id) === _gridEditRowModel.GridRowModes.View) {
return;
}
// The mechanism to detect if we can stop editing a row is different from
// the cell editing. Instead of triggering it when clicking outside a cell,
// we must check if another cell in the same row was not clicked. To achieve
// that, first we keep track of all cells that gained focus. When a cell loses
// focus we check if the next cell that received focus is from a different row.
nextFocusedCell.current = null;
focusTimeout.current = setTimeout(() => {
focusTimeout.current = null;
if (nextFocusedCell.current?.id !== params.id) {
// The row might have been deleted during the click
if (!apiRef.current.getRow(params.id)) {
return;
}
// The row may already changed its mode
if (apiRef.current.getRowMode(params.id) === _gridEditRowModel.GridRowModes.View) {
return;
}
const rowParams = apiRef.current.getRowParams(params.id);
const newParams = (0, _extends2.default)({}, rowParams, {
field: params.field,
reason: _gridRowParams.GridRowEditStopReasons.rowFocusOut
});
apiRef.current.publishEvent('rowEditStop', newParams, event);
}
});
}, [apiRef]);
React.useEffect(() => {
return () => {
clearTimeout(focusTimeout.current);
};
}, []);
const handleCellKeyDown = React.useCallback((params, event) => {
if (params.cellMode === _gridEditRowModel.GridRowModes.Edit) {
// Wait until IME is settled for Asian languages like Japanese and Chinese
// TODO: `event.which` is deprecated but this is a temporary workaround
if (event.which === 229) {
return;
}
let reason;
if (event.key === 'Escape') {
reason = _gridRowParams.GridRowEditStopReasons.escapeKeyDown;
} else if (event.key === 'Enter') {
reason = _gridRowParams.GridRowEditStopReasons.enterKeyDown;
} else if (event.key === 'Tab') {
const columnFields = (0, _gridColumnsSelector.gridVisibleColumnFieldsSelector)(apiRef).filter(field => {
const column = apiRef.current.getColumn(field);
if (column.type === _colDef.GRID_ACTIONS_COLUMN_TYPE) {
return true;
}
return apiRef.current.isCellEditable(apiRef.current.getCellParams(params.id, field));
});
if (event.shiftKey) {
if (params.field === columnFields[0]) {
// Exit if user pressed Shift+Tab on the first field
reason = _gridRowParams.GridRowEditStopReasons.shiftTabKeyDown;
}
} else if (params.field === columnFields[columnFields.length - 1]) {
// Exit if user pressed Tab on the last field
reason = _gridRowParams.GridRowEditStopReasons.tabKeyDown;
}
// Always prevent going to the next element in the tab sequence because the focus is
// handled manually to support edit components rendered inside Portals
event.preventDefault();
if (!reason) {
const index = columnFields.findIndex(field => field === params.field);
const nextFieldToFocus = columnFields[event.shiftKey ? index - 1 : index + 1];
apiRef.current.setCellFocus(params.id, nextFieldToFocus);
}
}
if (reason) {
const newParams = (0, _extends2.default)({}, apiRef.current.getRowParams(params.id), {
reason,
field: params.field
});
apiRef.current.publishEvent('rowEditStop', newParams, event);
}
} else if (params.isEditable) {
let reason;
const canStartEditing = apiRef.current.unstable_applyPipeProcessors('canStartEditing', true, {
event,
cellParams: params,
editMode: 'row'
});
if (!canStartEditing) {
return;
}
if ((0, _keyboardUtils.isPrintableKey)(event)) {
reason = _gridRowParams.GridRowEditStartReasons.printableKeyDown;
} else if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
reason = _gridRowParams.GridRowEditStartReasons.printableKeyDown;
} else if (event.key === 'Enter') {
reason = _gridRowParams.GridRowEditStartReasons.enterKeyDown;
} else if (event.key === 'Delete' || event.key === 'Backspace') {
// Delete on Windows, Backspace on macOS
reason = _gridRowParams.GridRowEditStartReasons.deleteKeyDown;
}
if (reason) {
const rowParams = apiRef.current.getRowParams(params.id);
const newParams = (0, _extends2.default)({}, rowParams, {
field: params.field,
reason
});
apiRef.current.publishEvent('rowEditStart', newParams, event);
}
}
}, [apiRef]);
const handleRowEditStart = React.useCallback(params => {
const {
id,
field,
reason
} = params;
const startRowEditModeParams = {
id,
fieldToFocus: field
};
if (reason === _gridRowParams.GridRowEditStartReasons.printableKeyDown || reason === _gridRowParams.GridRowEditStartReasons.deleteKeyDown) {
startRowEditModeParams.deleteValue = !!field;
}
apiRef.current.startRowEditMode(startRowEditModeParams);
}, [apiRef]);
const handleRowEditStop = React.useCallback(params => {
const {
id,
reason,
field
} = params;
apiRef.current.runPendingEditCellValueMutation(id);
let cellToFocusAfter;
if (reason === _gridRowParams.GridRowEditStopReasons.enterKeyDown) {
cellToFocusAfter = 'below';
} else if (reason === _gridRowParams.GridRowEditStopReasons.tabKeyDown) {
cellToFocusAfter = 'right';
} else if (reason === _gridRowParams.GridRowEditStopReasons.shiftTabKeyDown) {
cellToFocusAfter = 'left';
}
const ignoreModifications = reason === 'escapeKeyDown';
apiRef.current.stopRowEditMode({
id,
ignoreModifications,
field,
cellToFocusAfter
});
}, [apiRef]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', runIfEditModeIsRow(handleCellDoubleClick));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusIn', runIfEditModeIsRow(handleCellFocusIn));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusOut', runIfEditModeIsRow(handleCellFocusOut));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', runIfEditModeIsRow(handleCellKeyDown));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowEditStart', runIfEditModeIsRow(handleRowEditStart));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowEditStop', runIfEditModeIsRow(handleRowEditStop));
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowEditStart', props.onRowEditStart);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowEditStop', props.onRowEditStop);
const getRowMode = React.useCallback(id => {
if (props.editMode === _gridEditRowModel.GridEditModes.Cell) {
return _gridEditRowModel.GridRowModes.View;
}
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const isEditing = editingState[id] && Object.keys(editingState[id]).length > 0;
return isEditing ? _gridEditRowModel.GridRowModes.Edit : _gridEditRowModel.GridRowModes.View;
}, [apiRef, props.editMode]);
const updateRowModesModel = (0, _utils.unstable_useEventCallback)(newModel => {
const isNewModelDifferentFromProp = newModel !== props.rowModesModel;
if (onRowModesModelChange && isNewModelDifferentFromProp) {
onRowModesModelChange(newModel, {});
}
if (props.rowModesModel && isNewModelDifferentFromProp) {
return; // The prop always win
}
setRowModesModel(newModel);
rowModesModelRef.current = newModel;
apiRef.current.publishEvent('rowModesModelChange', newModel);
});
const updateRowInRowModesModel = React.useCallback((id, newProps) => {
const newModel = (0, _extends2.default)({}, rowModesModelRef.current);
if (newProps !== null) {
newModel[id] = (0, _extends2.default)({}, newProps);
} else {
delete newModel[id];
}
updateRowModesModel(newModel);
}, [updateRowModesModel]);
const updateOrDeleteRowState = React.useCallback((id, newProps) => {
apiRef.current.setState(state => {
const newEditingState = (0, _extends2.default)({}, state.editRows);
if (newProps !== null) {
newEditingState[id] = newProps;
} else {
delete newEditingState[id];
}
return (0, _extends2.default)({}, state, {
editRows: newEditingState
});
});
apiRef.current.forceUpdate();
}, [apiRef]);
const updateOrDeleteFieldState = React.useCallback((id, field, newProps) => {
apiRef.current.setState(state => {
const newEditingState = (0, _extends2.default)({}, state.editRows);
if (newProps !== null) {
newEditingState[id] = (0, _extends2.default)({}, newEditingState[id], {
[field]: (0, _extends2.default)({}, newProps)
});
} else {
delete newEditingState[id][field];
if (Object.keys(newEditingState[id]).length === 0) {
delete newEditingState[id];
}
}
return (0, _extends2.default)({}, state, {
editRows: newEditingState
});
});
apiRef.current.forceUpdate();
}, [apiRef]);
const startRowEditMode = React.useCallback(params => {
const {
id
} = params,
other = (0, _objectWithoutPropertiesLoose2.default)(params, _excluded);
throwIfNotInMode(id, _gridEditRowModel.GridRowModes.View);
updateRowInRowModesModel(id, (0, _extends2.default)({
mode: _gridEditRowModel.GridRowModes.Edit
}, other));
}, [throwIfNotInMode, updateRowInRowModesModel]);
const updateStateToStartRowEditMode = (0, _utils.unstable_useEventCallback)(params => {
const {
id,
fieldToFocus,
deleteValue,
initialValue
} = params;
const columnFields = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
const newProps = columnFields.reduce((acc, field) => {
const cellParams = apiRef.current.getCellParams(id, field);
if (!cellParams.isEditable) {
return acc;
}
let newValue = apiRef.current.getCellValue(id, field);
if (fieldToFocus === field && (deleteValue || initialValue)) {
newValue = deleteValue ? '' : initialValue;
}
acc[field] = {
value: newValue,
error: false,
isProcessingProps: false
};
return acc;
}, {});
updateOrDeleteRowState(id, newProps);
if (fieldToFocus) {
apiRef.current.setCellFocus(id, fieldToFocus);
}
});
const stopRowEditMode = React.useCallback(params => {
const {
id
} = params,
other = (0, _objectWithoutPropertiesLoose2.default)(params, _excluded2);
throwIfNotInMode(id, _gridEditRowModel.GridRowModes.Edit);
updateRowInRowModesModel(id, (0, _extends2.default)({
mode: _gridEditRowModel.GridRowModes.View
}, other));
}, [throwIfNotInMode, updateRowInRowModesModel]);
const updateStateToStopRowEditMode = (0, _utils.unstable_useEventCallback)(params => {
const {
id,
ignoreModifications,
field: focusedField,
cellToFocusAfter = 'none'
} = params;
apiRef.current.runPendingEditCellValueMutation(id);
const finishRowEditMode = () => {
if (cellToFocusAfter !== 'none' && focusedField) {
apiRef.current.moveFocusToRelativeCell(id, focusedField, cellToFocusAfter);
}
updateOrDeleteRowState(id, null);
updateRowInRowModesModel(id, null);
};
if (ignoreModifications) {
finishRowEditMode();
return;
}
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const row = apiRef.current.getRow(id);
const isSomeFieldProcessingProps = Object.values(editingState[id]).some(fieldProps => fieldProps.isProcessingProps);
if (isSomeFieldProcessingProps) {
prevRowModesModel.current[id].mode = _gridEditRowModel.GridRowModes.Edit;
return;
}
const hasSomeFieldWithError = Object.values(editingState[id]).some(fieldProps => fieldProps.error);
if (hasSomeFieldWithError) {
prevRowModesModel.current[id].mode = _gridEditRowModel.GridRowModes.Edit;
// Revert the mode in the rowModesModel prop back to "edit"
updateRowInRowModesModel(id, {
mode: _gridEditRowModel.GridRowModes.Edit
});
return;
}
const rowUpdate = apiRef.current.getRowWithUpdatedValuesFromRowEditing(id);
if (processRowUpdate) {
const handleError = errorThrown => {
prevRowModesModel.current[id].mode = _gridEditRowModel.GridRowModes.Edit;
// Revert the mode in the rowModesModel prop back to "edit"
updateRowInRowModesModel(id, {
mode: _gridEditRowModel.GridRowModes.Edit
});
if (onProcessRowUpdateError) {
onProcessRowUpdateError(errorThrown);
} else {
missingOnProcessRowUpdateErrorWarning();
}
};
try {
Promise.resolve(processRowUpdate(rowUpdate, row)).then(finalRowUpdate => {
apiRef.current.updateRows([finalRowUpdate]);
finishRowEditMode();
}).catch(handleError);
} catch (errorThrown) {
handleError(errorThrown);
}
} else {
apiRef.current.updateRows([rowUpdate]);
finishRowEditMode();
}
});
const setRowEditingEditCellValue = React.useCallback(params => {
const {
id,
field,
value,
debounceMs,
unstable_skipValueParser: skipValueParser
} = params;
throwIfNotEditable(id, field);
const column = apiRef.current.getColumn(field);
const row = apiRef.current.getRow(id);
let parsedValue = value;
if (column.valueParser && !skipValueParser) {
parsedValue = column.valueParser(value, apiRef.current.getCellParams(id, field));
}
let editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
let newProps = (0, _extends2.default)({}, editingState[id][field], {
value: parsedValue,
changeReason: debounceMs ? 'debouncedSetEditCellValue' : 'setEditCellValue'
});
if (!column.preProcessEditCellProps) {
updateOrDeleteFieldState(id, field, newProps);
}
return new Promise(resolve => {
const promises = [];
if (column.preProcessEditCellProps) {
const hasChanged = newProps.value !== editingState[id][field].value;
newProps = (0, _extends2.default)({}, newProps, {
isProcessingProps: true
});
updateOrDeleteFieldState(id, field, newProps);
const _editingState$id = editingState[id],
otherFieldsProps = (0, _objectWithoutPropertiesLoose2.default)(_editingState$id, [field].map(_toPropertyKey2.default));
const promise = Promise.resolve(column.preProcessEditCellProps({
id,
row,
props: newProps,
hasChanged,
otherFieldsProps
})).then(processedProps => {
// Check again if the row is in edit mode because the user may have
// discarded the changes while the props were being processed.
if (apiRef.current.getRowMode(id) === _gridEditRowModel.GridRowModes.View) {
resolve(false);
return;
}
editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
processedProps = (0, _extends2.default)({}, processedProps, {
isProcessingProps: false
});
// We don't reuse the value from the props pre-processing because when the
// promise resolves it may be already outdated. The only exception to this rule
// is when there's no pre-processing.
processedProps.value = column.preProcessEditCellProps ? editingState[id][field].value : parsedValue;
updateOrDeleteFieldState(id, field, processedProps);
});
promises.push(promise);
}
Object.entries(editingState[id]).forEach(([thisField, fieldProps]) => {
if (thisField === field) {
return;
}
const fieldColumn = apiRef.current.getColumn(thisField);
if (!fieldColumn.preProcessEditCellProps) {
return;
}
fieldProps = (0, _extends2.default)({}, fieldProps, {
isProcessingProps: true
});
updateOrDeleteFieldState(id, thisField, fieldProps);
editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const _editingState$id2 = editingState[id],
otherFieldsProps = (0, _objectWithoutPropertiesLoose2.default)(_editingState$id2, [thisField].map(_toPropertyKey2.default));
const promise = Promise.resolve(fieldColumn.preProcessEditCellProps({
id,
row,
props: fieldProps,
hasChanged: false,
otherFieldsProps
})).then(processedProps => {
// Check again if the row is in edit mode because the user may have
// discarded the changes while the props were being processed.
if (apiRef.current.getRowMode(id) === _gridEditRowModel.GridRowModes.View) {
resolve(false);
return;
}
processedProps = (0, _extends2.default)({}, processedProps, {
isProcessingProps: false
});
updateOrDeleteFieldState(id, thisField, processedProps);
});
promises.push(promise);
});
Promise.all(promises).then(() => {
if (apiRef.current.getRowMode(id) === _gridEditRowModel.GridRowModes.Edit) {
editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
resolve(!editingState[id][field].error);
} else {
resolve(false);
}
});
});
}, [apiRef, throwIfNotEditable, updateOrDeleteFieldState]);
const getRowWithUpdatedValuesFromRowEditing = React.useCallback(id => {
const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
const row = apiRef.current.getRow(id);
if (!editingState[id]) {
return apiRef.current.getRow(id);
}
let rowUpdate = (0, _extends2.default)({}, row);
Object.entries(editingState[id]).forEach(([field, fieldProps]) => {
const column = apiRef.current.getColumn(field);
if (column.valueSetter) {
rowUpdate = column.valueSetter({
value: fieldProps.value,
row: rowUpdate
});
} else {
rowUpdate[field] = fieldProps.value;
}
});
return rowUpdate;
}, [apiRef]);
const editingApi = {
getRowMode,
startRowEditMode,
stopRowEditMode
};
const editingPrivateApi = {
setRowEditingEditCellValue,
getRowWithUpdatedValuesFromRowEditing
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, editingApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, editingPrivateApi, 'private');
React.useEffect(() => {
if (rowModesModelProp) {
updateRowModesModel(rowModesModelProp);
}
}, [rowModesModelProp, updateRowModesModel]);
// Run this effect synchronously so that the keyboard event can impact the yet-to-be-rendered input.
(0, _utils.unstable_useEnhancedEffect)(() => {
const idToIdLookup = (0, _gridRowsSelector.gridRowsDataRowIdToIdLookupSelector)(apiRef);
// Update the ref here because updateStateToStopRowEditMode may change it later
const copyOfPrevRowModesModel = prevRowModesModel.current;
prevRowModesModel.current = (0, _utils2.deepClone)(rowModesModel); // Do a deep-clone because the attributes might be changed later
Object.entries(rowModesModel).forEach(([id, params]) => {
const prevMode = copyOfPrevRowModesModel[id]?.mode || _gridEditRowModel.GridRowModes.View;
const originalId = idToIdLookup[id] ?? id;
if (params.mode === _gridEditRowModel.GridRowModes.Edit && prevMode === _gridEditRowModel.GridRowModes.View) {
updateStateToStartRowEditMode((0, _extends2.default)({
id: originalId
}, params));
} else if (params.mode === _gridEditRowModel.GridRowModes.View && prevMode === _gridEditRowModel.GridRowModes.Edit) {
updateStateToStopRowEditMode((0, _extends2.default)({
id: originalId
}, params));
}
});
}, [apiRef, rowModesModel, updateStateToStartRowEditMode, updateStateToStopRowEditMode]);
};
exports.useGridRowEditing = useGridRowEditing;

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridEvents = useGridEvents;
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
/**
* @requires useGridFocus (event) - can be after, async only
* @requires useGridColumns (event) - can be after, async only
*/
function useGridEvents(apiRef, props) {
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnHeaderClick', props.onColumnHeaderClick);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnHeaderDoubleClick', props.onColumnHeaderDoubleClick);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnHeaderOver', props.onColumnHeaderOver);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnHeaderOut', props.onColumnHeaderOut);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnHeaderEnter', props.onColumnHeaderEnter);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnHeaderLeave', props.onColumnHeaderLeave);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellClick', props.onCellClick);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellDoubleClick', props.onCellDoubleClick);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'cellKeyDown', props.onCellKeyDown);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'preferencePanelClose', props.onPreferencePanelClose);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'preferencePanelOpen', props.onPreferencePanelOpen);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'menuOpen', props.onMenuOpen);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'menuClose', props.onMenuClose);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowDoubleClick', props.onRowDoubleClick);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'rowClick', props.onRowClick);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'stateChange', props.onStateChange);
}

View File

@@ -0,0 +1,154 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildCSV = buildCSV;
exports.serializeCellValue = void 0;
var _colDef = require("../../../../colDef");
var _warning = require("../../../../utils/warning");
function sanitizeCellValue(value, csvOptions) {
if (typeof value === 'string') {
if (csvOptions.shouldAppendQuotes || csvOptions.escapeFormulas) {
const escapedValue = value.replace(/"/g, '""');
// Make sure value containing delimiter or line break won't be split into multiple cells
if ([csvOptions.delimiter, '\n', '\r', '"'].some(delimiter => value.includes(delimiter))) {
return `"${escapedValue}"`;
}
if (csvOptions.escapeFormulas) {
// See https://owasp.org/www-community/attacks/CSV_Injection
if (['=', '+', '-', '@', '\t', '\r'].includes(escapedValue[0])) {
return `'${escapedValue}`;
}
}
return escapedValue;
}
return value;
}
return value;
}
const serializeCellValue = (cellParams, options) => {
const {
csvOptions,
ignoreValueFormatter
} = options;
let value;
if (ignoreValueFormatter) {
const columnType = cellParams.colDef.type;
if (columnType === 'number') {
value = String(cellParams.value);
} else if (columnType === 'date' || columnType === 'dateTime') {
value = cellParams.value?.toISOString();
} else if (typeof cellParams.value?.toString === 'function') {
value = cellParams.value.toString();
} else {
value = cellParams.value;
}
} else {
value = cellParams.formattedValue;
}
return sanitizeCellValue(value, csvOptions);
};
exports.serializeCellValue = serializeCellValue;
const objectFormattedValueWarning = (0, _warning.buildWarning)(['MUI: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
class CSVRow {
constructor(options) {
this.options = void 0;
this.rowString = '';
this.isEmpty = true;
this.options = options;
}
addValue(value) {
if (!this.isEmpty) {
this.rowString += this.options.csvOptions.delimiter;
}
if (value === null || value === undefined) {
this.rowString += '';
} else if (typeof this.options.sanitizeCellValue === 'function') {
this.rowString += this.options.sanitizeCellValue(value, this.options.csvOptions);
} else {
this.rowString += value;
}
this.isEmpty = false;
}
getRowString() {
return this.rowString;
}
}
const serializeRow = ({
id,
columns,
getCellParams,
csvOptions,
ignoreValueFormatter
}) => {
const row = new CSVRow({
csvOptions
});
columns.forEach(column => {
const cellParams = getCellParams(id, column.field);
if (process.env.NODE_ENV !== 'production') {
if (String(cellParams.formattedValue) === '[object Object]') {
objectFormattedValueWarning();
}
}
row.addValue(serializeCellValue(cellParams, {
ignoreValueFormatter,
csvOptions
}));
});
return row.getRowString();
};
function buildCSV(options) {
const {
columns,
rowIds,
csvOptions,
ignoreValueFormatter,
apiRef
} = options;
const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
id,
columns,
getCellParams: apiRef.current.getCellParams,
ignoreValueFormatter,
csvOptions
})}\r\n`, '').trim();
if (!csvOptions.includeHeaders) {
return CSVBody;
}
const filteredColumns = columns.filter(column => column.field !== _colDef.GRID_CHECKBOX_SELECTION_COL_DEF.field);
const headerRows = [];
if (csvOptions.includeColumnGroupsHeaders) {
const columnGroupLookup = apiRef.current.unstable_getAllGroupDetails();
let maxColumnGroupsDepth = 0;
const columnGroupPathsLookup = filteredColumns.reduce((acc, column) => {
const columnGroupPath = apiRef.current.unstable_getColumnGroupPath(column.field);
acc[column.field] = columnGroupPath;
maxColumnGroupsDepth = Math.max(maxColumnGroupsDepth, columnGroupPath.length);
return acc;
}, {});
for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
const headerGroupRow = new CSVRow({
csvOptions,
sanitizeCellValue
});
headerRows.push(headerGroupRow);
filteredColumns.forEach(column => {
const columnGroupId = (columnGroupPathsLookup[column.field] || [])[i];
const columnGroup = columnGroupLookup[columnGroupId];
headerGroupRow.addValue(columnGroup ? columnGroup.headerName || columnGroup.groupId : '');
});
}
}
const mainHeaderRow = new CSVRow({
csvOptions,
sanitizeCellValue
});
filteredColumns.forEach(column => {
mainHeaderRow.addValue(column.headerName || column.field);
});
headerRows.push(mainHeaderRow);
const CSVHead = `${headerRows.map(row => row.getRowString()).join('\r\n')}\r\n`;
return `${CSVHead}${CSVBody}`.trim();
}

View File

@@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridCsvExport = void 0;
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _exportAs = require("../../../utils/exportAs");
var _csvSerializer = require("./serializers/csvSerializer");
var _utils = require("./utils");
var _pipeProcessing = require("../../core/pipeProcessing");
var _GridToolbarExport = require("../../../components/toolbar/GridToolbarExport");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* @requires useGridColumns (state)
* @requires useGridFilter (state)
* @requires useGridSorting (state)
* @requires useGridSelection (state)
* @requires useGridParamsApi (method)
*/
const useGridCsvExport = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridCsvExport');
const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp?.csvExport : ignoreValueFormatterProp) || false;
const getDataAsCsv = React.useCallback((options = {}) => {
logger.debug(`Get data as CSV`);
const exportedColumns = (0, _utils.getColumnsToExport)({
apiRef,
options
});
const getRowsToExport = options.getRowsToExport ?? _utils.defaultGetRowsToExport;
const exportedRowIds = getRowsToExport({
apiRef
});
return (0, _csvSerializer.buildCSV)({
columns: exportedColumns,
rowIds: exportedRowIds,
csvOptions: {
delimiter: options.delimiter || ',',
shouldAppendQuotes: options.shouldAppendQuotes ?? true,
includeHeaders: options.includeHeaders ?? true,
includeColumnGroupsHeaders: options.includeColumnGroupsHeaders ?? true,
escapeFormulas: options.escapeFormulas ?? true
},
ignoreValueFormatter,
apiRef
});
}, [logger, apiRef, ignoreValueFormatter]);
const exportDataAsCsv = React.useCallback(options => {
logger.debug(`Export data as CSV`);
const csv = getDataAsCsv(options);
const blob = new Blob([options?.utf8WithBom ? new Uint8Array([0xef, 0xbb, 0xbf]) : '', csv], {
type: 'text/csv'
});
(0, _exportAs.exportAs)(blob, 'csv', options?.fileName);
}, [logger, getDataAsCsv]);
const csvExportApi = {
getDataAsCsv,
exportDataAsCsv
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, csvExportApi, 'public');
/**
* PRE-PROCESSING
*/
const addExportMenuButtons = React.useCallback((initialValue, options) => {
if (options.csvOptions?.disableToolbarButton) {
return initialValue;
}
return [...initialValue, {
component: /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridToolbarExport.GridCsvExportMenuItem, {
options: options.csvOptions
}),
componentName: 'csvExport'
}];
}, []);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportMenu', addExportMenuButtons);
};
exports.useGridCsvExport = useGridCsvExport;

View File

@@ -0,0 +1,290 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridPrintExport = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _gridClasses = require("../../../constants/gridClasses");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridRowsMetaSelector = require("../rows/gridRowsMetaSelector");
var _utils2 = require("./utils");
var _useGridPaginationModel = require("../pagination/useGridPaginationModel");
var _pipeProcessing = require("../../core/pipeProcessing");
var _GridToolbarExport = require("../../../components/toolbar/GridToolbarExport");
var _gridColumnsUtils = require("../columns/gridColumnsUtils");
var _gridCheckboxSelectionColDef = require("../../../colDef/gridCheckboxSelectionColDef");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function raf() {
return new Promise(resolve => {
requestAnimationFrame(() => {
resolve();
});
});
}
function buildPrintWindow(title) {
const iframeEl = document.createElement('iframe');
iframeEl.style.position = 'absolute';
iframeEl.style.width = '0px';
iframeEl.style.height = '0px';
iframeEl.title = title || document.title;
return iframeEl;
}
/**
* @requires useGridColumns (state)
* @requires useGridFilter (state)
* @requires useGridSorting (state)
* @requires useGridParamsApi (method)
*/
const useGridPrintExport = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridPrintExport');
const doc = React.useRef(null);
const previousGridState = React.useRef(null);
const previousColumnVisibility = React.useRef({});
const previousRows = React.useRef([]);
React.useEffect(() => {
doc.current = (0, _utils.unstable_ownerDocument)(apiRef.current.rootElementRef.current);
}, [apiRef]);
// Returns a promise because updateColumns triggers state update and
// the new state needs to be in place before the grid can be sized correctly
const updateGridColumnsForPrint = React.useCallback((fields, allColumns, includeCheckboxes) => new Promise(resolve => {
const exportedColumnFields = (0, _utils2.getColumnsToExport)({
apiRef,
options: {
fields,
allColumns
}
}).map(column => column.field);
const columns = (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef);
const newColumnVisibilityModel = {};
columns.forEach(column => {
newColumnVisibilityModel[column.field] = exportedColumnFields.includes(column.field);
});
if (includeCheckboxes) {
newColumnVisibilityModel[_gridCheckboxSelectionColDef.GRID_CHECKBOX_SELECTION_COL_DEF.field] = true;
}
apiRef.current.setColumnVisibilityModel(newColumnVisibilityModel);
resolve();
}), [apiRef]);
const updateGridRowsForPrint = React.useCallback(getRowsToExport => {
const rowsToExportIds = getRowsToExport({
apiRef
});
const newRows = rowsToExportIds.map(id => apiRef.current.getRow(id));
apiRef.current.setRows(newRows);
}, [apiRef]);
const handlePrintWindowLoad = React.useCallback((printWindow, options) => {
const normalizeOptions = (0, _extends2.default)({
copyStyles: true,
hideToolbar: false,
hideFooter: false,
includeCheckboxes: false
}, options);
const printDoc = printWindow.contentDocument;
if (!printDoc) {
return;
}
const rowsMeta = (0, _gridRowsMetaSelector.gridRowsMetaSelector)(apiRef.current.state);
const gridRootElement = apiRef.current.rootElementRef.current;
const gridClone = gridRootElement.cloneNode(true);
// Allow to overflow to not hide the border of the last row
const gridMain = gridClone.querySelector(`.${_gridClasses.gridClasses.main}`);
gridMain.style.overflow = 'visible';
// See https://support.google.com/chrome/thread/191619088?hl=en&msgid=193009642
gridClone.style.contain = 'size';
const columnHeaders = gridClone.querySelector(`.${_gridClasses.gridClasses.columnHeaders}`);
const columnHeadersInner = columnHeaders.querySelector(`.${_gridClasses.gridClasses.columnHeadersInner}`);
columnHeadersInner.style.width = '100%';
let gridToolbarElementHeight = gridRootElement.querySelector(`.${_gridClasses.gridClasses.toolbarContainer}`)?.offsetHeight || 0;
let gridFooterElementHeight = gridRootElement.querySelector(`.${_gridClasses.gridClasses.footerContainer}`)?.offsetHeight || 0;
if (normalizeOptions.hideToolbar) {
gridClone.querySelector(`.${_gridClasses.gridClasses.toolbarContainer}`)?.remove();
gridToolbarElementHeight = 0;
}
if (normalizeOptions.hideFooter) {
gridClone.querySelector(`.${_gridClasses.gridClasses.footerContainer}`)?.remove();
gridFooterElementHeight = 0;
}
// Expand container height to accommodate all rows
const computedTotalHeight = rowsMeta.currentPageTotalHeight + (0, _gridColumnsUtils.getTotalHeaderHeight)(apiRef, props.columnHeaderHeight) + gridToolbarElementHeight + gridFooterElementHeight;
gridClone.style.height = `${computedTotalHeight}px`;
// The height above does not include grid border width, so we need to exclude it
gridClone.style.boxSizing = 'content-box';
// the footer is always being placed at the bottom of the page as if all rows are exported
// so if getRowsToExport is being used to only export a subset of rows then we need to
// adjust the footer position to be correctly placed at the bottom of the grid
if (options?.getRowsToExport) {
const gridFooterElement = gridClone.querySelector(`.${_gridClasses.gridClasses.footerContainer}`);
gridFooterElement.style.position = 'absolute';
gridFooterElement.style.width = '100%';
gridFooterElement.style.top = `${computedTotalHeight - gridFooterElementHeight}px`;
}
// printDoc.body.appendChild(gridClone); should be enough but a clone isolation bug in Safari
// prevents us to do it
const container = document.createElement('div');
container.appendChild(gridClone);
printDoc.body.innerHTML = container.innerHTML;
const defaultPageStyle = typeof normalizeOptions.pageStyle === 'function' ? normalizeOptions.pageStyle() : normalizeOptions.pageStyle;
if (typeof defaultPageStyle === 'string') {
// TODO custom styles should always win
const styleElement = printDoc.createElement('style');
styleElement.appendChild(printDoc.createTextNode(defaultPageStyle));
printDoc.head.appendChild(styleElement);
}
if (normalizeOptions.bodyClassName) {
printDoc.body.classList.add(...normalizeOptions.bodyClassName.split(' '));
}
const stylesheetLoadPromises = [];
if (normalizeOptions.copyStyles) {
const rootCandidate = gridRootElement.getRootNode();
const root = rootCandidate.constructor.name === 'ShadowRoot' ? rootCandidate : doc.current;
const headStyleElements = root.querySelectorAll("style, link[rel='stylesheet']");
for (let i = 0; i < headStyleElements.length; i += 1) {
const node = headStyleElements[i];
if (node.tagName === 'STYLE') {
const newHeadStyleElements = printDoc.createElement(node.tagName);
const sheet = node.sheet;
if (sheet) {
let styleCSS = '';
// NOTE: for-of is not supported by IE
for (let j = 0; j < sheet.cssRules.length; j += 1) {
if (typeof sheet.cssRules[j].cssText === 'string') {
styleCSS += `${sheet.cssRules[j].cssText}\r\n`;
}
}
newHeadStyleElements.appendChild(printDoc.createTextNode(styleCSS));
printDoc.head.appendChild(newHeadStyleElements);
}
} else if (node.getAttribute('href')) {
// If `href` tag is empty, avoid loading these links
const newHeadStyleElements = printDoc.createElement(node.tagName);
for (let j = 0; j < node.attributes.length; j += 1) {
const attr = node.attributes[j];
if (attr) {
newHeadStyleElements.setAttribute(attr.nodeName, attr.nodeValue || '');
}
}
stylesheetLoadPromises.push(new Promise(resolve => {
newHeadStyleElements.addEventListener('load', () => resolve());
}));
printDoc.head.appendChild(newHeadStyleElements);
}
}
}
// Trigger print
if (process.env.NODE_ENV !== 'test') {
// wait for remote stylesheets to load
Promise.all(stylesheetLoadPromises).then(() => {
printWindow.contentWindow.print();
});
}
}, [apiRef, doc, props.columnHeaderHeight]);
const handlePrintWindowAfterPrint = React.useCallback(printWindow => {
// Remove the print iframe
doc.current.body.removeChild(printWindow);
// Revert grid to previous state
apiRef.current.restoreState(previousGridState.current || {});
if (!previousGridState.current?.columns?.columnVisibilityModel) {
// if the apiRef.current.exportState(); did not exported the column visibility, we update it
apiRef.current.setColumnVisibilityModel(previousColumnVisibility.current);
}
apiRef.current.unstable_setVirtualization(true);
apiRef.current.setRows(previousRows.current);
// Clear local state
previousGridState.current = null;
previousColumnVisibility.current = {};
previousRows.current = [];
}, [apiRef]);
const exportDataAsPrint = React.useCallback(async options => {
logger.debug(`Export data as Print`);
if (!apiRef.current.rootElementRef.current) {
throw new Error('MUI: No grid root element available.');
}
previousGridState.current = apiRef.current.exportState();
// It appends that the visibility model is not exported, especially if columnVisibility is not controlled
previousColumnVisibility.current = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const gridRowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
previousRows.current = (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef).map(rowId => gridRowsLookup[rowId]);
if (props.pagination) {
const visibleRowCount = (0, _gridFilterSelector.gridExpandedRowCountSelector)(apiRef);
const paginationModel = {
page: 0,
pageSize: visibleRowCount
};
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pagination: (0, _extends2.default)({}, state.pagination, {
paginationModel: (0, _useGridPaginationModel.getDerivedPaginationModel)(state.pagination,
// Using signature `DataGridPro` to allow more than 100 rows in the print export
'DataGridPro', paginationModel)
})
}));
apiRef.current.forceUpdate();
}
await updateGridColumnsForPrint(options?.fields, options?.allColumns, options?.includeCheckboxes);
if (options?.getRowsToExport) {
updateGridRowsForPrint(options.getRowsToExport);
}
apiRef.current.unstable_setVirtualization(false);
await raf(); // wait for the state changes to take action
const printWindow = buildPrintWindow(options?.fileName);
if (process.env.NODE_ENV === 'test') {
doc.current.body.appendChild(printWindow);
// In test env, run the all pipeline without waiting for loading
handlePrintWindowLoad(printWindow, options);
handlePrintWindowAfterPrint(printWindow);
} else {
printWindow.onload = () => {
handlePrintWindowLoad(printWindow, options);
const mediaQueryList = printWindow.contentWindow.matchMedia('print');
mediaQueryList.addEventListener('change', mql => {
const isAfterPrint = mql.matches === false;
if (isAfterPrint) {
handlePrintWindowAfterPrint(printWindow);
}
});
};
doc.current.body.appendChild(printWindow);
}
}, [props, logger, apiRef, handlePrintWindowLoad, handlePrintWindowAfterPrint, updateGridColumnsForPrint, updateGridRowsForPrint]);
const printExportApi = {
exportDataAsPrint
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, printExportApi, 'public');
/**
* PRE-PROCESSING
*/
const addExportMenuButtons = React.useCallback((initialValue, options) => {
if (options.printOptions?.disableToolbarButton) {
return initialValue;
}
return [...initialValue, {
component: /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridToolbarExport.GridPrintExportMenuItem, {
options: options.printOptions
}),
componentName: 'printExport'
}];
}, []);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportMenu', addExportMenuButtons);
};
exports.useGridPrintExport = useGridPrintExport;

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getColumnsToExport = exports.defaultGetRowsToExport = void 0;
var _columns = require("../columns");
var _filter = require("../filter");
var _gridRowsSelector = require("../rows/gridRowsSelector");
const getColumnsToExport = ({
apiRef,
options
}) => {
const columns = (0, _columns.gridColumnDefinitionsSelector)(apiRef);
if (options.fields) {
return options.fields.reduce((currentColumns, field) => {
const column = columns.find(col => col.field === field);
if (column) {
currentColumns.push(column);
}
return currentColumns;
}, []);
}
const validColumns = options.allColumns ? columns : (0, _columns.gridVisibleColumnDefinitionsSelector)(apiRef);
return validColumns.filter(column => !column.disableExport);
};
exports.getColumnsToExport = getColumnsToExport;
const defaultGetRowsToExport = ({
apiRef
}) => {
const filteredSortedRowIds = (0, _filter.gridFilteredSortedRowIdsSelector)(apiRef);
const rowTree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
const selectedRows = apiRef.current.getSelectedRows();
const bodyRows = filteredSortedRowIds.filter(id => rowTree[id].type !== 'footer');
const pinnedRows = (0, _gridRowsSelector.gridPinnedRowsSelector)(apiRef);
const topPinnedRowsIds = pinnedRows?.top?.map(row => row.id) || [];
const bottomPinnedRowsIds = pinnedRows?.bottom?.map(row => row.id) || [];
bodyRows.unshift(...topPinnedRowsIds);
bodyRows.push(...bottomPinnedRowsIds);
if (selectedRows.size > 0) {
return bodyRows.filter(id => selectedRows.has(id));
}
return bodyRows;
};
exports.defaultGetRowsToExport = defaultGetRowsToExport;

View File

@@ -0,0 +1,130 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridVisibleRowsLookupSelector = exports.gridQuickFilterValuesSelector = exports.gridFilteredTopLevelRowCountSelector = exports.gridFilteredSortedTopLevelRowEntriesSelector = exports.gridFilteredSortedRowIdsSelector = exports.gridFilteredSortedRowEntriesSelector = exports.gridFilteredRowsLookupSelector = exports.gridFilteredDescendantCountLookupSelector = exports.gridFilterModelSelector = exports.gridFilterActiveItemsSelector = exports.gridFilterActiveItemsLookupSelector = exports.gridExpandedSortedRowIdsSelector = exports.gridExpandedSortedRowEntriesSelector = exports.gridExpandedRowCountSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
var _gridSortingSelector = require("../sorting/gridSortingSelector");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _gridRowsSelector = require("../rows/gridRowsSelector");
/**
* @category Filtering
*/
const gridFilterStateSelector = state => state.filter;
/**
* Get the current filter model.
* @category Filtering
*/
const gridFilterModelSelector = exports.gridFilterModelSelector = (0, _createSelector.createSelector)(gridFilterStateSelector, filterState => filterState.filterModel);
/**
* Get the current quick filter values.
* @category Filtering
*/
const gridQuickFilterValuesSelector = exports.gridQuickFilterValuesSelector = (0, _createSelector.createSelector)(gridFilterModelSelector, filterModel => filterModel.quickFilterValues);
/**
* @category Visible rows
* @ignore - do not document.
*/
const gridVisibleRowsLookupSelector = state => state.visibleRowsLookup;
/**
* @category Filtering
* @ignore - do not document.
*/
exports.gridVisibleRowsLookupSelector = gridVisibleRowsLookupSelector;
const gridFilteredRowsLookupSelector = exports.gridFilteredRowsLookupSelector = (0, _createSelector.createSelector)(gridFilterStateSelector, filterState => filterState.filteredRowsLookup);
/**
* @category Filtering
* @ignore - do not document.
*/
const gridFilteredDescendantCountLookupSelector = exports.gridFilteredDescendantCountLookupSelector = (0, _createSelector.createSelector)(gridFilterStateSelector, filterState => filterState.filteredDescendantCountLookup);
/**
* Get the id and the model of the rows accessible after the filtering process.
* Does not contain the collapsed children.
* @category Filtering
*/
const gridExpandedSortedRowEntriesSelector = exports.gridExpandedSortedRowEntriesSelector = (0, _createSelector.createSelectorMemoized)(gridVisibleRowsLookupSelector, _gridSortingSelector.gridSortedRowEntriesSelector, (visibleRowsLookup, sortedRows) => sortedRows.filter(row => visibleRowsLookup[row.id] !== false));
/**
* Get the id of the rows accessible after the filtering process.
* Does not contain the collapsed children.
* @category Filtering
*/
const gridExpandedSortedRowIdsSelector = exports.gridExpandedSortedRowIdsSelector = (0, _createSelector.createSelectorMemoized)(gridExpandedSortedRowEntriesSelector, visibleSortedRowEntries => visibleSortedRowEntries.map(row => row.id));
/**
* Get the id and the model of the rows accessible after the filtering process.
* Contains the collapsed children.
* @category Filtering
*/
const gridFilteredSortedRowEntriesSelector = exports.gridFilteredSortedRowEntriesSelector = (0, _createSelector.createSelectorMemoized)(gridFilteredRowsLookupSelector, _gridSortingSelector.gridSortedRowEntriesSelector, (filteredRowsLookup, sortedRows) => sortedRows.filter(row => filteredRowsLookup[row.id] !== false));
/**
* Get the id of the rows accessible after the filtering process.
* Contains the collapsed children.
* @category Filtering
*/
const gridFilteredSortedRowIdsSelector = exports.gridFilteredSortedRowIdsSelector = (0, _createSelector.createSelectorMemoized)(gridFilteredSortedRowEntriesSelector, filteredSortedRowEntries => filteredSortedRowEntries.map(row => row.id));
/**
* Get the id and the model of the top level rows accessible after the filtering process.
* @category Filtering
*/
const gridFilteredSortedTopLevelRowEntriesSelector = exports.gridFilteredSortedTopLevelRowEntriesSelector = (0, _createSelector.createSelectorMemoized)(gridExpandedSortedRowEntriesSelector, _gridRowsSelector.gridRowTreeSelector, _gridRowsSelector.gridRowMaximumTreeDepthSelector, (visibleSortedRows, rowTree, rowTreeDepth) => {
if (rowTreeDepth < 2) {
return visibleSortedRows;
}
return visibleSortedRows.filter(row => rowTree[row.id]?.depth === 0);
});
/**
* Get the amount of rows accessible after the filtering process.
* @category Filtering
*/
const gridExpandedRowCountSelector = exports.gridExpandedRowCountSelector = (0, _createSelector.createSelector)(gridExpandedSortedRowEntriesSelector, visibleSortedRows => visibleSortedRows.length);
/**
* Get the amount of top level rows accessible after the filtering process.
* @category Filtering
*/
const gridFilteredTopLevelRowCountSelector = exports.gridFilteredTopLevelRowCountSelector = (0, _createSelector.createSelector)(gridFilteredSortedTopLevelRowEntriesSelector, visibleSortedTopLevelRows => visibleSortedTopLevelRows.length);
/**
* @category Filtering
* @ignore - do not document.
*/
const gridFilterActiveItemsSelector = exports.gridFilterActiveItemsSelector = (0, _createSelector.createSelectorMemoized)(gridFilterModelSelector, _gridColumnsSelector.gridColumnLookupSelector, (filterModel, columnLookup) => filterModel.items?.filter(item => {
if (!item.field) {
return false;
}
const column = columnLookup[item.field];
if (!column?.filterOperators || column?.filterOperators?.length === 0) {
return false;
}
const filterOperator = column.filterOperators.find(operator => operator.value === item.operator);
if (!filterOperator) {
return false;
}
return !filterOperator.InputComponent || item.value != null && item.value?.toString() !== '';
}));
/**
* @category Filtering
* @ignore - do not document.
*/
const gridFilterActiveItemsLookupSelector = exports.gridFilterActiveItemsLookupSelector = (0, _createSelector.createSelectorMemoized)(gridFilterActiveItemsSelector, activeFilters => {
const result = activeFilters.reduce((res, filterItem) => {
if (!res[filterItem.field]) {
res[filterItem.field] = [filterItem];
} else {
res[filterItem.field].push(filterItem);
}
return res;
}, {});
return result;
});

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getDefaultGridFilterModel = void 0;
var _gridFilterItem = require("../../../models/gridFilterItem");
const getDefaultGridFilterModel = () => ({
items: [],
logicOperator: _gridFilterItem.GridLogicOperator.And,
quickFilterValues: [],
quickFilterLogicOperator: _gridFilterItem.GridLogicOperator.And
});
/**
* @param {GridRowId} rowId The id of the row we want to filter.
* @param {(filterItem: GridFilterItem) => boolean} shouldApplyItem An optional callback to allow the filtering engine to only apply some items.
*/
/**
* Visibility status for each row.
* A row is visible if it is passing the filters AND if its parents are expanded.
* If a row is not registered in this lookup, it is visible.
*/
exports.getDefaultGridFilterModel = getDefaultGridFilterModel;

View File

@@ -0,0 +1,374 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sanitizeFilterModel = exports.removeDiacritics = exports.passFilterLogic = exports.mergeStateWithFilterModel = exports.cleanFilterItem = exports.buildAggregatedFilterApplier = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _models = require("../../../models");
var _utils = require("../../../colDef/utils");
var _gridFilterState = require("./gridFilterState");
var _warning = require("../../../utils/warning");
var _getPublicApiRef = require("../../../utils/getPublicApiRef");
var _columns = require("../columns");
let hasEval;
function getHasEval() {
if (hasEval !== undefined) {
return hasEval;
}
try {
hasEval = new Function('return true')();
} catch (_) {
hasEval = false;
}
return hasEval;
}
/**
* Adds default values to the optional fields of a filter items.
* @param {GridFilterItem} item The raw filter item.
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
* @return {GridFilterItem} The clean filter item with an uniq ID and an always-defined operator.
* TODO: Make the typing reflect the different between GridFilterInputItem and GridFilterItem.
*/
const cleanFilterItem = (item, apiRef) => {
const cleanItem = (0, _extends2.default)({}, item);
if (cleanItem.id == null) {
cleanItem.id = Math.round(Math.random() * 1e5);
}
if (cleanItem.operator == null) {
// Selects a default operator
// We don't use `apiRef.current.getColumn` because it is not ready during state initialization
const column = (0, _columns.gridColumnLookupSelector)(apiRef)[cleanItem.field];
cleanItem.operator = column && column.filterOperators[0].value;
}
return cleanItem;
};
exports.cleanFilterItem = cleanFilterItem;
const filterModelDisableMultiColumnsFilteringWarning = (0, _warning.buildWarning)(['MUI: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the `DataGrid`, this prop is always `true`.'], 'error');
const filterModelMissingItemIdWarning = (0, _warning.buildWarning)('MUI: The `id` field is required on `filterModel.items` when you use multiple filters.', 'error');
const filterModelMissingItemOperatorWarning = (0, _warning.buildWarning)('MUI: The `operator` field is required on `filterModel.items`, one or more of your filtering item has no `operator` provided.', 'error');
const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiRef) => {
const hasSeveralItems = model.items.length > 1;
let items;
if (hasSeveralItems && disableMultipleColumnsFiltering) {
filterModelDisableMultiColumnsFilteringWarning();
items = [model.items[0]];
} else {
items = model.items;
}
const hasItemsWithoutIds = hasSeveralItems && items.some(item => item.id == null);
const hasItemWithoutOperator = items.some(item => item.operator == null);
if (hasItemsWithoutIds) {
filterModelMissingItemIdWarning();
}
if (hasItemWithoutOperator) {
filterModelMissingItemOperatorWarning();
}
if (hasItemWithoutOperator || hasItemsWithoutIds) {
return (0, _extends2.default)({}, model, {
items: items.map(item => cleanFilterItem(item, apiRef))
});
}
if (model.items !== items) {
return (0, _extends2.default)({}, model, {
items
});
}
return model;
};
exports.sanitizeFilterModel = sanitizeFilterModel;
const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering, apiRef) => filteringState => (0, _extends2.default)({}, filteringState, {
filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
});
exports.mergeStateWithFilterModel = mergeStateWithFilterModel;
const removeDiacritics = value => {
if (typeof value === 'string') {
return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
return value;
};
exports.removeDiacritics = removeDiacritics;
const getFilterCallbackFromItem = (filterItem, apiRef) => {
if (!filterItem.field || !filterItem.operator) {
return null;
}
const column = apiRef.current.getColumn(filterItem.field);
if (!column) {
return null;
}
let parsedValue;
if (column.valueParser) {
const parser = column.valueParser;
parsedValue = Array.isArray(filterItem.value) ? filterItem.value?.map(x => parser(x)) : parser(filterItem.value);
} else {
parsedValue = filterItem.value;
}
const {
ignoreDiacritics
} = apiRef.current.rootProps;
if (ignoreDiacritics) {
parsedValue = removeDiacritics(parsedValue);
}
const newFilterItem = (0, _extends2.default)({}, filterItem, {
value: parsedValue
});
const filterOperators = column.filterOperators;
if (!filterOperators?.length) {
throw new Error(`MUI: No filter operators found for column '${column.field}'.`);
}
const filterOperator = filterOperators.find(operator => operator.value === newFilterItem.operator);
if (!filterOperator) {
throw new Error(`MUI: No filter operator found for column '${column.field}' and operator value '${newFilterItem.operator}'.`);
}
const hasUserFunctionLegacy = !(0, _utils.isInternalFilter)(filterOperator.getApplyFilterFn);
const hasUserFunctionV7 = !(0, _utils.isInternalFilter)(filterOperator.getApplyFilterFnV7);
const publicApiRef = (0, _getPublicApiRef.getPublicApiRef)(apiRef);
if (filterOperator.getApplyFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) {
const applyFilterOnRow = filterOperator.getApplyFilterFnV7(newFilterItem, column);
if (typeof applyFilterOnRow !== 'function') {
return null;
}
return {
v7: true,
item: newFilterItem,
fn: row => {
let value = apiRef.current.getRowValue(row, column);
if (ignoreDiacritics) {
value = removeDiacritics(value);
}
return applyFilterOnRow(value, row, column, publicApiRef);
}
};
}
const applyFilterOnRow = filterOperator.getApplyFilterFn(newFilterItem, column);
if (typeof applyFilterOnRow !== 'function') {
return null;
}
return {
v7: false,
item: newFilterItem,
fn: rowId => {
const params = apiRef.current.getCellParams(rowId, newFilterItem.field);
_utils.GLOBAL_API_REF.current = publicApiRef;
if (ignoreDiacritics) {
params.value = removeDiacritics(params.value);
}
const result = applyFilterOnRow(params);
_utils.GLOBAL_API_REF.current = null;
return result;
}
};
};
let filterItemsApplierId = 1;
/**
* Generates a method to easily check if a row is matching the current filter model.
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
*/
const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) => {
const {
items
} = filterModel;
const appliers = items.map(item => getFilterCallbackFromItem(item, apiRef)).filter(callback => !!callback);
if (appliers.length === 0) {
return null;
}
if (disableEval || !getHasEval()) {
// This is the original logic, which is used if `eval()` is not supported (aka prevented by CSP).
return (row, shouldApplyFilter) => {
const resultPerItemId = {};
for (let i = 0; i < appliers.length; i += 1) {
const applier = appliers[i];
if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) {
resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(apiRef.current.getRowId(row));
}
}
return resultPerItemId;
};
}
// We generate a new function with `new Function()` to avoid expensive patterns for JS engines
// such as a dynamic object assignment, e.g. `{ [dynamicKey]: value }`.
const filterItemCore = new Function('getRowId', 'appliers', 'row', 'shouldApplyFilter', `"use strict";
${appliers.map((applier, i) => `const shouldApply${i} = !shouldApplyFilter || shouldApplyFilter(${JSON.stringify(applier.item.field)});`).join('\n')}
const result$$ = {
${appliers.map((applier, i) => ` ${JSON.stringify(String(applier.item.id))}: !shouldApply${i}
? false
: ${applier.v7 ? `appliers[${i}].fn(row)` : `appliers[${i}].fn(getRowId(row))`},`).join('\n')}
};
return result$$;`.replaceAll('$$', String(filterItemsApplierId)));
filterItemsApplierId += 1;
// Assign to the arrow function a name to help debugging
const filterItem = (row, shouldApplyItem) => filterItemCore(apiRef.current.getRowId, appliers, row, shouldApplyItem);
return filterItem;
};
/**
* Generates a method to easily check if a row is matching the current quick filter.
* @param {any[]} filterModel The model with which we want to filter the rows.
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
*/
const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
const quickFilterValues = filterModel.quickFilterValues?.filter(Boolean) ?? [];
if (quickFilterValues.length === 0) {
return null;
}
const quickFilterExcludeHiddenColumns = filterModel.quickFilterExcludeHiddenColumns ?? false;
const columnFields = quickFilterExcludeHiddenColumns ? (0, _columns.gridVisibleColumnFieldsSelector)(apiRef) : (0, _columns.gridColumnFieldsSelector)(apiRef);
const appliersPerField = [];
const {
ignoreDiacritics
} = apiRef.current.rootProps;
const publicApiRef = (0, _getPublicApiRef.getPublicApiRef)(apiRef);
columnFields.forEach(field => {
const column = apiRef.current.getColumn(field);
const getApplyQuickFilterFn = column?.getApplyQuickFilterFn;
const getApplyQuickFilterFnV7 = column?.getApplyQuickFilterFnV7;
const hasUserFunctionLegacy = !(0, _utils.isInternalFilter)(getApplyQuickFilterFn);
const hasUserFunctionV7 = !(0, _utils.isInternalFilter)(getApplyQuickFilterFnV7);
if (getApplyQuickFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) {
appliersPerField.push({
column,
appliers: quickFilterValues.map(quickFilterValue => {
const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue;
return {
v7: true,
fn: getApplyQuickFilterFnV7(value, column, publicApiRef)
};
})
});
} else if (getApplyQuickFilterFn) {
appliersPerField.push({
column,
appliers: quickFilterValues.map(quickFilterValue => {
const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue;
return {
v7: false,
fn: getApplyQuickFilterFn(value, column, publicApiRef)
};
})
});
}
});
return function isRowMatchingQuickFilter(row, shouldApplyFilter) {
const result = {};
const usedCellParams = {};
/* eslint-disable no-restricted-syntax, no-labels */
outer: for (let v = 0; v < quickFilterValues.length; v += 1) {
const filterValue = quickFilterValues[v];
for (let i = 0; i < appliersPerField.length; i += 1) {
const {
column,
appliers
} = appliersPerField[i];
const {
field
} = column;
if (shouldApplyFilter && !shouldApplyFilter(field)) {
continue;
}
const applier = appliers[v];
let value = apiRef.current.getRowValue(row, column);
if (applier.fn === null) {
continue;
}
if (applier.v7) {
if (ignoreDiacritics) {
value = removeDiacritics(value);
}
const isMatching = applier.fn(value, row, column, publicApiRef);
if (isMatching) {
result[filterValue] = true;
continue outer;
}
} else {
const cellParams = usedCellParams[field] ?? apiRef.current.getCellParams(apiRef.current.getRowId(row), field);
if (ignoreDiacritics) {
cellParams.value = removeDiacritics(cellParams.value);
}
usedCellParams[field] = cellParams;
const isMatching = applier.fn(cellParams);
if (isMatching) {
result[filterValue] = true;
continue outer;
}
}
}
result[filterValue] = false;
}
/* eslint-enable no-restricted-syntax, no-labels */
return result;
};
};
const buildAggregatedFilterApplier = (filterModel, apiRef, disableEval) => {
const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(filterModel, apiRef, disableEval);
const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(filterModel, apiRef);
return function isRowMatchingFilters(row, shouldApplyFilter, result) {
result.passingFilterItems = isRowMatchingFilterItems?.(row, shouldApplyFilter) ?? null;
result.passingQuickFilterValues = isRowMatchingQuickFilter?.(row, shouldApplyFilter) ?? null;
};
};
exports.buildAggregatedFilterApplier = buildAggregatedFilterApplier;
const isNotNull = result => result != null;
const filterModelItems = (cache, apiRef, items) => {
if (!cache.cleanedFilterItems) {
cache.cleanedFilterItems = items.filter(item => getFilterCallbackFromItem(item, apiRef) !== null);
}
return cache.cleanedFilterItems;
};
const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel, apiRef, cache) => {
const cleanedFilterItems = filterModelItems(cache, apiRef, filterModel.items);
const cleanedFilterItemResults = allFilterItemResults.filter(isNotNull);
const cleanedQuickFilterResults = allQuickFilterResults.filter(isNotNull);
// get result for filter items model
if (cleanedFilterItemResults.length > 0) {
// Return true if the item pass with one of the rows
const filterItemPredicate = item => {
return cleanedFilterItemResults.some(filterItemResult => filterItemResult[item.id]);
};
const logicOperator = filterModel.logicOperator ?? (0, _gridFilterState.getDefaultGridFilterModel)().logicOperator;
if (logicOperator === _models.GridLogicOperator.And) {
const passesAllFilters = cleanedFilterItems.every(filterItemPredicate);
if (!passesAllFilters) {
return false;
}
} else {
const passesSomeFilters = cleanedFilterItems.some(filterItemPredicate);
if (!passesSomeFilters) {
return false;
}
}
}
// get result for quick filter model
if (cleanedQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) {
// Return true if the item pass with one of the rows
const quickFilterValuePredicate = value => {
return cleanedQuickFilterResults.some(quickFilterValueResult => quickFilterValueResult[value]);
};
const quickFilterLogicOperator = filterModel.quickFilterLogicOperator ?? (0, _gridFilterState.getDefaultGridFilterModel)().quickFilterLogicOperator;
if (quickFilterLogicOperator === _models.GridLogicOperator.And) {
const passesAllQuickFilterValues = filterModel.quickFilterValues.every(quickFilterValuePredicate);
if (!passesAllQuickFilterValues) {
return false;
}
} else {
const passesSomeQuickFilterValues = filterModel.quickFilterValues.some(quickFilterValuePredicate);
if (!passesSomeQuickFilterValues) {
return false;
}
}
}
return true;
};
exports.passFilterLogic = passFilterLogic;

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _exportNames = {
getDefaultGridFilterModel: true
};
Object.defineProperty(exports, "getDefaultGridFilterModel", {
enumerable: true,
get: function () {
return _gridFilterState.getDefaultGridFilterModel;
}
});
var _gridFilterState = require("./gridFilterState");
var _gridFilterSelector = require("./gridFilterSelector");
Object.keys(_gridFilterSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _gridFilterSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridFilterSelector[key];
}
});
});

View File

@@ -0,0 +1,374 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridFilter = exports.filterStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _reselect = require("reselect");
var _utils = require("@mui/utils");
var _useLazyRef = require("../../utils/useLazyRef");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _gridPreferencePanelsValue = require("../preferencesPanel/gridPreferencePanelsValue");
var _gridFilterState = require("./gridFilterState");
var _gridFilterSelector = require("./gridFilterSelector");
var _useFirstRender = require("../../utils/useFirstRender");
var _rows = require("../rows");
var _pipeProcessing = require("../../core/pipeProcessing");
var _strategyProcessing = require("../../core/strategyProcessing");
var _gridFilterUtils = require("./gridFilterUtils");
var _utils2 = require("../../../utils/utils");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const filterStateInitializer = (state, props, apiRef) => {
const filterModel = props.filterModel ?? props.initialState?.filter?.filterModel ?? (0, _gridFilterState.getDefaultGridFilterModel)();
return (0, _extends2.default)({}, state, {
filter: {
filterModel: (0, _gridFilterUtils.sanitizeFilterModel)(filterModel, props.disableMultipleColumnsFiltering, apiRef),
filteredRowsLookup: {},
filteredDescendantCountLookup: {}
},
visibleRowsLookup: {}
});
};
exports.filterStateInitializer = filterStateInitializer;
const getVisibleRowsLookup = params => {
// For flat tree, the `visibleRowsLookup` and the `filteredRowsLookup` are equals since no row is collapsed.
return params.filteredRowsLookup;
};
function getVisibleRowsLookupState(apiRef, state) {
return apiRef.current.applyStrategyProcessor('visibleRowsLookupCreation', {
tree: state.rows.tree,
filteredRowsLookup: state.filter.filteredRowsLookup
});
}
function createMemoizedValues() {
return (0, _reselect.defaultMemoize)(Object.values);
}
/**
* @requires useGridColumns (method, event)
* @requires useGridParamsApi (method)
* @requires useGridRows (event)
*/
const useGridFilter = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridFilter');
apiRef.current.registerControlState({
stateId: 'filter',
propModel: props.filterModel,
propOnChange: props.onFilterModelChange,
stateSelector: _gridFilterSelector.gridFilterModelSelector,
changeEvent: 'filterModelChange'
});
const updateFilteredRows = React.useCallback(() => {
apiRef.current.setState(state => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(state, apiRef.current.instanceId);
const isRowMatchingFilters = props.filterMode === 'client' ? (0, _gridFilterUtils.buildAggregatedFilterApplier)(filterModel, apiRef, props.disableEval) : null;
const filteringResult = apiRef.current.applyStrategyProcessor('filtering', {
isRowMatchingFilters,
filterModel: filterModel ?? (0, _gridFilterState.getDefaultGridFilterModel)()
});
const newState = (0, _extends2.default)({}, state, {
filter: (0, _extends2.default)({}, state.filter, filteringResult)
});
const visibleRowsLookupState = getVisibleRowsLookupState(apiRef, newState);
return (0, _extends2.default)({}, newState, {
visibleRowsLookup: visibleRowsLookupState
});
});
apiRef.current.publishEvent('filteredRowsSet');
}, [apiRef, props.filterMode, props.disableEval]);
const addColumnMenuItem = React.useCallback((columnMenuItems, colDef) => {
if (colDef == null || colDef.filterable === false || props.disableColumnFilter) {
return columnMenuItems;
}
return [...columnMenuItems, 'columnMenuFilterItem'];
}, [props.disableColumnFilter]);
/**
* API METHODS
*/
const applyFilters = React.useCallback(() => {
updateFilteredRows();
apiRef.current.forceUpdate();
}, [apiRef, updateFilteredRows]);
const upsertFilterItem = React.useCallback(item => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
const items = [...filterModel.items];
const itemIndex = items.findIndex(filterItem => filterItem.id === item.id);
if (itemIndex === -1) {
items.push(item);
} else {
items[itemIndex] = item;
}
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
items
}), 'upsertFilterItem');
}, [apiRef]);
const upsertFilterItems = React.useCallback(items => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
const existingItems = [...filterModel.items];
items.forEach(item => {
const itemIndex = items.findIndex(filterItem => filterItem.id === item.id);
if (itemIndex === -1) {
existingItems.push(item);
} else {
existingItems[itemIndex] = item;
}
});
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
items
}), 'upsertFilterItems');
}, [apiRef]);
const deleteFilterItem = React.useCallback(itemToDelete => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
const items = filterModel.items.filter(item => item.id !== itemToDelete.id);
if (items.length === filterModel.items.length) {
return;
}
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
items
}), 'deleteFilterItem');
}, [apiRef]);
const showFilterPanel = React.useCallback((targetColumnField, panelId, labelId) => {
logger.debug('Displaying filter panel');
if (targetColumnField) {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
const filterItemsWithValue = filterModel.items.filter(item => {
if (item.value !== undefined) {
// Some filters like `isAnyOf` support array as `item.value`.
// If array is empty, we want to remove it from the filter model.
if (Array.isArray(item.value) && item.value.length === 0) {
return false;
}
return true;
}
const column = apiRef.current.getColumn(item.field);
const filterOperator = column.filterOperators?.find(operator => operator.value === item.operator);
const requiresFilterValue = typeof filterOperator?.requiresFilterValue === 'undefined' ? true : filterOperator?.requiresFilterValue;
// Operators like `isEmpty` don't have and don't require `item.value`.
// So we don't want to remove them from the filter model if `item.value === undefined`.
// See https://github.com/mui/mui-x/issues/5402
if (requiresFilterValue) {
return false;
}
return true;
});
let newFilterItems;
const filterItemOnTarget = filterItemsWithValue.find(item => item.field === targetColumnField);
const targetColumn = apiRef.current.getColumn(targetColumnField);
if (filterItemOnTarget) {
newFilterItems = filterItemsWithValue;
} else if (props.disableMultipleColumnsFiltering) {
newFilterItems = [(0, _gridFilterUtils.cleanFilterItem)({
field: targetColumnField,
operator: targetColumn.filterOperators[0].value
}, apiRef)];
} else {
newFilterItems = [...filterItemsWithValue, (0, _gridFilterUtils.cleanFilterItem)({
field: targetColumnField,
operator: targetColumn.filterOperators[0].value
}, apiRef)];
}
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
items: newFilterItems
}));
}
apiRef.current.showPreferences(_gridPreferencePanelsValue.GridPreferencePanelsValue.filters, panelId, labelId);
}, [apiRef, logger, props.disableMultipleColumnsFiltering]);
const hideFilterPanel = React.useCallback(() => {
logger.debug('Hiding filter panel');
apiRef.current.hidePreferences();
}, [apiRef, logger]);
const setFilterLogicOperator = React.useCallback(logicOperator => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
if (filterModel.logicOperator === logicOperator) {
return;
}
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
logicOperator
}), 'changeLogicOperator');
}, [apiRef]);
const setQuickFilterValues = React.useCallback(values => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
if ((0, _utils2.isDeepEqual)(filterModel.quickFilterValues, values)) {
return;
}
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
quickFilterValues: [...values]
}));
}, [apiRef]);
const setFilterModel = React.useCallback((model, reason) => {
const currentModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
if (currentModel !== model) {
logger.debug('Setting filter model');
apiRef.current.updateControlState('filter', (0, _gridFilterUtils.mergeStateWithFilterModel)(model, props.disableMultipleColumnsFiltering, apiRef), reason);
apiRef.current.unstable_applyFilters();
}
}, [apiRef, logger, props.disableMultipleColumnsFiltering]);
const filterApi = {
setFilterLogicOperator,
unstable_applyFilters: applyFilters,
deleteFilterItem,
upsertFilterItem,
upsertFilterItems,
setFilterModel,
showFilterPanel,
hideFilterPanel,
setQuickFilterValues,
ignoreDiacritics: props.ignoreDiacritics
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, filterApi, 'public');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const filterModelToExport = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
const shouldExportFilterModel =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the model is controlled
props.filterModel != null ||
// Always export if the model has been initialized
props.initialState?.filter?.filterModel != null ||
// Export if the model is not equal to the default value
!(0, _utils2.isDeepEqual)(filterModelToExport, (0, _gridFilterState.getDefaultGridFilterModel)());
if (!shouldExportFilterModel) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
filter: {
filterModel: filterModelToExport
}
});
}, [apiRef, props.filterModel, props.initialState?.filter?.filterModel]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const filterModel = context.stateToRestore.filter?.filterModel;
if (filterModel == null) {
return params;
}
apiRef.current.updateControlState('filter', (0, _gridFilterUtils.mergeStateWithFilterModel)(filterModel, props.disableMultipleColumnsFiltering, apiRef), 'restoreState');
return (0, _extends2.default)({}, params, {
callbacks: [...params.callbacks, apiRef.current.unstable_applyFilters]
});
}, [apiRef, props.disableMultipleColumnsFiltering]);
const preferencePanelPreProcessing = React.useCallback((initialValue, value) => {
if (value === _gridPreferencePanelsValue.GridPreferencePanelsValue.filters) {
const FilterPanel = props.slots.filterPanel;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FilterPanel, (0, _extends2.default)({}, props.slotProps?.filterPanel));
}
return initialValue;
}, [props.slots.filterPanel, props.slotProps?.filterPanel]);
const {
getRowId
} = props;
const getRowsRef = (0, _useLazyRef.useLazyRef)(createMemoizedValues);
const flatFilteringMethod = React.useCallback(params => {
if (props.filterMode !== 'client' || !params.isRowMatchingFilters) {
return {
filteredRowsLookup: {},
filteredDescendantCountLookup: {}
};
}
const dataRowIdToModelLookup = (0, _rows.gridRowsLookupSelector)(apiRef);
const filteredRowsLookup = {};
const {
isRowMatchingFilters
} = params;
const filterCache = {};
const result = {
passingFilterItems: null,
passingQuickFilterValues: null
};
const rows = getRowsRef.current(apiRef.current.state.rows.dataRowIdToModelLookup);
for (let i = 0; i < rows.length; i += 1) {
const row = rows[i];
const id = getRowId ? getRowId(row) : row.id;
isRowMatchingFilters(row, undefined, result);
const isRowPassing = (0, _gridFilterUtils.passFilterLogic)([result.passingFilterItems], [result.passingQuickFilterValues], params.filterModel, apiRef, filterCache);
filteredRowsLookup[id] = isRowPassing;
}
const footerId = 'auto-generated-group-footer-root';
const footer = dataRowIdToModelLookup[footerId];
if (footer) {
filteredRowsLookup[footerId] = true;
}
return {
filteredRowsLookup,
filteredDescendantCountLookup: {}
};
}, [apiRef, props.filterMode, getRowId, getRowsRef]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'columnMenu', addColumnMenuItem);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'preferencePanel', preferencePanelPreProcessing);
(0, _strategyProcessing.useGridRegisterStrategyProcessor)(apiRef, _strategyProcessing.GRID_DEFAULT_STRATEGY, 'filtering', flatFilteringMethod);
(0, _strategyProcessing.useGridRegisterStrategyProcessor)(apiRef, _strategyProcessing.GRID_DEFAULT_STRATEGY, 'visibleRowsLookupCreation', getVisibleRowsLookup);
/**
* EVENTS
*/
const handleColumnsChange = React.useCallback(() => {
logger.debug('onColUpdated - GridColumns changed, applying filters');
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
const filterableColumnsLookup = (0, _gridColumnsSelector.gridFilterableColumnLookupSelector)(apiRef);
const newFilterItems = filterModel.items.filter(item => item.field && filterableColumnsLookup[item.field]);
if (newFilterItems.length < filterModel.items.length) {
apiRef.current.setFilterModel((0, _extends2.default)({}, filterModel, {
items: newFilterItems
}));
}
}, [apiRef, logger]);
const handleStrategyProcessorChange = React.useCallback(methodName => {
if (methodName === 'filtering') {
apiRef.current.unstable_applyFilters();
}
}, [apiRef]);
const updateVisibleRowsLookupState = React.useCallback(() => {
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
visibleRowsLookup: getVisibleRowsLookupState(apiRef, state)
});
});
apiRef.current.forceUpdate();
}, [apiRef]);
// Do not call `apiRef.current.forceUpdate` to avoid re-render before updating the sorted rows.
// Otherwise, the state is not consistent during the render
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowsSet', updateFilteredRows);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnsChange', handleColumnsChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'activeStrategyProcessorChange', handleStrategyProcessorChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowExpansionChange', updateVisibleRowsLookupState);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnVisibilityModelChange', () => {
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
if (filterModel.quickFilterValues && filterModel.quickFilterExcludeHiddenColumns) {
// re-apply filters because the quick filter results may have changed
apiRef.current.unstable_applyFilters();
}
});
/**
* 1ST RENDER
*/
(0, _useFirstRender.useFirstRender)(() => {
apiRef.current.unstable_applyFilters();
});
/**
* EFFECTS
*/
(0, _utils.unstable_useEnhancedEffect)(() => {
if (props.filterModel !== undefined) {
apiRef.current.setFilterModel(props.filterModel);
}
}, [apiRef, logger, props.filterModel]);
};
exports.useGridFilter = useGridFilter;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.unstable_gridTabIndexColumnHeaderFilterSelector = exports.unstable_gridTabIndexColumnGroupHeaderSelector = exports.unstable_gridFocusColumnHeaderFilterSelector = exports.unstable_gridFocusColumnGroupHeaderSelector = exports.gridTabIndexStateSelector = exports.gridTabIndexColumnHeaderSelector = exports.gridTabIndexCellSelector = exports.gridFocusStateSelector = exports.gridFocusColumnHeaderSelector = exports.gridFocusCellSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
const gridFocusStateSelector = state => state.focus;
exports.gridFocusStateSelector = gridFocusStateSelector;
const gridFocusCellSelector = exports.gridFocusCellSelector = (0, _createSelector.createSelector)(gridFocusStateSelector, focusState => focusState.cell);
const gridFocusColumnHeaderSelector = exports.gridFocusColumnHeaderSelector = (0, _createSelector.createSelector)(gridFocusStateSelector, focusState => focusState.columnHeader);
// eslint-disable-next-line @typescript-eslint/naming-convention
const unstable_gridFocusColumnHeaderFilterSelector = exports.unstable_gridFocusColumnHeaderFilterSelector = (0, _createSelector.createSelector)(gridFocusStateSelector, focusState => focusState.columnHeaderFilter);
// eslint-disable-next-line @typescript-eslint/naming-convention
const unstable_gridFocusColumnGroupHeaderSelector = exports.unstable_gridFocusColumnGroupHeaderSelector = (0, _createSelector.createSelector)(gridFocusStateSelector, focusState => focusState.columnGroupHeader);
const gridTabIndexStateSelector = state => state.tabIndex;
exports.gridTabIndexStateSelector = gridTabIndexStateSelector;
const gridTabIndexCellSelector = exports.gridTabIndexCellSelector = (0, _createSelector.createSelector)(gridTabIndexStateSelector, state => state.cell);
const gridTabIndexColumnHeaderSelector = exports.gridTabIndexColumnHeaderSelector = (0, _createSelector.createSelector)(gridTabIndexStateSelector, state => state.columnHeader);
// eslint-disable-next-line @typescript-eslint/naming-convention
const unstable_gridTabIndexColumnHeaderFilterSelector = exports.unstable_gridTabIndexColumnHeaderFilterSelector = (0, _createSelector.createSelector)(gridTabIndexStateSelector, state => state.columnHeaderFilter);
// eslint-disable-next-line @typescript-eslint/naming-convention
const unstable_gridTabIndexColumnGroupHeaderSelector = exports.unstable_gridTabIndexColumnGroupHeaderSelector = (0, _createSelector.createSelector)(gridTabIndexStateSelector, state => state.columnGroupHeader);

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridFocusStateSelector = require("./gridFocusStateSelector");
Object.keys(_gridFocusStateSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridFocusStateSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridFocusStateSelector[key];
}
});
});
var _gridFocusState = require("./gridFocusState");
Object.keys(_gridFocusState).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridFocusState[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridFocusState[key];
}
});
});

View File

@@ -0,0 +1,404 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridFocus = exports.focusStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _gridClasses = require("../../../constants/gridClasses");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _gridFocusStateSelector = require("./gridFocusStateSelector");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _utils2 = require("../../../utils/utils");
var _gridRowsSelector = require("../rows/gridRowsSelector");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const focusStateInitializer = state => (0, _extends2.default)({}, state, {
focus: {
cell: null,
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
},
tabIndex: {
cell: null,
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
}
});
/**
* @requires useGridParamsApi (method)
* @requires useGridRows (method)
* @requires useGridEditing (event)
*/
exports.focusStateInitializer = focusStateInitializer;
const useGridFocus = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridFocus');
const lastClickedCell = React.useRef(null);
const publishCellFocusOut = React.useCallback((cell, event) => {
if (cell) {
// The row might have been deleted
if (apiRef.current.getRow(cell.id)) {
apiRef.current.publishEvent('cellFocusOut', apiRef.current.getCellParams(cell.id, cell.field), event);
}
}
}, [apiRef]);
const setCellFocus = React.useCallback((id, field) => {
const focusedCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (focusedCell?.id === id && focusedCell?.field === field) {
return;
}
apiRef.current.setState(state => {
logger.debug(`Focusing on cell with id=${id} and field=${field}`);
return (0, _extends2.default)({}, state, {
tabIndex: {
cell: {
id,
field
},
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
},
focus: {
cell: {
id,
field
},
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
}
});
});
apiRef.current.forceUpdate();
// The row might have been deleted
if (!apiRef.current.getRow(id)) {
return;
}
if (focusedCell) {
// There's a focused cell but another cell was clicked
// Publishes an event to notify that the focus was lost
publishCellFocusOut(focusedCell, {});
}
apiRef.current.publishEvent('cellFocusIn', apiRef.current.getCellParams(id, field));
}, [apiRef, logger, publishCellFocusOut]);
const setColumnHeaderFocus = React.useCallback((field, event = {}) => {
const cell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
publishCellFocusOut(cell, event);
apiRef.current.setState(state => {
logger.debug(`Focusing on column header with colIndex=${field}`);
return (0, _extends2.default)({}, state, {
tabIndex: {
columnHeader: {
field
},
columnHeaderFilter: null,
cell: null,
columnGroupHeader: null
},
focus: {
columnHeader: {
field
},
columnHeaderFilter: null,
cell: null,
columnGroupHeader: null
}
});
});
apiRef.current.forceUpdate();
}, [apiRef, logger, publishCellFocusOut]);
const setColumnHeaderFilterFocus = React.useCallback((field, event = {}) => {
const cell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
publishCellFocusOut(cell, event);
apiRef.current.setState(state => {
logger.debug(`Focusing on column header filter with colIndex=${field}`);
return (0, _extends2.default)({}, state, {
tabIndex: {
columnHeader: null,
columnHeaderFilter: {
field
},
cell: null,
columnGroupHeader: null
},
focus: {
columnHeader: null,
columnHeaderFilter: {
field
},
cell: null,
columnGroupHeader: null
}
});
});
apiRef.current.forceUpdate();
}, [apiRef, logger, publishCellFocusOut]);
const setColumnGroupHeaderFocus = React.useCallback((field, depth, event = {}) => {
const cell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (cell) {
apiRef.current.publishEvent('cellFocusOut', apiRef.current.getCellParams(cell.id, cell.field), event);
}
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
tabIndex: {
columnGroupHeader: {
field,
depth
},
columnHeader: null,
columnHeaderFilter: null,
cell: null
},
focus: {
columnGroupHeader: {
field,
depth
},
columnHeader: null,
columnHeaderFilter: null,
cell: null
}
});
});
apiRef.current.forceUpdate();
}, [apiRef]);
const getColumnGroupHeaderFocus = React.useCallback(() => (0, _gridFocusStateSelector.unstable_gridFocusColumnGroupHeaderSelector)(apiRef), [apiRef]);
const moveFocusToRelativeCell = React.useCallback((id, field, direction) => {
let columnIndexToFocus = apiRef.current.getColumnIndex(field);
const visibleColumns = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef);
const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef, {
pagination: props.pagination,
paginationMode: props.paginationMode
});
const pinnedRows = (0, _gridRowsSelector.gridPinnedRowsSelector)(apiRef);
// Include pinned rows as well
const currentPageRows = [].concat(pinnedRows.top || [], currentPage.rows, pinnedRows.bottom || []);
let rowIndexToFocus = currentPageRows.findIndex(row => row.id === id);
if (direction === 'right') {
columnIndexToFocus += 1;
} else if (direction === 'left') {
columnIndexToFocus -= 1;
} else {
rowIndexToFocus += 1;
}
if (columnIndexToFocus >= visibleColumns.length) {
// Go to next row if we are after the last column
rowIndexToFocus += 1;
if (rowIndexToFocus < currentPageRows.length) {
// Go to first column of the next row if there's one more row
columnIndexToFocus = 0;
}
} else if (columnIndexToFocus < 0) {
// Go to previous row if we are before the first column
rowIndexToFocus -= 1;
if (rowIndexToFocus >= 0) {
// Go to last column of the previous if there's one more row
columnIndexToFocus = visibleColumns.length - 1;
}
}
rowIndexToFocus = (0, _utils2.clamp)(rowIndexToFocus, 0, currentPageRows.length - 1);
const rowToFocus = currentPageRows[rowIndexToFocus];
if (!rowToFocus) {
return;
}
const colSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowToFocus.id, columnIndexToFocus);
if (colSpanInfo && colSpanInfo.spannedByColSpan) {
if (direction === 'left' || direction === 'below') {
columnIndexToFocus = colSpanInfo.leftVisibleCellIndex;
} else if (direction === 'right') {
columnIndexToFocus = colSpanInfo.rightVisibleCellIndex;
}
}
columnIndexToFocus = (0, _utils2.clamp)(columnIndexToFocus, 0, visibleColumns.length - 1);
const columnToFocus = visibleColumns[columnIndexToFocus];
apiRef.current.setCellFocus(rowToFocus.id, columnToFocus.field);
}, [apiRef, props.pagination, props.paginationMode]);
const handleCellDoubleClick = React.useCallback(({
id,
field
}) => {
apiRef.current.setCellFocus(id, field);
}, [apiRef]);
const handleCellKeyDown = React.useCallback((params, event) => {
// GRID_CELL_NAVIGATION_KEY_DOWN handles the focus on Enter, Tab and navigation keys
if (event.key === 'Enter' || event.key === 'Tab' || event.key === 'Shift' || (0, _keyboardUtils.isNavigationKey)(event.key)) {
return;
}
apiRef.current.setCellFocus(params.id, params.field);
}, [apiRef]);
const handleColumnHeaderFocus = React.useCallback(({
field
}, event) => {
if (event.target !== event.currentTarget) {
return;
}
apiRef.current.setColumnHeaderFocus(field, event);
}, [apiRef]);
const handleColumnGroupHeaderFocus = React.useCallback(({
fields,
depth
}, event) => {
if (event.target !== event.currentTarget) {
return;
}
const focusedColumnGroup = (0, _gridFocusStateSelector.unstable_gridFocusColumnGroupHeaderSelector)(apiRef);
if (focusedColumnGroup !== null && focusedColumnGroup.depth === depth && fields.includes(focusedColumnGroup.field)) {
// This group cell has already been focused
return;
}
apiRef.current.setColumnGroupHeaderFocus(fields[0], depth, event);
}, [apiRef]);
const handleBlur = React.useCallback((_, event) => {
if (event.relatedTarget?.className.includes(_gridClasses.gridClasses.columnHeader)) {
return;
}
logger.debug(`Clearing focus`);
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
focus: {
cell: null,
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
}
}));
}, [logger, apiRef]);
const handleCellMouseDown = React.useCallback(params => {
lastClickedCell.current = params;
}, []);
const handleDocumentClick = React.useCallback(event => {
const cellParams = lastClickedCell.current;
lastClickedCell.current = null;
const focusedCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
const canUpdateFocus = apiRef.current.unstable_applyPipeProcessors('canUpdateFocus', true, {
event,
cell: cellParams
});
if (!canUpdateFocus) {
return;
}
if (!focusedCell) {
if (cellParams) {
apiRef.current.setCellFocus(cellParams.id, cellParams.field);
}
return;
}
if (cellParams?.id === focusedCell.id && cellParams?.field === focusedCell.field) {
return;
}
const cellElement = apiRef.current.getCellElement(focusedCell.id, focusedCell.field);
if (cellElement?.contains(event.target)) {
return;
}
if (cellParams) {
apiRef.current.setCellFocus(cellParams.id, cellParams.field);
} else {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
focus: {
cell: null,
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
}
}));
apiRef.current.forceUpdate();
// There's a focused cell but another element (not a cell) was clicked
// Publishes an event to notify that the focus was lost
publishCellFocusOut(focusedCell, event);
}
}, [apiRef, publishCellFocusOut]);
const handleCellModeChange = React.useCallback(params => {
if (params.cellMode === 'view') {
return;
}
const cell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (cell?.id !== params.id || cell?.field !== params.field) {
apiRef.current.setCellFocus(params.id, params.field);
}
}, [apiRef]);
const handleRowSet = React.useCallback(() => {
const cell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
// If the focused cell is in a row which does not exist anymore, then remove the focus
if (cell && !apiRef.current.getRow(cell.id)) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
focus: {
cell: null,
columnHeader: null,
columnHeaderFilter: null,
columnGroupHeader: null
}
}));
}
}, [apiRef]);
const handlePaginationModelChange = (0, _utils.unstable_useEventCallback)(() => {
const currentFocusedCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (!currentFocusedCell) {
return;
}
const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef, {
pagination: props.pagination,
paginationMode: props.paginationMode
});
const rowIsInCurrentPage = currentPage.rows.find(row => row.id === currentFocusedCell.id);
if (rowIsInCurrentPage) {
return;
}
const visibleColumns = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef);
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
tabIndex: {
cell: {
id: currentPage.rows[0].id,
field: visibleColumns[0].field
},
columnGroupHeader: null,
columnHeader: null,
columnHeaderFilter: null
}
});
});
});
const focusApi = {
setCellFocus,
setColumnHeaderFocus,
setColumnHeaderFilterFocus
};
const focusPrivateApi = {
moveFocusToRelativeCell,
setColumnGroupHeaderFocus,
getColumnGroupHeaderFocus
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, focusApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, focusPrivateApi, 'private');
React.useEffect(() => {
const doc = (0, _utils.unstable_ownerDocument)(apiRef.current.rootElementRef.current);
doc.addEventListener('mouseup', handleDocumentClick);
return () => {
doc.removeEventListener('mouseup', handleDocumentClick);
};
}, [apiRef, handleDocumentClick]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderBlur', handleBlur);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', handleCellDoubleClick);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellMouseDown', handleCellMouseDown);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', handleCellKeyDown);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellModeChange', handleCellModeChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderFocus', handleColumnHeaderFocus);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnGroupHeaderFocus', handleColumnGroupHeaderFocus);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowsSet', handleRowSet);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'paginationModelChange', handlePaginationModelChange);
};
exports.useGridFocus = useGridFocus;

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.unstable_gridHeaderFilteringStateSelector = exports.unstable_gridHeaderFilteringMenuSelector = exports.unstable_gridHeaderFilteringEditFieldSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
/* eslint-disable @typescript-eslint/naming-convention */
const unstable_gridHeaderFilteringStateSelector = state => state.headerFiltering;
exports.unstable_gridHeaderFilteringStateSelector = unstable_gridHeaderFilteringStateSelector;
const unstable_gridHeaderFilteringEditFieldSelector = exports.unstable_gridHeaderFilteringEditFieldSelector = (0, _createSelector.createSelector)(unstable_gridHeaderFilteringStateSelector, headerFilteringState => headerFilteringState.editing);
const unstable_gridHeaderFilteringMenuSelector = exports.unstable_gridHeaderFilteringMenuSelector = (0, _createSelector.createSelector)(unstable_gridHeaderFilteringStateSelector, headerFilteringState => headerFilteringState.menuOpen);

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridHeaderFilteringSelectors = require("./gridHeaderFilteringSelectors");
Object.keys(_gridHeaderFilteringSelectors).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridHeaderFilteringSelectors[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridHeaderFilteringSelectors[key];
}
});
});

View File

@@ -0,0 +1,101 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridHeaderFiltering = exports.headerFilteringStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _utils = require("../../utils");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const headerFilteringStateInitializer = state => (0, _extends2.default)({}, state, {
headerFiltering: {
editing: null,
menuOpen: null
}
});
exports.headerFilteringStateInitializer = headerFilteringStateInitializer;
const useGridHeaderFiltering = (apiRef, props) => {
const logger = (0, _utils.useGridLogger)(apiRef, 'useGridHeaderFiltering');
const setHeaderFilterState = React.useCallback(headerFilterState => {
apiRef.current.setState(state => {
// Safety check to avoid MIT users from using it
// This hook should ultimately be moved to the Pro package
if (props.signature === 'DataGrid') {
return state;
}
return (0, _extends2.default)({}, state, {
headerFiltering: {
editing: headerFilterState.editing ?? null,
menuOpen: headerFilterState.menuOpen ?? null
}
});
});
apiRef.current.forceUpdate();
}, [apiRef, props.signature]);
const startHeaderFilterEditMode = React.useCallback(field => {
logger.debug(`Starting edit mode on header filter for field: ${field}`);
apiRef.current.setHeaderFilterState({
editing: field
});
}, [apiRef, logger]);
const stopHeaderFilterEditMode = React.useCallback(() => {
logger.debug(`Stopping edit mode on header filter`);
apiRef.current.setHeaderFilterState({
editing: null
});
}, [apiRef, logger]);
const showHeaderFilterMenu = React.useCallback(field => {
logger.debug(`Opening header filter menu for field: ${field}`);
apiRef.current.setHeaderFilterState({
menuOpen: field
});
}, [apiRef, logger]);
const hideHeaderFilterMenu = React.useCallback(() => {
logger.debug(`Hiding header filter menu for active field`);
let fieldToFocus = apiRef.current.state.headerFiltering.menuOpen;
if (fieldToFocus) {
const columnLookup = (0, _gridColumnsSelector.gridColumnLookupSelector)(apiRef);
const columnVisibilityModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const orderedFields = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
// If the column was removed from the grid, we need to find the closest visible field
if (!columnLookup[fieldToFocus]) {
fieldToFocus = orderedFields[0];
}
// If the field to focus is hidden, we need to find the closest visible field
if (columnVisibilityModel[fieldToFocus] === false) {
// contains visible column fields + the field that was just hidden
const visibleOrderedFields = orderedFields.filter(field => {
if (field === fieldToFocus) {
return true;
}
return columnVisibilityModel[field] !== false;
});
const fieldIndex = visibleOrderedFields.indexOf(fieldToFocus);
fieldToFocus = visibleOrderedFields[fieldIndex + 1] || visibleOrderedFields[fieldIndex - 1];
}
apiRef.current.setHeaderFilterState({
menuOpen: null
});
apiRef.current.setColumnHeaderFilterFocus(fieldToFocus);
}
}, [apiRef, logger]);
const headerFilterPrivateApi = {
setHeaderFilterState
};
const headerFilterApi = {
startHeaderFilterEditMode,
stopHeaderFilterEditMode,
showHeaderFilterMenu,
hideHeaderFilterMenu
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, headerFilterApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, headerFilterPrivateApi, 'private');
};
exports.useGridHeaderFiltering = useGridHeaderFiltering;

View File

@@ -0,0 +1,170 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _columnMenu = require("./columnMenu");
Object.keys(_columnMenu).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _columnMenu[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _columnMenu[key];
}
});
});
var _columns = require("./columns");
Object.keys(_columns).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _columns[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _columns[key];
}
});
});
var _columnGrouping = require("./columnGrouping");
Object.keys(_columnGrouping).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _columnGrouping[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _columnGrouping[key];
}
});
});
var _density = require("./density");
Object.keys(_density).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _density[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _density[key];
}
});
});
var _filter = require("./filter");
Object.keys(_filter).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _filter[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _filter[key];
}
});
});
var _focus = require("./focus");
Object.keys(_focus).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _focus[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _focus[key];
}
});
});
var _pagination = require("./pagination");
Object.keys(_pagination).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _pagination[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _pagination[key];
}
});
});
var _preferencesPanel = require("./preferencesPanel");
Object.keys(_preferencesPanel).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _preferencesPanel[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _preferencesPanel[key];
}
});
});
var _rows = require("./rows");
Object.keys(_rows).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _rows[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _rows[key];
}
});
});
var _rowSelection = require("./rowSelection");
Object.keys(_rowSelection).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _rowSelection[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _rowSelection[key];
}
});
});
var _sorting = require("./sorting");
Object.keys(_sorting).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _sorting[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _sorting[key];
}
});
});
var _dimensions = require("./dimensions");
Object.keys(_dimensions).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _dimensions[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _dimensions[key];
}
});
});
var _statePersistence = require("./statePersistence");
Object.keys(_statePersistence).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _statePersistence[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _statePersistence[key];
}
});
});
var _headerFiltering = require("./headerFiltering");
Object.keys(_headerFiltering).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _headerFiltering[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _headerFiltering[key];
}
});
});
var _virtualization = require("./virtualization");
Object.keys(_virtualization).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _virtualization[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _virtualization[key];
}
});
});

View File

@@ -0,0 +1,585 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridKeyboardNavigation = void 0;
var React = _interopRequireWildcard(require("react"));
var _styles = require("@mui/material/styles");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _useGridLogger = require("../../utils/useGridLogger");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _gridCheckboxSelectionColDef = require("../../../colDef/gridCheckboxSelectionColDef");
var _gridClasses = require("../../../constants/gridClasses");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _gridDetailPanelToggleField = require("../../../constants/gridDetailPanelToggleField");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _focus = require("../focus");
var _gridColumnGroupsSelector = require("../columnGrouping/gridColumnGroupsSelector");
var _gridHeaderFilteringSelectors = require("../headerFiltering/gridHeaderFilteringSelectors");
var _pipeProcessing = require("../../core/pipeProcessing");
var _domUtils = require("../../../utils/domUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function enrichPageRowsWithPinnedRows(apiRef, rows) {
const pinnedRows = (0, _gridRowsSelector.gridPinnedRowsSelector)(apiRef) || {};
return [...(pinnedRows.top || []), ...rows, ...(pinnedRows.bottom || [])];
}
const getLeftColumnIndex = ({
currentColIndex,
firstColIndex,
lastColIndex,
direction
}) => {
if (direction === 'rtl') {
if (currentColIndex < lastColIndex) {
return currentColIndex + 1;
}
} else if (direction === 'ltr') {
if (currentColIndex > firstColIndex) {
return currentColIndex - 1;
}
}
return null;
};
const getRightColumnIndex = ({
currentColIndex,
firstColIndex,
lastColIndex,
direction
}) => {
if (direction === 'rtl') {
if (currentColIndex > firstColIndex) {
return currentColIndex - 1;
}
} else if (direction === 'ltr') {
if (currentColIndex < lastColIndex) {
return currentColIndex + 1;
}
}
return null;
};
/**
* @requires useGridSorting (method) - can be after
* @requires useGridFilter (state) - can be after
* @requires useGridColumns (state, method) - can be after
* @requires useGridDimensions (method) - can be after
* @requires useGridFocus (method) - can be after
* @requires useGridScroll (method) - can be after
* @requires useGridColumnSpanning (method) - can be after
*/
const useGridKeyboardNavigation = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridKeyboardNavigation');
const initialCurrentPageRows = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props).rows;
const theme = (0, _styles.useTheme)();
const currentPageRows = React.useMemo(() => enrichPageRowsWithPinnedRows(apiRef, initialCurrentPageRows), [apiRef, initialCurrentPageRows]);
const headerFilteringEnabled =
// @ts-expect-error // TODO move relevant code to the `DataGridPro`
props.signature !== 'DataGrid' && props.unstable_headerFilters;
/**
* @param {number} colIndex Index of the column to focus
* @param {number} rowIndex index of the row to focus
* @param {string} closestColumnToUse Which closest column cell to use when the cell is spanned by `colSpan`.
* TODO replace with apiRef.current.moveFocusToRelativeCell()
*/
const goToCell = React.useCallback((colIndex, rowId, closestColumnToUse = 'left') => {
const visibleSortedRows = (0, _gridFilterSelector.gridExpandedSortedRowEntriesSelector)(apiRef);
const nextCellColSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowId, colIndex);
if (nextCellColSpanInfo && nextCellColSpanInfo.spannedByColSpan) {
if (closestColumnToUse === 'left') {
colIndex = nextCellColSpanInfo.leftVisibleCellIndex;
} else if (closestColumnToUse === 'right') {
colIndex = nextCellColSpanInfo.rightVisibleCellIndex;
}
}
// `scrollToIndexes` requires a rowIndex relative to all visible rows.
// Those rows do not include pinned rows, but pinned rows do not need scroll anyway.
const rowIndexRelativeToAllRows = visibleSortedRows.findIndex(row => row.id === rowId);
logger.debug(`Navigating to cell row ${rowIndexRelativeToAllRows}, col ${colIndex}`);
apiRef.current.scrollToIndexes({
colIndex,
rowIndex: rowIndexRelativeToAllRows
});
const field = apiRef.current.getVisibleColumns()[colIndex].field;
apiRef.current.setCellFocus(rowId, field);
}, [apiRef, logger]);
const goToHeader = React.useCallback((colIndex, event) => {
logger.debug(`Navigating to header col ${colIndex}`);
apiRef.current.scrollToIndexes({
colIndex
});
const field = apiRef.current.getVisibleColumns()[colIndex].field;
apiRef.current.setColumnHeaderFocus(field, event);
}, [apiRef, logger]);
const goToHeaderFilter = React.useCallback((colIndex, event) => {
logger.debug(`Navigating to header filter col ${colIndex}`);
apiRef.current.scrollToIndexes({
colIndex
});
const field = apiRef.current.getVisibleColumns()[colIndex].field;
apiRef.current.setColumnHeaderFilterFocus(field, event);
}, [apiRef, logger]);
const goToGroupHeader = React.useCallback((colIndex, depth, event) => {
logger.debug(`Navigating to header col ${colIndex}`);
apiRef.current.scrollToIndexes({
colIndex
});
const {
field
} = apiRef.current.getVisibleColumns()[colIndex];
apiRef.current.setColumnGroupHeaderFocus(field, depth, event);
}, [apiRef, logger]);
const getRowIdFromIndex = React.useCallback(rowIndex => {
return currentPageRows[rowIndex]?.id;
}, [currentPageRows]);
const handleColumnHeaderKeyDown = React.useCallback((params, event) => {
const headerTitleNode = event.currentTarget.querySelector(`.${_gridClasses.gridClasses.columnHeaderTitleContainerContent}`);
const isFromInsideContent = !!headerTitleNode && headerTitleNode.contains(event.target);
if (isFromInsideContent && params.field !== _gridCheckboxSelectionColDef.GRID_CHECKBOX_SELECTION_COL_DEF.field) {
// When focus is on a nested input, keyboard events have no effect to avoid conflicts with native events.
// There is one exception for the checkBoxHeader
return;
}
const dimensions = apiRef.current.getRootDimensions();
if (!dimensions) {
return;
}
const viewportPageSize = apiRef.current.getViewportPageSize();
const colIndexBefore = params.field ? apiRef.current.getColumnIndex(params.field) : 0;
const firstRowIndexInPage = currentPageRows.length > 0 ? 0 : null;
const lastRowIndexInPage = currentPageRows.length - 1;
const firstColIndex = 0;
const lastColIndex = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef).length - 1;
const columnGroupMaxDepth = (0, _gridColumnGroupsSelector.gridColumnGroupsHeaderMaxDepthSelector)(apiRef);
let shouldPreventDefault = true;
switch (event.key) {
case 'ArrowDown':
{
if (firstRowIndexInPage !== null) {
if (headerFilteringEnabled) {
goToHeaderFilter(colIndexBefore, event);
} else {
goToCell(colIndexBefore, getRowIdFromIndex(firstRowIndexInPage));
}
}
break;
}
case 'ArrowRight':
{
const rightColIndex = getRightColumnIndex({
currentColIndex: colIndexBefore,
firstColIndex,
lastColIndex,
direction: theme.direction
});
if (rightColIndex !== null) {
goToHeader(rightColIndex, event);
}
break;
}
case 'ArrowLeft':
{
const leftColIndex = getLeftColumnIndex({
currentColIndex: colIndexBefore,
firstColIndex,
lastColIndex,
direction: theme.direction
});
if (leftColIndex !== null) {
goToHeader(leftColIndex, event);
}
break;
}
case 'ArrowUp':
{
if (columnGroupMaxDepth > 0) {
goToGroupHeader(colIndexBefore, columnGroupMaxDepth - 1, event);
}
break;
}
case 'PageDown':
{
if (firstRowIndexInPage !== null && lastRowIndexInPage !== null) {
goToCell(colIndexBefore, getRowIdFromIndex(Math.min(firstRowIndexInPage + viewportPageSize, lastRowIndexInPage)));
}
break;
}
case 'Home':
{
goToHeader(firstColIndex, event);
break;
}
case 'End':
{
goToHeader(lastColIndex, event);
break;
}
case 'Enter':
{
if (event.ctrlKey || event.metaKey) {
apiRef.current.toggleColumnMenu(params.field);
}
break;
}
case ' ':
{
// prevent Space event from scrolling
break;
}
default:
{
shouldPreventDefault = false;
}
}
if (shouldPreventDefault) {
event.preventDefault();
}
}, [apiRef, currentPageRows.length, headerFilteringEnabled, goToHeaderFilter, goToCell, getRowIdFromIndex, theme.direction, goToHeader, goToGroupHeader]);
const handleHeaderFilterKeyDown = React.useCallback((params, event) => {
const dimensions = apiRef.current.getRootDimensions();
if (!dimensions) {
return;
}
const isEditing = (0, _gridHeaderFilteringSelectors.unstable_gridHeaderFilteringEditFieldSelector)(apiRef) === params.field;
const isHeaderMenuOpen = (0, _gridHeaderFilteringSelectors.unstable_gridHeaderFilteringMenuSelector)(apiRef) === params.field;
if (isEditing || isHeaderMenuOpen || !(0, _keyboardUtils.isNavigationKey)(event.key)) {
return;
}
const viewportPageSize = apiRef.current.getViewportPageSize();
const colIndexBefore = params.field ? apiRef.current.getColumnIndex(params.field) : 0;
const firstRowIndexInPage = 0;
const lastRowIndexInPage = currentPageRows.length - 1;
const firstColIndex = 0;
const lastColIndex = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef).length - 1;
let shouldPreventDefault = true;
switch (event.key) {
case 'ArrowDown':
{
const rowId = getRowIdFromIndex(firstRowIndexInPage);
if (firstRowIndexInPage !== null && rowId != null) {
goToCell(colIndexBefore, rowId);
}
break;
}
case 'ArrowRight':
{
const rightColIndex = getRightColumnIndex({
currentColIndex: colIndexBefore,
firstColIndex,
lastColIndex,
direction: theme.direction
});
if (rightColIndex !== null) {
goToHeaderFilter(rightColIndex, event);
}
break;
}
case 'ArrowLeft':
{
const leftColIndex = getLeftColumnIndex({
currentColIndex: colIndexBefore,
firstColIndex,
lastColIndex,
direction: theme.direction
});
if (leftColIndex !== null) {
goToHeaderFilter(leftColIndex, event);
} else {
apiRef.current.setColumnHeaderFilterFocus(params.field, event);
}
break;
}
case 'ArrowUp':
{
goToHeader(colIndexBefore, event);
break;
}
case 'PageDown':
{
if (firstRowIndexInPage !== null && lastRowIndexInPage !== null) {
goToCell(colIndexBefore, getRowIdFromIndex(Math.min(firstRowIndexInPage + viewportPageSize, lastRowIndexInPage)));
}
break;
}
case 'Home':
{
goToHeaderFilter(firstColIndex, event);
break;
}
case 'End':
{
goToHeaderFilter(lastColIndex, event);
break;
}
case ' ':
{
// prevent Space event from scrolling
break;
}
default:
{
shouldPreventDefault = false;
}
}
if (shouldPreventDefault) {
event.preventDefault();
}
}, [apiRef, currentPageRows.length, goToHeaderFilter, theme.direction, goToHeader, goToCell, getRowIdFromIndex]);
const handleColumnGroupHeaderKeyDown = React.useCallback((params, event) => {
const dimensions = apiRef.current.getRootDimensions();
if (!dimensions) {
return;
}
const focusedColumnGroup = (0, _focus.unstable_gridFocusColumnGroupHeaderSelector)(apiRef);
if (focusedColumnGroup === null) {
return;
}
const {
field: currentField,
depth: currentDepth
} = focusedColumnGroup;
const {
fields,
depth,
maxDepth
} = params;
const viewportPageSize = apiRef.current.getViewportPageSize();
const currentColIndex = apiRef.current.getColumnIndex(currentField);
const colIndexBefore = currentField ? apiRef.current.getColumnIndex(currentField) : 0;
const firstRowIndexInPage = 0;
const lastRowIndexInPage = currentPageRows.length - 1;
const firstColIndex = 0;
const lastColIndex = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef).length - 1;
let shouldPreventDefault = true;
switch (event.key) {
case 'ArrowDown':
{
if (depth === maxDepth - 1) {
goToHeader(currentColIndex, event);
} else {
goToGroupHeader(currentColIndex, currentDepth + 1, event);
}
break;
}
case 'ArrowUp':
{
if (depth > 0) {
goToGroupHeader(currentColIndex, currentDepth - 1, event);
}
break;
}
case 'ArrowRight':
{
const remainingRightColumns = fields.length - fields.indexOf(currentField) - 1;
if (currentColIndex + remainingRightColumns + 1 <= lastColIndex) {
goToGroupHeader(currentColIndex + remainingRightColumns + 1, currentDepth, event);
}
break;
}
case 'ArrowLeft':
{
const remainingLeftColumns = fields.indexOf(currentField);
if (currentColIndex - remainingLeftColumns - 1 >= firstColIndex) {
goToGroupHeader(currentColIndex - remainingLeftColumns - 1, currentDepth, event);
}
break;
}
case 'PageDown':
{
if (firstRowIndexInPage !== null && lastRowIndexInPage !== null) {
goToCell(colIndexBefore, getRowIdFromIndex(Math.min(firstRowIndexInPage + viewportPageSize, lastRowIndexInPage)));
}
break;
}
case 'Home':
{
goToGroupHeader(firstColIndex, currentDepth, event);
break;
}
case 'End':
{
goToGroupHeader(lastColIndex, currentDepth, event);
break;
}
case ' ':
{
// prevent Space event from scrolling
break;
}
default:
{
shouldPreventDefault = false;
}
}
if (shouldPreventDefault) {
event.preventDefault();
}
}, [apiRef, currentPageRows.length, goToHeader, goToGroupHeader, goToCell, getRowIdFromIndex]);
const handleCellKeyDown = React.useCallback((params, event) => {
// Ignore portal
if ((0, _domUtils.isEventTargetInPortal)(event)) {
return;
}
// Get the most recent params because the cell mode may have changed by another listener
const cellParams = apiRef.current.getCellParams(params.id, params.field);
if (cellParams.cellMode === _gridEditRowModel.GridCellModes.Edit || !(0, _keyboardUtils.isNavigationKey)(event.key)) {
return;
}
const canUpdateFocus = apiRef.current.unstable_applyPipeProcessors('canUpdateFocus', true, {
event,
cell: cellParams
});
if (!canUpdateFocus) {
return;
}
const dimensions = apiRef.current.getRootDimensions();
if (currentPageRows.length === 0 || !dimensions) {
return;
}
const direction = theme.direction;
const viewportPageSize = apiRef.current.getViewportPageSize();
const colIndexBefore = params.field ? apiRef.current.getColumnIndex(params.field) : 0;
const rowIndexBefore = currentPageRows.findIndex(row => row.id === params.id);
const firstRowIndexInPage = 0;
const lastRowIndexInPage = currentPageRows.length - 1;
const firstColIndex = 0;
const lastColIndex = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef).length - 1;
let shouldPreventDefault = true;
switch (event.key) {
case 'ArrowDown':
{
// "Enter" is only triggered by the row / cell editing feature
if (rowIndexBefore < lastRowIndexInPage) {
goToCell(colIndexBefore, getRowIdFromIndex(rowIndexBefore + 1));
}
break;
}
case 'ArrowUp':
{
if (rowIndexBefore > firstRowIndexInPage) {
goToCell(colIndexBefore, getRowIdFromIndex(rowIndexBefore - 1));
} else if (headerFilteringEnabled) {
goToHeaderFilter(colIndexBefore, event);
} else {
goToHeader(colIndexBefore, event);
}
break;
}
case 'ArrowRight':
{
const rightColIndex = getRightColumnIndex({
currentColIndex: colIndexBefore,
firstColIndex,
lastColIndex,
direction
});
if (rightColIndex !== null) {
goToCell(rightColIndex, getRowIdFromIndex(rowIndexBefore), direction === 'rtl' ? 'left' : 'right');
}
break;
}
case 'ArrowLeft':
{
const leftColIndex = getLeftColumnIndex({
currentColIndex: colIndexBefore,
firstColIndex,
lastColIndex,
direction
});
if (leftColIndex !== null) {
goToCell(leftColIndex, getRowIdFromIndex(rowIndexBefore), direction === 'rtl' ? 'right' : 'left');
}
break;
}
case 'Tab':
{
// "Tab" is only triggered by the row / cell editing feature
if (event.shiftKey && colIndexBefore > firstColIndex) {
goToCell(colIndexBefore - 1, getRowIdFromIndex(rowIndexBefore), 'left');
} else if (!event.shiftKey && colIndexBefore < lastColIndex) {
goToCell(colIndexBefore + 1, getRowIdFromIndex(rowIndexBefore), 'right');
}
break;
}
case ' ':
{
const field = params.field;
if (field === _gridDetailPanelToggleField.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
break;
}
const colDef = params.colDef;
if (colDef && colDef.type === 'treeDataGroup') {
break;
}
if (!event.shiftKey && rowIndexBefore < lastRowIndexInPage) {
goToCell(colIndexBefore, getRowIdFromIndex(Math.min(rowIndexBefore + viewportPageSize, lastRowIndexInPage)));
}
break;
}
case 'PageDown':
{
if (rowIndexBefore < lastRowIndexInPage) {
goToCell(colIndexBefore, getRowIdFromIndex(Math.min(rowIndexBefore + viewportPageSize, lastRowIndexInPage)));
}
break;
}
case 'PageUp':
{
// Go to the first row before going to header
const nextRowIndex = Math.max(rowIndexBefore - viewportPageSize, firstRowIndexInPage);
if (nextRowIndex !== rowIndexBefore && nextRowIndex >= firstRowIndexInPage) {
goToCell(colIndexBefore, getRowIdFromIndex(nextRowIndex));
} else {
goToHeader(colIndexBefore, event);
}
break;
}
case 'Home':
{
if (event.ctrlKey || event.metaKey || event.shiftKey) {
goToCell(firstColIndex, getRowIdFromIndex(firstRowIndexInPage));
} else {
goToCell(firstColIndex, getRowIdFromIndex(rowIndexBefore));
}
break;
}
case 'End':
{
if (event.ctrlKey || event.metaKey || event.shiftKey) {
goToCell(lastColIndex, getRowIdFromIndex(lastRowIndexInPage));
} else {
goToCell(lastColIndex, getRowIdFromIndex(rowIndexBefore));
}
break;
}
default:
{
shouldPreventDefault = false;
}
}
if (shouldPreventDefault) {
event.preventDefault();
}
}, [apiRef, currentPageRows, theme.direction, goToCell, getRowIdFromIndex, headerFilteringEnabled, goToHeaderFilter, goToHeader]);
const checkIfCanStartEditing = React.useCallback((initialValue, {
event
}) => {
if (event.key === ' ') {
// Space scrolls to the last row
return false;
}
return initialValue;
}, []);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'canStartEditing', checkIfCanStartEditing);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderKeyDown', handleColumnHeaderKeyDown);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'headerFilterKeyDown', handleHeaderFilterKeyDown);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnGroupHeaderKeyDown', handleColumnGroupHeaderKeyDown);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', handleCellKeyDown);
};
exports.useGridKeyboardNavigation = useGridKeyboardNavigation;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridPaginationSelector = exports.gridPaginationRowRangeSelector = exports.gridPaginationRowCountSelector = exports.gridPaginationModelSelector = exports.gridPaginatedVisibleSortedGridRowIdsSelector = exports.gridPaginatedVisibleSortedGridRowEntriesSelector = exports.gridPageSizeSelector = exports.gridPageSelector = exports.gridPageCountSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _gridPaginationUtils = require("./gridPaginationUtils");
/**
* @category Pagination
* @ignore - do not document.
*/
const gridPaginationSelector = state => state.pagination;
/**
* Get the pagination model
* @category Pagination
*/
exports.gridPaginationSelector = gridPaginationSelector;
const gridPaginationModelSelector = exports.gridPaginationModelSelector = (0, _createSelector.createSelector)(gridPaginationSelector, pagination => pagination.paginationModel);
/**
* Get the row count
* @category Pagination
*/
const gridPaginationRowCountSelector = exports.gridPaginationRowCountSelector = (0, _createSelector.createSelector)(gridPaginationSelector, pagination => pagination.rowCount);
/**
* Get the index of the page to render if the pagination is enabled
* @category Pagination
*/
const gridPageSelector = exports.gridPageSelector = (0, _createSelector.createSelector)(gridPaginationModelSelector, paginationModel => paginationModel.page);
/**
* Get the maximum amount of rows to display on a single page if the pagination is enabled
* @category Pagination
*/
const gridPageSizeSelector = exports.gridPageSizeSelector = (0, _createSelector.createSelector)(gridPaginationModelSelector, paginationModel => paginationModel.pageSize);
/**
* Get the amount of pages needed to display all the rows if the pagination is enabled
* @category Pagination
*/
const gridPageCountSelector = exports.gridPageCountSelector = (0, _createSelector.createSelector)(gridPageSizeSelector, gridPaginationRowCountSelector, (pageSize, rowCount) => (0, _gridPaginationUtils.getPageCount)(rowCount, pageSize));
/**
* Get the index of the first and the last row to include in the current page if the pagination is enabled.
* @category Pagination
*/
const gridPaginationRowRangeSelector = exports.gridPaginationRowRangeSelector = (0, _createSelector.createSelectorMemoized)(gridPaginationModelSelector, _gridRowsSelector.gridRowTreeSelector, _gridRowsSelector.gridRowMaximumTreeDepthSelector, _gridFilterSelector.gridExpandedSortedRowEntriesSelector, _gridFilterSelector.gridFilteredSortedTopLevelRowEntriesSelector, (paginationModel, rowTree, rowTreeDepth, visibleSortedRowEntries, visibleSortedTopLevelRowEntries) => {
const visibleTopLevelRowCount = visibleSortedTopLevelRowEntries.length;
const topLevelFirstRowIndex = Math.min(paginationModel.pageSize * paginationModel.page, visibleTopLevelRowCount - 1);
const topLevelLastRowIndex = Math.min(topLevelFirstRowIndex + paginationModel.pageSize - 1, visibleTopLevelRowCount - 1);
// The range contains no element
if (topLevelFirstRowIndex === -1 || topLevelLastRowIndex === -1) {
return null;
}
// The tree is flat, there is no need to look for children
if (rowTreeDepth < 2) {
return {
firstRowIndex: topLevelFirstRowIndex,
lastRowIndex: topLevelLastRowIndex
};
}
const topLevelFirstRow = visibleSortedTopLevelRowEntries[topLevelFirstRowIndex];
const topLevelRowsInCurrentPageCount = topLevelLastRowIndex - topLevelFirstRowIndex + 1;
const firstRowIndex = visibleSortedRowEntries.findIndex(row => row.id === topLevelFirstRow.id);
let lastRowIndex = firstRowIndex;
let topLevelRowAdded = 0;
while (lastRowIndex < visibleSortedRowEntries.length && topLevelRowAdded <= topLevelRowsInCurrentPageCount) {
const row = visibleSortedRowEntries[lastRowIndex];
const depth = rowTree[row.id]?.depth;
if (depth === undefined) {
lastRowIndex += 1;
} else {
if (topLevelRowAdded < topLevelRowsInCurrentPageCount || depth > 0) {
lastRowIndex += 1;
}
if (depth === 0) {
topLevelRowAdded += 1;
}
}
}
return {
firstRowIndex,
lastRowIndex: lastRowIndex - 1
};
});
/**
* Get the id and the model of each row to include in the current page if the pagination is enabled.
* @category Pagination
*/
const gridPaginatedVisibleSortedGridRowEntriesSelector = exports.gridPaginatedVisibleSortedGridRowEntriesSelector = (0, _createSelector.createSelectorMemoized)(_gridFilterSelector.gridExpandedSortedRowEntriesSelector, gridPaginationRowRangeSelector, (visibleSortedRowEntries, paginationRange) => {
if (!paginationRange) {
return [];
}
return visibleSortedRowEntries.slice(paginationRange.firstRowIndex, paginationRange.lastRowIndex + 1);
});
/**
* Get the id of each row to include in the current page if the pagination is enabled.
* @category Pagination
*/
const gridPaginatedVisibleSortedGridRowIdsSelector = exports.gridPaginatedVisibleSortedGridRowIdsSelector = (0, _createSelector.createSelectorMemoized)(_gridFilterSelector.gridExpandedSortedRowIdsSelector, gridPaginationRowRangeSelector, (visibleSortedRowIds, paginationRange) => {
if (!paginationRange) {
return [];
}
return visibleSortedRowIds.slice(paginationRange.firstRowIndex, paginationRange.lastRowIndex + 1);
});

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.throwIfPageSizeExceedsTheLimit = exports.noRowCountInServerMode = exports.getValidPage = exports.getPageCount = exports.getDefaultGridPaginationModel = exports.defaultPageSize = void 0;
var _warning = require("../../../utils/warning");
var _utils = require("../../utils");
const MAX_PAGE_SIZE = 100;
const defaultPageSize = autoPageSize => autoPageSize ? 0 : 100;
exports.defaultPageSize = defaultPageSize;
const getPageCount = (rowCount, pageSize) => {
if (pageSize > 0 && rowCount > 0) {
return Math.ceil(rowCount / pageSize);
}
return 0;
};
exports.getPageCount = getPageCount;
const noRowCountInServerMode = exports.noRowCountInServerMode = (0, _warning.buildWarning)(["MUI: the 'rowCount' prop is undefined while using paginationMode='server'", 'For more detail, see http://mui.com/components/data-grid/pagination/#basic-implementation'], 'error');
const getDefaultGridPaginationModel = autoPageSize => ({
page: 0,
pageSize: autoPageSize ? 0 : 100
});
exports.getDefaultGridPaginationModel = getDefaultGridPaginationModel;
const getValidPage = (page, pageCount = 0) => {
if (pageCount === 0) {
return page;
}
return Math.max(Math.min(page, pageCount - 1), 0);
};
exports.getValidPage = getValidPage;
const throwIfPageSizeExceedsTheLimit = (pageSize, signatureProp) => {
if (signatureProp === _utils.GridSignature.DataGrid && pageSize > MAX_PAGE_SIZE) {
throw new Error(['MUI: `pageSize` cannot exceed 100 in the MIT version of the DataGrid.', 'You need to upgrade to DataGridPro or DataGridPremium component to unlock this feature.'].join('\n'));
}
};
exports.throwIfPageSizeExceedsTheLimit = throwIfPageSizeExceedsTheLimit;

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridPaginationSelector = require("./gridPaginationSelector");
Object.keys(_gridPaginationSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridPaginationSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridPaginationSelector[key];
}
});
});

View File

@@ -0,0 +1,33 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridPagination = exports.paginationStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _gridPaginationUtils = require("./gridPaginationUtils");
var _useGridPaginationModel = require("./useGridPaginationModel");
var _useGridRowCount = require("./useGridRowCount");
const paginationStateInitializer = (state, props) => {
const paginationModel = (0, _extends2.default)({}, (0, _gridPaginationUtils.getDefaultGridPaginationModel)(props.autoPageSize), props.paginationModel ?? props.initialState?.pagination?.paginationModel);
(0, _gridPaginationUtils.throwIfPageSizeExceedsTheLimit)(paginationModel.pageSize, props.signature);
const rowCount = props.rowCount ?? props.initialState?.pagination?.rowCount ?? 0;
return (0, _extends2.default)({}, state, {
pagination: {
paginationModel,
rowCount
}
});
};
/**
* @requires useGridFilter (state)
* @requires useGridDimensions (event) - can be after
*/
exports.paginationStateInitializer = paginationStateInitializer;
const useGridPagination = (apiRef, props) => {
(0, _useGridPaginationModel.useGridPaginationModel)(apiRef, props);
(0, _useGridRowCount.useGridRowCount)(apiRef, props);
};
exports.useGridPagination = useGridPagination;

View File

@@ -0,0 +1,182 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridPaginationModel = exports.getDerivedPaginationModel = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _density = require("../density");
var _gridRowsUtils = require("../rows/gridRowsUtils");
var _utils = require("../../utils");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridPaginationSelector = require("./gridPaginationSelector");
var _gridPaginationUtils = require("./gridPaginationUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const getDerivedPaginationModel = (paginationState, signature, paginationModelProp) => {
let paginationModel = paginationState.paginationModel;
const rowCount = paginationState.rowCount;
const pageSize = paginationModelProp?.pageSize ?? paginationModel.pageSize;
const pageCount = (0, _gridPaginationUtils.getPageCount)(rowCount, pageSize);
if (paginationModelProp && (paginationModelProp?.page !== paginationModel.page || paginationModelProp?.pageSize !== paginationModel.pageSize)) {
paginationModel = paginationModelProp;
}
const validPage = (0, _gridPaginationUtils.getValidPage)(paginationModel.page, pageCount);
if (validPage !== paginationModel.page) {
paginationModel = (0, _extends2.default)({}, paginationModel, {
page: validPage
});
}
(0, _gridPaginationUtils.throwIfPageSizeExceedsTheLimit)(paginationModel.pageSize, signature);
return paginationModel;
};
/**
* @requires useGridFilter (state)
* @requires useGridDimensions (event) - can be after
*/
exports.getDerivedPaginationModel = getDerivedPaginationModel;
const useGridPaginationModel = (apiRef, props) => {
const logger = (0, _utils.useGridLogger)(apiRef, 'useGridPaginationModel');
const densityFactor = (0, _utils.useGridSelector)(apiRef, _density.gridDensityFactorSelector);
const rowHeight = Math.floor(props.rowHeight * densityFactor);
apiRef.current.registerControlState({
stateId: 'paginationModel',
propModel: props.paginationModel,
propOnChange: props.onPaginationModelChange,
stateSelector: _gridPaginationSelector.gridPaginationModelSelector,
changeEvent: 'paginationModelChange'
});
/**
* API METHODS
*/
const setPage = React.useCallback(page => {
const currentModel = (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
if (page === currentModel.page) {
return;
}
logger.debug(`Setting page to ${page}`);
apiRef.current.setPaginationModel({
page,
pageSize: currentModel.pageSize
});
}, [apiRef, logger]);
const setPageSize = React.useCallback(pageSize => {
const currentModel = (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
if (pageSize === currentModel.pageSize) {
return;
}
logger.debug(`Setting page size to ${pageSize}`);
apiRef.current.setPaginationModel({
pageSize,
page: currentModel.page
});
}, [apiRef, logger]);
const setPaginationModel = React.useCallback(paginationModel => {
const currentModel = (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
if (paginationModel === currentModel) {
return;
}
logger.debug("Setting 'paginationModel' to", paginationModel);
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pagination: (0, _extends2.default)({}, state.pagination, {
paginationModel: getDerivedPaginationModel(state.pagination, props.signature, paginationModel)
})
}));
}, [apiRef, logger, props.signature]);
const paginationModelApi = {
setPage,
setPageSize,
setPaginationModel
};
(0, _utils.useGridApiMethod)(apiRef, paginationModelApi, 'public');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const paginationModel = (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
const shouldExportPaginationModel =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the `paginationModel` is controlled
props.paginationModel != null ||
// Always export if the `paginationModel` has been initialized
props.initialState?.pagination?.paginationModel != null ||
// Export if `page` or `pageSize` is not equal to the default value
paginationModel.page !== 0 && paginationModel.pageSize !== (0, _gridPaginationUtils.defaultPageSize)(props.autoPageSize);
if (!shouldExportPaginationModel) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
pagination: (0, _extends2.default)({}, prevState.pagination, {
paginationModel
})
});
}, [apiRef, props.paginationModel, props.initialState?.pagination?.paginationModel, props.autoPageSize]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const paginationModel = context.stateToRestore.pagination?.paginationModel ? (0, _extends2.default)({}, (0, _gridPaginationUtils.getDefaultGridPaginationModel)(props.autoPageSize), context.stateToRestore.pagination?.paginationModel) : (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pagination: (0, _extends2.default)({}, state.pagination, {
paginationModel: getDerivedPaginationModel(state.pagination, props.signature, paginationModel)
})
}));
return params;
}, [apiRef, props.autoPageSize, props.signature]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
/**
* EVENTS
*/
const handlePaginationModelChange = () => {
const paginationModel = (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
if (apiRef.current.virtualScrollerRef?.current) {
apiRef.current.scrollToIndexes({
rowIndex: paginationModel.page * paginationModel.pageSize
});
}
};
const handleUpdateAutoPageSize = React.useCallback(() => {
if (!props.autoPageSize) {
return;
}
const dimensions = apiRef.current.getRootDimensions() || {
viewportInnerSize: {
height: 0
}
};
const pinnedRowsHeight = (0, _gridRowsUtils.calculatePinnedRowsHeight)(apiRef);
const maximumPageSizeWithoutScrollBar = Math.floor((dimensions.viewportInnerSize.height - pinnedRowsHeight.top - pinnedRowsHeight.bottom) / rowHeight);
apiRef.current.setPageSize(maximumPageSizeWithoutScrollBar);
}, [apiRef, props.autoPageSize, rowHeight]);
const handleRowCountChange = React.useCallback(newRowCount => {
if (newRowCount == null) {
return;
}
const paginationModel = (0, _gridPaginationSelector.gridPaginationModelSelector)(apiRef);
const pageCount = (0, _gridPaginationSelector.gridPageCountSelector)(apiRef);
if (paginationModel.page > pageCount - 1) {
apiRef.current.setPage(Math.max(0, pageCount - 1));
}
}, [apiRef]);
(0, _utils.useGridApiEventHandler)(apiRef, 'viewportInnerSizeChange', handleUpdateAutoPageSize);
(0, _utils.useGridApiEventHandler)(apiRef, 'paginationModelChange', handlePaginationModelChange);
(0, _utils.useGridApiEventHandler)(apiRef, 'rowCountChange', handleRowCountChange);
/**
* EFFECTS
*/
React.useEffect(() => {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pagination: (0, _extends2.default)({}, state.pagination, {
paginationModel: getDerivedPaginationModel(state.pagination, props.signature, props.paginationModel)
})
}));
}, [apiRef, props.paginationModel, props.paginationMode, props.signature]);
React.useEffect(handleUpdateAutoPageSize, [handleUpdateAutoPageSize]);
};
exports.useGridPaginationModel = useGridPaginationModel;

View File

@@ -0,0 +1,103 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRowCount = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _filter = require("../filter");
var _utils = require("../../utils");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridPaginationSelector = require("./gridPaginationSelector");
var _gridPaginationUtils = require("./gridPaginationUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/**
* @requires useGridFilter (state)
* @requires useGridDimensions (event) - can be after
*/
const useGridRowCount = (apiRef, props) => {
const logger = (0, _utils.useGridLogger)(apiRef, 'useGridRowCount');
const visibleTopLevelRowCount = (0, _utils.useGridSelector)(apiRef, _filter.gridFilteredTopLevelRowCountSelector);
const rowCount = (0, _utils.useGridSelector)(apiRef, _gridPaginationSelector.gridPaginationRowCountSelector);
apiRef.current.registerControlState({
stateId: 'paginationRowCount',
propModel: props.rowCount,
propOnChange: props.onRowCountChange,
stateSelector: _gridPaginationSelector.gridPaginationRowCountSelector,
changeEvent: 'rowCountChange'
});
/**
* API METHODS
*/
const setRowCount = React.useCallback(newRowCount => {
if (rowCount === newRowCount) {
return;
}
logger.debug("Setting 'rowCount' to", newRowCount);
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pagination: (0, _extends2.default)({}, state.pagination, {
rowCount: newRowCount
})
}));
}, [apiRef, logger, rowCount]);
const paginationRowCountApi = {
setRowCount
};
(0, _utils.useGridApiMethod)(apiRef, paginationRowCountApi, 'public');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const exportedRowCount = (0, _gridPaginationSelector.gridPaginationRowCountSelector)(apiRef);
const shouldExportRowCount =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the `rowCount` is controlled
props.rowCount != null ||
// Always export if the `rowCount` has been initialized
props.initialState?.pagination?.rowCount != null;
if (!shouldExportRowCount) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
pagination: (0, _extends2.default)({}, prevState.pagination, {
rowCount: exportedRowCount
})
});
}, [apiRef, props.rowCount, props.initialState?.pagination?.rowCount]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const restoredRowCount = context.stateToRestore.pagination?.rowCount ? context.stateToRestore.pagination.rowCount : (0, _gridPaginationSelector.gridPaginationRowCountSelector)(apiRef);
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pagination: (0, _extends2.default)({}, state.pagination, {
rowCount: restoredRowCount
})
}));
return params;
}, [apiRef]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
/**
* EFFECTS
*/
React.useEffect(() => {
if (process.env.NODE_ENV !== 'production') {
if (props.paginationMode === 'server' && props.rowCount == null) {
(0, _gridPaginationUtils.noRowCountInServerMode)();
}
}
}, [props.rowCount, props.paginationMode]);
React.useEffect(() => {
if (props.paginationMode === 'client') {
apiRef.current.setRowCount(visibleTopLevelRowCount);
} else if (props.rowCount != null) {
apiRef.current.setRowCount(props.rowCount);
}
}, [apiRef, visibleTopLevelRowCount, props.paginationMode, props.rowCount]);
};
exports.useGridRowCount = useGridRowCount;

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridPreferencePanelStateSelector = void 0;
const gridPreferencePanelStateSelector = state => state.preferencePanel;
exports.gridPreferencePanelStateSelector = gridPreferencePanelStateSelector;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.GridPreferencePanelsValue = void 0;
var GridPreferencePanelsValue = exports.GridPreferencePanelsValue = /*#__PURE__*/function (GridPreferencePanelsValue) {
GridPreferencePanelsValue["filters"] = "filters";
GridPreferencePanelsValue["columns"] = "columns";
return GridPreferencePanelsValue;
}(GridPreferencePanelsValue || {});

View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridPreferencePanelSelector = require("./gridPreferencePanelSelector");
Object.keys(_gridPreferencePanelSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridPreferencePanelSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridPreferencePanelSelector[key];
}
});
});
var _gridPreferencePanelState = require("./gridPreferencePanelState");
Object.keys(_gridPreferencePanelState).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridPreferencePanelState[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridPreferencePanelState[key];
}
});
});
var _gridPreferencePanelsValue = require("./gridPreferencePanelsValue");
Object.keys(_gridPreferencePanelsValue).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridPreferencePanelsValue[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridPreferencePanelsValue[key];
}
});
});

View File

@@ -0,0 +1,123 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridPreferencesPanel = exports.preferencePanelStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridPreferencePanelSelector = require("./gridPreferencePanelSelector");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const preferencePanelStateInitializer = (state, props) => (0, _extends2.default)({}, state, {
preferencePanel: props.initialState?.preferencePanel ?? {
open: false
}
});
/**
* TODO: Add a single `setPreferencePanel` method to avoid multiple `setState`
*/
exports.preferencePanelStateInitializer = preferencePanelStateInitializer;
const useGridPreferencesPanel = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridPreferencesPanel');
const hideTimeout = React.useRef();
const immediateTimeout = React.useRef();
/**
* API METHODS
*/
const hidePreferences = React.useCallback(() => {
logger.debug('Hiding Preferences Panel');
const preferencePanelState = (0, _gridPreferencePanelSelector.gridPreferencePanelStateSelector)(apiRef.current.state);
if (preferencePanelState.openedPanelValue) {
apiRef.current.publishEvent('preferencePanelClose', {
openedPanelValue: preferencePanelState.openedPanelValue
});
}
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
preferencePanel: {
open: false
}
}));
apiRef.current.forceUpdate();
}, [apiRef, logger]);
// This is to prevent the preferences from closing when you open a select box or another panel,
// The issue is in MUI core V4 => Fixed in V5
const doNotHidePanel = React.useCallback(() => {
immediateTimeout.current = setTimeout(() => clearTimeout(hideTimeout.current), 0);
}, []);
// This is a hack for the issue with Core V4, by delaying hiding the panel on the clickAwayListener,
// we can cancel the action if the trigger element still need the panel...
const hidePreferencesDelayed = React.useCallback(() => {
hideTimeout.current = setTimeout(hidePreferences, 100);
}, [hidePreferences]);
const showPreferences = React.useCallback((newValue, panelId, labelId) => {
logger.debug('Opening Preferences Panel');
doNotHidePanel();
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
preferencePanel: (0, _extends2.default)({}, state.preferencePanel, {
open: true,
openedPanelValue: newValue,
panelId,
labelId
})
}));
apiRef.current.publishEvent('preferencePanelOpen', {
openedPanelValue: newValue
});
apiRef.current.forceUpdate();
}, [logger, doNotHidePanel, apiRef]);
(0, _useGridApiMethod.useGridApiMethod)(apiRef, {
showPreferences,
hidePreferences: hidePreferencesDelayed
}, 'public');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const preferencePanelToExport = (0, _gridPreferencePanelSelector.gridPreferencePanelStateSelector)(apiRef.current.state);
const shouldExportPreferencePanel =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the panel was initialized
props.initialState?.preferencePanel != null ||
// Always export if the panel is opened
preferencePanelToExport.open;
if (!shouldExportPreferencePanel) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
preferencePanel: preferencePanelToExport
});
}, [apiRef, props.initialState?.preferencePanel]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const preferencePanel = context.stateToRestore.preferencePanel;
if (preferencePanel != null) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
preferencePanel
}));
}
return params;
}, [apiRef]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
/**
* EFFECTS
*/
React.useEffect(() => {
return () => {
clearTimeout(hideTimeout.current);
clearTimeout(immediateTimeout.current);
};
}, []);
};
exports.useGridPreferencesPanel = useGridPreferencesPanel;

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.selectedIdsLookupSelector = exports.selectedGridRowsSelector = exports.selectedGridRowsCountSelector = exports.gridRowSelectionStateSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
var _gridRowsSelector = require("../rows/gridRowsSelector");
const gridRowSelectionStateSelector = state => state.rowSelection;
exports.gridRowSelectionStateSelector = gridRowSelectionStateSelector;
const selectedGridRowsCountSelector = exports.selectedGridRowsCountSelector = (0, _createSelector.createSelector)(gridRowSelectionStateSelector, selection => selection.length);
const selectedGridRowsSelector = exports.selectedGridRowsSelector = (0, _createSelector.createSelectorMemoized)(gridRowSelectionStateSelector, _gridRowsSelector.gridRowsLookupSelector, (selectedRows, rowsLookup) => new Map(selectedRows.map(id => [id, rowsLookup[id]])));
const selectedIdsLookupSelector = exports.selectedIdsLookupSelector = (0, _createSelector.createSelectorMemoized)(gridRowSelectionStateSelector, selection => selection.reduce((lookup, rowId) => {
lookup[rowId] = rowId;
return lookup;
}, {}));

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _gridRowSelectionSelector = require("./gridRowSelectionSelector");
Object.keys(_gridRowSelectionSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridRowSelectionSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridRowSelectionSelector[key];
}
});
});

View File

@@ -0,0 +1,398 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRowSelection = exports.rowSelectionStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _gridRowSelectionSelector = require("./gridRowSelectionSelector");
var _pagination = require("../pagination");
var _gridFocusStateSelector = require("../focus/gridFocusStateSelector");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _colDef = require("../../../colDef");
var _gridEditRowModel = require("../../../models/gridEditRowModel");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _gridDetailPanelToggleField = require("../../../constants/gridDetailPanelToggleField");
var _gridClasses = require("../../../constants/gridClasses");
var _domUtils = require("../../../utils/domUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const getSelectionModelPropValue = (selectionModelProp, prevSelectionModel) => {
if (selectionModelProp == null) {
return selectionModelProp;
}
if (Array.isArray(selectionModelProp)) {
return selectionModelProp;
}
if (prevSelectionModel && prevSelectionModel[0] === selectionModelProp) {
return prevSelectionModel;
}
return [selectionModelProp];
};
const rowSelectionStateInitializer = (state, props) => (0, _extends2.default)({}, state, {
rowSelection: props.rowSelection ? getSelectionModelPropValue(props.rowSelectionModel) ?? [] : []
});
/**
* @requires useGridRows (state, method) - can be after
* @requires useGridParamsApi (method) - can be after
* @requires useGridFocus (state) - can be after
* @requires useGridKeyboardNavigation (`cellKeyDown` event must first be consumed by it)
*/
exports.rowSelectionStateInitializer = rowSelectionStateInitializer;
const useGridRowSelection = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridSelection');
const runIfRowSelectionIsEnabled = callback => (...args) => {
if (props.rowSelection) {
callback(...args);
}
};
const propRowSelectionModel = React.useMemo(() => {
return getSelectionModelPropValue(props.rowSelectionModel, (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state));
}, [apiRef, props.rowSelectionModel]);
const lastRowToggled = React.useRef(null);
apiRef.current.registerControlState({
stateId: 'rowSelection',
propModel: propRowSelectionModel,
propOnChange: props.onRowSelectionModelChange,
stateSelector: _gridRowSelectionSelector.gridRowSelectionStateSelector,
changeEvent: 'rowSelectionChange'
});
const {
checkboxSelection,
disableMultipleRowSelection,
disableRowSelectionOnClick,
isRowSelectable: propIsRowSelectable
} = props;
const canHaveMultipleSelection = !disableMultipleRowSelection || checkboxSelection;
const visibleRows = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props);
const expandMouseRowRangeSelection = React.useCallback(id => {
let endId = id;
const startId = lastRowToggled.current ?? id;
const isSelected = apiRef.current.isRowSelected(id);
if (isSelected) {
const visibleRowIds = (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef);
const startIndex = visibleRowIds.findIndex(rowId => rowId === startId);
const endIndex = visibleRowIds.findIndex(rowId => rowId === endId);
if (startIndex === endIndex) {
return;
}
if (startIndex > endIndex) {
endId = visibleRowIds[endIndex + 1];
} else {
endId = visibleRowIds[endIndex - 1];
}
}
lastRowToggled.current = id;
apiRef.current.selectRowRange({
startId,
endId
}, !isSelected);
}, [apiRef]);
/**
* API METHODS
*/
const setRowSelectionModel = React.useCallback(model => {
if (props.signature === _useGridApiEventHandler.GridSignature.DataGrid && !props.checkboxSelection && Array.isArray(model) && model.length > 1) {
throw new Error(['MUI: `rowSelectionModel` can only contain 1 item in DataGrid.', 'You need to upgrade to DataGridPro or DataGridPremium component to unlock multiple selection.'].join('\n'));
}
const currentModel = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state);
if (currentModel !== model) {
logger.debug(`Setting selection model`);
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
rowSelection: props.rowSelection ? model : []
}));
apiRef.current.forceUpdate();
}
}, [apiRef, logger, props.rowSelection, props.signature, props.checkboxSelection]);
const isRowSelected = React.useCallback(id => (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state).includes(id), [apiRef]);
const isRowSelectable = React.useCallback(id => {
if (propIsRowSelectable && !propIsRowSelectable(apiRef.current.getRowParams(id))) {
return false;
}
const rowNode = apiRef.current.getRowNode(id);
if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow') {
return false;
}
return true;
}, [apiRef, propIsRowSelectable]);
const getSelectedRows = React.useCallback(() => (0, _gridRowSelectionSelector.selectedGridRowsSelector)(apiRef), [apiRef]);
const selectRow = React.useCallback((id, isSelected = true, resetSelection = false) => {
if (!apiRef.current.isRowSelectable(id)) {
return;
}
lastRowToggled.current = id;
if (resetSelection) {
logger.debug(`Setting selection for row ${id}`);
apiRef.current.setRowSelectionModel(isSelected ? [id] : []);
} else {
logger.debug(`Toggling selection for row ${id}`);
const selection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state);
const newSelection = selection.filter(el => el !== id);
if (isSelected) {
newSelection.push(id);
}
const isSelectionValid = newSelection.length < 2 || canHaveMultipleSelection;
if (isSelectionValid) {
apiRef.current.setRowSelectionModel(newSelection);
}
}
}, [apiRef, logger, canHaveMultipleSelection]);
const selectRows = React.useCallback((ids, isSelected = true, resetSelection = false) => {
logger.debug(`Setting selection for several rows`);
const selectableIds = ids.filter(id => apiRef.current.isRowSelectable(id));
let newSelection;
if (resetSelection) {
newSelection = isSelected ? selectableIds : [];
} else {
// We clone the existing object to avoid mutating the same object returned by the selector to others part of the project
const selectionLookup = (0, _extends2.default)({}, (0, _gridRowSelectionSelector.selectedIdsLookupSelector)(apiRef));
selectableIds.forEach(id => {
if (isSelected) {
selectionLookup[id] = id;
} else {
delete selectionLookup[id];
}
});
newSelection = Object.values(selectionLookup);
}
const isSelectionValid = newSelection.length < 2 || canHaveMultipleSelection;
if (isSelectionValid) {
apiRef.current.setRowSelectionModel(newSelection);
}
}, [apiRef, logger, canHaveMultipleSelection]);
const selectRowRange = React.useCallback(({
startId,
endId
}, isSelected = true, resetSelection = false) => {
if (!apiRef.current.getRow(startId) || !apiRef.current.getRow(endId)) {
return;
}
logger.debug(`Expanding selection from row ${startId} to row ${endId}`);
// Using rows from all pages allow to select a range across several pages
const allPagesRowIds = (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef);
const startIndex = allPagesRowIds.indexOf(startId);
const endIndex = allPagesRowIds.indexOf(endId);
const [start, end] = startIndex > endIndex ? [endIndex, startIndex] : [startIndex, endIndex];
const rowsBetweenStartAndEnd = allPagesRowIds.slice(start, end + 1);
apiRef.current.selectRows(rowsBetweenStartAndEnd, isSelected, resetSelection);
}, [apiRef, logger]);
const selectionPublicApi = {
selectRow,
setRowSelectionModel,
getSelectedRows,
isRowSelected,
isRowSelectable
};
const selectionPrivateApi = {
selectRows,
selectRowRange
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, selectionPublicApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, selectionPrivateApi, props.signature === _useGridApiEventHandler.GridSignature.DataGrid ? 'private' : 'public');
/**
* EVENTS
*/
const removeOutdatedSelection = React.useCallback(() => {
if (props.keepNonExistentRowsSelected) {
return;
}
const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state);
const rowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
// We clone the existing object to avoid mutating the same object returned by the selector to others part of the project
const selectionLookup = (0, _extends2.default)({}, (0, _gridRowSelectionSelector.selectedIdsLookupSelector)(apiRef));
let hasChanged = false;
currentSelection.forEach(id => {
if (!rowsLookup[id]) {
delete selectionLookup[id];
hasChanged = true;
}
});
if (hasChanged) {
apiRef.current.setRowSelectionModel(Object.values(selectionLookup));
}
}, [apiRef, props.keepNonExistentRowsSelected]);
const handleSingleRowSelection = React.useCallback((id, event) => {
const hasCtrlKey = event.metaKey || event.ctrlKey;
// multiple selection is only allowed if:
// - it is a checkboxSelection
// - it is a keyboard selection
// - Ctrl is pressed
const isMultipleSelectionDisabled = !checkboxSelection && !hasCtrlKey && !(0, _keyboardUtils.isKeyboardEvent)(event);
const resetSelection = !canHaveMultipleSelection || isMultipleSelectionDisabled;
const isSelected = apiRef.current.isRowSelected(id);
if (resetSelection) {
apiRef.current.selectRow(id, !isMultipleSelectionDisabled ? !isSelected : true, true);
} else {
apiRef.current.selectRow(id, !isSelected, false);
}
}, [apiRef, canHaveMultipleSelection, checkboxSelection]);
const handleRowClick = React.useCallback((params, event) => {
if (disableRowSelectionOnClick) {
return;
}
const field = event.target.closest(`.${_gridClasses.gridClasses.cell}`)?.getAttribute('data-field');
if (field === _colDef.GRID_CHECKBOX_SELECTION_COL_DEF.field) {
// click on checkbox should not trigger row selection
return;
}
if (field === _gridDetailPanelToggleField.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
// click to open the detail panel should not select the row
return;
}
if (field) {
const column = apiRef.current.getColumn(field);
if (column?.type === _colDef.GRID_ACTIONS_COLUMN_TYPE) {
return;
}
}
const rowNode = apiRef.current.getRowNode(params.id);
if (rowNode.type === 'pinnedRow') {
return;
}
if (event.shiftKey && (canHaveMultipleSelection || checkboxSelection)) {
expandMouseRowRangeSelection(params.id);
} else {
handleSingleRowSelection(params.id, event);
}
}, [disableRowSelectionOnClick, canHaveMultipleSelection, checkboxSelection, apiRef, expandMouseRowRangeSelection, handleSingleRowSelection]);
const preventSelectionOnShift = React.useCallback((params, event) => {
if (canHaveMultipleSelection && event.shiftKey) {
window.getSelection()?.removeAllRanges();
}
}, [canHaveMultipleSelection]);
const handleRowSelectionCheckboxChange = React.useCallback((params, event) => {
if (event.nativeEvent.shiftKey) {
expandMouseRowRangeSelection(params.id);
} else {
apiRef.current.selectRow(params.id, params.value);
}
}, [apiRef, expandMouseRowRangeSelection]);
const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
const shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
const rowsToBeSelected = shouldLimitSelectionToCurrentPage ? (0, _pagination.gridPaginatedVisibleSortedGridRowIdsSelector)(apiRef) : (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef);
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
apiRef.current.selectRows(rowsToBeSelected, params.value, filterModel?.items.length > 0);
}, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination]);
const handleCellKeyDown = React.useCallback((params, event) => {
// Get the most recent cell mode because it may have been changed by another listener
if (apiRef.current.getCellMode(params.id, params.field) === _gridEditRowModel.GridCellModes.Edit) {
return;
}
// Ignore portal
// Do not apply shortcuts if the focus is not on the cell root component
if ((0, _domUtils.isEventTargetInPortal)(event)) {
return;
}
if ((0, _keyboardUtils.isNavigationKey)(event.key) && event.shiftKey) {
// The cell that has focus after the keyboard navigation
const focusCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
if (focusCell && focusCell.id !== params.id) {
event.preventDefault();
const isNextRowSelected = apiRef.current.isRowSelected(focusCell.id);
if (!canHaveMultipleSelection) {
apiRef.current.selectRow(focusCell.id, !isNextRowSelected, true);
return;
}
const newRowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(focusCell.id);
const previousRowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(params.id);
let start;
let end;
if (newRowIndex > previousRowIndex) {
if (isNextRowSelected) {
// We are navigating to the bottom of the page and adding selected rows
start = previousRowIndex;
end = newRowIndex - 1;
} else {
// We are navigating to the bottom of the page and removing selected rows
start = previousRowIndex;
end = newRowIndex;
}
} else {
// eslint-disable-next-line no-lonely-if
if (isNextRowSelected) {
// We are navigating to the top of the page and removing selected rows
start = newRowIndex + 1;
end = previousRowIndex;
} else {
// We are navigating to the top of the page and adding selected rows
start = newRowIndex;
end = previousRowIndex;
}
}
const rowsBetweenStartAndEnd = visibleRows.rows.slice(start, end + 1).map(row => row.id);
apiRef.current.selectRows(rowsBetweenStartAndEnd, !isNextRowSelected);
return;
}
}
if (event.key === ' ' && event.shiftKey) {
event.preventDefault();
handleSingleRowSelection(params.id, event);
return;
}
if (event.key === 'a' && (event.ctrlKey || event.metaKey)) {
event.preventDefault();
selectRows(apiRef.current.getAllRowIds(), true);
}
}, [apiRef, handleSingleRowSelection, selectRows, visibleRows.rows, canHaveMultipleSelection]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'sortedRowsSet', runIfRowSelectionIsEnabled(removeOutdatedSelection));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowClick', runIfRowSelectionIsEnabled(handleRowClick));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowSelectionCheckboxChange', runIfRowSelectionIsEnabled(handleRowSelectionCheckboxChange));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'headerSelectionCheckboxChange', handleHeaderSelectionCheckboxChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellMouseDown', runIfRowSelectionIsEnabled(preventSelectionOnShift));
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', runIfRowSelectionIsEnabled(handleCellKeyDown));
/**
* EFFECTS
*/
React.useEffect(() => {
if (propRowSelectionModel !== undefined) {
apiRef.current.setRowSelectionModel(propRowSelectionModel);
}
}, [apiRef, propRowSelectionModel, props.rowSelection]);
React.useEffect(() => {
if (!props.rowSelection) {
apiRef.current.setRowSelectionModel([]);
}
}, [apiRef, props.rowSelection]);
const isStateControlled = propRowSelectionModel != null;
React.useEffect(() => {
if (isStateControlled || !props.rowSelection) {
return;
}
// props.isRowSelectable changed
const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state);
if (isRowSelectable) {
const newSelection = currentSelection.filter(id => isRowSelectable(id));
if (newSelection.length < currentSelection.length) {
apiRef.current.setRowSelectionModel(newSelection);
}
}
}, [apiRef, isRowSelectable, isStateControlled, props.rowSelection]);
React.useEffect(() => {
if (!props.rowSelection || isStateControlled) {
return;
}
const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state);
if (!canHaveMultipleSelection && currentSelection.length > 1) {
// See https://github.com/mui/mui-x/issues/8455
apiRef.current.setRowSelectionModel([]);
}
}, [apiRef, canHaveMultipleSelection, checkboxSelection, isStateControlled, props.rowSelection]);
};
exports.useGridRowSelection = useGridRowSelection;

View File

@@ -0,0 +1,54 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRowSelectionPreProcessors = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _pipeProcessing = require("../../core/pipeProcessing");
var _constants = require("../../../constants");
var _colDef = require("../../../colDef");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useUtilityClasses = ownerState => {
const {
classes
} = ownerState;
return React.useMemo(() => {
const slots = {
cellCheckbox: ['cellCheckbox'],
columnHeaderCheckbox: ['columnHeaderCheckbox']
};
return (0, _utils.unstable_composeClasses)(slots, _constants.getDataGridUtilityClass, classes);
}, [classes]);
};
const useGridRowSelectionPreProcessors = (apiRef, props) => {
const ownerState = {
classes: props.classes
};
const classes = useUtilityClasses(ownerState);
const updateSelectionColumn = React.useCallback(columnsState => {
const selectionColumn = (0, _extends2.default)({}, _colDef.GRID_CHECKBOX_SELECTION_COL_DEF, {
cellClassName: classes.cellCheckbox,
headerClassName: classes.columnHeaderCheckbox,
headerName: apiRef.current.getLocaleText('checkboxSelectionHeaderName')
});
const shouldHaveSelectionColumn = props.checkboxSelection;
const haveSelectionColumn = columnsState.lookup[_colDef.GRID_CHECKBOX_SELECTION_FIELD] != null;
if (shouldHaveSelectionColumn && !haveSelectionColumn) {
columnsState.lookup[_colDef.GRID_CHECKBOX_SELECTION_FIELD] = selectionColumn;
columnsState.orderedFields = [_colDef.GRID_CHECKBOX_SELECTION_FIELD, ...columnsState.orderedFields];
} else if (!shouldHaveSelectionColumn && haveSelectionColumn) {
delete columnsState.lookup[_colDef.GRID_CHECKBOX_SELECTION_FIELD];
columnsState.orderedFields = columnsState.orderedFields.filter(field => field !== _colDef.GRID_CHECKBOX_SELECTION_FIELD);
} else if (shouldHaveSelectionColumn && haveSelectionColumn) {
columnsState.lookup[_colDef.GRID_CHECKBOX_SELECTION_FIELD] = (0, _extends2.default)({}, selectionColumn, columnsState.lookup[_colDef.GRID_CHECKBOX_SELECTION_FIELD]);
}
return columnsState;
}, [apiRef, classes, props.checkboxSelection]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'hydrateColumns', updateSelectionColumn);
};
exports.useGridRowSelectionPreProcessors = useGridRowSelectionPreProcessors;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridRowsMetaSelector = void 0;
const gridRowsMetaSelector = state => state.rowsMeta;
exports.gridRowsMetaSelector = gridRowsMetaSelector;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridTopLevelRowCountSelector = exports.gridRowsLookupSelector = exports.gridRowsLoadingSelector = exports.gridRowsDataRowIdToIdLookupSelector = exports.gridRowTreeSelector = exports.gridRowTreeDepthsSelector = exports.gridRowMaximumTreeDepthSelector = exports.gridRowGroupingNameSelector = exports.gridRowCountSelector = exports.gridPinnedRowsSelector = exports.gridPinnedRowsCountSelector = exports.gridDataRowIdsSelector = exports.gridAdditionalRowGroupsSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
const gridRowsStateSelector = state => state.rows;
const gridRowCountSelector = exports.gridRowCountSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.totalRowCount);
const gridRowsLoadingSelector = exports.gridRowsLoadingSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.loading);
const gridTopLevelRowCountSelector = exports.gridTopLevelRowCountSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.totalTopLevelRowCount);
// TODO rows v6: Rename
const gridRowsLookupSelector = exports.gridRowsLookupSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.dataRowIdToModelLookup);
const gridRowsDataRowIdToIdLookupSelector = exports.gridRowsDataRowIdToIdLookupSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.dataRowIdToIdLookup);
const gridRowTreeSelector = exports.gridRowTreeSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.tree);
const gridRowGroupingNameSelector = exports.gridRowGroupingNameSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.groupingName);
const gridRowTreeDepthsSelector = exports.gridRowTreeDepthsSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.treeDepths);
const gridRowMaximumTreeDepthSelector = exports.gridRowMaximumTreeDepthSelector = (0, _createSelector.createSelectorMemoized)(gridRowsStateSelector, rows => {
const entries = Object.entries(rows.treeDepths);
if (entries.length === 0) {
return 1;
}
return entries.filter(([, nodeCount]) => nodeCount > 0).map(([depth]) => Number(depth)).sort((a, b) => b - a)[0] + 1;
});
const gridDataRowIdsSelector = exports.gridDataRowIdsSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows.dataRowIds);
/**
* @ignore - do not document.
*/
const gridAdditionalRowGroupsSelector = exports.gridAdditionalRowGroupsSelector = (0, _createSelector.createSelector)(gridRowsStateSelector, rows => rows?.additionalRowGroups);
/**
* @ignore - do not document.
*/
const gridPinnedRowsSelector = exports.gridPinnedRowsSelector = (0, _createSelector.createSelectorMemoized)(gridAdditionalRowGroupsSelector, additionalRowGroups => {
const rawPinnedRows = additionalRowGroups?.pinnedRows;
return {
bottom: rawPinnedRows?.bottom?.map(rowEntry => ({
id: rowEntry.id,
model: rowEntry.model ?? {}
})),
top: rawPinnedRows?.top?.map(rowEntry => ({
id: rowEntry.id,
model: rowEntry.model ?? {}
}))
};
});
/**
* @ignore - do not document.
*/
const gridPinnedRowsCountSelector = exports.gridPinnedRowsCountSelector = (0, _createSelector.createSelector)(gridPinnedRowsSelector, pinnedRows => {
return (pinnedRows?.top?.length || 0) + (pinnedRows?.bottom?.length || 0);
});

View File

@@ -0,0 +1,304 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildRootGroup = exports.GRID_ROOT_GROUP_ID = exports.GRID_ID_AUTOGENERATED = void 0;
exports.calculatePinnedRowsHeight = calculatePinnedRowsHeight;
exports.checkGridRowIdIsValid = checkGridRowIdIsValid;
exports.createRowsInternalCache = void 0;
exports.getMinimalContentHeight = getMinimalContentHeight;
exports.updateCacheWithNewRows = exports.isAutoGeneratedRow = exports.getTreeNodeDescendants = exports.getTopLevelRowCount = exports.getRowsStateFromCache = exports.getRowIdFromRowModel = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _gridRowsSelector = require("./gridRowsSelector");
var _densitySelector = require("../density/densitySelector");
const GRID_ROOT_GROUP_ID = exports.GRID_ROOT_GROUP_ID = `auto-generated-group-node-root`;
const GRID_ID_AUTOGENERATED = exports.GRID_ID_AUTOGENERATED = Symbol('mui.id_autogenerated');
const buildRootGroup = () => ({
type: 'group',
id: GRID_ROOT_GROUP_ID,
depth: -1,
groupingField: null,
groupingKey: null,
isAutoGenerated: true,
children: [],
childrenFromPath: {},
childrenExpanded: true,
parent: null
});
/**
* A helper function to check if the id provided is valid.
* @param {GridRowId} id Id as [[GridRowId]].
* @param {GridRowModel | Partial<GridRowModel>} row Row as [[GridRowModel]].
* @param {string} detailErrorMessage A custom error message to display for invalid IDs
*/
exports.buildRootGroup = buildRootGroup;
function checkGridRowIdIsValid(id, row, detailErrorMessage = 'A row was provided without id in the rows prop:') {
if (id == null) {
throw new Error(['MUI: The data grid component requires all rows to have a unique `id` property.', 'Alternatively, you can use the `getRowId` prop to specify a custom id for each row.', detailErrorMessage, JSON.stringify(row)].join('\n'));
}
}
const getRowIdFromRowModel = (rowModel, getRowId, detailErrorMessage) => {
const id = getRowId ? getRowId(rowModel) : rowModel.id;
checkGridRowIdIsValid(id, rowModel, detailErrorMessage);
return id;
};
exports.getRowIdFromRowModel = getRowIdFromRowModel;
const createRowsInternalCache = ({
rows,
getRowId,
loading,
rowCount
}) => {
const updates = {
type: 'full',
rows: []
};
const dataRowIdToModelLookup = {};
const dataRowIdToIdLookup = {};
for (let i = 0; i < rows.length; i += 1) {
const model = rows[i];
const id = getRowIdFromRowModel(model, getRowId);
dataRowIdToModelLookup[id] = model;
dataRowIdToIdLookup[id] = id;
updates.rows.push(id);
}
return {
rowsBeforePartialUpdates: rows,
loadingPropBeforePartialUpdates: loading,
rowCountPropBeforePartialUpdates: rowCount,
updates,
dataRowIdToIdLookup,
dataRowIdToModelLookup
};
};
exports.createRowsInternalCache = createRowsInternalCache;
const getTopLevelRowCount = ({
tree,
rowCountProp = 0
}) => {
const rootGroupNode = tree[GRID_ROOT_GROUP_ID];
return Math.max(rowCountProp, rootGroupNode.children.length + (rootGroupNode.footerId == null ? 0 : 1));
};
exports.getTopLevelRowCount = getTopLevelRowCount;
const getRowsStateFromCache = ({
apiRef,
rowCountProp = 0,
loadingProp,
previousTree,
previousTreeDepths
}) => {
const cache = apiRef.current.caches.rows;
// 1. Apply the "rowTreeCreation" family processing.
const {
tree: unProcessedTree,
treeDepths: unProcessedTreeDepths,
dataRowIds: unProcessedDataRowIds,
groupingName
} = apiRef.current.applyStrategyProcessor('rowTreeCreation', {
previousTree,
previousTreeDepths,
updates: cache.updates,
dataRowIdToIdLookup: cache.dataRowIdToIdLookup,
dataRowIdToModelLookup: cache.dataRowIdToModelLookup
});
// 2. Apply the "hydrateRows" pipe-processing.
const groupingParamsWithHydrateRows = apiRef.current.unstable_applyPipeProcessors('hydrateRows', {
tree: unProcessedTree,
treeDepths: unProcessedTreeDepths,
dataRowIdToIdLookup: cache.dataRowIdToIdLookup,
dataRowIds: unProcessedDataRowIds,
dataRowIdToModelLookup: cache.dataRowIdToModelLookup
});
// 3. Reset the cache updates
apiRef.current.caches.rows.updates = {
type: 'partial',
actions: {
insert: [],
modify: [],
remove: []
},
idToActionLookup: {}
};
return (0, _extends2.default)({}, groupingParamsWithHydrateRows, {
totalRowCount: Math.max(rowCountProp, groupingParamsWithHydrateRows.dataRowIds.length),
totalTopLevelRowCount: getTopLevelRowCount({
tree: groupingParamsWithHydrateRows.tree,
rowCountProp
}),
groupingName,
loading: loadingProp
});
};
exports.getRowsStateFromCache = getRowsStateFromCache;
const isAutoGeneratedRow = rowNode => rowNode.type === 'skeletonRow' || rowNode.type === 'footer' || rowNode.type === 'group' && rowNode.isAutoGenerated || rowNode.type === 'pinnedRow' && rowNode.isAutoGenerated;
exports.isAutoGeneratedRow = isAutoGeneratedRow;
const getTreeNodeDescendants = (tree, parentId, skipAutoGeneratedRows) => {
const node = tree[parentId];
if (node.type !== 'group') {
return [];
}
const validDescendants = [];
for (let i = 0; i < node.children.length; i += 1) {
const child = node.children[i];
if (!skipAutoGeneratedRows || !isAutoGeneratedRow(tree[child])) {
validDescendants.push(child);
}
const childDescendants = getTreeNodeDescendants(tree, child, skipAutoGeneratedRows);
for (let j = 0; j < childDescendants.length; j += 1) {
validDescendants.push(childDescendants[j]);
}
}
if (!skipAutoGeneratedRows && node.footerId != null) {
validDescendants.push(node.footerId);
}
return validDescendants;
};
exports.getTreeNodeDescendants = getTreeNodeDescendants;
const updateCacheWithNewRows = ({
previousCache,
getRowId,
updates
}) => {
if (previousCache.updates.type === 'full') {
throw new Error('MUI: Unable to prepare a partial update if a full update is not applied yet');
}
// Remove duplicate updates.
// A server can batch updates, and send several updates for the same row in one fn call.
const uniqueUpdates = new Map();
updates.forEach(update => {
const id = getRowIdFromRowModel(update, getRowId, 'A row was provided without id when calling updateRows():');
if (uniqueUpdates.has(id)) {
uniqueUpdates.set(id, (0, _extends2.default)({}, uniqueUpdates.get(id), update));
} else {
uniqueUpdates.set(id, update);
}
});
const partialUpdates = {
type: 'partial',
actions: {
insert: [...(previousCache.updates.actions.insert ?? [])],
modify: [...(previousCache.updates.actions.modify ?? [])],
remove: [...(previousCache.updates.actions.remove ?? [])]
},
idToActionLookup: (0, _extends2.default)({}, previousCache.updates.idToActionLookup)
};
const dataRowIdToModelLookup = (0, _extends2.default)({}, previousCache.dataRowIdToModelLookup);
const dataRowIdToIdLookup = (0, _extends2.default)({}, previousCache.dataRowIdToIdLookup);
const alreadyAppliedActionsToRemove = {
insert: {},
modify: {},
remove: {}
};
// Depending on the action already applied to the data row,
// We might want drop the already-applied-update.
// For instance:
// - if you delete then insert, then you don't want to apply the deletion in the tree.
// - if you insert, then modify, then you just want to apply the insertion in the tree.
uniqueUpdates.forEach((partialRow, id) => {
const actionAlreadyAppliedToRow = partialUpdates.idToActionLookup[id];
// Action === "delete"
// eslint-disable-next-line no-underscore-dangle
if (partialRow._action === 'delete') {
// If the data row has been removed since the last state update,
// Then do nothing.
if (actionAlreadyAppliedToRow === 'remove' || !dataRowIdToModelLookup[id]) {
return;
}
// If the data row has been inserted / modified since the last state update,
// Then drop this "insert" / "modify" update.
if (actionAlreadyAppliedToRow != null) {
alreadyAppliedActionsToRemove[actionAlreadyAppliedToRow][id] = true;
}
// Remove the data row from the lookups and add it to the "delete" update.
partialUpdates.actions.remove.push(id);
delete dataRowIdToModelLookup[id];
delete dataRowIdToIdLookup[id];
return;
}
const oldRow = dataRowIdToModelLookup[id];
// Action === "modify"
if (oldRow) {
// If the data row has been removed since the last state update,
// Then drop this "remove" update and add it to the "modify" update instead.
if (actionAlreadyAppliedToRow === 'remove') {
alreadyAppliedActionsToRemove.remove[id] = true;
partialUpdates.actions.modify.push(id);
}
// If the date has not been inserted / modified since the last state update,
// Then add it to the "modify" update (if it has been inserted it should just remain "inserted").
else if (actionAlreadyAppliedToRow == null) {
partialUpdates.actions.modify.push(id);
}
// Update the data row lookups.
dataRowIdToModelLookup[id] = (0, _extends2.default)({}, oldRow, partialRow);
return;
}
// Action === "insert"
// If the data row has been removed since the last state update,
// Then drop the "remove" update and add it to the "insert" update instead.
if (actionAlreadyAppliedToRow === 'remove') {
alreadyAppliedActionsToRemove.remove[id] = true;
partialUpdates.actions.insert.push(id);
}
// If the data row has not been inserted since the last state update,
// Then add it to the "insert" update.
// `actionAlreadyAppliedToRow` can't be equal to "modify", otherwise we would have an `oldRow` above.
else if (actionAlreadyAppliedToRow == null) {
partialUpdates.actions.insert.push(id);
}
// Update the data row lookups.
dataRowIdToModelLookup[id] = partialRow;
dataRowIdToIdLookup[id] = id;
});
const actionTypeWithActionsToRemove = Object.keys(alreadyAppliedActionsToRemove);
for (let i = 0; i < actionTypeWithActionsToRemove.length; i += 1) {
const actionType = actionTypeWithActionsToRemove[i];
const idsToRemove = alreadyAppliedActionsToRemove[actionType];
if (Object.keys(idsToRemove).length > 0) {
partialUpdates.actions[actionType] = partialUpdates.actions[actionType].filter(id => !idsToRemove[id]);
}
}
return {
dataRowIdToModelLookup,
dataRowIdToIdLookup,
updates: partialUpdates,
rowsBeforePartialUpdates: previousCache.rowsBeforePartialUpdates,
loadingPropBeforePartialUpdates: previousCache.loadingPropBeforePartialUpdates,
rowCountPropBeforePartialUpdates: previousCache.rowCountPropBeforePartialUpdates
};
};
exports.updateCacheWithNewRows = updateCacheWithNewRows;
function calculatePinnedRowsHeight(apiRef) {
const pinnedRows = (0, _gridRowsSelector.gridPinnedRowsSelector)(apiRef);
const topPinnedRowsHeight = pinnedRows?.top?.reduce((acc, value) => {
acc += apiRef.current.unstable_getRowHeight(value.id);
return acc;
}, 0) || 0;
const bottomPinnedRowsHeight = pinnedRows?.bottom?.reduce((acc, value) => {
acc += apiRef.current.unstable_getRowHeight(value.id);
return acc;
}, 0) || 0;
return {
top: topPinnedRowsHeight,
bottom: bottomPinnedRowsHeight
};
}
function getMinimalContentHeight(apiRef, rowHeight) {
const densityFactor = (0, _densitySelector.gridDensityFactorSelector)(apiRef);
return `var(--DataGrid-overlayHeight, ${2 * Math.floor(rowHeight * densityFactor)}px)`;
}

View File

@@ -0,0 +1,117 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _exportNames = {
gridRowCountSelector: true,
gridRowsLoadingSelector: true,
gridTopLevelRowCountSelector: true,
gridRowsLookupSelector: true,
gridRowsDataRowIdToIdLookupSelector: true,
gridRowTreeSelector: true,
gridRowGroupingNameSelector: true,
gridRowTreeDepthsSelector: true,
gridRowMaximumTreeDepthSelector: true,
gridDataRowIdsSelector: true,
GRID_ROOT_GROUP_ID: true,
checkGridRowIdIsValid: true
};
Object.defineProperty(exports, "GRID_ROOT_GROUP_ID", {
enumerable: true,
get: function () {
return _gridRowsUtils.GRID_ROOT_GROUP_ID;
}
});
Object.defineProperty(exports, "checkGridRowIdIsValid", {
enumerable: true,
get: function () {
return _gridRowsUtils.checkGridRowIdIsValid;
}
});
Object.defineProperty(exports, "gridDataRowIdsSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridDataRowIdsSelector;
}
});
Object.defineProperty(exports, "gridRowCountSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowCountSelector;
}
});
Object.defineProperty(exports, "gridRowGroupingNameSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowGroupingNameSelector;
}
});
Object.defineProperty(exports, "gridRowMaximumTreeDepthSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowMaximumTreeDepthSelector;
}
});
Object.defineProperty(exports, "gridRowTreeDepthsSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowTreeDepthsSelector;
}
});
Object.defineProperty(exports, "gridRowTreeSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowTreeSelector;
}
});
Object.defineProperty(exports, "gridRowsDataRowIdToIdLookupSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowsDataRowIdToIdLookupSelector;
}
});
Object.defineProperty(exports, "gridRowsLoadingSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowsLoadingSelector;
}
});
Object.defineProperty(exports, "gridRowsLookupSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridRowsLookupSelector;
}
});
Object.defineProperty(exports, "gridTopLevelRowCountSelector", {
enumerable: true,
get: function () {
return _gridRowsSelector.gridTopLevelRowCountSelector;
}
});
var _gridRowsMetaSelector = require("./gridRowsMetaSelector");
Object.keys(_gridRowsMetaSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _gridRowsMetaSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridRowsMetaSelector[key];
}
});
});
var _gridRowsMetaState = require("./gridRowsMetaState");
Object.keys(_gridRowsMetaState).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _gridRowsMetaState[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridRowsMetaState[key];
}
});
});
var _gridRowsSelector = require("./gridRowsSelector");
var _gridRowsUtils = require("./gridRowsUtils");

View File

@@ -0,0 +1,168 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MissingRowIdError = void 0;
exports.useGridParamsApi = useGridParamsApi;
var React = _interopRequireWildcard(require("react"));
var _domUtils = require("../../../utils/domUtils");
var _gridRowsUtils = require("./gridRowsUtils");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridFocusStateSelector = require("../focus/gridFocusStateSelector");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
class MissingRowIdError extends Error {}
/**
* @requires useGridColumns (method)
* @requires useGridRows (method)
* @requires useGridFocus (state)
* @requires useGridEditing (method)
* TODO: Impossible priority - useGridEditing also needs to be after useGridParamsApi
* TODO: Impossible priority - useGridFocus also needs to be after useGridParamsApi
*/
exports.MissingRowIdError = MissingRowIdError;
function useGridParamsApi(apiRef, props) {
const {
getRowId
} = props;
const getColumnHeaderParams = React.useCallback(field => ({
field,
colDef: apiRef.current.getColumn(field)
}), [apiRef]);
const getRowParams = React.useCallback(id => {
const row = apiRef.current.getRow(id);
if (!row) {
throw new MissingRowIdError(`No row with id #${id} found`);
}
const params = {
id,
columns: apiRef.current.getAllColumns(),
row
};
return params;
}, [apiRef]);
const getBaseCellParams = React.useCallback((id, field) => {
const row = apiRef.current.getRow(id);
const rowNode = apiRef.current.getRowNode(id);
if (!row || !rowNode) {
throw new MissingRowIdError(`No row with id #${id} found`);
}
const cellFocus = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
const cellTabIndex = (0, _gridFocusStateSelector.gridTabIndexCellSelector)(apiRef);
const params = {
id,
field,
row,
rowNode,
value: row[field],
colDef: apiRef.current.getColumn(field),
cellMode: apiRef.current.getCellMode(id, field),
api: apiRef.current,
hasFocus: cellFocus !== null && cellFocus.field === field && cellFocus.id === id,
tabIndex: cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === id ? 0 : -1
};
return params;
}, [apiRef]);
const getCellParams = React.useCallback((id, field) => {
const colDef = apiRef.current.getColumn(field);
const value = apiRef.current.getCellValue(id, field);
const row = apiRef.current.getRow(id);
const rowNode = apiRef.current.getRowNode(id);
if (!row || !rowNode) {
throw new MissingRowIdError(`No row with id #${id} found`);
}
const cellFocus = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
const cellTabIndex = (0, _gridFocusStateSelector.gridTabIndexCellSelector)(apiRef);
const params = {
id,
field,
row,
rowNode,
colDef,
cellMode: apiRef.current.getCellMode(id, field),
hasFocus: cellFocus !== null && cellFocus.field === field && cellFocus.id === id,
tabIndex: cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === id ? 0 : -1,
value,
formattedValue: value,
isEditable: false
};
if (colDef && colDef.valueFormatter) {
params.formattedValue = colDef.valueFormatter({
id,
field: params.field,
value: params.value,
api: apiRef.current
});
}
params.isEditable = colDef && apiRef.current.isCellEditable(params);
return params;
}, [apiRef]);
const getCellValue = React.useCallback((id, field) => {
const colDef = apiRef.current.getColumn(field);
if (!colDef || !colDef.valueGetter) {
const rowModel = apiRef.current.getRow(id);
if (!rowModel) {
throw new MissingRowIdError(`No row with id #${id} found`);
}
return rowModel[field];
}
return colDef.valueGetter(getBaseCellParams(id, field));
}, [apiRef, getBaseCellParams]);
const getRowValue = React.useCallback((row, colDef) => {
const id = _gridRowsUtils.GRID_ID_AUTOGENERATED in row ? row[_gridRowsUtils.GRID_ID_AUTOGENERATED] : getRowId?.(row) ?? row.id;
const field = colDef.field;
if (!colDef || !colDef.valueGetter) {
return row[field];
}
return colDef.valueGetter(getBaseCellParams(id, field));
}, [getBaseCellParams, getRowId]);
const getRowFormattedValue = React.useCallback((row, colDef) => {
const value = getRowValue(row, colDef);
if (!colDef || !colDef.valueFormatter) {
return value;
}
const id = (getRowId ? getRowId(row) : row.id) ?? row[_gridRowsUtils.GRID_ID_AUTOGENERATED];
const field = colDef.field;
return colDef.valueFormatter({
id,
field,
value,
api: apiRef.current
});
}, [apiRef, getRowId, getRowValue]);
const getColumnHeaderElement = React.useCallback(field => {
if (!apiRef.current.rootElementRef.current) {
return null;
}
return (0, _domUtils.getGridColumnHeaderElement)(apiRef.current.rootElementRef.current, field);
}, [apiRef]);
const getRowElement = React.useCallback(id => {
if (!apiRef.current.rootElementRef.current) {
return null;
}
return (0, _domUtils.getGridRowElement)(apiRef.current.rootElementRef.current, id);
}, [apiRef]);
const getCellElement = React.useCallback((id, field) => {
if (!apiRef.current.rootElementRef.current) {
return null;
}
return (0, _domUtils.getGridCellElement)(apiRef.current.rootElementRef.current, {
id,
field
});
}, [apiRef]);
const paramsApi = {
getCellValue,
getCellParams,
getCellElement,
getRowValue,
getRowFormattedValue,
getRowParams,
getRowElement,
getColumnHeaderParams,
getColumnHeaderElement
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, paramsApi, 'public');
}

View File

@@ -0,0 +1,453 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRows = exports.rowsStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridRowsSelector = require("./gridRowsSelector");
var _useTimeout = require("../../utils/useTimeout");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _gridSortingSelector = require("../sorting/gridSortingSelector");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _gridRowsUtils = require("./gridRowsUtils");
var _pipeProcessing = require("../../core/pipeProcessing");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const rowsStateInitializer = (state, props, apiRef) => {
apiRef.current.caches.rows = (0, _gridRowsUtils.createRowsInternalCache)({
rows: props.rows,
getRowId: props.getRowId,
loading: props.loading,
rowCount: props.rowCount
});
return (0, _extends2.default)({}, state, {
rows: (0, _gridRowsUtils.getRowsStateFromCache)({
apiRef,
rowCountProp: props.rowCount,
loadingProp: props.loading,
previousTree: null,
previousTreeDepths: null
})
});
};
exports.rowsStateInitializer = rowsStateInitializer;
const useGridRows = (apiRef, props) => {
if (process.env.NODE_ENV !== 'production') {
try {
// Freeze the `rows` prop so developers have a fast failure if they try to use Array.prototype.push().
Object.freeze(props.rows);
} catch (error) {
// Sometimes, it's impossible to freeze, so we give up on it.
}
}
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridRows');
const currentPage = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props);
const lastUpdateMs = React.useRef(Date.now());
const timeout = (0, _useTimeout.useTimeout)();
const getRow = React.useCallback(id => {
const model = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef)[id];
if (model) {
return model;
}
const node = apiRef.current.getRowNode(id);
if (node && (0, _gridRowsUtils.isAutoGeneratedRow)(node)) {
return {
[_gridRowsUtils.GRID_ID_AUTOGENERATED]: id
};
}
return null;
}, [apiRef]);
const getRowIdProp = props.getRowId;
const getRowId = React.useCallback(row => {
if (_gridRowsUtils.GRID_ID_AUTOGENERATED in row) {
return row[_gridRowsUtils.GRID_ID_AUTOGENERATED];
}
if (getRowIdProp) {
return getRowIdProp(row);
}
return row.id;
}, [getRowIdProp]);
const lookup = React.useMemo(() => currentPage.rows.reduce((acc, {
id
}, index) => {
acc[id] = index;
return acc;
}, {}), [currentPage.rows]);
const throttledRowsChange = React.useCallback(({
cache,
throttle
}) => {
const run = () => {
lastUpdateMs.current = Date.now();
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
rows: (0, _gridRowsUtils.getRowsStateFromCache)({
apiRef,
rowCountProp: props.rowCount,
loadingProp: props.loading,
previousTree: (0, _gridRowsSelector.gridRowTreeSelector)(apiRef),
previousTreeDepths: (0, _gridRowsSelector.gridRowTreeDepthsSelector)(apiRef)
})
}));
apiRef.current.publishEvent('rowsSet');
apiRef.current.forceUpdate();
};
timeout.clear();
apiRef.current.caches.rows = cache;
if (!throttle) {
run();
return;
}
const throttleRemainingTimeMs = props.throttleRowsMs - (Date.now() - lastUpdateMs.current);
if (throttleRemainingTimeMs > 0) {
timeout.start(throttleRemainingTimeMs, run);
return;
}
run();
}, [props.throttleRowsMs, props.rowCount, props.loading, apiRef, timeout]);
/**
* API METHODS
*/
const setRows = React.useCallback(rows => {
logger.debug(`Updating all rows, new length ${rows.length}`);
const cache = (0, _gridRowsUtils.createRowsInternalCache)({
rows,
getRowId: props.getRowId,
loading: props.loading,
rowCount: props.rowCount
});
const prevCache = apiRef.current.caches.rows;
cache.rowsBeforePartialUpdates = prevCache.rowsBeforePartialUpdates;
throttledRowsChange({
cache,
throttle: true
});
}, [logger, props.getRowId, props.loading, props.rowCount, throttledRowsChange, apiRef]);
const updateRows = React.useCallback(updates => {
if (props.signature === _useGridApiEventHandler.GridSignature.DataGrid && updates.length > 1) {
throw new Error(["MUI: You can't update several rows at once in `apiRef.current.updateRows` on the DataGrid.", 'You need to upgrade to DataGridPro or DataGridPremium component to unlock this feature.'].join('\n'));
}
const nonPinnedRowsUpdates = [];
updates.forEach(update => {
const id = (0, _gridRowsUtils.getRowIdFromRowModel)(update, props.getRowId, 'A row was provided without id when calling updateRows():');
const rowNode = apiRef.current.getRowNode(id);
if (rowNode?.type === 'pinnedRow') {
// @ts-ignore because otherwise `release:build` doesn't work
const pinnedRowsCache = apiRef.current.caches.pinnedRows;
const prevModel = pinnedRowsCache.idLookup[id];
if (prevModel) {
pinnedRowsCache.idLookup[id] = (0, _extends2.default)({}, prevModel, update);
}
} else {
nonPinnedRowsUpdates.push(update);
}
});
const cache = (0, _gridRowsUtils.updateCacheWithNewRows)({
updates: nonPinnedRowsUpdates,
getRowId: props.getRowId,
previousCache: apiRef.current.caches.rows
});
throttledRowsChange({
cache,
throttle: true
});
}, [props.signature, props.getRowId, throttledRowsChange, apiRef]);
const getRowModels = React.useCallback(() => {
const dataRows = (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef);
const idRowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
return new Map(dataRows.map(id => [id, idRowsLookup[id] ?? {}]));
}, [apiRef]);
const getRowsCount = React.useCallback(() => (0, _gridRowsSelector.gridRowCountSelector)(apiRef), [apiRef]);
const getAllRowIds = React.useCallback(() => (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef), [apiRef]);
const getRowIndexRelativeToVisibleRows = React.useCallback(id => lookup[id], [lookup]);
const setRowChildrenExpansion = React.useCallback((id, isExpanded) => {
const currentNode = apiRef.current.getRowNode(id);
if (!currentNode) {
throw new Error(`MUI: No row with id #${id} found`);
}
if (currentNode.type !== 'group') {
throw new Error('MUI: Only group nodes can be expanded or collapsed');
}
const newNode = (0, _extends2.default)({}, currentNode, {
childrenExpanded: isExpanded
});
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
rows: (0, _extends2.default)({}, state.rows, {
tree: (0, _extends2.default)({}, state.rows.tree, {
[id]: newNode
})
})
});
});
apiRef.current.forceUpdate();
apiRef.current.publishEvent('rowExpansionChange', newNode);
}, [apiRef]);
const getRowNode = React.useCallback(id => (0, _gridRowsSelector.gridRowTreeSelector)(apiRef)[id] ?? null, [apiRef]);
const getRowGroupChildren = React.useCallback(({
skipAutoGeneratedRows = true,
groupId,
applySorting,
applyFiltering
}) => {
const tree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
let children;
if (applySorting) {
const groupNode = tree[groupId];
if (!groupNode) {
return [];
}
const sortedRowIds = (0, _gridSortingSelector.gridSortedRowIdsSelector)(apiRef);
children = [];
const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1;
for (let index = startIndex; index < sortedRowIds.length && tree[sortedRowIds[index]].depth > groupNode.depth; index += 1) {
const id = sortedRowIds[index];
if (!skipAutoGeneratedRows || !(0, _gridRowsUtils.isAutoGeneratedRow)(tree[id])) {
children.push(id);
}
}
} else {
children = (0, _gridRowsUtils.getTreeNodeDescendants)(tree, groupId, skipAutoGeneratedRows);
}
if (applyFiltering) {
const filteredRowsLookup = (0, _gridFilterSelector.gridFilteredRowsLookupSelector)(apiRef);
children = children.filter(childId => filteredRowsLookup[childId] !== false);
}
return children;
}, [apiRef]);
const setRowIndex = React.useCallback((rowId, targetIndex) => {
const node = apiRef.current.getRowNode(rowId);
if (!node) {
throw new Error(`MUI: No row with id #${rowId} found`);
}
if (node.parent !== _gridRowsUtils.GRID_ROOT_GROUP_ID) {
throw new Error(`MUI: The row reordering do not support reordering of grouped rows yet`);
}
if (node.type !== 'leaf') {
throw new Error(`MUI: The row reordering do not support reordering of footer or grouping rows`);
}
apiRef.current.setState(state => {
const group = (0, _gridRowsSelector.gridRowTreeSelector)(state, apiRef.current.instanceId)[_gridRowsUtils.GRID_ROOT_GROUP_ID];
const allRows = group.children;
const oldIndex = allRows.findIndex(row => row === rowId);
if (oldIndex === -1 || oldIndex === targetIndex) {
return state;
}
logger.debug(`Moving row ${rowId} to index ${targetIndex}`);
const updatedRows = [...allRows];
updatedRows.splice(targetIndex, 0, updatedRows.splice(oldIndex, 1)[0]);
return (0, _extends2.default)({}, state, {
rows: (0, _extends2.default)({}, state.rows, {
tree: (0, _extends2.default)({}, state.rows.tree, {
[_gridRowsUtils.GRID_ROOT_GROUP_ID]: (0, _extends2.default)({}, group, {
children: updatedRows
})
})
})
});
});
apiRef.current.publishEvent('rowsSet');
}, [apiRef, logger]);
const replaceRows = React.useCallback((firstRowToRender, newRows) => {
if (props.signature === _useGridApiEventHandler.GridSignature.DataGrid && newRows.length > 1) {
throw new Error(["MUI: You can't replace rows using `apiRef.current.unstable_replaceRows` on the DataGrid.", 'You need to upgrade to DataGridPro or DataGridPremium component to unlock this feature.'].join('\n'));
}
if (newRows.length === 0) {
return;
}
const treeDepth = (0, _gridRowsSelector.gridRowMaximumTreeDepthSelector)(apiRef);
if (treeDepth > 1) {
throw new Error('`apiRef.current.unstable_replaceRows` is not compatible with tree data and row grouping');
}
const tree = (0, _extends2.default)({}, (0, _gridRowsSelector.gridRowTreeSelector)(apiRef));
const dataRowIdToModelLookup = (0, _extends2.default)({}, (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef));
const dataRowIdToIdLookup = (0, _extends2.default)({}, (0, _gridRowsSelector.gridRowsDataRowIdToIdLookupSelector)(apiRef));
const rootGroup = tree[_gridRowsUtils.GRID_ROOT_GROUP_ID];
const rootGroupChildren = [...rootGroup.children];
const seenIds = new Set();
for (let i = 0; i < newRows.length; i += 1) {
const rowModel = newRows[i];
const rowId = (0, _gridRowsUtils.getRowIdFromRowModel)(rowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
const [removedRowId] = rootGroupChildren.splice(firstRowToRender + i, 1, rowId);
if (!seenIds.has(removedRowId)) {
delete dataRowIdToModelLookup[removedRowId];
delete dataRowIdToIdLookup[removedRowId];
delete tree[removedRowId];
}
const rowTreeNodeConfig = {
id: rowId,
depth: 0,
parent: _gridRowsUtils.GRID_ROOT_GROUP_ID,
type: 'leaf',
groupingKey: null
};
dataRowIdToModelLookup[rowId] = rowModel;
dataRowIdToIdLookup[rowId] = rowId;
tree[rowId] = rowTreeNodeConfig;
seenIds.add(rowId);
}
tree[_gridRowsUtils.GRID_ROOT_GROUP_ID] = (0, _extends2.default)({}, rootGroup, {
children: rootGroupChildren
});
// Removes potential remaining skeleton rows from the dataRowIds.
const dataRowIds = rootGroupChildren.filter(childId => tree[childId].type === 'leaf');
apiRef.current.caches.rows.dataRowIdToModelLookup = dataRowIdToModelLookup;
apiRef.current.caches.rows.dataRowIdToIdLookup = dataRowIdToIdLookup;
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
rows: (0, _extends2.default)({}, state.rows, {
dataRowIdToModelLookup,
dataRowIdToIdLookup,
dataRowIds,
tree
})
}));
apiRef.current.publishEvent('rowsSet');
}, [apiRef, props.signature, props.getRowId]);
const rowApi = {
getRow,
getRowId,
getRowModels,
getRowsCount,
getAllRowIds,
setRows,
updateRows,
getRowNode,
getRowIndexRelativeToVisibleRows,
unstable_replaceRows: replaceRows
};
const rowProApi = {
setRowIndex,
setRowChildrenExpansion,
getRowGroupChildren
};
/**
* EVENTS
*/
const groupRows = React.useCallback(() => {
logger.info(`Row grouping pre-processing have changed, regenerating the row tree`);
let cache;
if (apiRef.current.caches.rows.rowsBeforePartialUpdates === props.rows) {
// The `props.rows` did not change since the last row grouping
// We can use the current rows cache which contains the partial updates done recently.
cache = (0, _extends2.default)({}, apiRef.current.caches.rows, {
updates: {
type: 'full',
rows: (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef)
}
});
} else {
// The `props.rows` has changed since the last row grouping
// We must use the new `props.rows` on the new grouping
// This occurs because this event is triggered before the `useEffect` on the rows when both the grouping pre-processing and the rows changes on the same render
cache = (0, _gridRowsUtils.createRowsInternalCache)({
rows: props.rows,
getRowId: props.getRowId,
loading: props.loading,
rowCount: props.rowCount
});
}
throttledRowsChange({
cache,
throttle: false
});
}, [logger, apiRef, props.rows, props.getRowId, props.loading, props.rowCount, throttledRowsChange]);
const handleStrategyProcessorChange = React.useCallback(methodName => {
if (methodName === 'rowTreeCreation') {
groupRows();
}
}, [groupRows]);
const handleStrategyActivityChange = React.useCallback(() => {
// `rowTreeCreation` is the only processor ran when `strategyAvailabilityChange` is fired.
// All the other processors listen to `rowsSet` which will be published by the `groupRows` method below.
if (apiRef.current.getActiveStrategy('rowTree') !== (0, _gridRowsSelector.gridRowGroupingNameSelector)(apiRef)) {
groupRows();
}
}, [apiRef, groupRows]);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'activeStrategyProcessorChange', handleStrategyProcessorChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'strategyAvailabilityChange', handleStrategyActivityChange);
/**
* APPLIERS
*/
const applyHydrateRowsProcessor = React.useCallback(() => {
apiRef.current.setState(state => {
const response = apiRef.current.unstable_applyPipeProcessors('hydrateRows', {
tree: (0, _gridRowsSelector.gridRowTreeSelector)(state, apiRef.current.instanceId),
treeDepths: (0, _gridRowsSelector.gridRowTreeDepthsSelector)(state, apiRef.current.instanceId),
dataRowIds: (0, _gridRowsSelector.gridDataRowIdsSelector)(state, apiRef.current.instanceId),
dataRowIdToModelLookup: (0, _gridRowsSelector.gridRowsLookupSelector)(state, apiRef.current.instanceId),
dataRowIdToIdLookup: (0, _gridRowsSelector.gridRowsDataRowIdToIdLookupSelector)(state, apiRef.current.instanceId)
});
return (0, _extends2.default)({}, state, {
rows: (0, _extends2.default)({}, state.rows, response, {
totalTopLevelRowCount: (0, _gridRowsUtils.getTopLevelRowCount)({
tree: response.tree,
rowCountProp: props.rowCount
})
})
});
});
apiRef.current.publishEvent('rowsSet');
apiRef.current.forceUpdate();
}, [apiRef, props.rowCount]);
(0, _pipeProcessing.useGridRegisterPipeApplier)(apiRef, 'hydrateRows', applyHydrateRowsProcessor);
(0, _useGridApiMethod.useGridApiMethod)(apiRef, rowApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, rowProApi, props.signature === _useGridApiEventHandler.GridSignature.DataGrid ? 'private' : 'public');
// The effect do not track any value defined synchronously during the 1st render by hooks called after `useGridRows`
// As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
const areNewRowsAlreadyInState = apiRef.current.caches.rows.rowsBeforePartialUpdates === props.rows;
const isNewLoadingAlreadyInState = apiRef.current.caches.rows.loadingPropBeforePartialUpdates === props.loading;
const isNewRowCountAlreadyInState = apiRef.current.caches.rows.rowCountPropBeforePartialUpdates === props.rowCount;
// The new rows have already been applied (most likely in the `'rowGroupsPreProcessingChange'` listener)
if (areNewRowsAlreadyInState) {
// If the loading prop has changed, we need to update its value in the state because it won't be done by `throttledRowsChange`
if (!isNewLoadingAlreadyInState) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
rows: (0, _extends2.default)({}, state.rows, {
loading: props.loading
})
}));
apiRef.current.caches.rows.loadingPropBeforePartialUpdates = props.loading;
apiRef.current.forceUpdate();
}
if (!isNewRowCountAlreadyInState) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
rows: (0, _extends2.default)({}, state.rows, {
totalRowCount: Math.max(props.rowCount || 0, state.rows.totalRowCount),
totalTopLevelRowCount: Math.max(props.rowCount || 0, state.rows.totalTopLevelRowCount)
})
}));
apiRef.current.caches.rows.rowCountPropBeforePartialUpdates = props.rowCount;
apiRef.current.forceUpdate();
}
return;
}
logger.debug(`Updating all rows, new length ${props.rows.length}`);
throttledRowsChange({
cache: (0, _gridRowsUtils.createRowsInternalCache)({
rows: props.rows,
getRowId: props.getRowId,
loading: props.loading,
rowCount: props.rowCount
}),
throttle: false
});
}, [props.rows, props.rowCount, props.getRowId, props.loading, logger, throttledRowsChange, apiRef]);
};
exports.useGridRows = useGridRows;

View File

@@ -0,0 +1,237 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRowsMeta = exports.rowsMetaStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridSelector = require("../../utils/useGridSelector");
var _densitySelector = require("../density/densitySelector");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _gridPaginationSelector = require("../pagination/gridPaginationSelector");
var _gridSortingSelector = require("../sorting/gridSortingSelector");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridRowsSelector = require("./gridRowsSelector");
var _useDataGridProps = require("../../../DataGrid/useDataGridProps");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const rowsMetaStateInitializer = state => (0, _extends2.default)({}, state, {
rowsMeta: {
currentPageTotalHeight: 0,
positions: []
}
});
exports.rowsMetaStateInitializer = rowsMetaStateInitializer;
let warnedOnceInvalidRowHeight = false;
const getValidRowHeight = (rowHeightProp, defaultRowHeight, warningMessage) => {
if (typeof rowHeightProp === 'number' && rowHeightProp > 0) {
return rowHeightProp;
}
if (process.env.NODE_ENV !== 'production' && !warnedOnceInvalidRowHeight && typeof rowHeightProp !== 'undefined' && rowHeightProp !== null) {
console.warn(warningMessage);
warnedOnceInvalidRowHeight = true;
}
return defaultRowHeight;
};
const rowHeightWarning = [`MUI: The \`rowHeight\` prop should be a number greater than 0.`, `The default value will be used instead.`].join('\n');
const getRowHeightWarning = [`MUI: The \`getRowHeight\` prop should return a number greater than 0 or 'auto'.`, `The default value will be used instead.`].join('\n');
/**
* @requires useGridPageSize (method)
* @requires useGridPage (method)
*/
const useGridRowsMeta = (apiRef, props) => {
const {
getRowHeight: getRowHeightProp,
getRowSpacing,
getEstimatedRowHeight
} = props;
const rowsHeightLookup = React.useRef(Object.create(null));
// Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
const lastMeasuredRowIndex = React.useRef(-1);
const hasRowWithAutoHeight = React.useRef(false);
const densityFactor = (0, _useGridSelector.useGridSelector)(apiRef, _densitySelector.gridDensityFactorSelector);
const filterModel = (0, _useGridSelector.useGridSelector)(apiRef, _gridFilterSelector.gridFilterModelSelector);
const paginationState = (0, _useGridSelector.useGridSelector)(apiRef, _gridPaginationSelector.gridPaginationSelector);
const sortModel = (0, _useGridSelector.useGridSelector)(apiRef, _gridSortingSelector.gridSortModelSelector);
const currentPage = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props);
const pinnedRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridPinnedRowsSelector);
const validRowHeight = getValidRowHeight(props.rowHeight, _useDataGridProps.DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, rowHeightWarning);
const rowHeight = Math.floor(validRowHeight * densityFactor);
const hydrateRowsMeta = React.useCallback(() => {
hasRowWithAutoHeight.current = false;
const calculateRowProcessedSizes = row => {
if (!rowsHeightLookup.current[row.id]) {
rowsHeightLookup.current[row.id] = {
sizes: {
baseCenter: rowHeight
},
isResized: false,
autoHeight: false,
needsFirstMeasurement: true // Assume all rows will need to be measured by default
};
}
const {
isResized,
needsFirstMeasurement,
sizes
} = rowsHeightLookup.current[row.id];
let baseRowHeight = typeof rowHeight === 'number' && rowHeight > 0 ? rowHeight : 52;
const existingBaseRowHeight = sizes.baseCenter;
if (isResized) {
// Do not recalculate resized row height and use the value from the lookup
baseRowHeight = existingBaseRowHeight;
} else if (getRowHeightProp) {
const rowHeightFromUser = getRowHeightProp((0, _extends2.default)({}, row, {
densityFactor
}));
if (rowHeightFromUser === 'auto') {
if (needsFirstMeasurement) {
const estimatedRowHeight = getEstimatedRowHeight ? getEstimatedRowHeight((0, _extends2.default)({}, row, {
densityFactor
})) : rowHeight;
// If the row was not measured yet use the estimated row height
baseRowHeight = estimatedRowHeight ?? rowHeight;
} else {
baseRowHeight = existingBaseRowHeight;
}
hasRowWithAutoHeight.current = true;
rowsHeightLookup.current[row.id].autoHeight = true;
} else {
// Default back to base rowHeight if getRowHeight returns invalid value.
baseRowHeight = getValidRowHeight(rowHeightFromUser, rowHeight, getRowHeightWarning);
rowsHeightLookup.current[row.id].needsFirstMeasurement = false;
rowsHeightLookup.current[row.id].autoHeight = false;
}
} else {
rowsHeightLookup.current[row.id].needsFirstMeasurement = false;
}
const initialHeights = {};
/* eslint-disable-next-line no-restricted-syntax */
for (const key in sizes) {
if (/^base[A-Z]/.test(key)) {
initialHeights[key] = sizes[key];
}
}
initialHeights.baseCenter = baseRowHeight;
if (getRowSpacing) {
const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id);
const spacing = getRowSpacing((0, _extends2.default)({}, row, {
isFirstVisible: indexRelativeToCurrentPage === 0,
isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1,
indexRelativeToCurrentPage
}));
initialHeights.spacingTop = spacing.top ?? 0;
initialHeights.spacingBottom = spacing.bottom ?? 0;
}
const processedSizes = apiRef.current.unstable_applyPipeProcessors('rowHeight', initialHeights, row);
rowsHeightLookup.current[row.id].sizes = processedSizes;
return processedSizes;
};
const positions = [];
const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => {
positions.push(acc);
let maximumBaseSize = 0;
let otherSizes = 0;
const processedSizes = calculateRowProcessedSizes(row);
/* eslint-disable-next-line no-restricted-syntax, guard-for-in */
for (const key in processedSizes) {
const value = processedSizes[key];
if (/^base[A-Z]/.test(key)) {
maximumBaseSize = value > maximumBaseSize ? value : maximumBaseSize;
} else {
otherSizes += value;
}
}
return acc + maximumBaseSize + otherSizes;
}, 0);
pinnedRows?.top?.forEach(row => {
calculateRowProcessedSizes(row);
});
pinnedRows?.bottom?.forEach(row => {
calculateRowProcessedSizes(row);
});
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
rowsMeta: {
currentPageTotalHeight,
positions
}
});
});
if (!hasRowWithAutoHeight.current) {
// No row has height=auto, so all rows are already measured
lastMeasuredRowIndex.current = Infinity;
}
apiRef.current.forceUpdate();
}, [apiRef, currentPage.rows, rowHeight, getRowHeightProp, getRowSpacing, getEstimatedRowHeight, pinnedRows, densityFactor]);
const getRowHeight = React.useCallback(rowId => {
const height = rowsHeightLookup.current[rowId];
return height ? height.sizes.baseCenter : rowHeight;
}, [rowHeight]);
const getRowInternalSizes = rowId => rowsHeightLookup.current[rowId]?.sizes;
const setRowHeight = React.useCallback((id, height) => {
rowsHeightLookup.current[id].sizes.baseCenter = height;
rowsHeightLookup.current[id].isResized = true;
rowsHeightLookup.current[id].needsFirstMeasurement = false;
hydrateRowsMeta();
}, [hydrateRowsMeta]);
const debouncedHydrateRowsMeta = React.useMemo(() => (0, _utils.unstable_debounce)(hydrateRowsMeta, props.rowPositionsDebounceMs), [hydrateRowsMeta, props.rowPositionsDebounceMs]);
const storeMeasuredRowHeight = React.useCallback((id, height, position) => {
if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) {
return;
}
// Only trigger hydration if the value is different, otherwise we trigger a loop
const needsHydration = rowsHeightLookup.current[id].sizes[`base${(0, _utils.unstable_capitalize)(position)}`] !== height;
rowsHeightLookup.current[id].needsFirstMeasurement = false;
rowsHeightLookup.current[id].sizes[`base${(0, _utils.unstable_capitalize)(position)}`] = height;
if (needsHydration) {
debouncedHydrateRowsMeta();
}
}, [debouncedHydrateRowsMeta]);
const rowHasAutoHeight = React.useCallback(id => {
return rowsHeightLookup.current[id]?.autoHeight || false;
}, []);
const getLastMeasuredRowIndex = React.useCallback(() => {
return lastMeasuredRowIndex.current;
}, []);
const setLastMeasuredRowIndex = React.useCallback(index => {
if (hasRowWithAutoHeight.current && index > lastMeasuredRowIndex.current) {
lastMeasuredRowIndex.current = index;
}
}, []);
const resetRowHeights = React.useCallback(() => {
rowsHeightLookup.current = {};
hydrateRowsMeta();
}, [hydrateRowsMeta]);
// The effect is used to build the rows meta data - currentPageTotalHeight and positions.
// Because of variable row height this is needed for the virtualization
React.useEffect(() => {
hydrateRowsMeta();
}, [rowHeight, filterModel, paginationState, sortModel, hydrateRowsMeta]);
(0, _pipeProcessing.useGridRegisterPipeApplier)(apiRef, 'rowHeight', hydrateRowsMeta);
const rowsMetaApi = {
unstable_setLastMeasuredRowIndex: setLastMeasuredRowIndex,
unstable_getRowHeight: getRowHeight,
unstable_getRowInternalSizes: getRowInternalSizes,
unstable_setRowHeight: setRowHeight,
unstable_storeRowHeightMeasurement: storeMeasuredRowHeight,
resetRowHeights
};
const rowsMetaPrivateApi = {
getLastMeasuredRowIndex,
rowHasAutoHeight
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, rowsMetaApi, 'public');
(0, _useGridApiMethod.useGridApiMethod)(apiRef, rowsMetaPrivateApi, 'private');
};
exports.useGridRowsMeta = useGridRowsMeta;

View File

@@ -0,0 +1,89 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridRowsPreProcessors = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _strategyProcessing = require("../../core/strategyProcessing");
var _gridRowsUtils = require("./gridRowsUtils");
const createFlatRowTree = rows => {
const tree = {
[_gridRowsUtils.GRID_ROOT_GROUP_ID]: (0, _extends2.default)({}, (0, _gridRowsUtils.buildRootGroup)(), {
children: rows
})
};
for (let i = 0; i < rows.length; i += 1) {
const rowId = rows[i];
tree[rowId] = {
id: rowId,
depth: 0,
parent: _gridRowsUtils.GRID_ROOT_GROUP_ID,
type: 'leaf',
groupingKey: null
};
}
return {
groupingName: _strategyProcessing.GRID_DEFAULT_STRATEGY,
tree,
treeDepths: {
0: rows.length
},
dataRowIds: rows
};
};
const updateFlatRowTree = ({
previousTree,
actions
}) => {
const tree = (0, _extends2.default)({}, previousTree);
const idsToRemoveFromRootGroup = {};
for (let i = 0; i < actions.remove.length; i += 1) {
const idToDelete = actions.remove[i];
idsToRemoveFromRootGroup[idToDelete] = true;
delete tree[idToDelete];
}
for (let i = 0; i < actions.insert.length; i += 1) {
const idToInsert = actions.insert[i];
tree[idToInsert] = {
id: idToInsert,
depth: 0,
parent: _gridRowsUtils.GRID_ROOT_GROUP_ID,
type: 'leaf',
groupingKey: null
};
}
// TODO rows v6: Support row unpinning
const rootGroup = tree[_gridRowsUtils.GRID_ROOT_GROUP_ID];
let rootGroupChildren = [...rootGroup.children, ...actions.insert];
if (Object.values(idsToRemoveFromRootGroup).length) {
rootGroupChildren = rootGroupChildren.filter(id => !idsToRemoveFromRootGroup[id]);
}
tree[_gridRowsUtils.GRID_ROOT_GROUP_ID] = (0, _extends2.default)({}, rootGroup, {
children: rootGroupChildren
});
return {
groupingName: _strategyProcessing.GRID_DEFAULT_STRATEGY,
tree,
treeDepths: {
0: rootGroupChildren.length
},
dataRowIds: rootGroupChildren
};
};
const flatRowTreeCreationMethod = params => {
if (params.updates.type === 'full') {
return createFlatRowTree(params.updates.rows);
}
return updateFlatRowTree({
previousTree: params.previousTree,
actions: params.updates.actions
});
};
const useGridRowsPreProcessors = apiRef => {
(0, _strategyProcessing.useGridRegisterStrategyProcessor)(apiRef, _strategyProcessing.GRID_DEFAULT_STRATEGY, 'rowTreeCreation', flatRowTreeCreationMethod);
};
exports.useGridRowsPreProcessors = useGridRowsPreProcessors;

View File

@@ -0,0 +1,142 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridScroll = void 0;
var React = _interopRequireWildcard(require("react"));
var _styles = require("@mui/material/styles");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _useGridSelector = require("../../utils/useGridSelector");
var _gridPaginationSelector = require("../pagination/gridPaginationSelector");
var _gridRowsSelector = require("../rows/gridRowsSelector");
var _gridRowsMetaSelector = require("../rows/gridRowsMetaSelector");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _gridFilterSelector = require("../filter/gridFilterSelector");
var _gridClasses = require("../../../constants/gridClasses");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
// Logic copied from https://www.w3.org/TR/wai-aria-practices/examples/listbox/js/listbox.js
// Similar to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
function scrollIntoView(dimensions) {
const {
clientHeight,
scrollTop,
offsetHeight,
offsetTop
} = dimensions;
const elementBottom = offsetTop + offsetHeight;
// Always scroll to top when cell is higher than viewport to avoid scroll jump
// See https://github.com/mui/mui-x/issues/4513 and https://github.com/mui/mui-x/issues/4514
if (offsetHeight > clientHeight) {
return offsetTop;
}
if (elementBottom - clientHeight > scrollTop) {
return elementBottom - clientHeight;
}
if (offsetTop < scrollTop) {
return offsetTop;
}
return undefined;
}
/**
* @requires useGridPagination (state) - can be after, async only
* @requires useGridColumns (state) - can be after, async only
* @requires useGridRows (state) - can be after, async only
* @requires useGridRowsMeta (state) - can be after, async only
* @requires useGridFilter (state)
* @requires useGridColumnSpanning (method)
*/
const useGridScroll = (apiRef, props) => {
const theme = (0, _styles.useTheme)();
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridScroll');
const colRef = apiRef.current.columnHeadersElementRef;
const virtualScrollerRef = apiRef.current.virtualScrollerRef;
const visibleSortedRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridFilterSelector.gridExpandedSortedRowEntriesSelector);
const scrollToIndexes = React.useCallback(params => {
const totalRowCount = (0, _gridRowsSelector.gridRowCountSelector)(apiRef);
const visibleColumns = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef);
const scrollToHeader = params.rowIndex == null;
if (!scrollToHeader && totalRowCount === 0 || visibleColumns.length === 0) {
return false;
}
logger.debug(`Scrolling to cell at row ${params.rowIndex}, col: ${params.colIndex} `);
let scrollCoordinates = {};
if (params.colIndex != null) {
const columnPositions = (0, _gridColumnsSelector.gridColumnPositionsSelector)(apiRef);
let cellWidth;
if (typeof params.rowIndex !== 'undefined') {
const rowId = visibleSortedRows[params.rowIndex]?.id;
const cellColSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowId, params.colIndex);
if (cellColSpanInfo && !cellColSpanInfo.spannedByColSpan) {
cellWidth = cellColSpanInfo.cellProps.width;
}
}
if (typeof cellWidth === 'undefined') {
cellWidth = visibleColumns[params.colIndex].computedWidth;
}
// When using RTL, `scrollLeft` becomes negative, so we must ensure that we only compare values.
scrollCoordinates.left = scrollIntoView({
clientHeight: virtualScrollerRef.current.clientWidth,
scrollTop: Math.abs(virtualScrollerRef.current.scrollLeft),
offsetHeight: cellWidth,
offsetTop: columnPositions[params.colIndex]
});
}
if (params.rowIndex != null) {
const rowsMeta = (0, _gridRowsMetaSelector.gridRowsMetaSelector)(apiRef.current.state);
const page = (0, _gridPaginationSelector.gridPageSelector)(apiRef);
const pageSize = (0, _gridPaginationSelector.gridPageSizeSelector)(apiRef);
const elementIndex = !props.pagination ? params.rowIndex : params.rowIndex - page * pageSize;
const targetOffsetHeight = rowsMeta.positions[elementIndex + 1] ? rowsMeta.positions[elementIndex + 1] - rowsMeta.positions[elementIndex] : rowsMeta.currentPageTotalHeight - rowsMeta.positions[elementIndex];
const topPinnedRowsHeight = virtualScrollerRef.current.querySelector(`.${_gridClasses.gridClasses['pinnedRows--top']}`)?.clientHeight || 0;
const bottomPinnedRowsHeight = virtualScrollerRef.current.querySelector(`.${_gridClasses.gridClasses['pinnedRows--bottom']}`)?.clientHeight || 0;
scrollCoordinates.top = scrollIntoView({
clientHeight: virtualScrollerRef.current.clientHeight - topPinnedRowsHeight - bottomPinnedRowsHeight,
scrollTop: virtualScrollerRef.current.scrollTop,
offsetHeight: targetOffsetHeight,
offsetTop: rowsMeta.positions[elementIndex]
});
}
scrollCoordinates = apiRef.current.unstable_applyPipeProcessors('scrollToIndexes', scrollCoordinates, params);
if (typeof scrollCoordinates.left !== undefined || typeof scrollCoordinates.top !== undefined) {
apiRef.current.scroll(scrollCoordinates);
return true;
}
return false;
}, [logger, apiRef, virtualScrollerRef, props.pagination, visibleSortedRows]);
const scroll = React.useCallback(params => {
if (virtualScrollerRef.current && params.left != null && colRef.current) {
const direction = theme.direction === 'rtl' ? -1 : 1;
colRef.current.scrollLeft = params.left;
virtualScrollerRef.current.scrollLeft = direction * params.left;
logger.debug(`Scrolling left: ${params.left}`);
}
if (virtualScrollerRef.current && params.top != null) {
virtualScrollerRef.current.scrollTop = params.top;
logger.debug(`Scrolling top: ${params.top}`);
}
logger.debug(`Scrolling, updating container, and viewport`);
}, [virtualScrollerRef, theme.direction, colRef, logger]);
const getScrollPosition = React.useCallback(() => {
if (!virtualScrollerRef?.current) {
return {
top: 0,
left: 0
};
}
return {
top: virtualScrollerRef.current.scrollTop,
left: virtualScrollerRef.current.scrollLeft
};
}, [virtualScrollerRef]);
const scrollApi = {
scroll,
scrollToIndexes,
getScrollPosition
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, scrollApi, 'public');
};
exports.useGridScroll = useGridScroll;

View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridSortedRowIdsSelector = exports.gridSortedRowEntriesSelector = exports.gridSortModelSelector = exports.gridSortColumnLookupSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
var _gridRowsSelector = require("../rows/gridRowsSelector");
/**
* @category Sorting
* @ignore - do not document.
*/
const gridSortingStateSelector = state => state.sorting;
/**
* Get the id of the rows after the sorting process.
* @category Sorting
*/
const gridSortedRowIdsSelector = exports.gridSortedRowIdsSelector = (0, _createSelector.createSelector)(gridSortingStateSelector, sortingState => sortingState.sortedRows);
/**
* Get the id and the model of the rows after the sorting process.
* @category Sorting
*/
const gridSortedRowEntriesSelector = exports.gridSortedRowEntriesSelector = (0, _createSelector.createSelectorMemoized)(gridSortedRowIdsSelector, _gridRowsSelector.gridRowsLookupSelector,
// TODO rows v6: Is this the best approach ?
(sortedIds, idRowsLookup) => sortedIds.map(id => ({
id,
model: idRowsLookup[id] ?? {}
})));
/**
* Get the current sorting model.
* @category Sorting
*/
const gridSortModelSelector = exports.gridSortModelSelector = (0, _createSelector.createSelector)(gridSortingStateSelector, sorting => sorting.sortModel);
/**
* @category Sorting
* @ignore - do not document.
*/
const gridSortColumnLookupSelector = exports.gridSortColumnLookupSelector = (0, _createSelector.createSelectorMemoized)(gridSortModelSelector, sortModel => {
const result = sortModel.reduce((res, sortItem, index) => {
res[sortItem.field] = {
sortDirection: sortItem.sort,
sortIndex: sortModel.length > 1 ? index + 1 : undefined
};
return res;
}, {});
return result;
});

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,142 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.sanitizeSortModel = exports.mergeStateWithSortModel = exports.gridStringOrNumberComparator = exports.gridNumberComparator = exports.gridDateComparator = exports.getNextGridSortDirection = exports.buildAggregatedSortingApplier = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _warning = require("../../../utils/warning");
const sortModelDisableMultiColumnsSortingWarning = (0, _warning.buildWarning)(['MUI: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the `DataGrid`, this prop is always `true`.'], 'error');
const sanitizeSortModel = (model, disableMultipleColumnsSorting) => {
if (disableMultipleColumnsSorting && model.length > 1) {
sortModelDisableMultiColumnsSortingWarning();
return [model[0]];
}
return model;
};
exports.sanitizeSortModel = sanitizeSortModel;
const mergeStateWithSortModel = (sortModel, disableMultipleColumnsSorting) => state => (0, _extends2.default)({}, state, {
sorting: (0, _extends2.default)({}, state.sorting, {
sortModel: sanitizeSortModel(sortModel, disableMultipleColumnsSorting)
})
});
exports.mergeStateWithSortModel = mergeStateWithSortModel;
const isDesc = direction => direction === 'desc';
/**
* Transform an item of the sorting model into a method comparing two rows.
* @param {GridSortItem} sortItem The sort item we want to apply.
* @param {React.MutableRefObject<GridApiCommunity>} apiRef The API of the grid.
* @returns {GridParsedSortItem | null} The parsed sort item. Returns `null` is the sort item is not valid.
*/
const parseSortItem = (sortItem, apiRef) => {
const column = apiRef.current.getColumn(sortItem.field);
if (!column) {
return null;
}
const comparator = isDesc(sortItem.sort) ? (...args) => -1 * column.sortComparator(...args) : column.sortComparator;
const getSortCellParams = id => ({
id,
field: column.field,
rowNode: apiRef.current.getRowNode(id),
value: apiRef.current.getCellValue(id, column.field),
api: apiRef.current
});
return {
getSortCellParams,
comparator
};
};
/**
* Compare two rows according to a list of valid sort items.
* The `row1Params` and `row2Params` must have the same length as `parsedSortItems`,
* and each of their index must contain the `GridSortCellParams` of the sort item with the same index.
* @param {GridParsedSortItem[]} parsedSortItems All the sort items with which we want to compare the rows.
* @param {GridRowAggregatedSortingParams} row1 The node and params of the 1st row for each sort item.
* @param {GridRowAggregatedSortingParams} row2 The node and params of the 2nd row for each sort item.
*/
const compareRows = (parsedSortItems, row1, row2) => {
return parsedSortItems.reduce((res, item, index) => {
if (res !== 0) {
// return the results of the first comparator which distinguish the two rows
return res;
}
const sortCellParams1 = row1.params[index];
const sortCellParams2 = row2.params[index];
res = item.comparator(sortCellParams1.value, sortCellParams2.value, sortCellParams1, sortCellParams2);
return res;
}, 0);
};
/**
* Generates a method to easily sort a list of rows according to the current sort model.
* @param {GridSortModel} sortModel The model with which we want to sort the rows.
* @param {React.MutableRefObject<GridApiCommunity>} apiRef The API of the grid.
* @returns {GridSortingModelApplier | null} A method that generates a list of sorted row ids from a list of rows according to the current sort model. If `null`, we consider that the rows should remain in the order there were provided.
*/
const buildAggregatedSortingApplier = (sortModel, apiRef) => {
const comparatorList = sortModel.map(item => parseSortItem(item, apiRef)).filter(comparator => !!comparator);
if (comparatorList.length === 0) {
return null;
}
return rowList => rowList.map(node => ({
node,
params: comparatorList.map(el => el.getSortCellParams(node.id))
})).sort((a, b) => compareRows(comparatorList, a, b)).map(row => row.node.id);
};
exports.buildAggregatedSortingApplier = buildAggregatedSortingApplier;
const getNextGridSortDirection = (sortingOrder, current) => {
const currentIdx = sortingOrder.indexOf(current);
if (!current || currentIdx === -1 || currentIdx + 1 === sortingOrder.length) {
return sortingOrder[0];
}
return sortingOrder[currentIdx + 1];
};
exports.getNextGridSortDirection = getNextGridSortDirection;
const gridNillComparator = (v1, v2) => {
if (v1 == null && v2 != null) {
return -1;
}
if (v2 == null && v1 != null) {
return 1;
}
if (v1 == null && v2 == null) {
return 0;
}
return null;
};
const collator = new Intl.Collator();
const gridStringOrNumberComparator = (value1, value2) => {
const nillResult = gridNillComparator(value1, value2);
if (nillResult !== null) {
return nillResult;
}
if (typeof value1 === 'string') {
return collator.compare(value1.toString(), value2.toString());
}
return value1 - value2;
};
exports.gridStringOrNumberComparator = gridStringOrNumberComparator;
const gridNumberComparator = (value1, value2) => {
const nillResult = gridNillComparator(value1, value2);
if (nillResult !== null) {
return nillResult;
}
return Number(value1) - Number(value2);
};
exports.gridNumberComparator = gridNumberComparator;
const gridDateComparator = (value1, value2) => {
const nillResult = gridNillComparator(value1, value2);
if (nillResult !== null) {
return nillResult;
}
if (value1 > value2) {
return 1;
}
if (value1 < value2) {
return -1;
}
return 0;
};
exports.gridDateComparator = gridDateComparator;

View File

@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _exportNames = {
gridDateComparator: true,
gridNumberComparator: true,
gridStringOrNumberComparator: true
};
Object.defineProperty(exports, "gridDateComparator", {
enumerable: true,
get: function () {
return _gridSortingUtils.gridDateComparator;
}
});
Object.defineProperty(exports, "gridNumberComparator", {
enumerable: true,
get: function () {
return _gridSortingUtils.gridNumberComparator;
}
});
Object.defineProperty(exports, "gridStringOrNumberComparator", {
enumerable: true,
get: function () {
return _gridSortingUtils.gridStringOrNumberComparator;
}
});
var _gridSortingSelector = require("./gridSortingSelector");
Object.keys(_gridSortingSelector).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _gridSortingSelector[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridSortingSelector[key];
}
});
});
var _gridSortingUtils = require("./gridSortingUtils");

View File

@@ -0,0 +1,258 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridSorting = exports.sortingStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _utils = require("@mui/utils");
var _keyboardUtils = require("../../../utils/keyboardUtils");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridColumnsSelector = require("../columns/gridColumnsSelector");
var _gridSortingSelector = require("./gridSortingSelector");
var _rows = require("../rows");
var _useFirstRender = require("../../utils/useFirstRender");
var _strategyProcessing = require("../../core/strategyProcessing");
var _gridSortingUtils = require("./gridSortingUtils");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridRowsUtils = require("../rows/gridRowsUtils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const sortingStateInitializer = (state, props) => {
const sortModel = props.sortModel ?? props.initialState?.sorting?.sortModel ?? [];
return (0, _extends2.default)({}, state, {
sorting: {
sortModel: (0, _gridSortingUtils.sanitizeSortModel)(sortModel, props.disableMultipleColumnsSorting),
sortedRows: []
}
});
};
/**
* @requires useGridRows (event)
* @requires useGridColumns (event)
*/
exports.sortingStateInitializer = sortingStateInitializer;
const useGridSorting = (apiRef, props) => {
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridSorting');
apiRef.current.registerControlState({
stateId: 'sortModel',
propModel: props.sortModel,
propOnChange: props.onSortModelChange,
stateSelector: _gridSortingSelector.gridSortModelSelector,
changeEvent: 'sortModelChange'
});
const upsertSortModel = React.useCallback((field, sortItem) => {
const sortModel = (0, _gridSortingSelector.gridSortModelSelector)(apiRef);
const existingIdx = sortModel.findIndex(c => c.field === field);
let newSortModel = [...sortModel];
if (existingIdx > -1) {
if (!sortItem) {
newSortModel.splice(existingIdx, 1);
} else {
newSortModel.splice(existingIdx, 1, sortItem);
}
} else {
newSortModel = [...sortModel, sortItem];
}
return newSortModel;
}, [apiRef]);
const createSortItem = React.useCallback((col, directionOverride) => {
const sortModel = (0, _gridSortingSelector.gridSortModelSelector)(apiRef);
const existing = sortModel.find(c => c.field === col.field);
if (existing) {
const nextSort = directionOverride === undefined ? (0, _gridSortingUtils.getNextGridSortDirection)(col.sortingOrder ?? props.sortingOrder, existing.sort) : directionOverride;
return nextSort == null ? undefined : (0, _extends2.default)({}, existing, {
sort: nextSort
});
}
return {
field: col.field,
sort: directionOverride === undefined ? (0, _gridSortingUtils.getNextGridSortDirection)(col.sortingOrder ?? props.sortingOrder) : directionOverride
};
}, [apiRef, props.sortingOrder]);
const addColumnMenuItem = React.useCallback((columnMenuItems, colDef) => {
if (colDef == null || colDef.sortable === false) {
return columnMenuItems;
}
const sortingOrder = colDef.sortingOrder || props.sortingOrder;
if (sortingOrder.some(item => !!item)) {
return [...columnMenuItems, 'columnMenuSortItem'];
}
return columnMenuItems;
}, [props.sortingOrder]);
/**
* API METHODS
*/
const applySorting = React.useCallback(() => {
apiRef.current.setState(state => {
if (props.sortingMode === 'server') {
logger.debug('Skipping sorting rows as sortingMode = server');
return (0, _extends2.default)({}, state, {
sorting: (0, _extends2.default)({}, state.sorting, {
sortedRows: (0, _gridRowsUtils.getTreeNodeDescendants)((0, _rows.gridRowTreeSelector)(apiRef), _rows.GRID_ROOT_GROUP_ID, false)
})
});
}
const sortModel = (0, _gridSortingSelector.gridSortModelSelector)(state, apiRef.current.instanceId);
const sortRowList = (0, _gridSortingUtils.buildAggregatedSortingApplier)(sortModel, apiRef);
const sortedRows = apiRef.current.applyStrategyProcessor('sorting', {
sortRowList
});
return (0, _extends2.default)({}, state, {
sorting: (0, _extends2.default)({}, state.sorting, {
sortedRows
})
});
});
apiRef.current.publishEvent('sortedRowsSet');
apiRef.current.forceUpdate();
}, [apiRef, logger, props.sortingMode]);
const setSortModel = React.useCallback(model => {
const currentModel = (0, _gridSortingSelector.gridSortModelSelector)(apiRef);
if (currentModel !== model) {
logger.debug(`Setting sort model`);
apiRef.current.setState((0, _gridSortingUtils.mergeStateWithSortModel)(model, props.disableMultipleColumnsSorting));
apiRef.current.forceUpdate();
apiRef.current.applySorting();
}
}, [apiRef, logger, props.disableMultipleColumnsSorting]);
const sortColumn = React.useCallback((column, direction, allowMultipleSorting) => {
if (!column.sortable) {
return;
}
const sortItem = createSortItem(column, direction);
let sortModel;
if (!allowMultipleSorting || props.disableMultipleColumnsSorting) {
sortModel = !sortItem ? [] : [sortItem];
} else {
sortModel = upsertSortModel(column.field, sortItem);
}
apiRef.current.setSortModel(sortModel);
}, [apiRef, upsertSortModel, createSortItem, props.disableMultipleColumnsSorting]);
const getSortModel = React.useCallback(() => (0, _gridSortingSelector.gridSortModelSelector)(apiRef), [apiRef]);
const getSortedRows = React.useCallback(() => {
const sortedRows = (0, _gridSortingSelector.gridSortedRowEntriesSelector)(apiRef);
return sortedRows.map(row => row.model);
}, [apiRef]);
const getSortedRowIds = React.useCallback(() => (0, _gridSortingSelector.gridSortedRowIdsSelector)(apiRef), [apiRef]);
const getRowIdFromRowIndex = React.useCallback(index => apiRef.current.getSortedRowIds()[index], [apiRef]);
const sortApi = {
getSortModel,
getSortedRows,
getSortedRowIds,
getRowIdFromRowIndex,
setSortModel,
sortColumn,
applySorting
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, sortApi, 'public');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const sortModelToExport = (0, _gridSortingSelector.gridSortModelSelector)(apiRef);
const shouldExportSortModel =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the model is controlled
props.sortModel != null ||
// Always export if the model has been initialized
props.initialState?.sorting?.sortModel != null ||
// Export if the model is not empty
sortModelToExport.length > 0;
if (!shouldExportSortModel) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
sorting: {
sortModel: sortModelToExport
}
});
}, [apiRef, props.sortModel, props.initialState?.sorting?.sortModel]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const sortModel = context.stateToRestore.sorting?.sortModel;
if (sortModel == null) {
return params;
}
apiRef.current.setState((0, _gridSortingUtils.mergeStateWithSortModel)(sortModel, props.disableMultipleColumnsSorting));
return (0, _extends2.default)({}, params, {
callbacks: [...params.callbacks, apiRef.current.applySorting]
});
}, [apiRef, props.disableMultipleColumnsSorting]);
const flatSortingMethod = React.useCallback(params => {
const rowTree = (0, _rows.gridRowTreeSelector)(apiRef);
const rootGroupNode = rowTree[_rows.GRID_ROOT_GROUP_ID];
const sortedChildren = params.sortRowList ? params.sortRowList(rootGroupNode.children.map(childId => rowTree[childId])) : [...rootGroupNode.children];
if (rootGroupNode.footerId != null) {
sortedChildren.push(rootGroupNode.footerId);
}
return sortedChildren;
}, [apiRef]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
(0, _strategyProcessing.useGridRegisterStrategyProcessor)(apiRef, _strategyProcessing.GRID_DEFAULT_STRATEGY, 'sorting', flatSortingMethod);
/**
* EVENTS
*/
const handleColumnHeaderClick = React.useCallback(({
colDef
}, event) => {
const allowMultipleSorting = event.shiftKey || event.metaKey || event.ctrlKey;
sortColumn(colDef, undefined, allowMultipleSorting);
}, [sortColumn]);
const handleColumnHeaderKeyDown = React.useCallback(({
colDef
}, event) => {
// Ctrl + Enter opens the column menu
if ((0, _keyboardUtils.isEnterKey)(event.key) && !event.ctrlKey && !event.metaKey) {
sortColumn(colDef, undefined, event.shiftKey);
}
}, [sortColumn]);
const handleColumnsChange = React.useCallback(() => {
// When the columns change we check that the sorted columns are still part of the dataset
const sortModel = (0, _gridSortingSelector.gridSortModelSelector)(apiRef);
const latestColumns = (0, _gridColumnsSelector.gridColumnLookupSelector)(apiRef);
if (sortModel.length > 0) {
const newModel = sortModel.filter(sortItem => latestColumns[sortItem.field]);
if (newModel.length < sortModel.length) {
apiRef.current.setSortModel(newModel);
}
}
}, [apiRef]);
const handleStrategyProcessorChange = React.useCallback(methodName => {
if (methodName === 'sorting') {
apiRef.current.applySorting();
}
}, [apiRef]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'columnMenu', addColumnMenuItem);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderClick', handleColumnHeaderClick);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderKeyDown', handleColumnHeaderKeyDown);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowsSet', apiRef.current.applySorting);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnsChange', handleColumnsChange);
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'activeStrategyProcessorChange', handleStrategyProcessorChange);
/**
* 1ST RENDER
*/
(0, _useFirstRender.useFirstRender)(() => {
apiRef.current.applySorting();
});
/**
* EFFECTS
*/
(0, _utils.unstable_useEnhancedEffect)(() => {
if (props.sortModel !== undefined) {
apiRef.current.setSortModel(props.sortModel);
}
}, [apiRef, props.sortModel]);
};
exports.useGridSorting = useGridSorting;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridStatePersistence = void 0;
var React = _interopRequireWildcard(require("react"));
var _utils = require("../../utils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const useGridStatePersistence = apiRef => {
const exportState = React.useCallback((params = {}) => {
const stateToExport = apiRef.current.unstable_applyPipeProcessors('exportState', {}, params);
return stateToExport;
}, [apiRef]);
const restoreState = React.useCallback(stateToRestore => {
const response = apiRef.current.unstable_applyPipeProcessors('restoreState', {
callbacks: []
}, {
stateToRestore
});
response.callbacks.forEach(callback => {
callback();
});
apiRef.current.forceUpdate();
}, [apiRef]);
const statePersistenceApi = {
exportState,
restoreState
};
(0, _utils.useGridApiMethod)(apiRef, statePersistenceApi, 'public');
};
exports.useGridStatePersistence = useGridStatePersistence;

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gridVirtualizationSelector = exports.gridVirtualizationEnabledSelector = exports.gridVirtualizationColumnEnabledSelector = void 0;
var _createSelector = require("../../../utils/createSelector");
/**
* Get the columns state
* @category Virtualization
*/
const gridVirtualizationSelector = state => state.virtualization;
/**
* Get the enabled state for virtualization
* @category Virtualization
*/
exports.gridVirtualizationSelector = gridVirtualizationSelector;
const gridVirtualizationEnabledSelector = exports.gridVirtualizationEnabledSelector = (0, _createSelector.createSelector)(gridVirtualizationSelector, state => state.enabled);
/**
* Get the enabled state for virtualization
* @category Virtualization
*/
const gridVirtualizationColumnEnabledSelector = exports.gridVirtualizationColumnEnabledSelector = (0, _createSelector.createSelector)(gridVirtualizationSelector, state => state.enabledForColumns);

View File

@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _useGridVirtualization = require("./useGridVirtualization");
Object.keys(_useGridVirtualization).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _useGridVirtualization[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _useGridVirtualization[key];
}
});
});
var _gridVirtualizationSelectors = require("./gridVirtualizationSelectors");
Object.keys(_gridVirtualizationSelectors).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _gridVirtualizationSelectors[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _gridVirtualizationSelectors[key];
}
});
});

Some files were not shown because too many files have changed in this diff Show More