export interface DashboardWidgetLayout { id: string; /** 0-based logical column of the inline-start edge. */ x: number; /** 0-based row of the block-start edge. */ y: number; /** Column span (≥ 1). */ w: number; /** Row span (≥ 1). */ h: number; minW?: number; minH?: number; maxW?: number; maxH?: number; } export declare function collides(a: DashboardWidgetLayout, b: DashboardWidgetLayout): boolean; /** Clamp a rect to the grid bounds and its own min/max constraints. */ export declare function clampRect(item: DashboardWidgetLayout, cols: number): DashboardWidgetLayout; /** * Resolve overlaps and apply upward gravity. The `activeId` rect (the one * being dragged/resized) keeps its exact position; every other widget makes * room for it, then rises as far as gravity allows. Deterministic: widgets * settle in reading order (y, then x). * * Reflow rules, so a board never keeps holes that only show once saved: * - A widget the active rect lands on first takes the nearest hole that fits * (reading order), or free space the moved rect left (`vacated`), between * its own height above and where a plain push down would put it. * - Otherwise it is pushed down. If it was pushed from its inline-start side, * it lines up under the start of the active rect through free cells, so it * does not leave a gap before itself. Pushed from above, it keeps its x. * - Last, during a gesture only, a widget may rise into a hole above it by * up to its own width sideways (never the active rect). Without an active * rect (a drop, a remove) only gravity runs, so a saved board is final: * compacting it again changes nothing. */ export declare function normalise(layout: DashboardWidgetLayout[], cols: number, activeId?: string, vacated?: DashboardWidgetLayout): DashboardWidgetLayout[]; /** Move a widget to a target cell, resolving collisions around it. */ export declare function moveItem(layout: DashboardWidgetLayout[], id: string, x: number, y: number, cols: number): DashboardWidgetLayout[]; /** Resize a widget to a target span, resolving collisions around it. */ export declare function resizeItem(layout: DashboardWidgetLayout[], id: string, w: number, h: number, cols: number): DashboardWidgetLayout[]; /** First free slot (reading order) that fits a `w`×`h` rect. */ export declare function firstFit(layout: DashboardWidgetLayout[], cols: number, w: number, h: number): { x: number; y: number; }; /** Total rows the layout occupies (for sizing the add tile / container). */ export declare function rowCount(layout: DashboardWidgetLayout[]): number; /** * Extra inline size (px) a stacked board must reach, above `stackBelow`, * before it returns to the grid. Without the band a width hovering on the * threshold could flip the board back and forth: sub-pixel rounding, or a * page scrollbar (classic scrollbars are up to about 20 px) that appears * in one mode and disappears in the other because the two modes differ * in height. */ export declare const STACK_HYSTERESIS_PX = 24; /** * Whether the board shows one stacked column for a measured inline size. * Stacks below `stackBelow`; unstacks at `stackBelow + STACK_HYSTERESIS_PX` * or wider. An unusable threshold never stacks. A board with no measurable * box (`display: none`, a hidden tab) keeps its current mode. */ export declare function shouldStack(inlineSize: number, stackBelow: number | undefined, wasStacked: boolean): boolean; /** * Reading order of the stacked column: row (`y`), then LOGICAL column * (`x`, so RTL keeps the same order), then the caller's `ids` order on a * tie. Ids without a layout entry keep their relative order at the end. */ export declare function stackOrder(ids: string[], layout: DashboardWidgetLayout[]): string[]; //# sourceMappingURL=dashboard-grid-engine.d.ts.map