@mui/x-data-grid-premium 8.14.1 → 8.16.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/DataGridPremium/DataGridPremium.js +4 -1
  3. package/DataGridPremium/useDataGridPremiumComponent.js +1 -1
  4. package/components/prompt/GridPrompt.js +11 -1
  5. package/esm/DataGridPremium/DataGridPremium.js +4 -1
  6. package/esm/DataGridPremium/useDataGridPremiumComponent.js +1 -1
  7. package/esm/components/prompt/GridPrompt.js +11 -1
  8. package/esm/hooks/features/aiAssistant/gridAiAssistantInterfaces.d.ts +5 -0
  9. package/esm/hooks/features/aiAssistant/useGridAiAssistant.d.ts +1 -1
  10. package/esm/hooks/features/aiAssistant/useGridAiAssistant.js +79 -12
  11. package/esm/hooks/features/chartsIntegration/gridChartsIntegrationSelectors.d.ts +6 -0
  12. package/esm/hooks/features/chartsIntegration/gridChartsIntegrationSelectors.js +1 -0
  13. package/esm/hooks/features/chartsIntegration/useGridChartsIntegration.d.ts +1 -1
  14. package/esm/hooks/features/chartsIntegration/useGridChartsIntegration.js +76 -13
  15. package/esm/hooks/features/dataSource/models.d.ts +4 -2
  16. package/esm/hooks/features/dataSource/useGridDataSourcePremium.js +31 -8
  17. package/esm/hooks/features/dataSource/utils.d.ts +3 -2
  18. package/esm/hooks/features/dataSource/utils.js +13 -1
  19. package/esm/hooks/features/editing/useGridCellEditable.d.ts +8 -0
  20. package/esm/hooks/features/editing/useGridCellEditable.js +35 -0
  21. package/esm/hooks/features/export/gridExcelExportInterface.d.ts +1 -1
  22. package/esm/hooks/features/export/serializer/excelSerializer.d.ts +1 -1
  23. package/esm/hooks/features/export/serializer/utils.d.ts +1 -1
  24. package/esm/hooks/features/export/serializer/utils.js +1 -1
  25. package/esm/hooks/features/rowGrouping/createGroupingColDef.js +3 -3
  26. package/esm/index.js +1 -1
  27. package/esm/material/index.d.ts +1 -0
  28. package/esm/material/index.js +1 -0
  29. package/esm/models/gridPremiumIconSlotsComponent.d.ts +5 -0
  30. package/hooks/features/aiAssistant/gridAiAssistantInterfaces.d.ts +5 -0
  31. package/hooks/features/aiAssistant/useGridAiAssistant.d.ts +1 -1
  32. package/hooks/features/aiAssistant/useGridAiAssistant.js +78 -11
  33. package/hooks/features/chartsIntegration/gridChartsIntegrationSelectors.d.ts +6 -0
  34. package/hooks/features/chartsIntegration/gridChartsIntegrationSelectors.js +2 -1
  35. package/hooks/features/chartsIntegration/useGridChartsIntegration.d.ts +1 -1
  36. package/hooks/features/chartsIntegration/useGridChartsIntegration.js +75 -12
  37. package/hooks/features/dataSource/models.d.ts +4 -2
  38. package/hooks/features/dataSource/useGridDataSourcePremium.js +28 -5
  39. package/hooks/features/dataSource/utils.d.ts +3 -2
  40. package/hooks/features/dataSource/utils.js +15 -2
  41. package/hooks/features/editing/useGridCellEditable.d.ts +8 -0
  42. package/hooks/features/editing/useGridCellEditable.js +41 -0
  43. package/hooks/features/export/gridExcelExportInterface.d.ts +1 -1
  44. package/hooks/features/export/serializer/excelSerializer.d.ts +1 -1
  45. package/hooks/features/export/serializer/utils.d.ts +1 -1
  46. package/hooks/features/export/serializer/utils.js +1 -1
  47. package/hooks/features/rowGrouping/createGroupingColDef.js +3 -3
  48. package/index.js +1 -1
  49. package/material/index.d.ts +1 -0
  50. package/material/index.js +1 -0
  51. package/models/gridPremiumIconSlotsComponent.d.ts +5 -0
  52. package/package.json +6 -6
@@ -6,7 +6,7 @@ import debounce from '@mui/utils/debounce';
6
6
  import { gridColumnGroupsLookupSelector, gridColumnGroupsUnwrappedModelSelector, gridRowIdSelector, gridRowNodeSelector, gridRowTreeSelector } from '@mui/x-data-grid-pro';
7
7
  import { useGridApiMethod, useGridEvent, gridColumnLookupSelector, runIf, gridPivotActiveSelector, useGridRegisterPipeProcessor, gridColumnFieldsSelector, gridFilteredSortedDepthRowEntriesSelector, GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD } from '@mui/x-data-grid-pro/internals';
8
8
  import { getRowGroupingFieldFromGroupingCriteria } from "../rowGrouping/gridRowGroupingUtils.js";
9
- import { gridChartsPanelOpenSelector, gridChartsDimensionsSelector, gridChartsValuesSelector, gridChartsIntegrationActiveChartIdSelector, gridChartableColumnsSelector } from "./gridChartsIntegrationSelectors.js";
9
+ import { gridChartsPanelOpenSelector, gridChartsDimensionsSelector, gridChartsValuesSelector, gridChartsIntegrationActiveChartIdSelector, gridChartableColumnsSelector, gridChartsIntegrationChartsLookupSelector } from "./gridChartsIntegrationSelectors.js";
10
10
  import { useGridChartsIntegrationContext } from "../../utils/useGridChartIntegration.js";
11
11
  import { isBlockedForSection } from "./utils.js";
12
12
  import { gridRowGroupingSanitizedModelSelector } from "../rowGrouping/gridRowGroupingSelector.js";
@@ -62,7 +62,6 @@ export const useGridChartsIntegration = (apiRef, props) => {
62
62
  const context = useGridChartsIntegrationContext(true);
63
63
  const isChartsIntegrationAvailable = !!props.chartsIntegration && !!props.experimentalFeatures?.charts && !!context;
64
64
  const activeChartId = gridChartsIntegrationActiveChartIdSelector(apiRef);
65
- const orderedFields = gridColumnFieldsSelector(apiRef);
66
65
  const aggregationModel = gridAggregationModelSelector(apiRef);
67
66
  const pivotActive = gridPivotActiveSelector(apiRef);
68
67
  const pivotModel = gridPivotModelSelector(apiRef);
@@ -151,25 +150,28 @@ export const useGridChartsIntegration = (apiRef, props) => {
151
150
  if (!pivotActive && visibleValues.current[activeChartId] && rowGroupingModel.length > 0) {
152
151
  // with row grouping add the aggregation model to the newly added value dataset
153
152
  const aggregatedFields = Object.keys(aggregationModel);
153
+ const aggregationsToAdd = {};
154
154
  visibleValues.current[activeChartId].forEach(item => {
155
155
  const hasAggregation = aggregatedFields.includes(item.field);
156
156
  if (!hasAggregation) {
157
- apiRef.current.setAggregationModel(_extends({}, aggregationModel, {
158
- // use the first available aggregation function
159
- [item.field]: getAvailableAggregationFunctions({
160
- aggregationFunctions: props.aggregationFunctions,
161
- colDef: item,
162
- isDataSource: !!props.dataSource
163
- })[0]
164
- }));
157
+ // use the first available aggregation function
158
+ aggregationsToAdd[item.field] = getAvailableAggregationFunctions({
159
+ aggregationFunctions: props.aggregationFunctions,
160
+ colDef: item,
161
+ isDataSource: !!props.dataSource
162
+ })[0];
165
163
  }
166
164
  });
165
+ if (Object.keys(aggregationsToAdd).length > 0) {
166
+ apiRef.current.setAggregationModel(_extends({}, aggregationModel, aggregationsToAdd));
167
+ }
167
168
  }
168
169
  }, [apiRef, props.aggregationFunctions, props.dataSource, activeChartId, pivotActive, aggregationModel]);
169
170
  const handleRowDataUpdate = React.useCallback(chartIds => {
170
171
  if (chartIds.length === 0 || chartIds.some(chartId => !visibleDimensions.current[chartId] || !visibleValues.current[chartId])) {
171
172
  return;
172
173
  }
174
+ const orderedFields = gridColumnFieldsSelector(apiRef);
173
175
  const rowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef);
174
176
  const rowTree = gridRowTreeSelector(apiRef);
175
177
  const rowsPerDepth = gridFilteredSortedDepthRowEntriesSelector(apiRef);
@@ -226,7 +228,7 @@ export const useGridChartsIntegration = (apiRef, props) => {
226
228
  }))
227
229
  });
228
230
  });
229
- }, [apiRef, orderedFields, getColumnName, getValueDatasetLabel, setChartState]);
231
+ }, [apiRef, getColumnName, getValueDatasetLabel, setChartState]);
230
232
  const debouncedHandleRowDataUpdate = React.useMemo(() => debounce(handleRowDataUpdate, 0), [handleRowDataUpdate]);
231
233
  const handleColumnDataUpdate = React.useCallback((chartIds, updatedChartStateLookup) => {
232
234
  // if there are no charts, skip the data processing
@@ -296,8 +298,8 @@ export const useGridChartsIntegration = (apiRef, props) => {
296
298
  }
297
299
  });
298
300
  updateOtherModels();
299
- handleRowDataUpdate(chartIds);
300
- }, [apiRef, chartStateLookup, pivotActive, pivotModel, handleRowDataUpdate, updateOtherModels]);
301
+ debouncedHandleRowDataUpdate(chartIds);
302
+ }, [apiRef, chartStateLookup, pivotActive, pivotModel, debouncedHandleRowDataUpdate, updateOtherModels]);
301
303
  const debouncedHandleColumnDataUpdate = React.useMemo(() => debounce(handleColumnDataUpdate, 0), [handleColumnDataUpdate]);
302
304
  const setChartsPanelOpen = React.useCallback(callback => {
303
305
  if (!isChartsIntegrationAvailable) {
@@ -496,6 +498,67 @@ export const useGridChartsIntegration = (apiRef, props) => {
496
498
  useGridEvent(apiRef, 'pivotModeChange', runIf(isChartsIntegrationAvailable, () => debouncedHandleColumnDataUpdate(syncedChartIds)));
497
499
  useGridEvent(apiRef, 'filteredRowsSet', runIf(isChartsIntegrationAvailable, () => debouncedHandleRowDataUpdate(syncedChartIds)));
498
500
  useGridEvent(apiRef, 'sortedRowsSet', runIf(isChartsIntegrationAvailable, () => debouncedHandleRowDataUpdate(syncedChartIds)));
501
+ const stateExportPreProcessing = React.useCallback((prevState, exportContext) => {
502
+ if (!props.chartsIntegration || !props.experimentalFeatures?.charts) {
503
+ return prevState;
504
+ }
505
+ const currentActiveChartId = gridChartsIntegrationActiveChartIdSelector(apiRef);
506
+ const chartsLookup = gridChartsIntegrationChartsLookupSelector(apiRef);
507
+ const integrationContextToExport = Object.fromEntries(Object.entries(chartStateLookup).map(([chartId, chartState]) => [chartId,
508
+ // keep only the state that is controlled by the user, drop the data and labels
509
+ {
510
+ synced: chartState.synced,
511
+ type: chartState.type,
512
+ configuration: chartState.configuration
513
+ }]));
514
+ const shouldExportChartState =
515
+ // Always export if the `exportOnlyDirtyModels` property is not activated
516
+ !exportContext.exportOnlyDirtyModels ||
517
+ // Always export if the chart state has been initialized
518
+ props.initialState?.chartsIntegration != null ||
519
+ // Export if the chart model or context is not empty
520
+ Object.keys(chartsLookup).length > 0 || Object.keys(integrationContextToExport).length > 0;
521
+ if (!shouldExportChartState) {
522
+ return prevState;
523
+ }
524
+ const chartStateToExport = {
525
+ activeChartId: currentActiveChartId,
526
+ charts: chartsLookup,
527
+ // add a custom prop to keep the integration context in the exported state
528
+ integrationContext: integrationContextToExport
529
+ };
530
+ return _extends({}, prevState, {
531
+ chartsIntegration: chartStateToExport
532
+ });
533
+ }, [apiRef, chartStateLookup, props.chartsIntegration, props.experimentalFeatures?.charts, props.initialState?.chartsIntegration]);
534
+ const stateRestorePreProcessing = React.useCallback((params, restoreContext) => {
535
+ const chartsRestoreState = restoreContext.stateToRestore.chartsIntegration;
536
+ if (!chartsRestoreState) {
537
+ return params;
538
+ }
539
+ const {
540
+ activeChartId: activeChartIdToRestore,
541
+ charts: chartsToRestore,
542
+ integrationContext
543
+ } = chartsRestoreState;
544
+ if (activeChartIdToRestore === undefined || chartsToRestore === undefined || Object.keys(chartsToRestore).length === 0) {
545
+ return params;
546
+ }
547
+ apiRef.current.setState(_extends({}, apiRef.current.state, {
548
+ chartsIntegration: {
549
+ activeChartId: activeChartIdToRestore,
550
+ charts: chartsToRestore
551
+ }
552
+ }));
553
+
554
+ // restore the integration context for each chart
555
+ Object.entries(integrationContext).forEach(([chartId, chartContextState]) => {
556
+ setChartState(chartId, chartContextState);
557
+ });
558
+ return params;
559
+ }, [apiRef, setChartState]);
560
+ useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
561
+ useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
499
562
  React.useEffect(() => {
500
563
  if (!activeChartId && availableChartIds.length > 0) {
501
564
  setActiveChartId(availableChartIds[0]);
@@ -1,4 +1,5 @@
1
1
  import type { GridColDef, GridRowId, GridValidRowModel, GridDataSource, GridGetRowsResponse, GridGetRowsParams, GridDataSourceApiBase, GridDataSourcePrivateApi, GridRowModel } from '@mui/x-data-grid-pro';
2
+ import type { GridDataSourceFetchRowsParams } from '@mui/x-data-grid-pro/internals';
2
3
  import type { GridAggregationModel } from "../aggregation/gridAggregationInterfaces.js";
3
4
  import type { GridPivotModel } from "../pivoting/gridPivotingInterfaces.js";
4
5
  export interface GridGetRowsResponsePivotColumn {
@@ -90,9 +91,10 @@ export interface GridDataSourceApiBasePremium extends Omit<GridDataSourceApiBase
90
91
  * If no `parentId` option is provided, it fetches the root rows.
91
92
  * Any missing parameter from `params` will be filled from the state (sorting, filtering, etc.).
92
93
  * @param {GridRowId} parentId The id of the parent node (default: `GRID_ROOT_GROUP_ID`).
93
- * @param {Partial<GridGetRowsParamsPremium>} params Request parameters override.
94
+ * @param {GridDataSourceFetchRowsParams<GridGetRowsParamsPremium>} params Request parameters override.
95
+ * @returns {Promise<void>} A promise that resolves when the rows are fetched.
94
96
  */
95
- fetchRows: (parentId?: GridRowId, params?: Partial<GridGetRowsParamsPremium>) => void;
97
+ fetchRows: (parentId?: GridRowId, params?: GridDataSourceFetchRowsParams<GridGetRowsParamsPremium>) => Promise<void>;
96
98
  }
97
99
  export interface GridDataSourceApiPremium {
98
100
  /**
@@ -2,10 +2,13 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
- import { useGridEvent as addEventHandler, useGridApiMethod, GRID_ROOT_GROUP_ID, useGridEvent } from '@mui/x-data-grid-pro';
6
- import { useGridDataSourceBasePro, useGridRegisterStrategyProcessor, useGridRegisterPipeProcessor, gridPivotInitialColumnsSelector, runIf, gridPivotActiveSelector } from '@mui/x-data-grid-pro/internals';
5
+ import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
6
+ import { useGridEvent as addEventHandler, useGridApiMethod, GRID_ROOT_GROUP_ID, useGridEvent, gridRowTreeSelector } from '@mui/x-data-grid-pro';
7
+ import { useGridDataSourceBasePro, useGridRegisterStrategyProcessor, useGridRegisterPipeProcessor, gridPivotInitialColumnsSelector, runIf, gridPivotActiveSelector, GridStrategyGroup, DataSourceRowsUpdateStrategy, getGroupKeys } from '@mui/x-data-grid-pro/internals';
7
8
  import { gridPivotModelSelector } from "../pivoting/gridPivotingSelectors.js";
8
- import { getPropsOverrides } from "./utils.js";
9
+ import { getPropsOverrides, fetchParents } from "./utils.js";
10
+ import { gridRowGroupingSanitizedModelSelector } from "../rowGrouping/gridRowGroupingSelector.js";
11
+ import { gridAggregationModelSelector } from "../aggregation/gridAggregationSelectors.js";
9
12
  function getKeyPremium(params) {
10
13
  return JSON.stringify([params.filterModel, params.sortModel, params.groupKeys, params.groupFields, params.start, params.end, params.pivotModel ? {} : params.aggregationModel, params.pivotModel]);
11
14
  }
@@ -15,13 +18,32 @@ const options = {
15
18
  }
16
19
  };
17
20
  export const useGridDataSourcePremium = (apiRef, props) => {
21
+ const aggregationModel = gridAggregationModelSelector(apiRef);
22
+ const groupingModelSize = gridRowGroupingSanitizedModelSelector(apiRef).length;
23
+ const setStrategyAvailability = React.useCallback(() => {
24
+ const targetStrategy = props.treeData || !props.disableRowGrouping && groupingModelSize > 0 ? DataSourceRowsUpdateStrategy.GroupedData : DataSourceRowsUpdateStrategy.Default;
25
+ apiRef.current.setStrategyAvailability(GridStrategyGroup.DataSource, targetStrategy, props.dataSource && !props.lazyLoading ? () => true : () => false);
26
+ }, [apiRef, props.dataSource, props.lazyLoading, props.treeData, props.disableRowGrouping, groupingModelSize]);
27
+ const handleEditRowWithAggregation = React.useCallback((params, updatedRow) => {
28
+ const rowTree = gridRowTreeSelector(apiRef);
29
+ if (updatedRow && !isDeepEqual(updatedRow, params.previousRow)) {
30
+ // Reset the outdated cache, only if the row is _actually_ updated
31
+ apiRef.current.dataSource.cache.clear();
32
+ }
33
+ const groupKeys = getGroupKeys(rowTree, params.rowId);
34
+ apiRef.current.updateNestedRows([updatedRow], groupKeys);
35
+ // To refresh the aggregation values of all parent rows and the footer row, recursively re-fetch all parent levels
36
+ fetchParents(rowTree, params.rowId, apiRef.current.dataSource.fetchRows);
37
+ }, [apiRef]);
18
38
  const {
19
39
  api,
20
40
  debouncedFetchRows,
21
- strategyProcessor,
22
- events,
23
- setStrategyAvailability
24
- } = useGridDataSourceBasePro(apiRef, props, options);
41
+ flatTreeStrategyProcessor,
42
+ groupedDataStrategyProcessor,
43
+ events
44
+ } = useGridDataSourceBasePro(apiRef, props, _extends({}, !props.disableAggregation && Object.keys(aggregationModel).length > 0 ? {
45
+ handleEditRow: handleEditRowWithAggregation
46
+ } : {}, options));
25
47
  const aggregateRowRef = React.useRef({});
26
48
  const initialColumns = gridPivotInitialColumnsSelector(apiRef);
27
49
  const pivotActive = gridPivotActiveSelector(apiRef);
@@ -74,7 +96,8 @@ export const useGridDataSourcePremium = (apiRef, props) => {
74
96
  });
75
97
  useGridApiMethod(apiRef, api.public, 'public');
76
98
  useGridApiMethod(apiRef, privateApi, 'private');
77
- useGridRegisterStrategyProcessor(apiRef, strategyProcessor.strategyName, strategyProcessor.group, strategyProcessor.processor);
99
+ useGridRegisterStrategyProcessor(apiRef, flatTreeStrategyProcessor.strategyName, flatTreeStrategyProcessor.group, flatTreeStrategyProcessor.processor);
100
+ useGridRegisterStrategyProcessor(apiRef, groupedDataStrategyProcessor.strategyName, groupedDataStrategyProcessor.group, groupedDataStrategyProcessor.processor);
78
101
  useGridRegisterPipeProcessor(apiRef, 'processDataSourceRows', processDataSourceRows);
79
102
  Object.entries(events).forEach(([event, handler]) => {
80
103
  addEventHandler(apiRef, event, handler);
@@ -1,6 +1,7 @@
1
1
  import type { RefObject } from '@mui/x-internals/types';
2
- import { GridColDef } from '@mui/x-data-grid-pro';
2
+ import { GridColDef, GridRowId, GridRowTreeConfig } from '@mui/x-data-grid-pro';
3
3
  import type { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
4
4
  import type { GridPivotingDynamicPropsOverrides, PivotingColDefCallback, GridPivotModel } from "../pivoting/gridPivotingInterfaces.js";
5
5
  import type { GridGetRowsResponsePivotColumn } from "./models.js";
6
- export declare const getPropsOverrides: (pivotColumns: GridGetRowsResponsePivotColumn[], pivotingColDef: PivotingColDefCallback, pivotModel: GridPivotModel, initialColumns: Map<string, GridColDef>, apiRef: RefObject<GridPrivateApiPremium>) => GridPivotingDynamicPropsOverrides;
6
+ export declare const getPropsOverrides: (pivotColumns: GridGetRowsResponsePivotColumn[], pivotingColDef: PivotingColDefCallback, pivotModel: GridPivotModel, initialColumns: Map<string, GridColDef>, apiRef: RefObject<GridPrivateApiPremium>) => GridPivotingDynamicPropsOverrides;
7
+ export declare const fetchParents: (rowTree: GridRowTreeConfig, rowId: GridRowId, fetchHandler: (id?: GridRowId) => Promise<void>) => Promise<void[]>;
@@ -1,5 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import { gridStringOrNumberComparator } from '@mui/x-data-grid-pro';
2
+ import { gridStringOrNumberComparator, GRID_ROOT_GROUP_ID } from '@mui/x-data-grid-pro';
3
3
  export const getPropsOverrides = (pivotColumns, pivotingColDef, pivotModel, initialColumns, apiRef) => {
4
4
  const visiblePivotColumns = pivotModel.columns.filter(column => !column.hidden);
5
5
  const visiblePivotValues = pivotModel.values.filter(value => !value.hidden);
@@ -137,4 +137,16 @@ export const getPropsOverrides = (pivotColumns, pivotingColDef, pivotModel, init
137
137
  columnGroupingModel,
138
138
  aggregationModel
139
139
  };
140
+ };
141
+ export const fetchParents = (rowTree, rowId, fetchHandler) => {
142
+ const parents = [];
143
+
144
+ // collect all parents ids
145
+ let currentId = rowId;
146
+ while (currentId !== undefined && currentId !== GRID_ROOT_GROUP_ID) {
147
+ const parentId = rowTree[currentId].parent;
148
+ parents.push(parentId);
149
+ currentId = parentId;
150
+ }
151
+ return Promise.all(parents.reverse().map(fetchHandler));
140
152
  };
@@ -0,0 +1,8 @@
1
+ import { RefObject } from '@mui/x-internals/types';
2
+ import { CellEditableConditionFn } from '@mui/x-data-grid-pro/internals';
3
+ import { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
4
+ import { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
5
+ /**
6
+ * Implementation of the cell editable condition hook of the Data Grid Premium
7
+ */
8
+ export declare const useIsCellEditable: (apiRef: RefObject<GridPrivateApiPremium>, props: DataGridPremiumProcessedProps) => CellEditableConditionFn;
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { useIsCellEditable as useIsCellEditableCommunity } from '@mui/x-data-grid-pro/internals';
5
+ import { gridAggregationModelSelector } from "../aggregation/gridAggregationSelectors.js";
6
+
7
+ /**
8
+ * Implementation of the cell editable condition hook of the Data Grid Premium
9
+ */
10
+ export const useIsCellEditable = (apiRef, props) => {
11
+ const isCellEditableCommunity = useIsCellEditableCommunity();
12
+ return React.useCallback(params => {
13
+ const isCellEditable = isCellEditableCommunity(params);
14
+
15
+ // If the cell is not editable by the community hook, return false immediately
16
+ if (!isCellEditable) {
17
+ return false;
18
+ }
19
+
20
+ // If the data source is not used or aggregation is disabled or both tree data and row grouping are disabled, return the community hook result
21
+ if (!props.dataSource || props.disableAggregation || !props.treeData && props.disableRowGrouping) {
22
+ return isCellEditable;
23
+ }
24
+
25
+ // If the cell is not a part of the aggregation model, return the community hook result
26
+ const aggregationModelFields = Object.keys(gridAggregationModelSelector(apiRef));
27
+ if (!aggregationModelFields.includes(params.field)) {
28
+ return isCellEditable;
29
+ }
30
+
31
+ // The cell is a part of the aggregation model and it is retrieved from the server-side data.
32
+ // Allow editing only for the non-grouped rows.
33
+ return params.rowNode.type !== 'group';
34
+ }, [apiRef, props.dataSource, props.treeData, props.disableAggregation, props.disableRowGrouping, isCellEditableCommunity]);
35
+ };
@@ -1,4 +1,4 @@
1
- import type * as Excel from 'exceljs';
1
+ import type * as Excel from '@mui/x-internal-exceljs-fork';
2
2
  import { GridFileExportOptions, GridExportFormat as GridExportFormatCommunity, GridExportExtension as GridExportExtensionCommunity } from '@mui/x-data-grid-pro';
3
3
  export type GridExportFormat = GridExportFormatCommunity | 'excel';
4
4
  export type GridExportExtension = GridExportExtensionCommunity | 'xlsx';
@@ -1,4 +1,4 @@
1
- import type * as Excel from 'exceljs';
1
+ import type * as Excel from '@mui/x-internal-exceljs-fork';
2
2
  import { RefObject } from '@mui/x-internals/types';
3
3
  import { GridRowId, GridColDef } from '@mui/x-data-grid-pro';
4
4
  import { GridStateColDef } from '@mui/x-data-grid/internals';
@@ -1,4 +1,4 @@
1
- import type * as Excel from 'exceljs';
1
+ import type * as Excel from '@mui/x-internal-exceljs-fork';
2
2
  import type { GridColumnGroupLookup } from '@mui/x-data-grid/internals';
3
3
  import type { GridExcelExportOptions } from "../gridExcelExportInterface.js";
4
4
  export declare const getExcelJs: () => Promise<typeof Excel>;
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  export const getExcelJs = async () => {
3
- const excelJsModule = await import('exceljs');
3
+ const excelJsModule = await import('@mui/x-internal-exceljs-fork');
4
4
  return excelJsModule.default ?? excelJsModule;
5
5
  };
6
6
  export const addColumnGroupingHeaders = (worksheet, columns, columnGroupPaths, columnGroupDetails) => {
@@ -84,12 +84,12 @@ function getGroupingCriteriaProperties(groupedByColDef, rowGroupingColumnMode, r
84
84
  const rowId = gridRowIdSelector(apiRef, row);
85
85
  const rowNode = gridRowNodeSelector(apiRef, rowId);
86
86
  if (rowNode?.type === 'group') {
87
- const originalColDef = columnsLookup[rowNode.groupingField];
88
- if (originalColDef.type === 'singleSelect') {
87
+ const originalColDef = rowNode.groupingField ? columnsLookup[rowNode.groupingField] : null;
88
+ if (originalColDef?.type === 'singleSelect') {
89
89
  // the default valueFormatter of a singleSelect colDef won't work with the grouping column values
90
90
  return value;
91
91
  }
92
- const columnValueFormatter = originalColDef.valueFormatter;
92
+ const columnValueFormatter = originalColDef?.valueFormatter;
93
93
  if (typeof columnValueFormatter === 'function') {
94
94
  return columnValueFormatter(value, row, column, apiRef);
95
95
  }
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-premium v8.14.1
2
+ * @mui/x-data-grid-premium v8.16.0
3
3
  *
4
4
  * @license SEE LICENSE IN LICENSE
5
5
  * This source code is licensed under the SEE LICENSE IN LICENSE license found in the
@@ -25,6 +25,7 @@ declare const materialSlots: {
25
25
  promptRerunIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
26
26
  promptSortAscIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
27
27
  promptSortDescIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
28
+ promptChartsIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
28
29
  promptGroupIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
29
30
  promptFilterIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
30
31
  promptPivotIcon: React.JSXElementConstructor<import("@mui/x-data-grid/models/gridBaseSlots").IconProps>;
@@ -33,6 +33,7 @@ const iconsSlots = {
33
33
  promptPivotIcon: GridPivotIcon,
34
34
  promptAggregationIcon: GridFunctionsIcon,
35
35
  promptGroupIcon: GridGroupWorkIcon,
36
+ promptChartsIcon: GridChartsIcon,
36
37
  promptChangesToggleIcon: GridExpandMoreIcon,
37
38
  chartsIcon: GridChartsIcon,
38
39
  chartsSearchIcon: GridSearchIcon,
@@ -132,6 +132,11 @@ export interface GridPremiumIconSlotsComponent {
132
132
  * @default GridArrowDownwardIcon
133
133
  */
134
134
  promptSortDescIcon: React.JSXElementConstructor<IconProps>;
135
+ /**
136
+ * Icon used to mark the request to visalize the data
137
+ * @default GridChartsIcon
138
+ */
139
+ promptChartsIcon: React.JSXElementConstructor<IconProps>;
135
140
  /**
136
141
  * Icon used to display group changes
137
142
  * @default GridGroupWorkIcon
@@ -39,6 +39,10 @@ type Pivoting = {
39
39
  rows: string[];
40
40
  values: Aggregation[];
41
41
  } | {};
42
+ type Chart = {
43
+ dimensions: string[];
44
+ values: string[];
45
+ };
42
46
  export type PromptResponse = {
43
47
  conversationId: string;
44
48
  select: number;
@@ -48,6 +52,7 @@ export type PromptResponse = {
48
52
  sorting: ColumnSort[];
49
53
  grouping: Grouping[];
50
54
  pivoting: Pivoting;
55
+ chart: Chart | null;
51
56
  };
52
57
  export type PromptResolverOptions = {
53
58
  /**
@@ -3,4 +3,4 @@ import { GridStateInitializer } from '@mui/x-data-grid-pro/internals';
3
3
  import { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
4
4
  import { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
5
5
  export declare const aiAssistantStateInitializer: GridStateInitializer<Pick<DataGridPremiumProcessedProps, 'initialState' | 'aiAssistantConversations' | 'aiAssistant'>>;
6
- export declare const useGridAiAssistant: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "aiAssistant" | "aiAssistantConversations" | "aiAssistantActiveConversationIndex" | "allowAiAssistantDataSampling" | "onAiAssistantConversationsChange" | "onAiAssistantActiveConversationIndexChange" | "onPrompt" | "slots" | "disableColumnFilter" | "disableRowGrouping" | "disableAggregation" | "disableColumnSorting" | "disablePivoting">) => void;
6
+ export declare const useGridAiAssistant: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "aiAssistant" | "aiAssistantConversations" | "aiAssistantActiveConversationIndex" | "allowAiAssistantDataSampling" | "onAiAssistantConversationsChange" | "onAiAssistantActiveConversationIndexChange" | "onPrompt" | "slots" | "rowSelection" | "disableColumnFilter" | "disableRowGrouping" | "disableAggregation" | "disableColumnSorting" | "disablePivoting" | "chartsIntegration" | "experimentalFeatures" | "getPivotDerivedColumns">) => void;
@@ -9,11 +9,14 @@ Object.defineProperty(exports, "__esModule", {
9
9
  exports.useGridAiAssistant = exports.aiAssistantStateInitializer = void 0;
10
10
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
11
  var React = _interopRequireWildcard(require("react"));
12
+ var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
12
13
  var _xDataGridPro = require("@mui/x-data-grid-pro");
13
14
  var _internals = require("@mui/x-data-grid-pro/internals");
14
15
  var _gridAiAssistantSelectors = require("./gridAiAssistantSelectors");
16
+ var _gridChartsIntegrationSelectors = require("../chartsIntegration/gridChartsIntegrationSelectors");
15
17
  var _jsxRuntime = require("react/jsx-runtime");
16
18
  const DEFAULT_SAMPLE_COUNT = 5;
19
+ const MAX_CHART_DATA_POINTS = 1000;
17
20
  const aiAssistantStateInitializer = (state, props) => {
18
21
  if (!props.aiAssistant) {
19
22
  return (0, _extends2.default)({}, state, {
@@ -36,12 +39,18 @@ const useGridAiAssistant = (apiRef, props) => {
36
39
  onPrompt,
37
40
  allowAiAssistantDataSampling,
38
41
  slots,
42
+ rowSelection,
39
43
  disableColumnFilter,
40
44
  disableRowGrouping,
41
45
  disableAggregation,
42
46
  disableColumnSorting,
43
- disablePivoting
47
+ disablePivoting,
48
+ chartsIntegration,
49
+ experimentalFeatures,
50
+ getPivotDerivedColumns
44
51
  } = props;
52
+ const previousUnwrappedGroupingModel = React.useRef([]);
53
+ const activeChartId = (0, _gridChartsIntegrationSelectors.gridChartsIntegrationActiveChartIdSelector)(apiRef);
45
54
  const columnsLookup = (0, _xDataGridPro.gridColumnLookupSelector)(apiRef);
46
55
  const columns = Object.values(columnsLookup);
47
56
  const rows = Object.values((0, _xDataGridPro.gridRowsLookupSelector)(apiRef));
@@ -86,15 +95,38 @@ const useGridAiAssistant = (apiRef, props) => {
86
95
  return '';
87
96
  }
88
97
  const examples = allowDataSampling ? collectSampleData() : {};
89
- const columnsContext = columns.map(column => ({
90
- field: column.field,
91
- description: column.description ?? null,
92
- examples: examples[column.field] ?? column.examples ?? [],
93
- type: column.type ?? 'string',
94
- allowedOperators: column.filterOperators?.map(operator => operator.value) ?? []
95
- }));
98
+ const columnsContext = columns.reduce((acc, column) => {
99
+ const columnContextWithoutExamples = {
100
+ field: column.field,
101
+ description: column.description ?? null,
102
+ examples: [],
103
+ type: column.type ?? 'string',
104
+ allowedOperators: column.filterOperators?.map(operator => operator.value) ?? []
105
+ };
106
+ acc.push((0, _extends2.default)({}, columnContextWithoutExamples, {
107
+ examples: examples[column.field] ?? column.examples ?? []
108
+ }));
109
+ if (disablePivoting) {
110
+ return acc;
111
+ }
112
+ (getPivotDerivedColumns?.(column, apiRef.current.getLocaleText) || []).forEach(col => acc.push((0, _extends2.default)({}, columnContextWithoutExamples, col, {
113
+ derivedFrom: column.field
114
+ })));
115
+ return acc;
116
+ }, []);
96
117
  return JSON.stringify(columnsContext);
97
- }, [columns, collectSampleData, isAiAssistantAvailable]);
118
+ }, [apiRef, columns, collectSampleData, getPivotDerivedColumns, isAiAssistantAvailable, disablePivoting]);
119
+ const updateChart = React.useCallback(result => {
120
+ if (!result.chart) {
121
+ return;
122
+ }
123
+ apiRef.current.updateChartDimensionsData(activeChartId, result.chart.dimensions.map(item => ({
124
+ field: item
125
+ })));
126
+ apiRef.current.updateChartValuesData(activeChartId, result.chart.values.map(item => ({
127
+ field: item
128
+ })));
129
+ }, [apiRef, activeChartId]);
98
130
  const applyPromptResult = React.useCallback(result => {
99
131
  if (!isAiAssistantAvailable) {
100
132
  return;
@@ -123,6 +155,8 @@ const useGridAiAssistant = (apiRef, props) => {
123
155
  quickFilterValues: []
124
156
  });
125
157
  interestColumns.push(...result.filters.map(f => f.column));
158
+ } else {
159
+ result.filters = [];
126
160
  }
127
161
  let appliedPivoting = false;
128
162
  if (!disablePivoting && 'columns' in result.pivoting) {
@@ -146,6 +180,7 @@ const useGridAiAssistant = (apiRef, props) => {
146
180
  appliedPivoting = true;
147
181
  } else if ('columns' in result.pivoting) {
148
182
  // if pivoting is disabled and there are pivoting results, try to move them into grouping and aggregation
183
+ apiRef.current.setPivotActive(false);
149
184
  result.pivoting.columns.forEach(c => {
150
185
  result.grouping.push({
151
186
  column: c.column
@@ -162,26 +197,58 @@ const useGridAiAssistant = (apiRef, props) => {
162
197
  });
163
198
  // remove the pivoting results data
164
199
  result.pivoting = {};
200
+ } else {
201
+ apiRef.current.setPivotActive(false);
165
202
  }
166
203
  if (!disableRowGrouping && !appliedPivoting) {
167
204
  apiRef.current.setRowGroupingModel(result.grouping.map(g => g.column));
205
+ } else {
206
+ result.grouping = [];
168
207
  }
169
208
  if (!disableAggregation && !appliedPivoting) {
170
209
  apiRef.current.setAggregationModel(result.aggregation);
171
210
  interestColumns.push(...Object.keys(result.aggregation));
211
+ } else {
212
+ result.aggregation = {};
172
213
  }
173
214
  if (!disableColumnSorting) {
174
215
  apiRef.current.setSortModel(result.sorting.map(s => ({
175
216
  field: s.column,
176
217
  sort: s.direction
177
218
  })));
219
+ } else {
220
+ result.sorting = [];
221
+ }
222
+ if (experimentalFeatures?.charts && chartsIntegration && activeChartId && result.chart) {
223
+ if (appliedPivoting) {
224
+ const unsubscribe = apiRef.current.subscribeEvent('rowsSet', () => {
225
+ const unwrappedGroupingModel = Object.keys((0, _xDataGridPro.gridColumnGroupsUnwrappedModelSelector)(apiRef));
226
+ // wait until unwrapped grouping model changes
227
+ if (!result.chart || unwrappedGroupingModel.length === 0 || (0, _isDeepEqual.isDeepEqual)(previousUnwrappedGroupingModel.current, unwrappedGroupingModel)) {
228
+ return;
229
+ }
230
+ previousUnwrappedGroupingModel.current = unwrappedGroupingModel;
231
+ const visibleRowsCount = (0, _xDataGridPro.gridVisibleRowsSelector)(apiRef).rows.length;
232
+ const maxColumns = Math.floor(MAX_CHART_DATA_POINTS / visibleRowsCount);
233
+
234
+ // we assume that the pivoting was adjusted to what needs to be shown in the chart
235
+ // so we can just pick up all the columns that were created by pivoting
236
+ // to avoid rendering issues, set the limit to MAX_CHART_DATA_POINTS data points (rows * columns)
237
+ result.chart.values = unwrappedGroupingModel.slice(0, maxColumns);
238
+ updateChart(result);
239
+ unsubscribe();
240
+ });
241
+ } else {
242
+ updateChart(result);
243
+ }
178
244
  }
179
245
  const visibleRowsData = (0, _internals.getVisibleRows)(apiRef);
180
246
  const rowSelectionModel = {
181
247
  type: 'include',
182
248
  ids: new Set()
183
249
  };
184
- if (result.select !== -1) {
250
+ const selection = rowSelection ? result.select : -1;
251
+ if (selection !== -1) {
185
252
  for (let i = 0; i < result.select; i += 1) {
186
253
  const row = visibleRowsData.rows[i];
187
254
  const id = apiRef.current.getRowId(row);
@@ -191,7 +258,7 @@ const useGridAiAssistant = (apiRef, props) => {
191
258
  apiRef.current.setRowSelectionModel(rowSelectionModel);
192
259
  const targetIndex = Number(columnsLookup[_xDataGridPro.GRID_CHECKBOX_SELECTION_FIELD] !== undefined) + Number(result.grouping.length);
193
260
  interestColumns.reverse().forEach(c => apiRef.current.setColumnIndex(c, targetIndex));
194
- }, [apiRef, disableColumnFilter, disableRowGrouping, disableAggregation, disableColumnSorting, disablePivoting, columnsLookup, isAiAssistantAvailable]);
261
+ }, [apiRef, updateChart, rowSelection, disableColumnFilter, disableRowGrouping, disableAggregation, disableColumnSorting, disablePivoting, columnsLookup, isAiAssistantAvailable, activeChartId, chartsIntegration, experimentalFeatures?.charts]);
195
262
  const setActiveConversationId = React.useCallback(id => {
196
263
  if (!isAiAssistantAvailable) {
197
264
  return;
@@ -3,6 +3,12 @@ import { GridStatePremium } from "../../../models/gridStatePremium.js";
3
3
  export declare const gridChartsIntegrationActiveChartIdSelector: (args_0: import("react").RefObject<{
4
4
  state: GridStatePremium;
5
5
  } | null>) => string;
6
+ export declare const gridChartsIntegrationChartsLookupSelector: (args_0: import("react").RefObject<{
7
+ state: GridStatePremium;
8
+ } | null>) => Record<string, {
9
+ dimensions: import("./gridChartsIntegrationInterfaces.js").GridChartsIntegrationItem[];
10
+ values: import("./gridChartsIntegrationInterfaces.js").GridChartsIntegrationItem[];
11
+ }>;
6
12
  export declare const gridChartsPanelOpenSelector: (args_0: import("react").RefObject<{
7
13
  state: GridStatePremium;
8
14
  } | null>) => boolean;
@@ -3,12 +3,13 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.gridChartsValuesSelector = exports.gridChartsPanelOpenSelector = exports.gridChartsIntegrationActiveChartIdSelector = exports.gridChartsDimensionsSelector = exports.gridChartableColumnsSelector = void 0;
6
+ exports.gridChartsValuesSelector = exports.gridChartsPanelOpenSelector = exports.gridChartsIntegrationChartsLookupSelector = exports.gridChartsIntegrationActiveChartIdSelector = exports.gridChartsDimensionsSelector = exports.gridChartableColumnsSelector = void 0;
7
7
  var _internals = require("@mui/x-data-grid-pro/internals");
8
8
  var _sidebar = require("../sidebar");
9
9
  var _gridPivotingSelectors = require("../pivoting/gridPivotingSelectors");
10
10
  const gridChartsIntegrationStateSelector = (0, _internals.createRootSelector)(state => state.chartsIntegration);
11
11
  const gridChartsIntegrationActiveChartIdSelector = exports.gridChartsIntegrationActiveChartIdSelector = (0, _internals.createSelector)(gridChartsIntegrationStateSelector, chartsIntegration => chartsIntegration.activeChartId);
12
+ const gridChartsIntegrationChartsLookupSelector = exports.gridChartsIntegrationChartsLookupSelector = (0, _internals.createSelector)(gridChartsIntegrationStateSelector, chartsIntegration => chartsIntegration.charts);
12
13
  const gridChartsPanelOpenSelector = exports.gridChartsPanelOpenSelector = (0, _internals.createSelector)(_sidebar.gridSidebarStateSelector, sidebar => sidebar.value === _sidebar.GridSidebarValue.Charts && sidebar.open);
13
14
  const gridChartableColumnsSelector = exports.gridChartableColumnsSelector = (0, _internals.createSelectorMemoized)(_internals.gridColumnLookupSelector, _internals.gridPivotActiveSelector, _gridPivotingSelectors.gridPivotModelSelector, (columns, pivotActive, pivotModel) => {
14
15
  let chartableColumns = Object.values(columns).filter(column => column.chartable);
@@ -1,7 +1,7 @@
1
1
  import { RefObject } from '@mui/x-internals/types';
2
2
  import { GridStateInitializer } from '@mui/x-data-grid-pro/internals';
3
3
  import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
4
- import { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
4
+ import type { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
5
5
  import { ChartState } from "../../../models/gridChartsIntegration.js";
6
6
  export declare const EMPTY_CHART_INTEGRATION_CONTEXT_STATE: ChartState;
7
7
  export declare const chartsIntegrationStateInitializer: GridStateInitializer<Pick<DataGridPremiumProcessedProps, 'chartsIntegration' | 'initialState' | 'activeChartId' | 'rowGroupingModel' | 'pivotModel' | 'experimentalFeatures'>, GridPrivateApiPremium>;