@redsift/table 12.5.2-muiv6 → 12.5.2

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.
@@ -1,1290 +1,18 @@
1
- import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends$1 } from './_rollupPluginBabelHelpers.js';
1
+ import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends } from './_rollupPluginBabelHelpers.js';
2
2
  import * as React from 'react';
3
- import React__default, { useCallback, useEffect, useMemo, forwardRef, useRef, useState } from 'react';
3
+ import React__default, { useCallback, useEffect, useRef, useMemo, forwardRef, useState } from 'react';
4
+ import { createTheme, ThemeProvider as ThemeProvider$1 } from '@mui/material/styles';
4
5
  import classNames from 'classnames';
5
- import { Icon, useTheme as useTheme$1, ThemeProvider, RedsiftColorBlueN, RedsiftColorNeutralXDarkGrey, RedsiftColorNeutralWhite } from '@redsift/design-system';
6
- import { getGridNumericOperators as getGridNumericOperators$1, GridFilterInputValue, GridFilterInputSingleSelect, GridFilterInputMultipleValue, GridFilterInputMultipleSingleSelect, getGridStringOperators as getGridStringOperators$1, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators, GridLogicOperator, useGridApiRef, gridPaginatedVisibleSortedGridRowEntriesSelector, gridPaginatedVisibleSortedGridRowIdsSelector, gridFilteredSortedRowEntriesSelector, gridFilteredSortedRowIdsSelector, DataGridPro } from '@mui/x-data-grid-pro';
7
- import { L as LicenseInfo, u as useControlledDatagridState, T as ThemeProvider$1, S as StyledDataGrid } from './useControlledDatagridState.js';
6
+ import { LicenseInfo } from '@mui/x-license';
7
+ import { Icon, useTheme, RedsiftColorBlueN, RedsiftColorNeutralXDarkGrey, RedsiftColorNeutralWhite, ThemeProvider } from '@redsift/design-system';
8
+ import { getGridNumericOperators as getGridNumericOperators$1, GridFilterInputValue, GridFilterInputSingleSelect, GridFilterInputMultipleValue, GridFilterInputMultipleSingleSelect, getGridStringOperators as getGridStringOperators$1, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators, GridLogicOperator, useGridApiRef, gridFilteredSortedRowEntriesSelector, gridFilteredSortedRowIdsSelector, DataGridPremium } from '@mui/x-data-grid-premium';
9
+ import { u as useControlledDatagridState, S as StyledDataGrid } from './useControlledDatagridState.js';
10
+ import Box from '@mui/material/Box';
11
+ import TextField from '@mui/material/TextField';
8
12
  import { mdiSync } from '@redsift/icons';
9
- import { _ as _objectWithoutPropertiesLoose, a as _extends, d as defaultSxConfig, i as isPlainObject, s as styled, b as styleFunctionSx, u as useTheme, c as clsx, e as createTheme, T as THEME_ID, C as ClassNameGenerator, P as PropTypes, g as generateUtilityClasses, f as generateUtilityClass, h as styled$1, j as useThemeProps, k as capitalize, l as composeClasses, r as rootShouldForwardProp, m as refType } from './Portal.js';
10
- import { j as jsxRuntimeExports } from './jsx-runtime.js';
11
- import { u as useFormControl, a as formControlState, i as isAdornedStart, b as isFilled, F as FormControlContext, c as useId, d as Select, I as Input, e as FilledInput, O as OutlinedInput, o as onServerSideSelectionStatusChange, S as ServerSideControlledPagination, C as ControlledPagination } from './ControlledPagination.js';
12
13
  import { decompressFromEncodedURIComponent, compressToEncodedURIComponent } from 'lz-string';
13
- import { T as Toolbar } from './Toolbar2.js';
14
- import { B as BaseButton, a as BaseCheckbox, c as BasePopper, b as BaseIcon } from './BasePopper.js';
15
- import { T as ToolbarWrapper } from './ToolbarWrapper2.js';
16
-
17
- function isMuiElement(element, muiNames) {
18
- return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf(element.type.muiName) !== -1;
19
- }
20
-
21
- const _excluded$7 = ["sx"];
22
- const splitProps = props => {
23
- var _props$theme$unstable, _props$theme;
24
- const result = {
25
- systemProps: {},
26
- otherProps: {}
27
- };
28
- const config = (_props$theme$unstable = props == null ? void 0 : (_props$theme = props.theme) == null ? void 0 : _props$theme.unstable_sxConfig) != null ? _props$theme$unstable : defaultSxConfig;
29
- Object.keys(props).forEach(prop => {
30
- if (config[prop]) {
31
- result.systemProps[prop] = props[prop];
32
- } else {
33
- result.otherProps[prop] = props[prop];
34
- }
35
- });
36
- return result;
37
- };
38
- function extendSxProp(props) {
39
- const {
40
- sx: inSx
41
- } = props,
42
- other = _objectWithoutPropertiesLoose(props, _excluded$7);
43
- const {
44
- systemProps,
45
- otherProps
46
- } = splitProps(other);
47
- let finalSx;
48
- if (Array.isArray(inSx)) {
49
- finalSx = [systemProps, ...inSx];
50
- } else if (typeof inSx === 'function') {
51
- finalSx = (...args) => {
52
- const result = inSx(...args);
53
- if (!isPlainObject(result)) {
54
- return systemProps;
55
- }
56
- return _extends({}, systemProps, result);
57
- };
58
- } else {
59
- finalSx = _extends({}, systemProps, inSx);
60
- }
61
- return _extends({}, otherProps, {
62
- sx: finalSx
63
- });
64
- }
65
-
66
- const _excluded$6 = ["className", "component"];
67
- function createBox(options = {}) {
68
- const {
69
- themeId,
70
- defaultTheme,
71
- defaultClassName = 'MuiBox-root',
72
- generateClassName
73
- } = options;
74
- const BoxRoot = styled('div', {
75
- shouldForwardProp: prop => prop !== 'theme' && prop !== 'sx' && prop !== 'as'
76
- })(styleFunctionSx);
77
- const Box = /*#__PURE__*/React.forwardRef(function Box(inProps, ref) {
78
- const theme = useTheme(defaultTheme);
79
- const _extendSxProp = extendSxProp(inProps),
80
- {
81
- className,
82
- component = 'div'
83
- } = _extendSxProp,
84
- other = _objectWithoutPropertiesLoose(_extendSxProp, _excluded$6);
85
- return /*#__PURE__*/jsxRuntimeExports.jsx(BoxRoot, _extends({
86
- as: component,
87
- ref: ref,
88
- className: clsx(className, generateClassName ? generateClassName(defaultClassName) : defaultClassName),
89
- theme: themeId ? theme[themeId] || theme : theme
90
- }, other));
91
- });
92
- return Box;
93
- }
94
-
95
- const defaultTheme = createTheme();
96
- const Box = createBox({
97
- themeId: THEME_ID,
98
- defaultTheme,
99
- defaultClassName: 'MuiBox-root',
100
- generateClassName: ClassNameGenerator.generate
101
- });
102
- process.env.NODE_ENV !== "production" ? Box.propTypes /* remove-proptypes */ = {
103
- // ----------------------------- Warning --------------------------------
104
- // | These PropTypes are generated from the TypeScript type definitions |
105
- // | To update them edit the d.ts file and run "yarn proptypes" |
106
- // ----------------------------------------------------------------------
107
- /**
108
- * @ignore
109
- */
110
- children: PropTypes.node,
111
- /**
112
- * The component used for the root node.
113
- * Either a string to use a HTML element or a component.
114
- */
115
- component: PropTypes.elementType,
116
- /**
117
- * The system prop that allows defining system overrides as well as additional CSS styles.
118
- */
119
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
120
- } : void 0;
121
- var Box$1 = Box;
122
-
123
- function getFormLabelUtilityClasses(slot) {
124
- return generateUtilityClass('MuiFormLabel', slot);
125
- }
126
- const formLabelClasses = generateUtilityClasses('MuiFormLabel', ['root', 'colorSecondary', 'focused', 'disabled', 'error', 'filled', 'required', 'asterisk']);
127
- var formLabelClasses$1 = formLabelClasses;
128
-
129
- const _excluded$5 = ["children", "className", "color", "component", "disabled", "error", "filled", "focused", "required"];
130
- const useUtilityClasses$4 = ownerState => {
131
- const {
132
- classes,
133
- color,
134
- focused,
135
- disabled,
136
- error,
137
- filled,
138
- required
139
- } = ownerState;
140
- const slots = {
141
- root: ['root', `color${capitalize(color)}`, disabled && 'disabled', error && 'error', filled && 'filled', focused && 'focused', required && 'required'],
142
- asterisk: ['asterisk', error && 'error']
143
- };
144
- return composeClasses(slots, getFormLabelUtilityClasses, classes);
145
- };
146
- const FormLabelRoot = styled$1('label', {
147
- name: 'MuiFormLabel',
148
- slot: 'Root',
149
- overridesResolver: ({
150
- ownerState
151
- }, styles) => {
152
- return _extends({}, styles.root, ownerState.color === 'secondary' && styles.colorSecondary, ownerState.filled && styles.filled);
153
- }
154
- })(({
155
- theme,
156
- ownerState
157
- }) => _extends({
158
- color: (theme.vars || theme).palette.text.secondary
159
- }, theme.typography.body1, {
160
- lineHeight: '1.4375em',
161
- padding: 0,
162
- position: 'relative',
163
- [`&.${formLabelClasses$1.focused}`]: {
164
- color: (theme.vars || theme).palette[ownerState.color].main
165
- },
166
- [`&.${formLabelClasses$1.disabled}`]: {
167
- color: (theme.vars || theme).palette.text.disabled
168
- },
169
- [`&.${formLabelClasses$1.error}`]: {
170
- color: (theme.vars || theme).palette.error.main
171
- }
172
- }));
173
- const AsteriskComponent = styled$1('span', {
174
- name: 'MuiFormLabel',
175
- slot: 'Asterisk',
176
- overridesResolver: (props, styles) => styles.asterisk
177
- })(({
178
- theme
179
- }) => ({
180
- [`&.${formLabelClasses$1.error}`]: {
181
- color: (theme.vars || theme).palette.error.main
182
- }
183
- }));
184
- const FormLabel = /*#__PURE__*/React.forwardRef(function FormLabel(inProps, ref) {
185
- const props = useThemeProps({
186
- props: inProps,
187
- name: 'MuiFormLabel'
188
- });
189
- const {
190
- children,
191
- className,
192
- component = 'label'
193
- } = props,
194
- other = _objectWithoutPropertiesLoose(props, _excluded$5);
195
- const muiFormControl = useFormControl();
196
- const fcs = formControlState({
197
- props,
198
- muiFormControl,
199
- states: ['color', 'required', 'focused', 'disabled', 'error', 'filled']
200
- });
201
- const ownerState = _extends({}, props, {
202
- color: fcs.color || 'primary',
203
- component,
204
- disabled: fcs.disabled,
205
- error: fcs.error,
206
- filled: fcs.filled,
207
- focused: fcs.focused,
208
- required: fcs.required
209
- });
210
- const classes = useUtilityClasses$4(ownerState);
211
- return /*#__PURE__*/jsxRuntimeExports.jsxs(FormLabelRoot, _extends({
212
- as: component,
213
- ownerState: ownerState,
214
- className: clsx(classes.root, className),
215
- ref: ref
216
- }, other, {
217
- children: [children, fcs.required && /*#__PURE__*/jsxRuntimeExports.jsxs(AsteriskComponent, {
218
- ownerState: ownerState,
219
- "aria-hidden": true,
220
- className: classes.asterisk,
221
- children: ["\u2009", '*']
222
- })]
223
- }));
224
- });
225
- process.env.NODE_ENV !== "production" ? FormLabel.propTypes /* remove-proptypes */ = {
226
- // ----------------------------- Warning --------------------------------
227
- // | These PropTypes are generated from the TypeScript type definitions |
228
- // | To update them edit the d.ts file and run "yarn proptypes" |
229
- // ----------------------------------------------------------------------
230
- /**
231
- * The content of the component.
232
- */
233
- children: PropTypes.node,
234
- /**
235
- * Override or extend the styles applied to the component.
236
- */
237
- classes: PropTypes.object,
238
- /**
239
- * @ignore
240
- */
241
- className: PropTypes.string,
242
- /**
243
- * The color of the component.
244
- * It supports both default and custom theme colors, which can be added as shown in the
245
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors).
246
- */
247
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
248
- /**
249
- * The component used for the root node.
250
- * Either a string to use a HTML element or a component.
251
- */
252
- component: PropTypes.elementType,
253
- /**
254
- * If `true`, the label should be displayed in a disabled state.
255
- */
256
- disabled: PropTypes.bool,
257
- /**
258
- * If `true`, the label is displayed in an error state.
259
- */
260
- error: PropTypes.bool,
261
- /**
262
- * If `true`, the label should use filled classes key.
263
- */
264
- filled: PropTypes.bool,
265
- /**
266
- * If `true`, the input of this label is focused (used by `FormGroup` components).
267
- */
268
- focused: PropTypes.bool,
269
- /**
270
- * If `true`, the label will indicate that the `input` is required.
271
- */
272
- required: PropTypes.bool,
273
- /**
274
- * The system prop that allows defining system overrides as well as additional CSS styles.
275
- */
276
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
277
- } : void 0;
278
- var FormLabel$1 = FormLabel;
279
-
280
- function getInputLabelUtilityClasses(slot) {
281
- return generateUtilityClass('MuiInputLabel', slot);
282
- }
283
- generateUtilityClasses('MuiInputLabel', ['root', 'focused', 'disabled', 'error', 'required', 'asterisk', 'formControl', 'sizeSmall', 'shrink', 'animated', 'standard', 'filled', 'outlined']);
284
-
285
- const _excluded$4 = ["disableAnimation", "margin", "shrink", "variant", "className"];
286
- const useUtilityClasses$3 = ownerState => {
287
- const {
288
- classes,
289
- formControl,
290
- size,
291
- shrink,
292
- disableAnimation,
293
- variant,
294
- required
295
- } = ownerState;
296
- const slots = {
297
- root: ['root', formControl && 'formControl', !disableAnimation && 'animated', shrink && 'shrink', size === 'small' && 'sizeSmall', variant],
298
- asterisk: [required && 'asterisk']
299
- };
300
- const composedClasses = composeClasses(slots, getInputLabelUtilityClasses, classes);
301
- return _extends({}, classes, composedClasses);
302
- };
303
- const InputLabelRoot = styled$1(FormLabel$1, {
304
- shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
305
- name: 'MuiInputLabel',
306
- slot: 'Root',
307
- overridesResolver: (props, styles) => {
308
- const {
309
- ownerState
310
- } = props;
311
- return [{
312
- [`& .${formLabelClasses$1.asterisk}`]: styles.asterisk
313
- }, styles.root, ownerState.formControl && styles.formControl, ownerState.size === 'small' && styles.sizeSmall, ownerState.shrink && styles.shrink, !ownerState.disableAnimation && styles.animated, styles[ownerState.variant]];
314
- }
315
- })(({
316
- theme,
317
- ownerState
318
- }) => _extends({
319
- display: 'block',
320
- transformOrigin: 'top left',
321
- whiteSpace: 'nowrap',
322
- overflow: 'hidden',
323
- textOverflow: 'ellipsis',
324
- maxWidth: '100%'
325
- }, ownerState.formControl && {
326
- position: 'absolute',
327
- left: 0,
328
- top: 0,
329
- // slight alteration to spec spacing to match visual spec result
330
- transform: 'translate(0, 20px) scale(1)'
331
- }, ownerState.size === 'small' && {
332
- // Compensation for the `Input.inputSizeSmall` style.
333
- transform: 'translate(0, 17px) scale(1)'
334
- }, ownerState.shrink && {
335
- transform: 'translate(0, -1.5px) scale(0.75)',
336
- transformOrigin: 'top left',
337
- maxWidth: '133%'
338
- }, !ownerState.disableAnimation && {
339
- transition: theme.transitions.create(['color', 'transform', 'max-width'], {
340
- duration: theme.transitions.duration.shorter,
341
- easing: theme.transitions.easing.easeOut
342
- })
343
- }, ownerState.variant === 'filled' && _extends({
344
- // Chrome's autofill feature gives the input field a yellow background.
345
- // Since the input field is behind the label in the HTML tree,
346
- // the input field is drawn last and hides the label with an opaque background color.
347
- // zIndex: 1 will raise the label above opaque background-colors of input.
348
- zIndex: 1,
349
- pointerEvents: 'none',
350
- transform: 'translate(12px, 16px) scale(1)',
351
- maxWidth: 'calc(100% - 24px)'
352
- }, ownerState.size === 'small' && {
353
- transform: 'translate(12px, 13px) scale(1)'
354
- }, ownerState.shrink && _extends({
355
- userSelect: 'none',
356
- pointerEvents: 'auto',
357
- transform: 'translate(12px, 7px) scale(0.75)',
358
- maxWidth: 'calc(133% - 24px)'
359
- }, ownerState.size === 'small' && {
360
- transform: 'translate(12px, 4px) scale(0.75)'
361
- })), ownerState.variant === 'outlined' && _extends({
362
- // see comment above on filled.zIndex
363
- zIndex: 1,
364
- pointerEvents: 'none',
365
- transform: 'translate(14px, 16px) scale(1)',
366
- maxWidth: 'calc(100% - 24px)'
367
- }, ownerState.size === 'small' && {
368
- transform: 'translate(14px, 9px) scale(1)'
369
- }, ownerState.shrink && {
370
- userSelect: 'none',
371
- pointerEvents: 'auto',
372
- // Theoretically, we should have (8+5)*2/0.75 = 34px
373
- // but it feels a better when it bleeds a bit on the left, so 32px.
374
- maxWidth: 'calc(133% - 32px)',
375
- transform: 'translate(14px, -9px) scale(0.75)'
376
- })));
377
- const InputLabel = /*#__PURE__*/React.forwardRef(function InputLabel(inProps, ref) {
378
- const props = useThemeProps({
379
- name: 'MuiInputLabel',
380
- props: inProps
381
- });
382
- const {
383
- disableAnimation = false,
384
- shrink: shrinkProp,
385
- className
386
- } = props,
387
- other = _objectWithoutPropertiesLoose(props, _excluded$4);
388
- const muiFormControl = useFormControl();
389
- let shrink = shrinkProp;
390
- if (typeof shrink === 'undefined' && muiFormControl) {
391
- shrink = muiFormControl.filled || muiFormControl.focused || muiFormControl.adornedStart;
392
- }
393
- const fcs = formControlState({
394
- props,
395
- muiFormControl,
396
- states: ['size', 'variant', 'required']
397
- });
398
- const ownerState = _extends({}, props, {
399
- disableAnimation,
400
- formControl: muiFormControl,
401
- shrink,
402
- size: fcs.size,
403
- variant: fcs.variant,
404
- required: fcs.required
405
- });
406
- const classes = useUtilityClasses$3(ownerState);
407
- return /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelRoot, _extends({
408
- "data-shrink": shrink,
409
- ownerState: ownerState,
410
- ref: ref,
411
- className: clsx(classes.root, className)
412
- }, other, {
413
- classes: classes
414
- }));
415
- });
416
- process.env.NODE_ENV !== "production" ? InputLabel.propTypes /* remove-proptypes */ = {
417
- // ----------------------------- Warning --------------------------------
418
- // | These PropTypes are generated from the TypeScript type definitions |
419
- // | To update them edit the d.ts file and run "yarn proptypes" |
420
- // ----------------------------------------------------------------------
421
- /**
422
- * The content of the component.
423
- */
424
- children: PropTypes.node,
425
- /**
426
- * Override or extend the styles applied to the component.
427
- */
428
- classes: PropTypes.object,
429
- /**
430
- * @ignore
431
- */
432
- className: PropTypes.string,
433
- /**
434
- * The color of the component.
435
- * It supports both default and custom theme colors, which can be added as shown in the
436
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors).
437
- */
438
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
439
- /**
440
- * If `true`, the transition animation is disabled.
441
- * @default false
442
- */
443
- disableAnimation: PropTypes.bool,
444
- /**
445
- * If `true`, the component is disabled.
446
- */
447
- disabled: PropTypes.bool,
448
- /**
449
- * If `true`, the label is displayed in an error state.
450
- */
451
- error: PropTypes.bool,
452
- /**
453
- * If `true`, the `input` of this label is focused.
454
- */
455
- focused: PropTypes.bool,
456
- /**
457
- * If `dense`, will adjust vertical spacing. This is normally obtained via context from
458
- * FormControl.
459
- */
460
- margin: PropTypes.oneOf(['dense']),
461
- /**
462
- * if `true`, the label will indicate that the `input` is required.
463
- */
464
- required: PropTypes.bool,
465
- /**
466
- * If `true`, the label is shrunk.
467
- */
468
- shrink: PropTypes.bool,
469
- /**
470
- * The size of the component.
471
- * @default 'normal'
472
- */
473
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['normal', 'small']), PropTypes.string]),
474
- /**
475
- * The system prop that allows defining system overrides as well as additional CSS styles.
476
- */
477
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
478
- /**
479
- * The variant to use.
480
- */
481
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
482
- } : void 0;
483
- var InputLabel$1 = InputLabel;
484
-
485
- function getFormControlUtilityClasses(slot) {
486
- return generateUtilityClass('MuiFormControl', slot);
487
- }
488
- generateUtilityClasses('MuiFormControl', ['root', 'marginNone', 'marginNormal', 'marginDense', 'fullWidth', 'disabled']);
489
-
490
- const _excluded$3 = ["children", "className", "color", "component", "disabled", "error", "focused", "fullWidth", "hiddenLabel", "margin", "required", "size", "variant"];
491
- const useUtilityClasses$2 = ownerState => {
492
- const {
493
- classes,
494
- margin,
495
- fullWidth
496
- } = ownerState;
497
- const slots = {
498
- root: ['root', margin !== 'none' && `margin${capitalize(margin)}`, fullWidth && 'fullWidth']
499
- };
500
- return composeClasses(slots, getFormControlUtilityClasses, classes);
501
- };
502
- const FormControlRoot = styled$1('div', {
503
- name: 'MuiFormControl',
504
- slot: 'Root',
505
- overridesResolver: ({
506
- ownerState
507
- }, styles) => {
508
- return _extends({}, styles.root, styles[`margin${capitalize(ownerState.margin)}`], ownerState.fullWidth && styles.fullWidth);
509
- }
510
- })(({
511
- ownerState
512
- }) => _extends({
513
- display: 'inline-flex',
514
- flexDirection: 'column',
515
- position: 'relative',
516
- // Reset fieldset default style.
517
- minWidth: 0,
518
- padding: 0,
519
- margin: 0,
520
- border: 0,
521
- verticalAlign: 'top'
522
- }, ownerState.margin === 'normal' && {
523
- marginTop: 16,
524
- marginBottom: 8
525
- }, ownerState.margin === 'dense' && {
526
- marginTop: 8,
527
- marginBottom: 4
528
- }, ownerState.fullWidth && {
529
- width: '100%'
530
- }));
531
-
532
- /**
533
- * Provides context such as filled/focused/error/required for form inputs.
534
- * Relying on the context provides high flexibility and ensures that the state always stays
535
- * consistent across the children of the `FormControl`.
536
- * This context is used by the following components:
537
- *
538
- * - FormLabel
539
- * - FormHelperText
540
- * - Input
541
- * - InputLabel
542
- *
543
- * You can find one composition example below and more going to [the demos](/material-ui/react-text-field/#components).
544
- *
545
- * ```jsx
546
- * <FormControl>
547
- * <InputLabel htmlFor="my-input">Email address</InputLabel>
548
- * <Input id="my-input" aria-describedby="my-helper-text" />
549
- * <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
550
- * </FormControl>
551
- * ```
552
- *
553
- * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies.
554
- * For instance, only one input can be focused at the same time, the state shouldn't be shared.
555
- */
556
- const FormControl = /*#__PURE__*/React.forwardRef(function FormControl(inProps, ref) {
557
- const props = useThemeProps({
558
- props: inProps,
559
- name: 'MuiFormControl'
560
- });
561
- const {
562
- children,
563
- className,
564
- color = 'primary',
565
- component = 'div',
566
- disabled = false,
567
- error = false,
568
- focused: visuallyFocused,
569
- fullWidth = false,
570
- hiddenLabel = false,
571
- margin = 'none',
572
- required = false,
573
- size = 'medium',
574
- variant = 'outlined'
575
- } = props,
576
- other = _objectWithoutPropertiesLoose(props, _excluded$3);
577
- const ownerState = _extends({}, props, {
578
- color,
579
- component,
580
- disabled,
581
- error,
582
- fullWidth,
583
- hiddenLabel,
584
- margin,
585
- required,
586
- size,
587
- variant
588
- });
589
- const classes = useUtilityClasses$2(ownerState);
590
- const [adornedStart, setAdornedStart] = React.useState(() => {
591
- // We need to iterate through the children and find the Input in order
592
- // to fully support server-side rendering.
593
- let initialAdornedStart = false;
594
- if (children) {
595
- React.Children.forEach(children, child => {
596
- if (!isMuiElement(child, ['Input', 'Select'])) {
597
- return;
598
- }
599
- const input = isMuiElement(child, ['Select']) ? child.props.input : child;
600
- if (input && isAdornedStart(input.props)) {
601
- initialAdornedStart = true;
602
- }
603
- });
604
- }
605
- return initialAdornedStart;
606
- });
607
- const [filled, setFilled] = React.useState(() => {
608
- // We need to iterate through the children and find the Input in order
609
- // to fully support server-side rendering.
610
- let initialFilled = false;
611
- if (children) {
612
- React.Children.forEach(children, child => {
613
- if (!isMuiElement(child, ['Input', 'Select'])) {
614
- return;
615
- }
616
- if (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) {
617
- initialFilled = true;
618
- }
619
- });
620
- }
621
- return initialFilled;
622
- });
623
- const [focusedState, setFocused] = React.useState(false);
624
- if (disabled && focusedState) {
625
- setFocused(false);
626
- }
627
- const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState;
628
- let registerEffect;
629
- if (process.env.NODE_ENV !== 'production') {
630
- // eslint-disable-next-line react-hooks/rules-of-hooks
631
- const registeredInput = React.useRef(false);
632
- registerEffect = () => {
633
- if (registeredInput.current) {
634
- console.error(['MUI: There are multiple `InputBase` components inside a FormControl.', 'This creates visual inconsistencies, only use one `InputBase`.'].join('\n'));
635
- }
636
- registeredInput.current = true;
637
- return () => {
638
- registeredInput.current = false;
639
- };
640
- };
641
- }
642
- const childContext = React.useMemo(() => {
643
- return {
644
- adornedStart,
645
- setAdornedStart,
646
- color,
647
- disabled,
648
- error,
649
- filled,
650
- focused,
651
- fullWidth,
652
- hiddenLabel,
653
- size,
654
- onBlur: () => {
655
- setFocused(false);
656
- },
657
- onEmpty: () => {
658
- setFilled(false);
659
- },
660
- onFilled: () => {
661
- setFilled(true);
662
- },
663
- onFocus: () => {
664
- setFocused(true);
665
- },
666
- registerEffect,
667
- required,
668
- variant
669
- };
670
- }, [adornedStart, color, disabled, error, filled, focused, fullWidth, hiddenLabel, registerEffect, required, size, variant]);
671
- return /*#__PURE__*/jsxRuntimeExports.jsx(FormControlContext.Provider, {
672
- value: childContext,
673
- children: /*#__PURE__*/jsxRuntimeExports.jsx(FormControlRoot, _extends({
674
- as: component,
675
- ownerState: ownerState,
676
- className: clsx(classes.root, className),
677
- ref: ref
678
- }, other, {
679
- children: children
680
- }))
681
- });
682
- });
683
- process.env.NODE_ENV !== "production" ? FormControl.propTypes /* remove-proptypes */ = {
684
- // ----------------------------- Warning --------------------------------
685
- // | These PropTypes are generated from the TypeScript type definitions |
686
- // | To update them edit the d.ts file and run "yarn proptypes" |
687
- // ----------------------------------------------------------------------
688
- /**
689
- * The content of the component.
690
- */
691
- children: PropTypes.node,
692
- /**
693
- * Override or extend the styles applied to the component.
694
- */
695
- classes: PropTypes.object,
696
- /**
697
- * @ignore
698
- */
699
- className: PropTypes.string,
700
- /**
701
- * The color of the component.
702
- * It supports both default and custom theme colors, which can be added as shown in the
703
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors).
704
- * @default 'primary'
705
- */
706
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
707
- /**
708
- * The component used for the root node.
709
- * Either a string to use a HTML element or a component.
710
- */
711
- component: PropTypes.elementType,
712
- /**
713
- * If `true`, the label, input and helper text should be displayed in a disabled state.
714
- * @default false
715
- */
716
- disabled: PropTypes.bool,
717
- /**
718
- * If `true`, the label is displayed in an error state.
719
- * @default false
720
- */
721
- error: PropTypes.bool,
722
- /**
723
- * If `true`, the component is displayed in focused state.
724
- */
725
- focused: PropTypes.bool,
726
- /**
727
- * If `true`, the component will take up the full width of its container.
728
- * @default false
729
- */
730
- fullWidth: PropTypes.bool,
731
- /**
732
- * If `true`, the label is hidden.
733
- * This is used to increase density for a `FilledInput`.
734
- * Be sure to add `aria-label` to the `input` element.
735
- * @default false
736
- */
737
- hiddenLabel: PropTypes.bool,
738
- /**
739
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
740
- * @default 'none'
741
- */
742
- margin: PropTypes.oneOf(['dense', 'none', 'normal']),
743
- /**
744
- * If `true`, the label will indicate that the `input` is required.
745
- * @default false
746
- */
747
- required: PropTypes.bool,
748
- /**
749
- * The size of the component.
750
- * @default 'medium'
751
- */
752
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
753
- /**
754
- * The system prop that allows defining system overrides as well as additional CSS styles.
755
- */
756
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
757
- /**
758
- * The variant to use.
759
- * @default 'outlined'
760
- */
761
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
762
- } : void 0;
763
- var FormControl$1 = FormControl;
764
-
765
- function getFormHelperTextUtilityClasses(slot) {
766
- return generateUtilityClass('MuiFormHelperText', slot);
767
- }
768
- const formHelperTextClasses = generateUtilityClasses('MuiFormHelperText', ['root', 'error', 'disabled', 'sizeSmall', 'sizeMedium', 'contained', 'focused', 'filled', 'required']);
769
- var formHelperTextClasses$1 = formHelperTextClasses;
770
-
771
- var _span;
772
- const _excluded$2 = ["children", "className", "component", "disabled", "error", "filled", "focused", "margin", "required", "variant"];
773
- const useUtilityClasses$1 = ownerState => {
774
- const {
775
- classes,
776
- contained,
777
- size,
778
- disabled,
779
- error,
780
- filled,
781
- focused,
782
- required
783
- } = ownerState;
784
- const slots = {
785
- root: ['root', disabled && 'disabled', error && 'error', size && `size${capitalize(size)}`, contained && 'contained', focused && 'focused', filled && 'filled', required && 'required']
786
- };
787
- return composeClasses(slots, getFormHelperTextUtilityClasses, classes);
788
- };
789
- const FormHelperTextRoot = styled$1('p', {
790
- name: 'MuiFormHelperText',
791
- slot: 'Root',
792
- overridesResolver: (props, styles) => {
793
- const {
794
- ownerState
795
- } = props;
796
- return [styles.root, ownerState.size && styles[`size${capitalize(ownerState.size)}`], ownerState.contained && styles.contained, ownerState.filled && styles.filled];
797
- }
798
- })(({
799
- theme,
800
- ownerState
801
- }) => _extends({
802
- color: (theme.vars || theme).palette.text.secondary
803
- }, theme.typography.caption, {
804
- textAlign: 'left',
805
- marginTop: 3,
806
- marginRight: 0,
807
- marginBottom: 0,
808
- marginLeft: 0,
809
- [`&.${formHelperTextClasses$1.disabled}`]: {
810
- color: (theme.vars || theme).palette.text.disabled
811
- },
812
- [`&.${formHelperTextClasses$1.error}`]: {
813
- color: (theme.vars || theme).palette.error.main
814
- }
815
- }, ownerState.size === 'small' && {
816
- marginTop: 4
817
- }, ownerState.contained && {
818
- marginLeft: 14,
819
- marginRight: 14
820
- }));
821
- const FormHelperText = /*#__PURE__*/React.forwardRef(function FormHelperText(inProps, ref) {
822
- const props = useThemeProps({
823
- props: inProps,
824
- name: 'MuiFormHelperText'
825
- });
826
- const {
827
- children,
828
- className,
829
- component = 'p'
830
- } = props,
831
- other = _objectWithoutPropertiesLoose(props, _excluded$2);
832
- const muiFormControl = useFormControl();
833
- const fcs = formControlState({
834
- props,
835
- muiFormControl,
836
- states: ['variant', 'size', 'disabled', 'error', 'filled', 'focused', 'required']
837
- });
838
- const ownerState = _extends({}, props, {
839
- component,
840
- contained: fcs.variant === 'filled' || fcs.variant === 'outlined',
841
- variant: fcs.variant,
842
- size: fcs.size,
843
- disabled: fcs.disabled,
844
- error: fcs.error,
845
- filled: fcs.filled,
846
- focused: fcs.focused,
847
- required: fcs.required
848
- });
849
- const classes = useUtilityClasses$1(ownerState);
850
- return /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextRoot, _extends({
851
- as: component,
852
- ownerState: ownerState,
853
- className: clsx(classes.root, className),
854
- ref: ref
855
- }, other, {
856
- children: children === ' ' ? // notranslate needed while Google Translate will not fix zero-width space issue
857
- _span || (_span = /*#__PURE__*/jsxRuntimeExports.jsx("span", {
858
- className: "notranslate",
859
- children: "\u200B"
860
- })) : children
861
- }));
862
- });
863
- process.env.NODE_ENV !== "production" ? FormHelperText.propTypes /* remove-proptypes */ = {
864
- // ----------------------------- Warning --------------------------------
865
- // | These PropTypes are generated from the TypeScript type definitions |
866
- // | To update them edit the d.ts file and run "yarn proptypes" |
867
- // ----------------------------------------------------------------------
868
- /**
869
- * The content of the component.
870
- *
871
- * If `' '` is provided, the component reserves one line height for displaying a future message.
872
- */
873
- children: PropTypes.node,
874
- /**
875
- * Override or extend the styles applied to the component.
876
- */
877
- classes: PropTypes.object,
878
- /**
879
- * @ignore
880
- */
881
- className: PropTypes.string,
882
- /**
883
- * The component used for the root node.
884
- * Either a string to use a HTML element or a component.
885
- */
886
- component: PropTypes.elementType,
887
- /**
888
- * If `true`, the helper text should be displayed in a disabled state.
889
- */
890
- disabled: PropTypes.bool,
891
- /**
892
- * If `true`, helper text should be displayed in an error state.
893
- */
894
- error: PropTypes.bool,
895
- /**
896
- * If `true`, the helper text should use filled classes key.
897
- */
898
- filled: PropTypes.bool,
899
- /**
900
- * If `true`, the helper text should use focused classes key.
901
- */
902
- focused: PropTypes.bool,
903
- /**
904
- * If `dense`, will adjust vertical spacing. This is normally obtained via context from
905
- * FormControl.
906
- */
907
- margin: PropTypes.oneOf(['dense']),
908
- /**
909
- * If `true`, the helper text should use required classes key.
910
- */
911
- required: PropTypes.bool,
912
- /**
913
- * The system prop that allows defining system overrides as well as additional CSS styles.
914
- */
915
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
916
- /**
917
- * The variant to use.
918
- */
919
- variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['filled', 'outlined', 'standard']), PropTypes.string])
920
- } : void 0;
921
- var FormHelperText$1 = FormHelperText;
922
-
923
- function getTextFieldUtilityClass(slot) {
924
- return generateUtilityClass('MuiTextField', slot);
925
- }
926
- generateUtilityClasses('MuiTextField', ['root']);
927
-
928
- const _excluded$1 = ["autoComplete", "autoFocus", "children", "className", "color", "defaultValue", "disabled", "error", "FormHelperTextProps", "fullWidth", "helperText", "id", "InputLabelProps", "inputProps", "InputProps", "inputRef", "label", "maxRows", "minRows", "multiline", "name", "onBlur", "onChange", "onClick", "onFocus", "placeholder", "required", "rows", "select", "SelectProps", "type", "value", "variant"];
929
- const variantComponent = {
930
- standard: Input,
931
- filled: FilledInput,
932
- outlined: OutlinedInput
933
- };
934
- const useUtilityClasses = ownerState => {
935
- const {
936
- classes
937
- } = ownerState;
938
- const slots = {
939
- root: ['root']
940
- };
941
- return composeClasses(slots, getTextFieldUtilityClass, classes);
942
- };
943
- const TextFieldRoot = styled$1(FormControl$1, {
944
- name: 'MuiTextField',
945
- slot: 'Root',
946
- overridesResolver: (props, styles) => styles.root
947
- })({});
948
-
949
- /**
950
- * The `TextField` is a convenience wrapper for the most common cases (80%).
951
- * It cannot be all things to all people, otherwise the API would grow out of control.
952
- *
953
- * ## Advanced Configuration
954
- *
955
- * It's important to understand that the text field is a simple abstraction
956
- * on top of the following components:
957
- *
958
- * - [FormControl](/material-ui/api/form-control/)
959
- * - [InputLabel](/material-ui/api/input-label/)
960
- * - [FilledInput](/material-ui/api/filled-input/)
961
- * - [OutlinedInput](/material-ui/api/outlined-input/)
962
- * - [Input](/material-ui/api/input/)
963
- * - [FormHelperText](/material-ui/api/form-helper-text/)
964
- *
965
- * If you wish to alter the props applied to the `input` element, you can do so as follows:
966
- *
967
- * ```jsx
968
- * const inputProps = {
969
- * step: 300,
970
- * };
971
- *
972
- * return <TextField id="time" type="time" inputProps={inputProps} />;
973
- * ```
974
- *
975
- * For advanced cases, please look at the source of TextField by clicking on the
976
- * "Edit this page" button above. Consider either:
977
- *
978
- * - using the upper case props for passing values directly to the components
979
- * - using the underlying components directly as shown in the demos
980
- */
981
- const TextField = /*#__PURE__*/React.forwardRef(function TextField(inProps, ref) {
982
- const props = useThemeProps({
983
- props: inProps,
984
- name: 'MuiTextField'
985
- });
986
- const {
987
- autoComplete,
988
- autoFocus = false,
989
- children,
990
- className,
991
- color = 'primary',
992
- defaultValue,
993
- disabled = false,
994
- error = false,
995
- FormHelperTextProps,
996
- fullWidth = false,
997
- helperText,
998
- id: idOverride,
999
- InputLabelProps,
1000
- inputProps,
1001
- InputProps,
1002
- inputRef,
1003
- label,
1004
- maxRows,
1005
- minRows,
1006
- multiline = false,
1007
- name,
1008
- onBlur,
1009
- onChange,
1010
- onClick,
1011
- onFocus,
1012
- placeholder,
1013
- required = false,
1014
- rows,
1015
- select = false,
1016
- SelectProps,
1017
- type,
1018
- value,
1019
- variant = 'outlined'
1020
- } = props,
1021
- other = _objectWithoutPropertiesLoose(props, _excluded$1);
1022
- const ownerState = _extends({}, props, {
1023
- autoFocus,
1024
- color,
1025
- disabled,
1026
- error,
1027
- fullWidth,
1028
- multiline,
1029
- required,
1030
- select,
1031
- variant
1032
- });
1033
- const classes = useUtilityClasses(ownerState);
1034
- if (process.env.NODE_ENV !== 'production') {
1035
- if (select && !children) {
1036
- console.error('MUI: `children` must be passed when using the `TextField` component with `select`.');
1037
- }
1038
- }
1039
- const InputMore = {};
1040
- if (variant === 'outlined') {
1041
- if (InputLabelProps && typeof InputLabelProps.shrink !== 'undefined') {
1042
- InputMore.notched = InputLabelProps.shrink;
1043
- }
1044
- InputMore.label = label;
1045
- }
1046
- if (select) {
1047
- // unset defaults from textbox inputs
1048
- if (!SelectProps || !SelectProps.native) {
1049
- InputMore.id = undefined;
1050
- }
1051
- InputMore['aria-describedby'] = undefined;
1052
- }
1053
- const id = useId(idOverride);
1054
- const helperTextId = helperText && id ? `${id}-helper-text` : undefined;
1055
- const inputLabelId = label && id ? `${id}-label` : undefined;
1056
- const InputComponent = variantComponent[variant];
1057
- const InputElement = /*#__PURE__*/jsxRuntimeExports.jsx(InputComponent, _extends({
1058
- "aria-describedby": helperTextId,
1059
- autoComplete: autoComplete,
1060
- autoFocus: autoFocus,
1061
- defaultValue: defaultValue,
1062
- fullWidth: fullWidth,
1063
- multiline: multiline,
1064
- name: name,
1065
- rows: rows,
1066
- maxRows: maxRows,
1067
- minRows: minRows,
1068
- type: type,
1069
- value: value,
1070
- id: id,
1071
- inputRef: inputRef,
1072
- onBlur: onBlur,
1073
- onChange: onChange,
1074
- onFocus: onFocus,
1075
- onClick: onClick,
1076
- placeholder: placeholder,
1077
- inputProps: inputProps
1078
- }, InputMore, InputProps));
1079
- return /*#__PURE__*/jsxRuntimeExports.jsxs(TextFieldRoot, _extends({
1080
- className: clsx(classes.root, className),
1081
- disabled: disabled,
1082
- error: error,
1083
- fullWidth: fullWidth,
1084
- ref: ref,
1085
- required: required,
1086
- color: color,
1087
- variant: variant,
1088
- ownerState: ownerState
1089
- }, other, {
1090
- children: [label != null && label !== '' && /*#__PURE__*/jsxRuntimeExports.jsx(InputLabel$1, _extends({
1091
- htmlFor: id,
1092
- id: inputLabelId
1093
- }, InputLabelProps, {
1094
- children: label
1095
- })), select ? /*#__PURE__*/jsxRuntimeExports.jsx(Select, _extends({
1096
- "aria-describedby": helperTextId,
1097
- id: id,
1098
- labelId: inputLabelId,
1099
- value: value,
1100
- input: InputElement
1101
- }, SelectProps, {
1102
- children: children
1103
- })) : InputElement, helperText && /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperText$1, _extends({
1104
- id: helperTextId
1105
- }, FormHelperTextProps, {
1106
- children: helperText
1107
- }))]
1108
- }));
1109
- });
1110
- process.env.NODE_ENV !== "production" ? TextField.propTypes /* remove-proptypes */ = {
1111
- // ----------------------------- Warning --------------------------------
1112
- // | These PropTypes are generated from the TypeScript type definitions |
1113
- // | To update them edit the d.ts file and run "yarn proptypes" |
1114
- // ----------------------------------------------------------------------
1115
- /**
1116
- * This prop helps users to fill forms faster, especially on mobile devices.
1117
- * The name can be confusing, as it's more like an autofill.
1118
- * You can learn more about it [following the specification](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill).
1119
- */
1120
- autoComplete: PropTypes.string,
1121
- /**
1122
- * If `true`, the `input` element is focused during the first mount.
1123
- * @default false
1124
- */
1125
- autoFocus: PropTypes.bool,
1126
- /**
1127
- * @ignore
1128
- */
1129
- children: PropTypes.node,
1130
- /**
1131
- * Override or extend the styles applied to the component.
1132
- */
1133
- classes: PropTypes.object,
1134
- /**
1135
- * @ignore
1136
- */
1137
- className: PropTypes.string,
1138
- /**
1139
- * The color of the component.
1140
- * It supports both default and custom theme colors, which can be added as shown in the
1141
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors).
1142
- * @default 'primary'
1143
- */
1144
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
1145
- /**
1146
- * The default value. Use when the component is not controlled.
1147
- */
1148
- defaultValue: PropTypes.any,
1149
- /**
1150
- * If `true`, the component is disabled.
1151
- * @default false
1152
- */
1153
- disabled: PropTypes.bool,
1154
- /**
1155
- * If `true`, the label is displayed in an error state.
1156
- * @default false
1157
- */
1158
- error: PropTypes.bool,
1159
- /**
1160
- * Props applied to the [`FormHelperText`](/material-ui/api/form-helper-text/) element.
1161
- */
1162
- FormHelperTextProps: PropTypes.object,
1163
- /**
1164
- * If `true`, the input will take up the full width of its container.
1165
- * @default false
1166
- */
1167
- fullWidth: PropTypes.bool,
1168
- /**
1169
- * The helper text content.
1170
- */
1171
- helperText: PropTypes.node,
1172
- /**
1173
- * The id of the `input` element.
1174
- * Use this prop to make `label` and `helperText` accessible for screen readers.
1175
- */
1176
- id: PropTypes.string,
1177
- /**
1178
- * Props applied to the [`InputLabel`](/material-ui/api/input-label/) element.
1179
- * Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
1180
- */
1181
- InputLabelProps: PropTypes.object,
1182
- /**
1183
- * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
1184
- */
1185
- inputProps: PropTypes.object,
1186
- /**
1187
- * Props applied to the Input element.
1188
- * It will be a [`FilledInput`](/material-ui/api/filled-input/),
1189
- * [`OutlinedInput`](/material-ui/api/outlined-input/) or [`Input`](/material-ui/api/input/)
1190
- * component depending on the `variant` prop value.
1191
- */
1192
- InputProps: PropTypes.object,
1193
- /**
1194
- * Pass a ref to the `input` element.
1195
- */
1196
- inputRef: refType,
1197
- /**
1198
- * The label content.
1199
- */
1200
- label: PropTypes.node,
1201
- /**
1202
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
1203
- * @default 'none'
1204
- */
1205
- margin: PropTypes.oneOf(['dense', 'none', 'normal']),
1206
- /**
1207
- * Maximum number of rows to display when multiline option is set to true.
1208
- */
1209
- maxRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1210
- /**
1211
- * Minimum number of rows to display when multiline option is set to true.
1212
- */
1213
- minRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1214
- /**
1215
- * If `true`, a `textarea` element is rendered instead of an input.
1216
- * @default false
1217
- */
1218
- multiline: PropTypes.bool,
1219
- /**
1220
- * Name attribute of the `input` element.
1221
- */
1222
- name: PropTypes.string,
1223
- /**
1224
- * @ignore
1225
- */
1226
- onBlur: PropTypes.func,
1227
- /**
1228
- * Callback fired when the value is changed.
1229
- *
1230
- * @param {object} event The event source of the callback.
1231
- * You can pull out the new value by accessing `event.target.value` (string).
1232
- */
1233
- onChange: PropTypes.func,
1234
- /**
1235
- * @ignore
1236
- */
1237
- onClick: PropTypes.func,
1238
- /**
1239
- * @ignore
1240
- */
1241
- onFocus: PropTypes.func,
1242
- /**
1243
- * The short hint displayed in the `input` before the user enters a value.
1244
- */
1245
- placeholder: PropTypes.string,
1246
- /**
1247
- * If `true`, the label is displayed as required and the `input` element is required.
1248
- * @default false
1249
- */
1250
- required: PropTypes.bool,
1251
- /**
1252
- * Number of rows to display when multiline option is set to true.
1253
- */
1254
- rows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1255
- /**
1256
- * Render a [`Select`](/material-ui/api/select/) element while passing the Input element to `Select` as `input` parameter.
1257
- * If this option is set you must pass the options of the select as children.
1258
- * @default false
1259
- */
1260
- select: PropTypes.bool,
1261
- /**
1262
- * Props applied to the [`Select`](/material-ui/api/select/) element.
1263
- */
1264
- SelectProps: PropTypes.object,
1265
- /**
1266
- * The size of the component.
1267
- */
1268
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
1269
- /**
1270
- * The system prop that allows defining system overrides as well as additional CSS styles.
1271
- */
1272
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1273
- /**
1274
- * Type of the `input` element. It should be [a valid HTML5 input type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types).
1275
- */
1276
- type: PropTypes /* @typescript-to-proptypes-ignore */.string,
1277
- /**
1278
- * The value of the `input` element, required for a controlled component.
1279
- */
1280
- value: PropTypes.any,
1281
- /**
1282
- * The variant to use.
1283
- * @default 'outlined'
1284
- */
1285
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
1286
- } : void 0;
1287
- var TextField$1 = TextField;
14
+ import { n as normalizeRowSelectionModel, o as onServerSideSelectionStatusChange, g as getSelectionCount, i as isRowSelected, S as ServerSideControlledPagination, C as ControlledPagination } from './ServerSideControlledPagination.js';
15
+ import { B as BaseButton, a as BaseCheckbox, c as BaseIconButton, b as BaseIcon } from './BaseIconButton.js';
1288
16
 
1289
17
  const SUBMIT_FILTER_STROKE_TIME = 500;
1290
18
  const InputNumberInterval = props => {
@@ -1326,7 +54,7 @@ const InputNumberInterval = props => {
1326
54
  const newLowerBound = event.target.value;
1327
55
  updateFilterValue(newLowerBound, filterValueState[1]);
1328
56
  };
1329
- return /*#__PURE__*/React.createElement(Box$1, {
57
+ return /*#__PURE__*/React.createElement(Box, {
1330
58
  sx: {
1331
59
  display: 'inline-flex',
1332
60
  flexDirection: 'row',
@@ -1334,7 +62,7 @@ const InputNumberInterval = props => {
1334
62
  height: 48,
1335
63
  pl: '20px'
1336
64
  }
1337
- }, /*#__PURE__*/React.createElement(TextField$1, {
65
+ }, /*#__PURE__*/React.createElement(TextField, {
1338
66
  name: "lower-bound-input",
1339
67
  placeholder: "From",
1340
68
  label: "From",
@@ -1346,7 +74,7 @@ const InputNumberInterval = props => {
1346
74
  sx: {
1347
75
  mr: 2
1348
76
  }
1349
- }), /*#__PURE__*/React.createElement(TextField$1, {
77
+ }), /*#__PURE__*/React.createElement(TextField, {
1350
78
  name: "upper-bound-input",
1351
79
  placeholder: "To",
1352
80
  label: "To",
@@ -1378,8 +106,8 @@ const isBetweenOperator = {
1378
106
  if (typeof filterItem.value[0] !== 'number' || typeof filterItem.value[1] !== 'number') {
1379
107
  return null;
1380
108
  }
1381
- return params => {
1382
- return params.value !== null && params.value !== undefined && filterItem.value[0] <= params.value && params.value <= filterItem.value[1];
109
+ return value => {
110
+ return value !== null && value !== undefined && filterItem.value[0] <= value && value <= filterItem.value[1];
1383
111
  };
1384
112
  },
1385
113
  InputComponent: InputNumberInterval
@@ -1395,14 +123,14 @@ const doesNotContain = {
1395
123
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1396
124
  return null;
1397
125
  }
1398
- return params => {
126
+ return value => {
1399
127
  if (filterItem.value.length === 0) {
1400
128
  return true;
1401
129
  }
1402
- if (params.value == null) {
130
+ if (value == null) {
1403
131
  return true;
1404
132
  }
1405
- if (String(params.value).indexOf(filterItem.value) !== -1) {
133
+ if (String(value).indexOf(filterItem.value) !== -1) {
1406
134
  return false;
1407
135
  }
1408
136
  return true;
@@ -1419,11 +147,11 @@ const doesNotEndWithOperator = {
1419
147
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1420
148
  return null;
1421
149
  }
1422
- return params => {
1423
- if (params.value == null) {
150
+ return value => {
151
+ if (value == null) {
1424
152
  return true;
1425
153
  }
1426
- return !String(params.value).endsWith(filterItem.value);
154
+ return !String(value).endsWith(filterItem.value);
1427
155
  };
1428
156
  },
1429
157
  InputComponent: GridFilterInputValue
@@ -1437,11 +165,11 @@ const doesNotEqual = {
1437
165
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1438
166
  return null;
1439
167
  }
1440
- return params => {
1441
- if (params.value == null) {
168
+ return value => {
169
+ if (value == null) {
1442
170
  return true;
1443
171
  }
1444
- if (String(params.value) === filterItem.value) {
172
+ if (String(value) === filterItem.value) {
1445
173
  return false;
1446
174
  }
1447
175
  return true;
@@ -1458,11 +186,11 @@ const doesNotHaveOperator = {
1458
186
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1459
187
  return null;
1460
188
  }
1461
- return params => {
1462
- if (params.value == null) {
189
+ return value => {
190
+ if (value == null) {
1463
191
  return true;
1464
192
  }
1465
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
193
+ const cellValues = Array.isArray(value) ? value : [value];
1466
194
  return !cellValues.map(value => String(value)).includes(filterItem.value);
1467
195
  };
1468
196
  },
@@ -1480,11 +208,11 @@ const doesNotStartWithOperator = {
1480
208
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1481
209
  return null;
1482
210
  }
1483
- return params => {
1484
- if (params.value == null) {
211
+ return value => {
212
+ if (value == null) {
1485
213
  return true;
1486
214
  }
1487
- return !String(params.value).startsWith(filterItem.value);
215
+ return !String(value).startsWith(filterItem.value);
1488
216
  };
1489
217
  },
1490
218
  InputComponent: GridFilterInputValue
@@ -1498,11 +226,11 @@ const hasOperator = {
1498
226
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1499
227
  return null;
1500
228
  }
1501
- return params => {
1502
- if (params.value == null) {
229
+ return value => {
230
+ if (value == null) {
1503
231
  return false;
1504
232
  }
1505
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
233
+ const cellValues = Array.isArray(value) ? value : [value];
1506
234
  return cellValues.map(value => String(value)).includes(filterItem.value);
1507
235
  };
1508
236
  },
@@ -1520,11 +248,11 @@ const hasOnlyOperator = {
1520
248
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1521
249
  return null;
1522
250
  }
1523
- return params => {
1524
- if (params.value == null) {
251
+ return value => {
252
+ if (value == null) {
1525
253
  return false;
1526
254
  }
1527
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
255
+ const cellValues = Array.isArray(value) ? value : [value];
1528
256
  return cellValues.length === 1 && String(cellValues[0]) === filterItem.value;
1529
257
  };
1530
258
  },
@@ -1542,14 +270,14 @@ const isOperator = {
1542
270
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1543
271
  return null;
1544
272
  }
1545
- return params => {
1546
- if (params.value == null) {
273
+ return value => {
274
+ if (value == null) {
1547
275
  return false;
1548
276
  }
1549
- if (Array.isArray(params.value)) {
277
+ if (Array.isArray(value)) {
1550
278
  return false;
1551
279
  }
1552
- return String(params.value) === filterItem.value;
280
+ return String(value) === filterItem.value;
1553
281
  };
1554
282
  },
1555
283
  InputComponent: GridFilterInputValue
@@ -1566,14 +294,14 @@ const isNotOperator = {
1566
294
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1567
295
  return null;
1568
296
  }
1569
- return params => {
1570
- if (params.value == null) {
297
+ return value => {
298
+ if (value == null) {
1571
299
  return true;
1572
300
  }
1573
- if (Array.isArray(params.value)) {
301
+ if (Array.isArray(value)) {
1574
302
  return true;
1575
303
  }
1576
- return String(params.value) !== filterItem.value;
304
+ return String(value) !== filterItem.value;
1577
305
  };
1578
306
  },
1579
307
  InputComponent: GridFilterInputValue
@@ -1590,14 +318,14 @@ const containsAnyOfOperator = {
1590
318
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1591
319
  return null;
1592
320
  }
1593
- return params => {
321
+ return value => {
1594
322
  if (filterItem.value.length === 0) {
1595
323
  return true;
1596
324
  }
1597
- if (params.value == null) {
325
+ if (value == null) {
1598
326
  return false;
1599
327
  }
1600
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
328
+ const paramValues = Array.isArray(value) ? value : [value];
1601
329
  let match = false;
1602
330
  filterItem.value.forEach(filteredValue => {
1603
331
  paramValues.forEach(paramValue => {
@@ -1620,14 +348,14 @@ const doesNotContainAnyOfOperator = {
1620
348
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1621
349
  return null;
1622
350
  }
1623
- return params => {
351
+ return value => {
1624
352
  if (filterItem.value.length === 0) {
1625
353
  return true;
1626
354
  }
1627
- if (params.value == null) {
355
+ if (value == null) {
1628
356
  return true;
1629
357
  }
1630
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
358
+ const paramValues = Array.isArray(value) ? value : [value];
1631
359
  for (const filteredValue of filterItem.value) {
1632
360
  for (const paramValue of paramValues) {
1633
361
  if (String(paramValue).indexOf(filteredValue) !== -1) {
@@ -1649,14 +377,14 @@ const doesNotEndWithAnyOfOperator = {
1649
377
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1650
378
  return null;
1651
379
  }
1652
- return params => {
380
+ return value => {
1653
381
  if (filterItem.value.length === 0) {
1654
382
  return true;
1655
383
  }
1656
- if (params.value == null) {
384
+ if (value == null) {
1657
385
  return true;
1658
386
  }
1659
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
387
+ const paramValues = Array.isArray(value) ? value : [value];
1660
388
  for (const filteredValue of filterItem.value) {
1661
389
  for (const paramValue of paramValues) {
1662
390
  if (String(paramValue).endsWith(filteredValue)) {
@@ -1678,11 +406,11 @@ const doesNotHaveAnyOf = {
1678
406
  if (!filterItem.field || !filterItem.value || !Array.isArray(filterItem.value) || filterItem.value.length === 0) {
1679
407
  return null;
1680
408
  }
1681
- return params => {
1682
- if (params.value == null) {
409
+ return value => {
410
+ if (value == null) {
1683
411
  return true;
1684
412
  }
1685
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
413
+ const cellValues = Array.isArray(value) ? value : [value];
1686
414
 
1687
415
  // Return true only if none of the filter values are in the cell values
1688
416
  return filterItem.value.every(filterVal => !cellValues.map(value => String(value)).includes(filterVal));
@@ -1702,14 +430,14 @@ const doesNotStartWithAnyOfOperator = {
1702
430
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1703
431
  return null;
1704
432
  }
1705
- return params => {
433
+ return value => {
1706
434
  if (filterItem.value.length === 0) {
1707
435
  return true;
1708
436
  }
1709
- if (params.value == null) {
437
+ if (value == null) {
1710
438
  return true;
1711
439
  }
1712
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
440
+ const paramValues = Array.isArray(value) ? value : [value];
1713
441
  for (const filteredValue of filterItem.value) {
1714
442
  for (const paramValue of paramValues) {
1715
443
  if (String(paramValue).startsWith(filteredValue)) {
@@ -1731,14 +459,14 @@ const endsWithAnyOfOperator = {
1731
459
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1732
460
  return null;
1733
461
  }
1734
- return params => {
462
+ return value => {
1735
463
  if (filterItem.value.length === 0) {
1736
464
  return true;
1737
465
  }
1738
- if (params.value == null) {
466
+ if (value == null) {
1739
467
  return false;
1740
468
  }
1741
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
469
+ const paramValues = Array.isArray(value) ? value : [value];
1742
470
  let match = false;
1743
471
  filterItem.value.forEach(filteredValue => {
1744
472
  paramValues.forEach(paramValue => {
@@ -1761,14 +489,14 @@ const hasAllOfOperator = {
1761
489
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1762
490
  return null;
1763
491
  }
1764
- return params => {
492
+ return value => {
1765
493
  if (filterItem.value.length === 0) {
1766
494
  return true;
1767
495
  }
1768
- if (params.value == null) {
496
+ if (value == null) {
1769
497
  return false;
1770
498
  }
1771
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
499
+ const cellValues = Array.isArray(value) ? value : [value];
1772
500
  const cellStrings = cellValues.map(value => String(value));
1773
501
  const filterItemValues = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
1774
502
  return filterItemValues.every(v => cellStrings.includes(v));
@@ -1788,14 +516,14 @@ const hasAnyOfOperator = {
1788
516
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1789
517
  return null;
1790
518
  }
1791
- return params => {
519
+ return value => {
1792
520
  if (filterItem.value.length === 0) {
1793
521
  return true;
1794
522
  }
1795
- if (params.value == null) {
523
+ if (value == null) {
1796
524
  return false;
1797
525
  }
1798
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
526
+ const cellValues = Array.isArray(value) ? value : [value];
1799
527
  const filterItemValues = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
1800
528
  return filterItemValues.some(v => cellValues.map(value => String(value)).includes(v));
1801
529
  };
@@ -1814,14 +542,14 @@ const isAnyOfOperator = {
1814
542
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1815
543
  return null;
1816
544
  }
1817
- return params => {
545
+ return value => {
1818
546
  if (filterItem.value.length === 0) {
1819
547
  return true;
1820
548
  }
1821
- if (params.value == null) {
549
+ if (value == null) {
1822
550
  return false;
1823
551
  }
1824
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
552
+ const paramValues = Array.isArray(value) ? value : [value];
1825
553
  for (const paramValue of paramValues) {
1826
554
  if (filterItem.value.includes(String(paramValue))) {
1827
555
  return true;
@@ -1844,14 +572,14 @@ const isNotAnyOfOperator = {
1844
572
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1845
573
  return null;
1846
574
  }
1847
- return params => {
575
+ return value => {
1848
576
  if (filterItem.value.length === 0) {
1849
577
  return true;
1850
578
  }
1851
- if (params.value == null) {
579
+ if (value == null) {
1852
580
  return true;
1853
581
  }
1854
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
582
+ const paramValues = Array.isArray(value) ? value : [value];
1855
583
  for (const paramValue of paramValues) {
1856
584
  if (filterItem.value.includes(String(paramValue))) {
1857
585
  return false;
@@ -1874,14 +602,14 @@ const startsWithAnyOfOperator = {
1874
602
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1875
603
  return null;
1876
604
  }
1877
- return params => {
605
+ return value => {
1878
606
  if (filterItem.value.length === 0) {
1879
607
  return true;
1880
608
  }
1881
- if (params.value == null) {
609
+ if (value == null) {
1882
610
  return false;
1883
611
  }
1884
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
612
+ const paramValues = Array.isArray(value) ? value : [value];
1885
613
  let match = false;
1886
614
  filterItem.value.forEach(filteredValue => {
1887
615
  paramValues.forEach(paramValue => {
@@ -1908,15 +636,15 @@ const isEmptyOperator = {
1908
636
  value: 'isEmpty',
1909
637
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1910
638
  getApplyFilterFn: _filterItem => {
1911
- return params => {
1912
- if (params.value == null) {
639
+ return value => {
640
+ if (value == null) {
1913
641
  return true;
1914
642
  }
1915
- if (Array.isArray(params.value)) {
1916
- return params.value.length === 0;
643
+ if (Array.isArray(value)) {
644
+ return value.length === 0;
1917
645
  }
1918
- if (typeof params.value === 'string') {
1919
- return params.value.trim() === '';
646
+ if (typeof value === 'string') {
647
+ return value.trim() === '';
1920
648
  }
1921
649
  return false;
1922
650
  };
@@ -1928,15 +656,15 @@ const isNotEmptyOperator = {
1928
656
  value: 'isNotEmpty',
1929
657
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1930
658
  getApplyFilterFn: _filterItem => {
1931
- return params => {
1932
- if (params.value == null) {
659
+ return value => {
660
+ if (value == null) {
1933
661
  return false;
1934
662
  }
1935
- if (Array.isArray(params.value)) {
1936
- return params.value.length > 0;
663
+ if (Array.isArray(value)) {
664
+ return value.length > 0;
1937
665
  }
1938
- if (typeof params.value === 'string') {
1939
- return params.value.trim() !== '';
666
+ if (typeof value === 'string') {
667
+ return value.trim() !== '';
1940
668
  }
1941
669
  return true;
1942
670
  };
@@ -1975,7 +703,10 @@ const DIMENSION_MODEL_KEY = 'dimension';
1975
703
  const FILTER_SEARCH_KEY = 'searchModel';
1976
704
  const DENSITY_MODEL_KEY = 'densityModel';
1977
705
  const COLUMN_ORDER_MODEL_KEY = 'columnOrderModel';
1978
- const CATEGORIES = [PAGINATION_MODEL_KEY, FILTER_MODEL_KEY, SORT_MODEL_KEY, VISIBILITY_MODEL_KEY, DIMENSION_MODEL_KEY, FILTER_SEARCH_KEY, PINNED_COLUMNS, DENSITY_MODEL_KEY, COLUMN_ORDER_MODEL_KEY];
706
+ const ROW_GROUPING_MODEL_KEY = 'rowGroupingModel';
707
+ const AGGREGATION_MODEL_KEY = 'aggregationModel';
708
+ const PIVOT_MODEL_KEY = 'pivotModel';
709
+ const CATEGORIES = [PAGINATION_MODEL_KEY, FILTER_MODEL_KEY, SORT_MODEL_KEY, VISIBILITY_MODEL_KEY, DIMENSION_MODEL_KEY, FILTER_SEARCH_KEY, PINNED_COLUMNS, DENSITY_MODEL_KEY, COLUMN_ORDER_MODEL_KEY, ROW_GROUPING_MODEL_KEY, AGGREGATION_MODEL_KEY, PIVOT_MODEL_KEY];
1979
710
  const buildStorageKey = _ref => {
1980
711
  let {
1981
712
  id,
@@ -2022,6 +753,18 @@ const clearPreviousVersionStorage = (id, previousLocalStorageVersions) => {
2022
753
  id,
2023
754
  version,
2024
755
  category: COLUMN_ORDER_MODEL_KEY
756
+ }), buildStorageKey({
757
+ id,
758
+ version,
759
+ category: ROW_GROUPING_MODEL_KEY
760
+ }), buildStorageKey({
761
+ id,
762
+ version,
763
+ category: AGGREGATION_MODEL_KEY
764
+ }), buildStorageKey({
765
+ id,
766
+ version,
767
+ category: PIVOT_MODEL_KEY
2025
768
  })];
2026
769
  for (const keyToDelete of keysToDelete) {
2027
770
  try {
@@ -2044,7 +787,7 @@ const COMPRESSED_PREFIX = '~';
2044
787
  * Params listed first are compressed first (least valuable to read in the URL).
2045
788
  * The filter aggregate step uses the special key `_filters_aggregate`.
2046
789
  */
2047
- const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_quickFilterValues'];
790
+ const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_aggregation', '_rowGrouping', '_quickFilterValues', '_pivot'];
2048
791
 
2049
792
  /** Params that are always short and should never be compressed. */
2050
793
  const NEVER_COMPRESS = new Set(['_sortColumn', '_pagination', '_density', '_logicOperator', 'v', 'tab']);
@@ -2285,6 +1028,13 @@ const convertToDisplayFormat = search => {
2285
1028
  const cleanSearch = search.startsWith('?') ? search.slice(1) : search;
2286
1029
  const params = cleanSearch.split('&');
2287
1030
  const converted = params.map(param => {
1031
+ const eqIndex = param.indexOf('=');
1032
+ if (eqIndex !== -1) {
1033
+ const value = param.slice(eqIndex + 1);
1034
+ // Skip conversion for compressed values — already URL-safe
1035
+ if (isCompressed(value)) return param;
1036
+ }
1037
+
2288
1038
  // Handle _sortColumn=[field,direction]
2289
1039
  if (param.startsWith('_sortColumn=')) {
2290
1040
  const value = param.slice('_sortColumn='.length);
@@ -2338,7 +1088,6 @@ const convertToDisplayFormat = search => {
2338
1088
  // Handle _columnOrder=[a,b,c]
2339
1089
  if (param.startsWith('_columnOrder=')) {
2340
1090
  const value = param.slice('_columnOrder='.length);
2341
- if (value.startsWith('~')) return param; // compressed — skip
2342
1091
  if (value.startsWith('[') && value.endsWith(']')) {
2343
1092
  const inner = value.slice(1, -1);
2344
1093
  return `_columnOrder=${inner}`;
@@ -2346,6 +1095,21 @@ const convertToDisplayFormat = search => {
2346
1095
  return param;
2347
1096
  }
2348
1097
 
1098
+ // Handle _rowGrouping=[a,b,c]
1099
+ if (param.startsWith('_rowGrouping=')) {
1100
+ const value = param.slice('_rowGrouping='.length);
1101
+ if (value.startsWith('[') && value.endsWith(']')) {
1102
+ const inner = value.slice(1, -1);
1103
+ return `_rowGrouping=${inner}`;
1104
+ }
1105
+ return param;
1106
+ }
1107
+
1108
+ // _aggregation and _pivot do not use bracket notation — pass through
1109
+ if (param.startsWith('_aggregation=') || param.startsWith('_pivot=')) {
1110
+ return param;
1111
+ }
1112
+
2349
1113
  // Handle _field[operator,type]=value or _field[operator,type]=list[a,b,c]
2350
1114
  const bracketMatch = param.match(/^_([^[]+)\[([^\]]+)\]=(.*)$/);
2351
1115
  if (bracketMatch) {
@@ -2385,6 +1149,13 @@ const convertFromDisplayFormat = (search, columns) => {
2385
1149
  const cleanSearch = search.startsWith('?') ? search.slice(1) : search;
2386
1150
  const params = cleanSearch.split('&');
2387
1151
  const converted = params.map(param => {
1152
+ const eqIndex = param.indexOf('=');
1153
+ if (eqIndex !== -1) {
1154
+ const value = param.slice(eqIndex + 1);
1155
+ // Skip conversion for compressed values — already URL-safe
1156
+ if (isCompressed(value)) return param;
1157
+ }
1158
+
2388
1159
  // Handle _sortColumn=field.direction or _sortColumn=
2389
1160
  if (param.startsWith('_sortColumn=')) {
2390
1161
  const value = param.slice('_sortColumn='.length);
@@ -2437,7 +1208,7 @@ const convertFromDisplayFormat = (search, columns) => {
2437
1208
  if (param.startsWith('_columnVisibility=')) {
2438
1209
  const value = param.slice('_columnVisibility='.length);
2439
1210
  // If it already has brackets, leave it alone
2440
- if (value.startsWith('[') || value.startsWith('~')) {
1211
+ if (value.startsWith('[')) {
2441
1212
  return param;
2442
1213
  }
2443
1214
  return `_columnVisibility=[${value}]`;
@@ -2446,13 +1217,26 @@ const convertFromDisplayFormat = (search, columns) => {
2446
1217
  // Handle _columnOrder=a,b,c
2447
1218
  if (param.startsWith('_columnOrder=')) {
2448
1219
  const value = param.slice('_columnOrder='.length);
2449
- // If it already has brackets or is compressed, leave it alone
2450
- if (value.startsWith('[') || value.startsWith('~')) {
1220
+ if (value.startsWith('[')) {
2451
1221
  return param;
2452
1222
  }
2453
1223
  return `_columnOrder=[${value}]`;
2454
1224
  }
2455
1225
 
1226
+ // Handle _rowGrouping=a,b,c
1227
+ if (param.startsWith('_rowGrouping=')) {
1228
+ const value = param.slice('_rowGrouping='.length);
1229
+ if (value.startsWith('[')) {
1230
+ return param;
1231
+ }
1232
+ return `_rowGrouping=[${value}]`;
1233
+ }
1234
+
1235
+ // _aggregation, _pivot, _filters — pass through (no bracket conversion needed)
1236
+ if (param.startsWith('_aggregation=') || param.startsWith('_pivot=') || param.startsWith('_filters=')) {
1237
+ return param;
1238
+ }
1239
+
2456
1240
  // Handle field.operator=value (dot notation for filters)
2457
1241
  const dotMatch = param.match(/^([^.]+)\.([a-zA-Z_]+)=(.*)$/);
2458
1242
  if (dotMatch) {
@@ -2495,9 +1279,10 @@ const getDecodedSearchFromUrl = (search, columns) => {
2495
1279
  const hasPaginationDotNotation = /_pagination=[^&[]+\.[^&]+/.test(searchWithoutLeadingQuestion);
2496
1280
  const hasPinnedWithoutBrackets = /(_pinnedColumnsLeft|_pinnedColumnsRight)=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2497
1281
  const hasVisibilityWithoutBrackets = /_columnVisibility=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2498
- const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[~]*(&|$)/.test(searchWithoutLeadingQuestion);
1282
+ const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1283
+ const hasRowGroupingWithoutBrackets = /_rowGrouping=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2499
1284
  const hasBracketNotation = /\[.*\]=/.test(searchWithoutLeadingQuestion);
2500
- const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets) && !hasBracketNotation;
1285
+ const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets || hasRowGroupingWithoutBrackets) && !hasBracketNotation;
2501
1286
  if (isDisplayFormat) {
2502
1287
  return '?' + convertFromDisplayFormat(searchWithoutLeadingQuestion, columns);
2503
1288
  }
@@ -2658,7 +1443,7 @@ const getFilterModelFromString = (searchString, columns) => {
2658
1443
  let quickFilterValues = [];
2659
1444
  const searchParams = new URLSearchParams();
2660
1445
  for (const [key, value] of new URLSearchParams(searchString)) {
2661
- if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_density', '_filters'].includes(key)) {
1446
+ if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_rowGrouping', '_aggregation', '_pivot', '_density', '_filters'].includes(key)) {
2662
1447
  searchParams.set(key, value);
2663
1448
  }
2664
1449
  if (key === '_logicOperator') {
@@ -3124,7 +1909,7 @@ const getSearchParamsFromDensity = density => {
3124
1909
  return searchParams;
3125
1910
  };
3126
1911
  const getDensityModel = (search, localStorageDensity, setLocalStorageDensity, _initialState, isNewVersion) => {
3127
- // MUI v6 GridInitialStatePro does not include density default to 'compact'
1912
+ // Default density when none is persisted
3128
1913
  const defaultValue = 'compact';
3129
1914
 
3130
1915
  // Persist initialState-derived density to localStorage so all three sources stay in sync
@@ -3206,7 +1991,212 @@ const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorag
3206
1991
  persistDefault();
3207
1992
  return defaultValue;
3208
1993
  };
3209
- const getFinalSearch = _ref => {
1994
+
1995
+ /** ROW GROUPING */
1996
+
1997
+ const getRowGroupingFromString = searchString => {
1998
+ if (!searchString) return 'invalid';
1999
+ const searchParams = new URLSearchParams(searchString);
2000
+ const value = searchParams.get('_rowGrouping');
2001
+ if (value === '' || value === null || value === '[]') return 'invalid';
2002
+ const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2003
+ if (!inner) return 'invalid';
2004
+ return inner.split(',').filter(Boolean);
2005
+ };
2006
+ const getSearchParamsFromRowGrouping = rowGrouping => {
2007
+ const searchParams = new URLSearchParams();
2008
+ if (rowGrouping.length > 0) {
2009
+ searchParams.set('_rowGrouping', `[${rowGrouping.join(',')}]`);
2010
+ }
2011
+ return searchParams;
2012
+ };
2013
+ const getRowGroupingModel = (search, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion) => {
2014
+ var _initialState$rowGrou, _initialState$rowGrou2;
2015
+ const defaultValue = (_initialState$rowGrou = initialState === null || initialState === void 0 ? void 0 : (_initialState$rowGrou2 = initialState.rowGrouping) === null || _initialState$rowGrou2 === void 0 ? void 0 : _initialState$rowGrou2.model) !== null && _initialState$rowGrou !== void 0 ? _initialState$rowGrou : [];
2016
+ const persistDefault = () => {
2017
+ const searchFromDefault = getSearchParamsFromRowGrouping(defaultValue);
2018
+ const searchString = urlSearchParamsToString(searchFromDefault);
2019
+ if (searchString !== localStorageRowGrouping) {
2020
+ setLocalStorageRowGrouping(searchString);
2021
+ }
2022
+ };
2023
+ if (isNewVersion) {
2024
+ persistDefault();
2025
+ return defaultValue;
2026
+ }
2027
+ const fromUrl = getRowGroupingFromString(search);
2028
+ if (fromUrl !== 'invalid') {
2029
+ const searchFromModel = getSearchParamsFromRowGrouping(fromUrl);
2030
+ const searchString = urlSearchParamsToString(searchFromModel);
2031
+ if (searchString !== localStorageRowGrouping) {
2032
+ setLocalStorageRowGrouping(searchString);
2033
+ }
2034
+ return fromUrl;
2035
+ }
2036
+ const fromLocalStorage = getRowGroupingFromString(localStorageRowGrouping);
2037
+ if (fromLocalStorage !== 'invalid') {
2038
+ return fromLocalStorage;
2039
+ }
2040
+ persistDefault();
2041
+ return defaultValue;
2042
+ };
2043
+
2044
+ /** AGGREGATION */
2045
+
2046
+ const getAggregationFromString = searchString => {
2047
+ if (!searchString) return 'invalid';
2048
+ const searchParams = new URLSearchParams(searchString);
2049
+ const value = searchParams.get('_aggregation');
2050
+ if (value === '' || value === null) return 'invalid';
2051
+
2052
+ // Format: field1.sum,field2.avg or [field1.sum,field2.avg]
2053
+ const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2054
+ if (!inner) return 'invalid';
2055
+ const model = {};
2056
+ for (const entry of inner.split(',')) {
2057
+ const dotIndex = entry.lastIndexOf('.');
2058
+ if (dotIndex <= 0) return 'invalid';
2059
+ const field = entry.slice(0, dotIndex);
2060
+ const aggFunc = entry.slice(dotIndex + 1);
2061
+ if (!field || !aggFunc) return 'invalid';
2062
+ model[field] = aggFunc;
2063
+ }
2064
+ return Object.keys(model).length > 0 ? model : 'invalid';
2065
+ };
2066
+ const getSearchParamsFromAggregation = aggregation => {
2067
+ const searchParams = new URLSearchParams();
2068
+ const entries = Object.entries(aggregation);
2069
+ if (entries.length > 0) {
2070
+ const value = entries.map(_ref => {
2071
+ let [field, aggFunc] = _ref;
2072
+ return `${field}.${aggFunc}`;
2073
+ }).join(',');
2074
+ searchParams.set('_aggregation', value);
2075
+ }
2076
+ return searchParams;
2077
+ };
2078
+ const getAggregationModel = (search, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion) => {
2079
+ var _initialState$aggrega, _initialState$aggrega2;
2080
+ const defaultValue = (_initialState$aggrega = initialState === null || initialState === void 0 ? void 0 : (_initialState$aggrega2 = initialState.aggregation) === null || _initialState$aggrega2 === void 0 ? void 0 : _initialState$aggrega2.model) !== null && _initialState$aggrega !== void 0 ? _initialState$aggrega : {};
2081
+ const persistDefault = () => {
2082
+ const searchFromDefault = getSearchParamsFromAggregation(defaultValue);
2083
+ const searchString = urlSearchParamsToString(searchFromDefault);
2084
+ if (searchString !== localStorageAggregation) {
2085
+ setLocalStorageAggregation(searchString);
2086
+ }
2087
+ };
2088
+ if (isNewVersion) {
2089
+ persistDefault();
2090
+ return defaultValue;
2091
+ }
2092
+ const fromUrl = getAggregationFromString(search);
2093
+ if (fromUrl !== 'invalid') {
2094
+ const searchFromModel = getSearchParamsFromAggregation(fromUrl);
2095
+ const searchString = urlSearchParamsToString(searchFromModel);
2096
+ if (searchString !== localStorageAggregation) {
2097
+ setLocalStorageAggregation(searchString);
2098
+ }
2099
+ return fromUrl;
2100
+ }
2101
+ const fromLocalStorage = getAggregationFromString(localStorageAggregation);
2102
+ if (fromLocalStorage !== 'invalid') {
2103
+ return fromLocalStorage;
2104
+ }
2105
+ persistDefault();
2106
+ return defaultValue;
2107
+ };
2108
+
2109
+ /** PIVOT */
2110
+
2111
+ /**
2112
+ * Pivot format: `cols:f1,f2;rows:f3;vals:f4.sum,f5.avg`
2113
+ */
2114
+ const getPivotFromString = searchString => {
2115
+ if (!searchString) return 'invalid';
2116
+ const searchParams = new URLSearchParams(searchString);
2117
+ const value = searchParams.get('_pivot');
2118
+ if (value === '' || value === null) return 'invalid';
2119
+ const model = {
2120
+ columns: [],
2121
+ rows: [],
2122
+ values: []
2123
+ };
2124
+ for (const segment of value.split(';')) {
2125
+ const colonIndex = segment.indexOf(':');
2126
+ if (colonIndex <= 0) return 'invalid';
2127
+ const key = segment.slice(0, colonIndex);
2128
+ const content = segment.slice(colonIndex + 1);
2129
+ if (key === 'cols') {
2130
+ model.columns = content ? content.split(',').filter(Boolean) : [];
2131
+ } else if (key === 'rows') {
2132
+ model.rows = content ? content.split(',').filter(Boolean) : [];
2133
+ } else if (key === 'vals') {
2134
+ if (!content) continue;
2135
+ for (const entry of content.split(',')) {
2136
+ const dotIndex = entry.lastIndexOf('.');
2137
+ if (dotIndex <= 0) return 'invalid';
2138
+ model.values.push({
2139
+ field: entry.slice(0, dotIndex),
2140
+ aggFunc: entry.slice(dotIndex + 1)
2141
+ });
2142
+ }
2143
+ }
2144
+ }
2145
+
2146
+ // At least one section must have content
2147
+ if (model.columns.length === 0 && model.rows.length === 0 && model.values.length === 0) {
2148
+ return 'invalid';
2149
+ }
2150
+ return model;
2151
+ };
2152
+ const getSearchParamsFromPivot = pivot => {
2153
+ const searchParams = new URLSearchParams();
2154
+ const hasContent = pivot.columns.length > 0 || pivot.rows.length > 0 || pivot.values.length > 0;
2155
+ if (hasContent) {
2156
+ const parts = [];
2157
+ parts.push(`cols:${pivot.columns.join(',')}`);
2158
+ parts.push(`rows:${pivot.rows.join(',')}`);
2159
+ if (pivot.values.length > 0) {
2160
+ parts.push(`vals:${pivot.values.map(v => `${v.field}.${v.aggFunc}`).join(',')}`);
2161
+ }
2162
+ searchParams.set('_pivot', parts.join(';'));
2163
+ }
2164
+ return searchParams;
2165
+ };
2166
+ const getPivotModel = (search, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion) => {
2167
+ const defaultValue = {
2168
+ columns: [],
2169
+ rows: [],
2170
+ values: []
2171
+ };
2172
+ const persistDefault = () => {
2173
+ const searchFromDefault = getSearchParamsFromPivot(defaultValue);
2174
+ const searchString = urlSearchParamsToString(searchFromDefault);
2175
+ if (searchString !== localStoragePivot) {
2176
+ setLocalStoragePivot(searchString);
2177
+ }
2178
+ };
2179
+ if (isNewVersion) {
2180
+ persistDefault();
2181
+ return defaultValue;
2182
+ }
2183
+ const fromUrl = getPivotFromString(search);
2184
+ if (fromUrl !== 'invalid') {
2185
+ const searchFromModel = getSearchParamsFromPivot(fromUrl);
2186
+ const searchString = urlSearchParamsToString(searchFromModel);
2187
+ if (searchString !== localStoragePivot) {
2188
+ setLocalStoragePivot(searchString);
2189
+ }
2190
+ return fromUrl;
2191
+ }
2192
+ const fromLocalStorage = getPivotFromString(localStoragePivot);
2193
+ if (fromLocalStorage !== 'invalid') {
2194
+ return fromLocalStorage;
2195
+ }
2196
+ persistDefault();
2197
+ return defaultValue;
2198
+ };
2199
+ const getFinalSearch = _ref2 => {
3210
2200
  let {
3211
2201
  search,
3212
2202
  localStorageVersion,
@@ -3218,8 +2208,11 @@ const getFinalSearch = _ref => {
3218
2208
  density,
3219
2209
  columnOrderModel,
3220
2210
  defaultColumnOrder,
2211
+ rowGroupingModel,
2212
+ aggregationModel,
2213
+ pivotModel,
3221
2214
  columns
3222
- } = _ref;
2215
+ } = _ref2;
3223
2216
  const filterModelSearch = getSearchParamsFromFilterModel(filterModel);
3224
2217
  const sortModelSearch = getSearchParamsFromSorting(sortModel);
3225
2218
  const paginationModelSearch = getSearchParamsFromPagination(paginationModel);
@@ -3228,6 +2221,9 @@ const getFinalSearch = _ref => {
3228
2221
  const densitySearch = getSearchParamsFromDensity(density);
3229
2222
  // Only include _columnOrder in URL when it differs from the default
3230
2223
  const columnOrderSearch = columnOrderModel.length !== defaultColumnOrder.length || columnOrderModel.some((field, i) => field !== defaultColumnOrder[i]) ? getSearchParamsFromColumnOrder(columnOrderModel) : new URLSearchParams();
2224
+ const rowGroupingSearch = getSearchParamsFromRowGrouping(rowGroupingModel);
2225
+ const aggregationSearch = getSearchParamsFromAggregation(aggregationModel);
2226
+ const pivotSearch = getSearchParamsFromPivot(pivotModel);
3231
2227
  const tabSearch = getSearchParamsFromTab(search);
3232
2228
  const searchParams = new URLSearchParams();
3233
2229
  for (const [key, value] of new URLSearchParams(search)) {
@@ -3242,7 +2238,7 @@ const getFinalSearch = _ref => {
3242
2238
  // Encode array as JSON string to preserve all values in one param
3243
2239
  searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
3244
2240
  }
3245
- return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch]);
2241
+ return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch, ...rowGroupingSearch, ...aggregationSearch, ...pivotSearch]);
3246
2242
  };
3247
2243
  /** Return the state of the table given the URL and the local storage state */
3248
2244
  const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage) => {
@@ -3267,7 +2263,13 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3267
2263
  localStorageDensity,
3268
2264
  setLocalStorageDensity,
3269
2265
  localStorageColumnOrder,
3270
- setLocalStorageColumnOrder
2266
+ setLocalStorageColumnOrder,
2267
+ localStorageRowGrouping,
2268
+ setLocalStorageRowGrouping,
2269
+ localStorageAggregation,
2270
+ setLocalStorageAggregation,
2271
+ localStoragePivot,
2272
+ setLocalStoragePivot
3271
2273
  } = localStorage;
3272
2274
  const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion);
3273
2275
  const sortModel = getSortModel(decodedSearch, columns, localStorageSorting, setLocalStorageSorting, initialState, isNewVersion);
@@ -3276,6 +2278,9 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3276
2278
  const pinnedColumnsModel = getPinnedColumns(decodedSearch, columns, localStoragePinnedColumns, setLocalStoragePinnedColumns, initialState, isNewVersion);
3277
2279
  const density = getDensityModel(decodedSearch, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion);
3278
2280
  const columnOrderModel = getColumnOrder(decodedSearch, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion);
2281
+ const rowGroupingModel = getRowGroupingModel(decodedSearch, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion);
2282
+ const aggregationModel = getAggregationModel(decodedSearch, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion);
2283
+ const pivotModel = getPivotModel(decodedSearch, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion);
3279
2284
  const defaultColumnOrder = (_initialState$columns6 = initialState === null || initialState === void 0 ? void 0 : (_initialState$columns7 = initialState.columns) === null || _initialState$columns7 === void 0 ? void 0 : _initialState$columns7.orderedFields) !== null && _initialState$columns6 !== void 0 ? _initialState$columns6 : columns.map(c => c.field);
3280
2285
  const finalSearch = getFinalSearch({
3281
2286
  localStorageVersion,
@@ -3288,6 +2293,9 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3288
2293
  density,
3289
2294
  columnOrderModel,
3290
2295
  defaultColumnOrder,
2296
+ rowGroupingModel,
2297
+ aggregationModel,
2298
+ pivotModel,
3291
2299
  columns
3292
2300
  });
3293
2301
  const internalSearchString = urlSearchParamsToString(finalSearch);
@@ -3308,10 +2316,13 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3308
2316
  pinnedColumnsModel,
3309
2317
  density,
3310
2318
  columnOrderModel,
2319
+ rowGroupingModel,
2320
+ aggregationModel,
2321
+ pivotModel,
3311
2322
  pendingSearch
3312
2323
  };
3313
2324
  };
3314
- const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns) => {
2325
+ const updateUrl = (_ref3, search, localStorageVersion, historyReplace, columns) => {
3315
2326
  let {
3316
2327
  filterModel,
3317
2328
  sortModel,
@@ -3320,8 +2331,11 @@ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns)
3320
2331
  pinnedColumnsModel,
3321
2332
  density,
3322
2333
  columnOrderModel,
3323
- defaultColumnOrder
3324
- } = _ref2;
2334
+ defaultColumnOrder,
2335
+ rowGroupingModel,
2336
+ aggregationModel,
2337
+ pivotModel
2338
+ } = _ref3;
3325
2339
  // Convert from display format to internal format if needed
3326
2340
  const decodedSearch = getDecodedSearchFromUrl(search, columns);
3327
2341
  const newSearch = getFinalSearch({
@@ -3335,6 +2349,9 @@ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns)
3335
2349
  density,
3336
2350
  columnOrderModel,
3337
2351
  defaultColumnOrder,
2352
+ rowGroupingModel,
2353
+ aggregationModel,
2354
+ pivotModel,
3338
2355
  columns
3339
2356
  });
3340
2357
  const internalSearchString = urlSearchParamsToString(newSearch);
@@ -3522,6 +2539,21 @@ const useTableStates = (id, version) => {
3522
2539
  version,
3523
2540
  category: COLUMN_ORDER_MODEL_KEY
3524
2541
  }));
2542
+ const [rowGroupingModel, setRowGroupingModel] = useFetchState('', buildStorageKey({
2543
+ id,
2544
+ version,
2545
+ category: ROW_GROUPING_MODEL_KEY
2546
+ }));
2547
+ const [aggregationModel, setAggregationModel] = useFetchState('', buildStorageKey({
2548
+ id,
2549
+ version,
2550
+ category: AGGREGATION_MODEL_KEY
2551
+ }));
2552
+ const [pivotModel, setPivotModel] = useFetchState('', buildStorageKey({
2553
+ id,
2554
+ version,
2555
+ category: PIVOT_MODEL_KEY
2556
+ }));
3525
2557
  return {
3526
2558
  paginationModel,
3527
2559
  setPaginationModel,
@@ -3538,10 +2570,69 @@ const useTableStates = (id, version) => {
3538
2570
  densityModel,
3539
2571
  setDensityModel,
3540
2572
  columnOrderModel,
3541
- setColumnOrderModel
2573
+ setColumnOrderModel,
2574
+ rowGroupingModel,
2575
+ setRowGroupingModel,
2576
+ aggregationModel,
2577
+ setAggregationModel,
2578
+ pivotModel,
2579
+ setPivotModel
3542
2580
  };
3543
2581
  };
3544
2582
 
2583
+ /** Convert our simplified PivotModel → MUI's GridPivotModel */
2584
+ const toGridPivotModel = model => ({
2585
+ columns: model.columns.map(field => ({
2586
+ field
2587
+ })),
2588
+ rows: model.rows.map(field => ({
2589
+ field
2590
+ })),
2591
+ values: model.values.map(_ref => {
2592
+ let {
2593
+ field,
2594
+ aggFunc
2595
+ } = _ref;
2596
+ return {
2597
+ field,
2598
+ aggFunc
2599
+ };
2600
+ })
2601
+ });
2602
+
2603
+ /** Convert MUI's GridPivotModel → our simplified PivotModel */
2604
+ const fromGridPivotModel = model => ({
2605
+ columns: model.columns.map(c => c.field),
2606
+ rows: model.rows.map(r => r.field),
2607
+ values: model.values.map(_ref2 => {
2608
+ let {
2609
+ field,
2610
+ aggFunc
2611
+ } = _ref2;
2612
+ return {
2613
+ field,
2614
+ aggFunc
2615
+ };
2616
+ })
2617
+ });
2618
+
2619
+ /**
2620
+ * Deep-equal comparison for plain objects / arrays.
2621
+ * Used to stabilise parsed model references so that MUI v8 does not
2622
+ * reset pagination on every render.
2623
+ */
2624
+ function isDeepEqual(a, b) {
2625
+ if (a === b) return true;
2626
+ if (a == null || b == null) return false;
2627
+ if (typeof a !== typeof b) return false;
2628
+ if (typeof a !== 'object') return false;
2629
+ const aObj = a;
2630
+ const bObj = b;
2631
+ const aKeys = Object.keys(aObj);
2632
+ const bKeys = Object.keys(bObj);
2633
+ if (aKeys.length !== bKeys.length) return false;
2634
+ return aKeys.every(key => isDeepEqual(aObj[key], bObj[key]));
2635
+ }
3545
2636
  const useStatefulTable = props => {
3546
2637
  var _initialState$columns, _initialState$columns2;
3547
2638
  const {
@@ -3554,6 +2645,9 @@ const useStatefulTable = props => {
3554
2645
  onPaginationModelChange: propsOnPaginationModelChange,
3555
2646
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3556
2647
  onSortModelChange: propsOnSortModelChange,
2648
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
2649
+ onAggregationModelChange: propsOnAggregationModelChange,
2650
+ onPivotModelChange: propsOnPivotModelChange,
3557
2651
  useRouter,
3558
2652
  localStorageVersion = 1,
3559
2653
  previousLocalStorageVersions = []
@@ -3582,16 +2676,22 @@ const useStatefulTable = props => {
3582
2676
  densityModel,
3583
2677
  setDensityModel,
3584
2678
  columnOrderModel: localStorageColumnOrder,
3585
- setColumnOrderModel: setLocalStorageColumnOrder
2679
+ setColumnOrderModel: setLocalStorageColumnOrder,
2680
+ rowGroupingModel: localStorageRowGrouping,
2681
+ setRowGroupingModel: setLocalStorageRowGrouping,
2682
+ aggregationModel: localStorageAggregation,
2683
+ setAggregationModel: setLocalStorageAggregation,
2684
+ pivotModel: localStoragePivot,
2685
+ setPivotModel: setLocalStoragePivot
3586
2686
  } = useTableStates(id, localStorageVersion);
3587
2687
 
3588
2688
  // clearing up old version keys, triggering only on first render
3589
2689
  useEffect(() => clearPreviousVersionStorage(id, previousLocalStorageVersions), [id, previousLocalStorageVersions]);
3590
- const onColumnDimensionChange = useCallback(_ref => {
2690
+ const onColumnDimensionChange = useCallback(_ref3 => {
3591
2691
  let {
3592
2692
  newWidth,
3593
2693
  field
3594
- } = _ref;
2694
+ } = _ref3;
3595
2695
  setDimensionModel(_objectSpread2(_objectSpread2({}, dimensionModel), {}, {
3596
2696
  [field]: newWidth
3597
2697
  }));
@@ -3604,6 +2704,9 @@ const useStatefulTable = props => {
3604
2704
  pinnedColumnsModel,
3605
2705
  density: densityParsed,
3606
2706
  columnOrderModel: columnOrderParsed,
2707
+ rowGroupingModel: rowGroupingParsed,
2708
+ aggregationModel: aggregationParsed,
2709
+ pivotModel: pivotParsed,
3607
2710
  pendingSearch
3608
2711
  } = getModelsParsedOrUpdateLocalStorage(search || '', localStorageVersion, propsColumns, initialState, {
3609
2712
  localStorageFilters,
@@ -3619,7 +2722,13 @@ const useStatefulTable = props => {
3619
2722
  localStorageDensity: densityModel,
3620
2723
  setLocalStorageDensity: setDensityModel,
3621
2724
  localStorageColumnOrder,
3622
- setLocalStorageColumnOrder
2725
+ setLocalStorageColumnOrder,
2726
+ localStorageRowGrouping,
2727
+ setLocalStorageRowGrouping,
2728
+ localStorageAggregation,
2729
+ setLocalStorageAggregation,
2730
+ localStoragePivot,
2731
+ setLocalStoragePivot
3623
2732
  });
3624
2733
 
3625
2734
  // Sync URL in an effect rather than during render to comply with React rules
@@ -3628,6 +2737,45 @@ const useStatefulTable = props => {
3628
2737
  historyReplace(pendingSearch);
3629
2738
  }
3630
2739
  }, [pendingSearch, historyReplace]);
2740
+
2741
+ // Stabilise parsed model references to prevent MUI v8 from resetting
2742
+ // pagination on every render due to new object identity.
2743
+ const filterParsedRef = useRef(filterParsed);
2744
+ if (!isDeepEqual(filterParsedRef.current, filterParsed)) {
2745
+ filterParsedRef.current = filterParsed;
2746
+ }
2747
+ const sortModelParsedRef = useRef(sortModelParsed);
2748
+ if (!isDeepEqual(sortModelParsedRef.current, sortModelParsed)) {
2749
+ sortModelParsedRef.current = sortModelParsed;
2750
+ }
2751
+ const paginationModelParsedRef = useRef(paginationModelParsed);
2752
+ if (!isDeepEqual(paginationModelParsedRef.current, paginationModelParsed)) {
2753
+ paginationModelParsedRef.current = paginationModelParsed;
2754
+ }
2755
+ const visibilityModelRef = useRef(visibilityModel);
2756
+ if (!isDeepEqual(visibilityModelRef.current, visibilityModel)) {
2757
+ visibilityModelRef.current = visibilityModel;
2758
+ }
2759
+ const pinnedColumnsModelRef = useRef(pinnedColumnsModel);
2760
+ if (!isDeepEqual(pinnedColumnsModelRef.current, pinnedColumnsModel)) {
2761
+ pinnedColumnsModelRef.current = pinnedColumnsModel;
2762
+ }
2763
+ const columnOrderParsedRef = useRef(columnOrderParsed);
2764
+ if (!isDeepEqual(columnOrderParsedRef.current, columnOrderParsed)) {
2765
+ columnOrderParsedRef.current = columnOrderParsed;
2766
+ }
2767
+ const rowGroupingParsedRef = useRef(rowGroupingParsed);
2768
+ if (!isDeepEqual(rowGroupingParsedRef.current, rowGroupingParsed)) {
2769
+ rowGroupingParsedRef.current = rowGroupingParsed;
2770
+ }
2771
+ const aggregationParsedRef = useRef(aggregationParsed);
2772
+ if (!isDeepEqual(aggregationParsedRef.current, aggregationParsed)) {
2773
+ aggregationParsedRef.current = aggregationParsed;
2774
+ }
2775
+ const pivotParsedRef = useRef(pivotParsed);
2776
+ if (!isDeepEqual(pivotParsedRef.current, pivotParsed)) {
2777
+ pivotParsedRef.current = pivotParsed;
2778
+ }
3631
2779
  const columns = useMemo(() => propsColumns.map(column => {
3632
2780
  return _objectSpread2(_objectSpread2({}, column), {}, {
3633
2781
  width: dimensionModel[column.field] || column.width || 100
@@ -3636,56 +2784,59 @@ const useStatefulTable = props => {
3636
2784
  if (apiRef.current) {
3637
2785
  /** Add resetPage method to apiRef. */
3638
2786
  apiRef.current.resetPage = () => {
3639
- apiRef.current.setPage(0);
2787
+ var _apiRef$current;
2788
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPage(0);
3640
2789
  };
3641
2790
  }
3642
2791
  const defaultColumnOrder = (_initialState$columns = initialState === null || initialState === void 0 ? void 0 : (_initialState$columns2 = initialState.columns) === null || _initialState$columns2 === void 0 ? void 0 : _initialState$columns2.orderedFields) !== null && _initialState$columns !== void 0 ? _initialState$columns : propsColumns.map(c => c.field);
3643
2792
 
3644
- // Helper to build the current DataGridModel for updateUrl calls
3645
- const buildModel = function () {
3646
- var _apiRef$current$state, _apiRef$current;
3647
- let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3648
- return _objectSpread2({
3649
- filterModel: filterParsed,
3650
- sortModel: sortModelParsed,
3651
- paginationModel: paginationModelParsed,
3652
- columnsModel: (_apiRef$current$state = (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.state.columns.columnVisibilityModel) !== null && _apiRef$current$state !== void 0 ? _apiRef$current$state : {},
3653
- pinnedColumnsModel: pinnedColumnsModel,
3654
- density: densityParsed,
3655
- columnOrderModel: columnOrderParsed,
3656
- defaultColumnOrder
3657
- }, overrides);
3658
- };
3659
-
3660
2793
  // Subscribe to density changes via stateChange event (MUI v6 has no densityChange event)
3661
2794
  useEffect(() => {
3662
2795
  const api = apiRef.current;
3663
2796
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3664
2797
  let prevDensity = densityParsed;
3665
2798
  const unsub = api.subscribeEvent('stateChange', () => {
3666
- const currentDensity = api.state.density.value;
2799
+ const currentDensity = api.state.density;
3667
2800
  if (currentDensity !== prevDensity) {
3668
2801
  prevDensity = currentDensity;
3669
- updateUrl(buildModel({
2802
+ updateUrl({
2803
+ filterModel: filterParsed,
2804
+ sortModel: sortModelParsed,
2805
+ paginationModel: paginationModelParsed,
3670
2806
  columnsModel: api.state.columns.columnVisibilityModel,
3671
- density: currentDensity
3672
- }), search, localStorageVersion, historyReplace, columns);
2807
+ pinnedColumnsModel: pinnedColumnsModel,
2808
+ density: currentDensity,
2809
+ columnOrderModel: columnOrderParsed,
2810
+ defaultColumnOrder,
2811
+ rowGroupingModel: rowGroupingParsed,
2812
+ aggregationModel: aggregationParsed,
2813
+ pivotModel: pivotParsed
2814
+ }, search, localStorageVersion, historyReplace, columns);
3673
2815
  }
3674
2816
  });
3675
2817
  return unsub;
3676
- }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, search, localStorageVersion, historyReplace, columns]);
2818
+ }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, rowGroupingParsed, aggregationParsed, pivotParsed, search, localStorageVersion, historyReplace, columns]);
3677
2819
 
3678
2820
  // Subscribe to column order changes via columnOrderChange (drag-drop) and columnIndexChange (programmatic setColumnIndex)
3679
2821
  useEffect(() => {
3680
2822
  const api = apiRef.current;
3681
2823
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3682
- const isDeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3683
2824
  const handleColumnOrderChange = () => {
3684
2825
  const orderedFields = api.state.columns.orderedFields;
3685
2826
  if (orderedFields && !isDeepEqual(orderedFields, columnOrderParsed)) {
3686
- updateUrl(buildModel({
3687
- columnOrderModel: orderedFields
3688
- }), search, localStorageVersion, historyReplace, columns);
2827
+ updateUrl({
2828
+ filterModel: filterParsed,
2829
+ sortModel: sortModelParsed,
2830
+ paginationModel: paginationModelParsed,
2831
+ columnsModel: api.state.columns.columnVisibilityModel,
2832
+ pinnedColumnsModel,
2833
+ density: densityParsed,
2834
+ columnOrderModel: orderedFields,
2835
+ defaultColumnOrder,
2836
+ rowGroupingModel: rowGroupingParsed,
2837
+ aggregationModel: aggregationParsed,
2838
+ pivotModel: pivotParsed
2839
+ }, search, localStorageVersion, historyReplace, columns);
3689
2840
  }
3690
2841
  };
3691
2842
  const unsub1 = api.subscribeEvent('columnOrderChange', handleColumnOrderChange);
@@ -3694,57 +2845,80 @@ const useStatefulTable = props => {
3694
2845
  unsub1();
3695
2846
  unsub2();
3696
2847
  };
3697
- }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, search, localStorageVersion, historyReplace, columns]);
2848
+ }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, rowGroupingParsed, aggregationParsed, pivotParsed, search, localStorageVersion, historyReplace, columns]);
2849
+
2850
+ // Helper to build the current DataGridModel for updateUrl calls
2851
+ const buildModel = function () {
2852
+ var _apiRef$current$state, _apiRef$current2;
2853
+ let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2854
+ return _objectSpread2({
2855
+ filterModel: filterParsed,
2856
+ sortModel: sortModelParsed,
2857
+ paginationModel: paginationModelParsed,
2858
+ columnsModel: (_apiRef$current$state = (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.state.columns.columnVisibilityModel) !== null && _apiRef$current$state !== void 0 ? _apiRef$current$state : {},
2859
+ pinnedColumnsModel: pinnedColumnsModel,
2860
+ density: densityParsed,
2861
+ columnOrderModel: columnOrderParsed,
2862
+ defaultColumnOrder,
2863
+ rowGroupingModel: rowGroupingParsed,
2864
+ aggregationModel: aggregationParsed,
2865
+ pivotModel: pivotParsed
2866
+ }, overrides);
2867
+ };
3698
2868
  return {
3699
2869
  apiRef,
3700
2870
  columns,
3701
2871
  density: densityParsed,
3702
- columnOrderModel: columnOrderParsed,
2872
+ columnOrderModel: columnOrderParsedRef.current,
2873
+ rowGroupingModel: rowGroupingParsedRef.current,
2874
+ aggregationModel: aggregationParsedRef.current,
2875
+ pivotModel: toGridPivotModel(pivotParsedRef.current),
3703
2876
  onFilterModelChange: (model, details) => {
3704
2877
  const filterModel = _objectSpread2(_objectSpread2({}, model), {}, {
3705
2878
  items: model.items.map(item => {
3706
- const column = apiRef.current.getColumn(item.field);
3707
- item.type = column.type || 'string';
2879
+ var _apiRef$current3;
2880
+ const column = (_apiRef$current3 = apiRef.current) === null || _apiRef$current3 === void 0 ? void 0 : _apiRef$current3.getColumn(item.field);
2881
+ item.type = (column === null || column === void 0 ? void 0 : column.type) || 'string';
3708
2882
  return item;
3709
2883
  }),
3710
2884
  quickFilterValues: model.quickFilterValues || []
3711
2885
  });
3712
- propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3713
2886
  updateUrl(buildModel({
3714
2887
  filterModel
3715
2888
  }), search, localStorageVersion, historyReplace, columns);
2889
+ propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3716
2890
  },
3717
- filterModel: filterParsed,
2891
+ filterModel: filterParsedRef.current,
3718
2892
  onSortModelChange: (model, details) => {
3719
- propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3720
2893
  updateUrl(buildModel({
3721
2894
  sortModel: model
3722
2895
  }), search, localStorageVersion, historyReplace, columns);
2896
+ propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3723
2897
  },
3724
- sortModel: sortModelParsed,
2898
+ sortModel: sortModelParsedRef.current,
3725
2899
  onPinnedColumnsChange: (pinnedColumns, details) => {
3726
- propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
3727
2900
  updateUrl(buildModel({
3728
2901
  pinnedColumnsModel: pinnedColumns
3729
2902
  }), search, localStorageVersion, historyReplace, columns);
2903
+ propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
3730
2904
  },
3731
- pinnedColumns: pinnedColumnsModel,
3732
- paginationModel: paginationModelParsed,
2905
+ pinnedColumns: pinnedColumnsModelRef.current,
2906
+ paginationModel: paginationModelParsedRef.current,
3733
2907
  onPaginationModelChange: (model, details) => {
3734
2908
  const paginationModel = _objectSpread2(_objectSpread2({}, model), {}, {
3735
2909
  direction: paginationModelParsed.page < model.page ? 'next' : 'back'
3736
2910
  });
3737
- propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3738
2911
  updateUrl(buildModel({
3739
2912
  paginationModel
3740
2913
  }), search, localStorageVersion, historyReplace, columns);
2914
+ propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3741
2915
  },
3742
- columnVisibilityModel: visibilityModel,
2916
+ columnVisibilityModel: visibilityModelRef.current,
3743
2917
  onColumnVisibilityModelChange: (columnsVisibilityModel, details) => {
3744
- propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
3745
2918
  updateUrl(buildModel({
3746
2919
  columnsModel: columnsVisibilityModel
3747
2920
  }), search, localStorageVersion, historyReplace, columns);
2921
+ propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
3748
2922
  },
3749
2923
  onColumnWidthChange: (params, event, details) => {
3750
2924
  propsOnColumnWidthChange === null || propsOnColumnWidthChange === void 0 ? void 0 : propsOnColumnWidthChange(params, event, details);
@@ -3752,11 +2926,30 @@ const useStatefulTable = props => {
3752
2926
  newWidth: params.width,
3753
2927
  field: params.colDef.field
3754
2928
  });
2929
+ },
2930
+ onRowGroupingModelChange: (model, details) => {
2931
+ updateUrl(buildModel({
2932
+ rowGroupingModel: model
2933
+ }), search, localStorageVersion, historyReplace, columns);
2934
+ propsOnRowGroupingModelChange === null || propsOnRowGroupingModelChange === void 0 ? void 0 : propsOnRowGroupingModelChange(model, details);
2935
+ },
2936
+ onAggregationModelChange: (model, details) => {
2937
+ updateUrl(buildModel({
2938
+ aggregationModel: model
2939
+ }), search, localStorageVersion, historyReplace, columns);
2940
+ propsOnAggregationModelChange === null || propsOnAggregationModelChange === void 0 ? void 0 : propsOnAggregationModelChange(model, details);
2941
+ },
2942
+ onPivotModelChange: model => {
2943
+ const simplified = fromGridPivotModel(model);
2944
+ updateUrl(buildModel({
2945
+ pivotModel: simplified
2946
+ }), search, localStorageVersion, historyReplace, columns);
2947
+ propsOnPivotModelChange === null || propsOnPivotModelChange === void 0 ? void 0 : propsOnPivotModelChange(model);
3755
2948
  }
3756
2949
  };
3757
2950
  };
3758
2951
 
3759
- const _excluded = ["apiRef", "autoHeight", "className", "columns", "slots", "slotProps", "filterModel", "columnVisibilityModel", "pinnedColumns", "sortModel", "paginationModel", "height", "hideToolbar", "initialState", "isRowSelectable", "license", "localStorageVersion", "previousLocalStorageVersions", "onFilterModelChange", "rowSelectionModel", "onColumnWidthChange", "onPaginationModelChange", "onRowSelectionModelChange", "onColumnVisibilityModelChange", "onPinnedColumnsChange", "onSortModelChange", "pagination", "paginationPlacement", "paginationProps", "rows", "pageSizeOptions", "sx", "theme", "useRouter", "paginationMode", "rowCount"];
2952
+ const _excluded = ["apiRef", "autoHeight", "className", "columns", "slots", "slotProps", "filterModel", "columnVisibilityModel", "pinnedColumns", "sortModel", "paginationModel", "height", "hideToolbar", "initialState", "isRowSelectable", "license", "localStorageVersion", "previousLocalStorageVersions", "onFilterModelChange", "rowSelectionModel", "onColumnWidthChange", "onPaginationModelChange", "onRowSelectionModelChange", "onColumnVisibilityModelChange", "onPinnedColumnsChange", "onSortModelChange", "onRowGroupingModelChange", "onAggregationModelChange", "onPivotModelChange", "pagination", "paginationPlacement", "paginationProps", "rows", "pageSizeOptions", "sx", "theme", "useRouter", "paginationMode", "rowCount", "density", "dataSource", "filterMode", "sortingMode"];
3760
2953
  const COMPONENT_NAME = 'DataGrid';
3761
2954
  const CLASSNAME = 'redsift-datagrid';
3762
2955
 
@@ -3840,6 +3033,9 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3840
3033
  onColumnVisibilityModelChange: propsOnColumnVisibilityModelChange,
3841
3034
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3842
3035
  onSortModelChange: propsOnSortModelChange,
3036
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3037
+ onAggregationModelChange: propsOnAggregationModelChange,
3038
+ onPivotModelChange: propsOnPivotModelChange,
3843
3039
  pagination,
3844
3040
  paginationPlacement = 'both',
3845
3041
  paginationProps,
@@ -3849,15 +3045,26 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3849
3045
  theme: propsTheme,
3850
3046
  useRouter,
3851
3047
  paginationMode = 'client',
3852
- rowCount
3048
+ rowCount,
3049
+ density: _density,
3050
+ dataSource,
3051
+ filterMode: propsFilterMode,
3052
+ sortingMode: propsSortingMode
3853
3053
  } = props,
3854
3054
  forwardedProps = _objectWithoutProperties(props, _excluded);
3855
- const theme = useTheme$1(propsTheme);
3055
+ const theme = useTheme(propsTheme);
3856
3056
  const _apiRef = useGridApiRef();
3857
3057
  const apiRef = propsApiRef !== null && propsApiRef !== void 0 ? propsApiRef : _apiRef;
3858
- const RenderedToolbar = slots !== null && slots !== void 0 && slots.toolbar ? slots.toolbar : Toolbar;
3859
3058
  LicenseInfo.setLicenseKey(license);
3860
3059
  const height = propsHeight !== null && propsHeight !== void 0 ? propsHeight : autoHeight ? undefined : '500px';
3060
+
3061
+ // When dataSource is present, MUI manages filter/sort/pagination internally.
3062
+ // We must not pass controlled models — only initialState (one-time) and
3063
+ // write-only onChange handlers for URL/localStorage persistence.
3064
+ const isDataSourceMode = Boolean(dataSource);
3065
+ const effectivePaginationMode = isDataSourceMode ? 'server' : paginationMode;
3066
+ const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode;
3067
+ const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode;
3861
3068
  const {
3862
3069
  onColumnVisibilityModelChange: controlledOnColumnVisibilityModelChange,
3863
3070
  onFilterModelChange: controlledOnFilterModelChange,
@@ -3891,7 +3098,13 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3891
3098
  pinnedColumns,
3892
3099
  sortModel,
3893
3100
  onColumnWidthChange,
3894
- columnOrderModel
3101
+ columnOrderModel,
3102
+ rowGroupingModel,
3103
+ aggregationModel,
3104
+ pivotModel,
3105
+ onRowGroupingModelChange,
3106
+ onAggregationModelChange,
3107
+ onPivotModelChange
3895
3108
  } = useStatefulTable({
3896
3109
  apiRef: apiRef,
3897
3110
  initialState,
@@ -3902,13 +3115,39 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3902
3115
  onPaginationModelChange: controlledOnPaginationModelChange,
3903
3116
  onPinnedColumnsChange: controlledOnPinnedColumnsChange,
3904
3117
  onSortModelChange: controlledOnSortModelChange,
3118
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3119
+ onAggregationModelChange: propsOnAggregationModelChange,
3120
+ onPivotModelChange: propsOnPivotModelChange,
3905
3121
  useRouter: useRouter,
3906
3122
  localStorageVersion,
3907
3123
  previousLocalStorageVersions
3908
3124
  });
3909
- const [rowSelectionModel, setRowSelectionModel] = useState(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3125
+
3126
+ // In dataSource mode, track pagination locally for the custom pagination slots
3127
+ // (rendered outside DataGridPremium). MUI owns the actual pagination state internally.
3128
+ const [dataSourcePaginationModel, setDataSourcePaginationModel] = useState(paginationModel);
3129
+
3130
+ // The pagination model to use for display in pagination slots
3131
+ const activePaginationModel = isDataSourceMode ? dataSourcePaginationModel : paginationModel;
3132
+
3133
+ // In dataSource mode, the top pagination (outside DataGridPremium) must go through
3134
+ // apiRef to change MUI's internal page. MUI then fires onPaginationModelChange
3135
+ // which updates URL and local state.
3136
+ const dataSourceTopPaginationChange = useCallback(model => {
3137
+ var _apiRef$current;
3138
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPaginationModel(model);
3139
+ }, [apiRef]);
3140
+
3141
+ // Wrap onPaginationModelChange to also track state locally in dataSource mode
3142
+ const wrappedOnPaginationModelChange = useCallback((model, details) => {
3143
+ if (isDataSourceMode) {
3144
+ setDataSourcePaginationModel(model);
3145
+ }
3146
+ onPaginationModelChange(model, details);
3147
+ }, [isDataSourceMode, onPaginationModelChange]);
3148
+ const [rowSelectionModel, setRowSelectionModel] = useState(() => normalizeRowSelectionModel(propsRowSelectionModel));
3910
3149
  useEffect(() => {
3911
- setRowSelectionModel(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3150
+ setRowSelectionModel(normalizeRowSelectionModel(propsRowSelectionModel));
3912
3151
  }, [propsRowSelectionModel]);
3913
3152
  const onRowSelectionModelChange = (selectionModel, details) => {
3914
3153
  setRowSelectionModel(selectionModel);
@@ -3922,18 +3161,41 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3922
3161
  pageSize: paginationModel.pageSize
3923
3162
  });
3924
3163
 
3164
+ // Version counter to force re-renders when selectionStatus ref changes
3165
+ const [, forceSelectionUpdate] = useState(0);
3166
+
3925
3167
  // The checkboxSelectionVisibleOnly should only be applied to client-side pagination,
3926
3168
  // for server-side pagination it produces inconsistent behavior when selecting all rows in pages 2 and beyond
3927
- const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(paginationMode != 'server');
3169
+ const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(effectivePaginationMode != 'server');
3170
+
3171
+ // Track when the grid API is ready to ensure top pagination renders correctly
3172
+ const [gridReady, setGridReady] = useState(false);
3173
+
3174
+ // Force re-render when the grid API becomes ready (for top pagination)
3175
+ useEffect(() => {
3176
+ if (apiRef.current && !gridReady) {
3177
+ setGridReady(true);
3178
+ }
3179
+ });
3180
+
3181
+ // Sync persisted density via apiRef — initialState only applies on mount,
3182
+ // so this handles SPA back/forward navigation where controlledDensity changes after mount
3183
+ useEffect(() => {
3184
+ if (apiRef.current) {
3185
+ apiRef.current.setDensity(controlledDensity);
3186
+ }
3187
+ }, [controlledDensity, apiRef]);
3928
3188
 
3929
3189
  // in server-side pagination we want to update the selection status
3930
3190
  // every time we navigate between pages, resize our page or select something
3931
3191
  useEffect(() => {
3932
- if (paginationMode == 'server') {
3933
- onServerSideSelectionStatusChange(Array.isArray(rowSelectionModel) ? rowSelectionModel : [rowSelectionModel], apiRef, selectionStatusRef, isRowSelectable, paginationModel.page, paginationModel.pageSize);
3192
+ if (effectivePaginationMode == 'server') {
3193
+ onServerSideSelectionStatusChange(rowSelectionModel, apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, activePaginationModel.page, activePaginationModel.pageSize);
3934
3194
  }
3935
- }, [rowSelectionModel, paginationModel.page, paginationModel.pageSize, rows]);
3936
- if (!Array.isArray(rows)) {
3195
+ }, [rowSelectionModel, activePaginationModel.page, activePaginationModel.pageSize, rows]);
3196
+
3197
+ // In dataSource mode MUI provides rows internally; skip the guard.
3198
+ if (!isDataSourceMode && !Array.isArray(rows)) {
3937
3199
  return null;
3938
3200
  }
3939
3201
 
@@ -3942,9 +3204,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3942
3204
  // receive the fresh value in the same render cycle — no extra re-render needed.
3943
3205
  // The ref is kept in sync for the onRowSelectionModelChange callback's deselect logic.
3944
3206
  let selectionStatus = selectionStatusRef.current;
3945
- if (pagination && paginationMode !== 'server' && Array.isArray(rowSelectionModel) && rowSelectionModel.length > 0) {
3207
+ if (pagination && effectivePaginationMode !== 'server' && getSelectionCount(rowSelectionModel) > 0) {
3946
3208
  try {
3947
- const selectableRowsInPage = isRowSelectable ? gridPaginatedVisibleSortedGridRowEntriesSelector(apiRef).filter(_ref => {
3209
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors.
3210
+ // MUI's paginated selectors use apiRef internal state which may be stale when
3211
+ // paginationModel prop changes — our React state is always up to date.
3212
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3213
+ const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3214
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3215
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref => {
3948
3216
  let {
3949
3217
  model
3950
3218
  } = _ref;
@@ -3956,24 +3224,29 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3956
3224
  id
3957
3225
  } = _ref2;
3958
3226
  return id;
3959
- }) : gridPaginatedVisibleSortedGridRowIdsSelector(apiRef);
3227
+ }) : pageEntries.map(_ref3 => {
3228
+ let {
3229
+ id
3230
+ } = _ref3;
3231
+ return id;
3232
+ });
3960
3233
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
3961
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref3 => {
3234
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref4 => {
3962
3235
  let {
3963
3236
  model
3964
- } = _ref3;
3237
+ } = _ref4;
3965
3238
  return isRowSelectable({
3966
3239
  row: model
3967
3240
  });
3968
- }).map(_ref4 => {
3241
+ }).map(_ref5 => {
3969
3242
  let {
3970
3243
  id
3971
- } = _ref4;
3244
+ } = _ref5;
3972
3245
  return id;
3973
3246
  }) : gridFilteredSortedRowIdsSelector(apiRef);
3974
3247
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
3975
- const numberOfSelectedRows = rowSelectionModel.length;
3976
- const selectedOnCurrentPage = selectableRowsInPage.filter(id => rowSelectionModel.includes(id));
3248
+ const numberOfSelectedRows = getSelectionCount(rowSelectionModel);
3249
+ const selectedOnCurrentPage = selectableRowsInPage.filter(id => isRowSelected(rowSelectionModel, id));
3977
3250
  if (numberOfSelectedRows === numberOfSelectableRowsInTable && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
3978
3251
  selectionStatus = {
3979
3252
  type: 'table',
@@ -3998,7 +3271,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3998
3271
  } catch {
3999
3272
  // apiRef may not be initialized on first render
4000
3273
  }
4001
- } else if (pagination && paginationMode !== 'server') {
3274
+ } else if (pagination && effectivePaginationMode !== 'server') {
4002
3275
  selectionStatus = {
4003
3276
  type: 'none',
4004
3277
  numberOfSelectedRows: 0
@@ -4027,156 +3300,201 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4027
3300
  ref: datagridRef,
4028
3301
  className: classNames(StatefulDataGrid.className, className),
4029
3302
  $height: height
4030
- }, /*#__PURE__*/React__default.createElement(DataGridPro, _extends$1({}, forwardedProps, {
3303
+ }, pagination && ['top', 'both'].includes(paginationPlacement) && gridReady ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, {
3304
+ displaySelection: true,
3305
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3306
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3307
+ selectionStatus: selectionStatus,
3308
+ paginationModel: activePaginationModel,
3309
+ onPaginationModelChange: isDataSourceMode ? dataSourceTopPaginationChange : onPaginationModelChange,
3310
+ pageSizeOptions: pageSizeOptions,
3311
+ paginationProps: paginationProps,
3312
+ rowCount: rowCount
3313
+ }) : /*#__PURE__*/React__default.createElement(ControlledPagination, {
3314
+ displaySelection: true,
3315
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3316
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3317
+ selectionStatus: selectionStatus,
4031
3318
  apiRef: apiRef,
3319
+ isRowSelectable: isRowSelectable,
3320
+ paginationModel: activePaginationModel,
3321
+ onPaginationModelChange: onPaginationModelChange,
3322
+ pageSizeOptions: pageSizeOptions,
3323
+ paginationProps: paginationProps
3324
+ }) : null, /*#__PURE__*/React__default.createElement(DataGridPremium, _extends({}, forwardedProps, {
3325
+ apiRef: apiRef,
3326
+ dataSource: dataSource,
4032
3327
  columns: columns,
4033
3328
  columnVisibilityModel: columnVisibilityModel,
4034
- density: controlledDensity,
4035
- filterModel: filterModel,
4036
3329
  onColumnVisibilityModelChange: onColumnVisibilityModelChange,
4037
- onFilterModelChange: onFilterModelChange,
4038
- onPaginationModelChange: onPaginationModelChange,
4039
3330
  onPinnedColumnsChange: onPinnedColumnsChange,
4040
- onSortModelChange: onSortModelChange,
4041
- paginationModel: paginationModel,
4042
3331
  pinnedColumns: pinnedColumns,
4043
- sortModel: sortModel,
4044
3332
  pageSizeOptions: pageSizeOptions,
4045
3333
  onColumnWidthChange: onColumnWidthChange,
3334
+ rowGroupingModel: rowGroupingModel,
3335
+ onRowGroupingModelChange: onRowGroupingModelChange,
3336
+ aggregationModel: aggregationModel,
3337
+ onAggregationModelChange: onAggregationModelChange,
3338
+ pivotModel: pivotModel,
3339
+ onPivotModelChange: onPivotModelChange
3340
+ // In dataSource mode: models are uncontrolled (MUI owns them),
3341
+ // onChange handlers are write-only for URL/localStorage persistence,
3342
+ // and initialState seeds MUI on mount from the persisted URL state.
3343
+ }, isDataSourceMode ? {
3344
+ onFilterModelChange: onFilterModelChange,
3345
+ onSortModelChange: onSortModelChange,
3346
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4046
3347
  initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3348
+ density: controlledDensity,
3349
+ columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3350
+ orderedFields: columnOrderModel
3351
+ }),
3352
+ filter: {
3353
+ filterModel
3354
+ },
3355
+ sorting: {
3356
+ sortModel
3357
+ },
3358
+ pagination: {
3359
+ paginationModel
3360
+ }
3361
+ })
3362
+ } : {
3363
+ filterModel,
3364
+ sortModel,
3365
+ paginationModel,
3366
+ onFilterModelChange: onFilterModelChange,
3367
+ onSortModelChange: onSortModelChange,
3368
+ onPaginationModelChange: wrappedOnPaginationModelChange,
3369
+ initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3370
+ density: controlledDensity,
4047
3371
  columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
4048
3372
  orderedFields: columnOrderModel
4049
3373
  })
4050
- }),
3374
+ })
3375
+ }, {
4051
3376
  isRowSelectable: isRowSelectable,
4052
3377
  pagination: pagination,
4053
- paginationMode: paginationMode,
4054
- keepNonExistentRowsSelected: paginationMode == 'server',
4055
- rows: rows,
3378
+ paginationMode: effectivePaginationMode,
3379
+ filterMode: effectiveFilterMode,
3380
+ sortingMode: effectiveSortingMode,
3381
+ keepNonExistentRowsSelected: effectivePaginationMode == 'server',
3382
+ rows: isDataSourceMode ? [] : rows,
4056
3383
  rowCount: rowCount,
4057
3384
  autoHeight: autoHeight,
4058
3385
  checkboxSelectionVisibleOnly: checkboxSelectionVisibleOnly,
3386
+ disableRowSelectionExcludeModel: true,
3387
+ showToolbar: !hideToolbar,
4059
3388
  slots: _objectSpread2(_objectSpread2({
4060
3389
  baseButton: BaseButton,
4061
3390
  baseCheckbox: BaseCheckbox,
4062
- // baseTextField,
4063
- basePopper: BasePopper,
4064
- columnFilteredIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4065
- displayName: "ColumnFilteredIcon"
3391
+ baseIconButton: BaseIconButton,
3392
+ columnFilteredIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3393
+ displayName: "columnFilteredIcon"
4066
3394
  })),
4067
- columnSelectorIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4068
- displayName: "ColumnSelectorIcon"
3395
+ columnSelectorIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3396
+ displayName: "columnSelectorIcon"
4069
3397
  })),
4070
- columnSortedAscendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4071
- displayName: "ColumnSortedAscendingIcon"
3398
+ columnSortedAscendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3399
+ displayName: "columnSortedAscendingIcon"
4072
3400
  })),
4073
- columnSortedDescendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4074
- displayName: "ColumnSortedDescendingIcon"
3401
+ columnSortedDescendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3402
+ displayName: "columnSortedDescendingIcon"
4075
3403
  })),
4076
- densityCompactIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4077
- displayName: "DensityCompactIcon"
3404
+ densityCompactIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3405
+ displayName: "densityCompactIcon"
4078
3406
  })),
4079
- densityStandardIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4080
- displayName: "DensityStandardIcon"
3407
+ densityStandardIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3408
+ displayName: "densityStandardIcon"
4081
3409
  })),
4082
- densityComfortableIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4083
- displayName: "DensityComfortableIcon"
3410
+ densityComfortableIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3411
+ displayName: "densityComfortableIcon"
4084
3412
  })),
4085
- detailPanelCollapseIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4086
- displayName: "DetailPanelCollapseIcon"
3413
+ detailPanelCollapseIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3414
+ displayName: "detailPanelCollapseIcon"
4087
3415
  })),
4088
- detailPanelExpandIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4089
- displayName: "DetailPanelExpandIcon"
3416
+ detailPanelExpandIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3417
+ displayName: "detailPanelExpandIcon"
4090
3418
  })),
4091
- exportIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({}, props, {
4092
- displayName: "ExportIcon"
3419
+ exportIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3420
+ displayName: "exportIcon"
4093
3421
  })),
4094
- openFilterButtonIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$1({
4095
- displayName: "OpenFilterButtonIcon"
4096
- }, props))
3422
+ openFilterButtonIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3423
+ displayName: "openFilterButtonIcon"
3424
+ }))
4097
3425
  }, slots), {}, {
4098
- toolbar: ToolbarWrapper,
4099
3426
  pagination: props => {
4100
- return pagination ? paginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends$1({}, props, {
3427
+ return pagination ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends({}, props, {
4101
3428
  displaySelection: false,
4102
3429
  displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
4103
3430
  displayPagination: ['bottom', 'both'].includes(paginationPlacement),
4104
3431
  selectionStatus: selectionStatus,
4105
- paginationModel: paginationModel,
4106
- onPaginationModelChange: onPaginationModelChange,
3432
+ paginationModel: activePaginationModel,
3433
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4107
3434
  pageSizeOptions: pageSizeOptions,
4108
3435
  paginationProps: paginationProps,
4109
- paginationMode: paginationMode,
4110
3436
  rowCount: rowCount
4111
- })) : /*#__PURE__*/React__default.createElement(ControlledPagination, _extends$1({}, props, {
3437
+ })) : /*#__PURE__*/React__default.createElement(ControlledPagination, _extends({}, props, {
4112
3438
  displaySelection: false,
4113
3439
  displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
4114
3440
  displayPagination: ['bottom', 'both'].includes(paginationPlacement),
4115
3441
  selectionStatus: selectionStatus,
4116
3442
  apiRef: apiRef,
4117
3443
  isRowSelectable: isRowSelectable,
4118
- paginationModel: paginationModel,
4119
- onPaginationModelChange: onPaginationModelChange,
3444
+ paginationModel: activePaginationModel,
3445
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4120
3446
  pageSizeOptions: pageSizeOptions,
4121
- paginationProps: paginationProps,
4122
- paginationMode: paginationMode
3447
+ paginationProps: paginationProps
4123
3448
  })) : null;
4124
3449
  }
4125
3450
  }),
4126
- slotProps: _objectSpread2(_objectSpread2({}, slotProps), {}, {
4127
- toolbar: _objectSpread2({
4128
- hideToolbar,
4129
- RenderedToolbar,
4130
- filterModel,
4131
- onFilterModelChange,
4132
- pagination,
4133
- paginationPlacement,
4134
- selectionStatus,
4135
- apiRef,
4136
- isRowSelectable,
4137
- paginationModel,
4138
- onPaginationModelChange,
4139
- pageSizeOptions,
4140
- paginationProps,
4141
- paginationMode,
4142
- rowCount
4143
- }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar)
4144
- }),
3451
+ slotProps: _objectSpread2({}, slotProps),
4145
3452
  rowSelectionModel: rowSelectionModel,
4146
3453
  onRowSelectionModelChange: (newSelectionModel, details) => {
4147
- if (pagination && paginationMode != 'server') {
4148
- const selectableRowsInPage = isRowSelectable ? gridPaginatedVisibleSortedGridRowEntriesSelector(apiRef).filter(_ref5 => {
3454
+ if (pagination && effectivePaginationMode != 'server') {
3455
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors
3456
+ // to avoid stale apiRef pagination state.
3457
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3458
+ const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3459
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3460
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref6 => {
4149
3461
  let {
4150
3462
  model
4151
- } = _ref5;
3463
+ } = _ref6;
4152
3464
  return isRowSelectable({
4153
3465
  row: model
4154
3466
  });
4155
- }).map(_ref6 => {
3467
+ }).map(_ref7 => {
4156
3468
  let {
4157
3469
  id
4158
- } = _ref6;
3470
+ } = _ref7;
4159
3471
  return id;
4160
- }) : gridPaginatedVisibleSortedGridRowIdsSelector(apiRef);
3472
+ }) : pageEntries.map(_ref8 => {
3473
+ let {
3474
+ id
3475
+ } = _ref8;
3476
+ return id;
3477
+ });
4161
3478
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4162
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref7 => {
3479
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref9 => {
4163
3480
  let {
4164
3481
  model
4165
- } = _ref7;
3482
+ } = _ref9;
4166
3483
  return isRowSelectable({
4167
3484
  row: model
4168
3485
  });
4169
- }).map(_ref8 => {
3486
+ }).map(_ref10 => {
4170
3487
  let {
4171
3488
  id
4172
- } = _ref8;
3489
+ } = _ref10;
4173
3490
  return id;
4174
3491
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4175
3492
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4176
- const numberOfSelectedRows = newSelectionModel.length;
3493
+ const numberOfSelectedRows = getSelectionCount(newSelectionModel);
4177
3494
  if (selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable - numberOfSelectableRowsInPage || selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable || selectionStatusRef.current.type === 'page' && numberOfSelectedRows === numberOfSelectableRowsInPage) {
4178
3495
  setTimeout(() => {
4179
- apiRef.current.selectRows([], true, true);
3496
+ var _apiRef$current2;
3497
+ (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.selectRows([], true, true);
4180
3498
  }, 0);
4181
3499
  }
4182
3500
  if (numberOfSelectedRows === numberOfSelectableRowsInPage && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
@@ -4200,6 +3518,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4200
3518
  numberOfSelectedRows
4201
3519
  };
4202
3520
  }
3521
+ forceSelectionUpdate(v => v + 1);
4203
3522
  }
4204
3523
  onRowSelectionModelChange === null || onRowSelectionModelChange === void 0 ? void 0 : onRowSelectionModelChange(newSelectionModel, details);
4205
3524
  },
@@ -4217,5 +3536,5 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4217
3536
  StatefulDataGrid.className = CLASSNAME;
4218
3537
  StatefulDataGrid.displayName = COMPONENT_NAME;
4219
3538
 
4220
- export { convertToDisplayFormat as $, ARRAY_IS_EMPTY as A, Box$1 as B, CONTAINS_ANY_OF as C, DOES_NOT_CONTAIN as D, ENDS_WITH_ANY_OF as E, IS as F, IS_NOT as G, HAS_WITH_SELECT as H, IS_ANY_OF as I, getGridStringOperators as J, getGridStringArrayOperators as K, getGridStringArrayOperatorsWithSelect as L, getGridStringArrayOperatorsWithSelectOnStringArrayColumns as M, FILTER_MODEL_KEY as N, SORT_MODEL_KEY as O, PAGINATION_MODEL_KEY as P, PINNED_COLUMNS as Q, DIMENSION_MODEL_KEY as R, STARTS_WITH_ANY_OF as S, TextField$1 as T, FILTER_SEARCH_KEY as U, VISIBILITY_MODEL_KEY as V, DENSITY_MODEL_KEY as W, COLUMN_ORDER_MODEL_KEY as X, CATEGORIES as Y, buildStorageKey as Z, clearPreviousVersionStorage as _, DOES_NOT_EQUAL as a, convertFromDisplayFormat as a0, getDecodedSearchFromUrl as a1, buildQueryParamsString as a2, areSearchStringsEqual as a3, decodeValue as a4, encodeValue as a5, urlSearchParamsToString as a6, numberOperatorEncoder as a7, numberOperatorDecoder as a8, isOperatorValueValid as a9, isValueValid as aa, getFilterModelFromString as ab, getSearchParamsFromFilterModel as ac, getSortingFromString as ad, getSearchParamsFromSorting as ae, getPaginationFromString as af, getSearchParamsFromPagination as ag, getColumnVisibilityFromString as ah, getSearchParamsFromColumnVisibility as ai, getPinnedColumnsFromString as aj, getSearchParamsFromPinnedColumns as ak, getSearchParamsFromTab as al, getDensityFromString as am, getSearchParamsFromDensity as an, getColumnOrderFromString as ao, getSearchParamsFromColumnOrder as ap, getFinalSearch as aq, getModelsParsedOrUpdateLocalStorage as ar, updateUrl as as, areFilterModelsEquivalent as at, StatefulDataGrid as au, DOES_NOT_START_WITH as b, DOES_NOT_END_WITH as c, IS_NOT_ANY_OF as d, DOES_NOT_CONTAIN_ANY_OF as e, DOES_NOT_START_WITH_ANY_OF as f, DOES_NOT_END_WITH_ANY_OF as g, IS_BETWEEN as h, IS_WITH_SELECT as i, IS_NOT_WITH_SELECT as j, IS_ANY_OF_WITH_SELECT as k, IS_NOT_ANY_OF_WITH_SELECT as l, ARRAY_IS_NOT_EMPTY as m, DOES_NOT_HAVE_WITH_SELECT as n, operatorList as o, HAS_ANY_OF_WITH_SELECT as p, HAS_ALL_OF_WITH_SELECT as q, DOES_NOT_HAVE_ANY_OF_WITH_SELECT as r, HAS_ONLY_WITH_SELECT as s, HAS as t, DOES_NOT_HAVE as u, HAS_ANY_OF as v, HAS_ALL_OF as w, DOES_NOT_HAVE_ANY_OF as x, HAS_ONLY as y, getGridNumericOperators as z };
3539
+ export { clearPreviousVersionStorage as $, ARRAY_IS_EMPTY as A, IS as B, CONTAINS_ANY_OF as C, DOES_NOT_CONTAIN as D, ENDS_WITH_ANY_OF as E, IS_NOT as F, getGridStringOperators as G, HAS_WITH_SELECT as H, IS_ANY_OF as I, getGridStringArrayOperators as J, getGridStringArrayOperatorsWithSelect as K, getGridStringArrayOperatorsWithSelectOnStringArrayColumns as L, FILTER_MODEL_KEY as M, SORT_MODEL_KEY as N, PINNED_COLUMNS as O, PAGINATION_MODEL_KEY as P, DIMENSION_MODEL_KEY as Q, FILTER_SEARCH_KEY as R, STARTS_WITH_ANY_OF as S, DENSITY_MODEL_KEY as T, COLUMN_ORDER_MODEL_KEY as U, VISIBILITY_MODEL_KEY as V, ROW_GROUPING_MODEL_KEY as W, AGGREGATION_MODEL_KEY as X, PIVOT_MODEL_KEY as Y, CATEGORIES as Z, buildStorageKey as _, DOES_NOT_EQUAL as a, convertToDisplayFormat as a0, convertFromDisplayFormat as a1, getDecodedSearchFromUrl as a2, buildQueryParamsString as a3, areSearchStringsEqual as a4, decodeValue as a5, encodeValue as a6, urlSearchParamsToString as a7, numberOperatorEncoder as a8, numberOperatorDecoder as a9, areFilterModelsEquivalent as aA, StatefulDataGrid as aB, isOperatorValueValid as aa, isValueValid as ab, getFilterModelFromString as ac, getSearchParamsFromFilterModel as ad, getSortingFromString as ae, getSearchParamsFromSorting as af, getPaginationFromString as ag, getSearchParamsFromPagination as ah, getColumnVisibilityFromString as ai, getSearchParamsFromColumnVisibility as aj, getPinnedColumnsFromString as ak, getSearchParamsFromPinnedColumns as al, getSearchParamsFromTab as am, getDensityFromString as an, getSearchParamsFromDensity as ao, getColumnOrderFromString as ap, getSearchParamsFromColumnOrder as aq, getRowGroupingFromString as ar, getSearchParamsFromRowGrouping as as, getAggregationFromString as at, getSearchParamsFromAggregation as au, getPivotFromString as av, getSearchParamsFromPivot as aw, getFinalSearch as ax, getModelsParsedOrUpdateLocalStorage as ay, updateUrl as az, DOES_NOT_START_WITH as b, DOES_NOT_END_WITH as c, IS_NOT_ANY_OF as d, DOES_NOT_CONTAIN_ANY_OF as e, DOES_NOT_START_WITH_ANY_OF as f, DOES_NOT_END_WITH_ANY_OF as g, IS_BETWEEN as h, IS_WITH_SELECT as i, IS_NOT_WITH_SELECT as j, IS_ANY_OF_WITH_SELECT as k, IS_NOT_ANY_OF_WITH_SELECT as l, ARRAY_IS_NOT_EMPTY as m, DOES_NOT_HAVE_WITH_SELECT as n, operatorList as o, HAS_ANY_OF_WITH_SELECT as p, HAS_ALL_OF_WITH_SELECT as q, DOES_NOT_HAVE_ANY_OF_WITH_SELECT as r, HAS_ONLY_WITH_SELECT as s, HAS as t, DOES_NOT_HAVE as u, HAS_ANY_OF as v, HAS_ALL_OF as w, DOES_NOT_HAVE_ANY_OF as x, HAS_ONLY as y, getGridNumericOperators as z };
4221
3540
  //# sourceMappingURL=StatefulDataGrid2.js.map