UNPKG

@ue-too/board

Version:

<h1 align="center"> uē-tôo </h1> <p align="center"> pan, zoom, rotate, and more with your html canvas. </p>

199 lines (198 loc) 8.6 kB
import { KmtOutputEvent } from "./input-state-machine/kmt-input-state-machine"; import { TouchOutputEvent } from "./input-state-machine/touch-input-state-machine"; import { UserInputPublisher } from "./raw-input-publisher/raw-input-publisher"; import { CameraMux } from "../camera/camera-mux"; import { CameraRig } from "../camera/camera-rig"; /** * Union type of all output events from state machines. * * @remarks * This type represents the unified output from both KMT (Keyboard/Mouse/Trackpad) and Touch state machines. * By unifying these outputs, the orchestrator can handle events from different input modalities uniformly. * * @category Input Interpretation */ export type OutputEvent = KmtOutputEvent | TouchOutputEvent; /** * Central orchestrator that coordinates input interpretation and camera control for the infinite canvas. * * @remarks * The InputOrchestrator serves as the mediator between input state machines and camera control systems. * It implements a permission-based architecture where: * * 1. **Event Flow**: State machines produce high-level gesture events (pan, zoom, rotate) * 2. **Permission Check**: Events are sent to CameraMux for permission validation * 3. **Execution**: If allowed, gestures are executed on CameraRig * 4. **Broadcasting**: Raw events are simultaneously broadcast to observers via UserInputPublisher * * **Architecture Pattern**: * ``` * State Machines → Orchestrator → CameraMux (permission) → CameraRig (execution) * ↓ * UserInputPublisher (observers) * ``` * * This design decouples state machines from camera control, allowing state machines to focus solely * on gesture recognition while the orchestrator handles the complexities of camera coordination, * permission management, and event distribution. * * **Key Benefits**: * - Single point of control for all camera operations * - State machines remain unaware of camera implementation * - Parallel path for observers to react to raw input events * - Consistent handling of KMT and Touch input modalities * * @category Input Interpretation * * @example * ```typescript * // Create the orchestrator * const cameraMux = new CameraMux(); * const cameraRig = new CameraRig(camera, viewport); * const publisher = new RawUserInputPublisher(); * const orchestrator = new InputOrchestrator(cameraMux, cameraRig, publisher); * * // State machines send their output to the orchestrator * const kmtStateMachine = createKmtInputStateMachine(kmtContext); * const result = kmtStateMachine.happens("leftPointerMove", {x: 100, y: 200}); * orchestrator.processInputEventOutput(result.output); * * // Observers can subscribe to raw input events * publisher.on("pan", (event) => { * console.log("Pan gesture detected:", event.diff); * }); * ``` */ export declare class InputOrchestrator { private _cameraMux; private _cameraRig; private _publisher?; /** * Creates a new InputOrchestrator instance. * * @param cameraMux - The camera multiplexer that validates and controls camera operation permissions * @param cameraRig - The camera rig that executes camera transformations * @param publisher - Optional publisher for broadcasting raw input events to observers * * @remarks * The publisher parameter is optional to support scenarios where event broadcasting is not needed. * When provided, all input events are broadcast in parallel to camera control execution. */ constructor(cameraMux: CameraMux, cameraRig: CameraRig, publisher?: UserInputPublisher); /** * Processes output events from state machines and routes them to camera control and observers. * * @param output - The output from a state machine, can be a single event, array of events, or any value * * @remarks * This method serves as the main entry point for state machine outputs. It: * 1. Validates whether the output is a valid OutputEvent * 2. Handles both single events and arrays of events * 3. Routes each valid event through the camera control pipeline * 4. Broadcasts events to observers via the publisher * * Called by event parsers after the state machine processes an input and produces output. * The method uses type guards to ensure type safety when handling dynamic output types. * * @example * ```typescript * const result = stateMachine.happens("scroll", {deltaX: 0, deltaY: 10, x: 100, y: 200}); * orchestrator.processInputEventOutput(result.output); * ``` */ processInputEventOutput(output: any): void; processInputEvent(input: OutputEvent): void; /** * Type guard to check if an output value is a valid OutputEvent. * * @param output - The value to check * @returns True if the output is a valid OutputEvent with a type property * * @remarks * This type guard ensures type safety when processing state machine outputs. * It checks for the presence of a 'type' property which is common to all OutputEvent variants. */ private isOutputEvent; /** * Handles individual output events from state machines by routing to camera control and observers. * * @param event - The output event from a state machine (pan, zoom, rotate, cursor, or none) * * @remarks * This method implements a dual-path architecture: * * **Parallel Path 1 - Observer Notification**: * - Immediately broadcasts the event to all subscribers via UserInputPublisher * - This allows external systems to react to user input in real-time * - Independent of camera permission/execution * * **Parallel Path 2 - Camera Control**: * - Requests permission from CameraMux for the operation * - CameraMux may modify the event (e.g., clamp values, deny operation) * - If permitted, executes the transformation on CameraRig * * Event types: * - **pan**: Translates the camera viewport * - **zoom**: Scales the camera around an anchor point * - **rotate**: Rotates the camera view * - **cursor**: Changes cursor appearance (handled by state machine) * - **none**: No operation needed */ private handleStateMachineOutput; /** * Processes pan output from CameraMux and executes the pan operation if permitted. * * @param output - The pan output from CameraMux containing permission and potentially modified delta * * @remarks * CameraMux may deny the operation (allowPassThrough = false) or modify the delta value * to enforce constraints like viewport bounds or animation states. * Only when permission is granted does the pan execute on CameraRig. */ private processPanMuxOutput; /** * Processes zoom output from CameraMux and executes the zoom operation if permitted. * * @param output - The zoom output from CameraMux containing permission and potentially modified parameters * * @remarks * CameraMux may deny the operation or modify zoom parameters to enforce constraints * like minimum/maximum zoom levels or animation states. The anchor point determines * the center of the zoom transformation in viewport coordinates. */ private processZoomMuxOutput; /** * Processes rotation output from CameraMux and executes the rotation operation if permitted. * * @param output - The rotation output from CameraMux containing permission and potentially modified delta * * @remarks * CameraMux may deny the operation or modify the rotation delta to enforce constraints * like rotation limits or animation states. */ private processRotateMuxOutput; /** * Gets the UserInputPublisher for direct access to event subscription. * * @returns The publisher instance, or undefined if not configured * * @remarks * Allows external code to subscribe to raw input events without going through the orchestrator. */ get publisher(): UserInputPublisher | undefined; /** * Gets the CameraMux instance for direct access to permission control. * * @returns The camera multiplexer instance */ get cameraMux(): CameraMux; /** * Sets a new CameraMux instance. * * @param cameraMux - The new camera multiplexer to use for permission control * * @remarks * Allows dynamic reconfiguration of camera permission logic at runtime. */ set cameraMux(cameraMux: CameraMux); }