UNPKG

@deckedout/visual-editor

Version:

A flexible visual editor for building interactive canvases with drag-and-drop elements

1,046 lines (1,020 loc) 30.9 kB
import React$1 from 'react'; /** * Visual Editor - Core Type Definitions * * This file contains all the type definitions for the extensible visual editor. * The editor supports multiple modes (Card Editor, Playground, etc.) through * a flexible, schema-driven architecture. */ /** * Base interface for all visual elements in the editor. * @template TProps - Custom properties specific to the element type */ interface EditorElement<TProps = any> { /** Unique identifier for the element */ id: string; /** Type identifier (e.g., "text", "image", "pile", "card") */ type: string; /** Position on the canvas */ position: { x: number; y: number; }; /** Size of the element */ size: { width: number; height: number; }; /** Rotation angle in degrees */ rotation: number; /** Opacity (0-1, where 0 is transparent and 1 is opaque) */ opacity: number; /** Layer order (higher = on top) */ zIndex: number; /** Whether the element is visible */ visible?: boolean; /** Whether the element is locked (cannot be selected/moved) */ locked?: boolean; /** Display name for layers panel */ displayName?: string; /** Element-specific properties */ props: TProps; } /** * Common text element properties - matches CardChildText */ interface TextElementProps { content: string; fontSize: number; fontFamily?: string; color: string; strokeColor?: string; strokeWidth?: number; align?: "left" | "center" | "right"; verticalAlign?: "top" | "middle" | "bottom"; bold?: boolean; italic?: boolean; underline?: boolean; overline?: boolean; strikethrough?: boolean; wordWrap?: "break-word"; textOverflow?: "clip" | "ellipsis" | "visible"; } /** * Common image element properties */ interface ImageElementProps { src: string; fit?: "contain" | "cover" | "fill"; } /** * Defines how an element type should be rendered and configured. * This is the core abstraction that makes the editor extensible. */ interface ElementRenderer<TProps = any> { /** Unique type identifier */ type: string; /** Display name for UI */ displayName: string; /** Render function for the element (for non-Konva contexts) */ render: (element: EditorElement<TProps>) => React.ReactNode; /** React component for Konva canvas rendering */ renderComponent?: React.ComponentType<{ element: EditorElement<TProps>; isSelected: boolean; onSelect: () => void; onTransform: (updates: Partial<EditorElement>) => void; allElements?: EditorElement[]; canvasSize?: { width: number; height: number; }; onSnapGuides?: (guides: any) => void; onClearSnapGuides?: () => void; [key: string]: any; }>; /** Default properties when creating a new element of this type */ defaultProps: TProps; /** Default size for new elements */ defaultSize?: { width: number; height: number; }; /** Schema for the property inspector */ inspectorSchema?: InspectorFieldSchema[]; /** Optional icon for element type selector */ icon?: React.ReactNode; } /** * Supported field types in the property inspector */ type InspectorFieldType = "string" | "number" | "color" | "select" | "boolean" | "slider" | "image" | "custom"; /** * Props passed to custom renderer components */ interface CustomRendererProps { /** Current field value */ value: any; /** Callback to update the value */ onChange: (value: any) => void; /** Field schema */ field: InspectorFieldSchema; /** All element props (for context) */ elementProps: any; /** Editor mode (for accessing mode context) */ mode?: EditorMode; } /** * Schema definition for a single inspector field */ interface InspectorFieldSchema { /** Property name in element.props */ name: string; /** Field type */ type: InspectorFieldType; /** Display label */ label: string; /** Optional description/help text */ description?: string; /** For select fields - available options */ options?: { value: any; label: string; }[]; /** For number/slider fields */ min?: number; max?: number; step?: number; /** Default value */ defaultValue?: any; /** For custom type - custom renderer component */ customRenderer?: React.ComponentType<CustomRendererProps>; } /** * Core API for manipulating elements in the editor. * This API is exposed to modes and external code. */ interface EditorAPI { /** Add a new element to the canvas */ addElement: (element: EditorElement) => void; /** Update an existing element */ updateElement: (id: string, updates: Partial<EditorElement>) => void; /** Remove an element from the canvas */ removeElement: (id: string) => void; /** Select an element (or null to deselect) */ selectElement: (id: string | null) => void; /** Get the currently selected element */ getSelectedElement: () => EditorElement | null; /** Get all elements */ getAllElements: () => EditorElement[]; /** Move an element by delta */ moveElement: (id: string, deltaX: number, deltaY: number) => void; /** Rotate an element */ rotateElement: (id: string, angle: number) => void; /** Resize an element */ resizeElement: (id: string, width: number, height: number) => void; /** Update element's z-index */ updateZIndex: (id: string, zIndex: number) => void; /** Reorder an element to a new position in the array */ reorderElement: (id: string, newIndex: number) => void; /** Export canvas to JSON */ exportJSON: () => CanvasExport; /** Import canvas from JSON */ importJSON: (data: CanvasExport) => void; /** Clear all elements */ clear: () => void; /** Clear undo/redo history */ clearHistory: () => void; /** Load elements without recording history (for initial load) */ loadElements: (elements: EditorElement[]) => void; /** Copy an element to clipboard (returns element data) */ copyElement: (id?: string | null) => EditorElement | null; /** Duplicate the selected element with an offset */ duplicateElement: (id?: string | null, offset?: { x: number; y: number; }) => void; /** Paste a copied element with an offset */ pasteElement: (copiedElement: EditorElement, offset?: { x: number; y: number; }) => void; } /** * Format for exporting/importing canvas data */ interface CanvasExport { /** Canvas dimensions */ width: number; height: number; /** All elements on the canvas */ elements: EditorElement[]; /** Optional metadata */ metadata?: { version?: string; mode?: string; created?: string; modified?: string; [key: string]: any; }; } /** * Base interface for all custom editor actions */ interface CustomEditorActionBase { /** Unique identifier */ id: string; /** Display label/tooltip */ label: string; /** Disabled state */ disabled?: boolean | ((api: EditorAPI) => boolean); } /** * Button action - Simple click handler */ interface CustomEditorButtonAction extends CustomEditorActionBase { type: "button"; /** Icon component */ icon?: React.ReactNode; /** Keyboard shortcut hint */ shortcut?: string; /** Click handler */ onClick: (api: EditorAPI) => void; } /** * Dropdown action - Select from options */ interface CustomEditorDropdownAction extends CustomEditorActionBase { type: "dropdown"; /** Icon component (optional) */ icon?: React.ReactNode; /** Dropdown options */ options: Array<{ value: string; label: string; icon?: React.ReactNode; }>; /** Current selected value */ value?: string; /** Change handler */ onChange: (value: string, api: EditorAPI) => void; /** Placeholder text when no value selected */ placeholder?: string; } /** * Input action - Text input field */ interface CustomEditorInputAction extends CustomEditorActionBase { type: "input"; /** Input type (text, number, etc.) */ inputType?: "text" | "number" | "email" | "password" | "search"; /** Current value */ value: string; /** Change handler */ onChange: (value: string, api: EditorAPI) => void; /** Placeholder text */ placeholder?: string; /** Min/max for number inputs */ min?: number; max?: number; step?: number; } /** * Color picker action - Color selection */ interface CustomEditorColorAction extends CustomEditorActionBase { type: "color"; /** Current color value */ value: string; /** Change handler */ onChange: (color: string, api: EditorAPI) => void; /** Show alpha channel */ showAlpha?: boolean; } /** * Toggle action - On/off switch */ interface CustomEditorToggleAction extends CustomEditorActionBase { type: "toggle"; /** Icon component (optional) */ icon?: React.ReactNode; /** Current toggle state */ value: boolean; /** Change handler */ onChange: (value: boolean, api: EditorAPI) => void; } /** * Separator - Visual divider (no interaction) */ interface CustomEditorSeparator { type: "separator"; id: string; } /** * Union type for all custom editor actions */ type CustomEditorAction = CustomEditorButtonAction | CustomEditorDropdownAction | CustomEditorInputAction | CustomEditorColorAction | CustomEditorToggleAction | CustomEditorSeparator; /** * Configuration for topbar controls visibility */ interface TopbarConfig { /** Show undo button */ showUndo?: boolean; /** Show redo button */ showRedo?: boolean; /** Show delete button */ showDelete?: boolean; /** Show copy button */ showCopy?: boolean; /** Show paste button */ showPaste?: boolean; /** Show duplicate button */ showDuplicate?: boolean; /** Show export button */ showExport?: boolean; /** Show import button */ showImport?: boolean; /** Show canvas size controls */ showCanvasSize?: boolean; /** Show snap guides toggle */ showSnapGuides?: boolean; /** Custom actions to add before default controls (left side) */ actionsStart?: CustomEditorAction[]; /** Custom actions to add after default controls (right side) */ actionsEnd?: CustomEditorAction[]; /** Custom CSS classes for the start actions container */ actionsStartClassName?: string; /** Custom CSS classes for the end actions container */ actionsEndClassName?: string; /** @deprecated Use actionsEnd instead. Custom actions to add to topbar (defaults to end) */ customActions?: CustomEditorAction[]; } /** * Configuration for toolbar controls visibility */ interface ToolbarConfig { /** Show element creation tools */ showElementTools?: boolean; /** Specific element types to hide from toolbar (by type string) */ hiddenElementTypes?: string[]; /** Custom tools to add before default element tools (top) */ toolsStart?: CustomEditorAction[]; /** Custom tools to add after default element tools (bottom) */ toolsEnd?: CustomEditorAction[]; /** Custom CSS classes for the start tools container */ toolsStartClassName?: string; /** Custom CSS classes for the end tools container */ toolsEndClassName?: string; /** @deprecated Use toolsEnd instead. Custom tools to add to toolbar (defaults to end) */ customTools?: CustomEditorAction[]; } /** * Configuration for different editor modes (Card Editor, Playground, etc.) */ interface EditorMode { /** Mode identifier */ name: string; /** Display name for UI */ displayName: string; /** * Elements available in this mode (optional) * If omitted, defaultElements will be used * If provided, will be merged with defaultElements */ registeredElements?: ElementRenderer[]; /** Default canvas size */ defaultCanvasSize: { width: number; height: number; }; /** Whether the canvas size can be changed */ canResizeCanvas?: boolean; /** Whether elements can be added/removed */ readonly?: boolean; /** Whether to show grid */ showGrid?: boolean; /** Grid size in pixels */ gridSize?: number; /** Whether to snap to grid */ snapToGrid?: boolean; /** Background color */ backgroundColor?: string; /** Background image (asset filename) */ backgroundImage?: string; /** Optional context data to pass to element renderers */ context?: Record<string, any>; /** Custom asset picker component */ assetPickerComponent?: React.ComponentType<any>; /** Props to pass to the custom asset picker */ assetPickerProps?: Record<string, any>; /** Asset picker height (CSS class like "h-64", "h-[40%]", "flex-1", etc.) */ assetPickerHeight?: string; /** Asset picker position - 'bottom' shows below inspector, 'right' shows as separate panel */ assetPickerPosition?: "bottom" | "right"; /** Custom inspector placeholder component (shown when no element is selected) */ inspectorPlaceholder?: React.ComponentType<any>; /** Configuration for topbar controls (hide/show specific actions) */ topbarConfig?: TopbarConfig; /** Configuration for toolbar controls (hide/show specific tools) */ toolbarConfig?: ToolbarConfig; /** Optional mode-specific behavior hooks */ onModeActivate?: (api: EditorAPI) => void; onModeDeactivate?: (api: EditorAPI) => void; onElementAdded?: (element: EditorElement, api: EditorAPI) => void; onElementRemoved?: (element: EditorElement, api: EditorAPI) => void; } /** * Main configuration for the Visual Editor component */ interface VisualEditorProps { /** Current editor mode */ mode?: EditorMode; /** Initial canvas data */ initialData?: CanvasExport; /** Canvas width (overrides mode default) */ width?: number; /** Canvas height (overrides mode default) */ height?: number; /** Whether the editor is in readonly mode */ readonly?: boolean; /** Callback when data changes */ onChange?: (data: CanvasExport) => void; /** Callback when an element is selected */ onSelectionChange?: (element: EditorElement | null) => void; /** Callback for export action */ onExport?: (data: CanvasExport) => void; /** Custom element renderers (extends mode elements) */ customElements?: ElementRenderer[]; /** Whether to show the toolbar */ showToolbar?: boolean; /** Whether to show the inspector panel */ showInspector?: boolean; /** Custom CSS class */ className?: string; /** Custom styles */ style?: React.CSSProperties; } /** * Internal editor state (not exposed externally) */ interface EditorState { elements: EditorElement[]; selectedElementId: string | null; canvasSize: { width: number; height: number; }; zoom: number; pan: { x: number; y: number; }; mode: EditorMode | null; history: { past: EditorElement[][]; future: EditorElement[][]; }; } /** * Actions for state management */ type EditorAction = { type: "ADD_ELEMENT"; element: EditorElement; } | { type: "UPDATE_ELEMENT"; id: string; updates: Partial<EditorElement>; } | { type: "REMOVE_ELEMENT"; id: string; } | { type: "SELECT_ELEMENT"; id: string | null; } | { type: "SET_ELEMENTS"; elements: EditorElement[]; } | { type: "LOAD_ELEMENTS"; elements: EditorElement[]; } | { type: "REORDER_ELEMENT"; elementId: string; newIndex: number; } | { type: "SET_CANVAS_SIZE"; width: number; height: number; } | { type: "SET_ZOOM"; zoom: number; } | { type: "SET_PAN"; x: number; y: number; } | { type: "SET_MODE"; mode: EditorMode; } | { type: "CLEAR"; } | { type: "UNDO"; } | { type: "REDO"; }; /** * Visual Editor - Main Editor Component * * The core editor component that integrates all functionality: * - Canvas rendering with Konva * - Element management * - Selection and transformation * - Mode switching */ /** * Main Visual Editor Component */ declare const VisualEditor: React$1.FC<VisualEditorProps>; /** * Inspector Component * * Schema-driven property panel for editing selected element properties. * Dynamically renders fields based on the element's inspectorSchema. */ interface InspectorProps { /** Currently selected element */ selectedElement: EditorElement | null; /** Element renderer for the selected element */ elementRenderer: ElementRenderer | null; /** Editor API for updating elements */ api: EditorAPI; /** Editor mode (for custom placeholder and context) */ mode?: EditorMode; /** Canvas size (passed to placeholder component) */ canvasSize?: { width: number; height: number; }; /** Function to set canvas size */ setCanvasSize?: (width: number, height: number) => void; /** Optional custom style */ style?: React$1.CSSProperties; /** Optional className */ className?: string; } /** * Inspector component that renders property fields based on element schema */ declare const Inspector: React$1.FC<InspectorProps>; /** * Render a single inspector field based on its type */ declare function renderField(field: InspectorFieldSchema, props: any, editingValues: Record<string, string>, onChange: (name: string, value: any) => void, onColorChange: (name: string, value: string) => void, mode?: EditorMode): React$1.ReactNode; /** * Layers Panel Component * * Displays all elements in the canvas with controls to show/hide, lock/unlock, * reorder, and delete elements. */ interface LayersPanelProps { /** All elements in the canvas */ elements: EditorElement[]; /** Currently selected element ID */ selectedElementId: string | null; /** Editor API for manipulating elements */ api: EditorAPI; /** Element registry to get renderer info */ elementRenderers: Map<string, ElementRenderer>; /** Optional custom style */ style?: React$1.CSSProperties; /** Optional className */ className?: string; } /** * Layers Panel component */ declare const LayersPanel: React$1.FC<LayersPanelProps>; /** * Visual Editor Workspace * * Integrated workspace that combines Toolbar, Canvas (VisualEditor), and Inspector. * This component creates a complete editor experience by coordinating all three parts. */ interface VisualEditorWorkspaceProps { /** Editor mode configuration */ mode?: EditorMode; /** Initial canvas data */ initialData?: CanvasExport; /** Canvas width (overrides mode default) */ width?: number; /** Canvas height (overrides mode default) */ height?: number; /** Whether the editor is in readonly mode */ readonly?: boolean; /** Callback when data changes */ onChange?: (data: CanvasExport) => void; /** Custom element renderers (extends mode elements) */ customElements?: any[]; /** Whether to show the toolbar */ showToolbar?: boolean; /** Whether to show the topbar (canvas size, undo, redo, delete, import, export) */ showTopbar?: boolean; /** Whether to show the inspector panel */ showInspector?: boolean; /** Whether to show the layers panel */ showLayers?: boolean; /** Whether to show the asset picker (if defined in mode) */ showAssetPicker?: boolean; /** Whether to show the canvas */ showCanvas?: boolean; /** Whether to enable snap guides */ enableSnapGuides?: boolean; /** Whether to enable pan and zoom controls */ enablePanZoom?: boolean; /** Optional background image URL - replaces solid background color when provided */ backgroundImageUrl?: string; /** Whether to hide all elements on the canvas */ hideElements?: boolean; /** Custom CSS class */ className?: string; /** Ref to access the editor API */ apiRef?: React$1.Ref<EditorAPI>; } /** * Complete visual editor workspace with toolbar, canvas, and inspector */ declare const VisualEditorWorkspace: React$1.FC<VisualEditorWorkspaceProps>; /** * Asset Picker Panel * * Displays project assets that can be dragged/clicked to use in the editor. * Integrates with useProjectAssets to show game assets. */ interface AssetPickerProps { /** List of assets to display */ assets: Array<{ name: string; path: string; type?: string; }>; /** Callback when an asset is selected */ onAssetSelect?: (assetPath: string) => void; /** Custom render function for asset items */ renderAsset?: (asset: { name: string; path: string; type?: string; }) => React$1.ReactNode; /** Custom CSS class */ className?: string; /** Title for the panel */ title?: string; } /** * Asset Picker component that displays available assets */ declare const AssetPicker: React$1.FC<AssetPickerProps>; /** * Visual Editor - Core State Management * * Provides the state management logic for the visual editor using useReducer. * This hook encapsulates all state mutations and provides a clean API. */ /** * Custom hook for managing editor state */ declare const useEditorState: (initialMode?: EditorMode | null) => { state: EditorState; api: EditorAPI; setCanvasSize: (width: number, height: number) => void; setMode: (mode: EditorMode) => void; undo: () => void; redo: () => void; canUndo: boolean; canRedo: boolean; }; /** * Visual Editor - Element Registry * * Manages registration and retrieval of element renderers. * This is what makes the editor extensible - new element types * can be registered dynamically. */ /** * Registry class for managing element renderers */ declare class ElementRegistry { private renderers; /** * Register a new element renderer */ register(renderer: ElementRenderer): void; /** * Register multiple element renderers at once */ registerMany(renderers: ElementRenderer[]): void; /** * Get a renderer by type */ get(type: string): ElementRenderer | undefined; /** * Check if a renderer exists for a type */ has(type: string): boolean; /** * Get all registered renderers */ getAll(): ElementRenderer[]; /** * Get the internal renderers map */ getMap(): Map<string, ElementRenderer>; /** * Get all registered types */ getAllTypes(): string[]; /** * Unregister a renderer */ unregister(type: string): boolean; /** * Clear all registered renderers */ clear(): void; /** * Get the number of registered renderers */ get size(): number; } /** * Create a global singleton registry (can be used across the app) */ declare const globalElementRegistry: ElementRegistry; declare const useElementRegistry: (initialRenderers?: ElementRenderer[]) => ElementRegistry; /** * Snapping Utilities * * Helper functions for snapping elements to guides, other elements, and canvas edges. */ interface SnapGuide { /** Position of the guide line */ position: number; /** Orientation of the guide (vertical or horizontal) */ orientation: "vertical" | "horizontal"; /** Snap type (element edge, center, or canvas edge) */ type: "edge" | "center" | "canvas"; } interface SnapResult { /** Snapped x position */ x: number; /** Snapped y position */ y: number; /** Vertical guides to display */ verticalGuides: SnapGuide[]; /** Horizontal guides to display */ horizontalGuides: SnapGuide[]; } interface SnapOptions { /** Snap threshold in pixels */ threshold?: number; /** Whether to snap to other elements */ snapToElements?: boolean; /** Whether to snap to canvas edges */ snapToCanvas?: boolean; /** Canvas size */ canvasSize?: { width: number; height: number; }; } /** * Calculate snapping for an element being dragged */ declare function getSnappingPosition(draggedElement: EditorElement, x: number, y: number, allElements: EditorElement[], options?: SnapOptions): SnapResult; /** * Visual Editor - Text Element Renderer * * Built-in text element renderer using Konva. */ /** * Text element renderer component */ declare const TextElementRenderer: React$1.FC<{ element: EditorElement<TextElementProps>; isSelected: boolean; onSelect: () => void; onTransform: (updates: Partial<EditorElement>) => void; allElements?: EditorElement[]; canvasSize?: { width: number; height: number; }; onSnapGuides?: (guides: { vertical: SnapGuide[]; horizontal: SnapGuide[]; }) => void; onClearSnapGuides?: () => void; elementId?: string; }>; /** * Text element renderer definition */ declare const textElementRenderer: ElementRenderer<TextElementProps>; /** * Visual Editor - Image Element Renderer * * Built-in image element renderer using Konva. */ /** * Image element renderer component */ declare const ImageElementRenderer: React$1.FC<{ element: EditorElement<ImageElementProps>; isSelected: boolean; onSelect: () => void; onTransform: (updates: Partial<EditorElement>) => void; allElements?: EditorElement[]; canvasSize?: { width: number; height: number; }; onSnapGuides?: (guides: { vertical: SnapGuide[]; horizontal: SnapGuide[]; }) => void; onClearSnapGuides?: () => void; imageUrls?: Map<string, string>; elementId?: string; onNodeUpdate?: () => void; }>; /** * Image element renderer definition */ declare const imageElementRenderer: ElementRenderer<ImageElementProps>; declare const defaultElements: (ElementRenderer<TextElementProps> | ElementRenderer<ImageElementProps>)[]; /** * Visual Editor - Utility Functions * * Common utility functions used throughout the visual editor. */ /** * Generate a unique ID for an element */ declare const generateElementId: () => string; /** * Create a new element with default values */ declare const createElement: <TProps = any>(type: string, props: TProps, options?: { position?: { x: number; y: number; }; size?: { width: number; height: number; }; rotation?: number; opacity?: number; zIndex?: number; visible?: boolean; locked?: boolean; displayName?: string; }) => EditorElement<TProps>; /** * Deep clone an element */ declare const cloneElement: <TProps = any>(element: EditorElement<TProps>) => EditorElement<TProps>; /** * Duplicate an element with a slight offset */ declare const duplicateElement: <TProps = any>(element: EditorElement<TProps>, offset?: { x: number; y: number; }) => EditorElement<TProps>; /** * Sort elements by z-index (ascending) */ declare const sortByZIndex: (elements: EditorElement[]) => EditorElement[]; /** * Get the highest z-index among elements */ declare const getMaxZIndex: (elements: EditorElement[]) => number; /** * Bring an element to front */ declare const bringToFront: (elements: EditorElement[], elementId: string) => EditorElement[]; /** * Send an element to back */ declare const sendToBack: (elements: EditorElement[], elementId: string) => EditorElement[]; /** * Check if two rectangles overlap */ declare const checkOverlap: (rect1: { x: number; y: number; width: number; height: number; }, rect2: { x: number; y: number; width: number; height: number; }) => boolean; /** * Check if a point is inside a rectangle */ declare const pointInRect: (point: { x: number; y: number; }, rect: { x: number; y: number; width: number; height: number; }) => boolean; /** * Snap a value to grid */ declare const snapToGrid: (value: number, gridSize: number) => number; /** * Snap position to grid */ declare const snapPositionToGrid: (position: { x: number; y: number; }, gridSize: number) => { x: number; y: number; }; /** * Constrain a value between min and max */ declare const clamp: (value: number, min: number, max: number) => number; /** * Constrain position within canvas bounds */ declare const constrainToCanvas: (position: { x: number; y: number; }, size: { width: number; height: number; }, canvasSize: { width: number; height: number; }) => { x: number; y: number; }; /** * Calculate bounding box for rotated rectangle */ declare const getRotatedBoundingBox: (x: number, y: number, width: number, height: number, rotation: number) => { x: number; y: number; width: number; height: number; }; /** * Export canvas to JSON string */ declare const exportToJSON: (data: CanvasExport) => string; /** * Import canvas from JSON string */ declare const importFromJSON: (json: string) => CanvasExport; /** * Calculate center point of an element */ declare const getElementCenter: (element: EditorElement) => { x: number; y: number; }; /** * Calculate distance between two points */ declare const distance: (p1: { x: number; y: number; }, p2: { x: number; y: number; }) => number; /** * Degrees to radians */ declare const degToRad: (degrees: number) => number; /** * Radians to degrees */ declare const radToDeg: (radians: number) => number; /** * Validate element data */ declare const isValidElement: (element: any) => element is EditorElement; /** * Validate canvas export data */ declare const isValidCanvasExport: (data: any) => data is CanvasExport; export { AssetPicker, type AssetPickerProps, type CanvasExport, type CustomRendererProps, type EditorAPI, type EditorAction, type EditorElement, type EditorMode, type EditorState, ElementRegistry, type ElementRenderer, type ImageElementProps, ImageElementRenderer, Inspector, type InspectorFieldSchema, type InspectorFieldType, LayersPanel, type SnapGuide, type SnapOptions, type SnapResult, type TextElementProps, TextElementRenderer, VisualEditor, type VisualEditorProps, VisualEditorWorkspace, bringToFront, checkOverlap, clamp, cloneElement, constrainToCanvas, createElement, defaultElements, degToRad, distance, duplicateElement, exportToJSON, generateElementId, getElementCenter, getMaxZIndex, getRotatedBoundingBox, getSnappingPosition, globalElementRegistry, imageElementRenderer, importFromJSON, isValidCanvasExport, isValidElement, pointInRect, radToDeg, renderField, sendToBack, snapPositionToGrid, snapToGrid, sortByZIndex, textElementRenderer, useEditorState, useElementRegistry };