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, @alaarab/ogrid-react-material).
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. |
selectedItems | T[] | Array of full row data objects for all currently selected rows. |
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 → 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 → width). |
filters | IFilters | Active filters (field → FilterValue). |
pinnedColumns | Record<string, 'left' | 'right'> | Pinned columns (column ID → 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;
rowHeight?: number;
overscan?: number;
}
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable virtual scrolling. |
rowHeight | number | Required when enabled | Fixed row height in pixels. All rows must have the same height. |
overscan | number | 5 | Number of extra rows to render above/below the visible area (for smoother scrolling). |
Usage Example
<OGrid
data={largeDataset} // 10,000+ rows
columns={columns}
getRowId={(item) => item.id}
virtualScroll={{
enabled: true,
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';
import type { IColumnDef, IOGridApi } from '@alaarab/ogrid-react-material';