import type { InteractionMode, StandardModeAction, Suppression, VerbEvent } from './interaction-mode.js'; /** The seven portable interaction forms owned by the universal surface. */ export type ActionSurfaceKind = 'run' | 'choice' | 'number' | 'text' | 'point' | 'asset' | 'takeover'; export interface ActionSurfaceOption { value: string; label: string; disabled?: boolean; reason?: string; } /** * Provenance for authority-resolved options. The presentation surface never * executes these queries; it receives their filtered `options` result. */ export interface ActionSurfaceOptionsFrom { query?: { has: string; scope?: 'room' | 'world'; }; inventory?: { accepts: string; }; var?: string; } export interface ActionSurfaceAvailability { state: 'available' | 'busy' | 'occupied'; /** Player-readable state such as "In use by Mira". Never render an internal id. */ label?: string; } /** * A caller-scoped, authority-resolved row. * * Dynamic labels and enabled/visible expressions are evaluated before this * value reaches the SDK. This list is an advisory presentation cache: every * invocation must be re-authorized by the authority. */ export interface ActionSurfaceAction { id: string; label: string; kind: ActionSurfaceKind; call?: string; socket?: string; enabled?: boolean; visible?: boolean; reason?: string; availability?: ActionSurfaceAvailability; /** `number` and picker actions: the current authoritative value. */ value?: number | string | null; /** `number`: the authority-backed variable this row writes. */ var?: string; min?: number; max?: number; step?: number; unit?: string; /** `text`: native text-entry hints. Authority still validates submitted text. */ placeholder?: string; maxLength?: number; inputMode?: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search'; /** `choice` or `asset`: caller-filtered concrete choices. */ options?: readonly ActionSurfaceOption[]; /** Describes where the authority obtained `options`; never resolved here. */ optionsFrom?: ActionSurfaceOptionsFrom; } export interface ActionSurfaceSnapshot { instanceId: string; title: string; actions: readonly ActionSurfaceAction[]; availability?: ActionSurfaceAvailability; } export type ActionSurfaceInvocation = { action: ActionSurfaceAction; kind: 'run' | 'point' | 'takeover'; } | { action: ActionSurfaceAction; kind: 'number'; value: number; } | { action: ActionSurfaceAction; kind: 'choice' | 'asset' | 'text'; value: string; }; export type ActionSurfaceDevice = 'keyboard' | 'gamepad' | 'touch'; /** Adapter over the trusted router's active-device and `hint()` surfaces. */ export interface ActionSurfaceHintSource { activeDevice(): ActionSurfaceDevice; hint(action: Extract): string; /** Optional active-device/rebind subscription. */ subscribe?(listener: () => void): () => void; } export interface UniversalActionSurfaceOptions { host: HTMLElement; hints: ActionSurfaceHintSource; onInvoke(invocation: ActionSurfaceInvocation): void; onDismiss?(instanceId: string): void; onOpenChange?(open: boolean): void; document?: Document; /** @deprecated Navigation cadence is owned by the trusted mode host. Retained for source compatibility. */ now?(): number; } /** Fail-fast validation for the trusted host-to-presentation boundary. */ export declare function validateActionSurfaceSnapshot(snapshot: ActionSurfaceSnapshot): string[]; /** * Portable DOM component for a proximity/list presentation. * * It installs no keyboard, pointer-lock, gamepad, or raw touch listeners. A * trusted mode host delivers the three semantic actions through `handleVerb`, * while ordinary DOM activation keeps the rendered controls accessible. */ export declare class UniversalActionSurface { #private; readonly element: HTMLElement; constructor(options: UniversalActionSurfaceOptions); get isOpen(): boolean; get instanceId(): string | null; get mode(): 'browse' | 'number' | 'text' | 'picker'; get selectedAction(): ActionSurfaceAction | null; get visibleActions(): readonly ActionSurfaceAction[]; get liveNumber(): number | null; get liveText(): string | null; /** Open or refresh the caller-scoped cache. Pass null to withdraw it. */ setSnapshot(snapshot: ActionSurfaceSnapshot | null): void; hide(): void; /** Dismiss this proximity offer until the host explicitly rearms it. */ dismiss(): void; rearm(): void; /** Refresh active-device/rebind text when the router has no subscription API. */ refreshHints(): void; /** * Record pointer input that reaches the host's opener before this surface. * This keeps the first rendered hints aligned with the input that opened it. */ observePointer(pointerType: string): void; /** Navigate one row/option or nudge a sustained number. */ move(delta: -1 | 1): void; confirm(): void; /** Back out of a sustained control; dismiss the proximity list at root. */ cancel(): void; /** Release modal focus without dismissing the still-valid proximity offer. */ endEngagement(): void; /** Semantic input entry point used by `createActionSurfaceMode`. */ handleVerb(verb: 'navigate' | 'activate' | 'back', event: VerbEvent): void; dispose(): void; } export interface ActionSurfaceModeOptions { surface: UniversalActionSurface; id?: string; suppression?: Suppression; } /** Fresh semantic map so hosts may safely decorate it per instance. */ export declare function createActionSurfaceInputMap(): { navigate: { action: "move"; label: string; touch: { kind: "stick"; zone: "left"; }; continuous: boolean; repeatMs: number; }; activate: { action: "primary"; label: string; touch: { kind: "tap"; zone: "primary"; }; }; back: { action: "cancel"; label: string; touch: { kind: "button"; zone: "secondary"; }; }; }; /** * Opt-in engaged menu mode. Showing a proximity offer alone must not push it: * callers engage explicitly, so merely walking near an item never captures the * player. The mode uses the same stack/lease as every takeover. */ export declare function createActionSurfaceMode(options: ActionSurfaceModeOptions): InteractionMode;