Types
Reference for all shared types exported from @alaarab/ogrid-core. These types are also re-exported from all UI packages (@alaarab/ogrid-react-radix, @alaarab/ogrid-react-fluent).
RowId
Unique identifier for a row. Used throughout the grid for row selection, tracking, and the getRowId callback.
type RowId = string | number;
FilterValue
A discriminated union representing a single filter value. Each variant has a type tag and a value field.
type FilterValue =
| { type: 'text'; value: string }
| { type: 'multiSelect'; value: string[] }
| { type: 'people'; value: UserLike }
| { type: 'date'; value: IDateFilterValue };
| Filter Type | type Tag | value Shape | Example |
|---|---|---|---|
| Text | 'text' | string | { type: 'text', value: 'Alice' } |
| Multi-select | 'multiSelect' | string[] | { type: 'multiSelect', value: ['Active', 'Pending'] } |
| People | 'people' | UserLike | { type: 'people', value: { displayName: 'Alice', email: 'alice@example.com' } } |
| Date range | 'date' | IDateFilterValue | { type: 'date', value: { from: '2024-01-01', to: '2024-12-31' } } |
IDateFilterValue
A date range for date column filters. Both fields are optional ISO YYYY-MM-DD strings.
interface IDateFilterValue {
from?: string;
to?: string;
}
| Name | Type | Description |
|---|---|---|
from | string | Start date (inclusive). ISO YYYY-MM-DD format. |
to | string | End date (inclusive). ISO YYYY-MM-DD format. |
IFilters
A record of active filters, keyed by field name. Each value is a FilterValue or undefined (when a filter has been cleared).
interface IFilters {
[field: string]: FilterValue | undefined;
}
Example
const filters: IFilters = {
name: { type: 'text', value: 'Alice' },
status: { type: 'multiSelect', value: ['Active', 'Pending'] },
owner: { type: 'people', value: { displayName: 'Bob', email: 'bob@example.com' } },
startDate: { type: 'date', value: { from: '2024-01-01' } },
department: undefined, // cleared filter
};
RowSelectionMode
Controls how row selection behaves in the grid.
type RowSelectionMode = 'none' | 'single' | 'multiple';
| Value | Description |
|---|---|
'none' | Row selection is disabled. No checkbox column is shown. |
'single' | Only one row can be selected at a time. Clicking a row replaces the previous selection. |
'multiple' | Multiple rows can be selected. A header checkbox toggles select/deselect all. Shift+click selects a range. |
ISelectionRange
Describes a rectangular range of cells selected in the grid. Used internally by cell selection and passed to aggregation utilities.
interface ISelectionRange {
startRow: number;
startCol: number;
endRow: number;
endCol: number;
}
| Name | Type | Description |
|---|---|---|
startRow | number | Row index where the selection began. |
startCol | number | Column index where the selection began. |
endRow | number | Row index where the selection ended. |
endCol | number | Column index where the selection ended. |
The range is inclusive. startRow may be greater than endRow (and likewise for columns) when the user selects from bottom-right to top-left; the grid normalizes the range internally.
IActiveCell
Identifies the currently active (focused) cell in the grid.
interface IActiveCell {
rowIndex: number;
columnIndex: number;
}
| Name | Type | Description |
|---|---|---|
rowIndex | number | Zero-based row index of the active cell. |
columnIndex | number | Zero-based column index of the active cell. |
UserLike
Represents a person/user. Used by people type column filters and the searchPeople / getUserByEmail methods on IDataSource.
interface UserLike {
id?: string;
displayName: string;
email: string;
photo?: string;
}
| Name | Type | Required | Description |
|---|---|---|---|
id | string | No | Unique identifier for the user. |
displayName | string | Yes | The user's display name, shown in filter chips and people cells. |
email | string | Yes | The user's email address. Used as the filter value and for user resolution. |
photo | string | No | URL to the user's profile photo. Displayed as an avatar in people filters. |
IStatusBarProps
Configuration for the grid status bar, which displays counts and aggregation information at the bottom of the grid.
interface IStatusBarProps {
totalCount: number;
filteredCount?: number;
selectedCount?: number;
panels?: StatusBarPanel[];
aggregation?: {
sum: number;
avg: number;
min: number;
max: number;
count: number;
} | null;
}
| Name | Type | Default | Description |
|---|---|---|---|
totalCount | number | Required | Total number of items in the data set. |
filteredCount | number | undefined | Number of items after filtering. When different from totalCount, the status bar shows "X of Y items". |
selectedCount | number | undefined | Number of selected rows. Shown when row selection is enabled. |
panels | StatusBarPanel[] | undefined | Custom status bar panels for additional content. |
aggregation | { sum, avg, min, max, count } | null | undefined | Aggregation values computed from the selected cell range. Displayed when the user selects a range containing numeric cells. |
Aggregation Object
When cells are selected and contain numeric values, the status bar can display aggregation values.
| Name | Type | Description |
|---|---|---|
sum | number | Sum of all numeric values in the selection. |
avg | number | Average of all numeric values in the selection. |
min | number | Minimum numeric value in the selection. |
max | number | Maximum numeric value in the selection. |
count | number | Count of numeric values in the selection. |
Usage
Pass true for a default status bar, or an object for full control:
// Default status bar (shows item counts automatically)
<OGrid statusBar={true} ... />
// Custom status bar with aggregation
<OGrid
statusBar={{
totalCount: data.length,
filteredCount: filteredData.length,
selectedCount: selectedRows.size,
aggregation: { sum: 1500, avg: 375, min: 100, max: 600, count: 4 },
}}
...
/>
ISideBarDef
Configuration for the grid side bar panel.
interface ISideBarDef {
panels?: ('columns' | 'filters')[];
defaultPanel?: 'columns' | 'filters';
position?: 'left' | 'right';
}
| Name | Type | Default | Description |
|---|---|---|---|
panels | ('columns' | 'filters')[] | ['columns', 'filters'] | Which panels to include in the side bar. 'columns' shows a column chooser. 'filters' shows filter controls. |
defaultPanel | 'columns' | 'filters' | undefined | Which panel is open by default. When not set, the side bar starts collapsed. |
position | 'left' | 'right' | 'right' | Which side of the grid the side bar appears on. |
Usage
// Default side bar
<OGrid sideBar={true} ... />
// Custom side bar on the left, showing only column chooser
<OGrid
sideBar={{
panels: ['columns'],
position: 'left',
defaultPanel: 'columns',
}}
...
/>
IRowSelectionChangeEvent<T>
Event object passed to the onSelectionChange callback when row selection changes.
interface IRowSelectionChangeEvent<T> {
selectedRowIds: RowId[];
selectedItems: T[];
}
| Name | Type | Description |
|---|---|---|
selectedRowIds | RowId[] | Array of IDs for all currently selected rows, including rows on other pages. |
selectedItems | T[] | Row objects for the selected rows the grid could resolve. Checkbox and header clicks resolve against the current page only, so with pagination this can be shorter than selectedRowIds. Treat the ids as the source of truth. |
Usage
<OGrid<Employee>
columns={columns}
data={data}
getRowId={(e) => e.id}
rowSelection="multiple"
onSelectionChange={(event) => {
console.log('Selected IDs:', event.selectedRowIds);
console.log('Selected items:', event.selectedItems);
}}
/>
IDataSource<T>
Server-side data source interface. When you pass a dataSource to OGrid instead of a data array, the grid calls these methods to fetch paginated data and filter options.
interface IDataSource<T> {
fetchPage(params: IFetchParams): Promise<IPageResult<T>>;
fetchFilterOptions?(field: string): Promise<string[]>;
searchPeople?(query: string): Promise<UserLike[]>;
getUserByEmail?(email: string): Promise<UserLike | undefined>;
}
| Method | Required | Description |
|---|---|---|
fetchPage | Yes | Fetch a page of data from the server. Called when the user changes page, page size, sort, or filters. |
fetchFilterOptions | No | Fetch filter options for a multi-select filter column. Called when a multi-select filter is opened. |
searchPeople | No | Search for people by name or email. Called when a user types in a people filter search box. |
getUserByEmail | No | Resolve a user by email address. Called when restoring a saved people filter. |
IFetchParams
Parameters passed to fetchPage:
interface IFetchParams {
page: number;
pageSize: number;
sort?: { field: string; direction: 'asc' | 'desc' };
filters: IFilters;
}
| Field | Type | Description |
|---|---|---|
page | number | Current page number (1-indexed). |
pageSize | number | Number of items per page. |
sort | { field, direction } | Active sort (field name + direction). Omit if no sort. |
filters | IFilters | Active filters (field to FilterValue). |
IPageResult<T>
Response shape from fetchPage:
interface IPageResult<T> {
items: T[];
totalCount: number;
}
| Field | Type | Description |
|---|---|---|
items | T[] | Array of data items for the current page. |
totalCount | number | Total number of items across all pages (used for pagination). |
Usage Example
import type { IDataSource, IFetchParams, IPageResult, UserLike } from '@alaarab/ogrid-react-radix';
interface Product {
id: number;
name: string;
category: string;
price: number;
}
const dataSource: IDataSource<Product> = {
async fetchPage(params: IFetchParams): Promise<IPageResult<Product>> {
// Build query string from params
const queryParams = new URLSearchParams({
page: params.page.toString(),
pageSize: params.pageSize.toString(),
sort: params.sort ? `${params.sort.field}:${params.sort.direction}` : '',
filters: JSON.stringify(params.filters),
});
const response = await fetch(`/api/products?${queryParams}`);
const data = await response.json();
return {
items: data.items,
totalCount: data.totalCount,
};
},
async fetchFilterOptions(field: string): Promise<string[]> {
const response = await fetch(`/api/products/filter-options/${field}`);
return response.json();
},
async searchPeople(query: string): Promise<UserLike[]> {
const response = await fetch(`/api/users/search?q=${encodeURIComponent(query)}`);
return response.json();
},
async getUserByEmail(email: string): Promise<UserLike | undefined> {
const response = await fetch(`/api/users/by-email/${encodeURIComponent(email)}`);
if (!response.ok) return undefined;
return response.json();
},
};
// Use with OGrid
<OGrid
dataSource={dataSource}
columns={columns}
getRowId={(item) => item.id}
/>
ICellEditorProps<T>
Props passed to custom cell editor components (React) or rendered by the inline cell editor.
interface ICellEditorProps<T> {
value: unknown;
onValueChange: (value: unknown) => void;
onCommit: () => void;
onCancel: () => void;
item: T;
column: IColumnDef<T>;
cellEditorParams?: CellEditorParams;
}
| Field | Type | Description |
|---|---|---|
value | unknown | Current cell value. |
onValueChange | (value: unknown) => void | Callback to update the value (doesn't commit yet). |
onCommit | () => void | Callback to commit the edit and close the editor. |
onCancel | () => void | Callback to cancel the edit and close the editor. |
item | T | Full row data object. |
column | IColumnDef<T> | Column definition. |
cellEditorParams | CellEditorParams | Optional params passed to the editor (e.g., values for a select editor). |
CellEditorParams
Parameters for built-in cell editors:
interface CellEditorParams {
values?: unknown[];
formatValue?: (value: unknown) => string;
}
| Field | Type | Description |
|---|---|---|
values | unknown[] | Array of allowed values for select/richSelect editors. |
formatValue | (value: unknown) => string | Custom formatter for values in rich select editor. |
Usage Example (React)
import type { ICellEditorProps } from '@alaarab/ogrid-react-radix';
interface Product {
id: number;
name: string;
category: string;
}
function CategoryEditor(props: ICellEditorProps<Product>) {
const { value, onValueChange, onCommit, onCancel, cellEditorParams } = props;
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
onValueChange(e.target.value);
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') onCommit();
if (e.key === 'Escape') onCancel();
};
return (
<select
value={value as string}
onChange={handleChange}
onKeyDown={handleKeyDown}
autoFocus
>
{cellEditorParams?.values?.map((v) => (
<option key={v as string} value={v as string}>
{v as string}
</option>
))}
</select>
);
}
// Use in column definition
const columns: IColumnDef<Product>[] = [
{
columnId: 'category',
name: 'Category',
editable: true,
cellEditor: CategoryEditor,
cellEditorParams: {
values: ['Electronics', 'Clothing', 'Books'],
},
},
];
ICellValueChangedEvent<T>
Event object passed to the onCellValueChanged callback when a cell value is committed after editing.
interface ICellValueChangedEvent<T> {
item: T;
columnId: string;
oldValue: unknown;
newValue: unknown;
rowIndex: number;
}
| Field | Type | Description |
|---|---|---|
item | T | Full row data object (with the new value already applied). |
columnId | string | ID of the column that was edited. |
oldValue | unknown | Value before the edit. |
newValue | unknown | Value after the edit. |
rowIndex | number | Zero-based row index. |
Usage Example
<OGrid<Product>
columns={columns}
data={data}
getRowId={(item) => item.id}
editable={true}
onCellValueChanged={(event) => {
console.log(`Cell edited: ${event.columnId}`);
console.log(`Old value: ${event.oldValue}`);
console.log(`New value: ${event.newValue}`);
console.log('Updated item:', event.item);
// Sync changes to the server
updateProduct(event.item);
}}
/>
IGridColumnState
Column state object returned by IOGridApi.getColumnState() and accepted by applyColumnState(). All fields are JSON-serializable for persistence (e.g., localStorage).
interface IGridColumnState {
visibleColumns: string[];
sort?: { field: string; direction: 'asc' | 'desc' };
columnOrder?: string[];
columnWidths?: Record<string, number>;
filters?: IFilters;
pinnedColumns?: Record<string, 'left' | 'right'>;
}
| Field | Type | Description |
|---|---|---|
visibleColumns | string[] | Array of visible column IDs. |
sort | { field, direction } | Active sort (field name + direction). |
columnOrder | string[] | Column display order (array of column IDs). |
columnWidths | Record<string, number> | Column widths in pixels (column ID to width). |
filters | IFilters | Active filters (field to FilterValue). |
pinnedColumns | Record<string, 'left' | 'right'> | Pinned columns (column ID to position). |
Usage Example
import { useRef } from 'react';
import { OGrid } from '@alaarab/ogrid-react-radix';
import type { IOGridApi } from '@alaarab/ogrid-react-radix';
function MyGrid() {
const apiRef = useRef<IOGridApi<Product>>(null);
const saveState = () => {
const state = apiRef.current?.getColumnState();
if (state) {
localStorage.setItem('gridState', JSON.stringify(state));
}
};
const restoreState = () => {
const saved = localStorage.getItem('gridState');
if (saved) {
const state = JSON.parse(saved);
apiRef.current?.applyColumnState(state);
}
};
return (
<>
<button onClick={saveState}>Save Grid State</button>
<button onClick={restoreState}>Restore Grid State</button>
<OGrid ref={apiRef} {...props} />
</>
);
}
IVirtualScrollConfig
Configuration for virtual scrolling (rendering only visible rows for large datasets).
interface IVirtualScrollConfig {
enabled?: boolean;
paginate?: boolean;
rowHeight?: number;
overscan?: number;
threshold?: number;
columns?: boolean;
columnOverscan?: number;
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable virtual scrolling. Must be true to activate. |
paginate | boolean | true | When false, bypass pagination and virtual-scroll the entire dataset in one viewport. Pagination controls are hidden. Client-side grids only. |
rowHeight | number | 36 | Fixed row height in pixels. All rows must have the same height. Required when enabled. |
overscan | number | 5 | Number of extra rows to render above/below the visible area (for smoother scrolling). |
threshold | number | 100 | Minimum row count before virtual scrolling activates. Below this, all rows render. |
columns | boolean | false | Enable column virtualization -- render only columns visible in the horizontal viewport. |
columnOverscan | number | 2 | Number of extra columns to render beyond the visible horizontal range on each side. |
Usage Example
<OGrid
data={largeDataset} // 10,000+ rows
columns={columns}
getRowId={(item) => item.id}
virtualScroll={{
enabled: true, // required to activate virtual scrolling
rowHeight: 40,
overscan: 10,
}}
/>
Type Imports
All types can be imported from any OGrid package:
// From the core package (useful in shared code)
import type {
RowId,
FilterValue,
IFilters,
RowSelectionMode,
ISelectionRange,
IActiveCell,
UserLike,
IStatusBarProps,
ISideBarDef,
IRowSelectionChangeEvent,
IColumnDef,
IColumnGroupDef,
IDataSource,
IOGridApi,
IOGridProps,
ICellEditorProps,
ICellValueChangedEvent,
IGridColumnState,
IVirtualScrollConfig,
IFetchParams,
IPageResult,
CellEditorParams,
} from '@alaarab/ogrid-react-radix';
// From UI packages (re-exports everything from core)
import type { IColumnDef, IOGridApi } from '@alaarab/ogrid-react-radix';
import type { IColumnDef, IOGridApi } from '@alaarab/ogrid-react-fluent';