@mui/x-data-grid-pro
Version:
The Pro plan edition of the MUI X Data Grid components.
203 lines (200 loc) • 8.62 kB
JavaScript
"use strict";
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridDetailPanel = exports.detailPanelStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _xDataGrid = require("@mui/x-data-grid");
var _internals = require("@mui/x-data-grid/internals");
var _gridDetailPanelToggleColDef = require("./gridDetailPanelToggleColDef");
var _gridDetailPanelSelector = require("./gridDetailPanelSelector");
const emptySet = new Set();
const detailPanelStateInitializer = (state, props) => {
return (0, _extends2.default)({}, state, {
detailPanel: {
heightCache: {},
expandedRowIds: props.detailPanelExpandedRowIds ?? props.initialState?.detailPanel?.expandedRowIds ?? emptySet
}
});
};
exports.detailPanelStateInitializer = detailPanelStateInitializer;
function cacheContentAndHeight(apiRef, getDetailPanelContent, getDetailPanelHeight, previousHeightCache) {
if (typeof getDetailPanelContent !== 'function') {
return {};
}
// TODO change to lazy approach using a Proxy
// only call getDetailPanelContent when asked for an id
const rowIds = (0, _xDataGrid.gridDataRowIdsSelector)(apiRef);
const contentCache = {};
const heightCache = {};
for (let i = 0; i < rowIds.length; i += 1) {
const id = rowIds[i];
const params = apiRef.current.getRowParams(id);
const content = getDetailPanelContent(params);
contentCache[id] = content;
if (content == null) {
continue;
}
const height = getDetailPanelHeight(params);
const autoHeight = height === 'auto';
heightCache[id] = {
autoHeight,
height: autoHeight ? previousHeightCache[id]?.height : height
};
}
return {
contentCache,
heightCache
};
}
const useGridDetailPanel = (apiRef, props) => {
const contentCache = (0, _xDataGrid.useGridSelector)(apiRef, _gridDetailPanelSelector.gridDetailPanelExpandedRowsContentCacheSelector);
const handleCellClick = React.useCallback((params, event) => {
if (params.field !== _gridDetailPanelToggleColDef.GRID_DETAIL_PANEL_TOGGLE_FIELD || props.getDetailPanelContent == null) {
return;
}
const content = contentCache[params.id];
if (! /*#__PURE__*/React.isValidElement(content)) {
return;
}
// Ignore if the user didn't click specifically in the "i" button
if (event.target === event.currentTarget) {
return;
}
apiRef.current.toggleDetailPanel(params.id);
}, [apiRef, contentCache, props.getDetailPanelContent]);
const handleCellKeyDown = React.useCallback((params, event) => {
if (props.getDetailPanelContent == null) {
return;
}
if (params.field === _gridDetailPanelToggleColDef.GRID_DETAIL_PANEL_TOGGLE_FIELD && event.key === ' ') {
apiRef.current.toggleDetailPanel(params.id);
}
}, [apiRef, props.getDetailPanelContent]);
(0, _xDataGrid.useGridEvent)(apiRef, 'cellClick', handleCellClick);
(0, _xDataGrid.useGridEvent)(apiRef, 'cellKeyDown', handleCellKeyDown);
apiRef.current.registerControlState({
stateId: 'detailPanels',
propModel: props.detailPanelExpandedRowIds,
propOnChange: props.onDetailPanelExpandedRowIdsChange,
stateSelector: _gridDetailPanelSelector.gridDetailPanelExpandedRowIdsSelector,
changeEvent: 'detailPanelsExpandedRowIdsChange'
});
const toggleDetailPanel = React.useCallback(id => {
if (props.getDetailPanelContent == null) {
return;
}
const content = contentCache[id];
if (! /*#__PURE__*/React.isValidElement(content)) {
return;
}
const ids = apiRef.current.getExpandedDetailPanels();
const newIds = new Set(ids);
if (ids.has(id)) {
newIds.delete(id);
} else {
newIds.add(id);
}
apiRef.current.setExpandedDetailPanels(newIds);
}, [apiRef, contentCache, props.getDetailPanelContent]);
const getExpandedDetailPanels = React.useCallback(() => (0, _gridDetailPanelSelector.gridDetailPanelExpandedRowIdsSelector)(apiRef), [apiRef]);
const setExpandedDetailPanels = React.useCallback(ids => {
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
detailPanel: (0, _extends2.default)({}, state.detailPanel, {
expandedRowIds: ids
})
});
});
apiRef.current.requestPipeProcessorsApplication('rowHeight');
}, [apiRef]);
const storeDetailPanelHeight = React.useCallback((id, height) => {
const heightCache = (0, _gridDetailPanelSelector.gridDetailPanelRawHeightCacheSelector)(apiRef);
if (!heightCache[id] || heightCache[id].height === height) {
return;
}
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
detailPanel: (0, _extends2.default)({}, state.detailPanel, {
heightCache: (0, _extends2.default)({}, heightCache, {
[id]: (0, _extends2.default)({}, heightCache[id], {
height
})
})
})
});
});
apiRef.current.requestPipeProcessorsApplication('rowHeight');
}, [apiRef]);
const detailPanelPubicApi = {
toggleDetailPanel,
getExpandedDetailPanels,
setExpandedDetailPanels
};
const detailPanelPrivateApi = {
storeDetailPanelHeight
};
(0, _xDataGrid.useGridApiMethod)(apiRef, detailPanelPubicApi, 'public');
(0, _xDataGrid.useGridApiMethod)(apiRef, detailPanelPrivateApi, 'private');
React.useEffect(() => {
if (props.detailPanelExpandedRowIds) {
const currentModel = (0, _gridDetailPanelSelector.gridDetailPanelExpandedRowIdsSelector)(apiRef);
if (currentModel !== props.detailPanelExpandedRowIds) {
apiRef.current.setExpandedDetailPanels(props.detailPanelExpandedRowIds);
}
}
}, [apiRef, props.detailPanelExpandedRowIds]);
const updateCaches = React.useCallback(() => {
if (!props.getDetailPanelContent) {
return;
}
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
detailPanel: (0, _extends2.default)({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight, state.detailPanel.heightCache))
});
});
}, [apiRef, props.getDetailPanelContent, props.getDetailPanelHeight]);
(0, _xDataGrid.useGridEvent)(apiRef, 'sortedRowsSet', updateCaches);
const previousGetDetailPanelContentProp = React.useRef(undefined);
const previousGetDetailPanelHeightProp = React.useRef(undefined);
const updateCachesIfNeeded = React.useCallback(() => {
if (props.getDetailPanelContent === previousGetDetailPanelContentProp.current && props.getDetailPanelHeight === previousGetDetailPanelHeightProp.current) {
return;
}
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
detailPanel: (0, _extends2.default)({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight, state.detailPanel.heightCache))
});
});
previousGetDetailPanelContentProp.current = props.getDetailPanelContent;
previousGetDetailPanelHeightProp.current = props.getDetailPanelHeight;
}, [apiRef, props.getDetailPanelContent, props.getDetailPanelHeight]);
const addDetailHeight = React.useCallback((initialValue, row) => {
const expandedRowIds = (0, _gridDetailPanelSelector.gridDetailPanelExpandedRowIdsSelector)(apiRef);
if (!expandedRowIds || !expandedRowIds.has(row.id)) {
initialValue.detail = 0;
return initialValue;
}
updateCachesIfNeeded();
const heightCache = (0, _gridDetailPanelSelector.gridDetailPanelRawHeightCacheSelector)(apiRef);
initialValue.detail = heightCache[row.id]?.height ?? 0; // Fallback to zero because the cache might not be ready yet (for example page was changed)
return initialValue;
}, [apiRef, updateCachesIfNeeded]);
const enabled = props.getDetailPanelContent !== undefined;
(0, _internals.useGridRegisterPipeProcessor)(apiRef, 'rowHeight', addDetailHeight, enabled);
const isFirstRender = React.useRef(true);
if (isFirstRender.current) {
updateCachesIfNeeded();
}
React.useEffect(() => {
if (!isFirstRender.current) {
updateCachesIfNeeded();
}
isFirstRender.current = false;
}, [apiRef, updateCachesIfNeeded]);
};
exports.useGridDetailPanel = useGridDetailPanel;