import type { IconRenderer } from '../icons/icon-renderer'; import { type ResolvedLoadingOverlayConfig } from '../types/loading.types'; /** * Body geometry the skeleton indicator lays its placeholder rows out against, * supplied by `GridRenderer` from values it has already computed for the frame. * * Deliberately carries column *identities* rather than widths. `ColumnStyleManager` * publishes `[data-photon-grid-id="…"] [data-col-id="X"] { width … }` into a * shared stylesheet that it rewrites on every frame of a resize drag, so a * placeholder cell tagged with `data-col-id` tracks its column's width with no * JavaScript at all — and, crucially, without this snapshot changing. Passing * widths instead would put them in the overlay's cache signature and rebuild * every placeholder row at 60fps for the duration of a resize drag. * * The row count is pre-bucketed for the same reason: a one-pixel container * resize must not invalidate the skeleton. */ export interface LoadingGeometry { /** Height of one placeholder row, in pixels. */ readonly rowHeight: number; /** Placeholder rows needed to fill the viewport. `0` when unmeasured. */ readonly viewportRows: number; /** Left-pinned column ids, in visual order. */ readonly leftColIds: readonly string[]; /** Unpinned (centre) column ids, in visual order. */ readonly centerColIds: readonly string[]; /** Right-pinned column ids, in visual order. */ readonly rightColIds: readonly string[]; } export declare class OverlayRenderer { private iconRenderer; private loadingEl; private noRowsEl; private errorEl; private errorTimer; private containerEl; /** * Pending {@link ResolvedLoadingOverlayConfig.delay} timer. At most one is * ever outstanding — a second `showLoading` replaces it rather than stacking, * and `hideLoading`/`destroy` clear it, so a rapid toggle can neither leak a * timer nor paint an overlay after the load finished. */ private loadingTimer; /** * Signature of the loading overlay currently mounted (or scheduled). The * renderer calls `showLoading` on every frame while the flag is set, so this * is what keeps a scroll or resize frame from rebuilding identical DOM. */ private loadingSignature; /** * Whether the overlay currently shows an ad-hoc progress message rather than * the grid's own loading state. * * These two compete: an import drives the grid through `setColumns`/`setData`, * each of which schedules a render, and the render loop's non-loading path * hides the loading overlay. Without this flag the "Parsing…/Mapping…" * message would be wiped by the very next frame it caused. */ private messageActive; constructor(iconRenderer: IconRenderer); mount(containerEl: HTMLElement): void; /** * Shows the configured loading indicator over the body. * * Idempotent: repeat calls with an equivalent config and geometry are a * no-op, so the per-frame call from `GridRenderer` costs one string compare * rather than a DOM rebuild. * * @param config - Fully resolved overlay configuration. * @param geometry - Body geometry for the skeleton indicator. Optional; the * spinner ignores it, and the skeleton falls back to * sensible dimensions when it is absent. */ showLoading(config: ResolvedLoadingOverlayConfig, geometry?: LoadingGeometry): void; /** * Shows a spinner with an ad-hoc message, bypassing the configured indicator. * * Used for transient, progress-reporting work that is not the grid's own * loading state — import progress, for example — where a skeleton would * misrepresent what is happening. * * @param text - Message to display beneath the spinner. */ showLoadingMessage(text: string): void; /** * Hides the *state-driven* loading overlay, leaving an ad-hoc progress * message in place. * * This is what the render loop calls. An import schedules renders as it feeds * rows in, and each of those would otherwise tear down the progress message * the import itself put up. */ hideLoadingState(): void; hideLoading(): void; /** * Drops the cached overlay identity without unmounting anything, so the next * `showLoading` rebuilds even though its config compares equal to the last * one seen. * * Used when the configuration object itself was replaced: hiding first would * flash the body between the two paints. */ invalidateLoadingSignature(): void; showNoRows(html?: string, text?: string): void; hideNoRows(): void; /** * Shows a compact, bottom-anchored error toast — used so import/validation * failures are visibly surfaced instead of failing silently. Auto-dismisses * after {@link autoHideMs} (pass `0` to keep it until {@link hideError}). * * @param text - The user-facing error message. * @param autoHideMs - Auto-dismiss delay in ms. @default 6000 */ showError(text: string, autoHideMs?: number): void; hideError(): void; hideAll(): void; destroy(): void; /** Clears any pending delayed paint. Safe to call when none is scheduled. */ private clearLoadingTimer; /** * Compact identity of a loading overlay. Compared as a string rather than * field-by-field so the per-frame check stays a single comparison, and so * geometry (a variable-length width list) folds in without a loop. */ private buildLoadingSignature; /** Dispatches to the indicator-specific builder. */ private buildLoadingOverlay; /** Root element shared by both indicators, carrying the backdrop + a11y state. */ private buildOverlayRoot; /** Centred spinner, with an optional caption beneath it. */ private buildSpinnerOverlay; /** * Placeholder rows aligned to the real column layout. * * Three panel tracks (left / centre / right) mirror the body's own panel * structure, so pinned columns stay pinned. Each cell carries `data-col-id`, * which `ColumnStyleManager`'s generated width rules target — so widths, and * live resize drags, cost this renderer nothing. The centre track uses the * same `--pg-scroll-x` custom property the real centre panel does, so it * follows horizontal scroll without a scroll listener. * * Reuses the `.pg-row--skeleton` / `.pg-cell` / `.pg-cell__inner` structure so * the shimmer bar, its per-column width variance and the reduced-motion * fallback all come from the shared `skeleton.css` rules rather than being * duplicated here. The whole tree is assembled into a `DocumentFragment` and * appended once, so N rows cost one layout, not N. */ private buildSkeletonOverlay; /** * One panel track of placeholder rows. * * @param panel - Which body panel this mirrors, for the modifier class. * @param colIds - Column ids to tag cells with, in visual order. * @param rowCount - Placeholder rows to draw. * @param untaggedCells - Cells to draw per row when `colIds` is empty. */ private buildSkeletonPanel; } //# sourceMappingURL=overlay-renderer.d.ts.map