CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-n8n-editor-ui

Workflow Editor UI for n8n - a comprehensive Vue.js-based visual workflow editor with drag-and-drop functionality.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

canvas-operations.mddocs/

Canvas Operations

Interactive canvas functionality for visual workflow editing with drag-and-drop node placement, connection management, and canvas navigation.

Capabilities

Canvas Component

Main canvas component providing the visual workflow editor interface.

/**
 * Canvas component props for workflow editor
 */
interface CanvasProps {
  id?: string;
  nodes: CanvasNode[];
  connections: CanvasConnection[];
  controlsPosition?: PanelPosition;
  eventBus?: EventBus<CanvasEventBusEvents>;
  readOnly?: boolean;
  executing?: boolean;
  keyBindings?: boolean;
  loading?: boolean;
}

/**
 * Canvas component events
 */
interface CanvasEvents {
  'update:modelValue': (elements: CanvasElement[]) => void;
  'update:node:position': (id: string, position: XYPosition) => void;
  'click:node': (id: string, event: MouseEvent) => void;
  'create:node': (nodeType: string, position: XYPosition) => void;
  'delete:node': (id: string) => void;
  'run:workflow': () => void;
  'save:workflow': () => void;
}

type PanelPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';

Canvas Node Data

Data structure representing nodes on the canvas.

interface CanvasNodeData {
  id: string;
  name: string;
  subtitle: string;
  type: string;
  typeVersion: number;
  disabled: boolean;
  inputs: CanvasConnectionPort[];
  outputs: CanvasConnectionPort[];
  connections: {
    [CanvasConnectionMode.Input]: INodeConnections;
    [CanvasConnectionMode.Output]: INodeConnections;
  };
  issues: {
    items: string[];
    visible: boolean;
  };
  pinnedData: {
    count: number;
    visible: boolean;
  };
  execution: {
    status?: ExecutionStatus;
    waiting?: string;
    running: boolean;
  };
  runData: {
    outputMap?: ExecutionOutputMap;
    iterations: number;
    visible: boolean;
  };
  render: CanvasNodeRender;
}

interface CanvasConnectionPort {
  node?: string;
  type: NodeConnectionType;
  index: number;
  required?: boolean;
  maxConnections?: number;
  label?: string;
}

interface CanvasNodeRender {
  type: CanvasNodeRenderType;
  options: CanvasNodeRenderOptions;
}

enum CanvasConnectionMode {
  Input = 'inputs',
  Output = 'outputs'
}

type NodeConnectionType = 'main' | 'ai_memory' | 'ai_document' | 'ai_tool' | 'ai_languageModel' | 'ai_embedding' | 'ai_vectorStore' | 'ai_textSplitter' | 'ai_outputParser';

Canvas Operations Composable

Composable providing canvas manipulation functions.

/**
 * Composable for canvas operations
 */
function useCanvasOperations(): {
  addNodes(nodes: AddedNode[], connections?: AddedNodeConnection[]): void;
  deleteNode(id: string): void;
  copyNodes(ids: string[]): void;
  cutNodes(ids: string[]): void;
  pasteNodes(position?: XYPosition): void;
  selectAllNodes(): void;
  deselectAllNodes(): void;
  revertDeleteNode(id: string): void;
  setNodeSelected(id: string, selected?: boolean): void;
  updateNodePosition(id: string, position: XYPosition): void;
  createConnection(source: CanvasConnectionPort, target: CanvasConnectionPort): void;
  deleteConnection(connection: CanvasConnection): void;
};

interface AddedNode {
  type: string;
  openDetail?: boolean;
  isAutoAdd?: boolean;
  actionName?: string;
  position?: XYPosition;
  name?: string;
}

interface AddedNodeConnection {
  from: {
    nodeIndex: number;
    outputIndex?: number;
    type?: NodeConnectionType;
  };
  to: {
    nodeIndex: number;
    inputIndex?: number;
    type?: NodeConnectionType;
  };
}

Usage Example:

import { useCanvasOperations } from '@/composables/useCanvasOperations';

const canvasOperations = useCanvasOperations();

// Add multiple nodes with connections
canvasOperations.addNodes([
  {
    type: 'n8n-nodes-base.httpRequest',
    position: [100, 100],
    name: 'Fetch Data'
  },
  {
    type: 'n8n-nodes-base.set',
    position: [300, 100],
    name: 'Process Data'
  }
], [
  {
    from: { nodeIndex: 0, outputIndex: 0 },
    to: { nodeIndex: 1, inputIndex: 0 }
  }
]);

// Select and delete nodes
canvasOperations.setNodeSelected('node-1', true);
canvasOperations.deleteNode('node-1');

Canvas Layout

Automatic node layout and arrangement functionality.

/**
 * Composable for canvas layout operations
 */
function useCanvasLayout(): {
  layout(target: 'all' | 'selection'): void;
  getLayoutedElements(nodes: CanvasNode[], connections: CanvasConnection[]): {
    nodes: CanvasNode[];
    connections: CanvasConnection[];
  };
  arrangeNodes(nodes: INodeUi[], direction?: 'horizontal' | 'vertical'): INodeUi[];
};

/**
 * Automatically arrange nodes on canvas
 * @param target - Whether to layout all nodes or just selected ones
 */
function layout(target: 'all' | 'selection'): void;

/**
 * Calculate optimal positions for nodes and connections
 * @param nodes - Canvas nodes to layout
 * @param connections - Canvas connections
 * @returns Layouted elements with new positions
 */
function getLayoutedElements(
  nodes: CanvasNode[], 
  connections: CanvasConnection[]
): {
  nodes: CanvasNode[];
  connections: CanvasConnection[];
};

Canvas Node Composable

Composable for accessing canvas node data within node components.

/**
 * Composable for accessing canvas node data
 */
function useCanvasNode(): UseCanvasNodeReturn;

interface UseCanvasNodeReturn {
  node: InjectedCanvasNode;
  id: ComputedRef<string>;
  name: ComputedRef<string>;
  label: ComputedRef<string>;
  subtitle: ComputedRef<string>;
  inputs: ComputedRef<CanvasConnectionPort[]>;
  outputs: ComputedRef<CanvasConnectionPort[]>;
  isDisabled: ComputedRef<boolean>;
  isReadOnly: ComputedRef<boolean>;
  isSelected: ComputedRef<boolean>;
  hasPinnedData: ComputedRef<boolean>;
  hasIssues: ComputedRef<boolean>;
  executionRunning: ComputedRef<boolean>;
  executionWaiting: ComputedRef<boolean>;
  executionStatus: ComputedRef<ExecutionStatus | undefined>;
}

interface InjectedCanvasNode {
  id: string;
  label: string;
  data: CanvasNodeData;
}

Canvas Utilities

Utility functions for canvas positioning and calculations.

/**
 * Calculate new node position avoiding conflicts
 * @param nodes - Existing nodes
 * @param position - Initial position
 * @param options - Position calculation options
 * @returns Conflict-free position
 */
function getNewNodePosition(
  nodes: INodeUi[],
  position: XYPosition,
  options?: {
    offsetX?: number;
    offsetY?: number;
    gridSize?: number;
  }
): XYPosition;

/**
 * Snap position to grid alignment
 * @param position - Position to snap
 * @param gridSize - Grid size for snapping
 * @returns Grid-aligned position
 */
function snapPositionToGrid(position: XYPosition, gridSize?: number): XYPosition;

/**
 * Get center position of canvas viewport
 * @param scale - Current canvas scale
 * @param offset - Current canvas offset
 * @returns Center position coordinates
 */
function getMidCanvasPosition(scale: number, offset: XYPosition): XYPosition;

/**
 * Calculate node dimensions based on configuration
 * @param isConfiguration - Whether node is in configuration mode
 * @param isConfigurable - Whether node is configurable
 * @param inputCount - Number of input ports
 * @param outputCount - Number of output ports
 * @param nonMainInputCount - Number of non-main inputs
 * @returns Node dimensions [width, height]
 */
function calculateNodeSize(
  isConfiguration: boolean,
  isConfigurable: boolean,
  inputCount: number,
  outputCount: number,
  nonMainInputCount: number
): [number, number];

// Canvas constants
const GRID_SIZE = 16;
const DEFAULT_NODE_SIZE: [number, number] = [96, 96];
const CONFIGURATION_NODE_SIZE: [number, number] = [80, 80];
const DEFAULT_START_POSITION_X = 176;
const DEFAULT_START_POSITION_Y = 240;

Canvas Event System

Event bus system for canvas communication.

interface CanvasEventBusEvents {
  fitView: never;
  'nodes:select': { ids: string[] };
  'nodes:action': { ids: string[]; action: string };
  'nodes:delete': { ids: string[] };
  'saved:workflow': never;
  'open:contextmenu': { event: MouseEvent; type: 'canvas' | 'node'; nodeId?: string };
}

/**
 * Canvas event bus for component communication
 */
interface EventBus<T> {
  emit<K extends keyof T>(event: K, ...args: T[K] extends never ? [] : [T[K]]): void;
  on<K extends keyof T>(event: K, handler: T[K] extends never ? () => void : (arg: T[K]) => void): void;
  off<K extends keyof T>(event: K, handler: Function): void;
}

Canvas Navigation

Canvas viewport navigation and zoom controls.

/**
 * Canvas navigation and zoom functionality
 */
interface CanvasNavigation {
  fitView(): void;
  zoomIn(): void;
  zoomOut(): void;
  zoomToFit(): void;
  resetView(): void;
  panTo(position: XYPosition): void;
  setViewport(viewport: CanvasViewport): void;
}

interface CanvasViewport {
  x: number;
  y: number;
  zoom: number;
}

interface IZoomConfig {
  scale: number;
  offset: XYPosition;
  origin?: XYPosition;
}

Types

type XYPosition = [number, number];

interface CanvasElement {
  id: string;
  type: 'node' | 'connection';
  position?: XYPosition;
  data?: any;
}

interface CanvasConnection {
  id: string;
  source: string;
  target: string;
  sourceHandle?: string;
  targetHandle?: string;
  type?: string;
  data?: any;
}

interface EndpointStyle {
  width?: number;
  height?: number;
  fill?: string;
  stroke?: string;
  outlineStroke?: string;
  lineWidth?: number;
  hover?: boolean;
  showOutputLabel?: boolean;
  size?: string;
  hoverMessage?: string;
}

interface IBounds {
  minX: number;
  minY: number;
  maxX: number;
  maxY: number;
}

type DraggableMode = 'mapping' | 'panel-resize' | 'move';

enum CanvasNodeRenderType {
  Default = 'default',
  StickyNote = 'sticky-note',
  Configuration = 'configuration'
}

interface CanvasNodeRenderOptions {
  configurable?: boolean;
  configuration?: boolean;
  trigger?: boolean;
}

docs

api-client.md

canvas-operations.md

component-system.md

composables.md

index.md

state-management.md

workflow-management.md

tile.json