@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.
Files changed (57) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/DataGrid/useDataGridProps.js +9 -2
  3. package/components/GridLoadingOverlay.d.ts +15 -3
  4. package/components/GridLoadingOverlay.js +48 -4
  5. package/components/GridRow.js +2 -1
  6. package/components/GridSkeletonLoadingOverlay.d.ts +3 -0
  7. package/components/GridSkeletonLoadingOverlay.js +181 -0
  8. package/components/base/GridOverlays.d.ts +11 -1
  9. package/components/base/GridOverlays.js +25 -39
  10. package/components/cell/GridSkeletonCell.d.ts +13 -6
  11. package/components/cell/GridSkeletonCell.js +61 -19
  12. package/components/containers/GridRootStyles.js +11 -2
  13. package/components/virtualization/GridVirtualScroller.js +7 -5
  14. package/constants/gridClasses.d.ts +9 -0
  15. package/constants/gridClasses.js +1 -1
  16. package/hooks/features/overlays/useGridOverlays.d.ts +11 -0
  17. package/hooks/features/overlays/useGridOverlays.js +35 -0
  18. package/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  19. package/hooks/utils/index.d.ts +0 -1
  20. package/hooks/utils/index.js +0 -1
  21. package/index.js +1 -1
  22. package/models/gridSlotsComponentsProps.d.ts +2 -1
  23. package/modern/DataGrid/useDataGridProps.js +9 -2
  24. package/modern/components/GridLoadingOverlay.js +48 -4
  25. package/modern/components/GridRow.js +2 -1
  26. package/modern/components/GridSkeletonLoadingOverlay.js +181 -0
  27. package/modern/components/base/GridOverlays.js +25 -39
  28. package/modern/components/cell/GridSkeletonCell.js +61 -19
  29. package/modern/components/containers/GridRootStyles.js +11 -2
  30. package/modern/components/virtualization/GridVirtualScroller.js +7 -5
  31. package/modern/constants/gridClasses.js +1 -1
  32. package/modern/hooks/features/overlays/useGridOverlays.js +35 -0
  33. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  34. package/modern/hooks/utils/index.js +0 -1
  35. package/modern/index.js +1 -1
  36. package/modern/utils/utils.js +10 -2
  37. package/node/DataGrid/useDataGridProps.js +9 -2
  38. package/node/components/GridLoadingOverlay.js +48 -4
  39. package/node/components/GridRow.js +2 -1
  40. package/node/components/GridSkeletonLoadingOverlay.js +189 -0
  41. package/node/components/base/GridOverlays.js +25 -39
  42. package/node/components/cell/GridSkeletonCell.js +60 -18
  43. package/node/components/containers/GridRootStyles.js +11 -2
  44. package/node/components/virtualization/GridVirtualScroller.js +6 -4
  45. package/node/constants/gridClasses.js +1 -1
  46. package/node/hooks/features/overlays/useGridOverlays.js +42 -0
  47. package/node/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  48. package/node/hooks/utils/index.js +0 -12
  49. package/node/index.js +1 -1
  50. package/node/utils/utils.js +11 -3
  51. package/package.json +5 -4
  52. package/utils/utils.d.ts +8 -1
  53. package/utils/utils.js +10 -2
  54. package/hooks/utils/useResizeObserver.d.ts +0 -2
  55. package/hooks/utils/useResizeObserver.js +0 -36
  56. package/modern/hooks/utils/useResizeObserver.js +0 -36
  57. package/node/hooks/utils/useResizeObserver.js +0 -44
@@ -161,7 +161,7 @@ export const GridRootStyles = styled('div', {
161
161
  const selectedOpacity = (t.vars || t).palette.action.selectedOpacity;
162
162
  const selectedBackground = t.vars ? `rgba(${t.vars.palette.primary.mainChannel} / ${selectedOpacity})` : alpha(t.palette.primary.main, selectedOpacity);
163
163
  const selectedHoverBackground = t.vars ? `rgba(${t.vars.palette.primary.mainChannel} / calc(
164
- ${t.vars.palette.action.selectedOpacity} +
164
+ ${t.vars.palette.action.selectedOpacity} +
165
165
  ${t.vars.palette.action.hoverOpacity}
166
166
  ))` : alpha(t.palette.primary.main, t.palette.action.selectedOpacity + t.palette.action.hoverOpacity);
167
167
  const pinnedHoverBackground = t.vars ? hoverColor : blend(pinnedBackground, hoverColor, hoverOpacity);
@@ -425,6 +425,9 @@ export const GridRootStyles = styled('div', {
425
425
  backgroundColor: 'transparent'
426
426
  }
427
427
  },
428
+ [`&.${c.rowSkeleton}:hover`]: {
429
+ backgroundColor: 'transparent'
430
+ },
428
431
  '&.Mui-selected': selectedStyles
429
432
  },
430
433
  [`& .${c['container--top']}, & .${c['container--bottom']}`]: {
@@ -631,7 +634,7 @@ export const GridRootStyles = styled('div', {
631
634
  minWidth: 'calc(var(--DataGrid-hasScrollY) * var(--DataGrid-scrollbarSize))',
632
635
  alignSelf: 'stretch',
633
636
  [`&.${c['scrollbarFiller--borderTop']}`]: {
634
- borderTop: '1px solid var(--DataGrid-rowBorderColor)'
637
+ borderTop: '1px solid var(--rowBorderColor)'
635
638
  },
636
639
  [`&.${c['scrollbarFiller--pinnedRight']}`]: {
637
640
  backgroundColor: 'var(--DataGrid-pinnedBackground)',
@@ -644,6 +647,12 @@ export const GridRootStyles = styled('div', {
644
647
  },
645
648
  [`& .${c['filler--borderTop']}`]: {
646
649
  borderTop: '1px solid var(--DataGrid-rowBorderColor)'
650
+ },
651
+ /* Hide grid rows and vertical scrollbar when skeleton overlay is visible */
652
+ [`& .${c['main--hasSkeletonLoadingOverlay']}`]: {
653
+ [`& .${c.virtualScrollerContent}, & .${c['scrollbar--vertical']}, & .${c.pinnedRows}`]: {
654
+ display: 'none'
655
+ }
647
656
  }
648
657
  });
649
658
  return gridStyle;
@@ -9,7 +9,8 @@ import { useGridSelector } from '../../hooks/utils/useGridSelector';
9
9
  import { getDataGridUtilityClass } from '../../constants/gridClasses';
10
10
  import { gridDimensionsSelector } from '../../hooks/features/dimensions';
11
11
  import { useGridVirtualScroller } from '../../hooks/features/virtualization/useGridVirtualScroller';
12
- import { GridOverlays } from '../base/GridOverlays';
12
+ import { useGridOverlays } from '../../hooks/features/overlays/useGridOverlays';
13
+ import { GridOverlays as Overlays } from '../base/GridOverlays';
13
14
  import { GridHeaders } from '../GridHeaders';
14
15
  import { GridMainContainer as Container } from './GridMainContainer';
15
16
  import { GridTopContainer as TopContainer } from './GridTopContainer';
@@ -19,12 +20,12 @@ import { GridVirtualScrollerFiller as SpaceFiller } from './GridVirtualScrollerF
19
20
  import { GridVirtualScrollerRenderZone as RenderZone } from './GridVirtualScrollerRenderZone';
20
21
  import { GridVirtualScrollbar as Scrollbar } from './GridVirtualScrollbar';
21
22
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
- const useUtilityClasses = (ownerState, dimensions) => {
23
+ const useUtilityClasses = (ownerState, dimensions, loadingOverlayVariant) => {
23
24
  const {
24
25
  classes
25
26
  } = ownerState;
26
27
  const slots = {
27
- root: ['main', dimensions.rightPinnedWidth > 0 && 'main--hasPinnedRight'],
28
+ root: ['main', dimensions.rightPinnedWidth > 0 && 'main--hasPinnedRight', loadingOverlayVariant === 'skeleton' && 'main--hasSkeletonLoadingOverlay'],
28
29
  scroller: ['virtualScroller']
29
30
  };
30
31
  return composeClasses(slots, getDataGridUtilityClass, classes);
@@ -51,7 +52,8 @@ function GridVirtualScroller(props) {
51
52
  const apiRef = useGridApiContext();
52
53
  const rootProps = useGridRootProps();
53
54
  const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
54
- const classes = useUtilityClasses(rootProps, dimensions);
55
+ const overlaysProps = useGridOverlays();
56
+ const classes = useUtilityClasses(rootProps, dimensions, overlaysProps.loadingOverlayVariant);
55
57
  const virtualScroller = useGridVirtualScroller();
56
58
  const {
57
59
  getContainerProps,
@@ -79,7 +81,7 @@ function GridVirtualScroller(props) {
79
81
  position: "top",
80
82
  virtualScroller: virtualScroller
81
83
  })]
82
- }), /*#__PURE__*/_jsx(GridOverlays, {}), /*#__PURE__*/_jsx(Content, _extends({}, getContentProps(), {
84
+ }), /*#__PURE__*/_jsx(Overlays, _extends({}, overlaysProps)), /*#__PURE__*/_jsx(Content, _extends({}, getContentProps(), {
83
85
  children: /*#__PURE__*/_jsxs(RenderZone, _extends({}, getRenderZoneProps(), {
84
86
  children: [rows, /*#__PURE__*/_jsx(rootProps.slots.detailPanels, {
85
87
  virtualScroller: virtualScroller
@@ -362,6 +362,11 @@ export interface GridClasses {
362
362
  * Styles applied to the main container element when it has right pinned columns.
363
363
  */
364
364
  'main--hasPinnedRight': string;
365
+ /**
366
+ * Styles applied to the main container element when it has an active skeleton loading overlay.
367
+ * @ignore - do not document.
368
+ */
369
+ 'main--hasSkeletonLoadingOverlay': string;
365
370
  /**
366
371
  * Styles applied to the menu element.
367
372
  */
@@ -483,6 +488,10 @@ export interface GridClasses {
483
488
  * Styles applied to the root element of the row reorder cell when dragging is allowed
484
489
  */
485
490
  'rowReorderCell--draggable': string;
491
+ /**
492
+ * Styles applied to the skeleton row element.
493
+ */
494
+ rowSkeleton: string;
486
495
  /**
487
496
  * Styles applied to both scroll area elements.
488
497
  */
@@ -2,4 +2,4 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, unstable_gen
2
2
  export function getDataGridUtilityClass(slot) {
3
3
  return generateUtilityClass('MuiDataGrid', slot);
4
4
  }
5
- export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderTop', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
5
+ export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderTop', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
@@ -0,0 +1,11 @@
1
+ import { GridLoadingOverlayVariant } from '../../../components/GridLoadingOverlay';
2
+ import { GridSlotsComponent } from '../../../models/gridSlotsComponent';
3
+ export type GridOverlayType = keyof Pick<GridSlotsComponent, 'noRowsOverlay' | 'noResultsOverlay' | 'loadingOverlay'> | null;
4
+ /**
5
+ * Uses the grid state to determine which overlay to display.
6
+ * Returns the active overlay type and the active loading overlay variant.
7
+ */
8
+ export declare const useGridOverlays: () => {
9
+ overlayType: GridOverlayType;
10
+ loadingOverlayVariant: GridLoadingOverlayVariant | null;
11
+ };
@@ -0,0 +1,35 @@
1
+ import { useGridSelector } from '../../utils';
2
+ import { useGridApiContext } from '../../utils/useGridApiContext';
3
+ import { useGridRootProps } from '../../utils/useGridRootProps';
4
+ import { gridExpandedRowCountSelector } from '../filter';
5
+ import { gridRowCountSelector, gridRowsLoadingSelector } from '../rows';
6
+ /**
7
+ * Uses the grid state to determine which overlay to display.
8
+ * Returns the active overlay type and the active loading overlay variant.
9
+ */
10
+ export const useGridOverlays = () => {
11
+ const apiRef = useGridApiContext();
12
+ const rootProps = useGridRootProps();
13
+ const totalRowCount = useGridSelector(apiRef, gridRowCountSelector);
14
+ const visibleRowCount = useGridSelector(apiRef, gridExpandedRowCountSelector);
15
+ const noRows = totalRowCount === 0;
16
+ const loading = useGridSelector(apiRef, gridRowsLoadingSelector);
17
+ const showNoRowsOverlay = !loading && noRows;
18
+ const showNoResultsOverlay = !loading && totalRowCount > 0 && visibleRowCount === 0;
19
+ let overlayType = null;
20
+ let loadingOverlayVariant = null;
21
+ if (showNoRowsOverlay) {
22
+ overlayType = 'noRowsOverlay';
23
+ }
24
+ if (showNoResultsOverlay) {
25
+ overlayType = 'noResultsOverlay';
26
+ }
27
+ if (loading) {
28
+ overlayType = 'loadingOverlay';
29
+ loadingOverlayVariant = rootProps.slotProps?.loadingOverlay?.[noRows ? 'noRowsVariant' : 'variant'] || null;
30
+ }
31
+ return {
32
+ overlayType,
33
+ loadingOverlayVariant
34
+ };
35
+ };
@@ -4,11 +4,11 @@ import * as ReactDOM from 'react-dom';
4
4
  import { unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
5
5
  import useLazyRef from '@mui/utils/useLazyRef';
6
6
  import useTimeout from '@mui/utils/useTimeout';
7
+ import { useResizeObserver } from '@mui/x-internals/useResizeObserver';
7
8
  import { useTheme } from '@mui/material/styles';
8
9
  import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
9
10
  import { useGridRootProps } from '../../utils/useGridRootProps';
10
11
  import { useGridSelector } from '../../utils/useGridSelector';
11
- import { useResizeObserver } from '../../utils/useResizeObserver';
12
12
  import { useRunOnce } from '../../utils/useRunOnce';
13
13
  import { gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, gridColumnPositionsSelector, gridHasColSpanSelector } from '../columns/gridColumnsSelector';
14
14
  import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors';
@@ -5,5 +5,4 @@ export { useGridSelector } from './useGridSelector';
5
5
  export * from './useGridNativeEventListener';
6
6
  export * from './useFirstRender';
7
7
  export * from './useOnMount';
8
- export * from './useResizeObserver';
9
8
  export * from './useRunOnce';
@@ -5,5 +5,4 @@ export { useGridSelector } from './useGridSelector';
5
5
  export * from './useGridNativeEventListener';
6
6
  export * from './useFirstRender';
7
7
  export * from './useOnMount';
8
- export * from './useResizeObserver';
9
8
  export * from './useRunOnce';
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.8.0
2
+ * @mui/x-data-grid v7.9.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -27,6 +27,7 @@ import type { GridColumnHeadersProps } from '../components/GridColumnHeaders';
27
27
  import type { GridDetailPanelsProps } from '../components/GridDetailPanels';
28
28
  import type { GridPinnedRowsProps } from '../components/GridPinnedRows';
29
29
  import type { GridColumnsManagementProps } from '../components/columnsManagement/GridColumnsManagement';
30
+ import type { GridLoadingOverlayProps } from '../components/GridLoadingOverlay';
30
31
  import type { GridRowCountProps } from '../components/GridRowCount';
31
32
  import type { GridColumnHeaderSortIconProps } from '../components/columnHeaders/GridColumnHeaderSortIcon';
32
33
  export interface BaseCheckboxPropsOverrides {
@@ -122,7 +123,7 @@ export interface GridSlotProps {
122
123
  filterPanel: GridFilterPanelProps & FilterPanelPropsOverrides;
123
124
  footer: GridFooterContainerProps & FooterPropsOverrides;
124
125
  footerRowCount: GridRowCountProps & FooterRowCountOverrides;
125
- loadingOverlay: GridOverlayProps & LoadingOverlayPropsOverrides;
126
+ loadingOverlay: GridLoadingOverlayProps & LoadingOverlayPropsOverrides;
126
127
  noResultsOverlay: GridOverlayProps & NoResultsOverlayPropsOverrides;
127
128
  noRowsOverlay: GridOverlayProps & NoRowsOverlayPropsOverrides;
128
129
  pagination: Partial<TablePaginationProps> & PaginationPropsOverrides;
@@ -85,8 +85,15 @@ export const useDataGridProps = inProps => {
85
85
  defaultSlots,
86
86
  slots: themedProps.slots
87
87
  }), [themedProps.slots]);
88
- return React.useMemo(() => _extends({}, DATA_GRID_PROPS_DEFAULT_VALUES, themedProps, {
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,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
- }, props, {
11
- children: /*#__PURE__*/_jsx(CircularProgress, {})
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
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
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 };
@@ -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 ?? 'left'
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 };
@@ -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
- overlayType: props.overlayType,
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" ? GridOverlayWrapper.propTypes = {
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
- overlayType: PropTypes.string.isRequired
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 apiRef = useGridApiContext();
85
+ export function GridOverlays(props) {
86
+ const {
87
+ overlayType
88
+ } = props;
85
89
  const rootProps = useGridRootProps();
86
- const totalRowCount = useGridSelector(apiRef, gridRowCountSelector);
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
- return /*#__PURE__*/_jsx(GridOverlayWrapper, {
109
- overlayType: overlayType,
110
- children: overlay
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
  }