import type { RowNode } from '../../types/row.types'; import type { GridOptions } from '../../types/grid.types'; import type { MasterDetailConfig } from '../../types/master-detail.types'; import type { DetailEvent } from '../../types/detail-component.types'; import { EmptyDetailToggleMode } from '../../types/master-detail.types'; import type { GridStore } from '../../core/grid-store'; import type { RowModel } from '../../core/row-model'; import type { EventBus } from '../../event-bus/event-bus'; import type { ThemeMode, ThemeVariant } from '../../types/theme.types'; /** * Drives the Master/Detail row-expansion feature. * * Owns expanded/collapsed state (repurposing the previously-unused * `GridStore.expandedRowIds`, mirroring how `GroupingEngine` owns * `expandedGroupKeys`), the per-row detail-height cache that survives pipeline * re-runs, and the async fetch/cache lifecycle for `getDetailData`. * * Deliberately holds no reference to `GridApi` or the renderer — like every * other engine in `GridContext`, it is a pure state/data layer. Rendering * (nested grid instantiation, DOM) lives entirely in `DetailRowRenderer`. */ export declare class MasterDetailEngine { private store; private eventBus; private rowModel; private config; /** Detail dataset fetched via `getDetailData`, keyed by parent row `nodeId`. Survives collapse/re-expand within the grid's lifetime. */ private detailDataCache; /** Detail row height, keyed by parent row `nodeId` — set by auto-measurement or manual resize, read back on every `injectDetailRows` call so height survives pipeline re-runs. */ private heightCache; /** Parent row node ids whose `getDetailData` fetch is in flight. */ private pendingNodeIds; /** Node ids already evaluated against `defaultExpanded` — ensures a user-collapsed row is never re-expanded on the next pipeline run. */ private defaultAppliedNodeIds; private refreshCallback; constructor(store: GridStore, eventBus: EventBus, rowModel: RowModel); /** Applies the grid's `masterDetail` option block. Called once from `GridCore.initialize`. */ configure(config: MasterDetailConfig | undefined): void; isEnabled(): boolean; /** Read-only access to the active config — used by `DetailRowRenderer` to resolve `detailRendererFn`/`detailResizable`/`detailAutoHeight`. */ getConfig(): MasterDetailConfig | null; /** Registers the callback used to re-run the pipeline after an async detail fetch resolves or a height changes. Wired from `GridCore`. */ setRefreshCallback(fn: () => void): void; isExpanded(nodeId: string): boolean; /** Whether `rowData` has real detail content behind it (drives which toggle variant renders, and whether `getDetailData` is called). */ hasDetail(rowData: Record): boolean; /** Resolved {@link MasterDetailConfig.emptyDetailToggle} — what the toggle column renders for a row `hasDetail` rejects. */ getEmptyDetailToggleMode(): EmptyDetailToggleMode; /** Resolved {@link MasterDetailConfig.emptyDetailText} — shown in place of a nested grid for a detail-less row. */ getEmptyDetailText(): string; /** * Whether a row gets a detail section injected when expanded. * * Wider than {@link hasDetail} on purpose: under * {@link EmptyDetailToggleMode.Interactive} a detail-less row keeps a working * chevron, so it must also get a detail row to expand into — one that * `DetailRowRenderer` fills with the empty-state message instead of a nested * grid. Under the other modes such a row has no toggle at all and can never * reach an expanded state. */ canExpand(rowData: Record): boolean; expand(row: RowNode): void; collapse(row: RowNode): void; toggle(row: RowNode): void; collapseAll(rows: RowNode[]): void; /** Whether `nodeId`'s `getDetailData` fetch is still in flight — `DetailRowRenderer` shows a loading state instead of mounting the nested grid. */ isPending(nodeId: string): boolean; /** * The pipeline's final step (called from `GridApi.applyPipeline`, after * sort/group/paginate). Splices a `type: 'detail'` `RowNode` after every * expanded, detail-eligible `'data'` row. Works uniformly whether grouping * is active or not because grouping has already flattened its tree into a * linear array by this point — this is a pure "insert after" pass with no * knowledge of group structure. */ injectDetailRows(rows: RowNode[]): RowNode[]; /** * Re-publishes a custom detail-component event on the grid's event bus. * * `masterDetail.events` already gives consumers named callbacks; this is the * single-stream counterpart framework wrappers bind to when they need to * surface every detail event as one output without knowing the names up * front. Called by `DetailComponentHost` after the named handler (if any) * has run. */ emitDetailEvent(event: DetailEvent): void; getCachedDetailData(nodeId: string): Record[] | undefined; /** * Updates a detail row's height (from auto-measurement or manual resize), * clamps it to the configured min/max, and — if it actually changed — * requests a pipeline refresh so `RowModel` relayouts subsequent rows. */ setDetailHeight(nodeId: string, height: number): void; /** * Resolves the full `GridOptions` for a parent row's nested grid instance: * merges the static/factory `detailGrid` config, inherits the parent's * active mode + variant unless the detail config specifies its own theming, * and injects the fetched detail dataset. */ resolveDetailGridOptions(row: RowNode, parentMode: ThemeMode | null, parentVariant: ThemeVariant | 'none' | null): GridOptions; destroy(): void; private clampHeight; private fetchDetailDataIfNeeded; } //# sourceMappingURL=master-detail-engine.d.ts.map