@alaarab/ogrid 1.6.0 → 1.7.2
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { useCallback, useRef } from 'react';
|
|
3
|
+
import { useCallback, useRef, useMemo } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
import * as Popover from '@radix-ui/react-popover';
|
|
6
6
|
import * as Checkbox from '@radix-ui/react-checkbox';
|
|
@@ -10,6 +10,11 @@ import { StatusBar } from './StatusBar';
|
|
|
10
10
|
import { GridContextMenu } from './GridContextMenu';
|
|
11
11
|
import { useDataGridState, useColumnResize, getHeaderFilterConfig, getCellRenderDescriptor, buildHeaderRows, MarchingAntsOverlay, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, } from '@alaarab/ogrid-core';
|
|
12
12
|
import styles from './DataGridTable.module.css';
|
|
13
|
+
// Module-scope stable constants (avoid per-render allocations)
|
|
14
|
+
const GRID_ROOT_STYLE = { position: 'relative', flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' };
|
|
15
|
+
const CURSOR_CELL_STYLE = { cursor: 'cell' };
|
|
16
|
+
const STOP_PROPAGATION = (e) => e.stopPropagation();
|
|
17
|
+
const PREVENT_DEFAULT = (e) => { e.preventDefault(); };
|
|
13
18
|
function DataGridTableInner(props) {
|
|
14
19
|
const wrapperRef = useRef(null);
|
|
15
20
|
const tableContainerRef = useRef(null);
|
|
@@ -23,15 +28,69 @@ function DataGridTableInner(props) {
|
|
|
23
28
|
const { menuPosition, handleCellContextMenu, closeContextMenu } = ctxMenu;
|
|
24
29
|
const { headerFilterInput, cellDescriptorInput, statusBarConfig, showEmptyInGrid } = viewModels;
|
|
25
30
|
const { items, columns, getRowId, emptyState, layoutMode = 'fill', rowSelection = 'none', freezeRows, freezeCols, suppressHorizontalScroll, isLoading = false, loadingMessage = 'Loading\u2026', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, visibleColumns, } = props;
|
|
26
|
-
|
|
31
|
+
// Memoize header rows (recursive tree traversal — avoid recomputing every render)
|
|
32
|
+
const headerRows = useMemo(() => buildHeaderRows(columns, visibleColumns), [columns, visibleColumns]);
|
|
27
33
|
const allowOverflowX = !suppressHorizontalScroll && containerWidth > 0 && (minTableWidth > containerWidth || desiredTableWidth > containerWidth);
|
|
28
34
|
const fitToContent = layoutMode === 'content';
|
|
29
35
|
const { handleResizeStart, getColumnWidth } = useColumnResize({
|
|
30
36
|
columnSizingOverrides,
|
|
31
37
|
setColumnSizingOverrides,
|
|
32
38
|
});
|
|
33
|
-
const editCallbacks =
|
|
34
|
-
const interactionHandlers =
|
|
39
|
+
const editCallbacks = useMemo(() => ({ commitCellEdit, setEditingCell, setPendingEditorValue, cancelPopoverEdit }), [commitCellEdit, setEditingCell, setPendingEditorValue, cancelPopoverEdit]);
|
|
40
|
+
const interactionHandlers = useMemo(() => ({ handleCellMouseDown, setActiveCell, setEditingCell, handleCellContextMenu }), [handleCellMouseDown, setActiveCell, setEditingCell, handleCellContextMenu]);
|
|
41
|
+
// Pre-compute column styles and classNames (avoids per-cell object creation in the row loop)
|
|
42
|
+
const columnMeta = useMemo(() => {
|
|
43
|
+
const cellStyles = {};
|
|
44
|
+
const cellClasses = {};
|
|
45
|
+
const hdrStyles = {};
|
|
46
|
+
const hdrClasses = {};
|
|
47
|
+
for (let i = 0; i < visibleCols.length; i++) {
|
|
48
|
+
const col = visibleCols[i];
|
|
49
|
+
const columnWidth = getColumnWidth(col);
|
|
50
|
+
const hasExplicitWidth = !!(columnSizingOverrides[col.columnId] || col.idealWidth != null || col.defaultWidth != null);
|
|
51
|
+
const isFreezeCol = freezeCols != null && freezeCols >= 1 && i < freezeCols;
|
|
52
|
+
const isPinnedLeft = col.pinned === 'left';
|
|
53
|
+
const isPinnedRight = col.pinned === 'right';
|
|
54
|
+
cellStyles[col.columnId] = {
|
|
55
|
+
minWidth: col.minWidth ?? 80,
|
|
56
|
+
width: hasExplicitWidth ? columnWidth : undefined,
|
|
57
|
+
maxWidth: hasExplicitWidth ? columnWidth : undefined,
|
|
58
|
+
textAlign: col.type === 'numeric' ? 'right' : col.type === 'boolean' ? 'center' : undefined,
|
|
59
|
+
};
|
|
60
|
+
hdrStyles[col.columnId] = {
|
|
61
|
+
minWidth: col.minWidth ?? 80,
|
|
62
|
+
width: hasExplicitWidth ? columnWidth : undefined,
|
|
63
|
+
maxWidth: hasExplicitWidth ? columnWidth : undefined,
|
|
64
|
+
};
|
|
65
|
+
const parts = [];
|
|
66
|
+
if (isFreezeCol)
|
|
67
|
+
parts.push(styles.freezeCol);
|
|
68
|
+
if (isFreezeCol && i === 0)
|
|
69
|
+
parts.push(styles.freezeColFirst);
|
|
70
|
+
if (isPinnedLeft)
|
|
71
|
+
parts.push(styles.pinnedColLeft);
|
|
72
|
+
if (isPinnedRight)
|
|
73
|
+
parts.push(styles.pinnedColRight);
|
|
74
|
+
const cn = parts.join(' ');
|
|
75
|
+
cellClasses[col.columnId] = cn;
|
|
76
|
+
hdrClasses[col.columnId] = cn;
|
|
77
|
+
}
|
|
78
|
+
return { cellStyles, cellClasses, hdrStyles, hdrClasses };
|
|
79
|
+
}, [visibleCols, getColumnWidth, columnSizingOverrides, freezeCols]);
|
|
80
|
+
// Stable row-click handler (avoids creating a new arrow function per row)
|
|
81
|
+
const selectedRowIdsRef = useRef(selectedRowIds);
|
|
82
|
+
selectedRowIdsRef.current = selectedRowIds;
|
|
83
|
+
const handleSingleRowClick = useCallback((e) => {
|
|
84
|
+
if (rowSelection !== 'single')
|
|
85
|
+
return;
|
|
86
|
+
const rowId = e.currentTarget.dataset.rowId;
|
|
87
|
+
if (!rowId)
|
|
88
|
+
return;
|
|
89
|
+
const ids = selectedRowIdsRef.current;
|
|
90
|
+
updateSelection(ids.has(rowId) ? new Set() : new Set([rowId]));
|
|
91
|
+
}, [rowSelection, updateSelection]);
|
|
92
|
+
// Stable header select-all handler
|
|
93
|
+
const handleSelectAllChecked = useCallback((c) => handleSelectAll(!!c), [handleSelectAll]);
|
|
35
94
|
const renderCellContent = useCallback((item, col, rowIndex, colIdx) => {
|
|
36
95
|
const descriptor = getCellRenderDescriptor(item, col, rowIndex, colIdx, cellDescriptorInput);
|
|
37
96
|
if (descriptor.mode === 'editing-inline') {
|
|
@@ -54,65 +113,28 @@ function DataGridTableInner(props) {
|
|
|
54
113
|
descriptor.isInCopyRange ? styles.cellCopied : '',
|
|
55
114
|
].filter(Boolean).join(' ');
|
|
56
115
|
const interactionProps = getCellInteractionProps(descriptor, col.columnId, interactionHandlers);
|
|
57
|
-
return (_jsxs("div", { className: cellClassNames, ...interactionProps, style: descriptor.canEditAny ?
|
|
116
|
+
return (_jsxs("div", { className: cellClassNames, ...interactionProps, style: descriptor.canEditAny ? CURSOR_CELL_STYLE : undefined, children: [styledContent, descriptor.canEditAny && descriptor.isSelectionEndCell && (_jsx("div", { className: styles.fillHandle, onMouseDown: handleFillHandleMouseDown, "aria-label": "Fill handle" }))] }));
|
|
58
117
|
}, [cellDescriptorInput, pendingEditorValue, popoverAnchorEl, editCallbacks, interactionHandlers, handleFillHandleMouseDown, setPopoverAnchorEl, cancelPopoverEdit]);
|
|
59
|
-
return (_jsxs("div", { ref: wrapperRef, tabIndex: 0, onMouseDown: (e) => { lastMouseShiftRef.current = e.shiftKey; }, className: `${styles.tableWrapper} ${rowSelection !== 'none' ? styles.selectableGrid : ''}`, role: "region", "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Data grid'), "aria-labelledby": ariaLabelledBy, "data-empty": showEmptyInGrid ? 'true' : undefined, "data-column-count": totalColCount, "data-freeze-rows": freezeRows != null && freezeRows >= 1 ? freezeRows : undefined, "data-freeze-cols": freezeCols != null && freezeCols >= 1 ? freezeCols : undefined, "data-overflow-x": allowOverflowX ? 'true' : 'false', "data-container-width": containerWidth, "data-min-table-width": Math.round(minTableWidth), "data-has-selection": rowSelection !== 'none' ? 'true' : undefined, onContextMenu:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
isFreezeCol ? styles.freezeCol : '',
|
|
81
|
-
isFreezeCol && colIdx === 0 ? styles.freezeColFirst : '',
|
|
82
|
-
isPinnedLeft ? styles.pinnedColLeft : '',
|
|
83
|
-
isPinnedRight ? styles.pinnedColRight : '',
|
|
84
|
-
].filter(Boolean).join(' '), style: {
|
|
85
|
-
minWidth: col.minWidth ?? 80,
|
|
86
|
-
width: hasExplicitWidth ? columnWidth : undefined,
|
|
87
|
-
maxWidth: hasExplicitWidth ? columnWidth : undefined,
|
|
88
|
-
}, children: [_jsx(ColumnHeaderFilter, { ...getHeaderFilterConfig(col, headerFilterInput) }), _jsx("div", { className: styles.resizeHandle, onMouseDown: (e) => handleResizeStart(e, col), "aria-label": `Resize ${col.name}` })] }, col.columnId));
|
|
89
|
-
})] }, rowIdx))) }), !showEmptyInGrid && (_jsx("tbody", { children: items.map((item, rowIndex) => {
|
|
90
|
-
const rowIdStr = getRowId(item);
|
|
91
|
-
const isSelected = selectedRowIds.has(rowIdStr);
|
|
92
|
-
return (_jsxs("tr", { className: isSelected ? styles.selectedRow : '', onClick: () => {
|
|
93
|
-
if (rowSelection === 'single') {
|
|
94
|
-
const id = getRowId(item);
|
|
95
|
-
updateSelection(selectedRowIds.has(id) ? new Set() : new Set([id]));
|
|
96
|
-
}
|
|
97
|
-
}, children: [hasCheckboxCol && (_jsx("td", { className: styles.selectionCell, children: _jsx("div", { className: styles.selectionCellInner, "data-row-index": rowIndex, "data-col-index": 0, onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox.Root, { className: styles.rowCheckbox, checked: selectedRowIds.has(rowIdStr), onCheckedChange: (c) => handleRowCheckboxChange(rowIdStr, !!c, rowIndex, lastMouseShiftRef.current), "aria-label": `Select row ${rowIndex + 1}`, children: _jsx(Checkbox.Indicator, { className: styles.rowCheckboxIndicator, children: "\u2713" }) }) }) })), visibleCols.map((col, colIdx) => {
|
|
98
|
-
const isFreezeCol = freezeCols != null && freezeCols >= 1 && colIdx < freezeCols;
|
|
99
|
-
const isPinnedLeft = col.pinned === 'left';
|
|
100
|
-
const isPinnedRight = col.pinned === 'right';
|
|
101
|
-
const columnWidth = getColumnWidth(col);
|
|
102
|
-
const hasExplicitWidth = !!(columnSizingOverrides[col.columnId] || col.idealWidth != null || col.defaultWidth != null);
|
|
103
|
-
return (_jsx("td", { className: [
|
|
104
|
-
isFreezeCol ? styles.freezeCol : '',
|
|
105
|
-
isFreezeCol && colIdx === 0 ? styles.freezeColFirst : '',
|
|
106
|
-
isPinnedLeft ? styles.pinnedColLeft : '',
|
|
107
|
-
isPinnedRight ? styles.pinnedColRight : '',
|
|
108
|
-
].filter(Boolean).join(' '), style: {
|
|
109
|
-
minWidth: col.minWidth ?? 80,
|
|
110
|
-
width: hasExplicitWidth ? columnWidth : undefined,
|
|
111
|
-
maxWidth: hasExplicitWidth ? columnWidth : undefined,
|
|
112
|
-
textAlign: col.type === 'numeric' ? 'right' : col.type === 'boolean' ? 'center' : undefined,
|
|
113
|
-
}, children: renderCellContent(item, col, rowIndex, colIdx) }, col.columnId));
|
|
114
|
-
})] }, rowIdStr));
|
|
115
|
-
}) }))] }), _jsx(MarchingAntsOverlay, { containerRef: tableContainerRef, selectionRange: selectionRange, copyRange: copyRange, cutRange: cutRange, colOffset: colOffset }), showEmptyInGrid && emptyState && (_jsx("div", { className: styles.emptyStateInGrid, children: _jsx("div", { children: emptyState.render ? (emptyState.render()) : (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.emptyStateInGridTitle, children: "No results found" }), _jsx("div", { className: styles.emptyStateInGridMessage, children: emptyState.message != null ? (emptyState.message) : emptyState.hasActiveFilters ? (_jsxs(_Fragment, { children: ["No items match your current filters. Try adjusting your search or", ' ', _jsx("button", { type: "button", className: styles.emptyStateInGridLink, onClick: emptyState.onClearAll, children: "clear all filters" }), ' ', "to see all items."] })) : ('There are no items available at this time.') })] })) }) }))] }) }), statusBarConfig && (_jsx(StatusBar, { totalCount: statusBarConfig.totalCount, filteredCount: statusBarConfig.filteredCount, selectedCount: statusBarConfig.selectedCount ?? selectedRowIds.size, selectedCellCount: selectionRange ? (Math.abs(selectionRange.endRow - selectionRange.startRow) + 1) * (Math.abs(selectionRange.endCol - selectionRange.startCol) + 1) : undefined, aggregation: statusBarConfig.aggregation, suppressRowCount: statusBarConfig.suppressRowCount }))] }), menuPosition &&
|
|
116
|
-
createPortal(_jsx(GridContextMenu, { x: menuPosition.x, y: menuPosition.y, hasSelection: hasCellSelection, canUndo: canUndo, canRedo: canRedo, onUndo: onUndo ?? (() => { }), onRedo: onRedo ?? (() => { }), onCopy: handleCopy, onCut: handleCut, onPaste: () => void handlePaste(), onSelectAll: handleSelectAllCells, onClose: closeContextMenu }), document.body)] }));
|
|
118
|
+
return (_jsxs("div", { style: GRID_ROOT_STYLE, children: [_jsxs("div", { ref: wrapperRef, tabIndex: 0, onMouseDown: (e) => { lastMouseShiftRef.current = e.shiftKey; }, className: `${styles.tableWrapper} ${rowSelection !== 'none' ? styles.selectableGrid : ''}`, role: "region", "aria-label": ariaLabel ?? (ariaLabelledBy ? undefined : 'Data grid'), "aria-labelledby": ariaLabelledBy, "data-empty": showEmptyInGrid ? 'true' : undefined, "data-column-count": totalColCount, "data-freeze-rows": freezeRows != null && freezeRows >= 1 ? freezeRows : undefined, "data-freeze-cols": freezeCols != null && freezeCols >= 1 ? freezeCols : undefined, "data-overflow-x": allowOverflowX ? 'true' : 'false', "data-container-width": containerWidth, "data-min-table-width": Math.round(minTableWidth), "data-has-selection": rowSelection !== 'none' ? 'true' : undefined, onContextMenu: PREVENT_DEFAULT, onKeyDown: handleGridKeyDown, style: {
|
|
119
|
+
['--data-table-column-count']: totalColCount,
|
|
120
|
+
['--data-table-width']: showEmptyInGrid ? '100%' : allowOverflowX ? 'fit-content' : fitToContent ? 'fit-content' : '100%',
|
|
121
|
+
['--data-table-min-width']: showEmptyInGrid ? '100%' : allowOverflowX ? 'max-content' : fitToContent ? 'max-content' : '100%',
|
|
122
|
+
['--data-table-total-min-width']: `${minTableWidth}px`,
|
|
123
|
+
}, children: [_jsxs("div", { className: styles.tableScrollContent, children: [_jsx("div", { className: isLoading && items.length > 0 ? styles.loadingDimmed : undefined, children: _jsxs("div", { className: styles.tableWidthAnchor, ref: tableContainerRef, children: [_jsxs("table", { className: styles.dataTable, children: [_jsx("thead", { className: styles.stickyHeader, children: headerRows.map((row, rowIdx) => (_jsxs("tr", { children: [rowIdx === headerRows.length - 1 && hasCheckboxCol && (_jsx("th", { className: styles.selectionHeaderCell, scope: "col", rowSpan: 1, children: _jsx("div", { className: styles.selectionHeaderCellInner, children: _jsx(Checkbox.Root, { className: styles.rowCheckbox, checked: allSelected ? true : someSelected ? 'indeterminate' : false, onCheckedChange: handleSelectAllChecked, "aria-label": "Select all rows", children: _jsx(Checkbox.Indicator, { className: styles.rowCheckboxIndicator, children: someSelected && !allSelected ? '–' : '✓' }) }) }) })), rowIdx === 0 && rowIdx < headerRows.length - 1 && hasCheckboxCol && (_jsx("th", { rowSpan: headerRows.length - 1 })), row.map((cell, cellIdx) => {
|
|
124
|
+
if (cell.isGroup) {
|
|
125
|
+
return (_jsx("th", { colSpan: cell.colSpan, className: styles.groupHeaderCell, scope: "colgroup", children: cell.label }, cellIdx));
|
|
126
|
+
}
|
|
127
|
+
// Leaf cell
|
|
128
|
+
const col = cell.columnDef;
|
|
129
|
+
const leafRowSpan = headerRows.length > 1 && rowIdx < headerRows.length - 1
|
|
130
|
+
? headerRows.length - rowIdx
|
|
131
|
+
: undefined;
|
|
132
|
+
return (_jsxs("th", { scope: "col", "data-column-id": col.columnId, rowSpan: leafRowSpan, className: columnMeta.hdrClasses[col.columnId] || undefined, style: columnMeta.hdrStyles[col.columnId], children: [_jsx(ColumnHeaderFilter, { ...getHeaderFilterConfig(col, headerFilterInput) }), _jsx("div", { className: styles.resizeHandle, onMouseDown: (e) => handleResizeStart(e, col), "aria-label": `Resize ${col.name}` })] }, col.columnId));
|
|
133
|
+
})] }, rowIdx))) }), !showEmptyInGrid && (_jsx("tbody", { children: items.map((item, rowIndex) => {
|
|
134
|
+
const rowIdStr = getRowId(item);
|
|
135
|
+
const isSelected = selectedRowIds.has(rowIdStr);
|
|
136
|
+
return (_jsxs("tr", { className: isSelected ? styles.selectedRow : '', "data-row-id": rowIdStr, onClick: handleSingleRowClick, children: [hasCheckboxCol && (_jsx("td", { className: styles.selectionCell, children: _jsx("div", { className: styles.selectionCellInner, "data-row-index": rowIndex, "data-col-index": 0, onClick: STOP_PROPAGATION, children: _jsx(Checkbox.Root, { className: styles.rowCheckbox, checked: selectedRowIds.has(rowIdStr), onCheckedChange: (c) => handleRowCheckboxChange(rowIdStr, !!c, rowIndex, lastMouseShiftRef.current), "aria-label": `Select row ${rowIndex + 1}`, children: _jsx(Checkbox.Indicator, { className: styles.rowCheckboxIndicator, children: "\u2713" }) }) }) })), visibleCols.map((col, colIdx) => (_jsx("td", { className: columnMeta.cellClasses[col.columnId] || undefined, style: columnMeta.cellStyles[col.columnId], children: renderCellContent(item, col, rowIndex, colIdx) }, col.columnId)))] }, rowIdStr));
|
|
137
|
+
}) }))] }), _jsx(MarchingAntsOverlay, { containerRef: tableContainerRef, selectionRange: selectionRange, copyRange: copyRange, cutRange: cutRange, colOffset: colOffset }), showEmptyInGrid && emptyState && (_jsx("div", { className: styles.emptyStateInGrid, children: _jsx("div", { children: emptyState.render ? (emptyState.render()) : (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.emptyStateInGridTitle, children: "No results found" }), _jsx("div", { className: styles.emptyStateInGridMessage, children: emptyState.message != null ? (emptyState.message) : emptyState.hasActiveFilters ? (_jsxs(_Fragment, { children: ["No items match your current filters. Try adjusting your search or", ' ', _jsx("button", { type: "button", className: styles.emptyStateInGridLink, onClick: emptyState.onClearAll, children: "clear all filters" }), ' ', "to see all items."] })) : ('There are no items available at this time.') })] })) }) }))] }) }), statusBarConfig && (_jsx(StatusBar, { totalCount: statusBarConfig.totalCount, filteredCount: statusBarConfig.filteredCount, selectedCount: statusBarConfig.selectedCount ?? selectedRowIds.size, selectedCellCount: selectionRange ? (Math.abs(selectionRange.endRow - selectionRange.startRow) + 1) * (Math.abs(selectionRange.endCol - selectionRange.startCol) + 1) : undefined, aggregation: statusBarConfig.aggregation, suppressRowCount: statusBarConfig.suppressRowCount }))] }), menuPosition &&
|
|
138
|
+
createPortal(_jsx(GridContextMenu, { x: menuPosition.x, y: menuPosition.y, hasSelection: hasCellSelection, canUndo: canUndo, canRedo: canRedo, onUndo: onUndo ?? (() => { }), onRedo: onRedo ?? (() => { }), onCopy: handleCopy, onCut: handleCut, onPaste: () => void handlePaste(), onSelectAll: handleSelectAllCells, onClose: closeContextMenu }), document.body)] }), isLoading && items.length > 0 && (_jsx("div", { className: styles.loadingOverlay, "aria-live": "polite", children: _jsxs("div", { className: styles.loadingOverlayContent, children: [_jsx("div", { className: styles.spinner }), _jsx("span", { className: styles.loadingOverlayText, children: loadingMessage })] }) }))] }));
|
|
117
139
|
}
|
|
118
140
|
export const DataGridTable = React.memo(DataGridTableInner);
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
max-width: 100%;
|
|
20
20
|
box-sizing: border-box;
|
|
21
21
|
background: var(--ogrid-bg, #fff);
|
|
22
|
+
will-change: scroll-position;
|
|
22
23
|
}
|
|
23
24
|
.tableWrapper[data-overflow-x=true] {
|
|
24
25
|
overflow-x: auto;
|
|
@@ -76,7 +77,7 @@
|
|
|
76
77
|
.dataTable thead.stickyHeader {
|
|
77
78
|
position: sticky;
|
|
78
79
|
top: 0;
|
|
79
|
-
z-index:
|
|
80
|
+
z-index: 6;
|
|
80
81
|
background: var(--ogrid-bg-subtle, #f3f2f1);
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -90,6 +91,7 @@
|
|
|
90
91
|
left: 0;
|
|
91
92
|
z-index: 2;
|
|
92
93
|
background: var(--ogrid-bg, #ffffff);
|
|
94
|
+
will-change: transform;
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
/* Freeze/pinned header cells need top: 0 + z-index: 3 so they stick in BOTH
|
|
@@ -99,7 +101,7 @@
|
|
|
99
101
|
.dataTable thead.stickyHeader .pinnedColLeft,
|
|
100
102
|
.dataTable thead.stickyHeader .pinnedColRight {
|
|
101
103
|
top: 0;
|
|
102
|
-
z-index:
|
|
104
|
+
z-index: 7;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
.dataTable thead .freezeColFirst {
|
|
@@ -114,6 +116,7 @@
|
|
|
114
116
|
left: 0;
|
|
115
117
|
z-index: 2;
|
|
116
118
|
background: var(--ogrid-bg, #ffffff);
|
|
119
|
+
will-change: transform;
|
|
117
120
|
}
|
|
118
121
|
.dataTable .pinnedColLeft::after {
|
|
119
122
|
content: "";
|
|
@@ -135,6 +138,7 @@
|
|
|
135
138
|
right: 0;
|
|
136
139
|
z-index: 2;
|
|
137
140
|
background: var(--ogrid-bg, #ffffff);
|
|
141
|
+
will-change: transform;
|
|
138
142
|
}
|
|
139
143
|
.dataTable .pinnedColRight::before {
|
|
140
144
|
content: "";
|
package/dist/esm/OGrid/OGrid.js
CHANGED
|
@@ -6,8 +6,8 @@ import { ColumnChooser } from '../ColumnChooser/ColumnChooser';
|
|
|
6
6
|
import { PaginationControls } from '../PaginationControls/PaginationControls';
|
|
7
7
|
import { useOGrid, OGridLayout, } from '@alaarab/ogrid-core';
|
|
8
8
|
const OGridInner = forwardRef(function OGridInner(props, ref) {
|
|
9
|
-
const { dataGridProps, page, pageSize, displayTotalCount, setPage, setPageSize, columnChooserColumns, visibleColumns, handleVisibilityChange, columnChooserPlacement, toolbar, className, entityLabelPlural, pageSizeOptions, sideBarProps, } = useOGrid(props, ref);
|
|
10
|
-
return (_jsx(OGridLayout, { className: className, sideBar: sideBarProps, toolbar: toolbar, toolbarEnd: columnChooserPlacement === 'toolbar' ? (_jsx(ColumnChooser, { columns: columnChooserColumns, visibleColumns: visibleColumns, onVisibilityChange: handleVisibilityChange })) : undefined, pagination: _jsx(PaginationControls, { currentPage: page, pageSize: pageSize, totalCount: displayTotalCount, onPageChange: setPage, onPageSizeChange: (size) => {
|
|
9
|
+
const { dataGridProps, page, pageSize, displayTotalCount, setPage, setPageSize, columnChooserColumns, visibleColumns, handleVisibilityChange, columnChooserPlacement, toolbar, toolbarBelow, className, entityLabelPlural, pageSizeOptions, sideBarProps, } = useOGrid(props, ref);
|
|
10
|
+
return (_jsx(OGridLayout, { className: className, sideBar: sideBarProps, toolbar: toolbar, toolbarBelow: toolbarBelow, toolbarEnd: columnChooserPlacement === 'toolbar' ? (_jsx(ColumnChooser, { columns: columnChooserColumns, visibleColumns: visibleColumns, onVisibilityChange: handleVisibilityChange })) : undefined, pagination: _jsx(PaginationControls, { currentPage: page, pageSize: pageSize, totalCount: displayTotalCount, onPageChange: setPage, onPageSizeChange: (size) => {
|
|
11
11
|
setPageSize(size);
|
|
12
12
|
setPage(1);
|
|
13
13
|
}, pageSizeOptions: pageSizeOptions, entityLabelPlural: entityLabelPlural }), children: _jsx(DataGridTable, { ...dataGridProps }) }));
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import type { IOGridDataGridProps } from '@alaarab/ogrid-core';
|
|
3
|
-
/** @deprecated Use IOGridDataGridProps from @alaarab/ogrid-core for new code. */
|
|
4
|
-
export type IDataGridTableProps<T> = IOGridDataGridProps<T>;
|
|
5
3
|
declare function DataGridTableInner<T>(props: IOGridDataGridProps<T>): React.ReactElement;
|
|
6
4
|
export declare const DataGridTable: typeof DataGridTableInner;
|
|
7
5
|
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { OGrid, type IOGridProps } from './OGrid/OGrid';
|
|
2
|
-
export { DataGridTable
|
|
2
|
+
export { DataGridTable } from './DataGridTable/DataGridTable';
|
|
3
3
|
export { ColumnChooser, type IColumnChooserProps } from './ColumnChooser/ColumnChooser';
|
|
4
4
|
export { ColumnHeaderFilter, type IColumnHeaderFilterProps } from './ColumnHeaderFilter/ColumnHeaderFilter';
|
|
5
5
|
export { PaginationControls, type IPaginationControlsProps } from './PaginationControls/PaginationControls';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "OGrid default (Radix) – Data grid with sorting, filtering, pagination, column chooser, and CSV export. Packed with Radix UI; no Fluent or Material required.",
|
|
5
5
|
"main": "dist/esm/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"node": ">=18"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@alaarab/ogrid-core": "^1.
|
|
44
|
+
"@alaarab/ogrid-core": "^1.7.2",
|
|
45
45
|
"@radix-ui/react-checkbox": "^1.1.2",
|
|
46
46
|
"@radix-ui/react-popover": "^1.1.2"
|
|
47
47
|
},
|