@redsift/table 12.5.3-muiv6 → 12.5.3

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,1249 +1,18 @@
1
- import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends$2 } 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, useRef, forwardRef, 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 { s as styled, a as styleFunctionSx, e as extendSxProp, _ as _objectWithoutPropertiesLoose, b as _extends, g as generateUtilityClasses, c as createTheme, T as THEME_ID, C as ClassNameGenerator, P as PropTypes, d as generateUtilityClass, f as styled$1, h as _extends$1, u as useDefaultProps, i as _objectWithoutPropertiesLoose$1, j as capitalize, k as composeClasses, r as rootShouldForwardProp, l as refType } from './Portal.js';
10
- import { u as useTheme, a as useFormControl, b as formControlState, c as clsx$1, i as isAdornedStart, d as isFilled, F as FormControlContext, e as useId, h as Select, I as Input, j as FilledInput, O as OutlinedInput, o as onServerSideSelectionStatusChange, S as ServerSideControlledPagination, C as ControlledPagination } from './ControlledPagination.js';
11
- import { j as jsxRuntimeExports } from './jsx-runtime.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 r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
18
-
19
- const _excluded$6 = ["className", "component"];
20
- function createBox(options = {}) {
21
- const {
22
- themeId,
23
- defaultTheme,
24
- defaultClassName = 'MuiBox-root',
25
- generateClassName
26
- } = options;
27
- const BoxRoot = styled('div', {
28
- shouldForwardProp: prop => prop !== 'theme' && prop !== 'sx' && prop !== 'as'
29
- })(styleFunctionSx);
30
- const Box = /*#__PURE__*/React.forwardRef(function Box(inProps, ref) {
31
- const theme = useTheme(defaultTheme);
32
- const _extendSxProp = extendSxProp(inProps),
33
- {
34
- className,
35
- component = 'div'
36
- } = _extendSxProp,
37
- other = _objectWithoutPropertiesLoose(_extendSxProp, _excluded$6);
38
- return /*#__PURE__*/jsxRuntimeExports.jsx(BoxRoot, _extends({
39
- as: component,
40
- ref: ref,
41
- className: clsx(className, generateClassName ? generateClassName(defaultClassName) : defaultClassName),
42
- theme: themeId ? theme[themeId] || theme : theme
43
- }, other));
44
- });
45
- return Box;
46
- }
47
-
48
- function isMuiElement(element, muiNames) {
49
- var _muiName, _element$type;
50
- return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf( // For server components `muiName` is avaialble in element.type._payload.value.muiName
51
- // relevant info - https://github.com/facebook/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
52
- // eslint-disable-next-line no-underscore-dangle
53
- (_muiName = element.type.muiName) != null ? _muiName : (_element$type = element.type) == null || (_element$type = _element$type._payload) == null || (_element$type = _element$type.value) == null ? void 0 : _element$type.muiName) !== -1;
54
- }
55
-
56
- const boxClasses = generateUtilityClasses('MuiBox', ['root']);
57
- var boxClasses$1 = boxClasses;
58
-
59
- const defaultTheme = createTheme();
60
- const Box = createBox({
61
- themeId: THEME_ID,
62
- defaultTheme,
63
- defaultClassName: boxClasses$1.root,
64
- generateClassName: ClassNameGenerator.generate
65
- });
66
- process.env.NODE_ENV !== "production" ? Box.propTypes /* remove-proptypes */ = {
67
- // ┌────────────────────────────── Warning ──────────────────────────────┐
68
- // │ These PropTypes are generated from the TypeScript type definitions. │
69
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
70
- // └─────────────────────────────────────────────────────────────────────┘
71
- /**
72
- * @ignore
73
- */
74
- children: PropTypes.node,
75
- /**
76
- * The component used for the root node.
77
- * Either a string to use a HTML element or a component.
78
- */
79
- component: PropTypes.elementType,
80
- /**
81
- * The system prop that allows defining system overrides as well as additional CSS styles.
82
- */
83
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
84
- } : void 0;
85
- var Box$1 = Box;
86
-
87
- function getFormLabelUtilityClasses(slot) {
88
- return generateUtilityClass('MuiFormLabel', slot);
89
- }
90
- const formLabelClasses = generateUtilityClasses('MuiFormLabel', ['root', 'colorSecondary', 'focused', 'disabled', 'error', 'filled', 'required', 'asterisk']);
91
- var formLabelClasses$1 = formLabelClasses;
92
-
93
- const _excluded$5 = ["children", "className", "color", "component", "disabled", "error", "filled", "focused", "required"];
94
- const useUtilityClasses$4 = ownerState => {
95
- const {
96
- classes,
97
- color,
98
- focused,
99
- disabled,
100
- error,
101
- filled,
102
- required
103
- } = ownerState;
104
- const slots = {
105
- root: ['root', `color${capitalize(color)}`, disabled && 'disabled', error && 'error', filled && 'filled', focused && 'focused', required && 'required'],
106
- asterisk: ['asterisk', error && 'error']
107
- };
108
- return composeClasses(slots, getFormLabelUtilityClasses, classes);
109
- };
110
- const FormLabelRoot = styled$1('label', {
111
- name: 'MuiFormLabel',
112
- slot: 'Root',
113
- overridesResolver: ({
114
- ownerState
115
- }, styles) => {
116
- return _extends$1({}, styles.root, ownerState.color === 'secondary' && styles.colorSecondary, ownerState.filled && styles.filled);
117
- }
118
- })(({
119
- theme,
120
- ownerState
121
- }) => _extends$1({
122
- color: (theme.vars || theme).palette.text.secondary
123
- }, theme.typography.body1, {
124
- lineHeight: '1.4375em',
125
- padding: 0,
126
- position: 'relative',
127
- [`&.${formLabelClasses$1.focused}`]: {
128
- color: (theme.vars || theme).palette[ownerState.color].main
129
- },
130
- [`&.${formLabelClasses$1.disabled}`]: {
131
- color: (theme.vars || theme).palette.text.disabled
132
- },
133
- [`&.${formLabelClasses$1.error}`]: {
134
- color: (theme.vars || theme).palette.error.main
135
- }
136
- }));
137
- const AsteriskComponent = styled$1('span', {
138
- name: 'MuiFormLabel',
139
- slot: 'Asterisk',
140
- overridesResolver: (props, styles) => styles.asterisk
141
- })(({
142
- theme
143
- }) => ({
144
- [`&.${formLabelClasses$1.error}`]: {
145
- color: (theme.vars || theme).palette.error.main
146
- }
147
- }));
148
- const FormLabel = /*#__PURE__*/React.forwardRef(function FormLabel(inProps, ref) {
149
- const props = useDefaultProps({
150
- props: inProps,
151
- name: 'MuiFormLabel'
152
- });
153
- const {
154
- children,
155
- className,
156
- component = 'label'
157
- } = props,
158
- other = _objectWithoutPropertiesLoose$1(props, _excluded$5);
159
- const muiFormControl = useFormControl();
160
- const fcs = formControlState({
161
- props,
162
- muiFormControl,
163
- states: ['color', 'required', 'focused', 'disabled', 'error', 'filled']
164
- });
165
- const ownerState = _extends$1({}, props, {
166
- color: fcs.color || 'primary',
167
- component,
168
- disabled: fcs.disabled,
169
- error: fcs.error,
170
- filled: fcs.filled,
171
- focused: fcs.focused,
172
- required: fcs.required
173
- });
174
- const classes = useUtilityClasses$4(ownerState);
175
- return /*#__PURE__*/jsxRuntimeExports.jsxs(FormLabelRoot, _extends$1({
176
- as: component,
177
- ownerState: ownerState,
178
- className: clsx$1(classes.root, className),
179
- ref: ref
180
- }, other, {
181
- children: [children, fcs.required && /*#__PURE__*/jsxRuntimeExports.jsxs(AsteriskComponent, {
182
- ownerState: ownerState,
183
- "aria-hidden": true,
184
- className: classes.asterisk,
185
- children: ["\u2009", '*']
186
- })]
187
- }));
188
- });
189
- process.env.NODE_ENV !== "production" ? FormLabel.propTypes /* remove-proptypes */ = {
190
- // ┌────────────────────────────── Warning ──────────────────────────────┐
191
- // │ These PropTypes are generated from the TypeScript type definitions. │
192
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
193
- // └─────────────────────────────────────────────────────────────────────┘
194
- /**
195
- * The content of the component.
196
- */
197
- children: PropTypes.node,
198
- /**
199
- * Override or extend the styles applied to the component.
200
- */
201
- classes: PropTypes.object,
202
- /**
203
- * @ignore
204
- */
205
- className: PropTypes.string,
206
- /**
207
- * The color of the component.
208
- * It supports both default and custom theme colors, which can be added as shown in the
209
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
210
- */
211
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
212
- /**
213
- * The component used for the root node.
214
- * Either a string to use a HTML element or a component.
215
- */
216
- component: PropTypes.elementType,
217
- /**
218
- * If `true`, the label should be displayed in a disabled state.
219
- */
220
- disabled: PropTypes.bool,
221
- /**
222
- * If `true`, the label is displayed in an error state.
223
- */
224
- error: PropTypes.bool,
225
- /**
226
- * If `true`, the label should use filled classes key.
227
- */
228
- filled: PropTypes.bool,
229
- /**
230
- * If `true`, the input of this label is focused (used by `FormGroup` components).
231
- */
232
- focused: PropTypes.bool,
233
- /**
234
- * If `true`, the label will indicate that the `input` is required.
235
- */
236
- required: PropTypes.bool,
237
- /**
238
- * The system prop that allows defining system overrides as well as additional CSS styles.
239
- */
240
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
241
- } : void 0;
242
- var FormLabel$1 = FormLabel;
243
-
244
- function getInputLabelUtilityClasses(slot) {
245
- return generateUtilityClass('MuiInputLabel', slot);
246
- }
247
- generateUtilityClasses('MuiInputLabel', ['root', 'focused', 'disabled', 'error', 'required', 'asterisk', 'formControl', 'sizeSmall', 'shrink', 'animated', 'standard', 'filled', 'outlined']);
248
-
249
- const _excluded$4 = ["disableAnimation", "margin", "shrink", "variant", "className"];
250
- const useUtilityClasses$3 = ownerState => {
251
- const {
252
- classes,
253
- formControl,
254
- size,
255
- shrink,
256
- disableAnimation,
257
- variant,
258
- required
259
- } = ownerState;
260
- const slots = {
261
- root: ['root', formControl && 'formControl', !disableAnimation && 'animated', shrink && 'shrink', size && size !== 'normal' && `size${capitalize(size)}`, variant],
262
- asterisk: [required && 'asterisk']
263
- };
264
- const composedClasses = composeClasses(slots, getInputLabelUtilityClasses, classes);
265
- return _extends$1({}, classes, composedClasses);
266
- };
267
- const InputLabelRoot = styled$1(FormLabel$1, {
268
- shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
269
- name: 'MuiInputLabel',
270
- slot: 'Root',
271
- overridesResolver: (props, styles) => {
272
- const {
273
- ownerState
274
- } = props;
275
- return [{
276
- [`& .${formLabelClasses$1.asterisk}`]: styles.asterisk
277
- }, styles.root, ownerState.formControl && styles.formControl, ownerState.size === 'small' && styles.sizeSmall, ownerState.shrink && styles.shrink, !ownerState.disableAnimation && styles.animated, ownerState.focused && styles.focused, styles[ownerState.variant]];
278
- }
279
- })(({
280
- theme,
281
- ownerState
282
- }) => _extends$1({
283
- display: 'block',
284
- transformOrigin: 'top left',
285
- whiteSpace: 'nowrap',
286
- overflow: 'hidden',
287
- textOverflow: 'ellipsis',
288
- maxWidth: '100%'
289
- }, ownerState.formControl && {
290
- position: 'absolute',
291
- left: 0,
292
- top: 0,
293
- // slight alteration to spec spacing to match visual spec result
294
- transform: 'translate(0, 20px) scale(1)'
295
- }, ownerState.size === 'small' && {
296
- // Compensation for the `Input.inputSizeSmall` style.
297
- transform: 'translate(0, 17px) scale(1)'
298
- }, ownerState.shrink && {
299
- transform: 'translate(0, -1.5px) scale(0.75)',
300
- transformOrigin: 'top left',
301
- maxWidth: '133%'
302
- }, !ownerState.disableAnimation && {
303
- transition: theme.transitions.create(['color', 'transform', 'max-width'], {
304
- duration: theme.transitions.duration.shorter,
305
- easing: theme.transitions.easing.easeOut
306
- })
307
- }, ownerState.variant === 'filled' && _extends$1({
308
- // Chrome's autofill feature gives the input field a yellow background.
309
- // Since the input field is behind the label in the HTML tree,
310
- // the input field is drawn last and hides the label with an opaque background color.
311
- // zIndex: 1 will raise the label above opaque background-colors of input.
312
- zIndex: 1,
313
- pointerEvents: 'none',
314
- transform: 'translate(12px, 16px) scale(1)',
315
- maxWidth: 'calc(100% - 24px)'
316
- }, ownerState.size === 'small' && {
317
- transform: 'translate(12px, 13px) scale(1)'
318
- }, ownerState.shrink && _extends$1({
319
- userSelect: 'none',
320
- pointerEvents: 'auto',
321
- transform: 'translate(12px, 7px) scale(0.75)',
322
- maxWidth: 'calc(133% - 24px)'
323
- }, ownerState.size === 'small' && {
324
- transform: 'translate(12px, 4px) scale(0.75)'
325
- })), ownerState.variant === 'outlined' && _extends$1({
326
- // see comment above on filled.zIndex
327
- zIndex: 1,
328
- pointerEvents: 'none',
329
- transform: 'translate(14px, 16px) scale(1)',
330
- maxWidth: 'calc(100% - 24px)'
331
- }, ownerState.size === 'small' && {
332
- transform: 'translate(14px, 9px) scale(1)'
333
- }, ownerState.shrink && {
334
- userSelect: 'none',
335
- pointerEvents: 'auto',
336
- // Theoretically, we should have (8+5)*2/0.75 = 34px
337
- // but it feels a better when it bleeds a bit on the left, so 32px.
338
- maxWidth: 'calc(133% - 32px)',
339
- transform: 'translate(14px, -9px) scale(0.75)'
340
- })));
341
- const InputLabel = /*#__PURE__*/React.forwardRef(function InputLabel(inProps, ref) {
342
- const props = useDefaultProps({
343
- name: 'MuiInputLabel',
344
- props: inProps
345
- });
346
- const {
347
- disableAnimation = false,
348
- shrink: shrinkProp,
349
- className
350
- } = props,
351
- other = _objectWithoutPropertiesLoose$1(props, _excluded$4);
352
- const muiFormControl = useFormControl();
353
- let shrink = shrinkProp;
354
- if (typeof shrink === 'undefined' && muiFormControl) {
355
- shrink = muiFormControl.filled || muiFormControl.focused || muiFormControl.adornedStart;
356
- }
357
- const fcs = formControlState({
358
- props,
359
- muiFormControl,
360
- states: ['size', 'variant', 'required', 'focused']
361
- });
362
- const ownerState = _extends$1({}, props, {
363
- disableAnimation,
364
- formControl: muiFormControl,
365
- shrink,
366
- size: fcs.size,
367
- variant: fcs.variant,
368
- required: fcs.required,
369
- focused: fcs.focused
370
- });
371
- const classes = useUtilityClasses$3(ownerState);
372
- return /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelRoot, _extends$1({
373
- "data-shrink": shrink,
374
- ownerState: ownerState,
375
- ref: ref,
376
- className: clsx$1(classes.root, className)
377
- }, other, {
378
- classes: classes
379
- }));
380
- });
381
- process.env.NODE_ENV !== "production" ? InputLabel.propTypes /* remove-proptypes */ = {
382
- // ┌────────────────────────────── Warning ──────────────────────────────┐
383
- // │ These PropTypes are generated from the TypeScript type definitions. │
384
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
385
- // └─────────────────────────────────────────────────────────────────────┘
386
- /**
387
- * The content of the component.
388
- */
389
- children: PropTypes.node,
390
- /**
391
- * Override or extend the styles applied to the component.
392
- */
393
- classes: PropTypes.object,
394
- /**
395
- * @ignore
396
- */
397
- className: PropTypes.string,
398
- /**
399
- * The color of the component.
400
- * It supports both default and custom theme colors, which can be added as shown in the
401
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
402
- */
403
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
404
- /**
405
- * If `true`, the transition animation is disabled.
406
- * @default false
407
- */
408
- disableAnimation: PropTypes.bool,
409
- /**
410
- * If `true`, the component is disabled.
411
- */
412
- disabled: PropTypes.bool,
413
- /**
414
- * If `true`, the label is displayed in an error state.
415
- */
416
- error: PropTypes.bool,
417
- /**
418
- * If `true`, the `input` of this label is focused.
419
- */
420
- focused: PropTypes.bool,
421
- /**
422
- * If `dense`, will adjust vertical spacing. This is normally obtained via context from
423
- * FormControl.
424
- */
425
- margin: PropTypes.oneOf(['dense']),
426
- /**
427
- * if `true`, the label will indicate that the `input` is required.
428
- */
429
- required: PropTypes.bool,
430
- /**
431
- * If `true`, the label is shrunk.
432
- */
433
- shrink: PropTypes.bool,
434
- /**
435
- * The size of the component.
436
- * @default 'normal'
437
- */
438
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['normal', 'small']), PropTypes.string]),
439
- /**
440
- * The system prop that allows defining system overrides as well as additional CSS styles.
441
- */
442
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
443
- /**
444
- * The variant to use.
445
- */
446
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
447
- } : void 0;
448
- var InputLabel$1 = InputLabel;
449
-
450
- function getFormControlUtilityClasses(slot) {
451
- return generateUtilityClass('MuiFormControl', slot);
452
- }
453
- generateUtilityClasses('MuiFormControl', ['root', 'marginNone', 'marginNormal', 'marginDense', 'fullWidth', 'disabled']);
454
-
455
- const _excluded$3 = ["children", "className", "color", "component", "disabled", "error", "focused", "fullWidth", "hiddenLabel", "margin", "required", "size", "variant"];
456
- const useUtilityClasses$2 = ownerState => {
457
- const {
458
- classes,
459
- margin,
460
- fullWidth
461
- } = ownerState;
462
- const slots = {
463
- root: ['root', margin !== 'none' && `margin${capitalize(margin)}`, fullWidth && 'fullWidth']
464
- };
465
- return composeClasses(slots, getFormControlUtilityClasses, classes);
466
- };
467
- const FormControlRoot = styled$1('div', {
468
- name: 'MuiFormControl',
469
- slot: 'Root',
470
- overridesResolver: ({
471
- ownerState
472
- }, styles) => {
473
- return _extends$1({}, styles.root, styles[`margin${capitalize(ownerState.margin)}`], ownerState.fullWidth && styles.fullWidth);
474
- }
475
- })(({
476
- ownerState
477
- }) => _extends$1({
478
- display: 'inline-flex',
479
- flexDirection: 'column',
480
- position: 'relative',
481
- // Reset fieldset default style.
482
- minWidth: 0,
483
- padding: 0,
484
- margin: 0,
485
- border: 0,
486
- verticalAlign: 'top'
487
- }, ownerState.margin === 'normal' && {
488
- marginTop: 16,
489
- marginBottom: 8
490
- }, ownerState.margin === 'dense' && {
491
- marginTop: 8,
492
- marginBottom: 4
493
- }, ownerState.fullWidth && {
494
- width: '100%'
495
- }));
496
-
497
- /**
498
- * Provides context such as filled/focused/error/required for form inputs.
499
- * Relying on the context provides high flexibility and ensures that the state always stays
500
- * consistent across the children of the `FormControl`.
501
- * This context is used by the following components:
502
- *
503
- * - FormLabel
504
- * - FormHelperText
505
- * - Input
506
- * - InputLabel
507
- *
508
- * You can find one composition example below and more going to [the demos](/material-ui/react-text-field/#components).
509
- *
510
- * ```jsx
511
- * <FormControl>
512
- * <InputLabel htmlFor="my-input">Email address</InputLabel>
513
- * <Input id="my-input" aria-describedby="my-helper-text" />
514
- * <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
515
- * </FormControl>
516
- * ```
517
- *
518
- * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies.
519
- * For instance, only one input can be focused at the same time, the state shouldn't be shared.
520
- */
521
- const FormControl = /*#__PURE__*/React.forwardRef(function FormControl(inProps, ref) {
522
- const props = useDefaultProps({
523
- props: inProps,
524
- name: 'MuiFormControl'
525
- });
526
- const {
527
- children,
528
- className,
529
- color = 'primary',
530
- component = 'div',
531
- disabled = false,
532
- error = false,
533
- focused: visuallyFocused,
534
- fullWidth = false,
535
- hiddenLabel = false,
536
- margin = 'none',
537
- required = false,
538
- size = 'medium',
539
- variant = 'outlined'
540
- } = props,
541
- other = _objectWithoutPropertiesLoose$1(props, _excluded$3);
542
- const ownerState = _extends$1({}, props, {
543
- color,
544
- component,
545
- disabled,
546
- error,
547
- fullWidth,
548
- hiddenLabel,
549
- margin,
550
- required,
551
- size,
552
- variant
553
- });
554
- const classes = useUtilityClasses$2(ownerState);
555
- const [adornedStart, setAdornedStart] = React.useState(() => {
556
- // We need to iterate through the children and find the Input in order
557
- // to fully support server-side rendering.
558
- let initialAdornedStart = false;
559
- if (children) {
560
- React.Children.forEach(children, child => {
561
- if (!isMuiElement(child, ['Input', 'Select'])) {
562
- return;
563
- }
564
- const input = isMuiElement(child, ['Select']) ? child.props.input : child;
565
- if (input && isAdornedStart(input.props)) {
566
- initialAdornedStart = true;
567
- }
568
- });
569
- }
570
- return initialAdornedStart;
571
- });
572
- const [filled, setFilled] = React.useState(() => {
573
- // We need to iterate through the children and find the Input in order
574
- // to fully support server-side rendering.
575
- let initialFilled = false;
576
- if (children) {
577
- React.Children.forEach(children, child => {
578
- if (!isMuiElement(child, ['Input', 'Select'])) {
579
- return;
580
- }
581
- if (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) {
582
- initialFilled = true;
583
- }
584
- });
585
- }
586
- return initialFilled;
587
- });
588
- const [focusedState, setFocused] = React.useState(false);
589
- if (disabled && focusedState) {
590
- setFocused(false);
591
- }
592
- const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState;
593
- let registerEffect;
594
- if (process.env.NODE_ENV !== 'production') {
595
- // eslint-disable-next-line react-hooks/rules-of-hooks
596
- const registeredInput = React.useRef(false);
597
- registerEffect = () => {
598
- if (registeredInput.current) {
599
- console.error(['MUI: There are multiple `InputBase` components inside a FormControl.', 'This creates visual inconsistencies, only use one `InputBase`.'].join('\n'));
600
- }
601
- registeredInput.current = true;
602
- return () => {
603
- registeredInput.current = false;
604
- };
605
- };
606
- }
607
- const childContext = React.useMemo(() => {
608
- return {
609
- adornedStart,
610
- setAdornedStart,
611
- color,
612
- disabled,
613
- error,
614
- filled,
615
- focused,
616
- fullWidth,
617
- hiddenLabel,
618
- size,
619
- onBlur: () => {
620
- setFocused(false);
621
- },
622
- onEmpty: () => {
623
- setFilled(false);
624
- },
625
- onFilled: () => {
626
- setFilled(true);
627
- },
628
- onFocus: () => {
629
- setFocused(true);
630
- },
631
- registerEffect,
632
- required,
633
- variant
634
- };
635
- }, [adornedStart, color, disabled, error, filled, focused, fullWidth, hiddenLabel, registerEffect, required, size, variant]);
636
- return /*#__PURE__*/jsxRuntimeExports.jsx(FormControlContext.Provider, {
637
- value: childContext,
638
- children: /*#__PURE__*/jsxRuntimeExports.jsx(FormControlRoot, _extends$1({
639
- as: component,
640
- ownerState: ownerState,
641
- className: clsx$1(classes.root, className),
642
- ref: ref
643
- }, other, {
644
- children: children
645
- }))
646
- });
647
- });
648
- process.env.NODE_ENV !== "production" ? FormControl.propTypes /* remove-proptypes */ = {
649
- // ┌────────────────────────────── Warning ──────────────────────────────┐
650
- // │ These PropTypes are generated from the TypeScript type definitions. │
651
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
652
- // └─────────────────────────────────────────────────────────────────────┘
653
- /**
654
- * The content of the component.
655
- */
656
- children: PropTypes.node,
657
- /**
658
- * Override or extend the styles applied to the component.
659
- */
660
- classes: PropTypes.object,
661
- /**
662
- * @ignore
663
- */
664
- className: PropTypes.string,
665
- /**
666
- * The color of the component.
667
- * It supports both default and custom theme colors, which can be added as shown in the
668
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
669
- * @default 'primary'
670
- */
671
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
672
- /**
673
- * The component used for the root node.
674
- * Either a string to use a HTML element or a component.
675
- */
676
- component: PropTypes.elementType,
677
- /**
678
- * If `true`, the label, input and helper text should be displayed in a disabled state.
679
- * @default false
680
- */
681
- disabled: PropTypes.bool,
682
- /**
683
- * If `true`, the label is displayed in an error state.
684
- * @default false
685
- */
686
- error: PropTypes.bool,
687
- /**
688
- * If `true`, the component is displayed in focused state.
689
- */
690
- focused: PropTypes.bool,
691
- /**
692
- * If `true`, the component will take up the full width of its container.
693
- * @default false
694
- */
695
- fullWidth: PropTypes.bool,
696
- /**
697
- * If `true`, the label is hidden.
698
- * This is used to increase density for a `FilledInput`.
699
- * Be sure to add `aria-label` to the `input` element.
700
- * @default false
701
- */
702
- hiddenLabel: PropTypes.bool,
703
- /**
704
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
705
- * @default 'none'
706
- */
707
- margin: PropTypes.oneOf(['dense', 'none', 'normal']),
708
- /**
709
- * If `true`, the label will indicate that the `input` is required.
710
- * @default false
711
- */
712
- required: PropTypes.bool,
713
- /**
714
- * The size of the component.
715
- * @default 'medium'
716
- */
717
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
718
- /**
719
- * The system prop that allows defining system overrides as well as additional CSS styles.
720
- */
721
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
722
- /**
723
- * The variant to use.
724
- * @default 'outlined'
725
- */
726
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
727
- } : void 0;
728
- var FormControl$1 = FormControl;
729
-
730
- function getFormHelperTextUtilityClasses(slot) {
731
- return generateUtilityClass('MuiFormHelperText', slot);
732
- }
733
- const formHelperTextClasses = generateUtilityClasses('MuiFormHelperText', ['root', 'error', 'disabled', 'sizeSmall', 'sizeMedium', 'contained', 'focused', 'filled', 'required']);
734
- var formHelperTextClasses$1 = formHelperTextClasses;
735
-
736
- var _span;
737
- const _excluded$2 = ["children", "className", "component", "disabled", "error", "filled", "focused", "margin", "required", "variant"];
738
- const useUtilityClasses$1 = ownerState => {
739
- const {
740
- classes,
741
- contained,
742
- size,
743
- disabled,
744
- error,
745
- filled,
746
- focused,
747
- required
748
- } = ownerState;
749
- const slots = {
750
- root: ['root', disabled && 'disabled', error && 'error', size && `size${capitalize(size)}`, contained && 'contained', focused && 'focused', filled && 'filled', required && 'required']
751
- };
752
- return composeClasses(slots, getFormHelperTextUtilityClasses, classes);
753
- };
754
- const FormHelperTextRoot = styled$1('p', {
755
- name: 'MuiFormHelperText',
756
- slot: 'Root',
757
- overridesResolver: (props, styles) => {
758
- const {
759
- ownerState
760
- } = props;
761
- return [styles.root, ownerState.size && styles[`size${capitalize(ownerState.size)}`], ownerState.contained && styles.contained, ownerState.filled && styles.filled];
762
- }
763
- })(({
764
- theme,
765
- ownerState
766
- }) => _extends$1({
767
- color: (theme.vars || theme).palette.text.secondary
768
- }, theme.typography.caption, {
769
- textAlign: 'left',
770
- marginTop: 3,
771
- marginRight: 0,
772
- marginBottom: 0,
773
- marginLeft: 0,
774
- [`&.${formHelperTextClasses$1.disabled}`]: {
775
- color: (theme.vars || theme).palette.text.disabled
776
- },
777
- [`&.${formHelperTextClasses$1.error}`]: {
778
- color: (theme.vars || theme).palette.error.main
779
- }
780
- }, ownerState.size === 'small' && {
781
- marginTop: 4
782
- }, ownerState.contained && {
783
- marginLeft: 14,
784
- marginRight: 14
785
- }));
786
- const FormHelperText = /*#__PURE__*/React.forwardRef(function FormHelperText(inProps, ref) {
787
- const props = useDefaultProps({
788
- props: inProps,
789
- name: 'MuiFormHelperText'
790
- });
791
- const {
792
- children,
793
- className,
794
- component = 'p'
795
- } = props,
796
- other = _objectWithoutPropertiesLoose$1(props, _excluded$2);
797
- const muiFormControl = useFormControl();
798
- const fcs = formControlState({
799
- props,
800
- muiFormControl,
801
- states: ['variant', 'size', 'disabled', 'error', 'filled', 'focused', 'required']
802
- });
803
- const ownerState = _extends$1({}, props, {
804
- component,
805
- contained: fcs.variant === 'filled' || fcs.variant === 'outlined',
806
- variant: fcs.variant,
807
- size: fcs.size,
808
- disabled: fcs.disabled,
809
- error: fcs.error,
810
- filled: fcs.filled,
811
- focused: fcs.focused,
812
- required: fcs.required
813
- });
814
- const classes = useUtilityClasses$1(ownerState);
815
- return /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextRoot, _extends$1({
816
- as: component,
817
- ownerState: ownerState,
818
- className: clsx$1(classes.root, className),
819
- ref: ref
820
- }, other, {
821
- children: children === ' ' ? // notranslate needed while Google Translate will not fix zero-width space issue
822
- _span || (_span = /*#__PURE__*/jsxRuntimeExports.jsx("span", {
823
- className: "notranslate",
824
- children: "\u200B"
825
- })) : children
826
- }));
827
- });
828
- process.env.NODE_ENV !== "production" ? FormHelperText.propTypes /* remove-proptypes */ = {
829
- // ┌────────────────────────────── Warning ──────────────────────────────┐
830
- // │ These PropTypes are generated from the TypeScript type definitions. │
831
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
832
- // └─────────────────────────────────────────────────────────────────────┘
833
- /**
834
- * The content of the component.
835
- *
836
- * If `' '` is provided, the component reserves one line height for displaying a future message.
837
- */
838
- children: PropTypes.node,
839
- /**
840
- * Override or extend the styles applied to the component.
841
- */
842
- classes: PropTypes.object,
843
- /**
844
- * @ignore
845
- */
846
- className: PropTypes.string,
847
- /**
848
- * The component used for the root node.
849
- * Either a string to use a HTML element or a component.
850
- */
851
- component: PropTypes.elementType,
852
- /**
853
- * If `true`, the helper text should be displayed in a disabled state.
854
- */
855
- disabled: PropTypes.bool,
856
- /**
857
- * If `true`, helper text should be displayed in an error state.
858
- */
859
- error: PropTypes.bool,
860
- /**
861
- * If `true`, the helper text should use filled classes key.
862
- */
863
- filled: PropTypes.bool,
864
- /**
865
- * If `true`, the helper text should use focused classes key.
866
- */
867
- focused: PropTypes.bool,
868
- /**
869
- * If `dense`, will adjust vertical spacing. This is normally obtained via context from
870
- * FormControl.
871
- */
872
- margin: PropTypes.oneOf(['dense']),
873
- /**
874
- * If `true`, the helper text should use required classes key.
875
- */
876
- required: PropTypes.bool,
877
- /**
878
- * The system prop that allows defining system overrides as well as additional CSS styles.
879
- */
880
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
881
- /**
882
- * The variant to use.
883
- */
884
- variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['filled', 'outlined', 'standard']), PropTypes.string])
885
- } : void 0;
886
- var FormHelperText$1 = FormHelperText;
887
-
888
- function getTextFieldUtilityClass(slot) {
889
- return generateUtilityClass('MuiTextField', slot);
890
- }
891
- generateUtilityClasses('MuiTextField', ['root']);
892
-
893
- 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", "onFocus", "placeholder", "required", "rows", "select", "SelectProps", "type", "value", "variant"];
894
- const variantComponent = {
895
- standard: Input,
896
- filled: FilledInput,
897
- outlined: OutlinedInput
898
- };
899
- const useUtilityClasses = ownerState => {
900
- const {
901
- classes
902
- } = ownerState;
903
- const slots = {
904
- root: ['root']
905
- };
906
- return composeClasses(slots, getTextFieldUtilityClass, classes);
907
- };
908
- const TextFieldRoot = styled$1(FormControl$1, {
909
- name: 'MuiTextField',
910
- slot: 'Root',
911
- overridesResolver: (props, styles) => styles.root
912
- })({});
913
-
914
- /**
915
- * The `TextField` is a convenience wrapper for the most common cases (80%).
916
- * It cannot be all things to all people, otherwise the API would grow out of control.
917
- *
918
- * ## Advanced Configuration
919
- *
920
- * It's important to understand that the text field is a simple abstraction
921
- * on top of the following components:
922
- *
923
- * - [FormControl](/material-ui/api/form-control/)
924
- * - [InputLabel](/material-ui/api/input-label/)
925
- * - [FilledInput](/material-ui/api/filled-input/)
926
- * - [OutlinedInput](/material-ui/api/outlined-input/)
927
- * - [Input](/material-ui/api/input/)
928
- * - [FormHelperText](/material-ui/api/form-helper-text/)
929
- *
930
- * If you wish to alter the props applied to the `input` element, you can do so as follows:
931
- *
932
- * ```jsx
933
- * const inputProps = {
934
- * step: 300,
935
- * };
936
- *
937
- * return <TextField id="time" type="time" inputProps={inputProps} />;
938
- * ```
939
- *
940
- * For advanced cases, please look at the source of TextField by clicking on the
941
- * "Edit this page" button above. Consider either:
942
- *
943
- * - using the upper case props for passing values directly to the components
944
- * - using the underlying components directly as shown in the demos
945
- */
946
- const TextField = /*#__PURE__*/React.forwardRef(function TextField(inProps, ref) {
947
- const props = useDefaultProps({
948
- props: inProps,
949
- name: 'MuiTextField'
950
- });
951
- const {
952
- autoComplete,
953
- autoFocus = false,
954
- children,
955
- className,
956
- color = 'primary',
957
- defaultValue,
958
- disabled = false,
959
- error = false,
960
- FormHelperTextProps,
961
- fullWidth = false,
962
- helperText,
963
- id: idOverride,
964
- InputLabelProps,
965
- inputProps,
966
- InputProps,
967
- inputRef,
968
- label,
969
- maxRows,
970
- minRows,
971
- multiline = false,
972
- name,
973
- onBlur,
974
- onChange,
975
- onFocus,
976
- placeholder,
977
- required = false,
978
- rows,
979
- select = false,
980
- SelectProps,
981
- type,
982
- value,
983
- variant = 'outlined'
984
- } = props,
985
- other = _objectWithoutPropertiesLoose$1(props, _excluded$1);
986
- const ownerState = _extends$1({}, props, {
987
- autoFocus,
988
- color,
989
- disabled,
990
- error,
991
- fullWidth,
992
- multiline,
993
- required,
994
- select,
995
- variant
996
- });
997
- const classes = useUtilityClasses(ownerState);
998
- if (process.env.NODE_ENV !== 'production') {
999
- if (select && !children) {
1000
- console.error('MUI: `children` must be passed when using the `TextField` component with `select`.');
1001
- }
1002
- }
1003
- const InputMore = {};
1004
- if (variant === 'outlined') {
1005
- if (InputLabelProps && typeof InputLabelProps.shrink !== 'undefined') {
1006
- InputMore.notched = InputLabelProps.shrink;
1007
- }
1008
- InputMore.label = label;
1009
- }
1010
- if (select) {
1011
- // unset defaults from textbox inputs
1012
- if (!SelectProps || !SelectProps.native) {
1013
- InputMore.id = undefined;
1014
- }
1015
- InputMore['aria-describedby'] = undefined;
1016
- }
1017
- const id = useId(idOverride);
1018
- const helperTextId = helperText && id ? `${id}-helper-text` : undefined;
1019
- const inputLabelId = label && id ? `${id}-label` : undefined;
1020
- const InputComponent = variantComponent[variant];
1021
- const InputElement = /*#__PURE__*/jsxRuntimeExports.jsx(InputComponent, _extends$1({
1022
- "aria-describedby": helperTextId,
1023
- autoComplete: autoComplete,
1024
- autoFocus: autoFocus,
1025
- defaultValue: defaultValue,
1026
- fullWidth: fullWidth,
1027
- multiline: multiline,
1028
- name: name,
1029
- rows: rows,
1030
- maxRows: maxRows,
1031
- minRows: minRows,
1032
- type: type,
1033
- value: value,
1034
- id: id,
1035
- inputRef: inputRef,
1036
- onBlur: onBlur,
1037
- onChange: onChange,
1038
- onFocus: onFocus,
1039
- placeholder: placeholder,
1040
- inputProps: inputProps
1041
- }, InputMore, InputProps));
1042
- return /*#__PURE__*/jsxRuntimeExports.jsxs(TextFieldRoot, _extends$1({
1043
- className: clsx$1(classes.root, className),
1044
- disabled: disabled,
1045
- error: error,
1046
- fullWidth: fullWidth,
1047
- ref: ref,
1048
- required: required,
1049
- color: color,
1050
- variant: variant,
1051
- ownerState: ownerState
1052
- }, other, {
1053
- children: [label != null && label !== '' && /*#__PURE__*/jsxRuntimeExports.jsx(InputLabel$1, _extends$1({
1054
- htmlFor: id,
1055
- id: inputLabelId
1056
- }, InputLabelProps, {
1057
- children: label
1058
- })), select ? /*#__PURE__*/jsxRuntimeExports.jsx(Select, _extends$1({
1059
- "aria-describedby": helperTextId,
1060
- id: id,
1061
- labelId: inputLabelId,
1062
- value: value,
1063
- input: InputElement
1064
- }, SelectProps, {
1065
- children: children
1066
- })) : InputElement, helperText && /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperText$1, _extends$1({
1067
- id: helperTextId
1068
- }, FormHelperTextProps, {
1069
- children: helperText
1070
- }))]
1071
- }));
1072
- });
1073
- process.env.NODE_ENV !== "production" ? TextField.propTypes /* remove-proptypes */ = {
1074
- // ┌────────────────────────────── Warning ──────────────────────────────┐
1075
- // │ These PropTypes are generated from the TypeScript type definitions. │
1076
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
1077
- // └─────────────────────────────────────────────────────────────────────┘
1078
- /**
1079
- * This prop helps users to fill forms faster, especially on mobile devices.
1080
- * The name can be confusing, as it's more like an autofill.
1081
- * You can learn more about it [following the specification](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill).
1082
- */
1083
- autoComplete: PropTypes.string,
1084
- /**
1085
- * If `true`, the `input` element is focused during the first mount.
1086
- * @default false
1087
- */
1088
- autoFocus: PropTypes.bool,
1089
- /**
1090
- * @ignore
1091
- */
1092
- children: PropTypes.node,
1093
- /**
1094
- * Override or extend the styles applied to the component.
1095
- */
1096
- classes: PropTypes.object,
1097
- /**
1098
- * @ignore
1099
- */
1100
- className: PropTypes.string,
1101
- /**
1102
- * The color of the component.
1103
- * It supports both default and custom theme colors, which can be added as shown in the
1104
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
1105
- * @default 'primary'
1106
- */
1107
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
1108
- /**
1109
- * The default value. Use when the component is not controlled.
1110
- */
1111
- defaultValue: PropTypes.any,
1112
- /**
1113
- * If `true`, the component is disabled.
1114
- * @default false
1115
- */
1116
- disabled: PropTypes.bool,
1117
- /**
1118
- * If `true`, the label is displayed in an error state.
1119
- * @default false
1120
- */
1121
- error: PropTypes.bool,
1122
- /**
1123
- * Props applied to the [`FormHelperText`](/material-ui/api/form-helper-text/) element.
1124
- */
1125
- FormHelperTextProps: PropTypes.object,
1126
- /**
1127
- * If `true`, the input will take up the full width of its container.
1128
- * @default false
1129
- */
1130
- fullWidth: PropTypes.bool,
1131
- /**
1132
- * The helper text content.
1133
- */
1134
- helperText: PropTypes.node,
1135
- /**
1136
- * The id of the `input` element.
1137
- * Use this prop to make `label` and `helperText` accessible for screen readers.
1138
- */
1139
- id: PropTypes.string,
1140
- /**
1141
- * Props applied to the [`InputLabel`](/material-ui/api/input-label/) element.
1142
- * Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
1143
- */
1144
- InputLabelProps: PropTypes.object,
1145
- /**
1146
- * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
1147
- */
1148
- inputProps: PropTypes.object,
1149
- /**
1150
- * Props applied to the Input element.
1151
- * It will be a [`FilledInput`](/material-ui/api/filled-input/),
1152
- * [`OutlinedInput`](/material-ui/api/outlined-input/) or [`Input`](/material-ui/api/input/)
1153
- * component depending on the `variant` prop value.
1154
- */
1155
- InputProps: PropTypes.object,
1156
- /**
1157
- * Pass a ref to the `input` element.
1158
- */
1159
- inputRef: refType,
1160
- /**
1161
- * The label content.
1162
- */
1163
- label: PropTypes.node,
1164
- /**
1165
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
1166
- * @default 'none'
1167
- */
1168
- margin: PropTypes.oneOf(['dense', 'none', 'normal']),
1169
- /**
1170
- * Maximum number of rows to display when multiline option is set to true.
1171
- */
1172
- maxRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1173
- /**
1174
- * Minimum number of rows to display when multiline option is set to true.
1175
- */
1176
- minRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1177
- /**
1178
- * If `true`, a `textarea` element is rendered instead of an input.
1179
- * @default false
1180
- */
1181
- multiline: PropTypes.bool,
1182
- /**
1183
- * Name attribute of the `input` element.
1184
- */
1185
- name: PropTypes.string,
1186
- /**
1187
- * @ignore
1188
- */
1189
- onBlur: PropTypes.func,
1190
- /**
1191
- * Callback fired when the value is changed.
1192
- *
1193
- * @param {object} event The event source of the callback.
1194
- * You can pull out the new value by accessing `event.target.value` (string).
1195
- */
1196
- onChange: PropTypes.func,
1197
- /**
1198
- * @ignore
1199
- */
1200
- onFocus: PropTypes.func,
1201
- /**
1202
- * The short hint displayed in the `input` before the user enters a value.
1203
- */
1204
- placeholder: PropTypes.string,
1205
- /**
1206
- * If `true`, the label is displayed as required and the `input` element is required.
1207
- * @default false
1208
- */
1209
- required: PropTypes.bool,
1210
- /**
1211
- * Number of rows to display when multiline option is set to true.
1212
- */
1213
- rows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1214
- /**
1215
- * Render a [`Select`](/material-ui/api/select/) element while passing the Input element to `Select` as `input` parameter.
1216
- * If this option is set you must pass the options of the select as children.
1217
- * @default false
1218
- */
1219
- select: PropTypes.bool,
1220
- /**
1221
- * Props applied to the [`Select`](/material-ui/api/select/) element.
1222
- */
1223
- SelectProps: PropTypes.object,
1224
- /**
1225
- * The size of the component.
1226
- */
1227
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
1228
- /**
1229
- * The system prop that allows defining system overrides as well as additional CSS styles.
1230
- */
1231
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1232
- /**
1233
- * 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).
1234
- */
1235
- type: PropTypes /* @typescript-to-proptypes-ignore */.string,
1236
- /**
1237
- * The value of the `input` element, required for a controlled component.
1238
- */
1239
- value: PropTypes.any,
1240
- /**
1241
- * The variant to use.
1242
- * @default 'outlined'
1243
- */
1244
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
1245
- } : void 0;
1246
- 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';
1247
16
 
1248
17
  const SUBMIT_FILTER_STROKE_TIME = 500;
1249
18
  const InputNumberInterval = props => {
@@ -1285,7 +54,7 @@ const InputNumberInterval = props => {
1285
54
  const newLowerBound = event.target.value;
1286
55
  updateFilterValue(newLowerBound, filterValueState[1]);
1287
56
  };
1288
- return /*#__PURE__*/React.createElement(Box$1, {
57
+ return /*#__PURE__*/React.createElement(Box, {
1289
58
  sx: {
1290
59
  display: 'inline-flex',
1291
60
  flexDirection: 'row',
@@ -1293,7 +62,7 @@ const InputNumberInterval = props => {
1293
62
  height: 48,
1294
63
  pl: '20px'
1295
64
  }
1296
- }, /*#__PURE__*/React.createElement(TextField$1, {
65
+ }, /*#__PURE__*/React.createElement(TextField, {
1297
66
  name: "lower-bound-input",
1298
67
  placeholder: "From",
1299
68
  label: "From",
@@ -1305,7 +74,7 @@ const InputNumberInterval = props => {
1305
74
  sx: {
1306
75
  mr: 2
1307
76
  }
1308
- }), /*#__PURE__*/React.createElement(TextField$1, {
77
+ }), /*#__PURE__*/React.createElement(TextField, {
1309
78
  name: "upper-bound-input",
1310
79
  placeholder: "To",
1311
80
  label: "To",
@@ -1337,8 +106,8 @@ const isBetweenOperator = {
1337
106
  if (typeof filterItem.value[0] !== 'number' || typeof filterItem.value[1] !== 'number') {
1338
107
  return null;
1339
108
  }
1340
- return params => {
1341
- 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];
1342
111
  };
1343
112
  },
1344
113
  InputComponent: InputNumberInterval
@@ -1354,14 +123,14 @@ const doesNotContain = {
1354
123
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1355
124
  return null;
1356
125
  }
1357
- return params => {
126
+ return value => {
1358
127
  if (filterItem.value.length === 0) {
1359
128
  return true;
1360
129
  }
1361
- if (params.value == null) {
130
+ if (value == null) {
1362
131
  return true;
1363
132
  }
1364
- if (String(params.value).indexOf(filterItem.value) !== -1) {
133
+ if (String(value).indexOf(filterItem.value) !== -1) {
1365
134
  return false;
1366
135
  }
1367
136
  return true;
@@ -1378,11 +147,11 @@ const doesNotEndWithOperator = {
1378
147
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1379
148
  return null;
1380
149
  }
1381
- return params => {
1382
- if (params.value == null) {
150
+ return value => {
151
+ if (value == null) {
1383
152
  return true;
1384
153
  }
1385
- return !String(params.value).endsWith(filterItem.value);
154
+ return !String(value).endsWith(filterItem.value);
1386
155
  };
1387
156
  },
1388
157
  InputComponent: GridFilterInputValue
@@ -1396,11 +165,11 @@ const doesNotEqual = {
1396
165
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1397
166
  return null;
1398
167
  }
1399
- return params => {
1400
- if (params.value == null) {
168
+ return value => {
169
+ if (value == null) {
1401
170
  return true;
1402
171
  }
1403
- if (String(params.value) === filterItem.value) {
172
+ if (String(value) === filterItem.value) {
1404
173
  return false;
1405
174
  }
1406
175
  return true;
@@ -1417,11 +186,11 @@ const doesNotHaveOperator = {
1417
186
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1418
187
  return null;
1419
188
  }
1420
- return params => {
1421
- if (params.value == null) {
189
+ return value => {
190
+ if (value == null) {
1422
191
  return true;
1423
192
  }
1424
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
193
+ const cellValues = Array.isArray(value) ? value : [value];
1425
194
  return !cellValues.map(value => String(value)).includes(filterItem.value);
1426
195
  };
1427
196
  },
@@ -1439,11 +208,11 @@ const doesNotStartWithOperator = {
1439
208
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1440
209
  return null;
1441
210
  }
1442
- return params => {
1443
- if (params.value == null) {
211
+ return value => {
212
+ if (value == null) {
1444
213
  return true;
1445
214
  }
1446
- return !String(params.value).startsWith(filterItem.value);
215
+ return !String(value).startsWith(filterItem.value);
1447
216
  };
1448
217
  },
1449
218
  InputComponent: GridFilterInputValue
@@ -1457,11 +226,11 @@ const hasOperator = {
1457
226
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1458
227
  return null;
1459
228
  }
1460
- return params => {
1461
- if (params.value == null) {
229
+ return value => {
230
+ if (value == null) {
1462
231
  return false;
1463
232
  }
1464
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
233
+ const cellValues = Array.isArray(value) ? value : [value];
1465
234
  return cellValues.map(value => String(value)).includes(filterItem.value);
1466
235
  };
1467
236
  },
@@ -1479,11 +248,11 @@ const hasOnlyOperator = {
1479
248
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1480
249
  return null;
1481
250
  }
1482
- return params => {
1483
- if (params.value == null) {
251
+ return value => {
252
+ if (value == null) {
1484
253
  return false;
1485
254
  }
1486
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
255
+ const cellValues = Array.isArray(value) ? value : [value];
1487
256
  return cellValues.length === 1 && String(cellValues[0]) === filterItem.value;
1488
257
  };
1489
258
  },
@@ -1501,14 +270,14 @@ const isOperator = {
1501
270
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1502
271
  return null;
1503
272
  }
1504
- return params => {
1505
- if (params.value == null) {
273
+ return value => {
274
+ if (value == null) {
1506
275
  return false;
1507
276
  }
1508
- if (Array.isArray(params.value)) {
277
+ if (Array.isArray(value)) {
1509
278
  return false;
1510
279
  }
1511
- return String(params.value) === filterItem.value;
280
+ return String(value) === filterItem.value;
1512
281
  };
1513
282
  },
1514
283
  InputComponent: GridFilterInputValue
@@ -1525,14 +294,14 @@ const isNotOperator = {
1525
294
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1526
295
  return null;
1527
296
  }
1528
- return params => {
1529
- if (params.value == null) {
297
+ return value => {
298
+ if (value == null) {
1530
299
  return true;
1531
300
  }
1532
- if (Array.isArray(params.value)) {
301
+ if (Array.isArray(value)) {
1533
302
  return true;
1534
303
  }
1535
- return String(params.value) !== filterItem.value;
304
+ return String(value) !== filterItem.value;
1536
305
  };
1537
306
  },
1538
307
  InputComponent: GridFilterInputValue
@@ -1549,14 +318,14 @@ const containsAnyOfOperator = {
1549
318
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1550
319
  return null;
1551
320
  }
1552
- return params => {
321
+ return value => {
1553
322
  if (filterItem.value.length === 0) {
1554
323
  return true;
1555
324
  }
1556
- if (params.value == null) {
325
+ if (value == null) {
1557
326
  return false;
1558
327
  }
1559
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
328
+ const paramValues = Array.isArray(value) ? value : [value];
1560
329
  let match = false;
1561
330
  filterItem.value.forEach(filteredValue => {
1562
331
  paramValues.forEach(paramValue => {
@@ -1579,14 +348,14 @@ const doesNotContainAnyOfOperator = {
1579
348
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1580
349
  return null;
1581
350
  }
1582
- return params => {
351
+ return value => {
1583
352
  if (filterItem.value.length === 0) {
1584
353
  return true;
1585
354
  }
1586
- if (params.value == null) {
355
+ if (value == null) {
1587
356
  return true;
1588
357
  }
1589
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
358
+ const paramValues = Array.isArray(value) ? value : [value];
1590
359
  for (const filteredValue of filterItem.value) {
1591
360
  for (const paramValue of paramValues) {
1592
361
  if (String(paramValue).indexOf(filteredValue) !== -1) {
@@ -1608,14 +377,14 @@ const doesNotEndWithAnyOfOperator = {
1608
377
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1609
378
  return null;
1610
379
  }
1611
- return params => {
380
+ return value => {
1612
381
  if (filterItem.value.length === 0) {
1613
382
  return true;
1614
383
  }
1615
- if (params.value == null) {
384
+ if (value == null) {
1616
385
  return true;
1617
386
  }
1618
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
387
+ const paramValues = Array.isArray(value) ? value : [value];
1619
388
  for (const filteredValue of filterItem.value) {
1620
389
  for (const paramValue of paramValues) {
1621
390
  if (String(paramValue).endsWith(filteredValue)) {
@@ -1637,11 +406,11 @@ const doesNotHaveAnyOf = {
1637
406
  if (!filterItem.field || !filterItem.value || !Array.isArray(filterItem.value) || filterItem.value.length === 0) {
1638
407
  return null;
1639
408
  }
1640
- return params => {
1641
- if (params.value == null) {
409
+ return value => {
410
+ if (value == null) {
1642
411
  return true;
1643
412
  }
1644
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
413
+ const cellValues = Array.isArray(value) ? value : [value];
1645
414
 
1646
415
  // Return true only if none of the filter values are in the cell values
1647
416
  return filterItem.value.every(filterVal => !cellValues.map(value => String(value)).includes(filterVal));
@@ -1661,14 +430,14 @@ const doesNotStartWithAnyOfOperator = {
1661
430
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1662
431
  return null;
1663
432
  }
1664
- return params => {
433
+ return value => {
1665
434
  if (filterItem.value.length === 0) {
1666
435
  return true;
1667
436
  }
1668
- if (params.value == null) {
437
+ if (value == null) {
1669
438
  return true;
1670
439
  }
1671
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
440
+ const paramValues = Array.isArray(value) ? value : [value];
1672
441
  for (const filteredValue of filterItem.value) {
1673
442
  for (const paramValue of paramValues) {
1674
443
  if (String(paramValue).startsWith(filteredValue)) {
@@ -1690,14 +459,14 @@ const endsWithAnyOfOperator = {
1690
459
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1691
460
  return null;
1692
461
  }
1693
- return params => {
462
+ return value => {
1694
463
  if (filterItem.value.length === 0) {
1695
464
  return true;
1696
465
  }
1697
- if (params.value == null) {
466
+ if (value == null) {
1698
467
  return false;
1699
468
  }
1700
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
469
+ const paramValues = Array.isArray(value) ? value : [value];
1701
470
  let match = false;
1702
471
  filterItem.value.forEach(filteredValue => {
1703
472
  paramValues.forEach(paramValue => {
@@ -1720,14 +489,14 @@ const hasAllOfOperator = {
1720
489
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1721
490
  return null;
1722
491
  }
1723
- return params => {
492
+ return value => {
1724
493
  if (filterItem.value.length === 0) {
1725
494
  return true;
1726
495
  }
1727
- if (params.value == null) {
496
+ if (value == null) {
1728
497
  return false;
1729
498
  }
1730
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
499
+ const cellValues = Array.isArray(value) ? value : [value];
1731
500
  const cellStrings = cellValues.map(value => String(value));
1732
501
  const filterItemValues = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
1733
502
  return filterItemValues.every(v => cellStrings.includes(v));
@@ -1747,14 +516,14 @@ const hasAnyOfOperator = {
1747
516
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1748
517
  return null;
1749
518
  }
1750
- return params => {
519
+ return value => {
1751
520
  if (filterItem.value.length === 0) {
1752
521
  return true;
1753
522
  }
1754
- if (params.value == null) {
523
+ if (value == null) {
1755
524
  return false;
1756
525
  }
1757
- const cellValues = Array.isArray(params.value) ? params.value : [params.value];
526
+ const cellValues = Array.isArray(value) ? value : [value];
1758
527
  const filterItemValues = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
1759
528
  return filterItemValues.some(v => cellValues.map(value => String(value)).includes(v));
1760
529
  };
@@ -1773,14 +542,14 @@ const isAnyOfOperator = {
1773
542
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1774
543
  return null;
1775
544
  }
1776
- return params => {
545
+ return value => {
1777
546
  if (filterItem.value.length === 0) {
1778
547
  return true;
1779
548
  }
1780
- if (params.value == null) {
549
+ if (value == null) {
1781
550
  return false;
1782
551
  }
1783
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
552
+ const paramValues = Array.isArray(value) ? value : [value];
1784
553
  for (const paramValue of paramValues) {
1785
554
  if (filterItem.value.includes(String(paramValue))) {
1786
555
  return true;
@@ -1803,14 +572,14 @@ const isNotAnyOfOperator = {
1803
572
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1804
573
  return null;
1805
574
  }
1806
- return params => {
575
+ return value => {
1807
576
  if (filterItem.value.length === 0) {
1808
577
  return true;
1809
578
  }
1810
- if (params.value == null) {
579
+ if (value == null) {
1811
580
  return true;
1812
581
  }
1813
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
582
+ const paramValues = Array.isArray(value) ? value : [value];
1814
583
  for (const paramValue of paramValues) {
1815
584
  if (filterItem.value.includes(String(paramValue))) {
1816
585
  return false;
@@ -1833,14 +602,14 @@ const startsWithAnyOfOperator = {
1833
602
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
1834
603
  return null;
1835
604
  }
1836
- return params => {
605
+ return value => {
1837
606
  if (filterItem.value.length === 0) {
1838
607
  return true;
1839
608
  }
1840
- if (params.value == null) {
609
+ if (value == null) {
1841
610
  return false;
1842
611
  }
1843
- const paramValues = Array.isArray(params.value) ? params.value : [params.value];
612
+ const paramValues = Array.isArray(value) ? value : [value];
1844
613
  let match = false;
1845
614
  filterItem.value.forEach(filteredValue => {
1846
615
  paramValues.forEach(paramValue => {
@@ -1867,15 +636,15 @@ const isEmptyOperator = {
1867
636
  value: 'isEmpty',
1868
637
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1869
638
  getApplyFilterFn: _filterItem => {
1870
- return params => {
1871
- if (params.value == null) {
639
+ return value => {
640
+ if (value == null) {
1872
641
  return true;
1873
642
  }
1874
- if (Array.isArray(params.value)) {
1875
- return params.value.length === 0;
643
+ if (Array.isArray(value)) {
644
+ return value.length === 0;
1876
645
  }
1877
- if (typeof params.value === 'string') {
1878
- return params.value.trim() === '';
646
+ if (typeof value === 'string') {
647
+ return value.trim() === '';
1879
648
  }
1880
649
  return false;
1881
650
  };
@@ -1887,15 +656,15 @@ const isNotEmptyOperator = {
1887
656
  value: 'isNotEmpty',
1888
657
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1889
658
  getApplyFilterFn: _filterItem => {
1890
- return params => {
1891
- if (params.value == null) {
659
+ return value => {
660
+ if (value == null) {
1892
661
  return false;
1893
662
  }
1894
- if (Array.isArray(params.value)) {
1895
- return params.value.length > 0;
663
+ if (Array.isArray(value)) {
664
+ return value.length > 0;
1896
665
  }
1897
- if (typeof params.value === 'string') {
1898
- return params.value.trim() !== '';
666
+ if (typeof value === 'string') {
667
+ return value.trim() !== '';
1899
668
  }
1900
669
  return true;
1901
670
  };
@@ -1934,14 +703,20 @@ const DIMENSION_MODEL_KEY = 'dimension';
1934
703
  const FILTER_SEARCH_KEY = 'searchModel';
1935
704
  const DENSITY_MODEL_KEY = 'densityModel';
1936
705
  const COLUMN_ORDER_MODEL_KEY = 'columnOrderModel';
1937
- 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
+ /** Storage category key for the pivot column/row/value configuration. Consumer interop — use with `buildStorageKey`. */
709
+ const PIVOT_MODEL_KEY = 'pivotModel';
710
+ /** Storage category key for whether pivoting is active. Consumer interop — use with `buildStorageKey`. */
711
+ const PIVOT_ACTIVE_KEY = 'pivotActive';
712
+ 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, PIVOT_ACTIVE_KEY];
1938
713
  /**
1939
714
  * Build the localStorage key for a specific grid state category.
1940
715
  * Consumers can use this to read or clear individual state entries directly.
1941
716
  *
1942
717
  * @example
1943
718
  * ```ts
1944
- * const key = buildStorageKey({ id: pathname, version: 2, category: 'filterModel' });
719
+ * const key = buildStorageKey({ id: pathname, version: 2, category: PIVOT_ACTIVE_KEY });
1945
720
  * localStorage.removeItem(key);
1946
721
  * ```
1947
722
  */
@@ -1991,6 +766,22 @@ const clearPreviousVersionStorage = (id, previousLocalStorageVersions) => {
1991
766
  id,
1992
767
  version,
1993
768
  category: COLUMN_ORDER_MODEL_KEY
769
+ }), buildStorageKey({
770
+ id,
771
+ version,
772
+ category: ROW_GROUPING_MODEL_KEY
773
+ }), buildStorageKey({
774
+ id,
775
+ version,
776
+ category: AGGREGATION_MODEL_KEY
777
+ }), buildStorageKey({
778
+ id,
779
+ version,
780
+ category: PIVOT_MODEL_KEY
781
+ }), buildStorageKey({
782
+ id,
783
+ version,
784
+ category: PIVOT_ACTIVE_KEY
1994
785
  })];
1995
786
  for (const keyToDelete of keysToDelete) {
1996
787
  try {
@@ -2055,7 +846,7 @@ const COMPRESSED_PREFIX = '~';
2055
846
  * Params listed first are compressed first (least valuable to read in the URL).
2056
847
  * The filter aggregate step uses the special key `_filters_aggregate`.
2057
848
  */
2058
- const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_quickFilterValues'];
849
+ const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_aggregation', '_rowGrouping', '_quickFilterValues', '_pivot'];
2059
850
 
2060
851
  /** Params that are always short and should never be compressed. */
2061
852
  const NEVER_COMPRESS = new Set(['_sortColumn', '_pagination', '_density', '_logicOperator', 'v', 'tab']);
@@ -2296,6 +1087,13 @@ const convertToDisplayFormat = search => {
2296
1087
  const cleanSearch = search.startsWith('?') ? search.slice(1) : search;
2297
1088
  const params = cleanSearch.split('&');
2298
1089
  const converted = params.map(param => {
1090
+ const eqIndex = param.indexOf('=');
1091
+ if (eqIndex !== -1) {
1092
+ const value = param.slice(eqIndex + 1);
1093
+ // Skip conversion for compressed values — already URL-safe
1094
+ if (isCompressed(value)) return param;
1095
+ }
1096
+
2299
1097
  // Handle _sortColumn=[field,direction]
2300
1098
  if (param.startsWith('_sortColumn=')) {
2301
1099
  const value = param.slice('_sortColumn='.length);
@@ -2349,7 +1147,6 @@ const convertToDisplayFormat = search => {
2349
1147
  // Handle _columnOrder=[a,b,c]
2350
1148
  if (param.startsWith('_columnOrder=')) {
2351
1149
  const value = param.slice('_columnOrder='.length);
2352
- if (value.startsWith('~')) return param; // compressed — skip
2353
1150
  if (value.startsWith('[') && value.endsWith(']')) {
2354
1151
  const inner = value.slice(1, -1);
2355
1152
  return `_columnOrder=${inner}`;
@@ -2357,6 +1154,21 @@ const convertToDisplayFormat = search => {
2357
1154
  return param;
2358
1155
  }
2359
1156
 
1157
+ // Handle _rowGrouping=[a,b,c]
1158
+ if (param.startsWith('_rowGrouping=')) {
1159
+ const value = param.slice('_rowGrouping='.length);
1160
+ if (value.startsWith('[') && value.endsWith(']')) {
1161
+ const inner = value.slice(1, -1);
1162
+ return `_rowGrouping=${inner}`;
1163
+ }
1164
+ return param;
1165
+ }
1166
+
1167
+ // _aggregation and _pivot do not use bracket notation — pass through
1168
+ if (param.startsWith('_aggregation=') || param.startsWith('_pivot=')) {
1169
+ return param;
1170
+ }
1171
+
2360
1172
  // Handle _field[operator,type]=value or _field[operator,type]=list[a,b,c]
2361
1173
  const bracketMatch = param.match(/^_([^[]+)\[([^\]]+)\]=(.*)$/);
2362
1174
  if (bracketMatch) {
@@ -2396,6 +1208,13 @@ const convertFromDisplayFormat = (search, columns) => {
2396
1208
  const cleanSearch = search.startsWith('?') ? search.slice(1) : search;
2397
1209
  const params = cleanSearch.split('&');
2398
1210
  const converted = params.map(param => {
1211
+ const eqIndex = param.indexOf('=');
1212
+ if (eqIndex !== -1) {
1213
+ const value = param.slice(eqIndex + 1);
1214
+ // Skip conversion for compressed values — already URL-safe
1215
+ if (isCompressed(value)) return param;
1216
+ }
1217
+
2399
1218
  // Handle _sortColumn=field.direction or _sortColumn=
2400
1219
  if (param.startsWith('_sortColumn=')) {
2401
1220
  const value = param.slice('_sortColumn='.length);
@@ -2448,7 +1267,7 @@ const convertFromDisplayFormat = (search, columns) => {
2448
1267
  if (param.startsWith('_columnVisibility=')) {
2449
1268
  const value = param.slice('_columnVisibility='.length);
2450
1269
  // If it already has brackets, leave it alone
2451
- if (value.startsWith('[') || value.startsWith('~')) {
1270
+ if (value.startsWith('[')) {
2452
1271
  return param;
2453
1272
  }
2454
1273
  return `_columnVisibility=[${value}]`;
@@ -2457,13 +1276,26 @@ const convertFromDisplayFormat = (search, columns) => {
2457
1276
  // Handle _columnOrder=a,b,c
2458
1277
  if (param.startsWith('_columnOrder=')) {
2459
1278
  const value = param.slice('_columnOrder='.length);
2460
- // If it already has brackets or is compressed, leave it alone
2461
- if (value.startsWith('[') || value.startsWith('~')) {
1279
+ if (value.startsWith('[')) {
2462
1280
  return param;
2463
1281
  }
2464
1282
  return `_columnOrder=[${value}]`;
2465
1283
  }
2466
1284
 
1285
+ // Handle _rowGrouping=a,b,c
1286
+ if (param.startsWith('_rowGrouping=')) {
1287
+ const value = param.slice('_rowGrouping='.length);
1288
+ if (value.startsWith('[')) {
1289
+ return param;
1290
+ }
1291
+ return `_rowGrouping=[${value}]`;
1292
+ }
1293
+
1294
+ // _aggregation, _pivot, _filters — pass through (no bracket conversion needed)
1295
+ if (param.startsWith('_aggregation=') || param.startsWith('_pivot=') || param.startsWith('_filters=')) {
1296
+ return param;
1297
+ }
1298
+
2467
1299
  // Handle field.operator=value (dot notation for filters)
2468
1300
  const dotMatch = param.match(/^([^.]+)\.([a-zA-Z_]+)=(.*)$/);
2469
1301
  if (dotMatch) {
@@ -2506,9 +1338,10 @@ const getDecodedSearchFromUrl = (search, columns) => {
2506
1338
  const hasPaginationDotNotation = /_pagination=[^&[]+\.[^&]+/.test(searchWithoutLeadingQuestion);
2507
1339
  const hasPinnedWithoutBrackets = /(_pinnedColumnsLeft|_pinnedColumnsRight)=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2508
1340
  const hasVisibilityWithoutBrackets = /_columnVisibility=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2509
- const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[~]*(&|$)/.test(searchWithoutLeadingQuestion);
1341
+ const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1342
+ const hasRowGroupingWithoutBrackets = /_rowGrouping=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2510
1343
  const hasBracketNotation = /\[.*\]=/.test(searchWithoutLeadingQuestion);
2511
- const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets) && !hasBracketNotation;
1344
+ const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets || hasRowGroupingWithoutBrackets) && !hasBracketNotation;
2512
1345
  if (isDisplayFormat) {
2513
1346
  return '?' + convertFromDisplayFormat(searchWithoutLeadingQuestion, columns);
2514
1347
  }
@@ -2669,7 +1502,7 @@ const getFilterModelFromString = (searchString, columns) => {
2669
1502
  let quickFilterValues = [];
2670
1503
  const searchParams = new URLSearchParams();
2671
1504
  for (const [key, value] of new URLSearchParams(searchString)) {
2672
- if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_density', '_filters'].includes(key)) {
1505
+ if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_rowGrouping', '_aggregation', '_pivot', '_density', '_filters'].includes(key)) {
2673
1506
  searchParams.set(key, value);
2674
1507
  }
2675
1508
  if (key === '_logicOperator') {
@@ -3134,9 +1967,10 @@ const getSearchParamsFromDensity = density => {
3134
1967
  searchParams.set('_density', density);
3135
1968
  return searchParams;
3136
1969
  };
3137
- const getDensityModel = (search, localStorageDensity, setLocalStorageDensity, _initialState, isNewVersion) => {
3138
- // MUI v6 GridInitialStatePro does not include density default to 'compact'
3139
- const defaultValue = 'compact';
1970
+ const getDensityModel = (search, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion) => {
1971
+ // Default density: honour initialState.density if valid, otherwise fall back to 'compact'
1972
+ const initialDensity = initialState === null || initialState === void 0 ? void 0 : initialState.density;
1973
+ const defaultValue = initialDensity && VALID_DENSITIES.includes(initialDensity) ? initialDensity : 'compact';
3140
1974
 
3141
1975
  // Persist initialState-derived density to localStorage so all three sources stay in sync
3142
1976
  const persistDefaultDensity = () => {
@@ -3217,7 +2051,275 @@ const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorag
3217
2051
  persistDefault();
3218
2052
  return defaultValue;
3219
2053
  };
3220
- const getFinalSearch = _ref => {
2054
+
2055
+ /** ROW GROUPING */
2056
+
2057
+ const getRowGroupingFromString = searchString => {
2058
+ if (!searchString) return 'invalid';
2059
+ const searchParams = new URLSearchParams(searchString);
2060
+ const value = searchParams.get('_rowGrouping');
2061
+ if (value === '' || value === null || value === '[]') return 'invalid';
2062
+ const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2063
+ if (!inner) return 'invalid';
2064
+ return inner.split(',').filter(Boolean);
2065
+ };
2066
+ const getSearchParamsFromRowGrouping = rowGrouping => {
2067
+ const searchParams = new URLSearchParams();
2068
+ if (rowGrouping.length > 0) {
2069
+ searchParams.set('_rowGrouping', `[${rowGrouping.join(',')}]`);
2070
+ }
2071
+ return searchParams;
2072
+ };
2073
+ const getRowGroupingModel = (search, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion) => {
2074
+ var _initialState$rowGrou, _initialState$rowGrou2;
2075
+ 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 : [];
2076
+ const persistDefault = () => {
2077
+ const searchFromDefault = getSearchParamsFromRowGrouping(defaultValue);
2078
+ const searchString = urlSearchParamsToString(searchFromDefault);
2079
+ if (searchString !== localStorageRowGrouping) {
2080
+ setLocalStorageRowGrouping(searchString);
2081
+ }
2082
+ };
2083
+ if (isNewVersion) {
2084
+ persistDefault();
2085
+ return defaultValue;
2086
+ }
2087
+ const fromUrl = getRowGroupingFromString(search);
2088
+ if (fromUrl !== 'invalid') {
2089
+ const searchFromModel = getSearchParamsFromRowGrouping(fromUrl);
2090
+ const searchString = urlSearchParamsToString(searchFromModel);
2091
+ if (searchString !== localStorageRowGrouping) {
2092
+ setLocalStorageRowGrouping(searchString);
2093
+ }
2094
+ return fromUrl;
2095
+ }
2096
+ const fromLocalStorage = getRowGroupingFromString(localStorageRowGrouping);
2097
+ if (fromLocalStorage !== 'invalid') {
2098
+ return fromLocalStorage;
2099
+ }
2100
+ persistDefault();
2101
+ return defaultValue;
2102
+ };
2103
+
2104
+ /** AGGREGATION */
2105
+
2106
+ const getAggregationFromString = searchString => {
2107
+ if (!searchString) return 'invalid';
2108
+ const searchParams = new URLSearchParams(searchString);
2109
+ const value = searchParams.get('_aggregation');
2110
+ if (value === '' || value === null) return 'invalid';
2111
+
2112
+ // Format: field1.sum,field2.avg or [field1.sum,field2.avg]
2113
+ const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2114
+ if (!inner) return 'invalid';
2115
+ const model = {};
2116
+ for (const entry of inner.split(',')) {
2117
+ const dotIndex = entry.lastIndexOf('.');
2118
+ if (dotIndex <= 0) return 'invalid';
2119
+ const field = entry.slice(0, dotIndex);
2120
+ const aggFunc = entry.slice(dotIndex + 1);
2121
+ if (!field || !aggFunc) return 'invalid';
2122
+ model[field] = aggFunc;
2123
+ }
2124
+ return Object.keys(model).length > 0 ? model : 'invalid';
2125
+ };
2126
+ const getSearchParamsFromAggregation = aggregation => {
2127
+ const searchParams = new URLSearchParams();
2128
+ const entries = Object.entries(aggregation);
2129
+ if (entries.length > 0) {
2130
+ const value = entries.map(_ref => {
2131
+ let [field, aggFunc] = _ref;
2132
+ return `${field}.${aggFunc}`;
2133
+ }).join(',');
2134
+ searchParams.set('_aggregation', value);
2135
+ }
2136
+ return searchParams;
2137
+ };
2138
+ const getAggregationModel = (search, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion) => {
2139
+ var _initialState$aggrega, _initialState$aggrega2;
2140
+ 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 : {};
2141
+ const persistDefault = () => {
2142
+ const searchFromDefault = getSearchParamsFromAggregation(defaultValue);
2143
+ const searchString = urlSearchParamsToString(searchFromDefault);
2144
+ if (searchString !== localStorageAggregation) {
2145
+ setLocalStorageAggregation(searchString);
2146
+ }
2147
+ };
2148
+ if (isNewVersion) {
2149
+ persistDefault();
2150
+ return defaultValue;
2151
+ }
2152
+ const fromUrl = getAggregationFromString(search);
2153
+ if (fromUrl !== 'invalid') {
2154
+ const searchFromModel = getSearchParamsFromAggregation(fromUrl);
2155
+ const searchString = urlSearchParamsToString(searchFromModel);
2156
+ if (searchString !== localStorageAggregation) {
2157
+ setLocalStorageAggregation(searchString);
2158
+ }
2159
+ return fromUrl;
2160
+ }
2161
+ const fromLocalStorage = getAggregationFromString(localStorageAggregation);
2162
+ if (fromLocalStorage !== 'invalid') {
2163
+ return fromLocalStorage;
2164
+ }
2165
+ persistDefault();
2166
+ return defaultValue;
2167
+ };
2168
+
2169
+ /** PIVOT */
2170
+
2171
+ /** Convert MUI's GridPivotModel → our simplified PivotModel */
2172
+ const fromGridPivotModel = model => ({
2173
+ columns: model.columns.map(c => c.field),
2174
+ rows: model.rows.map(r => r.field),
2175
+ values: model.values.map(_ref2 => {
2176
+ let {
2177
+ field,
2178
+ aggFunc
2179
+ } = _ref2;
2180
+ return {
2181
+ field,
2182
+ aggFunc
2183
+ };
2184
+ })
2185
+ });
2186
+
2187
+ /**
2188
+ * Pivot format: `cols:f1,f2;rows:f3;vals:f4.sum,f5.avg`
2189
+ */
2190
+ const getPivotFromString = searchString => {
2191
+ if (!searchString) return 'invalid';
2192
+ const searchParams = new URLSearchParams(searchString);
2193
+ const value = searchParams.get('_pivot');
2194
+ if (value === '' || value === null) return 'invalid';
2195
+ const model = {
2196
+ columns: [],
2197
+ rows: [],
2198
+ values: []
2199
+ };
2200
+ for (const segment of value.split(';')) {
2201
+ const colonIndex = segment.indexOf(':');
2202
+ if (colonIndex <= 0) return 'invalid';
2203
+ const key = segment.slice(0, colonIndex);
2204
+ const content = segment.slice(colonIndex + 1);
2205
+ if (key === 'cols') {
2206
+ model.columns = content ? content.split(',').filter(Boolean) : [];
2207
+ } else if (key === 'rows') {
2208
+ model.rows = content ? content.split(',').filter(Boolean) : [];
2209
+ } else if (key === 'vals') {
2210
+ if (!content) continue;
2211
+ for (const entry of content.split(',')) {
2212
+ const dotIndex = entry.lastIndexOf('.');
2213
+ if (dotIndex <= 0) return 'invalid';
2214
+ model.values.push({
2215
+ field: entry.slice(0, dotIndex),
2216
+ aggFunc: entry.slice(dotIndex + 1)
2217
+ });
2218
+ }
2219
+ }
2220
+ }
2221
+
2222
+ // At least one section must have content
2223
+ if (model.columns.length === 0 && model.rows.length === 0 && model.values.length === 0) {
2224
+ return 'invalid';
2225
+ }
2226
+ return model;
2227
+ };
2228
+ const getSearchParamsFromPivot = pivot => {
2229
+ const searchParams = new URLSearchParams();
2230
+ const hasContent = pivot.columns.length > 0 || pivot.rows.length > 0 || pivot.values.length > 0;
2231
+ if (hasContent) {
2232
+ const parts = [];
2233
+ parts.push(`cols:${pivot.columns.join(',')}`);
2234
+ parts.push(`rows:${pivot.rows.join(',')}`);
2235
+ if (pivot.values.length > 0) {
2236
+ parts.push(`vals:${pivot.values.map(v => `${v.field}.${v.aggFunc}`).join(',')}`);
2237
+ }
2238
+ searchParams.set('_pivot', parts.join(';'));
2239
+ }
2240
+ return searchParams;
2241
+ };
2242
+ const getPivotModel = (search, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion) => {
2243
+ var _initialState$pivotin;
2244
+ const defaultValue = initialState !== null && initialState !== void 0 && (_initialState$pivotin = initialState.pivoting) !== null && _initialState$pivotin !== void 0 && _initialState$pivotin.model ? fromGridPivotModel(initialState.pivoting.model) : {
2245
+ columns: [],
2246
+ rows: [],
2247
+ values: []
2248
+ };
2249
+ const persistDefault = () => {
2250
+ const searchFromDefault = getSearchParamsFromPivot(defaultValue);
2251
+ const searchString = urlSearchParamsToString(searchFromDefault);
2252
+ if (searchString !== localStoragePivot) {
2253
+ setLocalStoragePivot(searchString);
2254
+ }
2255
+ };
2256
+ if (isNewVersion) {
2257
+ persistDefault();
2258
+ return defaultValue;
2259
+ }
2260
+ const fromUrl = getPivotFromString(search);
2261
+ if (fromUrl !== 'invalid') {
2262
+ const searchFromModel = getSearchParamsFromPivot(fromUrl);
2263
+ const searchString = urlSearchParamsToString(searchFromModel);
2264
+ if (searchString !== localStoragePivot) {
2265
+ setLocalStoragePivot(searchString);
2266
+ }
2267
+ return fromUrl;
2268
+ }
2269
+ const fromLocalStorage = getPivotFromString(localStoragePivot);
2270
+ if (fromLocalStorage !== 'invalid') {
2271
+ return fromLocalStorage;
2272
+ }
2273
+ persistDefault();
2274
+ return defaultValue;
2275
+ };
2276
+
2277
+ /** PIVOT ACTIVE */
2278
+
2279
+ const getPivotActiveFromString = searchString => {
2280
+ if (!searchString) return 'invalid';
2281
+ const searchParams = new URLSearchParams(searchString);
2282
+ const value = searchParams.get('_pivotActive');
2283
+ if (value === 'true') return true;
2284
+ if (value === 'false') return false;
2285
+ return 'invalid';
2286
+ };
2287
+ const getSearchParamsFromPivotActive = active => {
2288
+ const searchParams = new URLSearchParams();
2289
+ searchParams.set('_pivotActive', String(active));
2290
+ return searchParams;
2291
+ };
2292
+ const getPivotActive = (search, localStoragePivotActive, setLocalStoragePivotActive, initialState, isNewVersion) => {
2293
+ var _initialState$pivotin2, _initialState$pivotin3;
2294
+ const defaultValue = (_initialState$pivotin2 = initialState === null || initialState === void 0 ? void 0 : (_initialState$pivotin3 = initialState.pivoting) === null || _initialState$pivotin3 === void 0 ? void 0 : _initialState$pivotin3.enabled) !== null && _initialState$pivotin2 !== void 0 ? _initialState$pivotin2 : false;
2295
+ const persistDefault = () => {
2296
+ const searchFromDefault = getSearchParamsFromPivotActive(defaultValue);
2297
+ const searchString = urlSearchParamsToString(searchFromDefault);
2298
+ if (searchString !== localStoragePivotActive) {
2299
+ setLocalStoragePivotActive(searchString);
2300
+ }
2301
+ };
2302
+ if (isNewVersion) {
2303
+ persistDefault();
2304
+ return defaultValue;
2305
+ }
2306
+ const fromUrl = getPivotActiveFromString(search);
2307
+ if (fromUrl !== 'invalid') {
2308
+ const searchFromModel = getSearchParamsFromPivotActive(fromUrl);
2309
+ const searchString = urlSearchParamsToString(searchFromModel);
2310
+ if (searchString !== localStoragePivotActive) {
2311
+ setLocalStoragePivotActive(searchString);
2312
+ }
2313
+ return fromUrl;
2314
+ }
2315
+ const fromLocalStorage = getPivotActiveFromString(localStoragePivotActive);
2316
+ if (fromLocalStorage !== 'invalid') {
2317
+ return fromLocalStorage;
2318
+ }
2319
+ persistDefault();
2320
+ return defaultValue;
2321
+ };
2322
+ const getFinalSearch = _ref3 => {
3221
2323
  let {
3222
2324
  search,
3223
2325
  localStorageVersion,
@@ -3229,8 +2331,12 @@ const getFinalSearch = _ref => {
3229
2331
  density,
3230
2332
  columnOrderModel,
3231
2333
  defaultColumnOrder,
2334
+ rowGroupingModel,
2335
+ aggregationModel,
2336
+ pivotModel,
2337
+ pivotActive,
3232
2338
  columns
3233
- } = _ref;
2339
+ } = _ref3;
3234
2340
  const filterModelSearch = getSearchParamsFromFilterModel(filterModel);
3235
2341
  const sortModelSearch = getSearchParamsFromSorting(sortModel);
3236
2342
  const paginationModelSearch = getSearchParamsFromPagination(paginationModel);
@@ -3239,6 +2345,10 @@ const getFinalSearch = _ref => {
3239
2345
  const densitySearch = getSearchParamsFromDensity(density);
3240
2346
  // Only include _columnOrder in URL when it differs from the default
3241
2347
  const columnOrderSearch = columnOrderModel.length !== defaultColumnOrder.length || columnOrderModel.some((field, i) => field !== defaultColumnOrder[i]) ? getSearchParamsFromColumnOrder(columnOrderModel) : new URLSearchParams();
2348
+ const rowGroupingSearch = getSearchParamsFromRowGrouping(rowGroupingModel);
2349
+ const aggregationSearch = getSearchParamsFromAggregation(aggregationModel);
2350
+ const pivotSearch = getSearchParamsFromPivot(pivotModel);
2351
+ const pivotActiveSearch = getSearchParamsFromPivotActive(pivotActive);
3242
2352
  const tabSearch = getSearchParamsFromTab(search);
3243
2353
  const searchParams = new URLSearchParams();
3244
2354
  for (const [key, value] of new URLSearchParams(search)) {
@@ -3253,7 +2363,7 @@ const getFinalSearch = _ref => {
3253
2363
  // Encode array as JSON string to preserve all values in one param
3254
2364
  searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
3255
2365
  }
3256
- return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch]);
2366
+ return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch, ...rowGroupingSearch, ...aggregationSearch, ...pivotSearch, ...pivotActiveSearch]);
3257
2367
  };
3258
2368
  /** Return the state of the table given the URL and the local storage state */
3259
2369
  const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage) => {
@@ -3278,7 +2388,15 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3278
2388
  localStorageDensity,
3279
2389
  setLocalStorageDensity,
3280
2390
  localStorageColumnOrder,
3281
- setLocalStorageColumnOrder
2391
+ setLocalStorageColumnOrder,
2392
+ localStorageRowGrouping,
2393
+ setLocalStorageRowGrouping,
2394
+ localStorageAggregation,
2395
+ setLocalStorageAggregation,
2396
+ localStoragePivot,
2397
+ setLocalStoragePivot,
2398
+ localStoragePivotActive,
2399
+ setLocalStoragePivotActive
3282
2400
  } = localStorage;
3283
2401
  const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion);
3284
2402
  const sortModel = getSortModel(decodedSearch, columns, localStorageSorting, setLocalStorageSorting, initialState, isNewVersion);
@@ -3287,6 +2405,10 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3287
2405
  const pinnedColumnsModel = getPinnedColumns(decodedSearch, columns, localStoragePinnedColumns, setLocalStoragePinnedColumns, initialState, isNewVersion);
3288
2406
  const density = getDensityModel(decodedSearch, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion);
3289
2407
  const columnOrderModel = getColumnOrder(decodedSearch, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion);
2408
+ const rowGroupingModel = getRowGroupingModel(decodedSearch, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion);
2409
+ const aggregationModel = getAggregationModel(decodedSearch, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion);
2410
+ const pivotModel = getPivotModel(decodedSearch, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion);
2411
+ const pivotActive = getPivotActive(decodedSearch, localStoragePivotActive, setLocalStoragePivotActive, initialState, isNewVersion);
3290
2412
  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);
3291
2413
  const finalSearch = getFinalSearch({
3292
2414
  localStorageVersion,
@@ -3299,6 +2421,10 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3299
2421
  density,
3300
2422
  columnOrderModel,
3301
2423
  defaultColumnOrder,
2424
+ rowGroupingModel,
2425
+ aggregationModel,
2426
+ pivotModel,
2427
+ pivotActive,
3302
2428
  columns
3303
2429
  });
3304
2430
  const internalSearchString = urlSearchParamsToString(finalSearch);
@@ -3319,10 +2445,14 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3319
2445
  pinnedColumnsModel,
3320
2446
  density,
3321
2447
  columnOrderModel,
2448
+ rowGroupingModel,
2449
+ aggregationModel,
2450
+ pivotModel,
2451
+ pivotActive,
3322
2452
  pendingSearch
3323
2453
  };
3324
2454
  };
3325
- const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns) => {
2455
+ const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns) => {
3326
2456
  let {
3327
2457
  filterModel,
3328
2458
  sortModel,
@@ -3331,8 +2461,12 @@ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns)
3331
2461
  pinnedColumnsModel,
3332
2462
  density,
3333
2463
  columnOrderModel,
3334
- defaultColumnOrder
3335
- } = _ref2;
2464
+ defaultColumnOrder,
2465
+ rowGroupingModel,
2466
+ aggregationModel,
2467
+ pivotModel,
2468
+ pivotActive
2469
+ } = _ref4;
3336
2470
  // Convert from display format to internal format if needed
3337
2471
  const decodedSearch = getDecodedSearchFromUrl(search, columns);
3338
2472
  const newSearch = getFinalSearch({
@@ -3346,6 +2480,10 @@ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns)
3346
2480
  density,
3347
2481
  columnOrderModel,
3348
2482
  defaultColumnOrder,
2483
+ rowGroupingModel,
2484
+ aggregationModel,
2485
+ pivotModel,
2486
+ pivotActive,
3349
2487
  columns
3350
2488
  });
3351
2489
  const internalSearchString = urlSearchParamsToString(newSearch);
@@ -3533,6 +2671,26 @@ const useTableStates = (id, version) => {
3533
2671
  version,
3534
2672
  category: COLUMN_ORDER_MODEL_KEY
3535
2673
  }));
2674
+ const [rowGroupingModel, setRowGroupingModel] = useFetchState('', buildStorageKey({
2675
+ id,
2676
+ version,
2677
+ category: ROW_GROUPING_MODEL_KEY
2678
+ }));
2679
+ const [aggregationModel, setAggregationModel] = useFetchState('', buildStorageKey({
2680
+ id,
2681
+ version,
2682
+ category: AGGREGATION_MODEL_KEY
2683
+ }));
2684
+ const [pivotModel, setPivotModel] = useFetchState('', buildStorageKey({
2685
+ id,
2686
+ version,
2687
+ category: PIVOT_MODEL_KEY
2688
+ }));
2689
+ const [pivotActive, setPivotActive] = useFetchState('', buildStorageKey({
2690
+ id,
2691
+ version,
2692
+ category: PIVOT_ACTIVE_KEY
2693
+ }));
3536
2694
  return {
3537
2695
  paginationModel,
3538
2696
  setPaginationModel,
@@ -3549,10 +2707,55 @@ const useTableStates = (id, version) => {
3549
2707
  densityModel,
3550
2708
  setDensityModel,
3551
2709
  columnOrderModel,
3552
- setColumnOrderModel
2710
+ setColumnOrderModel,
2711
+ rowGroupingModel,
2712
+ setRowGroupingModel,
2713
+ aggregationModel,
2714
+ setAggregationModel,
2715
+ pivotModel,
2716
+ setPivotModel,
2717
+ pivotActive,
2718
+ setPivotActive
3553
2719
  };
3554
2720
  };
3555
2721
 
2722
+ /** Convert our simplified PivotModel → MUI's GridPivotModel */
2723
+ const toGridPivotModel = model => ({
2724
+ columns: model.columns.map(field => ({
2725
+ field
2726
+ })),
2727
+ rows: model.rows.map(field => ({
2728
+ field
2729
+ })),
2730
+ values: model.values.map(_ref => {
2731
+ let {
2732
+ field,
2733
+ aggFunc
2734
+ } = _ref;
2735
+ return {
2736
+ field,
2737
+ aggFunc
2738
+ };
2739
+ })
2740
+ });
2741
+
2742
+ /**
2743
+ * Deep-equal comparison for plain objects / arrays.
2744
+ * Used to stabilise parsed model references so that MUI v8 does not
2745
+ * reset pagination on every render.
2746
+ */
2747
+ function isDeepEqual(a, b) {
2748
+ if (a === b) return true;
2749
+ if (a == null || b == null) return false;
2750
+ if (typeof a !== typeof b) return false;
2751
+ if (typeof a !== 'object') return false;
2752
+ const aObj = a;
2753
+ const bObj = b;
2754
+ const aKeys = Object.keys(aObj);
2755
+ const bKeys = Object.keys(bObj);
2756
+ if (aKeys.length !== bKeys.length) return false;
2757
+ return aKeys.every(key => isDeepEqual(aObj[key], bObj[key]));
2758
+ }
3556
2759
  const useStatefulTable = props => {
3557
2760
  var _initialState$columns, _initialState$columns2;
3558
2761
  const {
@@ -3565,6 +2768,9 @@ const useStatefulTable = props => {
3565
2768
  onPaginationModelChange: propsOnPaginationModelChange,
3566
2769
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3567
2770
  onSortModelChange: propsOnSortModelChange,
2771
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
2772
+ onAggregationModelChange: propsOnAggregationModelChange,
2773
+ onPivotModelChange: propsOnPivotModelChange,
3568
2774
  useRouter,
3569
2775
  localStorageVersion = 1,
3570
2776
  previousLocalStorageVersions = []
@@ -3593,16 +2799,24 @@ const useStatefulTable = props => {
3593
2799
  densityModel,
3594
2800
  setDensityModel,
3595
2801
  columnOrderModel: localStorageColumnOrder,
3596
- setColumnOrderModel: setLocalStorageColumnOrder
2802
+ setColumnOrderModel: setLocalStorageColumnOrder,
2803
+ rowGroupingModel: localStorageRowGrouping,
2804
+ setRowGroupingModel: setLocalStorageRowGrouping,
2805
+ aggregationModel: localStorageAggregation,
2806
+ setAggregationModel: setLocalStorageAggregation,
2807
+ pivotModel: localStoragePivot,
2808
+ setPivotModel: setLocalStoragePivot,
2809
+ pivotActive: localStoragePivotActive,
2810
+ setPivotActive: setLocalStoragePivotActive
3597
2811
  } = useTableStates(id, localStorageVersion);
3598
2812
 
3599
2813
  // clearing up old version keys, triggering only on first render
3600
2814
  useEffect(() => clearPreviousVersionStorage(id, previousLocalStorageVersions), [id, previousLocalStorageVersions]);
3601
- const onColumnDimensionChange = useCallback(_ref => {
2815
+ const onColumnDimensionChange = useCallback(_ref2 => {
3602
2816
  let {
3603
2817
  newWidth,
3604
2818
  field
3605
- } = _ref;
2819
+ } = _ref2;
3606
2820
  setDimensionModel(_objectSpread2(_objectSpread2({}, dimensionModel), {}, {
3607
2821
  [field]: newWidth
3608
2822
  }));
@@ -3615,6 +2829,10 @@ const useStatefulTable = props => {
3615
2829
  pinnedColumnsModel,
3616
2830
  density: densityParsed,
3617
2831
  columnOrderModel: columnOrderParsed,
2832
+ rowGroupingModel: rowGroupingParsed,
2833
+ aggregationModel: aggregationParsed,
2834
+ pivotModel: pivotParsed,
2835
+ pivotActive: pivotActiveParsed,
3618
2836
  pendingSearch
3619
2837
  } = getModelsParsedOrUpdateLocalStorage(search || '', localStorageVersion, propsColumns, initialState, {
3620
2838
  localStorageFilters,
@@ -3630,7 +2848,15 @@ const useStatefulTable = props => {
3630
2848
  localStorageDensity: densityModel,
3631
2849
  setLocalStorageDensity: setDensityModel,
3632
2850
  localStorageColumnOrder,
3633
- setLocalStorageColumnOrder
2851
+ setLocalStorageColumnOrder,
2852
+ localStorageRowGrouping,
2853
+ setLocalStorageRowGrouping,
2854
+ localStorageAggregation,
2855
+ setLocalStorageAggregation,
2856
+ localStoragePivot,
2857
+ setLocalStoragePivot,
2858
+ localStoragePivotActive: localStoragePivotActive,
2859
+ setLocalStoragePivotActive: setLocalStoragePivotActive
3634
2860
  });
3635
2861
 
3636
2862
  // Sync URL in an effect rather than during render to comply with React rules
@@ -3639,6 +2865,45 @@ const useStatefulTable = props => {
3639
2865
  historyReplace(pendingSearch);
3640
2866
  }
3641
2867
  }, [pendingSearch, historyReplace]);
2868
+
2869
+ // Stabilise parsed model references to prevent MUI v8 from resetting
2870
+ // pagination on every render due to new object identity.
2871
+ const filterParsedRef = useRef(filterParsed);
2872
+ if (!isDeepEqual(filterParsedRef.current, filterParsed)) {
2873
+ filterParsedRef.current = filterParsed;
2874
+ }
2875
+ const sortModelParsedRef = useRef(sortModelParsed);
2876
+ if (!isDeepEqual(sortModelParsedRef.current, sortModelParsed)) {
2877
+ sortModelParsedRef.current = sortModelParsed;
2878
+ }
2879
+ const paginationModelParsedRef = useRef(paginationModelParsed);
2880
+ if (!isDeepEqual(paginationModelParsedRef.current, paginationModelParsed)) {
2881
+ paginationModelParsedRef.current = paginationModelParsed;
2882
+ }
2883
+ const visibilityModelRef = useRef(visibilityModel);
2884
+ if (!isDeepEqual(visibilityModelRef.current, visibilityModel)) {
2885
+ visibilityModelRef.current = visibilityModel;
2886
+ }
2887
+ const pinnedColumnsModelRef = useRef(pinnedColumnsModel);
2888
+ if (!isDeepEqual(pinnedColumnsModelRef.current, pinnedColumnsModel)) {
2889
+ pinnedColumnsModelRef.current = pinnedColumnsModel;
2890
+ }
2891
+ const columnOrderParsedRef = useRef(columnOrderParsed);
2892
+ if (!isDeepEqual(columnOrderParsedRef.current, columnOrderParsed)) {
2893
+ columnOrderParsedRef.current = columnOrderParsed;
2894
+ }
2895
+ const rowGroupingParsedRef = useRef(rowGroupingParsed);
2896
+ if (!isDeepEqual(rowGroupingParsedRef.current, rowGroupingParsed)) {
2897
+ rowGroupingParsedRef.current = rowGroupingParsed;
2898
+ }
2899
+ const aggregationParsedRef = useRef(aggregationParsed);
2900
+ if (!isDeepEqual(aggregationParsedRef.current, aggregationParsed)) {
2901
+ aggregationParsedRef.current = aggregationParsed;
2902
+ }
2903
+ const pivotParsedRef = useRef(pivotParsed);
2904
+ if (!isDeepEqual(pivotParsedRef.current, pivotParsed)) {
2905
+ pivotParsedRef.current = pivotParsed;
2906
+ }
3642
2907
  const columns = useMemo(() => propsColumns.map(column => {
3643
2908
  return _objectSpread2(_objectSpread2({}, column), {}, {
3644
2909
  width: dimensionModel[column.field] || column.width || 100
@@ -3647,56 +2912,61 @@ const useStatefulTable = props => {
3647
2912
  if (apiRef.current) {
3648
2913
  /** Add resetPage method to apiRef. */
3649
2914
  apiRef.current.resetPage = () => {
3650
- apiRef.current.setPage(0);
2915
+ var _apiRef$current;
2916
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPage(0);
3651
2917
  };
3652
2918
  }
3653
2919
  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);
3654
2920
 
3655
- // Helper to build the current DataGridModel for updateUrl calls
3656
- const buildModel = function () {
3657
- var _apiRef$current$state, _apiRef$current;
3658
- let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3659
- return _objectSpread2({
3660
- filterModel: filterParsed,
3661
- sortModel: sortModelParsed,
3662
- paginationModel: paginationModelParsed,
3663
- 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 : {},
3664
- pinnedColumnsModel: pinnedColumnsModel,
3665
- density: densityParsed,
3666
- columnOrderModel: columnOrderParsed,
3667
- defaultColumnOrder
3668
- }, overrides);
3669
- };
3670
-
3671
2921
  // Subscribe to density changes via stateChange event (MUI v6 has no densityChange event)
3672
2922
  useEffect(() => {
3673
2923
  const api = apiRef.current;
3674
2924
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3675
2925
  let prevDensity = densityParsed;
3676
2926
  const unsub = api.subscribeEvent('stateChange', () => {
3677
- const currentDensity = api.state.density.value;
2927
+ const currentDensity = api.state.density;
3678
2928
  if (currentDensity !== prevDensity) {
3679
2929
  prevDensity = currentDensity;
3680
- updateUrl(buildModel({
2930
+ updateUrl({
2931
+ filterModel: filterParsed,
2932
+ sortModel: sortModelParsed,
2933
+ paginationModel: paginationModelParsed,
3681
2934
  columnsModel: api.state.columns.columnVisibilityModel,
3682
- density: currentDensity
3683
- }), search, localStorageVersion, historyReplace, columns);
2935
+ pinnedColumnsModel: pinnedColumnsModel,
2936
+ density: currentDensity,
2937
+ columnOrderModel: columnOrderParsed,
2938
+ defaultColumnOrder,
2939
+ rowGroupingModel: rowGroupingParsed,
2940
+ aggregationModel: aggregationParsed,
2941
+ pivotModel: pivotParsed,
2942
+ pivotActive: pivotActiveParsed
2943
+ }, search, localStorageVersion, historyReplace, columns);
3684
2944
  }
3685
2945
  });
3686
2946
  return unsub;
3687
- }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, search, localStorageVersion, historyReplace, columns]);
2947
+ }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
3688
2948
 
3689
2949
  // Subscribe to column order changes via columnOrderChange (drag-drop) and columnIndexChange (programmatic setColumnIndex)
3690
2950
  useEffect(() => {
3691
2951
  const api = apiRef.current;
3692
2952
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3693
- const isDeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3694
2953
  const handleColumnOrderChange = () => {
3695
2954
  const orderedFields = api.state.columns.orderedFields;
3696
2955
  if (orderedFields && !isDeepEqual(orderedFields, columnOrderParsed)) {
3697
- updateUrl(buildModel({
3698
- columnOrderModel: orderedFields
3699
- }), search, localStorageVersion, historyReplace, columns);
2956
+ updateUrl({
2957
+ filterModel: filterParsed,
2958
+ sortModel: sortModelParsed,
2959
+ paginationModel: paginationModelParsed,
2960
+ columnsModel: api.state.columns.columnVisibilityModel,
2961
+ pinnedColumnsModel,
2962
+ density: densityParsed,
2963
+ columnOrderModel: orderedFields,
2964
+ defaultColumnOrder,
2965
+ rowGroupingModel: rowGroupingParsed,
2966
+ aggregationModel: aggregationParsed,
2967
+ pivotModel: pivotParsed,
2968
+ pivotActive: pivotActiveParsed
2969
+ }, search, localStorageVersion, historyReplace, columns);
3700
2970
  }
3701
2971
  };
3702
2972
  const unsub1 = api.subscribeEvent('columnOrderChange', handleColumnOrderChange);
@@ -3705,69 +2975,99 @@ const useStatefulTable = props => {
3705
2975
  unsub1();
3706
2976
  unsub2();
3707
2977
  };
3708
- }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, search, localStorageVersion, historyReplace, columns]);
2978
+ }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
2979
+
2980
+ // Helper to build the current DataGridModel for updateUrl calls
2981
+ const buildModel = function () {
2982
+ var _apiRef$current$state, _apiRef$current2;
2983
+ let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2984
+ return _objectSpread2({
2985
+ filterModel: filterParsed,
2986
+ sortModel: sortModelParsed,
2987
+ paginationModel: paginationModelParsed,
2988
+ 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 : {},
2989
+ pinnedColumnsModel: pinnedColumnsModel,
2990
+ density: densityParsed,
2991
+ columnOrderModel: columnOrderParsed,
2992
+ defaultColumnOrder,
2993
+ rowGroupingModel: rowGroupingParsed,
2994
+ aggregationModel: aggregationParsed,
2995
+ pivotModel: pivotParsed,
2996
+ pivotActive: pivotActiveParsed
2997
+ }, overrides);
2998
+ };
2999
+
3000
+ // Stable GridPivotModel identity — only recompute when the simplified value changes.
3001
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3002
+ const pivotModelMui = useMemo(() => toGridPivotModel(pivotParsed), [JSON.stringify(pivotParsed)]);
3709
3003
 
3710
3004
  // Track last emitted values for deep-equal guards to avoid feedback loops.
3005
+ // Initialised from the current parsed values; updated only when we actually fire.
3711
3006
  const lastEmittedFilterRef = useRef(filterParsed);
3712
3007
  const lastEmittedSortRef = useRef(sortModelParsed);
3713
3008
  const lastEmittedPaginationRef = useRef(paginationModelParsed);
3714
- const isModelDeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3009
+ const lastEmittedPivotRef = useRef(pivotParsed);
3715
3010
  return {
3716
3011
  apiRef,
3717
3012
  columns,
3718
3013
  density: densityParsed,
3719
- columnOrderModel: columnOrderParsed,
3014
+ columnOrderModel: columnOrderParsedRef.current,
3015
+ rowGroupingModel: rowGroupingParsedRef.current,
3016
+ aggregationModel: aggregationParsedRef.current,
3017
+ pivotModel: pivotModelMui,
3018
+ pivotActive: pivotActiveParsed,
3720
3019
  onFilterModelChange: (model, details) => {
3721
3020
  const filterModel = _objectSpread2(_objectSpread2({}, model), {}, {
3722
3021
  items: model.items.map(item => {
3723
- const column = apiRef.current.getColumn(item.field);
3724
- item.type = column.type || 'string';
3022
+ var _apiRef$current3;
3023
+ const column = (_apiRef$current3 = apiRef.current) === null || _apiRef$current3 === void 0 ? void 0 : _apiRef$current3.getColumn(item.field);
3024
+ item.type = (column === null || column === void 0 ? void 0 : column.type) || 'string';
3725
3025
  return item;
3726
3026
  }),
3727
3027
  quickFilterValues: model.quickFilterValues || []
3728
3028
  });
3729
- if (isModelDeepEqual(filterModel, lastEmittedFilterRef.current)) return;
3029
+ if (isDeepEqual(filterModel, lastEmittedFilterRef.current)) return;
3730
3030
  lastEmittedFilterRef.current = filterModel;
3731
- propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3732
3031
  updateUrl(buildModel({
3733
3032
  filterModel
3734
3033
  }), search, localStorageVersion, historyReplace, columns);
3034
+ propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3735
3035
  },
3736
- filterModel: filterParsed,
3036
+ filterModel: filterParsedRef.current,
3737
3037
  onSortModelChange: (model, details) => {
3738
- if (isModelDeepEqual(model, lastEmittedSortRef.current)) return;
3038
+ if (isDeepEqual(model, lastEmittedSortRef.current)) return;
3739
3039
  lastEmittedSortRef.current = model;
3740
- propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3741
3040
  updateUrl(buildModel({
3742
3041
  sortModel: model
3743
3042
  }), search, localStorageVersion, historyReplace, columns);
3043
+ propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3744
3044
  },
3745
- sortModel: sortModelParsed,
3045
+ sortModel: sortModelParsedRef.current,
3746
3046
  onPinnedColumnsChange: (pinnedColumns, details) => {
3747
- propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
3748
3047
  updateUrl(buildModel({
3749
3048
  pinnedColumnsModel: pinnedColumns
3750
3049
  }), search, localStorageVersion, historyReplace, columns);
3050
+ propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
3751
3051
  },
3752
- pinnedColumns: pinnedColumnsModel,
3753
- paginationModel: paginationModelParsed,
3052
+ pinnedColumns: pinnedColumnsModelRef.current,
3053
+ paginationModel: paginationModelParsedRef.current,
3754
3054
  onPaginationModelChange: (model, details) => {
3755
3055
  const paginationModel = _objectSpread2(_objectSpread2({}, model), {}, {
3756
3056
  direction: paginationModelParsed.page < model.page ? 'next' : 'back'
3757
3057
  });
3758
- if (isModelDeepEqual(paginationModel, lastEmittedPaginationRef.current)) return;
3058
+ if (isDeepEqual(paginationModel, lastEmittedPaginationRef.current)) return;
3759
3059
  lastEmittedPaginationRef.current = paginationModel;
3760
- propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3761
3060
  updateUrl(buildModel({
3762
3061
  paginationModel
3763
3062
  }), search, localStorageVersion, historyReplace, columns);
3063
+ propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3764
3064
  },
3765
- columnVisibilityModel: visibilityModel,
3065
+ columnVisibilityModel: visibilityModelRef.current,
3766
3066
  onColumnVisibilityModelChange: (columnsVisibilityModel, details) => {
3767
- propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
3768
3067
  updateUrl(buildModel({
3769
3068
  columnsModel: columnsVisibilityModel
3770
3069
  }), search, localStorageVersion, historyReplace, columns);
3070
+ propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
3771
3071
  },
3772
3072
  onColumnWidthChange: (params, event, details) => {
3773
3073
  propsOnColumnWidthChange === null || propsOnColumnWidthChange === void 0 ? void 0 : propsOnColumnWidthChange(params, event, details);
@@ -3775,11 +3075,38 @@ const useStatefulTable = props => {
3775
3075
  newWidth: params.width,
3776
3076
  field: params.colDef.field
3777
3077
  });
3078
+ },
3079
+ onRowGroupingModelChange: (model, details) => {
3080
+ updateUrl(buildModel({
3081
+ rowGroupingModel: model
3082
+ }), search, localStorageVersion, historyReplace, columns);
3083
+ propsOnRowGroupingModelChange === null || propsOnRowGroupingModelChange === void 0 ? void 0 : propsOnRowGroupingModelChange(model, details);
3084
+ },
3085
+ onAggregationModelChange: (model, details) => {
3086
+ updateUrl(buildModel({
3087
+ aggregationModel: model
3088
+ }), search, localStorageVersion, historyReplace, columns);
3089
+ propsOnAggregationModelChange === null || propsOnAggregationModelChange === void 0 ? void 0 : propsOnAggregationModelChange(model, details);
3090
+ },
3091
+ onPivotModelChange: model => {
3092
+ const simplified = fromGridPivotModel(model);
3093
+ if (isDeepEqual(simplified, lastEmittedPivotRef.current)) return;
3094
+ lastEmittedPivotRef.current = simplified;
3095
+ updateUrl(buildModel({
3096
+ pivotModel: simplified
3097
+ }), search, localStorageVersion, historyReplace, columns);
3098
+ propsOnPivotModelChange === null || propsOnPivotModelChange === void 0 ? void 0 : propsOnPivotModelChange(model);
3099
+ },
3100
+ onPivotActiveChange: active => {
3101
+ if (active === pivotActiveParsed) return;
3102
+ updateUrl(buildModel({
3103
+ pivotActive: active
3104
+ }), search, localStorageVersion, historyReplace, columns);
3778
3105
  }
3779
3106
  };
3780
3107
  };
3781
3108
 
3782
- 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"];
3109
+ 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"];
3783
3110
  const COMPONENT_NAME = 'DataGrid';
3784
3111
  const CLASSNAME = 'redsift-datagrid';
3785
3112
 
@@ -3863,6 +3190,9 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3863
3190
  onColumnVisibilityModelChange: propsOnColumnVisibilityModelChange,
3864
3191
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3865
3192
  onSortModelChange: propsOnSortModelChange,
3193
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3194
+ onAggregationModelChange: propsOnAggregationModelChange,
3195
+ onPivotModelChange: propsOnPivotModelChange,
3866
3196
  pagination,
3867
3197
  paginationPlacement = 'both',
3868
3198
  paginationProps,
@@ -3872,15 +3202,26 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3872
3202
  theme: propsTheme,
3873
3203
  useRouter,
3874
3204
  paginationMode = 'client',
3875
- rowCount
3205
+ rowCount,
3206
+ density: _density,
3207
+ dataSource,
3208
+ filterMode: propsFilterMode,
3209
+ sortingMode: propsSortingMode
3876
3210
  } = props,
3877
3211
  forwardedProps = _objectWithoutProperties(props, _excluded);
3878
- const theme = useTheme$1(propsTheme);
3212
+ const theme = useTheme(propsTheme);
3879
3213
  const _apiRef = useGridApiRef();
3880
3214
  const apiRef = propsApiRef !== null && propsApiRef !== void 0 ? propsApiRef : _apiRef;
3881
- const RenderedToolbar = slots !== null && slots !== void 0 && slots.toolbar ? slots.toolbar : Toolbar;
3882
3215
  LicenseInfo.setLicenseKey(license);
3883
3216
  const height = propsHeight !== null && propsHeight !== void 0 ? propsHeight : autoHeight ? undefined : '500px';
3217
+
3218
+ // When dataSource is present, MUI manages filter/sort/pagination internally.
3219
+ // We must not pass controlled models — only initialState (one-time) and
3220
+ // write-only onChange handlers for URL/localStorage persistence.
3221
+ const isDataSourceMode = Boolean(dataSource);
3222
+ const effectivePaginationMode = isDataSourceMode ? 'server' : paginationMode;
3223
+ const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode;
3224
+ const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode;
3884
3225
  const {
3885
3226
  onColumnVisibilityModelChange: controlledOnColumnVisibilityModelChange,
3886
3227
  onFilterModelChange: controlledOnFilterModelChange,
@@ -3914,7 +3255,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3914
3255
  pinnedColumns,
3915
3256
  sortModel,
3916
3257
  onColumnWidthChange,
3917
- columnOrderModel
3258
+ columnOrderModel,
3259
+ rowGroupingModel,
3260
+ aggregationModel,
3261
+ pivotModel,
3262
+ pivotActive,
3263
+ onRowGroupingModelChange,
3264
+ onAggregationModelChange,
3265
+ onPivotModelChange,
3266
+ onPivotActiveChange
3918
3267
  } = useStatefulTable({
3919
3268
  apiRef: apiRef,
3920
3269
  initialState,
@@ -3925,13 +3274,39 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3925
3274
  onPaginationModelChange: controlledOnPaginationModelChange,
3926
3275
  onPinnedColumnsChange: controlledOnPinnedColumnsChange,
3927
3276
  onSortModelChange: controlledOnSortModelChange,
3277
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3278
+ onAggregationModelChange: propsOnAggregationModelChange,
3279
+ onPivotModelChange: propsOnPivotModelChange,
3928
3280
  useRouter: useRouter,
3929
3281
  localStorageVersion,
3930
3282
  previousLocalStorageVersions
3931
3283
  });
3932
- const [rowSelectionModel, setRowSelectionModel] = useState(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3284
+
3285
+ // In dataSource mode, track pagination locally for the custom pagination slots
3286
+ // (rendered outside DataGridPremium). MUI owns the actual pagination state internally.
3287
+ const [dataSourcePaginationModel, setDataSourcePaginationModel] = useState(paginationModel);
3288
+
3289
+ // The pagination model to use for display in pagination slots
3290
+ const activePaginationModel = isDataSourceMode ? dataSourcePaginationModel : paginationModel;
3291
+
3292
+ // In dataSource mode, the top pagination (outside DataGridPremium) must go through
3293
+ // apiRef to change MUI's internal page. MUI then fires onPaginationModelChange
3294
+ // which updates URL and local state.
3295
+ const dataSourceTopPaginationChange = useCallback(model => {
3296
+ var _apiRef$current;
3297
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPaginationModel(model);
3298
+ }, [apiRef]);
3299
+
3300
+ // Wrap onPaginationModelChange to also track state locally in dataSource mode
3301
+ const wrappedOnPaginationModelChange = useCallback((model, details) => {
3302
+ if (isDataSourceMode) {
3303
+ setDataSourcePaginationModel(model);
3304
+ }
3305
+ onPaginationModelChange(model, details);
3306
+ }, [isDataSourceMode, onPaginationModelChange]);
3307
+ const [rowSelectionModel, setRowSelectionModel] = useState(() => normalizeRowSelectionModel(propsRowSelectionModel));
3933
3308
  useEffect(() => {
3934
- setRowSelectionModel(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3309
+ setRowSelectionModel(normalizeRowSelectionModel(propsRowSelectionModel));
3935
3310
  }, [propsRowSelectionModel]);
3936
3311
  const onRowSelectionModelChange = (selectionModel, details) => {
3937
3312
  setRowSelectionModel(selectionModel);
@@ -3945,18 +3320,41 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3945
3320
  pageSize: paginationModel.pageSize
3946
3321
  });
3947
3322
 
3323
+ // Version counter to force re-renders when selectionStatus ref changes
3324
+ const [, forceSelectionUpdate] = useState(0);
3325
+
3948
3326
  // The checkboxSelectionVisibleOnly should only be applied to client-side pagination,
3949
3327
  // for server-side pagination it produces inconsistent behavior when selecting all rows in pages 2 and beyond
3950
- const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(paginationMode != 'server');
3328
+ const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(effectivePaginationMode != 'server');
3329
+
3330
+ // Track when the grid API is ready to ensure top pagination renders correctly
3331
+ const [gridReady, setGridReady] = useState(false);
3332
+
3333
+ // Force re-render when the grid API becomes ready (for top pagination)
3334
+ useEffect(() => {
3335
+ if (apiRef.current && !gridReady) {
3336
+ setGridReady(true);
3337
+ }
3338
+ });
3339
+
3340
+ // Sync persisted density via apiRef — initialState only applies on mount,
3341
+ // so this handles SPA back/forward navigation where controlledDensity changes after mount
3342
+ useEffect(() => {
3343
+ if (apiRef.current) {
3344
+ apiRef.current.setDensity(controlledDensity);
3345
+ }
3346
+ }, [controlledDensity, apiRef]);
3951
3347
 
3952
3348
  // in server-side pagination we want to update the selection status
3953
3349
  // every time we navigate between pages, resize our page or select something
3954
3350
  useEffect(() => {
3955
- if (paginationMode == 'server') {
3956
- onServerSideSelectionStatusChange(Array.isArray(rowSelectionModel) ? rowSelectionModel : [rowSelectionModel], apiRef, selectionStatusRef, isRowSelectable, paginationModel.page, paginationModel.pageSize);
3351
+ if (effectivePaginationMode == 'server') {
3352
+ onServerSideSelectionStatusChange(rowSelectionModel, apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, activePaginationModel.page, activePaginationModel.pageSize);
3957
3353
  }
3958
- }, [rowSelectionModel, paginationModel.page, paginationModel.pageSize, rows]);
3959
- if (!Array.isArray(rows)) {
3354
+ }, [rowSelectionModel, activePaginationModel.page, activePaginationModel.pageSize, rows]);
3355
+
3356
+ // In dataSource mode MUI provides rows internally; skip the guard.
3357
+ if (!isDataSourceMode && !Array.isArray(rows)) {
3960
3358
  return null;
3961
3359
  }
3962
3360
 
@@ -3965,9 +3363,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3965
3363
  // receive the fresh value in the same render cycle — no extra re-render needed.
3966
3364
  // The ref is kept in sync for the onRowSelectionModelChange callback's deselect logic.
3967
3365
  let selectionStatus = selectionStatusRef.current;
3968
- if (pagination && paginationMode !== 'server' && Array.isArray(rowSelectionModel) && rowSelectionModel.length > 0) {
3366
+ if (pagination && effectivePaginationMode !== 'server' && getSelectionCount(rowSelectionModel) > 0) {
3969
3367
  try {
3970
- const selectableRowsInPage = isRowSelectable ? gridPaginatedVisibleSortedGridRowEntriesSelector(apiRef).filter(_ref => {
3368
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors.
3369
+ // MUI's paginated selectors use apiRef internal state which may be stale when
3370
+ // paginationModel prop changes — our React state is always up to date.
3371
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3372
+ const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3373
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3374
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref => {
3971
3375
  let {
3972
3376
  model
3973
3377
  } = _ref;
@@ -3979,24 +3383,29 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3979
3383
  id
3980
3384
  } = _ref2;
3981
3385
  return id;
3982
- }) : gridPaginatedVisibleSortedGridRowIdsSelector(apiRef);
3386
+ }) : pageEntries.map(_ref3 => {
3387
+ let {
3388
+ id
3389
+ } = _ref3;
3390
+ return id;
3391
+ });
3983
3392
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
3984
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref3 => {
3393
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref4 => {
3985
3394
  let {
3986
3395
  model
3987
- } = _ref3;
3396
+ } = _ref4;
3988
3397
  return isRowSelectable({
3989
3398
  row: model
3990
3399
  });
3991
- }).map(_ref4 => {
3400
+ }).map(_ref5 => {
3992
3401
  let {
3993
3402
  id
3994
- } = _ref4;
3403
+ } = _ref5;
3995
3404
  return id;
3996
3405
  }) : gridFilteredSortedRowIdsSelector(apiRef);
3997
3406
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
3998
- const numberOfSelectedRows = rowSelectionModel.length;
3999
- const selectedOnCurrentPage = selectableRowsInPage.filter(id => rowSelectionModel.includes(id));
3407
+ const numberOfSelectedRows = getSelectionCount(rowSelectionModel);
3408
+ const selectedOnCurrentPage = selectableRowsInPage.filter(id => isRowSelected(rowSelectionModel, id));
4000
3409
  if (numberOfSelectedRows === numberOfSelectableRowsInTable && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
4001
3410
  selectionStatus = {
4002
3411
  type: 'table',
@@ -4021,7 +3430,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4021
3430
  } catch {
4022
3431
  // apiRef may not be initialized on first render
4023
3432
  }
4024
- } else if (pagination && paginationMode !== 'server') {
3433
+ } else if (pagination && effectivePaginationMode !== 'server') {
4025
3434
  selectionStatus = {
4026
3435
  type: 'none',
4027
3436
  numberOfSelectedRows: 0
@@ -4050,156 +3459,206 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4050
3459
  ref: datagridRef,
4051
3460
  className: classNames(StatefulDataGrid.className, className),
4052
3461
  $height: height
4053
- }, /*#__PURE__*/React__default.createElement(DataGridPro, _extends$2({}, forwardedProps, {
3462
+ }, pagination && ['top', 'both'].includes(paginationPlacement) && gridReady ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, {
3463
+ displaySelection: true,
3464
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3465
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3466
+ selectionStatus: selectionStatus,
3467
+ paginationModel: activePaginationModel,
3468
+ onPaginationModelChange: isDataSourceMode ? dataSourceTopPaginationChange : onPaginationModelChange,
3469
+ pageSizeOptions: pageSizeOptions,
3470
+ paginationProps: paginationProps,
3471
+ rowCount: rowCount
3472
+ }) : /*#__PURE__*/React__default.createElement(ControlledPagination, {
3473
+ displaySelection: true,
3474
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3475
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3476
+ selectionStatus: selectionStatus,
3477
+ apiRef: apiRef,
3478
+ isRowSelectable: isRowSelectable,
3479
+ paginationModel: activePaginationModel,
3480
+ onPaginationModelChange: onPaginationModelChange,
3481
+ pageSizeOptions: pageSizeOptions,
3482
+ paginationProps: paginationProps
3483
+ }) : null, /*#__PURE__*/React__default.createElement(DataGridPremium, _extends({}, forwardedProps, {
4054
3484
  apiRef: apiRef,
3485
+ dataSource: dataSource,
4055
3486
  columns: columns,
4056
3487
  columnVisibilityModel: columnVisibilityModel,
4057
- density: controlledDensity,
4058
- filterModel: filterModel,
4059
3488
  onColumnVisibilityModelChange: onColumnVisibilityModelChange,
4060
- onFilterModelChange: onFilterModelChange,
4061
- onPaginationModelChange: onPaginationModelChange,
4062
3489
  onPinnedColumnsChange: onPinnedColumnsChange,
4063
- onSortModelChange: onSortModelChange,
4064
- paginationModel: paginationModel,
4065
3490
  pinnedColumns: pinnedColumns,
4066
- sortModel: sortModel,
4067
3491
  pageSizeOptions: pageSizeOptions,
4068
3492
  onColumnWidthChange: onColumnWidthChange,
3493
+ rowGroupingModel: rowGroupingModel,
3494
+ onRowGroupingModelChange: onRowGroupingModelChange,
3495
+ aggregationModel: aggregationModel,
3496
+ onAggregationModelChange: onAggregationModelChange,
3497
+ pivotModel: pivotModel,
3498
+ onPivotModelChange: onPivotModelChange,
3499
+ pivotActive: pivotActive,
3500
+ onPivotActiveChange: onPivotActiveChange
3501
+ // In dataSource mode: models are uncontrolled (MUI owns them),
3502
+ // onChange handlers are write-only for URL/localStorage persistence,
3503
+ // and initialState seeds MUI on mount from the persisted URL state.
3504
+ }, isDataSourceMode ? {
3505
+ onFilterModelChange: onFilterModelChange,
3506
+ onSortModelChange: onSortModelChange,
3507
+ onPaginationModelChange: wrappedOnPaginationModelChange,
3508
+ initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3509
+ density: controlledDensity,
3510
+ columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3511
+ orderedFields: columnOrderModel
3512
+ }),
3513
+ filter: {
3514
+ filterModel
3515
+ },
3516
+ sorting: {
3517
+ sortModel
3518
+ },
3519
+ pagination: {
3520
+ paginationModel
3521
+ },
3522
+ pivoting: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.pivoting), {}, {
3523
+ enabled: pivotActive
3524
+ })
3525
+ })
3526
+ } : {
3527
+ filterModel,
3528
+ sortModel,
3529
+ paginationModel,
3530
+ onFilterModelChange: onFilterModelChange,
3531
+ onSortModelChange: onSortModelChange,
3532
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4069
3533
  initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3534
+ density: controlledDensity,
4070
3535
  columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
4071
3536
  orderedFields: columnOrderModel
4072
3537
  })
4073
- }),
3538
+ })
3539
+ }, {
4074
3540
  isRowSelectable: isRowSelectable,
4075
3541
  pagination: pagination,
4076
- paginationMode: paginationMode,
4077
- keepNonExistentRowsSelected: paginationMode == 'server',
4078
- rows: rows,
3542
+ paginationMode: effectivePaginationMode,
3543
+ filterMode: effectiveFilterMode,
3544
+ sortingMode: effectiveSortingMode,
3545
+ keepNonExistentRowsSelected: effectivePaginationMode == 'server',
3546
+ rows: isDataSourceMode ? [] : rows,
4079
3547
  rowCount: rowCount,
4080
3548
  autoHeight: autoHeight,
4081
3549
  checkboxSelectionVisibleOnly: checkboxSelectionVisibleOnly,
3550
+ disableRowSelectionExcludeModel: true,
3551
+ showToolbar: !hideToolbar,
4082
3552
  slots: _objectSpread2(_objectSpread2({
4083
3553
  baseButton: BaseButton,
4084
3554
  baseCheckbox: BaseCheckbox,
4085
- // baseTextField,
4086
- basePopper: BasePopper,
4087
- columnFilteredIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4088
- displayName: "ColumnFilteredIcon"
3555
+ baseIconButton: BaseIconButton,
3556
+ columnFilteredIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3557
+ displayName: "columnFilteredIcon"
4089
3558
  })),
4090
- columnSelectorIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4091
- displayName: "ColumnSelectorIcon"
3559
+ columnSelectorIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3560
+ displayName: "columnSelectorIcon"
4092
3561
  })),
4093
- columnSortedAscendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4094
- displayName: "ColumnSortedAscendingIcon"
3562
+ columnSortedAscendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3563
+ displayName: "columnSortedAscendingIcon"
4095
3564
  })),
4096
- columnSortedDescendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4097
- displayName: "ColumnSortedDescendingIcon"
3565
+ columnSortedDescendingIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3566
+ displayName: "columnSortedDescendingIcon"
4098
3567
  })),
4099
- densityCompactIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4100
- displayName: "DensityCompactIcon"
3568
+ densityCompactIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3569
+ displayName: "densityCompactIcon"
4101
3570
  })),
4102
- densityStandardIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4103
- displayName: "DensityStandardIcon"
3571
+ densityStandardIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3572
+ displayName: "densityStandardIcon"
4104
3573
  })),
4105
- densityComfortableIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4106
- displayName: "DensityComfortableIcon"
3574
+ densityComfortableIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3575
+ displayName: "densityComfortableIcon"
4107
3576
  })),
4108
- detailPanelCollapseIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4109
- displayName: "DetailPanelCollapseIcon"
3577
+ detailPanelCollapseIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3578
+ displayName: "detailPanelCollapseIcon"
4110
3579
  })),
4111
- detailPanelExpandIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4112
- displayName: "DetailPanelExpandIcon"
3580
+ detailPanelExpandIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3581
+ displayName: "detailPanelExpandIcon"
4113
3582
  })),
4114
- exportIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({}, props, {
4115
- displayName: "ExportIcon"
3583
+ exportIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3584
+ displayName: "exportIcon"
4116
3585
  })),
4117
- openFilterButtonIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends$2({
4118
- displayName: "OpenFilterButtonIcon"
4119
- }, props))
3586
+ openFilterButtonIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
3587
+ displayName: "openFilterButtonIcon"
3588
+ }))
4120
3589
  }, slots), {}, {
4121
- toolbar: ToolbarWrapper,
4122
3590
  pagination: props => {
4123
- return pagination ? paginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends$2({}, props, {
3591
+ return pagination ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends({}, props, {
4124
3592
  displaySelection: false,
4125
3593
  displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
4126
3594
  displayPagination: ['bottom', 'both'].includes(paginationPlacement),
4127
3595
  selectionStatus: selectionStatus,
4128
- paginationModel: paginationModel,
4129
- onPaginationModelChange: onPaginationModelChange,
3596
+ paginationModel: activePaginationModel,
3597
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4130
3598
  pageSizeOptions: pageSizeOptions,
4131
3599
  paginationProps: paginationProps,
4132
- paginationMode: paginationMode,
4133
3600
  rowCount: rowCount
4134
- })) : /*#__PURE__*/React__default.createElement(ControlledPagination, _extends$2({}, props, {
3601
+ })) : /*#__PURE__*/React__default.createElement(ControlledPagination, _extends({}, props, {
4135
3602
  displaySelection: false,
4136
3603
  displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
4137
3604
  displayPagination: ['bottom', 'both'].includes(paginationPlacement),
4138
3605
  selectionStatus: selectionStatus,
4139
3606
  apiRef: apiRef,
4140
3607
  isRowSelectable: isRowSelectable,
4141
- paginationModel: paginationModel,
4142
- onPaginationModelChange: onPaginationModelChange,
3608
+ paginationModel: activePaginationModel,
3609
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4143
3610
  pageSizeOptions: pageSizeOptions,
4144
- paginationProps: paginationProps,
4145
- paginationMode: paginationMode
3611
+ paginationProps: paginationProps
4146
3612
  })) : null;
4147
3613
  }
4148
3614
  }),
4149
- slotProps: _objectSpread2(_objectSpread2({}, slotProps), {}, {
4150
- toolbar: _objectSpread2({
4151
- hideToolbar,
4152
- RenderedToolbar,
4153
- filterModel,
4154
- onFilterModelChange,
4155
- pagination,
4156
- paginationPlacement,
4157
- selectionStatus,
4158
- apiRef,
4159
- isRowSelectable,
4160
- paginationModel,
4161
- onPaginationModelChange,
4162
- pageSizeOptions,
4163
- paginationProps,
4164
- paginationMode,
4165
- rowCount
4166
- }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar)
4167
- }),
3615
+ slotProps: _objectSpread2({}, slotProps),
4168
3616
  rowSelectionModel: rowSelectionModel,
4169
3617
  onRowSelectionModelChange: (newSelectionModel, details) => {
4170
- if (pagination && paginationMode != 'server') {
4171
- const selectableRowsInPage = isRowSelectable ? gridPaginatedVisibleSortedGridRowEntriesSelector(apiRef).filter(_ref5 => {
3618
+ if (pagination && effectivePaginationMode != 'server') {
3619
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors
3620
+ // to avoid stale apiRef pagination state.
3621
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3622
+ const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3623
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3624
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref6 => {
4172
3625
  let {
4173
3626
  model
4174
- } = _ref5;
3627
+ } = _ref6;
4175
3628
  return isRowSelectable({
4176
3629
  row: model
4177
3630
  });
4178
- }).map(_ref6 => {
3631
+ }).map(_ref7 => {
4179
3632
  let {
4180
3633
  id
4181
- } = _ref6;
3634
+ } = _ref7;
4182
3635
  return id;
4183
- }) : gridPaginatedVisibleSortedGridRowIdsSelector(apiRef);
3636
+ }) : pageEntries.map(_ref8 => {
3637
+ let {
3638
+ id
3639
+ } = _ref8;
3640
+ return id;
3641
+ });
4184
3642
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4185
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref7 => {
3643
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref9 => {
4186
3644
  let {
4187
3645
  model
4188
- } = _ref7;
3646
+ } = _ref9;
4189
3647
  return isRowSelectable({
4190
3648
  row: model
4191
3649
  });
4192
- }).map(_ref8 => {
3650
+ }).map(_ref10 => {
4193
3651
  let {
4194
3652
  id
4195
- } = _ref8;
3653
+ } = _ref10;
4196
3654
  return id;
4197
3655
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4198
3656
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4199
- const numberOfSelectedRows = newSelectionModel.length;
3657
+ const numberOfSelectedRows = getSelectionCount(newSelectionModel);
4200
3658
  if (selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable - numberOfSelectableRowsInPage || selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable || selectionStatusRef.current.type === 'page' && numberOfSelectedRows === numberOfSelectableRowsInPage) {
4201
3659
  setTimeout(() => {
4202
- apiRef.current.selectRows([], true, true);
3660
+ var _apiRef$current2;
3661
+ (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.selectRows([], true, true);
4203
3662
  }, 0);
4204
3663
  }
4205
3664
  if (numberOfSelectedRows === numberOfSelectableRowsInPage && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
@@ -4223,6 +3682,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4223
3682
  numberOfSelectedRows
4224
3683
  };
4225
3684
  }
3685
+ forceSelectionUpdate(v => v + 1);
4226
3686
  }
4227
3687
  onRowSelectionModelChange === null || onRowSelectionModelChange === void 0 ? void 0 : onRowSelectionModelChange(newSelectionModel, details);
4228
3688
  },
@@ -4240,5 +3700,5 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4240
3700
  StatefulDataGrid.className = CLASSNAME;
4241
3701
  StatefulDataGrid.displayName = COMPONENT_NAME;
4242
3702
 
4243
- export { clearAllVersionStorage 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, resetStatefulDataGridState as a0, convertToDisplayFormat as a1, convertFromDisplayFormat as a2, getDecodedSearchFromUrl as a3, buildQueryParamsString as a4, areSearchStringsEqual as a5, decodeValue as a6, encodeValue as a7, urlSearchParamsToString as a8, numberOperatorEncoder as a9, numberOperatorDecoder as aa, isOperatorValueValid as ab, isValueValid as ac, getFilterModelFromString as ad, getSearchParamsFromFilterModel as ae, getSortingFromString as af, getSearchParamsFromSorting as ag, getPaginationFromString as ah, getSearchParamsFromPagination as ai, getColumnVisibilityFromString as aj, getSearchParamsFromColumnVisibility as ak, getPinnedColumnsFromString as al, getSearchParamsFromPinnedColumns as am, getSearchParamsFromTab as an, getDensityFromString as ao, getSearchParamsFromDensity as ap, getColumnOrderFromString as aq, getSearchParamsFromColumnOrder as ar, getFinalSearch as as, getModelsParsedOrUpdateLocalStorage as at, updateUrl as au, areFilterModelsEquivalent as av, StatefulDataGrid as aw, 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 };
3703
+ export { buildStorageKey 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, PIVOT_ACTIVE_KEY as Z, CATEGORIES as _, DOES_NOT_EQUAL as a, clearPreviousVersionStorage as a0, clearAllVersionStorage as a1, resetStatefulDataGridState as a2, convertToDisplayFormat as a3, convertFromDisplayFormat as a4, getDecodedSearchFromUrl as a5, buildQueryParamsString as a6, areSearchStringsEqual as a7, decodeValue as a8, encodeValue as a9, getPivotFromString as aA, getSearchParamsFromPivot as aB, getPivotActiveFromString as aC, getSearchParamsFromPivotActive as aD, getFinalSearch as aE, getModelsParsedOrUpdateLocalStorage as aF, updateUrl as aG, areFilterModelsEquivalent as aH, StatefulDataGrid as aI, urlSearchParamsToString as aa, numberOperatorEncoder as ab, numberOperatorDecoder as ac, isOperatorValueValid as ad, isValueValid as ae, getFilterModelFromString as af, getSearchParamsFromFilterModel as ag, getSortingFromString as ah, getSearchParamsFromSorting as ai, getPaginationFromString as aj, getSearchParamsFromPagination as ak, getColumnVisibilityFromString as al, getSearchParamsFromColumnVisibility as am, getPinnedColumnsFromString as an, getSearchParamsFromPinnedColumns as ao, getSearchParamsFromTab as ap, getDensityFromString as aq, getSearchParamsFromDensity as ar, getDensityModel as as, getColumnOrderFromString as at, getSearchParamsFromColumnOrder as au, getRowGroupingFromString as av, getSearchParamsFromRowGrouping as aw, getAggregationFromString as ax, getSearchParamsFromAggregation as ay, fromGridPivotModel 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 };
4244
3704
  //# sourceMappingURL=StatefulDataGrid2.js.map