@mui/x-data-grid 7.8.0 → 7.9.0
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/CHANGELOG.md +66 -0
- package/DataGrid/useDataGridProps.js +9 -2
- package/components/GridLoadingOverlay.d.ts +15 -3
- package/components/GridLoadingOverlay.js +48 -4
- package/components/GridRow.js +2 -1
- package/components/GridSkeletonLoadingOverlay.d.ts +3 -0
- package/components/GridSkeletonLoadingOverlay.js +181 -0
- package/components/base/GridOverlays.d.ts +11 -1
- package/components/base/GridOverlays.js +25 -39
- package/components/cell/GridSkeletonCell.d.ts +13 -6
- package/components/cell/GridSkeletonCell.js +61 -19
- package/components/containers/GridRootStyles.js +11 -2
- package/components/virtualization/GridVirtualScroller.js +7 -5
- package/constants/gridClasses.d.ts +9 -0
- package/constants/gridClasses.js +1 -1
- package/hooks/features/overlays/useGridOverlays.d.ts +11 -0
- package/hooks/features/overlays/useGridOverlays.js +35 -0
- package/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
- package/hooks/utils/index.d.ts +0 -1
- package/hooks/utils/index.js +0 -1
- package/index.js +1 -1
- package/models/gridSlotsComponentsProps.d.ts +2 -1
- package/modern/DataGrid/useDataGridProps.js +9 -2
- package/modern/components/GridLoadingOverlay.js +48 -4
- package/modern/components/GridRow.js +2 -1
- package/modern/components/GridSkeletonLoadingOverlay.js +181 -0
- package/modern/components/base/GridOverlays.js +25 -39
- package/modern/components/cell/GridSkeletonCell.js +61 -19
- package/modern/components/containers/GridRootStyles.js +11 -2
- package/modern/components/virtualization/GridVirtualScroller.js +7 -5
- package/modern/constants/gridClasses.js +1 -1
- package/modern/hooks/features/overlays/useGridOverlays.js +35 -0
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
- package/modern/hooks/utils/index.js +0 -1
- package/modern/index.js +1 -1
- package/modern/utils/utils.js +10 -2
- package/node/DataGrid/useDataGridProps.js +9 -2
- package/node/components/GridLoadingOverlay.js +48 -4
- package/node/components/GridRow.js +2 -1
- package/node/components/GridSkeletonLoadingOverlay.js +189 -0
- package/node/components/base/GridOverlays.js +25 -39
- package/node/components/cell/GridSkeletonCell.js +60 -18
- package/node/components/containers/GridRootStyles.js +11 -2
- package/node/components/virtualization/GridVirtualScroller.js +6 -4
- package/node/constants/gridClasses.js +1 -1
- package/node/hooks/features/overlays/useGridOverlays.js +42 -0
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
- package/node/hooks/utils/index.js +0 -12
- package/node/index.js +1 -1
- package/node/utils/utils.js +11 -3
- package/package.json +5 -4
- package/utils/utils.d.ts +8 -1
- package/utils/utils.js +10 -2
- package/hooks/utils/useResizeObserver.d.ts +0 -2
- package/hooks/utils/useResizeObserver.js +0 -36
- package/modern/hooks/utils/useResizeObserver.js +0 -36
- package/node/hooks/utils/useResizeObserver.js +0 -44
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,72 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 7.9.0
|
|
7
|
+
|
|
8
|
+
_Jul 5, 2024_
|
|
9
|
+
|
|
10
|
+
We'd like to offer a big thanks to the 7 contributors who made this release possible. Here are some highlights ✨:
|
|
11
|
+
|
|
12
|
+
- 🔄 Add loading overlay variants, including a skeleton loader option to the Data Grid component. See [Loading overlay docs](https://mui.com/x/react-data-grid/overlays/#loading-overlay) for more details.
|
|
13
|
+
- 🌳 Add `selectItem` and `getItemDOMElement` methods to the TreeView component public API
|
|
14
|
+
- ⛏️ Make the `usePickersTranslations` hook public in the pickers component
|
|
15
|
+
- 🐞 Bugfixes
|
|
16
|
+
|
|
17
|
+
<!--/ HIGHLIGHT_ABOVE_SEPARATOR /-->
|
|
18
|
+
|
|
19
|
+
### Data Grid
|
|
20
|
+
|
|
21
|
+
#### `@mui/x-data-grid@7.9.0`
|
|
22
|
+
|
|
23
|
+
- [DataGrid] Add skeleton loading overlay support (#13293) @KenanYusuf
|
|
24
|
+
- [DataGrid] Fix pagination when `pagination={undefined}` (#13349) @sai6855
|
|
25
|
+
|
|
26
|
+
#### `@mui/x-data-grid-pro@7.9.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
27
|
+
|
|
28
|
+
Same changes as in `@mui/x-data-grid@7.9.0`.
|
|
29
|
+
|
|
30
|
+
#### `@mui/x-data-grid-premium@7.9.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
31
|
+
|
|
32
|
+
Same changes as in `@mui/x-data-grid-pro@7.9.0`.
|
|
33
|
+
|
|
34
|
+
### Date and Time Pickers
|
|
35
|
+
|
|
36
|
+
#### `@mui/x-date-pickers@7.9.0`
|
|
37
|
+
|
|
38
|
+
- [pickers] Make the `usePickersTranslations` hook public (#13657) @flaviendelangle
|
|
39
|
+
|
|
40
|
+
#### `@mui/x-date-pickers-pro@7.9.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
41
|
+
|
|
42
|
+
Same changes as in `@mui/x-date-pickers@7.9.0`.
|
|
43
|
+
|
|
44
|
+
### Charts
|
|
45
|
+
|
|
46
|
+
#### `@mui/x-charts@7.9.0`
|
|
47
|
+
|
|
48
|
+
- [charts] Add Heatmap (unreleased) (#13209) @alexfauquette
|
|
49
|
+
- [charts] Add initial `Zoom&Pan` to the Pro charts (unreleased) (#13405) @JCQuintas
|
|
50
|
+
- [charts] Fix Axis Highlight on horizontal bar charts regression (#13717) @JCQuintas
|
|
51
|
+
- [charts] Improve charts interaction for mobile users (#13692) @JCQuintas
|
|
52
|
+
- [charts] Add documentation on how to disable the tooltip on charts (#13724) @JCQuintas
|
|
53
|
+
|
|
54
|
+
### Tree View
|
|
55
|
+
|
|
56
|
+
#### `@mui/x-tree-view@7.9.0`
|
|
57
|
+
|
|
58
|
+
- [TreeView] Add `selectItem` and `getItemDOMElement` methods to the public API (#13485) @flaviendelangle
|
|
59
|
+
|
|
60
|
+
### Docs
|
|
61
|
+
|
|
62
|
+
- [docs] Fix custom "no results overlay" demo in dark mode (#13715) @KenanYusuf
|
|
63
|
+
|
|
64
|
+
### Core
|
|
65
|
+
|
|
66
|
+
- [core] Add `react_next` workflow in CircleCI (#13360) @cherniavskii
|
|
67
|
+
- [core] Create a new package to share utils across X packages (#13528) @flaviendelangle
|
|
68
|
+
- [core] Fix dependency setup (#13684) @LukasTy
|
|
69
|
+
- [core] Remove `jscodeshift-add-imports` package (#13720) @LukasTy
|
|
70
|
+
- [code-infra] Cleanup monorepo and `@mui/docs` usage (#13713) @LukasTy
|
|
71
|
+
|
|
6
72
|
## 7.8.0
|
|
7
73
|
|
|
8
74
|
_Jun 28, 2024_
|
|
@@ -85,8 +85,15 @@ export const useDataGridProps = inProps => {
|
|
|
85
85
|
defaultSlots,
|
|
86
86
|
slots: themedProps.slots
|
|
87
87
|
}), [themedProps.slots]);
|
|
88
|
-
|
|
88
|
+
const injectDefaultProps = React.useMemo(() => {
|
|
89
|
+
return Object.keys(DATA_GRID_PROPS_DEFAULT_VALUES).reduce((acc, key) => {
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
acc[key] = themedProps[key] ?? DATA_GRID_PROPS_DEFAULT_VALUES[key];
|
|
92
|
+
return acc;
|
|
93
|
+
}, {});
|
|
94
|
+
}, [themedProps]);
|
|
95
|
+
return React.useMemo(() => _extends({}, themedProps, injectDefaultProps, {
|
|
89
96
|
localeText,
|
|
90
97
|
slots
|
|
91
|
-
}, DATA_GRID_FORCED_PROPS), [themedProps, localeText, slots]);
|
|
98
|
+
}, DATA_GRID_FORCED_PROPS), [themedProps, localeText, slots, injectDefaultProps]);
|
|
92
99
|
};
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { GridOverlayProps } from './containers/GridOverlay';
|
|
3
|
+
export type GridLoadingOverlayVariant = 'circular-progress' | 'linear-progress' | 'skeleton';
|
|
4
|
+
export interface GridLoadingOverlayProps extends GridOverlayProps {
|
|
5
|
+
/**
|
|
6
|
+
* The variant of the overlay.
|
|
7
|
+
* @default 'circular-progress'
|
|
8
|
+
*/
|
|
9
|
+
variant?: GridLoadingOverlayVariant;
|
|
10
|
+
/**
|
|
11
|
+
* The variant of the overlay when no rows are displayed.
|
|
12
|
+
* @default 'circular-progress'
|
|
13
|
+
*/
|
|
14
|
+
noRowsVariant?: GridLoadingOverlayVariant;
|
|
15
|
+
}
|
|
16
|
+
declare const GridLoadingOverlay: React.ForwardRefExoticComponent<GridLoadingOverlayProps & React.RefAttributes<HTMLDivElement>>;
|
|
5
17
|
export { GridLoadingOverlay };
|
|
@@ -1,14 +1,48 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
+
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
|
+
const _excluded = ["variant", "noRowsVariant", "style"];
|
|
2
4
|
import * as React from 'react';
|
|
3
5
|
import PropTypes from 'prop-types';
|
|
6
|
+
import LinearProgress from '@mui/material/LinearProgress';
|
|
4
7
|
import CircularProgress from '@mui/material/CircularProgress';
|
|
5
8
|
import { GridOverlay } from './containers/GridOverlay';
|
|
9
|
+
import { GridSkeletonLoadingOverlay } from './GridSkeletonLoadingOverlay';
|
|
10
|
+
import { useGridApiContext } from '../hooks/utils/useGridApiContext';
|
|
11
|
+
import { gridRowCountSelector, useGridSelector } from '../hooks';
|
|
6
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
const LOADING_VARIANTS = {
|
|
14
|
+
'circular-progress': {
|
|
15
|
+
component: CircularProgress,
|
|
16
|
+
style: {}
|
|
17
|
+
},
|
|
18
|
+
'linear-progress': {
|
|
19
|
+
component: LinearProgress,
|
|
20
|
+
style: {
|
|
21
|
+
display: 'block'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
skeleton: {
|
|
25
|
+
component: GridSkeletonLoadingOverlay,
|
|
26
|
+
style: {
|
|
27
|
+
display: 'block'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
7
31
|
const GridLoadingOverlay = /*#__PURE__*/React.forwardRef(function GridLoadingOverlay(props, ref) {
|
|
32
|
+
const {
|
|
33
|
+
variant = 'circular-progress',
|
|
34
|
+
noRowsVariant = 'circular-progress',
|
|
35
|
+
style
|
|
36
|
+
} = props,
|
|
37
|
+
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
38
|
+
const apiRef = useGridApiContext();
|
|
39
|
+
const rowsCount = useGridSelector(apiRef, gridRowCountSelector);
|
|
40
|
+
const activeVariant = LOADING_VARIANTS[rowsCount === 0 ? noRowsVariant : variant];
|
|
8
41
|
return /*#__PURE__*/_jsx(GridOverlay, _extends({
|
|
9
|
-
ref: ref
|
|
10
|
-
|
|
11
|
-
|
|
42
|
+
ref: ref,
|
|
43
|
+
style: _extends({}, activeVariant.style, style)
|
|
44
|
+
}, other, {
|
|
45
|
+
children: /*#__PURE__*/_jsx(activeVariant.component, {})
|
|
12
46
|
}));
|
|
13
47
|
});
|
|
14
48
|
process.env.NODE_ENV !== "production" ? GridLoadingOverlay.propTypes = {
|
|
@@ -16,6 +50,16 @@ process.env.NODE_ENV !== "production" ? GridLoadingOverlay.propTypes = {
|
|
|
16
50
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
17
51
|
// | To update them edit the TypeScript types and run "pnpm proptypes" |
|
|
18
52
|
// ----------------------------------------------------------------------
|
|
19
|
-
|
|
53
|
+
/**
|
|
54
|
+
* The variant of the overlay when no rows are displayed.
|
|
55
|
+
* @default 'circular-progress'
|
|
56
|
+
*/
|
|
57
|
+
noRowsVariant: PropTypes.oneOf(['circular-progress', 'linear-progress', 'skeleton']),
|
|
58
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
59
|
+
/**
|
|
60
|
+
* The variant of the overlay.
|
|
61
|
+
* @default 'circular-progress'
|
|
62
|
+
*/
|
|
63
|
+
variant: PropTypes.oneOf(['circular-progress', 'linear-progress', 'skeleton'])
|
|
20
64
|
} : void 0;
|
|
21
65
|
export { GridLoadingOverlay };
|
package/components/GridRow.js
CHANGED
|
@@ -249,10 +249,11 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
249
249
|
const pinnedOffset = getPinnedCellOffset(gridPinnedColumnPositionLookup[pinnedPosition], column.computedWidth, indexRelativeToAllColumns, columnPositions, dimensions);
|
|
250
250
|
if (rowNode?.type === 'skeletonRow') {
|
|
251
251
|
return /*#__PURE__*/_jsx(slots.skeletonCell, {
|
|
252
|
+
type: column.type,
|
|
252
253
|
width: width,
|
|
253
254
|
height: rowHeight,
|
|
254
255
|
field: column.field,
|
|
255
|
-
align: column.align
|
|
256
|
+
align: column.align
|
|
256
257
|
}, column.field);
|
|
257
258
|
}
|
|
258
259
|
const editCellState = editRowsState[rowId]?.[column.field] ?? null;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { styled } from '@mui/system';
|
|
5
|
+
import useForkRef from '@mui/utils/useForkRef';
|
|
6
|
+
import composeClasses from '@mui/utils/composeClasses';
|
|
7
|
+
import { useGridApiContext } from '../hooks/utils/useGridApiContext';
|
|
8
|
+
import { useGridRootProps } from '../hooks/utils/useGridRootProps';
|
|
9
|
+
import { GridPinnedColumnPosition, gridColumnPositionsSelector, gridColumnsTotalWidthSelector, gridDimensionsSelector, gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, useGridApiEventHandler, useGridSelector } from '../hooks';
|
|
10
|
+
import { getDataGridUtilityClass, gridClasses } from '../constants/gridClasses';
|
|
11
|
+
import { getPinnedCellOffset } from '../internals/utils/getPinnedCellOffset';
|
|
12
|
+
import { shouldCellShowLeftBorder, shouldCellShowRightBorder } from '../utils/cellBorderUtils';
|
|
13
|
+
import { escapeOperandAttributeSelector } from '../utils/domUtils';
|
|
14
|
+
import { GridScrollbarFillerCell } from './GridScrollbarFillerCell';
|
|
15
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
16
|
+
const SkeletonOverlay = styled('div', {
|
|
17
|
+
name: 'MuiDataGrid',
|
|
18
|
+
slot: 'SkeletonLoadingOverlay',
|
|
19
|
+
overridesResolver: (props, styles) => styles.skeletonLoadingOverlay
|
|
20
|
+
})({
|
|
21
|
+
minWidth: '100%',
|
|
22
|
+
width: 'max-content',
|
|
23
|
+
// prevents overflow: clip; cutting off the x axis
|
|
24
|
+
height: '100%',
|
|
25
|
+
overflow: 'clip' // y axis is hidden while the x axis is allowed to overflow
|
|
26
|
+
});
|
|
27
|
+
const useUtilityClasses = ownerState => {
|
|
28
|
+
const {
|
|
29
|
+
classes
|
|
30
|
+
} = ownerState;
|
|
31
|
+
const slots = {
|
|
32
|
+
root: ['skeletonLoadingOverlay']
|
|
33
|
+
};
|
|
34
|
+
return composeClasses(slots, getDataGridUtilityClass, classes);
|
|
35
|
+
};
|
|
36
|
+
const getColIndex = el => parseInt(el.getAttribute('data-colindex'), 10);
|
|
37
|
+
const GridSkeletonLoadingOverlay = /*#__PURE__*/React.forwardRef(function GridSkeletonLoadingOverlay(props, forwardedRef) {
|
|
38
|
+
const rootProps = useGridRootProps();
|
|
39
|
+
const {
|
|
40
|
+
slots
|
|
41
|
+
} = rootProps;
|
|
42
|
+
const classes = useUtilityClasses({
|
|
43
|
+
classes: rootProps.classes
|
|
44
|
+
});
|
|
45
|
+
const ref = React.useRef(null);
|
|
46
|
+
const handleRef = useForkRef(ref, forwardedRef);
|
|
47
|
+
const apiRef = useGridApiContext();
|
|
48
|
+
const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
|
|
49
|
+
const viewportHeight = dimensions?.viewportInnerSize.height ?? 0;
|
|
50
|
+
const skeletonRowsCount = Math.ceil(viewportHeight / dimensions.rowHeight);
|
|
51
|
+
const totalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector);
|
|
52
|
+
const positions = useGridSelector(apiRef, gridColumnPositionsSelector);
|
|
53
|
+
const inViewportCount = React.useMemo(() => positions.filter(value => value <= totalWidth).length, [totalWidth, positions]);
|
|
54
|
+
const allVisibleColumns = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
|
|
55
|
+
const columns = React.useMemo(() => allVisibleColumns.slice(0, inViewportCount), [allVisibleColumns, inViewportCount]);
|
|
56
|
+
const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
|
|
57
|
+
const getPinnedStyle = React.useCallback((computedWidth, index, position) => {
|
|
58
|
+
const pinnedOffset = getPinnedCellOffset(position, computedWidth, index, positions, dimensions);
|
|
59
|
+
return {
|
|
60
|
+
[position]: pinnedOffset
|
|
61
|
+
};
|
|
62
|
+
}, [dimensions, positions]);
|
|
63
|
+
const getPinnedPosition = React.useCallback(field => {
|
|
64
|
+
if (pinnedColumns.left.findIndex(col => col.field === field) !== -1) {
|
|
65
|
+
return GridPinnedColumnPosition.LEFT;
|
|
66
|
+
}
|
|
67
|
+
if (pinnedColumns.right.findIndex(col => col.field === field) !== -1) {
|
|
68
|
+
return GridPinnedColumnPosition.RIGHT;
|
|
69
|
+
}
|
|
70
|
+
return undefined;
|
|
71
|
+
}, [pinnedColumns.left, pinnedColumns.right]);
|
|
72
|
+
const children = React.useMemo(() => {
|
|
73
|
+
const array = [];
|
|
74
|
+
for (let i = 0; i < skeletonRowsCount; i += 1) {
|
|
75
|
+
const rowCells = [];
|
|
76
|
+
for (let colIndex = 0; colIndex < columns.length; colIndex += 1) {
|
|
77
|
+
const column = columns[colIndex];
|
|
78
|
+
const pinnedPosition = getPinnedPosition(column.field);
|
|
79
|
+
const isPinnedLeft = pinnedPosition === GridPinnedColumnPosition.LEFT;
|
|
80
|
+
const isPinnedRight = pinnedPosition === GridPinnedColumnPosition.RIGHT;
|
|
81
|
+
const sectionLength = pinnedPosition ? pinnedColumns[pinnedPosition].length // pinned section
|
|
82
|
+
: columns.length - pinnedColumns.left.length - pinnedColumns.right.length; // middle section
|
|
83
|
+
const sectionIndex = pinnedPosition ? pinnedColumns[pinnedPosition].findIndex(col => col.field === column.field) // pinned section
|
|
84
|
+
: colIndex - pinnedColumns.left.length; // middle section
|
|
85
|
+
const pinnedStyle = pinnedPosition && getPinnedStyle(column.computedWidth, colIndex, pinnedPosition);
|
|
86
|
+
const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width;
|
|
87
|
+
const showRightBorder = shouldCellShowRightBorder(pinnedPosition, sectionIndex, sectionLength, rootProps.showCellVerticalBorder, gridHasFiller);
|
|
88
|
+
const showLeftBorder = shouldCellShowLeftBorder(pinnedPosition, sectionIndex);
|
|
89
|
+
const isLastColumn = colIndex === columns.length - 1;
|
|
90
|
+
const isFirstPinnedRight = isPinnedRight && sectionIndex === 0;
|
|
91
|
+
const hasFillerBefore = isFirstPinnedRight && gridHasFiller;
|
|
92
|
+
const hasFillerAfter = isLastColumn && !isFirstPinnedRight && gridHasFiller;
|
|
93
|
+
const expandedWidth = dimensions.viewportOuterSize.width - dimensions.columnsTotalWidth;
|
|
94
|
+
const emptyCellWidth = Math.max(0, expandedWidth);
|
|
95
|
+
const emptyCell = /*#__PURE__*/_jsx(slots.skeletonCell, {
|
|
96
|
+
width: emptyCellWidth,
|
|
97
|
+
empty: true
|
|
98
|
+
}, `skeleton-filler-column-${i}`);
|
|
99
|
+
const scrollbarWidth = dimensions.hasScrollY ? dimensions.scrollbarSize : 0;
|
|
100
|
+
const hasScrollbarFiller = isLastColumn && scrollbarWidth !== 0;
|
|
101
|
+
if (hasFillerBefore) {
|
|
102
|
+
rowCells.push(emptyCell);
|
|
103
|
+
}
|
|
104
|
+
rowCells.push( /*#__PURE__*/_jsx(slots.skeletonCell, {
|
|
105
|
+
field: column.field,
|
|
106
|
+
type: column.type,
|
|
107
|
+
align: column.align,
|
|
108
|
+
width: "var(--width)",
|
|
109
|
+
height: dimensions.rowHeight,
|
|
110
|
+
"data-colindex": colIndex,
|
|
111
|
+
className: clsx(isPinnedLeft && gridClasses['cell--pinnedLeft'], isPinnedRight && gridClasses['cell--pinnedRight'], showRightBorder && gridClasses['cell--withRightBorder'], showLeftBorder && gridClasses['cell--withLeftBorder']),
|
|
112
|
+
style: _extends({
|
|
113
|
+
'--width': `${column.computedWidth}px`
|
|
114
|
+
}, pinnedStyle)
|
|
115
|
+
}, `skeleton-column-${i}-${column.field}`));
|
|
116
|
+
if (hasFillerAfter) {
|
|
117
|
+
rowCells.push(emptyCell);
|
|
118
|
+
}
|
|
119
|
+
if (hasScrollbarFiller) {
|
|
120
|
+
rowCells.push( /*#__PURE__*/_jsx(GridScrollbarFillerCell, {
|
|
121
|
+
pinnedRight: pinnedColumns.right.length > 0
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
array.push( /*#__PURE__*/_jsx("div", {
|
|
126
|
+
className: clsx(gridClasses.row, gridClasses.rowSkeleton, i === 0 && gridClasses['row--firstVisible']),
|
|
127
|
+
children: rowCells
|
|
128
|
+
}, `skeleton-row-${i}`));
|
|
129
|
+
}
|
|
130
|
+
return array;
|
|
131
|
+
}, [slots, columns, pinnedColumns, skeletonRowsCount, rootProps.showCellVerticalBorder, dimensions.columnsTotalWidth, dimensions.viewportOuterSize.width, dimensions.rowHeight, dimensions.hasScrollY, dimensions.scrollbarSize, getPinnedPosition, getPinnedStyle]);
|
|
132
|
+
|
|
133
|
+
// Sync the column resize of the overlay columns with the grid
|
|
134
|
+
const handleColumnResize = params => {
|
|
135
|
+
const {
|
|
136
|
+
colDef,
|
|
137
|
+
width
|
|
138
|
+
} = params;
|
|
139
|
+
const cells = ref.current?.querySelectorAll(`[data-field="${escapeOperandAttributeSelector(colDef.field)}"]`);
|
|
140
|
+
if (!cells) {
|
|
141
|
+
throw new Error('MUI X: Expected skeleton cells to be defined with `data-field` attribute.');
|
|
142
|
+
}
|
|
143
|
+
const resizedColIndex = columns.findIndex(col => col.field === colDef.field);
|
|
144
|
+
const pinnedPosition = getPinnedPosition(colDef.field);
|
|
145
|
+
const isPinnedLeft = pinnedPosition === GridPinnedColumnPosition.LEFT;
|
|
146
|
+
const isPinnedRight = pinnedPosition === GridPinnedColumnPosition.RIGHT;
|
|
147
|
+
const currentWidth = getComputedStyle(cells[0]).getPropertyValue('--width');
|
|
148
|
+
const delta = parseInt(currentWidth, 10) - width;
|
|
149
|
+
if (cells) {
|
|
150
|
+
cells.forEach(element => {
|
|
151
|
+
element.style.setProperty('--width', `${width}px`);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (isPinnedLeft) {
|
|
155
|
+
const pinnedCells = ref.current?.querySelectorAll(`.${gridClasses['cell--pinnedLeft']}`);
|
|
156
|
+
pinnedCells?.forEach(element => {
|
|
157
|
+
const colIndex = getColIndex(element);
|
|
158
|
+
if (colIndex > resizedColIndex) {
|
|
159
|
+
element.style.left = `${parseInt(getComputedStyle(element).left, 10) - delta}px`;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if (isPinnedRight) {
|
|
164
|
+
const pinnedCells = ref.current?.querySelectorAll(`.${gridClasses['cell--pinnedRight']}`);
|
|
165
|
+
pinnedCells?.forEach(element => {
|
|
166
|
+
const colIndex = getColIndex(element);
|
|
167
|
+
if (colIndex < resizedColIndex) {
|
|
168
|
+
element.style.right = `${parseInt(getComputedStyle(element).right, 10) + delta}px`;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
useGridApiEventHandler(apiRef, 'columnResize', handleColumnResize);
|
|
174
|
+
return /*#__PURE__*/_jsx(SkeletonOverlay, _extends({
|
|
175
|
+
className: classes.root,
|
|
176
|
+
ref: handleRef
|
|
177
|
+
}, props, {
|
|
178
|
+
children: children
|
|
179
|
+
}));
|
|
180
|
+
});
|
|
181
|
+
export { GridSkeletonLoadingOverlay };
|
|
@@ -1,2 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
2
|
+
import { GridOverlayType } from '../../hooks/features/overlays/useGridOverlays';
|
|
3
|
+
import { GridLoadingOverlayVariant } from '../GridLoadingOverlay';
|
|
4
|
+
interface GridOverlaysProps {
|
|
5
|
+
overlayType: GridOverlayType;
|
|
6
|
+
loadingOverlayVariant: GridLoadingOverlayVariant | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function GridOverlays(props: GridOverlaysProps): React.JSX.Element | null;
|
|
9
|
+
export declare namespace GridOverlays {
|
|
10
|
+
var propTypes: any;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -5,8 +5,6 @@ import { styled } from '@mui/system';
|
|
|
5
5
|
import { unstable_composeClasses as composeClasses } from '@mui/utils';
|
|
6
6
|
import clsx from 'clsx';
|
|
7
7
|
import { useGridSelector } from '../../hooks/utils/useGridSelector';
|
|
8
|
-
import { gridExpandedRowCountSelector } from '../../hooks/features/filter/gridFilterSelector';
|
|
9
|
-
import { gridRowCountSelector, gridRowsLoadingSelector } from '../../hooks/features/rows/gridRowsSelector';
|
|
10
8
|
import { gridDimensionsSelector } from '../../hooks/features/dimensions';
|
|
11
9
|
import { useGridApiContext } from '../../hooks/utils/useGridApiContext';
|
|
12
10
|
import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
|
|
@@ -17,11 +15,14 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
17
15
|
const GridOverlayWrapperRoot = styled('div', {
|
|
18
16
|
name: 'MuiDataGrid',
|
|
19
17
|
slot: 'OverlayWrapper',
|
|
20
|
-
shouldForwardProp: prop => prop !== 'overlayType',
|
|
18
|
+
shouldForwardProp: prop => prop !== 'overlayType' && prop !== 'loadingOverlayVariant',
|
|
21
19
|
overridesResolver: (props, styles) => styles.overlayWrapper
|
|
22
20
|
})(({
|
|
23
|
-
overlayType
|
|
24
|
-
|
|
21
|
+
overlayType,
|
|
22
|
+
loadingOverlayVariant
|
|
23
|
+
}) =>
|
|
24
|
+
// Skeleton overlay should flow with the scroll container and not be sticky
|
|
25
|
+
loadingOverlayVariant !== 'skeleton' ? {
|
|
25
26
|
position: 'sticky',
|
|
26
27
|
// To stay in place while scrolling
|
|
27
28
|
top: 'var(--DataGrid-headersTotalHeight)',
|
|
@@ -32,11 +33,11 @@ const GridOverlayWrapperRoot = styled('div', {
|
|
|
32
33
|
// To stay above the content instead of shifting it down
|
|
33
34
|
zIndex: overlayType === 'loadingOverlay' ? 5 // Should be above pinned columns, pinned rows, and detail panel
|
|
34
35
|
: 4 // Should be above pinned columns and detail panel
|
|
35
|
-
})
|
|
36
|
+
} : {});
|
|
36
37
|
const GridOverlayWrapperInner = styled('div', {
|
|
37
38
|
name: 'MuiDataGrid',
|
|
38
39
|
slot: 'OverlayWrapperInner',
|
|
39
|
-
shouldForwardProp: prop => prop !== 'overlayType',
|
|
40
|
+
shouldForwardProp: prop => prop !== 'overlayType' && prop !== 'loadingOverlayVariant',
|
|
40
41
|
overridesResolver: (props, styles) => styles.overlayWrapperInner
|
|
41
42
|
})({});
|
|
42
43
|
const useUtilityClasses = ownerState => {
|
|
@@ -61,9 +62,9 @@ function GridOverlayWrapper(props) {
|
|
|
61
62
|
const classes = useUtilityClasses(_extends({}, props, {
|
|
62
63
|
classes: rootProps.classes
|
|
63
64
|
}));
|
|
64
|
-
return /*#__PURE__*/_jsx(GridOverlayWrapperRoot, {
|
|
65
|
-
className: clsx(classes.root)
|
|
66
|
-
|
|
65
|
+
return /*#__PURE__*/_jsx(GridOverlayWrapperRoot, _extends({
|
|
66
|
+
className: clsx(classes.root)
|
|
67
|
+
}, props, {
|
|
67
68
|
children: /*#__PURE__*/_jsx(GridOverlayWrapperInner, _extends({
|
|
68
69
|
className: clsx(classes.inner),
|
|
69
70
|
style: {
|
|
@@ -71,42 +72,27 @@ function GridOverlayWrapper(props) {
|
|
|
71
72
|
width: dimensions.viewportOuterSize.width
|
|
72
73
|
}
|
|
73
74
|
}, props))
|
|
74
|
-
});
|
|
75
|
+
}));
|
|
75
76
|
}
|
|
76
|
-
process.env.NODE_ENV !== "production" ?
|
|
77
|
+
process.env.NODE_ENV !== "production" ? GridOverlays.propTypes = {
|
|
77
78
|
// ----------------------------- Warning --------------------------------
|
|
78
79
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
79
80
|
// | To update them edit the TypeScript types and run "pnpm proptypes" |
|
|
80
81
|
// ----------------------------------------------------------------------
|
|
81
|
-
|
|
82
|
+
loadingOverlayVariant: PropTypes.oneOf(['circular-progress', 'linear-progress', 'skeleton']),
|
|
83
|
+
overlayType: PropTypes.oneOf(['loadingOverlay', 'noResultsOverlay', 'noRowsOverlay'])
|
|
82
84
|
} : void 0;
|
|
83
|
-
export function GridOverlays() {
|
|
84
|
-
const
|
|
85
|
+
export function GridOverlays(props) {
|
|
86
|
+
const {
|
|
87
|
+
overlayType
|
|
88
|
+
} = props;
|
|
85
89
|
const rootProps = useGridRootProps();
|
|
86
|
-
|
|
87
|
-
const visibleRowCount = useGridSelector(apiRef, gridExpandedRowCountSelector);
|
|
88
|
-
const loading = useGridSelector(apiRef, gridRowsLoadingSelector);
|
|
89
|
-
const showNoRowsOverlay = !loading && totalRowCount === 0;
|
|
90
|
-
const showNoResultsOverlay = !loading && totalRowCount > 0 && visibleRowCount === 0;
|
|
91
|
-
let overlay = null;
|
|
92
|
-
let overlayType = '';
|
|
93
|
-
if (showNoRowsOverlay) {
|
|
94
|
-
overlay = /*#__PURE__*/_jsx(rootProps.slots.noRowsOverlay, _extends({}, rootProps.slotProps?.noRowsOverlay));
|
|
95
|
-
overlayType = 'noRowsOverlay';
|
|
96
|
-
}
|
|
97
|
-
if (showNoResultsOverlay) {
|
|
98
|
-
overlay = /*#__PURE__*/_jsx(rootProps.slots.noResultsOverlay, _extends({}, rootProps.slotProps?.noResultsOverlay));
|
|
99
|
-
overlayType = 'noResultsOverlay';
|
|
100
|
-
}
|
|
101
|
-
if (loading) {
|
|
102
|
-
overlay = /*#__PURE__*/_jsx(rootProps.slots.loadingOverlay, _extends({}, rootProps.slotProps?.loadingOverlay));
|
|
103
|
-
overlayType = 'loadingOverlay';
|
|
104
|
-
}
|
|
105
|
-
if (overlay === null) {
|
|
90
|
+
if (!overlayType) {
|
|
106
91
|
return null;
|
|
107
92
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
93
|
+
const Overlay = rootProps.slots?.[overlayType];
|
|
94
|
+
const overlayProps = rootProps.slotProps?.[overlayType];
|
|
95
|
+
return /*#__PURE__*/_jsx(GridOverlayWrapper, _extends({}, props, {
|
|
96
|
+
children: /*#__PURE__*/_jsx(Overlay, _extends({}, overlayProps))
|
|
97
|
+
}));
|
|
112
98
|
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { GridColType } from '../../models';
|
|
3
|
+
export interface GridSkeletonCellProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
type?: GridColType;
|
|
5
|
+
width?: number | string;
|
|
6
|
+
height?: number | 'auto';
|
|
7
|
+
field?: string;
|
|
8
|
+
align?: string;
|
|
9
|
+
/**
|
|
10
|
+
* If `true`, the cell will not display the skeleton but still reserve the cell space.
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
empty?: boolean;
|
|
7
14
|
}
|
|
8
|
-
declare function GridSkeletonCell(props:
|
|
15
|
+
declare function GridSkeletonCell(props: GridSkeletonCellProps): React.JSX.Element;
|
|
9
16
|
declare namespace GridSkeletonCell {
|
|
10
17
|
var propTypes: any;
|
|
11
18
|
}
|
|
@@ -1,52 +1,88 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
|
-
const _excluded = ["field", "align", "width", "height"];
|
|
3
|
+
const _excluded = ["field", "type", "align", "width", "height", "empty", "style", "className"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import Skeleton from '@mui/material/Skeleton';
|
|
7
7
|
import { unstable_composeClasses as composeClasses, unstable_capitalize as capitalize } from '@mui/utils';
|
|
8
|
+
import clsx from 'clsx';
|
|
8
9
|
import { fastMemo } from '../../utils/fastMemo';
|
|
9
|
-
import {
|
|
10
|
+
import { createRandomNumberGenerator } from '../../utils/utils';
|
|
10
11
|
import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
|
|
11
12
|
import { getDataGridUtilityClass } from '../../constants/gridClasses';
|
|
12
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
-
const
|
|
14
|
+
const CIRCULAR_CONTENT_SIZE = '1.3em';
|
|
15
|
+
const CONTENT_HEIGHT = '1.2em';
|
|
16
|
+
const DEFAULT_CONTENT_WIDTH_RANGE = [40, 80];
|
|
17
|
+
const CONTENT_WIDTH_RANGE_BY_TYPE = {
|
|
18
|
+
number: [40, 60],
|
|
19
|
+
string: [40, 80],
|
|
20
|
+
date: [40, 60],
|
|
21
|
+
dateTime: [60, 80],
|
|
22
|
+
singleSelect: [40, 80]
|
|
23
|
+
};
|
|
14
24
|
const useUtilityClasses = ownerState => {
|
|
15
25
|
const {
|
|
16
26
|
align,
|
|
17
|
-
classes
|
|
27
|
+
classes,
|
|
28
|
+
empty
|
|
18
29
|
} = ownerState;
|
|
19
30
|
const slots = {
|
|
20
|
-
root: ['cell', 'cellSkeleton', `cell--text${capitalize(align)}`, '
|
|
31
|
+
root: ['cell', 'cellSkeleton', `cell--text${align ? capitalize(align) : 'Left'}`, empty && 'cellEmpty']
|
|
21
32
|
};
|
|
22
33
|
return composeClasses(slots, getDataGridUtilityClass, classes);
|
|
23
34
|
};
|
|
35
|
+
const randomNumberGenerator = createRandomNumberGenerator(12345);
|
|
24
36
|
function GridSkeletonCell(props) {
|
|
25
37
|
const {
|
|
38
|
+
field,
|
|
39
|
+
type,
|
|
26
40
|
align,
|
|
27
41
|
width,
|
|
28
|
-
height
|
|
42
|
+
height,
|
|
43
|
+
empty = false,
|
|
44
|
+
style,
|
|
45
|
+
className
|
|
29
46
|
} = props,
|
|
30
47
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
31
48
|
const rootProps = useGridRootProps();
|
|
32
49
|
const ownerState = {
|
|
33
50
|
classes: rootProps.classes,
|
|
34
|
-
align
|
|
51
|
+
align,
|
|
52
|
+
empty
|
|
35
53
|
};
|
|
36
54
|
const classes = useUtilityClasses(ownerState);
|
|
37
|
-
|
|
55
|
+
|
|
56
|
+
// Memo prevents the non-circular skeleton widths changing to random widths on every render
|
|
57
|
+
const skeletonProps = React.useMemo(() => {
|
|
58
|
+
const isCircularContent = type === 'boolean' || type === 'actions';
|
|
59
|
+
if (isCircularContent) {
|
|
60
|
+
return {
|
|
61
|
+
variant: 'circular',
|
|
62
|
+
width: CIRCULAR_CONTENT_SIZE,
|
|
63
|
+
height: CIRCULAR_CONTENT_SIZE
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// The width of the skeleton is a random number between the min and max values
|
|
68
|
+
// The min and max values are determined by the type of the column
|
|
69
|
+
const [min, max] = type ? CONTENT_WIDTH_RANGE_BY_TYPE[type] ?? DEFAULT_CONTENT_WIDTH_RANGE : DEFAULT_CONTENT_WIDTH_RANGE;
|
|
70
|
+
return {
|
|
71
|
+
variant: 'text',
|
|
72
|
+
width: `${Math.round(randomNumberGenerator(min, max))}%`,
|
|
73
|
+
height: CONTENT_HEIGHT
|
|
74
|
+
};
|
|
75
|
+
}, [type]);
|
|
38
76
|
return /*#__PURE__*/_jsx("div", _extends({
|
|
39
|
-
|
|
40
|
-
|
|
77
|
+
"data-field": field,
|
|
78
|
+
className: clsx(classes.root, className),
|
|
79
|
+
style: _extends({
|
|
41
80
|
height,
|
|
42
81
|
maxWidth: width,
|
|
43
82
|
minWidth: width
|
|
44
|
-
}
|
|
83
|
+
}, style)
|
|
45
84
|
}, other, {
|
|
46
|
-
children: /*#__PURE__*/_jsx(Skeleton, {
|
|
47
|
-
width: `${contentWidth}%`,
|
|
48
|
-
height: 25
|
|
49
|
-
})
|
|
85
|
+
children: !empty && /*#__PURE__*/_jsx(Skeleton, _extends({}, skeletonProps))
|
|
50
86
|
}));
|
|
51
87
|
}
|
|
52
88
|
process.env.NODE_ENV !== "production" ? GridSkeletonCell.propTypes = {
|
|
@@ -54,10 +90,16 @@ process.env.NODE_ENV !== "production" ? GridSkeletonCell.propTypes = {
|
|
|
54
90
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
55
91
|
// | To update them edit the TypeScript types and run "pnpm proptypes" |
|
|
56
92
|
// ----------------------------------------------------------------------
|
|
57
|
-
align: PropTypes.string
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
93
|
+
align: PropTypes.string,
|
|
94
|
+
/**
|
|
95
|
+
* If `true`, the cell will not display the skeleton but still reserve the cell space.
|
|
96
|
+
* @default false
|
|
97
|
+
*/
|
|
98
|
+
empty: PropTypes.bool,
|
|
99
|
+
field: PropTypes.string,
|
|
100
|
+
height: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]),
|
|
101
|
+
type: PropTypes.oneOf(['actions', 'boolean', 'custom', 'date', 'dateTime', 'number', 'singleSelect', 'string']),
|
|
102
|
+
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
|
|
61
103
|
} : void 0;
|
|
62
104
|
const Memoized = fastMemo(GridSkeletonCell);
|
|
63
105
|
export { Memoized as GridSkeletonCell };
|