@redsift/table 12.5.6 → 12.5.7-muiv7

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,19 +1,1500 @@
1
1
  import { _ as _objectSpread2, a as _objectWithoutProperties, b as _extends } from './_rollupPluginBabelHelpers.js';
2
2
  import * as React from 'react';
3
3
  import React__default, { useCallback, useEffect, useRef, useMemo, forwardRef, useState } from 'react';
4
- import { createTheme, ThemeProvider as ThemeProvider$1 } from '@mui/material/styles';
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, RedsiftColorBlueN, RedsiftColorNeutralXDarkGrey, RedsiftColorNeutralWhite, ThemeProvider } from '@redsift/design-system';
6
+ import { getGridNumericOperators as getGridNumericOperators$1, GridFilterInputValue, GridFilterInputSingleSelect, GridFilterInputMultipleValue, GridFilterInputMultipleSingleSelect, getGridStringOperators as getGridStringOperators$1, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators, GridLogicOperator, useGridApiRef, 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 BelowToolbar, a as BottomPagination, b as baseGridSlots } from './useControlledDatagridState.js';
12
8
  import { mdiSync } from '@redsift/icons';
9
+ import { d as defaultSxConfig, i as isPlainObject, s as styled, a as styleFunctionSx, c as clsx, g as generateUtilityClasses, b as createTheme, T as THEME_ID, C as ClassNameGenerator, P as PropTypes, e as generateUtilityClass, f as styled$1, u as useDefaultProps, h as composeClasses, r as rootShouldForwardProp, j as refType } from './Portal.js';
10
+ import { j as jsxRuntimeExports } from './jsx-runtime.js';
11
+ import { u as useTheme, m as memoTheme, c as createSimplePaletteValueFilter, a as useFormControl, b as formControlState, d as capitalize, i as isAdornedStart, e as isFilled, F as FormControlContext, h as useId, j as useSlot, k as Select, I as Input, l as FilledInput, O as OutlinedInput, o as onServerSideSelectionStatusChange } from './ServerSideControlledPagination.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';
16
14
 
15
+ const splitProps = props => {
16
+ const result = {
17
+ systemProps: {},
18
+ otherProps: {}
19
+ };
20
+ const config = props?.theme?.unstable_sxConfig ?? defaultSxConfig;
21
+ Object.keys(props).forEach(prop => {
22
+ if (config[prop]) {
23
+ result.systemProps[prop] = props[prop];
24
+ } else {
25
+ result.otherProps[prop] = props[prop];
26
+ }
27
+ });
28
+ return result;
29
+ };
30
+ function extendSxProp(props) {
31
+ const {
32
+ sx: inSx,
33
+ ...other
34
+ } = props;
35
+ const {
36
+ systemProps,
37
+ otherProps
38
+ } = splitProps(other);
39
+ let finalSx;
40
+ if (Array.isArray(inSx)) {
41
+ finalSx = [systemProps, ...inSx];
42
+ } else if (typeof inSx === 'function') {
43
+ finalSx = (...args) => {
44
+ const result = inSx(...args);
45
+ if (!isPlainObject(result)) {
46
+ return systemProps;
47
+ }
48
+ return {
49
+ ...systemProps,
50
+ ...result
51
+ };
52
+ };
53
+ } else {
54
+ finalSx = {
55
+ ...systemProps,
56
+ ...inSx
57
+ };
58
+ }
59
+ return {
60
+ ...otherProps,
61
+ sx: finalSx
62
+ };
63
+ }
64
+
65
+ function createBox(options = {}) {
66
+ const {
67
+ themeId,
68
+ defaultTheme,
69
+ defaultClassName = 'MuiBox-root',
70
+ generateClassName
71
+ } = options;
72
+ const BoxRoot = styled('div', {
73
+ shouldForwardProp: prop => prop !== 'theme' && prop !== 'sx' && prop !== 'as'
74
+ })(styleFunctionSx);
75
+ const Box = /*#__PURE__*/React.forwardRef(function Box(inProps, ref) {
76
+ const theme = useTheme(defaultTheme);
77
+ const {
78
+ className,
79
+ component = 'div',
80
+ ...other
81
+ } = extendSxProp(inProps);
82
+ return /*#__PURE__*/jsxRuntimeExports.jsx(BoxRoot, {
83
+ as: component,
84
+ ref: ref,
85
+ className: clsx(className, generateClassName ? generateClassName(defaultClassName) : defaultClassName),
86
+ theme: themeId ? theme[themeId] || theme : theme,
87
+ ...other
88
+ });
89
+ });
90
+ return Box;
91
+ }
92
+
93
+ function isMuiElement(element, muiNames) {
94
+ return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf(
95
+ // For server components `muiName` is avaialble in element.type._payload.value.muiName
96
+ // relevant info - https://github.com/facebook/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
97
+ // eslint-disable-next-line no-underscore-dangle
98
+ element.type.muiName ?? element.type?._payload?.value?.muiName) !== -1;
99
+ }
100
+
101
+ const boxClasses = generateUtilityClasses('MuiBox', ['root']);
102
+ var boxClasses$1 = boxClasses;
103
+
104
+ const defaultTheme = createTheme();
105
+ const Box = createBox({
106
+ themeId: THEME_ID,
107
+ defaultTheme,
108
+ defaultClassName: boxClasses$1.root,
109
+ generateClassName: ClassNameGenerator.generate
110
+ });
111
+ process.env.NODE_ENV !== "production" ? Box.propTypes /* remove-proptypes */ = {
112
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
113
+ // │ These PropTypes are generated from the TypeScript type definitions. │
114
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
115
+ // └─────────────────────────────────────────────────────────────────────┘
116
+ /**
117
+ * @ignore
118
+ */
119
+ children: PropTypes.node,
120
+ /**
121
+ * The component used for the root node.
122
+ * Either a string to use a HTML element or a component.
123
+ */
124
+ component: PropTypes.elementType,
125
+ /**
126
+ * The system prop that allows defining system overrides as well as additional CSS styles.
127
+ */
128
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
129
+ } : void 0;
130
+ var Box$1 = Box;
131
+
132
+ function getFormLabelUtilityClasses(slot) {
133
+ return generateUtilityClass('MuiFormLabel', slot);
134
+ }
135
+ const formLabelClasses = generateUtilityClasses('MuiFormLabel', ['root', 'colorSecondary', 'focused', 'disabled', 'error', 'filled', 'required', 'asterisk']);
136
+ var formLabelClasses$1 = formLabelClasses;
137
+
138
+ const useUtilityClasses$4 = ownerState => {
139
+ const {
140
+ classes,
141
+ color,
142
+ focused,
143
+ disabled,
144
+ error,
145
+ filled,
146
+ required
147
+ } = ownerState;
148
+ const slots = {
149
+ root: ['root', `color${capitalize(color)}`, disabled && 'disabled', error && 'error', filled && 'filled', focused && 'focused', required && 'required'],
150
+ asterisk: ['asterisk', error && 'error']
151
+ };
152
+ return composeClasses(slots, getFormLabelUtilityClasses, classes);
153
+ };
154
+ const FormLabelRoot = styled$1('label', {
155
+ name: 'MuiFormLabel',
156
+ slot: 'Root',
157
+ overridesResolver: (props, styles) => {
158
+ const {
159
+ ownerState
160
+ } = props;
161
+ return [styles.root, ownerState.color === 'secondary' && styles.colorSecondary, ownerState.filled && styles.filled];
162
+ }
163
+ })(memoTheme(({
164
+ theme
165
+ }) => ({
166
+ color: (theme.vars || theme).palette.text.secondary,
167
+ ...theme.typography.body1,
168
+ lineHeight: '1.4375em',
169
+ padding: 0,
170
+ position: 'relative',
171
+ variants: [...Object.entries(theme.palette).filter(createSimplePaletteValueFilter()).map(([color]) => ({
172
+ props: {
173
+ color
174
+ },
175
+ style: {
176
+ [`&.${formLabelClasses$1.focused}`]: {
177
+ color: (theme.vars || theme).palette[color].main
178
+ }
179
+ }
180
+ })), {
181
+ props: {},
182
+ style: {
183
+ [`&.${formLabelClasses$1.disabled}`]: {
184
+ color: (theme.vars || theme).palette.text.disabled
185
+ },
186
+ [`&.${formLabelClasses$1.error}`]: {
187
+ color: (theme.vars || theme).palette.error.main
188
+ }
189
+ }
190
+ }]
191
+ })));
192
+ const AsteriskComponent = styled$1('span', {
193
+ name: 'MuiFormLabel',
194
+ slot: 'Asterisk',
195
+ overridesResolver: (props, styles) => styles.asterisk
196
+ })(memoTheme(({
197
+ theme
198
+ }) => ({
199
+ [`&.${formLabelClasses$1.error}`]: {
200
+ color: (theme.vars || theme).palette.error.main
201
+ }
202
+ })));
203
+ const FormLabel = /*#__PURE__*/React.forwardRef(function FormLabel(inProps, ref) {
204
+ const props = useDefaultProps({
205
+ props: inProps,
206
+ name: 'MuiFormLabel'
207
+ });
208
+ const {
209
+ children,
210
+ className,
211
+ color,
212
+ component = 'label',
213
+ disabled,
214
+ error,
215
+ filled,
216
+ focused,
217
+ required,
218
+ ...other
219
+ } = props;
220
+ const muiFormControl = useFormControl();
221
+ const fcs = formControlState({
222
+ props,
223
+ muiFormControl,
224
+ states: ['color', 'required', 'focused', 'disabled', 'error', 'filled']
225
+ });
226
+ const ownerState = {
227
+ ...props,
228
+ color: fcs.color || 'primary',
229
+ component,
230
+ disabled: fcs.disabled,
231
+ error: fcs.error,
232
+ filled: fcs.filled,
233
+ focused: fcs.focused,
234
+ required: fcs.required
235
+ };
236
+ const classes = useUtilityClasses$4(ownerState);
237
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(FormLabelRoot, {
238
+ as: component,
239
+ ownerState: ownerState,
240
+ className: clsx(classes.root, className),
241
+ ref: ref,
242
+ ...other,
243
+ children: [children, fcs.required && /*#__PURE__*/jsxRuntimeExports.jsxs(AsteriskComponent, {
244
+ ownerState: ownerState,
245
+ "aria-hidden": true,
246
+ className: classes.asterisk,
247
+ children: ["\u2009", '*']
248
+ })]
249
+ });
250
+ });
251
+ process.env.NODE_ENV !== "production" ? FormLabel.propTypes /* remove-proptypes */ = {
252
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
253
+ // │ These PropTypes are generated from the TypeScript type definitions. │
254
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
255
+ // └─────────────────────────────────────────────────────────────────────┘
256
+ /**
257
+ * The content of the component.
258
+ */
259
+ children: PropTypes.node,
260
+ /**
261
+ * Override or extend the styles applied to the component.
262
+ */
263
+ classes: PropTypes.object,
264
+ /**
265
+ * @ignore
266
+ */
267
+ className: PropTypes.string,
268
+ /**
269
+ * The color of the component.
270
+ * It supports both default and custom theme colors, which can be added as shown in the
271
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
272
+ */
273
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
274
+ /**
275
+ * The component used for the root node.
276
+ * Either a string to use a HTML element or a component.
277
+ */
278
+ component: PropTypes.elementType,
279
+ /**
280
+ * If `true`, the label should be displayed in a disabled state.
281
+ */
282
+ disabled: PropTypes.bool,
283
+ /**
284
+ * If `true`, the label is displayed in an error state.
285
+ */
286
+ error: PropTypes.bool,
287
+ /**
288
+ * If `true`, the label should use filled classes key.
289
+ */
290
+ filled: PropTypes.bool,
291
+ /**
292
+ * If `true`, the input of this label is focused (used by `FormGroup` components).
293
+ */
294
+ focused: PropTypes.bool,
295
+ /**
296
+ * If `true`, the label will indicate that the `input` is required.
297
+ */
298
+ required: PropTypes.bool,
299
+ /**
300
+ * The system prop that allows defining system overrides as well as additional CSS styles.
301
+ */
302
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
303
+ } : void 0;
304
+ var FormLabel$1 = FormLabel;
305
+
306
+ function getInputLabelUtilityClasses(slot) {
307
+ return generateUtilityClass('MuiInputLabel', slot);
308
+ }
309
+ generateUtilityClasses('MuiInputLabel', ['root', 'focused', 'disabled', 'error', 'required', 'asterisk', 'formControl', 'sizeSmall', 'shrink', 'animated', 'standard', 'filled', 'outlined']);
310
+
311
+ const useUtilityClasses$3 = ownerState => {
312
+ const {
313
+ classes,
314
+ formControl,
315
+ size,
316
+ shrink,
317
+ disableAnimation,
318
+ variant,
319
+ required
320
+ } = ownerState;
321
+ const slots = {
322
+ root: ['root', formControl && 'formControl', !disableAnimation && 'animated', shrink && 'shrink', size && size !== 'normal' && `size${capitalize(size)}`, variant],
323
+ asterisk: [required && 'asterisk']
324
+ };
325
+ const composedClasses = composeClasses(slots, getInputLabelUtilityClasses, classes);
326
+ return {
327
+ ...classes,
328
+ // forward the focused, disabled, etc. classes to the FormLabel
329
+ ...composedClasses
330
+ };
331
+ };
332
+ const InputLabelRoot = styled$1(FormLabel$1, {
333
+ shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
334
+ name: 'MuiInputLabel',
335
+ slot: 'Root',
336
+ overridesResolver: (props, styles) => {
337
+ const {
338
+ ownerState
339
+ } = props;
340
+ return [{
341
+ [`& .${formLabelClasses$1.asterisk}`]: styles.asterisk
342
+ }, 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]];
343
+ }
344
+ })(memoTheme(({
345
+ theme
346
+ }) => ({
347
+ display: 'block',
348
+ transformOrigin: 'top left',
349
+ whiteSpace: 'nowrap',
350
+ overflow: 'hidden',
351
+ textOverflow: 'ellipsis',
352
+ maxWidth: '100%',
353
+ variants: [{
354
+ props: ({
355
+ ownerState
356
+ }) => ownerState.formControl,
357
+ style: {
358
+ position: 'absolute',
359
+ left: 0,
360
+ top: 0,
361
+ // slight alteration to spec spacing to match visual spec result
362
+ transform: 'translate(0, 20px) scale(1)'
363
+ }
364
+ }, {
365
+ props: {
366
+ size: 'small'
367
+ },
368
+ style: {
369
+ // Compensation for the `Input.inputSizeSmall` style.
370
+ transform: 'translate(0, 17px) scale(1)'
371
+ }
372
+ }, {
373
+ props: ({
374
+ ownerState
375
+ }) => ownerState.shrink,
376
+ style: {
377
+ transform: 'translate(0, -1.5px) scale(0.75)',
378
+ transformOrigin: 'top left',
379
+ maxWidth: '133%'
380
+ }
381
+ }, {
382
+ props: ({
383
+ ownerState
384
+ }) => !ownerState.disableAnimation,
385
+ style: {
386
+ transition: theme.transitions.create(['color', 'transform', 'max-width'], {
387
+ duration: theme.transitions.duration.shorter,
388
+ easing: theme.transitions.easing.easeOut
389
+ })
390
+ }
391
+ }, {
392
+ props: {
393
+ variant: 'filled'
394
+ },
395
+ style: {
396
+ // Chrome's autofill feature gives the input field a yellow background.
397
+ // Since the input field is behind the label in the HTML tree,
398
+ // the input field is drawn last and hides the label with an opaque background color.
399
+ // zIndex: 1 will raise the label above opaque background-colors of input.
400
+ zIndex: 1,
401
+ pointerEvents: 'none',
402
+ transform: 'translate(12px, 16px) scale(1)',
403
+ maxWidth: 'calc(100% - 24px)'
404
+ }
405
+ }, {
406
+ props: {
407
+ variant: 'filled',
408
+ size: 'small'
409
+ },
410
+ style: {
411
+ transform: 'translate(12px, 13px) scale(1)'
412
+ }
413
+ }, {
414
+ props: ({
415
+ variant,
416
+ ownerState
417
+ }) => variant === 'filled' && ownerState.shrink,
418
+ style: {
419
+ userSelect: 'none',
420
+ pointerEvents: 'auto',
421
+ transform: 'translate(12px, 7px) scale(0.75)',
422
+ maxWidth: 'calc(133% - 24px)'
423
+ }
424
+ }, {
425
+ props: ({
426
+ variant,
427
+ ownerState,
428
+ size
429
+ }) => variant === 'filled' && ownerState.shrink && size === 'small',
430
+ style: {
431
+ transform: 'translate(12px, 4px) scale(0.75)'
432
+ }
433
+ }, {
434
+ props: {
435
+ variant: 'outlined'
436
+ },
437
+ style: {
438
+ // see comment above on filled.zIndex
439
+ zIndex: 1,
440
+ pointerEvents: 'none',
441
+ transform: 'translate(14px, 16px) scale(1)',
442
+ maxWidth: 'calc(100% - 24px)'
443
+ }
444
+ }, {
445
+ props: {
446
+ variant: 'outlined',
447
+ size: 'small'
448
+ },
449
+ style: {
450
+ transform: 'translate(14px, 9px) scale(1)'
451
+ }
452
+ }, {
453
+ props: ({
454
+ variant,
455
+ ownerState
456
+ }) => variant === 'outlined' && ownerState.shrink,
457
+ style: {
458
+ userSelect: 'none',
459
+ pointerEvents: 'auto',
460
+ // Theoretically, we should have (8+5)*2/0.75 = 34px
461
+ // but it feels a better when it bleeds a bit on the left, so 32px.
462
+ maxWidth: 'calc(133% - 32px)',
463
+ transform: 'translate(14px, -9px) scale(0.75)'
464
+ }
465
+ }]
466
+ })));
467
+ const InputLabel = /*#__PURE__*/React.forwardRef(function InputLabel(inProps, ref) {
468
+ const props = useDefaultProps({
469
+ name: 'MuiInputLabel',
470
+ props: inProps
471
+ });
472
+ const {
473
+ disableAnimation = false,
474
+ margin,
475
+ shrink: shrinkProp,
476
+ variant,
477
+ className,
478
+ ...other
479
+ } = props;
480
+ const muiFormControl = useFormControl();
481
+ let shrink = shrinkProp;
482
+ if (typeof shrink === 'undefined' && muiFormControl) {
483
+ shrink = muiFormControl.filled || muiFormControl.focused || muiFormControl.adornedStart;
484
+ }
485
+ const fcs = formControlState({
486
+ props,
487
+ muiFormControl,
488
+ states: ['size', 'variant', 'required', 'focused']
489
+ });
490
+ const ownerState = {
491
+ ...props,
492
+ disableAnimation,
493
+ formControl: muiFormControl,
494
+ shrink,
495
+ size: fcs.size,
496
+ variant: fcs.variant,
497
+ required: fcs.required,
498
+ focused: fcs.focused
499
+ };
500
+ const classes = useUtilityClasses$3(ownerState);
501
+ return /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelRoot, {
502
+ "data-shrink": shrink,
503
+ ref: ref,
504
+ className: clsx(classes.root, className),
505
+ ...other,
506
+ ownerState: ownerState,
507
+ classes: classes
508
+ });
509
+ });
510
+ process.env.NODE_ENV !== "production" ? InputLabel.propTypes /* remove-proptypes */ = {
511
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
512
+ // │ These PropTypes are generated from the TypeScript type definitions. │
513
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
514
+ // └─────────────────────────────────────────────────────────────────────┘
515
+ /**
516
+ * The content of the component.
517
+ */
518
+ children: PropTypes.node,
519
+ /**
520
+ * Override or extend the styles applied to the component.
521
+ */
522
+ classes: PropTypes.object,
523
+ /**
524
+ * @ignore
525
+ */
526
+ className: PropTypes.string,
527
+ /**
528
+ * The color of the component.
529
+ * It supports both default and custom theme colors, which can be added as shown in the
530
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
531
+ */
532
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
533
+ /**
534
+ * If `true`, the transition animation is disabled.
535
+ * @default false
536
+ */
537
+ disableAnimation: PropTypes.bool,
538
+ /**
539
+ * If `true`, the component is disabled.
540
+ */
541
+ disabled: PropTypes.bool,
542
+ /**
543
+ * If `true`, the label is displayed in an error state.
544
+ */
545
+ error: PropTypes.bool,
546
+ /**
547
+ * If `true`, the `input` of this label is focused.
548
+ */
549
+ focused: PropTypes.bool,
550
+ /**
551
+ * If `dense`, will adjust vertical spacing. This is normally obtained via context from
552
+ * FormControl.
553
+ */
554
+ margin: PropTypes.oneOf(['dense']),
555
+ /**
556
+ * if `true`, the label will indicate that the `input` is required.
557
+ */
558
+ required: PropTypes.bool,
559
+ /**
560
+ * If `true`, the label is shrunk.
561
+ */
562
+ shrink: PropTypes.bool,
563
+ /**
564
+ * The size of the component.
565
+ * @default 'normal'
566
+ */
567
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['normal', 'small']), PropTypes.string]),
568
+ /**
569
+ * The system prop that allows defining system overrides as well as additional CSS styles.
570
+ */
571
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
572
+ /**
573
+ * The variant to use.
574
+ */
575
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
576
+ } : void 0;
577
+ var InputLabel$1 = InputLabel;
578
+
579
+ function getFormControlUtilityClasses(slot) {
580
+ return generateUtilityClass('MuiFormControl', slot);
581
+ }
582
+ generateUtilityClasses('MuiFormControl', ['root', 'marginNone', 'marginNormal', 'marginDense', 'fullWidth', 'disabled']);
583
+
584
+ const useUtilityClasses$2 = ownerState => {
585
+ const {
586
+ classes,
587
+ margin,
588
+ fullWidth
589
+ } = ownerState;
590
+ const slots = {
591
+ root: ['root', margin !== 'none' && `margin${capitalize(margin)}`, fullWidth && 'fullWidth']
592
+ };
593
+ return composeClasses(slots, getFormControlUtilityClasses, classes);
594
+ };
595
+ const FormControlRoot = styled$1('div', {
596
+ name: 'MuiFormControl',
597
+ slot: 'Root',
598
+ overridesResolver: (props, styles) => {
599
+ const {
600
+ ownerState
601
+ } = props;
602
+ return [styles.root, styles[`margin${capitalize(ownerState.margin)}`], ownerState.fullWidth && styles.fullWidth];
603
+ }
604
+ })({
605
+ display: 'inline-flex',
606
+ flexDirection: 'column',
607
+ position: 'relative',
608
+ // Reset fieldset default style.
609
+ minWidth: 0,
610
+ padding: 0,
611
+ margin: 0,
612
+ border: 0,
613
+ verticalAlign: 'top',
614
+ // Fix alignment issue on Safari.
615
+ variants: [{
616
+ props: {
617
+ margin: 'normal'
618
+ },
619
+ style: {
620
+ marginTop: 16,
621
+ marginBottom: 8
622
+ }
623
+ }, {
624
+ props: {
625
+ margin: 'dense'
626
+ },
627
+ style: {
628
+ marginTop: 8,
629
+ marginBottom: 4
630
+ }
631
+ }, {
632
+ props: {
633
+ fullWidth: true
634
+ },
635
+ style: {
636
+ width: '100%'
637
+ }
638
+ }]
639
+ });
640
+
641
+ /**
642
+ * Provides context such as filled/focused/error/required for form inputs.
643
+ * Relying on the context provides high flexibility and ensures that the state always stays
644
+ * consistent across the children of the `FormControl`.
645
+ * This context is used by the following components:
646
+ *
647
+ * - FormLabel
648
+ * - FormHelperText
649
+ * - Input
650
+ * - InputLabel
651
+ *
652
+ * You can find one composition example below and more going to [the demos](/material-ui/react-text-field/#components).
653
+ *
654
+ * ```jsx
655
+ * <FormControl>
656
+ * <InputLabel htmlFor="my-input">Email address</InputLabel>
657
+ * <Input id="my-input" aria-describedby="my-helper-text" />
658
+ * <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
659
+ * </FormControl>
660
+ * ```
661
+ *
662
+ * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies.
663
+ * For instance, only one input can be focused at the same time, the state shouldn't be shared.
664
+ */
665
+ const FormControl = /*#__PURE__*/React.forwardRef(function FormControl(inProps, ref) {
666
+ const props = useDefaultProps({
667
+ props: inProps,
668
+ name: 'MuiFormControl'
669
+ });
670
+ const {
671
+ children,
672
+ className,
673
+ color = 'primary',
674
+ component = 'div',
675
+ disabled = false,
676
+ error = false,
677
+ focused: visuallyFocused,
678
+ fullWidth = false,
679
+ hiddenLabel = false,
680
+ margin = 'none',
681
+ required = false,
682
+ size = 'medium',
683
+ variant = 'outlined',
684
+ ...other
685
+ } = props;
686
+ const ownerState = {
687
+ ...props,
688
+ color,
689
+ component,
690
+ disabled,
691
+ error,
692
+ fullWidth,
693
+ hiddenLabel,
694
+ margin,
695
+ required,
696
+ size,
697
+ variant
698
+ };
699
+ const classes = useUtilityClasses$2(ownerState);
700
+ const [adornedStart, setAdornedStart] = React.useState(() => {
701
+ // We need to iterate through the children and find the Input in order
702
+ // to fully support server-side rendering.
703
+ let initialAdornedStart = false;
704
+ if (children) {
705
+ React.Children.forEach(children, child => {
706
+ if (!isMuiElement(child, ['Input', 'Select'])) {
707
+ return;
708
+ }
709
+ const input = isMuiElement(child, ['Select']) ? child.props.input : child;
710
+ if (input && isAdornedStart(input.props)) {
711
+ initialAdornedStart = true;
712
+ }
713
+ });
714
+ }
715
+ return initialAdornedStart;
716
+ });
717
+ const [filled, setFilled] = React.useState(() => {
718
+ // We need to iterate through the children and find the Input in order
719
+ // to fully support server-side rendering.
720
+ let initialFilled = false;
721
+ if (children) {
722
+ React.Children.forEach(children, child => {
723
+ if (!isMuiElement(child, ['Input', 'Select'])) {
724
+ return;
725
+ }
726
+ if (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) {
727
+ initialFilled = true;
728
+ }
729
+ });
730
+ }
731
+ return initialFilled;
732
+ });
733
+ const [focusedState, setFocused] = React.useState(false);
734
+ if (disabled && focusedState) {
735
+ setFocused(false);
736
+ }
737
+ const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState;
738
+ let registerEffect;
739
+ const registeredInput = React.useRef(false);
740
+ if (process.env.NODE_ENV !== 'production') {
741
+ registerEffect = () => {
742
+ if (registeredInput.current) {
743
+ console.error(['MUI: There are multiple `InputBase` components inside a FormControl.', 'This creates visual inconsistencies, only use one `InputBase`.'].join('\n'));
744
+ }
745
+ registeredInput.current = true;
746
+ return () => {
747
+ registeredInput.current = false;
748
+ };
749
+ };
750
+ }
751
+ const onFilled = React.useCallback(() => {
752
+ setFilled(true);
753
+ }, []);
754
+ const onEmpty = React.useCallback(() => {
755
+ setFilled(false);
756
+ }, []);
757
+ const childContext = React.useMemo(() => {
758
+ return {
759
+ adornedStart,
760
+ setAdornedStart,
761
+ color,
762
+ disabled,
763
+ error,
764
+ filled,
765
+ focused,
766
+ fullWidth,
767
+ hiddenLabel,
768
+ size,
769
+ onBlur: () => {
770
+ setFocused(false);
771
+ },
772
+ onFocus: () => {
773
+ setFocused(true);
774
+ },
775
+ onEmpty,
776
+ onFilled,
777
+ registerEffect,
778
+ required,
779
+ variant
780
+ };
781
+ }, [adornedStart, color, disabled, error, filled, focused, fullWidth, hiddenLabel, registerEffect, onEmpty, onFilled, required, size, variant]);
782
+ return /*#__PURE__*/jsxRuntimeExports.jsx(FormControlContext.Provider, {
783
+ value: childContext,
784
+ children: /*#__PURE__*/jsxRuntimeExports.jsx(FormControlRoot, {
785
+ as: component,
786
+ ownerState: ownerState,
787
+ className: clsx(classes.root, className),
788
+ ref: ref,
789
+ ...other,
790
+ children: children
791
+ })
792
+ });
793
+ });
794
+ process.env.NODE_ENV !== "production" ? FormControl.propTypes /* remove-proptypes */ = {
795
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
796
+ // │ These PropTypes are generated from the TypeScript type definitions. │
797
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
798
+ // └─────────────────────────────────────────────────────────────────────┘
799
+ /**
800
+ * The content of the component.
801
+ */
802
+ children: PropTypes.node,
803
+ /**
804
+ * Override or extend the styles applied to the component.
805
+ */
806
+ classes: PropTypes.object,
807
+ /**
808
+ * @ignore
809
+ */
810
+ className: PropTypes.string,
811
+ /**
812
+ * The color of the component.
813
+ * It supports both default and custom theme colors, which can be added as shown in the
814
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
815
+ * @default 'primary'
816
+ */
817
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
818
+ /**
819
+ * The component used for the root node.
820
+ * Either a string to use a HTML element or a component.
821
+ */
822
+ component: PropTypes.elementType,
823
+ /**
824
+ * If `true`, the label, input and helper text should be displayed in a disabled state.
825
+ * @default false
826
+ */
827
+ disabled: PropTypes.bool,
828
+ /**
829
+ * If `true`, the label is displayed in an error state.
830
+ * @default false
831
+ */
832
+ error: PropTypes.bool,
833
+ /**
834
+ * If `true`, the component is displayed in focused state.
835
+ */
836
+ focused: PropTypes.bool,
837
+ /**
838
+ * If `true`, the component will take up the full width of its container.
839
+ * @default false
840
+ */
841
+ fullWidth: PropTypes.bool,
842
+ /**
843
+ * If `true`, the label is hidden.
844
+ * This is used to increase density for a `FilledInput`.
845
+ * Be sure to add `aria-label` to the `input` element.
846
+ * @default false
847
+ */
848
+ hiddenLabel: PropTypes.bool,
849
+ /**
850
+ * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
851
+ * @default 'none'
852
+ */
853
+ margin: PropTypes.oneOf(['dense', 'none', 'normal']),
854
+ /**
855
+ * If `true`, the label will indicate that the `input` is required.
856
+ * @default false
857
+ */
858
+ required: PropTypes.bool,
859
+ /**
860
+ * The size of the component.
861
+ * @default 'medium'
862
+ */
863
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
864
+ /**
865
+ * The system prop that allows defining system overrides as well as additional CSS styles.
866
+ */
867
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
868
+ /**
869
+ * The variant to use.
870
+ * @default 'outlined'
871
+ */
872
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
873
+ } : void 0;
874
+ var FormControl$1 = FormControl;
875
+
876
+ function getFormHelperTextUtilityClasses(slot) {
877
+ return generateUtilityClass('MuiFormHelperText', slot);
878
+ }
879
+ const formHelperTextClasses = generateUtilityClasses('MuiFormHelperText', ['root', 'error', 'disabled', 'sizeSmall', 'sizeMedium', 'contained', 'focused', 'filled', 'required']);
880
+ var formHelperTextClasses$1 = formHelperTextClasses;
881
+
882
+ var _span;
883
+ const useUtilityClasses$1 = ownerState => {
884
+ const {
885
+ classes,
886
+ contained,
887
+ size,
888
+ disabled,
889
+ error,
890
+ filled,
891
+ focused,
892
+ required
893
+ } = ownerState;
894
+ const slots = {
895
+ root: ['root', disabled && 'disabled', error && 'error', size && `size${capitalize(size)}`, contained && 'contained', focused && 'focused', filled && 'filled', required && 'required']
896
+ };
897
+ return composeClasses(slots, getFormHelperTextUtilityClasses, classes);
898
+ };
899
+ const FormHelperTextRoot = styled$1('p', {
900
+ name: 'MuiFormHelperText',
901
+ slot: 'Root',
902
+ overridesResolver: (props, styles) => {
903
+ const {
904
+ ownerState
905
+ } = props;
906
+ return [styles.root, ownerState.size && styles[`size${capitalize(ownerState.size)}`], ownerState.contained && styles.contained, ownerState.filled && styles.filled];
907
+ }
908
+ })(memoTheme(({
909
+ theme
910
+ }) => ({
911
+ color: (theme.vars || theme).palette.text.secondary,
912
+ ...theme.typography.caption,
913
+ textAlign: 'left',
914
+ marginTop: 3,
915
+ marginRight: 0,
916
+ marginBottom: 0,
917
+ marginLeft: 0,
918
+ [`&.${formHelperTextClasses$1.disabled}`]: {
919
+ color: (theme.vars || theme).palette.text.disabled
920
+ },
921
+ [`&.${formHelperTextClasses$1.error}`]: {
922
+ color: (theme.vars || theme).palette.error.main
923
+ },
924
+ variants: [{
925
+ props: {
926
+ size: 'small'
927
+ },
928
+ style: {
929
+ marginTop: 4
930
+ }
931
+ }, {
932
+ props: ({
933
+ ownerState
934
+ }) => ownerState.contained,
935
+ style: {
936
+ marginLeft: 14,
937
+ marginRight: 14
938
+ }
939
+ }]
940
+ })));
941
+ const FormHelperText = /*#__PURE__*/React.forwardRef(function FormHelperText(inProps, ref) {
942
+ const props = useDefaultProps({
943
+ props: inProps,
944
+ name: 'MuiFormHelperText'
945
+ });
946
+ const {
947
+ children,
948
+ className,
949
+ component = 'p',
950
+ disabled,
951
+ error,
952
+ filled,
953
+ focused,
954
+ margin,
955
+ required,
956
+ variant,
957
+ ...other
958
+ } = props;
959
+ const muiFormControl = useFormControl();
960
+ const fcs = formControlState({
961
+ props,
962
+ muiFormControl,
963
+ states: ['variant', 'size', 'disabled', 'error', 'filled', 'focused', 'required']
964
+ });
965
+ const ownerState = {
966
+ ...props,
967
+ component,
968
+ contained: fcs.variant === 'filled' || fcs.variant === 'outlined',
969
+ variant: fcs.variant,
970
+ size: fcs.size,
971
+ disabled: fcs.disabled,
972
+ error: fcs.error,
973
+ filled: fcs.filled,
974
+ focused: fcs.focused,
975
+ required: fcs.required
976
+ };
977
+
978
+ // This issue explains why this is required: https://github.com/mui/material-ui/issues/42184
979
+ delete ownerState.ownerState;
980
+ const classes = useUtilityClasses$1(ownerState);
981
+ return /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextRoot, {
982
+ as: component,
983
+ className: clsx(classes.root, className),
984
+ ref: ref,
985
+ ...other,
986
+ ownerState: ownerState,
987
+ children: children === ' ' ? // notranslate needed while Google Translate will not fix zero-width space issue
988
+ _span || (_span = /*#__PURE__*/jsxRuntimeExports.jsx("span", {
989
+ className: "notranslate",
990
+ "aria-hidden": true,
991
+ children: "\u200B"
992
+ })) : children
993
+ });
994
+ });
995
+ process.env.NODE_ENV !== "production" ? FormHelperText.propTypes /* remove-proptypes */ = {
996
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
997
+ // │ These PropTypes are generated from the TypeScript type definitions. │
998
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
999
+ // └─────────────────────────────────────────────────────────────────────┘
1000
+ /**
1001
+ * The content of the component.
1002
+ *
1003
+ * If `' '` is provided, the component reserves one line height for displaying a future message.
1004
+ */
1005
+ children: PropTypes.node,
1006
+ /**
1007
+ * Override or extend the styles applied to the component.
1008
+ */
1009
+ classes: PropTypes.object,
1010
+ /**
1011
+ * @ignore
1012
+ */
1013
+ className: PropTypes.string,
1014
+ /**
1015
+ * The component used for the root node.
1016
+ * Either a string to use a HTML element or a component.
1017
+ */
1018
+ component: PropTypes.elementType,
1019
+ /**
1020
+ * If `true`, the helper text should be displayed in a disabled state.
1021
+ */
1022
+ disabled: PropTypes.bool,
1023
+ /**
1024
+ * If `true`, helper text should be displayed in an error state.
1025
+ */
1026
+ error: PropTypes.bool,
1027
+ /**
1028
+ * If `true`, the helper text should use filled classes key.
1029
+ */
1030
+ filled: PropTypes.bool,
1031
+ /**
1032
+ * If `true`, the helper text should use focused classes key.
1033
+ */
1034
+ focused: PropTypes.bool,
1035
+ /**
1036
+ * If `dense`, will adjust vertical spacing. This is normally obtained via context from
1037
+ * FormControl.
1038
+ */
1039
+ margin: PropTypes.oneOf(['dense']),
1040
+ /**
1041
+ * If `true`, the helper text should use required classes key.
1042
+ */
1043
+ required: PropTypes.bool,
1044
+ /**
1045
+ * The system prop that allows defining system overrides as well as additional CSS styles.
1046
+ */
1047
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1048
+ /**
1049
+ * The variant to use.
1050
+ */
1051
+ variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['filled', 'outlined', 'standard']), PropTypes.string])
1052
+ } : void 0;
1053
+ var FormHelperText$1 = FormHelperText;
1054
+
1055
+ function getTextFieldUtilityClass(slot) {
1056
+ return generateUtilityClass('MuiTextField', slot);
1057
+ }
1058
+ generateUtilityClasses('MuiTextField', ['root']);
1059
+
1060
+ const variantComponent = {
1061
+ standard: Input,
1062
+ filled: FilledInput,
1063
+ outlined: OutlinedInput
1064
+ };
1065
+ const useUtilityClasses = ownerState => {
1066
+ const {
1067
+ classes
1068
+ } = ownerState;
1069
+ const slots = {
1070
+ root: ['root']
1071
+ };
1072
+ return composeClasses(slots, getTextFieldUtilityClass, classes);
1073
+ };
1074
+ const TextFieldRoot = styled$1(FormControl$1, {
1075
+ name: 'MuiTextField',
1076
+ slot: 'Root',
1077
+ overridesResolver: (props, styles) => styles.root
1078
+ })({});
1079
+
1080
+ /**
1081
+ * The `TextField` is a convenience wrapper for the most common cases (80%).
1082
+ * It cannot be all things to all people, otherwise the API would grow out of control.
1083
+ *
1084
+ * ## Advanced Configuration
1085
+ *
1086
+ * It's important to understand that the text field is a simple abstraction
1087
+ * on top of the following components:
1088
+ *
1089
+ * - [FormControl](/material-ui/api/form-control/)
1090
+ * - [InputLabel](/material-ui/api/input-label/)
1091
+ * - [FilledInput](/material-ui/api/filled-input/)
1092
+ * - [OutlinedInput](/material-ui/api/outlined-input/)
1093
+ * - [Input](/material-ui/api/input/)
1094
+ * - [FormHelperText](/material-ui/api/form-helper-text/)
1095
+ *
1096
+ * If you wish to alter the props applied to the `input` element, you can do so as follows:
1097
+ *
1098
+ * ```jsx
1099
+ * const inputProps = {
1100
+ * step: 300,
1101
+ * };
1102
+ *
1103
+ * return <TextField id="time" type="time" inputProps={inputProps} />;
1104
+ * ```
1105
+ *
1106
+ * For advanced cases, please look at the source of TextField by clicking on the
1107
+ * "Edit this page" button above. Consider either:
1108
+ *
1109
+ * - using the upper case props for passing values directly to the components
1110
+ * - using the underlying components directly as shown in the demos
1111
+ */
1112
+ const TextField = /*#__PURE__*/React.forwardRef(function TextField(inProps, ref) {
1113
+ const props = useDefaultProps({
1114
+ props: inProps,
1115
+ name: 'MuiTextField'
1116
+ });
1117
+ const {
1118
+ autoComplete,
1119
+ autoFocus = false,
1120
+ children,
1121
+ className,
1122
+ color = 'primary',
1123
+ defaultValue,
1124
+ disabled = false,
1125
+ error = false,
1126
+ FormHelperTextProps: FormHelperTextPropsProp,
1127
+ fullWidth = false,
1128
+ helperText,
1129
+ id: idOverride,
1130
+ InputLabelProps: InputLabelPropsProp,
1131
+ inputProps: inputPropsProp,
1132
+ InputProps: InputPropsProp,
1133
+ inputRef,
1134
+ label,
1135
+ maxRows,
1136
+ minRows,
1137
+ multiline = false,
1138
+ name,
1139
+ onBlur,
1140
+ onChange,
1141
+ onFocus,
1142
+ placeholder,
1143
+ required = false,
1144
+ rows,
1145
+ select = false,
1146
+ SelectProps: SelectPropsProp,
1147
+ slots = {},
1148
+ slotProps = {},
1149
+ type,
1150
+ value,
1151
+ variant = 'outlined',
1152
+ ...other
1153
+ } = props;
1154
+ const ownerState = {
1155
+ ...props,
1156
+ autoFocus,
1157
+ color,
1158
+ disabled,
1159
+ error,
1160
+ fullWidth,
1161
+ multiline,
1162
+ required,
1163
+ select,
1164
+ variant
1165
+ };
1166
+ const classes = useUtilityClasses(ownerState);
1167
+ if (process.env.NODE_ENV !== 'production') {
1168
+ if (select && !children) {
1169
+ console.error('MUI: `children` must be passed when using the `TextField` component with `select`.');
1170
+ }
1171
+ }
1172
+ const id = useId(idOverride);
1173
+ const helperTextId = helperText && id ? `${id}-helper-text` : undefined;
1174
+ const inputLabelId = label && id ? `${id}-label` : undefined;
1175
+ const InputComponent = variantComponent[variant];
1176
+ const externalForwardedProps = {
1177
+ slots,
1178
+ slotProps: {
1179
+ input: InputPropsProp,
1180
+ inputLabel: InputLabelPropsProp,
1181
+ htmlInput: inputPropsProp,
1182
+ formHelperText: FormHelperTextPropsProp,
1183
+ select: SelectPropsProp,
1184
+ ...slotProps
1185
+ }
1186
+ };
1187
+ const inputAdditionalProps = {};
1188
+ const inputLabelSlotProps = externalForwardedProps.slotProps.inputLabel;
1189
+ if (variant === 'outlined') {
1190
+ if (inputLabelSlotProps && typeof inputLabelSlotProps.shrink !== 'undefined') {
1191
+ inputAdditionalProps.notched = inputLabelSlotProps.shrink;
1192
+ }
1193
+ inputAdditionalProps.label = label;
1194
+ }
1195
+ if (select) {
1196
+ // unset defaults from textbox inputs
1197
+ if (!SelectPropsProp || !SelectPropsProp.native) {
1198
+ inputAdditionalProps.id = undefined;
1199
+ }
1200
+ inputAdditionalProps['aria-describedby'] = undefined;
1201
+ }
1202
+ const [RootSlot, rootProps] = useSlot('root', {
1203
+ elementType: TextFieldRoot,
1204
+ shouldForwardComponentProp: true,
1205
+ externalForwardedProps: {
1206
+ ...externalForwardedProps,
1207
+ ...other
1208
+ },
1209
+ ownerState,
1210
+ className: clsx(classes.root, className),
1211
+ ref,
1212
+ additionalProps: {
1213
+ disabled,
1214
+ error,
1215
+ fullWidth,
1216
+ required,
1217
+ color,
1218
+ variant
1219
+ }
1220
+ });
1221
+ const [InputSlot, inputProps] = useSlot('input', {
1222
+ elementType: InputComponent,
1223
+ externalForwardedProps,
1224
+ additionalProps: inputAdditionalProps,
1225
+ ownerState
1226
+ });
1227
+ const [InputLabelSlot, inputLabelProps] = useSlot('inputLabel', {
1228
+ elementType: InputLabel$1,
1229
+ externalForwardedProps,
1230
+ ownerState
1231
+ });
1232
+ const [HtmlInputSlot, htmlInputProps] = useSlot('htmlInput', {
1233
+ elementType: 'input',
1234
+ externalForwardedProps,
1235
+ ownerState
1236
+ });
1237
+ const [FormHelperTextSlot, formHelperTextProps] = useSlot('formHelperText', {
1238
+ elementType: FormHelperText$1,
1239
+ externalForwardedProps,
1240
+ ownerState
1241
+ });
1242
+ const [SelectSlot, selectProps] = useSlot('select', {
1243
+ elementType: Select,
1244
+ externalForwardedProps,
1245
+ ownerState
1246
+ });
1247
+ const InputElement = /*#__PURE__*/jsxRuntimeExports.jsx(InputSlot, {
1248
+ "aria-describedby": helperTextId,
1249
+ autoComplete: autoComplete,
1250
+ autoFocus: autoFocus,
1251
+ defaultValue: defaultValue,
1252
+ fullWidth: fullWidth,
1253
+ multiline: multiline,
1254
+ name: name,
1255
+ rows: rows,
1256
+ maxRows: maxRows,
1257
+ minRows: minRows,
1258
+ type: type,
1259
+ value: value,
1260
+ id: id,
1261
+ inputRef: inputRef,
1262
+ onBlur: onBlur,
1263
+ onChange: onChange,
1264
+ onFocus: onFocus,
1265
+ placeholder: placeholder,
1266
+ inputProps: htmlInputProps,
1267
+ slots: {
1268
+ input: slots.htmlInput ? HtmlInputSlot : undefined
1269
+ },
1270
+ ...inputProps
1271
+ });
1272
+ return /*#__PURE__*/jsxRuntimeExports.jsxs(RootSlot, {
1273
+ ...rootProps,
1274
+ children: [label != null && label !== '' && /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelSlot, {
1275
+ htmlFor: id,
1276
+ id: inputLabelId,
1277
+ ...inputLabelProps,
1278
+ children: label
1279
+ }), select ? /*#__PURE__*/jsxRuntimeExports.jsx(SelectSlot, {
1280
+ "aria-describedby": helperTextId,
1281
+ id: id,
1282
+ labelId: inputLabelId,
1283
+ value: value,
1284
+ input: InputElement,
1285
+ ...selectProps,
1286
+ children: children
1287
+ }) : InputElement, helperText && /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextSlot, {
1288
+ id: helperTextId,
1289
+ ...formHelperTextProps,
1290
+ children: helperText
1291
+ })]
1292
+ });
1293
+ });
1294
+ process.env.NODE_ENV !== "production" ? TextField.propTypes /* remove-proptypes */ = {
1295
+ // ┌────────────────────────────── Warning ──────────────────────────────┐
1296
+ // │ These PropTypes are generated from the TypeScript type definitions. │
1297
+ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
1298
+ // └─────────────────────────────────────────────────────────────────────┘
1299
+ /**
1300
+ * This prop helps users to fill forms faster, especially on mobile devices.
1301
+ * The name can be confusing, as it's more like an autofill.
1302
+ * You can learn more about it [following the specification](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill).
1303
+ */
1304
+ autoComplete: PropTypes.string,
1305
+ /**
1306
+ * If `true`, the `input` element is focused during the first mount.
1307
+ * @default false
1308
+ */
1309
+ autoFocus: PropTypes.bool,
1310
+ /**
1311
+ * @ignore
1312
+ */
1313
+ children: PropTypes.node,
1314
+ /**
1315
+ * Override or extend the styles applied to the component.
1316
+ */
1317
+ classes: PropTypes.object,
1318
+ /**
1319
+ * @ignore
1320
+ */
1321
+ className: PropTypes.string,
1322
+ /**
1323
+ * The color of the component.
1324
+ * It supports both default and custom theme colors, which can be added as shown in the
1325
+ * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
1326
+ * @default 'primary'
1327
+ */
1328
+ color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
1329
+ /**
1330
+ * The default value. Use when the component is not controlled.
1331
+ */
1332
+ defaultValue: PropTypes.any,
1333
+ /**
1334
+ * If `true`, the component is disabled.
1335
+ * @default false
1336
+ */
1337
+ disabled: PropTypes.bool,
1338
+ /**
1339
+ * If `true`, the label is displayed in an error state.
1340
+ * @default false
1341
+ */
1342
+ error: PropTypes.bool,
1343
+ /**
1344
+ * Props applied to the [`FormHelperText`](https://mui.com/material-ui/api/form-helper-text/) element.
1345
+ * @deprecated Use `slotProps.formHelperText` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
1346
+ */
1347
+ FormHelperTextProps: PropTypes.object,
1348
+ /**
1349
+ * If `true`, the input will take up the full width of its container.
1350
+ * @default false
1351
+ */
1352
+ fullWidth: PropTypes.bool,
1353
+ /**
1354
+ * The helper text content.
1355
+ */
1356
+ helperText: PropTypes.node,
1357
+ /**
1358
+ * The id of the `input` element.
1359
+ * Use this prop to make `label` and `helperText` accessible for screen readers.
1360
+ */
1361
+ id: PropTypes.string,
1362
+ /**
1363
+ * Props applied to the [`InputLabel`](https://mui.com/material-ui/api/input-label/) element.
1364
+ * Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
1365
+ * @deprecated Use `slotProps.inputLabel` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
1366
+ */
1367
+ InputLabelProps: PropTypes.object,
1368
+ /**
1369
+ * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
1370
+ * @deprecated Use `slotProps.htmlInput` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
1371
+ */
1372
+ inputProps: PropTypes.object,
1373
+ /**
1374
+ * Props applied to the Input element.
1375
+ * It will be a [`FilledInput`](https://mui.com/material-ui/api/filled-input/),
1376
+ * [`OutlinedInput`](https://mui.com/material-ui/api/outlined-input/) or [`Input`](https://mui.com/material-ui/api/input/)
1377
+ * component depending on the `variant` prop value.
1378
+ * @deprecated Use `slotProps.input` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
1379
+ */
1380
+ InputProps: PropTypes.object,
1381
+ /**
1382
+ * Pass a ref to the `input` element.
1383
+ */
1384
+ inputRef: refType,
1385
+ /**
1386
+ * The label content.
1387
+ */
1388
+ label: PropTypes.node,
1389
+ /**
1390
+ * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
1391
+ * @default 'none'
1392
+ */
1393
+ margin: PropTypes.oneOf(['dense', 'none', 'normal']),
1394
+ /**
1395
+ * Maximum number of rows to display when multiline option is set to true.
1396
+ */
1397
+ maxRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1398
+ /**
1399
+ * Minimum number of rows to display when multiline option is set to true.
1400
+ */
1401
+ minRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1402
+ /**
1403
+ * If `true`, a `textarea` element is rendered instead of an input.
1404
+ * @default false
1405
+ */
1406
+ multiline: PropTypes.bool,
1407
+ /**
1408
+ * Name attribute of the `input` element.
1409
+ */
1410
+ name: PropTypes.string,
1411
+ /**
1412
+ * @ignore
1413
+ */
1414
+ onBlur: PropTypes.func,
1415
+ /**
1416
+ * Callback fired when the value is changed.
1417
+ *
1418
+ * @param {object} event The event source of the callback.
1419
+ * You can pull out the new value by accessing `event.target.value` (string).
1420
+ */
1421
+ onChange: PropTypes.func,
1422
+ /**
1423
+ * @ignore
1424
+ */
1425
+ onFocus: PropTypes.func,
1426
+ /**
1427
+ * The short hint displayed in the `input` before the user enters a value.
1428
+ */
1429
+ placeholder: PropTypes.string,
1430
+ /**
1431
+ * If `true`, the label is displayed as required and the `input` element is required.
1432
+ * @default false
1433
+ */
1434
+ required: PropTypes.bool,
1435
+ /**
1436
+ * Number of rows to display when multiline option is set to true.
1437
+ */
1438
+ rows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1439
+ /**
1440
+ * Render a [`Select`](https://mui.com/material-ui/api/select/) element while passing the Input element to `Select` as `input` parameter.
1441
+ * If this option is set you must pass the options of the select as children.
1442
+ * @default false
1443
+ */
1444
+ select: PropTypes.bool,
1445
+ /**
1446
+ * Props applied to the [`Select`](https://mui.com/material-ui/api/select/) element.
1447
+ * @deprecated Use `slotProps.select` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
1448
+ */
1449
+ SelectProps: PropTypes.object,
1450
+ /**
1451
+ * The size of the component.
1452
+ * @default 'medium'
1453
+ */
1454
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
1455
+ /**
1456
+ * The props used for each slot inside.
1457
+ * @default {}
1458
+ */
1459
+ slotProps: PropTypes /* @typescript-to-proptypes-ignore */.shape({
1460
+ formHelperText: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1461
+ htmlInput: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1462
+ input: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1463
+ inputLabel: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1464
+ select: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
1465
+ }),
1466
+ /**
1467
+ * The components used for each slot inside.
1468
+ * @default {}
1469
+ */
1470
+ slots: PropTypes.shape({
1471
+ formHelperText: PropTypes.elementType,
1472
+ htmlInput: PropTypes.elementType,
1473
+ input: PropTypes.elementType,
1474
+ inputLabel: PropTypes.elementType,
1475
+ root: PropTypes.elementType,
1476
+ select: PropTypes.elementType
1477
+ }),
1478
+ /**
1479
+ * The system prop that allows defining system overrides as well as additional CSS styles.
1480
+ */
1481
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1482
+ /**
1483
+ * 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).
1484
+ */
1485
+ type: PropTypes /* @typescript-to-proptypes-ignore */.string,
1486
+ /**
1487
+ * The value of the `input` element, required for a controlled component.
1488
+ */
1489
+ value: PropTypes.any,
1490
+ /**
1491
+ * The variant to use.
1492
+ * @default 'outlined'
1493
+ */
1494
+ variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
1495
+ } : void 0;
1496
+ var TextField$1 = TextField;
1497
+
17
1498
  const SUBMIT_FILTER_STROKE_TIME = 500;
18
1499
  const InputNumberInterval = props => {
19
1500
  var _item$value;
@@ -54,7 +1535,7 @@ const InputNumberInterval = props => {
54
1535
  const newLowerBound = event.target.value;
55
1536
  updateFilterValue(newLowerBound, filterValueState[1]);
56
1537
  };
57
- return /*#__PURE__*/React.createElement(Box, {
1538
+ return /*#__PURE__*/React.createElement(Box$1, {
58
1539
  sx: {
59
1540
  display: 'inline-flex',
60
1541
  flexDirection: 'row',
@@ -62,7 +1543,7 @@ const InputNumberInterval = props => {
62
1543
  height: 48,
63
1544
  pl: '20px'
64
1545
  }
65
- }, /*#__PURE__*/React.createElement(TextField, {
1546
+ }, /*#__PURE__*/React.createElement(TextField$1, {
66
1547
  name: "lower-bound-input",
67
1548
  placeholder: "From",
68
1549
  label: "From",
@@ -74,7 +1555,7 @@ const InputNumberInterval = props => {
74
1555
  sx: {
75
1556
  mr: 2
76
1557
  }
77
- }), /*#__PURE__*/React.createElement(TextField, {
1558
+ }), /*#__PURE__*/React.createElement(TextField$1, {
78
1559
  name: "upper-bound-input",
79
1560
  placeholder: "To",
80
1561
  label: "To",
@@ -703,20 +2184,14 @@ const DIMENSION_MODEL_KEY = 'dimension';
703
2184
  const FILTER_SEARCH_KEY = 'searchModel';
704
2185
  const DENSITY_MODEL_KEY = 'densityModel';
705
2186
  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];
2187
+ 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
2188
  /**
714
2189
  * Build the localStorage key for a specific grid state category.
715
2190
  * Consumers can use this to read or clear individual state entries directly.
716
2191
  *
717
2192
  * @example
718
2193
  * ```ts
719
- * const key = buildStorageKey({ id: pathname, version: 2, category: PIVOT_ACTIVE_KEY });
2194
+ * const key = buildStorageKey({ id: pathname, version: 2, category: SORT_MODEL_KEY });
720
2195
  * localStorage.removeItem(key);
721
2196
  * ```
722
2197
  */
@@ -766,22 +2241,6 @@ const clearPreviousVersionStorage = (id, previousLocalStorageVersions) => {
766
2241
  id,
767
2242
  version,
768
2243
  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
2244
  })];
786
2245
  for (const keyToDelete of keysToDelete) {
787
2246
  try {
@@ -856,14 +2315,13 @@ const resetStatefulDataGridState = _ref2 => {
856
2315
  * default (all columns visible). Clears the persisted `visibilityModel`
857
2316
  * localStorage entry for the given versions and strips the `_columnVisibility`
858
2317
  * param from the live URL, leaving every other piece of grid state (filters,
859
- * sort, pivot, pagination, pinned columns, …) untouched.
2318
+ * sort, pagination, pinned columns, …) untouched.
860
2319
  *
861
2320
  * 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.
2321
+ * Reach for it at transition points where a stale visibility snapshot would
2322
+ * otherwise re-seed and keep base columns hidden. Because it leaves the other
2323
+ * params alone it will not clobber a filter the caller is writing in the same
2324
+ * transition.
867
2325
  *
868
2326
  * Like `resetStatefulDataGridState`, the URL strip reads `window.location.search`
869
2327
  * directly so it operates on the live URL (the caller's captured snapshot may
@@ -913,7 +2371,7 @@ const COMPRESSED_PREFIX = '~';
913
2371
  * Params listed first are compressed first (least valuable to read in the URL).
914
2372
  * The filter aggregate step uses the special key `_filters_aggregate`.
915
2373
  */
916
- const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_aggregation', '_rowGrouping', '_quickFilterValues', '_pivot'];
2374
+ const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_quickFilterValues'];
917
2375
 
918
2376
  /** Params that are always short and should never be compressed. */
919
2377
  const NEVER_COMPRESS = new Set(['_sortColumn', '_pagination', '_density', '_logicOperator', 'v', 'tab']);
@@ -991,7 +2449,7 @@ const tryAggregateFilters = (params, filterKeys) => {
991
2449
  * Filter params are those that start with `_` but are not well-known system params.
992
2450
  */
993
2451
  const getFilterParamKeys = params => {
994
- const systemPrefixes = ['_sortColumn', '_pagination', '_density', '_logicOperator', '_quickFilterValues', '_columnVisibility', '_columnOrder', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_rowGrouping', '_aggregation', '_pivot', '_filters'];
2452
+ const systemPrefixes = ['_sortColumn', '_pagination', '_density', '_logicOperator', '_quickFilterValues', '_columnVisibility', '_columnOrder', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters'];
995
2453
  const filterKeys = [];
996
2454
  for (const key of params.keys()) {
997
2455
  if (!key.startsWith('_')) continue;
@@ -1222,21 +2680,6 @@ const convertToDisplayFormat = search => {
1222
2680
  return param;
1223
2681
  }
1224
2682
 
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
2683
  // Handle _field[operator,type]=value or _field[operator,type]=list[a,b,c]
1241
2684
  const bracketMatch = param.match(/^_([^[]+)\[([^\]]+)\]=(.*)$/);
1242
2685
  if (bracketMatch) {
@@ -1350,17 +2793,8 @@ const convertFromDisplayFormat = (search, columns) => {
1350
2793
  return `_columnOrder=[${value}]`;
1351
2794
  }
1352
2795
 
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=')) {
2796
+ // _filters — pass through (no bracket conversion needed)
2797
+ if (param.startsWith('_filters=')) {
1364
2798
  return param;
1365
2799
  }
1366
2800
 
@@ -1407,9 +2841,8 @@ const getDecodedSearchFromUrl = (search, columns) => {
1407
2841
  const hasPinnedWithoutBrackets = /(_pinnedColumnsLeft|_pinnedColumnsRight)=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1408
2842
  const hasVisibilityWithoutBrackets = /_columnVisibility=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1409
2843
  const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1410
- const hasRowGroupingWithoutBrackets = /_rowGrouping=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1411
2844
  const hasBracketNotation = /\[.*\]=/.test(searchWithoutLeadingQuestion);
1412
- const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets || hasRowGroupingWithoutBrackets) && !hasBracketNotation;
2845
+ const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets) && !hasBracketNotation;
1413
2846
  if (isDisplayFormat) {
1414
2847
  return '?' + convertFromDisplayFormat(searchWithoutLeadingQuestion, columns);
1415
2848
  }
@@ -1534,17 +2967,12 @@ const isValueValid = (value, field, columns, operator) => {
1534
2967
  }
1535
2968
  const type = (_column$type = column['type']) !== null && _column$type !== void 0 ? _column$type : 'string';
1536
2969
 
1537
- // Only date, dateTime and rating need value validation; other types either
1538
- // accept any string or reset themselves to undefined.
1539
- if (type !== 'date' && type !== 'dateTime' && type !== 'rating') {
2970
+ // Only date and dateTime need value validation; other types either accept
2971
+ // any string or reset themselves to undefined.
2972
+ if (type !== 'date' && type !== 'dateTime') {
1540
2973
  return true;
1541
2974
  }
1542
2975
 
1543
- // just checking that rating is a number.
1544
- if (type === 'rating') {
1545
- return !isNaN(Number(value));
1546
- }
1547
-
1548
2976
  // format: YYYY-MM-DD — strict, so corrupt/locale/ISO strings (e.g. a
1549
2977
  // stringified Date, or an ISO value with a `T` suffix) are rejected rather
1550
2978
  // than reaching a server consumer. Canonical values come from
@@ -1578,7 +3006,7 @@ const getFilterModelFromString = (searchString, columns) => {
1578
3006
  let hasFilterMeta = false;
1579
3007
  const searchParams = new URLSearchParams();
1580
3008
  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)) {
3009
+ if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_density', '_filters'].includes(key)) {
1582
3010
  searchParams.set(key, value);
1583
3011
  }
1584
3012
  if (key === '_logicOperator') {
@@ -1673,7 +3101,7 @@ const getFilterModelFromString = (searchString, columns) => {
1673
3101
  * - `dateTime` → `YYYY-MM-DDTHH:mm:ss` (local wall-clock, matching the
1674
3102
  * datetime-local input)
1675
3103
  * Non-date types, empty values, arrays of dates (e.g. `isBetween`) and
1676
- * unparseable values are handled so the existing string / number / list / rating
3104
+ * unparseable values are handled so the existing string / number / list
1677
3105
  * paths are untouched and invalid values still fall through to `isValueValid`.
1678
3106
  */
1679
3107
  const normalizeDateValue = (value, type) => {
@@ -1928,8 +3356,8 @@ const getColumnVisibilityFromString = (searchString, columns) => {
1928
3356
  // by 12.5.5-muiv8-alpha.5/alpha.6 (replaced by the URL-safe `!` form below — see
1929
3357
  // getSearchParamsFromColumnVisibility). Still parsed so any localStorage entry
1930
3358
  // persisted by those alphas keeps working; never written anymore. The two sets are
1931
- // split on the fixed `];h:[` separator, so a `[` or `]` inside a pivot field name
1932
- // (e.g. `["gmail"]>->email_volume`) does not break parsing.
3359
+ // split on the fixed `];h:[` separator, so a `[` or `]` inside a field name does
3360
+ // not break parsing.
1933
3361
  if (value.startsWith('v:[') && value.endsWith(']') && value.includes('];h:[')) {
1934
3362
  const inner = value.slice('v:['.length, -1);
1935
3363
  const separatorIndex = inner.indexOf('];h:[');
@@ -2019,14 +3447,14 @@ const getSearchParamsFromColumnVisibility = (columnVisibility, columns) => {
2019
3447
  }, columnVisibility);
2020
3448
 
2021
3449
  // Serialise a single comma list over the static columns plus any extra keys present
2022
- // in the model (dynamically-generated pivot fields, preserved in model order).
2023
- // Hidden fields are prefixed `!`; visible fields are bare. This URL-safe form
2024
- // round-trips idempotently through `URLSearchParams.toString()` percent-encoding —
2025
- // the earlier `v:[..];h:[..]` form did NOT (its `:`/`;` were percent-encoded and
2026
- // mis-parsed on read-back, driving an unbounded `history.replace` loop, ODM-3033).
2027
- // `!` (not `~`, which is the compression sentinel — compression.ts COMPRESSED_PREFIX)
2028
- // is used so a leading hidden field can't be mistaken for a compressed value.
2029
- // The hidden set is still explicit, so deselected dynamic columns survive reloads.
3450
+ // in the model (dynamically-generated fields, preserved in model order). Hidden
3451
+ // fields are prefixed `!`; visible fields are bare. This URL-safe form round-trips
3452
+ // idempotently through `URLSearchParams.toString()` percent-encoding — the earlier
3453
+ // `v:[..];h:[..]` form did NOT (its `:`/`;` were percent-encoded and mis-parsed on
3454
+ // read-back, driving an unbounded `history.replace` loop, ODM-3033). `!` (not `~`,
3455
+ // the compression sentinel — compression.ts COMPRESSED_PREFIX) is used so a leading
3456
+ // hidden field can't be mistaken for a compressed value. The hidden set is still
3457
+ // explicit, so deselected dynamic columns survive reloads.
2030
3458
  const allFields = [...fields];
2031
3459
  for (const field of Object.keys(finalColumnVisibility)) {
2032
3460
  if (!allFields.includes(field)) {
@@ -2242,6 +3670,29 @@ const getSearchParamsFromColumnOrder = columnOrder => {
2242
3670
  }
2243
3671
  return searchParams;
2244
3672
  };
3673
+
3674
+ /**
3675
+ * Builds the `v=<version>` search param the grid uses to detect stale URLs.
3676
+ *
3677
+ * Use this when constructing a deep link or share URL outside the grid (e.g. via
3678
+ * `getSearchParamsFromFilterModel` + `buildQueryParamsString`). The grid itself
3679
+ * always includes `v` in URLs it writes via `getFinalSearch`, but external helpers
3680
+ * do not — include this when you want a stale `localStorageVersion` bump to invalidate
3681
+ * the link. Omitting `v` is also safe: a missing `v` is treated as "current version"
3682
+ * and the URL state is applied as-is.
3683
+ *
3684
+ * @example
3685
+ * const params = new URLSearchParams([
3686
+ * ...getSearchParamsFromFilterModel(filterModel),
3687
+ * ...getSearchParamsFromVersion(1),
3688
+ * ]);
3689
+ * const url = `/my-grid${buildQueryParamsString(urlSearchParamsToString(params))}`;
3690
+ */
3691
+ const getSearchParamsFromVersion = version => {
3692
+ const searchParams = new URLSearchParams();
3693
+ searchParams.set('v', String(version));
3694
+ return searchParams;
3695
+ };
2245
3696
  const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion) => {
2246
3697
  var _initialState$columns4, _initialState$columns5;
2247
3698
  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);
@@ -2272,298 +3723,7 @@ const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorag
2272
3723
  persistDefault();
2273
3724
  return defaultValue;
2274
3725
  };
2275
-
2276
- /** ROW GROUPING */
2277
-
2278
- const getRowGroupingFromString = searchString => {
2279
- if (!searchString) return 'invalid';
2280
- const searchParams = new URLSearchParams(searchString);
2281
- const value = searchParams.get('_rowGrouping');
2282
- if (value === '' || value === null || value === '[]') return 'invalid';
2283
- const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2284
- if (!inner) return 'invalid';
2285
- return inner.split(',').filter(Boolean);
2286
- };
2287
- const getSearchParamsFromRowGrouping = rowGrouping => {
2288
- const searchParams = new URLSearchParams();
2289
- if (rowGrouping.length > 0) {
2290
- searchParams.set('_rowGrouping', `[${rowGrouping.join(',')}]`);
2291
- }
2292
- return searchParams;
2293
- };
2294
- const getRowGroupingModel = (search, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion) => {
2295
- var _initialState$rowGrou, _initialState$rowGrou2;
2296
- 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 : [];
2297
- const persistDefault = () => {
2298
- const searchFromDefault = getSearchParamsFromRowGrouping(defaultValue);
2299
- const searchString = urlSearchParamsToString(searchFromDefault);
2300
- if (searchString !== localStorageRowGrouping) {
2301
- setLocalStorageRowGrouping(searchString);
2302
- }
2303
- };
2304
- if (isNewVersion) {
2305
- persistDefault();
2306
- return defaultValue;
2307
- }
2308
- const fromUrl = getRowGroupingFromString(search);
2309
- if (fromUrl !== 'invalid') {
2310
- const searchFromModel = getSearchParamsFromRowGrouping(fromUrl);
2311
- const searchString = urlSearchParamsToString(searchFromModel);
2312
- if (searchString !== localStorageRowGrouping) {
2313
- setLocalStorageRowGrouping(searchString);
2314
- }
2315
- return fromUrl;
2316
- }
2317
- const fromLocalStorage = getRowGroupingFromString(localStorageRowGrouping);
2318
- if (fromLocalStorage !== 'invalid') {
2319
- return fromLocalStorage;
2320
- }
2321
- persistDefault();
2322
- return defaultValue;
2323
- };
2324
-
2325
- /** AGGREGATION */
2326
-
2327
- const getAggregationFromString = searchString => {
2328
- if (!searchString) return 'invalid';
2329
- const searchParams = new URLSearchParams(searchString);
2330
- const value = searchParams.get('_aggregation');
2331
- if (value === '' || value === null) return 'invalid';
2332
-
2333
- // Format: field1.sum,field2.avg or [field1.sum,field2.avg]
2334
- const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2335
- if (!inner) return 'invalid';
2336
- const model = {};
2337
- for (const entry of inner.split(',')) {
2338
- const dotIndex = entry.lastIndexOf('.');
2339
- if (dotIndex <= 0) return 'invalid';
2340
- const field = entry.slice(0, dotIndex);
2341
- const aggFunc = entry.slice(dotIndex + 1);
2342
- if (!field || !aggFunc) return 'invalid';
2343
- model[field] = aggFunc;
2344
- }
2345
- return Object.keys(model).length > 0 ? model : 'invalid';
2346
- };
2347
- const getSearchParamsFromAggregation = aggregation => {
2348
- const searchParams = new URLSearchParams();
2349
- const entries = Object.entries(aggregation);
2350
- if (entries.length > 0) {
2351
- const value = entries.map(_ref => {
2352
- let [field, aggFunc] = _ref;
2353
- return `${field}.${aggFunc}`;
2354
- }).join(',');
2355
- searchParams.set('_aggregation', value);
2356
- }
2357
- return searchParams;
2358
- };
2359
- const getAggregationModel = (search, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion) => {
2360
- var _initialState$aggrega, _initialState$aggrega2;
2361
- 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 : {};
2362
- const persistDefault = () => {
2363
- const searchFromDefault = getSearchParamsFromAggregation(defaultValue);
2364
- const searchString = urlSearchParamsToString(searchFromDefault);
2365
- if (searchString !== localStorageAggregation) {
2366
- setLocalStorageAggregation(searchString);
2367
- }
2368
- };
2369
- if (isNewVersion) {
2370
- persistDefault();
2371
- return defaultValue;
2372
- }
2373
- const fromUrl = getAggregationFromString(search);
2374
- if (fromUrl !== 'invalid') {
2375
- const searchFromModel = getSearchParamsFromAggregation(fromUrl);
2376
- const searchString = urlSearchParamsToString(searchFromModel);
2377
- if (searchString !== localStorageAggregation) {
2378
- setLocalStorageAggregation(searchString);
2379
- }
2380
- return fromUrl;
2381
- }
2382
- const fromLocalStorage = getAggregationFromString(localStorageAggregation);
2383
- if (fromLocalStorage !== 'invalid') {
2384
- return fromLocalStorage;
2385
- }
2386
- persistDefault();
2387
- return defaultValue;
2388
- };
2389
-
2390
- /** PIVOT */
2391
-
2392
- /** Convert MUI's GridPivotModel → our simplified PivotModel */
2393
- const fromGridPivotModel = model => ({
2394
- columns: model.columns.map(c => c.field),
2395
- rows: model.rows.map(r => r.field),
2396
- values: model.values.map(_ref2 => {
2397
- let {
2398
- field,
2399
- aggFunc
2400
- } = _ref2;
2401
- return {
2402
- field,
2403
- aggFunc
2404
- };
2405
- })
2406
- });
2407
-
2408
- /**
2409
- * Pivot format: `cols:f1,f2;rows:f3;vals:f4.sum,f5.avg`
2410
- */
2411
- const getPivotFromString = searchString => {
2412
- if (!searchString) return 'invalid';
2413
- const searchParams = new URLSearchParams(searchString);
2414
- const value = searchParams.get('_pivot');
2415
- if (value === '' || value === null) return 'invalid';
2416
- const model = {
2417
- columns: [],
2418
- rows: [],
2419
- values: []
2420
- };
2421
- for (const segment of value.split(';')) {
2422
- const colonIndex = segment.indexOf(':');
2423
- if (colonIndex <= 0) return 'invalid';
2424
- const key = segment.slice(0, colonIndex);
2425
- const content = segment.slice(colonIndex + 1);
2426
- if (key === 'cols') {
2427
- model.columns = content ? content.split(',').filter(Boolean) : [];
2428
- } else if (key === 'rows') {
2429
- model.rows = content ? content.split(',').filter(Boolean) : [];
2430
- } else if (key === 'vals') {
2431
- if (!content) continue;
2432
- for (const entry of content.split(',')) {
2433
- const dotIndex = entry.lastIndexOf('.');
2434
- if (dotIndex <= 0) return 'invalid';
2435
- model.values.push({
2436
- field: entry.slice(0, dotIndex),
2437
- aggFunc: entry.slice(dotIndex + 1)
2438
- });
2439
- }
2440
- }
2441
- }
2442
-
2443
- // At least one section must have content
2444
- if (model.columns.length === 0 && model.rows.length === 0 && model.values.length === 0) {
2445
- return 'invalid';
2446
- }
2447
- return model;
2448
- };
2449
- const getSearchParamsFromPivot = pivot => {
2450
- const searchParams = new URLSearchParams();
2451
- const hasContent = pivot.columns.length > 0 || pivot.rows.length > 0 || pivot.values.length > 0;
2452
- if (hasContent) {
2453
- const parts = [];
2454
- parts.push(`cols:${pivot.columns.join(',')}`);
2455
- parts.push(`rows:${pivot.rows.join(',')}`);
2456
- if (pivot.values.length > 0) {
2457
- parts.push(`vals:${pivot.values.map(v => `${v.field}.${v.aggFunc}`).join(',')}`);
2458
- }
2459
- searchParams.set('_pivot', parts.join(';'));
2460
- }
2461
- return searchParams;
2462
- };
2463
- const getPivotModel = (search, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion) => {
2464
- var _initialState$pivotin;
2465
- const defaultValue = initialState !== null && initialState !== void 0 && (_initialState$pivotin = initialState.pivoting) !== null && _initialState$pivotin !== void 0 && _initialState$pivotin.model ? fromGridPivotModel(initialState.pivoting.model) : {
2466
- columns: [],
2467
- rows: [],
2468
- values: []
2469
- };
2470
- const persistDefault = () => {
2471
- const searchFromDefault = getSearchParamsFromPivot(defaultValue);
2472
- const searchString = urlSearchParamsToString(searchFromDefault);
2473
- if (searchString !== localStoragePivot) {
2474
- setLocalStoragePivot(searchString);
2475
- }
2476
- };
2477
- if (isNewVersion) {
2478
- persistDefault();
2479
- return defaultValue;
2480
- }
2481
- const fromUrl = getPivotFromString(search);
2482
- if (fromUrl !== 'invalid') {
2483
- const searchFromModel = getSearchParamsFromPivot(fromUrl);
2484
- const searchString = urlSearchParamsToString(searchFromModel);
2485
- if (searchString !== localStoragePivot) {
2486
- setLocalStoragePivot(searchString);
2487
- }
2488
- return fromUrl;
2489
- }
2490
- const fromLocalStorage = getPivotFromString(localStoragePivot);
2491
- if (fromLocalStorage !== 'invalid') {
2492
- return fromLocalStorage;
2493
- }
2494
- persistDefault();
2495
- return defaultValue;
2496
- };
2497
-
2498
- /** PIVOT ACTIVE */
2499
-
2500
- const getPivotActiveFromString = searchString => {
2501
- if (!searchString) return 'invalid';
2502
- const searchParams = new URLSearchParams(searchString);
2503
- const value = searchParams.get('_pivotActive');
2504
- if (value === 'true') return true;
2505
- if (value === 'false') return false;
2506
- return 'invalid';
2507
- };
2508
- const getSearchParamsFromPivotActive = active => {
2509
- const searchParams = new URLSearchParams();
2510
- searchParams.set('_pivotActive', String(active));
2511
- return searchParams;
2512
- };
2513
-
2514
- /**
2515
- * Builds the `v=<version>` search param the grid uses to detect stale URLs.
2516
- *
2517
- * Use this when constructing a deep link or share URL outside the grid (e.g. via
2518
- * `getSearchParamsFromFilterModel` + `buildQueryParamsString`). The grid itself
2519
- * always includes `v` in URLs it writes via `getFinalSearch`, but external helpers
2520
- * do not — include this when you want a stale `localStorageVersion` bump to invalidate
2521
- * the link. Omitting `v` is also safe: a missing `v` is treated as "current version"
2522
- * and the URL state is applied as-is.
2523
- *
2524
- * @example
2525
- * const params = new URLSearchParams([
2526
- * ...getSearchParamsFromFilterModel(filterModel),
2527
- * ...getSearchParamsFromVersion(1),
2528
- * ]);
2529
- * const url = `/my-grid${buildQueryParamsString(urlSearchParamsToString(params))}`;
2530
- */
2531
- const getSearchParamsFromVersion = version => {
2532
- const searchParams = new URLSearchParams();
2533
- searchParams.set('v', String(version));
2534
- return searchParams;
2535
- };
2536
- const getPivotActive = (search, localStoragePivotActive, setLocalStoragePivotActive, initialState, isNewVersion) => {
2537
- var _initialState$pivotin2, _initialState$pivotin3;
2538
- 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;
2539
- const persistDefault = () => {
2540
- const searchFromDefault = getSearchParamsFromPivotActive(defaultValue);
2541
- const searchString = urlSearchParamsToString(searchFromDefault);
2542
- if (searchString !== localStoragePivotActive) {
2543
- setLocalStoragePivotActive(searchString);
2544
- }
2545
- };
2546
- if (isNewVersion) {
2547
- persistDefault();
2548
- return defaultValue;
2549
- }
2550
- const fromUrl = getPivotActiveFromString(search);
2551
- if (fromUrl !== 'invalid') {
2552
- const searchFromModel = getSearchParamsFromPivotActive(fromUrl);
2553
- const searchString = urlSearchParamsToString(searchFromModel);
2554
- if (searchString !== localStoragePivotActive) {
2555
- setLocalStoragePivotActive(searchString);
2556
- }
2557
- return fromUrl;
2558
- }
2559
- const fromLocalStorage = getPivotActiveFromString(localStoragePivotActive);
2560
- if (fromLocalStorage !== 'invalid') {
2561
- return fromLocalStorage;
2562
- }
2563
- persistDefault();
2564
- return defaultValue;
2565
- };
2566
- const getFinalSearch = _ref3 => {
3726
+ const getFinalSearch = _ref => {
2567
3727
  let {
2568
3728
  search,
2569
3729
  localStorageVersion,
@@ -2575,12 +3735,8 @@ const getFinalSearch = _ref3 => {
2575
3735
  density,
2576
3736
  columnOrderModel,
2577
3737
  defaultColumnOrder,
2578
- rowGroupingModel,
2579
- aggregationModel,
2580
- pivotModel,
2581
- pivotActive,
2582
3738
  columns
2583
- } = _ref3;
3739
+ } = _ref;
2584
3740
  const filterModelSearch = getSearchParamsFromFilterModel(filterModel);
2585
3741
  const sortModelSearch = getSearchParamsFromSorting(sortModel);
2586
3742
  const paginationModelSearch = getSearchParamsFromPagination(paginationModel);
@@ -2589,10 +3745,6 @@ const getFinalSearch = _ref3 => {
2589
3745
  const densitySearch = getSearchParamsFromDensity(density);
2590
3746
  // Only include _columnOrder in URL when it differs from the default
2591
3747
  const columnOrderSearch = columnOrderModel.length !== defaultColumnOrder.length || columnOrderModel.some((field, i) => field !== defaultColumnOrder[i]) ? getSearchParamsFromColumnOrder(columnOrderModel) : new URLSearchParams();
2592
- const rowGroupingSearch = getSearchParamsFromRowGrouping(rowGroupingModel);
2593
- const aggregationSearch = getSearchParamsFromAggregation(aggregationModel);
2594
- const pivotSearch = getSearchParamsFromPivot(pivotModel);
2595
- const pivotActiveSearch = getSearchParamsFromPivotActive(pivotActive);
2596
3748
  const tabSearch = getSearchParamsFromTab(search);
2597
3749
  const searchParams = new URLSearchParams();
2598
3750
  for (const [key, value] of new URLSearchParams(search)) {
@@ -2607,7 +3759,7 @@ const getFinalSearch = _ref3 => {
2607
3759
  // Encode array as JSON string to preserve all values in one param
2608
3760
  searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
2609
3761
  }
2610
- return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch, ...rowGroupingSearch, ...aggregationSearch, ...pivotSearch, ...pivotActiveSearch]);
3762
+ return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch]);
2611
3763
  };
2612
3764
  /** Return the state of the table given the URL and the local storage state */
2613
3765
  const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage) => {
@@ -2647,15 +3799,7 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2647
3799
  localStorageDensity,
2648
3800
  setLocalStorageDensity,
2649
3801
  localStorageColumnOrder,
2650
- setLocalStorageColumnOrder,
2651
- localStorageRowGrouping,
2652
- setLocalStorageRowGrouping,
2653
- localStorageAggregation,
2654
- setLocalStorageAggregation,
2655
- localStoragePivot,
2656
- setLocalStoragePivot,
2657
- localStoragePivotActive,
2658
- setLocalStoragePivotActive
3802
+ setLocalStorageColumnOrder
2659
3803
  } = localStorage;
2660
3804
  const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion);
2661
3805
  const sortModel = getSortModel(decodedSearch, columns, localStorageSorting, setLocalStorageSorting, initialState, isNewVersion);
@@ -2664,10 +3808,6 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2664
3808
  const pinnedColumnsModel = getPinnedColumns(decodedSearch, columns, localStoragePinnedColumns, setLocalStoragePinnedColumns, initialState, isNewVersion);
2665
3809
  const density = getDensityModel(decodedSearch, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion);
2666
3810
  const columnOrderModel = getColumnOrder(decodedSearch, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion);
2667
- const rowGroupingModel = getRowGroupingModel(decodedSearch, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion);
2668
- const aggregationModel = getAggregationModel(decodedSearch, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion);
2669
- const pivotModel = getPivotModel(decodedSearch, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion);
2670
- const pivotActive = getPivotActive(decodedSearch, localStoragePivotActive, setLocalStoragePivotActive, initialState, isNewVersion);
2671
3811
  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);
2672
3812
  const finalSearch = getFinalSearch({
2673
3813
  localStorageVersion,
@@ -2680,10 +3820,6 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2680
3820
  density,
2681
3821
  columnOrderModel,
2682
3822
  defaultColumnOrder,
2683
- rowGroupingModel,
2684
- aggregationModel,
2685
- pivotModel,
2686
- pivotActive,
2687
3823
  columns
2688
3824
  });
2689
3825
  const internalSearchString = urlSearchParamsToString(finalSearch);
@@ -2704,14 +3840,10 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
2704
3840
  pinnedColumnsModel,
2705
3841
  density,
2706
3842
  columnOrderModel,
2707
- rowGroupingModel,
2708
- aggregationModel,
2709
- pivotModel,
2710
- pivotActive,
2711
3843
  pendingSearch
2712
3844
  };
2713
3845
  };
2714
- const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns) => {
3846
+ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns) => {
2715
3847
  let {
2716
3848
  filterModel,
2717
3849
  sortModel,
@@ -2720,12 +3852,8 @@ const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns)
2720
3852
  pinnedColumnsModel,
2721
3853
  density,
2722
3854
  columnOrderModel,
2723
- defaultColumnOrder,
2724
- rowGroupingModel,
2725
- aggregationModel,
2726
- pivotModel,
2727
- pivotActive
2728
- } = _ref4;
3855
+ defaultColumnOrder
3856
+ } = _ref2;
2729
3857
  // Convert from display format to internal format if needed
2730
3858
  const decodedSearch = getDecodedSearchFromUrl(search, columns);
2731
3859
  const newSearch = getFinalSearch({
@@ -2739,10 +3867,6 @@ const updateUrl = (_ref4, search, localStorageVersion, historyReplace, columns)
2739
3867
  density,
2740
3868
  columnOrderModel,
2741
3869
  defaultColumnOrder,
2742
- rowGroupingModel,
2743
- aggregationModel,
2744
- pivotModel,
2745
- pivotActive,
2746
3870
  columns
2747
3871
  });
2748
3872
  const internalSearchString = urlSearchParamsToString(newSearch);
@@ -2935,26 +4059,6 @@ const useTableStates = (id, version) => {
2935
4059
  version,
2936
4060
  category: COLUMN_ORDER_MODEL_KEY
2937
4061
  }));
2938
- const [rowGroupingModel, setRowGroupingModel] = useFetchState('', buildStorageKey({
2939
- id,
2940
- version,
2941
- category: ROW_GROUPING_MODEL_KEY
2942
- }));
2943
- const [aggregationModel, setAggregationModel] = useFetchState('', buildStorageKey({
2944
- id,
2945
- version,
2946
- category: AGGREGATION_MODEL_KEY
2947
- }));
2948
- const [pivotModel, setPivotModel] = useFetchState('', buildStorageKey({
2949
- id,
2950
- version,
2951
- category: PIVOT_MODEL_KEY
2952
- }));
2953
- const [pivotActive, setPivotActive] = useFetchState('', buildStorageKey({
2954
- id,
2955
- version,
2956
- category: PIVOT_ACTIVE_KEY
2957
- }));
2958
4062
  return {
2959
4063
  paginationModel,
2960
4064
  setPaginationModel,
@@ -2971,41 +4075,13 @@ const useTableStates = (id, version) => {
2971
4075
  densityModel,
2972
4076
  setDensityModel,
2973
4077
  columnOrderModel,
2974
- setColumnOrderModel,
2975
- rowGroupingModel,
2976
- setRowGroupingModel,
2977
- aggregationModel,
2978
- setAggregationModel,
2979
- pivotModel,
2980
- setPivotModel,
2981
- pivotActive,
2982
- setPivotActive
4078
+ setColumnOrderModel
2983
4079
  };
2984
4080
  };
2985
4081
 
2986
- /** Convert our simplified PivotModel → MUI's GridPivotModel */
2987
- const toGridPivotModel = model => ({
2988
- columns: model.columns.map(field => ({
2989
- field
2990
- })),
2991
- rows: model.rows.map(field => ({
2992
- field
2993
- })),
2994
- values: model.values.map(_ref => {
2995
- let {
2996
- field,
2997
- aggFunc
2998
- } = _ref;
2999
- return {
3000
- field,
3001
- aggFunc
3002
- };
3003
- })
3004
- });
3005
-
3006
4082
  /**
3007
4083
  * Deep-equal comparison for plain objects / arrays.
3008
- * Used to stabilise parsed model references so that MUI v8 does not
4084
+ * Used to stabilise parsed model references so that MUI does not
3009
4085
  * reset pagination on every render.
3010
4086
  */
3011
4087
  function isDeepEqual(a, b) {
@@ -3032,9 +4108,6 @@ const useStatefulTable = props => {
3032
4108
  onPaginationModelChange: propsOnPaginationModelChange,
3033
4109
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3034
4110
  onSortModelChange: propsOnSortModelChange,
3035
- onRowGroupingModelChange: propsOnRowGroupingModelChange,
3036
- onAggregationModelChange: propsOnAggregationModelChange,
3037
- onPivotModelChange: propsOnPivotModelChange,
3038
4111
  useRouter,
3039
4112
  localStorageVersion = 1,
3040
4113
  previousLocalStorageVersions = []
@@ -3063,24 +4136,16 @@ const useStatefulTable = props => {
3063
4136
  densityModel,
3064
4137
  setDensityModel,
3065
4138
  columnOrderModel: localStorageColumnOrder,
3066
- setColumnOrderModel: setLocalStorageColumnOrder,
3067
- rowGroupingModel: localStorageRowGrouping,
3068
- setRowGroupingModel: setLocalStorageRowGrouping,
3069
- aggregationModel: localStorageAggregation,
3070
- setAggregationModel: setLocalStorageAggregation,
3071
- pivotModel: localStoragePivot,
3072
- setPivotModel: setLocalStoragePivot,
3073
- pivotActive: localStoragePivotActive,
3074
- setPivotActive: setLocalStoragePivotActive
4139
+ setColumnOrderModel: setLocalStorageColumnOrder
3075
4140
  } = useTableStates(id, localStorageVersion);
3076
4141
 
3077
4142
  // clearing up old version keys, triggering only on first render
3078
4143
  useEffect(() => clearPreviousVersionStorage(id, previousLocalStorageVersions), [id, previousLocalStorageVersions]);
3079
- const onColumnDimensionChange = useCallback(_ref2 => {
4144
+ const onColumnDimensionChange = useCallback(_ref => {
3080
4145
  let {
3081
4146
  newWidth,
3082
4147
  field
3083
- } = _ref2;
4148
+ } = _ref;
3084
4149
  setDimensionModel(_objectSpread2(_objectSpread2({}, dimensionModel), {}, {
3085
4150
  [field]: newWidth
3086
4151
  }));
@@ -3093,10 +4158,6 @@ const useStatefulTable = props => {
3093
4158
  pinnedColumnsModel,
3094
4159
  density: densityParsed,
3095
4160
  columnOrderModel: columnOrderParsed,
3096
- rowGroupingModel: rowGroupingParsed,
3097
- aggregationModel: aggregationParsed,
3098
- pivotModel: pivotParsed,
3099
- pivotActive: pivotActiveParsed,
3100
4161
  pendingSearch
3101
4162
  } = getModelsParsedOrUpdateLocalStorage(search || '', localStorageVersion, propsColumns, initialState, {
3102
4163
  localStorageFilters,
@@ -3112,15 +4173,7 @@ const useStatefulTable = props => {
3112
4173
  localStorageDensity: densityModel,
3113
4174
  setLocalStorageDensity: setDensityModel,
3114
4175
  localStorageColumnOrder,
3115
- setLocalStorageColumnOrder,
3116
- localStorageRowGrouping,
3117
- setLocalStorageRowGrouping,
3118
- localStorageAggregation,
3119
- setLocalStorageAggregation,
3120
- localStoragePivot,
3121
- setLocalStoragePivot,
3122
- localStoragePivotActive: localStoragePivotActive,
3123
- setLocalStoragePivotActive: setLocalStoragePivotActive
4176
+ setLocalStorageColumnOrder
3124
4177
  });
3125
4178
 
3126
4179
  // Sync URL in an effect rather than during render to comply with React rules
@@ -3130,7 +4183,7 @@ const useStatefulTable = props => {
3130
4183
  }
3131
4184
  }, [pendingSearch, historyReplace]);
3132
4185
 
3133
- // Stabilise parsed model references to prevent MUI v8 from resetting
4186
+ // Stabilise parsed model references to prevent MUI from resetting
3134
4187
  // pagination on every render due to new object identity.
3135
4188
  const filterParsedRef = useRef(filterParsed);
3136
4189
  if (!isDeepEqual(filterParsedRef.current, filterParsed)) {
@@ -3156,18 +4209,6 @@ const useStatefulTable = props => {
3156
4209
  if (!isDeepEqual(columnOrderParsedRef.current, columnOrderParsed)) {
3157
4210
  columnOrderParsedRef.current = columnOrderParsed;
3158
4211
  }
3159
- const rowGroupingParsedRef = useRef(rowGroupingParsed);
3160
- if (!isDeepEqual(rowGroupingParsedRef.current, rowGroupingParsed)) {
3161
- rowGroupingParsedRef.current = rowGroupingParsed;
3162
- }
3163
- const aggregationParsedRef = useRef(aggregationParsed);
3164
- if (!isDeepEqual(aggregationParsedRef.current, aggregationParsed)) {
3165
- aggregationParsedRef.current = aggregationParsed;
3166
- }
3167
- const pivotParsedRef = useRef(pivotParsed);
3168
- if (!isDeepEqual(pivotParsedRef.current, pivotParsed)) {
3169
- pivotParsedRef.current = pivotParsed;
3170
- }
3171
4212
  const columns = useMemo(() => propsColumns.map(column => {
3172
4213
  return _objectSpread2(_objectSpread2({}, column), {}, {
3173
4214
  width: dimensionModel[column.field] || column.width || 100
@@ -3176,13 +4217,29 @@ const useStatefulTable = props => {
3176
4217
  if (apiRef.current) {
3177
4218
  /** Add resetPage method to apiRef. */
3178
4219
  apiRef.current.resetPage = () => {
3179
- var _apiRef$current;
3180
- (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPage(0);
4220
+ apiRef.current.setPage(0);
3181
4221
  };
3182
4222
  }
3183
4223
  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);
3184
4224
 
3185
- // Subscribe to density changes via stateChange event (MUI v6 has no densityChange event)
4225
+ // Helper to build the current DataGridModel for updateUrl calls
4226
+ const buildModel = function () {
4227
+ var _apiRef$current$state, _apiRef$current;
4228
+ let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4229
+ return _objectSpread2({
4230
+ filterModel: filterParsed,
4231
+ sortModel: sortModelParsed,
4232
+ paginationModel: paginationModelParsed,
4233
+ 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 : {},
4234
+ pinnedColumnsModel: pinnedColumnsModel,
4235
+ density: densityParsed,
4236
+ columnOrderModel: columnOrderParsed,
4237
+ defaultColumnOrder
4238
+ }, overrides);
4239
+ };
4240
+
4241
+ // Subscribe to density changes via stateChange event
4242
+ // (MUI v7 supports onDensityChange, but stateChange works and avoids a larger refactor)
3186
4243
  useEffect(() => {
3187
4244
  const api = apiRef.current;
3188
4245
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
@@ -3191,24 +4248,14 @@ const useStatefulTable = props => {
3191
4248
  const currentDensity = api.state.density;
3192
4249
  if (currentDensity !== prevDensity) {
3193
4250
  prevDensity = currentDensity;
3194
- updateUrl({
3195
- filterModel: filterParsed,
3196
- sortModel: sortModelParsed,
3197
- paginationModel: paginationModelParsed,
4251
+ updateUrl(buildModel({
3198
4252
  columnsModel: api.state.columns.columnVisibilityModel,
3199
- pinnedColumnsModel: pinnedColumnsModel,
3200
- density: currentDensity,
3201
- columnOrderModel: columnOrderParsed,
3202
- defaultColumnOrder,
3203
- rowGroupingModel: rowGroupingParsed,
3204
- aggregationModel: aggregationParsed,
3205
- pivotModel: pivotParsed,
3206
- pivotActive: pivotActiveParsed
3207
- }, search, localStorageVersion, historyReplace, columns);
4253
+ density: currentDensity
4254
+ }), search, localStorageVersion, historyReplace, columns);
3208
4255
  }
3209
4256
  });
3210
4257
  return unsub;
3211
- }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
4258
+ }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, search, localStorageVersion, historyReplace, columns]);
3212
4259
 
3213
4260
  // Subscribe to column order changes via columnOrderChange (drag-drop) and columnIndexChange (programmatic setColumnIndex)
3214
4261
  useEffect(() => {
@@ -3217,20 +4264,9 @@ const useStatefulTable = props => {
3217
4264
  const handleColumnOrderChange = () => {
3218
4265
  const orderedFields = api.state.columns.orderedFields;
3219
4266
  if (orderedFields && !isDeepEqual(orderedFields, columnOrderParsed)) {
3220
- updateUrl({
3221
- filterModel: filterParsed,
3222
- sortModel: sortModelParsed,
3223
- paginationModel: paginationModelParsed,
3224
- columnsModel: api.state.columns.columnVisibilityModel,
3225
- pinnedColumnsModel,
3226
- density: densityParsed,
3227
- columnOrderModel: orderedFields,
3228
- defaultColumnOrder,
3229
- rowGroupingModel: rowGroupingParsed,
3230
- aggregationModel: aggregationParsed,
3231
- pivotModel: pivotParsed,
3232
- pivotActive: pivotActiveParsed
3233
- }, search, localStorageVersion, historyReplace, columns);
4267
+ updateUrl(buildModel({
4268
+ columnOrderModel: orderedFields
4269
+ }), search, localStorageVersion, historyReplace, columns);
3234
4270
  }
3235
4271
  };
3236
4272
  const unsub1 = api.subscribeEvent('columnOrderChange', handleColumnOrderChange);
@@ -3239,53 +4275,28 @@ const useStatefulTable = props => {
3239
4275
  unsub1();
3240
4276
  unsub2();
3241
4277
  };
3242
- }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, rowGroupingParsed, aggregationParsed, pivotParsed, pivotActiveParsed, search, localStorageVersion, historyReplace, columns]);
3243
-
3244
- // Helper to build the current DataGridModel for updateUrl calls
3245
- const buildModel = function () {
3246
- var _apiRef$current$state, _apiRef$current2;
3247
- let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3248
- return _objectSpread2({
3249
- filterModel: filterParsed,
3250
- sortModel: sortModelParsed,
3251
- paginationModel: paginationModelParsed,
3252
- 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 : {},
3253
- pinnedColumnsModel: pinnedColumnsModel,
3254
- density: densityParsed,
3255
- columnOrderModel: columnOrderParsed,
3256
- defaultColumnOrder,
3257
- rowGroupingModel: rowGroupingParsed,
3258
- aggregationModel: aggregationParsed,
3259
- pivotModel: pivotParsed,
3260
- pivotActive: pivotActiveParsed
3261
- }, overrides);
3262
- };
3263
-
3264
- // Stable GridPivotModel identity — only recompute when the simplified value changes.
3265
- // eslint-disable-next-line react-hooks/exhaustive-deps
3266
- const pivotModelMui = useMemo(() => toGridPivotModel(pivotParsed), [JSON.stringify(pivotParsed)]);
4278
+ }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, search, localStorageVersion, historyReplace, columns]);
3267
4279
 
3268
4280
  // Track last emitted values for deep-equal guards to avoid feedback loops.
3269
4281
  // Initialised from the current parsed values; updated only when we actually fire.
3270
4282
  const lastEmittedFilterRef = useRef(filterParsed);
3271
4283
  const lastEmittedSortRef = useRef(sortModelParsed);
3272
4284
  const lastEmittedPaginationRef = useRef(paginationModelParsed);
3273
- const lastEmittedPivotRef = useRef(pivotParsed);
3274
4285
  return {
3275
4286
  apiRef,
3276
4287
  columns,
3277
4288
  density: densityParsed,
4289
+ onDensityChange: newDensity => {
4290
+ updateUrl(buildModel({
4291
+ density: newDensity
4292
+ }), search, localStorageVersion, historyReplace, columns);
4293
+ },
3278
4294
  columnOrderModel: columnOrderParsedRef.current,
3279
- rowGroupingModel: rowGroupingParsedRef.current,
3280
- aggregationModel: aggregationParsedRef.current,
3281
- pivotModel: pivotModelMui,
3282
- pivotActive: pivotActiveParsed,
3283
4295
  onFilterModelChange: (model, details) => {
3284
4296
  const filterModel = _objectSpread2(_objectSpread2({}, model), {}, {
3285
4297
  items: model.items.map(item => {
3286
- var _apiRef$current3;
3287
- const column = (_apiRef$current3 = apiRef.current) === null || _apiRef$current3 === void 0 ? void 0 : _apiRef$current3.getColumn(item.field);
3288
- item.type = (column === null || column === void 0 ? void 0 : column.type) || 'string';
4298
+ const column = apiRef.current.getColumn(item.field);
4299
+ item.type = column.type || 'string';
3289
4300
  return item;
3290
4301
  }),
3291
4302
  quickFilterValues: model.quickFilterValues || []
@@ -3308,20 +4319,10 @@ const useStatefulTable = props => {
3308
4319
  },
3309
4320
  sortModel: sortModelParsedRef.current,
3310
4321
  onPinnedColumnsChange: (pinnedColumns, details) => {
3311
- var _apiRef$current$state2, _apiRef$current4, _apiRef$current4$stat, _apiRef$current4$stat2;
3312
- // While pivot mode is active, MUI Premium emits synthetic pinned-column
3313
- // models (e.g. `__row_group_by_columns_group__` for the grouping column)
3314
- // that must not be persisted to the URL / localStorage. Read the live
3315
- // grid state from apiRef rather than the parsed URL value because the
3316
- // URL lags by a tick during pivot enable/disable transitions. Consumer
3317
- // callbacks are always forwarded so observers can still react.
3318
- 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;
3319
- if (!pivotActiveLive) {
3320
- updateUrl(buildModel({
3321
- pinnedColumnsModel: pinnedColumns
3322
- }), search, localStorageVersion, historyReplace, columns);
3323
- }
3324
4322
  propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
4323
+ updateUrl(buildModel({
4324
+ pinnedColumnsModel: pinnedColumns
4325
+ }), search, localStorageVersion, historyReplace, columns);
3325
4326
  },
3326
4327
  pinnedColumns: pinnedColumnsModelRef.current,
3327
4328
  paginationModel: paginationModelParsedRef.current,
@@ -3338,21 +4339,10 @@ const useStatefulTable = props => {
3338
4339
  },
3339
4340
  columnVisibilityModel: visibilityModelRef.current,
3340
4341
  onColumnVisibilityModelChange: (columnsVisibilityModel, details) => {
3341
- var _apiRef$current$state3, _apiRef$current5, _apiRef$current5$stat, _apiRef$current5$stat2;
3342
- // While pivot mode is active, MUI Premium emits synthetic visibility
3343
- // models that whitelist only the pivot value fields (hiding every base
3344
- // column). Persisting that to the URL would re-hide all base columns
3345
- // on the next load (see getColumnVisibilityFromString whitelist logic).
3346
- // Read the live grid state 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.
3349
- 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;
3350
- if (!pivotActiveLive) {
3351
- updateUrl(buildModel({
3352
- columnsModel: columnsVisibilityModel
3353
- }), search, localStorageVersion, historyReplace, columns);
3354
- }
3355
4342
  propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
4343
+ updateUrl(buildModel({
4344
+ columnsModel: columnsVisibilityModel
4345
+ }), search, localStorageVersion, historyReplace, columns);
3356
4346
  },
3357
4347
  onColumnWidthChange: (params, event, details) => {
3358
4348
  propsOnColumnWidthChange === null || propsOnColumnWidthChange === void 0 ? void 0 : propsOnColumnWidthChange(params, event, details);
@@ -3360,38 +4350,11 @@ const useStatefulTable = props => {
3360
4350
  newWidth: params.width,
3361
4351
  field: params.colDef.field
3362
4352
  });
3363
- },
3364
- onRowGroupingModelChange: (model, details) => {
3365
- updateUrl(buildModel({
3366
- rowGroupingModel: model
3367
- }), search, localStorageVersion, historyReplace, columns);
3368
- propsOnRowGroupingModelChange === null || propsOnRowGroupingModelChange === void 0 ? void 0 : propsOnRowGroupingModelChange(model, details);
3369
- },
3370
- onAggregationModelChange: (model, details) => {
3371
- updateUrl(buildModel({
3372
- aggregationModel: model
3373
- }), search, localStorageVersion, historyReplace, columns);
3374
- propsOnAggregationModelChange === null || propsOnAggregationModelChange === void 0 ? void 0 : propsOnAggregationModelChange(model, details);
3375
- },
3376
- onPivotModelChange: model => {
3377
- const simplified = fromGridPivotModel(model);
3378
- if (isDeepEqual(simplified, lastEmittedPivotRef.current)) return;
3379
- lastEmittedPivotRef.current = simplified;
3380
- updateUrl(buildModel({
3381
- pivotModel: simplified
3382
- }), search, localStorageVersion, historyReplace, columns);
3383
- propsOnPivotModelChange === null || propsOnPivotModelChange === void 0 ? void 0 : propsOnPivotModelChange(model);
3384
- },
3385
- onPivotActiveChange: active => {
3386
- if (active === pivotActiveParsed) return;
3387
- updateUrl(buildModel({
3388
- pivotActive: active
3389
- }), search, localStorageVersion, historyReplace, columns);
3390
4353
  }
3391
4354
  };
3392
4355
  };
3393
4356
 
3394
- 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"];
4357
+ 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"];
3395
4358
  const COMPONENT_NAME = 'DataGrid';
3396
4359
  const CLASSNAME = 'redsift-datagrid';
3397
4360
 
@@ -3447,7 +4410,6 @@ const CLASSNAME = 'redsift-datagrid';
3447
4410
  */
3448
4411
 
3449
4412
  const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3450
- var _ref7;
3451
4413
  const datagridRef = ref || useRef();
3452
4414
  const {
3453
4415
  apiRef: propsApiRef,
@@ -3476,9 +4438,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3476
4438
  onColumnVisibilityModelChange: propsOnColumnVisibilityModelChange,
3477
4439
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3478
4440
  onSortModelChange: propsOnSortModelChange,
3479
- onRowGroupingModelChange: propsOnRowGroupingModelChange,
3480
- onAggregationModelChange: propsOnAggregationModelChange,
3481
- onPivotModelChange: propsOnPivotModelChange,
3482
4441
  pagination,
3483
4442
  paginationPlacement = 'both',
3484
4443
  selectionBannerPlacement = 'top',
@@ -3489,26 +4448,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3489
4448
  theme: propsTheme,
3490
4449
  useRouter,
3491
4450
  paginationMode = 'client',
3492
- rowCount,
3493
- density: _density,
3494
- dataSource,
3495
- filterMode: propsFilterMode,
3496
- sortingMode: propsSortingMode
4451
+ rowCount
3497
4452
  } = props,
3498
4453
  forwardedProps = _objectWithoutProperties(props, _excluded);
3499
- const theme = useTheme(propsTheme);
4454
+ const theme = useTheme$1(propsTheme);
3500
4455
  const _apiRef = useGridApiRef();
3501
4456
  const apiRef = propsApiRef !== null && propsApiRef !== void 0 ? propsApiRef : _apiRef;
4457
+ const RenderedToolbar = slots !== null && slots !== void 0 && slots.toolbar ? slots.toolbar : Toolbar;
3502
4458
  LicenseInfo.setLicenseKey(license);
3503
4459
  const height = propsHeight !== null && propsHeight !== void 0 ? propsHeight : autoHeight ? undefined : '500px';
3504
-
3505
- // When dataSource is present, MUI manages filter/sort/pagination internally.
3506
- // We must not pass controlled models — only initialState (one-time) and
3507
- // write-only onChange handlers for URL/localStorage persistence.
3508
- const isDataSourceMode = Boolean(dataSource);
3509
- const effectivePaginationMode = isDataSourceMode ? 'server' : paginationMode;
3510
- const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode;
3511
- const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode;
3512
4460
  const {
3513
4461
  onColumnVisibilityModelChange: controlledOnColumnVisibilityModelChange,
3514
4462
  onFilterModelChange: controlledOnFilterModelChange,
@@ -3534,6 +4482,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3534
4482
  density: controlledDensity,
3535
4483
  filterModel,
3536
4484
  onColumnVisibilityModelChange,
4485
+ onDensityChange,
3537
4486
  onFilterModelChange,
3538
4487
  onPaginationModelChange,
3539
4488
  onPinnedColumnsChange,
@@ -3542,15 +4491,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3542
4491
  pinnedColumns,
3543
4492
  sortModel,
3544
4493
  onColumnWidthChange,
3545
- columnOrderModel,
3546
- rowGroupingModel,
3547
- aggregationModel,
3548
- pivotModel,
3549
- pivotActive,
3550
- onRowGroupingModelChange,
3551
- onAggregationModelChange,
3552
- onPivotModelChange,
3553
- onPivotActiveChange
4494
+ columnOrderModel
3554
4495
  } = useStatefulTable({
3555
4496
  apiRef: apiRef,
3556
4497
  initialState,
@@ -3561,9 +4502,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3561
4502
  onPaginationModelChange: controlledOnPaginationModelChange,
3562
4503
  onPinnedColumnsChange: controlledOnPinnedColumnsChange,
3563
4504
  onSortModelChange: controlledOnSortModelChange,
3564
- onRowGroupingModelChange: propsOnRowGroupingModelChange,
3565
- onAggregationModelChange: propsOnAggregationModelChange,
3566
- onPivotModelChange: propsOnPivotModelChange,
3567
4505
  useRouter: useRouter,
3568
4506
  localStorageVersion,
3569
4507
  previousLocalStorageVersions
@@ -3599,61 +4537,9 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3599
4537
  return column;
3600
4538
  });
3601
4539
  }, [columns, columnOrderModel]);
3602
-
3603
- // In dataSource mode, track pagination locally for the custom pagination slots
3604
- // (rendered outside DataGridPremium). MUI owns the actual pagination state internally.
3605
- const [dataSourcePaginationModel, setDataSourcePaginationModel] = useState(paginationModel);
3606
-
3607
- // The pagination model to use for display in pagination slots
3608
- const activePaginationModel = isDataSourceMode ? dataSourcePaginationModel : paginationModel;
3609
-
3610
- // Wrap onPaginationModelChange to also track state locally in dataSource mode
3611
- const wrappedOnPaginationModelChange = useCallback((model, details) => {
3612
- if (isDataSourceMode) {
3613
- setDataSourcePaginationModel(model);
3614
- }
3615
- onPaginationModelChange(model, details);
3616
- }, [isDataSourceMode, onPaginationModelChange]);
3617
-
3618
- // In dataSource mode, pagination changes from our custom pagination slots
3619
- // (rendered outside MUI's pagination state) route through apiRef so MUI's
3620
- // internal page state updates and dataSource.getRows() refetches with the
3621
- // new params. The `paginationModelChange` subscription below picks up the
3622
- // resulting state change and propagates it to URL/localStorage and local
3623
- // React state via wrappedOnPaginationModelChange.
3624
- const dataSourcePaginationChange = useCallback(model => {
3625
- var _apiRef$current;
3626
- (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPaginationModel(model);
3627
- }, [apiRef]);
3628
-
3629
- // In dataSource mode, subscribe to MUI's `paginationModelChange` event so
3630
- // URL state stays in sync with MUI's internal pagination regardless of how
3631
- // it changed (slot click, apiRef.setPaginationModel from consumer code,
3632
- // MUI internal updates, etc.). Relying on MUI's `onPaginationModelChange`
3633
- // prop callback alone is not sufficient: in pivot/GroupedData strategy mode
3634
- // and with `paginationModel` seeded via `initialState` (rather than as a
3635
- // controlled prop), the prop callback can be missed under certain
3636
- // re-render orderings. The event fires reliably whenever the internal
3637
- // state changes via `setState('setPaginationModel')`, see
3638
- // `useGridStateInitialization.setState` → `publishEvent(changeEvent, …)`.
3639
- // The deep-equal guard inside `useStatefulTable.onPaginationModelChange`
3640
- // dedupes any duplicate emits, so overlap with the prop callback is safe.
3641
- useEffect(() => {
3642
- if (!isDataSourceMode) return;
3643
- const api = apiRef.current;
3644
- if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
3645
- return api.subscribeEvent('paginationModelChange', model => {
3646
- wrappedOnPaginationModelChange({
3647
- page: model.page,
3648
- pageSize: model.pageSize
3649
- }, {
3650
- reason: 'paginationModelChange'
3651
- });
3652
- });
3653
- }, [isDataSourceMode, apiRef, wrappedOnPaginationModelChange]);
3654
- const [rowSelectionModel, setRowSelectionModel] = useState(() => normalizeRowSelectionModel(propsRowSelectionModel));
4540
+ const [rowSelectionModel, setRowSelectionModel] = useState(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3655
4541
  useEffect(() => {
3656
- setRowSelectionModel(normalizeRowSelectionModel(propsRowSelectionModel));
4542
+ setRowSelectionModel(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3657
4543
  }, [propsRowSelectionModel]);
3658
4544
  const onRowSelectionModelChange = (selectionModel, details) => {
3659
4545
  setRowSelectionModel(selectionModel);
@@ -3672,44 +4558,23 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3672
4558
 
3673
4559
  // The checkboxSelectionVisibleOnly should only be applied to client-side pagination,
3674
4560
  // for server-side pagination it produces inconsistent behavior when selecting all rows in pages 2 and beyond
3675
- const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(effectivePaginationMode != 'server');
4561
+ const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(paginationMode != 'server');
3676
4562
 
3677
4563
  // Banner and pager placements are independent. `belowToolbar` (for either) renders
3678
- // in a row inside the toolbar slot, and only applies when pagination is on.
4564
+ // in the toolbar-slot row, and only applies when pagination is on.
3679
4565
  const bannerAtTop = selectionBannerPlacement === 'top';
3680
4566
  const bannerAtBottom = selectionBannerPlacement === 'bottom';
3681
4567
  const bannerBelowToolbar = selectionBannerPlacement === 'belowToolbar' && Boolean(pagination);
3682
4568
  const pagerBelowToolbar = paginationPlacement === 'belowToolbar' && Boolean(pagination);
3683
- const belowToolbarActive = bannerBelowToolbar || pagerBelowToolbar;
3684
-
3685
- // Track when the grid API is ready to ensure top pagination renders correctly
3686
- const [gridReady, setGridReady] = useState(false);
3687
-
3688
- // Force re-render when the grid API becomes ready (for top pagination)
3689
- useEffect(() => {
3690
- if (apiRef.current && !gridReady) {
3691
- setGridReady(true);
3692
- }
3693
- });
3694
-
3695
- // Sync persisted density via apiRef — initialState only applies on mount,
3696
- // so this handles SPA back/forward navigation where controlledDensity changes after mount
3697
- useEffect(() => {
3698
- if (apiRef.current) {
3699
- apiRef.current.setDensity(controlledDensity);
3700
- }
3701
- }, [controlledDensity, apiRef]);
3702
4569
 
3703
4570
  // in server-side pagination we want to update the selection status
3704
4571
  // every time we navigate between pages, resize our page or select something
3705
4572
  useEffect(() => {
3706
- if (effectivePaginationMode == 'server') {
3707
- onServerSideSelectionStatusChange(rowSelectionModel, apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, activePaginationModel.page, activePaginationModel.pageSize);
4573
+ if (paginationMode == 'server') {
4574
+ onServerSideSelectionStatusChange(Array.isArray(rowSelectionModel) ? rowSelectionModel : [rowSelectionModel], apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, paginationModel.page, paginationModel.pageSize);
3708
4575
  }
3709
- }, [rowSelectionModel, activePaginationModel.page, activePaginationModel.pageSize, rows]);
3710
-
3711
- // In dataSource mode MUI provides rows internally; skip the guard.
3712
- if (!isDataSourceMode && !Array.isArray(rows)) {
4576
+ }, [rowSelectionModel, paginationModel.page, paginationModel.pageSize, rows]);
4577
+ if (!Array.isArray(rows)) {
3713
4578
  return null;
3714
4579
  }
3715
4580
 
@@ -3718,15 +4583,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3718
4583
  // receive the fresh value in the same render cycle — no extra re-render needed.
3719
4584
  // The ref is kept in sync for the onRowSelectionModelChange callback's deselect logic.
3720
4585
  let selectionStatus = selectionStatusRef.current;
3721
- if (pagination && effectivePaginationMode !== 'server' && getSelectionCount(rowSelectionModel) > 0) {
4586
+ if (pagination && paginationMode !== 'server' && Array.isArray(rowSelectionModel) && rowSelectionModel.length > 0) {
3722
4587
  try {
3723
- // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors.
3724
- // MUI's paginated selectors use apiRef internal state which may be stale when
3725
- // paginationModel prop changes our React state is always up to date.
3726
- const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3727
- const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3728
- const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3729
- const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref2 => {
4588
+ // Use manual page slicing with our React state's paginationModel instead of
4589
+ // gridPaginatedVisibleSortedGridRow*Selector(apiRef). In MUI v7, the apiRef's
4590
+ // internal pagination state can lag behind the React state after a page change,
4591
+ // causing the selection status to be one page behind.
4592
+ const pageStart = paginationModel.page * paginationModel.pageSize;
4593
+ const pageEnd = pageStart + paginationModel.pageSize;
4594
+ const selectableRowsInPage = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).slice(pageStart, pageEnd).filter(_ref2 => {
3730
4595
  let {
3731
4596
  model
3732
4597
  } = _ref2;
@@ -3738,29 +4603,24 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3738
4603
  id
3739
4604
  } = _ref3;
3740
4605
  return id;
3741
- }) : pageEntries.map(_ref4 => {
3742
- let {
3743
- id
3744
- } = _ref4;
3745
- return id;
3746
- });
4606
+ }) : gridFilteredSortedRowIdsSelector(apiRef).slice(pageStart, pageEnd);
3747
4607
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
3748
- const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref5 => {
4608
+ const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref4 => {
3749
4609
  let {
3750
4610
  model
3751
- } = _ref5;
4611
+ } = _ref4;
3752
4612
  return isRowSelectable({
3753
4613
  row: model
3754
4614
  });
3755
- }).map(_ref6 => {
4615
+ }).map(_ref5 => {
3756
4616
  let {
3757
4617
  id
3758
- } = _ref6;
4618
+ } = _ref5;
3759
4619
  return id;
3760
4620
  }) : gridFilteredSortedRowIdsSelector(apiRef);
3761
4621
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
3762
- const numberOfSelectedRows = getSelectionCount(rowSelectionModel);
3763
- const selectedOnCurrentPage = selectableRowsInPage.filter(id => isRowSelected(rowSelectionModel, id));
4622
+ const numberOfSelectedRows = rowSelectionModel.length;
4623
+ const selectedOnCurrentPage = selectableRowsInPage.filter(id => rowSelectionModel.includes(id));
3764
4624
  if (numberOfSelectedRows === numberOfSelectableRowsInTable && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
3765
4625
  selectionStatus = {
3766
4626
  type: 'table',
@@ -3785,7 +4645,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3785
4645
  } catch {
3786
4646
  // apiRef may not be initialized on first render
3787
4647
  }
3788
- } else if (pagination && effectivePaginationMode !== 'server') {
4648
+ } else if (pagination && paginationMode !== 'server') {
3789
4649
  selectionStatus = {
3790
4650
  type: 'none',
3791
4651
  numberOfSelectedRows: 0
@@ -3810,39 +4670,37 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3810
4670
  // remounted (remounting the toolbar dropped quick-search focus on every keystroke). Typed as
3811
4671
  // ToolbarWrapper props so mistakes are caught here; cast to MUI's slot types at the injection
3812
4672
  // sites below. See ../DataGrid/defaultSlots.
3813
- const belowToolbarSlotProps = {
3814
- RenderedToolbar: (_ref7 = slots === null || slots === void 0 ? void 0 : slots.toolbar) !== null && _ref7 !== void 0 ? _ref7 : Toolbar,
4673
+ const toolbarSlotProps = {
3815
4674
  hideToolbar,
4675
+ RenderedToolbar,
3816
4676
  filterModel,
3817
4677
  onFilterModelChange,
3818
4678
  pagination,
3819
- paginationMode: effectivePaginationMode,
3820
- displaySelection: bannerBelowToolbar,
3821
- displayPagination: pagerBelowToolbar,
4679
+ displaySelection: bannerAtTop || bannerBelowToolbar,
4680
+ displayPagination: ['top', 'both'].includes(paginationPlacement) || pagerBelowToolbar,
3822
4681
  displayRowsPerPage: pagerBelowToolbar,
3823
4682
  selectionStatus,
3824
4683
  apiRef,
3825
4684
  isRowSelectable,
3826
- paginationModel: activePaginationModel,
3827
- onPaginationModelChange: isDataSourceMode ? dataSourcePaginationChange : onPaginationModelChange,
3828
- pageSizeOptions: pageSizeOptions,
4685
+ paginationModel,
4686
+ onPaginationModelChange,
4687
+ pageSizeOptions,
3829
4688
  paginationProps,
4689
+ paginationMode,
3830
4690
  rowCount
3831
4691
  };
3832
4692
  const bottomPaginationSlotProps = {
3833
4693
  pagination,
3834
- paginationMode: effectivePaginationMode,
4694
+ paginationMode,
3835
4695
  displaySelection: bannerAtBottom,
3836
4696
  displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
3837
4697
  displayPagination: ['bottom', 'both'].includes(paginationPlacement),
3838
4698
  selectionStatus,
3839
- paginationModel: activePaginationModel,
3840
- // Bottom pager routes non-dataSource changes through the wrapped handler (the
3841
- // belowToolbar/top pagers use the unwrapped one) — preserved from the previous inline slot.
3842
- onPaginationModelChange: isDataSourceMode ? dataSourcePaginationChange : wrappedOnPaginationModelChange,
4699
+ paginationModel,
4700
+ onPaginationModelChange,
3843
4701
  apiRef,
3844
4702
  isRowSelectable,
3845
- pageSizeOptions: pageSizeOptions,
4703
+ pageSizeOptions,
3846
4704
  paginationProps,
3847
4705
  rowCount
3848
4706
  };
@@ -3856,172 +4714,90 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
3856
4714
  ref: datagridRef,
3857
4715
  className: classNames(StatefulDataGrid.className, className),
3858
4716
  $height: height
3859
- }, pagination && gridReady && (bannerAtTop || ['top', 'both'].includes(paginationPlacement)) ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, {
3860
- displaySelection: bannerAtTop,
3861
- displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3862
- displayPagination: ['top', 'both'].includes(paginationPlacement),
3863
- selectionStatus: selectionStatus,
3864
- paginationModel: activePaginationModel,
3865
- onPaginationModelChange: isDataSourceMode ? dataSourcePaginationChange : onPaginationModelChange,
3866
- pageSizeOptions: pageSizeOptions,
3867
- paginationProps: paginationProps,
3868
- rowCount: rowCount
3869
- }) : /*#__PURE__*/React__default.createElement(ControlledPagination, {
3870
- displaySelection: bannerAtTop,
3871
- displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3872
- displayPagination: ['top', 'both'].includes(paginationPlacement),
3873
- selectionStatus: selectionStatus,
4717
+ }, /*#__PURE__*/React__default.createElement(DataGridPro, _extends({}, forwardedProps, {
3874
4718
  apiRef: apiRef,
3875
- isRowSelectable: isRowSelectable,
3876
- paginationModel: activePaginationModel,
3877
- onPaginationModelChange: onPaginationModelChange,
3878
- pageSizeOptions: pageSizeOptions,
3879
- paginationProps: paginationProps
3880
- }) : null, /*#__PURE__*/React__default.createElement(DataGridPremium, _extends({}, forwardedProps, {
3881
- apiRef: apiRef,
3882
- dataSource: dataSource,
3883
4719
  columns: orderedColumns,
4720
+ columnVisibilityModel: columnVisibilityModel,
4721
+ density: controlledDensity,
4722
+ filterModel: filterModel,
3884
4723
  onColumnVisibilityModelChange: onColumnVisibilityModelChange,
4724
+ onDensityChange: onDensityChange,
4725
+ onFilterModelChange: onFilterModelChange,
4726
+ onPaginationModelChange: onPaginationModelChange,
3885
4727
  onPinnedColumnsChange: onPinnedColumnsChange,
4728
+ onSortModelChange: onSortModelChange,
4729
+ paginationModel: paginationModel,
4730
+ pinnedColumns: pinnedColumns,
4731
+ sortModel: sortModel,
3886
4732
  pageSizeOptions: pageSizeOptions,
3887
4733
  onColumnWidthChange: onColumnWidthChange,
3888
- onRowGroupingModelChange: onRowGroupingModelChange,
3889
- onAggregationModelChange: onAggregationModelChange,
3890
- onPivotModelChange: onPivotModelChange,
3891
- pivotActive: pivotActive,
3892
- onPivotActiveChange: onPivotActiveChange
3893
- // In dataSource mode: models are uncontrolled (MUI owns them),
3894
- // onChange handlers are write-only for URL/localStorage persistence,
3895
- // and initialState seeds MUI on mount from the persisted URL state.
3896
- // columnVisibilityModel / pinnedColumns / rowGroupingModel /
3897
- // aggregationModel / pivotModel are also uncontrolled here to
3898
- // avoid a controlled re-render race with consumer-side
3899
- // microtask-deferred history updates (otherwise user toggles
3900
- // flip back when MUI re-emits with the stale controlled value).
3901
- // pivotModel specifically also carries `hidden`/`sort` field
3902
- // metadata that our simplified URL representation strips — so
3903
- // controlling it would prevent users from unchecking fields in
3904
- // the pivot panel (the controlled prop would immediately re-add
3905
- // them). Consumers needing programmatic changes should use the
3906
- // apiRef imperative API.
3907
- }, isDataSourceMode ? {
3908
- onFilterModelChange: onFilterModelChange,
3909
- onSortModelChange: onSortModelChange,
3910
- onPaginationModelChange: wrappedOnPaginationModelChange,
3911
4734
  initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3912
- density: controlledDensity,
3913
- columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3914
- orderedFields: columnOrderModel,
3915
- columnVisibilityModel
3916
- }),
3917
- pinnedColumns,
3918
- rowGrouping: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.rowGrouping), {}, {
3919
- model: rowGroupingModel
3920
- }),
3921
- aggregation: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.aggregation), {}, {
3922
- model: aggregationModel
3923
- }),
3924
- filter: {
3925
- filterModel
3926
- },
3927
- sorting: {
3928
- sortModel
3929
- },
3930
- pagination: {
3931
- paginationModel
3932
- },
3933
- pivoting: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.pivoting), {}, {
3934
- model: pivotModel,
3935
- enabled: pivotActive
3936
- })
3937
- })
3938
- } : {
3939
- columnVisibilityModel,
3940
- pinnedColumns,
3941
- rowGroupingModel,
3942
- aggregationModel,
3943
- filterModel,
3944
- sortModel,
3945
- paginationModel,
3946
- pivotModel,
3947
- onFilterModelChange: onFilterModelChange,
3948
- onSortModelChange: onSortModelChange,
3949
- onPaginationModelChange: wrappedOnPaginationModelChange,
3950
- initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3951
- density: controlledDensity,
3952
4735
  columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3953
4736
  orderedFields: columnOrderModel
3954
4737
  })
3955
- })
3956
- }, {
4738
+ }),
3957
4739
  isRowSelectable: isRowSelectable,
3958
4740
  pagination: pagination,
3959
- paginationMode: effectivePaginationMode,
3960
- filterMode: effectiveFilterMode,
3961
- sortingMode: effectiveSortingMode,
3962
- keepNonExistentRowsSelected: effectivePaginationMode == 'server',
3963
- rows: isDataSourceMode ? [] : rows,
4741
+ paginationMode: paginationMode,
4742
+ keepNonExistentRowsSelected: paginationMode == 'server',
4743
+ rows: rows,
3964
4744
  rowCount: rowCount,
3965
4745
  autoHeight: autoHeight,
3966
4746
  checkboxSelectionVisibleOnly: checkboxSelectionVisibleOnly,
3967
- disableRowSelectionExcludeModel: true,
3968
- showToolbar: !hideToolbar || belowToolbarActive,
3969
- slots: _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, baseGridSlots), slots), belowToolbarActive ? {
3970
- toolbar: BelowToolbar
3971
- } : {}), {}, {
4747
+ slots: _objectSpread2(_objectSpread2(_objectSpread2({}, baseGridSlots), slots), {}, {
4748
+ // `BelowToolbar` and `BottomPagination` are stable module-level components; their
4749
+ // per-render data is injected via `slotProps` below. A fresh inline function here
4750
+ // would remount the slot's subtree every render — for the toolbar that dropped
4751
+ // quick-search focus on every keystroke. The consumer's `slots.toolbar` (or the
4752
+ // default DS Toolbar) is preserved via `RenderedToolbar` inside ToolbarWrapper.
4753
+ toolbar: BelowToolbar,
3972
4754
  pagination: BottomPagination
3973
4755
  }),
3974
- slotProps: _objectSpread2(_objectSpread2(_objectSpread2({}, slotProps), belowToolbarActive ? {
3975
- toolbar: _objectSpread2(_objectSpread2({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar), belowToolbarSlotProps)
3976
- } : {}), {}, {
4756
+ slotProps: _objectSpread2(_objectSpread2({}, slotProps), {}, {
4757
+ // Inject the per-render slot data (built above) here rather than closing over it
4758
+ // in inline slots, so the slot identities stay stable. Consumer slot props are
4759
+ // spread first; the DS layout data wins. Cast at the MUI boundary because these
4760
+ // are ToolbarWrapper props, not the MUI slot prop types.
4761
+ toolbar: _objectSpread2(_objectSpread2({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.toolbar), toolbarSlotProps),
3977
4762
  pagination: _objectSpread2(_objectSpread2({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.pagination), bottomPaginationSlotProps)
3978
4763
  }),
3979
4764
  rowSelectionModel: rowSelectionModel,
3980
4765
  onRowSelectionModelChange: (newSelectionModel, details) => {
3981
- if (pagination && effectivePaginationMode != 'server') {
3982
- // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors
3983
- // to avoid stale apiRef pagination state.
3984
- const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3985
- const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3986
- const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3987
- const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref8 => {
4766
+ if (pagination && paginationMode != 'server') {
4767
+ const cbPageStart = paginationModel.page * paginationModel.pageSize;
4768
+ const cbPageEnd = cbPageStart + paginationModel.pageSize;
4769
+ const selectableRowsInPage = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).slice(cbPageStart, cbPageEnd).filter(_ref6 => {
3988
4770
  let {
3989
4771
  model
3990
- } = _ref8;
4772
+ } = _ref6;
3991
4773
  return isRowSelectable({
3992
4774
  row: model
3993
4775
  });
3994
- }).map(_ref9 => {
3995
- let {
3996
- id
3997
- } = _ref9;
3998
- return id;
3999
- }) : pageEntries.map(_ref10 => {
4776
+ }).map(_ref7 => {
4000
4777
  let {
4001
4778
  id
4002
- } = _ref10;
4779
+ } = _ref7;
4003
4780
  return id;
4004
- });
4781
+ }) : gridFilteredSortedRowIdsSelector(apiRef).slice(cbPageStart, cbPageEnd);
4005
4782
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4006
- const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref11 => {
4783
+ const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref8 => {
4007
4784
  let {
4008
4785
  model
4009
- } = _ref11;
4786
+ } = _ref8;
4010
4787
  return isRowSelectable({
4011
4788
  row: model
4012
4789
  });
4013
- }).map(_ref12 => {
4790
+ }).map(_ref9 => {
4014
4791
  let {
4015
4792
  id
4016
- } = _ref12;
4793
+ } = _ref9;
4017
4794
  return id;
4018
4795
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4019
4796
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4020
- const numberOfSelectedRows = getSelectionCount(newSelectionModel);
4797
+ const numberOfSelectedRows = newSelectionModel.length;
4021
4798
  if (selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable - numberOfSelectableRowsInPage || selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable || selectionStatusRef.current.type === 'page' && numberOfSelectedRows === numberOfSelectableRowsInPage) {
4022
4799
  setTimeout(() => {
4023
- var _apiRef$current2;
4024
- (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.selectRows([], true, true);
4800
+ apiRef.current.selectRows([], true, true);
4025
4801
  }, 0);
4026
4802
  }
4027
4803
  if (numberOfSelectedRows === numberOfSelectableRowsInPage && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
@@ -4063,5 +4839,5 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4063
4839
  StatefulDataGrid.className = CLASSNAME;
4064
4840
  StatefulDataGrid.displayName = COMPONENT_NAME;
4065
4841
 
4066
- 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 };
4842
+ 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, StatefulDataGrid as aA, 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, getDensityModel as as, getColumnOrderFromString as at, getSearchParamsFromColumnOrder as au, getSearchParamsFromVersion as av, getFinalSearch as aw, getModelsParsedOrUpdateLocalStorage as ax, updateUrl as ay, areFilterModelsEquivalent 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 };
4067
4843
  //# sourceMappingURL=StatefulDataGrid2.js.map