Extensible plugin architecture providing additional functionality for graph interaction and editing. X6's plugin system allows modular enhancement of core graph capabilities through installable plugins that integrate seamlessly with the graph lifecycle.
Base interface and management system for all X6 plugins.
/**
* Base plugin interface that all plugins must implement
*/
interface Graph.Plugin {
/** Unique plugin name for identification */
name: string;
/** Initialize plugin on graph instance */
init(graph: Graph, options?: any): void;
/** Optional cleanup when plugin is removed */
uninstall?(graph: Graph): void;
}
/**
* Plugin management methods on Graph class
*/
interface Graph {
/** Load and activate a plugin */
use(plugin: Graph.Plugin, ...options: any[]): this;
/** Get installed plugin by name */
getPlugin<T extends Graph.Plugin>(pluginName: string): T | undefined;
/** Enable one or more plugins */
enablePlugins(plugins: string[] | string): this;
/** Disable one or more plugins */
disablePlugins(plugins: string[] | string): this;
/** Check if plugin is enabled */
isPluginEnabled(pluginName: string): boolean;
}Multi-selection functionality with rubberband selection and selection management.
/**
* Selection plugin for multi-selection with rubberband
*/
class Selection implements Graph.Plugin {
readonly name: 'selection';
/** Initialize plugin with options */
init(graph: Graph, options?: Selection.Options): void;
/** Enable selection functionality */
enable(): this;
/** Disable selection functionality */
disable(): this;
/** Select cells */
select(cells: Cell | Cell[]): this;
/** Unselect cells */
unselect(cells?: Cell | Cell[]): this;
/** Get currently selected cells */
getSelectedCells(): Cell[];
/** Check if selection is empty */
isEmpty(): boolean;
/** Clear all selections */
clean(): this;
/** Check if cell is selected */
isSelected(cell: Cell): boolean;
/** Start rubberband selection */
startRubberband(e: MouseEvent): void;
/** Update rubberband during drag */
updateRubberband(e: MouseEvent): void;
/** Stop rubberband selection */
stopRubberband(): void;
}
interface Selection.Options {
/** Enable/disable selection */
enabled?: boolean;
/** Allow multiple selection */
multiple?: boolean;
/** Enable rubberband selection */
rubberband?: boolean;
/** Make selected cells movable */
movable?: boolean;
/** Show selection box for nodes */
showNodeSelectionBox?: boolean;
/** Show selection box for edges */
showEdgeSelectionBox?: boolean;
/** Modifier keys for multi-selection */
modifiers?: string | string[];
/** Selection box styling */
className?: string;
/** Rubberband styling */
rubberband?: {
className?: string;
};
/** Custom filter for selectable cells */
filter?: (this: Selection, cell: Cell) => boolean;
/** Event handlers */
eventTypes?: string[];
}Usage Examples:
import { Selection } from "@antv/x6";
// Basic selection setup
const selection = new Selection({
enabled: true,
multiple: true,
rubberband: true,
movable: true
});
graph.use(selection);
// Programmatic selection
selection.select([node1, node2]);
selection.unselect(node1);
const selectedCells = selection.getSelectedCells();
console.log('Selected:', selectedCells.length);
// Custom selection with filter
const customSelection = new Selection({
filter: (cell) => {
// Only allow selection of specific cell types
return cell.shape === 'rect' || cell.shape === 'circle';
}
});Undo/redo functionality for graph operations with command pattern implementation.
/**
* History plugin providing undo/redo functionality
*/
class History implements Graph.Plugin {
readonly name: 'history';
/** Initialize plugin with options */
init(graph: Graph, options?: History.Options): void;
/** Undo last operation */
undo(): this;
/** Redo next operation */
redo(): this;
/** Check if undo is available */
canUndo(): boolean;
/** Check if redo is available */
canRedo(): boolean;
/** Clear all history */
clean(): this;
/** Push command to history stack */
push(cmd: History.Command): this;
/** Get undo stack size */
getUndoStackSize(): number;
/** Get redo stack size */
getRedoStackSize(): number;
/** Enable history tracking */
enable(): this;
/** Disable history tracking */
disable(): this;
}
interface History.Options {
/** Enable/disable history */
enabled?: boolean;
/** Maximum history stack size */
stackSize?: number;
/** Commands to ignore */
ignoreAdd?: boolean;
ignoreRemove?: boolean;
ignoreChange?: boolean;
/** Before command execution hooks */
beforeAddCommand?: (this: History, event: string, args: any) => any;
afterAddCommand?: (this: History, event: string, args: any, cmd: History.Command) => void;
executeCommand?: (this: History, cmd: History.Command, revert: boolean, options: any) => void;
revertCommand?: (this: History, cmd: History.Command, isUndo: boolean, options: any) => void;
}
interface History.Command {
batch?: boolean;
options?: any;
data?: {
id: string;
type: string;
args: any;
};
}Usage Examples:
import { History } from "@antv/x6";
// Basic history setup
const history = new History({
enabled: true,
stackSize: 50
});
graph.use(history);
// Add some nodes and edges
const node1 = graph.addNode({ x: 100, y: 100, width: 80, height: 40 });
const node2 = graph.addNode({ x: 300, y: 200, width: 80, height: 40 });
const edge = graph.addEdge({ source: node1, target: node2 });
// Undo/redo operations
console.log('Can undo:', history.canUndo()); // true
history.undo(); // Removes the edge
history.undo(); // Removes node2
history.undo(); // Removes node1
console.log('Can redo:', history.canRedo()); // true
history.redo(); // Adds node1 back
history.redo(); // Adds node2 backKeyboard shortcut management with customizable key bindings and event handling.
/**
* Keyboard plugin for keyboard shortcut management
*/
class Keyboard implements Graph.Plugin {
readonly name: 'keyboard';
/** Initialize plugin with options */
init(graph: Graph, options?: Keyboard.Options): void;
/** Bind keyboard shortcut */
bindKey(keys: string | string[], callback: Keyboard.Handler, action?: Keyboard.Action): this;
/** Unbind keyboard shortcut */
unbindKey(keys: string | string[]): this;
/** Trigger keyboard event */
trigger(event: KeyboardEvent): this;
/** Clear all key bindings */
clear(): this;
/** Enable keyboard handling */
enable(): this;
/** Disable keyboard handling */
disable(): this;
/** Check if keyboard is enabled */
isEnabled(): boolean;
/** Get target element for keyboard events */
getTarget(): Element | null;
}
interface Keyboard.Options {
/** Enable/disable keyboard */
enabled?: boolean;
/** Target element for keyboard events */
target?: Element;
/** Global keyboard shortcuts */
global?: boolean;
/** Default key bindings */
bindings?: { [key: string]: Keyboard.Handler };
/** Format function for key combinations */
format?: (keys: string[]) => string;
/** Guard function to prevent handling */
guard?: (this: Keyboard, e: KeyboardEvent) => boolean;
}
type Keyboard.Handler = (this: Graph, e: KeyboardEvent) => void;
type Keyboard.Action = 'keypress' | 'keydown' | 'keyup';Usage Examples:
import { Keyboard } from "@antv/x6";
// Basic keyboard setup
const keyboard = new Keyboard({
enabled: true,
global: true
});
graph.use(keyboard);
// Bind keyboard shortcuts
keyboard.bindKey('delete', function() {
const selection = this.getPlugin<Selection>('selection');
if (selection) {
const cells = selection.getSelectedCells();
if (cells.length) {
this.removeCells(cells);
}
}
});
keyboard.bindKey('ctrl+z', function() {
const history = this.getPlugin<History>('history');
if (history && history.canUndo()) {
history.undo();
}
});
keyboard.bindKey('ctrl+y', function() {
const history = this.getPlugin<History>('history');
if (history && history.canRedo()) {
history.redo();
}
});
keyboard.bindKey(['ctrl+c', 'cmd+c'], function() {
const selection = this.getPlugin<Selection>('selection');
const clipboard = this.getPlugin<Clipboard>('clipboard');
if (selection && clipboard) {
clipboard.copy(selection.getSelectedCells());
}
});Copy/paste functionality for cells with local storage persistence option.
/**
* Clipboard plugin for copy/paste operations
*/
class Clipboard implements Graph.Plugin {
readonly name: 'clipboard';
/** Initialize plugin with options */
init(graph: Graph, options?: Clipboard.Options): void;
/** Copy cells to clipboard */
copy(cells?: Cell[]): this;
/** Cut cells to clipboard */
cut(cells?: Cell[]): this;
/** Paste cells from clipboard */
paste(options?: Clipboard.PasteOptions): Cell[];
/** Clear clipboard */
clear(): this;
/** Check if clipboard is empty */
isEmpty(): boolean;
/** Enable clipboard functionality */
enable(): this;
/** Disable clipboard functionality */
disable(): this;
}
interface Clipboard.Options {
/** Enable/disable clipboard */
enabled?: boolean;
/** Use local storage for persistence */
useLocalStorage?: boolean;
/** Local storage key name */
localStorageKey?: string;
/** Custom copy function */
copyCell?: (this: Clipboard, cell: Cell) => Cell.Properties;
/** Custom paste function */
pasteCell?: (this: Clipboard, cellData: Cell.Properties) => Cell;
/** Validate function for pasteable cells */
validateCell?: (this: Clipboard, cellData: Cell.Properties) => boolean;
}
interface Clipboard.PasteOptions {
/** Paste offset from original position */
offset?: { dx: number; dy: number };
/** Target position for paste */
position?: { x: number; y: number };
/** Silent paste without events */
silent?: boolean;
}Drag and drop functionality for adding nodes from external sources.
/**
* Drag and Drop plugin for external drag operations
*/
class Dnd implements Graph.Plugin {
readonly name: 'dnd';
/** Initialize plugin with options */
init(graph: Graph, options?: Dnd.Options): void;
/** Start drag operation */
start(node: Node, e: MouseEvent): void;
/** Stop drag operation */
stop(): void;
/** Check if currently dragging */
isDragging(): boolean;
}
interface Dnd.Options {
/** Target container for drop */
target?: Element;
/** Drag image element */
dragImageOffset?: { x: number; y: number };
/** Get drag image element */
getDragImage?: (this: Dnd, node: Node) => Element;
/** Get drop position */
getDropPosition?: (this: Dnd, e: DragEvent) => { x: number; y: number };
/** Validate drop target */
validateNode?: (this: Dnd, droppedNode: Node, droppedPosition: { x: number; y: number }) => boolean;
}Interactive transformation handles for resizing and rotating cells.
/**
* Transform plugin providing interactive transformation handles
*/
class Transform implements Graph.Plugin {
readonly name: 'transform';
/** Initialize plugin with options */
init(graph: Graph, options?: Transform.Options): void;
/** Create transformation handles for cell */
createHandle(cell: Cell, options?: Transform.CreateHandleOptions): HTMLElement;
/** Update transformation handles */
updateHandles(): this;
/** Remove transformation handles */
clearHandles(): this;
}
interface Transform.Options {
/** Resizing options */
resizing?: boolean | Transform.ResizingOptions;
/** Rotating options */
rotating?: boolean | Transform.RotatingOptions;
}
interface Transform.ResizingOptions {
enabled?: boolean;
minWidth?: number;
minHeight?: number;
maxWidth?: number;
maxHeight?: number;
orthogonal?: boolean;
restrict?: boolean;
preserveAspectRatio?: boolean;
}
interface Transform.RotatingOptions {
enabled?: boolean;
grid?: number;
}Scrollable canvas with viewport management and minimap integration.
/**
* Scroller plugin providing scrollable canvas functionality
*/
class Scroller implements Graph.Plugin {
readonly name: 'scroller';
/** Initialize plugin with options */
init(graph: Graph, options?: Scroller.Options): void;
/** Scroll to position */
scrollTo(x: number, y: number, options?: Scroller.ScrollOptions): this;
/** Scroll to cell */
scrollToCell(cell: Cell, options?: Scroller.ScrollToCellOptions): this;
/** Center content */
center(options?: Scroller.CenterOptions): this;
/** Center content in viewport */
centerContent(options?: Scroller.CenterContentOptions): this;
/** Get current scroll position */
getScrollbarPosition(): { left: number; top: number };
/** Set zoom level */
zoom(factor?: number): this | number;
/** Zoom to fit content */
zoomToFit(options?: Scroller.ZoomToFitOptions): this;
/** Lock scrolling */
lock(): this;
/** Unlock scrolling */
unlock(): this;
/** Update scroller size */
update(): this;
}
interface Scroller.Options {
enabled?: boolean;
pannable?: boolean;
className?: string;
width?: number;
height?: number;
autoResize?: boolean;
autoResizeOptions?: {
minWidth?: number;
maxWidth?: number;
minHeight?: number;
maxHeight?: number;
};
background?: {
color?: string;
image?: string;
position?: string;
size?: string;
repeat?: string;
};
}Miniature overview map of the graph with navigation capabilities.
/**
* MiniMap plugin providing miniature graph overview
*/
class MiniMap implements Graph.Plugin {
readonly name: 'minimap';
/** Initialize plugin with options */
init(graph: Graph, options?: MiniMap.Options): void;
/** Resize minimap */
resize(width?: number, height?: number): this;
/** Toggle minimap visibility */
toggle(): this;
/** Show minimap */
show(): this;
/** Hide minimap */
hide(): this;
/** Focus on specific area */
focus(rect: Rectangle): this;
}
interface MiniMap.Options {
enabled?: boolean;
container?: Element;
width?: number;
height?: number;
padding?: number;
scalable?: boolean;
minScale?: number;
maxScale?: number;
graphOptions?: Partial<Graph.Options>;
}Export functionality for generating images and SVG files from graphs.
/**
* Export plugin for generating images and SVG from graphs
*/
class Export implements Graph.Plugin {
readonly name: 'export';
/** Initialize plugin with options */
init(graph: Graph, options?: Export.Options): void;
/** Export as PNG image */
exportPNG(fileName?: string, options?: Export.ImageOptions): Promise<string>;
/** Export as JPEG image */
exportJPEG(fileName?: string, options?: Export.ImageOptions): Promise<string>;
/** Export as SVG */
exportSVG(fileName?: string, options?: Export.SVGOptions): Promise<string>;
/** Get data URL */
toDataURL(type?: string, options?: Export.ImageOptions): Promise<string>;
/** Get SVG string */
toSVG(options?: Export.SVGOptions): string;
}
interface Export.Options {
/** Default export quality */
quality?: number;
/** Default background color */
backgroundColor?: string;
/** Default padding */
padding?: number;
}
interface Export.ImageOptions {
width?: number;
height?: number;
quality?: number;
backgroundColor?: string;
padding?: number;
}
interface Export.SVGOptions {
preserveAspectRatio?: string;
viewBox?: string;
copyStyles?: boolean;
}Alignment guides that appear automatically during node dragging for precise positioning.
/**
* Snapline plugin providing alignment guides during dragging
*/
class Snapline implements Graph.Plugin {
readonly name: 'snapline';
/** Initialize plugin with options */
init(graph: Graph, options?: Snapline.Options): void;
/** Enable snaplines */
enable(): this;
/** Disable snaplines */
disable(): this;
/** Show snaplines */
show(): this;
/** Hide snaplines */
hide(): this;
/** Capture snaplines for alignment */
capture(): this;
/** Clean snaplines */
clean(): this;
}
interface Snapline.Options {
enabled?: boolean;
className?: string;
tolerance?: number;
sharp?: boolean;
clean?: boolean;
filter?: (this: Snapline, node: Node) => boolean;
}Component library with drag-and-drop functionality for adding predefined shapes.
/**
* Stencil plugin providing component library with drag-and-drop
*/
class Stencil implements Graph.Plugin {
readonly name: 'stencil';
/** Initialize plugin with options */
init(graph: Graph, options?: Stencil.Options): void;
/** Load shapes into stencil */
load(shapes: Node[], groupName?: string): this;
/** Unload shapes from stencil */
unload(shapes: Node[], groupName?: string): this;
/** Add single shape */
add(shape: Node, groupName?: string): this;
/** Remove single shape */
remove(shape: Node, groupName?: string): this;
/** Clear all shapes */
clear(): this;
/** Resize stencil */
resize(width?: number, height?: number): this;
}
interface Stencil.Options {
title?: string;
width?: number;
height?: number;
search?: boolean | Stencil.SearchOptions;
collapsable?: boolean;
groups?: Stencil.Group[];
layout?: Stencil.LayoutOptions;
layoutOptions?: any;
}
interface Stencil.Group {
name: string;
title?: string;
collapsable?: boolean;
collapsed?: boolean;
graphOptions?: Partial<Graph.Options>;
layoutOptions?: any;
}
interface Stencil.SearchOptions {
rect?: boolean;
placeholder?: string;
}
interface Stencil.LayoutOptions {
columns?: number;
rowHeight?: number;
columnWidth?: number;
dx?: number;
dy?: number;
marginX?: number;
marginY?: number;
center?: boolean;
resizeToFit?: boolean;
}// Plugin base types
interface Graph.Plugin {
name: string;
init(graph: Graph, options?: any): void;
uninstall?(graph: Graph): void;
}
// Event types for plugins
interface PluginEventArgs {
'plugin:installed': { plugin: Graph.Plugin; options?: any };
'plugin:uninstalled': { plugin: Graph.Plugin };
'selection:changed': { added: Cell[]; removed: Cell[] };
'history:undo': { command: History.Command };
'history:redo': { command: History.Command };
'keyboard:shortcut': { keys: string; event: KeyboardEvent };
'clipboard:copied': { cells: Cell[] };
'clipboard:pasted': { cells: Cell[] };
}
// Utility types
interface Rectangle {
x: number;
y: number;
width: number;
height: number;
}
interface Point {
x: number;
y: number;
}
type KeyValue = { [key: string]: any };