@mui/x-data-grid 6.9.1 → 6.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +287 -107
- package/DataGrid/DataGrid.js +5 -1
- package/README.md +1 -1
- package/components/GridPagination.js +16 -3
- package/components/cell/GridEditDateCell.js +1 -1
- package/components/cell/GridEditInputCell.js +3 -3
- package/components/toolbar/GridToolbarQuickFilter.d.ts +1 -1
- package/components/toolbar/GridToolbarQuickFilter.js +12 -9
- package/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/hooks/core/useGridApiInitialization.d.ts +1 -0
- package/hooks/core/useGridApiInitialization.js +59 -36
- package/hooks/features/columns/gridColumnsUtils.js +2 -1
- package/hooks/features/dimensions/useGridDimensions.js +3 -3
- package/hooks/features/editing/useGridEditing.js +2 -1
- package/hooks/features/export/serializers/csvSerializer.d.ts +9 -6
- package/hooks/features/export/serializers/csvSerializer.js +78 -15
- package/hooks/features/export/useGridCsvExport.js +4 -3
- package/hooks/features/filter/gridFilterUtils.js +6 -5
- package/hooks/features/filter/useGridFilter.js +14 -2
- package/hooks/features/rows/gridRowsUtils.js +1 -1
- package/hooks/features/rows/useGridParamsApi.js +4 -4
- package/hooks/utils/useGridApiMethod.js +7 -23
- package/index.js +1 -1
- package/internals/index.d.ts +1 -0
- package/internals/index.js +1 -0
- package/joy/joySlots.js +17 -5
- package/legacy/DataGrid/DataGrid.js +5 -1
- package/legacy/components/GridPagination.js +16 -3
- package/legacy/components/cell/GridEditDateCell.js +1 -1
- package/legacy/components/cell/GridEditInputCell.js +3 -3
- package/legacy/components/toolbar/GridToolbarQuickFilter.js +12 -12
- package/legacy/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/legacy/hooks/core/useGridApiInitialization.js +62 -39
- package/legacy/hooks/features/columns/gridColumnsUtils.js +4 -1
- package/legacy/hooks/features/dimensions/useGridDimensions.js +3 -3
- package/legacy/hooks/features/editing/useGridEditing.js +2 -1
- package/legacy/hooks/features/export/serializers/csvSerializer.js +84 -11
- package/legacy/hooks/features/export/useGridCsvExport.js +4 -3
- package/legacy/hooks/features/filter/gridFilterUtils.js +6 -5
- package/legacy/hooks/features/filter/useGridFilter.js +12 -2
- package/legacy/hooks/features/rows/gridRowsUtils.js +1 -1
- package/legacy/hooks/features/rows/useGridParamsApi.js +4 -4
- package/legacy/hooks/utils/useGridApiMethod.js +7 -25
- package/legacy/index.js +1 -1
- package/legacy/internals/index.js +1 -0
- package/legacy/joy/joySlots.js +17 -5
- package/legacy/locales/esES.js +3 -3
- package/legacy/locales/plPL.js +7 -7
- package/locales/esES.js +3 -3
- package/locales/plPL.js +7 -7
- package/models/api/gridEditingApi.d.ts +1 -1
- package/models/events/gridEventLookup.d.ts +0 -1
- package/models/gridExport.d.ts +8 -1
- package/models/gridFilterModel.d.ts +5 -0
- package/models/props/DataGridProps.d.ts +4 -1
- package/modern/DataGrid/DataGrid.js +5 -1
- package/modern/components/GridPagination.js +16 -2
- package/modern/components/cell/GridEditDateCell.js +1 -1
- package/modern/components/cell/GridEditInputCell.js +3 -3
- package/modern/components/toolbar/GridToolbarQuickFilter.js +12 -9
- package/modern/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/modern/hooks/core/useGridApiInitialization.js +58 -36
- package/modern/hooks/features/columns/gridColumnsUtils.js +2 -1
- package/modern/hooks/features/dimensions/useGridDimensions.js +3 -3
- package/modern/hooks/features/editing/useGridEditing.js +1 -1
- package/modern/hooks/features/export/serializers/csvSerializer.js +78 -15
- package/modern/hooks/features/export/useGridCsvExport.js +3 -2
- package/modern/hooks/features/filter/gridFilterUtils.js +3 -2
- package/modern/hooks/features/filter/useGridFilter.js +14 -2
- package/modern/hooks/features/rows/gridRowsUtils.js +1 -1
- package/modern/hooks/features/rows/useGridParamsApi.js +1 -1
- package/modern/hooks/utils/useGridApiMethod.js +7 -23
- package/modern/index.js +1 -1
- package/modern/internals/index.js +1 -0
- package/modern/joy/joySlots.js +17 -4
- package/modern/locales/esES.js +3 -3
- package/modern/locales/plPL.js +7 -7
- package/node/DataGrid/DataGrid.js +5 -1
- package/node/components/GridPagination.js +16 -2
- package/node/components/cell/GridEditDateCell.js +1 -1
- package/node/components/cell/GridEditInputCell.js +3 -3
- package/node/components/toolbar/GridToolbarQuickFilter.js +12 -9
- package/node/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/node/hooks/core/useGridApiInitialization.js +59 -36
- package/node/hooks/features/columns/gridColumnsUtils.js +2 -1
- package/node/hooks/features/dimensions/useGridDimensions.js +3 -3
- package/node/hooks/features/editing/useGridEditing.js +1 -1
- package/node/hooks/features/export/serializers/csvSerializer.js +78 -15
- package/node/hooks/features/export/useGridCsvExport.js +3 -2
- package/node/hooks/features/filter/gridFilterUtils.js +2 -1
- package/node/hooks/features/filter/useGridFilter.js +14 -2
- package/node/hooks/features/rows/gridRowsUtils.js +1 -1
- package/node/hooks/features/rows/useGridParamsApi.js +1 -1
- package/node/hooks/utils/useGridApiMethod.js +7 -23
- package/node/index.js +1 -1
- package/node/internals/index.js +8 -0
- package/node/joy/joySlots.js +17 -4
- package/node/locales/esES.js +3 -3
- package/node/locales/plPL.js +7 -7
- package/package.json +1 -1
package/DataGrid/DataGrid.js
CHANGED
|
@@ -181,6 +181,7 @@ DataGridRaw.propTypes = {
|
|
|
181
181
|
value: PropTypes.any
|
|
182
182
|
})).isRequired,
|
|
183
183
|
logicOperator: PropTypes.oneOf(['and', 'or']),
|
|
184
|
+
quickFilterExcludeHiddenColumns: PropTypes.bool,
|
|
184
185
|
quickFilterLogicOperator: PropTypes.oneOf(['and', 'or']),
|
|
185
186
|
quickFilterValues: PropTypes.array
|
|
186
187
|
}),
|
|
@@ -513,7 +514,10 @@ DataGridRaw.propTypes = {
|
|
|
513
514
|
* Select the pageSize dynamically using the component UI.
|
|
514
515
|
* @default [25, 50, 100]
|
|
515
516
|
*/
|
|
516
|
-
pageSizeOptions: PropTypes.arrayOf(PropTypes.number
|
|
517
|
+
pageSizeOptions: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
|
|
518
|
+
label: PropTypes.string.isRequired,
|
|
519
|
+
value: PropTypes.number.isRequired
|
|
520
|
+
})]).isRequired),
|
|
517
521
|
pagination: props => {
|
|
518
522
|
if (props.pagination === false) {
|
|
519
523
|
return new Error(['MUI: `<DataGrid pagination={false} />` is not a valid prop.', 'Infinite scrolling is not available in the MIT version.', '', 'You need to upgrade to DataGridPro or DataGridPremium component to disable the pagination.'].join('\n'));
|
package/README.md
CHANGED
|
@@ -25,7 +25,6 @@ const GridPaginationRoot = styled(TablePagination)(({
|
|
|
25
25
|
}
|
|
26
26
|
}));
|
|
27
27
|
export const GridPagination = /*#__PURE__*/React.forwardRef(function GridPagination(props, ref) {
|
|
28
|
-
var _rootProps$pageSizeOp;
|
|
29
28
|
const apiRef = useGridApiContext();
|
|
30
29
|
const rootProps = useGridRootProps();
|
|
31
30
|
const paginationModel = useGridSelector(apiRef, gridPaginationModelSelector);
|
|
@@ -42,22 +41,36 @@ export const GridPagination = /*#__PURE__*/React.forwardRef(function GridPaginat
|
|
|
42
41
|
const handlePageChange = React.useCallback((_, page) => {
|
|
43
42
|
apiRef.current.setPage(page);
|
|
44
43
|
}, [apiRef]);
|
|
44
|
+
const isPageSizeIncludedInPageSizeOptions = pageSize => {
|
|
45
|
+
for (let i = 0; i < rootProps.pageSizeOptions.length; i += 1) {
|
|
46
|
+
const option = rootProps.pageSizeOptions[i];
|
|
47
|
+
if (typeof option === 'number') {
|
|
48
|
+
if (option === pageSize) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
} else if (option.value === pageSize) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
};
|
|
45
57
|
if (process.env.NODE_ENV !== 'production') {
|
|
46
58
|
var _rootProps$pagination, _rootProps$pagination2;
|
|
47
59
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
48
60
|
const warnedOnceMissingInPageSizeOptions = React.useRef(false);
|
|
49
61
|
const pageSize = (_rootProps$pagination = (_rootProps$pagination2 = rootProps.paginationModel) == null ? void 0 : _rootProps$pagination2.pageSize) != null ? _rootProps$pagination : paginationModel.pageSize;
|
|
50
|
-
if (!warnedOnceMissingInPageSizeOptions.current && !rootProps.autoPageSize && !
|
|
62
|
+
if (!warnedOnceMissingInPageSizeOptions.current && !rootProps.autoPageSize && !isPageSizeIncludedInPageSizeOptions(pageSize)) {
|
|
51
63
|
console.warn([`MUI: The page size \`${paginationModel.pageSize}\` is not preset in the \`pageSizeOptions\``, `Add it to show the pagination select.`].join('\n'));
|
|
52
64
|
warnedOnceMissingInPageSizeOptions.current = true;
|
|
53
65
|
}
|
|
54
66
|
}
|
|
67
|
+
const pageSizeOptions = isPageSizeIncludedInPageSizeOptions(paginationModel.pageSize) ? rootProps.pageSizeOptions : [];
|
|
55
68
|
return /*#__PURE__*/_jsx(GridPaginationRoot, _extends({
|
|
56
69
|
ref: ref,
|
|
57
70
|
component: "div",
|
|
58
71
|
count: rowCount,
|
|
59
72
|
page: paginationModel.page <= lastPage ? paginationModel.page : lastPage,
|
|
60
|
-
rowsPerPageOptions:
|
|
73
|
+
rowsPerPageOptions: pageSizeOptions,
|
|
61
74
|
rowsPerPage: paginationModel.pageSize,
|
|
62
75
|
onPageChange: handlePageChange,
|
|
63
76
|
onRowsPerPageChange: handlePageSizeChange
|
|
@@ -112,7 +112,7 @@ function GridEditDateCell(props) {
|
|
|
112
112
|
const meta = apiRef.current.unstable_getEditCellMeta(id, field);
|
|
113
113
|
const handleInputRef = el => {
|
|
114
114
|
inputRef.current = el;
|
|
115
|
-
if (meta.unstable_updateValueOnRender && !hasUpdatedEditValueOnMount.current) {
|
|
115
|
+
if (meta != null && meta.unstable_updateValueOnRender && !hasUpdatedEditValueOnMount.current) {
|
|
116
116
|
const inputValue = inputRef.current.value;
|
|
117
117
|
const parsedDate = parseValueToDate(inputValue);
|
|
118
118
|
setValueState({
|
|
@@ -68,12 +68,12 @@ const GridEditInputCell = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
68
68
|
unstable_skipValueParser: true
|
|
69
69
|
}, event);
|
|
70
70
|
}, [apiRef, debounceMs, field, id, onValueChange]);
|
|
71
|
-
const meta = apiRef.current.unstable_getEditCellMeta
|
|
71
|
+
const meta = apiRef.current.unstable_getEditCellMeta(id, field);
|
|
72
72
|
React.useEffect(() => {
|
|
73
|
-
if (meta.changeReason !== 'debouncedSetEditCellValue') {
|
|
73
|
+
if ((meta == null ? void 0 : meta.changeReason) !== 'debouncedSetEditCellValue') {
|
|
74
74
|
setValueState(value);
|
|
75
75
|
}
|
|
76
|
-
}, [meta
|
|
76
|
+
}, [meta, value]);
|
|
77
77
|
useEnhancedEffect(() => {
|
|
78
78
|
if (hasFocus) {
|
|
79
79
|
inputRef.current.focus();
|
|
@@ -13,7 +13,7 @@ export type GridToolbarQuickFilterProps = TextFieldProps & {
|
|
|
13
13
|
* @param {any[]} values The new values passed to the quick filter model
|
|
14
14
|
* @returns {string} The string to display in the text field
|
|
15
15
|
*/
|
|
16
|
-
quickFilterFormatter?: (values: GridFilterModel['quickFilterValues']) => string;
|
|
16
|
+
quickFilterFormatter?: (values: NonNullable<GridFilterModel['quickFilterValues']>) => string;
|
|
17
17
|
/**
|
|
18
18
|
* The debounce time in milliseconds.
|
|
19
19
|
* @default 500
|
|
@@ -56,18 +56,20 @@ function GridToolbarQuickFilter(props) {
|
|
|
56
56
|
const rootProps = useGridRootProps();
|
|
57
57
|
const quickFilterValues = useGridSelector(apiRef, gridQuickFilterValuesSelector);
|
|
58
58
|
const [searchValue, setSearchValue] = React.useState(() => quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []));
|
|
59
|
-
const
|
|
59
|
+
const prevQuickFilterValuesRef = React.useRef(quickFilterValues);
|
|
60
60
|
React.useEffect(() => {
|
|
61
|
-
if (!isDeepEqual(
|
|
61
|
+
if (!isDeepEqual(prevQuickFilterValuesRef.current, quickFilterValues)) {
|
|
62
62
|
// The model of quick filter value has been updated
|
|
63
|
-
|
|
63
|
+
prevQuickFilterValuesRef.current = quickFilterValues;
|
|
64
64
|
|
|
65
65
|
// Update the input value if needed to match the new model
|
|
66
66
|
setSearchValue(prevSearchValue => isDeepEqual(quickFilterParser(prevSearchValue), quickFilterValues) ? prevSearchValue : quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []));
|
|
67
67
|
}
|
|
68
|
-
}, [
|
|
68
|
+
}, [quickFilterValues, quickFilterFormatter, quickFilterParser]);
|
|
69
69
|
const updateSearchValue = React.useCallback(newSearchValue => {
|
|
70
|
-
|
|
70
|
+
const newQuickFilterValues = quickFilterParser(newSearchValue);
|
|
71
|
+
prevQuickFilterValuesRef.current = newQuickFilterValues;
|
|
72
|
+
apiRef.current.setQuickFilterValues(newQuickFilterValues);
|
|
71
73
|
}, [apiRef, quickFilterParser]);
|
|
72
74
|
const debouncedUpdateSearchValue = React.useMemo(() => debounce(updateSearchValue, debounceMs), [updateSearchValue, debounceMs]);
|
|
73
75
|
const handleSearchValueChange = React.useCallback(event => {
|
|
@@ -87,8 +89,9 @@ function GridToolbarQuickFilter(props) {
|
|
|
87
89
|
onChange: handleSearchValueChange,
|
|
88
90
|
placeholder: apiRef.current.getLocaleText('toolbarQuickFilterPlaceholder'),
|
|
89
91
|
"aria-label": apiRef.current.getLocaleText('toolbarQuickFilterLabel'),
|
|
90
|
-
type: "search"
|
|
91
|
-
|
|
92
|
+
type: "search"
|
|
93
|
+
}, other, {
|
|
94
|
+
InputProps: _extends({
|
|
92
95
|
startAdornment: /*#__PURE__*/_jsx(rootProps.slots.quickFilterIcon, {
|
|
93
96
|
fontSize: "small"
|
|
94
97
|
}),
|
|
@@ -104,8 +107,8 @@ function GridToolbarQuickFilter(props) {
|
|
|
104
107
|
fontSize: "small"
|
|
105
108
|
})
|
|
106
109
|
}))
|
|
107
|
-
}
|
|
108
|
-
},
|
|
110
|
+
}, other.InputProps)
|
|
111
|
+
}, (_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseTextField));
|
|
109
112
|
}
|
|
110
113
|
process.env.NODE_ENV !== "production" ? GridToolbarQuickFilter.propTypes = {
|
|
111
114
|
// ----------------------------- Warning --------------------------------
|
|
@@ -33,13 +33,16 @@ import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
|
33
33
|
*/
|
|
34
34
|
export const useGridPipeProcessing = apiRef => {
|
|
35
35
|
const processorsCache = React.useRef({});
|
|
36
|
+
const isRunning = React.useRef(false);
|
|
36
37
|
const runAppliers = React.useCallback(groupCache => {
|
|
37
|
-
if (!groupCache) {
|
|
38
|
+
if (isRunning.current || !groupCache) {
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
41
|
+
isRunning.current = true;
|
|
40
42
|
Object.values(groupCache.appliers).forEach(callback => {
|
|
41
43
|
callback();
|
|
42
44
|
});
|
|
45
|
+
isRunning.current = false;
|
|
43
46
|
}, []);
|
|
44
47
|
const registerPipeProcessor = React.useCallback((group, id, processor) => {
|
|
45
48
|
if (!processorsCache.current[group]) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { DataGridProcessedProps } from '../../models/props/DataGridProps';
|
|
3
3
|
import type { GridApiCommon, GridPrivateApiCommon } from '../../models/api/gridApiCommon';
|
|
4
|
+
export declare function unwrapPrivateAPI<PrivateApi extends GridPrivateApiCommon, Api extends GridApiCommon>(publicApi: Api): PrivateApi;
|
|
4
5
|
export declare function useGridApiInitialization<PrivateApi extends GridPrivateApiCommon, Api extends GridApiCommon>(inputApiRef: React.MutableRefObject<Api> | undefined, props: Pick<DataGridProcessedProps, 'signature'>): React.MutableRefObject<PrivateApi>;
|
|
@@ -3,58 +3,80 @@ import { Store } from '../../utils/Store';
|
|
|
3
3
|
import { useGridApiMethod } from '../utils/useGridApiMethod';
|
|
4
4
|
import { GridSignature } from '../utils/useGridApiEventHandler';
|
|
5
5
|
import { EventManager } from '../../utils/EventManager';
|
|
6
|
+
const SYMBOL_API_PRIVATE = Symbol('mui.api_private');
|
|
6
7
|
const isSyntheticEvent = event => {
|
|
7
8
|
return event.isPropagationStopped !== undefined;
|
|
8
9
|
};
|
|
10
|
+
export function unwrapPrivateAPI(publicApi) {
|
|
11
|
+
return publicApi[SYMBOL_API_PRIVATE];
|
|
12
|
+
}
|
|
9
13
|
let globalId = 0;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
function createPrivateAPI(publicApiRef) {
|
|
15
|
+
var _publicApiRef$current;
|
|
16
|
+
const existingPrivateApi = (_publicApiRef$current = publicApiRef.current) == null ? void 0 : _publicApiRef$current[SYMBOL_API_PRIVATE];
|
|
17
|
+
if (existingPrivateApi) {
|
|
18
|
+
return existingPrivateApi;
|
|
19
|
+
}
|
|
20
|
+
const state = {};
|
|
21
|
+
const privateApi = {
|
|
22
|
+
state,
|
|
23
|
+
store: Store.create(state),
|
|
24
|
+
instanceId: {
|
|
25
|
+
id: globalId
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
globalId += 1;
|
|
29
|
+
privateApi.getPublicApi = () => publicApiRef.current;
|
|
30
|
+
privateApi.register = (visibility, methods) => {
|
|
14
31
|
Object.keys(methods).forEach(methodName => {
|
|
15
|
-
|
|
16
|
-
|
|
32
|
+
const method = methods[methodName];
|
|
33
|
+
const currentPrivateMethod = privateApi[methodName];
|
|
34
|
+
if ((currentPrivateMethod == null ? void 0 : currentPrivateMethod.spying) === true) {
|
|
35
|
+
currentPrivateMethod.target = method;
|
|
17
36
|
} else {
|
|
18
|
-
|
|
37
|
+
privateApi[methodName] = method;
|
|
38
|
+
}
|
|
39
|
+
if (visibility === 'public') {
|
|
40
|
+
const publicApi = publicApiRef.current;
|
|
41
|
+
const currentPublicMethod = publicApi[methodName];
|
|
42
|
+
if ((currentPublicMethod == null ? void 0 : currentPublicMethod.spying) === true) {
|
|
43
|
+
currentPublicMethod.target = method;
|
|
44
|
+
} else {
|
|
45
|
+
publicApi[methodName] = method;
|
|
46
|
+
}
|
|
19
47
|
}
|
|
20
48
|
});
|
|
21
49
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
50
|
+
privateApi.register('private', {
|
|
51
|
+
caches: {},
|
|
52
|
+
eventManager: new EventManager()
|
|
53
|
+
});
|
|
54
|
+
return privateApi;
|
|
55
|
+
}
|
|
56
|
+
function createPublicAPI(privateApiRef) {
|
|
57
|
+
const publicApi = {
|
|
58
|
+
get state() {
|
|
59
|
+
return privateApiRef.current.state;
|
|
28
60
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
61
|
+
get store() {
|
|
62
|
+
return privateApiRef.current.store;
|
|
63
|
+
},
|
|
64
|
+
get instanceId() {
|
|
65
|
+
return privateApiRef.current.instanceId;
|
|
66
|
+
},
|
|
67
|
+
[SYMBOL_API_PRIVATE]: privateApiRef.current
|
|
33
68
|
};
|
|
34
|
-
return
|
|
35
|
-
}
|
|
69
|
+
return publicApi;
|
|
70
|
+
}
|
|
36
71
|
export function useGridApiInitialization(inputApiRef, props) {
|
|
37
72
|
const publicApiRef = React.useRef();
|
|
38
|
-
if (!publicApiRef.current) {
|
|
39
|
-
const state = {};
|
|
40
|
-
publicApiRef.current = {
|
|
41
|
-
state,
|
|
42
|
-
store: Store.create(state),
|
|
43
|
-
instanceId: {
|
|
44
|
-
id: globalId
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
globalId += 1;
|
|
48
|
-
}
|
|
49
73
|
const privateApiRef = React.useRef();
|
|
50
74
|
if (!privateApiRef.current) {
|
|
51
|
-
privateApiRef.current =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
75
|
+
privateApiRef.current = createPrivateAPI(publicApiRef);
|
|
76
|
+
}
|
|
77
|
+
if (!publicApiRef.current) {
|
|
78
|
+
publicApiRef.current = createPublicAPI(privateApiRef);
|
|
56
79
|
}
|
|
57
|
-
React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
|
|
58
80
|
const publishEvent = React.useCallback((...args) => {
|
|
59
81
|
const [name, params, event = {}] = args;
|
|
60
82
|
event.defaultMuiPrevented = false;
|
|
@@ -77,6 +99,7 @@ export function useGridApiInitialization(inputApiRef, props) {
|
|
|
77
99
|
subscribeEvent,
|
|
78
100
|
publishEvent
|
|
79
101
|
}, 'public');
|
|
102
|
+
React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
|
|
80
103
|
React.useEffect(() => {
|
|
81
104
|
const api = privateApiRef.current;
|
|
82
105
|
return () => {
|
|
@@ -15,6 +15,7 @@ export function computeFlexColumnsWidth({
|
|
|
15
15
|
totalFlexUnits,
|
|
16
16
|
flexColumns
|
|
17
17
|
}) {
|
|
18
|
+
const uniqueFlexColumns = new Set(flexColumns.map(col => col.field));
|
|
18
19
|
const flexColumnsLookup = {
|
|
19
20
|
all: {},
|
|
20
21
|
frozenFields: [],
|
|
@@ -30,7 +31,7 @@ export function computeFlexColumnsWidth({
|
|
|
30
31
|
// Step 5 of https://drafts.csswg.org/css-flexbox-1/#resolve-flexible-lengths
|
|
31
32
|
function loopOverFlexItems() {
|
|
32
33
|
// 5a: If all the flex items on the line are frozen, free space has been distributed.
|
|
33
|
-
if (flexColumnsLookup.frozenFields.length ===
|
|
34
|
+
if (flexColumnsLookup.frozenFields.length === uniqueFlexColumns.size) {
|
|
34
35
|
return;
|
|
35
36
|
}
|
|
36
37
|
const violationsLookup = {
|
|
@@ -73,7 +73,7 @@ export function useGridDimensions(apiRef, props) {
|
|
|
73
73
|
let hasScrollY;
|
|
74
74
|
if (props.autoHeight) {
|
|
75
75
|
hasScrollY = false;
|
|
76
|
-
hasScrollX = columnsTotalWidth > rootDimensionsRef.current.width;
|
|
76
|
+
hasScrollX = Math.round(columnsTotalWidth) > Math.round(rootDimensionsRef.current.width);
|
|
77
77
|
viewportOuterSize = {
|
|
78
78
|
width: rootDimensionsRef.current.width,
|
|
79
79
|
height: rowsMeta.currentPageTotalHeight + (hasScrollX ? scrollBarSize : 0)
|
|
@@ -85,11 +85,11 @@ export function useGridDimensions(apiRef, props) {
|
|
|
85
85
|
};
|
|
86
86
|
const scrollInformation = hasScroll({
|
|
87
87
|
content: {
|
|
88
|
-
width: columnsTotalWidth,
|
|
88
|
+
width: Math.round(columnsTotalWidth),
|
|
89
89
|
height: rowsMeta.currentPageTotalHeight
|
|
90
90
|
},
|
|
91
91
|
container: {
|
|
92
|
-
width: viewportOuterSize.width,
|
|
92
|
+
width: Math.round(viewportOuterSize.width),
|
|
93
93
|
height: viewportOuterSize.height - pinnedRowsHeight.top - pinnedRowsHeight.bottom
|
|
94
94
|
},
|
|
95
95
|
scrollBarSize
|
|
@@ -106,8 +106,9 @@ export const useGridEditing = (apiRef, props) => {
|
|
|
106
106
|
return props.editMode === GridEditModes.Cell ? apiRef.current.getRowWithUpdatedValuesFromCellEditing(id, field) : apiRef.current.getRowWithUpdatedValuesFromRowEditing(id);
|
|
107
107
|
}, [apiRef, props.editMode]);
|
|
108
108
|
const getEditCellMeta = React.useCallback((id, field) => {
|
|
109
|
+
var _editingState$id$fiel, _editingState$id;
|
|
109
110
|
const editingState = gridEditRowsStateSelector(apiRef.current.state);
|
|
110
|
-
return editingState[id][field];
|
|
111
|
+
return (_editingState$id$fiel = (_editingState$id = editingState[id]) == null ? void 0 : _editingState$id[field]) != null ? _editingState$id$fiel : null;
|
|
111
112
|
}, [apiRef]);
|
|
112
113
|
const editingSharedApi = {
|
|
113
114
|
isCellEditable,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { GridCsvExportOptions, GridRowId } from '../../../../models';
|
|
3
|
+
import type { GridCellParams } from '../../../../models/params/gridCellParams';
|
|
4
|
+
import type { GridStateColDef } from '../../../../models/colDef/gridColDef';
|
|
5
|
+
import type { GridApiCommunity } from '../../../../models/api/gridApiCommunity';
|
|
4
6
|
export declare const serializeCellValue: (cellParams: GridCellParams, options: {
|
|
5
7
|
delimiterCharacter: string;
|
|
6
8
|
ignoreValueFormatter: boolean;
|
|
@@ -8,10 +10,11 @@ export declare const serializeCellValue: (cellParams: GridCellParams, options: {
|
|
|
8
10
|
interface BuildCSVOptions {
|
|
9
11
|
columns: GridStateColDef[];
|
|
10
12
|
rowIds: GridRowId[];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
delimiterCharacter: NonNullable<GridCsvExportOptions['delimiter']>;
|
|
14
|
+
includeHeaders: NonNullable<GridCsvExportOptions['includeHeaders']>;
|
|
15
|
+
includeColumnGroupsHeaders: NonNullable<GridCsvExportOptions['includeColumnGroupsHeaders']>;
|
|
14
16
|
ignoreValueFormatter: boolean;
|
|
17
|
+
apiRef: React.MutableRefObject<GridApiCommunity>;
|
|
15
18
|
}
|
|
16
19
|
export declare function buildCSV(options: BuildCSVOptions): string;
|
|
17
20
|
export {};
|
|
@@ -37,43 +37,106 @@ export const serializeCellValue = (cellParams, options) => {
|
|
|
37
37
|
return sanitizeCellValue(value, delimiterCharacter);
|
|
38
38
|
};
|
|
39
39
|
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.']);
|
|
40
|
+
class CSVRow {
|
|
41
|
+
constructor(options) {
|
|
42
|
+
this.options = void 0;
|
|
43
|
+
this.rowString = '';
|
|
44
|
+
this.isEmpty = true;
|
|
45
|
+
this.options = options;
|
|
46
|
+
}
|
|
47
|
+
addValue(value) {
|
|
48
|
+
if (!this.isEmpty) {
|
|
49
|
+
this.rowString += this.options.delimiterCharacter;
|
|
50
|
+
}
|
|
51
|
+
if (value === null || value === undefined) {
|
|
52
|
+
this.rowString += '';
|
|
53
|
+
} else if (typeof this.options.sanitizeCellValue === 'function') {
|
|
54
|
+
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
|
|
55
|
+
} else {
|
|
56
|
+
this.rowString += value;
|
|
57
|
+
}
|
|
58
|
+
this.isEmpty = false;
|
|
59
|
+
}
|
|
60
|
+
getRowString() {
|
|
61
|
+
return this.rowString;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
40
64
|
const serializeRow = ({
|
|
41
65
|
id,
|
|
42
66
|
columns,
|
|
43
67
|
getCellParams,
|
|
44
68
|
delimiterCharacter,
|
|
45
69
|
ignoreValueFormatter
|
|
46
|
-
}) =>
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
}) => {
|
|
71
|
+
const row = new CSVRow({
|
|
72
|
+
delimiterCharacter
|
|
73
|
+
});
|
|
74
|
+
columns.forEach(column => {
|
|
75
|
+
const cellParams = getCellParams(id, column.field);
|
|
76
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
77
|
+
if (String(cellParams.formattedValue) === '[object Object]') {
|
|
78
|
+
objectFormattedValueWarning();
|
|
79
|
+
}
|
|
51
80
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
row.addValue(serializeCellValue(cellParams, {
|
|
82
|
+
delimiterCharacter,
|
|
83
|
+
ignoreValueFormatter
|
|
84
|
+
}));
|
|
56
85
|
});
|
|
57
|
-
|
|
86
|
+
return row.getRowString();
|
|
87
|
+
};
|
|
58
88
|
export function buildCSV(options) {
|
|
59
89
|
const {
|
|
60
90
|
columns,
|
|
61
91
|
rowIds,
|
|
62
|
-
getCellParams,
|
|
63
92
|
delimiterCharacter,
|
|
64
93
|
includeHeaders,
|
|
65
|
-
|
|
94
|
+
includeColumnGroupsHeaders,
|
|
95
|
+
ignoreValueFormatter,
|
|
96
|
+
apiRef
|
|
66
97
|
} = options;
|
|
67
98
|
const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
|
|
68
99
|
id,
|
|
69
100
|
columns,
|
|
70
|
-
getCellParams,
|
|
101
|
+
getCellParams: apiRef.current.getCellParams,
|
|
71
102
|
delimiterCharacter,
|
|
72
103
|
ignoreValueFormatter
|
|
73
|
-
})
|
|
104
|
+
})}\r\n`, '').trim();
|
|
74
105
|
if (!includeHeaders) {
|
|
75
106
|
return CSVBody;
|
|
76
107
|
}
|
|
77
|
-
const
|
|
108
|
+
const filteredColumns = columns.filter(column => column.field !== GRID_CHECKBOX_SELECTION_COL_DEF.field);
|
|
109
|
+
const headerRows = [];
|
|
110
|
+
if (includeColumnGroupsHeaders) {
|
|
111
|
+
const columnGroupLookup = apiRef.current.unstable_getAllGroupDetails();
|
|
112
|
+
let maxColumnGroupsDepth = 0;
|
|
113
|
+
const columnGroupPathsLookup = filteredColumns.reduce((acc, column) => {
|
|
114
|
+
const columnGroupPath = apiRef.current.unstable_getColumnGroupPath(column.field);
|
|
115
|
+
acc[column.field] = columnGroupPath;
|
|
116
|
+
maxColumnGroupsDepth = Math.max(maxColumnGroupsDepth, columnGroupPath.length);
|
|
117
|
+
return acc;
|
|
118
|
+
}, {});
|
|
119
|
+
for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
|
|
120
|
+
const headerGroupRow = new CSVRow({
|
|
121
|
+
delimiterCharacter,
|
|
122
|
+
sanitizeCellValue
|
|
123
|
+
});
|
|
124
|
+
headerRows.push(headerGroupRow);
|
|
125
|
+
filteredColumns.forEach(column => {
|
|
126
|
+
const columnGroupId = (columnGroupPathsLookup[column.field] || [])[i];
|
|
127
|
+
const columnGroup = columnGroupLookup[columnGroupId];
|
|
128
|
+
headerGroupRow.addValue(columnGroup ? columnGroup.headerName || columnGroup.groupId : '');
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const mainHeaderRow = new CSVRow({
|
|
133
|
+
delimiterCharacter,
|
|
134
|
+
sanitizeCellValue
|
|
135
|
+
});
|
|
136
|
+
filteredColumns.forEach(column => {
|
|
137
|
+
mainHeaderRow.addValue(column.headerName || column.field);
|
|
138
|
+
});
|
|
139
|
+
headerRows.push(mainHeaderRow);
|
|
140
|
+
const CSVHead = `${headerRows.map(row => row.getRowString()).join('\r\n')}\r\n`;
|
|
78
141
|
return `${CSVHead}${CSVBody}`.trim();
|
|
79
142
|
}
|
|
@@ -19,7 +19,7 @@ export const useGridCsvExport = (apiRef, props) => {
|
|
|
19
19
|
const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
|
|
20
20
|
const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp == null ? void 0 : ignoreValueFormatterProp.csvExport : ignoreValueFormatterProp) || false;
|
|
21
21
|
const getDataAsCsv = React.useCallback((options = {}) => {
|
|
22
|
-
var _options$getRowsToExp, _options$includeHeade;
|
|
22
|
+
var _options$getRowsToExp, _options$includeHeade, _options$includeColum;
|
|
23
23
|
logger.debug(`Get data as CSV`);
|
|
24
24
|
const exportedColumns = getColumnsToExport({
|
|
25
25
|
apiRef,
|
|
@@ -32,10 +32,11 @@ export const useGridCsvExport = (apiRef, props) => {
|
|
|
32
32
|
return buildCSV({
|
|
33
33
|
columns: exportedColumns,
|
|
34
34
|
rowIds: exportedRowIds,
|
|
35
|
-
getCellParams: apiRef.current.getCellParams,
|
|
36
35
|
delimiterCharacter: options.delimiter || ',',
|
|
37
36
|
includeHeaders: (_options$includeHeade = options.includeHeaders) != null ? _options$includeHeade : true,
|
|
38
|
-
|
|
37
|
+
includeColumnGroupsHeaders: (_options$includeColum = options.includeColumnGroupsHeaders) != null ? _options$includeColum : true,
|
|
38
|
+
ignoreValueFormatter,
|
|
39
|
+
apiRef
|
|
39
40
|
});
|
|
40
41
|
}, [logger, apiRef, ignoreValueFormatter]);
|
|
41
42
|
const exportDataAsCsv = React.useCallback(options => {
|
|
@@ -3,7 +3,7 @@ import { GridLogicOperator } from '../../../models';
|
|
|
3
3
|
import { GLOBAL_API_REF, isInternalFilter } from '../../../colDef/utils';
|
|
4
4
|
import { getDefaultGridFilterModel } from './gridFilterState';
|
|
5
5
|
import { buildWarning } from '../../../utils/warning';
|
|
6
|
-
import { gridColumnFieldsSelector, gridColumnLookupSelector } from '../columns';
|
|
6
|
+
import { gridColumnFieldsSelector, gridColumnLookupSelector, gridVisibleColumnFieldsSelector } from '../columns';
|
|
7
7
|
/**
|
|
8
8
|
* Adds default values to the optional fields of a filter items.
|
|
9
9
|
* @param {GridFilterItem} item The raw filter item.
|
|
@@ -154,12 +154,13 @@ export const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef)
|
|
|
154
154
|
* @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.
|
|
155
155
|
*/
|
|
156
156
|
export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
157
|
-
var _filterModel$quickFil, _filterModel$quickFil2;
|
|
157
|
+
var _filterModel$quickFil, _filterModel$quickFil2, _filterModel$quickFil3;
|
|
158
158
|
const quickFilterValues = (_filterModel$quickFil = (_filterModel$quickFil2 = filterModel.quickFilterValues) == null ? void 0 : _filterModel$quickFil2.filter(Boolean)) != null ? _filterModel$quickFil : [];
|
|
159
159
|
if (quickFilterValues.length === 0) {
|
|
160
160
|
return null;
|
|
161
161
|
}
|
|
162
|
-
const
|
|
162
|
+
const quickFilterExcludeHiddenColumns = (_filterModel$quickFil3 = filterModel.quickFilterExcludeHiddenColumns) != null ? _filterModel$quickFil3 : false;
|
|
163
|
+
const columnFields = quickFilterExcludeHiddenColumns ? gridVisibleColumnFieldsSelector(apiRef) : gridColumnFieldsSelector(apiRef);
|
|
163
164
|
const appliersPerField = [];
|
|
164
165
|
columnFields.forEach(field => {
|
|
165
166
|
const column = apiRef.current.getColumn(field);
|
|
@@ -276,12 +277,12 @@ export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, fil
|
|
|
276
277
|
|
|
277
278
|
// get result for quick filter model
|
|
278
279
|
if (cleanedQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) {
|
|
279
|
-
var _filterModel$
|
|
280
|
+
var _filterModel$quickFil4;
|
|
280
281
|
// Return true if the item pass with one of the rows
|
|
281
282
|
const quickFilterValuePredicate = value => {
|
|
282
283
|
return cleanedQuickFilterResults.some(quickFilterValueResult => quickFilterValueResult[value]);
|
|
283
284
|
};
|
|
284
|
-
const quickFilterLogicOperator = (_filterModel$
|
|
285
|
+
const quickFilterLogicOperator = (_filterModel$quickFil4 = filterModel.quickFilterLogicOperator) != null ? _filterModel$quickFil4 : getDefaultGridFilterModel().quickFilterLogicOperator;
|
|
285
286
|
if (quickFilterLogicOperator === GridLogicOperator.And) {
|
|
286
287
|
const passesAllQuickFilterValues = filterModel.quickFilterValues.every(quickFilterValuePredicate);
|
|
287
288
|
if (!passesAllQuickFilterValues) {
|
|
@@ -21,6 +21,7 @@ export const filterStateInitializer = (state, props, apiRef) => {
|
|
|
21
21
|
return _extends({}, state, {
|
|
22
22
|
filter: {
|
|
23
23
|
filterModel: sanitizeFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef),
|
|
24
|
+
filteredRowsLookup: {},
|
|
24
25
|
filteredDescendantCountLookup: {}
|
|
25
26
|
},
|
|
26
27
|
visibleRowsLookup: {}
|
|
@@ -258,6 +259,9 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
258
259
|
}, [props.slots.filterPanel, (_props$slotProps2 = props.slotProps) == null ? void 0 : _props$slotProps2.filterPanel]);
|
|
259
260
|
const dataRowIdToIdLookup = apiRef.current.state.rows.dataRowIdToModelLookup;
|
|
260
261
|
const rows = React.useMemo(() => Object.values(dataRowIdToIdLookup), [dataRowIdToIdLookup]);
|
|
262
|
+
const {
|
|
263
|
+
getRowId
|
|
264
|
+
} = props;
|
|
261
265
|
const flatFilteringMethod = React.useCallback(params => {
|
|
262
266
|
if (props.filterMode !== 'client' || !params.isRowMatchingFilters) {
|
|
263
267
|
return {
|
|
@@ -277,9 +281,10 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
277
281
|
};
|
|
278
282
|
for (let i = 0; i < rows.length; i += 1) {
|
|
279
283
|
const row = rows[i];
|
|
284
|
+
const id = getRowId ? getRowId(row) : row.id;
|
|
280
285
|
isRowMatchingFilters(row, undefined, result);
|
|
281
286
|
const isRowPassing = passFilterLogic([result.passingFilterItems], [result.passingQuickFilterValues], params.filterModel, apiRef, filterCache);
|
|
282
|
-
filteredRowsLookup[
|
|
287
|
+
filteredRowsLookup[id] = isRowPassing;
|
|
283
288
|
}
|
|
284
289
|
const footerId = 'auto-generated-group-footer-root';
|
|
285
290
|
const footer = dataRowIdToModelLookup[footerId];
|
|
@@ -290,7 +295,7 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
290
295
|
filteredRowsLookup,
|
|
291
296
|
filteredDescendantCountLookup: {}
|
|
292
297
|
};
|
|
293
|
-
}, [apiRef, props.filterMode,
|
|
298
|
+
}, [apiRef, rows, props.filterMode, getRowId]);
|
|
294
299
|
useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItem);
|
|
295
300
|
useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
|
|
296
301
|
useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
|
|
@@ -332,6 +337,13 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
332
337
|
useGridApiEventHandler(apiRef, 'columnsChange', handleColumnsChange);
|
|
333
338
|
useGridApiEventHandler(apiRef, 'activeStrategyProcessorChange', handleStrategyProcessorChange);
|
|
334
339
|
useGridApiEventHandler(apiRef, 'rowExpansionChange', updateVisibleRowsLookupState);
|
|
340
|
+
useGridApiEventHandler(apiRef, 'columnVisibilityModelChange', () => {
|
|
341
|
+
const filterModel = gridFilterModelSelector(apiRef);
|
|
342
|
+
if (filterModel.quickFilterValues && filterModel.quickFilterExcludeHiddenColumns) {
|
|
343
|
+
// re-apply filters because the quick filter results may have changed
|
|
344
|
+
apiRef.current.unstable_applyFilters();
|
|
345
|
+
}
|
|
346
|
+
});
|
|
335
347
|
|
|
336
348
|
/**
|
|
337
349
|
* 1ST RENDER
|
|
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import { gridPinnedRowsSelector } from './gridRowsSelector';
|
|
3
3
|
import { gridDensityFactorSelector } from '../density/densitySelector';
|
|
4
4
|
export const GRID_ROOT_GROUP_ID = `auto-generated-group-node-root`;
|
|
5
|
-
export const GRID_ID_AUTOGENERATED = Symbol('mui
|
|
5
|
+
export const GRID_ID_AUTOGENERATED = Symbol('mui.id_autogenerated');
|
|
6
6
|
export const buildRootGroup = () => ({
|
|
7
7
|
type: 'group',
|
|
8
8
|
id: GRID_ROOT_GROUP_ID,
|