@redsift/table 12.5.12 → 12.5.13-muiv6

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,18 +1,1248 @@
1
- import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends } from './_rollupPluginBabelHelpers.js';
1
+ import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends$2 } from './_rollupPluginBabelHelpers.js';
2
2
  import * as React 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';
3
+ import React__default, { useCallback, useEffect, useMemo, useRef, forwardRef, useState } from 'react';
5
4
  import classNames from 'classnames';
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, B as BottomPagination, b as baseGridSlots, a as BelowToolbar } from './useControlledDatagridState.js';
10
- import Box from '@mui/material/Box';
11
- import TextField from '@mui/material/TextField';
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, B as BottomPagination, b as baseGridSlots } from './useControlledDatagridState.js';
12
8
  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 } from './ControlledPagination.js';
11
+ import { j as jsxRuntimeExports } from './jsx-runtime.js';
13
12
  import { decompressFromEncodedURIComponent, compressToEncodedURIComponent } from 'lz-string';
14
- import { n as normalizeRowSelectionModel, o as onServerSideSelectionStatusChange, g as getSelectionCount, i as isRowSelected, S as ServerSideControlledPagination, C as ControlledPagination } from './ServerSideControlledPagination.js';
15
13
  import { T as Toolbar } from './Toolbar2.js';
14
+ import { T as ToolbarWrapper } from './ToolbarWrapper2.js';
15
+
16
+ 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}
17
+
18
+ const _excluded$6 = ["className", "component"];
19
+ function createBox(options = {}) {
20
+ const {
21
+ themeId,
22
+ defaultTheme,
23
+ defaultClassName = 'MuiBox-root',
24
+ generateClassName
25
+ } = options;
26
+ const BoxRoot = styled('div', {
27
+ shouldForwardProp: prop => prop !== 'theme' && prop !== 'sx' && prop !== 'as'
28
+ })(styleFunctionSx);
29
+ const Box = /*#__PURE__*/React.forwardRef(function Box(inProps, ref) {
30
+ const theme = useTheme(defaultTheme);
31
+ const _extendSxProp = extendSxProp(inProps),
32
+ {
33
+ className,
34
+ component = 'div'
35
+ } = _extendSxProp,
36
+ other = _objectWithoutPropertiesLoose(_extendSxProp, _excluded$6);
37
+ return /*#__PURE__*/jsxRuntimeExports.jsx(BoxRoot, _extends({
38
+ as: component,
39
+ ref: ref,
40
+ className: clsx(className, generateClassName ? generateClassName(defaultClassName) : defaultClassName),
41
+ theme: themeId ? theme[themeId] || theme : theme
42
+ }, other));
43
+ });
44
+ return Box;
45
+ }
46
+
47
+ function isMuiElement(element, muiNames) {
48
+ var _muiName, _element$type;
49
+ return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf( // For server components `muiName` is avaialble in element.type._payload.value.muiName
50
+ // relevant info - https://github.com/facebook/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
51
+ // eslint-disable-next-line no-underscore-dangle
52
+ (_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;
53
+ }
54
+
55
+ const boxClasses = generateUtilityClasses('MuiBox', ['root']);
56
+ var boxClasses$1 = boxClasses;
57
+
58
+ const defaultTheme = createTheme();
59
+ const Box = createBox({
60
+ themeId: THEME_ID,
61
+ defaultTheme,
62
+ defaultClassName: boxClasses$1.root,
63
+ generateClassName: ClassNameGenerator.generate
64
+ });
65
+ process.env.NODE_ENV !== "production" ? Box.propTypes /* remove-proptypes */ = {
66
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
67
+ // │ These PropTypes are generated from the TypeScript type definitions. │
68
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
69
+ // └─────────────────────────────────────────────────────────────────────┘
70
+ /**
71
+ * @ignore
72
+ */
73
+ children: PropTypes.node,
74
+ /**
75
+ * The component used for the root node.
76
+ * Either a string to use a HTML element or a component.
77
+ */
78
+ component: PropTypes.elementType,
79
+ /**
80
+ * The system prop that allows defining system overrides as well as additional CSS styles.
81
+ */
82
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
83
+ } : void 0;
84
+ var Box$1 = Box;
85
+
86
+ function getFormLabelUtilityClasses(slot) {
87
+ return generateUtilityClass('MuiFormLabel', slot);
88
+ }
89
+ const formLabelClasses = generateUtilityClasses('MuiFormLabel', ['root', 'colorSecondary', 'focused', 'disabled', 'error', 'filled', 'required', 'asterisk']);
90
+ var formLabelClasses$1 = formLabelClasses;
91
+
92
+ const _excluded$5 = ["children", "className", "color", "component", "disabled", "error", "filled", "focused", "required"];
93
+ const useUtilityClasses$4 = ownerState => {
94
+ const {
95
+ classes,
96
+ color,
97
+ focused,
98
+ disabled,
99
+ error,
100
+ filled,
101
+ required
102
+ } = ownerState;
103
+ const slots = {
104
+ root: ['root', `color${capitalize(color)}`, disabled && 'disabled', error && 'error', filled && 'filled', focused && 'focused', required && 'required'],
105
+ asterisk: ['asterisk', error && 'error']
106
+ };
107
+ return composeClasses(slots, getFormLabelUtilityClasses, classes);
108
+ };
109
+ const FormLabelRoot = styled$1('label', {
110
+ name: 'MuiFormLabel',
111
+ slot: 'Root',
112
+ overridesResolver: ({
113
+ ownerState
114
+ }, styles) => {
115
+ return _extends$1({}, styles.root, ownerState.color === 'secondary' && styles.colorSecondary, ownerState.filled && styles.filled);
116
+ }
117
+ })(({
118
+ theme,
119
+ ownerState
120
+ }) => _extends$1({
121
+ color: (theme.vars || theme).palette.text.secondary
122
+ }, theme.typography.body1, {
123
+ lineHeight: '1.4375em',
124
+ padding: 0,
125
+ position: 'relative',
126
+ [`&.${formLabelClasses$1.focused}`]: {
127
+ color: (theme.vars || theme).palette[ownerState.color].main
128
+ },
129
+ [`&.${formLabelClasses$1.disabled}`]: {
130
+ color: (theme.vars || theme).palette.text.disabled
131
+ },
132
+ [`&.${formLabelClasses$1.error}`]: {
133
+ color: (theme.vars || theme).palette.error.main
134
+ }
135
+ }));
136
+ const AsteriskComponent = styled$1('span', {
137
+ name: 'MuiFormLabel',
138
+ slot: 'Asterisk',
139
+ overridesResolver: (props, styles) => styles.asterisk
140
+ })(({
141
+ theme
142
+ }) => ({
143
+ [`&.${formLabelClasses$1.error}`]: {
144
+ color: (theme.vars || theme).palette.error.main
145
+ }
146
+ }));
147
+ const FormLabel = /*#__PURE__*/React.forwardRef(function FormLabel(inProps, ref) {
148
+ const props = useDefaultProps({
149
+ props: inProps,
150
+ name: 'MuiFormLabel'
151
+ });
152
+ const {
153
+ children,
154
+ className,
155
+ component = 'label'
156
+ } = props,
157
+ other = _objectWithoutPropertiesLoose$1(props, _excluded$5);
158
+ const muiFormControl = useFormControl();
159
+ const fcs = formControlState({
160
+ props,
161
+ muiFormControl,
162
+ states: ['color', 'required', 'focused', 'disabled', 'error', 'filled']
163
+ });
164
+ const ownerState = _extends$1({}, props, {
165
+ color: fcs.color || 'primary',
166
+ component,
167
+ disabled: fcs.disabled,
168
+ error: fcs.error,
169
+ filled: fcs.filled,
170
+ focused: fcs.focused,
171
+ required: fcs.required
172
+ });
173
+ const classes = useUtilityClasses$4(ownerState);
174
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(FormLabelRoot, _extends$1({
175
+ as: component,
176
+ ownerState: ownerState,
177
+ className: clsx$1(classes.root, className),
178
+ ref: ref
179
+ }, other, {
180
+ children: [children, fcs.required && /*#__PURE__*/jsxRuntimeExports.jsxs(AsteriskComponent, {
181
+ ownerState: ownerState,
182
+ "aria-hidden": true,
183
+ className: classes.asterisk,
184
+ children: ["\u2009", '*']
185
+ })]
186
+ }));
187
+ });
188
+ process.env.NODE_ENV !== "production" ? FormLabel.propTypes /* remove-proptypes */ = {
189
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
190
+ // │ These PropTypes are generated from the TypeScript type definitions. │
191
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
192
+ // └─────────────────────────────────────────────────────────────────────┘
193
+ /**
194
+ * The content of the component.
195
+ */
196
+ children: PropTypes.node,
197
+ /**
198
+ * Override or extend the styles applied to the component.
199
+ */
200
+ classes: PropTypes.object,
201
+ /**
202
+ * @ignore
203
+ */
204
+ className: PropTypes.string,
205
+ /**
206
+ * The color of the component.
207
+ * It supports both default and custom theme colors, which can be added as shown in the
208
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
209
+ */
210
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
211
+ /**
212
+ * The component used for the root node.
213
+ * Either a string to use a HTML element or a component.
214
+ */
215
+ component: PropTypes.elementType,
216
+ /**
217
+ * If `true`, the label should be displayed in a disabled state.
218
+ */
219
+ disabled: PropTypes.bool,
220
+ /**
221
+ * If `true`, the label is displayed in an error state.
222
+ */
223
+ error: PropTypes.bool,
224
+ /**
225
+ * If `true`, the label should use filled classes key.
226
+ */
227
+ filled: PropTypes.bool,
228
+ /**
229
+ * If `true`, the input of this label is focused (used by `FormGroup` components).
230
+ */
231
+ focused: PropTypes.bool,
232
+ /**
233
+ * If `true`, the label will indicate that the `input` is required.
234
+ */
235
+ required: PropTypes.bool,
236
+ /**
237
+ * The system prop that allows defining system overrides as well as additional CSS styles.
238
+ */
239
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
240
+ } : void 0;
241
+ var FormLabel$1 = FormLabel;
242
+
243
+ function getInputLabelUtilityClasses(slot) {
244
+ return generateUtilityClass('MuiInputLabel', slot);
245
+ }
246
+ generateUtilityClasses('MuiInputLabel', ['root', 'focused', 'disabled', 'error', 'required', 'asterisk', 'formControl', 'sizeSmall', 'shrink', 'animated', 'standard', 'filled', 'outlined']);
247
+
248
+ const _excluded$4 = ["disableAnimation", "margin", "shrink", "variant", "className"];
249
+ const useUtilityClasses$3 = ownerState => {
250
+ const {
251
+ classes,
252
+ formControl,
253
+ size,
254
+ shrink,
255
+ disableAnimation,
256
+ variant,
257
+ required
258
+ } = ownerState;
259
+ const slots = {
260
+ root: ['root', formControl && 'formControl', !disableAnimation && 'animated', shrink && 'shrink', size && size !== 'normal' && `size${capitalize(size)}`, variant],
261
+ asterisk: [required && 'asterisk']
262
+ };
263
+ const composedClasses = composeClasses(slots, getInputLabelUtilityClasses, classes);
264
+ return _extends$1({}, classes, composedClasses);
265
+ };
266
+ const InputLabelRoot = styled$1(FormLabel$1, {
267
+ shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
268
+ name: 'MuiInputLabel',
269
+ slot: 'Root',
270
+ overridesResolver: (props, styles) => {
271
+ const {
272
+ ownerState
273
+ } = props;
274
+ return [{
275
+ [`& .${formLabelClasses$1.asterisk}`]: styles.asterisk
276
+ }, 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]];
277
+ }
278
+ })(({
279
+ theme,
280
+ ownerState
281
+ }) => _extends$1({
282
+ display: 'block',
283
+ transformOrigin: 'top left',
284
+ whiteSpace: 'nowrap',
285
+ overflow: 'hidden',
286
+ textOverflow: 'ellipsis',
287
+ maxWidth: '100%'
288
+ }, ownerState.formControl && {
289
+ position: 'absolute',
290
+ left: 0,
291
+ top: 0,
292
+ // slight alteration to spec spacing to match visual spec result
293
+ transform: 'translate(0, 20px) scale(1)'
294
+ }, ownerState.size === 'small' && {
295
+ // Compensation for the `Input.inputSizeSmall` style.
296
+ transform: 'translate(0, 17px) scale(1)'
297
+ }, ownerState.shrink && {
298
+ transform: 'translate(0, -1.5px) scale(0.75)',
299
+ transformOrigin: 'top left',
300
+ maxWidth: '133%'
301
+ }, !ownerState.disableAnimation && {
302
+ transition: theme.transitions.create(['color', 'transform', 'max-width'], {
303
+ duration: theme.transitions.duration.shorter,
304
+ easing: theme.transitions.easing.easeOut
305
+ })
306
+ }, ownerState.variant === 'filled' && _extends$1({
307
+ // Chrome's autofill feature gives the input field a yellow background.
308
+ // Since the input field is behind the label in the HTML tree,
309
+ // the input field is drawn last and hides the label with an opaque background color.
310
+ // zIndex: 1 will raise the label above opaque background-colors of input.
311
+ zIndex: 1,
312
+ pointerEvents: 'none',
313
+ transform: 'translate(12px, 16px) scale(1)',
314
+ maxWidth: 'calc(100% - 24px)'
315
+ }, ownerState.size === 'small' && {
316
+ transform: 'translate(12px, 13px) scale(1)'
317
+ }, ownerState.shrink && _extends$1({
318
+ userSelect: 'none',
319
+ pointerEvents: 'auto',
320
+ transform: 'translate(12px, 7px) scale(0.75)',
321
+ maxWidth: 'calc(133% - 24px)'
322
+ }, ownerState.size === 'small' && {
323
+ transform: 'translate(12px, 4px) scale(0.75)'
324
+ })), ownerState.variant === 'outlined' && _extends$1({
325
+ // see comment above on filled.zIndex
326
+ zIndex: 1,
327
+ pointerEvents: 'none',
328
+ transform: 'translate(14px, 16px) scale(1)',
329
+ maxWidth: 'calc(100% - 24px)'
330
+ }, ownerState.size === 'small' && {
331
+ transform: 'translate(14px, 9px) scale(1)'
332
+ }, ownerState.shrink && {
333
+ userSelect: 'none',
334
+ pointerEvents: 'auto',
335
+ // Theoretically, we should have (8+5)*2/0.75 = 34px
336
+ // but it feels a better when it bleeds a bit on the left, so 32px.
337
+ maxWidth: 'calc(133% - 32px)',
338
+ transform: 'translate(14px, -9px) scale(0.75)'
339
+ })));
340
+ const InputLabel = /*#__PURE__*/React.forwardRef(function InputLabel(inProps, ref) {
341
+ const props = useDefaultProps({
342
+ name: 'MuiInputLabel',
343
+ props: inProps
344
+ });
345
+ const {
346
+ disableAnimation = false,
347
+ shrink: shrinkProp,
348
+ className
349
+ } = props,
350
+ other = _objectWithoutPropertiesLoose$1(props, _excluded$4);
351
+ const muiFormControl = useFormControl();
352
+ let shrink = shrinkProp;
353
+ if (typeof shrink === 'undefined' && muiFormControl) {
354
+ shrink = muiFormControl.filled || muiFormControl.focused || muiFormControl.adornedStart;
355
+ }
356
+ const fcs = formControlState({
357
+ props,
358
+ muiFormControl,
359
+ states: ['size', 'variant', 'required', 'focused']
360
+ });
361
+ const ownerState = _extends$1({}, props, {
362
+ disableAnimation,
363
+ formControl: muiFormControl,
364
+ shrink,
365
+ size: fcs.size,
366
+ variant: fcs.variant,
367
+ required: fcs.required,
368
+ focused: fcs.focused
369
+ });
370
+ const classes = useUtilityClasses$3(ownerState);
371
+ return /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelRoot, _extends$1({
372
+ "data-shrink": shrink,
373
+ ownerState: ownerState,
374
+ ref: ref,
375
+ className: clsx$1(classes.root, className)
376
+ }, other, {
377
+ classes: classes
378
+ }));
379
+ });
380
+ process.env.NODE_ENV !== "production" ? InputLabel.propTypes /* remove-proptypes */ = {
381
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
382
+ // │ These PropTypes are generated from the TypeScript type definitions. │
383
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
384
+ // └─────────────────────────────────────────────────────────────────────┘
385
+ /**
386
+ * The content of the component.
387
+ */
388
+ children: PropTypes.node,
389
+ /**
390
+ * Override or extend the styles applied to the component.
391
+ */
392
+ classes: PropTypes.object,
393
+ /**
394
+ * @ignore
395
+ */
396
+ className: PropTypes.string,
397
+ /**
398
+ * The color of the component.
399
+ * It supports both default and custom theme colors, which can be added as shown in the
400
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
401
+ */
402
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
403
+ /**
404
+ * If `true`, the transition animation is disabled.
405
+ * @default false
406
+ */
407
+ disableAnimation: PropTypes.bool,
408
+ /**
409
+ * If `true`, the component is disabled.
410
+ */
411
+ disabled: PropTypes.bool,
412
+ /**
413
+ * If `true`, the label is displayed in an error state.
414
+ */
415
+ error: PropTypes.bool,
416
+ /**
417
+ * If `true`, the `input` of this label is focused.
418
+ */
419
+ focused: PropTypes.bool,
420
+ /**
421
+ * If `dense`, will adjust vertical spacing. This is normally obtained via context from
422
+ * FormControl.
423
+ */
424
+ margin: PropTypes.oneOf(['dense']),
425
+ /**
426
+ * if `true`, the label will indicate that the `input` is required.
427
+ */
428
+ required: PropTypes.bool,
429
+ /**
430
+ * If `true`, the label is shrunk.
431
+ */
432
+ shrink: PropTypes.bool,
433
+ /**
434
+ * The size of the component.
435
+ * @default 'normal'
436
+ */
437
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['normal', 'small']), PropTypes.string]),
438
+ /**
439
+ * The system prop that allows defining system overrides as well as additional CSS styles.
440
+ */
441
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
442
+ /**
443
+ * The variant to use.
444
+ */
445
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
446
+ } : void 0;
447
+ var InputLabel$1 = InputLabel;
448
+
449
+ function getFormControlUtilityClasses(slot) {
450
+ return generateUtilityClass('MuiFormControl', slot);
451
+ }
452
+ generateUtilityClasses('MuiFormControl', ['root', 'marginNone', 'marginNormal', 'marginDense', 'fullWidth', 'disabled']);
453
+
454
+ const _excluded$3 = ["children", "className", "color", "component", "disabled", "error", "focused", "fullWidth", "hiddenLabel", "margin", "required", "size", "variant"];
455
+ const useUtilityClasses$2 = ownerState => {
456
+ const {
457
+ classes,
458
+ margin,
459
+ fullWidth
460
+ } = ownerState;
461
+ const slots = {
462
+ root: ['root', margin !== 'none' && `margin${capitalize(margin)}`, fullWidth && 'fullWidth']
463
+ };
464
+ return composeClasses(slots, getFormControlUtilityClasses, classes);
465
+ };
466
+ const FormControlRoot = styled$1('div', {
467
+ name: 'MuiFormControl',
468
+ slot: 'Root',
469
+ overridesResolver: ({
470
+ ownerState
471
+ }, styles) => {
472
+ return _extends$1({}, styles.root, styles[`margin${capitalize(ownerState.margin)}`], ownerState.fullWidth && styles.fullWidth);
473
+ }
474
+ })(({
475
+ ownerState
476
+ }) => _extends$1({
477
+ display: 'inline-flex',
478
+ flexDirection: 'column',
479
+ position: 'relative',
480
+ // Reset fieldset default style.
481
+ minWidth: 0,
482
+ padding: 0,
483
+ margin: 0,
484
+ border: 0,
485
+ verticalAlign: 'top'
486
+ }, ownerState.margin === 'normal' && {
487
+ marginTop: 16,
488
+ marginBottom: 8
489
+ }, ownerState.margin === 'dense' && {
490
+ marginTop: 8,
491
+ marginBottom: 4
492
+ }, ownerState.fullWidth && {
493
+ width: '100%'
494
+ }));
495
+
496
+ /**
497
+ * Provides context such as filled/focused/error/required for form inputs.
498
+ * Relying on the context provides high flexibility and ensures that the state always stays
499
+ * consistent across the children of the `FormControl`.
500
+ * This context is used by the following components:
501
+ *
502
+ * - FormLabel
503
+ * - FormHelperText
504
+ * - Input
505
+ * - InputLabel
506
+ *
507
+ * You can find one composition example below and more going to [the demos](/material-ui/react-text-field/#components).
508
+ *
509
+ * ```jsx
510
+ * <FormControl>
511
+ * <InputLabel htmlFor="my-input">Email address</InputLabel>
512
+ * <Input id="my-input" aria-describedby="my-helper-text" />
513
+ * <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
514
+ * </FormControl>
515
+ * ```
516
+ *
517
+ * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies.
518
+ * For instance, only one input can be focused at the same time, the state shouldn't be shared.
519
+ */
520
+ const FormControl = /*#__PURE__*/React.forwardRef(function FormControl(inProps, ref) {
521
+ const props = useDefaultProps({
522
+ props: inProps,
523
+ name: 'MuiFormControl'
524
+ });
525
+ const {
526
+ children,
527
+ className,
528
+ color = 'primary',
529
+ component = 'div',
530
+ disabled = false,
531
+ error = false,
532
+ focused: visuallyFocused,
533
+ fullWidth = false,
534
+ hiddenLabel = false,
535
+ margin = 'none',
536
+ required = false,
537
+ size = 'medium',
538
+ variant = 'outlined'
539
+ } = props,
540
+ other = _objectWithoutPropertiesLoose$1(props, _excluded$3);
541
+ const ownerState = _extends$1({}, props, {
542
+ color,
543
+ component,
544
+ disabled,
545
+ error,
546
+ fullWidth,
547
+ hiddenLabel,
548
+ margin,
549
+ required,
550
+ size,
551
+ variant
552
+ });
553
+ const classes = useUtilityClasses$2(ownerState);
554
+ const [adornedStart, setAdornedStart] = React.useState(() => {
555
+ // We need to iterate through the children and find the Input in order
556
+ // to fully support server-side rendering.
557
+ let initialAdornedStart = false;
558
+ if (children) {
559
+ React.Children.forEach(children, child => {
560
+ if (!isMuiElement(child, ['Input', 'Select'])) {
561
+ return;
562
+ }
563
+ const input = isMuiElement(child, ['Select']) ? child.props.input : child;
564
+ if (input && isAdornedStart(input.props)) {
565
+ initialAdornedStart = true;
566
+ }
567
+ });
568
+ }
569
+ return initialAdornedStart;
570
+ });
571
+ const [filled, setFilled] = React.useState(() => {
572
+ // We need to iterate through the children and find the Input in order
573
+ // to fully support server-side rendering.
574
+ let initialFilled = false;
575
+ if (children) {
576
+ React.Children.forEach(children, child => {
577
+ if (!isMuiElement(child, ['Input', 'Select'])) {
578
+ return;
579
+ }
580
+ if (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) {
581
+ initialFilled = true;
582
+ }
583
+ });
584
+ }
585
+ return initialFilled;
586
+ });
587
+ const [focusedState, setFocused] = React.useState(false);
588
+ if (disabled && focusedState) {
589
+ setFocused(false);
590
+ }
591
+ const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState;
592
+ let registerEffect;
593
+ if (process.env.NODE_ENV !== 'production') {
594
+ // eslint-disable-next-line react-hooks/rules-of-hooks
595
+ const registeredInput = React.useRef(false);
596
+ registerEffect = () => {
597
+ if (registeredInput.current) {
598
+ console.error(['MUI: There are multiple `InputBase` components inside a FormControl.', 'This creates visual inconsistencies, only use one `InputBase`.'].join('\n'));
599
+ }
600
+ registeredInput.current = true;
601
+ return () => {
602
+ registeredInput.current = false;
603
+ };
604
+ };
605
+ }
606
+ const childContext = React.useMemo(() => {
607
+ return {
608
+ adornedStart,
609
+ setAdornedStart,
610
+ color,
611
+ disabled,
612
+ error,
613
+ filled,
614
+ focused,
615
+ fullWidth,
616
+ hiddenLabel,
617
+ size,
618
+ onBlur: () => {
619
+ setFocused(false);
620
+ },
621
+ onEmpty: () => {
622
+ setFilled(false);
623
+ },
624
+ onFilled: () => {
625
+ setFilled(true);
626
+ },
627
+ onFocus: () => {
628
+ setFocused(true);
629
+ },
630
+ registerEffect,
631
+ required,
632
+ variant
633
+ };
634
+ }, [adornedStart, color, disabled, error, filled, focused, fullWidth, hiddenLabel, registerEffect, required, size, variant]);
635
+ return /*#__PURE__*/jsxRuntimeExports.jsx(FormControlContext.Provider, {
636
+ value: childContext,
637
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(FormControlRoot, _extends$1({
638
+ as: component,
639
+ ownerState: ownerState,
640
+ className: clsx$1(classes.root, className),
641
+ ref: ref
642
+ }, other, {
643
+ children: children
644
+ }))
645
+ });
646
+ });
647
+ process.env.NODE_ENV !== "production" ? FormControl.propTypes /* remove-proptypes */ = {
648
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
649
+ // │ These PropTypes are generated from the TypeScript type definitions. │
650
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
651
+ // └─────────────────────────────────────────────────────────────────────┘
652
+ /**
653
+ * The content of the component.
654
+ */
655
+ children: PropTypes.node,
656
+ /**
657
+ * Override or extend the styles applied to the component.
658
+ */
659
+ classes: PropTypes.object,
660
+ /**
661
+ * @ignore
662
+ */
663
+ className: PropTypes.string,
664
+ /**
665
+ * The color of the component.
666
+ * It supports both default and custom theme colors, which can be added as shown in the
667
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
668
+ * @default 'primary'
669
+ */
670
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
671
+ /**
672
+ * The component used for the root node.
673
+ * Either a string to use a HTML element or a component.
674
+ */
675
+ component: PropTypes.elementType,
676
+ /**
677
+ * If `true`, the label, input and helper text should be displayed in a disabled state.
678
+ * @default false
679
+ */
680
+ disabled: PropTypes.bool,
681
+ /**
682
+ * If `true`, the label is displayed in an error state.
683
+ * @default false
684
+ */
685
+ error: PropTypes.bool,
686
+ /**
687
+ * If `true`, the component is displayed in focused state.
688
+ */
689
+ focused: PropTypes.bool,
690
+ /**
691
+ * If `true`, the component will take up the full width of its container.
692
+ * @default false
693
+ */
694
+ fullWidth: PropTypes.bool,
695
+ /**
696
+ * If `true`, the label is hidden.
697
+ * This is used to increase density for a `FilledInput`.
698
+ * Be sure to add `aria-label` to the `input` element.
699
+ * @default false
700
+ */
701
+ hiddenLabel: PropTypes.bool,
702
+ /**
703
+ * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
704
+ * @default 'none'
705
+ */
706
+ margin: PropTypes.oneOf(['dense', 'none', 'normal']),
707
+ /**
708
+ * If `true`, the label will indicate that the `input` is required.
709
+ * @default false
710
+ */
711
+ required: PropTypes.bool,
712
+ /**
713
+ * The size of the component.
714
+ * @default 'medium'
715
+ */
716
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
717
+ /**
718
+ * The system prop that allows defining system overrides as well as additional CSS styles.
719
+ */
720
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
721
+ /**
722
+ * The variant to use.
723
+ * @default 'outlined'
724
+ */
725
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
726
+ } : void 0;
727
+ var FormControl$1 = FormControl;
728
+
729
+ function getFormHelperTextUtilityClasses(slot) {
730
+ return generateUtilityClass('MuiFormHelperText', slot);
731
+ }
732
+ const formHelperTextClasses = generateUtilityClasses('MuiFormHelperText', ['root', 'error', 'disabled', 'sizeSmall', 'sizeMedium', 'contained', 'focused', 'filled', 'required']);
733
+ var formHelperTextClasses$1 = formHelperTextClasses;
734
+
735
+ var _span;
736
+ const _excluded$2 = ["children", "className", "component", "disabled", "error", "filled", "focused", "margin", "required", "variant"];
737
+ const useUtilityClasses$1 = ownerState => {
738
+ const {
739
+ classes,
740
+ contained,
741
+ size,
742
+ disabled,
743
+ error,
744
+ filled,
745
+ focused,
746
+ required
747
+ } = ownerState;
748
+ const slots = {
749
+ root: ['root', disabled && 'disabled', error && 'error', size && `size${capitalize(size)}`, contained && 'contained', focused && 'focused', filled && 'filled', required && 'required']
750
+ };
751
+ return composeClasses(slots, getFormHelperTextUtilityClasses, classes);
752
+ };
753
+ const FormHelperTextRoot = styled$1('p', {
754
+ name: 'MuiFormHelperText',
755
+ slot: 'Root',
756
+ overridesResolver: (props, styles) => {
757
+ const {
758
+ ownerState
759
+ } = props;
760
+ return [styles.root, ownerState.size && styles[`size${capitalize(ownerState.size)}`], ownerState.contained && styles.contained, ownerState.filled && styles.filled];
761
+ }
762
+ })(({
763
+ theme,
764
+ ownerState
765
+ }) => _extends$1({
766
+ color: (theme.vars || theme).palette.text.secondary
767
+ }, theme.typography.caption, {
768
+ textAlign: 'left',
769
+ marginTop: 3,
770
+ marginRight: 0,
771
+ marginBottom: 0,
772
+ marginLeft: 0,
773
+ [`&.${formHelperTextClasses$1.disabled}`]: {
774
+ color: (theme.vars || theme).palette.text.disabled
775
+ },
776
+ [`&.${formHelperTextClasses$1.error}`]: {
777
+ color: (theme.vars || theme).palette.error.main
778
+ }
779
+ }, ownerState.size === 'small' && {
780
+ marginTop: 4
781
+ }, ownerState.contained && {
782
+ marginLeft: 14,
783
+ marginRight: 14
784
+ }));
785
+ const FormHelperText = /*#__PURE__*/React.forwardRef(function FormHelperText(inProps, ref) {
786
+ const props = useDefaultProps({
787
+ props: inProps,
788
+ name: 'MuiFormHelperText'
789
+ });
790
+ const {
791
+ children,
792
+ className,
793
+ component = 'p'
794
+ } = props,
795
+ other = _objectWithoutPropertiesLoose$1(props, _excluded$2);
796
+ const muiFormControl = useFormControl();
797
+ const fcs = formControlState({
798
+ props,
799
+ muiFormControl,
800
+ states: ['variant', 'size', 'disabled', 'error', 'filled', 'focused', 'required']
801
+ });
802
+ const ownerState = _extends$1({}, props, {
803
+ component,
804
+ contained: fcs.variant === 'filled' || fcs.variant === 'outlined',
805
+ variant: fcs.variant,
806
+ size: fcs.size,
807
+ disabled: fcs.disabled,
808
+ error: fcs.error,
809
+ filled: fcs.filled,
810
+ focused: fcs.focused,
811
+ required: fcs.required
812
+ });
813
+ const classes = useUtilityClasses$1(ownerState);
814
+ return /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextRoot, _extends$1({
815
+ as: component,
816
+ ownerState: ownerState,
817
+ className: clsx$1(classes.root, className),
818
+ ref: ref
819
+ }, other, {
820
+ children: children === ' ' ? // notranslate needed while Google Translate will not fix zero-width space issue
821
+ _span || (_span = /*#__PURE__*/jsxRuntimeExports.jsx("span", {
822
+ className: "notranslate",
823
+ children: "\u200B"
824
+ })) : children
825
+ }));
826
+ });
827
+ process.env.NODE_ENV !== "production" ? FormHelperText.propTypes /* remove-proptypes */ = {
828
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
829
+ // │ These PropTypes are generated from the TypeScript type definitions. │
830
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
831
+ // └─────────────────────────────────────────────────────────────────────┘
832
+ /**
833
+ * The content of the component.
834
+ *
835
+ * If `' '` is provided, the component reserves one line height for displaying a future message.
836
+ */
837
+ children: PropTypes.node,
838
+ /**
839
+ * Override or extend the styles applied to the component.
840
+ */
841
+ classes: PropTypes.object,
842
+ /**
843
+ * @ignore
844
+ */
845
+ className: PropTypes.string,
846
+ /**
847
+ * The component used for the root node.
848
+ * Either a string to use a HTML element or a component.
849
+ */
850
+ component: PropTypes.elementType,
851
+ /**
852
+ * If `true`, the helper text should be displayed in a disabled state.
853
+ */
854
+ disabled: PropTypes.bool,
855
+ /**
856
+ * If `true`, helper text should be displayed in an error state.
857
+ */
858
+ error: PropTypes.bool,
859
+ /**
860
+ * If `true`, the helper text should use filled classes key.
861
+ */
862
+ filled: PropTypes.bool,
863
+ /**
864
+ * If `true`, the helper text should use focused classes key.
865
+ */
866
+ focused: PropTypes.bool,
867
+ /**
868
+ * If `dense`, will adjust vertical spacing. This is normally obtained via context from
869
+ * FormControl.
870
+ */
871
+ margin: PropTypes.oneOf(['dense']),
872
+ /**
873
+ * If `true`, the helper text should use required classes key.
874
+ */
875
+ required: PropTypes.bool,
876
+ /**
877
+ * The system prop that allows defining system overrides as well as additional CSS styles.
878
+ */
879
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
880
+ /**
881
+ * The variant to use.
882
+ */
883
+ variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['filled', 'outlined', 'standard']), PropTypes.string])
884
+ } : void 0;
885
+ var FormHelperText$1 = FormHelperText;
886
+
887
+ function getTextFieldUtilityClass(slot) {
888
+ return generateUtilityClass('MuiTextField', slot);
889
+ }
890
+ generateUtilityClasses('MuiTextField', ['root']);
891
+
892
+ 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"];
893
+ const variantComponent = {
894
+ standard: Input,
895
+ filled: FilledInput,
896
+ outlined: OutlinedInput
897
+ };
898
+ const useUtilityClasses = ownerState => {
899
+ const {
900
+ classes
901
+ } = ownerState;
902
+ const slots = {
903
+ root: ['root']
904
+ };
905
+ return composeClasses(slots, getTextFieldUtilityClass, classes);
906
+ };
907
+ const TextFieldRoot = styled$1(FormControl$1, {
908
+ name: 'MuiTextField',
909
+ slot: 'Root',
910
+ overridesResolver: (props, styles) => styles.root
911
+ })({});
912
+
913
+ /**
914
+ * The `TextField` is a convenience wrapper for the most common cases (80%).
915
+ * It cannot be all things to all people, otherwise the API would grow out of control.
916
+ *
917
+ * ## Advanced Configuration
918
+ *
919
+ * It's important to understand that the text field is a simple abstraction
920
+ * on top of the following components:
921
+ *
922
+ * - [FormControl](/material-ui/api/form-control/)
923
+ * - [InputLabel](/material-ui/api/input-label/)
924
+ * - [FilledInput](/material-ui/api/filled-input/)
925
+ * - [OutlinedInput](/material-ui/api/outlined-input/)
926
+ * - [Input](/material-ui/api/input/)
927
+ * - [FormHelperText](/material-ui/api/form-helper-text/)
928
+ *
929
+ * If you wish to alter the props applied to the `input` element, you can do so as follows:
930
+ *
931
+ * ```jsx
932
+ * const inputProps = {
933
+ * step: 300,
934
+ * };
935
+ *
936
+ * return <TextField id="time" type="time" inputProps={inputProps} />;
937
+ * ```
938
+ *
939
+ * For advanced cases, please look at the source of TextField by clicking on the
940
+ * "Edit this page" button above. Consider either:
941
+ *
942
+ * - using the upper case props for passing values directly to the components
943
+ * - using the underlying components directly as shown in the demos
944
+ */
945
+ const TextField = /*#__PURE__*/React.forwardRef(function TextField(inProps, ref) {
946
+ const props = useDefaultProps({
947
+ props: inProps,
948
+ name: 'MuiTextField'
949
+ });
950
+ const {
951
+ autoComplete,
952
+ autoFocus = false,
953
+ children,
954
+ className,
955
+ color = 'primary',
956
+ defaultValue,
957
+ disabled = false,
958
+ error = false,
959
+ FormHelperTextProps,
960
+ fullWidth = false,
961
+ helperText,
962
+ id: idOverride,
963
+ InputLabelProps,
964
+ inputProps,
965
+ InputProps,
966
+ inputRef,
967
+ label,
968
+ maxRows,
969
+ minRows,
970
+ multiline = false,
971
+ name,
972
+ onBlur,
973
+ onChange,
974
+ onFocus,
975
+ placeholder,
976
+ required = false,
977
+ rows,
978
+ select = false,
979
+ SelectProps,
980
+ type,
981
+ value,
982
+ variant = 'outlined'
983
+ } = props,
984
+ other = _objectWithoutPropertiesLoose$1(props, _excluded$1);
985
+ const ownerState = _extends$1({}, props, {
986
+ autoFocus,
987
+ color,
988
+ disabled,
989
+ error,
990
+ fullWidth,
991
+ multiline,
992
+ required,
993
+ select,
994
+ variant
995
+ });
996
+ const classes = useUtilityClasses(ownerState);
997
+ if (process.env.NODE_ENV !== 'production') {
998
+ if (select && !children) {
999
+ console.error('MUI: `children` must be passed when using the `TextField` component with `select`.');
1000
+ }
1001
+ }
1002
+ const InputMore = {};
1003
+ if (variant === 'outlined') {
1004
+ if (InputLabelProps && typeof InputLabelProps.shrink !== 'undefined') {
1005
+ InputMore.notched = InputLabelProps.shrink;
1006
+ }
1007
+ InputMore.label = label;
1008
+ }
1009
+ if (select) {
1010
+ // unset defaults from textbox inputs
1011
+ if (!SelectProps || !SelectProps.native) {
1012
+ InputMore.id = undefined;
1013
+ }
1014
+ InputMore['aria-describedby'] = undefined;
1015
+ }
1016
+ const id = useId(idOverride);
1017
+ const helperTextId = helperText && id ? `${id}-helper-text` : undefined;
1018
+ const inputLabelId = label && id ? `${id}-label` : undefined;
1019
+ const InputComponent = variantComponent[variant];
1020
+ const InputElement = /*#__PURE__*/jsxRuntimeExports.jsx(InputComponent, _extends$1({
1021
+ "aria-describedby": helperTextId,
1022
+ autoComplete: autoComplete,
1023
+ autoFocus: autoFocus,
1024
+ defaultValue: defaultValue,
1025
+ fullWidth: fullWidth,
1026
+ multiline: multiline,
1027
+ name: name,
1028
+ rows: rows,
1029
+ maxRows: maxRows,
1030
+ minRows: minRows,
1031
+ type: type,
1032
+ value: value,
1033
+ id: id,
1034
+ inputRef: inputRef,
1035
+ onBlur: onBlur,
1036
+ onChange: onChange,
1037
+ onFocus: onFocus,
1038
+ placeholder: placeholder,
1039
+ inputProps: inputProps
1040
+ }, InputMore, InputProps));
1041
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(TextFieldRoot, _extends$1({
1042
+ className: clsx$1(classes.root, className),
1043
+ disabled: disabled,
1044
+ error: error,
1045
+ fullWidth: fullWidth,
1046
+ ref: ref,
1047
+ required: required,
1048
+ color: color,
1049
+ variant: variant,
1050
+ ownerState: ownerState
1051
+ }, other, {
1052
+ children: [label != null && label !== '' && /*#__PURE__*/jsxRuntimeExports.jsx(InputLabel$1, _extends$1({
1053
+ htmlFor: id,
1054
+ id: inputLabelId
1055
+ }, InputLabelProps, {
1056
+ children: label
1057
+ })), select ? /*#__PURE__*/jsxRuntimeExports.jsx(Select, _extends$1({
1058
+ "aria-describedby": helperTextId,
1059
+ id: id,
1060
+ labelId: inputLabelId,
1061
+ value: value,
1062
+ input: InputElement
1063
+ }, SelectProps, {
1064
+ children: children
1065
+ })) : InputElement, helperText && /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperText$1, _extends$1({
1066
+ id: helperTextId
1067
+ }, FormHelperTextProps, {
1068
+ children: helperText
1069
+ }))]
1070
+ }));
1071
+ });
1072
+ process.env.NODE_ENV !== "production" ? TextField.propTypes /* remove-proptypes */ = {
1073
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
1074
+ // │ These PropTypes are generated from the TypeScript type definitions. │
1075
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
1076
+ // └─────────────────────────────────────────────────────────────────────┘
1077
+ /**
1078
+ * This prop helps users to fill forms faster, especially on mobile devices.
1079
+ * The name can be confusing, as it's more like an autofill.
1080
+ * You can learn more about it [following the specification](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill).
1081
+ */
1082
+ autoComplete: PropTypes.string,
1083
+ /**
1084
+ * If `true`, the `input` element is focused during the first mount.
1085
+ * @default false
1086
+ */
1087
+ autoFocus: PropTypes.bool,
1088
+ /**
1089
+ * @ignore
1090
+ */
1091
+ children: PropTypes.node,
1092
+ /**
1093
+ * Override or extend the styles applied to the component.
1094
+ */
1095
+ classes: PropTypes.object,
1096
+ /**
1097
+ * @ignore
1098
+ */
1099
+ className: PropTypes.string,
1100
+ /**
1101
+ * The color of the component.
1102
+ * It supports both default and custom theme colors, which can be added as shown in the
1103
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
1104
+ * @default 'primary'
1105
+ */
1106
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
1107
+ /**
1108
+ * The default value. Use when the component is not controlled.
1109
+ */
1110
+ defaultValue: PropTypes.any,
1111
+ /**
1112
+ * If `true`, the component is disabled.
1113
+ * @default false
1114
+ */
1115
+ disabled: PropTypes.bool,
1116
+ /**
1117
+ * If `true`, the label is displayed in an error state.
1118
+ * @default false
1119
+ */
1120
+ error: PropTypes.bool,
1121
+ /**
1122
+ * Props applied to the [`FormHelperText`](/material-ui/api/form-helper-text/) element.
1123
+ */
1124
+ FormHelperTextProps: PropTypes.object,
1125
+ /**
1126
+ * If `true`, the input will take up the full width of its container.
1127
+ * @default false
1128
+ */
1129
+ fullWidth: PropTypes.bool,
1130
+ /**
1131
+ * The helper text content.
1132
+ */
1133
+ helperText: PropTypes.node,
1134
+ /**
1135
+ * The id of the `input` element.
1136
+ * Use this prop to make `label` and `helperText` accessible for screen readers.
1137
+ */
1138
+ id: PropTypes.string,
1139
+ /**
1140
+ * Props applied to the [`InputLabel`](/material-ui/api/input-label/) element.
1141
+ * Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
1142
+ */
1143
+ InputLabelProps: PropTypes.object,
1144
+ /**
1145
+ * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
1146
+ */
1147
+ inputProps: PropTypes.object,
1148
+ /**
1149
+ * Props applied to the Input element.
1150
+ * It will be a [`FilledInput`](/material-ui/api/filled-input/),
1151
+ * [`OutlinedInput`](/material-ui/api/outlined-input/) or [`Input`](/material-ui/api/input/)
1152
+ * component depending on the `variant` prop value.
1153
+ */
1154
+ InputProps: PropTypes.object,
1155
+ /**
1156
+ * Pass a ref to the `input` element.
1157
+ */
1158
+ inputRef: refType,
1159
+ /**
1160
+ * The label content.
1161
+ */
1162
+ label: PropTypes.node,
1163
+ /**
1164
+ * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
1165
+ * @default 'none'
1166
+ */
1167
+ margin: PropTypes.oneOf(['dense', 'none', 'normal']),
1168
+ /**
1169
+ * Maximum number of rows to display when multiline option is set to true.
1170
+ */
1171
+ maxRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1172
+ /**
1173
+ * Minimum number of rows to display when multiline option is set to true.
1174
+ */
1175
+ minRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1176
+ /**
1177
+ * If `true`, a `textarea` element is rendered instead of an input.
1178
+ * @default false
1179
+ */
1180
+ multiline: PropTypes.bool,
1181
+ /**
1182
+ * Name attribute of the `input` element.
1183
+ */
1184
+ name: PropTypes.string,
1185
+ /**
1186
+ * @ignore
1187
+ */
1188
+ onBlur: PropTypes.func,
1189
+ /**
1190
+ * Callback fired when the value is changed.
1191
+ *
1192
+ * @param {object} event The event source of the callback.
1193
+ * You can pull out the new value by accessing `event.target.value` (string).
1194
+ */
1195
+ onChange: PropTypes.func,
1196
+ /**
1197
+ * @ignore
1198
+ */
1199
+ onFocus: PropTypes.func,
1200
+ /**
1201
+ * The short hint displayed in the `input` before the user enters a value.
1202
+ */
1203
+ placeholder: PropTypes.string,
1204
+ /**
1205
+ * If `true`, the label is displayed as required and the `input` element is required.
1206
+ * @default false
1207
+ */
1208
+ required: PropTypes.bool,
1209
+ /**
1210
+ * Number of rows to display when multiline option is set to true.
1211
+ */
1212
+ rows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1213
+ /**
1214
+ * Render a [`Select`](/material-ui/api/select/) element while passing the Input element to `Select` as `input` parameter.
1215
+ * If this option is set you must pass the options of the select as children.
1216
+ * @default false
1217
+ */
1218
+ select: PropTypes.bool,
1219
+ /**
1220
+ * Props applied to the [`Select`](/material-ui/api/select/) element.
1221
+ */
1222
+ SelectProps: PropTypes.object,
1223
+ /**
1224
+ * The size of the component.
1225
+ */
1226
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
1227
+ /**
1228
+ * The system prop that allows defining system overrides as well as additional CSS styles.
1229
+ */
1230
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1231
+ /**
1232
+ * 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).
1233
+ */
1234
+ type: PropTypes /* @typescript-to-proptypes-ignore */.string,
1235
+ /**
1236
+ * The value of the `input` element, required for a controlled component.
1237
+ */
1238
+ value: PropTypes.any,
1239
+ /**
1240
+ * The variant to use.
1241
+ * @default 'outlined'
1242
+ */
1243
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
1244
+ } : void 0;
1245
+ var TextField$1 = TextField;
16
1246
 
17
1247
  const SUBMIT_FILTER_STROKE_TIME = 500;
18
1248
  const InputNumberInterval = props => {
@@ -54,7 +1284,7 @@ const InputNumberInterval = props => {
54
1284
  const newLowerBound = event.target.value;
55
1285
  updateFilterValue(newLowerBound, filterValueState[1]);
56
1286
  };
57
- return /*#__PURE__*/React.createElement(Box, {
1287
+ return /*#__PURE__*/React.createElement(Box$1, {
58
1288
  sx: {
59
1289
  display: 'inline-flex',
60
1290
  flexDirection: 'row',
@@ -62,7 +1292,7 @@ const InputNumberInterval = props => {
62
1292
  height: 48,
63
1293
  pl: '20px'
64
1294
  }
65
- }, /*#__PURE__*/React.createElement(TextField, {
1295
+ }, /*#__PURE__*/React.createElement(TextField$1, {
66
1296
  name: "lower-bound-input",
67
1297
  placeholder: "From",
68
1298
  label: "From",
@@ -74,7 +1304,7 @@ const InputNumberInterval = props => {
74
1304
  sx: {
75
1305
  mr: 2
76
1306
  }
77
- }), /*#__PURE__*/React.createElement(TextField, {
1307
+ }), /*#__PURE__*/React.createElement(TextField$1, {
78
1308
  name: "upper-bound-input",
79
1309
  placeholder: "To",
80
1310
  label: "To",
@@ -106,8 +1336,8 @@ const isBetweenOperator = {
106
1336
  if (typeof filterItem.value[0] !== 'number' || typeof filterItem.value[1] !== 'number') {
107
1337
  return null;
108
1338
  }
109
- return value => {
110
- return value !== null && value !== undefined && filterItem.value[0] <= value && value <= filterItem.value[1];
1339
+ return params => {
1340
+ return params.value !== null && params.value !== undefined && filterItem.value[0] <= params.value && params.value <= filterItem.value[1];
111
1341
  };
112
1342
  },
113
1343
  InputComponent: InputNumberInterval
@@ -123,14 +1353,14 @@ const doesNotContain = {
123
1353
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
124
1354
  return null;
125
1355
  }
126
- return value => {
1356
+ return params => {
127
1357
  if (filterItem.value.length === 0) {
128
1358
  return true;
129
1359
  }
130
- if (value == null) {
1360
+ if (params.value == null) {
131
1361
  return true;
132
1362
  }
133
- if (String(value).indexOf(filterItem.value) !== -1) {
1363
+ if (String(params.value).indexOf(filterItem.value) !== -1) {
134
1364
  return false;
135
1365
  }
136
1366
  return true;
@@ -147,11 +1377,11 @@ const doesNotEndWithOperator = {
147
1377
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
148
1378
  return null;
149
1379
  }
150
- return value => {
151
- if (value == null) {
1380
+ return params => {
1381
+ if (params.value == null) {
152
1382
  return true;
153
1383
  }
154
- return !String(value).endsWith(filterItem.value);
1384
+ return !String(params.value).endsWith(filterItem.value);
155
1385
  };
156
1386
  },
157
1387
  InputComponent: GridFilterInputValue
@@ -165,11 +1395,11 @@ const doesNotEqual = {
165
1395
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
166
1396
  return null;
167
1397
  }
168
- return value => {
169
- if (value == null) {
1398
+ return params => {
1399
+ if (params.value == null) {
170
1400
  return true;
171
1401
  }
172
- if (String(value) === filterItem.value) {
1402
+ if (String(params.value) === filterItem.value) {
173
1403
  return false;
174
1404
  }
175
1405
  return true;
@@ -186,11 +1416,11 @@ const doesNotHaveOperator = {
186
1416
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
187
1417
  return null;
188
1418
  }
189
- return value => {
190
- if (value == null) {
1419
+ return params => {
1420
+ if (params.value == null) {
191
1421
  return true;
192
1422
  }
193
- const cellValues = Array.isArray(value) ? value : [value];
1423
+ const cellValues = Array.isArray(params.value) ? params.value : [params.value];
194
1424
  return !cellValues.map(value => String(value)).includes(filterItem.value);
195
1425
  };
196
1426
  },
@@ -208,11 +1438,11 @@ const doesNotStartWithOperator = {
208
1438
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
209
1439
  return null;
210
1440
  }
211
- return value => {
212
- if (value == null) {
1441
+ return params => {
1442
+ if (params.value == null) {
213
1443
  return true;
214
1444
  }
215
- return !String(value).startsWith(filterItem.value);
1445
+ return !String(params.value).startsWith(filterItem.value);
216
1446
  };
217
1447
  },
218
1448
  InputComponent: GridFilterInputValue
@@ -226,11 +1456,11 @@ const hasOperator = {
226
1456
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
227
1457
  return null;
228
1458
  }
229
- return value => {
230
- if (value == null) {
1459
+ return params => {
1460
+ if (params.value == null) {
231
1461
  return false;
232
1462
  }
233
- const cellValues = Array.isArray(value) ? value : [value];
1463
+ const cellValues = Array.isArray(params.value) ? params.value : [params.value];
234
1464
  return cellValues.map(value => String(value)).includes(filterItem.value);
235
1465
  };
236
1466
  },
@@ -248,11 +1478,11 @@ const hasOnlyOperator = {
248
1478
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
249
1479
  return null;
250
1480
  }
251
- return value => {
252
- if (value == null) {
1481
+ return params => {
1482
+ if (params.value == null) {
253
1483
  return false;
254
1484
  }
255
- const cellValues = Array.isArray(value) ? value : [value];
1485
+ const cellValues = Array.isArray(params.value) ? params.value : [params.value];
256
1486
  return cellValues.length === 1 && String(cellValues[0]) === filterItem.value;
257
1487
  };
258
1488
  },
@@ -270,14 +1500,14 @@ const isOperator = {
270
1500
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
271
1501
  return null;
272
1502
  }
273
- return value => {
274
- if (value == null) {
1503
+ return params => {
1504
+ if (params.value == null) {
275
1505
  return false;
276
1506
  }
277
- if (Array.isArray(value)) {
1507
+ if (Array.isArray(params.value)) {
278
1508
  return false;
279
1509
  }
280
- return String(value) === filterItem.value;
1510
+ return String(params.value) === filterItem.value;
281
1511
  };
282
1512
  },
283
1513
  InputComponent: GridFilterInputValue
@@ -294,14 +1524,14 @@ const isNotOperator = {
294
1524
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
295
1525
  return null;
296
1526
  }
297
- return value => {
298
- if (value == null) {
1527
+ return params => {
1528
+ if (params.value == null) {
299
1529
  return true;
300
1530
  }
301
- if (Array.isArray(value)) {
1531
+ if (Array.isArray(params.value)) {
302
1532
  return true;
303
1533
  }
304
- return String(value) !== filterItem.value;
1534
+ return String(params.value) !== filterItem.value;
305
1535
  };
306
1536
  },
307
1537
  InputComponent: GridFilterInputValue
@@ -318,14 +1548,14 @@ const containsAnyOfOperator = {
318
1548
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
319
1549
  return null;
320
1550
  }
321
- return value => {
1551
+ return params => {
322
1552
  if (filterItem.value.length === 0) {
323
1553
  return true;
324
1554
  }
325
- if (value == null) {
1555
+ if (params.value == null) {
326
1556
  return false;
327
1557
  }
328
- const paramValues = Array.isArray(value) ? value : [value];
1558
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
329
1559
  let match = false;
330
1560
  filterItem.value.forEach(filteredValue => {
331
1561
  paramValues.forEach(paramValue => {
@@ -348,14 +1578,14 @@ const doesNotContainAnyOfOperator = {
348
1578
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
349
1579
  return null;
350
1580
  }
351
- return value => {
1581
+ return params => {
352
1582
  if (filterItem.value.length === 0) {
353
1583
  return true;
354
1584
  }
355
- if (value == null) {
1585
+ if (params.value == null) {
356
1586
  return true;
357
1587
  }
358
- const paramValues = Array.isArray(value) ? value : [value];
1588
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
359
1589
  for (const filteredValue of filterItem.value) {
360
1590
  for (const paramValue of paramValues) {
361
1591
  if (String(paramValue).indexOf(filteredValue) !== -1) {
@@ -377,14 +1607,14 @@ const doesNotEndWithAnyOfOperator = {
377
1607
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
378
1608
  return null;
379
1609
  }
380
- return value => {
1610
+ return params => {
381
1611
  if (filterItem.value.length === 0) {
382
1612
  return true;
383
1613
  }
384
- if (value == null) {
1614
+ if (params.value == null) {
385
1615
  return true;
386
1616
  }
387
- const paramValues = Array.isArray(value) ? value : [value];
1617
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
388
1618
  for (const filteredValue of filterItem.value) {
389
1619
  for (const paramValue of paramValues) {
390
1620
  if (String(paramValue).endsWith(filteredValue)) {
@@ -406,11 +1636,11 @@ const doesNotHaveAnyOf = {
406
1636
  if (!filterItem.field || !filterItem.value || !Array.isArray(filterItem.value) || filterItem.value.length === 0) {
407
1637
  return null;
408
1638
  }
409
- return value => {
410
- if (value == null) {
1639
+ return params => {
1640
+ if (params.value == null) {
411
1641
  return true;
412
1642
  }
413
- const cellValues = Array.isArray(value) ? value : [value];
1643
+ const cellValues = Array.isArray(params.value) ? params.value : [params.value];
414
1644
 
415
1645
  // Return true only if none of the filter values are in the cell values
416
1646
  return filterItem.value.every(filterVal => !cellValues.map(value => String(value)).includes(filterVal));
@@ -430,14 +1660,14 @@ const doesNotStartWithAnyOfOperator = {
430
1660
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
431
1661
  return null;
432
1662
  }
433
- return value => {
1663
+ return params => {
434
1664
  if (filterItem.value.length === 0) {
435
1665
  return true;
436
1666
  }
437
- if (value == null) {
1667
+ if (params.value == null) {
438
1668
  return true;
439
1669
  }
440
- const paramValues = Array.isArray(value) ? value : [value];
1670
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
441
1671
  for (const filteredValue of filterItem.value) {
442
1672
  for (const paramValue of paramValues) {
443
1673
  if (String(paramValue).startsWith(filteredValue)) {
@@ -459,14 +1689,14 @@ const endsWithAnyOfOperator = {
459
1689
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
460
1690
  return null;
461
1691
  }
462
- return value => {
1692
+ return params => {
463
1693
  if (filterItem.value.length === 0) {
464
1694
  return true;
465
1695
  }
466
- if (value == null) {
1696
+ if (params.value == null) {
467
1697
  return false;
468
1698
  }
469
- const paramValues = Array.isArray(value) ? value : [value];
1699
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
470
1700
  let match = false;
471
1701
  filterItem.value.forEach(filteredValue => {
472
1702
  paramValues.forEach(paramValue => {
@@ -489,14 +1719,14 @@ const hasAllOfOperator = {
489
1719
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
490
1720
  return null;
491
1721
  }
492
- return value => {
1722
+ return params => {
493
1723
  if (filterItem.value.length === 0) {
494
1724
  return true;
495
1725
  }
496
- if (value == null) {
1726
+ if (params.value == null) {
497
1727
  return false;
498
1728
  }
499
- const cellValues = Array.isArray(value) ? value : [value];
1729
+ const cellValues = Array.isArray(params.value) ? params.value : [params.value];
500
1730
  const cellStrings = cellValues.map(value => String(value));
501
1731
  const filterItemValues = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
502
1732
  return filterItemValues.every(v => cellStrings.includes(v));
@@ -516,14 +1746,14 @@ const hasAnyOfOperator = {
516
1746
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
517
1747
  return null;
518
1748
  }
519
- return value => {
1749
+ return params => {
520
1750
  if (filterItem.value.length === 0) {
521
1751
  return true;
522
1752
  }
523
- if (value == null) {
1753
+ if (params.value == null) {
524
1754
  return false;
525
1755
  }
526
- const cellValues = Array.isArray(value) ? value : [value];
1756
+ const cellValues = Array.isArray(params.value) ? params.value : [params.value];
527
1757
  const filterItemValues = Array.isArray(filterItem.value) ? filterItem.value : [filterItem.value];
528
1758
  return filterItemValues.some(v => cellValues.map(value => String(value)).includes(v));
529
1759
  };
@@ -542,14 +1772,14 @@ const isAnyOfOperator = {
542
1772
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
543
1773
  return null;
544
1774
  }
545
- return value => {
1775
+ return params => {
546
1776
  if (filterItem.value.length === 0) {
547
1777
  return true;
548
1778
  }
549
- if (value == null) {
1779
+ if (params.value == null) {
550
1780
  return false;
551
1781
  }
552
- const paramValues = Array.isArray(value) ? value : [value];
1782
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
553
1783
  for (const paramValue of paramValues) {
554
1784
  if (filterItem.value.includes(String(paramValue))) {
555
1785
  return true;
@@ -572,14 +1802,14 @@ const isNotAnyOfOperator = {
572
1802
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
573
1803
  return null;
574
1804
  }
575
- return value => {
1805
+ return params => {
576
1806
  if (filterItem.value.length === 0) {
577
1807
  return true;
578
1808
  }
579
- if (value == null) {
1809
+ if (params.value == null) {
580
1810
  return true;
581
1811
  }
582
- const paramValues = Array.isArray(value) ? value : [value];
1812
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
583
1813
  for (const paramValue of paramValues) {
584
1814
  if (filterItem.value.includes(String(paramValue))) {
585
1815
  return false;
@@ -602,14 +1832,14 @@ const startsWithAnyOfOperator = {
602
1832
  if (!filterItem.field || !filterItem.value || !filterItem.operator) {
603
1833
  return null;
604
1834
  }
605
- return value => {
1835
+ return params => {
606
1836
  if (filterItem.value.length === 0) {
607
1837
  return true;
608
1838
  }
609
- if (value == null) {
1839
+ if (params.value == null) {
610
1840
  return false;
611
1841
  }
612
- const paramValues = Array.isArray(value) ? value : [value];
1842
+ const paramValues = Array.isArray(params.value) ? params.value : [params.value];
613
1843
  let match = false;
614
1844
  filterItem.value.forEach(filteredValue => {
615
1845
  paramValues.forEach(paramValue => {
@@ -636,15 +1866,15 @@ const isEmptyOperator = {
636
1866
  value: 'isEmpty',
637
1867
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
638
1868
  getApplyFilterFn: _filterItem => {
639
- return value => {
640
- if (value == null) {
1869
+ return params => {
1870
+ if (params.value == null) {
641
1871
  return true;
642
1872
  }
643
- if (Array.isArray(value)) {
644
- return value.length === 0;
1873
+ if (Array.isArray(params.value)) {
1874
+ return params.value.length === 0;
645
1875
  }
646
- if (typeof value === 'string') {
647
- return value.trim() === '';
1876
+ if (typeof params.value === 'string') {
1877
+ return params.value.trim() === '';
648
1878
  }
649
1879
  return false;
650
1880
  };
@@ -656,15 +1886,15 @@ const isNotEmptyOperator = {
656
1886
  value: 'isNotEmpty',
657
1887
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
658
1888
  getApplyFilterFn: _filterItem => {
659
- return value => {
660
- if (value == null) {
1889
+ return params => {
1890
+ if (params.value == null) {
661
1891
  return false;
662
1892
  }
663
- if (Array.isArray(value)) {
664
- return value.length > 0;
1893
+ if (Array.isArray(params.value)) {
1894
+ return params.value.length > 0;
665
1895
  }
666
- if (typeof value === 'string') {
667
- return value.trim() !== '';
1896
+ if (typeof params.value === 'string') {
1897
+ return params.value.trim() !== '';
668
1898
  }
669
1899
  return true;
670
1900
  };
@@ -703,20 +1933,14 @@ const DIMENSION_MODEL_KEY = 'dimension';
703
1933
  const FILTER_SEARCH_KEY = 'searchModel';
704
1934
  const DENSITY_MODEL_KEY = 'densityModel';
705
1935
  const COLUMN_ORDER_MODEL_KEY = 'columnOrderModel';
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];
1936
+ 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];
713
1937
  /**
714
1938
  * Build the localStorage key for a specific grid state category.
715
1939
  * Consumers can use this to read or clear individual state entries directly.
716
1940
  *
717
1941
  * @example
718
1942
  * ```ts
719
- * const key = buildStorageKey({ id: pathname, version: 2, category: PIVOT_ACTIVE_KEY });
1943
+ * const key = buildStorageKey({ id: pathname, version: 2, category: 'filterModel' });
720
1944
  * localStorage.removeItem(key);
721
1945
  * ```
722
1946
  */
@@ -766,22 +1990,6 @@ const clearPreviousVersionStorage = (id, previousLocalStorageVersions) => {
766
1990
  id,
767
1991
  version,
768
1992
  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
785
1993
  })];
786
1994
  for (const keyToDelete of keysToDelete) {
787
1995
  try {
@@ -856,14 +2064,13 @@ const resetStatefulDataGridState = _ref2 => {
856
2064
  * default (all columns visible). Clears the persisted `visibilityModel`
857
2065
  * localStorage entry for the given versions and strips the `_columnVisibility`
858
2066
  * param from the live URL, leaving every other piece of grid state (filters,
859
- * sort, pivot, pagination, pinned columns, …) untouched.
2067
+ * sort, pagination, pinned columns, …) untouched.
860
2068
  *
861
2069
  * This is the visibility-scoped counterpart to `resetStatefulDataGridState`.
862
- * Reach for it at transition points — for example drilling down from pivot
863
- * mode to a flat record view — where a stale pivot-era visibility snapshot
864
- * would otherwise re-seed and keep base columns hidden. Because it leaves the
865
- * other params alone it will not clobber a filter the caller is writing in the
866
- * same transition.
2070
+ * Reach for it at transition points where a stale visibility snapshot would
2071
+ * otherwise re-seed and keep base columns hidden. Because it leaves the other
2072
+ * params alone it will not clobber a filter the caller is writing in the same
2073
+ * transition.
867
2074
  *
868
2075
  * Like `resetStatefulDataGridState`, the URL strip reads `window.location.search`
869
2076
  * directly so it operates on the live URL (the caller's captured snapshot may
@@ -913,7 +2120,7 @@ const COMPRESSED_PREFIX = '~';
913
2120
  * Params listed first are compressed first (least valuable to read in the URL).
914
2121
  * The filter aggregate step uses the special key `_filters_aggregate`.
915
2122
  */
916
- const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_aggregation', '_rowGrouping', '_quickFilterValues', '_pivot'];
2123
+ const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_quickFilterValues'];
917
2124
 
918
2125
  /** Params that are always short and should never be compressed. */
919
2126
  const NEVER_COMPRESS = new Set(['_sortColumn', '_pagination', '_density', '_logicOperator', 'v', 'tab']);
@@ -1154,13 +2361,6 @@ const convertToDisplayFormat = search => {
1154
2361
  const cleanSearch = search.startsWith('?') ? search.slice(1) : search;
1155
2362
  const params = cleanSearch.split('&');
1156
2363
  const converted = params.map(param => {
1157
- const eqIndex = param.indexOf('=');
1158
- if (eqIndex !== -1) {
1159
- const value = param.slice(eqIndex + 1);
1160
- // Skip conversion for compressed values — already URL-safe
1161
- if (isCompressed(value)) return param;
1162
- }
1163
-
1164
2364
  // Handle _sortColumn=[field,direction]
1165
2365
  if (param.startsWith('_sortColumn=')) {
1166
2366
  const value = param.slice('_sortColumn='.length);
@@ -1215,6 +2415,7 @@ const convertToDisplayFormat = search => {
1215
2415
  // Handle _columnOrder=[a,b,c]
1216
2416
  if (param.startsWith('_columnOrder=')) {
1217
2417
  const value = param.slice('_columnOrder='.length);
2418
+ if (value.startsWith('~')) return param; // compressed — skip
1218
2419
  if (value.startsWith('[') && value.endsWith(']')) {
1219
2420
  const inner = value.slice(1, -1);
1220
2421
  return `_columnOrder=${inner}`;
@@ -1222,21 +2423,6 @@ const convertToDisplayFormat = search => {
1222
2423
  return param;
1223
2424
  }
1224
2425
 
1225
- // Handle _rowGrouping=[a,b,c]
1226
- if (param.startsWith('_rowGrouping=')) {
1227
- const value = param.slice('_rowGrouping='.length);
1228
- if (value.startsWith('[') && value.endsWith(']')) {
1229
- const inner = value.slice(1, -1);
1230
- return `_rowGrouping=${inner}`;
1231
- }
1232
- return param;
1233
- }
1234
-
1235
- // _aggregation and _pivot do not use bracket notation — pass through
1236
- if (param.startsWith('_aggregation=') || param.startsWith('_pivot=')) {
1237
- return param;
1238
- }
1239
-
1240
2426
  // Handle _field[operator,type]=value or _field[operator,type]=list[a,b,c]
1241
2427
  const bracketMatch = param.match(/^_([^[]+)\[([^\]]+)\]=(.*)$/);
1242
2428
  if (bracketMatch) {
@@ -1276,13 +2462,6 @@ const convertFromDisplayFormat = (search, columns) => {
1276
2462
  const cleanSearch = search.startsWith('?') ? search.slice(1) : search;
1277
2463
  const params = cleanSearch.split('&');
1278
2464
  const converted = params.map(param => {
1279
- const eqIndex = param.indexOf('=');
1280
- if (eqIndex !== -1) {
1281
- const value = param.slice(eqIndex + 1);
1282
- // Skip conversion for compressed values — already URL-safe
1283
- if (isCompressed(value)) return param;
1284
- }
1285
-
1286
2465
  // Handle _sortColumn=field.direction or _sortColumn=
1287
2466
  if (param.startsWith('_sortColumn=')) {
1288
2467
  const value = param.slice('_sortColumn='.length);
@@ -1334,8 +2513,8 @@ const convertFromDisplayFormat = (search, columns) => {
1334
2513
  // Handle _columnVisibility display `a,b,!c` → internal `[a,b,!c]`.
1335
2514
  if (param.startsWith('_columnVisibility=')) {
1336
2515
  const value = param.slice('_columnVisibility='.length);
1337
- // Already internal (bracketed) — leave it alone.
1338
- if (value.startsWith('[')) {
2516
+ // If it already has brackets, leave it alone
2517
+ if (value.startsWith('[') || value.startsWith('~')) {
1339
2518
  return param;
1340
2519
  }
1341
2520
  return `_columnVisibility=[${value}]`;
@@ -1344,26 +2523,13 @@ const convertFromDisplayFormat = (search, columns) => {
1344
2523
  // Handle _columnOrder=a,b,c
1345
2524
  if (param.startsWith('_columnOrder=')) {
1346
2525
  const value = param.slice('_columnOrder='.length);
1347
- if (value.startsWith('[')) {
2526
+ // If it already has brackets or is compressed, leave it alone
2527
+ if (value.startsWith('[') || value.startsWith('~')) {
1348
2528
  return param;
1349
2529
  }
1350
2530
  return `_columnOrder=[${value}]`;
1351
2531
  }
1352
2532
 
1353
- // Handle _rowGrouping=a,b,c
1354
- if (param.startsWith('_rowGrouping=')) {
1355
- const value = param.slice('_rowGrouping='.length);
1356
- if (value.startsWith('[')) {
1357
- return param;
1358
- }
1359
- return `_rowGrouping=[${value}]`;
1360
- }
1361
-
1362
- // _aggregation, _pivot, _filters — pass through (no bracket conversion needed)
1363
- if (param.startsWith('_aggregation=') || param.startsWith('_pivot=') || param.startsWith('_filters=')) {
1364
- return param;
1365
- }
1366
-
1367
2533
  // Handle field.operator=value (dot notation for filters)
1368
2534
  const dotMatch = param.match(/^([^.]+)\.([a-zA-Z_]+)=(.*)$/);
1369
2535
  if (dotMatch) {
@@ -1406,10 +2572,9 @@ const getDecodedSearchFromUrl = (search, columns) => {
1406
2572
  const hasPaginationDotNotation = /_pagination=[^&[]+\.[^&]+/.test(searchWithoutLeadingQuestion);
1407
2573
  const hasPinnedWithoutBrackets = /(_pinnedColumnsLeft|_pinnedColumnsRight)=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1408
2574
  const hasVisibilityWithoutBrackets = /_columnVisibility=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1409
- const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1410
- const hasRowGroupingWithoutBrackets = /_rowGrouping=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2575
+ const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[~]*(&|$)/.test(searchWithoutLeadingQuestion);
1411
2576
  const hasBracketNotation = /\[.*\]=/.test(searchWithoutLeadingQuestion);
1412
- const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets || hasRowGroupingWithoutBrackets) && !hasBracketNotation;
2577
+ const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets) && !hasBracketNotation;
1413
2578
  if (isDisplayFormat) {
1414
2579
  return '?' + convertFromDisplayFormat(searchWithoutLeadingQuestion, columns);
1415
2580
  }
@@ -1565,7 +2730,7 @@ const isValueValid = (value, field, columns, operator) => {
1565
2730
 
1566
2731
  // example:
1567
2732
  // unicodeDomain[contains]=a&unicodeDomain[contains]=dsa&logicOperator=and&tab=ignored
1568
- const getFilterModelFromString = (searchString, columns, previousModel) => {
2733
+ const getFilterModelFromString = (searchString, columns) => {
1569
2734
  if (!searchString) {
1570
2735
  return 'invalid';
1571
2736
  }
@@ -1578,7 +2743,7 @@ const getFilterModelFromString = (searchString, columns, previousModel) => {
1578
2743
  let hasFilterMeta = false;
1579
2744
  const searchParams = new URLSearchParams();
1580
2745
  for (const [key, value] of new URLSearchParams(searchString)) {
1581
- if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_rowGrouping', '_aggregation', '_pivot', '_density', '_filters'].includes(key)) {
2746
+ if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_density', '_filters'].includes(key)) {
1582
2747
  searchParams.set(key, value);
1583
2748
  }
1584
2749
  if (key === '_logicOperator') {
@@ -1595,21 +2760,6 @@ const getFilterModelFromString = (searchString, columns, previousModel) => {
1595
2760
  }
1596
2761
  }
1597
2762
  let id = 5000;
1598
-
1599
- // Positional id-reuse map keyed by `${field}|${operator}` (decoded operator, matching
1600
- // the item we push below). FIFO per key so duplicate field+operator items map by order.
1601
- // Reusing the id of a previously parsed/emitted item keeps `item.id` stable across the
1602
- // URL write→parse roundtrip (the URL never carries the id), so MUI's GridFilterForm
1603
- // React key does not change and the filter panel input keeps focus. (DS-81)
1604
- const previousIdsByKey = new Map();
1605
- if (previousModel) {
1606
- for (const prev of previousModel.items) {
1607
- if (prev.id === undefined) continue;
1608
- const key = `${prev.field}|${prev.operator}`;
1609
- const bucket = previousIdsByKey.get(key);
1610
- if (bucket) bucket.push(prev.id);else previousIdsByKey.set(key, [prev.id]);
1611
- }
1612
- }
1613
2763
  const fields = columns.map(column => column.field);
1614
2764
  let isInvalid = false;
1615
2765
  const items = [];
@@ -1645,13 +2795,10 @@ const getFilterModelFromString = (searchString, columns, previousModel) => {
1645
2795
  isInvalid = true;
1646
2796
  return;
1647
2797
  }
1648
- const finalOperator = columnType === 'number' && Object.keys(numberOperatorDecoder).includes(operator) ? numberOperatorDecoder[operator] : operator;
1649
- const reuseBucket = previousIdsByKey.get(`${field}|${finalOperator}`);
1650
- const stableId = reuseBucket && reuseBucket.length > 0 ? reuseBucket.shift() : id;
1651
2798
  items.push({
1652
2799
  field,
1653
- operator: finalOperator,
1654
- id: stableId,
2800
+ operator: columnType === 'number' && Object.keys(numberOperatorDecoder).includes(operator) ? numberOperatorDecoder[operator] : operator,
2801
+ id,
1655
2802
  value: listOperators.includes(operator) && decodedValue === '' ? [] : decodedValue,
1656
2803
  type
1657
2804
  });
@@ -1745,7 +2892,7 @@ const getSearchParamsFromFilterModel = filterModel => {
1745
2892
  // - if we have something in the URL, use that info
1746
2893
  // - if we don't have that, use the localStorage and update the URL
1747
2894
  // - if we don't have that, return an empty FilterModel
1748
- const getFilterModel = (search, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion, previousModel) => {
2895
+ const getFilterModel = (search, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion) => {
1749
2896
  const defaultValue = initialState && initialState.filter && initialState.filter.filterModel ? initialState.filter.filterModel : {
1750
2897
  items: [],
1751
2898
  logicOperator: GridLogicOperator.And
@@ -1763,7 +2910,7 @@ const getFilterModel = (search, columns, localStorageFilters, setLocalStorageFil
1763
2910
  persistDefaultFilters();
1764
2911
  return defaultValue;
1765
2912
  }
1766
- const filterModelFromSearch = getFilterModelFromString(search, columns, previousModel);
2913
+ const filterModelFromSearch = getFilterModelFromString(search, columns);
1767
2914
  if (filterModelFromSearch !== 'invalid') {
1768
2915
  const searchFromFilterModel = getSearchParamsFromFilterModel(filterModelFromSearch);
1769
2916
  const searchString = urlSearchParamsToString(searchFromFilterModel);
@@ -1946,8 +3093,8 @@ const getColumnVisibilityFromString = (searchString, columns) => {
1946
3093
  // by 12.5.5-muiv8-alpha.5/alpha.6 (replaced by the URL-safe `!` form below — see
1947
3094
  // getSearchParamsFromColumnVisibility). Still parsed so any localStorage entry
1948
3095
  // persisted by those alphas keeps working; never written anymore. The two sets are
1949
- // split on the fixed `];h:[` separator, so a `[` or `]` inside a pivot field name
1950
- // (e.g. `["gmail"]>->email_volume`) does not break parsing.
3096
+ // split on the fixed `];h:[` separator, so a `[` or `]` inside a field name does
3097
+ // not break parsing.
1951
3098
  if (value.startsWith('v:[') && value.endsWith(']') && value.includes('];h:[')) {
1952
3099
  const inner = value.slice('v:['.length, -1);
1953
3100
  const separatorIndex = inner.indexOf('];h:[');
@@ -2037,14 +3184,14 @@ const getSearchParamsFromColumnVisibility = (columnVisibility, columns) => {
2037
3184
  }, columnVisibility);
2038
3185
 
2039
3186
  // Serialise a single comma list over the static columns plus any extra keys present
2040
- // in the model (dynamically-generated pivot fields, preserved in model order).
2041
- // Hidden fields are prefixed `!`; visible fields are bare. This URL-safe form
2042
- // round-trips idempotently through `URLSearchParams.toString()` percent-encoding —
2043
- // the earlier `v:[..];h:[..]` form did NOT (its `:`/`;` were percent-encoded and
2044
- // mis-parsed on read-back, driving an unbounded `history.replace` loop, ODM-3033).
2045
- // `!` (not `~`, which is the compression sentinel — compression.ts COMPRESSED_PREFIX)
2046
- // is used so a leading hidden field can't be mistaken for a compressed value.
2047
- // The hidden set is still explicit, so deselected dynamic columns survive reloads.
3187
+ // in the model (dynamically-generated fields, preserved in model order). Hidden
3188
+ // fields are prefixed `!`; visible fields are bare. This URL-safe form round-trips
3189
+ // idempotently through `URLSearchParams.toString()` percent-encoding — the earlier
3190
+ // `v:[..];h:[..]` form did NOT (its `:`/`;` were percent-encoded and mis-parsed on
3191
+ // read-back, driving an unbounded `history.replace` loop, ODM-3033). `!` (not `~`,
3192
+ // the compression sentinel — compression.ts COMPRESSED_PREFIX) is used so a leading
3193
+ // hidden field can't be mistaken for a compressed value. The hidden set is still
3194
+ // explicit, so deselected dynamic columns survive reloads.
2048
3195
  const allFields = [...fields];
2049
3196
  for (const field of Object.keys(finalColumnVisibility)) {
2050
3197
  if (!allFields.includes(field)) {
@@ -2207,7 +3354,8 @@ const getSearchParamsFromDensity = density => {
2207
3354
  return searchParams;
2208
3355
  };
2209
3356
  const getDensityModel = (search, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion) => {
2210
- // Default density: honour initialState.density if valid, otherwise fall back to 'compact'
3357
+ // MUI v6 GridInitialStatePro does not expose density on its type, but consumers
3358
+ // can still pass it through. Honour it when provided, otherwise fall back to 'compact'.
2211
3359
  const initialDensity = initialState === null || initialState === void 0 ? void 0 : initialState.density;
2212
3360
  const defaultValue = initialDensity && VALID_DENSITIES.includes(initialDensity) ? initialDensity : 'compact';
2213
3361
 
@@ -2260,6 +3408,29 @@ const getSearchParamsFromColumnOrder = columnOrder => {
2260
3408
  }
2261
3409
  return searchParams;
2262
3410
  };
3411
+
3412
+ /**
3413
+ * Builds the `v=<version>` search param the grid uses to detect stale URLs.
3414
+ *
3415
+ * Use this when constructing a deep link or share URL outside the grid (e.g. via
3416
+ * `getSearchParamsFromFilterModel` + `buildQueryParamsString`). The grid itself
3417
+ * always includes `v` in URLs it writes via `getFinalSearch`, but external helpers
3418
+ * do not — include this when you want a stale `localStorageVersion` bump to invalidate
3419
+ * the link. Omitting `v` is also safe: a missing `v` is treated as "current version"
3420
+ * and the URL state is applied as-is.
3421
+ *
3422
+ * @example
3423
+ * const params = new URLSearchParams([
3424
+ * ...getSearchParamsFromFilterModel(filterModel),
3425
+ * ...getSearchParamsFromVersion(1),
3426
+ * ]);
3427
+ * const url = `/my-grid${buildQueryParamsString(urlSearchParamsToString(params))}`;
3428
+ */
3429
+ const getSearchParamsFromVersion = version => {
3430
+ const searchParams = new URLSearchParams();
3431
+ searchParams.set('v', String(version));
3432
+ return searchParams;
3433
+ };
2263
3434
  const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion) => {
2264
3435
  var _initialState$columns4, _initialState$columns5;
2265
3436
  const defaultValue = (_initialState$columns4 = initialState === null || initialState === void 0 ? void 0 : (_initialState$columns5 = initialState.columns) === null || _initialState$columns5 === void 0 ? void 0 : _initialState$columns5.orderedFields) !== null && _initialState$columns4 !== void 0 ? _initialState$columns4 : columns.map(c => c.field);
@@ -2290,345 +3461,46 @@ const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorag
2290
3461
  persistDefault();
2291
3462
  return defaultValue;
2292
3463
  };
2293
-
2294
- /** ROW GROUPING */
2295
-
2296
- const getRowGroupingFromString = searchString => {
2297
- if (!searchString) return 'invalid';
2298
- const searchParams = new URLSearchParams(searchString);
2299
- const value = searchParams.get('_rowGrouping');
2300
- if (value === '' || value === null || value === '[]') return 'invalid';
2301
- const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2302
- if (!inner) return 'invalid';
2303
- return inner.split(',').filter(Boolean);
2304
- };
2305
- const getSearchParamsFromRowGrouping = rowGrouping => {
3464
+ const getFinalSearch = _ref => {
3465
+ let {
3466
+ search,
3467
+ localStorageVersion,
3468
+ filterModel,
3469
+ sortModel,
3470
+ paginationModel,
3471
+ columnsVisibilityModel,
3472
+ pinnedColumnsModel,
3473
+ density,
3474
+ columnOrderModel,
3475
+ defaultColumnOrder,
3476
+ columns
3477
+ } = _ref;
3478
+ const filterModelSearch = getSearchParamsFromFilterModel(filterModel);
3479
+ const sortModelSearch = getSearchParamsFromSorting(sortModel);
3480
+ const paginationModelSearch = getSearchParamsFromPagination(paginationModel);
3481
+ const columnVisibilityModelSearch = getSearchParamsFromColumnVisibility(columnsVisibilityModel, columns);
3482
+ const pinnedColumnsModelSearch = getSearchParamsFromPinnedColumns(pinnedColumnsModel);
3483
+ const densitySearch = getSearchParamsFromDensity(density);
3484
+ // Only include _columnOrder in URL when it differs from the default
3485
+ const columnOrderSearch = columnOrderModel.length !== defaultColumnOrder.length || columnOrderModel.some((field, i) => field !== defaultColumnOrder[i]) ? getSearchParamsFromColumnOrder(columnOrderModel) : new URLSearchParams();
3486
+ const tabSearch = getSearchParamsFromTab(search);
2306
3487
  const searchParams = new URLSearchParams();
2307
- if (rowGrouping.length > 0) {
2308
- searchParams.set('_rowGrouping', `[${rowGrouping.join(',')}]`);
2309
- }
2310
- return searchParams;
2311
- };
2312
- const getRowGroupingModel = (search, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion) => {
2313
- var _initialState$rowGrou, _initialState$rowGrou2;
2314
- 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 : [];
2315
- const persistDefault = () => {
2316
- const searchFromDefault = getSearchParamsFromRowGrouping(defaultValue);
2317
- const searchString = urlSearchParamsToString(searchFromDefault);
2318
- if (searchString !== localStorageRowGrouping) {
2319
- setLocalStorageRowGrouping(searchString);
2320
- }
2321
- };
2322
- if (isNewVersion) {
2323
- persistDefault();
2324
- return defaultValue;
2325
- }
2326
- const fromUrl = getRowGroupingFromString(search);
2327
- if (fromUrl !== 'invalid') {
2328
- const searchFromModel = getSearchParamsFromRowGrouping(fromUrl);
2329
- const searchString = urlSearchParamsToString(searchFromModel);
2330
- if (searchString !== localStorageRowGrouping) {
2331
- setLocalStorageRowGrouping(searchString);
3488
+ for (const [key, value] of new URLSearchParams(search)) {
3489
+ if (!key.startsWith('_')) {
3490
+ searchParams.set(key, value);
2332
3491
  }
2333
- return fromUrl;
2334
- }
2335
- const fromLocalStorage = getRowGroupingFromString(localStorageRowGrouping);
2336
- if (fromLocalStorage !== 'invalid') {
2337
- return fromLocalStorage;
2338
3492
  }
2339
- persistDefault();
2340
- return defaultValue;
2341
- };
2342
-
2343
- /** AGGREGATION */
2344
-
2345
- const getAggregationFromString = searchString => {
2346
- if (!searchString) return 'invalid';
2347
- const searchParams = new URLSearchParams(searchString);
2348
- const value = searchParams.get('_aggregation');
2349
- if (value === '' || value === null) return 'invalid';
3493
+ searchParams.set('v', `${localStorageVersion}`);
2350
3494
 
2351
- // Format: field1.sum,field2.avg or [field1.sum,field2.avg]
2352
- const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2353
- if (!inner) return 'invalid';
2354
- const model = {};
2355
- for (const entry of inner.split(',')) {
2356
- const dotIndex = entry.lastIndexOf('.');
2357
- if (dotIndex <= 0) return 'invalid';
2358
- const field = entry.slice(0, dotIndex);
2359
- const aggFunc = entry.slice(dotIndex + 1);
2360
- if (!field || !aggFunc) return 'invalid';
2361
- model[field] = aggFunc;
3495
+ // Add quickFilterValues explicitly if present in filterModel
3496
+ if (filterModel.quickFilterValues && filterModel.quickFilterValues.length > 0) {
3497
+ // Encode array as JSON string to preserve all values in one param
3498
+ searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
2362
3499
  }
2363
- return Object.keys(model).length > 0 ? model : 'invalid';
2364
- };
2365
- const getSearchParamsFromAggregation = aggregation => {
2366
- const searchParams = new URLSearchParams();
2367
- const entries = Object.entries(aggregation);
2368
- if (entries.length > 0) {
2369
- const value = entries.map(_ref => {
2370
- let [field, aggFunc] = _ref;
2371
- return `${field}.${aggFunc}`;
2372
- }).join(',');
2373
- searchParams.set('_aggregation', value);
2374
- }
2375
- return searchParams;
2376
- };
2377
- const getAggregationModel = (search, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion) => {
2378
- var _initialState$aggrega, _initialState$aggrega2;
2379
- 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 : {};
2380
- const persistDefault = () => {
2381
- const searchFromDefault = getSearchParamsFromAggregation(defaultValue);
2382
- const searchString = urlSearchParamsToString(searchFromDefault);
2383
- if (searchString !== localStorageAggregation) {
2384
- setLocalStorageAggregation(searchString);
2385
- }
2386
- };
2387
- if (isNewVersion) {
2388
- persistDefault();
2389
- return defaultValue;
2390
- }
2391
- const fromUrl = getAggregationFromString(search);
2392
- if (fromUrl !== 'invalid') {
2393
- const searchFromModel = getSearchParamsFromAggregation(fromUrl);
2394
- const searchString = urlSearchParamsToString(searchFromModel);
2395
- if (searchString !== localStorageAggregation) {
2396
- setLocalStorageAggregation(searchString);
2397
- }
2398
- return fromUrl;
2399
- }
2400
- const fromLocalStorage = getAggregationFromString(localStorageAggregation);
2401
- if (fromLocalStorage !== 'invalid') {
2402
- return fromLocalStorage;
2403
- }
2404
- persistDefault();
2405
- return defaultValue;
2406
- };
2407
-
2408
- /** PIVOT */
2409
-
2410
- /** Convert MUI's GridPivotModel → our simplified PivotModel */
2411
- const fromGridPivotModel = model => ({
2412
- columns: model.columns.map(c => c.field),
2413
- rows: model.rows.map(r => r.field),
2414
- values: model.values.map(_ref2 => {
2415
- let {
2416
- field,
2417
- aggFunc
2418
- } = _ref2;
2419
- return {
2420
- field,
2421
- aggFunc
2422
- };
2423
- })
2424
- });
2425
-
2426
- /**
2427
- * Pivot format: `cols:f1,f2;rows:f3;vals:f4.sum,f5.avg`
2428
- */
2429
- const getPivotFromString = searchString => {
2430
- if (!searchString) return 'invalid';
2431
- const searchParams = new URLSearchParams(searchString);
2432
- const value = searchParams.get('_pivot');
2433
- if (value === '' || value === null) return 'invalid';
2434
- const model = {
2435
- columns: [],
2436
- rows: [],
2437
- values: []
2438
- };
2439
- for (const segment of value.split(';')) {
2440
- const colonIndex = segment.indexOf(':');
2441
- if (colonIndex <= 0) return 'invalid';
2442
- const key = segment.slice(0, colonIndex);
2443
- const content = segment.slice(colonIndex + 1);
2444
- if (key === 'cols') {
2445
- model.columns = content ? content.split(',').filter(Boolean) : [];
2446
- } else if (key === 'rows') {
2447
- model.rows = content ? content.split(',').filter(Boolean) : [];
2448
- } else if (key === 'vals') {
2449
- if (!content) continue;
2450
- for (const entry of content.split(',')) {
2451
- const dotIndex = entry.lastIndexOf('.');
2452
- if (dotIndex <= 0) return 'invalid';
2453
- model.values.push({
2454
- field: entry.slice(0, dotIndex),
2455
- aggFunc: entry.slice(dotIndex + 1)
2456
- });
2457
- }
2458
- }
2459
- }
2460
-
2461
- // At least one section must have content
2462
- if (model.columns.length === 0 && model.rows.length === 0 && model.values.length === 0) {
2463
- return 'invalid';
2464
- }
2465
- return model;
2466
- };
2467
- const getSearchParamsFromPivot = pivot => {
2468
- const searchParams = new URLSearchParams();
2469
- const hasContent = pivot.columns.length > 0 || pivot.rows.length > 0 || pivot.values.length > 0;
2470
- if (hasContent) {
2471
- const parts = [];
2472
- parts.push(`cols:${pivot.columns.join(',')}`);
2473
- parts.push(`rows:${pivot.rows.join(',')}`);
2474
- if (pivot.values.length > 0) {
2475
- parts.push(`vals:${pivot.values.map(v => `${v.field}.${v.aggFunc}`).join(',')}`);
2476
- }
2477
- searchParams.set('_pivot', parts.join(';'));
2478
- }
2479
- return searchParams;
2480
- };
2481
- const getPivotModel = (search, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion) => {
2482
- var _initialState$pivotin;
2483
- const defaultValue = initialState !== null && initialState !== void 0 && (_initialState$pivotin = initialState.pivoting) !== null && _initialState$pivotin !== void 0 && _initialState$pivotin.model ? fromGridPivotModel(initialState.pivoting.model) : {
2484
- columns: [],
2485
- rows: [],
2486
- values: []
2487
- };
2488
- const persistDefault = () => {
2489
- const searchFromDefault = getSearchParamsFromPivot(defaultValue);
2490
- const searchString = urlSearchParamsToString(searchFromDefault);
2491
- if (searchString !== localStoragePivot) {
2492
- setLocalStoragePivot(searchString);
2493
- }
2494
- };
2495
- if (isNewVersion) {
2496
- persistDefault();
2497
- return defaultValue;
2498
- }
2499
- const fromUrl = getPivotFromString(search);
2500
- if (fromUrl !== 'invalid') {
2501
- const searchFromModel = getSearchParamsFromPivot(fromUrl);
2502
- const searchString = urlSearchParamsToString(searchFromModel);
2503
- if (searchString !== localStoragePivot) {
2504
- setLocalStoragePivot(searchString);
2505
- }
2506
- return fromUrl;
2507
- }
2508
- const fromLocalStorage = getPivotFromString(localStoragePivot);
2509
- if (fromLocalStorage !== 'invalid') {
2510
- return fromLocalStorage;
2511
- }
2512
- persistDefault();
2513
- return defaultValue;
2514
- };
2515
-
2516
- /** PIVOT ACTIVE */
2517
-
2518
- const getPivotActiveFromString = searchString => {
2519
- if (!searchString) return 'invalid';
2520
- const searchParams = new URLSearchParams(searchString);
2521
- const value = searchParams.get('_pivotActive');
2522
- if (value === 'true') return true;
2523
- if (value === 'false') return false;
2524
- return 'invalid';
2525
- };
2526
- const getSearchParamsFromPivotActive = active => {
2527
- const searchParams = new URLSearchParams();
2528
- searchParams.set('_pivotActive', String(active));
2529
- return searchParams;
2530
- };
2531
-
2532
- /**
2533
- * Builds the `v=<version>` search param the grid uses to detect stale URLs.
2534
- *
2535
- * Use this when constructing a deep link or share URL outside the grid (e.g. via
2536
- * `getSearchParamsFromFilterModel` + `buildQueryParamsString`). The grid itself
2537
- * always includes `v` in URLs it writes via `getFinalSearch`, but external helpers
2538
- * do not — include this when you want a stale `localStorageVersion` bump to invalidate
2539
- * the link. Omitting `v` is also safe: a missing `v` is treated as "current version"
2540
- * and the URL state is applied as-is.
2541
- *
2542
- * @example
2543
- * const params = new URLSearchParams([
2544
- * ...getSearchParamsFromFilterModel(filterModel),
2545
- * ...getSearchParamsFromVersion(1),
2546
- * ]);
2547
- * const url = `/my-grid${buildQueryParamsString(urlSearchParamsToString(params))}`;
2548
- */
2549
- const getSearchParamsFromVersion = version => {
2550
- const searchParams = new URLSearchParams();
2551
- searchParams.set('v', String(version));
2552
- return searchParams;
2553
- };
2554
- const getPivotActive = (search, localStoragePivotActive, setLocalStoragePivotActive, initialState, isNewVersion) => {
2555
- var _initialState$pivotin2, _initialState$pivotin3;
2556
- 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;
2557
- const persistDefault = () => {
2558
- const searchFromDefault = getSearchParamsFromPivotActive(defaultValue);
2559
- const searchString = urlSearchParamsToString(searchFromDefault);
2560
- if (searchString !== localStoragePivotActive) {
2561
- setLocalStoragePivotActive(searchString);
2562
- }
2563
- };
2564
- if (isNewVersion) {
2565
- persistDefault();
2566
- return defaultValue;
2567
- }
2568
- const fromUrl = getPivotActiveFromString(search);
2569
- if (fromUrl !== 'invalid') {
2570
- const searchFromModel = getSearchParamsFromPivotActive(fromUrl);
2571
- const searchString = urlSearchParamsToString(searchFromModel);
2572
- if (searchString !== localStoragePivotActive) {
2573
- setLocalStoragePivotActive(searchString);
2574
- }
2575
- return fromUrl;
2576
- }
2577
- const fromLocalStorage = getPivotActiveFromString(localStoragePivotActive);
2578
- if (fromLocalStorage !== 'invalid') {
2579
- return fromLocalStorage;
2580
- }
2581
- persistDefault();
2582
- return defaultValue;
2583
- };
2584
- const getFinalSearch = _ref3 => {
2585
- let {
2586
- search,
2587
- localStorageVersion,
2588
- filterModel,
2589
- sortModel,
2590
- paginationModel,
2591
- columnsVisibilityModel,
2592
- pinnedColumnsModel,
2593
- density,
2594
- columnOrderModel,
2595
- defaultColumnOrder,
2596
- rowGroupingModel,
2597
- aggregationModel,
2598
- pivotModel,
2599
- pivotActive,
2600
- columns
2601
- } = _ref3;
2602
- const filterModelSearch = getSearchParamsFromFilterModel(filterModel);
2603
- const sortModelSearch = getSearchParamsFromSorting(sortModel);
2604
- const paginationModelSearch = getSearchParamsFromPagination(paginationModel);
2605
- const columnVisibilityModelSearch = getSearchParamsFromColumnVisibility(columnsVisibilityModel, columns);
2606
- const pinnedColumnsModelSearch = getSearchParamsFromPinnedColumns(pinnedColumnsModel);
2607
- const densitySearch = getSearchParamsFromDensity(density);
2608
- // Only include _columnOrder in URL when it differs from the default
2609
- const columnOrderSearch = columnOrderModel.length !== defaultColumnOrder.length || columnOrderModel.some((field, i) => field !== defaultColumnOrder[i]) ? getSearchParamsFromColumnOrder(columnOrderModel) : new URLSearchParams();
2610
- const rowGroupingSearch = getSearchParamsFromRowGrouping(rowGroupingModel);
2611
- const aggregationSearch = getSearchParamsFromAggregation(aggregationModel);
2612
- const pivotSearch = getSearchParamsFromPivot(pivotModel);
2613
- const pivotActiveSearch = getSearchParamsFromPivotActive(pivotActive);
2614
- const tabSearch = getSearchParamsFromTab(search);
2615
- const searchParams = new URLSearchParams();
2616
- for (const [key, value] of new URLSearchParams(search)) {
2617
- if (!key.startsWith('_')) {
2618
- searchParams.set(key, value);
2619
- }
2620
- }
2621
- searchParams.set('v', `${localStorageVersion}`);
2622
-
2623
- // Add quickFilterValues explicitly if present in filterModel
2624
- if (filterModel.quickFilterValues && filterModel.quickFilterValues.length > 0) {
2625
- // Encode array as JSON string to preserve all values in one param
2626
- searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
2627
- }
2628
- return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch, ...rowGroupingSearch, ...aggregationSearch, ...pivotSearch, ...pivotActiveSearch]);
3500
+ return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch]);
2629
3501
  };
2630
3502
  /** Return the state of the table given the URL and the local storage state */
2631
- const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage, previousFilterModel) => {
3503
+ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage) => {
2632
3504
  var _initialState$columns6, _initialState$columns7;
2633
3505
  // Decompress any compressed params in the search string before processing
2634
3506
  const decompressedSearch = decompressSearchParams(search);
@@ -2665,27 +3537,15 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2665
3537
  localStorageDensity,
2666
3538
  setLocalStorageDensity,
2667
3539
  localStorageColumnOrder,
2668
- setLocalStorageColumnOrder,
2669
- localStorageRowGrouping,
2670
- setLocalStorageRowGrouping,
2671
- localStorageAggregation,
2672
- setLocalStorageAggregation,
2673
- localStoragePivot,
2674
- setLocalStoragePivot,
2675
- localStoragePivotActive,
2676
- setLocalStoragePivotActive
3540
+ setLocalStorageColumnOrder
2677
3541
  } = localStorage;
2678
- const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion, previousFilterModel);
3542
+ const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion);
2679
3543
  const sortModel = getSortModel(decodedSearch, columns, localStorageSorting, setLocalStorageSorting, initialState, isNewVersion);
2680
3544
  const paginationModel = getPaginationModel(decodedSearch, localStoragePagination, setLocalStoragePagination, initialState, isNewVersion);
2681
3545
  const columnVisibilityModel = getColumnsVisibility(decodedSearch, columns, localStorageColumnsVisibility, setLocalStorageColumnsVisibility, initialState, isNewVersion);
2682
3546
  const pinnedColumnsModel = getPinnedColumns(decodedSearch, columns, localStoragePinnedColumns, setLocalStoragePinnedColumns, initialState, isNewVersion);
2683
3547
  const density = getDensityModel(decodedSearch, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion);
2684
3548
  const columnOrderModel = getColumnOrder(decodedSearch, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion);
2685
- const rowGroupingModel = getRowGroupingModel(decodedSearch, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion);
2686
- const aggregationModel = getAggregationModel(decodedSearch, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion);
2687
- const pivotModel = getPivotModel(decodedSearch, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion);
2688
- const pivotActive = getPivotActive(decodedSearch, localStoragePivotActive, setLocalStoragePivotActive, initialState, isNewVersion);
2689
3549
  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);
2690
3550
  const finalSearch = getFinalSearch({
2691
3551
  localStorageVersion,
@@ -2698,10 +3558,6 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2698
3558
  density,
2699
3559
  columnOrderModel,
2700
3560
  defaultColumnOrder,
2701
- rowGroupingModel,
2702
- aggregationModel,
2703
- pivotModel,
2704
- pivotActive,
2705
3561
  columns
2706
3562
  });
2707
3563
  const internalSearchString = urlSearchParamsToString(finalSearch);
@@ -2722,14 +3578,10 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2722
3578
  pinnedColumnsModel,
2723
3579
  density,
2724
3580
  columnOrderModel,
2725
- rowGroupingModel,
2726
- aggregationModel,
2727
- pivotModel,
2728
- pivotActive,
2729
3581
  pendingSearch
2730
3582
  };
2731
3583
  };
2732
- const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns) => {
3584
+ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns) => {
2733
3585
  let {
2734
3586
  filterModel,
2735
3587
  sortModel,
@@ -2738,12 +3590,8 @@ const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns)
2738
3590
  pinnedColumnsModel,
2739
3591
  density,
2740
3592
  columnOrderModel,
2741
- defaultColumnOrder,
2742
- rowGroupingModel,
2743
- aggregationModel,
2744
- pivotModel,
2745
- pivotActive
2746
- } = _ref4;
3593
+ defaultColumnOrder
3594
+ } = _ref2;
2747
3595
  // Convert from display format to internal format if needed
2748
3596
  const decodedSearch = getDecodedSearchFromUrl(search, columns);
2749
3597
  const newSearch = getFinalSearch({
@@ -2757,10 +3605,6 @@ const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns)
2757
3605
  density,
2758
3606
  columnOrderModel,
2759
3607
  defaultColumnOrder,
2760
- rowGroupingModel,
2761
- aggregationModel,
2762
- pivotModel,
2763
- pivotActive,
2764
3608
  columns
2765
3609
  });
2766
3610
  const internalSearchString = urlSearchParamsToString(newSearch);
@@ -2953,26 +3797,6 @@ const useTableStates = (id, version) => {
2953
3797
  version,
2954
3798
  category: COLUMN_ORDER_MODEL_KEY
2955
3799
  }));
2956
- const [rowGroupingModel, setRowGroupingModel] = useFetchState('', buildStorageKey({
2957
- id,
2958
- version,
2959
- category: ROW_GROUPING_MODEL_KEY
2960
- }));
2961
- const [aggregationModel, setAggregationModel] = useFetchState('', buildStorageKey({
2962
- id,
2963
- version,
2964
- category: AGGREGATION_MODEL_KEY
2965
- }));
2966
- const [pivotModel, setPivotModel] = useFetchState('', buildStorageKey({
2967
- id,
2968
- version,
2969
- category: PIVOT_MODEL_KEY
2970
- }));
2971
- const [pivotActive, setPivotActive] = useFetchState('', buildStorageKey({
2972
- id,
2973
- version,
2974
- category: PIVOT_ACTIVE_KEY
2975
- }));
2976
3800
  return {
2977
3801
  paginationModel,
2978
3802
  setPaginationModel,
@@ -2989,55 +3813,10 @@ const useTableStates = (id, version) => {
2989
3813
  densityModel,
2990
3814
  setDensityModel,
2991
3815
  columnOrderModel,
2992
- setColumnOrderModel,
2993
- rowGroupingModel,
2994
- setRowGroupingModel,
2995
- aggregationModel,
2996
- setAggregationModel,
2997
- pivotModel,
2998
- setPivotModel,
2999
- pivotActive,
3000
- setPivotActive
3816
+ setColumnOrderModel
3001
3817
  };
3002
3818
  };
3003
3819
 
3004
- /** Convert our simplified PivotModel → MUI's GridPivotModel */
3005
- const toGridPivotModel = model => ({
3006
- columns: model.columns.map(field => ({
3007
- field
3008
- })),
3009
- rows: model.rows.map(field => ({
3010
- field
3011
- })),
3012
- values: model.values.map(_ref => {
3013
- let {
3014
- field,
3015
- aggFunc
3016
- } = _ref;
3017
- return {
3018
- field,
3019
- aggFunc
3020
- };
3021
- })
3022
- });
3023
-
3024
- /**
3025
- * Deep-equal comparison for plain objects / arrays.
3026
- * Used to stabilise parsed model references so that MUI v8 does not
3027
- * reset pagination on every render.
3028
- */
3029
- function isDeepEqual(a, b) {
3030
- if (a === b) return true;
3031
- if (a == null || b == null) return false;
3032
- if (typeof a !== typeof b) return false;
3033
- if (typeof a !== 'object') return false;
3034
- const aObj = a;
3035
- const bObj = b;
3036
- const aKeys = Object.keys(aObj);
3037
- const bKeys = Object.keys(bObj);
3038
- if (aKeys.length !== bKeys.length) return false;
3039
- return aKeys.every(key => isDeepEqual(aObj[key], bObj[key]));
3040
- }
3041
3820
  const useStatefulTable = props => {
3042
3821
  var _initialState$columns, _initialState$columns2;
3043
3822
  const {
@@ -3050,9 +3829,6 @@ const useStatefulTable = props => {
3050
3829
  onPaginationModelChange: propsOnPaginationModelChange,
3051
3830
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3052
3831
  onSortModelChange: propsOnSortModelChange,
3053
- onRowGroupingModelChange: propsOnRowGroupingModelChange,
3054
- onAggregationModelChange: propsOnAggregationModelChange,
3055
- onPivotModelChange: propsOnPivotModelChange,
3056
3832
  useRouter,
3057
3833
  localStorageVersion = 1,
3058
3834
  previousLocalStorageVersions = []
@@ -3081,33 +3857,20 @@ const useStatefulTable = props => {
3081
3857
  densityModel,
3082
3858
  setDensityModel,
3083
3859
  columnOrderModel: localStorageColumnOrder,
3084
- setColumnOrderModel: setLocalStorageColumnOrder,
3085
- rowGroupingModel: localStorageRowGrouping,
3086
- setRowGroupingModel: setLocalStorageRowGrouping,
3087
- aggregationModel: localStorageAggregation,
3088
- setAggregationModel: setLocalStorageAggregation,
3089
- pivotModel: localStoragePivot,
3090
- setPivotModel: setLocalStoragePivot,
3091
- pivotActive: localStoragePivotActive,
3092
- setPivotActive: setLocalStoragePivotActive
3860
+ setColumnOrderModel: setLocalStorageColumnOrder
3093
3861
  } = useTableStates(id, localStorageVersion);
3094
3862
 
3095
3863
  // clearing up old version keys, triggering only on first render
3096
3864
  useEffect(() => clearPreviousVersionStorage(id, previousLocalStorageVersions), [id, previousLocalStorageVersions]);
3097
- const onColumnDimensionChange = useCallback(_ref2 => {
3865
+ const onColumnDimensionChange = useCallback(_ref => {
3098
3866
  let {
3099
3867
  newWidth,
3100
3868
  field
3101
- } = _ref2;
3869
+ } = _ref;
3102
3870
  setDimensionModel(_objectSpread2(_objectSpread2({}, dimensionModel), {}, {
3103
3871
  [field]: newWidth
3104
3872
  }));
3105
3873
  }, [dimensionModel, setDimensionModel]);
3106
-
3107
- // Source of ids for content-matching in the parser, so item.id is stable across the
3108
- // URL write→parse roundtrip (DS-81). Holds MUI's just-emitted model (random placeholder
3109
- // id) after onFilterModelChange, then the stabilised parsed model each render.
3110
- const filterIdSourceRef = useRef(undefined);
3111
3874
  const {
3112
3875
  filterModel: filterParsed,
3113
3876
  sortModel: sortModelParsed,
@@ -3116,10 +3879,6 @@ const useStatefulTable = props => {
3116
3879
  pinnedColumnsModel,
3117
3880
  density: densityParsed,
3118
3881
  columnOrderModel: columnOrderParsed,
3119
- rowGroupingModel: rowGroupingParsed,
3120
- aggregationModel: aggregationParsed,
3121
- pivotModel: pivotParsed,
3122
- pivotActive: pivotActiveParsed,
3123
3882
  pendingSearch
3124
3883
  } = getModelsParsedOrUpdateLocalStorage(search || '', localStorageVersion, propsColumns, initialState, {
3125
3884
  localStorageFilters,
@@ -3135,16 +3894,8 @@ const useStatefulTable = props => {
3135
3894
  localStorageDensity: densityModel,
3136
3895
  setLocalStorageDensity: setDensityModel,
3137
3896
  localStorageColumnOrder,
3138
- setLocalStorageColumnOrder,
3139
- localStorageRowGrouping,
3140
- setLocalStorageRowGrouping,
3141
- localStorageAggregation,
3142
- setLocalStorageAggregation,
3143
- localStoragePivot,
3144
- setLocalStoragePivot,
3145
- localStoragePivotActive: localStoragePivotActive,
3146
- setLocalStoragePivotActive: setLocalStoragePivotActive
3147
- }, filterIdSourceRef.current);
3897
+ setLocalStorageColumnOrder
3898
+ });
3148
3899
 
3149
3900
  // Sync URL in an effect rather than during render to comply with React rules
3150
3901
  useEffect(() => {
@@ -3152,49 +3903,6 @@ const useStatefulTable = props => {
3152
3903
  historyReplace(pendingSearch);
3153
3904
  }
3154
3905
  }, [pendingSearch, historyReplace]);
3155
-
3156
- // Stabilise parsed model references to prevent MUI v8 from resetting
3157
- // pagination on every render due to new object identity.
3158
- const filterParsedRef = useRef(filterParsed);
3159
- if (!isDeepEqual(filterParsedRef.current, filterParsed)) {
3160
- filterParsedRef.current = filterParsed;
3161
- }
3162
- // Keep the id source in sync with the stabilised parsed model so re-parses triggered
3163
- // by unrelated state (pagination/sort/visibility) reuse the same ids (DS-81). The parse
3164
- // call above reads the ref before this write (read-before-write within the render).
3165
- filterIdSourceRef.current = filterParsed;
3166
- const sortModelParsedRef = useRef(sortModelParsed);
3167
- if (!isDeepEqual(sortModelParsedRef.current, sortModelParsed)) {
3168
- sortModelParsedRef.current = sortModelParsed;
3169
- }
3170
- const paginationModelParsedRef = useRef(paginationModelParsed);
3171
- if (!isDeepEqual(paginationModelParsedRef.current, paginationModelParsed)) {
3172
- paginationModelParsedRef.current = paginationModelParsed;
3173
- }
3174
- const visibilityModelRef = useRef(visibilityModel);
3175
- if (!isDeepEqual(visibilityModelRef.current, visibilityModel)) {
3176
- visibilityModelRef.current = visibilityModel;
3177
- }
3178
- const pinnedColumnsModelRef = useRef(pinnedColumnsModel);
3179
- if (!isDeepEqual(pinnedColumnsModelRef.current, pinnedColumnsModel)) {
3180
- pinnedColumnsModelRef.current = pinnedColumnsModel;
3181
- }
3182
- const columnOrderParsedRef = useRef(columnOrderParsed);
3183
- if (!isDeepEqual(columnOrderParsedRef.current, columnOrderParsed)) {
3184
- columnOrderParsedRef.current = columnOrderParsed;
3185
- }
3186
- const rowGroupingParsedRef = useRef(rowGroupingParsed);
3187
- if (!isDeepEqual(rowGroupingParsedRef.current, rowGroupingParsed)) {
3188
- rowGroupingParsedRef.current = rowGroupingParsed;
3189
- }
3190
- const aggregationParsedRef = useRef(aggregationParsed);
3191
- if (!isDeepEqual(aggregationParsedRef.current, aggregationParsed)) {
3192
- aggregationParsedRef.current = aggregationParsed;
3193
- }
3194
- const pivotParsedRef = useRef(pivotParsed);
3195
- if (!isDeepEqual(pivotParsedRef.current, pivotParsed)) {
3196
- pivotParsedRef.current = pivotParsed;
3197
- }
3198
3906
  const columns = useMemo(() => propsColumns.map(column => {
3199
3907
  return _objectSpread2(_objectSpread2({}, column), {}, {
3200
3908
  width: dimensionModel[column.field] || column.width || 100
@@ -3203,61 +3911,56 @@ const useStatefulTable = props => {
3203
3911
  if (apiRef.current) {
3204
3912
  /** Add resetPage method to apiRef. */
3205
3913
  apiRef.current.resetPage = () => {
3206
- var _apiRef$current;
3207
- (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPage(0);
3914
+ apiRef.current.setPage(0);
3208
3915
  };
3209
3916
  }
3210
3917
  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);
3211
3918
 
3919
+ // Helper to build the current DataGridModel for updateUrl calls
3920
+ const buildModel = function () {
3921
+ var _apiRef$current$state, _apiRef$current;
3922
+ let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3923
+ return _objectSpread2({
3924
+ filterModel: filterParsed,
3925
+ sortModel: sortModelParsed,
3926
+ paginationModel: paginationModelParsed,
3927
+ 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 : {},
3928
+ pinnedColumnsModel: pinnedColumnsModel,
3929
+ density: densityParsed,
3930
+ columnOrderModel: columnOrderParsed,
3931
+ defaultColumnOrder
3932
+ }, overrides);
3933
+ };
3934
+
3212
3935
  // Subscribe to density changes via stateChange event (MUI v6 has no densityChange event)
3213
3936
  useEffect(() => {
3214
3937
  const api = apiRef.current;
3215
3938
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3216
3939
  let prevDensity = densityParsed;
3217
3940
  const unsub = api.subscribeEvent('stateChange', () => {
3218
- const currentDensity = api.state.density;
3941
+ const currentDensity = api.state.density.value;
3219
3942
  if (currentDensity !== prevDensity) {
3220
3943
  prevDensity = currentDensity;
3221
- updateUrl({
3222
- filterModel: filterParsed,
3223
- sortModel: sortModelParsed,
3224
- paginationModel: paginationModelParsed,
3944
+ updateUrl(buildModel({
3225
3945
  columnsModel: api.state.columns.columnVisibilityModel,
3226
- pinnedColumnsModel: pinnedColumnsModel,
3227
- density: currentDensity,
3228
- columnOrderModel: columnOrderParsed,
3229
- defaultColumnOrder,
3230
- rowGroupingModel: rowGroupingParsed,
3231
- aggregationModel: aggregationParsed,
3232
- pivotModel: pivotParsed,
3233
- pivotActive: pivotActiveParsed
3234
- }, search, localStorageVersion, historyReplace, columns);
3946
+ density: currentDensity
3947
+ }), search, localStorageVersion, historyReplace, columns);
3235
3948
  }
3236
3949
  });
3237
3950
  return unsub;
3238
- }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
3951
+ }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, search, localStorageVersion, historyReplace, columns]);
3239
3952
 
3240
3953
  // Subscribe to column order changes via columnOrderChange (drag-drop) and columnIndexChange (programmatic setColumnIndex)
3241
3954
  useEffect(() => {
3242
3955
  const api = apiRef.current;
3243
3956
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3957
+ const isDeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3244
3958
  const handleColumnOrderChange = () => {
3245
3959
  const orderedFields = api.state.columns.orderedFields;
3246
3960
  if (orderedFields && !isDeepEqual(orderedFields, columnOrderParsed)) {
3247
- updateUrl({
3248
- filterModel: filterParsed,
3249
- sortModel: sortModelParsed,
3250
- paginationModel: paginationModelParsed,
3251
- columnsModel: api.state.columns.columnVisibilityModel,
3252
- pinnedColumnsModel,
3253
- density: densityParsed,
3254
- columnOrderModel: orderedFields,
3255
- defaultColumnOrder,
3256
- rowGroupingModel: rowGroupingParsed,
3257
- aggregationModel: aggregationParsed,
3258
- pivotModel: pivotParsed,
3259
- pivotActive: pivotActiveParsed
3260
- }, search, localStorageVersion, historyReplace, columns);
3961
+ updateUrl(buildModel({
3962
+ columnOrderModel: orderedFields
3963
+ }), search, localStorageVersion, historyReplace, columns);
3261
3964
  }
3262
3965
  };
3263
3966
  const unsub1 = api.subscribeEvent('columnOrderChange', handleColumnOrderChange);
@@ -3266,124 +3969,69 @@ const useStatefulTable = props => {
3266
3969
  unsub1();
3267
3970
  unsub2();
3268
3971
  };
3269
- }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
3270
-
3271
- // Helper to build the current DataGridModel for updateUrl calls
3272
- const buildModel = function () {
3273
- var _apiRef$current$state, _apiRef$current2;
3274
- let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3275
- return _objectSpread2({
3276
- filterModel: filterParsed,
3277
- sortModel: sortModelParsed,
3278
- paginationModel: paginationModelParsed,
3279
- 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 : {},
3280
- pinnedColumnsModel: pinnedColumnsModel,
3281
- density: densityParsed,
3282
- columnOrderModel: columnOrderParsed,
3283
- defaultColumnOrder,
3284
- rowGroupingModel: rowGroupingParsed,
3285
- aggregationModel: aggregationParsed,
3286
- pivotModel: pivotParsed,
3287
- pivotActive: pivotActiveParsed
3288
- }, overrides);
3289
- };
3290
-
3291
- // Stable GridPivotModel identity — only recompute when the simplified value changes.
3292
- // eslint-disable-next-line react-hooks/exhaustive-deps
3293
- const pivotModelMui = useMemo(() => toGridPivotModel(pivotParsed), [JSON.stringify(pivotParsed)]);
3972
+ }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, search, localStorageVersion, historyReplace, columns]);
3294
3973
 
3295
3974
  // Track last emitted values for deep-equal guards to avoid feedback loops.
3296
- // Initialised from the current parsed values; updated only when we actually fire.
3297
3975
  const lastEmittedFilterRef = useRef(filterParsed);
3298
3976
  const lastEmittedSortRef = useRef(sortModelParsed);
3299
3977
  const lastEmittedPaginationRef = useRef(paginationModelParsed);
3300
- const lastEmittedPivotRef = useRef(pivotParsed);
3978
+ const isModelDeepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3301
3979
  return {
3302
3980
  apiRef,
3303
3981
  columns,
3304
3982
  density: densityParsed,
3305
- columnOrderModel: columnOrderParsedRef.current,
3306
- rowGroupingModel: rowGroupingParsedRef.current,
3307
- aggregationModel: aggregationParsedRef.current,
3308
- pivotModel: pivotModelMui,
3309
- pivotActive: pivotActiveParsed,
3983
+ columnOrderModel: columnOrderParsed,
3310
3984
  onFilterModelChange: (model, details) => {
3311
3985
  const filterModel = _objectSpread2(_objectSpread2({}, model), {}, {
3312
3986
  items: model.items.map(item => {
3313
- var _apiRef$current3;
3314
- const column = (_apiRef$current3 = apiRef.current) === null || _apiRef$current3 === void 0 ? void 0 : _apiRef$current3.getColumn(item.field);
3315
- item.type = (column === null || column === void 0 ? void 0 : column.type) || 'string';
3987
+ const column = apiRef.current.getColumn(item.field);
3988
+ item.type = column.type || 'string';
3316
3989
  return item;
3317
3990
  }),
3318
3991
  quickFilterValues: model.quickFilterValues || []
3319
3992
  });
3320
- if (isDeepEqual(filterModel, lastEmittedFilterRef.current)) return;
3993
+ if (isModelDeepEqual(filterModel, lastEmittedFilterRef.current)) return;
3321
3994
  lastEmittedFilterRef.current = filterModel;
3322
- // Capture MUI's just-emitted model (carrying the placeholder's random id) so the
3323
- // next render's URL re-parse reuses that id and the GridFilterForm key — and thus
3324
- // the value input's focus — survives the write→parse roundtrip (DS-81).
3325
- filterIdSourceRef.current = filterModel;
3995
+ propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3326
3996
  updateUrl(buildModel({
3327
3997
  filterModel
3328
3998
  }), search, localStorageVersion, historyReplace, columns);
3329
- propsOnFilterModelChange === null || propsOnFilterModelChange === void 0 ? void 0 : propsOnFilterModelChange(filterModel, details);
3330
3999
  },
3331
- filterModel: filterParsedRef.current,
4000
+ filterModel: filterParsed,
3332
4001
  onSortModelChange: (model, details) => {
3333
- if (isDeepEqual(model, lastEmittedSortRef.current)) return;
4002
+ if (isModelDeepEqual(model, lastEmittedSortRef.current)) return;
3334
4003
  lastEmittedSortRef.current = model;
4004
+ propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3335
4005
  updateUrl(buildModel({
3336
4006
  sortModel: model
3337
4007
  }), search, localStorageVersion, historyReplace, columns);
3338
- propsOnSortModelChange === null || propsOnSortModelChange === void 0 ? void 0 : propsOnSortModelChange(model, details);
3339
4008
  },
3340
- sortModel: sortModelParsedRef.current,
4009
+ sortModel: sortModelParsed,
3341
4010
  onPinnedColumnsChange: (pinnedColumns, details) => {
3342
- var _apiRef$current$state2, _apiRef$current4, _apiRef$current4$stat, _apiRef$current4$stat2;
3343
- // While pivot mode is active, MUI Premium emits synthetic pinned-column
3344
- // models (e.g. `__row_group_by_columns_group__` for the grouping column)
3345
- // that must not be persisted to the URL / localStorage. Read the live
3346
- // grid state from apiRef rather than the parsed URL value because the
3347
- // URL lags by a tick during pivot enable/disable transitions. Consumer
3348
- // callbacks are always forwarded so observers can still react.
3349
- const pivotActiveLive = (_apiRef$current$state2 = (_apiRef$current4 = apiRef.current) === null || _apiRef$current4 === void 0 ? void 0 : (_apiRef$current4$stat = _apiRef$current4.state) === null || _apiRef$current4$stat === void 0 ? void 0 : (_apiRef$current4$stat2 = _apiRef$current4$stat.pivoting) === null || _apiRef$current4$stat2 === void 0 ? void 0 : _apiRef$current4$stat2.active) !== null && _apiRef$current$state2 !== void 0 ? _apiRef$current$state2 : pivotActiveParsed;
3350
- if (!pivotActiveLive) {
3351
- updateUrl(buildModel({
3352
- pinnedColumnsModel: pinnedColumns
3353
- }), search, localStorageVersion, historyReplace, columns);
3354
- }
3355
4011
  propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
4012
+ updateUrl(buildModel({
4013
+ pinnedColumnsModel: pinnedColumns
4014
+ }), search, localStorageVersion, historyReplace, columns);
3356
4015
  },
3357
- pinnedColumns: pinnedColumnsModelRef.current,
3358
- paginationModel: paginationModelParsedRef.current,
4016
+ pinnedColumns: pinnedColumnsModel,
4017
+ paginationModel: paginationModelParsed,
3359
4018
  onPaginationModelChange: (model, details) => {
3360
4019
  const paginationModel = _objectSpread2(_objectSpread2({}, model), {}, {
3361
4020
  direction: paginationModelParsed.page < model.page ? 'next' : 'back'
3362
4021
  });
3363
- if (isDeepEqual(paginationModel, lastEmittedPaginationRef.current)) return;
4022
+ if (isModelDeepEqual(paginationModel, lastEmittedPaginationRef.current)) return;
3364
4023
  lastEmittedPaginationRef.current = paginationModel;
4024
+ propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3365
4025
  updateUrl(buildModel({
3366
4026
  paginationModel
3367
4027
  }), search, localStorageVersion, historyReplace, columns);
3368
- propsOnPaginationModelChange === null || propsOnPaginationModelChange === void 0 ? void 0 : propsOnPaginationModelChange(paginationModel, details);
3369
4028
  },
3370
- columnVisibilityModel: visibilityModelRef.current,
4029
+ columnVisibilityModel: visibilityModel,
3371
4030
  onColumnVisibilityModelChange: (columnsVisibilityModel, details) => {
3372
- var _apiRef$current$state3, _apiRef$current5, _apiRef$current5$stat, _apiRef$current5$stat2;
3373
- // While pivot mode is active, MUI Premium emits synthetic visibility
3374
- // models that whitelist only the pivot value fields (hiding every base
3375
- // column). Persisting that to the URL would re-hide all base columns
3376
- // on the next load (see getColumnVisibilityFromString whitelist logic).
3377
- // Read the live grid state rather than the parsed URL value because the
3378
- // URL lags by a tick during pivot enable/disable transitions. Consumer
3379
- // callbacks are always forwarded.
3380
- const pivotActiveLive = (_apiRef$current$state3 = (_apiRef$current5 = apiRef.current) === null || _apiRef$current5 === void 0 ? void 0 : (_apiRef$current5$stat = _apiRef$current5.state) === null || _apiRef$current5$stat === void 0 ? void 0 : (_apiRef$current5$stat2 = _apiRef$current5$stat.pivoting) === null || _apiRef$current5$stat2 === void 0 ? void 0 : _apiRef$current5$stat2.active) !== null && _apiRef$current$state3 !== void 0 ? _apiRef$current$state3 : pivotActiveParsed;
3381
- if (!pivotActiveLive) {
3382
- updateUrl(buildModel({
3383
- columnsModel: columnsVisibilityModel
3384
- }), search, localStorageVersion, historyReplace, columns);
3385
- }
3386
4031
  propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
4032
+ updateUrl(buildModel({
4033
+ columnsModel: columnsVisibilityModel
4034
+ }), search, localStorageVersion, historyReplace, columns);
3387
4035
  },
3388
4036
  onColumnWidthChange: (params, event, details) => {
3389
4037
  propsOnColumnWidthChange === null || propsOnColumnWidthChange === void 0 ? void 0 : propsOnColumnWidthChange(params, event, details);
@@ -3391,38 +4039,11 @@ const useStatefulTable = props => {
3391
4039
  newWidth: params.width,
3392
4040
  field: params.colDef.field
3393
4041
  });
3394
- },
3395
- onRowGroupingModelChange: (model, details) => {
3396
- updateUrl(buildModel({
3397
- rowGroupingModel: model
3398
- }), search, localStorageVersion, historyReplace, columns);
3399
- propsOnRowGroupingModelChange === null || propsOnRowGroupingModelChange === void 0 ? void 0 : propsOnRowGroupingModelChange(model, details);
3400
- },
3401
- onAggregationModelChange: (model, details) => {
3402
- updateUrl(buildModel({
3403
- aggregationModel: model
3404
- }), search, localStorageVersion, historyReplace, columns);
3405
- propsOnAggregationModelChange === null || propsOnAggregationModelChange === void 0 ? void 0 : propsOnAggregationModelChange(model, details);
3406
- },
3407
- onPivotModelChange: model => {
3408
- const simplified = fromGridPivotModel(model);
3409
- if (isDeepEqual(simplified, lastEmittedPivotRef.current)) return;
3410
- lastEmittedPivotRef.current = simplified;
3411
- updateUrl(buildModel({
3412
- pivotModel: simplified
3413
- }), search, localStorageVersion, historyReplace, columns);
3414
- propsOnPivotModelChange === null || propsOnPivotModelChange === void 0 ? void 0 : propsOnPivotModelChange(model);
3415
- },
3416
- onPivotActiveChange: active => {
3417
- if (active === pivotActiveParsed) return;
3418
- updateUrl(buildModel({
3419
- pivotActive: active
3420
- }), search, localStorageVersion, historyReplace, columns);
3421
4042
  }
3422
4043
  };
3423
4044
  };
3424
4045
 
3425
- 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", "selectionBannerPlacement", "paginationProps", "rows", "pageSizeOptions", "sx", "theme", "useRouter", "paginationMode", "rowCount", "density", "dataSource", "filterMode", "sortingMode"];
4046
+ 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", "selectionBannerPlacement", "paginationProps", "rows", "pageSizeOptions", "sx", "theme", "useRouter", "paginationMode", "rowCount"];
3426
4047
  const COMPONENT_NAME = 'DataGrid';
3427
4048
  const CLASSNAME = 'redsift-datagrid';
3428
4049
 
@@ -3478,7 +4099,6 @@ const CLASSNAME = 'redsift-datagrid';
3478
4099
  */
3479
4100
 
3480
4101
  const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3481
- var _ref7;
3482
4102
  const datagridRef = ref || useRef();
3483
4103
  const {
3484
4104
  apiRef: propsApiRef,
@@ -3507,9 +4127,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3507
4127
  onColumnVisibilityModelChange: propsOnColumnVisibilityModelChange,
3508
4128
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3509
4129
  onSortModelChange: propsOnSortModelChange,
3510
- onRowGroupingModelChange: propsOnRowGroupingModelChange,
3511
- onAggregationModelChange: propsOnAggregationModelChange,
3512
- onPivotModelChange: propsOnPivotModelChange,
3513
4130
  pagination,
3514
4131
  paginationPlacement = 'both',
3515
4132
  selectionBannerPlacement = 'top',
@@ -3520,26 +4137,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3520
4137
  theme: propsTheme,
3521
4138
  useRouter,
3522
4139
  paginationMode = 'client',
3523
- rowCount,
3524
- density: _density,
3525
- dataSource,
3526
- filterMode: propsFilterMode,
3527
- sortingMode: propsSortingMode
4140
+ rowCount
3528
4141
  } = props,
3529
4142
  forwardedProps = _objectWithoutProperties(props, _excluded);
3530
- const theme = useTheme(propsTheme);
4143
+ const theme = useTheme$1(propsTheme);
3531
4144
  const _apiRef = useGridApiRef();
3532
4145
  const apiRef = propsApiRef !== null && propsApiRef !== void 0 ? propsApiRef : _apiRef;
4146
+ const RenderedToolbar = slots !== null && slots !== void 0 && slots.toolbar ? slots.toolbar : Toolbar;
3533
4147
  LicenseInfo.setLicenseKey(license);
3534
4148
  const height = propsHeight !== null && propsHeight !== void 0 ? propsHeight : autoHeight ? undefined : '500px';
3535
-
3536
- // When dataSource is present, MUI manages filter/sort/pagination internally.
3537
- // We must not pass controlled models — only initialState (one-time) and
3538
- // write-only onChange handlers for URL/localStorage persistence.
3539
- const isDataSourceMode = Boolean(dataSource);
3540
- const effectivePaginationMode = isDataSourceMode ? 'server' : paginationMode;
3541
- const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode;
3542
- const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode;
3543
4149
  const {
3544
4150
  onColumnVisibilityModelChange: controlledOnColumnVisibilityModelChange,
3545
4151
  onFilterModelChange: controlledOnFilterModelChange,
@@ -3573,15 +4179,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3573
4179
  pinnedColumns,
3574
4180
  sortModel,
3575
4181
  onColumnWidthChange,
3576
- columnOrderModel,
3577
- rowGroupingModel,
3578
- aggregationModel,
3579
- pivotModel,
3580
- pivotActive,
3581
- onRowGroupingModelChange,
3582
- onAggregationModelChange,
3583
- onPivotModelChange,
3584
- onPivotActiveChange
4182
+ columnOrderModel
3585
4183
  } = useStatefulTable({
3586
4184
  apiRef: apiRef,
3587
4185
  initialState,
@@ -3592,9 +4190,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3592
4190
  onPaginationModelChange: controlledOnPaginationModelChange,
3593
4191
  onPinnedColumnsChange: controlledOnPinnedColumnsChange,
3594
4192
  onSortModelChange: controlledOnSortModelChange,
3595
- onRowGroupingModelChange: propsOnRowGroupingModelChange,
3596
- onAggregationModelChange: propsOnAggregationModelChange,
3597
- onPivotModelChange: propsOnPivotModelChange,
3598
4193
  useRouter: useRouter,
3599
4194
  localStorageVersion,
3600
4195
  previousLocalStorageVersions
@@ -3630,61 +4225,9 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3630
4225
  return column;
3631
4226
  });
3632
4227
  }, [columns, columnOrderModel]);
3633
-
3634
- // In dataSource mode, track pagination locally for the custom pagination slots
3635
- // (rendered outside DataGridPremium). MUI owns the actual pagination state internally.
3636
- const [dataSourcePaginationModel, setDataSourcePaginationModel] = useState(paginationModel);
3637
-
3638
- // The pagination model to use for display in pagination slots
3639
- const activePaginationModel = isDataSourceMode ? dataSourcePaginationModel : paginationModel;
3640
-
3641
- // Wrap onPaginationModelChange to also track state locally in dataSource mode
3642
- const wrappedOnPaginationModelChange = useCallback((model, details) => {
3643
- if (isDataSourceMode) {
3644
- setDataSourcePaginationModel(model);
3645
- }
3646
- onPaginationModelChange(model, details);
3647
- }, [isDataSourceMode, onPaginationModelChange]);
3648
-
3649
- // In dataSource mode, pagination changes from our custom pagination slots
3650
- // (rendered outside MUI's pagination state) route through apiRef so MUI's
3651
- // internal page state updates and dataSource.getRows() refetches with the
3652
- // new params. The `paginationModelChange` subscription below picks up the
3653
- // resulting state change and propagates it to URL/localStorage and local
3654
- // React state via wrappedOnPaginationModelChange.
3655
- const dataSourcePaginationChange = useCallback(model => {
3656
- var _apiRef$current;
3657
- (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPaginationModel(model);
3658
- }, [apiRef]);
3659
-
3660
- // In dataSource mode, subscribe to MUI's `paginationModelChange` event so
3661
- // URL state stays in sync with MUI's internal pagination regardless of how
3662
- // it changed (slot click, apiRef.setPaginationModel from consumer code,
3663
- // MUI internal updates, etc.). Relying on MUI's `onPaginationModelChange`
3664
- // prop callback alone is not sufficient: in pivot/GroupedData strategy mode
3665
- // and with `paginationModel` seeded via `initialState` (rather than as a
3666
- // controlled prop), the prop callback can be missed under certain
3667
- // re-render orderings. The event fires reliably whenever the internal
3668
- // state changes via `setState('setPaginationModel')`, see
3669
- // `useGridStateInitialization.setState` → `publishEvent(changeEvent, …)`.
3670
- // The deep-equal guard inside `useStatefulTable.onPaginationModelChange`
3671
- // dedupes any duplicate emits, so overlap with the prop callback is safe.
3672
- useEffect(() => {
3673
- if (!isDataSourceMode) return;
3674
- const api = apiRef.current;
3675
- if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3676
- return api.subscribeEvent('paginationModelChange', model => {
3677
- wrappedOnPaginationModelChange({
3678
- page: model.page,
3679
- pageSize: model.pageSize
3680
- }, {
3681
- reason: 'paginationModelChange'
3682
- });
3683
- });
3684
- }, [isDataSourceMode, apiRef, wrappedOnPaginationModelChange]);
3685
- const [rowSelectionModel, setRowSelectionModel] = useState(() => normalizeRowSelectionModel(propsRowSelectionModel));
4228
+ const [rowSelectionModel, setRowSelectionModel] = useState(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3686
4229
  useEffect(() => {
3687
- setRowSelectionModel(normalizeRowSelectionModel(propsRowSelectionModel));
4230
+ setRowSelectionModel(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3688
4231
  }, [propsRowSelectionModel]);
3689
4232
  const onRowSelectionModelChange = (selectionModel, details) => {
3690
4233
  setRowSelectionModel(selectionModel);
@@ -3698,49 +4241,25 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3698
4241
  pageSize: paginationModel.pageSize
3699
4242
  });
3700
4243
 
3701
- // Version counter to force re-renders when selectionStatus ref changes
3702
- const [, forceSelectionUpdate] = useState(0);
3703
-
3704
4244
  // The checkboxSelectionVisibleOnly should only be applied to client-side pagination,
3705
4245
  // for server-side pagination it produces inconsistent behavior when selecting all rows in pages 2 and beyond
3706
- const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(effectivePaginationMode != 'server');
4246
+ const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(paginationMode != 'server');
3707
4247
 
3708
4248
  // Banner and pager placements are independent. `belowToolbar` (for either) renders
3709
- // in a row inside the toolbar slot, and only applies when pagination is on.
4249
+ // in the toolbar-slot row, and only applies when pagination is on.
3710
4250
  const bannerAtTop = selectionBannerPlacement === 'top';
3711
4251
  const bannerAtBottom = selectionBannerPlacement === 'bottom';
3712
4252
  const bannerBelowToolbar = selectionBannerPlacement === 'belowToolbar' && Boolean(pagination);
3713
4253
  const pagerBelowToolbar = paginationPlacement === 'belowToolbar' && Boolean(pagination);
3714
- const belowToolbarActive = bannerBelowToolbar || pagerBelowToolbar;
3715
-
3716
- // Track when the grid API is ready to ensure top pagination renders correctly
3717
- const [gridReady, setGridReady] = useState(false);
3718
-
3719
- // Force re-render when the grid API becomes ready (for top pagination)
3720
- useEffect(() => {
3721
- if (apiRef.current && !gridReady) {
3722
- setGridReady(true);
3723
- }
3724
- });
3725
-
3726
- // Sync persisted density via apiRef — initialState only applies on mount,
3727
- // so this handles SPA back/forward navigation where controlledDensity changes after mount
3728
- useEffect(() => {
3729
- if (apiRef.current) {
3730
- apiRef.current.setDensity(controlledDensity);
3731
- }
3732
- }, [controlledDensity, apiRef]);
3733
4254
 
3734
4255
  // in server-side pagination we want to update the selection status
3735
4256
  // every time we navigate between pages, resize our page or select something
3736
4257
  useEffect(() => {
3737
- if (effectivePaginationMode == 'server') {
3738
- onServerSideSelectionStatusChange(rowSelectionModel, apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, activePaginationModel.page, activePaginationModel.pageSize);
4258
+ if (paginationMode == 'server') {
4259
+ onServerSideSelectionStatusChange(Array.isArray(rowSelectionModel) ? rowSelectionModel : [rowSelectionModel], apiRef, selectionStatusRef, isRowSelectable, paginationModel.page, paginationModel.pageSize);
3739
4260
  }
3740
- }, [rowSelectionModel, activePaginationModel.page, activePaginationModel.pageSize, rows]);
3741
-
3742
- // In dataSource mode MUI provides rows internally; skip the guard.
3743
- if (!isDataSourceMode && !Array.isArray(rows)) {
4261
+ }, [rowSelectionModel, paginationModel.page, paginationModel.pageSize, rows]);
4262
+ if (!Array.isArray(rows)) {
3744
4263
  return null;
3745
4264
  }
3746
4265
 
@@ -3749,15 +4268,9 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3749
4268
  // receive the fresh value in the same render cycle — no extra re-render needed.
3750
4269
  // The ref is kept in sync for the onRowSelectionModelChange callback's deselect logic.
3751
4270
  let selectionStatus = selectionStatusRef.current;
3752
- if (pagination && effectivePaginationMode !== 'server' && getSelectionCount(rowSelectionModel) > 0) {
4271
+ if (pagination && paginationMode !== 'server' && Array.isArray(rowSelectionModel) && rowSelectionModel.length > 0) {
3753
4272
  try {
3754
- // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors.
3755
- // MUI's paginated selectors use apiRef internal state which may be stale when
3756
- // paginationModel prop changes — our React state is always up to date.
3757
- const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3758
- const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3759
- const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3760
- const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref2 => {
4273
+ const selectableRowsInPage = isRowSelectable ? gridPaginatedVisibleSortedGridRowEntriesSelector(apiRef).filter(_ref2 => {
3761
4274
  let {
3762
4275
  model
3763
4276
  } = _ref2;
@@ -3769,29 +4282,24 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3769
4282
  id
3770
4283
  } = _ref3;
3771
4284
  return id;
3772
- }) : pageEntries.map(_ref4 => {
3773
- let {
3774
- id
3775
- } = _ref4;
3776
- return id;
3777
- });
4285
+ }) : gridPaginatedVisibleSortedGridRowIdsSelector(apiRef);
3778
4286
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
3779
- const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref5 => {
4287
+ const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref4 => {
3780
4288
  let {
3781
4289
  model
3782
- } = _ref5;
4290
+ } = _ref4;
3783
4291
  return isRowSelectable({
3784
4292
  row: model
3785
4293
  });
3786
- }).map(_ref6 => {
4294
+ }).map(_ref5 => {
3787
4295
  let {
3788
4296
  id
3789
- } = _ref6;
4297
+ } = _ref5;
3790
4298
  return id;
3791
4299
  }) : gridFilteredSortedRowIdsSelector(apiRef);
3792
4300
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
3793
- const numberOfSelectedRows = getSelectionCount(rowSelectionModel);
3794
- const selectedOnCurrentPage = selectableRowsInPage.filter(id => isRowSelected(rowSelectionModel, id));
4301
+ const numberOfSelectedRows = rowSelectionModel.length;
4302
+ const selectedOnCurrentPage = selectableRowsInPage.filter(id => rowSelectionModel.includes(id));
3795
4303
  if (numberOfSelectedRows === numberOfSelectableRowsInTable && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
3796
4304
  selectionStatus = {
3797
4305
  type: 'table',
@@ -3816,7 +4324,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3816
4324
  } catch {
3817
4325
  // apiRef may not be initialized on first render
3818
4326
  }
3819
- } else if (pagination && effectivePaginationMode !== 'server') {
4327
+ } else if (pagination && paginationMode !== 'server') {
3820
4328
  selectionStatus = {
3821
4329
  type: 'none',
3822
4330
  numberOfSelectedRows: 0
@@ -3835,48 +4343,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3835
4343
  }
3836
4344
  }
3837
4345
  }), [theme]);
3838
-
3839
- // Per-render data for the stable `BelowToolbar`/`BottomPagination` slots, injected via
3840
- // `slotProps` so the slot identities stay constant and their subtrees are re-rendered, not
3841
- // remounted (remounting the toolbar dropped quick-search focus on every keystroke). Typed as
3842
- // ToolbarWrapper props so mistakes are caught here; cast to MUI's slot types at the injection
3843
- // sites below. See ../DataGrid/defaultSlots.
3844
- const belowToolbarSlotProps = {
3845
- RenderedToolbar: (_ref7 = slots === null || slots === void 0 ? void 0 : slots.toolbar) !== null && _ref7 !== void 0 ? _ref7 : Toolbar,
3846
- hideToolbar,
3847
- filterModel,
3848
- onFilterModelChange,
3849
- pagination,
3850
- paginationMode: effectivePaginationMode,
3851
- displaySelection: bannerBelowToolbar,
3852
- displayPagination: pagerBelowToolbar,
3853
- displayRowsPerPage: pagerBelowToolbar,
3854
- selectionStatus,
3855
- apiRef,
3856
- isRowSelectable,
3857
- paginationModel: activePaginationModel,
3858
- onPaginationModelChange: isDataSourceMode ? dataSourcePaginationChange : onPaginationModelChange,
3859
- pageSizeOptions: pageSizeOptions,
3860
- paginationProps,
3861
- rowCount
3862
- };
3863
- const bottomPaginationSlotProps = {
3864
- pagination,
3865
- paginationMode: effectivePaginationMode,
3866
- displaySelection: bannerAtBottom,
3867
- displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
3868
- displayPagination: ['bottom', 'both'].includes(paginationPlacement),
3869
- selectionStatus,
3870
- paginationModel: activePaginationModel,
3871
- // Bottom pager routes non-dataSource changes through the wrapped handler (the
3872
- // belowToolbar/top pagers use the unwrapped one) — preserved from the previous inline slot.
3873
- onPaginationModelChange: isDataSourceMode ? dataSourcePaginationChange : wrappedOnPaginationModelChange,
3874
- apiRef,
3875
- isRowSelectable,
3876
- pageSizeOptions: pageSizeOptions,
3877
- paginationProps,
3878
- rowCount
3879
- };
3880
4346
  return /*#__PURE__*/React__default.createElement(ThemeProvider, {
3881
4347
  value: {
3882
4348
  theme
@@ -3887,172 +4353,117 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3887
4353
  ref: datagridRef,
3888
4354
  className: classNames(StatefulDataGrid.className, className),
3889
4355
  $height: height
3890
- }, pagination && gridReady && (bannerAtTop || ['top', 'both'].includes(paginationPlacement)) ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, {
3891
- displaySelection: bannerAtTop,
3892
- displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3893
- displayPagination: ['top', 'both'].includes(paginationPlacement),
3894
- selectionStatus: selectionStatus,
3895
- paginationModel: activePaginationModel,
3896
- onPaginationModelChange: isDataSourceMode ? dataSourcePaginationChange : onPaginationModelChange,
3897
- pageSizeOptions: pageSizeOptions,
3898
- paginationProps: paginationProps,
3899
- rowCount: rowCount
3900
- }) : /*#__PURE__*/React__default.createElement(ControlledPagination, {
3901
- displaySelection: bannerAtTop,
3902
- displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3903
- displayPagination: ['top', 'both'].includes(paginationPlacement),
3904
- selectionStatus: selectionStatus,
3905
- apiRef: apiRef,
3906
- isRowSelectable: isRowSelectable,
3907
- paginationModel: activePaginationModel,
3908
- onPaginationModelChange: onPaginationModelChange,
3909
- pageSizeOptions: pageSizeOptions,
3910
- paginationProps: paginationProps
3911
- }) : null, /*#__PURE__*/React__default.createElement(DataGridPremium, _extends({}, forwardedProps, {
4356
+ }, /*#__PURE__*/React__default.createElement(DataGridPro, _extends$2({}, forwardedProps, {
3912
4357
  apiRef: apiRef,
3913
- dataSource: dataSource,
3914
4358
  columns: orderedColumns,
4359
+ columnVisibilityModel: columnVisibilityModel,
4360
+ density: controlledDensity,
4361
+ filterModel: filterModel,
3915
4362
  onColumnVisibilityModelChange: onColumnVisibilityModelChange,
4363
+ onFilterModelChange: onFilterModelChange,
4364
+ onPaginationModelChange: onPaginationModelChange,
3916
4365
  onPinnedColumnsChange: onPinnedColumnsChange,
4366
+ onSortModelChange: onSortModelChange,
4367
+ paginationModel: paginationModel,
4368
+ pinnedColumns: pinnedColumns,
4369
+ sortModel: sortModel,
3917
4370
  pageSizeOptions: pageSizeOptions,
3918
4371
  onColumnWidthChange: onColumnWidthChange,
3919
- onRowGroupingModelChange: onRowGroupingModelChange,
3920
- onAggregationModelChange: onAggregationModelChange,
3921
- onPivotModelChange: onPivotModelChange,
3922
- pivotActive: pivotActive,
3923
- onPivotActiveChange: onPivotActiveChange
3924
- // In dataSource mode: models are uncontrolled (MUI owns them),
3925
- // onChange handlers are write-only for URL/localStorage persistence,
3926
- // and initialState seeds MUI on mount from the persisted URL state.
3927
- // columnVisibilityModel / pinnedColumns / rowGroupingModel /
3928
- // aggregationModel / pivotModel are also uncontrolled here to
3929
- // avoid a controlled re-render race with consumer-side
3930
- // microtask-deferred history updates (otherwise user toggles
3931
- // flip back when MUI re-emits with the stale controlled value).
3932
- // pivotModel specifically also carries `hidden`/`sort` field
3933
- // metadata that our simplified URL representation strips — so
3934
- // controlling it would prevent users from unchecking fields in
3935
- // the pivot panel (the controlled prop would immediately re-add
3936
- // them). Consumers needing programmatic changes should use the
3937
- // apiRef imperative API.
3938
- }, isDataSourceMode ? {
3939
- onFilterModelChange: onFilterModelChange,
3940
- onSortModelChange: onSortModelChange,
3941
- onPaginationModelChange: wrappedOnPaginationModelChange,
3942
- initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3943
- density: controlledDensity,
3944
- columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3945
- orderedFields: columnOrderModel,
3946
- columnVisibilityModel
3947
- }),
3948
- pinnedColumns,
3949
- rowGrouping: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.rowGrouping), {}, {
3950
- model: rowGroupingModel
3951
- }),
3952
- aggregation: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.aggregation), {}, {
3953
- model: aggregationModel
3954
- }),
3955
- filter: {
3956
- filterModel
3957
- },
3958
- sorting: {
3959
- sortModel
3960
- },
3961
- pagination: {
3962
- paginationModel
3963
- },
3964
- pivoting: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.pivoting), {}, {
3965
- model: pivotModel,
3966
- enabled: pivotActive
3967
- })
3968
- })
3969
- } : {
3970
- columnVisibilityModel,
3971
- pinnedColumns,
3972
- rowGroupingModel,
3973
- aggregationModel,
3974
- filterModel,
3975
- sortModel,
3976
- paginationModel,
3977
- pivotModel,
3978
- onFilterModelChange: onFilterModelChange,
3979
- onSortModelChange: onSortModelChange,
3980
- onPaginationModelChange: wrappedOnPaginationModelChange,
3981
4372
  initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3982
- density: controlledDensity,
3983
4373
  columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3984
4374
  orderedFields: columnOrderModel
3985
4375
  })
3986
- })
3987
- }, {
4376
+ }),
3988
4377
  isRowSelectable: isRowSelectable,
3989
4378
  pagination: pagination,
3990
- paginationMode: effectivePaginationMode,
3991
- filterMode: effectiveFilterMode,
3992
- sortingMode: effectiveSortingMode,
3993
- keepNonExistentRowsSelected: effectivePaginationMode == 'server',
3994
- rows: isDataSourceMode ? [] : rows,
4379
+ paginationMode: paginationMode,
4380
+ keepNonExistentRowsSelected: paginationMode == 'server',
4381
+ rows: rows,
3995
4382
  rowCount: rowCount,
3996
4383
  autoHeight: autoHeight,
3997
4384
  checkboxSelectionVisibleOnly: checkboxSelectionVisibleOnly,
3998
- disableRowSelectionExcludeModel: true,
3999
- showToolbar: !hideToolbar || belowToolbarActive,
4000
- slots: _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, baseGridSlots), slots), belowToolbarActive ? {
4001
- toolbar: BelowToolbar
4002
- } : {}), {}, {
4385
+ slots: _objectSpread2(_objectSpread2(_objectSpread2({}, baseGridSlots), slots), {}, {
4386
+ // The toolbar is already a stable module-level component (ToolbarWrapper) with its
4387
+ // per-render data injected via `slotProps.toolbar` below. `BottomPagination` is
4388
+ // likewise stable; a fresh inline function here would remount the slot's subtree
4389
+ // every render.
4390
+ toolbar: ToolbarWrapper,
4003
4391
  pagination: BottomPagination
4004
4392
  }),
4005
- slotProps: _objectSpread2(_objectSpread2(_objectSpread2({}, slotProps), belowToolbarActive ? {
4006
- toolbar: _objectSpread2(_objectSpread2({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar), belowToolbarSlotProps)
4007
- } : {}), {}, {
4008
- pagination: _objectSpread2(_objectSpread2({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.pagination), bottomPaginationSlotProps)
4393
+ slotProps: _objectSpread2(_objectSpread2({}, slotProps), {}, {
4394
+ toolbar: _objectSpread2({
4395
+ hideToolbar,
4396
+ RenderedToolbar,
4397
+ filterModel,
4398
+ onFilterModelChange,
4399
+ pagination,
4400
+ displaySelection: bannerAtTop || bannerBelowToolbar,
4401
+ displayPagination: ['top', 'both'].includes(paginationPlacement) || pagerBelowToolbar,
4402
+ displayRowsPerPage: pagerBelowToolbar,
4403
+ selectionStatus,
4404
+ apiRef,
4405
+ isRowSelectable,
4406
+ paginationModel,
4407
+ onPaginationModelChange,
4408
+ pageSizeOptions,
4409
+ paginationProps,
4410
+ paginationMode,
4411
+ rowCount
4412
+ }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar),
4413
+ // Per-render data for the stable `BottomPagination` slot. Consumer slot props are
4414
+ // spread first; the DS layout data wins. Cast at the MUI boundary because these are
4415
+ // ToolbarWrapper props, not the MUI slot prop types.
4416
+ pagination: _objectSpread2(_objectSpread2({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.pagination), {}, {
4417
+ pagination,
4418
+ paginationMode,
4419
+ displaySelection: bannerAtBottom,
4420
+ displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
4421
+ displayPagination: ['bottom', 'both'].includes(paginationPlacement),
4422
+ selectionStatus,
4423
+ paginationModel,
4424
+ onPaginationModelChange,
4425
+ apiRef,
4426
+ isRowSelectable,
4427
+ pageSizeOptions,
4428
+ paginationProps,
4429
+ rowCount
4430
+ })
4009
4431
  }),
4010
4432
  rowSelectionModel: rowSelectionModel,
4011
4433
  onRowSelectionModelChange: (newSelectionModel, details) => {
4012
- if (pagination && effectivePaginationMode != 'server') {
4013
- // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors
4014
- // to avoid stale apiRef pagination state.
4015
- const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
4016
- const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
4017
- const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
4018
- const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref8 => {
4434
+ if (pagination && paginationMode != 'server') {
4435
+ const selectableRowsInPage = isRowSelectable ? gridPaginatedVisibleSortedGridRowEntriesSelector(apiRef).filter(_ref6 => {
4019
4436
  let {
4020
4437
  model
4021
- } = _ref8;
4438
+ } = _ref6;
4022
4439
  return isRowSelectable({
4023
4440
  row: model
4024
4441
  });
4025
- }).map(_ref9 => {
4026
- let {
4027
- id
4028
- } = _ref9;
4029
- return id;
4030
- }) : pageEntries.map(_ref10 => {
4442
+ }).map(_ref7 => {
4031
4443
  let {
4032
4444
  id
4033
- } = _ref10;
4445
+ } = _ref7;
4034
4446
  return id;
4035
- });
4447
+ }) : gridPaginatedVisibleSortedGridRowIdsSelector(apiRef);
4036
4448
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4037
- const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref11 => {
4449
+ const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref8 => {
4038
4450
  let {
4039
4451
  model
4040
- } = _ref11;
4452
+ } = _ref8;
4041
4453
  return isRowSelectable({
4042
4454
  row: model
4043
4455
  });
4044
- }).map(_ref12 => {
4456
+ }).map(_ref9 => {
4045
4457
  let {
4046
4458
  id
4047
- } = _ref12;
4459
+ } = _ref9;
4048
4460
  return id;
4049
4461
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4050
4462
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4051
- const numberOfSelectedRows = getSelectionCount(newSelectionModel);
4463
+ const numberOfSelectedRows = newSelectionModel.length;
4052
4464
  if (selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable - numberOfSelectableRowsInPage || selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable || selectionStatusRef.current.type === 'page' && numberOfSelectedRows === numberOfSelectableRowsInPage) {
4053
4465
  setTimeout(() => {
4054
- var _apiRef$current2;
4055
- (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.selectRows([], true, true);
4466
+ apiRef.current.selectRows([], true, true);
4056
4467
  }, 0);
4057
4468
  }
4058
4469
  if (numberOfSelectedRows === numberOfSelectableRowsInPage && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
@@ -4076,7 +4487,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4076
4487
  numberOfSelectedRows
4077
4488
  };
4078
4489
  }
4079
- forceSelectionUpdate(v => v + 1);
4080
4490
  }
4081
4491
  onRowSelectionModelChange === null || onRowSelectionModelChange === void 0 ? void 0 : onRowSelectionModelChange(newSelectionModel, details);
4082
4492
  },
@@ -4094,5 +4504,5 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4094
4504
  StatefulDataGrid.className = CLASSNAME;
4095
4505
  StatefulDataGrid.displayName = COMPONENT_NAME;
4096
4506
 
4097
- 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, resetColumnVisibility as a3, convertToDisplayFormat as a4, convertFromDisplayFormat as a5, getDecodedSearchFromUrl as a6, buildQueryParamsString as a7, areSearchStringsEqual as a8, decodeValue as a9, getSearchParamsFromAggregation as aA, fromGridPivotModel as aB, getPivotFromString as aC, getSearchParamsFromPivot as aD, getPivotActiveFromString as aE, getSearchParamsFromPivotActive as aF, getSearchParamsFromVersion as aG, getFinalSearch as aH, getModelsParsedOrUpdateLocalStorage as aI, updateUrl as aJ, areFilterModelsEquivalent as aK, StatefulDataGrid as aL, encodeValue as aa, urlSearchParamsToString as ab, numberOperatorEncoder as ac, numberOperatorDecoder as ad, isOperatorValueValid as ae, isValueValid as af, getFilterModelFromString as ag, normalizeDateValue as ah, getSearchParamsFromFilterModel as ai, getSortingFromString as aj, getSearchParamsFromSorting as ak, getPaginationFromString as al, getSearchParamsFromPagination as am, getColumnVisibilityFromString as an, getSearchParamsFromColumnVisibility as ao, getPinnedColumnsFromString as ap, getSearchParamsFromPinnedColumns as aq, getSearchParamsFromTab as ar, getDensityFromString as as, getSearchParamsFromDensity as at, getDensityModel as au, getColumnOrderFromString as av, getSearchParamsFromColumnOrder as aw, getRowGroupingFromString as ax, getSearchParamsFromRowGrouping as ay, getAggregationFromString 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 };
4507
+ 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, resetColumnVisibility as a1, convertToDisplayFormat as a2, convertFromDisplayFormat as a3, getDecodedSearchFromUrl as a4, buildQueryParamsString as a5, areSearchStringsEqual as a6, decodeValue as a7, encodeValue as a8, urlSearchParamsToString as a9, numberOperatorEncoder as aa, numberOperatorDecoder as ab, isOperatorValueValid as ac, isValueValid as ad, getFilterModelFromString as ae, normalizeDateValue 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, getColumnOrderFromString as as, getSearchParamsFromColumnOrder as at, getSearchParamsFromVersion as au, getFinalSearch as av, getModelsParsedOrUpdateLocalStorage as aw, updateUrl as ax, areFilterModelsEquivalent as ay, StatefulDataGrid 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 };
4098
4508
  //# sourceMappingURL=StatefulDataGrid2.js.map