UNPKG

react-command-flow

Version:

A beautiful interactive CLI-style command interface for React apps

337 lines (336 loc) 12.5 kB
/** * Type definitions for React Command Flow */ /** * Session data that persists throughout command execution * Keys are either field names or step indices (step0, step1, etc.) */ export interface SessionData { [key: string]: any; } /** * Configuration for a single step in a command flow */ export interface CommandStep { /** * Text displayed at the start of the step * Can be a static string or a function that receives session data and callbacks */ intro?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>); /** * Text displayed at the end of the step (after user input or auto-advance) * Can be a static string or a function that receives input, session data, and callbacks */ outro?: string | ((input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>); /** * Prompt text asking for user input * Can be a static string or a function that receives session data and callbacks * If omitted and skipToNext is true, step will auto-advance */ prompt?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>); /** * Field name to store the user's input in sessionData * If provided, input will be stored as sessionData[field] * If omitted, input is stored as sessionData[`step${index}`] */ field?: string; /** * Handler function called when user submits input for this step * Return value should be an object that will be merged into sessionData * Can be async for API calls or delayed processing * * Note: For display output, use the `outro` property instead * * @param input - The user's input string (null for auto-advance steps) * @param sessionData - Current session data * @param callbacks - Callback trigger functions * @returns Object to merge into sessionData, or empty object */ onStep?: (input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => Record<string, any> | Promise<Record<string, any>>; /** * Validation function to check user input before processing * Return true/false for simple validation, or a string error message for custom errors * * @param input - The user's input string * @param sessionData - Current session data * @param callbacks - Callback trigger functions * @returns true if valid, false or error message string if invalid */ validate?: (input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => boolean | string | Promise<boolean | string>; /** * Custom validation error message * Shown when validate returns false * Can be a static string or function */ validationMessage?: string | ((input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => string); /** * Redirect to another command after this step completes * Return the command name to redirect to * * @param input - The user's input for this step * @param sessionData - Current session data * @param callbacks - Callback trigger functions * @returns Name of the command to redirect to */ redirect?: (input: string, sessionData: SessionData, callbacks?: CallbackTriggers) => string; /** * If true, this step will auto-advance without waiting for user input * Useful for displaying information or processing data between prompts */ skipToNext?: boolean; /** * Dynamically skip this step based on session data. * If the function returns true, the step is skipped entirely * and the engine advances to the next step. * * @param sessionData - Current session data * @returns true to skip this step, false to execute normally */ skipIf?: (sessionData: SessionData) => boolean | Promise<boolean>; } /** * Configuration for a complete command */ export interface Command { /** * Description of the command (shown in help menu) */ description?: string; /** * Text displayed when the command starts (before any steps) * Can be a static string or a function that receives session data and callbacks */ intro?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>); /** * Text displayed when the command completes (after all steps) * Can be a static string or a function that receives session data and callbacks */ outro?: string | ((sessionData: SessionData, callbacks?: CallbackTriggers) => string | Promise<string>); /** * Array of steps that make up the command flow * Steps are executed in order * Can be empty for simple commands with just intro/outro */ steps?: CommandStep[]; /** * Handler function called when all steps complete * Return value is displayed as output * Can be async for final API calls or data processing * * @param sessionData - Complete session data from all steps * @param callbacks - Callback trigger functions * @returns Final output text to display */ onComplete?: (sessionData: SessionData, callbacks?: CallbackTriggers) => any | Promise<any>; /** * Redirect to another command after completion * Return the command name to redirect to * * @param sessionData - Complete session data * @param callbacks - Callback trigger functions * @returns Name of the command to redirect to */ redirect?: (sessionData: SessionData, callbacks?: CallbackTriggers) => string; } /** * Collection of all available commands * Key is the command name, value is the command configuration */ export interface Commands { [commandName: string]: Command; } /** * Custom translations for UI text */ export interface Translations { unknownCommand?: string; typeHelpForHelp?: string; availableCommands?: string; noDescription?: string; validationError?: string; loading?: string; [key: string]: string | undefined; } /** * Theme configuration for terminal styling */ export interface Theme { fontFamily?: string; fontSize?: string; backgroundColor?: string; textColor?: string; promptColor?: string; inputColor?: string; outputColor?: string; errorColor?: string; successColor?: string; [key: string]: string | undefined; } /** * Custom callback function that can be triggered from within commands */ export interface CustomCallback { (data: any, context: CallbackContext): any | Promise<any>; } /** * Context information passed to custom callbacks */ export interface CallbackContext { commandName: string; sessionData: SessionData; timestamp: string; engine?: any; } /** * Collection of custom callbacks that can be triggered from commands */ export interface CustomCallbacks { [callbackName: string]: CustomCallback; } /** * Callback trigger functions injected into commands * These allow commands to invoke registered callbacks */ export interface CallbackTriggers { /** * Fire a callback (fire and forget) * @param callbackName - Name of the callback to trigger * @param data - Data to pass to the callback */ fire: (callbackName: string, data?: any) => Promise<any>; /** * Call a callback and await the response * @param callbackName - Name of the callback to trigger * @param data - Data to pass to the callback */ call: (callbackName: string, data?: any) => Promise<any>; /** * Fire multiple callbacks in sequence * @param callbackNames - Array of callback names * @param data - Data to pass to each callback */ fireMultiple: (callbackNames: string[], data?: any) => Promise<any[]>; /** * Conditionally fire a callback * @param condition - Whether to fire the callback * @param callbackName - Name of the callback to trigger * @param data - Data to pass to the callback */ fireIf: (condition: boolean, callbackName: string, data?: any) => Promise<any>; /** * Fire a callback with transformed data * @param callbackName - Name of the callback to trigger * @param dataTransformer - Function or value to transform data */ fireWith: (callbackName: string, dataTransformer: any | ((context: CallbackContext) => any)) => Promise<any>; } /** * Props for the CommandLine component */ export interface CommandLineProps { /** * Commands configuration object */ commands: Commands; /** * Custom translations for UI text */ translations?: Translations; /** * Theme configuration for styling */ theme?: Theme; /** * Delay for system output in milliseconds (default: 800) */ outputDelay?: number; /** * Delay before prompt appears after output in milliseconds (default: 300) */ promptDelay?: number; /** * Typing speed in milliseconds between characters (default: 300) */ typingSpeed?: number; /** * Height of the terminal container (default: "500px") */ height?: string; /** * Whether to display the terminal (default: true) */ display?: boolean; /** * Opacity of the terminal (default: 1) */ opacity?: number; /** * CSS transition string (default: "opacity 0.3s ease, height 0.6s ease") */ transition?: string; /** * Prompt label character (default: ">") */ promptLabel?: string; /** * Custom callbacks that can be triggered from within command steps * Each callback receives data and context information */ callbacks?: CustomCallbacks; /** * Called when a command completes execution * @param commandName - Name of the completed command * @param sessionData - Final session data from the command */ onCommandComplete?: (commandName: string, sessionData: SessionData) => void; /** * Called when a command session begins — i.e. the user typed a command * that has prompted steps and the engine has set up the first prompt. * Fires once per command session, NOT once per step (use `onStepStart` for * per-step events). Does not fire for commands without prompts (e.g. `help`) * since those complete synchronously without entering a session. * * @param commandName - Name of the command that just started * @param sessionData - Initial session data */ onCommandStart?: (commandName: string, sessionData: SessionData) => void; /** * Called when the user aborts an in-progress command via `exit` or one of * its aliases (`cancel`, `quit`, `ώπα`). Semantically: "I'm quitting this * command". * * Always fires when the exit keyword is recognized — the session always * ends in this case. * * @param commandName - Name of the command that was active at abort time * @param sessionData - Session data at the time of abort */ onCommandAbort?: (commandName: string, sessionData: SessionData) => void; /** * Called when the user types `back` (or `πίσω`) inside a command flow. * Semantically: "go back" — a navigation action. * * Fires on EVERY back keystroke regardless of what happens next: * - back at first step + non-empty redirect chain (re-enters parent umbrella) * - back at first step + empty chain (ends the session) * - back mid-flow (pops one step, session continues) * * @param commandName - Name of the command that was active when back was pressed * @param sessionData - Session data at the time of the back action */ onCommandBack?: (commandName: string, sessionData: SessionData) => void; /** * Called when a step starts execution * @param commandName - Name of the command * @param stepIndex - Index of the step that started * @param sessionData - Current session data */ onStepStart?: (commandName: string, stepIndex: number, sessionData: SessionData) => void; /** * Called when a step completes execution * @param commandName - Name of the command * @param stepIndex - Index of the step that completed * @param sessionData - Current session data */ onStepComplete?: (commandName: string, stepIndex: number, sessionData: SessionData) => void; }