import * as jotai from 'jotai'; import { Getter, Setter } from 'jotai'; import * as react_jsx_runtime from 'react/jsx-runtime'; import React from 'react'; import * as jotai_utils from 'jotai/utils'; /** * Core types for @blinksgg/canvas */ /** * JSON type compatible with Supabase's generated types. * This allows the package to work with database JSONB fields. */ type Json = string | number | boolean | null | { [key: string]: Json | undefined; } | Json[]; type NodeId = string; interface NodePosition { x: number; y: number; } /** * Database node record - the shape of node data from your database. * Uses Json type for JSONB fields to be compatible with Supabase's generated types. */ interface DBGraphNode { id: string; graph_id: string; label: string | null; node_type: string | null; configuration: Json | null; ui_properties: Json | null; /** App-specific customization data */ data?: Json | null; created_at: string; updated_at: string; } /** * Graph node attributes stored in Graphology */ interface GraphNodeAttributes { x: number; y: number; size: number; width: number; height: number; color: string; label?: string; zIndex: number; dbData: DBGraphNode; /** Parent group node ID (for nested grouping) */ parentId?: string; } /** * Complete UI node state for rendering */ interface UINodeState extends GraphNodeAttributes { id: NodeId; position: NodePosition; isDragging: boolean; } /** * Command System Types * * Type definitions for the command palette system. * The command system provides a way to execute commands with * sequential input collection and visual feedback. */ /** * Input types supported by the command system. * Each type determines how the input is collected from the user. */ type InputType = 'text' | 'number' | 'point' | 'node' | 'nodes' | 'edge' | 'select' | 'boolean' | 'color'; /** * A selectable option for 'select' type inputs. */ type SelectOption = { /** Display label for the option */ label: string; /** Value to use when selected */ value: string; /** Single key shortcut (e.g., 'w' for widget) */ shortcut: string; /** Optional description shown on hover */ description?: string; }; /** * Definition for a single input prompt in a command. */ type InputDefinition = { /** Parameter name (used as key in collected inputs) */ name: string; /** Type of input to collect */ type: InputType; /** Displayed prompt text */ prompt: string; /** Whether this input is required (default: true) */ required?: boolean; /** Default value if skipped or not provided */ default?: unknown; /** Options for 'select' type */ options?: SelectOption[]; /** Min value for 'number' type */ min?: number; /** Max value for 'number' type */ max?: number; /** Snap to grid for 'point' type */ snapToGrid?: boolean; /** Validation function - returns true or error message */ validate?: (value: unknown, collected: Record) => boolean | string; /** Filter function for node/edge picking */ filter?: (item: UINodeState, collected: Record) => boolean; }; type Point = { x: number; y: number; }; /** * Visual feedback to show on the canvas during input collection. */ type CommandFeedback = { /** Node to highlight */ highlightNodeId?: string; /** Preview edge to draw */ previewEdge?: { from: Point; toCursor: boolean; } | { from: Point; to: Point; }; /** Ghost node following cursor */ ghostNode?: { position: Point; opacity: number; }; /** Show crosshair at cursor */ crosshair?: boolean; }; /** * Payload for creating a new node. */ type CreateNodePayload = { graph_id: string; node_type: string; label?: string; configuration?: Record; ui_properties?: Record; }; /** * Payload for creating a new edge. */ type CreateEdgePayload = { graph_id: string; source_node_id: string; target_node_id: string; edge_type?: string; ui_properties?: Record; }; /** * Context passed to command execute() function. * Provides access to state, mutations, and current graph context. */ type CommandContext = { /** Jotai getter for reading atoms */ get: Getter; /** Jotai setter for writing atoms */ set: Setter; /** Current graph ID */ currentGraphId: string | null; /** Set of currently selected node IDs */ selectedNodeIds: Set; /** Current viewport state */ viewport: { zoom: number; pan: { x: number; y: number; }; }; /** Pre-bound mutation functions (provided by app) */ mutations: { createNode: (payload: CreateNodePayload) => Promise; updateNode: (nodeId: string, updates: Record) => Promise; deleteNode: (nodeId: string) => Promise; createEdge: (payload: CreateEdgePayload) => Promise; deleteEdge: (edgeId: string) => Promise; }; /** Layout functions */ layout: { fitToBounds: (mode: 'graph' | 'selection', padding?: number) => void; applyForceLayout: () => Promise; applyTreeLayout: (opts?: { direction?: 'top-down' | 'left-right'; }) => Promise; applyGridLayout: (opts?: { columns?: number; }) => Promise; }; /** History functions */ history: { undo: () => void; redo: () => void; }; }; /** * Category for organizing commands. */ type CommandCategory = 'nodes' | 'edges' | 'viewport' | 'selection' | 'history' | 'layout' | 'custom'; /** * Full command definition. */ type CommandDefinition = { /** Unique command name */ name: string; /** Alternative names/shortcuts (e.g., ['cn'] for createNode) */ aliases?: string[]; /** Human-readable description */ description: string; /** Category for organization and filtering */ category: CommandCategory; /** Sequential input definitions */ inputs: InputDefinition[]; /** Execute the command with collected inputs */ execute: (inputs: Record, ctx: CommandContext) => Promise; /** * Optional: Generate visual feedback during input collection. * Called after each input is collected. */ feedback?: (collected: Record, currentInput: InputDefinition) => CommandFeedback | null; }; /** * Command line state machine phases. */ type CommandLineState = { phase: 'idle'; } | { phase: 'searching'; query: string; suggestions: CommandDefinition[]; } | { phase: 'collecting'; command: CommandDefinition; inputIndex: number; collected: Record; } | { phase: 'executing'; command: CommandDefinition; } | { phase: 'error'; message: string; }; /** * Visual feedback state for the canvas overlay. */ type FeedbackState = { hoveredNodeId?: string; cursorWorldPos?: Point; previewEdge?: { from: Point; to: Point; }; ghostNode?: { position: Point; opacity: number; }; crosshair?: boolean; } | null; /** * Command Registry * * Singleton class for managing all available commands. * Commands can be registered by the canvas package (built-ins) * or by consuming apps (custom commands). */ /** * Command Registry - Singleton class for managing all available commands. * * Usage: * ```typescript * import { commandRegistry } from '@blinksgg/canvas'; * * // Register a command * commandRegistry.register(myCommand); * * // Get a command by name or alias * const cmd = commandRegistry.get('createNode'); // or 'cn' * * // Search commands * const results = commandRegistry.search('node'); * ``` */ declare class CommandRegistry { private commands; private aliases; /** * Register a command with the registry. * @param command The command definition to register * @throws Error if command name or alias already exists */ register(command: CommandDefinition): void; /** * Unregister a command by name. * @param name The command name to remove */ unregister(name: string): void; /** * Get a command by name or alias. * @param nameOrAlias Command name or alias * @returns The command definition or undefined if not found */ get(nameOrAlias: string): CommandDefinition | undefined; /** * Check if a command exists by name or alias. * @param nameOrAlias Command name or alias */ has(nameOrAlias: string): boolean; /** * Search for commands matching a query. * Searches command names, aliases, and descriptions. * @param query Search query (case-insensitive) * @returns Array of matching commands, sorted by relevance */ search(query: string): CommandDefinition[]; /** * Get all registered commands. * @returns Array of all commands, sorted alphabetically by name */ all(): CommandDefinition[]; /** * Get commands by category. * @param category The category to filter by * @returns Array of commands in the category */ byCategory(category: CommandCategory): CommandDefinition[]; /** * Get all available categories. * @returns Array of unique categories */ categories(): CommandCategory[]; /** * Get the count of registered commands. */ get size(): number; /** * Clear all registered commands. * Useful for testing. */ clear(): void; /** * Get a serializable list of commands for API responses. */ toJSON(): Array<{ name: string; aliases: string[]; description: string; category: CommandCategory; inputs: Array<{ name: string; type: string; prompt: string; required: boolean; }>; }>; } declare const commandRegistry: CommandRegistry; declare function registerCommand(command: CommandDefinition): void; /** * Whether the command line UI is visible. */ declare const commandLineVisibleAtom: jotai.PrimitiveAtom & { init: boolean; }; /** * Command line state machine. */ declare const commandLineStateAtom: jotai.PrimitiveAtom & { init: CommandLineState; }; /** * Visual feedback state for the canvas overlay. */ declare const commandFeedbackAtom: jotai.PrimitiveAtom & { init: FeedbackState; }; /** * Command history (persisted to localStorage). */ declare const commandHistoryAtom: jotai.WritableAtom string[] | typeof jotai_utils.RESET)], void>; /** * Currently selected suggestion index for keyboard navigation. */ declare const selectedSuggestionIndexAtom: jotai.PrimitiveAtom & { init: number; }; /** * Whether a command is currently being executed or inputs collected. */ declare const isCommandActiveAtom: jotai.Atom; /** * Current input definition (if collecting). */ declare const currentInputAtom: jotai.Atom; /** * Progress through current command (e.g., "2/3"). */ declare const commandProgressAtom: jotai.Atom<{ current: number; total: number; } | null>; /** * Open the command line and enter search mode. */ declare const openCommandLineAtom: jotai.WritableAtom & { init: null; }; /** * Close the command line and reset state. */ declare const closeCommandLineAtom: jotai.WritableAtom & { init: null; }; /** * Update search query and suggestions. */ declare const updateSearchQueryAtom: jotai.WritableAtom & { init: null; }; /** * Select a command and start collecting inputs. */ declare const selectCommandAtom: jotai.WritableAtom & { init: null; }; /** * Skip the current optional input and use default value. */ declare const skipInputAtom: jotai.WritableAtom & { init: null; }; /** * Go back to the previous input. */ declare const goBackInputAtom: jotai.WritableAtom & { init: null; }; /** * Set error state. */ declare const setCommandErrorAtom: jotai.WritableAtom & { init: null; }; /** * Clear error and go back to idle. */ declare const clearCommandErrorAtom: jotai.WritableAtom & { init: null; }; /** * Legacy keyboard hook surface. * * Keyboard ownership now lives in the shared input runtime under * `InputProvider`. These exports remain as no-op compatibility shims * for callers that still mount them. */ declare const DEFAULT_SHORTCUTS: Record; interface UseGlobalKeyboardOptions { onDelete?: (nodeIds: string[]) => void | Promise; } declare function useGlobalKeyboard(_options?: UseGlobalKeyboardOptions): void; declare function useKeyState(_key: string): boolean; /** * Command Executor * * Helper functions for executing commands and handling input collection. */ /** * Collects a single input from the user. * Currently rejects immediately — interactive input collection * is not yet implemented. Pre-fill all inputs via `initialInputs`. */ declare function collectInput(_get: Getter, _set: Setter, _inputDef: InputDefinition, _collected: Record): Promise; /** * Execute a command with interactive input collection. * This is the main entry point for running commands from the UI. */ declare function executeCommandInteractive(get: Getter, set: Setter, command: CommandDefinition, initialInputs?: Record): Promise; /** * Handle a picked point from the canvas. * Called by Viewport when user clicks while in pickPoint mode. */ declare function handlePickedPoint(set: Setter, point: Point): void; /** * Handle a picked node from the canvas. * Called by Node component when user clicks while in pickNode mode. */ declare function handlePickedNode(set: Setter, node: UINodeState): void; /** * Cancel the current command. */ declare function cancelCommand(set: Setter): void; interface CommandProviderProps { children: React.ReactNode; onCreateNode?: (payload: CreateNodePayload) => Promise; onUpdateNode?: (nodeId: string, updates: Record) => Promise; onDeleteNode?: (nodeId: string) => Promise; onCreateEdge?: (payload: CreateEdgePayload) => Promise; onDeleteEdge?: (edgeId: string) => Promise; onForceLayoutPersist?: (positions: Array<{ nodeId: string; x: number; y: number; }>) => Promise; } type CommandContextValue = { /** * Execute a command by name with given inputs. * @param commandName Name or alias of the command * @param inputs Pre-collected inputs (for programmatic execution) */ executeCommand: (commandName: string, inputs: Record) => Promise; /** * Get the current command context (for use in command execute functions). */ getContext: () => CommandContext; /** * Check if a command exists. */ hasCommand: (name: string) => boolean; }; declare function CommandProvider({ children, onCreateNode, onUpdateNode, onDeleteNode, onCreateEdge, onDeleteEdge, onForceLayoutPersist, }: CommandProviderProps): react_jsx_runtime.JSX.Element; /** * Hook to access the command context. * Must be used within a CommandProvider. */ declare function useCommandContext(): CommandContextValue; /** * Hook to execute commands. * Returns a function that can be called with command name and inputs. */ declare function useExecuteCommand(): (commandName: string, inputs: Record) => Promise; /** * Built-in Viewport Commands * * Commands for viewport manipulation: * - fitToView: Fit all nodes in view * - fitSelection: Fit selected nodes in view * - resetViewport: Reset zoom and pan * - zoomIn: Zoom in * - zoomOut: Zoom out */ /** * Fit all nodes in view */ declare const fitToViewCommand: CommandDefinition; /** * Fit selected nodes in view */ declare const fitSelectionCommand: CommandDefinition; /** * Reset viewport to default */ declare const resetViewportCommand: CommandDefinition; /** * Zoom in */ declare const zoomInCommand: CommandDefinition; /** * Zoom out */ declare const zoomOutCommand: CommandDefinition; /** * Register all viewport commands */ declare function registerViewportCommands(): void; /** * Built-in Selection Commands * * Commands for selection manipulation: * - selectAll: Select all nodes * - clearSelection: Clear selection * - invertSelection: Invert selection */ /** * Select all nodes */ declare const selectAllCommand: CommandDefinition; /** * Clear selection */ declare const clearSelectionCommand: CommandDefinition; /** * Invert selection */ declare const invertSelectionCommand: CommandDefinition; /** * Register all selection commands */ declare function registerSelectionCommands(): void; /** * Built-in History Commands * * Commands for history manipulation: * - undo: Undo last action * - redo: Redo last undone action */ /** * Undo last action */ declare const undoCommand: CommandDefinition; /** * Redo last undone action */ declare const redoCommand: CommandDefinition; /** * Register all history commands */ declare function registerHistoryCommands(): void; /** * Built-in Layout Commands * * Commands for layout operations: * - forceLayout: Apply force-directed layout * - treeLayout: Hierarchical tree (top-down) * - gridLayout: Uniform grid * - horizontalLayout: Tree (left-to-right) */ declare const forceLayoutCommand: CommandDefinition; declare function registerLayoutCommands(): void; /** * Built-in Clipboard Commands * * Commands for copy/cut/paste operations: * - copy: Copy selected nodes to clipboard * - cut: Cut selected nodes (copy + prepare for delete) * - paste: Paste clipboard content at position * - duplicate: Duplicate selected nodes with offset */ /** * Copy selected nodes to clipboard */ declare const copyCommand: CommandDefinition; /** * Cut selected nodes (copy to clipboard) * Note: Actual deletion is handled by the app via onDeleteNode */ declare const cutCommand: CommandDefinition; /** * Paste clipboard content */ declare const pasteCommand: CommandDefinition; /** * Duplicate selected nodes with offset */ declare const duplicateCommand: CommandDefinition; /** * Delete selected nodes */ declare const deleteSelectedCommand: CommandDefinition; /** * Register all clipboard commands */ declare function registerClipboardCommands(): void; /** * Built-in Commands Index * * Export all built-in command definitions and registration functions. */ /** * Register all built-in commands. * Call this once during app initialization to make built-in commands available. */ declare function registerBuiltinCommands(): void; export { type CommandCategory, type CommandContext, type CommandDefinition, type CommandFeedback, type CommandLineState, CommandProvider, type CommandProviderProps, type CreateEdgePayload, type CreateNodePayload, DEFAULT_SHORTCUTS, type InputDefinition, type InputType, type UINodeState, cancelCommand, clearCommandErrorAtom, clearSelectionCommand, closeCommandLineAtom, collectInput, commandFeedbackAtom, commandHistoryAtom, commandLineStateAtom, commandLineVisibleAtom, commandProgressAtom, commandRegistry, copyCommand, currentInputAtom, cutCommand, deleteSelectedCommand, duplicateCommand, executeCommandInteractive, fitSelectionCommand, fitToViewCommand, forceLayoutCommand, goBackInputAtom, handlePickedNode, handlePickedPoint, invertSelectionCommand, isCommandActiveAtom, openCommandLineAtom, pasteCommand, redoCommand, registerBuiltinCommands, registerClipboardCommands, registerCommand, registerHistoryCommands, registerLayoutCommands, registerSelectionCommands, registerViewportCommands, resetViewportCommand, selectAllCommand, selectCommandAtom, selectedSuggestionIndexAtom, setCommandErrorAtom, skipInputAtom, undoCommand, updateSearchQueryAtom, useCommandContext, useExecuteCommand, useGlobalKeyboard, useKeyState, zoomInCommand, zoomOutCommand };