@alaarab/ogrid 1.4.0 → 1.6.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.
@@ -44,6 +44,7 @@
44
44
  display: flex;
45
45
  flex-direction: column;
46
46
  padding: 0;
47
+ z-index: 50;
47
48
  }
48
49
 
49
50
  .header {
@@ -15,7 +15,13 @@ function DataGridTableInner(props) {
15
15
  const tableContainerRef = useRef(null);
16
16
  const state = useDataGridState({ props, wrapperRef });
17
17
  const lastMouseShiftRef = useRef(false);
18
- const { visibleCols, totalColCount, hasCheckboxCol, selectedRowIds, updateSelection, handleRowCheckboxChange, handleSelectAll, allSelected, someSelected, setEditingCell, pendingEditorValue, setPendingEditorValue, setActiveCell, handleCellMouseDown, handleSelectAllCells, contextMenu, handleCellContextMenu, closeContextMenu, canUndo, canRedo, onUndo, onRedo, handleCopy, handleCut, handlePaste, handleGridKeyDown, handleFillHandleMouseDown, containerWidth, minTableWidth, desiredTableWidth, columnSizingOverrides, setColumnSizingOverrides, statusBarConfig, showEmptyInGrid, hasCellSelection, selectionRange, copyRange, cutRange, colOffset, headerFilterInput, cellDescriptorInput, commitCellEdit, cancelPopoverEdit, popoverAnchorEl, setPopoverAnchorEl, } = state;
18
+ const { layout, rowSelection: rowSel, editing, interaction, contextMenu: ctxMenu, viewModels } = state;
19
+ const { visibleCols, totalColCount, hasCheckboxCol, colOffset, containerWidth, minTableWidth, desiredTableWidth, columnSizingOverrides, setColumnSizingOverrides } = layout;
20
+ const { selectedRowIds, updateSelection, handleRowCheckboxChange, handleSelectAll, allSelected, someSelected } = rowSel;
21
+ const { setEditingCell, pendingEditorValue, setPendingEditorValue, commitCellEdit, cancelPopoverEdit, popoverAnchorEl, setPopoverAnchorEl } = editing;
22
+ const { setActiveCell, handleCellMouseDown, handleSelectAllCells, selectionRange, hasCellSelection, handleGridKeyDown, handleFillHandleMouseDown, handleCopy, handleCut, handlePaste, cutRange, copyRange, canUndo, canRedo, onUndo, onRedo } = interaction;
23
+ const { menuPosition, handleCellContextMenu, closeContextMenu } = ctxMenu;
24
+ const { headerFilterInput, cellDescriptorInput, statusBarConfig, showEmptyInGrid } = viewModels;
19
25
  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;
20
26
  const headerRows = buildHeaderRows(columns, visibleColumns);
21
27
  const allowOverflowX = !suppressHorizontalScroll && containerWidth > 0 && (minTableWidth > containerWidth || desiredTableWidth > containerWidth);
@@ -106,7 +112,7 @@ function DataGridTableInner(props) {
106
112
  textAlign: col.type === 'numeric' ? 'right' : col.type === 'boolean' ? 'center' : undefined,
107
113
  }, children: renderCellContent(item, col, rowIndex, colIdx) }, col.columnId));
108
114
  })] }, rowIdStr));
109
- }) }))] }), _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 }))] }), contextMenu &&
110
- createPortal(_jsx(GridContextMenu, { x: contextMenu.x, y: contextMenu.y, hasSelection: hasCellSelection, canUndo: canUndo, canRedo: canRedo, onUndo: onUndo ?? (() => { }), onRedo: onRedo ?? (() => { }), onCopy: handleCopy, onCut: handleCut, onPaste: () => void handlePaste(), onSelectAll: handleSelectAllCells, onClose: closeContextMenu }), document.body)] }));
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)] }));
111
117
  }
112
118
  export const DataGridTable = React.memo(DataGridTableInner);
@@ -1,8 +1,10 @@
1
+ @charset "UTF-8";
1
2
  .tableScrollContent {
2
3
  display: flex;
3
4
  flex-direction: column;
4
5
  width: 100%;
5
6
  min-width: 0;
7
+ min-height: 100%;
6
8
  background: var(--ogrid-bg, #fff);
7
9
  }
8
10
 
@@ -90,6 +92,16 @@
90
92
  background: var(--ogrid-bg, #ffffff);
91
93
  }
92
94
 
95
+ /* Freeze/pinned header cells need top: 0 + z-index: 3 so they stick in BOTH
96
+ directions — left (from .freezeCol/.pinnedCol) AND top (from .stickyHeader).
97
+ Without explicit top, the child's own position: sticky overrides the parent's. */
98
+ .dataTable thead.stickyHeader .freezeColFirst,
99
+ .dataTable thead.stickyHeader .pinnedColLeft,
100
+ .dataTable thead.stickyHeader .pinnedColRight {
101
+ top: 0;
102
+ z-index: 3;
103
+ }
104
+
93
105
  .dataTable thead .freezeColFirst {
94
106
  background: var(--ogrid-bg-subtle, #f3f2f1);
95
107
  }
@@ -156,21 +168,29 @@
156
168
  background: var(--ogrid-header-bg, #f5f5f5);
157
169
  }
158
170
 
159
- /* Column resize handle */
171
+ /* Column resize handle — wide hit area with narrow visual indicator */
160
172
  .resizeHandle {
161
173
  position: absolute;
162
174
  top: 0;
163
- right: 0;
175
+ right: -3px;
164
176
  bottom: 0;
165
- width: 4px;
177
+ width: 8px;
166
178
  cursor: col-resize;
167
179
  user-select: none;
168
180
  z-index: 1;
169
181
  }
170
- .resizeHandle:hover {
182
+ .resizeHandle::after {
183
+ content: "";
184
+ position: absolute;
185
+ top: 0;
186
+ right: 3px;
187
+ bottom: 0;
188
+ width: 2px;
189
+ }
190
+ .resizeHandle:hover::after {
171
191
  background-color: var(--ogrid-accent, #0078d4);
172
192
  }
173
- .resizeHandle:active {
193
+ .resizeHandle:active::after {
174
194
  background-color: var(--ogrid-accent-dark, #005a9e);
175
195
  }
176
196
 
@@ -305,6 +325,7 @@
305
325
  background: var(--ogrid-bg-subtle, #f3f2f1);
306
326
  border-top: 1px solid var(--ogrid-border, #e0e0e0);
307
327
  min-height: 28px;
328
+ margin-top: auto;
308
329
  }
309
330
 
310
331
  .statusBarItem {
@@ -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, title, toolbar, className, entityLabelPlural, pageSizeOptions, sideBarProps, } = useOGrid(props, ref);
10
- return (_jsx(OGridLayout, { className: className, gap: 8, sideBar: sideBarProps, title: title, 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, 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) => {
11
11
  setPageSize(size);
12
12
  setPage(1);
13
13
  }, pageSizeOptions: pageSizeOptions, entityLabelPlural: entityLabelPlural }), children: _jsx(DataGridTable, { ...dataGridProps }) }));
package/dist/esm/index.js CHANGED
@@ -4,5 +4,5 @@ export { DataGridTable } from './DataGridTable/DataGridTable';
4
4
  export { ColumnChooser } from './ColumnChooser/ColumnChooser';
5
5
  export { ColumnHeaderFilter } from './ColumnHeaderFilter/ColumnHeaderFilter';
6
6
  export { PaginationControls } from './PaginationControls/PaginationControls';
7
- // Re-export from core
8
- export { toUserLike, isInSelectionRange, normalizeSelectionRange, toDataGridFilterProps, useFilterOptions, getCellValue, flattenColumns, escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, } from '@alaarab/ogrid-core';
7
+ // Re-export everything from core
8
+ export * from '@alaarab/ogrid-core';
@@ -11,5 +11,6 @@ export interface StatusBarProps {
11
11
  max: number;
12
12
  count: number;
13
13
  } | null;
14
+ suppressRowCount?: boolean;
14
15
  }
15
16
  export declare function StatusBar(props: StatusBarProps): React.ReactElement;
@@ -3,4 +3,4 @@ export { DataGridTable, type IDataGridTableProps } from './DataGridTable/DataGri
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';
6
- export { type ColumnFilterType, type IColumnFilterDef, type IColumnMeta, type IColumnDef, type IColumnGroupDef, type IColumnDefinition, type ICellValueChangedEvent, type ICellEditorProps, type UserLike, type IFilters, type IFetchParams, type IPageResult, type IDataSource, type IGridColumnState, type IOGridApi, type RowSelectionMode, type IRowSelectionChangeEvent, type StatusBarPanel, type IStatusBarProps, type IActiveCell, type ISelectionRange, toUserLike, isInSelectionRange, normalizeSelectionRange, toDataGridFilterProps, useFilterOptions, type UseFilterOptionsResult, getCellValue, flattenColumns, escapeCsvValue, buildCsvHeader, buildCsvRows, exportToCsv, triggerCsvDownload, type CsvColumn, } from '@alaarab/ogrid-core';
6
+ export * from '@alaarab/ogrid-core';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
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.2.0",
44
+ "@alaarab/ogrid-core": "^1.6.0",
45
45
  "@radix-ui/react-checkbox": "^1.1.2",
46
46
  "@radix-ui/react-popover": "^1.1.2"
47
47
  },