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

    Interface AffordanceRegion<TScratch>Experimental

    One interactive region produced by an affordance. The framework owns the local↔world transform for targetId (when non-null), so shape, paint.sizePx, and hitRadiusPx are always specified in coordinates the affordance can reason about directly.

    interface AffordanceRegion<TScratch = unknown> {
        cursor?: string;
        hitKind?: string;
        id: string;
        paint?:
            | { fill?: FillStyle; kind: "square"; sizePx: number; stroke?: Stroke }
            | { fill?: FillStyle; insetPx?: number; kind: "annulus"; stroke?: Stroke }
            | { draw: (ctx: CustomPaintContext) => DrawCommand[]; kind: "custom" };
        shape:
            | { hitRadiusPx: number; kind: "point"; x: number; y: number }
            | { height: number; kind: "rect"; width: number; x: number; y: number }
            | {
                cx: number;
                cy: number;
                innerHeight: number;
                innerWidth: number;
                innerX: number;
                innerY: number;
                kind: "annulus";
                minBandPx?: number;
                rx: number;
                ry: number;
            };
        targetId: string
        | null;
        bind(): AffordanceBinding<TScratch>;
    }

    Type Parameters

    • TScratch = unknown
    Index

    Properties

    cursor?: string

    CSS cursor to show while hovering this region. Read by the hover-cursor pump in useGestureDispatcher via AffordanceHit.cursor, which buildAffordanceAt fills in from the region the walk landed on.

    hitKind?: string

    Discriminator a press on this region reports as AffordanceHit.kind — the string routing specs match on ('handle:top-left', 'rotate-handle', 'anchor:3'). Omit for regions that only exist inside a consumer-registered layer, where the layer id is the discriminator; buildAffordanceAt falls back to <affordanceId>:<regionId>.

    id: string

    Stable id, e.g. corner-min-min. Used for debug overlays + a11y.

    paint?:
        | { fill?: FillStyle; kind: "square"; sizePx: number; stroke?: Stroke }
        | { fill?: FillStyle; insetPx?: number; kind: "annulus"; stroke?: Stroke }
        | { draw: (ctx: CustomPaintContext) => DrawCommand[]; kind: "custom" }

    Optional paint. World position is derived from shape + target transform; visual size stays in screen pixels (so handles don't warp under zoom or non-uniform scale). Omit for hit-only regions.

    • square — small fixed-size square (only valid over point shapes).
    • annulus — fill + stroke the annulus ring (only valid over annulus shapes). Uses even-odd fill rule to punch the inner-rect cutout.
    • custom — emit arbitrary draw commands; receives a CustomPaintContext.
    shape:
        | { hitRadiusPx: number; kind: "point"; x: number; y: number }
        | { height: number; kind: "rect"; width: number; x: number; y: number }
        | {
            cx: number;
            cy: number;
            innerHeight: number;
            innerWidth: number;
            innerX: number;
            innerY: number;
            kind: "annulus";
            minBandPx?: number;
            rx: number;
            ry: number;
        }

    Region geometry, expressed in the target's local frame.

    • point — circular hit (hitRadiusPx is screen-space).
    • rect — axis-aligned rect (target rotation applies).
    • annulus — outer ellipse minus inner rect cutout. Used for invisible zones that sit around the AABB (e.g. rotate-on- hover band). The outer ellipse is defined by world-space semi-axes rx / ry around (cx, cy); the inner rect is the same target-local rect that defines the AABB. Hit-test: inside outer ellipse AND outside inner rect.

    Type Declaration

    • { hitRadiusPx: number; kind: "point"; x: number; y: number }
    • { height: number; kind: "rect"; width: number; x: number; y: number }
    • {
          cx: number;
          cy: number;
          innerHeight: number;
          innerWidth: number;
          innerX: number;
          innerY: number;
          kind: "annulus";
          minBandPx?: number;
          rx: number;
          ry: number;
      }
      • cx: number

        Outer-ellipse center (target-local).

      • cy: number
      • innerHeight: number
      • innerWidth: number
      • innerX: number

        Inner rect (target-local) — the cutout. Typically the selection's AABB.

      • innerY: number
      • kind: "annulus"
      • OptionalminBandPx?: number

        Minimum band thickness outside the inner rect, in screen pixels. The framework widens rx/ry to at least innerHalfExtent + minBandPx / meanScale(view.scale) for both paint and hit-test.

        This exists because the clamp has to know the view and the affordance doesn't: ChromeState carries no scale. Expressing the floor in world units instead (which is what the rotate ring used to do) makes the band shrink on screen as you zoom in, until the ring around a small shape is too thin to hover.

      • rx: number

        Outer-ellipse semi-axes (target-local).

      • ry: number
    targetId: string | null

    Target id whose state.boundsOf(targetId) defines this region's local frame. bounds.rotation (if present) is the only transform applied — translation is the AABB origin; scale is identity. Pass null for affordances anchored to the viewport / world frame (identity transform).

    Methods