@mui/x-data-grid-premium 8.24.0 → 8.26.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 +196 -6479
- package/DataGridPremium/DataGridPremium.js +25 -1
- package/DataGridPremium/useDataGridPremiumComponent.js +3 -0
- package/DataGridPremium/useDataGridPremiumProps.js +5 -1
- package/components/GridAggregationRowOverlay.js +1 -0
- package/components/GridEmptyPivotOverlay.js +1 -0
- package/components/GridPremiumColumnMenu.js +1 -0
- package/components/GridPremiumToolbar.js +55 -3
- package/components/columnMenu/menuItems/GridColumnMenuAggregationItem.js +1 -0
- package/components/resizablePanel/ResizablePanel.js +1 -0
- package/components/resizablePanel/ResizablePanelHandle.js +1 -0
- package/esm/DataGridPremium/DataGridPremium.js +25 -1
- package/esm/DataGridPremium/useDataGridPremiumComponent.js +3 -0
- package/esm/DataGridPremium/useDataGridPremiumProps.js +5 -1
- package/esm/components/GridAggregationRowOverlay.js +2 -0
- package/esm/components/GridEmptyPivotOverlay.js +2 -0
- package/esm/components/GridPremiumColumnMenu.js +2 -0
- package/esm/components/GridPremiumToolbar.js +57 -5
- package/esm/components/columnMenu/menuItems/GridColumnMenuAggregationItem.js +2 -0
- package/esm/components/resizablePanel/ResizablePanel.js +2 -0
- package/esm/components/resizablePanel/ResizablePanelHandle.js +2 -0
- package/esm/hooks/features/aggregation/useGridAggregationPreProcessors.js +2 -0
- package/esm/hooks/features/clipboard/useGridClipboardImport.js +20 -9
- package/esm/hooks/features/history/constants.d.ts +2 -0
- package/esm/hooks/features/history/constants.js +1 -0
- package/esm/hooks/features/history/defaultHistoryHandlers.d.ts +20 -0
- package/esm/hooks/features/history/defaultHistoryHandlers.js +365 -0
- package/esm/hooks/features/history/gridHistoryInterfaces.d.ts +95 -0
- package/esm/hooks/features/history/gridHistoryInterfaces.js +1 -0
- package/esm/hooks/features/history/gridHistorySelectors.d.ts +16 -0
- package/esm/hooks/features/history/gridHistorySelectors.js +7 -0
- package/esm/hooks/features/history/index.d.ts +3 -0
- package/esm/hooks/features/history/index.js +2 -0
- package/esm/hooks/features/history/useGridHistory.d.ts +6 -0
- package/esm/hooks/features/history/useGridHistory.js +294 -0
- package/esm/hooks/features/index.d.ts +2 -1
- package/esm/hooks/features/index.js +2 -1
- package/esm/hooks/utils/useGridChartIntegration.js +2 -0
- package/esm/index.js +1 -1
- package/esm/models/dataGridPremiumProps.d.ts +26 -1
- package/esm/models/gridApiPremium.d.ts +2 -1
- package/esm/models/gridStatePremium.d.ts +2 -0
- package/esm/typeOverloads/modules.d.ts +25 -2
- package/esm/typeOverloads/modules.js +5 -1
- package/hooks/features/aggregation/useGridAggregationPreProcessors.js +1 -0
- package/hooks/features/clipboard/useGridClipboardImport.js +20 -9
- package/hooks/features/history/constants.d.ts +2 -0
- package/hooks/features/history/constants.js +7 -0
- package/hooks/features/history/defaultHistoryHandlers.d.ts +20 -0
- package/hooks/features/history/defaultHistoryHandlers.js +376 -0
- package/hooks/features/history/gridHistoryInterfaces.d.ts +95 -0
- package/hooks/features/history/gridHistoryInterfaces.js +5 -0
- package/hooks/features/history/gridHistorySelectors.d.ts +16 -0
- package/hooks/features/history/gridHistorySelectors.js +13 -0
- package/hooks/features/history/index.d.ts +3 -0
- package/hooks/features/history/index.js +43 -0
- package/hooks/features/history/useGridHistory.d.ts +6 -0
- package/hooks/features/history/useGridHistory.js +303 -0
- package/hooks/features/index.d.ts +2 -1
- package/hooks/features/index.js +11 -0
- package/hooks/utils/useGridChartIntegration.js +1 -0
- package/index.js +1 -1
- package/models/dataGridPremiumProps.d.ts +26 -1
- package/models/gridApiPremium.d.ts +2 -1
- package/models/gridStatePremium.d.ts +2 -0
- package/package.json +5 -5
- package/typeOverloads/modules.d.ts +25 -2
- package/typeOverloads/modules.js +1 -3
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty';
|
|
6
|
+
import debounce from '@mui/utils/debounce';
|
|
7
|
+
import { useGridEvent, useGridApiMethod, isUndoShortcut, isRedoShortcut, runIf, useGridNativeEventListener } from '@mui/x-data-grid-pro/internals';
|
|
8
|
+
import { gridHistoryCurrentPositionSelector, gridHistoryStackSelector, gridHistoryCanUndoSelector, gridHistoryCanRedoSelector } from "./gridHistorySelectors.js";
|
|
9
|
+
import { createDefaultHistoryHandlers } from "./defaultHistoryHandlers.js";
|
|
10
|
+
export const historyStateInitializer = state => {
|
|
11
|
+
return _extends({}, state, {
|
|
12
|
+
history: {
|
|
13
|
+
stack: [],
|
|
14
|
+
currentPosition: -1,
|
|
15
|
+
enabled: false
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
export const useGridHistory = (apiRef, props) => {
|
|
20
|
+
const {
|
|
21
|
+
historyStackSize,
|
|
22
|
+
onUndo,
|
|
23
|
+
onRedo,
|
|
24
|
+
historyValidationEvents
|
|
25
|
+
} = props;
|
|
26
|
+
|
|
27
|
+
// Use default history events if none provided
|
|
28
|
+
const historyEventHandlers = React.useMemo(() => {
|
|
29
|
+
if (props.historyEventHandlers && !isObjectEmpty(props.historyEventHandlers)) {
|
|
30
|
+
return props.historyEventHandlers;
|
|
31
|
+
}
|
|
32
|
+
return createDefaultHistoryHandlers(apiRef, {
|
|
33
|
+
dataSource: props.dataSource,
|
|
34
|
+
columns: props.columns,
|
|
35
|
+
isCellEditable: props.isCellEditable
|
|
36
|
+
});
|
|
37
|
+
}, [apiRef, props.columns, props.isCellEditable, props.dataSource, props.historyEventHandlers]);
|
|
38
|
+
const isEnabled = React.useMemo(() => historyStackSize > 0 && !isObjectEmpty(historyEventHandlers), [historyStackSize, historyEventHandlers]);
|
|
39
|
+
const isValidationNeeded = React.useMemo(() => isEnabled && historyValidationEvents.length > 0 && Object.values(historyEventHandlers).some(handler => handler.validate), [isEnabled, historyEventHandlers, historyValidationEvents]);
|
|
40
|
+
|
|
41
|
+
// Internal ref to track undo/redo operation state
|
|
42
|
+
// - 'idle': everything is done
|
|
43
|
+
// - 'in-progress': during async undo/redo handler execution (skip validation and prevent the state change by other events)
|
|
44
|
+
// - 'waiting-replay': after undo/redo handler is done, the validation event is triggered again (as undo/redo is changing the state).
|
|
45
|
+
// In this hook we want to skip the replayed event.
|
|
46
|
+
const operationStateRef = React.useRef('idle');
|
|
47
|
+
|
|
48
|
+
// History event unsubscribers
|
|
49
|
+
const eventUnsubscribersRef = React.useRef([]);
|
|
50
|
+
// Validation event unsubscribers
|
|
51
|
+
const validationEventUnsubscribersRef = React.useRef([]);
|
|
52
|
+
const updateHistoryState = React.useCallback(newState => {
|
|
53
|
+
apiRef.current.setState(state => _extends({}, state, {
|
|
54
|
+
history: _extends({}, state.history, newState)
|
|
55
|
+
}));
|
|
56
|
+
}, [apiRef]);
|
|
57
|
+
const addToStack = React.useCallback(item => {
|
|
58
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
59
|
+
let newStack = [...gridHistoryStackSelector(apiRef)];
|
|
60
|
+
|
|
61
|
+
// If we're not at the end of the stack, truncate forward history
|
|
62
|
+
if (currentPosition < newStack.length - 1) {
|
|
63
|
+
newStack = newStack.slice(0, currentPosition + 1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Add the new item
|
|
67
|
+
newStack.push(item);
|
|
68
|
+
|
|
69
|
+
// If stack exceeds size, remove oldest items
|
|
70
|
+
if (newStack.length > historyStackSize) {
|
|
71
|
+
newStack = newStack.slice(newStack.length - historyStackSize);
|
|
72
|
+
}
|
|
73
|
+
updateHistoryState({
|
|
74
|
+
stack: newStack,
|
|
75
|
+
currentPosition: newStack.length - 1
|
|
76
|
+
});
|
|
77
|
+
}, [apiRef, updateHistoryState, historyStackSize]);
|
|
78
|
+
const clear = React.useCallback(() => {
|
|
79
|
+
updateHistoryState({
|
|
80
|
+
stack: [],
|
|
81
|
+
currentPosition: -1
|
|
82
|
+
});
|
|
83
|
+
}, [updateHistoryState]);
|
|
84
|
+
const clearUndoItems = React.useCallback(() => {
|
|
85
|
+
const stack = gridHistoryStackSelector(apiRef);
|
|
86
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
87
|
+
|
|
88
|
+
// If we're at the end of the stack (no redo items), clear everything
|
|
89
|
+
if (currentPosition >= stack.length - 1) {
|
|
90
|
+
clear();
|
|
91
|
+
} else {
|
|
92
|
+
updateHistoryState({
|
|
93
|
+
stack: stack.slice(currentPosition + 1),
|
|
94
|
+
currentPosition: -1
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}, [apiRef, clear, updateHistoryState]);
|
|
98
|
+
const clearRedoItems = React.useCallback(() => {
|
|
99
|
+
const stack = gridHistoryStackSelector(apiRef);
|
|
100
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
101
|
+
updateHistoryState({
|
|
102
|
+
stack: stack.slice(0, currentPosition + 1)
|
|
103
|
+
});
|
|
104
|
+
}, [apiRef, updateHistoryState]);
|
|
105
|
+
const canUndo = React.useCallback(() => gridHistoryCanUndoSelector(apiRef), [apiRef]);
|
|
106
|
+
const canRedo = React.useCallback(() => gridHistoryCanRedoSelector(apiRef), [apiRef]);
|
|
107
|
+
const validateStackItems = React.useCallback(() => {
|
|
108
|
+
/**
|
|
109
|
+
* When:
|
|
110
|
+
* - idle: continue with the validation
|
|
111
|
+
* - in-progress: skip the validation and don't change the state
|
|
112
|
+
* - waiting-replay: skip the validation this time and reset the state to idle
|
|
113
|
+
*/
|
|
114
|
+
if (operationStateRef.current !== 'idle') {
|
|
115
|
+
if (operationStateRef.current === 'waiting-replay') {
|
|
116
|
+
operationStateRef.current = 'idle';
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const stack = gridHistoryStackSelector(apiRef);
|
|
121
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
122
|
+
if (historyStackSize === 0) {
|
|
123
|
+
if (stack.length > 0) {
|
|
124
|
+
clear();
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (stack.length === 0) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const newStack = [...stack];
|
|
132
|
+
|
|
133
|
+
// Redo check
|
|
134
|
+
if (currentPosition + 1 < newStack.length) {
|
|
135
|
+
const item = newStack[currentPosition + 1];
|
|
136
|
+
const handler = historyEventHandlers[item.eventName];
|
|
137
|
+
if (!handler) {
|
|
138
|
+
clearRedoItems();
|
|
139
|
+
} else {
|
|
140
|
+
const isValid = handler.validate ? handler.validate(item.data, 'redo') : true;
|
|
141
|
+
if (!isValid) {
|
|
142
|
+
clearRedoItems();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Undo check
|
|
148
|
+
if (currentPosition >= 0) {
|
|
149
|
+
const item = newStack[currentPosition];
|
|
150
|
+
const handler = historyEventHandlers[item.eventName];
|
|
151
|
+
if (!handler) {
|
|
152
|
+
clearUndoItems();
|
|
153
|
+
} else {
|
|
154
|
+
const isValid = handler.validate ? handler.validate(item.data, 'undo') : true;
|
|
155
|
+
if (!isValid) {
|
|
156
|
+
clearUndoItems();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}, [apiRef, historyEventHandlers, historyStackSize, clear, clearUndoItems, clearRedoItems]);
|
|
161
|
+
const debouncedValidateStackItems = React.useMemo(() => debounce(validateStackItems, 0), [validateStackItems]);
|
|
162
|
+
const apply = React.useCallback(async (item, operation) => {
|
|
163
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
164
|
+
const clearMethod = operation === 'undo' ? clearUndoItems : clearRedoItems;
|
|
165
|
+
const {
|
|
166
|
+
eventName,
|
|
167
|
+
data
|
|
168
|
+
} = item;
|
|
169
|
+
const handler = historyEventHandlers[eventName];
|
|
170
|
+
if (!handler) {
|
|
171
|
+
// If the handler is not found, it means tha we are updating the handlers map, so we can igore this request
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
const isValid = handler.validate ? handler.validate(data, operation) : true;
|
|
175
|
+
|
|
176
|
+
// The data is validated every time state change event happens.
|
|
177
|
+
// We can get into a situation where the operation is not valid at this point only with the direct state updates.
|
|
178
|
+
if (!isValid) {
|
|
179
|
+
// Clear history and return false
|
|
180
|
+
clearMethod();
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Execute the operation
|
|
185
|
+
operationStateRef.current = 'in-progress';
|
|
186
|
+
await handler[operation](data);
|
|
187
|
+
operationStateRef.current = 'waiting-replay';
|
|
188
|
+
updateHistoryState({
|
|
189
|
+
currentPosition: operation === 'undo' ? currentPosition - 1 : currentPosition + 1
|
|
190
|
+
});
|
|
191
|
+
apiRef.current.publishEvent(operation, {
|
|
192
|
+
eventName,
|
|
193
|
+
data
|
|
194
|
+
});
|
|
195
|
+
// If there are no validations in the current setup, skip calling it and change the operation state to idle
|
|
196
|
+
if (isValidationNeeded) {
|
|
197
|
+
validateStackItems();
|
|
198
|
+
} else {
|
|
199
|
+
operationStateRef.current = 'idle';
|
|
200
|
+
}
|
|
201
|
+
return true;
|
|
202
|
+
}, [apiRef, isValidationNeeded, historyEventHandlers, clearUndoItems, clearRedoItems, updateHistoryState, validateStackItems]);
|
|
203
|
+
const undo = React.useCallback(async () => {
|
|
204
|
+
if (!canUndo()) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const stack = gridHistoryStackSelector(apiRef);
|
|
208
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
209
|
+
return apply(stack[currentPosition], 'undo');
|
|
210
|
+
}, [apiRef, apply, canUndo]);
|
|
211
|
+
const redo = React.useCallback(async () => {
|
|
212
|
+
if (!canRedo()) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const stack = gridHistoryStackSelector(apiRef);
|
|
216
|
+
const currentPosition = gridHistoryCurrentPositionSelector(apiRef);
|
|
217
|
+
return apply(stack[currentPosition + 1], 'redo');
|
|
218
|
+
}, [apiRef, apply, canRedo]);
|
|
219
|
+
const historyApi = {
|
|
220
|
+
undo,
|
|
221
|
+
redo,
|
|
222
|
+
clear,
|
|
223
|
+
canUndo,
|
|
224
|
+
canRedo
|
|
225
|
+
};
|
|
226
|
+
useGridApiMethod(apiRef, {
|
|
227
|
+
history: historyApi
|
|
228
|
+
}, 'public');
|
|
229
|
+
const handleKeyDown = React.useCallback(async event => {
|
|
230
|
+
if (!isUndoShortcut(event) && !isRedoShortcut(event)) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const action = isUndoShortcut(event) ? apiRef.current.history.undo : apiRef.current.history.redo;
|
|
234
|
+
event.preventDefault();
|
|
235
|
+
event.stopPropagation();
|
|
236
|
+
await action();
|
|
237
|
+
}, [apiRef]);
|
|
238
|
+
useGridNativeEventListener(apiRef, () => apiRef.current.rootElementRef.current, 'keydown', runIf(isEnabled, handleKeyDown));
|
|
239
|
+
useGridEvent(apiRef, 'undo', onUndo);
|
|
240
|
+
useGridEvent(apiRef, 'redo', onRedo);
|
|
241
|
+
React.useEffect(() => {
|
|
242
|
+
updateHistoryState({
|
|
243
|
+
enabled: isEnabled
|
|
244
|
+
});
|
|
245
|
+
}, [isEnabled, updateHistoryState]);
|
|
246
|
+
React.useEffect(() => {
|
|
247
|
+
if (!isValidationNeeded) {
|
|
248
|
+
return () => {};
|
|
249
|
+
}
|
|
250
|
+
historyValidationEvents.forEach(eventName => {
|
|
251
|
+
validationEventUnsubscribersRef.current.push(apiRef.current.subscribeEvent(eventName, debouncedValidateStackItems));
|
|
252
|
+
});
|
|
253
|
+
return () => {
|
|
254
|
+
validationEventUnsubscribersRef.current.forEach(unsubscribe => unsubscribe());
|
|
255
|
+
validationEventUnsubscribersRef.current = [];
|
|
256
|
+
};
|
|
257
|
+
}, [apiRef, isValidationNeeded, historyValidationEvents, debouncedValidateStackItems]);
|
|
258
|
+
React.useEffect(() => {
|
|
259
|
+
if (historyStackSize === 0) {
|
|
260
|
+
return () => {};
|
|
261
|
+
}
|
|
262
|
+
const events = Object.keys(historyEventHandlers);
|
|
263
|
+
// Subscribe to all events in the map
|
|
264
|
+
events.forEach(eventName => {
|
|
265
|
+
const handler = historyEventHandlers[eventName];
|
|
266
|
+
const unsubscribe = apiRef.current.subscribeEvent(eventName, (...params) => {
|
|
267
|
+
// Don't store if the event was triggered by undo/redo
|
|
268
|
+
if (operationStateRef.current !== 'idle') {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const data = handler.store(...params);
|
|
272
|
+
if (data !== null) {
|
|
273
|
+
addToStack({
|
|
274
|
+
eventName,
|
|
275
|
+
data
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
eventUnsubscribersRef.current.push(unsubscribe);
|
|
280
|
+
});
|
|
281
|
+
return () => {
|
|
282
|
+
eventUnsubscribersRef.current.forEach(unsubscribe => unsubscribe());
|
|
283
|
+
eventUnsubscribersRef.current = [];
|
|
284
|
+
};
|
|
285
|
+
}, [apiRef, historyEventHandlers, historyStackSize, addToStack]);
|
|
286
|
+
|
|
287
|
+
// If the stack size is changed and it is smaller than the current stack size, clear the stack
|
|
288
|
+
React.useEffect(() => {
|
|
289
|
+
const currentStackSize = gridHistoryStackSelector(apiRef).length;
|
|
290
|
+
if (currentStackSize > historyStackSize) {
|
|
291
|
+
clear();
|
|
292
|
+
}
|
|
293
|
+
}, [apiRef, historyStackSize, clear]);
|
|
294
|
+
};
|
|
@@ -4,4 +4,5 @@ export * from "./export/index.js";
|
|
|
4
4
|
export * from "./cellSelection/index.js";
|
|
5
5
|
export * from "./aiAssistant/index.js";
|
|
6
6
|
export * from "./sidebar/index.js";
|
|
7
|
-
export * from "./pivoting/index.js";
|
|
7
|
+
export * from "./pivoting/index.js";
|
|
8
|
+
export * from "./history/index.js";
|
|
@@ -5,4 +5,5 @@ export * from "./export/index.js";
|
|
|
5
5
|
export * from "./cellSelection/index.js";
|
|
6
6
|
export * from "./aiAssistant/index.js";
|
|
7
7
|
export * from "./sidebar/index.js";
|
|
8
|
-
export * from "./pivoting/index.js";
|
|
8
|
+
export * from "./pivoting/index.js";
|
|
9
|
+
export * from "./history/index.js";
|
package/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RefObject } from '@mui/x-internals/types';
|
|
2
|
-
import { GridCallbackDetails, GridValidRowModel, GridGroupNode, GridEventListener, GridGetRowsError, GridUpdateRowError, type GridColDef, GridLocaleTextApi } from '@mui/x-data-grid-pro';
|
|
2
|
+
import { GridCallbackDetails, GridValidRowModel, GridGroupNode, GridEventListener, GridGetRowsError, GridUpdateRowError, type GridColDef, GridLocaleTextApi, type GridEvents } from '@mui/x-data-grid-pro';
|
|
3
3
|
import { GridExperimentalProFeatures, DataGridProPropsWithDefaultValue, DataGridProPropsWithoutDefaultValue, DataGridPropsWithComplexDefaultValueAfterProcessing, DataGridPropsWithComplexDefaultValueBeforeProcessing, DataGridPremiumSharedPropsWithDefaultValue } from '@mui/x-data-grid-pro/internals';
|
|
4
4
|
import type { GridRowGroupingModel } from "../hooks/features/rowGrouping/index.js";
|
|
5
5
|
import type { GridAggregationModel, GridAggregationFunction, GridAggregationFunctionDataSource, GridAggregationPosition } from "../hooks/features/aggregation/index.js";
|
|
@@ -11,6 +11,7 @@ import { GridCellSelectionModel } from "../hooks/features/cellSelection/index.js
|
|
|
11
11
|
import type { GridPivotingColDefOverrides, PivotingColDefCallback, GridPivotModel } from "../hooks/features/pivoting/gridPivotingInterfaces.js";
|
|
12
12
|
import { GridDataSourcePremium as GridDataSource, GridGetRowsParamsPremium as GridGetRowsParams } from "../hooks/features/dataSource/models.js";
|
|
13
13
|
import { Conversation, PromptResponse, PromptSuggestion } from "../hooks/features/aiAssistant/gridAiAssistantInterfaces.js";
|
|
14
|
+
import type { GridHistoryEventHandler } from "../hooks/features/history/gridHistoryInterfaces.js";
|
|
14
15
|
export interface GridExperimentalPremiumFeatures extends GridExperimentalProFeatures {
|
|
15
16
|
charts?: boolean;
|
|
16
17
|
}
|
|
@@ -101,6 +102,22 @@ export interface DataGridPremiumPropsWithDefaultValue<R extends GridValidRowMode
|
|
|
101
102
|
* @default false
|
|
102
103
|
*/
|
|
103
104
|
chartsIntegration: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* The maximum size of the history stack.
|
|
107
|
+
* Set to 0 to disable the undo/redo feature.
|
|
108
|
+
* @default 30
|
|
109
|
+
*/
|
|
110
|
+
historyStackSize: number;
|
|
111
|
+
/**
|
|
112
|
+
* Map of grid events to their undo/redo handlers.
|
|
113
|
+
* @default Handlers for `rowEditStop`, `cellEditStop` and `clipboardPasteEnd` events
|
|
114
|
+
*/
|
|
115
|
+
historyEventHandlers: Record<GridEvents, GridHistoryEventHandler<any>>;
|
|
116
|
+
/**
|
|
117
|
+
* List of grid events after which the history stack items should be re-validated.
|
|
118
|
+
* @default ['columnsChange', 'rowsSet', 'sortedRowsSet', 'filteredRowsSet', 'paginationModelChange']
|
|
119
|
+
*/
|
|
120
|
+
historyValidationEvents: GridEvents[];
|
|
104
121
|
}
|
|
105
122
|
export interface DataGridPremiumPropsWithoutDefaultValue<R extends GridValidRowModel = any> extends Omit<DataGridProPropsWithoutDefaultValue<R>, 'initialState' | 'apiRef' | 'dataSource' | 'onDataSourceError'> {
|
|
106
123
|
/**
|
|
@@ -292,4 +309,12 @@ export interface DataGridPremiumPropsWithoutDefaultValue<R extends GridValidRowM
|
|
|
292
309
|
* @param {string} activeChartId The new active chart id.
|
|
293
310
|
*/
|
|
294
311
|
onActiveChartIdChange?: (activeChartId: string) => void;
|
|
312
|
+
/**
|
|
313
|
+
* Callback fired when an undo operation is executed.
|
|
314
|
+
*/
|
|
315
|
+
onUndo?: GridEventListener<'undo'>;
|
|
316
|
+
/**
|
|
317
|
+
* Callback fired when a redo operation is executed.
|
|
318
|
+
*/
|
|
319
|
+
onRedo?: GridEventListener<'redo'>;
|
|
295
320
|
}
|
|
@@ -11,9 +11,10 @@ import type { GridPivotingApi, GridPivotingPrivateApi } from "../hooks/features/
|
|
|
11
11
|
import { GridAiAssistantApi } from "../hooks/features/aiAssistant/gridAiAssistantInterfaces.js";
|
|
12
12
|
import { GridSidebarApi } from "../hooks/features/sidebar/gridSidebarInterfaces.js";
|
|
13
13
|
import { GridChartsIntegrationApi, GridChartsIntegrationPrivateApi } from "../hooks/features/chartsIntegration/gridChartsIntegrationInterfaces.js";
|
|
14
|
+
import type { GridHistoryApi } from "../hooks/features/history/gridHistoryInterfaces.js";
|
|
14
15
|
/**
|
|
15
16
|
* The api of Data Grid Premium.
|
|
16
17
|
* TODO: Do not redefine manually the pro features
|
|
17
18
|
*/
|
|
18
|
-
export interface GridApiPremium extends GridApiCommon<GridStatePremium, GridInitialStatePremium>, GridRowProApi, GridColumnPinningApi, GridDetailPanelApi, GridRowGroupingApi, GridExcelExportApi, GridAggregationApi, GridRowPinningApi, GridDataSourceApiPremium, GridCellSelectionApi, GridPivotingApi, GridAiAssistantApi, GridSidebarApi, GridChartsIntegrationApi, GridRowMultiSelectionApi, GridColumnReorderApi {}
|
|
19
|
+
export interface GridApiPremium extends GridApiCommon<GridStatePremium, GridInitialStatePremium>, GridRowProApi, GridColumnPinningApi, GridDetailPanelApi, GridRowGroupingApi, GridExcelExportApi, GridAggregationApi, GridRowPinningApi, GridDataSourceApiPremium, GridCellSelectionApi, GridPivotingApi, GridAiAssistantApi, GridSidebarApi, GridChartsIntegrationApi, GridHistoryApi, GridRowMultiSelectionApi, GridColumnReorderApi {}
|
|
19
20
|
export interface GridPrivateApiPremium extends GridApiPremium, GridPrivateOnlyApiCommon<GridApiPremium, GridPrivateApiPremium, DataGridPremiumProcessedProps>, GridDataSourcePremiumPrivateApi, GridAggregationPrivateApi, GridDetailPanelPrivateApi, GridRowReorderPrivateApi, GridPivotingPrivateApi, GridChartsIntegrationPrivateApi {}
|
|
@@ -4,6 +4,7 @@ import type { GridPivotingInitialState, GridPivotingState } from "../hooks/featu
|
|
|
4
4
|
import type { GridAiAssistantInitialState, GridAiAssistantState } from "../hooks/features/aiAssistant/gridAiAssistantInterfaces.js";
|
|
5
5
|
import type { GridSidebarInitialState, GridSidebarState } from "../hooks/features/sidebar/gridSidebarState.js";
|
|
6
6
|
import type { GridChartsIntegrationState, GridChartsIntegrationInitialState } from "../hooks/features/chartsIntegration/gridChartsIntegrationInterfaces.js";
|
|
7
|
+
import type { GridHistoryState } from "../hooks/features/history/gridHistoryInterfaces.js";
|
|
7
8
|
/**
|
|
8
9
|
* The state of Data Grid Premium.
|
|
9
10
|
*/
|
|
@@ -15,6 +16,7 @@ export interface GridStatePremium extends GridStatePro {
|
|
|
15
16
|
aiAssistant: GridAiAssistantState;
|
|
16
17
|
sidebar: GridSidebarState;
|
|
17
18
|
chartsIntegration: GridChartsIntegrationState;
|
|
19
|
+
history: GridHistoryState;
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
* The initial state of Data Grid Premium.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { GridEventLookup, GridExportDisplayOptions, GridRowId, GridValidRowModel } from '@mui/x-data-grid-pro';
|
|
2
2
|
import type { GridAggregationCellMeta } from '@mui/x-data-grid-pro/internals';
|
|
3
3
|
import type { GridPipeProcessingLookupPro, GridControlledStateEventLookupPro, GridApiCachesPro, GridEventLookupPro } from '@mui/x-data-grid-pro/typeOverloads';
|
|
4
4
|
import type { GridGroupingValueGetter, GridGroupingValueSetter, GridPastedValueParser } from "../models/index.js";
|
|
@@ -79,7 +79,12 @@ interface GridEventLookupPremium extends GridEventLookupPro {
|
|
|
79
79
|
/**
|
|
80
80
|
* Fired when the clipboard paste operation ends.
|
|
81
81
|
*/
|
|
82
|
-
clipboardPasteEnd: {
|
|
82
|
+
clipboardPasteEnd: {
|
|
83
|
+
params: {
|
|
84
|
+
oldRows: Map<GridRowId, GridValidRowModel>;
|
|
85
|
+
newRows: Map<GridRowId, GridValidRowModel>;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
83
88
|
/**
|
|
84
89
|
* Fired when the sidebar is opened.
|
|
85
90
|
*/
|
|
@@ -105,6 +110,24 @@ interface GridEventLookupPremium extends GridEventLookupPro {
|
|
|
105
110
|
synced: boolean;
|
|
106
111
|
};
|
|
107
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* Fired when an undo operation is executed.
|
|
115
|
+
*/
|
|
116
|
+
undo: {
|
|
117
|
+
params: {
|
|
118
|
+
eventName: keyof GridEventLookup;
|
|
119
|
+
data: any;
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Fired when a redo operation is executed.
|
|
124
|
+
*/
|
|
125
|
+
redo: {
|
|
126
|
+
params: {
|
|
127
|
+
eventName: keyof GridEventLookup;
|
|
128
|
+
data: any;
|
|
129
|
+
};
|
|
130
|
+
};
|
|
108
131
|
}
|
|
109
132
|
export interface GridColDefPremium<R extends GridValidRowModel = any, V = any, F = V> {
|
|
110
133
|
/**
|
|
@@ -61,7 +61,7 @@ async function getTextFromClipboard(rootEl) {
|
|
|
61
61
|
|
|
62
62
|
// Keeps track of updated rows during clipboard paste
|
|
63
63
|
class CellValueUpdater {
|
|
64
|
-
rowsToUpdate =
|
|
64
|
+
rowsToUpdate = new Map();
|
|
65
65
|
constructor(options) {
|
|
66
66
|
this.options = options;
|
|
67
67
|
this.updateRow = batchRowUpdates(options.apiRef.current.updateRows, 50);
|
|
@@ -82,7 +82,7 @@ class CellValueUpdater {
|
|
|
82
82
|
if (!colDef || !colDef.editable) {
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
|
-
const row = this.rowsToUpdate
|
|
85
|
+
const row = this.rowsToUpdate.get(rowId) || (0, _extends2.default)({}, apiRef.current.getRow(rowId));
|
|
86
86
|
if (!row) {
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
@@ -112,7 +112,7 @@ class CellValueUpdater {
|
|
|
112
112
|
// We cannot update row id, so this cell value update should be ignored
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
|
-
this.rowsToUpdate
|
|
115
|
+
this.rowsToUpdate.set(rowId, rowCopy);
|
|
116
116
|
}
|
|
117
117
|
applyUpdates() {
|
|
118
118
|
const {
|
|
@@ -121,13 +121,20 @@ class CellValueUpdater {
|
|
|
121
121
|
onProcessRowUpdateError
|
|
122
122
|
} = this.options;
|
|
123
123
|
const rowsToUpdate = this.rowsToUpdate;
|
|
124
|
-
const rowIdsToUpdate =
|
|
124
|
+
const rowIdsToUpdate = Array.from(rowsToUpdate.keys());
|
|
125
125
|
if (rowIdsToUpdate.length === 0) {
|
|
126
|
-
apiRef.current.publishEvent('clipboardPasteEnd'
|
|
126
|
+
apiRef.current.publishEvent('clipboardPasteEnd', {
|
|
127
|
+
oldRows: new Map(),
|
|
128
|
+
newRows: new Map()
|
|
129
|
+
});
|
|
127
130
|
return;
|
|
128
131
|
}
|
|
132
|
+
const oldRows = new Map();
|
|
133
|
+
const newRows = new Map();
|
|
129
134
|
const handleRowUpdate = async rowId => {
|
|
130
|
-
const
|
|
135
|
+
const oldRow = apiRef.current.getRow(rowId);
|
|
136
|
+
const newRow = rowsToUpdate.get(rowId);
|
|
137
|
+
oldRows.set(rowId, oldRow);
|
|
131
138
|
if (typeof processRowUpdate === 'function') {
|
|
132
139
|
const handleError = errorThrown => {
|
|
133
140
|
if (onProcessRowUpdateError) {
|
|
@@ -137,15 +144,16 @@ class CellValueUpdater {
|
|
|
137
144
|
}
|
|
138
145
|
};
|
|
139
146
|
try {
|
|
140
|
-
const oldRow = apiRef.current.getRow(rowId);
|
|
141
147
|
const finalRowUpdate = await processRowUpdate(newRow, oldRow, {
|
|
142
148
|
rowId
|
|
143
149
|
});
|
|
150
|
+
newRows.set(rowId, finalRowUpdate);
|
|
144
151
|
this.updateRow(finalRowUpdate);
|
|
145
152
|
} catch (error) {
|
|
146
153
|
handleError(error);
|
|
147
154
|
}
|
|
148
155
|
} else {
|
|
156
|
+
newRows.set(rowId, newRow);
|
|
149
157
|
this.updateRow(newRow);
|
|
150
158
|
}
|
|
151
159
|
};
|
|
@@ -157,8 +165,11 @@ class CellValueUpdater {
|
|
|
157
165
|
});
|
|
158
166
|
});
|
|
159
167
|
Promise.all(promises).then(() => {
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
apiRef.current.publishEvent('clipboardPasteEnd', {
|
|
169
|
+
oldRows,
|
|
170
|
+
newRows
|
|
171
|
+
});
|
|
172
|
+
this.rowsToUpdate.clear();
|
|
162
173
|
});
|
|
163
174
|
}
|
|
164
175
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.DEFAULT_HISTORY_VALIDATION_EVENTS = void 0;
|
|
7
|
+
const DEFAULT_HISTORY_VALIDATION_EVENTS = exports.DEFAULT_HISTORY_VALIDATION_EVENTS = ['columnsChange', 'rowsSet', 'sortedRowsSet', 'filteredRowsSet', 'paginationModelChange'];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RefObject } from '@mui/x-internals/types';
|
|
2
|
+
import type { GridApiPremium } from "../../../models/gridApiPremium.js";
|
|
3
|
+
import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
|
|
4
|
+
import type { GridHistoryEventHandler, GridCellEditHistoryData, GridRowEditHistoryData, GridClipboardPasteHistoryData } from "./gridHistoryInterfaces.js";
|
|
5
|
+
/**
|
|
6
|
+
* Create the default handler for cellEditStop events.
|
|
7
|
+
*/
|
|
8
|
+
export declare const createCellEditHistoryHandler: (apiRef: RefObject<GridApiPremium>) => GridHistoryEventHandler<GridCellEditHistoryData>;
|
|
9
|
+
/**
|
|
10
|
+
* Create the default handler for rowEditStop events.
|
|
11
|
+
*/
|
|
12
|
+
export declare const createRowEditHistoryHandler: (apiRef: RefObject<GridApiPremium>) => GridHistoryEventHandler<GridRowEditHistoryData>;
|
|
13
|
+
/**
|
|
14
|
+
* Create the default handler for clipboardPasteEnd events.
|
|
15
|
+
*/
|
|
16
|
+
export declare const createClipboardPasteHistoryHandler: (apiRef: RefObject<GridApiPremium>) => GridHistoryEventHandler<GridClipboardPasteHistoryData>;
|
|
17
|
+
/**
|
|
18
|
+
* Create the default history events map.
|
|
19
|
+
*/
|
|
20
|
+
export declare const createDefaultHistoryHandlers: (apiRef: RefObject<GridApiPremium>, props: Pick<DataGridPremiumProcessedProps, "columns" | "isCellEditable" | "dataSource">) => Record<keyof import("@mui/x-data-grid").GridEventLookup, GridHistoryEventHandler<GridCellEditHistoryData> | GridHistoryEventHandler<GridRowEditHistoryData> | GridHistoryEventHandler<GridClipboardPasteHistoryData>>;
|