@mui/x-data-grid 9.12.0 → 9.13.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 (74) hide show
  1. package/CHANGELOG.md +152 -0
  2. package/DataGrid/DataGrid.js +1 -1
  3. package/DataGrid/DataGrid.mjs +1 -1
  4. package/components/GridPagination.js +1 -1
  5. package/components/GridPagination.mjs +1 -1
  6. package/components/GridRow.d.mts +1 -0
  7. package/components/GridRow.d.ts +1 -0
  8. package/components/GridRow.js +41 -6
  9. package/components/GridRow.mjs +41 -6
  10. package/components/cell/GridCell.js +7 -4
  11. package/components/cell/GridCell.mjs +7 -4
  12. package/components/cell/GridEditBooleanCell.d.mts +1 -1
  13. package/components/cell/GridEditBooleanCell.d.ts +1 -1
  14. package/components/cell/GridEditBooleanCell.js +4 -4
  15. package/components/cell/GridEditBooleanCell.mjs +4 -4
  16. package/components/cell/GridEditDateCell.d.mts +1 -1
  17. package/components/cell/GridEditDateCell.d.ts +1 -1
  18. package/components/cell/GridEditDateCell.js +5 -5
  19. package/components/cell/GridEditDateCell.mjs +5 -5
  20. package/components/cell/GridEditInputCell.d.mts +1 -1
  21. package/components/cell/GridEditInputCell.d.ts +1 -1
  22. package/components/cell/GridEditInputCell.js +1 -1
  23. package/components/cell/GridEditInputCell.mjs +1 -1
  24. package/components/cell/GridEditLongTextCell.d.mts +1 -1
  25. package/components/cell/GridEditLongTextCell.d.ts +1 -1
  26. package/components/cell/GridEditLongTextCell.js +2 -2
  27. package/components/cell/GridEditLongTextCell.mjs +2 -2
  28. package/components/cell/GridEditSingleSelectCell.d.mts +1 -1
  29. package/components/cell/GridEditSingleSelectCell.d.ts +1 -1
  30. package/components/cell/GridEditSingleSelectCell.js +4 -4
  31. package/components/cell/GridEditSingleSelectCell.mjs +4 -4
  32. package/components/toolbarV8/Toolbar.d.mts +5 -1
  33. package/components/toolbarV8/Toolbar.d.ts +5 -1
  34. package/components/toolbarV8/Toolbar.js +34 -12
  35. package/components/toolbarV8/Toolbar.mjs +33 -11
  36. package/hooks/core/useGridVirtualizer.js +14 -1
  37. package/hooks/core/useGridVirtualizer.mjs +14 -1
  38. package/hooks/features/dataSource/models.d.mts +2 -2
  39. package/hooks/features/dataSource/models.d.ts +2 -2
  40. package/hooks/features/dataSource/useGridDataSourceBase.js +11 -7
  41. package/hooks/features/dataSource/useGridDataSourceBase.mjs +12 -8
  42. package/hooks/features/pivoting/gridPivotingInterfaces.d.mts +2 -2
  43. package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +2 -2
  44. package/hooks/features/rowSelection/useGridRowSelection.js +1 -1
  45. package/hooks/features/rowSelection/useGridRowSelection.mjs +2 -2
  46. package/hooks/features/rows/gridRowsUtils.d.mts +37 -3
  47. package/hooks/features/rows/gridRowsUtils.d.ts +37 -3
  48. package/hooks/features/rows/gridRowsUtils.js +120 -23
  49. package/hooks/features/rows/gridRowsUtils.mjs +115 -22
  50. package/hooks/features/rows/useGridRows.js +10 -1
  51. package/hooks/features/rows/useGridRows.mjs +10 -1
  52. package/index.js +1 -1
  53. package/index.mjs +1 -1
  54. package/internals/index.d.mts +2 -2
  55. package/internals/index.d.ts +2 -2
  56. package/internals/index.js +28 -0
  57. package/internals/index.mjs +2 -2
  58. package/material/variables.d.mts +6 -1
  59. package/material/variables.d.ts +6 -1
  60. package/material/variables.js +17 -3
  61. package/material/variables.mjs +14 -4
  62. package/models/api/gridRowApi.d.mts +7 -7
  63. package/models/api/gridRowApi.d.ts +7 -7
  64. package/models/gridDataSource.d.mts +3 -0
  65. package/models/gridDataSource.d.ts +3 -0
  66. package/models/gridRows.d.mts +28 -1
  67. package/models/gridRows.d.ts +28 -1
  68. package/models/props/DataGridProps.d.mts +3 -3
  69. package/models/props/DataGridProps.d.ts +3 -3
  70. package/package.json +6 -6
  71. package/utils/keyboardUtils.d.mts +1 -0
  72. package/utils/keyboardUtils.d.ts +1 -0
  73. package/utils/keyboardUtils.js +6 -0
  74. package/utils/keyboardUtils.mjs +5 -0
@@ -1,5 +1,5 @@
1
1
  import type { RefObject } from '@mui/x-internals/types';
2
- import type { GridAutoGeneratedGroupNode, GridAutoGeneratedPinnedRowNode, GridColDef, GridFooterNode, GridGroupNode, GridRowId, GridRowIdGetter, GridRowModel, GridRowModelUpdate, GridRowTreeConfig, GridSkeletonRowNode, GridTreeNode, GridValidRowModel } from "../../../models/index.js";
2
+ import type { GridAutoGeneratedGroupNode, GridAutoGeneratedPinnedRowNode, GridColDef, GridFooterNode, GridGroupNode, GridRowId, GridRowIdGetter, GridRowModel, GridRowModelUpdate, GridRowModelReplace, GridRowTreeConfig, GridSkeletonRowNode, GridTreeNode, GridValidRowModel } from "../../../models/index.js";
3
3
  import type { DataGridProcessedProps } from "../../../models/props/DataGridProps.js";
4
4
  import type { GridApiCommunity, GridPrivateApiCommunity } from "../../../models/api/gridApiCommunity.js";
5
5
  import type { GridRowsInternalCache, GridRowsState, GridRowTreeCreationParams } from "./gridRowsInterfaces.js";
@@ -43,6 +43,40 @@ export declare const getRowsStateFromCache: ({
43
43
  export declare const isAutogeneratedRow: (row: GridRowModel) => boolean;
44
44
  export declare const isAutogeneratedRowNode: (rowNode: GridTreeNode) => rowNode is GridFooterNode | GridSkeletonRowNode | GridAutoGeneratedGroupNode | GridAutoGeneratedPinnedRowNode;
45
45
  export declare const getTreeNodeDescendants: (tree: GridRowTreeConfig, parentId: GridRowId, skipAutoGeneratedRows: boolean, directChildrenOnly?: boolean) => GridRowId[];
46
+ export declare const isReplaceUpdate: (update: GridRowModelUpdate | GridRowModelReplace) => update is GridRowModelReplace;
47
+ /**
48
+ * Extracts the replacement row from a `{ _action: 'replace', row }` update.
49
+ * The marker lives on the throwaway envelope, so the row object itself is never touched.
50
+ * @param {GridRowModelReplace} update The update provided to `updateRows()`.
51
+ * @returns {GridRowModel} The object to store as the row, verbatim.
52
+ */
53
+ export declare const getReplaceRow: (update: GridRowModelReplace) => GridRowModel;
54
+ /**
55
+ * Merges a partial update into the existing row.
56
+ * Prototype-preservation rules:
57
+ * 1. If partialRow is a class instance (non-plain object), use its prototype — the
58
+ * caller is passing in a fully-constructed instance and owns the prototype chain.
59
+ * 2. If partialRow is a plain object (Object.prototype), prefer oldRow's prototype so
60
+ * that a partial-update object does not silently discard the existing row's class.
61
+ * 3. If both are plain objects the result is also a plain object (no-op).
62
+ *
63
+ * Note: private class fields (#field syntax) cannot be preserved through a spread-style
64
+ * merge because the brand check is tied to the original instance. Rows that rely on
65
+ * private fields must either supply a fully-constructed instance as partialRow (rule 1
66
+ * above) or use `_action: 'replace'` rather than a plain-object partial update.
67
+ * @param {GridRowModel} oldRow The row currently stored in the lookup.
68
+ * @param {GridRowModelUpdate} partialRow The update to merge into it.
69
+ * @returns {GridRowModel} The merged row.
70
+ */
71
+ export declare const mergeRowUpdate: (oldRow: GridRowModel, partialRow: GridRowModelUpdate) => GridRowModel;
72
+ /**
73
+ * Warns when a replace demotes a class instance to a plain object, which happens when the
74
+ * replacement was built with a spread instead of being passed as-is.
75
+ * Dev-only, does nothing in production.
76
+ * @param {GridRowModel | undefined} oldRow The row being replaced, if any.
77
+ * @param {GridRowModel} replacement The row provided in a `{ _action: 'replace', row }` update.
78
+ */
79
+ export declare const warnIfReplaceLosesPrototype: (oldRow: GridRowModel | undefined, replacement: GridRowModel) => void;
46
80
  export declare const updateCacheWithNewRows: ({
47
81
  previousCache,
48
82
  getRowId,
@@ -51,10 +85,10 @@ export declare const updateCacheWithNewRows: ({
51
85
  }: {
52
86
  previousCache: GridRowsInternalCache;
53
87
  getRowId: DataGridProcessedProps['getRowId'];
54
- updates: GridRowModelUpdate[];
88
+ updates: Array<GridRowModelUpdate | GridRowModelReplace>;
55
89
  groupKeys?: string[];
56
90
  }) => GridRowsInternalCache;
57
91
  export declare const minimalContentHeight = "var(--DataGrid-overlayHeight, calc(var(--height) * 2))";
58
- export declare function computeRowsUpdates(apiRef: RefObject<GridApiCommunity>, updates: GridRowModelUpdate[], getRowId: DataGridProcessedProps['getRowId']): GridRowModelUpdate[];
92
+ export declare function computeRowsUpdates(apiRef: RefObject<GridApiCommunity>, updates: Array<GridRowModelUpdate | GridRowModelReplace>, getRowId: DataGridProcessedProps['getRowId']): (GridRowModelReplace<GridValidRowModel> | GridRowModelUpdate)[];
59
93
  export declare const getValidRowHeight: (rowHeightProp: any, defaultRowHeight: number, warningMessage: string) => number;
60
94
  export declare const rowHeightWarning: string;
@@ -7,9 +7,10 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.buildRootGroup = exports.GRID_ROOT_GROUP_ID = exports.GRID_ID_AUTOGENERATED = void 0;
8
8
  exports.checkGridRowIdIsValid = checkGridRowIdIsValid;
9
9
  exports.computeRowsUpdates = computeRowsUpdates;
10
- exports.updateCacheWithNewRows = exports.rowHeightWarning = exports.minimalContentHeight = exports.isAutogeneratedRowNode = exports.isAutogeneratedRow = exports.getValidRowHeight = exports.getTreeNodeDescendants = exports.getTopLevelRowCount = exports.getRowsStateFromCache = exports.getRowValue = exports.getRowIdFromRowModel = exports.createRowsInternalCache = void 0;
10
+ exports.warnIfReplaceLosesPrototype = exports.updateCacheWithNewRows = exports.rowHeightWarning = exports.minimalContentHeight = exports.mergeRowUpdate = exports.isReplaceUpdate = exports.isAutogeneratedRowNode = exports.isAutogeneratedRow = exports.getValidRowHeight = exports.getTreeNodeDescendants = exports.getTopLevelRowCount = exports.getRowsStateFromCache = exports.getRowValue = exports.getRowIdFromRowModel = exports.getReplaceRow = exports.createRowsInternalCache = void 0;
11
11
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
12
12
  var _formatErrorMessage2 = _interopRequireDefault(require("@mui/x-internals/formatErrorMessage"));
13
+ var _warning = require("@mui/x-internals/warning");
13
14
  var _gridRowsSelector = require("./gridRowsSelector");
14
15
  const GRID_ROOT_GROUP_ID = exports.GRID_ROOT_GROUP_ID = `auto-generated-group-node-root`;
15
16
  const GRID_ID_AUTOGENERATED = exports.GRID_ID_AUTOGENERATED = Symbol('mui.id_autogenerated');
@@ -178,6 +179,83 @@ const getTreeNodeDescendants = (tree, parentId, skipAutoGeneratedRows, directChi
178
179
  return validDescendants;
179
180
  };
180
181
  exports.getTreeNodeDescendants = getTreeNodeDescendants;
182
+ const isReplaceUpdate = update =>
183
+ // eslint-disable-next-line no-underscore-dangle
184
+ update._action === 'replace';
185
+
186
+ /**
187
+ * Extracts the replacement row from a `{ _action: 'replace', row }` update.
188
+ * The marker lives on the throwaway envelope, so the row object itself is never touched.
189
+ * @param {GridRowModelReplace} update The update provided to `updateRows()`.
190
+ * @returns {GridRowModel} The object to store as the row, verbatim.
191
+ */
192
+ exports.isReplaceUpdate = isReplaceUpdate;
193
+ const getReplaceRow = update => {
194
+ const {
195
+ row
196
+ } = update;
197
+ if (row == null) {
198
+ throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Data Grid: A row update with \`_action: 'replace'\` was provided without a \`row\` property.
199
+ Without it, the Data Grid does not know which object to store for that row.
200
+ Provide the replacement object in the \`row\` property, for example \`updateRows([{ _action: 'replace', row }])\`.
201
+ For more detail, see https://mui.com/x/react-data-grid/row-updates/.` : (0, _formatErrorMessage2.default)(304));
202
+ }
203
+ return row;
204
+ };
205
+
206
+ /**
207
+ * Merges a partial update into the existing row.
208
+ * Prototype-preservation rules:
209
+ * 1. If partialRow is a class instance (non-plain object), use its prototype — the
210
+ * caller is passing in a fully-constructed instance and owns the prototype chain.
211
+ * 2. If partialRow is a plain object (Object.prototype), prefer oldRow's prototype so
212
+ * that a partial-update object does not silently discard the existing row's class.
213
+ * 3. If both are plain objects the result is also a plain object (no-op).
214
+ *
215
+ * Note: private class fields (#field syntax) cannot be preserved through a spread-style
216
+ * merge because the brand check is tied to the original instance. Rows that rely on
217
+ * private fields must either supply a fully-constructed instance as partialRow (rule 1
218
+ * above) or use `_action: 'replace'` rather than a plain-object partial update.
219
+ * @param {GridRowModel} oldRow The row currently stored in the lookup.
220
+ * @param {GridRowModelUpdate} partialRow The update to merge into it.
221
+ * @returns {GridRowModel} The merged row.
222
+ */
223
+ exports.getReplaceRow = getReplaceRow;
224
+ const mergeRowUpdate = (oldRow, partialRow) => {
225
+ const partialRowProto = Object.getPrototypeOf(partialRow);
226
+ const isPartialRowPlain = partialRowProto === Object.prototype || partialRowProto === null;
227
+ const proto = isPartialRowPlain ? Object.getPrototypeOf(oldRow) : partialRowProto;
228
+ const merged = Object.create(proto);
229
+ Object.assign(merged, oldRow, partialRow);
230
+ return merged;
231
+ };
232
+
233
+ /**
234
+ * Warns when a replace demotes a class instance to a plain object, which happens when the
235
+ * replacement was built with a spread instead of being passed as-is.
236
+ * Dev-only, does nothing in production.
237
+ * @param {GridRowModel | undefined} oldRow The row being replaced, if any.
238
+ * @param {GridRowModel} replacement The row provided in a `{ _action: 'replace', row }` update.
239
+ */
240
+ exports.mergeRowUpdate = mergeRowUpdate;
241
+ const warnIfReplaceLosesPrototype = (oldRow, replacement) => {
242
+ if (process.env.NODE_ENV === 'production' || !oldRow) {
243
+ return;
244
+ }
245
+ const replacementProto = Object.getPrototypeOf(replacement);
246
+ if (replacementProto !== Object.prototype && replacementProto !== null) {
247
+ return;
248
+ }
249
+ const oldRowProto = Object.getPrototypeOf(oldRow);
250
+ if (oldRowProto === Object.prototype || oldRowProto === null) {
251
+ return;
252
+ }
253
+
254
+ // The message must stay free of row-specific details: `warnOnce()` caches by message, so
255
+ // interpolating the id would log once per row and grow the cache with every update.
256
+ (0, _warning.warnOnce)(["MUI X Data Grid: A plain object was provided as the `row` of a `_action: 'replace'` update, but the row it replaces is a class instance.", "Building the replacement with a spread (`{ _action: 'replace', row: { ...row } }`) creates a plain object, dropping the prototype chain and the private fields that `_action: 'replace'` exists to preserve.", "Pass the instance itself instead, for example `{ _action: 'replace', row }`.", 'For more detail, see https://mui.com/x/react-data-grid/row-updates/.']);
257
+ };
258
+ exports.warnIfReplaceLosesPrototype = warnIfReplaceLosesPrototype;
181
259
  const updateCacheWithNewRows = ({
182
260
  previousCache,
183
261
  getRowId,
@@ -191,10 +269,28 @@ const updateCacheWithNewRows = ({
191
269
  // Remove duplicate updates.
192
270
  // A server can batch updates, and send several updates for the same row in one fn call.
193
271
  const uniqueUpdates = new Map();
272
+ // Ids whose accumulated update is stored as the row instead of being merged into the
273
+ // existing one. The flag lives outside the row object so that it is never mutated.
274
+ const replaceIds = new Set();
194
275
  updates.forEach(update => {
195
- const id = getRowIdFromRowModel(update, getRowId, 'A row was provided without id when calling updateRows():');
196
- if (uniqueUpdates.has(id)) {
197
- uniqueUpdates.set(id, (0, _extends2.default)({}, uniqueUpdates.get(id), update));
276
+ // A replace is provided as a `{ _action: 'replace', row }` envelope: the marker stays
277
+ // on the throwaway envelope and the inner row is used verbatim, so that the object
278
+ // provided by the caller is the one that ends up in the lookup.
279
+ const isReplace = isReplaceUpdate(update);
280
+ const row = isReplace ? getReplaceRow(update) : update;
281
+ const id = getRowIdFromRowModel(row, getRowId, 'A row was provided without id when calling updateRows():');
282
+ if (isReplace) {
283
+ // A replace resets whatever has been accumulated for that id.
284
+ uniqueUpdates.set(id, row);
285
+ replaceIds.add(id);
286
+ } else if (uniqueUpdates.has(id)) {
287
+ const accumulatedUpdate = uniqueUpdates.get(id);
288
+ if (process.env.NODE_ENV !== 'production' && replaceIds.has(id)) {
289
+ (0, _warning.warnOnce)(["MUI X Data Grid: A row was provided with `_action: 'replace'` but it is not the last update for that row in this batch.", 'The remaining updates are merged onto the replacement, so the row keeps its prototype but is neither the same object nor carries its `#private` fields, which a merge cannot copy.', 'Make the replace the last update for that row if `apiRef.current.getRow(id)` must return the object you passed in.', 'For more detail, see https://mui.com/x/react-data-grid/row-updates/.']);
290
+ }
291
+ // The merge keeps the accumulated entry's prototype and the id stays in `replaceIds`,
292
+ // so the result is still applied as a replace.
293
+ uniqueUpdates.set(id, mergeRowUpdate(accumulatedUpdate, update));
198
294
  } else {
199
295
  uniqueUpdates.set(id, update);
200
296
  }
@@ -246,6 +342,15 @@ const updateCacheWithNewRows = ({
246
342
  }
247
343
  const oldRow = dataRowIdToModelLookup[id];
248
344
 
345
+ // Action === "replace"
346
+ // The bookkeeping is the same as for "modify" / "insert" below, only the way the row
347
+ // is stored differs: the object is stored as-is so that its prototype chain, private
348
+ // fields (#field) and reference identity are all preserved.
349
+ const isReplace = replaceIds.has(id);
350
+ if (isReplace) {
351
+ warnIfReplaceLosesPrototype(oldRow, partialRow);
352
+ }
353
+
249
354
  // Action === "modify"
250
355
  if (oldRow) {
251
356
  // If the data row has been removed since the last state update,
@@ -261,23 +366,7 @@ const updateCacheWithNewRows = ({
261
366
  }
262
367
 
263
368
  // Update the data row lookups.
264
- // Prototype-preservation rules:
265
- // 1. If partialRow is a class instance (non-plain object), use its prototype — the
266
- // caller is passing in a fully-constructed instance and owns the prototype chain.
267
- // 2. If partialRow is a plain object (Object.prototype), prefer oldRow's prototype so
268
- // that a partial-update object does not silently discard the existing row's class.
269
- // 3. If both are plain objects the result is also a plain object (no-op).
270
- //
271
- // Note: private class fields (#field syntax) cannot be preserved through a spread-style
272
- // merge because the brand check is tied to the original instance. Rows that rely on
273
- // private fields must supply a fully-constructed instance as partialRow (rule 1 above)
274
- // rather than a plain-object partial update.
275
- const partialRowProto = Object.getPrototypeOf(partialRow);
276
- const isPartialRowPlain = partialRowProto === Object.prototype || partialRowProto === null;
277
- const proto = isPartialRowPlain ? Object.getPrototypeOf(oldRow) : partialRowProto;
278
- const merged = Object.create(proto);
279
- Object.assign(merged, oldRow, partialRow);
280
- dataRowIdToModelLookup[id] = merged;
369
+ dataRowIdToModelLookup[id] = isReplace ? partialRow : mergeRowUpdate(oldRow, partialRow);
281
370
  return;
282
371
  }
283
372
 
@@ -319,16 +408,24 @@ const minimalContentHeight = exports.minimalContentHeight = 'var(--DataGrid-over
319
408
  function computeRowsUpdates(apiRef, updates, getRowId) {
320
409
  const nonPinnedRowsUpdates = [];
321
410
  updates.forEach(update => {
322
- const id = getRowIdFromRowModel(update, getRowId, 'A row was provided without id when calling updateRows():');
411
+ const isReplace = isReplaceUpdate(update);
412
+ const row = isReplace ? getReplaceRow(update) : update;
413
+ const id = getRowIdFromRowModel(row, getRowId, 'A row was provided without id when calling updateRows():');
323
414
  const rowNode = (0, _gridRowsSelector.gridRowNodeSelector)(apiRef, id);
324
415
  if (rowNode?.type === 'pinnedRow') {
325
416
  // @ts-ignore because otherwise `release:build` doesn't work
326
417
  const pinnedRowsCache = apiRef.current.caches.pinnedRows;
327
418
  const prevModel = pinnedRowsCache.idLookup[id];
328
419
  if (prevModel) {
329
- pinnedRowsCache.idLookup[id] = (0, _extends2.default)({}, prevModel, update);
420
+ if (isReplace) {
421
+ warnIfReplaceLosesPrototype(prevModel, row);
422
+ pinnedRowsCache.idLookup[id] = row;
423
+ } else {
424
+ pinnedRowsCache.idLookup[id] = mergeRowUpdate(prevModel, update);
425
+ }
330
426
  }
331
427
  } else {
428
+ // The envelope is passed through untouched, `updateCacheWithNewRows` unwraps it.
332
429
  nonPinnedRowsUpdates.push(update);
333
430
  }
334
431
  });
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _formatErrorMessage from "@mui/x-internals/formatErrorMessage";
3
+ import { warnOnce } from '@mui/x-internals/warning';
3
4
  import { gridRowNodeSelector } from "./gridRowsSelector.mjs";
4
5
  export const GRID_ROOT_GROUP_ID = `auto-generated-group-node-root`;
5
6
  export const GRID_ID_AUTOGENERATED = Symbol('mui.id_autogenerated');
@@ -159,6 +160,79 @@ export const getTreeNodeDescendants = (tree, parentId, skipAutoGeneratedRows, di
159
160
  }
160
161
  return validDescendants;
161
162
  };
163
+ export const isReplaceUpdate = update =>
164
+ // eslint-disable-next-line no-underscore-dangle
165
+ update._action === 'replace';
166
+
167
+ /**
168
+ * Extracts the replacement row from a `{ _action: 'replace', row }` update.
169
+ * The marker lives on the throwaway envelope, so the row object itself is never touched.
170
+ * @param {GridRowModelReplace} update The update provided to `updateRows()`.
171
+ * @returns {GridRowModel} The object to store as the row, verbatim.
172
+ */
173
+ export const getReplaceRow = update => {
174
+ const {
175
+ row
176
+ } = update;
177
+ if (row == null) {
178
+ throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Data Grid: A row update with \`_action: 'replace'\` was provided without a \`row\` property.
179
+ Without it, the Data Grid does not know which object to store for that row.
180
+ Provide the replacement object in the \`row\` property, for example \`updateRows([{ _action: 'replace', row }])\`.
181
+ For more detail, see https://mui.com/x/react-data-grid/row-updates/.` : _formatErrorMessage(304));
182
+ }
183
+ return row;
184
+ };
185
+
186
+ /**
187
+ * Merges a partial update into the existing row.
188
+ * Prototype-preservation rules:
189
+ * 1. If partialRow is a class instance (non-plain object), use its prototype — the
190
+ * caller is passing in a fully-constructed instance and owns the prototype chain.
191
+ * 2. If partialRow is a plain object (Object.prototype), prefer oldRow's prototype so
192
+ * that a partial-update object does not silently discard the existing row's class.
193
+ * 3. If both are plain objects the result is also a plain object (no-op).
194
+ *
195
+ * Note: private class fields (#field syntax) cannot be preserved through a spread-style
196
+ * merge because the brand check is tied to the original instance. Rows that rely on
197
+ * private fields must either supply a fully-constructed instance as partialRow (rule 1
198
+ * above) or use `_action: 'replace'` rather than a plain-object partial update.
199
+ * @param {GridRowModel} oldRow The row currently stored in the lookup.
200
+ * @param {GridRowModelUpdate} partialRow The update to merge into it.
201
+ * @returns {GridRowModel} The merged row.
202
+ */
203
+ export const mergeRowUpdate = (oldRow, partialRow) => {
204
+ const partialRowProto = Object.getPrototypeOf(partialRow);
205
+ const isPartialRowPlain = partialRowProto === Object.prototype || partialRowProto === null;
206
+ const proto = isPartialRowPlain ? Object.getPrototypeOf(oldRow) : partialRowProto;
207
+ const merged = Object.create(proto);
208
+ Object.assign(merged, oldRow, partialRow);
209
+ return merged;
210
+ };
211
+
212
+ /**
213
+ * Warns when a replace demotes a class instance to a plain object, which happens when the
214
+ * replacement was built with a spread instead of being passed as-is.
215
+ * Dev-only, does nothing in production.
216
+ * @param {GridRowModel | undefined} oldRow The row being replaced, if any.
217
+ * @param {GridRowModel} replacement The row provided in a `{ _action: 'replace', row }` update.
218
+ */
219
+ export const warnIfReplaceLosesPrototype = (oldRow, replacement) => {
220
+ if (process.env.NODE_ENV === 'production' || !oldRow) {
221
+ return;
222
+ }
223
+ const replacementProto = Object.getPrototypeOf(replacement);
224
+ if (replacementProto !== Object.prototype && replacementProto !== null) {
225
+ return;
226
+ }
227
+ const oldRowProto = Object.getPrototypeOf(oldRow);
228
+ if (oldRowProto === Object.prototype || oldRowProto === null) {
229
+ return;
230
+ }
231
+
232
+ // The message must stay free of row-specific details: `warnOnce()` caches by message, so
233
+ // interpolating the id would log once per row and grow the cache with every update.
234
+ warnOnce(["MUI X Data Grid: A plain object was provided as the `row` of a `_action: 'replace'` update, but the row it replaces is a class instance.", "Building the replacement with a spread (`{ _action: 'replace', row: { ...row } }`) creates a plain object, dropping the prototype chain and the private fields that `_action: 'replace'` exists to preserve.", "Pass the instance itself instead, for example `{ _action: 'replace', row }`.", 'For more detail, see https://mui.com/x/react-data-grid/row-updates/.']);
235
+ };
162
236
  export const updateCacheWithNewRows = ({
163
237
  previousCache,
164
238
  getRowId,
@@ -172,10 +246,28 @@ export const updateCacheWithNewRows = ({
172
246
  // Remove duplicate updates.
173
247
  // A server can batch updates, and send several updates for the same row in one fn call.
174
248
  const uniqueUpdates = new Map();
249
+ // Ids whose accumulated update is stored as the row instead of being merged into the
250
+ // existing one. The flag lives outside the row object so that it is never mutated.
251
+ const replaceIds = new Set();
175
252
  updates.forEach(update => {
176
- const id = getRowIdFromRowModel(update, getRowId, 'A row was provided without id when calling updateRows():');
177
- if (uniqueUpdates.has(id)) {
178
- uniqueUpdates.set(id, _extends({}, uniqueUpdates.get(id), update));
253
+ // A replace is provided as a `{ _action: 'replace', row }` envelope: the marker stays
254
+ // on the throwaway envelope and the inner row is used verbatim, so that the object
255
+ // provided by the caller is the one that ends up in the lookup.
256
+ const isReplace = isReplaceUpdate(update);
257
+ const row = isReplace ? getReplaceRow(update) : update;
258
+ const id = getRowIdFromRowModel(row, getRowId, 'A row was provided without id when calling updateRows():');
259
+ if (isReplace) {
260
+ // A replace resets whatever has been accumulated for that id.
261
+ uniqueUpdates.set(id, row);
262
+ replaceIds.add(id);
263
+ } else if (uniqueUpdates.has(id)) {
264
+ const accumulatedUpdate = uniqueUpdates.get(id);
265
+ if (process.env.NODE_ENV !== 'production' && replaceIds.has(id)) {
266
+ warnOnce(["MUI X Data Grid: A row was provided with `_action: 'replace'` but it is not the last update for that row in this batch.", 'The remaining updates are merged onto the replacement, so the row keeps its prototype but is neither the same object nor carries its `#private` fields, which a merge cannot copy.', 'Make the replace the last update for that row if `apiRef.current.getRow(id)` must return the object you passed in.', 'For more detail, see https://mui.com/x/react-data-grid/row-updates/.']);
267
+ }
268
+ // The merge keeps the accumulated entry's prototype and the id stays in `replaceIds`,
269
+ // so the result is still applied as a replace.
270
+ uniqueUpdates.set(id, mergeRowUpdate(accumulatedUpdate, update));
179
271
  } else {
180
272
  uniqueUpdates.set(id, update);
181
273
  }
@@ -227,6 +319,15 @@ export const updateCacheWithNewRows = ({
227
319
  }
228
320
  const oldRow = dataRowIdToModelLookup[id];
229
321
 
322
+ // Action === "replace"
323
+ // The bookkeeping is the same as for "modify" / "insert" below, only the way the row
324
+ // is stored differs: the object is stored as-is so that its prototype chain, private
325
+ // fields (#field) and reference identity are all preserved.
326
+ const isReplace = replaceIds.has(id);
327
+ if (isReplace) {
328
+ warnIfReplaceLosesPrototype(oldRow, partialRow);
329
+ }
330
+
230
331
  // Action === "modify"
231
332
  if (oldRow) {
232
333
  // If the data row has been removed since the last state update,
@@ -242,23 +343,7 @@ export const updateCacheWithNewRows = ({
242
343
  }
243
344
 
244
345
  // Update the data row lookups.
245
- // Prototype-preservation rules:
246
- // 1. If partialRow is a class instance (non-plain object), use its prototype — the
247
- // caller is passing in a fully-constructed instance and owns the prototype chain.
248
- // 2. If partialRow is a plain object (Object.prototype), prefer oldRow's prototype so
249
- // that a partial-update object does not silently discard the existing row's class.
250
- // 3. If both are plain objects the result is also a plain object (no-op).
251
- //
252
- // Note: private class fields (#field syntax) cannot be preserved through a spread-style
253
- // merge because the brand check is tied to the original instance. Rows that rely on
254
- // private fields must supply a fully-constructed instance as partialRow (rule 1 above)
255
- // rather than a plain-object partial update.
256
- const partialRowProto = Object.getPrototypeOf(partialRow);
257
- const isPartialRowPlain = partialRowProto === Object.prototype || partialRowProto === null;
258
- const proto = isPartialRowPlain ? Object.getPrototypeOf(oldRow) : partialRowProto;
259
- const merged = Object.create(proto);
260
- Object.assign(merged, oldRow, partialRow);
261
- dataRowIdToModelLookup[id] = merged;
346
+ dataRowIdToModelLookup[id] = isReplace ? partialRow : mergeRowUpdate(oldRow, partialRow);
262
347
  return;
263
348
  }
264
349
 
@@ -299,16 +384,24 @@ export const minimalContentHeight = 'var(--DataGrid-overlayHeight, calc(var(--he
299
384
  export function computeRowsUpdates(apiRef, updates, getRowId) {
300
385
  const nonPinnedRowsUpdates = [];
301
386
  updates.forEach(update => {
302
- const id = getRowIdFromRowModel(update, getRowId, 'A row was provided without id when calling updateRows():');
387
+ const isReplace = isReplaceUpdate(update);
388
+ const row = isReplace ? getReplaceRow(update) : update;
389
+ const id = getRowIdFromRowModel(row, getRowId, 'A row was provided without id when calling updateRows():');
303
390
  const rowNode = gridRowNodeSelector(apiRef, id);
304
391
  if (rowNode?.type === 'pinnedRow') {
305
392
  // @ts-ignore because otherwise `release:build` doesn't work
306
393
  const pinnedRowsCache = apiRef.current.caches.pinnedRows;
307
394
  const prevModel = pinnedRowsCache.idLookup[id];
308
395
  if (prevModel) {
309
- pinnedRowsCache.idLookup[id] = _extends({}, prevModel, update);
396
+ if (isReplace) {
397
+ warnIfReplaceLosesPrototype(prevModel, row);
398
+ pinnedRowsCache.idLookup[id] = row;
399
+ } else {
400
+ pinnedRowsCache.idLookup[id] = mergeRowUpdate(prevModel, update);
401
+ }
310
402
  }
311
403
  } else {
404
+ // The envelope is passed through untouched, `updateCacheWithNewRows` unwraps it.
312
405
  nonPinnedRowsUpdates.push(update);
313
406
  }
314
407
  });
@@ -57,6 +57,7 @@ const useGridRows = (apiRef, props, configuration) => {
57
57
  const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridRows');
58
58
  const lastUpdateMs = React.useRef(Date.now());
59
59
  const lastRowCount = React.useRef(props.rowCount);
60
+ const lastGetRowId = React.useRef(props.getRowId);
60
61
  const timeout = (0, _useTimeout.useTimeout)();
61
62
 
62
63
  // Get overridable methods from configuration
@@ -450,8 +451,16 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock this f
450
451
  isRowCountPropUpdated = true;
451
452
  lastRowCount.current = props.rowCount;
452
453
  }
454
+ let isGetRowIdPropUpdated = false;
455
+ if (props.getRowId !== lastGetRowId.current) {
456
+ isGetRowIdPropUpdated = true;
457
+ lastGetRowId.current = props.getRowId;
458
+ }
453
459
  const currentRows = props.dataSource ? (0, _gridRowsSelector.gridDataRowsSelector)(apiRef) : props.rows;
454
- const areNewRowsAlreadyInState = apiRef.current.caches.rows.rowsBeforePartialUpdates === currentRows;
460
+ // Data source rows live in the state, not in props: there is never a new set to apply, and
461
+ // `gridDataRowsSelector` returns a new array each time so the identity check never holds.
462
+ // Only a new `getRowId` needs a rebuild, to re-key them.
463
+ const areNewRowsAlreadyInState = props.dataSource ? !isGetRowIdPropUpdated : apiRef.current.caches.rows.rowsBeforePartialUpdates === currentRows;
455
464
  const isNewLoadingAlreadyInState = apiRef.current.caches.rows.loadingPropBeforePartialUpdates === props.loading;
456
465
  const isNewRowCountAlreadyInState = apiRef.current.caches.rows.rowCountPropBeforePartialUpdates === props.rowCount;
457
466
 
@@ -49,6 +49,7 @@ export const useGridRows = (apiRef, props, configuration) => {
49
49
  const logger = useGridLogger(apiRef, 'useGridRows');
50
50
  const lastUpdateMs = React.useRef(Date.now());
51
51
  const lastRowCount = React.useRef(props.rowCount);
52
+ const lastGetRowId = React.useRef(props.getRowId);
52
53
  const timeout = useTimeout();
53
54
 
54
55
  // Get overridable methods from configuration
@@ -442,8 +443,16 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock this f
442
443
  isRowCountPropUpdated = true;
443
444
  lastRowCount.current = props.rowCount;
444
445
  }
446
+ let isGetRowIdPropUpdated = false;
447
+ if (props.getRowId !== lastGetRowId.current) {
448
+ isGetRowIdPropUpdated = true;
449
+ lastGetRowId.current = props.getRowId;
450
+ }
445
451
  const currentRows = props.dataSource ? gridDataRowsSelector(apiRef) : props.rows;
446
- const areNewRowsAlreadyInState = apiRef.current.caches.rows.rowsBeforePartialUpdates === currentRows;
452
+ // Data source rows live in the state, not in props: there is never a new set to apply, and
453
+ // `gridDataRowsSelector` returns a new array each time so the identity check never holds.
454
+ // Only a new `getRowId` needs a rebuild, to re-key them.
455
+ const areNewRowsAlreadyInState = props.dataSource ? !isGetRowIdPropUpdated : apiRef.current.caches.rows.rowsBeforePartialUpdates === currentRows;
447
456
  const isNewLoadingAlreadyInState = apiRef.current.caches.rows.loadingPropBeforePartialUpdates === props.loading;
448
457
  const isNewRowCountAlreadyInState = apiRef.current.caches.rows.rowCountPropBeforePartialUpdates === props.rowCount;
449
458
 
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v9.12.0
2
+ * @mui/x-data-grid v9.13.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v9.12.0
2
+ * @mui/x-data-grid v9.13.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -67,7 +67,7 @@ export type { GridRowTreeCreationParams, GridRowTreeCreationValue, GridHydrateRo
67
67
  export { getTreeNodeDescendants, buildRootGroup } from "../hooks/features/rows/gridRowsUtils.mjs";
68
68
  export { useGridRowsMeta, rowsMetaStateInitializer } from "../hooks/features/rows/useGridRowsMeta.mjs";
69
69
  export { useGridParamsApi } from "../hooks/features/rows/useGridParamsApi.mjs";
70
- export { getRowIdFromRowModel, GRID_ID_AUTOGENERATED, getRowValue } from "../hooks/features/rows/gridRowsUtils.mjs";
70
+ export { getRowIdFromRowModel, GRID_ID_AUTOGENERATED, getRowValue, isReplaceUpdate, getReplaceRow, warnIfReplaceLosesPrototype } from "../hooks/features/rows/gridRowsUtils.mjs";
71
71
  export { gridAdditionalRowGroupsSelector, gridPinnedRowsSelector, gridRowSelector } from "../hooks/features/rows/gridRowsSelector.mjs";
72
72
  export { headerFilteringStateInitializer, useGridHeaderFiltering } from "../hooks/features/headerFiltering/useGridHeaderFiltering.mjs";
73
73
  export { useGridRowSelection, rowSelectionStateInitializer } from "../hooks/features/rowSelection/useGridRowSelection.mjs";
@@ -110,7 +110,7 @@ export { NotRendered } from "../utils/assert.mjs";
110
110
  export { createSelector, createRootSelector, createSelectorMemoized } from "../utils/createSelector.mjs";
111
111
  export { gridRowGroupsToFetchSelector } from "../hooks/features/rows/gridRowsSelector.mjs";
112
112
  export { findParentElementFromClassName, getActiveElement, getGridCellElement, isEventTargetInPortal } from "../utils/domUtils.mjs";
113
- export { isNavigationKey, isPasteShortcut, isCopyShortcut, isUndoShortcut, isRedoShortcut, isFillDownShortcut, isFillRightShortcut } from "../utils/keyboardUtils.mjs";
113
+ export { isNavigationKey, isPasteShortcut, isCopyShortcut, isSelectAllShortcut, isUndoShortcut, isRedoShortcut, isFillDownShortcut, isFillRightShortcut } from "../utils/keyboardUtils.mjs";
114
114
  export * from "../utils/utils.mjs";
115
115
  export { exportAs } from "../utils/exportAs.mjs";
116
116
  export * from "../utils/getPublicApiRef.mjs";
@@ -67,7 +67,7 @@ export type { GridRowTreeCreationParams, GridRowTreeCreationValue, GridHydrateRo
67
67
  export { getTreeNodeDescendants, buildRootGroup } from "../hooks/features/rows/gridRowsUtils.js";
68
68
  export { useGridRowsMeta, rowsMetaStateInitializer } from "../hooks/features/rows/useGridRowsMeta.js";
69
69
  export { useGridParamsApi } from "../hooks/features/rows/useGridParamsApi.js";
70
- export { getRowIdFromRowModel, GRID_ID_AUTOGENERATED, getRowValue } from "../hooks/features/rows/gridRowsUtils.js";
70
+ export { getRowIdFromRowModel, GRID_ID_AUTOGENERATED, getRowValue, isReplaceUpdate, getReplaceRow, warnIfReplaceLosesPrototype } from "../hooks/features/rows/gridRowsUtils.js";
71
71
  export { gridAdditionalRowGroupsSelector, gridPinnedRowsSelector, gridRowSelector } from "../hooks/features/rows/gridRowsSelector.js";
72
72
  export { headerFilteringStateInitializer, useGridHeaderFiltering } from "../hooks/features/headerFiltering/useGridHeaderFiltering.js";
73
73
  export { useGridRowSelection, rowSelectionStateInitializer } from "../hooks/features/rowSelection/useGridRowSelection.js";
@@ -110,7 +110,7 @@ export { NotRendered } from "../utils/assert.js";
110
110
  export { createSelector, createRootSelector, createSelectorMemoized } from "../utils/createSelector.js";
111
111
  export { gridRowGroupsToFetchSelector } from "../hooks/features/rows/gridRowsSelector.js";
112
112
  export { findParentElementFromClassName, getActiveElement, getGridCellElement, isEventTargetInPortal } from "../utils/domUtils.js";
113
- export { isNavigationKey, isPasteShortcut, isCopyShortcut, isUndoShortcut, isRedoShortcut, isFillDownShortcut, isFillRightShortcut } from "../utils/keyboardUtils.js";
113
+ export { isNavigationKey, isPasteShortcut, isCopyShortcut, isSelectAllShortcut, isUndoShortcut, isRedoShortcut, isFillDownShortcut, isFillRightShortcut } from "../utils/keyboardUtils.js";
114
114
  export * from "../utils/utils.js";
115
115
  export { exportAs } from "../utils/exportAs.js";
116
116
  export * from "../utils/getPublicApiRef.js";
@@ -80,6 +80,9 @@ var _exportNames = {
80
80
  getRowIdFromRowModel: true,
81
81
  GRID_ID_AUTOGENERATED: true,
82
82
  getRowValue: true,
83
+ isReplaceUpdate: true,
84
+ getReplaceRow: true,
85
+ warnIfReplaceLosesPrototype: true,
83
86
  useGridRowsMeta: true,
84
87
  rowsMetaStateInitializer: true,
85
88
  useGridParamsApi: true,
@@ -131,6 +134,7 @@ var _exportNames = {
131
134
  isNavigationKey: true,
132
135
  isPasteShortcut: true,
133
136
  isCopyShortcut: true,
137
+ isSelectAllShortcut: true,
134
138
  isUndoShortcut: true,
135
139
  isRedoShortcut: true,
136
140
  isFillDownShortcut: true,
@@ -389,6 +393,12 @@ Object.defineProperty(exports, "getGridFilter", {
389
393
  return _GridFilterPanel.getGridFilter;
390
394
  }
391
395
  });
396
+ Object.defineProperty(exports, "getReplaceRow", {
397
+ enumerable: true,
398
+ get: function () {
399
+ return _gridRowsUtils.getReplaceRow;
400
+ }
401
+ });
392
402
  Object.defineProperty(exports, "getRowIdFromRowModel", {
393
403
  enumerable: true,
394
404
  get: function () {
@@ -581,6 +591,18 @@ Object.defineProperty(exports, "isRedoShortcut", {
581
591
  return _keyboardUtils.isRedoShortcut;
582
592
  }
583
593
  });
594
+ Object.defineProperty(exports, "isReplaceUpdate", {
595
+ enumerable: true,
596
+ get: function () {
597
+ return _gridRowsUtils.isReplaceUpdate;
598
+ }
599
+ });
600
+ Object.defineProperty(exports, "isSelectAllShortcut", {
601
+ enumerable: true,
602
+ get: function () {
603
+ return _keyboardUtils.isSelectAllShortcut;
604
+ }
605
+ });
584
606
  Object.defineProperty(exports, "isSingleSelectColDef", {
585
607
  enumerable: true,
586
608
  get: function () {
@@ -971,6 +993,12 @@ Object.defineProperty(exports, "vars", {
971
993
  return _cssVariables.vars;
972
994
  }
973
995
  });
996
+ Object.defineProperty(exports, "warnIfReplaceLosesPrototype", {
997
+ enumerable: true,
998
+ get: function () {
999
+ return _gridRowsUtils.warnIfReplaceLosesPrototype;
1000
+ }
1001
+ });
974
1002
  var _gridStringColDef = require("../colDef/gridStringColDef");
975
1003
  var _gridColumnTypesRegistry = require("../colDef/gridColumnTypesRegistry");
976
1004
  var _gridPropsSelectors = require("../hooks/core/gridPropsSelectors");
@@ -54,7 +54,7 @@ export { useGridRowsPreProcessors } from "../hooks/features/rows/useGridRowsPreP
54
54
  export { getTreeNodeDescendants, buildRootGroup } from "../hooks/features/rows/gridRowsUtils.mjs";
55
55
  export { useGridRowsMeta, rowsMetaStateInitializer } from "../hooks/features/rows/useGridRowsMeta.mjs";
56
56
  export { useGridParamsApi } from "../hooks/features/rows/useGridParamsApi.mjs";
57
- export { getRowIdFromRowModel, GRID_ID_AUTOGENERATED, getRowValue } from "../hooks/features/rows/gridRowsUtils.mjs";
57
+ export { getRowIdFromRowModel, GRID_ID_AUTOGENERATED, getRowValue, isReplaceUpdate, getReplaceRow, warnIfReplaceLosesPrototype } from "../hooks/features/rows/gridRowsUtils.mjs";
58
58
  export { gridAdditionalRowGroupsSelector, gridPinnedRowsSelector, gridRowSelector } from "../hooks/features/rows/gridRowsSelector.mjs";
59
59
  export { headerFilteringStateInitializer, useGridHeaderFiltering } from "../hooks/features/headerFiltering/useGridHeaderFiltering.mjs";
60
60
  export { useGridRowSelection, rowSelectionStateInitializer } from "../hooks/features/rowSelection/useGridRowSelection.mjs";
@@ -88,7 +88,7 @@ export { NotRendered } from "../utils/assert.mjs";
88
88
  export { createSelector, createRootSelector, createSelectorMemoized } from "../utils/createSelector.mjs";
89
89
  export { gridRowGroupsToFetchSelector } from "../hooks/features/rows/gridRowsSelector.mjs";
90
90
  export { findParentElementFromClassName, getActiveElement, getGridCellElement, isEventTargetInPortal } from "../utils/domUtils.mjs";
91
- export { isNavigationKey, isPasteShortcut, isCopyShortcut, isUndoShortcut, isRedoShortcut, isFillDownShortcut, isFillRightShortcut } from "../utils/keyboardUtils.mjs";
91
+ export { isNavigationKey, isPasteShortcut, isCopyShortcut, isSelectAllShortcut, isUndoShortcut, isRedoShortcut, isFillDownShortcut, isFillRightShortcut } from "../utils/keyboardUtils.mjs";
92
92
  export * from "../utils/utils.mjs";
93
93
  export { exportAs } from "../utils/exportAs.mjs";
94
94
  export * from "../utils/getPublicApiRef.mjs";
@@ -1,5 +1,10 @@
1
+ import type { Theme } from '@mui/material/styles';
1
2
  import type { GridCSSVariablesInterface } from "../constants/cssVariables.mjs";
2
3
  export declare function useMaterialCSSVariables(): {
3
4
  id: string;
4
5
  variables: GridCSSVariablesInterface;
5
- };
6
+ };
7
+ export declare function getBackgroundBase(theme: Theme): string;
8
+ export declare function getFontBody(theme: Theme): any;
9
+ export declare function getSpacingUnit(theme: Theme): any;
10
+ export declare function getBorderColor(theme: Theme): string;