export interface BaseContext { setup(): void; cleanup(): void; } type NOOP = () => void; export declare const NO_OP: NOOP; /** * @description This is the interface for the state machine. The interface takes in a few generic parameters. * * Generic parameters: * - EventPayloadMapping: A mapping of events to their payloads. * - Context: The context of the state machine. (which can be used by each state to do calculations that would persist across states) * - States: All of the possible states that the state machine can be in. e.g. a string literal union like "IDLE" | "SELECTING" | "PAN" | "ZOOM" * * You can probably get by using the TemplateStateMachine class. * The naming is that an event would "happen" and the state of the state machine would "handle" it. * * @see {@link TemplateStateMachine} * @see {@link KmtInputStateMachine} * * @category being */ export interface StateMachine { switchTo(state: States): void; happens(event: K, payload: EventPayloadMapping[K]): States | undefined; setContext(context: Context): void; states: Record>; onStateChange(callback: StateChangeCallback): void; possibleStates: States[]; onHappens(callback: (event: keyof EventPayloadMapping, payload: EventPayloadMapping[keyof EventPayloadMapping], context: Context) => void): void; } /** * @description This is the type for the callback that is called when the state changes. * * @category being */ export type StateChangeCallback = (currentState: States, nextState: States) => void; /** * @description This is the interface for the state. The interface takes in a few generic parameters: * You can probably get by extending the TemplateState class. * * Generic parameters: * - EventPayloadMapping: A mapping of events to their payloads. * - Context: The context of the state machine. (which can be used by each state to do calculations that would persist across states) * - States: All of the possible states that the state machine can be in. e.g. a string literal union like "IDLE" | "SELECTING" | "PAN" | "ZOOM" * * A state's all possible states can be only a subset of the possible states of the state machine. (a state only needs to know what states it can transition to) * This allows for a state to be reusable across different state machines. * * @see {@link TemplateState} * * @category being */ export interface State { uponEnter(context: Context, stateMachine: StateMachine, from: States): void; beforeExit(context: Context, stateMachine: StateMachine, to: States): void; handles>(event: K, payload: EventPayloadMapping[K], context: Context, stateMachine: StateMachine): States | undefined; eventReactions: EventReactions; guards: Guard; eventGuards: Partial>>; delay: Delay | undefined; } /** * @description This is the type for the event reactions of a state. * * Generic parameters: * - EventPayloadMapping: A mapping of events to their payloads. * - Context: The context of the state machine. (which can be used by each state to do calculations that would persist across states) * - States: All of the possible states that the state machine can be in. e.g. a string literal union like "IDLE" | "SELECTING" | "PAN" | "ZOOM" * * @category being */ export type EventReactions = { [K in keyof Partial]: { action: (context: Context, event: EventPayloadMapping[K], stateMachine: StateMachine) => void; defaultTargetState: States; }; }; /** * @description This is the type for the guard evaluation when a state transition is happening. * * Guard evaluations are evaluated after the state has handled the event with the action. * Guard evaluations can be defined in an array and the first guard that evaluates to true will be used to determine the next state. * * Generic parameters: * - Context: The context of the state machine. (which can be used by each state to do calculations that would persist across states) * * @category being */ export type GuardEvaluation = (context: Context) => boolean; /** * @description This is the type for the guard of a state. * * guard is an object that maps a key to a guard evaluation. * K is all the possible keys that can be used to evaluate the guard. * K is optional but if it is not provided, typescript won't be able to type guard in the EventGuards type. * * @category being */ export type Guard = { [P in K]: GuardEvaluation; }; export type Action = { action: (context: Context, event: EventPayloadMapping[keyof EventPayloadMapping], stateMachine: StateMachine) => void; defaultTargetState: States; }; export type Delay = { time: number; action: Action; }; /** * @description This is a mapping of a guard to a target state. * * Generic parameters: * - Context: The context of the state machine. (which can be used by each state to do calculations that would persist across states) * - G: The guard type. * - States: All of the possible states that the state machine can be in. e.g. a string literal union like "IDLE" | "SELECTING" | "PAN" | "ZOOM" * * You probably don't need to use this type directly. * * @see {@link TemplateState['eventGuards']} * * @category being */ export type GuardMapping = { guard: G extends Guard ? K : never; target: States; }; /** * @description This is a mapping of an event to a guard evaluation. * * Generic parameters: * - EventPayloadMapping: A mapping of events to their payloads. * - States: All of the possible states that the state machine can be in. e.g. a string literal union like "IDLE" | "SELECTING" | "PAN" | "ZOOM" * - Context: The context of the state machine. (which can be used by each state to do calculations that would persist across states) * - T: The guard type. * * You probably don't need to use this type directly. * This is a mapping of an event to a guard evaluation. * * @see {@link TemplateState['eventGuards']} * * @category being */ export type EventGuards> = { [K in keyof EventPayloadMapping]: GuardMapping[]; }; /** * @description This is the template for the state machine. * * You can use this class to create a state machine. Usually this is all you need for the state machine. Unless you need extra functionality. * To create a state machine, just instantiate this class and pass in the states, initial state and context. * * @see {@link createKmtInputStateMachine} for an example of how to create a state machine. * * @category being */ export declare class TemplateStateMachine implements StateMachine { protected _currentState: States; protected _states: Record>; protected _context: Context; protected _statesArray: States[]; protected _stateChangeCallbacks: StateChangeCallback[]; protected _happensCallbacks: ((event: keyof EventPayloadMapping, payload: EventPayloadMapping[keyof EventPayloadMapping], context: Context) => void)[]; protected _timeouts: ReturnType | undefined; constructor(states: Record>, initialState: States, context: Context); switchTo(state: States): void; happens(event: K, payload: EventPayloadMapping[K]): States | undefined; onStateChange(callback: StateChangeCallback): void; onHappens(callback: (event: keyof EventPayloadMapping, payload: EventPayloadMapping[keyof EventPayloadMapping], context: Context) => void): void; get currentState(): States; setContext(context: Context): void; get possibleStates(): States[]; get states(): Record>; } /** * @description This is the template for the state. * * This is a base template that you can extend to create a state. * Unlike the TemplateStateMachine, this class is abstract. You need to implement the specific methods that you need. * The core part off the state is the event reactions in which you would define how to handle each event in a state. * You can define an eventReactions object that maps only the events that you need. If this state does not need to handle a specific event, you can just not define it in the eventReactions object. * * @category being */ export declare abstract class TemplateState implements State { abstract eventReactions: EventReactions; protected _guards: Guard; protected _eventGuards: Partial>>; protected _delay: Delay | undefined; get guards(): Guard; get eventGuards(): Partial>>; get delay(): Delay | undefined; uponEnter(context: Context, stateMachine: StateMachine, from: States): void; beforeExit(context: Context, stateMachine: StateMachine, to: States): void; handles(event: K, payload: EventPayloadMapping[K], context: Context, stateMachine: StateMachine): States | undefined; } export {};