@alaarab/ogrid-react-radix 2.0.2 → 2.0.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.
- package/dist/esm/ColumnChooser/ColumnChooser.module.css +1 -1
- package/dist/esm/ColumnHeaderFilter/ColumnHeaderFilter.module.css +1 -1
- package/dist/esm/ColumnHeaderFilter/PeopleFilterPopover.js +1 -1
- package/dist/esm/DataGridTable/DataGridTable.js +33 -7
- package/dist/esm/DataGridTable/DataGridTable.module.css +17 -5
- package/package.json +2 -2
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
min-width: 220px;
|
|
40
40
|
background: var(--ogrid-bg, #fff);
|
|
41
41
|
border-radius: 6px;
|
|
42
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
42
|
+
box-shadow: var(--ogrid-shadow, 0 4px 16px rgba(0, 0, 0, 0.12));
|
|
43
43
|
border: 1px solid var(--ogrid-border, #e0e0e0);
|
|
44
44
|
display: flex;
|
|
45
45
|
flex-direction: column;
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
background: var(--ogrid-bg, #fff);
|
|
109
109
|
border: 1px solid var(--ogrid-border, #d1d1d1);
|
|
110
110
|
border-radius: 8px;
|
|
111
|
-
box-shadow: 0
|
|
111
|
+
box-shadow: var(--ogrid-shadow, 0 4px 16px rgba(0, 0, 0, 0.12));
|
|
112
112
|
overflow: hidden;
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -8,7 +8,7 @@ import { ColumnHeaderFilter } from '../ColumnHeaderFilter';
|
|
|
8
8
|
import { InlineCellEditor } from './InlineCellEditor';
|
|
9
9
|
import { StatusBar } from './StatusBar';
|
|
10
10
|
import { GridContextMenu } from './GridContextMenu';
|
|
11
|
-
import { useDataGridState, useColumnResize, useLatestRef, getHeaderFilterConfig, getCellRenderDescriptor, buildHeaderRows, MarchingAntsOverlay, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, areGridRowPropsEqual, CellErrorBoundary, DEFAULT_MIN_COLUMN_WIDTH, } from '@alaarab/ogrid-react';
|
|
11
|
+
import { useDataGridState, useColumnResize, useColumnReorder, useVirtualScroll, useLatestRef, getHeaderFilterConfig, getCellRenderDescriptor, buildHeaderRows, MarchingAntsOverlay, resolveCellDisplayContent, resolveCellStyle, buildInlineEditorProps, buildPopoverEditorProps, getCellInteractionProps, areGridRowPropsEqual, CellErrorBoundary, DEFAULT_MIN_COLUMN_WIDTH, } from '@alaarab/ogrid-react';
|
|
12
12
|
import styles from './DataGridTable.module.css';
|
|
13
13
|
// Module-scope stable constants (avoid per-render allocations)
|
|
14
14
|
const GRID_ROOT_STYLE = { position: 'relative', flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' };
|
|
@@ -35,7 +35,7 @@ function DataGridTableInner(props) {
|
|
|
35
35
|
const handlePasteVoid = useCallback(() => { void handlePaste(); }, [handlePaste]);
|
|
36
36
|
const { menuPosition, handleCellContextMenu, closeContextMenu } = ctxMenu;
|
|
37
37
|
const { headerFilterInput, cellDescriptorInput, statusBarConfig, showEmptyInGrid, onCellError } = viewModels;
|
|
38
|
-
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;
|
|
38
|
+
const { items, columns, getRowId, emptyState, layoutMode = 'fill', rowSelection = 'none', freezeRows, freezeCols, suppressHorizontalScroll, isLoading = false, loadingMessage = 'Loading\u2026', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, visibleColumns, columnOrder, onColumnOrderChange, columnReorder, virtualScroll, pinnedColumns, } = props;
|
|
39
39
|
// Memoize header rows (recursive tree traversal — avoid recomputing every render)
|
|
40
40
|
const headerRows = useMemo(() => buildHeaderRows(columns, visibleColumns), [columns, visibleColumns]);
|
|
41
41
|
const allowOverflowX = !suppressHorizontalScroll && containerWidth > 0 && (minTableWidth > containerWidth || desiredTableWidth > containerWidth);
|
|
@@ -44,6 +44,23 @@ function DataGridTableInner(props) {
|
|
|
44
44
|
columnSizingOverrides,
|
|
45
45
|
setColumnSizingOverrides,
|
|
46
46
|
});
|
|
47
|
+
const { isDragging: isReorderDragging, dropIndicatorX, handleHeaderMouseDown } = useColumnReorder({
|
|
48
|
+
columns: visibleCols,
|
|
49
|
+
columnOrder,
|
|
50
|
+
onColumnOrderChange,
|
|
51
|
+
enabled: columnReorder === true,
|
|
52
|
+
pinnedColumns,
|
|
53
|
+
wrapperRef,
|
|
54
|
+
});
|
|
55
|
+
const virtualScrollEnabled = virtualScroll?.enabled === true;
|
|
56
|
+
const virtualRowHeight = virtualScroll?.rowHeight ?? 36;
|
|
57
|
+
const { visibleRange } = useVirtualScroll({
|
|
58
|
+
totalRows: items.length,
|
|
59
|
+
rowHeight: virtualRowHeight,
|
|
60
|
+
enabled: virtualScrollEnabled,
|
|
61
|
+
overscan: virtualScroll?.overscan,
|
|
62
|
+
containerRef: wrapperRef,
|
|
63
|
+
});
|
|
47
64
|
const editCallbacks = useMemo(() => ({ commitCellEdit, setEditingCell, setPendingEditorValue, cancelPopoverEdit }), [commitCellEdit, setEditingCell, setPendingEditorValue, cancelPopoverEdit]);
|
|
48
65
|
const interactionHandlers = useMemo(() => ({ handleCellMouseDown, setActiveCell, setEditingCell, handleCellContextMenu }), [handleCellMouseDown, setActiveCell, setEditingCell, handleCellContextMenu]);
|
|
49
66
|
// Refs for volatile state — lets renderCellContent be stable (same function ref across
|
|
@@ -145,11 +162,20 @@ function DataGridTableInner(props) {
|
|
|
145
162
|
const leafRowSpan = headerRows.length > 1 && rowIdx < headerRows.length - 1
|
|
146
163
|
? headerRows.length - rowIdx
|
|
147
164
|
: undefined;
|
|
148
|
-
return (_jsxs("th", { scope: "col", "data-column-id": col.columnId, rowSpan: leafRowSpan, className: columnMeta.hdrClasses[col.columnId] || undefined, style:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
return (_jsxs("th", { scope: "col", "data-column-id": col.columnId, rowSpan: leafRowSpan, className: columnMeta.hdrClasses[col.columnId] || undefined, style: {
|
|
166
|
+
...columnMeta.hdrStyles[col.columnId],
|
|
167
|
+
...(columnReorder ? { cursor: isReorderDragging ? 'grabbing' : 'grab' } : undefined),
|
|
168
|
+
}, onMouseDown: columnReorder ? (e) => handleHeaderMouseDown(col.columnId, e) : undefined, children: [_jsx(ColumnHeaderFilter, { ...getHeaderFilterConfig(col, headerFilterInput) }), _jsx("div", { className: styles.resizeHandle, onMouseDown: (e) => handleResizeStart(e, col), "aria-label": `Resize ${col.name}` })] }, col.columnId));
|
|
169
|
+
})] }, rowIdx))) }), !showEmptyInGrid && (_jsxs("tbody", { children: [virtualScrollEnabled && visibleRange.offsetTop > 0 && (_jsx("tr", { style: { height: visibleRange.offsetTop }, "aria-hidden": true })), (virtualScrollEnabled
|
|
170
|
+
? items.slice(visibleRange.startIndex, visibleRange.endIndex + 1).map((item, i) => {
|
|
171
|
+
const rowIndex = visibleRange.startIndex + i;
|
|
172
|
+
const rowIdStr = getRowId(item);
|
|
173
|
+
return (_jsx(GridRow, { item: item, rowIndex: rowIndex, rowId: rowIdStr, isSelected: selectedRowIds.has(rowIdStr), visibleCols: visibleCols, columnMeta: columnMeta, renderCellContent: renderCellContent, handleSingleRowClick: handleSingleRowClick, handleRowCheckboxChange: handleRowCheckboxChange, lastMouseShiftRef: lastMouseShiftRef, hasCheckboxCol: hasCheckboxCol, selectionRange: selectionRange, activeCell: interaction.activeCell, cutRange: cutRange, copyRange: copyRange, isDragging: isDragging, editingRowId: editingCell?.rowId ?? null }, rowIdStr));
|
|
174
|
+
})
|
|
175
|
+
: items.map((item, rowIndex) => {
|
|
176
|
+
const rowIdStr = getRowId(item);
|
|
177
|
+
return (_jsx(GridRow, { item: item, rowIndex: rowIndex, rowId: rowIdStr, isSelected: selectedRowIds.has(rowIdStr), visibleCols: visibleCols, columnMeta: columnMeta, renderCellContent: renderCellContent, handleSingleRowClick: handleSingleRowClick, handleRowCheckboxChange: handleRowCheckboxChange, lastMouseShiftRef: lastMouseShiftRef, hasCheckboxCol: hasCheckboxCol, selectionRange: selectionRange, activeCell: interaction.activeCell, cutRange: cutRange, copyRange: copyRange, isDragging: isDragging, editingRowId: editingCell?.rowId ?? null }, rowIdStr));
|
|
178
|
+
})), virtualScrollEnabled && visibleRange.offsetBottom > 0 && (_jsx("tr", { style: { height: visibleRange.offsetBottom }, "aria-hidden": true }))] }))] }), isReorderDragging && dropIndicatorX != null && (_jsx("div", { className: styles.dropIndicator, style: { left: dropIndicatorX - (wrapperRef.current?.getBoundingClientRect().left ?? 0) } })), _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.') })] })) }) }))] }) }) }), menuPosition &&
|
|
153
179
|
createPortal(_jsx(GridContextMenu, { x: menuPosition.x, y: menuPosition.y, hasSelection: hasCellSelection, canUndo: canUndo, canRedo: canRedo, onUndo: onUndo ?? NOOP, onRedo: onRedo ?? NOOP, onCopy: handleCopy, onCut: handleCut, onPaste: handlePasteVoid, onSelectAll: handleSelectAllCells, onClose: closeContextMenu }), document.body)] }), 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 })), isLoading && (_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 })] }) }))] }));
|
|
154
180
|
}
|
|
155
181
|
export const DataGridTable = React.memo(DataGridTableInner);
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
right: -4px;
|
|
126
126
|
bottom: 0;
|
|
127
127
|
width: 4px;
|
|
128
|
-
background: linear-gradient(to right, rgba(0, 0, 0, 0.
|
|
128
|
+
background: linear-gradient(to right, var(--ogrid-pinned-shadow, rgba(0, 0, 0, 0.12)), transparent);
|
|
129
129
|
pointer-events: none;
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
left: -4px;
|
|
148
148
|
bottom: 0;
|
|
149
149
|
width: 4px;
|
|
150
|
-
background: linear-gradient(to left, rgba(0, 0, 0, 0.
|
|
150
|
+
background: linear-gradient(to left, var(--ogrid-pinned-shadow, rgba(0, 0, 0, 0.12)), transparent);
|
|
151
151
|
pointer-events: none;
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -172,6 +172,18 @@
|
|
|
172
172
|
background: var(--ogrid-header-bg, #f5f5f5);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
/* Column reorder drop indicator */
|
|
176
|
+
.dropIndicator {
|
|
177
|
+
position: absolute;
|
|
178
|
+
top: 0;
|
|
179
|
+
bottom: 0;
|
|
180
|
+
width: 3px;
|
|
181
|
+
background: var(--ogrid-primary, #217346);
|
|
182
|
+
pointer-events: none;
|
|
183
|
+
z-index: 100;
|
|
184
|
+
transition: left 0.05s;
|
|
185
|
+
}
|
|
186
|
+
|
|
175
187
|
/* Column resize handle — wide hit area with narrow visual indicator */
|
|
176
188
|
.resizeHandle {
|
|
177
189
|
position: absolute;
|
|
@@ -361,7 +373,7 @@
|
|
|
361
373
|
background: var(--ogrid-bg, #fff);
|
|
362
374
|
border: 1px solid var(--ogrid-border, #e0e0e0);
|
|
363
375
|
border-radius: 6px;
|
|
364
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
376
|
+
box-shadow: var(--ogrid-shadow, 0 4px 16px rgba(0, 0, 0, 0.12));
|
|
365
377
|
}
|
|
366
378
|
|
|
367
379
|
.contextMenuItem {
|
|
@@ -408,7 +420,7 @@
|
|
|
408
420
|
display: flex;
|
|
409
421
|
align-items: center;
|
|
410
422
|
justify-content: center;
|
|
411
|
-
background: rgba(255, 255, 255, 0.7);
|
|
423
|
+
background: var(--ogrid-loading-bg, rgba(255, 255, 255, 0.7));
|
|
412
424
|
backdrop-filter: blur(1px);
|
|
413
425
|
pointer-events: all;
|
|
414
426
|
}
|
|
@@ -422,7 +434,7 @@
|
|
|
422
434
|
background: var(--ogrid-bg, #fff);
|
|
423
435
|
border: 1px solid var(--ogrid-border, #c4c4c4);
|
|
424
436
|
border-radius: 6px;
|
|
425
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.
|
|
437
|
+
box-shadow: var(--ogrid-shadow-sm, 0 2px 4px rgba(0, 0, 0, 0.08));
|
|
426
438
|
}
|
|
427
439
|
|
|
428
440
|
.loadingOverlayText {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alaarab/ogrid-react-radix",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
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-react": "2.0.
|
|
44
|
+
"@alaarab/ogrid-react": "2.0.3",
|
|
45
45
|
"@radix-ui/react-checkbox": "^1.1.2",
|
|
46
46
|
"@radix-ui/react-popover": "^1.1.2"
|
|
47
47
|
},
|