weasel API - v0.8.0
    Preparing search index...

    Interface CanvasHelpers<TPose>

    Live overlay-aware lookups exposed to custom layers via helpersRef.

    interface CanvasHelpers<TPose> {
        getChromeState(): ChromeState;
        getDebug(): DebugSink | null;
        getEffectiveBounds(id: string): Bounds | null;
        getEffectivePose(id: string): TPose | null;
        getGestureBounds(): Bounds | null;
        getGestureVersion(): number;
        getIsVisible(): (id: string) => boolean;
        subscribeGestures(fn: () => void): () => void;
    }

    Type Parameters

    • TPose
    Index

    Methods

    • Active debug sink, when <Canvas debug=...> is enabled. Layers that want to participate in hitboxes/bounds/etc. visualization can call into this from their draw callback. Returns null when debug is off — no-op for production renders.

      Returns DebugSink | null

    • Pose currently displayed for id — drag/resize/rotate overlay if active, otherwise the committed pose from the adapter. Returns null if the id isn't known.

      Parameters

      • id: string

      Returns TPose | null

    • World-space AABB of everything the in-flight gesture proposes — the displaced poses of nodes being moved / resized / rotated / cloned, plus any nascent insert that has no scene node yet. null when no gesture is in flight.

      This reports the gesture, not the document: committed content the gesture isn't touching is excluded, so a consumer that wants the union with the rest of the scene still walks its own ids through getEffectiveBounds. It exists because every other lookup here is keyed by node id, which can't answer "where is the shape the user is drawing right now" — a drag-to-insert has no id until pointer-up.

      Select-only gestures are deliberately excluded: a marquee or lasso has geometry but proposes no content, and a consumer sizing itself to the gesture must not grow because the user swept a selection rectangle.

      The result is a plain AABB — never rotated. Rotated parts are folded in by their rotated extent (a union of several oriented boxes has no single orientation to report).

      Returns Bounds | null

    • Monotonic counter bumped on exactly the events subscribeGestures fires on. Pair the two for useSyncExternalStore:

      const gestureVersion = useSyncExternalStore(
      useCallback((cb) => helpersRef.current?.subscribeGestures(cb) ?? (() => {}), []),
      () => helpersRef.current?.getGestureVersion() ?? 0,
      );

      Starts at 0 and only increases. 0 is also what a bare <Canvas> with no gesture source reports, forever.

      Returns number

    • Chrome-caps visibility predicate, keyed by chrome id. Returns a function that affordance/overlay layers can call per-element to decide whether to draw / hit-test. When the parent didn't supply a resolver, this returns the universal () => true.

      Returns (id: string) => boolean

    • Subscribe to the gesture layer's change signal — the other half of the useSyncExternalStore contract for everything on this object that moves during a drag (getEffectivePose, getEffectiveBounds, getGestureBounds). Returns an unsubscribe.

      Fires once per dispatcher pump: gesture start, every pointermove that reaches an in-flight handle, end, and cancel — plus UI-driven ongoing actions (a slider bound to an ongoing action pumps the same way). It fires on the pump, not on a diff: a pump that changed nothing observable still notifies, so don't hang expensive work directly off the callback.

      It does not cover committed scene edits (subscribe to the scene for those) or previews a consumer's own tool publishes from React state (that tool re-renders on its own).

      Without a gesture source wired — a bare <Canvas> — this is a no-op subscription that never fires.

      Parameters

      • fn: () => void

      Returns () => void