@redsift/table 12.5.2-muiv7 → 12.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1501 +1,18 @@
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';
4
5
  import classNames from 'classnames';
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 } from './useControlledDatagridState.js';
6
+ import { LicenseInfo } from '@mui/x-license';
7
+ import { Icon, useTheme, RedsiftColorBlueN, RedsiftColorNeutralXDarkGrey, RedsiftColorNeutralWhite, ThemeProvider } from '@redsift/design-system';
8
+ import { getGridNumericOperators as getGridNumericOperators$1, GridFilterInputValue, GridFilterInputSingleSelect, GridFilterInputMultipleValue, GridFilterInputMultipleSingleSelect, getGridStringOperators as getGridStringOperators$1, getGridBooleanOperators, getGridDateOperators, getGridSingleSelectOperators, GridLogicOperator, useGridApiRef, gridFilteredSortedRowEntriesSelector, gridFilteredSortedRowIdsSelector, DataGridPremium } from '@mui/x-data-grid-premium';
9
+ import { u as useControlledDatagridState, S as StyledDataGrid } from './useControlledDatagridState.js';
10
+ import Box from '@mui/material/Box';
11
+ import TextField from '@mui/material/TextField';
8
12
  import { mdiSync } from '@redsift/icons';
9
- import { 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, S as ServerSideControlledPagination, C as ControlledPagination } from './ControlledPagination.js';
12
13
  import { decompressFromEncodedURIComponent, compressToEncodedURIComponent } from 'lz-string';
13
- import { T as Toolbar } from './Toolbar2.js';
14
- import { B as BaseButton, a as BaseCheckbox, c as BasePopper, b as BaseIcon } from './BasePopper.js';
15
- import { T as ToolbarWrapper } from './ToolbarWrapper2.js';
16
-
17
- const splitProps = props => {
18
- const result = {
19
- systemProps: {},
20
- otherProps: {}
21
- };
22
- const config = props?.theme?.unstable_sxConfig ?? defaultSxConfig;
23
- Object.keys(props).forEach(prop => {
24
- if (config[prop]) {
25
- result.systemProps[prop] = props[prop];
26
- } else {
27
- result.otherProps[prop] = props[prop];
28
- }
29
- });
30
- return result;
31
- };
32
- function extendSxProp(props) {
33
- const {
34
- sx: inSx,
35
- ...other
36
- } = props;
37
- const {
38
- systemProps,
39
- otherProps
40
- } = splitProps(other);
41
- let finalSx;
42
- if (Array.isArray(inSx)) {
43
- finalSx = [systemProps, ...inSx];
44
- } else if (typeof inSx === 'function') {
45
- finalSx = (...args) => {
46
- const result = inSx(...args);
47
- if (!isPlainObject(result)) {
48
- return systemProps;
49
- }
50
- return {
51
- ...systemProps,
52
- ...result
53
- };
54
- };
55
- } else {
56
- finalSx = {
57
- ...systemProps,
58
- ...inSx
59
- };
60
- }
61
- return {
62
- ...otherProps,
63
- sx: finalSx
64
- };
65
- }
66
-
67
- function createBox(options = {}) {
68
- const {
69
- themeId,
70
- defaultTheme,
71
- defaultClassName = 'MuiBox-root',
72
- generateClassName
73
- } = options;
74
- const BoxRoot = styled('div', {
75
- shouldForwardProp: prop => prop !== 'theme' && prop !== 'sx' && prop !== 'as'
76
- })(styleFunctionSx);
77
- const Box = /*#__PURE__*/React.forwardRef(function Box(inProps, ref) {
78
- const theme = useTheme(defaultTheme);
79
- const {
80
- className,
81
- component = 'div',
82
- ...other
83
- } = extendSxProp(inProps);
84
- return /*#__PURE__*/jsxRuntimeExports.jsx(BoxRoot, {
85
- as: component,
86
- ref: ref,
87
- className: clsx(className, generateClassName ? generateClassName(defaultClassName) : defaultClassName),
88
- theme: themeId ? theme[themeId] || theme : theme,
89
- ...other
90
- });
91
- });
92
- return Box;
93
- }
94
-
95
- function isMuiElement(element, muiNames) {
96
- return /*#__PURE__*/React.isValidElement(element) && muiNames.indexOf(
97
- // For server components `muiName` is avaialble in element.type._payload.value.muiName
98
- // relevant info - https://github.com/facebook/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
99
- // eslint-disable-next-line no-underscore-dangle
100
- element.type.muiName ?? element.type?._payload?.value?.muiName) !== -1;
101
- }
102
-
103
- const boxClasses = generateUtilityClasses('MuiBox', ['root']);
104
- var boxClasses$1 = boxClasses;
105
-
106
- const defaultTheme = createTheme();
107
- const Box = createBox({
108
- themeId: THEME_ID,
109
- defaultTheme,
110
- defaultClassName: boxClasses$1.root,
111
- generateClassName: ClassNameGenerator.generate
112
- });
113
- process.env.NODE_ENV !== "production" ? Box.propTypes /* remove-proptypes */ = {
114
- // ┌────────────────────────────── Warning ──────────────────────────────┐
115
- // │ These PropTypes are generated from the TypeScript type definitions. │
116
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
117
- // └─────────────────────────────────────────────────────────────────────┘
118
- /**
119
- * @ignore
120
- */
121
- children: PropTypes.node,
122
- /**
123
- * The component used for the root node.
124
- * Either a string to use a HTML element or a component.
125
- */
126
- component: PropTypes.elementType,
127
- /**
128
- * The system prop that allows defining system overrides as well as additional CSS styles.
129
- */
130
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
131
- } : void 0;
132
- var Box$1 = Box;
133
-
134
- function getFormLabelUtilityClasses(slot) {
135
- return generateUtilityClass('MuiFormLabel', slot);
136
- }
137
- const formLabelClasses = generateUtilityClasses('MuiFormLabel', ['root', 'colorSecondary', 'focused', 'disabled', 'error', 'filled', 'required', 'asterisk']);
138
- var formLabelClasses$1 = formLabelClasses;
139
-
140
- const useUtilityClasses$4 = ownerState => {
141
- const {
142
- classes,
143
- color,
144
- focused,
145
- disabled,
146
- error,
147
- filled,
148
- required
149
- } = ownerState;
150
- const slots = {
151
- root: ['root', `color${capitalize(color)}`, disabled && 'disabled', error && 'error', filled && 'filled', focused && 'focused', required && 'required'],
152
- asterisk: ['asterisk', error && 'error']
153
- };
154
- return composeClasses(slots, getFormLabelUtilityClasses, classes);
155
- };
156
- const FormLabelRoot = styled$1('label', {
157
- name: 'MuiFormLabel',
158
- slot: 'Root',
159
- overridesResolver: (props, styles) => {
160
- const {
161
- ownerState
162
- } = props;
163
- return [styles.root, ownerState.color === 'secondary' && styles.colorSecondary, ownerState.filled && styles.filled];
164
- }
165
- })(memoTheme(({
166
- theme
167
- }) => ({
168
- color: (theme.vars || theme).palette.text.secondary,
169
- ...theme.typography.body1,
170
- lineHeight: '1.4375em',
171
- padding: 0,
172
- position: 'relative',
173
- variants: [...Object.entries(theme.palette).filter(createSimplePaletteValueFilter()).map(([color]) => ({
174
- props: {
175
- color
176
- },
177
- style: {
178
- [`&.${formLabelClasses$1.focused}`]: {
179
- color: (theme.vars || theme).palette[color].main
180
- }
181
- }
182
- })), {
183
- props: {},
184
- style: {
185
- [`&.${formLabelClasses$1.disabled}`]: {
186
- color: (theme.vars || theme).palette.text.disabled
187
- },
188
- [`&.${formLabelClasses$1.error}`]: {
189
- color: (theme.vars || theme).palette.error.main
190
- }
191
- }
192
- }]
193
- })));
194
- const AsteriskComponent = styled$1('span', {
195
- name: 'MuiFormLabel',
196
- slot: 'Asterisk',
197
- overridesResolver: (props, styles) => styles.asterisk
198
- })(memoTheme(({
199
- theme
200
- }) => ({
201
- [`&.${formLabelClasses$1.error}`]: {
202
- color: (theme.vars || theme).palette.error.main
203
- }
204
- })));
205
- const FormLabel = /*#__PURE__*/React.forwardRef(function FormLabel(inProps, ref) {
206
- const props = useDefaultProps({
207
- props: inProps,
208
- name: 'MuiFormLabel'
209
- });
210
- const {
211
- children,
212
- className,
213
- color,
214
- component = 'label',
215
- disabled,
216
- error,
217
- filled,
218
- focused,
219
- required,
220
- ...other
221
- } = props;
222
- const muiFormControl = useFormControl();
223
- const fcs = formControlState({
224
- props,
225
- muiFormControl,
226
- states: ['color', 'required', 'focused', 'disabled', 'error', 'filled']
227
- });
228
- const ownerState = {
229
- ...props,
230
- color: fcs.color || 'primary',
231
- component,
232
- disabled: fcs.disabled,
233
- error: fcs.error,
234
- filled: fcs.filled,
235
- focused: fcs.focused,
236
- required: fcs.required
237
- };
238
- const classes = useUtilityClasses$4(ownerState);
239
- return /*#__PURE__*/jsxRuntimeExports.jsxs(FormLabelRoot, {
240
- as: component,
241
- ownerState: ownerState,
242
- className: clsx(classes.root, className),
243
- ref: ref,
244
- ...other,
245
- children: [children, fcs.required && /*#__PURE__*/jsxRuntimeExports.jsxs(AsteriskComponent, {
246
- ownerState: ownerState,
247
- "aria-hidden": true,
248
- className: classes.asterisk,
249
- children: ["\u2009", '*']
250
- })]
251
- });
252
- });
253
- process.env.NODE_ENV !== "production" ? FormLabel.propTypes /* remove-proptypes */ = {
254
- // ┌────────────────────────────── Warning ──────────────────────────────┐
255
- // │ These PropTypes are generated from the TypeScript type definitions. │
256
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
257
- // └─────────────────────────────────────────────────────────────────────┘
258
- /**
259
- * The content of the component.
260
- */
261
- children: PropTypes.node,
262
- /**
263
- * Override or extend the styles applied to the component.
264
- */
265
- classes: PropTypes.object,
266
- /**
267
- * @ignore
268
- */
269
- className: PropTypes.string,
270
- /**
271
- * The color of the component.
272
- * It supports both default and custom theme colors, which can be added as shown in the
273
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
274
- */
275
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
276
- /**
277
- * The component used for the root node.
278
- * Either a string to use a HTML element or a component.
279
- */
280
- component: PropTypes.elementType,
281
- /**
282
- * If `true`, the label should be displayed in a disabled state.
283
- */
284
- disabled: PropTypes.bool,
285
- /**
286
- * If `true`, the label is displayed in an error state.
287
- */
288
- error: PropTypes.bool,
289
- /**
290
- * If `true`, the label should use filled classes key.
291
- */
292
- filled: PropTypes.bool,
293
- /**
294
- * If `true`, the input of this label is focused (used by `FormGroup` components).
295
- */
296
- focused: PropTypes.bool,
297
- /**
298
- * If `true`, the label will indicate that the `input` is required.
299
- */
300
- required: PropTypes.bool,
301
- /**
302
- * The system prop that allows defining system overrides as well as additional CSS styles.
303
- */
304
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
305
- } : void 0;
306
- var FormLabel$1 = FormLabel;
307
-
308
- function getInputLabelUtilityClasses(slot) {
309
- return generateUtilityClass('MuiInputLabel', slot);
310
- }
311
- generateUtilityClasses('MuiInputLabel', ['root', 'focused', 'disabled', 'error', 'required', 'asterisk', 'formControl', 'sizeSmall', 'shrink', 'animated', 'standard', 'filled', 'outlined']);
312
-
313
- const useUtilityClasses$3 = ownerState => {
314
- const {
315
- classes,
316
- formControl,
317
- size,
318
- shrink,
319
- disableAnimation,
320
- variant,
321
- required
322
- } = ownerState;
323
- const slots = {
324
- root: ['root', formControl && 'formControl', !disableAnimation && 'animated', shrink && 'shrink', size && size !== 'normal' && `size${capitalize(size)}`, variant],
325
- asterisk: [required && 'asterisk']
326
- };
327
- const composedClasses = composeClasses(slots, getInputLabelUtilityClasses, classes);
328
- return {
329
- ...classes,
330
- // forward the focused, disabled, etc. classes to the FormLabel
331
- ...composedClasses
332
- };
333
- };
334
- const InputLabelRoot = styled$1(FormLabel$1, {
335
- shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
336
- name: 'MuiInputLabel',
337
- slot: 'Root',
338
- overridesResolver: (props, styles) => {
339
- const {
340
- ownerState
341
- } = props;
342
- return [{
343
- [`& .${formLabelClasses$1.asterisk}`]: styles.asterisk
344
- }, 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]];
345
- }
346
- })(memoTheme(({
347
- theme
348
- }) => ({
349
- display: 'block',
350
- transformOrigin: 'top left',
351
- whiteSpace: 'nowrap',
352
- overflow: 'hidden',
353
- textOverflow: 'ellipsis',
354
- maxWidth: '100%',
355
- variants: [{
356
- props: ({
357
- ownerState
358
- }) => ownerState.formControl,
359
- style: {
360
- position: 'absolute',
361
- left: 0,
362
- top: 0,
363
- // slight alteration to spec spacing to match visual spec result
364
- transform: 'translate(0, 20px) scale(1)'
365
- }
366
- }, {
367
- props: {
368
- size: 'small'
369
- },
370
- style: {
371
- // Compensation for the `Input.inputSizeSmall` style.
372
- transform: 'translate(0, 17px) scale(1)'
373
- }
374
- }, {
375
- props: ({
376
- ownerState
377
- }) => ownerState.shrink,
378
- style: {
379
- transform: 'translate(0, -1.5px) scale(0.75)',
380
- transformOrigin: 'top left',
381
- maxWidth: '133%'
382
- }
383
- }, {
384
- props: ({
385
- ownerState
386
- }) => !ownerState.disableAnimation,
387
- style: {
388
- transition: theme.transitions.create(['color', 'transform', 'max-width'], {
389
- duration: theme.transitions.duration.shorter,
390
- easing: theme.transitions.easing.easeOut
391
- })
392
- }
393
- }, {
394
- props: {
395
- variant: 'filled'
396
- },
397
- style: {
398
- // Chrome's autofill feature gives the input field a yellow background.
399
- // Since the input field is behind the label in the HTML tree,
400
- // the input field is drawn last and hides the label with an opaque background color.
401
- // zIndex: 1 will raise the label above opaque background-colors of input.
402
- zIndex: 1,
403
- pointerEvents: 'none',
404
- transform: 'translate(12px, 16px) scale(1)',
405
- maxWidth: 'calc(100% - 24px)'
406
- }
407
- }, {
408
- props: {
409
- variant: 'filled',
410
- size: 'small'
411
- },
412
- style: {
413
- transform: 'translate(12px, 13px) scale(1)'
414
- }
415
- }, {
416
- props: ({
417
- variant,
418
- ownerState
419
- }) => variant === 'filled' && ownerState.shrink,
420
- style: {
421
- userSelect: 'none',
422
- pointerEvents: 'auto',
423
- transform: 'translate(12px, 7px) scale(0.75)',
424
- maxWidth: 'calc(133% - 24px)'
425
- }
426
- }, {
427
- props: ({
428
- variant,
429
- ownerState,
430
- size
431
- }) => variant === 'filled' && ownerState.shrink && size === 'small',
432
- style: {
433
- transform: 'translate(12px, 4px) scale(0.75)'
434
- }
435
- }, {
436
- props: {
437
- variant: 'outlined'
438
- },
439
- style: {
440
- // see comment above on filled.zIndex
441
- zIndex: 1,
442
- pointerEvents: 'none',
443
- transform: 'translate(14px, 16px) scale(1)',
444
- maxWidth: 'calc(100% - 24px)'
445
- }
446
- }, {
447
- props: {
448
- variant: 'outlined',
449
- size: 'small'
450
- },
451
- style: {
452
- transform: 'translate(14px, 9px) scale(1)'
453
- }
454
- }, {
455
- props: ({
456
- variant,
457
- ownerState
458
- }) => variant === 'outlined' && ownerState.shrink,
459
- style: {
460
- userSelect: 'none',
461
- pointerEvents: 'auto',
462
- // Theoretically, we should have (8+5)*2/0.75 = 34px
463
- // but it feels a better when it bleeds a bit on the left, so 32px.
464
- maxWidth: 'calc(133% - 32px)',
465
- transform: 'translate(14px, -9px) scale(0.75)'
466
- }
467
- }]
468
- })));
469
- const InputLabel = /*#__PURE__*/React.forwardRef(function InputLabel(inProps, ref) {
470
- const props = useDefaultProps({
471
- name: 'MuiInputLabel',
472
- props: inProps
473
- });
474
- const {
475
- disableAnimation = false,
476
- margin,
477
- shrink: shrinkProp,
478
- variant,
479
- className,
480
- ...other
481
- } = props;
482
- const muiFormControl = useFormControl();
483
- let shrink = shrinkProp;
484
- if (typeof shrink === 'undefined' && muiFormControl) {
485
- shrink = muiFormControl.filled || muiFormControl.focused || muiFormControl.adornedStart;
486
- }
487
- const fcs = formControlState({
488
- props,
489
- muiFormControl,
490
- states: ['size', 'variant', 'required', 'focused']
491
- });
492
- const ownerState = {
493
- ...props,
494
- disableAnimation,
495
- formControl: muiFormControl,
496
- shrink,
497
- size: fcs.size,
498
- variant: fcs.variant,
499
- required: fcs.required,
500
- focused: fcs.focused
501
- };
502
- const classes = useUtilityClasses$3(ownerState);
503
- return /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelRoot, {
504
- "data-shrink": shrink,
505
- ref: ref,
506
- className: clsx(classes.root, className),
507
- ...other,
508
- ownerState: ownerState,
509
- classes: classes
510
- });
511
- });
512
- process.env.NODE_ENV !== "production" ? InputLabel.propTypes /* remove-proptypes */ = {
513
- // ┌────────────────────────────── Warning ──────────────────────────────┐
514
- // │ These PropTypes are generated from the TypeScript type definitions. │
515
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
516
- // └─────────────────────────────────────────────────────────────────────┘
517
- /**
518
- * The content of the component.
519
- */
520
- children: PropTypes.node,
521
- /**
522
- * Override or extend the styles applied to the component.
523
- */
524
- classes: PropTypes.object,
525
- /**
526
- * @ignore
527
- */
528
- className: PropTypes.string,
529
- /**
530
- * The color of the component.
531
- * It supports both default and custom theme colors, which can be added as shown in the
532
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
533
- */
534
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['error', 'info', 'primary', 'secondary', 'success', 'warning']), PropTypes.string]),
535
- /**
536
- * If `true`, the transition animation is disabled.
537
- * @default false
538
- */
539
- disableAnimation: PropTypes.bool,
540
- /**
541
- * If `true`, the component is disabled.
542
- */
543
- disabled: PropTypes.bool,
544
- /**
545
- * If `true`, the label is displayed in an error state.
546
- */
547
- error: PropTypes.bool,
548
- /**
549
- * If `true`, the `input` of this label is focused.
550
- */
551
- focused: PropTypes.bool,
552
- /**
553
- * If `dense`, will adjust vertical spacing. This is normally obtained via context from
554
- * FormControl.
555
- */
556
- margin: PropTypes.oneOf(['dense']),
557
- /**
558
- * if `true`, the label will indicate that the `input` is required.
559
- */
560
- required: PropTypes.bool,
561
- /**
562
- * If `true`, the label is shrunk.
563
- */
564
- shrink: PropTypes.bool,
565
- /**
566
- * The size of the component.
567
- * @default 'normal'
568
- */
569
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['normal', 'small']), PropTypes.string]),
570
- /**
571
- * The system prop that allows defining system overrides as well as additional CSS styles.
572
- */
573
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
574
- /**
575
- * The variant to use.
576
- */
577
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
578
- } : void 0;
579
- var InputLabel$1 = InputLabel;
580
-
581
- function getFormControlUtilityClasses(slot) {
582
- return generateUtilityClass('MuiFormControl', slot);
583
- }
584
- generateUtilityClasses('MuiFormControl', ['root', 'marginNone', 'marginNormal', 'marginDense', 'fullWidth', 'disabled']);
585
-
586
- const useUtilityClasses$2 = ownerState => {
587
- const {
588
- classes,
589
- margin,
590
- fullWidth
591
- } = ownerState;
592
- const slots = {
593
- root: ['root', margin !== 'none' && `margin${capitalize(margin)}`, fullWidth && 'fullWidth']
594
- };
595
- return composeClasses(slots, getFormControlUtilityClasses, classes);
596
- };
597
- const FormControlRoot = styled$1('div', {
598
- name: 'MuiFormControl',
599
- slot: 'Root',
600
- overridesResolver: (props, styles) => {
601
- const {
602
- ownerState
603
- } = props;
604
- return [styles.root, styles[`margin${capitalize(ownerState.margin)}`], ownerState.fullWidth && styles.fullWidth];
605
- }
606
- })({
607
- display: 'inline-flex',
608
- flexDirection: 'column',
609
- position: 'relative',
610
- // Reset fieldset default style.
611
- minWidth: 0,
612
- padding: 0,
613
- margin: 0,
614
- border: 0,
615
- verticalAlign: 'top',
616
- // Fix alignment issue on Safari.
617
- variants: [{
618
- props: {
619
- margin: 'normal'
620
- },
621
- style: {
622
- marginTop: 16,
623
- marginBottom: 8
624
- }
625
- }, {
626
- props: {
627
- margin: 'dense'
628
- },
629
- style: {
630
- marginTop: 8,
631
- marginBottom: 4
632
- }
633
- }, {
634
- props: {
635
- fullWidth: true
636
- },
637
- style: {
638
- width: '100%'
639
- }
640
- }]
641
- });
642
-
643
- /**
644
- * Provides context such as filled/focused/error/required for form inputs.
645
- * Relying on the context provides high flexibility and ensures that the state always stays
646
- * consistent across the children of the `FormControl`.
647
- * This context is used by the following components:
648
- *
649
- * - FormLabel
650
- * - FormHelperText
651
- * - Input
652
- * - InputLabel
653
- *
654
- * You can find one composition example below and more going to [the demos](/material-ui/react-text-field/#components).
655
- *
656
- * ```jsx
657
- * <FormControl>
658
- * <InputLabel htmlFor="my-input">Email address</InputLabel>
659
- * <Input id="my-input" aria-describedby="my-helper-text" />
660
- * <FormHelperText id="my-helper-text">We'll never share your email.</FormHelperText>
661
- * </FormControl>
662
- * ```
663
- *
664
- * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies.
665
- * For instance, only one input can be focused at the same time, the state shouldn't be shared.
666
- */
667
- const FormControl = /*#__PURE__*/React.forwardRef(function FormControl(inProps, ref) {
668
- const props = useDefaultProps({
669
- props: inProps,
670
- name: 'MuiFormControl'
671
- });
672
- const {
673
- children,
674
- className,
675
- color = 'primary',
676
- component = 'div',
677
- disabled = false,
678
- error = false,
679
- focused: visuallyFocused,
680
- fullWidth = false,
681
- hiddenLabel = false,
682
- margin = 'none',
683
- required = false,
684
- size = 'medium',
685
- variant = 'outlined',
686
- ...other
687
- } = props;
688
- const ownerState = {
689
- ...props,
690
- color,
691
- component,
692
- disabled,
693
- error,
694
- fullWidth,
695
- hiddenLabel,
696
- margin,
697
- required,
698
- size,
699
- variant
700
- };
701
- const classes = useUtilityClasses$2(ownerState);
702
- const [adornedStart, setAdornedStart] = React.useState(() => {
703
- // We need to iterate through the children and find the Input in order
704
- // to fully support server-side rendering.
705
- let initialAdornedStart = false;
706
- if (children) {
707
- React.Children.forEach(children, child => {
708
- if (!isMuiElement(child, ['Input', 'Select'])) {
709
- return;
710
- }
711
- const input = isMuiElement(child, ['Select']) ? child.props.input : child;
712
- if (input && isAdornedStart(input.props)) {
713
- initialAdornedStart = true;
714
- }
715
- });
716
- }
717
- return initialAdornedStart;
718
- });
719
- const [filled, setFilled] = React.useState(() => {
720
- // We need to iterate through the children and find the Input in order
721
- // to fully support server-side rendering.
722
- let initialFilled = false;
723
- if (children) {
724
- React.Children.forEach(children, child => {
725
- if (!isMuiElement(child, ['Input', 'Select'])) {
726
- return;
727
- }
728
- if (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) {
729
- initialFilled = true;
730
- }
731
- });
732
- }
733
- return initialFilled;
734
- });
735
- const [focusedState, setFocused] = React.useState(false);
736
- if (disabled && focusedState) {
737
- setFocused(false);
738
- }
739
- const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState;
740
- let registerEffect;
741
- const registeredInput = React.useRef(false);
742
- if (process.env.NODE_ENV !== 'production') {
743
- registerEffect = () => {
744
- if (registeredInput.current) {
745
- console.error(['MUI: There are multiple `InputBase` components inside a FormControl.', 'This creates visual inconsistencies, only use one `InputBase`.'].join('\n'));
746
- }
747
- registeredInput.current = true;
748
- return () => {
749
- registeredInput.current = false;
750
- };
751
- };
752
- }
753
- const onFilled = React.useCallback(() => {
754
- setFilled(true);
755
- }, []);
756
- const onEmpty = React.useCallback(() => {
757
- setFilled(false);
758
- }, []);
759
- const childContext = React.useMemo(() => {
760
- return {
761
- adornedStart,
762
- setAdornedStart,
763
- color,
764
- disabled,
765
- error,
766
- filled,
767
- focused,
768
- fullWidth,
769
- hiddenLabel,
770
- size,
771
- onBlur: () => {
772
- setFocused(false);
773
- },
774
- onFocus: () => {
775
- setFocused(true);
776
- },
777
- onEmpty,
778
- onFilled,
779
- registerEffect,
780
- required,
781
- variant
782
- };
783
- }, [adornedStart, color, disabled, error, filled, focused, fullWidth, hiddenLabel, registerEffect, onEmpty, onFilled, required, size, variant]);
784
- return /*#__PURE__*/jsxRuntimeExports.jsx(FormControlContext.Provider, {
785
- value: childContext,
786
- children: /*#__PURE__*/jsxRuntimeExports.jsx(FormControlRoot, {
787
- as: component,
788
- ownerState: ownerState,
789
- className: clsx(classes.root, className),
790
- ref: ref,
791
- ...other,
792
- children: children
793
- })
794
- });
795
- });
796
- process.env.NODE_ENV !== "production" ? FormControl.propTypes /* remove-proptypes */ = {
797
- // ┌────────────────────────────── Warning ──────────────────────────────┐
798
- // │ These PropTypes are generated from the TypeScript type definitions. │
799
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
800
- // └─────────────────────────────────────────────────────────────────────┘
801
- /**
802
- * The content of the component.
803
- */
804
- children: PropTypes.node,
805
- /**
806
- * Override or extend the styles applied to the component.
807
- */
808
- classes: PropTypes.object,
809
- /**
810
- * @ignore
811
- */
812
- className: PropTypes.string,
813
- /**
814
- * The color of the component.
815
- * It supports both default and custom theme colors, which can be added as shown in the
816
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
817
- * @default 'primary'
818
- */
819
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
820
- /**
821
- * The component used for the root node.
822
- * Either a string to use a HTML element or a component.
823
- */
824
- component: PropTypes.elementType,
825
- /**
826
- * If `true`, the label, input and helper text should be displayed in a disabled state.
827
- * @default false
828
- */
829
- disabled: PropTypes.bool,
830
- /**
831
- * If `true`, the label is displayed in an error state.
832
- * @default false
833
- */
834
- error: PropTypes.bool,
835
- /**
836
- * If `true`, the component is displayed in focused state.
837
- */
838
- focused: PropTypes.bool,
839
- /**
840
- * If `true`, the component will take up the full width of its container.
841
- * @default false
842
- */
843
- fullWidth: PropTypes.bool,
844
- /**
845
- * If `true`, the label is hidden.
846
- * This is used to increase density for a `FilledInput`.
847
- * Be sure to add `aria-label` to the `input` element.
848
- * @default false
849
- */
850
- hiddenLabel: PropTypes.bool,
851
- /**
852
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
853
- * @default 'none'
854
- */
855
- margin: PropTypes.oneOf(['dense', 'none', 'normal']),
856
- /**
857
- * If `true`, the label will indicate that the `input` is required.
858
- * @default false
859
- */
860
- required: PropTypes.bool,
861
- /**
862
- * The size of the component.
863
- * @default 'medium'
864
- */
865
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
866
- /**
867
- * The system prop that allows defining system overrides as well as additional CSS styles.
868
- */
869
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
870
- /**
871
- * The variant to use.
872
- * @default 'outlined'
873
- */
874
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
875
- } : void 0;
876
- var FormControl$1 = FormControl;
877
-
878
- function getFormHelperTextUtilityClasses(slot) {
879
- return generateUtilityClass('MuiFormHelperText', slot);
880
- }
881
- const formHelperTextClasses = generateUtilityClasses('MuiFormHelperText', ['root', 'error', 'disabled', 'sizeSmall', 'sizeMedium', 'contained', 'focused', 'filled', 'required']);
882
- var formHelperTextClasses$1 = formHelperTextClasses;
883
-
884
- var _span;
885
- const useUtilityClasses$1 = ownerState => {
886
- const {
887
- classes,
888
- contained,
889
- size,
890
- disabled,
891
- error,
892
- filled,
893
- focused,
894
- required
895
- } = ownerState;
896
- const slots = {
897
- root: ['root', disabled && 'disabled', error && 'error', size && `size${capitalize(size)}`, contained && 'contained', focused && 'focused', filled && 'filled', required && 'required']
898
- };
899
- return composeClasses(slots, getFormHelperTextUtilityClasses, classes);
900
- };
901
- const FormHelperTextRoot = styled$1('p', {
902
- name: 'MuiFormHelperText',
903
- slot: 'Root',
904
- overridesResolver: (props, styles) => {
905
- const {
906
- ownerState
907
- } = props;
908
- return [styles.root, ownerState.size && styles[`size${capitalize(ownerState.size)}`], ownerState.contained && styles.contained, ownerState.filled && styles.filled];
909
- }
910
- })(memoTheme(({
911
- theme
912
- }) => ({
913
- color: (theme.vars || theme).palette.text.secondary,
914
- ...theme.typography.caption,
915
- textAlign: 'left',
916
- marginTop: 3,
917
- marginRight: 0,
918
- marginBottom: 0,
919
- marginLeft: 0,
920
- [`&.${formHelperTextClasses$1.disabled}`]: {
921
- color: (theme.vars || theme).palette.text.disabled
922
- },
923
- [`&.${formHelperTextClasses$1.error}`]: {
924
- color: (theme.vars || theme).palette.error.main
925
- },
926
- variants: [{
927
- props: {
928
- size: 'small'
929
- },
930
- style: {
931
- marginTop: 4
932
- }
933
- }, {
934
- props: ({
935
- ownerState
936
- }) => ownerState.contained,
937
- style: {
938
- marginLeft: 14,
939
- marginRight: 14
940
- }
941
- }]
942
- })));
943
- const FormHelperText = /*#__PURE__*/React.forwardRef(function FormHelperText(inProps, ref) {
944
- const props = useDefaultProps({
945
- props: inProps,
946
- name: 'MuiFormHelperText'
947
- });
948
- const {
949
- children,
950
- className,
951
- component = 'p',
952
- disabled,
953
- error,
954
- filled,
955
- focused,
956
- margin,
957
- required,
958
- variant,
959
- ...other
960
- } = props;
961
- const muiFormControl = useFormControl();
962
- const fcs = formControlState({
963
- props,
964
- muiFormControl,
965
- states: ['variant', 'size', 'disabled', 'error', 'filled', 'focused', 'required']
966
- });
967
- const ownerState = {
968
- ...props,
969
- component,
970
- contained: fcs.variant === 'filled' || fcs.variant === 'outlined',
971
- variant: fcs.variant,
972
- size: fcs.size,
973
- disabled: fcs.disabled,
974
- error: fcs.error,
975
- filled: fcs.filled,
976
- focused: fcs.focused,
977
- required: fcs.required
978
- };
979
-
980
- // This issue explains why this is required: https://github.com/mui/material-ui/issues/42184
981
- delete ownerState.ownerState;
982
- const classes = useUtilityClasses$1(ownerState);
983
- return /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextRoot, {
984
- as: component,
985
- className: clsx(classes.root, className),
986
- ref: ref,
987
- ...other,
988
- ownerState: ownerState,
989
- children: children === ' ' ? // notranslate needed while Google Translate will not fix zero-width space issue
990
- _span || (_span = /*#__PURE__*/jsxRuntimeExports.jsx("span", {
991
- className: "notranslate",
992
- "aria-hidden": true,
993
- children: "\u200B"
994
- })) : children
995
- });
996
- });
997
- process.env.NODE_ENV !== "production" ? FormHelperText.propTypes /* remove-proptypes */ = {
998
- // ┌────────────────────────────── Warning ──────────────────────────────┐
999
- // │ These PropTypes are generated from the TypeScript type definitions. │
1000
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
1001
- // └─────────────────────────────────────────────────────────────────────┘
1002
- /**
1003
- * The content of the component.
1004
- *
1005
- * If `' '` is provided, the component reserves one line height for displaying a future message.
1006
- */
1007
- children: PropTypes.node,
1008
- /**
1009
- * Override or extend the styles applied to the component.
1010
- */
1011
- classes: PropTypes.object,
1012
- /**
1013
- * @ignore
1014
- */
1015
- className: PropTypes.string,
1016
- /**
1017
- * The component used for the root node.
1018
- * Either a string to use a HTML element or a component.
1019
- */
1020
- component: PropTypes.elementType,
1021
- /**
1022
- * If `true`, the helper text should be displayed in a disabled state.
1023
- */
1024
- disabled: PropTypes.bool,
1025
- /**
1026
- * If `true`, helper text should be displayed in an error state.
1027
- */
1028
- error: PropTypes.bool,
1029
- /**
1030
- * If `true`, the helper text should use filled classes key.
1031
- */
1032
- filled: PropTypes.bool,
1033
- /**
1034
- * If `true`, the helper text should use focused classes key.
1035
- */
1036
- focused: PropTypes.bool,
1037
- /**
1038
- * If `dense`, will adjust vertical spacing. This is normally obtained via context from
1039
- * FormControl.
1040
- */
1041
- margin: PropTypes.oneOf(['dense']),
1042
- /**
1043
- * If `true`, the helper text should use required classes key.
1044
- */
1045
- required: PropTypes.bool,
1046
- /**
1047
- * The system prop that allows defining system overrides as well as additional CSS styles.
1048
- */
1049
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1050
- /**
1051
- * The variant to use.
1052
- */
1053
- variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['filled', 'outlined', 'standard']), PropTypes.string])
1054
- } : void 0;
1055
- var FormHelperText$1 = FormHelperText;
1056
-
1057
- function getTextFieldUtilityClass(slot) {
1058
- return generateUtilityClass('MuiTextField', slot);
1059
- }
1060
- generateUtilityClasses('MuiTextField', ['root']);
1061
-
1062
- const variantComponent = {
1063
- standard: Input,
1064
- filled: FilledInput,
1065
- outlined: OutlinedInput
1066
- };
1067
- const useUtilityClasses = ownerState => {
1068
- const {
1069
- classes
1070
- } = ownerState;
1071
- const slots = {
1072
- root: ['root']
1073
- };
1074
- return composeClasses(slots, getTextFieldUtilityClass, classes);
1075
- };
1076
- const TextFieldRoot = styled$1(FormControl$1, {
1077
- name: 'MuiTextField',
1078
- slot: 'Root',
1079
- overridesResolver: (props, styles) => styles.root
1080
- })({});
1081
-
1082
- /**
1083
- * The `TextField` is a convenience wrapper for the most common cases (80%).
1084
- * It cannot be all things to all people, otherwise the API would grow out of control.
1085
- *
1086
- * ## Advanced Configuration
1087
- *
1088
- * It's important to understand that the text field is a simple abstraction
1089
- * on top of the following components:
1090
- *
1091
- * - [FormControl](/material-ui/api/form-control/)
1092
- * - [InputLabel](/material-ui/api/input-label/)
1093
- * - [FilledInput](/material-ui/api/filled-input/)
1094
- * - [OutlinedInput](/material-ui/api/outlined-input/)
1095
- * - [Input](/material-ui/api/input/)
1096
- * - [FormHelperText](/material-ui/api/form-helper-text/)
1097
- *
1098
- * If you wish to alter the props applied to the `input` element, you can do so as follows:
1099
- *
1100
- * ```jsx
1101
- * const inputProps = {
1102
- * step: 300,
1103
- * };
1104
- *
1105
- * return <TextField id="time" type="time" inputProps={inputProps} />;
1106
- * ```
1107
- *
1108
- * For advanced cases, please look at the source of TextField by clicking on the
1109
- * "Edit this page" button above. Consider either:
1110
- *
1111
- * - using the upper case props for passing values directly to the components
1112
- * - using the underlying components directly as shown in the demos
1113
- */
1114
- const TextField = /*#__PURE__*/React.forwardRef(function TextField(inProps, ref) {
1115
- const props = useDefaultProps({
1116
- props: inProps,
1117
- name: 'MuiTextField'
1118
- });
1119
- const {
1120
- autoComplete,
1121
- autoFocus = false,
1122
- children,
1123
- className,
1124
- color = 'primary',
1125
- defaultValue,
1126
- disabled = false,
1127
- error = false,
1128
- FormHelperTextProps: FormHelperTextPropsProp,
1129
- fullWidth = false,
1130
- helperText,
1131
- id: idOverride,
1132
- InputLabelProps: InputLabelPropsProp,
1133
- inputProps: inputPropsProp,
1134
- InputProps: InputPropsProp,
1135
- inputRef,
1136
- label,
1137
- maxRows,
1138
- minRows,
1139
- multiline = false,
1140
- name,
1141
- onBlur,
1142
- onChange,
1143
- onFocus,
1144
- placeholder,
1145
- required = false,
1146
- rows,
1147
- select = false,
1148
- SelectProps: SelectPropsProp,
1149
- slots = {},
1150
- slotProps = {},
1151
- type,
1152
- value,
1153
- variant = 'outlined',
1154
- ...other
1155
- } = props;
1156
- const ownerState = {
1157
- ...props,
1158
- autoFocus,
1159
- color,
1160
- disabled,
1161
- error,
1162
- fullWidth,
1163
- multiline,
1164
- required,
1165
- select,
1166
- variant
1167
- };
1168
- const classes = useUtilityClasses(ownerState);
1169
- if (process.env.NODE_ENV !== 'production') {
1170
- if (select && !children) {
1171
- console.error('MUI: `children` must be passed when using the `TextField` component with `select`.');
1172
- }
1173
- }
1174
- const id = useId(idOverride);
1175
- const helperTextId = helperText && id ? `${id}-helper-text` : undefined;
1176
- const inputLabelId = label && id ? `${id}-label` : undefined;
1177
- const InputComponent = variantComponent[variant];
1178
- const externalForwardedProps = {
1179
- slots,
1180
- slotProps: {
1181
- input: InputPropsProp,
1182
- inputLabel: InputLabelPropsProp,
1183
- htmlInput: inputPropsProp,
1184
- formHelperText: FormHelperTextPropsProp,
1185
- select: SelectPropsProp,
1186
- ...slotProps
1187
- }
1188
- };
1189
- const inputAdditionalProps = {};
1190
- const inputLabelSlotProps = externalForwardedProps.slotProps.inputLabel;
1191
- if (variant === 'outlined') {
1192
- if (inputLabelSlotProps && typeof inputLabelSlotProps.shrink !== 'undefined') {
1193
- inputAdditionalProps.notched = inputLabelSlotProps.shrink;
1194
- }
1195
- inputAdditionalProps.label = label;
1196
- }
1197
- if (select) {
1198
- // unset defaults from textbox inputs
1199
- if (!SelectPropsProp || !SelectPropsProp.native) {
1200
- inputAdditionalProps.id = undefined;
1201
- }
1202
- inputAdditionalProps['aria-describedby'] = undefined;
1203
- }
1204
- const [RootSlot, rootProps] = useSlot('root', {
1205
- elementType: TextFieldRoot,
1206
- shouldForwardComponentProp: true,
1207
- externalForwardedProps: {
1208
- ...externalForwardedProps,
1209
- ...other
1210
- },
1211
- ownerState,
1212
- className: clsx(classes.root, className),
1213
- ref,
1214
- additionalProps: {
1215
- disabled,
1216
- error,
1217
- fullWidth,
1218
- required,
1219
- color,
1220
- variant
1221
- }
1222
- });
1223
- const [InputSlot, inputProps] = useSlot('input', {
1224
- elementType: InputComponent,
1225
- externalForwardedProps,
1226
- additionalProps: inputAdditionalProps,
1227
- ownerState
1228
- });
1229
- const [InputLabelSlot, inputLabelProps] = useSlot('inputLabel', {
1230
- elementType: InputLabel$1,
1231
- externalForwardedProps,
1232
- ownerState
1233
- });
1234
- const [HtmlInputSlot, htmlInputProps] = useSlot('htmlInput', {
1235
- elementType: 'input',
1236
- externalForwardedProps,
1237
- ownerState
1238
- });
1239
- const [FormHelperTextSlot, formHelperTextProps] = useSlot('formHelperText', {
1240
- elementType: FormHelperText$1,
1241
- externalForwardedProps,
1242
- ownerState
1243
- });
1244
- const [SelectSlot, selectProps] = useSlot('select', {
1245
- elementType: Select,
1246
- externalForwardedProps,
1247
- ownerState
1248
- });
1249
- const InputElement = /*#__PURE__*/jsxRuntimeExports.jsx(InputSlot, {
1250
- "aria-describedby": helperTextId,
1251
- autoComplete: autoComplete,
1252
- autoFocus: autoFocus,
1253
- defaultValue: defaultValue,
1254
- fullWidth: fullWidth,
1255
- multiline: multiline,
1256
- name: name,
1257
- rows: rows,
1258
- maxRows: maxRows,
1259
- minRows: minRows,
1260
- type: type,
1261
- value: value,
1262
- id: id,
1263
- inputRef: inputRef,
1264
- onBlur: onBlur,
1265
- onChange: onChange,
1266
- onFocus: onFocus,
1267
- placeholder: placeholder,
1268
- inputProps: htmlInputProps,
1269
- slots: {
1270
- input: slots.htmlInput ? HtmlInputSlot : undefined
1271
- },
1272
- ...inputProps
1273
- });
1274
- return /*#__PURE__*/jsxRuntimeExports.jsxs(RootSlot, {
1275
- ...rootProps,
1276
- children: [label != null && label !== '' && /*#__PURE__*/jsxRuntimeExports.jsx(InputLabelSlot, {
1277
- htmlFor: id,
1278
- id: inputLabelId,
1279
- ...inputLabelProps,
1280
- children: label
1281
- }), select ? /*#__PURE__*/jsxRuntimeExports.jsx(SelectSlot, {
1282
- "aria-describedby": helperTextId,
1283
- id: id,
1284
- labelId: inputLabelId,
1285
- value: value,
1286
- input: InputElement,
1287
- ...selectProps,
1288
- children: children
1289
- }) : InputElement, helperText && /*#__PURE__*/jsxRuntimeExports.jsx(FormHelperTextSlot, {
1290
- id: helperTextId,
1291
- ...formHelperTextProps,
1292
- children: helperText
1293
- })]
1294
- });
1295
- });
1296
- process.env.NODE_ENV !== "production" ? TextField.propTypes /* remove-proptypes */ = {
1297
- // ┌────────────────────────────── Warning ──────────────────────────────┐
1298
- // │ These PropTypes are generated from the TypeScript type definitions. │
1299
- // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
1300
- // └─────────────────────────────────────────────────────────────────────┘
1301
- /**
1302
- * This prop helps users to fill forms faster, especially on mobile devices.
1303
- * The name can be confusing, as it's more like an autofill.
1304
- * You can learn more about it [following the specification](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill).
1305
- */
1306
- autoComplete: PropTypes.string,
1307
- /**
1308
- * If `true`, the `input` element is focused during the first mount.
1309
- * @default false
1310
- */
1311
- autoFocus: PropTypes.bool,
1312
- /**
1313
- * @ignore
1314
- */
1315
- children: PropTypes.node,
1316
- /**
1317
- * Override or extend the styles applied to the component.
1318
- */
1319
- classes: PropTypes.object,
1320
- /**
1321
- * @ignore
1322
- */
1323
- className: PropTypes.string,
1324
- /**
1325
- * The color of the component.
1326
- * It supports both default and custom theme colors, which can be added as shown in the
1327
- * [palette customization guide](https://mui.com/material-ui/customization/palette/#custom-colors).
1328
- * @default 'primary'
1329
- */
1330
- color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string]),
1331
- /**
1332
- * The default value. Use when the component is not controlled.
1333
- */
1334
- defaultValue: PropTypes.any,
1335
- /**
1336
- * If `true`, the component is disabled.
1337
- * @default false
1338
- */
1339
- disabled: PropTypes.bool,
1340
- /**
1341
- * If `true`, the label is displayed in an error state.
1342
- * @default false
1343
- */
1344
- error: PropTypes.bool,
1345
- /**
1346
- * Props applied to the [`FormHelperText`](https://mui.com/material-ui/api/form-helper-text/) element.
1347
- * @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.
1348
- */
1349
- FormHelperTextProps: PropTypes.object,
1350
- /**
1351
- * If `true`, the input will take up the full width of its container.
1352
- * @default false
1353
- */
1354
- fullWidth: PropTypes.bool,
1355
- /**
1356
- * The helper text content.
1357
- */
1358
- helperText: PropTypes.node,
1359
- /**
1360
- * The id of the `input` element.
1361
- * Use this prop to make `label` and `helperText` accessible for screen readers.
1362
- */
1363
- id: PropTypes.string,
1364
- /**
1365
- * Props applied to the [`InputLabel`](https://mui.com/material-ui/api/input-label/) element.
1366
- * Pointer events like `onClick` are enabled if and only if `shrink` is `true`.
1367
- * @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.
1368
- */
1369
- InputLabelProps: PropTypes.object,
1370
- /**
1371
- * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
1372
- * @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.
1373
- */
1374
- inputProps: PropTypes.object,
1375
- /**
1376
- * Props applied to the Input element.
1377
- * It will be a [`FilledInput`](https://mui.com/material-ui/api/filled-input/),
1378
- * [`OutlinedInput`](https://mui.com/material-ui/api/outlined-input/) or [`Input`](https://mui.com/material-ui/api/input/)
1379
- * component depending on the `variant` prop value.
1380
- * @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.
1381
- */
1382
- InputProps: PropTypes.object,
1383
- /**
1384
- * Pass a ref to the `input` element.
1385
- */
1386
- inputRef: refType,
1387
- /**
1388
- * The label content.
1389
- */
1390
- label: PropTypes.node,
1391
- /**
1392
- * If `dense` or `normal`, will adjust vertical spacing of this and contained components.
1393
- * @default 'none'
1394
- */
1395
- margin: PropTypes.oneOf(['dense', 'none', 'normal']),
1396
- /**
1397
- * Maximum number of rows to display when multiline option is set to true.
1398
- */
1399
- maxRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1400
- /**
1401
- * Minimum number of rows to display when multiline option is set to true.
1402
- */
1403
- minRows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1404
- /**
1405
- * If `true`, a `textarea` element is rendered instead of an input.
1406
- * @default false
1407
- */
1408
- multiline: PropTypes.bool,
1409
- /**
1410
- * Name attribute of the `input` element.
1411
- */
1412
- name: PropTypes.string,
1413
- /**
1414
- * @ignore
1415
- */
1416
- onBlur: PropTypes.func,
1417
- /**
1418
- * Callback fired when the value is changed.
1419
- *
1420
- * @param {object} event The event source of the callback.
1421
- * You can pull out the new value by accessing `event.target.value` (string).
1422
- */
1423
- onChange: PropTypes.func,
1424
- /**
1425
- * @ignore
1426
- */
1427
- onFocus: PropTypes.func,
1428
- /**
1429
- * The short hint displayed in the `input` before the user enters a value.
1430
- */
1431
- placeholder: PropTypes.string,
1432
- /**
1433
- * If `true`, the label is displayed as required and the `input` element is required.
1434
- * @default false
1435
- */
1436
- required: PropTypes.bool,
1437
- /**
1438
- * Number of rows to display when multiline option is set to true.
1439
- */
1440
- rows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
1441
- /**
1442
- * Render a [`Select`](https://mui.com/material-ui/api/select/) element while passing the Input element to `Select` as `input` parameter.
1443
- * If this option is set you must pass the options of the select as children.
1444
- * @default false
1445
- */
1446
- select: PropTypes.bool,
1447
- /**
1448
- * Props applied to the [`Select`](https://mui.com/material-ui/api/select/) element.
1449
- * @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.
1450
- */
1451
- SelectProps: PropTypes.object,
1452
- /**
1453
- * The size of the component.
1454
- * @default 'medium'
1455
- */
1456
- size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
1457
- /**
1458
- * The props used for each slot inside.
1459
- * @default {}
1460
- */
1461
- slotProps: PropTypes /* @typescript-to-proptypes-ignore */.shape({
1462
- formHelperText: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1463
- htmlInput: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1464
- input: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1465
- inputLabel: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
1466
- select: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
1467
- }),
1468
- /**
1469
- * The components used for each slot inside.
1470
- * @default {}
1471
- */
1472
- slots: PropTypes.shape({
1473
- formHelperText: PropTypes.elementType,
1474
- htmlInput: PropTypes.elementType,
1475
- input: PropTypes.elementType,
1476
- inputLabel: PropTypes.elementType,
1477
- root: PropTypes.elementType,
1478
- select: PropTypes.elementType
1479
- }),
1480
- /**
1481
- * The system prop that allows defining system overrides as well as additional CSS styles.
1482
- */
1483
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
1484
- /**
1485
- * 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).
1486
- */
1487
- type: PropTypes /* @typescript-to-proptypes-ignore */.string,
1488
- /**
1489
- * The value of the `input` element, required for a controlled component.
1490
- */
1491
- value: PropTypes.any,
1492
- /**
1493
- * The variant to use.
1494
- * @default 'outlined'
1495
- */
1496
- variant: PropTypes.oneOf(['filled', 'outlined', 'standard'])
1497
- } : void 0;
1498
- var TextField$1 = TextField;
14
+ import { n as normalizeRowSelectionModel, o as onServerSideSelectionStatusChange, g as getSelectionCount, i as isRowSelected, S as ServerSideControlledPagination, C as ControlledPagination } from './ServerSideControlledPagination.js';
15
+ import { B as BaseButton, a as BaseCheckbox, c as BaseIconButton, b as BaseIcon } from './BaseIconButton.js';
1499
16
 
1500
17
  const SUBMIT_FILTER_STROKE_TIME = 500;
1501
18
  const InputNumberInterval = props => {
@@ -1537,7 +54,7 @@ const InputNumberInterval = props => {
1537
54
  const newLowerBound = event.target.value;
1538
55
  updateFilterValue(newLowerBound, filterValueState[1]);
1539
56
  };
1540
- return /*#__PURE__*/React.createElement(Box$1, {
57
+ return /*#__PURE__*/React.createElement(Box, {
1541
58
  sx: {
1542
59
  display: 'inline-flex',
1543
60
  flexDirection: 'row',
@@ -1545,7 +62,7 @@ const InputNumberInterval = props => {
1545
62
  height: 48,
1546
63
  pl: '20px'
1547
64
  }
1548
- }, /*#__PURE__*/React.createElement(TextField$1, {
65
+ }, /*#__PURE__*/React.createElement(TextField, {
1549
66
  name: "lower-bound-input",
1550
67
  placeholder: "From",
1551
68
  label: "From",
@@ -1557,7 +74,7 @@ const InputNumberInterval = props => {
1557
74
  sx: {
1558
75
  mr: 2
1559
76
  }
1560
- }), /*#__PURE__*/React.createElement(TextField$1, {
77
+ }), /*#__PURE__*/React.createElement(TextField, {
1561
78
  name: "upper-bound-input",
1562
79
  placeholder: "To",
1563
80
  label: "To",
@@ -2186,7 +703,10 @@ const DIMENSION_MODEL_KEY = 'dimension';
2186
703
  const FILTER_SEARCH_KEY = 'searchModel';
2187
704
  const DENSITY_MODEL_KEY = 'densityModel';
2188
705
  const COLUMN_ORDER_MODEL_KEY = 'columnOrderModel';
2189
- const CATEGORIES = [PAGINATION_MODEL_KEY, FILTER_MODEL_KEY, SORT_MODEL_KEY, VISIBILITY_MODEL_KEY, DIMENSION_MODEL_KEY, FILTER_SEARCH_KEY, PINNED_COLUMNS, DENSITY_MODEL_KEY, COLUMN_ORDER_MODEL_KEY];
706
+ const ROW_GROUPING_MODEL_KEY = 'rowGroupingModel';
707
+ const AGGREGATION_MODEL_KEY = 'aggregationModel';
708
+ const PIVOT_MODEL_KEY = 'pivotModel';
709
+ const CATEGORIES = [PAGINATION_MODEL_KEY, FILTER_MODEL_KEY, SORT_MODEL_KEY, VISIBILITY_MODEL_KEY, DIMENSION_MODEL_KEY, FILTER_SEARCH_KEY, PINNED_COLUMNS, DENSITY_MODEL_KEY, COLUMN_ORDER_MODEL_KEY, ROW_GROUPING_MODEL_KEY, AGGREGATION_MODEL_KEY, PIVOT_MODEL_KEY];
2190
710
  const buildStorageKey = _ref => {
2191
711
  let {
2192
712
  id,
@@ -2233,6 +753,18 @@ const clearPreviousVersionStorage = (id, previousLocalStorageVersions) => {
2233
753
  id,
2234
754
  version,
2235
755
  category: COLUMN_ORDER_MODEL_KEY
756
+ }), buildStorageKey({
757
+ id,
758
+ version,
759
+ category: ROW_GROUPING_MODEL_KEY
760
+ }), buildStorageKey({
761
+ id,
762
+ version,
763
+ category: AGGREGATION_MODEL_KEY
764
+ }), buildStorageKey({
765
+ id,
766
+ version,
767
+ category: PIVOT_MODEL_KEY
2236
768
  })];
2237
769
  for (const keyToDelete of keysToDelete) {
2238
770
  try {
@@ -2255,7 +787,7 @@ const COMPRESSED_PREFIX = '~';
2255
787
  * Params listed first are compressed first (least valuable to read in the URL).
2256
788
  * The filter aggregate step uses the special key `_filters_aggregate`.
2257
789
  */
2258
- const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_quickFilterValues'];
790
+ const COMPRESSION_PRIORITY = ['_columnOrder', '_columnVisibility', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters_aggregate', '_aggregation', '_rowGrouping', '_quickFilterValues', '_pivot'];
2259
791
 
2260
792
  /** Params that are always short and should never be compressed. */
2261
793
  const NEVER_COMPRESS = new Set(['_sortColumn', '_pagination', '_density', '_logicOperator', 'v', 'tab']);
@@ -2333,7 +865,7 @@ const tryAggregateFilters = (params, filterKeys) => {
2333
865
  * Filter params are those that start with `_` but are not well-known system params.
2334
866
  */
2335
867
  const getFilterParamKeys = params => {
2336
- const systemPrefixes = ['_sortColumn', '_pagination', '_density', '_logicOperator', '_quickFilterValues', '_columnVisibility', '_columnOrder', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_filters'];
868
+ const systemPrefixes = ['_sortColumn', '_pagination', '_density', '_logicOperator', '_quickFilterValues', '_columnVisibility', '_columnOrder', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_rowGrouping', '_aggregation', '_pivot', '_filters'];
2337
869
  const filterKeys = [];
2338
870
  for (const key of params.keys()) {
2339
871
  if (!key.startsWith('_')) continue;
@@ -2563,6 +1095,21 @@ const convertToDisplayFormat = search => {
2563
1095
  return param;
2564
1096
  }
2565
1097
 
1098
+ // Handle _rowGrouping=[a,b,c]
1099
+ if (param.startsWith('_rowGrouping=')) {
1100
+ const value = param.slice('_rowGrouping='.length);
1101
+ if (value.startsWith('[') && value.endsWith(']')) {
1102
+ const inner = value.slice(1, -1);
1103
+ return `_rowGrouping=${inner}`;
1104
+ }
1105
+ return param;
1106
+ }
1107
+
1108
+ // _aggregation and _pivot do not use bracket notation — pass through
1109
+ if (param.startsWith('_aggregation=') || param.startsWith('_pivot=')) {
1110
+ return param;
1111
+ }
1112
+
2566
1113
  // Handle _field[operator,type]=value or _field[operator,type]=list[a,b,c]
2567
1114
  const bracketMatch = param.match(/^_([^[]+)\[([^\]]+)\]=(.*)$/);
2568
1115
  if (bracketMatch) {
@@ -2676,8 +1223,17 @@ const convertFromDisplayFormat = (search, columns) => {
2676
1223
  return `_columnOrder=[${value}]`;
2677
1224
  }
2678
1225
 
2679
- // _filters — pass through (no bracket conversion needed)
2680
- if (param.startsWith('_filters=')) {
1226
+ // Handle _rowGrouping=a,b,c
1227
+ if (param.startsWith('_rowGrouping=')) {
1228
+ const value = param.slice('_rowGrouping='.length);
1229
+ if (value.startsWith('[')) {
1230
+ return param;
1231
+ }
1232
+ return `_rowGrouping=[${value}]`;
1233
+ }
1234
+
1235
+ // _aggregation, _pivot, _filters — pass through (no bracket conversion needed)
1236
+ if (param.startsWith('_aggregation=') || param.startsWith('_pivot=') || param.startsWith('_filters=')) {
2681
1237
  return param;
2682
1238
  }
2683
1239
 
@@ -2724,8 +1280,9 @@ const getDecodedSearchFromUrl = (search, columns) => {
2724
1280
  const hasPinnedWithoutBrackets = /(_pinnedColumnsLeft|_pinnedColumnsRight)=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2725
1281
  const hasVisibilityWithoutBrackets = /_columnVisibility=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2726
1282
  const hasColumnOrderWithoutBrackets = /_columnOrder=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
1283
+ const hasRowGroupingWithoutBrackets = /_rowGrouping=[^&[]*(&|$)/.test(searchWithoutLeadingQuestion);
2727
1284
  const hasBracketNotation = /\[.*\]=/.test(searchWithoutLeadingQuestion);
2728
- const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets) && !hasBracketNotation;
1285
+ const isDisplayFormat = (hasDotNotationFilter || hasEmptySortColumn || hasSortDotNotation || hasPaginationDotNotation || hasPinnedWithoutBrackets || hasVisibilityWithoutBrackets || hasColumnOrderWithoutBrackets || hasRowGroupingWithoutBrackets) && !hasBracketNotation;
2729
1286
  if (isDisplayFormat) {
2730
1287
  return '?' + convertFromDisplayFormat(searchWithoutLeadingQuestion, columns);
2731
1288
  }
@@ -2850,11 +1407,16 @@ const isValueValid = (value, field, columns, operator) => {
2850
1407
  }
2851
1408
  const type = (_column$type = column['type']) !== null && _column$type !== void 0 ? _column$type : 'string';
2852
1409
 
2853
- // Only date fails with 500s, other set themselves as undefined
2854
- if (type !== 'date') {
1410
+ // Only date and rating fail with 500s, other set themselves as undefined
1411
+ if (type !== 'date' && type !== 'rating') {
2855
1412
  return true;
2856
1413
  }
2857
1414
 
1415
+ // just checking that rating is a number.
1416
+ if (type === 'rating') {
1417
+ return !isNaN(Number(value));
1418
+ }
1419
+
2858
1420
  // format: YYYY-MM-DD
2859
1421
  // just verifying that the 3 values are numbers to avoid 500s,
2860
1422
  // If the value is invalid the form will appear as undefined
@@ -2881,7 +1443,7 @@ const getFilterModelFromString = (searchString, columns) => {
2881
1443
  let quickFilterValues = [];
2882
1444
  const searchParams = new URLSearchParams();
2883
1445
  for (const [key, value] of new URLSearchParams(searchString)) {
2884
- if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_density', '_filters'].includes(key)) {
1446
+ if (key.startsWith('_') && !['_logicOperator', '_sortColumn', '_pinnedColumnsLeft', '_pinnedColumnsRight', '_columnVisibility', '_pagination', '_quickFilterValues', '_columnOrder', '_rowGrouping', '_aggregation', '_pivot', '_density', '_filters'].includes(key)) {
2885
1447
  searchParams.set(key, value);
2886
1448
  }
2887
1449
  if (key === '_logicOperator') {
@@ -3347,7 +1909,7 @@ const getSearchParamsFromDensity = density => {
3347
1909
  return searchParams;
3348
1910
  };
3349
1911
  const getDensityModel = (search, localStorageDensity, setLocalStorageDensity, _initialState, isNewVersion) => {
3350
- // Default to 'compact' when no density is provided via URL, localStorage, or initialState
1912
+ // Default density when none is persisted
3351
1913
  const defaultValue = 'compact';
3352
1914
 
3353
1915
  // Persist initialState-derived density to localStorage so all three sources stay in sync
@@ -3429,7 +1991,212 @@ const getColumnOrder = (search, columns, localStorageColumnOrder, setLocalStorag
3429
1991
  persistDefault();
3430
1992
  return defaultValue;
3431
1993
  };
3432
- const getFinalSearch = _ref => {
1994
+
1995
+ /** ROW GROUPING */
1996
+
1997
+ const getRowGroupingFromString = searchString => {
1998
+ if (!searchString) return 'invalid';
1999
+ const searchParams = new URLSearchParams(searchString);
2000
+ const value = searchParams.get('_rowGrouping');
2001
+ if (value === '' || value === null || value === '[]') return 'invalid';
2002
+ const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2003
+ if (!inner) return 'invalid';
2004
+ return inner.split(',').filter(Boolean);
2005
+ };
2006
+ const getSearchParamsFromRowGrouping = rowGrouping => {
2007
+ const searchParams = new URLSearchParams();
2008
+ if (rowGrouping.length > 0) {
2009
+ searchParams.set('_rowGrouping', `[${rowGrouping.join(',')}]`);
2010
+ }
2011
+ return searchParams;
2012
+ };
2013
+ const getRowGroupingModel = (search, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion) => {
2014
+ var _initialState$rowGrou, _initialState$rowGrou2;
2015
+ const defaultValue = (_initialState$rowGrou = initialState === null || initialState === void 0 ? void 0 : (_initialState$rowGrou2 = initialState.rowGrouping) === null || _initialState$rowGrou2 === void 0 ? void 0 : _initialState$rowGrou2.model) !== null && _initialState$rowGrou !== void 0 ? _initialState$rowGrou : [];
2016
+ const persistDefault = () => {
2017
+ const searchFromDefault = getSearchParamsFromRowGrouping(defaultValue);
2018
+ const searchString = urlSearchParamsToString(searchFromDefault);
2019
+ if (searchString !== localStorageRowGrouping) {
2020
+ setLocalStorageRowGrouping(searchString);
2021
+ }
2022
+ };
2023
+ if (isNewVersion) {
2024
+ persistDefault();
2025
+ return defaultValue;
2026
+ }
2027
+ const fromUrl = getRowGroupingFromString(search);
2028
+ if (fromUrl !== 'invalid') {
2029
+ const searchFromModel = getSearchParamsFromRowGrouping(fromUrl);
2030
+ const searchString = urlSearchParamsToString(searchFromModel);
2031
+ if (searchString !== localStorageRowGrouping) {
2032
+ setLocalStorageRowGrouping(searchString);
2033
+ }
2034
+ return fromUrl;
2035
+ }
2036
+ const fromLocalStorage = getRowGroupingFromString(localStorageRowGrouping);
2037
+ if (fromLocalStorage !== 'invalid') {
2038
+ return fromLocalStorage;
2039
+ }
2040
+ persistDefault();
2041
+ return defaultValue;
2042
+ };
2043
+
2044
+ /** AGGREGATION */
2045
+
2046
+ const getAggregationFromString = searchString => {
2047
+ if (!searchString) return 'invalid';
2048
+ const searchParams = new URLSearchParams(searchString);
2049
+ const value = searchParams.get('_aggregation');
2050
+ if (value === '' || value === null) return 'invalid';
2051
+
2052
+ // Format: field1.sum,field2.avg or [field1.sum,field2.avg]
2053
+ const inner = value.startsWith('[') && value.endsWith(']') ? value.slice(1, -1) : value;
2054
+ if (!inner) return 'invalid';
2055
+ const model = {};
2056
+ for (const entry of inner.split(',')) {
2057
+ const dotIndex = entry.lastIndexOf('.');
2058
+ if (dotIndex <= 0) return 'invalid';
2059
+ const field = entry.slice(0, dotIndex);
2060
+ const aggFunc = entry.slice(dotIndex + 1);
2061
+ if (!field || !aggFunc) return 'invalid';
2062
+ model[field] = aggFunc;
2063
+ }
2064
+ return Object.keys(model).length > 0 ? model : 'invalid';
2065
+ };
2066
+ const getSearchParamsFromAggregation = aggregation => {
2067
+ const searchParams = new URLSearchParams();
2068
+ const entries = Object.entries(aggregation);
2069
+ if (entries.length > 0) {
2070
+ const value = entries.map(_ref => {
2071
+ let [field, aggFunc] = _ref;
2072
+ return `${field}.${aggFunc}`;
2073
+ }).join(',');
2074
+ searchParams.set('_aggregation', value);
2075
+ }
2076
+ return searchParams;
2077
+ };
2078
+ const getAggregationModel = (search, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion) => {
2079
+ var _initialState$aggrega, _initialState$aggrega2;
2080
+ const defaultValue = (_initialState$aggrega = initialState === null || initialState === void 0 ? void 0 : (_initialState$aggrega2 = initialState.aggregation) === null || _initialState$aggrega2 === void 0 ? void 0 : _initialState$aggrega2.model) !== null && _initialState$aggrega !== void 0 ? _initialState$aggrega : {};
2081
+ const persistDefault = () => {
2082
+ const searchFromDefault = getSearchParamsFromAggregation(defaultValue);
2083
+ const searchString = urlSearchParamsToString(searchFromDefault);
2084
+ if (searchString !== localStorageAggregation) {
2085
+ setLocalStorageAggregation(searchString);
2086
+ }
2087
+ };
2088
+ if (isNewVersion) {
2089
+ persistDefault();
2090
+ return defaultValue;
2091
+ }
2092
+ const fromUrl = getAggregationFromString(search);
2093
+ if (fromUrl !== 'invalid') {
2094
+ const searchFromModel = getSearchParamsFromAggregation(fromUrl);
2095
+ const searchString = urlSearchParamsToString(searchFromModel);
2096
+ if (searchString !== localStorageAggregation) {
2097
+ setLocalStorageAggregation(searchString);
2098
+ }
2099
+ return fromUrl;
2100
+ }
2101
+ const fromLocalStorage = getAggregationFromString(localStorageAggregation);
2102
+ if (fromLocalStorage !== 'invalid') {
2103
+ return fromLocalStorage;
2104
+ }
2105
+ persistDefault();
2106
+ return defaultValue;
2107
+ };
2108
+
2109
+ /** PIVOT */
2110
+
2111
+ /**
2112
+ * Pivot format: `cols:f1,f2;rows:f3;vals:f4.sum,f5.avg`
2113
+ */
2114
+ const getPivotFromString = searchString => {
2115
+ if (!searchString) return 'invalid';
2116
+ const searchParams = new URLSearchParams(searchString);
2117
+ const value = searchParams.get('_pivot');
2118
+ if (value === '' || value === null) return 'invalid';
2119
+ const model = {
2120
+ columns: [],
2121
+ rows: [],
2122
+ values: []
2123
+ };
2124
+ for (const segment of value.split(';')) {
2125
+ const colonIndex = segment.indexOf(':');
2126
+ if (colonIndex <= 0) return 'invalid';
2127
+ const key = segment.slice(0, colonIndex);
2128
+ const content = segment.slice(colonIndex + 1);
2129
+ if (key === 'cols') {
2130
+ model.columns = content ? content.split(',').filter(Boolean) : [];
2131
+ } else if (key === 'rows') {
2132
+ model.rows = content ? content.split(',').filter(Boolean) : [];
2133
+ } else if (key === 'vals') {
2134
+ if (!content) continue;
2135
+ for (const entry of content.split(',')) {
2136
+ const dotIndex = entry.lastIndexOf('.');
2137
+ if (dotIndex <= 0) return 'invalid';
2138
+ model.values.push({
2139
+ field: entry.slice(0, dotIndex),
2140
+ aggFunc: entry.slice(dotIndex + 1)
2141
+ });
2142
+ }
2143
+ }
2144
+ }
2145
+
2146
+ // At least one section must have content
2147
+ if (model.columns.length === 0 && model.rows.length === 0 && model.values.length === 0) {
2148
+ return 'invalid';
2149
+ }
2150
+ return model;
2151
+ };
2152
+ const getSearchParamsFromPivot = pivot => {
2153
+ const searchParams = new URLSearchParams();
2154
+ const hasContent = pivot.columns.length > 0 || pivot.rows.length > 0 || pivot.values.length > 0;
2155
+ if (hasContent) {
2156
+ const parts = [];
2157
+ parts.push(`cols:${pivot.columns.join(',')}`);
2158
+ parts.push(`rows:${pivot.rows.join(',')}`);
2159
+ if (pivot.values.length > 0) {
2160
+ parts.push(`vals:${pivot.values.map(v => `${v.field}.${v.aggFunc}`).join(',')}`);
2161
+ }
2162
+ searchParams.set('_pivot', parts.join(';'));
2163
+ }
2164
+ return searchParams;
2165
+ };
2166
+ const getPivotModel = (search, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion) => {
2167
+ const defaultValue = {
2168
+ columns: [],
2169
+ rows: [],
2170
+ values: []
2171
+ };
2172
+ const persistDefault = () => {
2173
+ const searchFromDefault = getSearchParamsFromPivot(defaultValue);
2174
+ const searchString = urlSearchParamsToString(searchFromDefault);
2175
+ if (searchString !== localStoragePivot) {
2176
+ setLocalStoragePivot(searchString);
2177
+ }
2178
+ };
2179
+ if (isNewVersion) {
2180
+ persistDefault();
2181
+ return defaultValue;
2182
+ }
2183
+ const fromUrl = getPivotFromString(search);
2184
+ if (fromUrl !== 'invalid') {
2185
+ const searchFromModel = getSearchParamsFromPivot(fromUrl);
2186
+ const searchString = urlSearchParamsToString(searchFromModel);
2187
+ if (searchString !== localStoragePivot) {
2188
+ setLocalStoragePivot(searchString);
2189
+ }
2190
+ return fromUrl;
2191
+ }
2192
+ const fromLocalStorage = getPivotFromString(localStoragePivot);
2193
+ if (fromLocalStorage !== 'invalid') {
2194
+ return fromLocalStorage;
2195
+ }
2196
+ persistDefault();
2197
+ return defaultValue;
2198
+ };
2199
+ const getFinalSearch = _ref2 => {
3433
2200
  let {
3434
2201
  search,
3435
2202
  localStorageVersion,
@@ -3441,8 +2208,11 @@ const getFinalSearch = _ref => {
3441
2208
  density,
3442
2209
  columnOrderModel,
3443
2210
  defaultColumnOrder,
2211
+ rowGroupingModel,
2212
+ aggregationModel,
2213
+ pivotModel,
3444
2214
  columns
3445
- } = _ref;
2215
+ } = _ref2;
3446
2216
  const filterModelSearch = getSearchParamsFromFilterModel(filterModel);
3447
2217
  const sortModelSearch = getSearchParamsFromSorting(sortModel);
3448
2218
  const paginationModelSearch = getSearchParamsFromPagination(paginationModel);
@@ -3451,6 +2221,9 @@ const getFinalSearch = _ref => {
3451
2221
  const densitySearch = getSearchParamsFromDensity(density);
3452
2222
  // Only include _columnOrder in URL when it differs from the default
3453
2223
  const columnOrderSearch = columnOrderModel.length !== defaultColumnOrder.length || columnOrderModel.some((field, i) => field !== defaultColumnOrder[i]) ? getSearchParamsFromColumnOrder(columnOrderModel) : new URLSearchParams();
2224
+ const rowGroupingSearch = getSearchParamsFromRowGrouping(rowGroupingModel);
2225
+ const aggregationSearch = getSearchParamsFromAggregation(aggregationModel);
2226
+ const pivotSearch = getSearchParamsFromPivot(pivotModel);
3454
2227
  const tabSearch = getSearchParamsFromTab(search);
3455
2228
  const searchParams = new URLSearchParams();
3456
2229
  for (const [key, value] of new URLSearchParams(search)) {
@@ -3465,7 +2238,7 @@ const getFinalSearch = _ref => {
3465
2238
  // Encode array as JSON string to preserve all values in one param
3466
2239
  searchParams.set('_quickFilterValues', encodeURIComponent(JSON.stringify(filterModel.quickFilterValues)));
3467
2240
  }
3468
- return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch]);
2241
+ return new URLSearchParams([...searchParams, ...filterModelSearch, ...sortModelSearch, ...paginationModelSearch, ...tabSearch, ...pinnedColumnsModelSearch, ...columnVisibilityModelSearch, ...densitySearch, ...columnOrderSearch, ...rowGroupingSearch, ...aggregationSearch, ...pivotSearch]);
3469
2242
  };
3470
2243
  /** Return the state of the table given the URL and the local storage state */
3471
2244
  const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, columns, initialState, localStorage) => {
@@ -3490,7 +2263,13 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3490
2263
  localStorageDensity,
3491
2264
  setLocalStorageDensity,
3492
2265
  localStorageColumnOrder,
3493
- setLocalStorageColumnOrder
2266
+ setLocalStorageColumnOrder,
2267
+ localStorageRowGrouping,
2268
+ setLocalStorageRowGrouping,
2269
+ localStorageAggregation,
2270
+ setLocalStorageAggregation,
2271
+ localStoragePivot,
2272
+ setLocalStoragePivot
3494
2273
  } = localStorage;
3495
2274
  const filterModel = getFilterModel(decodedSearch, columns, localStorageFilters, setLocalStorageFilters, initialState, isNewVersion);
3496
2275
  const sortModel = getSortModel(decodedSearch, columns, localStorageSorting, setLocalStorageSorting, initialState, isNewVersion);
@@ -3499,6 +2278,9 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3499
2278
  const pinnedColumnsModel = getPinnedColumns(decodedSearch, columns, localStoragePinnedColumns, setLocalStoragePinnedColumns, initialState, isNewVersion);
3500
2279
  const density = getDensityModel(decodedSearch, localStorageDensity, setLocalStorageDensity, initialState, isNewVersion);
3501
2280
  const columnOrderModel = getColumnOrder(decodedSearch, columns, localStorageColumnOrder, setLocalStorageColumnOrder, initialState, isNewVersion);
2281
+ const rowGroupingModel = getRowGroupingModel(decodedSearch, localStorageRowGrouping, setLocalStorageRowGrouping, initialState, isNewVersion);
2282
+ const aggregationModel = getAggregationModel(decodedSearch, localStorageAggregation, setLocalStorageAggregation, initialState, isNewVersion);
2283
+ const pivotModel = getPivotModel(decodedSearch, localStoragePivot, setLocalStoragePivot, initialState, isNewVersion);
3502
2284
  const defaultColumnOrder = (_initialState$columns6 = initialState === null || initialState === void 0 ? void 0 : (_initialState$columns7 = initialState.columns) === null || _initialState$columns7 === void 0 ? void 0 : _initialState$columns7.orderedFields) !== null && _initialState$columns6 !== void 0 ? _initialState$columns6 : columns.map(c => c.field);
3503
2285
  const finalSearch = getFinalSearch({
3504
2286
  localStorageVersion,
@@ -3511,6 +2293,9 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3511
2293
  density,
3512
2294
  columnOrderModel,
3513
2295
  defaultColumnOrder,
2296
+ rowGroupingModel,
2297
+ aggregationModel,
2298
+ pivotModel,
3514
2299
  columns
3515
2300
  });
3516
2301
  const internalSearchString = urlSearchParamsToString(finalSearch);
@@ -3531,10 +2316,13 @@ const getModelsParsedOrUpdateLocalStorage = (search, localStorageVersion, column
3531
2316
  pinnedColumnsModel,
3532
2317
  density,
3533
2318
  columnOrderModel,
2319
+ rowGroupingModel,
2320
+ aggregationModel,
2321
+ pivotModel,
3534
2322
  pendingSearch
3535
2323
  };
3536
2324
  };
3537
- const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns) => {
2325
+ const updateUrl = (_ref3, search, localStorageVersion, historyReplace, columns) => {
3538
2326
  let {
3539
2327
  filterModel,
3540
2328
  sortModel,
@@ -3543,8 +2331,11 @@ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns)
3543
2331
  pinnedColumnsModel,
3544
2332
  density,
3545
2333
  columnOrderModel,
3546
- defaultColumnOrder
3547
- } = _ref2;
2334
+ defaultColumnOrder,
2335
+ rowGroupingModel,
2336
+ aggregationModel,
2337
+ pivotModel
2338
+ } = _ref3;
3548
2339
  // Convert from display format to internal format if needed
3549
2340
  const decodedSearch = getDecodedSearchFromUrl(search, columns);
3550
2341
  const newSearch = getFinalSearch({
@@ -3558,6 +2349,9 @@ const updateUrl = (_ref2, search, localStorageVersion, historyReplace, columns)
3558
2349
  density,
3559
2350
  columnOrderModel,
3560
2351
  defaultColumnOrder,
2352
+ rowGroupingModel,
2353
+ aggregationModel,
2354
+ pivotModel,
3561
2355
  columns
3562
2356
  });
3563
2357
  const internalSearchString = urlSearchParamsToString(newSearch);
@@ -3745,6 +2539,21 @@ const useTableStates = (id, version) => {
3745
2539
  version,
3746
2540
  category: COLUMN_ORDER_MODEL_KEY
3747
2541
  }));
2542
+ const [rowGroupingModel, setRowGroupingModel] = useFetchState('', buildStorageKey({
2543
+ id,
2544
+ version,
2545
+ category: ROW_GROUPING_MODEL_KEY
2546
+ }));
2547
+ const [aggregationModel, setAggregationModel] = useFetchState('', buildStorageKey({
2548
+ id,
2549
+ version,
2550
+ category: AGGREGATION_MODEL_KEY
2551
+ }));
2552
+ const [pivotModel, setPivotModel] = useFetchState('', buildStorageKey({
2553
+ id,
2554
+ version,
2555
+ category: PIVOT_MODEL_KEY
2556
+ }));
3748
2557
  return {
3749
2558
  paginationModel,
3750
2559
  setPaginationModel,
@@ -3761,13 +2570,55 @@ const useTableStates = (id, version) => {
3761
2570
  densityModel,
3762
2571
  setDensityModel,
3763
2572
  columnOrderModel,
3764
- setColumnOrderModel
2573
+ setColumnOrderModel,
2574
+ rowGroupingModel,
2575
+ setRowGroupingModel,
2576
+ aggregationModel,
2577
+ setAggregationModel,
2578
+ pivotModel,
2579
+ setPivotModel
3765
2580
  };
3766
2581
  };
3767
2582
 
2583
+ /** Convert our simplified PivotModel → MUI's GridPivotModel */
2584
+ const toGridPivotModel = model => ({
2585
+ columns: model.columns.map(field => ({
2586
+ field
2587
+ })),
2588
+ rows: model.rows.map(field => ({
2589
+ field
2590
+ })),
2591
+ values: model.values.map(_ref => {
2592
+ let {
2593
+ field,
2594
+ aggFunc
2595
+ } = _ref;
2596
+ return {
2597
+ field,
2598
+ aggFunc
2599
+ };
2600
+ })
2601
+ });
2602
+
2603
+ /** Convert MUI's GridPivotModel → our simplified PivotModel */
2604
+ const fromGridPivotModel = model => ({
2605
+ columns: model.columns.map(c => c.field),
2606
+ rows: model.rows.map(r => r.field),
2607
+ values: model.values.map(_ref2 => {
2608
+ let {
2609
+ field,
2610
+ aggFunc
2611
+ } = _ref2;
2612
+ return {
2613
+ field,
2614
+ aggFunc
2615
+ };
2616
+ })
2617
+ });
2618
+
3768
2619
  /**
3769
2620
  * Deep-equal comparison for plain objects / arrays.
3770
- * Used to stabilise parsed model references so that MUI does not
2621
+ * Used to stabilise parsed model references so that MUI v8 does not
3771
2622
  * reset pagination on every render.
3772
2623
  */
3773
2624
  function isDeepEqual(a, b) {
@@ -3794,6 +2645,9 @@ const useStatefulTable = props => {
3794
2645
  onPaginationModelChange: propsOnPaginationModelChange,
3795
2646
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
3796
2647
  onSortModelChange: propsOnSortModelChange,
2648
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
2649
+ onAggregationModelChange: propsOnAggregationModelChange,
2650
+ onPivotModelChange: propsOnPivotModelChange,
3797
2651
  useRouter,
3798
2652
  localStorageVersion = 1,
3799
2653
  previousLocalStorageVersions = []
@@ -3822,16 +2676,22 @@ const useStatefulTable = props => {
3822
2676
  densityModel,
3823
2677
  setDensityModel,
3824
2678
  columnOrderModel: localStorageColumnOrder,
3825
- setColumnOrderModel: setLocalStorageColumnOrder
2679
+ setColumnOrderModel: setLocalStorageColumnOrder,
2680
+ rowGroupingModel: localStorageRowGrouping,
2681
+ setRowGroupingModel: setLocalStorageRowGrouping,
2682
+ aggregationModel: localStorageAggregation,
2683
+ setAggregationModel: setLocalStorageAggregation,
2684
+ pivotModel: localStoragePivot,
2685
+ setPivotModel: setLocalStoragePivot
3826
2686
  } = useTableStates(id, localStorageVersion);
3827
2687
 
3828
2688
  // clearing up old version keys, triggering only on first render
3829
2689
  useEffect(() => clearPreviousVersionStorage(id, previousLocalStorageVersions), [id, previousLocalStorageVersions]);
3830
- const onColumnDimensionChange = useCallback(_ref => {
2690
+ const onColumnDimensionChange = useCallback(_ref3 => {
3831
2691
  let {
3832
2692
  newWidth,
3833
2693
  field
3834
- } = _ref;
2694
+ } = _ref3;
3835
2695
  setDimensionModel(_objectSpread2(_objectSpread2({}, dimensionModel), {}, {
3836
2696
  [field]: newWidth
3837
2697
  }));
@@ -3844,6 +2704,9 @@ const useStatefulTable = props => {
3844
2704
  pinnedColumnsModel,
3845
2705
  density: densityParsed,
3846
2706
  columnOrderModel: columnOrderParsed,
2707
+ rowGroupingModel: rowGroupingParsed,
2708
+ aggregationModel: aggregationParsed,
2709
+ pivotModel: pivotParsed,
3847
2710
  pendingSearch
3848
2711
  } = getModelsParsedOrUpdateLocalStorage(search || '', localStorageVersion, propsColumns, initialState, {
3849
2712
  localStorageFilters,
@@ -3859,7 +2722,13 @@ const useStatefulTable = props => {
3859
2722
  localStorageDensity: densityModel,
3860
2723
  setLocalStorageDensity: setDensityModel,
3861
2724
  localStorageColumnOrder,
3862
- setLocalStorageColumnOrder
2725
+ setLocalStorageColumnOrder,
2726
+ localStorageRowGrouping,
2727
+ setLocalStorageRowGrouping,
2728
+ localStorageAggregation,
2729
+ setLocalStorageAggregation,
2730
+ localStoragePivot,
2731
+ setLocalStoragePivot
3863
2732
  });
3864
2733
 
3865
2734
  // Sync URL in an effect rather than during render to comply with React rules
@@ -3869,7 +2738,7 @@ const useStatefulTable = props => {
3869
2738
  }
3870
2739
  }, [pendingSearch, historyReplace]);
3871
2740
 
3872
- // Stabilise parsed model references to prevent MUI from resetting
2741
+ // Stabilise parsed model references to prevent MUI v8 from resetting
3873
2742
  // pagination on every render due to new object identity.
3874
2743
  const filterParsedRef = useRef(filterParsed);
3875
2744
  if (!isDeepEqual(filterParsedRef.current, filterParsed)) {
@@ -3895,6 +2764,18 @@ const useStatefulTable = props => {
3895
2764
  if (!isDeepEqual(columnOrderParsedRef.current, columnOrderParsed)) {
3896
2765
  columnOrderParsedRef.current = columnOrderParsed;
3897
2766
  }
2767
+ const rowGroupingParsedRef = useRef(rowGroupingParsed);
2768
+ if (!isDeepEqual(rowGroupingParsedRef.current, rowGroupingParsed)) {
2769
+ rowGroupingParsedRef.current = rowGroupingParsed;
2770
+ }
2771
+ const aggregationParsedRef = useRef(aggregationParsed);
2772
+ if (!isDeepEqual(aggregationParsedRef.current, aggregationParsed)) {
2773
+ aggregationParsedRef.current = aggregationParsed;
2774
+ }
2775
+ const pivotParsedRef = useRef(pivotParsed);
2776
+ if (!isDeepEqual(pivotParsedRef.current, pivotParsed)) {
2777
+ pivotParsedRef.current = pivotParsed;
2778
+ }
3898
2779
  const columns = useMemo(() => propsColumns.map(column => {
3899
2780
  return _objectSpread2(_objectSpread2({}, column), {}, {
3900
2781
  width: dimensionModel[column.field] || column.width || 100
@@ -3903,29 +2784,13 @@ const useStatefulTable = props => {
3903
2784
  if (apiRef.current) {
3904
2785
  /** Add resetPage method to apiRef. */
3905
2786
  apiRef.current.resetPage = () => {
3906
- apiRef.current.setPage(0);
2787
+ var _apiRef$current;
2788
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPage(0);
3907
2789
  };
3908
2790
  }
3909
2791
  const defaultColumnOrder = (_initialState$columns = initialState === null || initialState === void 0 ? void 0 : (_initialState$columns2 = initialState.columns) === null || _initialState$columns2 === void 0 ? void 0 : _initialState$columns2.orderedFields) !== null && _initialState$columns !== void 0 ? _initialState$columns : propsColumns.map(c => c.field);
3910
2792
 
3911
- // Helper to build the current DataGridModel for updateUrl calls
3912
- const buildModel = function () {
3913
- var _apiRef$current$state, _apiRef$current;
3914
- let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
3915
- return _objectSpread2({
3916
- filterModel: filterParsed,
3917
- sortModel: sortModelParsed,
3918
- paginationModel: paginationModelParsed,
3919
- 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 : {},
3920
- pinnedColumnsModel: pinnedColumnsModel,
3921
- density: densityParsed,
3922
- columnOrderModel: columnOrderParsed,
3923
- defaultColumnOrder
3924
- }, overrides);
3925
- };
3926
-
3927
- // Subscribe to density changes via stateChange event
3928
- // (MUI v7 supports onDensityChange, but stateChange works and avoids a larger refactor)
2793
+ // Subscribe to density changes via stateChange event (MUI v6 has no densityChange event)
3929
2794
  useEffect(() => {
3930
2795
  const api = apiRef.current;
3931
2796
  if (!(api !== null && api !== void 0 && api.subscribeEvent)) return;
@@ -3934,14 +2799,23 @@ const useStatefulTable = props => {
3934
2799
  const currentDensity = api.state.density;
3935
2800
  if (currentDensity !== prevDensity) {
3936
2801
  prevDensity = currentDensity;
3937
- updateUrl(buildModel({
2802
+ updateUrl({
2803
+ filterModel: filterParsed,
2804
+ sortModel: sortModelParsed,
2805
+ paginationModel: paginationModelParsed,
3938
2806
  columnsModel: api.state.columns.columnVisibilityModel,
3939
- density: currentDensity
3940
- }), search, localStorageVersion, historyReplace, columns);
2807
+ pinnedColumnsModel: pinnedColumnsModel,
2808
+ density: currentDensity,
2809
+ columnOrderModel: columnOrderParsed,
2810
+ defaultColumnOrder,
2811
+ rowGroupingModel: rowGroupingParsed,
2812
+ aggregationModel: aggregationParsed,
2813
+ pivotModel: pivotParsed
2814
+ }, search, localStorageVersion, historyReplace, columns);
3941
2815
  }
3942
2816
  });
3943
2817
  return unsub;
3944
- }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, search, localStorageVersion, historyReplace, columns]);
2818
+ }, [apiRef, densityParsed, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, columnOrderParsed, defaultColumnOrder, rowGroupingParsed, aggregationParsed, pivotParsed, search, localStorageVersion, historyReplace, columns]);
3945
2819
 
3946
2820
  // Subscribe to column order changes via columnOrderChange (drag-drop) and columnIndexChange (programmatic setColumnIndex)
3947
2821
  useEffect(() => {
@@ -3950,9 +2824,19 @@ const useStatefulTable = props => {
3950
2824
  const handleColumnOrderChange = () => {
3951
2825
  const orderedFields = api.state.columns.orderedFields;
3952
2826
  if (orderedFields && !isDeepEqual(orderedFields, columnOrderParsed)) {
3953
- updateUrl(buildModel({
3954
- columnOrderModel: orderedFields
3955
- }), search, localStorageVersion, historyReplace, columns);
2827
+ updateUrl({
2828
+ filterModel: filterParsed,
2829
+ sortModel: sortModelParsed,
2830
+ paginationModel: paginationModelParsed,
2831
+ columnsModel: api.state.columns.columnVisibilityModel,
2832
+ pinnedColumnsModel,
2833
+ density: densityParsed,
2834
+ columnOrderModel: orderedFields,
2835
+ defaultColumnOrder,
2836
+ rowGroupingModel: rowGroupingParsed,
2837
+ aggregationModel: aggregationParsed,
2838
+ pivotModel: pivotParsed
2839
+ }, search, localStorageVersion, historyReplace, columns);
3956
2840
  }
3957
2841
  };
3958
2842
  const unsub1 = api.subscribeEvent('columnOrderChange', handleColumnOrderChange);
@@ -3961,22 +2845,40 @@ const useStatefulTable = props => {
3961
2845
  unsub1();
3962
2846
  unsub2();
3963
2847
  };
3964
- }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, search, localStorageVersion, historyReplace, columns]);
2848
+ }, [apiRef, columnOrderParsed, defaultColumnOrder, filterParsed, sortModelParsed, paginationModelParsed, pinnedColumnsModel, densityParsed, rowGroupingParsed, aggregationParsed, pivotParsed, search, localStorageVersion, historyReplace, columns]);
2849
+
2850
+ // Helper to build the current DataGridModel for updateUrl calls
2851
+ const buildModel = function () {
2852
+ var _apiRef$current$state, _apiRef$current2;
2853
+ let overrides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2854
+ return _objectSpread2({
2855
+ filterModel: filterParsed,
2856
+ sortModel: sortModelParsed,
2857
+ paginationModel: paginationModelParsed,
2858
+ columnsModel: (_apiRef$current$state = (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.state.columns.columnVisibilityModel) !== null && _apiRef$current$state !== void 0 ? _apiRef$current$state : {},
2859
+ pinnedColumnsModel: pinnedColumnsModel,
2860
+ density: densityParsed,
2861
+ columnOrderModel: columnOrderParsed,
2862
+ defaultColumnOrder,
2863
+ rowGroupingModel: rowGroupingParsed,
2864
+ aggregationModel: aggregationParsed,
2865
+ pivotModel: pivotParsed
2866
+ }, overrides);
2867
+ };
3965
2868
  return {
3966
2869
  apiRef,
3967
2870
  columns,
3968
2871
  density: densityParsed,
3969
- onDensityChange: newDensity => {
3970
- updateUrl(buildModel({
3971
- density: newDensity
3972
- }), search, localStorageVersion, historyReplace, columns);
3973
- },
3974
2872
  columnOrderModel: columnOrderParsedRef.current,
2873
+ rowGroupingModel: rowGroupingParsedRef.current,
2874
+ aggregationModel: aggregationParsedRef.current,
2875
+ pivotModel: toGridPivotModel(pivotParsedRef.current),
3975
2876
  onFilterModelChange: (model, details) => {
3976
2877
  const filterModel = _objectSpread2(_objectSpread2({}, model), {}, {
3977
2878
  items: model.items.map(item => {
3978
- const column = apiRef.current.getColumn(item.field);
3979
- item.type = column.type || 'string';
2879
+ var _apiRef$current3;
2880
+ const column = (_apiRef$current3 = apiRef.current) === null || _apiRef$current3 === void 0 ? void 0 : _apiRef$current3.getColumn(item.field);
2881
+ item.type = (column === null || column === void 0 ? void 0 : column.type) || 'string';
3980
2882
  return item;
3981
2883
  }),
3982
2884
  quickFilterValues: model.quickFilterValues || []
@@ -3995,10 +2897,10 @@ const useStatefulTable = props => {
3995
2897
  },
3996
2898
  sortModel: sortModelParsedRef.current,
3997
2899
  onPinnedColumnsChange: (pinnedColumns, details) => {
3998
- propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
3999
2900
  updateUrl(buildModel({
4000
2901
  pinnedColumnsModel: pinnedColumns
4001
2902
  }), search, localStorageVersion, historyReplace, columns);
2903
+ propsOnPinnedColumnsChange === null || propsOnPinnedColumnsChange === void 0 ? void 0 : propsOnPinnedColumnsChange(pinnedColumns, details);
4002
2904
  },
4003
2905
  pinnedColumns: pinnedColumnsModelRef.current,
4004
2906
  paginationModel: paginationModelParsedRef.current,
@@ -4013,10 +2915,10 @@ const useStatefulTable = props => {
4013
2915
  },
4014
2916
  columnVisibilityModel: visibilityModelRef.current,
4015
2917
  onColumnVisibilityModelChange: (columnsVisibilityModel, details) => {
4016
- propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
4017
2918
  updateUrl(buildModel({
4018
2919
  columnsModel: columnsVisibilityModel
4019
2920
  }), search, localStorageVersion, historyReplace, columns);
2921
+ propsOnColumnVisibilityModelChange === null || propsOnColumnVisibilityModelChange === void 0 ? void 0 : propsOnColumnVisibilityModelChange(columnsVisibilityModel, details);
4020
2922
  },
4021
2923
  onColumnWidthChange: (params, event, details) => {
4022
2924
  propsOnColumnWidthChange === null || propsOnColumnWidthChange === void 0 ? void 0 : propsOnColumnWidthChange(params, event, details);
@@ -4024,11 +2926,30 @@ const useStatefulTable = props => {
4024
2926
  newWidth: params.width,
4025
2927
  field: params.colDef.field
4026
2928
  });
2929
+ },
2930
+ onRowGroupingModelChange: (model, details) => {
2931
+ updateUrl(buildModel({
2932
+ rowGroupingModel: model
2933
+ }), search, localStorageVersion, historyReplace, columns);
2934
+ propsOnRowGroupingModelChange === null || propsOnRowGroupingModelChange === void 0 ? void 0 : propsOnRowGroupingModelChange(model, details);
2935
+ },
2936
+ onAggregationModelChange: (model, details) => {
2937
+ updateUrl(buildModel({
2938
+ aggregationModel: model
2939
+ }), search, localStorageVersion, historyReplace, columns);
2940
+ propsOnAggregationModelChange === null || propsOnAggregationModelChange === void 0 ? void 0 : propsOnAggregationModelChange(model, details);
2941
+ },
2942
+ onPivotModelChange: model => {
2943
+ const simplified = fromGridPivotModel(model);
2944
+ updateUrl(buildModel({
2945
+ pivotModel: simplified
2946
+ }), search, localStorageVersion, historyReplace, columns);
2947
+ propsOnPivotModelChange === null || propsOnPivotModelChange === void 0 ? void 0 : propsOnPivotModelChange(model);
4027
2948
  }
4028
2949
  };
4029
2950
  };
4030
2951
 
4031
- const _excluded = ["apiRef", "autoHeight", "className", "columns", "slots", "slotProps", "filterModel", "columnVisibilityModel", "pinnedColumns", "sortModel", "paginationModel", "height", "hideToolbar", "initialState", "isRowSelectable", "license", "localStorageVersion", "previousLocalStorageVersions", "onFilterModelChange", "rowSelectionModel", "onColumnWidthChange", "onPaginationModelChange", "onRowSelectionModelChange", "onColumnVisibilityModelChange", "onPinnedColumnsChange", "onSortModelChange", "pagination", "paginationPlacement", "paginationProps", "rows", "pageSizeOptions", "sx", "theme", "useRouter", "paginationMode", "rowCount"];
2952
+ const _excluded = ["apiRef", "autoHeight", "className", "columns", "slots", "slotProps", "filterModel", "columnVisibilityModel", "pinnedColumns", "sortModel", "paginationModel", "height", "hideToolbar", "initialState", "isRowSelectable", "license", "localStorageVersion", "previousLocalStorageVersions", "onFilterModelChange", "rowSelectionModel", "onColumnWidthChange", "onPaginationModelChange", "onRowSelectionModelChange", "onColumnVisibilityModelChange", "onPinnedColumnsChange", "onSortModelChange", "onRowGroupingModelChange", "onAggregationModelChange", "onPivotModelChange", "pagination", "paginationPlacement", "paginationProps", "rows", "pageSizeOptions", "sx", "theme", "useRouter", "paginationMode", "rowCount", "density", "dataSource", "filterMode", "sortingMode"];
4032
2953
  const COMPONENT_NAME = 'DataGrid';
4033
2954
  const CLASSNAME = 'redsift-datagrid';
4034
2955
 
@@ -4112,6 +3033,9 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4112
3033
  onColumnVisibilityModelChange: propsOnColumnVisibilityModelChange,
4113
3034
  onPinnedColumnsChange: propsOnPinnedColumnsChange,
4114
3035
  onSortModelChange: propsOnSortModelChange,
3036
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3037
+ onAggregationModelChange: propsOnAggregationModelChange,
3038
+ onPivotModelChange: propsOnPivotModelChange,
4115
3039
  pagination,
4116
3040
  paginationPlacement = 'both',
4117
3041
  paginationProps,
@@ -4121,15 +3045,26 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4121
3045
  theme: propsTheme,
4122
3046
  useRouter,
4123
3047
  paginationMode = 'client',
4124
- rowCount
3048
+ rowCount,
3049
+ density: _density,
3050
+ dataSource,
3051
+ filterMode: propsFilterMode,
3052
+ sortingMode: propsSortingMode
4125
3053
  } = props,
4126
3054
  forwardedProps = _objectWithoutProperties(props, _excluded);
4127
- const theme = useTheme$1(propsTheme);
3055
+ const theme = useTheme(propsTheme);
4128
3056
  const _apiRef = useGridApiRef();
4129
3057
  const apiRef = propsApiRef !== null && propsApiRef !== void 0 ? propsApiRef : _apiRef;
4130
- const RenderedToolbar = slots !== null && slots !== void 0 && slots.toolbar ? slots.toolbar : Toolbar;
4131
3058
  LicenseInfo.setLicenseKey(license);
4132
3059
  const height = propsHeight !== null && propsHeight !== void 0 ? propsHeight : autoHeight ? undefined : '500px';
3060
+
3061
+ // When dataSource is present, MUI manages filter/sort/pagination internally.
3062
+ // We must not pass controlled models — only initialState (one-time) and
3063
+ // write-only onChange handlers for URL/localStorage persistence.
3064
+ const isDataSourceMode = Boolean(dataSource);
3065
+ const effectivePaginationMode = isDataSourceMode ? 'server' : paginationMode;
3066
+ const effectiveFilterMode = isDataSourceMode ? 'server' : propsFilterMode;
3067
+ const effectiveSortingMode = isDataSourceMode ? 'server' : propsSortingMode;
4133
3068
  const {
4134
3069
  onColumnVisibilityModelChange: controlledOnColumnVisibilityModelChange,
4135
3070
  onFilterModelChange: controlledOnFilterModelChange,
@@ -4155,7 +3090,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4155
3090
  density: controlledDensity,
4156
3091
  filterModel,
4157
3092
  onColumnVisibilityModelChange,
4158
- onDensityChange,
4159
3093
  onFilterModelChange,
4160
3094
  onPaginationModelChange,
4161
3095
  onPinnedColumnsChange,
@@ -4164,7 +3098,13 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4164
3098
  pinnedColumns,
4165
3099
  sortModel,
4166
3100
  onColumnWidthChange,
4167
- columnOrderModel
3101
+ columnOrderModel,
3102
+ rowGroupingModel,
3103
+ aggregationModel,
3104
+ pivotModel,
3105
+ onRowGroupingModelChange,
3106
+ onAggregationModelChange,
3107
+ onPivotModelChange
4168
3108
  } = useStatefulTable({
4169
3109
  apiRef: apiRef,
4170
3110
  initialState,
@@ -4175,13 +3115,39 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4175
3115
  onPaginationModelChange: controlledOnPaginationModelChange,
4176
3116
  onPinnedColumnsChange: controlledOnPinnedColumnsChange,
4177
3117
  onSortModelChange: controlledOnSortModelChange,
3118
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3119
+ onAggregationModelChange: propsOnAggregationModelChange,
3120
+ onPivotModelChange: propsOnPivotModelChange,
4178
3121
  useRouter: useRouter,
4179
3122
  localStorageVersion,
4180
3123
  previousLocalStorageVersions
4181
3124
  });
4182
- const [rowSelectionModel, setRowSelectionModel] = useState(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3125
+
3126
+ // In dataSource mode, track pagination locally for the custom pagination slots
3127
+ // (rendered outside DataGridPremium). MUI owns the actual pagination state internally.
3128
+ const [dataSourcePaginationModel, setDataSourcePaginationModel] = useState(paginationModel);
3129
+
3130
+ // The pagination model to use for display in pagination slots
3131
+ const activePaginationModel = isDataSourceMode ? dataSourcePaginationModel : paginationModel;
3132
+
3133
+ // In dataSource mode, the top pagination (outside DataGridPremium) must go through
3134
+ // apiRef to change MUI's internal page. MUI then fires onPaginationModelChange
3135
+ // which updates URL and local state.
3136
+ const dataSourceTopPaginationChange = useCallback(model => {
3137
+ var _apiRef$current;
3138
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.setPaginationModel(model);
3139
+ }, [apiRef]);
3140
+
3141
+ // Wrap onPaginationModelChange to also track state locally in dataSource mode
3142
+ const wrappedOnPaginationModelChange = useCallback((model, details) => {
3143
+ if (isDataSourceMode) {
3144
+ setDataSourcePaginationModel(model);
3145
+ }
3146
+ onPaginationModelChange(model, details);
3147
+ }, [isDataSourceMode, onPaginationModelChange]);
3148
+ const [rowSelectionModel, setRowSelectionModel] = useState(() => normalizeRowSelectionModel(propsRowSelectionModel));
4183
3149
  useEffect(() => {
4184
- setRowSelectionModel(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3150
+ setRowSelectionModel(normalizeRowSelectionModel(propsRowSelectionModel));
4185
3151
  }, [propsRowSelectionModel]);
4186
3152
  const onRowSelectionModelChange = (selectionModel, details) => {
4187
3153
  setRowSelectionModel(selectionModel);
@@ -4200,16 +3166,36 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4200
3166
 
4201
3167
  // The checkboxSelectionVisibleOnly should only be applied to client-side pagination,
4202
3168
  // for server-side pagination it produces inconsistent behavior when selecting all rows in pages 2 and beyond
4203
- const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(paginationMode != 'server');
3169
+ const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(effectivePaginationMode != 'server');
3170
+
3171
+ // Track when the grid API is ready to ensure top pagination renders correctly
3172
+ const [gridReady, setGridReady] = useState(false);
3173
+
3174
+ // Force re-render when the grid API becomes ready (for top pagination)
3175
+ useEffect(() => {
3176
+ if (apiRef.current && !gridReady) {
3177
+ setGridReady(true);
3178
+ }
3179
+ });
3180
+
3181
+ // Sync persisted density via apiRef — initialState only applies on mount,
3182
+ // so this handles SPA back/forward navigation where controlledDensity changes after mount
3183
+ useEffect(() => {
3184
+ if (apiRef.current) {
3185
+ apiRef.current.setDensity(controlledDensity);
3186
+ }
3187
+ }, [controlledDensity, apiRef]);
4204
3188
 
4205
3189
  // in server-side pagination we want to update the selection status
4206
3190
  // every time we navigate between pages, resize our page or select something
4207
3191
  useEffect(() => {
4208
- if (paginationMode == 'server') {
4209
- onServerSideSelectionStatusChange(Array.isArray(rowSelectionModel) ? rowSelectionModel : [rowSelectionModel], apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, paginationModel.page, paginationModel.pageSize);
3192
+ if (effectivePaginationMode == 'server') {
3193
+ onServerSideSelectionStatusChange(rowSelectionModel, apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, activePaginationModel.page, activePaginationModel.pageSize);
4210
3194
  }
4211
- }, [rowSelectionModel, paginationModel.page, paginationModel.pageSize, rows]);
4212
- if (!Array.isArray(rows)) {
3195
+ }, [rowSelectionModel, activePaginationModel.page, activePaginationModel.pageSize, rows]);
3196
+
3197
+ // In dataSource mode MUI provides rows internally; skip the guard.
3198
+ if (!isDataSourceMode && !Array.isArray(rows)) {
4213
3199
  return null;
4214
3200
  }
4215
3201
 
@@ -4218,15 +3204,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4218
3204
  // receive the fresh value in the same render cycle — no extra re-render needed.
4219
3205
  // The ref is kept in sync for the onRowSelectionModelChange callback's deselect logic.
4220
3206
  let selectionStatus = selectionStatusRef.current;
4221
- if (pagination && paginationMode !== 'server' && Array.isArray(rowSelectionModel) && rowSelectionModel.length > 0) {
3207
+ if (pagination && effectivePaginationMode !== 'server' && getSelectionCount(rowSelectionModel) > 0) {
4222
3208
  try {
4223
- // Use manual page slicing with our React state's paginationModel instead of
4224
- // gridPaginatedVisibleSortedGridRow*Selector(apiRef). In MUI v7, the apiRef's
4225
- // internal pagination state can lag behind the React state after a page change,
4226
- // causing the selection status to be one page behind.
4227
- const pageStart = paginationModel.page * paginationModel.pageSize;
4228
- const pageEnd = pageStart + paginationModel.pageSize;
4229
- const selectableRowsInPage = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).slice(pageStart, pageEnd).filter(_ref => {
3209
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors.
3210
+ // MUI's paginated selectors use apiRef internal state which may be stale when
3211
+ // paginationModel prop changes our React state is always up to date.
3212
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3213
+ const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3214
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3215
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref => {
4230
3216
  let {
4231
3217
  model
4232
3218
  } = _ref;
@@ -4238,24 +3224,29 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4238
3224
  id
4239
3225
  } = _ref2;
4240
3226
  return id;
4241
- }) : gridFilteredSortedRowIdsSelector(apiRef).slice(pageStart, pageEnd);
3227
+ }) : pageEntries.map(_ref3 => {
3228
+ let {
3229
+ id
3230
+ } = _ref3;
3231
+ return id;
3232
+ });
4242
3233
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4243
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref3 => {
3234
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref4 => {
4244
3235
  let {
4245
3236
  model
4246
- } = _ref3;
3237
+ } = _ref4;
4247
3238
  return isRowSelectable({
4248
3239
  row: model
4249
3240
  });
4250
- }).map(_ref4 => {
3241
+ }).map(_ref5 => {
4251
3242
  let {
4252
3243
  id
4253
- } = _ref4;
3244
+ } = _ref5;
4254
3245
  return id;
4255
3246
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4256
3247
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4257
- const numberOfSelectedRows = rowSelectionModel.length;
4258
- const selectedOnCurrentPage = selectableRowsInPage.filter(id => rowSelectionModel.includes(id));
3248
+ const numberOfSelectedRows = getSelectionCount(rowSelectionModel);
3249
+ const selectedOnCurrentPage = selectableRowsInPage.filter(id => isRowSelected(rowSelectionModel, id));
4259
3250
  if (numberOfSelectedRows === numberOfSelectableRowsInTable && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
4260
3251
  selectionStatus = {
4261
3252
  type: 'table',
@@ -4280,7 +3271,7 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4280
3271
  } catch {
4281
3272
  // apiRef may not be initialized on first render
4282
3273
  }
4283
- } else if (pagination && paginationMode !== 'server') {
3274
+ } else if (pagination && effectivePaginationMode !== 'server') {
4284
3275
  selectionStatus = {
4285
3276
  type: 'none',
4286
3277
  numberOfSelectedRows: 0
@@ -4309,41 +3300,95 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4309
3300
  ref: datagridRef,
4310
3301
  className: classNames(StatefulDataGrid.className, className),
4311
3302
  $height: height
4312
- }, /*#__PURE__*/React__default.createElement(DataGridPro, _extends({}, forwardedProps, {
3303
+ }, pagination && ['top', 'both'].includes(paginationPlacement) && gridReady ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, {
3304
+ displaySelection: true,
3305
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3306
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3307
+ selectionStatus: selectionStatus,
3308
+ paginationModel: activePaginationModel,
3309
+ onPaginationModelChange: isDataSourceMode ? dataSourceTopPaginationChange : onPaginationModelChange,
3310
+ pageSizeOptions: pageSizeOptions,
3311
+ paginationProps: paginationProps,
3312
+ rowCount: rowCount
3313
+ }) : /*#__PURE__*/React__default.createElement(ControlledPagination, {
3314
+ displaySelection: true,
3315
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3316
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3317
+ selectionStatus: selectionStatus,
3318
+ apiRef: apiRef,
3319
+ isRowSelectable: isRowSelectable,
3320
+ paginationModel: activePaginationModel,
3321
+ onPaginationModelChange: onPaginationModelChange,
3322
+ pageSizeOptions: pageSizeOptions,
3323
+ paginationProps: paginationProps
3324
+ }) : null, /*#__PURE__*/React__default.createElement(DataGridPremium, _extends({}, forwardedProps, {
4313
3325
  apiRef: apiRef,
3326
+ dataSource: dataSource,
4314
3327
  columns: columns,
4315
3328
  columnVisibilityModel: columnVisibilityModel,
4316
- density: controlledDensity,
4317
- filterModel: filterModel,
4318
3329
  onColumnVisibilityModelChange: onColumnVisibilityModelChange,
4319
- onDensityChange: onDensityChange,
4320
- onFilterModelChange: onFilterModelChange,
4321
- onPaginationModelChange: onPaginationModelChange,
4322
3330
  onPinnedColumnsChange: onPinnedColumnsChange,
4323
- onSortModelChange: onSortModelChange,
4324
- paginationModel: paginationModel,
4325
3331
  pinnedColumns: pinnedColumns,
4326
- sortModel: sortModel,
4327
3332
  pageSizeOptions: pageSizeOptions,
4328
3333
  onColumnWidthChange: onColumnWidthChange,
3334
+ rowGroupingModel: rowGroupingModel,
3335
+ onRowGroupingModelChange: onRowGroupingModelChange,
3336
+ aggregationModel: aggregationModel,
3337
+ onAggregationModelChange: onAggregationModelChange,
3338
+ pivotModel: pivotModel,
3339
+ onPivotModelChange: onPivotModelChange
3340
+ // In dataSource mode: models are uncontrolled (MUI owns them),
3341
+ // onChange handlers are write-only for URL/localStorage persistence,
3342
+ // and initialState seeds MUI on mount from the persisted URL state.
3343
+ }, isDataSourceMode ? {
3344
+ onFilterModelChange: onFilterModelChange,
3345
+ onSortModelChange: onSortModelChange,
3346
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4329
3347
  initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3348
+ density: controlledDensity,
3349
+ columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
3350
+ orderedFields: columnOrderModel
3351
+ }),
3352
+ filter: {
3353
+ filterModel
3354
+ },
3355
+ sorting: {
3356
+ sortModel
3357
+ },
3358
+ pagination: {
3359
+ paginationModel
3360
+ }
3361
+ })
3362
+ } : {
3363
+ filterModel,
3364
+ sortModel,
3365
+ paginationModel,
3366
+ onFilterModelChange: onFilterModelChange,
3367
+ onSortModelChange: onSortModelChange,
3368
+ onPaginationModelChange: wrappedOnPaginationModelChange,
3369
+ initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3370
+ density: controlledDensity,
4330
3371
  columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
4331
3372
  orderedFields: columnOrderModel
4332
3373
  })
4333
- }),
3374
+ })
3375
+ }, {
4334
3376
  isRowSelectable: isRowSelectable,
4335
3377
  pagination: pagination,
4336
- paginationMode: paginationMode,
4337
- keepNonExistentRowsSelected: paginationMode == 'server',
4338
- rows: rows,
3378
+ paginationMode: effectivePaginationMode,
3379
+ filterMode: effectiveFilterMode,
3380
+ sortingMode: effectiveSortingMode,
3381
+ keepNonExistentRowsSelected: effectivePaginationMode == 'server',
3382
+ rows: isDataSourceMode ? [] : rows,
4339
3383
  rowCount: rowCount,
4340
3384
  autoHeight: autoHeight,
4341
3385
  checkboxSelectionVisibleOnly: checkboxSelectionVisibleOnly,
3386
+ disableRowSelectionExcludeModel: true,
3387
+ showToolbar: !hideToolbar,
4342
3388
  slots: _objectSpread2(_objectSpread2({
4343
3389
  baseButton: BaseButton,
4344
3390
  baseCheckbox: BaseCheckbox,
4345
- // baseTextField,
4346
- basePopper: BasePopper,
3391
+ baseIconButton: BaseIconButton,
4347
3392
  columnFilteredIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
4348
3393
  displayName: "columnFilteredIcon"
4349
3394
  })),
@@ -4378,31 +3423,14 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4378
3423
  displayName: "openFilterButtonIcon"
4379
3424
  }))
4380
3425
  }, slots), {}, {
4381
- toolbar: props => /*#__PURE__*/React__default.createElement(ToolbarWrapper, _extends({}, props, {
4382
- hideToolbar: hideToolbar,
4383
- RenderedToolbar: RenderedToolbar,
4384
- filterModel: filterModel,
4385
- onFilterModelChange: onFilterModelChange,
4386
- pagination: pagination,
4387
- paginationPlacement: paginationPlacement,
4388
- selectionStatus: selectionStatus,
4389
- apiRef: apiRef,
4390
- isRowSelectable: isRowSelectable,
4391
- paginationModel: paginationModel,
4392
- onPaginationModelChange: onPaginationModelChange,
4393
- pageSizeOptions: pageSizeOptions,
4394
- paginationProps: paginationProps,
4395
- paginationMode: paginationMode,
4396
- rowCount: rowCount
4397
- })),
4398
3426
  pagination: props => {
4399
- return pagination ? paginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends({}, props, {
3427
+ return pagination ? effectivePaginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends({}, props, {
4400
3428
  displaySelection: false,
4401
3429
  displayRowsPerPage: ['bottom', 'both'].includes(paginationPlacement),
4402
3430
  displayPagination: ['bottom', 'both'].includes(paginationPlacement),
4403
3431
  selectionStatus: selectionStatus,
4404
- paginationModel: paginationModel,
4405
- onPaginationModelChange: onPaginationModelChange,
3432
+ paginationModel: activePaginationModel,
3433
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4406
3434
  pageSizeOptions: pageSizeOptions,
4407
3435
  paginationProps: paginationProps,
4408
3436
  rowCount: rowCount
@@ -4413,8 +3441,8 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4413
3441
  selectionStatus: selectionStatus,
4414
3442
  apiRef: apiRef,
4415
3443
  isRowSelectable: isRowSelectable,
4416
- paginationModel: paginationModel,
4417
- onPaginationModelChange: onPaginationModelChange,
3444
+ paginationModel: activePaginationModel,
3445
+ onPaginationModelChange: wrappedOnPaginationModelChange,
4418
3446
  pageSizeOptions: pageSizeOptions,
4419
3447
  paginationProps: paginationProps
4420
3448
  })) : null;
@@ -4423,41 +3451,50 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4423
3451
  slotProps: _objectSpread2({}, slotProps),
4424
3452
  rowSelectionModel: rowSelectionModel,
4425
3453
  onRowSelectionModelChange: (newSelectionModel, details) => {
4426
- if (pagination && paginationMode != 'server') {
4427
- const cbPageStart = paginationModel.page * paginationModel.pageSize;
4428
- const cbPageEnd = cbPageStart + paginationModel.pageSize;
4429
- const selectableRowsInPage = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).slice(cbPageStart, cbPageEnd).filter(_ref5 => {
3454
+ if (pagination && effectivePaginationMode != 'server') {
3455
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors
3456
+ // to avoid stale apiRef pagination state.
3457
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3458
+ const pageStart = activePaginationModel.page * activePaginationModel.pageSize;
3459
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + activePaginationModel.pageSize);
3460
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref6 => {
4430
3461
  let {
4431
3462
  model
4432
- } = _ref5;
3463
+ } = _ref6;
4433
3464
  return isRowSelectable({
4434
3465
  row: model
4435
3466
  });
4436
- }).map(_ref6 => {
3467
+ }).map(_ref7 => {
4437
3468
  let {
4438
3469
  id
4439
- } = _ref6;
3470
+ } = _ref7;
4440
3471
  return id;
4441
- }) : gridFilteredSortedRowIdsSelector(apiRef).slice(cbPageStart, cbPageEnd);
3472
+ }) : pageEntries.map(_ref8 => {
3473
+ let {
3474
+ id
3475
+ } = _ref8;
3476
+ return id;
3477
+ });
4442
3478
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4443
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref7 => {
3479
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref9 => {
4444
3480
  let {
4445
3481
  model
4446
- } = _ref7;
3482
+ } = _ref9;
4447
3483
  return isRowSelectable({
4448
3484
  row: model
4449
3485
  });
4450
- }).map(_ref8 => {
3486
+ }).map(_ref10 => {
4451
3487
  let {
4452
3488
  id
4453
- } = _ref8;
3489
+ } = _ref10;
4454
3490
  return id;
4455
3491
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4456
3492
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4457
- const numberOfSelectedRows = newSelectionModel.length;
3493
+ const numberOfSelectedRows = getSelectionCount(newSelectionModel);
4458
3494
  if (selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable - numberOfSelectableRowsInPage || selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable || selectionStatusRef.current.type === 'page' && numberOfSelectedRows === numberOfSelectableRowsInPage) {
4459
3495
  setTimeout(() => {
4460
- apiRef.current.selectRows([], true, true);
3496
+ var _apiRef$current2;
3497
+ (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.selectRows([], true, true);
4461
3498
  }, 0);
4462
3499
  }
4463
3500
  if (numberOfSelectedRows === numberOfSelectableRowsInPage && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
@@ -4499,5 +3536,5 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4499
3536
  StatefulDataGrid.className = CLASSNAME;
4500
3537
  StatefulDataGrid.displayName = COMPONENT_NAME;
4501
3538
 
4502
- export { convertToDisplayFormat as $, ARRAY_IS_EMPTY as A, Box$1 as B, CONTAINS_ANY_OF as C, DOES_NOT_CONTAIN as D, ENDS_WITH_ANY_OF as E, IS as F, IS_NOT as G, HAS_WITH_SELECT as H, IS_ANY_OF as I, getGridStringOperators as J, getGridStringArrayOperators as K, getGridStringArrayOperatorsWithSelect as L, getGridStringArrayOperatorsWithSelectOnStringArrayColumns as M, FILTER_MODEL_KEY as N, SORT_MODEL_KEY as O, PAGINATION_MODEL_KEY as P, PINNED_COLUMNS as Q, DIMENSION_MODEL_KEY as R, STARTS_WITH_ANY_OF as S, TextField$1 as T, FILTER_SEARCH_KEY as U, VISIBILITY_MODEL_KEY as V, DENSITY_MODEL_KEY as W, COLUMN_ORDER_MODEL_KEY as X, CATEGORIES as Y, buildStorageKey as Z, clearPreviousVersionStorage as _, DOES_NOT_EQUAL as a, convertFromDisplayFormat as a0, getDecodedSearchFromUrl as a1, buildQueryParamsString as a2, areSearchStringsEqual as a3, decodeValue as a4, encodeValue as a5, urlSearchParamsToString as a6, numberOperatorEncoder as a7, numberOperatorDecoder as a8, isOperatorValueValid as a9, isValueValid as aa, getFilterModelFromString as ab, getSearchParamsFromFilterModel as ac, getSortingFromString as ad, getSearchParamsFromSorting as ae, getPaginationFromString as af, getSearchParamsFromPagination as ag, getColumnVisibilityFromString as ah, getSearchParamsFromColumnVisibility as ai, getPinnedColumnsFromString as aj, getSearchParamsFromPinnedColumns as ak, getSearchParamsFromTab as al, getDensityFromString as am, getSearchParamsFromDensity as an, getColumnOrderFromString as ao, getSearchParamsFromColumnOrder as ap, getFinalSearch as aq, getModelsParsedOrUpdateLocalStorage as ar, updateUrl as as, areFilterModelsEquivalent as at, StatefulDataGrid as au, DOES_NOT_START_WITH as b, DOES_NOT_END_WITH as c, IS_NOT_ANY_OF as d, DOES_NOT_CONTAIN_ANY_OF as e, DOES_NOT_START_WITH_ANY_OF as f, DOES_NOT_END_WITH_ANY_OF as g, IS_BETWEEN as h, IS_WITH_SELECT as i, IS_NOT_WITH_SELECT as j, IS_ANY_OF_WITH_SELECT as k, IS_NOT_ANY_OF_WITH_SELECT as l, ARRAY_IS_NOT_EMPTY as m, DOES_NOT_HAVE_WITH_SELECT as n, operatorList as o, HAS_ANY_OF_WITH_SELECT as p, HAS_ALL_OF_WITH_SELECT as q, DOES_NOT_HAVE_ANY_OF_WITH_SELECT as r, HAS_ONLY_WITH_SELECT as s, HAS as t, DOES_NOT_HAVE as u, HAS_ANY_OF as v, HAS_ALL_OF as w, DOES_NOT_HAVE_ANY_OF as x, HAS_ONLY as y, getGridNumericOperators as z };
3539
+ export { clearPreviousVersionStorage as $, ARRAY_IS_EMPTY as A, IS as B, CONTAINS_ANY_OF as C, DOES_NOT_CONTAIN as D, ENDS_WITH_ANY_OF as E, IS_NOT as F, getGridStringOperators as G, HAS_WITH_SELECT as H, IS_ANY_OF as I, getGridStringArrayOperators as J, getGridStringArrayOperatorsWithSelect as K, getGridStringArrayOperatorsWithSelectOnStringArrayColumns as L, FILTER_MODEL_KEY as M, SORT_MODEL_KEY as N, PINNED_COLUMNS as O, PAGINATION_MODEL_KEY as P, DIMENSION_MODEL_KEY as Q, FILTER_SEARCH_KEY as R, STARTS_WITH_ANY_OF as S, DENSITY_MODEL_KEY as T, COLUMN_ORDER_MODEL_KEY as U, VISIBILITY_MODEL_KEY as V, ROW_GROUPING_MODEL_KEY as W, AGGREGATION_MODEL_KEY as X, PIVOT_MODEL_KEY as Y, CATEGORIES as Z, buildStorageKey as _, DOES_NOT_EQUAL as a, convertToDisplayFormat as a0, convertFromDisplayFormat as a1, getDecodedSearchFromUrl as a2, buildQueryParamsString as a3, areSearchStringsEqual as a4, decodeValue as a5, encodeValue as a6, urlSearchParamsToString as a7, numberOperatorEncoder as a8, numberOperatorDecoder as a9, areFilterModelsEquivalent as aA, StatefulDataGrid as aB, isOperatorValueValid as aa, isValueValid as ab, getFilterModelFromString as ac, getSearchParamsFromFilterModel as ad, getSortingFromString as ae, getSearchParamsFromSorting as af, getPaginationFromString as ag, getSearchParamsFromPagination as ah, getColumnVisibilityFromString as ai, getSearchParamsFromColumnVisibility as aj, getPinnedColumnsFromString as ak, getSearchParamsFromPinnedColumns as al, getSearchParamsFromTab as am, getDensityFromString as an, getSearchParamsFromDensity as ao, getColumnOrderFromString as ap, getSearchParamsFromColumnOrder as aq, getRowGroupingFromString as ar, getSearchParamsFromRowGrouping as as, getAggregationFromString as at, getSearchParamsFromAggregation as au, getPivotFromString as av, getSearchParamsFromPivot as aw, getFinalSearch as ax, getModelsParsedOrUpdateLocalStorage as ay, updateUrl as az, DOES_NOT_START_WITH as b, DOES_NOT_END_WITH as c, IS_NOT_ANY_OF as d, DOES_NOT_CONTAIN_ANY_OF as e, DOES_NOT_START_WITH_ANY_OF as f, DOES_NOT_END_WITH_ANY_OF as g, IS_BETWEEN as h, IS_WITH_SELECT as i, IS_NOT_WITH_SELECT as j, IS_ANY_OF_WITH_SELECT as k, IS_NOT_ANY_OF_WITH_SELECT as l, ARRAY_IS_NOT_EMPTY as m, DOES_NOT_HAVE_WITH_SELECT as n, operatorList as o, HAS_ANY_OF_WITH_SELECT as p, HAS_ALL_OF_WITH_SELECT as q, DOES_NOT_HAVE_ANY_OF_WITH_SELECT as r, HAS_ONLY_WITH_SELECT as s, HAS as t, DOES_NOT_HAVE as u, HAS_ANY_OF as v, HAS_ALL_OF as w, DOES_NOT_HAVE_ANY_OF as x, HAS_ONLY as y, getGridNumericOperators as z };
4503
3540
  //# sourceMappingURL=StatefulDataGrid2.js.map