@alaarab/ogrid-react 2.0.16 → 2.0.18

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.
@@ -27,6 +27,7 @@ export { useSideBarState } from './useSideBarState';
27
27
  export { useTableLayout } from './useTableLayout';
28
28
  export { useColumnReorder } from './useColumnReorder';
29
29
  export { useVirtualScroll } from './useVirtualScroll';
30
+ export { useListVirtualizer } from './useListVirtualizer';
30
31
  export { useLatestRef } from './useLatestRef';
31
32
  export { usePaginationControls } from './usePaginationControls';
32
33
  export { useDataGridTableOrchestration } from './useDataGridTableOrchestration';
@@ -35,7 +35,7 @@ export function useDataGridTableOrchestration(params) {
35
35
  const { headerMenu } = pinning;
36
36
  const handlePasteVoid = useCallback(() => { void handlePaste(); }, [handlePaste]);
37
37
  // ── Props destructuring ─────────────────────────────────────────────────
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, density = 'normal', pinnedColumns, currentPage = 1, pageSize: propPageSize = 25, } = props;
38
+ const { items, columns, getRowId, emptyState, layoutMode = 'fill', rowSelection = 'none', suppressHorizontalScroll, isLoading = false, loadingMessage = 'Loading\u2026', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, visibleColumns, columnOrder, onColumnOrderChange, columnReorder, virtualScroll, density = 'normal', pinnedColumns, currentPage = 1, pageSize: propPageSize = 25, } = props;
39
39
  // ── Derived values ──────────────────────────────────────────────────────
40
40
  const rowNumberOffset = hasRowNumbersCol ? (currentPage - 1) * propPageSize : 0;
41
41
  const headerRows = useMemo(() => buildHeaderRows(columns, visibleColumns), [columns, visibleColumns]);
@@ -117,8 +117,6 @@ export function useDataGridTableOrchestration(params) {
117
117
  emptyState,
118
118
  layoutMode,
119
119
  rowSelection,
120
- freezeRows,
121
- freezeCols,
122
120
  suppressHorizontalScroll,
123
121
  isLoading,
124
122
  loadingMessage,
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Lightweight list virtualizer for fixed-height items in a scrollable container.
3
+ * Zero external dependencies — uses only React state and refs.
4
+ */
5
+ import { useRef, useState, useCallback, useMemo } from 'react';
6
+ export function useListVirtualizer(opts) {
7
+ const { count, itemHeight, containerHeight = 250, overscan = 5 } = opts;
8
+ const containerRef = useRef(null);
9
+ const [scrollTop, setScrollTop] = useState(0);
10
+ const onScroll = useCallback(() => {
11
+ if (containerRef.current) {
12
+ setScrollTop(containerRef.current.scrollTop);
13
+ }
14
+ }, []);
15
+ const totalHeight = count * itemHeight;
16
+ const visibleItems = useMemo(() => {
17
+ if (count === 0)
18
+ return [];
19
+ const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
20
+ const visibleCount = Math.ceil(containerHeight / itemHeight);
21
+ const endIndex = Math.min(count - 1, startIndex + visibleCount + overscan * 2);
22
+ const items = [];
23
+ for (let i = startIndex; i <= endIndex; i++) {
24
+ items.push({ index: i, offsetTop: i * itemHeight });
25
+ }
26
+ return items;
27
+ }, [count, itemHeight, containerHeight, overscan, scrollTop]);
28
+ return { totalHeight, visibleItems, containerRef, onScroll };
29
+ }
@@ -11,7 +11,7 @@ const EMPTY_LOADING_OPTIONS = {};
11
11
  * @returns Grouped props for DataGridTable, pagination controls, column chooser, layout, and filters.
12
12
  */
13
13
  export function useOGrid(props, ref) {
14
- const { columns: columnsProp, getRowId, data, dataSource, page: controlledPage, pageSize: controlledPageSize, sort: controlledSort, filters: controlledFilters, visibleColumns: controlledVisibleColumns, isLoading: controlledLoading, onPageChange, onPageSizeChange, onSortChange, onFiltersChange, onVisibleColumnsChange, columnOrder, onColumnOrderChange, onColumnResized, onColumnPinned, freezeRows, freezeCols, defaultPageSize = DEFAULT_PAGE_SIZE, defaultSortBy, defaultSortDirection = 'asc', toolbar, toolbarBelow, emptyState, entityLabelPlural = 'items', className, layoutMode = 'fill', suppressHorizontalScroll, editable, cellSelection, onCellValueChanged, onUndo, onRedo, canUndo, canRedo, rowSelection = 'none', selectedRows, onSelectionChange, showRowNumbers, statusBar, pageSizeOptions, sideBar, onFirstDataRendered, onError, columnChooser: columnChooserProp, columnReorder, virtualScroll, density = 'normal', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, } = props;
14
+ const { columns: columnsProp, getRowId, data, dataSource, page: controlledPage, pageSize: controlledPageSize, sort: controlledSort, filters: controlledFilters, visibleColumns: controlledVisibleColumns, isLoading: controlledLoading, onPageChange, onPageSizeChange, onSortChange, onFiltersChange, onVisibleColumnsChange, columnOrder, onColumnOrderChange, onColumnResized, onColumnPinned, defaultPageSize = DEFAULT_PAGE_SIZE, defaultSortBy, defaultSortDirection = 'asc', toolbar, toolbarBelow, emptyState, entityLabelPlural = 'items', className, layoutMode = 'fill', suppressHorizontalScroll, editable, cellSelection, onCellValueChanged, onUndo, onRedo, canUndo, canRedo, rowSelection = 'none', selectedRows, onSelectionChange, showRowNumbers, statusBar, pageSizeOptions, sideBar, onFirstDataRendered, onError, columnChooser: columnChooserProp, columnReorder, virtualScroll, density = 'normal', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, } = props;
15
15
  // Resolve column chooser placement
16
16
  const columnChooserPlacement = columnChooserProp === false ? 'none'
17
17
  : columnChooserProp === 'sidebar' ? 'sidebar'
@@ -395,8 +395,6 @@ export function useOGrid(props, ref) {
395
395
  onColumnPinned: handleColumnPinned,
396
396
  pinnedColumns: pinnedOverrides,
397
397
  initialColumnWidths: columnWidthOverrides,
398
- freezeRows,
399
- freezeCols,
400
398
  editable,
401
399
  cellSelection,
402
400
  onCellValueChanged,
@@ -434,7 +432,7 @@ export function useOGrid(props, ref) {
434
432
  }), [
435
433
  displayItems, columnsProp, getRowId, sort.field, sort.direction, handleSort,
436
434
  visibleColumns, columnOrder, onColumnOrderChange, handleColumnResized,
437
- handleColumnPinned, pinnedOverrides, columnWidthOverrides, freezeRows, freezeCols,
435
+ handleColumnPinned, pinnedOverrides, columnWidthOverrides,
438
436
  editable, cellSelection, onCellValueChanged, onUndo, onRedo, canUndo, canRedo,
439
437
  rowSelection, effectiveSelectedRows, handleSelectionChange, showRowNumbers, page, pageSize, statusBarConfig,
440
438
  isLoadingResolved, filters, handleFilterChange, clientFilterOptions, dataSource,
package/dist/esm/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  export { CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, GRID_BORDER_RADIUS, } from '@alaarab/ogrid-core';
3
3
  export { toUserLike, isInSelectionRange, normalizeSelectionRange } from './types';
4
4
  // Hooks
5
- export { useFilterOptions, useOGrid, useActiveCell, useCellEditing, useContextMenu, useCellSelection, useClipboard, useRowSelection, useKeyboardNavigation, useUndoRedo, useDebounce, useFillHandle, useDataGridState, useColumnHeaderFilterState, useTextFilterState, useMultiSelectFilterState, usePeopleFilterState, useDateFilterState, useColumnChooserState, useInlineCellEditorState, useColumnResize, useRichSelectState, useSelectState, useSideBarState, useTableLayout, useColumnReorder, useVirtualScroll, useLatestRef, usePaginationControls, useDataGridTableOrchestration, } from './hooks';
5
+ export { useFilterOptions, useOGrid, useActiveCell, useCellEditing, useContextMenu, useCellSelection, useClipboard, useRowSelection, useKeyboardNavigation, useUndoRedo, useDebounce, useFillHandle, useDataGridState, useColumnHeaderFilterState, useTextFilterState, useMultiSelectFilterState, usePeopleFilterState, useDateFilterState, useColumnChooserState, useInlineCellEditorState, useColumnResize, useRichSelectState, useSelectState, useSideBarState, useTableLayout, useColumnReorder, useVirtualScroll, useListVirtualizer, useLatestRef, usePaginationControls, useDataGridTableOrchestration, } from './hooks';
6
6
  // Constants
7
7
  export { GRID_ROOT_STYLE, CURSOR_CELL_STYLE, POPOVER_ANCHOR_STYLE, PREVENT_DEFAULT, NOOP, STOP_PROPAGATION, } from './constants/domHelpers';
8
8
  // Components
@@ -55,6 +55,8 @@ export { useColumnReorder } from './useColumnReorder';
55
55
  export type { UseColumnReorderParams, UseColumnReorderResult, } from './useColumnReorder';
56
56
  export { useVirtualScroll } from './useVirtualScroll';
57
57
  export type { IVirtualScrollConfig, UseVirtualScrollParams, UseVirtualScrollResult, } from './useVirtualScroll';
58
+ export { useListVirtualizer } from './useListVirtualizer';
59
+ export type { UseListVirtualizerOptions, UseListVirtualizerResult, VirtualItem, } from './useListVirtualizer';
58
60
  export { useLatestRef } from './useLatestRef';
59
61
  export { usePaginationControls } from './usePaginationControls';
60
62
  export type { UsePaginationControlsProps, UsePaginationControlsResult, } from './usePaginationControls';
@@ -37,8 +37,6 @@ export interface UseDataGridTableOrchestrationResult<T> {
37
37
  emptyState: IOGridDataGridProps<T>['emptyState'];
38
38
  layoutMode: 'fill' | 'content';
39
39
  rowSelection: IOGridDataGridProps<T>['rowSelection'];
40
- freezeRows: IOGridDataGridProps<T>['freezeRows'];
41
- freezeCols: IOGridDataGridProps<T>['freezeCols'];
42
40
  suppressHorizontalScroll: IOGridDataGridProps<T>['suppressHorizontalScroll'];
43
41
  isLoading: boolean;
44
42
  loadingMessage: string;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Lightweight list virtualizer for fixed-height items in a scrollable container.
3
+ * Zero external dependencies — uses only React state and refs.
4
+ */
5
+ export interface UseListVirtualizerOptions {
6
+ /** Total number of items in the list. */
7
+ count: number;
8
+ /** Height of each item in pixels (uniform). */
9
+ itemHeight: number;
10
+ /** Container height in pixels. Defaults to 250. */
11
+ containerHeight?: number;
12
+ /** Extra items to render above/below the visible window. Defaults to 5. */
13
+ overscan?: number;
14
+ }
15
+ export interface VirtualItem {
16
+ index: number;
17
+ offsetTop: number;
18
+ }
19
+ export interface UseListVirtualizerResult {
20
+ /** Total scrollable height (count * itemHeight). */
21
+ totalHeight: number;
22
+ /** Items currently visible (plus overscan buffer). */
23
+ visibleItems: VirtualItem[];
24
+ /** Ref to attach to the scrollable container div. */
25
+ containerRef: React.RefObject<HTMLDivElement | null>;
26
+ /** Scroll handler to attach to the scrollable container div. */
27
+ onScroll: () => void;
28
+ }
29
+ export declare function useListVirtualizer(opts: UseListVirtualizerOptions): UseListVirtualizerResult;
@@ -1,7 +1,7 @@
1
1
  export { CHECKBOX_COLUMN_WIDTH, ROW_NUMBER_COLUMN_WIDTH, DEFAULT_MIN_COLUMN_WIDTH, CELL_PADDING, GRID_BORDER_RADIUS, } from '@alaarab/ogrid-core';
2
2
  export type { ColumnFilterType, IColumnFilterDef, IColumnMeta, IColumnDef, IColumnGroupDef, IColumnDefinition, ICellValueChangedEvent, ICellEditorProps, CellEditorParams, IValueParserParams, UserLike, UserLikeInput, FilterValue, IFilters, IFetchParams, IPageResult, IDataSource, IGridColumnState, IOGridApi, IOGridProps, IOGridDataGridProps, RowSelectionMode, RowId, IRowSelectionChangeEvent, StatusBarPanel, IStatusBarProps, IActiveCell, ISelectionRange, HeaderCell, HeaderRow, SideBarPanelId, ISideBarDef, IDateFilterValue, IVirtualScrollConfig, IColumnReorderConfig, } from './types';
3
3
  export { toUserLike, isInSelectionRange, normalizeSelectionRange } from './types';
4
- export { useFilterOptions, useOGrid, useActiveCell, useCellEditing, useContextMenu, useCellSelection, useClipboard, useRowSelection, useKeyboardNavigation, useUndoRedo, useDebounce, useFillHandle, useDataGridState, useColumnHeaderFilterState, useTextFilterState, useMultiSelectFilterState, usePeopleFilterState, useDateFilterState, useColumnChooserState, useInlineCellEditorState, useColumnResize, useRichSelectState, useSelectState, useSideBarState, useTableLayout, useColumnReorder, useVirtualScroll, useLatestRef, usePaginationControls, useDataGridTableOrchestration, } from './hooks';
4
+ export { useFilterOptions, useOGrid, useActiveCell, useCellEditing, useContextMenu, useCellSelection, useClipboard, useRowSelection, useKeyboardNavigation, useUndoRedo, useDebounce, useFillHandle, useDataGridState, useColumnHeaderFilterState, useTextFilterState, useMultiSelectFilterState, usePeopleFilterState, useDateFilterState, useColumnChooserState, useInlineCellEditorState, useColumnResize, useRichSelectState, useSelectState, useSideBarState, useTableLayout, useColumnReorder, useVirtualScroll, useListVirtualizer, useLatestRef, usePaginationControls, useDataGridTableOrchestration, } from './hooks';
5
5
  export type { UseFilterOptionsResult, UseOGridResult, UseOGridPagination, UseOGridColumnChooser, UseOGridLayout, UseOGridFilters, ColumnChooserPlacement, UseActiveCellResult, UseCellEditingResult, EditingCell, UseContextMenuResult, ContextMenuPosition, UseCellSelectionResult, UseCellSelectionParams, UseClipboardResult, UseClipboardParams, UseRowSelectionResult, UseRowSelectionParams, UseKeyboardNavigationResult, UseKeyboardNavigationParams, UseUndoRedoResult, UseUndoRedoParams, UseFillHandleResult, UseFillHandleParams, UseDataGridStateParams, UseDataGridStateResult, DataGridLayoutState, DataGridRowSelectionState, DataGridEditingState, DataGridCellInteractionState, DataGridContextMenuState, DataGridViewModelState, DataGridPinningState, UseColumnHeaderFilterStateParams, UseColumnHeaderFilterStateResult, UseTextFilterStateParams, UseTextFilterStateResult, UseMultiSelectFilterStateParams, UseMultiSelectFilterStateResult, UsePeopleFilterStateParams, UsePeopleFilterStateResult, UseDateFilterStateParams, UseDateFilterStateResult, UseColumnChooserStateParams, UseColumnChooserStateResult, UseInlineCellEditorStateParams, UseInlineCellEditorStateResult, InlineCellEditorType, UseColumnResizeParams, UseColumnResizeResult, UseRichSelectStateParams, UseRichSelectStateResult, UseSelectStateParams, UseSelectStateResult, UseSideBarStateParams, UseSideBarStateResult, UseTableLayoutParams, UseTableLayoutResult, UseColumnReorderParams, UseColumnReorderResult, UseVirtualScrollParams, UseVirtualScrollResult, UsePaginationControlsProps, UsePaginationControlsResult, UseDataGridTableOrchestrationParams, UseDataGridTableOrchestrationResult, } from './hooks';
6
6
  export { GRID_ROOT_STYLE, CURSOR_CELL_STYLE, POPOVER_ANCHOR_STYLE, PREVENT_DEFAULT, NOOP, STOP_PROPAGATION, } from './constants/domHelpers';
7
7
  export { OGridLayout } from './components/OGridLayout';
@@ -30,8 +30,6 @@ interface IOGridBaseProps<T> {
30
30
  onColumnResized?: (columnId: string, width: number) => void;
31
31
  /** Called when a column is pinned or unpinned. */
32
32
  onColumnPinned?: (columnId: string, pinned: 'left' | 'right' | null) => void;
33
- freezeRows?: number;
34
- freezeCols?: number;
35
33
  editable?: boolean;
36
34
  /** Enable spreadsheet-like cell selection (active cell, range, fill handle, clipboard, context menu). Default: true. */
37
35
  cellSelection?: boolean;
@@ -118,10 +116,6 @@ export interface IOGridDataGridProps<T> {
118
116
  pinnedColumns?: Record<string, 'left' | 'right'>;
119
117
  /** Initial column width overrides (from restored state). */
120
118
  initialColumnWidths?: Record<string, number>;
121
- /** Number of rows to freeze (sticky), e.g. 1 = header row. */
122
- freezeRows?: number;
123
- /** Number of data columns to freeze (sticky left). */
124
- freezeCols?: number;
125
119
  layoutMode?: 'content' | 'fill';
126
120
  /** When true, horizontal scrolling is suppressed (overflow-x hidden). */
127
121
  suppressHorizontalScroll?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-react",
3
- "version": "2.0.16",
3
+ "version": "2.0.18",
4
4
  "description": "OGrid React – React hooks, headless components, and utilities for OGrid data grids.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -36,7 +36,7 @@
36
36
  "node": ">=18"
37
37
  },
38
38
  "dependencies": {
39
- "@alaarab/ogrid-core": "2.0.15"
39
+ "@alaarab/ogrid-core": "2.0.18"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@tanstack/react-virtual": "^3.0.0",