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