← All packages

@searsuite/sear-render-cursor

Portable cursor policies with Web and headless host adapters.

Cursor engines

classCursorEngine

Abstract cursor presentation layer.

Responsibilities: translate a logical CursorToken into a concrete presentation (CSS cursor, Canvas sprite, Electron native cursor, test stub, …). Fully decoupled from the Plugin system and the rule system.

Contract:

  • mount() called once during plugin initialization, receives the render target.
  • apply() called on every cursor change; implementations must be idempotent.
  • unmount() called during plugin destruction; must clean up all side-effects.
constructorCursorEngine(): CursorEngine
propertyreadonly symbol: symbolstatic

DI token for resolving CursorEngine.

methodapply(token: CursorToken): void

Applies a transaction to CursorEngine state.

methodmount(target: unknown): void

Attaches this adapter to its host surface.

methodoverride(token: CursorToken | null): void

Lock the cursor to a fixed token (e.g. during cell editing). Pass null to release.

methodunmount(): void

Detaches this adapter from its host surface.

classCursorRegistry

Stores cursor rules and resolves the correct CursorToken for a given CellProperties.

Resolution priority (highest → lowest):

  1. Matching PositionCursorRule at the greatest layer — last registered wins
  2. PredicateCursorRule { priority: 'high' } — last registered wins
  3. RegionCursorRule — exact region match
  4. TypeCursorRule — exact type match
  5. PredicateCursorRule { priority: 'low' } — last registered wins
  6. Fallback: 'default'
constructorCursorRegistry(platform?: Platform): CursorRegistry

Creates a registry and optionally enables position-rule conflict diagnostics.

propertyreadonly symbol: symbolstatic

DI token for resolving CursorRegistry.

methodregister(rule: CursorRule): (): void

Registers a cursor rule and returns an idempotent disposer that restores the previous rule for the same key when applicable.

methodregisterPosition(rule: Omit<PositionCursorRule, "kind">): (): void

Registers a coordinate-aware cursor rule without requiring callers to repeat the position-rule discriminator.

ReturnsAn idempotent disposer that restores the previous rule for its key.

rule

Position rule fields excluding the fixed kind discriminator.

methodresolve(properties: CellProperties | null, position?: CursorPosition): CursorToken

Resolves a logical cursor token without exposing presentation details.

properties

Hit-tested cell properties, if any.

position

Pointer context used by registered coordinate rules.

classHeadlessCursorEngine
class HeadlessCursorEngine extends CursorEngine

Cursor adapter for environments that have no visible pointer.

constructorHeadlessCursorEngine(): HeadlessCursorEngine
propertyreadonly symbol: symbolstatic

DI token for resolving HeadlessCursorEngine.

methodapply(_token: CursorToken): void

Applies a transaction to HeadlessCursorEngine state.

methodmount(_target: unknown): void

Attaches this adapter to its host surface.

methodoverride(_token: CursorToken | null): void

Applies a temporary host cursor override.

methodunmount(): void

Detaches this adapter from its host surface.

classSheetCursorPlugin
class SheetCursorPlugin extends Plugin<SearCoreSheet, CellProperties, ISheetCursorState>

Projects Sheet interaction state into host cursor behavior.

constructorSheetCursorPlugin(cursorRegistry: CursorRegistry, cursorEngine: CursorEngine, coordinates: CoordinateEngine, renderContext: RenderContext): SheetCursorPlugin
propertyreadonly symbol: symbolstatic

DI token for resolving SheetCursorPlugin.

methodapply(_state: ISheetCursorState, _tx: Transaction): ISheetCursorState | null

Applies a transaction to SheetCursorPlugin state.

methodgetPluginConfig(): { }

Returns the plugin config.

methodonMouseMove(_searCore: SearCoreSheet, event: EventWithOffsetAndTarget<CellProperties>): void

Returns void (not false) so the event continues to propagate to downstream plugins (selection, editor, etc.). See Guide.md §8: returning false blocks subsequent plugins.

methodregisterState(): { key: PluginKey; state: { } }

Registers the state.

methodrender(): null

Returns null: this plugin produces no scene nodes. Nothing is written to SceneGraph → DirtyTree, StickyRenderStrategy, and Hit Canvas are completely unaffected (Rule.md §1.4, §1.5).

Inherited members 29

Inherited from Plugin.

classWebCursorEngine
class WebCursorEngine extends CursorEngine

Browser CSS cursor implementation. Maps CursorToken to CSS cursor values (including SVG data URI custom cursors).

constructorWebCursorEngine(): WebCursorEngine
methodapply(token: CursorToken): void

Applies a transaction to WebCursorEngine state.

methodmount(target: unknown): void

Attaches this adapter to its host surface.

methodoverride(token: CursorToken | null): void

Applies a temporary host cursor override.

methodregisterToken(token: string, cssCursor: string): void

Allow third parties to extend or override Token → CSS mapping.

methodunmount(): void

Detaches this adapter from its host surface.

Inherited members 1

Inherited from CursorEngine.

Cursor rules

interfaceCursorPosition

Pointer coordinates supplied to a position cursor rule for one pointer event.

propertycore: SearCoreSheet

Sheet core whose current data and interaction state may inform the cursor decision.

propertyorigin: EventWithOffset

Original host pointer event.

propertytarget: CellProperties | null

Hit-tested cell properties, or null when the pointer is not over a scene node.

propertyview: { x: number; y: number }

Pointer location relative to the rendered viewport.

propertyworld: { x: number; y: number }

Pointer location in scrollable sheet-world coordinates.

interfacePositionCursorRule

Cursor rule evaluated from the pointer location rather than a hit node. Higher layers win over lower layers and all structural cursor rules. When multiple matching rules share the highest layer, the last registered rule wins and CursorRegistry reports the ambiguous registration once.

propertycursor: CursorToken

Logical cursor presented while this rule owns the pointer.

propertykey: string | symbol

Stable owner key used for replacement, removal, and conflict diagnostics.

propertykind: "position"
propertylayer: number

Precedence among position rules; larger values take precedence.

propertytest: (position: CursorPosition): boolean

Returns whether this rule owns the supplied pointer location.

interfacePredicateCursorRule

Fully custom predicate rule.

priority: 'high' → evaluated before region/type rules (e.g., isEdit override). priority: 'low' → evaluated after region/type rules as a fallback (default).

propertycursor: CursorToken
propertykey?: string | symbol

Predicates need an explicit key to replace a previous predicate rule.

propertykind: "predicate"
propertypriority?: "high" | "low"
propertytest: (properties: CellProperties): boolean
interfaceRegionCursorRule

Exact region-match rule (highest priority among structural rules).

propertycursor: CursorToken
propertykey?: string | symbol

Optional extension key; defaults to the region identifier.

propertykind: "region"
propertyregion: CellRegion
interfaceTypeCursorRule

Type-field match rule (secondary match).

propertycellType: string | symbol
propertycursor: CursorToken
propertykey?: string | symbol

Optional extension key; defaults to the cell type.

propertykind: "type"
typeCursorRule
type CursorRule = RegionCursorRule | TypeCursorRule | PredicateCursorRule | PositionCursorRule
typeCursorToken
type CursorToken = typeof CursorToken[keyof typeof CursorToken] | string & { } CursorToken: { Cell: "cell"; ColumnResize: "col-resize"; ColumnSelect: "col-select"; Copy: "copy"; Default: "default"; Grab: "grab"; Grabbing: "grabbing"; Move: "move"; … }

Built-in tokens plus an extension point for third-party plugins.

variableCursorRuleKind
CursorRuleKind: { Position: "position"; Predicate: "predicate"; Region: "region"; Type: "type" }
variableCursorRulePriority
CursorRulePriority: { High: "high"; Low: "low" }