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,19 @@
/// <reference types="react" />
import type { GridCsvExportOptions, GridRowId } from '../../../../models';
import type { GridCellParams } from '../../../../models/params/gridCellParams';
import type { GridStateColDef } from '../../../../models/colDef/gridColDef';
import type { GridApiCommunity } from '../../../../models/api/gridApiCommunity';
export declare const serializeCellValue: (cellParams: GridCellParams, options: {
csvOptions: CSVOptions;
ignoreValueFormatter: boolean;
}) => any;
type CSVOptions = Required<Pick<GridCsvExportOptions, 'delimiter' | 'shouldAppendQuotes' | 'escapeFormulas'>>;
interface BuildCSVOptions {
columns: GridStateColDef[];
rowIds: GridRowId[];
csvOptions: Required<Pick<GridCsvExportOptions, 'delimiter' | 'includeColumnGroupsHeaders' | 'includeHeaders' | 'shouldAppendQuotes' | 'escapeFormulas'>>;
ignoreValueFormatter: boolean;
apiRef: React.MutableRefObject<GridApiCommunity>;
}
export declare function buildCSV(options: BuildCSVOptions): string;
export {};

View File

@@ -0,0 +1,148 @@
import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../../colDef';
import { buildWarning } from '../../../../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;
}
export const serializeCellValue = (cellParams, options) => {
const {
csvOptions,
ignoreValueFormatter
} = options;
let value;
if (ignoreValueFormatter) {
var _cellParams$value2;
const columnType = cellParams.colDef.type;
if (columnType === 'number') {
value = String(cellParams.value);
} else if (columnType === 'date' || columnType === 'dateTime') {
var _cellParams$value;
value = (_cellParams$value = cellParams.value) == null ? void 0 : _cellParams$value.toISOString();
} else if (typeof ((_cellParams$value2 = cellParams.value) == null ? void 0 : _cellParams$value2.toString) === 'function') {
value = cellParams.value.toString();
} else {
value = cellParams.value;
}
} else {
value = cellParams.formattedValue;
}
return sanitizeCellValue(value, csvOptions);
};
const objectFormattedValueWarning = 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();
};
export 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 !== 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,11 @@
import * as React from 'react';
import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
import type { DataGridProcessedProps } from '../../../models/props/DataGridProps';
/**
* @requires useGridColumns (state)
* @requires useGridFilter (state)
* @requires useGridSorting (state)
* @requires useGridSelection (state)
* @requires useGridParamsApi (method)
*/
export declare const useGridCsvExport: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'unstable_ignoreValueFormatterDuringExport'>) => void;

View File

@@ -0,0 +1,76 @@
import * as React from 'react';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { useGridLogger } from '../../utils/useGridLogger';
import { exportAs } from '../../../utils/exportAs';
import { buildCSV } from './serializers/csvSerializer';
import { getColumnsToExport, defaultGetRowsToExport } from './utils';
import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
import { GridCsvExportMenuItem } from '../../../components/toolbar/GridToolbarExport';
import { jsx as _jsx } from "react/jsx-runtime";
/**
* @requires useGridColumns (state)
* @requires useGridFilter (state)
* @requires useGridSorting (state)
* @requires useGridSelection (state)
* @requires useGridParamsApi (method)
*/
export const useGridCsvExport = (apiRef, props) => {
const logger = useGridLogger(apiRef, 'useGridCsvExport');
const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp == null ? void 0 : ignoreValueFormatterProp.csvExport : ignoreValueFormatterProp) || false;
const getDataAsCsv = React.useCallback((options = {}) => {
var _options$getRowsToExp, _options$shouldAppend, _options$includeHeade, _options$includeColum, _options$escapeFormul;
logger.debug(`Get data as CSV`);
const exportedColumns = getColumnsToExport({
apiRef,
options
});
const getRowsToExport = (_options$getRowsToExp = options.getRowsToExport) != null ? _options$getRowsToExp : defaultGetRowsToExport;
const exportedRowIds = getRowsToExport({
apiRef
});
return buildCSV({
columns: exportedColumns,
rowIds: exportedRowIds,
csvOptions: {
delimiter: options.delimiter || ',',
shouldAppendQuotes: (_options$shouldAppend = options.shouldAppendQuotes) != null ? _options$shouldAppend : true,
includeHeaders: (_options$includeHeade = options.includeHeaders) != null ? _options$includeHeade : true,
includeColumnGroupsHeaders: (_options$includeColum = options.includeColumnGroupsHeaders) != null ? _options$includeColum : true,
escapeFormulas: (_options$escapeFormul = options.escapeFormulas) != null ? _options$escapeFormul : 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 != null && options.utf8WithBom ? new Uint8Array([0xef, 0xbb, 0xbf]) : '', csv], {
type: 'text/csv'
});
exportAs(blob, 'csv', options == null ? void 0 : options.fileName);
}, [logger, getDataAsCsv]);
const csvExportApi = {
getDataAsCsv,
exportDataAsCsv
};
useGridApiMethod(apiRef, csvExportApi, 'public');
/**
* PRE-PROCESSING
*/
const addExportMenuButtons = React.useCallback((initialValue, options) => {
var _options$csvOptions;
if ((_options$csvOptions = options.csvOptions) != null && _options$csvOptions.disableToolbarButton) {
return initialValue;
}
return [...initialValue, {
component: /*#__PURE__*/_jsx(GridCsvExportMenuItem, {
options: options.csvOptions
}),
componentName: 'csvExport'
}];
}, []);
useGridRegisterPipeProcessor(apiRef, 'exportMenu', addExportMenuButtons);
};

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
/**
* @requires useGridColumns (state)
* @requires useGridFilter (state)
* @requires useGridSorting (state)
* @requires useGridParamsApi (method)
*/
export declare const useGridPrintExport: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'pagination' | 'columnHeaderHeight'>) => void;

View File

@@ -0,0 +1,285 @@
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import { unstable_ownerDocument as ownerDocument } from '@mui/utils';
import { useGridLogger } from '../../utils/useGridLogger';
import { gridExpandedRowCountSelector } from '../filter/gridFilterSelector';
import { gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector } from '../columns/gridColumnsSelector';
import { gridClasses } from '../../../constants/gridClasses';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector';
import { getColumnsToExport } from './utils';
import { getDerivedPaginationModel } from '../pagination/useGridPaginationModel';
import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
import { GridPrintExportMenuItem } from '../../../components/toolbar/GridToolbarExport';
import { getTotalHeaderHeight } from '../columns/gridColumnsUtils';
import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../colDef/gridCheckboxSelectionColDef';
import { gridDataRowIdsSelector, gridRowsLookupSelector } from '../rows/gridRowsSelector';
import { jsx as _jsx } from "react/jsx-runtime";
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)
*/
export const useGridPrintExport = (apiRef, props) => {
const logger = 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 = 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 = getColumnsToExport({
apiRef,
options: {
fields,
allColumns
}
}).map(column => column.field);
const columns = gridColumnDefinitionsSelector(apiRef);
const newColumnVisibilityModel = {};
columns.forEach(column => {
newColumnVisibilityModel[column.field] = exportedColumnFields.includes(column.field);
});
if (includeCheckboxes) {
newColumnVisibilityModel[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) => {
var _querySelector, _querySelector2;
const normalizeOptions = _extends({
copyStyles: true,
hideToolbar: false,
hideFooter: false,
includeCheckboxes: false
}, options);
const printDoc = printWindow.contentDocument;
if (!printDoc) {
return;
}
const rowsMeta = 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.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.columnHeaders}`);
const columnHeadersInner = columnHeaders.querySelector(`.${gridClasses.columnHeadersInner}`);
columnHeadersInner.style.width = '100%';
let gridToolbarElementHeight = ((_querySelector = gridRootElement.querySelector(`.${gridClasses.toolbarContainer}`)) == null ? void 0 : _querySelector.offsetHeight) || 0;
let gridFooterElementHeight = ((_querySelector2 = gridRootElement.querySelector(`.${gridClasses.footerContainer}`)) == null ? void 0 : _querySelector2.offsetHeight) || 0;
if (normalizeOptions.hideToolbar) {
var _gridClone$querySelec;
(_gridClone$querySelec = gridClone.querySelector(`.${gridClasses.toolbarContainer}`)) == null || _gridClone$querySelec.remove();
gridToolbarElementHeight = 0;
}
if (normalizeOptions.hideFooter) {
var _gridClone$querySelec2;
(_gridClone$querySelec2 = gridClone.querySelector(`.${gridClasses.footerContainer}`)) == null || _gridClone$querySelec2.remove();
gridFooterElementHeight = 0;
}
// Expand container height to accommodate all rows
const computedTotalHeight = rowsMeta.currentPageTotalHeight + 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 != null && options.getRowsToExport) {
const gridFooterElement = gridClone.querySelector(`.${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 => {
var _previousGridState$cu;
// Remove the print iframe
doc.current.body.removeChild(printWindow);
// Revert grid to previous state
apiRef.current.restoreState(previousGridState.current || {});
if (!((_previousGridState$cu = previousGridState.current) != null && (_previousGridState$cu = _previousGridState$cu.columns) != null && _previousGridState$cu.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 = gridColumnVisibilityModelSelector(apiRef);
const gridRowsLookup = gridRowsLookupSelector(apiRef);
previousRows.current = gridDataRowIdsSelector(apiRef).map(rowId => gridRowsLookup[rowId]);
if (props.pagination) {
const visibleRowCount = gridExpandedRowCountSelector(apiRef);
const paginationModel = {
page: 0,
pageSize: visibleRowCount
};
apiRef.current.setState(state => _extends({}, state, {
pagination: _extends({}, state.pagination, {
paginationModel: getDerivedPaginationModel(state.pagination,
// Using signature `DataGridPro` to allow more than 100 rows in the print export
'DataGridPro', paginationModel)
})
}));
apiRef.current.forceUpdate();
}
await updateGridColumnsForPrint(options == null ? void 0 : options.fields, options == null ? void 0 : options.allColumns, options == null ? void 0 : options.includeCheckboxes);
if (options != null && options.getRowsToExport) {
updateGridRowsForPrint(options.getRowsToExport);
}
apiRef.current.unstable_setVirtualization(false);
await raf(); // wait for the state changes to take action
const printWindow = buildPrintWindow(options == null ? void 0 : 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
};
useGridApiMethod(apiRef, printExportApi, 'public');
/**
* PRE-PROCESSING
*/
const addExportMenuButtons = React.useCallback((initialValue, options) => {
var _options$printOptions;
if ((_options$printOptions = options.printOptions) != null && _options$printOptions.disableToolbarButton) {
return initialValue;
}
return [...initialValue, {
component: /*#__PURE__*/_jsx(GridPrintExportMenuItem, {
options: options.printOptions
}),
componentName: 'printExport'
}];
}, []);
useGridRegisterPipeProcessor(apiRef, 'exportMenu', addExportMenuButtons);
};

View File

@@ -0,0 +1,15 @@
import * as React from 'react';
import { GridApiCommunity } from '../../../models/api/gridApiCommunity';
import { GridExportOptions, GridCsvGetRowsToExportParams } from '../../../models/gridExport';
import { GridStateColDef } from '../../../models/colDef/gridColDef';
import { GridRowId } from '../../../models';
interface GridGetColumnsToExportParams {
/**
* The API of the grid.
*/
apiRef: React.MutableRefObject<GridApiCommunity>;
options: GridExportOptions;
}
export declare const getColumnsToExport: ({ apiRef, options, }: GridGetColumnsToExportParams) => GridStateColDef[];
export declare const defaultGetRowsToExport: ({ apiRef }: GridCsvGetRowsToExportParams) => GridRowId[];
export {};

View File

@@ -0,0 +1,38 @@
import { gridColumnDefinitionsSelector, gridVisibleColumnDefinitionsSelector } from '../columns';
import { gridFilteredSortedRowIdsSelector } from '../filter';
import { gridPinnedRowsSelector, gridRowTreeSelector } from '../rows/gridRowsSelector';
export const getColumnsToExport = ({
apiRef,
options
}) => {
const 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 : gridVisibleColumnDefinitionsSelector(apiRef);
return validColumns.filter(column => !column.disableExport);
};
export const defaultGetRowsToExport = ({
apiRef
}) => {
var _pinnedRows$top, _pinnedRows$bottom;
const filteredSortedRowIds = gridFilteredSortedRowIdsSelector(apiRef);
const rowTree = gridRowTreeSelector(apiRef);
const selectedRows = apiRef.current.getSelectedRows();
const bodyRows = filteredSortedRowIds.filter(id => rowTree[id].type !== 'footer');
const pinnedRows = gridPinnedRowsSelector(apiRef);
const topPinnedRowsIds = (pinnedRows == null || (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.map(row => row.id)) || [];
const bottomPinnedRowsIds = (pinnedRows == null || (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _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;
};