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

    Interface ActionExperimental

    Single registered action. v1: one binding per action.

    interface Action {
        activeCursor?: string;
        cursor?: string;
        defaultBinding?: GestureSpec | BoundGesture[];
        eligible?: Rule | Condition;
        enabled?: (deps?: ActionDeps) => true | ActionDisabledReason;
        group?: string;
        icon?: ReactNode | (() => ReactNode);
        id: string;
        invoker?: Invoker;
        label: string;
        requires?: readonly (keyof DepSchema)[];
        scope?: "hotkey";
        shortcut?: string;
    }
    Index

    Properties

    activeCursor?: string

    CSS cursor shown while THIS action's ongoing handle is in flight — grabbing while panning, move while dragging a selection, crosshair while pulling a marquee.

    Separate from cursor because the two answer different questions: cursor is a prediction ("a drag from here would pan"), this is a state ("you are panning"). An action can declare either, both, or neither; with only cursor set, the hover hint holds for the duration of the gesture.

    This is where mid-gesture cursors live now. They used to come from the tool side — ViewportToolDef.engaged.cursor for a phase-gated string, or a function-form Tool.cursor reading the gesture scratch out of the tool-routing dispatcher. Both belonged to a pipeline whose whole job was being taken over by bindings, and neither could describe a cursor for an action a tool doesn't own.

    cursor?: string

    CSS cursor shown while the pointer hovers a spot where this action would win the drag. The hover-cursor pump (in useGestureDispatcher) runs Dispatcher.resolveOnly on each idle pointermove — the same match walk a real pointerdown takes — and applies the winning action's cursor, so the hint and the actual click target stay in sync by construction. Omitted = no override (the active tool's Tool.cursor shows). Affordance hits are resolved earlier in the pump via AffordanceRegion.cursor and never reach this field.

    Static string only. Prediction runs enabled() but cannot run the invoker, so an action that matches yet bails at start() (empty handle) may still show its cursor — keep enabled accurate for actions that declare one.

    defaultBinding?: GestureSpec | BoundGesture[]

    The gesture-spec form of the binding, read by the gesture dispatcher. May be a single GestureSpec, a bare GestureSpec[] (any-of semantics), or a BoundGesture[] where each entry is either a bare GestureSpec or { spec, opts } — use the object form for parametric actions where two bindings for the same action differ only by opts.params (e.g. flip with axis: 'x' vs 'y'). The dispatcher extracts opts.params and passes them to ImmediateInvoker.run as its second argument.

    eligible?: Rule | Condition

    Declarative eligibility rule, evaluated against the current RuleCtx by the dispatcher before invoking start(). Omitted = always eligible.

    Accepts either a fluent Condition (callable with .rule) or a raw Rule tree; the dispatcher normalizes via .rule unwrap.

    Prefer capability:-based rules (e.g. { capability: 'transforms-selection' }) over mode: rules — capability rules survive new modes being added that allow the same capability.

    enabled?: (deps?: ActionDeps) => true | ActionDisabledReason

    Optional predicate the command palette consults when rendering. Return true when the action is currently triggerable. Return a reason string (e.g. 'Selection required') when disabled — the palette greys out the row, skips it in keyboard nav, ignores clicks, and shows the reason next to the label. Keystroke dispatch (the registered binding) is unaffected; the action's own run should self-guard.

    Contract: must be pure (no side effects), fast (< 4ms in dev), and must not throw. If a call throws or exceeds the budget in dev mode, evaluateEnabled logs a one-time warning per action id; throws are caught and treated as disabled with reason '(predicate threw)'.

    Snapshot-on-open semantics: the palette evaluates enabled once when opened and does NOT re-evaluate on selection changes while open. Live reactive updates are deferred — palette is short-lived.

    The reason set is a closed enum — to add a new reason, edit ActionDisabledReason and the consumer's display map.

    The optional deps argument is the same bag passed to ImmediateInvoker.run; callers (evaluateEnabled / the ActionBar) may synthesize it from the surrounding DepRegistry so predicates can inspect selection / scene / etc. Predicates that don't need deps just ignore the arg.

    group?: string

    Grouping key for palette/menu surfaces. Free-form string; the kit ships defaults for 'align' (six edges/centers), 'distribute' (two axes), and recommends 'pathfinder' for boolean ops.

    icon?: ReactNode | (() => ReactNode)

    Inline-SVG icon for palette / toolbar surfaces. Mirrors ToolPresentation.icon so a generic <ActionBar> can render from action metadata the same way <ToolPalette> renders from tool metadata. May be a static ReactNode or a function (rare; useful for state-aware icons like a "lock" toggle).

    id: string
    invoker?: Invoker

    Pluggable invocation strategy. The gesture dispatcher routes matched bindings through invoker.start / invoker.run depending on timing. All kit-standard descriptors ship one; consumer-supplied actions without an invoker can still register but won't be triggered.

    label: string
    requires?: readonly (keyof DepSchema)[]

    Names of the deps this action's invoker reads (keys of DepSchema). The dispatcher (and trigger, when requires is present) resolves each name against the DepRegistry at invocation time and passes the resulting bag to the invoker. Dev builds warn when the invoker reads a dep it didn't declare here — see buildDepsFromRequires.

    scope?: "hotkey"

    When set to 'hotkey', this action's defaultBinding rides the hotkey BindingScope instead of the ambient scope — meaning it beats any active-tool binding on the same input shape. Use for tool-switch shortcuts and global held-key triggers. Default: ambient.

    shortcut?: string

    Display override for the keyboard shortcut. When omitted, palette surfaces derive a label from defaultBinding via their own formatter.