@redsift/table 12.5.1-muiv7 → 12.5.1

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"];
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,13 +3045,13 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4121
3045
  theme: propsTheme,
4122
3046
  useRouter,
4123
3047
  paginationMode = 'client',
4124
- rowCount
3048
+ rowCount,
3049
+ density: _density
4125
3050
  } = props,
4126
3051
  forwardedProps = _objectWithoutProperties(props, _excluded);
4127
- const theme = useTheme$1(propsTheme);
3052
+ const theme = useTheme(propsTheme);
4128
3053
  const _apiRef = useGridApiRef();
4129
3054
  const apiRef = propsApiRef !== null && propsApiRef !== void 0 ? propsApiRef : _apiRef;
4130
- const RenderedToolbar = slots !== null && slots !== void 0 && slots.toolbar ? slots.toolbar : Toolbar;
4131
3055
  LicenseInfo.setLicenseKey(license);
4132
3056
  const height = propsHeight !== null && propsHeight !== void 0 ? propsHeight : autoHeight ? undefined : '500px';
4133
3057
  const {
@@ -4155,7 +3079,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4155
3079
  density: controlledDensity,
4156
3080
  filterModel,
4157
3081
  onColumnVisibilityModelChange,
4158
- onDensityChange,
4159
3082
  onFilterModelChange,
4160
3083
  onPaginationModelChange,
4161
3084
  onPinnedColumnsChange,
@@ -4164,7 +3087,13 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4164
3087
  pinnedColumns,
4165
3088
  sortModel,
4166
3089
  onColumnWidthChange,
4167
- columnOrderModel
3090
+ columnOrderModel,
3091
+ rowGroupingModel,
3092
+ aggregationModel,
3093
+ pivotModel,
3094
+ onRowGroupingModelChange,
3095
+ onAggregationModelChange,
3096
+ onPivotModelChange
4168
3097
  } = useStatefulTable({
4169
3098
  apiRef: apiRef,
4170
3099
  initialState,
@@ -4175,13 +3104,16 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4175
3104
  onPaginationModelChange: controlledOnPaginationModelChange,
4176
3105
  onPinnedColumnsChange: controlledOnPinnedColumnsChange,
4177
3106
  onSortModelChange: controlledOnSortModelChange,
3107
+ onRowGroupingModelChange: propsOnRowGroupingModelChange,
3108
+ onAggregationModelChange: propsOnAggregationModelChange,
3109
+ onPivotModelChange: propsOnPivotModelChange,
4178
3110
  useRouter: useRouter,
4179
3111
  localStorageVersion,
4180
3112
  previousLocalStorageVersions
4181
3113
  });
4182
- const [rowSelectionModel, setRowSelectionModel] = useState(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3114
+ const [rowSelectionModel, setRowSelectionModel] = useState(() => normalizeRowSelectionModel(propsRowSelectionModel));
4183
3115
  useEffect(() => {
4184
- setRowSelectionModel(propsRowSelectionModel !== null && propsRowSelectionModel !== void 0 ? propsRowSelectionModel : []);
3116
+ setRowSelectionModel(normalizeRowSelectionModel(propsRowSelectionModel));
4185
3117
  }, [propsRowSelectionModel]);
4186
3118
  const onRowSelectionModelChange = (selectionModel, details) => {
4187
3119
  setRowSelectionModel(selectionModel);
@@ -4202,11 +3134,29 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4202
3134
  // for server-side pagination it produces inconsistent behavior when selecting all rows in pages 2 and beyond
4203
3135
  const checkboxSelectionVisibleOnly = Boolean(pagination) && Boolean(paginationMode != 'server');
4204
3136
 
3137
+ // Track when the grid API is ready to ensure top pagination renders correctly
3138
+ const [gridReady, setGridReady] = useState(false);
3139
+
3140
+ // Force re-render when the grid API becomes ready (for top pagination)
3141
+ useEffect(() => {
3142
+ if (apiRef.current && !gridReady) {
3143
+ setGridReady(true);
3144
+ }
3145
+ });
3146
+
3147
+ // Sync persisted density via apiRef — initialState only applies on mount,
3148
+ // so this handles SPA back/forward navigation where controlledDensity changes after mount
3149
+ useEffect(() => {
3150
+ if (apiRef.current) {
3151
+ apiRef.current.setDensity(controlledDensity);
3152
+ }
3153
+ }, [controlledDensity, apiRef]);
3154
+
4205
3155
  // in server-side pagination we want to update the selection status
4206
3156
  // every time we navigate between pages, resize our page or select something
4207
3157
  useEffect(() => {
4208
3158
  if (paginationMode == 'server') {
4209
- onServerSideSelectionStatusChange(Array.isArray(rowSelectionModel) ? rowSelectionModel : [rowSelectionModel], apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, paginationModel.page, paginationModel.pageSize);
3159
+ onServerSideSelectionStatusChange(rowSelectionModel, apiRef, selectionStatusRef, forceSelectionUpdate, isRowSelectable, paginationModel.page, paginationModel.pageSize);
4210
3160
  }
4211
3161
  }, [rowSelectionModel, paginationModel.page, paginationModel.pageSize, rows]);
4212
3162
  if (!Array.isArray(rows)) {
@@ -4218,15 +3168,15 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4218
3168
  // receive the fresh value in the same render cycle — no extra re-render needed.
4219
3169
  // The ref is kept in sync for the onRowSelectionModelChange callback's deselect logic.
4220
3170
  let selectionStatus = selectionStatusRef.current;
4221
- if (pagination && paginationMode !== 'server' && Array.isArray(rowSelectionModel) && rowSelectionModel.length > 0) {
3171
+ if (pagination && paginationMode !== 'server' && getSelectionCount(rowSelectionModel) > 0) {
4222
3172
  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.
3173
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors.
3174
+ // MUI's paginated selectors use apiRef internal state which may be stale when
3175
+ // paginationModel prop changes our React state is always up to date.
3176
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
4227
3177
  const pageStart = paginationModel.page * paginationModel.pageSize;
4228
- const pageEnd = pageStart + paginationModel.pageSize;
4229
- const selectableRowsInPage = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).slice(pageStart, pageEnd).filter(_ref => {
3178
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + paginationModel.pageSize);
3179
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref => {
4230
3180
  let {
4231
3181
  model
4232
3182
  } = _ref;
@@ -4238,24 +3188,29 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4238
3188
  id
4239
3189
  } = _ref2;
4240
3190
  return id;
4241
- }) : gridFilteredSortedRowIdsSelector(apiRef).slice(pageStart, pageEnd);
3191
+ }) : pageEntries.map(_ref3 => {
3192
+ let {
3193
+ id
3194
+ } = _ref3;
3195
+ return id;
3196
+ });
4242
3197
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4243
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref3 => {
3198
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref4 => {
4244
3199
  let {
4245
3200
  model
4246
- } = _ref3;
3201
+ } = _ref4;
4247
3202
  return isRowSelectable({
4248
3203
  row: model
4249
3204
  });
4250
- }).map(_ref4 => {
3205
+ }).map(_ref5 => {
4251
3206
  let {
4252
3207
  id
4253
- } = _ref4;
3208
+ } = _ref5;
4254
3209
  return id;
4255
3210
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4256
3211
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4257
- const numberOfSelectedRows = rowSelectionModel.length;
4258
- const selectedOnCurrentPage = selectableRowsInPage.filter(id => rowSelectionModel.includes(id));
3212
+ const numberOfSelectedRows = getSelectionCount(rowSelectionModel);
3213
+ const selectedOnCurrentPage = selectableRowsInPage.filter(id => isRowSelected(rowSelectionModel, id));
4259
3214
  if (numberOfSelectedRows === numberOfSelectableRowsInTable && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
4260
3215
  selectionStatus = {
4261
3216
  type: 'table',
@@ -4309,14 +3264,33 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4309
3264
  ref: datagridRef,
4310
3265
  className: classNames(StatefulDataGrid.className, className),
4311
3266
  $height: height
4312
- }, /*#__PURE__*/React__default.createElement(DataGridPro, _extends({}, forwardedProps, {
3267
+ }, pagination && ['top', 'both'].includes(paginationPlacement) && gridReady ? paginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, {
3268
+ displaySelection: true,
3269
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3270
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3271
+ selectionStatus: selectionStatus,
3272
+ paginationModel: paginationModel,
3273
+ onPaginationModelChange: onPaginationModelChange,
3274
+ pageSizeOptions: pageSizeOptions,
3275
+ paginationProps: paginationProps,
3276
+ rowCount: rowCount
3277
+ }) : /*#__PURE__*/React__default.createElement(ControlledPagination, {
3278
+ displaySelection: true,
3279
+ displayRowsPerPage: ['top', 'both'].includes(paginationPlacement),
3280
+ displayPagination: ['top', 'both'].includes(paginationPlacement),
3281
+ selectionStatus: selectionStatus,
3282
+ apiRef: apiRef,
3283
+ isRowSelectable: isRowSelectable,
3284
+ paginationModel: paginationModel,
3285
+ onPaginationModelChange: onPaginationModelChange,
3286
+ pageSizeOptions: pageSizeOptions,
3287
+ paginationProps: paginationProps
3288
+ }) : null, /*#__PURE__*/React__default.createElement(DataGridPremium, _extends({}, forwardedProps, {
4313
3289
  apiRef: apiRef,
4314
3290
  columns: columns,
4315
3291
  columnVisibilityModel: columnVisibilityModel,
4316
- density: controlledDensity,
4317
3292
  filterModel: filterModel,
4318
3293
  onColumnVisibilityModelChange: onColumnVisibilityModelChange,
4319
- onDensityChange: onDensityChange,
4320
3294
  onFilterModelChange: onFilterModelChange,
4321
3295
  onPaginationModelChange: onPaginationModelChange,
4322
3296
  onPinnedColumnsChange: onPinnedColumnsChange,
@@ -4326,7 +3300,14 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4326
3300
  sortModel: sortModel,
4327
3301
  pageSizeOptions: pageSizeOptions,
4328
3302
  onColumnWidthChange: onColumnWidthChange,
3303
+ rowGroupingModel: rowGroupingModel,
3304
+ onRowGroupingModelChange: onRowGroupingModelChange,
3305
+ aggregationModel: aggregationModel,
3306
+ onAggregationModelChange: onAggregationModelChange,
3307
+ pivotModel: pivotModel,
3308
+ onPivotModelChange: onPivotModelChange,
4329
3309
  initialState: _objectSpread2(_objectSpread2({}, initialState), {}, {
3310
+ density: controlledDensity,
4330
3311
  columns: _objectSpread2(_objectSpread2({}, initialState === null || initialState === void 0 ? void 0 : initialState.columns), {}, {
4331
3312
  orderedFields: columnOrderModel
4332
3313
  })
@@ -4339,11 +3320,12 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4339
3320
  rowCount: rowCount,
4340
3321
  autoHeight: autoHeight,
4341
3322
  checkboxSelectionVisibleOnly: checkboxSelectionVisibleOnly,
3323
+ disableRowSelectionExcludeModel: true,
3324
+ showToolbar: !hideToolbar,
4342
3325
  slots: _objectSpread2(_objectSpread2({
4343
3326
  baseButton: BaseButton,
4344
3327
  baseCheckbox: BaseCheckbox,
4345
- // baseTextField,
4346
- basePopper: BasePopper,
3328
+ baseIconButton: BaseIconButton,
4347
3329
  columnFilteredIcon: props => /*#__PURE__*/React__default.createElement(BaseIcon, _extends({}, props, {
4348
3330
  displayName: "columnFilteredIcon"
4349
3331
  })),
@@ -4378,23 +3360,6 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4378
3360
  displayName: "openFilterButtonIcon"
4379
3361
  }))
4380
3362
  }, 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
3363
  pagination: props => {
4399
3364
  return pagination ? paginationMode == 'server' ? /*#__PURE__*/React__default.createElement(ServerSideControlledPagination, _extends({}, props, {
4400
3365
  displaySelection: false,
@@ -4424,40 +3389,49 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4424
3389
  rowSelectionModel: rowSelectionModel,
4425
3390
  onRowSelectionModelChange: (newSelectionModel, details) => {
4426
3391
  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 => {
3392
+ // Use manual page slicing instead of gridPaginatedVisibleSorted* selectors
3393
+ // to avoid stale apiRef pagination state.
3394
+ const allFilteredEntries = gridFilteredSortedRowEntriesSelector(apiRef);
3395
+ const pageStart = paginationModel.page * paginationModel.pageSize;
3396
+ const pageEntries = allFilteredEntries.slice(pageStart, pageStart + paginationModel.pageSize);
3397
+ const selectableRowsInPage = isRowSelectable ? pageEntries.filter(_ref6 => {
4430
3398
  let {
4431
3399
  model
4432
- } = _ref5;
3400
+ } = _ref6;
4433
3401
  return isRowSelectable({
4434
3402
  row: model
4435
3403
  });
4436
- }).map(_ref6 => {
3404
+ }).map(_ref7 => {
4437
3405
  let {
4438
3406
  id
4439
- } = _ref6;
3407
+ } = _ref7;
4440
3408
  return id;
4441
- }) : gridFilteredSortedRowIdsSelector(apiRef).slice(cbPageStart, cbPageEnd);
3409
+ }) : pageEntries.map(_ref8 => {
3410
+ let {
3411
+ id
3412
+ } = _ref8;
3413
+ return id;
3414
+ });
4442
3415
  const numberOfSelectableRowsInPage = selectableRowsInPage.length;
4443
- const selectableRowsInTable = isRowSelectable ? gridFilteredSortedRowEntriesSelector(apiRef).filter(_ref7 => {
3416
+ const selectableRowsInTable = isRowSelectable ? allFilteredEntries.filter(_ref9 => {
4444
3417
  let {
4445
3418
  model
4446
- } = _ref7;
3419
+ } = _ref9;
4447
3420
  return isRowSelectable({
4448
3421
  row: model
4449
3422
  });
4450
- }).map(_ref8 => {
3423
+ }).map(_ref10 => {
4451
3424
  let {
4452
3425
  id
4453
- } = _ref8;
3426
+ } = _ref10;
4454
3427
  return id;
4455
3428
  }) : gridFilteredSortedRowIdsSelector(apiRef);
4456
3429
  const numberOfSelectableRowsInTable = selectableRowsInTable.length;
4457
- const numberOfSelectedRows = newSelectionModel.length;
3430
+ const numberOfSelectedRows = getSelectionCount(newSelectionModel);
4458
3431
  if (selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable - numberOfSelectableRowsInPage || selectionStatusRef.current.type === 'table' && numberOfSelectedRows === numberOfSelectableRowsInTable || selectionStatusRef.current.type === 'page' && numberOfSelectedRows === numberOfSelectableRowsInPage) {
4459
3432
  setTimeout(() => {
4460
- apiRef.current.selectRows([], true, true);
3433
+ var _apiRef$current;
3434
+ (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.selectRows([], true, true);
4461
3435
  }, 0);
4462
3436
  }
4463
3437
  if (numberOfSelectedRows === numberOfSelectableRowsInPage && numberOfSelectableRowsInPage < numberOfSelectableRowsInTable) {
@@ -4499,5 +3473,5 @@ const StatefulDataGrid = /*#__PURE__*/forwardRef((props, ref) => {
4499
3473
  StatefulDataGrid.className = CLASSNAME;
4500
3474
  StatefulDataGrid.displayName = COMPONENT_NAME;
4501
3475
 
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 };
3476
+ 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
3477
  //# sourceMappingURL=StatefulDataGrid2.js.map