Skip to content

Data-source contracts and state

View as Markdown

Use these contracts when implementing a custom source or adapting an application store to GridCore.

A GridDataSource acquires the root source and resolves one source for each materialized child path.

type GridDataSource = {
rootSource(): LevelDataSource;
resolveChild(
parentPath: GridPath,
parentRowKey: RowKey,
childLevelName: string,
): LevelDataSource;
dispose(): void;
};

The runtime calls rootSource() during construction. It calls resolveChild() the first time a row expands. Collapse retains the resolved source for reuse. runtime.dispose() disposes every level source and then the grid source.

type LevelSnapshot = {
readonly nodes: readonly TreeNode[];
readonly footerRows?: readonly FooterRow[];
};
type LevelSourceState =
| { status: "initialLoading"; snapshot: LevelSnapshot }
| { status: "ready"; snapshot: LevelSnapshot }
| {
status: "refreshing";
snapshot: LevelSnapshot;
previous: LevelSnapshot;
}
| { status: "initialError"; snapshot: LevelSnapshot; error: Error }
| {
status: "refreshError";
snapshot: LevelSnapshot;
previous: LevelSnapshot;
error: Error;
};

Snapshots contain display-ready rows. Every TreeNode includes its own stable rowKey. The runtime renders source order and does not apply a second sort, filter, or page stage.

type LevelDataSource = {
state(): LevelSourceState;
subscribe(listener: () => void): () => void;
dispose(): void;
query?: LevelQueryCapabilities;
write?: WriteCapability;
};

A source without write is readonly. Query capabilities are optional and awaitable:

type LevelQueryCapabilities = {
sort?: {
current(): readonly SortDescriptor[] | undefined;
set(sort: readonly SortDescriptor[] | undefined): Promise<SourceLoadResult>;
};
filter?: {
current(): unknown;
set(filter: unknown): Promise<SourceLoadResult>;
};
refetch?: () => Promise<SourceLoadResult>;
};
type SourceLoadResult =
| { kind: "ready"; state: Extract<LevelSourceState, { status: "ready" }> }
| {
kind: "error";
state: Extract<
LevelSourceState,
{ status: "initialError" | "refreshError" }
>;
}
| { kind: "unchanged"; state: LevelSourceState }
| { kind: "superseded" }
| { kind: "disposed" };

The promise resolves after the source publishes its resulting state. Pagination remains a source or host concern.