@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,
|
|
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:
|
|
44
|
-
'& th': { bgcolor:
|
|
46
|
+
bgcolor: HEADER_BG,
|
|
47
|
+
'& th': { bgcolor: HEADER_BG }
|
|
45
48
|
};
|
|
46
|
-
const HEADER_ROW_SX = { bgcolor:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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:
|
|
327
|
+
backgroundColor: HEADER_BG,
|
|
324
328
|
position: 'sticky',
|
|
325
329
|
left: hasCheckboxCol ? CHECKBOX_COLUMN_WIDTH : 0,
|
|
326
330
|
zIndex: 4,
|
package/dist/esm/OGrid/OGrid.js
CHANGED
|
@@ -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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
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.
|
|
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.
|
|
42
|
+
"@alaarab/ogrid-react": "2.1.3"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@emotion/react": "^11.0.0",
|