export interface AdaptiveFrameSize { width: number; height: number; } export interface AdaptiveFramePosition extends AdaptiveFrameSize { x: number; y: number; } export interface AdaptiveFrameLayout { frames: AdaptiveFramePosition[]; width: number; height: number; rowWidth: number; } export interface AdaptiveFrameLayoutOptions { gap?: number; targetAspectRatio?: number; maxRowWidth?: number; } export interface AdaptiveMasonryLayoutOptions { gap?: number; targetAspectRatio?: number; maxColumns?: number; maxWidth?: number; } export interface AdaptiveMasonryLayout extends AdaptiveFrameLayout { columnCount: number; } export interface LaneInput { laneId: string; frames: readonly AdaptiveFrameSize[]; } export interface LaneBand { laneId: string; x: number; y: number; width: number; height: number; } export interface LanedFrameLayout { /** Positions in the input order, lanes concatenated. */ frames: AdaptiveFramePosition[]; bands: LaneBand[]; width: number; height: number; } export interface LaneLayoutOptions { /** Between frames inside one lane — "the next thing in this situation". */ gap?: number; /** Between lanes — "a different situation". Wider than gap on purpose. */ laneGap?: number; /** Frames per lane row before the lane wraps into a continuation row. */ maxFramesPerRow?: number; } /** * Lays lanes out as rows: one lane is one horizontal run, read left to right, * and lanes stack downward separated by a wider gap. * * Rows are left-aligned rather than column-aligned across lanes. Forcing a * grid would imply a correspondence between, say, the third screen of the * recording run and the third error path, and would punch holes wherever a * lane is shorter — the gap is what carries the grouping, so it does the work * instead. * * A lane longer than `maxFramesPerRow` wraps into continuation rows at the * intra-lane gap, which keeps a whole lane inside one viewport at overview * zoom while still reading as one block. */ export declare function layoutLaneRows(lanes: readonly LaneInput[], options?: LaneLayoutOptions): LanedFrameLayout; /** * Packs ordered frames into a compact storyboard block. The target row width is * derived from total rendered area, so larger stories gain columns gradually * without relying on a fixed column count. Hosts may still provide an explicit * maximum when their canvas has a known horizontal constraint. */ export declare function layoutAdaptiveFrames(frames: readonly AdaptiveFrameSize[], options?: AdaptiveFrameLayoutOptions): AdaptiveFrameLayout; /** * Packs independent, content-sized sheets into geometry-aware columns. * * A normal storyboard keeps authored order in horizontal rows. Catalog sheets * are different: their heights can vary by thousands of pixels, so a single * tall sheet must not reserve that height underneath every neighbour in its * row. This layout tries several column counts, places each next sheet in the * shortest column, then chooses the compact result closest to the requested * aspect ratio. The result can be two, four, or five columns; three is never a * hard-coded layout rule. */ export declare function layoutAdaptiveMasonryFrames(frames: readonly AdaptiveFrameSize[], options?: AdaptiveMasonryLayoutOptions): AdaptiveMasonryLayout;