import type { WalkontableInstance } from '../types'; import type { EngineContext } from '../wire'; import type Settings from '../settings'; import type Table from '../table/baseTable'; import type EventManager from '../../../../eventManager'; import type { CalculationTypeLike, ColumnsCalculationType, RowsCalculationType } from '../calculator/viewportBase'; import { PositionCache } from '../axisSizing/positionCache'; import { type WorkspaceSize } from './workspaceSize'; import { type CalculatorFactory } from './calculatorFactory'; import type { LayoutSnapshot } from './boxLayout/layoutSnapshot'; /** * Assembles the Viewport module's dependencies from the engine composition context. * * Everything the Viewport once received as separate constructor arguments (DOM bindings, settings, * event manager, table) now flows through this one object. The `EventManager` is created once here * (matching the previous per-module `this.eventManager`), and the table is resolved concretely * because the Viewport is constructed after the master table exists. * * @param {EngineContext} ctx The engine composition context. * @returns {object} The Viewport dependency set. */ export declare function createViewportDeps(ctx: EngineContext): { wot: WalkontableInstance; rootDocument: Document; rootWindow: Window; geometryReader: import("../domMeasure/geometryReader").GeometryReader; rowSizeSource: import("../axisSizing/axisSizeSource").RowSizeSource; columnSizeSource: import("../axisSizing/axisSizeSource").AxisSizeSource; layoutDeps: { geometryReader: import("../domMeasure/geometryReader").GeometryReader; wtSettings: Settings; rootDocument: Document; rootWindow: Window; getWtTable: () => Table; getWtViewport: () => Viewport; getTopOverlay: () => import("../overlay").Overlay; getInlineStartOverlay: () => import("../overlay").Overlay; }; wtSettings: Settings; eventManager: EventManager; wtTable: Table; getTopOverlay: () => import("../overlay").Overlay; getInlineStartOverlay: () => import("../overlay").Overlay; getBottomOverlay: () => import("../overlay").Overlay; }; /** * The Viewport module dependencies, inferred from `createViewportDeps`. */ export type ViewportDeps = ReturnType; /** * The Viewport owns the per-draw calculator objects and the size prefix-sum caches. Its * workspace-size / scroll-detection queries and its calculator-creation logic are supplied by two * mixins (`workspaceSize`, `calculatorFactory`); the method bodies live in their own files so the * single-pass refactor can rework the workspace-size group in isolation. The mixin methods reach the * private dependency set through the public `deps` getter. * * @class Viewport */ declare class Viewport { #private; /** * @type {WalkontableInstance} */ wot: WalkontableInstance; /** * @type {Settings} */ wtSettings: Settings; /** * @type {Table} */ wtTable: Table; /** * @type {Record} */ oversizedRows: Record; /** * The `oversizedRows` keys whose height was discovered in a FROZEN column — content the master * table does not render, so `markOversizedRows` on the master can never re-detect it. * * `resetOversizedRows` skips these keys: wiping them would drop the record before the row-height * cache and the viewport calculators are built, and the master could not put it back. They are * cleared instead by `resetFrozenOversizedRows`, in the seam between the master's render and the * frozen overlays' — late enough that the master rendered at the right height, early enough that * the frozen clone renders at its natural height and stays re-measurable. * * @type {Set} */ frozenOversizedRows: Set; /** * The row-height cache's `buildSeq` as it stood when this draw cleared the frozen-derived * records. * * Between that clear and the frozen sync putting the records back, `oversizedRows` is missing * every frozen-derived height — so a cache built in that window is short by all of them. It is * not self-correcting: the records come back unchanged, so nothing invalidates, and the hider * keeps a scrollbar that cannot reach the end of the grid while every rendered row still looks * right. The bottom clone reaches exactly this window, since it renders (and measures) inside * `wtOverlays.refresh()`. Comparing the counter afterwards is how the sync notices. * * @type {number} */ frozenClearRowCacheBuildSeq: number; /** * @type {Record} */ hasOversizedColumnHeadersMarked: Record; /** * @type {number} */ clientHeight: number; /** * @type {number} */ columnHeaderHeight: number; /** * @type {number} */ rowHeaderWidth: number; /** * @type {RowsCalculationType | null} */ rowsVisibleCalculator: RowsCalculationType | null; /** * @type {ColumnsCalculationType | null} */ columnsVisibleCalculator: ColumnsCalculationType | null; /** * @type {Map CalculationTypeLike>} */ rowsCalculatorTypes: Map CalculationTypeLike>; /** * @type {Map CalculationTypeLike>} */ columnsCalculatorTypes: Map CalculationTypeLike>; /** * @type {EventManager} */ eventManager: EventManager; /** * @type {RowsCalculationType | null} */ rowsRenderCalculator: RowsCalculationType | null; /** * @type {ColumnsCalculationType | null} */ columnsRenderCalculator: ColumnsCalculationType | null; /** * Monotonic counter of cell-band renders, bumped by every `renderCellBand` call (see * `table/drawCycle.ts`). Overlay clones share the master's Viewport instance, so a render by ANY * table of this Walkontable — the master or any clone, nested inside a hook or not — advances it. * The master's `skipRender` rollback compares it against the value read right before the * `beforeDraw` hook fired to answer "did the hook render a DOM cell band?" — see * `restoreRenderedStateIfSafe`. * * @type {number} */ renderCycleSeq: number; /** * @type {RowsCalculationType | null} */ rowsPartiallyVisibleCalculator: RowsCalculationType | null; /** * @type {ColumnsCalculationType | null} */ columnsPartiallyVisibleCalculator: ColumnsCalculationType | null; /** * @type {PositionCache} */ rowHeightCache: PositionCache; /** * @type {PositionCache} */ columnWidthCache: PositionCache; /** * Read-only access to the dependencies, for the `workspaceSize` / `calculatorFactory` mixins, which * are defined outside this class and so cannot reach the private `#deps`. * * @returns {ViewportDeps} */ get deps(): ViewportDeps; /** * @param {ViewportDeps} deps The Viewport module dependencies. */ constructor(deps: ViewportDeps); /** * Resolves the layout snapshot for the draw that is starting, stores it, and returns it. Called * once per master draw, after the size caches are built and before the calculators run, so the * snapshot reflects the geometry the draw will render into. * * On the single-pass gated path (element mode, uniform sizes) the calculators and the * scroll-detection queries read this snapshot, so the scrollbars are predicted from content totals * and the draw renders in one pass. Off that path (merged cells, window scroll, non-uniform sizes) * the engine keeps measuring the rendered DOM; the snapshot is still resolved and its prediction * stays in agreement with the live measurement (asserted in `viewport.spec.js`). * * @returns {LayoutSnapshot} */ beginDrawLayout(): LayoutSnapshot; /** * Returns the current layout snapshot. Recomputes lazily when there is none (between draws, or after * an invalidation) so API callers outside the draw get a fresh answer. * * @returns {LayoutSnapshot} */ getLayout(): LayoutSnapshot; /** * Drops the cached layout snapshot so the next `getLayout()` recomputes it. Called whenever the * geometry that feeds the snapshot may have changed (a resize or a size-cache invalidation). */ invalidateLayout(): void; /** * Sums the heights of the `[from, to)` row range in O(1) using the row-height prefix-sum cache, * with the exact semantics of a live per-row walk. Row heights are position-independent except * for one row: the first rendered visible row reports a 1px border-top compensation * (`StylesHandler#getDefaultRowHeight`, AutoRowSize). The cache holds the heights read at build * time, so the row that carried the compensation then, and the row that carries it now, are * re-read live and the cached values are replaced by the live ones. * * @param {number} from Start row index (inclusive). * @param {number} to End row index (exclusive). * @returns {number} The height sum in pixels. */ sumRowHeights(from: number, to: number): number; /** * Marks the row height position cache as stale. The cache will be rebuilt * on the next viewport calculation. */ invalidateRowHeightCache(): void; /** * Drops every oversized-row record, not just the rendered band's, and marks the row-height cache * stale so the next draw measures the rows again. * * `resetOversizedRows` deliberately wipes only the rendered band, because a record outside it is * still the best height known for that row. That assumption breaks when the records were taken * against a table with no layout: `getComputedStyle` returned nothing, so the default row height * was unknown and every row was recorded oversized at a height it never had. Then the whole map * has to go at once, or the rows outside the band keep inflating the scroll range for good. */ resetAllOversizedRows(): void; /** * Hands the frozen-derived row records back to the ordinary oversized-row machinery, keeping their * heights but dropping their exemption from `resetOversizedRows`. * * Called on any draw that does NOT run the frozen-column row sync — the master's rendered band * starts at column 0, so it renders every frozen column and can measure those rows itself. Without * this the records would keep their exemption while nothing re-measured them, so they could only * ever grow. */ releaseFrozenOversizedRows(): void; /** * Marks the column width position cache as stale. The cache will be rebuilt * on the next viewport calculation. */ invalidateColumnWidthCache(): void; /** * Marks both the row height and column width position caches as stale. */ invalidateAllCaches(): void; /** * Resets values in keys of the hasOversizedColumnHeadersMarked object after updateSettings. */ resetHasOversizedColumnHeadersMarked(): void; } interface Viewport extends WorkspaceSize, CalculatorFactory { } export default Viewport;