@alaarab/ogrid-react-material 2.1.2 → 2.1.3

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.
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import * as React from 'react';
3
3
  import { useCallback, useMemo } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
- import { Box, Popover, Checkbox, Table, TableHead, TableBody, TableRow, TableCell, TableContainer, } from '@mui/material';
5
+ import { Box, Popover, Checkbox, Table, TableHead, TableBody, TableRow, TableCell, } from '@mui/material';
6
6
  import { ColumnHeaderFilter } from '../ColumnHeaderFilter';
7
7
  import { ColumnHeaderMenu } from '../ColumnHeaderMenu';
8
8
  import { InlineCellEditor } from './InlineCellEditor';
@@ -35,15 +35,18 @@ const ROW_HOVER_SX = { '&:hover': { bgcolor: 'action.hover' } };
35
35
  const CHECKBOX_CELL_SX = { width: CHECKBOX_COLUMN_WIDTH, minWidth: CHECKBOX_COLUMN_WIDTH, maxWidth: CHECKBOX_COLUMN_WIDTH, textAlign: 'center' };
36
36
  const CHECKBOX_WRAPPER_SX = { display: 'flex', alignItems: 'center', justifyContent: 'center' };
37
37
  const CHECKBOX_PLACEHOLDER_SX = { width: CHECKBOX_COLUMN_WIDTH, minWidth: CHECKBOX_COLUMN_WIDTH, p: 0 };
38
- // Header
38
+ // Header — use opaque var(--ogrid-header-bg) (not semi-transparent action.hover) so sticky
39
+ // headers fully occlude pinned-column content scrolling beneath them.
40
+ // The CSS variable is theme-aware: light=#f5f5f5, dark=#2c2c2c (set by each UI package).
41
+ const HEADER_BG = 'var(--ogrid-header-bg, #f5f5f5)';
39
42
  const STICKY_HEADER_SX = {
40
43
  /* Removed position: 'sticky', top: 0 - breaks horizontal sticky on pinned columns.
41
44
  Instead, apply sticky to individual header cells (HEADER_BASE_SX). */
42
45
  zIndex: 8,
43
- bgcolor: 'action.hover',
44
- '& th': { bgcolor: 'action.hover' }
46
+ bgcolor: HEADER_BG,
47
+ '& th': { bgcolor: HEADER_BG }
45
48
  };
46
- const HEADER_ROW_SX = { bgcolor: 'action.hover' };
49
+ const HEADER_ROW_SX = { bgcolor: HEADER_BG };
47
50
  const GROUP_HEADER_CELL_SX = { textAlign: 'center', fontWeight: 600, borderBottom: 2, borderColor: 'divider', py: 0.75 };
48
51
  // Density padding helper
49
52
  function getDensityPadding(density) {
@@ -137,22 +140,23 @@ const CELL_TD_PINNED_RIGHT_SX = {
137
140
  boxShadow: '-2px 0 4px -1px rgba(0,0,0,0.1)',
138
141
  };
139
142
  // Header cell positioning variants (sticky)
143
+ // Use opaque HEADER_BG so headers fully occlude content scrolling beneath them.
140
144
  const HEADER_BASE_SX = {
141
145
  fontWeight: 600,
142
146
  position: 'sticky', /* Enables vertical sticky for all headers */
143
147
  top: 0, /* Sticky vertically */
144
148
  zIndex: 8, /* Stack above body cells */
145
- bgcolor: 'action.hover' /* Required for sticky overlap */
149
+ bgcolor: HEADER_BG /* Opaque — required for sticky overlap */
146
150
  };
147
151
  const HEADER_PINNED_LEFT_SX = {
148
152
  ...HEADER_BASE_SX, position: 'sticky', left: 0, top: 0,
149
- zIndex: 10, bgcolor: 'action.hover', willChange: 'transform',
153
+ zIndex: 10, bgcolor: HEADER_BG, willChange: 'transform',
150
154
  borderRight: '1px solid', borderRightColor: 'divider',
151
155
  boxShadow: '2px 0 4px -1px rgba(0,0,0,0.1)',
152
156
  };
153
157
  const HEADER_PINNED_RIGHT_SX = {
154
158
  ...HEADER_BASE_SX, position: 'sticky', right: 0, top: 0,
155
- zIndex: 10, bgcolor: 'action.hover', willChange: 'transform',
159
+ zIndex: 10, bgcolor: HEADER_BG, willChange: 'transform',
156
160
  borderLeft: '1px solid', borderLeftColor: 'divider',
157
161
  boxShadow: '-2px 0 4px -1px rgba(0,0,0,0.1)',
158
162
  };
@@ -160,17 +164,17 @@ const HEADER_PINNED_RIGHT_SX = {
160
164
  const HEADER_BASE_NO_STICKY_SX = {
161
165
  fontWeight: 600,
162
166
  zIndex: 8,
163
- bgcolor: 'action.hover',
167
+ bgcolor: HEADER_BG,
164
168
  };
165
169
  const HEADER_PINNED_LEFT_NO_STICKY_SX = {
166
170
  ...HEADER_BASE_NO_STICKY_SX, position: 'sticky', left: 0,
167
- zIndex: 10, willChange: 'transform',
171
+ zIndex: 10, bgcolor: HEADER_BG, willChange: 'transform',
168
172
  borderRight: '1px solid', borderRightColor: 'divider',
169
173
  boxShadow: '2px 0 4px -1px rgba(0,0,0,0.1)',
170
174
  };
171
175
  const HEADER_PINNED_RIGHT_NO_STICKY_SX = {
172
176
  ...HEADER_BASE_NO_STICKY_SX, position: 'sticky', right: 0,
173
- zIndex: 10, willChange: 'transform',
177
+ zIndex: 10, bgcolor: HEADER_BG, willChange: 'transform',
174
178
  borderLeft: '1px solid', borderLeftColor: 'divider',
175
179
  boxShadow: '-2px 0 4px -1px rgba(0,0,0,0.1)',
176
180
  };
@@ -310,7 +314,7 @@ function DataGridTableInner(props) {
310
314
  }
311
315
  return (_jsx(CellErrorBoundary, { onError: onCellError, children: cellContent }, `${rowId}-${col.columnId}`));
312
316
  }, [editCallbacks, interactionHandlers, handleFillHandleMouseDown, setPopoverAnchorEl, cancelPopoverEdit, getRowId, onCellError, cellDescriptorInputRef, densityPadding, pendingEditorValueRef, popoverAnchorElRef]);
313
- return (_jsxs(Box, { sx: gridRootSx, children: [_jsxs(Box, { ref: wrapperRef, tabIndex: 0, role: "region", "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Data grid'), "aria-labelledby": ariaLabelledBy, onMouseDown: (e) => { lastMouseShiftRef.current = e.shiftKey; }, onKeyDown: handleGridKeyDown, onContextMenu: PREVENT_DEFAULT, "data-overflow-x": allowOverflowX ? 'true' : 'false', "data-density": density, sx: wrapperSx, children: [_jsx(Box, { sx: WRAPPER_SCROLL_SX, children: _jsx(TableContainer, { sx: { minWidth: allowOverflowX ? minTableWidth : undefined }, children: _jsxs(Box, { ref: tableContainerRef, sx: isLoading && items.length > 0 ? TABLE_WRAPPER_LOADING_SX : TABLE_WRAPPER_SX, children: [_jsxs(Table, { size: "small", sx: { minWidth: minTableWidth, borderCollapse: 'separate', borderSpacing: 0 }, children: [_jsx(TableHead, { sx: STICKY_HEADER_SX, children: headerRows.map((row, rowIdx) => (_jsxs(TableRow, { sx: HEADER_ROW_SX, children: [rowIdx === headerRows.length - 1 && hasCheckboxCol && (_jsx(TableCell, { ...{ padding: "checkbox", rowSpan: headerRows.length > 1 ? 1 : undefined, sx: CHECKBOX_CELL_SX }, children: _jsx(Checkbox, { checked: allSelected, indeterminate: someSelected, onChange: (_, c) => handleSelectAll(!!c), size: "small", "aria-label": "Select all rows" }) })), rowIdx === 0 && rowIdx < headerRows.length - 1 && hasCheckboxCol && (_jsx(TableCell, { ...{ rowSpan: headerRows.length - 1, sx: CHECKBOX_PLACEHOLDER_SX } })), rowIdx === headerRows.length - 1 && hasRowNumbersCol && (_jsx(TableCell, { ...{
317
+ return (_jsxs(Box, { sx: gridRootSx, children: [_jsxs(Box, { ref: wrapperRef, tabIndex: 0, role: "region", "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Data grid'), "aria-labelledby": ariaLabelledBy, onMouseDown: (e) => { lastMouseShiftRef.current = e.shiftKey; }, onKeyDown: handleGridKeyDown, onContextMenu: PREVENT_DEFAULT, "data-overflow-x": allowOverflowX ? 'true' : 'false', "data-density": density, sx: wrapperSx, children: [_jsx(Box, { sx: WRAPPER_SCROLL_SX, children: _jsx("div", { style: { minWidth: allowOverflowX ? minTableWidth : undefined }, children: _jsxs(Box, { ref: tableContainerRef, sx: isLoading && items.length > 0 ? TABLE_WRAPPER_LOADING_SX : TABLE_WRAPPER_SX, children: [_jsxs(Table, { size: "small", sx: { minWidth: minTableWidth, borderCollapse: 'separate', borderSpacing: 0 }, children: [_jsx(TableHead, { sx: STICKY_HEADER_SX, children: headerRows.map((row, rowIdx) => (_jsxs(TableRow, { sx: HEADER_ROW_SX, children: [rowIdx === headerRows.length - 1 && hasCheckboxCol && (_jsx(TableCell, { ...{ padding: "checkbox", rowSpan: headerRows.length > 1 ? 1 : undefined, sx: CHECKBOX_CELL_SX }, children: _jsx(Checkbox, { checked: allSelected, indeterminate: someSelected, onChange: (_, c) => handleSelectAll(!!c), size: "small", "aria-label": "Select all rows" }) })), rowIdx === 0 && rowIdx < headerRows.length - 1 && hasCheckboxCol && (_jsx(TableCell, { ...{ rowSpan: headerRows.length - 1, sx: CHECKBOX_PLACEHOLDER_SX } })), rowIdx === headerRows.length - 1 && hasRowNumbersCol && (_jsx(TableCell, { ...{
314
318
  component: "th",
315
319
  scope: "col",
316
320
  rowSpan: headerRows.length > 1 ? 1 : undefined,
@@ -320,7 +324,7 @@ function DataGridTableInner(props) {
320
324
  maxWidth: ROW_NUMBER_COLUMN_WIDTH,
321
325
  textAlign: 'center',
322
326
  fontWeight: 600,
323
- backgroundColor: 'action.hover',
327
+ backgroundColor: HEADER_BG,
324
328
  position: 'sticky',
325
329
  left: hasCheckboxCol ? CHECKBOX_COLUMN_WIDTH : 0,
326
330
  zIndex: 4,
@@ -1,28 +1,31 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import * as React from 'react';
3
- import { forwardRef } from 'react';
4
3
  import { Box, useTheme } from '@mui/material';
4
+ import { createOGrid } from '@alaarab/ogrid-react';
5
5
  import { DataGridTable } from '../DataGridTable/DataGridTable';
6
6
  import { ColumnChooser } from '../ColumnChooser/ColumnChooser';
7
7
  import { PaginationControls } from '../PaginationControls/PaginationControls';
8
- import { useOGrid, OGridLayout, } from '@alaarab/ogrid-react';
9
- const OGridInner = forwardRef(function OGridInner(props, ref) {
10
- const { dataGridProps, pagination, columnChooser, layout } = useOGrid(props, ref);
8
+ /**
9
+ * MUI theme bridge: reads the MUI palette and sets --ogrid-* CSS variables
10
+ * so the shared OGridLayout and DataGridTable styles adapt to the MUI theme.
11
+ */
12
+ const MuiThemeContainer = React.forwardRef(function MuiThemeContainer(props, ref) {
11
13
  const theme = useTheme();
12
- // Set --ogrid-* CSS variables so the shared OGridLayout adapts to MUI theme (both modes)
13
- const containerSx = React.useMemo(() => ({
14
+ const sx = React.useMemo(() => ({
14
15
  display: 'flex', flexDirection: 'column', gap: 1,
15
16
  '--ogrid-bg': theme.palette.background.default,
16
17
  '--ogrid-border': theme.palette.divider,
17
- '--ogrid-header-bg': theme.palette.action.hover,
18
+ '--ogrid-header-bg': theme.palette.mode === 'dark' ? theme.palette.grey[800] : theme.palette.grey[100],
18
19
  '--ogrid-fg': theme.palette.text.primary,
19
20
  '--ogrid-fg-secondary': theme.palette.text.secondary,
20
21
  '--ogrid-fg-muted': theme.palette.text.disabled,
21
22
  '--ogrid-hover-bg': theme.palette.action.hover,
22
23
  }), [theme]);
23
- return (_jsx(OGridLayout, { containerComponent: Box, containerProps: { sx: containerSx }, className: layout.className, sideBar: layout.sideBarProps, toolbar: layout.toolbar, toolbarBelow: layout.toolbarBelow, fullScreen: layout.fullScreen, toolbarEnd: columnChooser.placement === 'toolbar' ? (_jsx(ColumnChooser, { columns: columnChooser.columns, visibleColumns: columnChooser.visibleColumns, onVisibilityChange: columnChooser.onVisibilityChange })) : undefined, pagination: _jsx(PaginationControls, { currentPage: pagination.page, pageSize: pagination.pageSize, totalCount: pagination.displayTotalCount, onPageChange: pagination.setPage, onPageSizeChange: (size) => {
24
- pagination.setPageSize(size);
25
- }, pageSizeOptions: pagination.pageSizeOptions, entityLabelPlural: pagination.entityLabelPlural }), children: _jsx(DataGridTable, { ...dataGridProps }) }));
24
+ return _jsx(Box, { ref: ref, sx: sx, ...props });
25
+ });
26
+ export const OGrid = createOGrid({
27
+ DataGridTable: DataGridTable,
28
+ ColumnChooser: ColumnChooser,
29
+ PaginationControls,
30
+ containerComponent: MuiThemeContainer,
26
31
  });
27
- OGridInner.displayName = 'OGrid';
28
- export const OGrid = React.memo(OGridInner);
@@ -1,5 +1,3 @@
1
1
  import * as React from 'react';
2
- import { type IOGridProps, type IOGridApi } from '@alaarab/ogrid-react';
3
2
  export type { IOGridProps } from '@alaarab/ogrid-react';
4
- declare const OGridInner: React.ForwardRefExoticComponent<IOGridProps<unknown> & React.RefAttributes<IOGridApi<unknown>>>;
5
- export declare const OGrid: typeof OGridInner;
3
+ export declare const OGrid: React.ForwardRefExoticComponent<import("@alaarab/ogrid-react").IOGridProps<unknown> & React.RefAttributes<import("@alaarab/ogrid-react").IOGridApi<unknown>>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-react-material",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "OGrid React Material implementation – MUI Table–based data grid with sorting, filtering, pagination, column chooser, spreadsheet selection, and CSV export.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -39,7 +39,7 @@
39
39
  "node": ">=18"
40
40
  },
41
41
  "dependencies": {
42
- "@alaarab/ogrid-react": "2.1.2"
42
+ "@alaarab/ogrid-react": "2.1.3"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@emotion/react": "^11.0.0",