Props
GridExportFormat, GridExportOptions, GridExportRowScope, GridExportScope and 12 more: generated from the source of active-grid.
Exported by @workspace/. Generated from the package source; part of the index of every export.
Types#
type GridExportFormat = 'csv' | 'xlsx' | 'json' | 'pdf';interface GridExportOptions {
enabled?: boolean;
formats?: GridExportFormat[];
filename?: string;
fonts?: GridExportFonts | 'inherit';
onExportComplete?: (format: GridExportFormat, scope: GridExportScope) => void;
onExportError?: (
format: GridExportFormat,
error: unknown,
scope: GridExportScope,
) => void;
}- Type
type GridExport Row Scope = 'page' | 'loaded';
The row set the built-in row menu can export, and which it may therefore name HONESTLY.
Two values and no third. page is the current paginated grid page -- after filtering, after sorting, within page/page -- and means the same in client and server mode, because both read the same pagination model. loaded belongs to infinite scrolling, where no page exists and the model carries all blocks fetched so far.
There is deliberately no value for "the whole set": the grid does not own those rows, and a label promising it is then an untruth. A full dataset export is a separate product feature.
The row set one export wrote: the current page or the loaded rows (the Grid of the grid), or the reader's selection.
type GridExportScope = GridExportRowScope | 'selection';interface GridImperativeHandle {
refetch: () => void;
resetSelection: () => void;
addRow: (row: any) => void;
removeRow: (rowId: string) => void;
}ONE action offered on the current selection.
The grid owns the bar, the count, the fixed Actions menu, the keyboard behaviour and the two presentations. The consumer owns everything that is a PRODUCT statement: which actions exist, what they are called, what they do, and whether the caller may perform them at all.
Permission is absence. An action the user may not perform is left out of the array; the grid never renders a disabled item to stand for a missing right. The same rule governs selection SHAPE — see Grid.
There is no `ReactNode` slot. A free slot would let every consumer design its own bulk bar again, which is the divergence this contract replaces. One action renders in the same menu as five.
interface GridSelectionAction {
readonly id: string;
readonly label: string;
readonly icon?: React.ComponentType<{className?: string}>;
readonly tone?: GridSelectionActionTone;
readonly separatorBefore?: boolean;
readonly supportsDatasetWideSelection?: boolean;
readonly onAction: (selection: SelectionModel) => void | Promise<void>;
}How a selection action is presented. danger is the destructive presentation of Dropdown; there is deliberately no third tone — a menu that colours more than "this one removes something" stops communicating anything.
type GridSelectionActionTone = 'default' | 'danger';interface GridToolbarConfig<TData = DefaultRowData> {
hidden?: boolean;
className?: string;
search?: {
enabled?: boolean;
placeholder?: string;
className?: string;
debounceMs?: number;
};
showColumnChooser?: boolean;
actions?: React.ReactNode | ((grid: Grid<TData>) => React.ReactNode);
}Represents the current selection state, distinguishing between inclusive mode (specific IDs selected) and exclusive mode (all selected except specific IDs — used for server-side select-all).
`totalCount` is for DISPLAY. It is what the last response reported and what the banner counts with. A mutation must never compute its own effect from it: rows can appear or disappear between the selection and the call, and the number arrives from the client anyway. Server-side, the count comes from the same query that performs the work.
type SelectionModel =
| {mode: 'inclusive'; rowIds: string[]}
| {
mode: 'exclusive';
excludedRowIds: string[];
totalCount: number;
query: SelectionQuery;
};The QUESTION an exclusive selection answers.
An exclusive selection says "everything except these ids" — and *everything* is only meaningful together with the query that produced it. Without the query a consumer cannot execute the selection: it either processes the rows it happens to have loaded (silently wrong) or the whole table (dangerously wrong). This is that query, split by OWNER:
filtersandsearchare what the GRID owns — its column filters and its own toolbar search;externalis theKey serverthe CONSUMER supplied, i.e. the part of the question the grid never saw.Query Key
The grid never parses any of it. It is carried, not interpreted, so a consumer can (a) verify the selection still belongs to the scope on screen and (b) refuse an action it cannot execute rather than execute a narrower one. A mutation must still re-derive and re-authorize all of it server-side; see docs/ § Executing an exclusive selection.
interface SelectionQuery {
readonly filters: ReadonlyArray<SelectionQueryFilter>;
readonly search: string;
readonly externalKey: string | undefined;
}One column filter that was active at the moment an EXCLUSIVE selection was made. Opaque to the grid beyond its shape: id is the column id, value is whatever that column's filter carries.
interface SelectionQueryFilter {
readonly id: string;
readonly value: unknown;
}interface GridPaginationOptions {
enabled?: boolean;
mode?: 'paginated' | 'infinite';
position?: 'top' | 'bottom' | 'both';
pageSizeOptions?: number[];
showRowCount?: boolean;
showPageSizeSelector?: boolean;
showPageIndicator?: boolean;
showFirstLastButtons?: boolean;
showPrevNextButtons?: boolean;
rowCountPosition?: 'left' | 'right';
className?: string;
}type GridProps<TData extends Record<string, unknown> | unknown> =
RequireGetRowIdIfMissingId<GridPropsBase<TData>, TData>;Per-state loading configuration. First load and refetch are different situations — one has an empty grid, the other has rows that just went stale — so they are configured separately rather than through a single mode that guesses.
interface LoadingDisplayOptions {
firstLoad?: LoadingDisplayValue;
refetch?: LoadingDisplayValue;
delayMs?: number;
}An indicator name, or your own node rendered inside the grid box.
type LoadingDisplayValue = LoadingIndicator | React.ReactNode;A built-in loading indicator. See Base for what each one looks like and when it fits.
'skeleton' is deliberately part of this library and is not dead code. Datyx product apps do not use skeleton loading -- a product-level rule enforced separately by lint-, which fails any app that opts into this value -- but active-grid is a general-purpose package that may be consumed outside Datyx, and a product rule does not remove a generic library feature. See docs/ § Why 'skeleton' stays.
type LoadingIndicator =
'none' | 'progress' | 'skeleton' | 'spinner' | 'text';