← All packages

@searsuite/sear-render-strategy

Drawing strategies

classDirtyRenderStrategy
class DirtyRenderStrategy<NodeTypeProperties> extends RenderStrategy<NodeTypeProperties>

Incremental renderer that redraws only dirty regions.

It reads dirty rectangles from the registered dirty tracker, clears those regions on both on-screen and off-screen contexts, redraws intersected nodes, and finally resets the dirty tracker.

constructorDirtyRenderStrategy<NodeTypeProperties>(renderContext: RenderContext, offScreenRenderContext: RenderContext, hitRenderContext: RenderContext, scrollManager: ScrollManager, configEngine: ConfigEngine, renderCoordinatorManager: RenderCoordinatorManager, stage: SceneGraph<NodeTypeProperties>, tree: Tree<PositionRect<templateLiteral>>, dirtyTree: GenerationalDirtyTracker): DirtyRenderStrategy<NodeTypeProperties>
propertyreadonly symbol: typeof symbolstatic

DI token for resolving DirtyRenderStrategy.

methodgetContext(): RenderContext

Returns the screen render context used by this strategy.

methodgetNodeByCoordinates(node: Node<NodeTypeProperties>, x: number, y: number): Node<NodeTypeProperties>[]

Dirty strategy does not currently expose coordinate lookup.

ThrowsError Always thrown until this API is implemented.

methodrender(node: Node<NodeTypeProperties>): void

Redraws all dirty regions for both render targets.

Each dirty rect is processed atomically: clearRect followed immediately by redraw of intersecting nodes. This guarantees that a later rect's clear can erase pixels re-painted by an earlier rect's redraw — critical for cases like cell-editor exit where the overflow area must stay clean despite the grid cell's TextNode redrawing overflow text into it.

Inherited members 9

Inherited from RenderStrategy.

classEventRenderStrategy
class EventRenderStrategy<NodeTypeProperties> extends RenderStrategy<NodeTypeProperties>

Render strategy dedicated to event-layer integration.

This strategy currently acts as a placeholder extension point. It shares the same contract as all render strategies so event visualization can be added later without changing orchestration code.

Inherited members 9

Inherited from RenderStrategy.

classHitRenderStrategy
class HitRenderStrategy<NodeTypeProperties> extends RenderStrategy<NodeTypeProperties>

Strategy for hit-testing rendering and coordinate-to-node lookup.

The hit layer paints interactive nodes with unique colors on an off-screen canvas. Pointer coordinates are then resolved by reading back pixel colors and mapping them to scene nodes.

constructorHitRenderStrategy<NodeTypeProperties>(renderContext: RenderContext, offScreenRenderContext: RenderContext, hitRenderContext: RenderContext, scrollManager: ScrollManager, configEngine: ConfigEngine, renderCoordinatorManager: RenderCoordinatorManager, stage: SceneGraph<NodeTypeProperties>, tree: Tree<PositionRect<templateLiteral>>, dirtyTree: GenerationalDirtyTracker, platform: Platform): HitRenderStrategy<NodeTypeProperties>
propertyreadonly symbol: typeof symbolstatic

DI token for resolving HitRenderStrategy.

methoddebouncedRender(node: Node<NodeTypeProperties>): void

Actually performs the hit-canvas rendering after debounce.

node

Node to render

methoddestroy(): void

Cancels deferred hit-layer work when the owning editor is destroyed.

methodflushPendingScrollRender(): void

Ensures a pointer event never reads a hit layer from before the latest scroll-driven scene rebuild. The normal path remains frame-coalesced; this only runs when the user interacts before that frame is delivered.

methodgetContext(): RenderContext

Get the current rendering context.

ReturnsRenderContext

methodgetNodeByCoordinates(node: Node<NodeTypeProperties>, x: number, y: number): Node<NodeTypeProperties>[]

Get all nodes at the given (x, y) coordinate by reading the hit-canvas pixel.

ReturnsArray of nodes at the given coordinate

node

Root node to search from

x

X coordinate

y

Y coordinate

methodrender(node: Node<NodeTypeProperties>, delay?: number): void

Debounced render entry. Only the last call within the delay will trigger rendering.

node

Node to render

delay

Debounce delay in ms

methodrenderImmediate(node: Node<NodeTypeProperties>): void

Render the hit canvas immediately, bypassing the debounce timer.

Used after viewport-culled plugins rebuild their scene nodes during scroll. Since new FixBoxNode instances get new random color keys, the hit canvas must be redrawn before the next click event. The normal debounced path would keep resetting the timer during continuous scrolling, leaving the hit canvas stale and clicks unresolvable.

methodrenderOnNextFrame(node: Node<NodeTypeProperties>): void

Schedules a hit-layer refresh for the next frame. Wheel events can be delivered many times per frame; only the newest rebuilt scene matters.

Inherited members 9

Inherited from RenderStrategy.

classOverlayRenderStrategy
class OverlayRenderStrategy<NodeTypeProperties> extends RenderStrategy<NodeTypeProperties>

Render pass that paints editor overlays at the very end of the pipeline.

This pass guarantees edit-mode visuals stay above sticky headers and any other layers by drawing nodes with isEdit after StickyRenderStrategy.

Inherited members 9

Inherited from RenderStrategy.

classRenderStrategy
class RenderStrategy<T>

Base abstraction for all render strategies.

A render strategy encapsulates one rendering concern (screen layer, hit layer, sticky overlays, dirty-region redraw, etc.) and shares a common life-cycle:

  1. Receive scroll updates from ScrollManager.
  2. Derive absolute scroll position and frame delta.
  3. Trigger strategy-specific rendering.
  4. Persist previous scroll state for the next frame comparison.

Subclasses only need to implement how they render, which context they expose, and how they perform coordinate-based node lookup for their layer.

classRenderStrategyManager
class RenderStrategyManager<NodeTypeProperties>

Registry and lookup manager for render strategies.

The render engine uses this manager to compose a strategy pipeline by name. Names can be string keys or symbols to avoid collisions in plugin scenarios.

constructorRenderStrategyManager<NodeTypeProperties>(): RenderStrategyManager<NodeTypeProperties>
propertyreadonly symbol: symbolstatic

DI token for resolving RenderStrategyManager.

methodaddStrategy(name: string | Symbol, strategy: RenderStrategy<NodeTypeProperties>): void

Registers or replaces a strategy under the provided key.

methodaddStrategyAfter(reference: string | Symbol, name: string | Symbol, strategy: RenderStrategy<NodeTypeProperties>): void

Inserts a strategy immediately after an existing strategy.

methodaddStrategyBefore(reference: string | Symbol, name: string | Symbol, strategy: RenderStrategy<NodeTypeProperties>): void

Inserts a strategy immediately before an existing strategy.

methodenforceCommandBoundary(isExecuting: (): boolean): void

Closes direct strategy and view-scale changes after Sheet startup.

methodgetAllStrategy(): RenderStrategy<NodeTypeProperties>[]

Returns all currently registered strategies in insertion order.

methodgetStrategy(name: string | Symbol): RenderStrategy<NodeTypeProperties> | undefined

Retrieves a strategy by key.

methodsetViewScale(scale: number): void

Propagates view scale to every context contributed by registered strategies. Shared base/off-screen/hit contexts are updated once.

classScreenRenderStrategy
class ScreenRenderStrategy<NodeTypeProperties> extends RenderStrategy<NodeTypeProperties>

Base abstraction for all render strategies.

A render strategy encapsulates one rendering concern (screen layer, hit layer, sticky overlays, dirty-region redraw, etc.) and shares a common life-cycle:

  1. Receive scroll updates from ScrollManager.
  2. Derive absolute scroll position and frame delta.
  3. Trigger strategy-specific rendering.
  4. Persist previous scroll state for the next frame comparison.

Subclasses only need to implement how they render, which context they expose, and how they perform coordinate-based node lookup for their layer.

constructorScreenRenderStrategy<NodeTypeProperties>(renderContext: RenderContext, offScreenRenderContext: RenderContext, hitRenderContext: RenderContext, scrollManager: ScrollManager, configEngine: ConfigEngine, renderCoordinatorManager: RenderCoordinatorManager, stage: SceneGraph<NodeTypeProperties>, tree: Tree<PositionRect<templateLiteral>>, dirtyTree: GenerationalDirtyTracker, rasterCopyExecutor: RasterCopyExecutor): ScreenRenderStrategy<NodeTypeProperties>

Creates a screen render strategy with injected render targets and copy executor.

propertyreadonly symbol: typeof symbolstatic

DI token for resolving ScreenRenderStrategy.

methodconfigureRuntime(runtime: ScreenRenderStrategyRuntime<NodeTypeProperties>): void

Configures host-specific viewport, query, and drawing semantics.

methodgetContext(): RenderContext

Returns the current render context.

The returned context targets the on-screen canvas.

methodgetNodeByCoordinates(node: Node<NodeTypeProperties>, x: number, y: number): Node<NodeTypeProperties>[]

Not implemented: Finds nodes at the given coordinates.

ThrowsError

methodrender(node: Node<NodeTypeProperties>): void

Renders the scene graph node using an off-screen buffer for efficient scrolling.

node

The root node to render.

Inherited members 9

Inherited from RenderStrategy.

classStickyRenderStrategy
class StickyRenderStrategy<NodeTypeProperties> extends RenderStrategy<NodeTypeProperties>

StickyRenderStrategy is responsible for rendering all StickyNode instances. It should be used after the main render strategy to overlay sticky elements.

Inherited members 9

Inherited from RenderStrategy.

interfaceScreenRenderStrategyRuntime
interface ScreenRenderStrategyRuntime<NodeTypeProperties>
propertyreadonly consumeBlockRasterCopyPlan?: (): BlockRasterCopyPlan | null

Consumes a pending block-copy plan for layout-shift frames, if the host has one.

propertyreadonly drawNodes?: (input: { context: RenderContext; nodes: readonly Node<NodeTypeProperties>[]; scrollState: ScrollManagerState; worldRect: PositionRect<templateLiteral> }): void

Draws already queried nodes into the visible render context.

propertyreadonly forceFullRepaint?: (): boolean

Forces a full visible body repaint even when the off-screen cache is ready.

propertyreadonly getScrollState?: (): ScrollManagerState

Returns the scroll state used for world queries and raster copy deltas.

propertyreadonly getViewport?: (): PositionRect<templateLiteral>

Returns the viewport-space rectangle covered by this screen layer.

propertyreadonly isScrollStateChanged?: (scrollState: ScrollManagerState): boolean

Returns whether the current scroll state requires a scroll-copy frame.

propertyreadonly onFrameRendered?: (mode: ScreenRenderFrameMode): void

Called after a full, scroll, or rebuilt frame is rendered.

propertyreadonly queryNodes?: (root: Node<NodeTypeProperties>, worldRect: PositionRect<templateLiteral>): readonly Node<NodeTypeProperties>[]

Returns screen-body nodes to draw for the supplied world-space rectangle.

propertyreadonly requiresFrameRebuild?: (): boolean

Returns whether this frame should rebuild a retained render target.

propertyreadonly toWorldRect?: (viewportRect: PositionRect<templateLiteral>, scrollState: ScrollManagerState): PositionRect<templateLiteral>

Maps a viewport-space repaint rectangle to a world-space query rectangle.

typeScreenRenderFrameMode
type ScreenRenderFrameMode = "rebuild" | "full" | "scroll" | "block-copy"

ScreenRenderStrategy handles rendering with an off-screen buffer to optimize scroll performance. It minimizes redraws by copying unchanged regions and only re-rendering areas affected by scrolling.

Rendering modes:

  • First frame: full draw to screen, then clone into off-screen buffer.
  • Scroll frame: blit preserved region from off-screen, redraw only newly exposed strip, then sync back to off-screen.

Incremental redraw

Dirty regions and the incremental policy decide whether a frame can reuse the previous one or needs a rebuild.

classDirtyRegionCollector
class DirtyRegionCollector<T>

Collects frame-scoped dirty regions and builds dirty clip geometry.

The collector is intentionally independent from Sheet cells. It owns only rectangle collection, frame cleanup, stroke expansion and the concave union clip used when a dirty region must include both a changed area and the previously painted node bounds.

constructorDirtyRegionCollector<T>(source: DirtyRegionSource<T>): DirtyRegionCollector<T>

Creates a collector around a frame-scoped dirty source.

source

Dirty source owned by the host renderer.

methodclear(): void

Clears all dirty rectangles from the underlying source.

methodcollect(): PositionRect<T>[]

Returns all dirty rectangles accumulated for the current frame.

The source is not cleared by this method; callers should clear only after the frame's redraw work has succeeded or has been intentionally skipped.

methodcreateClipRegion<T>(dirtyRect: PositionRect<T>, nodeRect: PositionRect<T>, strokeWidth: number, useUnionClip: boolean): PositionRect<templateLiteral> | [number, number][]static

Builds the repaint clip for one dirty region and one intersecting node.

Most nodes can repaint within the expanded dirty rectangle. Selection-like nodes may need a concave clip covering the union of the dirty region and the node's previous bounds so erased borders do not leave seams.

ReturnsA rectangle or polygon accepted by scene node draw calls.

dirtyRect

Dirty rectangle in world coordinates.

nodeRect

Node bounds in world coordinates.

strokeWidth

Stroke width used to expand both dirty and node bounds.

useUnionClip

Whether to compute the concave union boundary.

methoddedupePoints(points: [number, number][]): [number, number][]static

Removes duplicated points while preserving first occurrence order.

ReturnsDeduplicated polygon points.

points

Polygon points.

methodexpand<T>(rect: PositionRect<T>, padding: number): PositionRect<templateLiteral>static

Expands a dirty rectangle by a symmetric stroke padding.

ReturnsExpanded rectangle suitable for clipping repaint work.

rect

Dirty rectangle in world coordinates.

padding

Pixels added to every edge.

methodremoveCollinear(points: [number, number][]): [number, number][]static

Drops middle vertices that lie on a straight line.

Degenerate polygons are preserved as-is so callers can fall back to a rectangle when the boundary cannot form a useful clip.

ReturnsCleaned polygon points.

points

Polygon points in boundary order.

methodtraceUnionBoundary(rectA: DirtyRegionBounds, rectB: DirtyRegionBounds): [number, number][]static

Traces the outer boundary of the union of two axis-aligned rectangles.

The returned path may be concave and is intended for clip construction, not for hit testing or layout geometry.

ReturnsBoundary points in drawing order.

rectA

First rectangle bounds.

rectB

Second rectangle bounds.

classIncrementalRenderPolicy

Decides whether an incremental render candidate is worth using for the next frame.

classViewportFrameCache

Manages the off-screen viewport frame used by Canvas scroll optimization.

The cache wraps RenderContext.isDrawn so consumers do not need to reach into the render target directly. It provides explicit operations for clearing, priming after first paint, and refreshing after an incremental scroll redraw.

constructorViewportFrameCache(cacheContext: RenderContext, copyExecutor: RasterCopyExecutor): ViewportFrameCache

Creates a viewport frame cache facade.

cacheContext

Off-screen render target that stores the last complete base frame.

copyExecutor

Raster copy executor used for cache synchronization.

methodclear(viewport: PositionRectProps): void

Clears the cached viewport with an identity transform.

viewport

Viewport-space rectangle to erase from the cache.

methodinvalidate(): void

Marks the cached frame invalid so the next render performs a full prime.

methodisReady(): boolean

Returns whether the cache already contains a complete base frame.

methodmarkReady(): void

Marks the cached frame ready after a complete frame has been copied in.

methodprimeFromVisibleFrame(visibleContext: RenderContext, viewport: PositionRectProps): void

Primes the cache from the visible frame after a first full paint.

visibleContext

Visible render target containing a complete base frame.

viewport

Viewport-space rectangle to clear before copying.

methodrefreshFromVisibleFrame(visibleContext: RenderContext, viewport: PositionRectProps): void

Refreshes the cache from the visible target after incremental redraw.

visibleContext

Visible render target containing the latest base frame.

viewport

Viewport-space rectangle to copy into the cache.

interfaceDirtyRegionBounds

Boundary represented by four world-space edges.

propertyreadonly x1: number

Left edge in world coordinates.

propertyreadonly x2: number

Right edge in world coordinates.

propertyreadonly y1: number

Top edge in world coordinates.

propertyreadonly y2: number

Bottom edge in world coordinates.

interfaceDirtyRegionSource
interface DirtyRegionSource<T>

Minimal dirty-region storage contract consumed by DirtyRegionCollector.

Sheet uses GenerationalDirtyTracker; future document renderers can provide a block/page dirty source with the same boundary, query and frame-clear contract without depending on Sheet scene internals.

methodclear(): void

Clears dirty state after the owning frame has consumed it.

methodgetBoundary(): PositionRect<T>

Returns the total query boundary that contains all possible dirty entries.

methodquery(range: PositionRect<T>): PositionRect<T>[]

Returns dirty rectangles intersecting the provided query range.

interfaceIncrementalRenderCandidate

Measured cost shape for one proposed incremental render frame.

propertyreadonly copiedArea: number

Total destination pixel area copied from the retained/off-screen frame cache.

propertyreadonly copyCount: number

Number of raster copy rectangles in the candidate plan.

propertyreadonly invalidArea: number

Total world pixel area that still needs redraw after raster reuse.

propertyreadonly invalidRectCount: number

Number of invalid redraw rectangles in the candidate plan.

propertyreadonly viewport: Pick<PositionRectProps, "width" | "height">

Viewport dimensions used as the baseline for area ratios.

interfaceIncrementalRenderPolicyLimits

Guardrails used to decide whether an incremental render plan is cheaper and safe enough to use.

propertyreadonly maxCopiedAreaRatio: number

Maximum total copied pixel area divided by viewport area. Values above 1 allow overlapping or repeated copies.

propertyreadonly maxCopyCount: number

Maximum number of raster copy rectangles allowed in one frame.

propertyreadonly maxInvalidAreaRatio: number

Maximum invalid redraw area divided by viewport area after raster copies have been applied.

propertyreadonly maxInvalidRectCount: number

Maximum number of invalid redraw rectangles allowed in one frame.

interfaceRenderContextCapabilities

Capability snapshot used by viewport render coordinators before choosing a raster strategy.

typeIncrementalRenderDecisionReason
type IncrementalRenderDecisionReason = typeof IncrementalRenderDecisionReason[keyof typeof IncrementalRenderDecisionReason] IncrementalRenderDecisionReason: { Accepted: "accepted"; EmptyViewport: "empty-viewport"; ExcessiveCopiedArea: "excessive-copied-area"; ExcessiveCopyCount: "excessive-copy-count"; ExcessiveInvalidArea: "excessive-invalid-area"; ExcessiveInvalidRectCount: "excessive-invalid-rect-count"; NotCandidate: "not-candidate" }
variableDEFAULT_INCREMENTAL_RENDER_POLICY_LIMITS
DEFAULT_INCREMENTAL_RENDER_POLICY_LIMITS: IncrementalRenderPolicyLimits
functionclearViewport
clearViewport(context: RenderContext, viewport: PositionRectProps): void
functionclearViewportRect
clearViewportRect(context: RenderContext, rect: PositionRectProps): void
functioncreateViewportFrameCache
createViewportFrameCache(cacheContext: RenderContext, copyExecutor: RasterCopyExecutor): ViewportFrameCache
functionreadRenderContextCapabilities
readRenderContextCapabilities(context: RenderContext): RenderContextCapabilities
functionrequiresViewportExplicitNodeClear
requiresViewportExplicitNodeClear(context: RenderContext): boolean
functionrequiresViewportFrameRebuild
requiresViewportFrameRebuild(context: RenderContext): boolean
functionsupportsViewportDirtyRedraw
supportsViewportDirtyRedraw(context: RenderContext): boolean
functionworldRectToViewportClearRect
worldRectToViewportClearRect<T>(rect: PositionRect<T>, scrollX: number, scrollY: number, padding: number): PositionRect<templateLiteral>

Raster copying

Raster copy plans reuse already painted pixels when a viewport change makes that safe.

classRasterCopyExecutor

Executes raster copies between render contexts with transform isolation.

The executor owns the identity-transform save/restore wrapper used by Canvas viewport copy paths. Retained targets can avoid this executor entirely by selecting a full-frame rebuild through context capabilities.

constructorRasterCopyExecutor(): RasterCopyExecutor
propertyreadonly symbol: typeof symbolstatic

DI token for resolving RasterCopyExecutor.

methodcopy(source: RenderContext, destination: RenderContext, copy: RasterCopyRect): void

Copies a rectangular pixel region from one render target into another.

source

Source render context.

destination

Destination render context.

copy

Source and destination rectangles in viewport coordinates.

methodcopyNatural(source: RenderContext, destination: RenderContext, x?: number, y?: number): void

Copies the source target at its natural size to a viewport-space origin.

This keeps initial off-screen cache priming compatible with existing Canvas behavior where the complete visible backing store is cloned after first paint.

source

Source render context.

destination

Destination render context.

x

Destination x-coordinate.

y

Destination y-coordinate.

classRasterCopyPlan

Immutable plan for reusing viewport pixels across render targets.

A plan describes the off-screen-to-visible copy for a scroll frame, the newly exposed viewport rectangle that still needs node redraw, and the final visible-to-off-screen copy that refreshes the cache after redraw.

constructorRasterCopyPlan(viewport: PositionRect<templateLiteral>, cacheToViewportCopy: RasterCopyRect, blankViewportRect: PositionRect<templateLiteral>, blankWorldRect: PositionRect<templateLiteral>, viewportToCacheCopy: RasterCopyRect): RasterCopyPlan

Creates a raster copy plan.

viewport

Viewport rectangle in viewport coordinates.

cacheToViewportCopy

Copy from the cached frame into the visible target.

blankViewportRect

Newly exposed viewport-space area to redraw.

blankWorldRect

Newly exposed world-space area to query from the scene.

viewportToCacheCopy

Copy from the visible target back into the cache.

propertyreadonly blankViewportRect: PositionRect<templateLiteral>

Newly exposed viewport-space area to redraw.

propertyreadonly blankWorldRect: PositionRect<templateLiteral>

Newly exposed world-space area to query from the scene.

propertyreadonly cacheToViewportCopy: RasterCopyRect

Copy from the cached frame into the visible target.

propertyreadonly viewport: PositionRect<templateLiteral>

Viewport rectangle in viewport coordinates.

propertyreadonly viewportToCacheCopy: RasterCopyRect

Copy from the visible target back into the cache.

methodcreateViewportToCacheCopy(viewport: PositionRectProps): RasterCopyRectstatic

Creates a full-viewport copy from the visible target into the frame cache.

ReturnsCopy rectangle with identical source and destination bounds.

viewport

Viewport-space bounds to copy.

methodfromScroll(viewport: PositionRect<templateLiteral>, scrollState: ScrollManagerState): RasterCopyPlanstatic

Builds the scroll-copy plan used by Canvas viewport renderers.

The delta convention follows RenderStrategy: delta is previous minus current, while drawImage source offsets use current minus previous.

ReturnsPlan for copy, exposed-area redraw, and cache refresh.

viewport

Visible viewport rectangle in viewport coordinates.

scrollState

Current scroll snapshot.

interfaceRasterCopyRect

Source and destination rectangles for one raster copy.

propertyreadonly destination: PositionRectProps

Destination pixels inside the destination render target, expressed in viewport coordinates.

propertyreadonly source: PositionRectProps

Source pixels inside the source render target, expressed in viewport coordinates.