@ngroznykh/papirus 0.3.21 → 0.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/papirus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"papirus.js","sources":["../src/events/EventEmitter.ts","../src/events/InputHandler.ts","../src/utils/geometry.ts","../src/constants.ts","../src/core/SelectionManager.ts","../src/core/DragManager.ts","../src/core/ResizeManager.ts","../src/utils/contentBounds.ts","../src/core/NavigationManager.ts","../src/core/ConnectionManager.ts","../src/utils/style.ts","../src/elements/TextLabel.ts","../src/core/history/commands.ts","../src/core/HistoryManager.ts","../src/elements/Element.ts","../src/elements/paths/StraightPathStrategy.ts","../src/utils/direction.ts","../src/elements/paths/PolylinePathStrategy.ts","../src/elements/paths/BezierPathStrategy.ts","../src/elements/Edge.ts","../src/core/LabelEditor.ts","../src/core/InteractionManager.ts","../src/core/AnimationManager.ts","../src/core/ContextMenuManager.ts","../src/core/DiagramRenderer.ts","../src/core/SearchManager.ts","../src/elements/Port.ts","../src/utils/LRUCache.ts","../src/elements/NodeImage.ts","../src/elements/Node.ts","../src/elements/Group.ts","../src/elements/nodes/RectangleNode.ts","../src/elements/nodes/CircleNode.ts","../src/elements/nodes/DiamondNode.ts","../src/elements/nodes/CustomShapeNode.ts","../src/styles/StyleManager.ts","../src/utils/omitDefaults.ts","../src/utils/Serializer.ts","../src/utils/download.ts","../src/utils/elementIterator.ts","../src/utils/ImageExporter.ts","../src/utils/markers.ts","../src/utils/SvgExporter.ts","../src/utils/AutoLayout.ts","../src/utils/AutoRouting.ts","../src/utils/AlignDistribute.ts","../src/core/overlays/BaseOverlay.ts","../src/core/overlays/GridOverlay.ts","../src/core/overlays/RulersOverlay.ts","../src/core/overlays/GuidesOverlay.ts","../src/core/overlays/MiniMap.ts","../src/utils/canvas.ts"],"sourcesContent":["/**\n * Type-safe event emitter with support for typed event maps\n */\nexport class EventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n private listeners = new Map<keyof TEvents, Set<(...args: unknown[]) => void>>();\n\n /**\n * Subscribe to an event\n * @param event - Event name\n * @param listener - Callback function\n * @returns Unsubscribe function\n */\n on<K extends keyof TEvents>(event: K, listener: (...args: TEvents[K]) => void): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n const listeners = this.listeners.get(event)!;\n listeners.add(listener as (...args: unknown[]) => void);\n\n return () => {\n this.off(event, listener);\n };\n }\n\n /**\n * Unsubscribe from an event\n * @param event - Event name\n * @param listener - Callback function to remove\n */\n off<K extends keyof TEvents>(event: K, listener: (...args: TEvents[K]) => void): void {\n const listeners = this.listeners.get(event);\n if (listeners !== undefined) {\n listeners.delete(listener as (...args: unknown[]) => void);\n }\n }\n\n /**\n * Subscribe to an event for a single emission\n * @param event - Event name\n * @param listener - Callback function\n * @returns Unsubscribe function\n */\n once<K extends keyof TEvents>(event: K, listener: (...args: TEvents[K]) => void): () => void {\n const wrapper = (...args: TEvents[K]): void => {\n this.off(event, wrapper);\n listener(...args);\n };\n return this.on(event, wrapper);\n }\n\n /**\n * Emit an event to all subscribers\n * @param event - Event name\n * @param args - Event arguments\n */\n emit<K extends keyof TEvents>(event: K, ...args: TEvents[K]): void {\n const listeners = this.listeners.get(event);\n if (listeners !== undefined) {\n for (const listener of listeners) {\n listener(...args);\n }\n }\n }\n\n /**\n * Remove all listeners for an event or all events\n * @param event - Optional event name. If not provided, removes all listeners\n */\n removeAllListeners<K extends keyof TEvents>(event?: K): void {\n if (event !== undefined) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event\n * @param event - Event name\n * @returns Number of listeners\n */\n listenerCount<K extends keyof TEvents>(event: K): number {\n const listeners = this.listeners.get(event);\n return listeners?.size ?? 0;\n }\n}\n","import { EventEmitter } from './EventEmitter';\nimport type { Point } from '@/types';\n\n/**\n * Input events\n */\nexport interface InputEvents {\n click: [event: InputEvent];\n dblclick: [event: InputEvent];\n mousedown: [event: InputEvent];\n mouseup: [event: InputEvent];\n mousemove: [event: InputEvent];\n wheel: [event: WheelInputEvent];\n pan: [event: PanInputEvent];\n pinch: [event: PinchInputEvent];\n keydown: [event: KeyboardEvent];\n keyup: [event: KeyboardEvent];\n}\n\n/**\n * Normalized input event\n */\nexport interface InputEvent {\n screenX: number;\n screenY: number;\n worldX: number;\n worldY: number;\n button: number;\n ctrlKey: boolean;\n shiftKey: boolean;\n altKey: boolean;\n metaKey: boolean;\n originalEvent: MouseEvent | TouchEvent;\n}\n\n/**\n * Wheel input event\n */\nexport interface WheelInputEvent extends InputEvent {\n deltaX: number;\n deltaY: number;\n deltaZ: number;\n originalEvent: WheelEvent;\n}\n\n/**\n * Pan gesture event (touch)\n */\nexport interface PanInputEvent extends InputEvent {\n deltaX: number;\n deltaY: number;\n}\n\n/**\n * Pinch gesture event (touch)\n */\nexport interface PinchInputEvent extends InputEvent {\n scale: number;\n}\n\nexport interface InputHandlerOptions {\n canvas: HTMLCanvasElement;\n screenToWorld: (screenX: number, screenY: number) => Point;\n}\n\n/**\n * Handles mouse, touch, and keyboard input\n * Normalizes events and converts coordinates\n */\nexport class InputHandler extends EventEmitter<InputEvents> {\n private readonly canvas: HTMLCanvasElement;\n private screenToWorld: (screenX: number, screenY: number) => Point;\n private boundHandlers = new Map<string, EventListener>();\n private lastTouchDistance: number | null = null;\n private lastTouchCenter: Point | null = null;\n\n constructor(options: InputHandlerOptions) {\n super();\n this.canvas = options.canvas;\n this.screenToWorld = options.screenToWorld;\n this.setupEventListeners();\n }\n\n /**\n * Update the coordinate transform function\n */\n setScreenToWorld(fn: (screenX: number, screenY: number) => Point): void {\n this.screenToWorld = fn;\n }\n\n /**\n * Clean up event listeners\n */\n destroy(): void {\n for (const [eventName, handler] of this.boundHandlers) {\n if (eventName.startsWith('key')) {\n window.removeEventListener(eventName, handler);\n } else {\n this.canvas.removeEventListener(eventName, handler);\n }\n }\n this.boundHandlers.clear();\n this.removeAllListeners();\n }\n\n private setupEventListeners(): void {\n // Mouse events\n this.addCanvasListener('click', this.handleClick.bind(this));\n this.addCanvasListener('dblclick', this.handleDblClick.bind(this));\n this.addCanvasListener('mousedown', this.handleMouseDown.bind(this));\n this.addCanvasListener('mouseup', this.handleMouseUp.bind(this));\n this.addCanvasListener('mousemove', this.handleMouseMove.bind(this));\n this.addCanvasListener('wheel', this.handleWheel.bind(this), { passive: false });\n\n // Touch events\n this.addCanvasListener('touchstart', this.handleTouchStart.bind(this));\n this.addCanvasListener('touchend', this.handleTouchEnd.bind(this));\n this.addCanvasListener('touchmove', this.handleTouchMove.bind(this));\n\n // Keyboard events (on window)\n this.addWindowListener('keydown', this.handleKeyDown.bind(this));\n this.addWindowListener('keyup', this.handleKeyUp.bind(this));\n\n // Prevent context menu on canvas\n this.addCanvasListener('contextmenu', (e) => e.preventDefault());\n }\n\n private addCanvasListener(\n eventName: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void {\n this.canvas.addEventListener(eventName, handler, options);\n this.boundHandlers.set(eventName, handler);\n }\n\n private addWindowListener(eventName: string, handler: EventListener): void {\n window.addEventListener(eventName, handler);\n this.boundHandlers.set(eventName, handler);\n }\n\n private handleClick(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('click', event);\n }\n\n private handleDblClick(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('dblclick', event);\n }\n\n private handleMouseDown(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('mousedown', event);\n }\n\n private handleMouseUp(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('mouseup', event);\n }\n\n private handleMouseMove(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('mousemove', event);\n }\n\n private handleWheel(e: Event): void {\n e.preventDefault();\n const wheelEvent = e as WheelEvent;\n const baseEvent = this.normalizeMouseEvent(wheelEvent);\n const event: WheelInputEvent = {\n ...baseEvent,\n deltaX: wheelEvent.deltaX,\n deltaY: wheelEvent.deltaY,\n deltaZ: wheelEvent.deltaZ,\n originalEvent: wheelEvent,\n };\n this.emit('wheel', event);\n }\n\n private handleTouchStart(e: Event): void {\n const event = this.normalizeTouchEvent(e as TouchEvent);\n if (event !== null) {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length >= 2) {\n const { distance, center } = this.getTouchDistanceAndCenter(touchEvent);\n this.lastTouchDistance = distance;\n this.lastTouchCenter = center;\n return;\n }\n this.emit('mousedown', event);\n }\n }\n\n private handleTouchEnd(e: Event): void {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length < 2) {\n this.lastTouchDistance = null;\n this.lastTouchCenter = null;\n }\n\n const event = this.normalizeTouchEvent(touchEvent);\n if (event !== null) {\n this.emit('mouseup', event);\n }\n }\n\n private handleTouchMove(e: Event): void {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length >= 2) {\n const { distance, center } = this.getTouchDistanceAndCenter(touchEvent);\n if (this.lastTouchDistance !== null && this.lastTouchCenter !== null) {\n const deltaX = center.x - this.lastTouchCenter.x;\n const deltaY = center.y - this.lastTouchCenter.y;\n const scale = distance / this.lastTouchDistance;\n\n const worldPos = this.screenToWorld(center.x, center.y);\n const baseEvent: InputEvent = {\n screenX: center.x,\n screenY: center.y,\n worldX: worldPos.x,\n worldY: worldPos.y,\n button: 0,\n ctrlKey: touchEvent.ctrlKey,\n shiftKey: touchEvent.shiftKey,\n altKey: touchEvent.altKey,\n metaKey: touchEvent.metaKey,\n originalEvent: touchEvent,\n };\n\n if (deltaX !== 0 || deltaY !== 0) {\n this.emit('pan', { ...baseEvent, deltaX, deltaY });\n }\n if (scale !== 1) {\n this.emit('pinch', { ...baseEvent, scale });\n }\n }\n\n this.lastTouchDistance = distance;\n this.lastTouchCenter = center;\n return;\n }\n\n const event = this.normalizeTouchEvent(touchEvent);\n if (event !== null) {\n this.emit('mousemove', event);\n }\n }\n\n private handleKeyDown(e: Event): void {\n // Only handle if canvas has focus or no element is focused\n if (this.shouldHandleKeyboard()) {\n this.emit('keydown', e as KeyboardEvent);\n }\n }\n\n private handleKeyUp(e: Event): void {\n if (this.shouldHandleKeyboard()) {\n this.emit('keyup', e as KeyboardEvent);\n }\n }\n\n private shouldHandleKeyboard(): boolean {\n const active = document.activeElement;\n if (\n active === null ||\n active === document.body ||\n active === this.canvas ||\n active.tagName === 'CANVAS'\n ) {\n return true;\n }\n\n if (active instanceof HTMLElement) {\n if (active.isContentEditable) {\n return false;\n }\n\n const tag = active.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') {\n return false;\n }\n }\n\n return true;\n }\n\n private normalizeMouseEvent(e: MouseEvent): InputEvent {\n const worldPos = this.screenToWorld(e.clientX, e.clientY);\n return {\n screenX: e.clientX,\n screenY: e.clientY,\n worldX: worldPos.x,\n worldY: worldPos.y,\n button: e.button,\n ctrlKey: e.ctrlKey,\n shiftKey: e.shiftKey,\n altKey: e.altKey,\n metaKey: e.metaKey,\n originalEvent: e,\n };\n }\n\n private normalizeTouchEvent(e: TouchEvent): InputEvent | null {\n const touch = e.touches[0] ?? e.changedTouches[0];\n if (touch === undefined) {\n return null;\n }\n\n const worldPos = this.screenToWorld(touch.clientX, touch.clientY);\n return {\n screenX: touch.clientX,\n screenY: touch.clientY,\n worldX: worldPos.x,\n worldY: worldPos.y,\n button: 0,\n ctrlKey: e.ctrlKey,\n shiftKey: e.shiftKey,\n altKey: e.altKey,\n metaKey: e.metaKey,\n originalEvent: e,\n };\n }\n\n private getTouchDistanceAndCenter(event: TouchEvent): { distance: number; center: Point } {\n const [t1, t2] = [event.touches[0], event.touches[1]];\n if (!t1 || !t2) {\n return { distance: 0, center: { x: 0, y: 0 } };\n }\n\n const dx = t2.clientX - t1.clientX;\n const dy = t2.clientY - t1.clientY;\n const center = {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n };\n\n return { distance: Math.hypot(dx, dy), center };\n }\n}\n","import type { Bounds, Point } from '@/types';\n\n/**\n * Calculate distance between two points\n */\nexport function distance(p1: Point, p2: Point): number {\n const dx = p2.x - p1.x;\n const dy = p2.y - p1.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * Calculate distance from point to line segment\n */\nexport function distanceToSegment(point: Point, segStart: Point, segEnd: Point): number {\n const dx = segEnd.x - segStart.x;\n const dy = segEnd.y - segStart.y;\n const lengthSq = dx * dx + dy * dy;\n\n if (lengthSq === 0) {\n return distance(point, segStart);\n }\n\n let t = ((point.x - segStart.x) * dx + (point.y - segStart.y) * dy) / lengthSq;\n t = Math.max(0, Math.min(1, t));\n\n const projX = segStart.x + t * dx;\n const projY = segStart.y + t * dy;\n\n return distance(point, { x: projX, y: projY });\n}\n\n/**\n * Check if a point is inside a rectangle\n */\nexport function pointInRect(point: Point, rect: Bounds): boolean {\n return (\n point.x >= rect.x &&\n point.x <= rect.x + rect.width &&\n point.y >= rect.y &&\n point.y <= rect.y + rect.height\n );\n}\n\n/**\n * Check if two rectangles intersect\n */\nexport function rectsIntersect(a: Bounds, b: Bounds): boolean {\n return (\n a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y\n );\n}\n\n/**\n * Calculate the intersection of two rectangles\n */\nexport function rectIntersection(a: Bounds, b: Bounds): Bounds | null {\n const x = Math.max(a.x, b.x);\n const y = Math.max(a.y, b.y);\n const right = Math.min(a.x + a.width, b.x + b.width);\n const bottom = Math.min(a.y + a.height, b.y + b.height);\n\n if (right > x && bottom > y) {\n return { x, y, width: right - x, height: bottom - y };\n }\n\n return null;\n}\n\n/**\n * Calculate the union of two rectangles\n */\nexport function rectUnion(a: Bounds, b: Bounds): Bounds {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n const right = Math.max(a.x + a.width, b.x + b.width);\n const bottom = Math.max(a.y + a.height, b.y + b.height);\n\n return { x, y, width: right - x, height: bottom - y };\n}\n\n/**\n * Check if a point is inside an ellipse\n */\nexport function pointInEllipse(point: Point, center: Point, radiusX: number, radiusY: number): boolean {\n const dx = point.x - center.x;\n const dy = point.y - center.y;\n return (dx * dx) / (radiusX * radiusX) + (dy * dy) / (radiusY * radiusY) <= 1;\n}\n\n/**\n * Calculate angle between two points (in radians)\n */\nexport function angle(from: Point, to: Point): number {\n return Math.atan2(to.y - from.y, to.x - from.x);\n}\n\n/**\n * Rotate a point around a center\n */\nexport function rotatePoint(point: Point, center: Point, angleRad: number): Point {\n const cos = Math.cos(angleRad);\n const sin = Math.sin(angleRad);\n const dx = point.x - center.x;\n const dy = point.y - center.y;\n\n return {\n x: center.x + dx * cos - dy * sin,\n y: center.y + dx * sin + dy * cos,\n };\n}\n\n/**\n * Linear interpolation between two points\n */\nexport function lerp(a: Point, b: Point, t: number): Point {\n return {\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n };\n}\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/**\n * Snap a value to a grid\n */\nexport function snapToGrid(value: number, gridSize: number): number {\n return Math.round(value / gridSize) * gridSize;\n}\n\n/**\n * Snap a point to a grid\n */\nexport function snapPointToGrid(point: Point, gridSize: number): Point {\n return {\n x: snapToGrid(point.x, gridSize),\n y: snapToGrid(point.y, gridSize),\n };\n}\n\n/**\n * Expand bounds by a given amount\n */\nexport function expandBounds(bounds: Bounds, amount: number): Bounds {\n return {\n x: bounds.x - amount,\n y: bounds.y - amount,\n width: bounds.width + amount * 2,\n height: bounds.height + amount * 2,\n };\n}\n\n/**\n * Get center point of bounds\n */\nexport function boundsCenter(bounds: Bounds): Point {\n return {\n x: bounds.x + bounds.width / 2,\n y: bounds.y + bounds.height / 2,\n };\n}\n\n/**\n * Calculate control points for a cubic Bézier curve between two points\n * Returns array of 4 points: [start, control1, control2, end]\n */\nexport function calculateBezierControlPoints(\n from: Point,\n to: Point,\n maxOffset = 100,\n offsetFactor = 0.5\n): [Point, Point, Point, Point] {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const offset = Math.min(Math.abs(dx), Math.abs(dy), maxOffset) * offsetFactor;\n\n // Horizontal dominant\n if (Math.abs(dx) > Math.abs(dy)) {\n const offsetX = offset * Math.sign(dx || 1);\n return [\n from,\n { x: from.x + offsetX, y: from.y },\n { x: to.x - offsetX, y: to.y },\n to,\n ];\n }\n\n // Vertical dominant\n return [\n from,\n { x: from.x, y: from.y + offset * Math.sign(dy) },\n { x: to.x, y: to.y - offset * Math.sign(dy) },\n to,\n ];\n}\n\n/**\n * Calculate a point on a cubic Bézier curve at parameter t\n */\nexport function bezierPoint(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point {\n const mt = 1 - t;\n return {\n x: mt * mt * mt * p0.x + 3 * mt * mt * t * p1.x + 3 * mt * t * t * p2.x + t * t * t * p3.x,\n y: mt * mt * mt * p0.y + 3 * mt * mt * t * p1.y + 3 * mt * t * t * p2.y + t * t * t * p3.y,\n };\n}\n\n/**\n * Merge multiple bounds into a single bounding box.\n * Returns null if the iterable is empty.\n */\nexport function mergeBounds(\n sources: Iterable<{ x: number; y: number; width: number; height: number }>\n): Bounds | null {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let hasContent = false;\n\n for (const b of sources) {\n minX = Math.min(minX, b.x);\n minY = Math.min(minY, b.y);\n maxX = Math.max(maxX, b.x + b.width);\n maxY = Math.max(maxY, b.y + b.height);\n hasContent = true;\n }\n\n return hasContent ? { x: minX, y: minY, width: maxX - minX, height: maxY - minY } : null;\n}\n\n/**\n * Create a shallow copy of an array of points.\n */\nexport function clonePoints(points: Point[]): Point[] {\n return points.map((p) => ({ ...p }));\n}\n\n/**\n * Draw a rounded rectangle path\n */\nexport function drawRoundedRectPath(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number\n): void {\n const r = Math.min(radius, width / 2, height / 2);\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + r);\n ctx.lineTo(x + width, y + height - r);\n ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n ctx.lineTo(x + r, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n}\n","/**\n * Centralized constants for the diagram library\n */\n\n// Edge rendering\nexport const EDGE_HANDLE_RADIUS = 6;\nexport const EDGE_CONTROL_POINT_RADIUS = 6;\nexport const EDGE_ADD_CONTROL_RADIUS = 4;\nexport const ARROW_SIZE = 10;\nexport const ARROW_ANGLE = Math.PI / 6; // 30 degrees\n\n// Marker sizes\nexport const MARKER_SIZES: Record<string, number> = {\n arrow: 12,\n open: 12,\n diamond: 14,\n circle: 6,\n};\n\n// Edge label\nexport const EDGE_LABEL_BACKGROUND_PADDING = 4;\nexport const EDGE_LABEL_BACKGROUND_RADIUS = 2;\n\n// Resize handles\nexport const RESIZE_HANDLE_SIZE = 8;\nexport const RESIZE_HANDLE_OFFSET = 6;\n\n// Anchor points\nexport const ANCHOR_POINT_RADIUS = 4;\nexport const ANCHOR_POINT_HOVER_RADIUS = 6;\nexport const ANCHOR_POINT_HITBOX_RADIUS = 10;\nexport const NODE_HITBOX_PADDING = 10;\n\n// Anchor points\nexport const ANCHOR_PORT_PREFIX = 'anchor:';\n\n// Bezier curve calculation\nexport const BEZIER_MAX_OFFSET = 100;\n\n/** Screen distance (px) within which edge endpoint snaps to shape outline when attachToOutline */\nexport const OUTLINE_SNAP_SCREEN_TOLERANCE = 40;\n\n// Selection\nexport const SELECTION_RECT_MIN_SIZE = 1;\nexport const DEFAULT_SELECTION_COLOR = '#3b82f6';\nexport const DEFAULT_HOVER_COLOR = '#6366f1';\n\n// Drag\n/** Minimum distance (world units) to start a drag */\nexport const DRAG_START_THRESHOLD = 3;\n/** Screen tolerance for alignment guides when dragging */\nexport const ALIGNMENT_SCREEN_TOLERANCE = 8;\n\n// Editable polyline\n/** Max distance (world units) for control point to be considered orthogonal to endpoint */\nexport const EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE = 6;\n/** Screen tolerance for axis magnet when dragging editable polyline control points */\nexport const EDGE_AXIS_MAGNET_SCREEN_TOLERANCE = 10;\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { Bounds, Point } from '@/types';\nimport { rectsIntersect } from '@/utils/geometry';\nimport { SELECTION_RECT_MIN_SIZE, DEFAULT_SELECTION_COLOR } from '@/constants';\n\n/**\n * Selection events\n */\nexport interface SelectionEvents {\n select: [selectedIds: string[]];\n selectionStart: [point: Point];\n selectionMove: [bounds: Bounds];\n selectionEnd: [bounds: Bounds];\n}\n\n/**\n * Manages element selection\n */\nexport class SelectionManager extends EventEmitter<SelectionEvents> {\n private renderer: DiagramRenderer;\n private _selectedIds = new Set<string>();\n private selectionStart: Point | null = null;\n private selectionRect: Bounds | null = null;\n\n constructor(renderer: DiagramRenderer) {\n super();\n this.renderer = renderer;\n }\n\n /**\n * Currently selected element IDs\n */\n get selectedIds(): ReadonlySet<string> {\n return this._selectedIds;\n }\n\n /**\n * Current selection rectangle (during drag selection)\n */\n get selectionRectangle(): Bounds | null {\n return this.selectionRect;\n }\n\n /**\n * Check if an element is selected\n */\n isSelected(elementId: string): boolean {\n return this._selectedIds.has(elementId);\n }\n\n /**\n * Select a single element\n */\n select(elementId: string): void {\n this.clearSelection();\n this._selectedIds.add(elementId);\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Add element to selection\n */\n addToSelection(elementId: string): void {\n this._selectedIds.add(elementId);\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Remove element from selection\n */\n removeFromSelection(elementId: string): void {\n this._selectedIds.delete(elementId);\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Toggle element selection\n */\n toggleSelection(elementId: string): void {\n if (this._selectedIds.has(elementId)) {\n this._selectedIds.delete(elementId);\n } else {\n this._selectedIds.add(elementId);\n }\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Select multiple elements\n */\n selectMultiple(elementIds: string[]): void {\n this.clearSelection();\n for (const id of elementIds) {\n this._selectedIds.add(id);\n }\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Clear all selections\n */\n clearSelection(): void {\n if (this._selectedIds.size > 0) {\n this._selectedIds.clear();\n this.updateElementStates();\n this.emitSelect();\n }\n }\n\n /**\n * Handle click event\n */\n handleClick(event: InputEvent): void {\n const point = { x: event.worldX, y: event.worldY };\n const element = this.renderer.getElementAtPoint(point);\n\n if (element === undefined) {\n if (!event.ctrlKey && !event.metaKey) {\n this.clearSelection();\n }\n return;\n }\n\n if (event.ctrlKey || event.metaKey) {\n this.toggleSelection(element.id);\n } else {\n this.select(element.id);\n }\n }\n\n /**\n * Start selection rectangle\n */\n startSelectionRect(point: Point): void {\n this.selectionStart = point;\n this.selectionRect = { x: point.x, y: point.y, width: 0, height: 0 };\n this.emit('selectionStart', point);\n }\n\n /**\n * Update selection rectangle\n */\n updateSelectionRect(point: Point): void {\n if (this.selectionStart === null) {\n return;\n }\n\n const x = Math.min(this.selectionStart.x, point.x);\n const y = Math.min(this.selectionStart.y, point.y);\n const width = Math.abs(point.x - this.selectionStart.x);\n const height = Math.abs(point.y - this.selectionStart.y);\n\n this.selectionRect = { x, y, width, height };\n this.emit('selectionMove', this.selectionRect);\n this.renderer.markDirty();\n }\n\n /**\n * End selection rectangle and select enclosed elements\n */\n endSelectionRect(): void {\n if (this.selectionRect === null) {\n return;\n }\n\n const rect = this.selectionRect;\n const selected: string[] = [];\n\n // Find nodes within selection rect\n for (const node of this.renderer.nodes.values()) {\n const bounds = node.getBounds();\n if (rectsIntersect(rect, bounds)) {\n selected.push(node.id);\n }\n }\n\n // Find groups within selection rect\n for (const group of this.renderer.groups.values()) {\n const bounds = group.getBounds();\n if (rectsIntersect(rect, bounds)) {\n selected.push(group.id);\n }\n }\n\n if (selected.length > 0) {\n this.selectMultiple(selected);\n }\n\n this.emit('selectionEnd', rect);\n this.selectionStart = null;\n this.selectionRect = null;\n this.renderer.markDirty();\n }\n\n /**\n * Cancel selection rectangle\n */\n cancelSelectionRect(): void {\n this.selectionStart = null;\n this.selectionRect = null;\n this.renderer.markDirty();\n }\n\n /**\n * Render selection rectangle\n */\n renderSelectionRect(ctx: CanvasRenderingContext2D): void {\n if (this.selectionRect === null) {\n return;\n }\n\n const { x, y, width, height } = this.selectionRect;\n\n // Skip if rectangle is too small (just started)\n if (width < SELECTION_RECT_MIN_SIZE && height < SELECTION_RECT_MIN_SIZE) {\n return;\n }\n\n ctx.fillStyle = 'rgba(59, 130, 246, 0.15)';\n ctx.fillRect(x, y, width, height);\n\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([5, 3]);\n ctx.strokeRect(x, y, width, height);\n ctx.setLineDash([]);\n }\n\n private updateElementStates(): void {\n const updateState = (elements: Iterable<{ id: string; state: string }>): void => {\n for (const element of elements) {\n if (this._selectedIds.has(element.id)) {\n element.state = 'selected';\n } else if (element.state === 'selected') {\n element.state = 'normal';\n }\n }\n };\n\n updateState(this.renderer.nodes.values());\n updateState(this.renderer.edges.values());\n updateState(this.renderer.groups.values());\n\n this.renderer.markDirty();\n this.renderer.markStyleDirty();\n }\n\n private emitSelect(): void {\n this.emit('select', Array.from(this._selectedIds));\n this.renderer.emit('select', Array.from(this._selectedIds));\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { SelectionManager } from './SelectionManager';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { Node } from '@/elements/Node';\nimport type { Bounds, Point } from '@/types';\nimport { ALIGNMENT_SCREEN_TOLERANCE, DRAG_START_THRESHOLD, EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE } from '@/constants';\nimport { distance, mergeBounds, clonePoints, rectsIntersect } from '@/utils/geometry';\n\ninterface AlignmentGuide {\n orientation: 'vertical' | 'horizontal';\n position: number;\n from: number;\n to: number;\n}\n\n/**\n * Drag events\n */\nexport interface DragEvents {\n dragstart: [nodeIds: string[], startPoint: Point];\n drag: [nodeIds: string[], currentPoint: Point, delta: Point];\n dragend: [nodeIds: string[], endPoint: Point];\n}\n\nexport interface DragManagerOptions {\n renderer: DiagramRenderer;\n selectionManager: SelectionManager;\n snapToGrid?: boolean;\n gridSize?: number;\n alignToNodes?: boolean;\n}\n\n/**\n * Manages node dragging\n */\nexport class DragManager extends EventEmitter<DragEvents> {\n private renderer: DiagramRenderer;\n private selectionManager: SelectionManager;\n private snapToGrid: boolean;\n private gridSize: number;\n private alignToNodes: boolean;\n\n private isDragging = false;\n private draggedNodes: Node[] = [];\n private dragStartPoint: Point | null = null;\n private lastDragPoint: Point | null = null;\n private initialPositions = new Map<string, Point>();\n private editableBendFollow = new Map<\n string,\n Array<{ edgeId: string; controlPointIndex: number; axis: 'vertical' | 'horizontal' }>\n >();\n /** Edges (editable-polyline) where both endpoints are in selection — control points follow delta */\n private editablePolylineFullyConnectedEdges = new Set<string>();\n /** Snapshot of control points at drag start for cancel/restore */\n private initialControlPointsForFullyConnected = new Map<string, Point[]>();\n private alignmentGuides: AlignmentGuide[] = [];\n private _handledMouseDown = false;\n private draggedGroupSelection = false;\n\n constructor(options: DragManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.selectionManager = options.selectionManager;\n this.snapToGrid = options.snapToGrid ?? false;\n this.gridSize = options.gridSize ?? 20;\n this.alignToNodes = options.alignToNodes ?? true;\n }\n\n /**\n * Check if currently dragging\n */\n get dragging(): boolean {\n return this.isDragging;\n }\n\n /**\n * Check if last mousedown was handled (for skipping click handling)\n */\n get handledMouseDown(): boolean {\n return this._handledMouseDown;\n }\n\n renderAlignmentGuides(ctx: CanvasRenderingContext2D): void {\n if (!this.alignToNodes || !this.isDragging || this.alignmentGuides.length === 0) {\n return;\n }\n\n const zoom = Math.max(this.renderer.zoom, 0.0001);\n ctx.save();\n ctx.setLineDash([6 / zoom, 4 / zoom]);\n ctx.strokeStyle = '#6366f1';\n ctx.lineWidth = 1.5 / zoom;\n\n for (const guide of this.alignmentGuides) {\n ctx.beginPath();\n if (guide.orientation === 'vertical') {\n ctx.moveTo(guide.position, guide.from);\n ctx.lineTo(guide.position, guide.to);\n } else {\n ctx.moveTo(guide.from, guide.position);\n ctx.lineTo(guide.to, guide.position);\n }\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Enable/disable snap to grid\n */\n setSnapToGrid(enabled: boolean, gridSize?: number): void {\n this.snapToGrid = enabled;\n if (gridSize !== undefined) {\n this.gridSize = gridSize;\n }\n }\n\n /**\n * Enable/disable smart alignment to other nodes while dragging.\n */\n setAlignmentEnabled(enabled: boolean): void {\n this.alignToNodes = enabled;\n if (!enabled && this.alignmentGuides.length > 0) {\n this.alignmentGuides = [];\n this.renderer.markDirty();\n }\n }\n\n /**\n * Handle mouse down - start potential drag\n */\n handleMouseDown(event: InputEvent): boolean {\n // Reset handledMouseDown at the start of new interaction\n this._handledMouseDown = false;\n\n const point = { x: event.worldX, y: event.worldY };\n const element = this.renderer.getElementAtPoint(point);\n\n if (element === undefined) {\n return false;\n }\n\n // Check if it's a node\n const node = this.renderer.getNode(element.id);\n const group = node === undefined ? this.renderer.getGroup(element.id) : undefined;\n const edge =\n node === undefined && group === undefined ? this.renderer.getEdge(element.id) : undefined;\n if (node === undefined && group === undefined && edge === undefined) {\n return false;\n }\n\n // Edge dragging: allow dragging selected nodes through edge hit area.\n // Useful for relation anchors that are hidden and hard to click directly.\n if (edge !== undefined) {\n if (edge.state !== 'selected') {\n return false;\n }\n const hasSelectedNodes = Array.from(this.selectionManager.selectedIds).some(\n (id) => this.renderer.getNode(id) !== undefined\n );\n if (!hasSelectedNodes) {\n return false;\n }\n this._handledMouseDown = true;\n this.dragStartPoint = point;\n this.lastDragPoint = point;\n this.draggedGroupSelection = false;\n this.draggedNodes = [];\n this.initialPositions.clear();\n for (const id of this.selectionManager.selectedIds) {\n const selectedNode = this.renderer.getNode(id);\n if (selectedNode !== undefined) {\n this.addDraggedNode(selectedNode);\n }\n }\n return this.draggedNodes.length > 0;\n }\n\n const targetId = node?.id ?? group!.id;\n\n // Handle selection based on modifier keys\n if (!this.selectionManager.isSelected(targetId)) {\n if (event.ctrlKey || event.metaKey) {\n // Ctrl+click on unselected: add to selection\n this.selectionManager.addToSelection(targetId);\n } else {\n // Regular click on unselected: select only this element\n this.selectionManager.select(targetId);\n }\n // Mark as handled since we changed selection\n this._handledMouseDown = true;\n }\n // If already selected - don't mark as handled yet\n // Let click event handle toggle (Ctrl+click) or re-select (regular click)\n // We'll mark as handled if actual drag starts\n\n // Prepare for drag\n this.dragStartPoint = point;\n this.lastDragPoint = point;\n this.draggedGroupSelection = false;\n\n // Get all selected nodes (expand groups to children)\n this.draggedNodes = [];\n for (const id of this.selectionManager.selectedIds) {\n const selectedNode = this.renderer.getNode(id);\n if (selectedNode !== undefined) {\n this.addDraggedNode(selectedNode);\n continue;\n }\n\n const selectedGroup = this.renderer.getGroup(id);\n if (selectedGroup !== undefined) {\n this.draggedGroupSelection = true;\n for (const child of selectedGroup.getAllChildren()) {\n const childNode = this.renderer.getNode(child.id);\n if (childNode) {\n this.addDraggedNode(childNode);\n }\n }\n }\n }\n\n return true;\n }\n\n /**\n * Handle mouse move - update drag\n */\n handleMouseMove(event: InputEvent): boolean {\n if (this.dragStartPoint === null) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n\n // Check if we've moved enough to start dragging\n if (!this.isDragging) {\n const dist = distance(point, this.dragStartPoint);\n\n if (dist < DRAG_START_THRESHOLD) {\n return false;\n }\n\n // Start dragging\n this.isDragging = true;\n this._handledMouseDown = true; // Mark as handled now that drag started\n this.buildEditableBendFollowBindings();\n this.alignmentGuides = [];\n for (const node of this.draggedNodes) {\n node.state = 'dragging';\n }\n this.emit(\n 'dragstart',\n this.draggedNodes.map((n) => n.id),\n this.dragStartPoint\n );\n }\n\n // Calculate total offset from drag start (not incremental delta)\n const totalDelta = {\n x: point.x - this.dragStartPoint.x,\n y: point.y - this.dragStartPoint.y,\n };\n\n // Delta from last point (for event)\n const delta = {\n x: point.x - this.lastDragPoint!.x,\n y: point.y - this.lastDragPoint!.y,\n };\n\n const alignedDelta = this.resolveAlignmentDelta(totalDelta);\n\n // Move nodes using initial position + total offset\n let firstDelta: Point | null = null;\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (initial === undefined) continue;\n const prevX = node.x;\n const prevY = node.y;\n\n let newX = initial.x + alignedDelta.x;\n let newY = initial.y + alignedDelta.y;\n\n if (this.snapToGrid) {\n newX = Math.round(newX / this.gridSize) * this.gridSize;\n newY = Math.round(newY / this.gridSize) * this.gridSize;\n }\n\n node.x = newX;\n node.y = newY;\n const dx = newX - prevX;\n const dy = newY - prevY;\n if (firstDelta === null) {\n firstDelta = { x: dx, y: dy };\n }\n this.followNearestEditableBend(node.id, dx, dy);\n }\n\n if (firstDelta !== null) {\n this.followEditableBendForFullyConnectedEdges(firstDelta.x, firstDelta.y);\n }\n this.emit(\n 'drag',\n this.draggedNodes.map((n) => n.id),\n point,\n delta\n );\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Handle mouse up - end drag\n */\n handleMouseUp(event: InputEvent): boolean {\n if (this.dragStartPoint === null) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const wasDragging = this.isDragging;\n\n if (this.isDragging) {\n // Restore selected state\n for (const node of this.draggedNodes) {\n node.state = 'selected';\n }\n this.emit(\n 'dragend',\n this.draggedNodes.map((n) => n.id),\n point\n );\n if (this.draggedGroupSelection) {\n this.selectionManager.clearSelection();\n }\n }\n\n this.reset();\n this.renderer.markDirty();\n\n return wasDragging;\n }\n\n /**\n * Cancel current drag operation\n */\n cancelDrag(): void {\n if (this.isDragging) {\n // Restore original positions\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (initial !== undefined) {\n node.x = initial.x;\n node.y = initial.y;\n }\n node.state = 'selected';\n }\n // Restore control points for fully-connected editable polyline edges\n for (const [edgeId, points] of this.initialControlPointsForFullyConnected) {\n const edge = this.renderer.getEdge(edgeId);\n if (edge) {\n edge.controlPoints = clonePoints(points);\n }\n }\n }\n\n this.reset();\n this.renderer.markDirty();\n }\n\n private addDraggedNode(node: Node): void {\n if (this.initialPositions.has(node.id)) {\n return;\n }\n this.draggedNodes.push(node);\n this.initialPositions.set(node.id, { x: node.x, y: node.y });\n }\n\n private reset(): void {\n this.isDragging = false;\n this.draggedNodes = [];\n this.dragStartPoint = null;\n this.lastDragPoint = null;\n this.initialPositions.clear();\n this.editableBendFollow.clear();\n this.editablePolylineFullyConnectedEdges.clear();\n this.initialControlPointsForFullyConnected.clear();\n this.alignmentGuides = [];\n this.draggedGroupSelection = false;\n // Note: _handledMouseDown is reset at the start of next handleMouseDown\n // to prevent click handler from firing after mouseup\n }\n\n private buildEditableBendFollowBindings(): void {\n this.editableBendFollow.clear();\n this.editablePolylineFullyConnectedEdges.clear();\n this.initialControlPointsForFullyConnected.clear();\n const draggedIds = new Set(this.draggedNodes.map((node) => node.id));\n const nodeBindings = new Map<string, Array<{ edgeId: string; controlPointIndex: number; axis: 'vertical' | 'horizontal' }>>();\n\n // Single pass: collect fully-connected edges and single-node bindings\n for (const edge of this.renderer.edges.values()) {\n if (!edge.hasEditableControlPoints()) {\n continue;\n }\n\n const isFromDragged = draggedIds.has(edge.from.nodeId);\n const isToDragged = draggedIds.has(edge.to.nodeId);\n\n if (isFromDragged && isToDragged) {\n this.editablePolylineFullyConnectedEdges.add(edge.id);\n this.initialControlPointsForFullyConnected.set(edge.id, clonePoints(edge.controlPoints!));\n continue;\n }\n\n for (const node of this.draggedNodes) {\n const isFrom = edge.from.nodeId === node.id;\n const isTo = edge.to.nodeId === node.id;\n if (!isFrom && !isTo) {\n continue;\n }\n\n const oppositeNodeId = isFrom ? edge.to.nodeId : edge.from.nodeId;\n if (draggedIds.has(oppositeNodeId)) {\n continue;\n }\n\n const controlPointIndex = isFrom ? 0 : edge.controlPoints!.length - 1;\n const nearestPoint = edge.controlPoints![controlPointIndex]!;\n const endpoint = isFrom ? edge.startPoint : edge.endPoint;\n const deltaX = Math.abs(nearestPoint.x - endpoint.x);\n const deltaY = Math.abs(nearestPoint.y - endpoint.y);\n\n if (deltaX <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE && deltaY <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE) {\n continue;\n }\n\n let axis: 'vertical' | 'horizontal' | null = null;\n if (deltaX <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE || deltaX <= deltaY) {\n axis = 'vertical';\n } else if (deltaY <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE || deltaY < deltaX) {\n axis = 'horizontal';\n }\n\n if (!axis) {\n continue;\n }\n\n const bindings = nodeBindings.get(node.id) ?? [];\n bindings.push({ edgeId: edge.id, controlPointIndex, axis });\n nodeBindings.set(node.id, bindings);\n }\n }\n\n for (const [nodeId, bindings] of nodeBindings) {\n if (bindings.length > 0) {\n this.editableBendFollow.set(nodeId, bindings);\n }\n }\n }\n\n private followNearestEditableBend(nodeId: string, deltaX: number, deltaY: number): void {\n const bindings = this.editableBendFollow.get(nodeId);\n if (!bindings || bindings.length === 0) {\n return;\n }\n\n for (const binding of bindings) {\n const edge = this.renderer.getEdge(binding.edgeId);\n if (!edge?.controlPoints) {\n continue;\n }\n if (binding.controlPointIndex < 0 || binding.controlPointIndex >= edge.controlPoints.length) {\n continue;\n }\n\n const nextControlPoints = [...edge.controlPoints];\n const point = { ...nextControlPoints[binding.controlPointIndex]! };\n if (binding.axis === 'vertical' && deltaX !== 0) {\n point.x += deltaX;\n } else if (binding.axis === 'horizontal' && deltaY !== 0) {\n point.y += deltaY;\n } else {\n continue;\n }\n nextControlPoints[binding.controlPointIndex] = point;\n edge.controlPoints = nextControlPoints;\n }\n }\n\n /**\n * For editable-polyline edges where both endpoints are dragged:\n * move all control points by the same delta to preserve relative positions.\n */\n private followEditableBendForFullyConnectedEdges(deltaX: number, deltaY: number): void {\n if (deltaX === 0 && deltaY === 0) {\n return;\n }\n for (const edgeId of this.editablePolylineFullyConnectedEdges) {\n const edge = this.renderer.getEdge(edgeId);\n if (!edge?.controlPoints || edge.controlPoints.length === 0) {\n continue;\n }\n const nextControlPoints = edge.controlPoints.map((p) => ({\n x: p.x + deltaX,\n y: p.y + deltaY,\n }));\n edge.controlPoints = nextControlPoints;\n }\n }\n\n private resolveAlignmentDelta(totalDelta: Point): Point {\n this.alignmentGuides = [];\n if (!this.alignToNodes) {\n return totalDelta;\n }\n if (this.draggedNodes.length === 0) {\n return totalDelta;\n }\n\n const draggedBounds = this.getDraggedBounds(totalDelta);\n if (!draggedBounds) {\n return totalDelta;\n }\n\n const tolerance = ALIGNMENT_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n const draggedIds = new Set(this.draggedNodes.map((node) => node.id));\n const searchPadding = tolerance * 2;\n const searchBounds: Bounds = {\n x: draggedBounds.x - searchPadding,\n y: draggedBounds.y - searchPadding,\n width: draggedBounds.width + searchPadding * 2,\n height: draggedBounds.height + searchPadding * 2,\n };\n\n const movingXLines = [\n { key: 'start', value: draggedBounds.x },\n { key: 'center', value: draggedBounds.x + draggedBounds.width / 2 },\n { key: 'end', value: draggedBounds.x + draggedBounds.width },\n ];\n const movingYLines = [\n { key: 'start', value: draggedBounds.y },\n { key: 'center', value: draggedBounds.y + draggedBounds.height / 2 },\n { key: 'end', value: draggedBounds.y + draggedBounds.height },\n ];\n\n let bestVertical: {\n offset: number;\n x: number;\n fromY: number;\n toY: number;\n distance: number;\n } | null = null;\n let bestHorizontal: {\n offset: number;\n y: number;\n fromX: number;\n toX: number;\n distance: number;\n } | null = null;\n\n for (const node of this.renderer.nodes.values()) {\n if (!node.visible || draggedIds.has(node.id)) {\n continue;\n }\n const bounds = node.getBounds();\n if (!rectsIntersect(searchBounds, bounds)) {\n continue;\n }\n const targetXLines = [\n { key: 'start', value: bounds.x },\n { key: 'center', value: bounds.x + bounds.width / 2 },\n { key: 'end', value: bounds.x + bounds.width },\n ];\n const targetYLines = [\n { key: 'start', value: bounds.y },\n { key: 'center', value: bounds.y + bounds.height / 2 },\n { key: 'end', value: bounds.y + bounds.height },\n ];\n\n for (const moving of movingXLines) {\n for (const target of targetXLines) {\n if (moving.key !== target.key) {\n continue;\n }\n const dist = Math.abs(moving.value - target.value);\n if (dist > tolerance) {\n continue;\n }\n if (!bestVertical || dist < bestVertical.distance) {\n bestVertical = {\n offset: target.value - moving.value,\n x: target.value,\n fromY: Math.min(draggedBounds.y, bounds.y),\n toY: Math.max(draggedBounds.y + draggedBounds.height, bounds.y + bounds.height),\n distance: dist,\n };\n }\n }\n }\n\n for (const moving of movingYLines) {\n for (const target of targetYLines) {\n if (moving.key !== target.key) {\n continue;\n }\n const dist = Math.abs(moving.value - target.value);\n if (dist > tolerance) {\n continue;\n }\n if (!bestHorizontal || dist < bestHorizontal.distance) {\n bestHorizontal = {\n offset: target.value - moving.value,\n y: target.value,\n fromX: Math.min(draggedBounds.x, bounds.x),\n toX: Math.max(draggedBounds.x + draggedBounds.width, bounds.x + bounds.width),\n distance: dist,\n };\n }\n }\n }\n }\n\n const result = { ...totalDelta };\n if (bestVertical) {\n result.x += bestVertical.offset;\n this.alignmentGuides.push({\n orientation: 'vertical',\n position: bestVertical.x,\n from: bestVertical.fromY,\n to: bestVertical.toY,\n });\n }\n if (bestHorizontal) {\n result.y += bestHorizontal.offset;\n this.alignmentGuides.push({\n orientation: 'horizontal',\n position: bestHorizontal.y,\n from: bestHorizontal.fromX,\n to: bestHorizontal.toX,\n });\n }\n\n return result;\n }\n\n private getDraggedBounds(delta: Point): Bounds | null {\n const sources: Bounds[] = [];\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (!initial) continue;\n sources.push({\n x: initial.x + delta.x,\n y: initial.y + delta.y,\n width: node.width,\n height: node.height,\n });\n }\n return mergeBounds(sources);\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { SelectionManager } from './SelectionManager';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { Bounds, Point } from '@/types';\nimport type { ResizeHandle } from '@/elements/Node';\nimport { distance } from '@/utils/geometry';\n\n/**\n * Resize events\n */\nexport interface ResizeEvents {\n resizeStart: [nodeId: string, handle: ResizeHandle, startBounds: Bounds];\n resize: [nodeId: string, bounds: Bounds, delta: Point];\n resizeEnd: [nodeId: string, bounds: Bounds];\n}\n\nexport interface ResizeManagerOptions {\n renderer: DiagramRenderer;\n selectionManager: SelectionManager;\n snapToGrid?: boolean;\n gridSize?: number;\n minSize?: number;\n}\n\n/**\n * Manages node resizing via corner handles\n */\nexport class ResizeManager extends EventEmitter<ResizeEvents> {\n private renderer: DiagramRenderer;\n private selectionManager: SelectionManager;\n private snapToGrid: boolean;\n private gridSize: number;\n private readonly minSize: number;\n private minWidth: number;\n private minHeight: number;\n\n private isResizing = false;\n private resizedNodeId: string | null = null;\n private handle: ResizeHandle | null = null;\n private startPoint: Point | null = null;\n private startBounds: Bounds | null = null;\n private _handledMouseDown = false;\n\n constructor(options: ResizeManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.selectionManager = options.selectionManager;\n this.snapToGrid = options.snapToGrid ?? false;\n this.gridSize = options.gridSize ?? 20;\n this.minSize = options.minSize ?? 20;\n this.minWidth = this.minSize;\n this.minHeight = this.minSize;\n }\n\n /**\n * Check if currently resizing\n */\n get resizing(): boolean {\n return this.isResizing;\n }\n\n /**\n * Check if last mousedown was handled (for skipping click handling)\n */\n get handledMouseDown(): boolean {\n return this._handledMouseDown;\n }\n\n /**\n * Enable/disable snap to grid\n */\n setSnapToGrid(enabled: boolean, gridSize?: number): void {\n this.snapToGrid = enabled;\n if (gridSize !== undefined) {\n this.gridSize = gridSize;\n }\n }\n\n /**\n * Handle mouse down - start potential resize\n */\n handleMouseDown(event: InputEvent): boolean {\n this._handledMouseDown = false;\n\n const selectedIds = Array.from(this.selectionManager.selectedIds);\n if (selectedIds.length !== 1) {\n return false;\n }\n\n const node = this.renderer.getNode(selectedIds[0]!);\n if (!node) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const hit = node.hitTestResizeHandle(point);\n if (!hit) {\n return false;\n }\n\n this.resizedNodeId = node.id;\n this.handle = hit;\n this.startPoint = point;\n this.startBounds = node.getBounds();\n const contentMinSize = node.getContentMinSize(this.renderer.getContext());\n this.minWidth = Math.max(this.minSize, contentMinSize.width);\n this.minHeight = Math.max(this.minSize, contentMinSize.height);\n return true;\n }\n\n /**\n * Handle mouse move - update resize\n */\n handleMouseMove(event: InputEvent): boolean {\n if (!this.startPoint || !this.startBounds || !this.resizedNodeId || !this.handle) {\n return false;\n }\n\n const node = this.renderer.getNode(this.resizedNodeId);\n if (!node) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n\n if (!this.isResizing) {\n const dist = distance(point, this.startPoint);\n if (dist < 3) {\n return false;\n }\n this.isResizing = true;\n this._handledMouseDown = true;\n node.state = 'dragging';\n this.emit('resizeStart', node.id, this.handle, this.startBounds);\n }\n\n const bounds = this.calculateBounds(point);\n node.x = bounds.x;\n node.y = bounds.y;\n node.width = bounds.width;\n node.height = bounds.height;\n\n this.emit('resize', node.id, bounds, {\n x: bounds.x - this.startBounds.x,\n y: bounds.y - this.startBounds.y,\n });\n this.renderer.markDirty();\n return true;\n }\n\n /**\n * Handle mouse up - end resize\n */\n handleMouseUp(): boolean {\n if (!this.startPoint || !this.startBounds || !this.resizedNodeId) {\n return false;\n }\n\n const node = this.renderer.getNode(this.resizedNodeId);\n const wasResizing = this.isResizing;\n if (this.isResizing && node) {\n node.state = 'selected';\n this.emit('resizeEnd', node.id, node.getBounds());\n }\n\n this.reset();\n this.renderer.markDirty();\n return wasResizing;\n }\n\n /**\n * Cancel current resize operation\n */\n cancelResize(): void {\n if (this.isResizing && this.resizedNodeId && this.startBounds) {\n const node = this.renderer.getNode(this.resizedNodeId);\n if (node) {\n node.x = this.startBounds.x;\n node.y = this.startBounds.y;\n node.width = this.startBounds.width;\n node.height = this.startBounds.height;\n node.state = 'selected';\n }\n }\n\n this.reset();\n this.renderer.markDirty();\n }\n\n private calculateBounds(point: Point): Bounds {\n const start = this.startBounds!;\n const handle = this.handle!;\n const dx = point.x - this.startPoint!.x;\n const dy = point.y - this.startPoint!.y;\n\n let x = start.x;\n let y = start.y;\n let width = start.width;\n let height = start.height;\n\n if (handle.includes('e')) {\n width = start.width + dx;\n }\n if (handle.includes('s')) {\n height = start.height + dy;\n }\n if (handle.includes('w')) {\n x = start.x + dx;\n width = start.width - dx;\n }\n if (handle.includes('n')) {\n y = start.y + dy;\n height = start.height - dy;\n }\n\n ({ x, y, width, height } = this.applyMinSize(x, y, width, height, start, handle));\n\n if (this.snapToGrid) {\n const snap = (value: number): number => Math.round(value / this.gridSize) * this.gridSize;\n let right = x + width;\n let bottom = y + height;\n\n if (handle.includes('w')) {\n x = snap(x);\n }\n if (handle.includes('e')) {\n right = snap(right);\n }\n if (handle.includes('n')) {\n y = snap(y);\n }\n if (handle.includes('s')) {\n bottom = snap(bottom);\n }\n\n width = right - x;\n height = bottom - y;\n ({ x, y, width, height } = this.applyMinSize(x, y, width, height, start, handle));\n }\n\n return { x, y, width, height };\n }\n\n private applyMinSize(\n x: number,\n y: number,\n width: number,\n height: number,\n start: Bounds,\n handle: ResizeHandle\n ): Bounds {\n if (width < this.minWidth) {\n width = this.minWidth;\n if (handle.includes('w')) {\n x = start.x + start.width - this.minWidth;\n }\n }\n\n if (height < this.minHeight) {\n height = this.minHeight;\n if (handle.includes('n')) {\n y = start.y + start.height - this.minHeight;\n }\n }\n\n return { x, y, width, height };\n }\n\n private reset(): void {\n this.isResizing = false;\n this.resizedNodeId = null;\n this.handle = null;\n this.startPoint = null;\n this.startBounds = null;\n this.minWidth = this.minSize;\n this.minHeight = this.minSize;\n }\n}\n","import type { Bounds } from '@/types';\n\nexport interface BoundsSource {\n visible: boolean;\n getBounds(): Bounds;\n}\n\nexport interface ContentBoundsInput {\n nodes?: Iterable<BoundsSource>;\n edges?: Iterable<BoundsSource>;\n groups?: Iterable<BoundsSource>;\n includeInvisible?: boolean;\n}\n\nexport function getContentBounds({\n nodes,\n edges,\n groups,\n includeInvisible = false,\n}: ContentBoundsInput): Bounds | null {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let hasContent = false;\n\n const consider = (source: BoundsSource): void => {\n if (!includeInvisible && !source.visible) {\n return;\n }\n const bounds = source.getBounds();\n minX = Math.min(minX, bounds.x);\n minY = Math.min(minY, bounds.y);\n maxX = Math.max(maxX, bounds.x + bounds.width);\n maxY = Math.max(maxY, bounds.y + bounds.height);\n hasContent = true;\n };\n\n if (nodes) {\n for (const node of nodes) {\n consider(node);\n }\n }\n\n if (edges) {\n for (const edge of edges) {\n consider(edge);\n }\n }\n\n if (groups) {\n for (const group of groups) {\n consider(group);\n }\n }\n\n if (!hasContent) {\n return null;\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { InputEvent, WheelInputEvent, PanInputEvent, PinchInputEvent } from '@/events/InputHandler';\nimport type { Bounds, Point } from '@/types';\nimport { getContentBounds } from '@/utils/contentBounds';\n\n/**\n * Navigation events\n */\nexport interface NavigationEvents {\n panStart: [];\n pan: [offsetX: number, offsetY: number];\n panEnd: [];\n zoomChange: [zoom: number, center: Point];\n}\n\nexport interface NavigationManagerOptions {\n renderer: DiagramRenderer;\n zoomSensitivity?: number;\n panButton?: number;\n}\n\n/**\n * Manages canvas panning and zooming\n */\nexport class NavigationManager extends EventEmitter<NavigationEvents> {\n private renderer: DiagramRenderer;\n private readonly zoomSensitivity: number;\n private readonly panButton: number;\n\n private isPanning = false;\n private panStart: Point | null = null;\n private spacePressed = false;\n\n constructor(options: NavigationManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.zoomSensitivity = options.zoomSensitivity ?? 0.001;\n this.panButton = options.panButton ?? 1; // Middle mouse button\n }\n\n /**\n * Check if currently panning\n */\n get panning(): boolean {\n return this.isPanning;\n }\n\n /**\n * Handle wheel event for zooming\n */\n handleWheel(event: WheelInputEvent): void {\n const sensitivity = event.ctrlKey ? this.zoomSensitivity * 0.2 : this.zoomSensitivity;\n const zoomFactor = 1 - event.deltaY * sensitivity;\n const oldZoom = this.renderer.zoom;\n const oldOffsetX = this.renderer.offsetX;\n const oldOffsetY = this.renderer.offsetY;\n\n // World position under cursor (calculated with old zoom)\n const worldX = event.worldX;\n const worldY = event.worldY;\n\n // Apply new zoom\n this.renderer.zoom = oldZoom * zoomFactor;\n const actualNewZoom = this.renderer.zoom; // may be clamped by min/max\n\n // Adjust offset to keep cursor at same world position\n // Formula: newOffset = oldOffset + worldPos * (oldZoom - newZoom)\n this.renderer.offsetX = oldOffsetX + worldX * (oldZoom - actualNewZoom);\n this.renderer.offsetY = oldOffsetY + worldY * (oldZoom - actualNewZoom);\n\n this.emit('zoomChange', this.renderer.zoom, { x: worldX, y: worldY });\n }\n\n /**\n * Handle touch pan gesture\n */\n handlePanGesture(event: PanInputEvent): void {\n this.renderer.offsetX += event.deltaX;\n this.renderer.offsetY += event.deltaY;\n this.emit('pan', this.renderer.offsetX, this.renderer.offsetY);\n }\n\n /**\n * Handle touch pinch gesture\n */\n handlePinch(event: PinchInputEvent): void {\n const oldZoom = this.renderer.zoom;\n const oldOffsetX = this.renderer.offsetX;\n const oldOffsetY = this.renderer.offsetY;\n\n const worldX = event.worldX;\n const worldY = event.worldY;\n\n this.renderer.zoom = oldZoom * event.scale;\n const actualNewZoom = this.renderer.zoom;\n\n this.renderer.offsetX = oldOffsetX + worldX * (oldZoom - actualNewZoom);\n this.renderer.offsetY = oldOffsetY + worldY * (oldZoom - actualNewZoom);\n\n this.emit('zoomChange', this.renderer.zoom, { x: worldX, y: worldY });\n }\n\n /**\n * Handle mouse down for panning\n */\n handleMouseDown(event: InputEvent): boolean {\n // Middle mouse button or space+left click\n if (event.button === this.panButton || (this.spacePressed && event.button === 0)) {\n this.startPan(event);\n return true;\n }\n return false;\n }\n\n /**\n * Handle mouse move for panning\n */\n handleMouseMove(event: InputEvent): boolean {\n if (!this.isPanning || this.panStart === null) {\n return false;\n }\n\n const dx = event.screenX - this.panStart.x;\n const dy = event.screenY - this.panStart.y;\n\n this.renderer.offsetX += dx;\n this.renderer.offsetY += dy;\n\n this.panStart = { x: event.screenX, y: event.screenY };\n this.emit('pan', this.renderer.offsetX, this.renderer.offsetY);\n\n return true;\n }\n\n /**\n * Handle mouse up for panning\n */\n handleMouseUp(_event: InputEvent): boolean {\n if (!this.isPanning) {\n return false;\n }\n\n this.endPan();\n return true;\n }\n\n /**\n * Handle key down for space panning\n */\n handleKeyDown(event: KeyboardEvent): void {\n if (event.code === 'Space' && !this.spacePressed) {\n this.spacePressed = true;\n }\n }\n\n /**\n * Handle key up for space panning\n */\n handleKeyUp(event: KeyboardEvent): void {\n if (event.code === 'Space') {\n this.spacePressed = false;\n if (this.isPanning) {\n this.endPan();\n }\n }\n }\n\n /**\n * Set zoom level\n */\n setZoom(zoom: number, center?: Point): void {\n const centerPoint = center ?? {\n x: this.renderer.width / 2,\n y: this.renderer.height / 2,\n };\n\n const oldZoom = this.renderer.zoom;\n const oldOffsetX = this.renderer.offsetX;\n const oldOffsetY = this.renderer.offsetY;\n\n // Get world position at center point\n const worldPos = this.renderer.screenToWorld(centerPoint.x, centerPoint.y);\n\n // Apply new zoom\n this.renderer.zoom = zoom;\n const actualNewZoom = this.renderer.zoom; // may be clamped by min/max\n\n // Adjust offset to keep center point at same world position\n this.renderer.offsetX = oldOffsetX + worldPos.x * (oldZoom - actualNewZoom);\n this.renderer.offsetY = oldOffsetY + worldPos.y * (oldZoom - actualNewZoom);\n\n this.emit('zoomChange', this.renderer.zoom, centerPoint);\n }\n\n /**\n * Fit all content in view\n */\n fitToView(padding = 50): void {\n const bounds = getContentBounds({\n nodes: this.renderer.nodes.values(),\n includeInvisible: true,\n });\n if (bounds === null) {\n return;\n }\n\n this.zoomToRect(bounds, padding);\n }\n\n /**\n * Zoom to fit a specific rectangle\n */\n zoomToRect(rect: Bounds, padding = 50): void {\n const viewWidth = this.renderer.width - padding * 2;\n const viewHeight = this.renderer.height - padding * 2;\n\n const scaleX = viewWidth / rect.width;\n const scaleY = viewHeight / rect.height;\n const scale = Math.min(scaleX, scaleY, 1); // Don't zoom in beyond 100%\n\n this.renderer.zoom = scale;\n\n // Center the content\n const contentCenterX = rect.x + rect.width / 2;\n const contentCenterY = rect.y + rect.height / 2;\n\n this.renderer.offsetX = this.renderer.width / 2 - contentCenterX * scale;\n this.renderer.offsetY = this.renderer.height / 2 - contentCenterY * scale;\n\n this.emit('zoomChange', this.renderer.zoom, { x: contentCenterX, y: contentCenterY });\n }\n\n /**\n * Zoom to a selection bounds\n */\n zoomToSelection(bounds: Bounds, padding = 50): void {\n this.zoomToRect(bounds, padding);\n }\n\n /**\n * Reset view to default\n */\n resetView(): void {\n this.renderer.zoom = 1;\n this.renderer.offsetX = 0;\n this.renderer.offsetY = 0;\n this.emit('zoomChange', 1, { x: 0, y: 0 });\n }\n\n startPan(event: InputEvent): void {\n this.isPanning = true;\n this.panStart = { x: event.screenX, y: event.screenY };\n this.emit('panStart');\n }\n\n private endPan(): void {\n this.isPanning = false;\n this.panStart = null;\n this.emit('panEnd');\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { AnchorId, Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { EdgeEndpoint, Point } from '@/types';\nimport {\n ANCHOR_PORT_PREFIX,\n EDGE_AXIS_MAGNET_SCREEN_TOLERANCE,\n EDGE_ADD_CONTROL_RADIUS,\n EDGE_CONTROL_POINT_RADIUS,\n EDGE_HANDLE_RADIUS,\n OUTLINE_SNAP_SCREEN_TOLERANCE,\n ANCHOR_POINT_HITBOX_RADIUS,\n ANCHOR_POINT_HOVER_RADIUS,\n ANCHOR_POINT_RADIUS,\n BEZIER_MAX_OFFSET,\n} from '@/constants';\nimport { clonePoints, distance } from '@/utils/geometry';\n\n/**\n * Connection events\n */\nexport interface ConnectionEvents {\n connectionStart: [fromNode: Node];\n connectionMove: [fromPoint: Point, toPoint: Point];\n connectionEnd: [edge: Edge | null];\n connect: [edge: Edge];\n edgeReconnectStart: [edge: Edge, endpoint: 'start' | 'end', original: EdgeEndpoint];\n edgeReconnect: [edge: Edge, endpoint: 'start' | 'end'];\n}\n\nexport type ConnectionValidator = (sourceNodeId: string, targetNodeId: string) => boolean;\n\nexport interface ConnectionManagerOptions {\n renderer: DiagramRenderer;\n createEdge: (from: EdgeEndpoint, to: EdgeEndpoint) => Edge;\n addEdge?: (edge: Edge) => void;\n snapToGrid?: boolean;\n gridSize?: number;\n /** When true, edges can be attached anywhere on the shape outline (not just ports) */\n attachToOutline?: boolean;\n}\n\n/**\n * Manages port-to-port connection creation\n */\nexport class ConnectionManager extends EventEmitter<ConnectionEvents> {\n private renderer: DiagramRenderer;\n private readonly createEdge: (from: EdgeEndpoint, to: EdgeEndpoint) => Edge;\n private readonly addEdge: (edge: Edge) => void;\n private _connectionValidator: ConnectionValidator | null = null;\n\n private isConnecting = false;\n private sourceNode: Node | null = null;\n private sourcePoint: Point | null = null;\n private previewEndpoint: Point | null = null;\n private sourceAnchorId: string | null = null;\n private hoverNodeId: string | null = null;\n private hoverAnchorId: string | null = null;\n private hoverDisabled = false;\n private reconnectPoint: Point | null = null;\n private previewTargetAnchorId: string | null = null;\n private sourceOutlineParam: number | null = null;\n private previewTargetOutlineParam: number | null = null;\n private previewTargetNodeId: string | null = null;\n\n // Edge reconnection state\n private isReconnecting = false;\n private reconnectingEdge: Edge | null = null;\n private reconnectingEndpoint: 'start' | 'end' | null = null;\n private originalEdgeEndpoint: EdgeEndpoint | null = null;\n private reconnectingOutlineParam: number | null = null;\n private reconnectingTargetNodeId: string | null = null;\n private activeControlPointDrag: { edge: Edge; index: number } | null = null;\n private snapToGrid: boolean;\n private gridSize: number;\n private attachToOutline: boolean;\n\n constructor(options: ConnectionManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.createEdge = options.createEdge;\n this.addEdge = options.addEdge ?? ((edge): void => this.renderer.addEdge(edge));\n this.snapToGrid = options.snapToGrid ?? false;\n this.gridSize = options.gridSize ?? 20;\n this.attachToOutline = options.attachToOutline ?? false;\n }\n\n /**\n * Enable/disable attach-to-outline mode (edges attach anywhere on shape contour)\n */\n setAttachToOutline(enabled: boolean): void {\n this.attachToOutline = enabled;\n this.renderer.attachToOutline = enabled;\n }\n\n /**\n * Enable/disable snap to grid for editable polyline control points.\n */\n setSnapToGrid(enabled: boolean, gridSize?: number): void {\n this.snapToGrid = enabled;\n if (gridSize !== undefined) {\n this.gridSize = gridSize;\n }\n }\n\n /**\n * Set a validator that determines whether a connection between two nodes is allowed.\n * When set, disallowed targets show forbidden styling and connections are blocked.\n */\n set connectionValidator(validator: ConnectionValidator | null) {\n this._connectionValidator = validator;\n }\n\n /**\n * Check if currently creating a connection\n */\n get connecting(): boolean {\n return this.isConnecting || this.isReconnecting;\n }\n\n /**\n * Check if currently reconnecting an edge\n */\n get reconnecting(): boolean {\n return this.isReconnecting;\n }\n\n /**\n * Get the edge being reconnected (to hide it during preview)\n */\n get reconnectingEdgeId(): string | null {\n return this.reconnectingEdge?.id ?? null;\n }\n\n /**\n * Current preview endpoint\n */\n get previewEnd(): Point | null {\n return this.previewEndpoint;\n }\n\n /**\n * Disable hover and clear state (used when dragging starts)\n */\n disableHover(): void {\n this.hoverDisabled = true;\n if (this.hoverNodeId !== null || this.hoverAnchorId !== null) {\n this.hoverNodeId = null;\n this.hoverAnchorId = null;\n this.renderer.markDirty();\n }\n }\n\n /**\n * Re-enable hover (used when dragging ends)\n */\n enableHover(): void {\n this.hoverDisabled = false;\n }\n\n /**\n * Try to start connection from a hovered anchor point.\n * When attachToOutline + Shift: start from anywhere on node outline.\n * Otherwise: requires clicking on an anchor/port so that node drag still works.\n */\n tryStartConnectionAtPoint(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n const node = this.getNodeAtPoint(point, false);\n if (!node) {\n return false;\n }\n\n if (this.attachToOutline && event.shiftKey) {\n const { point: outlinePoint, param } = node.getClosestPointOnOutline(point);\n this.sourceNode = node;\n this.isConnecting = true;\n this.sourceAnchorId = null;\n this.sourcePoint = outlinePoint;\n this.sourceOutlineParam = param;\n this.previewEndpoint = point;\n this.emit('connectionStart', node);\n this.renderer.markDirty();\n return true;\n }\n\n // Try to find anchor at point (for precise click on port)\n const hover = this.getAnchorAtPoint(node, point);\n if (hover) {\n this.sourceNode = node;\n this.isConnecting = true;\n this.sourceAnchorId = hover.id;\n this.sourcePoint = hover.point;\n this.previewEndpoint = point;\n if (this.attachToOutline) {\n const { param } = node.getClosestPointOnOutline(point);\n this.sourceOutlineParam = param;\n } else {\n this.sourceOutlineParam = null;\n }\n this.emit('connectionStart', node);\n this.renderer.markDirty();\n return true;\n }\n\n return false;\n }\n\n /**\n * Try to start edge reconnection from handle\n */\n tryStartReconnection(event: InputEvent): boolean {\n if (this.tryStartEditableControlInteraction(event)) {\n return true;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const handleRadius = EDGE_HANDLE_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n\n // Check selected edges for handle hit\n for (const edge of this.renderer.edges.values()) {\n if (edge.state !== 'selected') {\n continue;\n }\n\n if (edge.hitTestStartHandle(point, handleRadius)) {\n this.isReconnecting = true;\n this.reconnectingEdge = edge;\n this.reconnectingEdge.autoUpdateEndpoints = false;\n this.reconnectingEndpoint = 'start';\n this.originalEdgeEndpoint = { ...edge.from };\n this.emit('edgeReconnectStart', edge, 'start', this.originalEdgeEndpoint);\n // Update edge to follow cursor immediately\n this.updateReconnectingEdge(point);\n return true;\n }\n\n if (edge.hitTestEndHandle(point, handleRadius)) {\n this.isReconnecting = true;\n this.reconnectingEdge = edge;\n this.reconnectingEdge.autoUpdateEndpoints = false;\n this.reconnectingEndpoint = 'end';\n this.originalEdgeEndpoint = { ...edge.to };\n this.emit('edgeReconnectStart', edge, 'end', this.originalEdgeEndpoint);\n // Update edge to follow cursor immediately\n this.updateReconnectingEdge(point);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Update the reconnecting edge to follow cursor\n */\n private updateReconnectingEdge(point: Point): void {\n if (!this.reconnectingEdge) return;\n\n const edge = this.reconnectingEdge;\n const fromNode = this.renderer.getNode(edge.from.nodeId);\n const toNode = this.renderer.getNode(edge.to.nodeId);\n\n let snappedPoint = point;\n let snappedDir: string | undefined;\n let targetNode = this.getNodeAtPoint(point, true);\n\n if (this.attachToOutline) {\n const tolerance = OUTLINE_SNAP_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n const toleranceSq = tolerance * tolerance;\n let bestDistSq = Infinity;\n let bestResult: { node: Node; point: Point; param: number } | null = null;\n\n for (const node of this.renderer.nodes.values()) {\n if (!node.visible) continue;\n const { point: outlinePoint, param } = node.getClosestPointOnOutline(point);\n const dx = point.x - outlinePoint.x;\n const dy = point.y - outlinePoint.y;\n const distSq = dx * dx + dy * dy;\n if (distSq <= toleranceSq && distSq < bestDistSq) {\n bestDistSq = distSq;\n bestResult = { node, point: outlinePoint, param };\n }\n }\n\n if (bestResult) {\n targetNode = bestResult.node;\n snappedPoint = bestResult.point;\n this.reconnectingOutlineParam = bestResult.param;\n this.reconnectingTargetNodeId = bestResult.node.id;\n snappedDir = this.getDirectionFromOutlineParam(bestResult.param, bestResult.node);\n\n const otherNode = this.reconnectingEndpoint === 'start' ? toNode : fromNode;\n if (otherNode) {\n const alignRef = edge.isEditablePolyline()\n ? this.getNearestBendPointForAxisAlignment(edge, this.reconnectingEndpoint!)\n : this.reconnectingEndpoint === 'start'\n ? this.getTargetPointForReconnect(edge, toNode!, 'to', snappedPoint)\n : this.getTargetPointForReconnect(edge, fromNode!, 'from', snappedPoint);\n snappedPoint = this.applyAxisAlignmentToPoint(snappedPoint, alignRef);\n const reprojected = targetNode.getClosestPointOnOutline(snappedPoint);\n snappedPoint = reprojected.point;\n this.reconnectingOutlineParam = reprojected.param;\n snappedDir = this.getDirectionFromOutlineParam(reprojected.param, targetNode);\n }\n } else {\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n }\n } else if (targetNode) {\n const nearestAnchor = targetNode.getNearestAnchor(point);\n if (nearestAnchor) {\n snappedPoint = nearestAnchor.point;\n snappedDir = nearestAnchor.id.split(':')[0];\n }\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n } else {\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n }\n\n this.reconnectPoint = snappedPoint;\n\n if (this.reconnectingEndpoint === 'start') {\n if (toNode) {\n const target = this.getTargetPointForReconnect(edge, toNode, 'to', snappedPoint);\n const toDir = this.getTargetDirForReconnect(edge, toNode, 'to');\n edge.updateEndpoints(snappedPoint, target, snappedDir, toDir);\n }\n } else {\n if (fromNode) {\n const start = this.getTargetPointForReconnect(edge, fromNode, 'from', snappedPoint);\n const fromDir = this.getTargetDirForReconnect(edge, fromNode, 'from');\n edge.updateEndpoints(start, snappedPoint, fromDir, snappedDir);\n }\n }\n\n this.renderer.markDirty();\n }\n\n private getTargetPointForReconnect(\n edge: Edge,\n node: Node,\n endpoint: 'from' | 'to',\n fallbackPoint: Point\n ): Point {\n const ep = endpoint === 'from' ? edge.from : edge.to;\n if (this.attachToOutline && ep.outlineParam !== undefined) {\n return node.getConnectionPointAtOutlineParam(ep.outlineParam);\n }\n const anchorId = ep.portId?.replace(ANCHOR_PORT_PREFIX, '');\n if (anchorId) {\n return node.getAnchorPointById(anchorId) ?? node.getConnectionPoint(fallbackPoint);\n }\n return node.getConnectionPoint(fallbackPoint);\n }\n\n private getTargetDirForReconnect(\n edge: Edge,\n node: Node,\n endpoint: 'from' | 'to'\n ): string | undefined {\n const ep = endpoint === 'from' ? edge.from : edge.to;\n if (this.attachToOutline && ep.outlineParam !== undefined) {\n return this.getDirectionFromOutlineParam(ep.outlineParam, node);\n }\n const anchorId = ep.portId?.replace(ANCHOR_PORT_PREFIX, '');\n return anchorId?.split(':')[0];\n }\n\n private getDirectionFromOutlineParam(param: number, _node: Node): string {\n const p = ((param % 1) + 1) % 1;\n if (p < 0.25) return 'top';\n if (p < 0.5) return 'right';\n if (p < 0.75) return 'bottom';\n return 'left';\n }\n\n /**\n * For editable polyline: return the nearest bend point for axis alignment.\n * When reconnecting 'end', use last control point (or start). When reconnecting 'start', use first control point (or end).\n */\n private getNearestBendPointForAxisAlignment(edge: Edge, endpoint: 'start' | 'end'): Point {\n const cps = edge.isEditablePolyline()\n ? (edge.controlPoints ?? edge.getEditableControlPoints())\n : [];\n if (endpoint === 'end') {\n return cps.length > 0 ? cps[cps.length - 1]! : edge.startPoint;\n }\n return cps.length > 0 ? cps[0]! : edge.endPoint;\n }\n\n /**\n * When attachToOutline: snap moving point to horizontal/vertical alignment with fixed point.\n */\n private applyAxisAlignmentToPoint(moving: Point, fixed: Point): Point {\n const tolerance = EDGE_AXIS_MAGNET_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n let x = moving.x;\n let y = moving.y;\n if (Math.abs(moving.x - fixed.x) <= tolerance) {\n x = fixed.x;\n }\n if (Math.abs(moving.y - fixed.y) <= tolerance) {\n y = fixed.y;\n }\n return { x, y };\n }\n\n /**\n * Handle mouse move during connection\n */\n handleMouseMove(event: InputEvent): boolean {\n if (this.activeControlPointDrag) {\n const controlPoints = this.activeControlPointDrag.edge.controlPoints\n ? [...this.activeControlPointDrag.edge.controlPoints]\n : this.activeControlPointDrag.edge.getEditableControlPoints();\n if (this.activeControlPointDrag.index < controlPoints.length) {\n const rawPoint = this.snapPoint({ x: event.worldX, y: event.worldY });\n const magnetized = this.applyAxisMagnet(\n this.activeControlPointDrag.edge,\n controlPoints,\n this.activeControlPointDrag.index,\n rawPoint\n );\n controlPoints[this.activeControlPointDrag.index] = magnetized;\n this.activeControlPointDrag.edge.controlPoints = controlPoints;\n }\n return true;\n }\n\n // Handle edge reconnection\n if (this.isReconnecting && this.reconnectingEdge) {\n const point = { x: event.worldX, y: event.worldY };\n\n // Update edge to follow cursor\n this.updateReconnectingEdge(point);\n\n return true;\n }\n\n if (!this.isConnecting) {\n this.updateHover({ x: event.worldX, y: event.worldY });\n return false;\n }\n\n const cursorPoint = { x: event.worldX, y: event.worldY };\n\n let snappedPoint = cursorPoint;\n this.previewTargetAnchorId = null;\n this.previewTargetOutlineParam = null;\n this.previewTargetNodeId = null;\n let targetNode = this.getNodeAtPoint(cursorPoint, false);\n\n if (this.attachToOutline) {\n const tolerance = OUTLINE_SNAP_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n const toleranceSq = tolerance * tolerance;\n let bestDistSq = Infinity;\n let bestResult: { node: Node; point: Point; param: number } | null = null;\n\n for (const node of this.renderer.nodes.values()) {\n if (!node.visible || !this.isCompatibleTarget(node)) continue;\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, node.id);\n if (forbidden) continue;\n\n const { point: outlinePoint, param } = node.getClosestPointOnOutline(cursorPoint);\n const dx = cursorPoint.x - outlinePoint.x;\n const dy = cursorPoint.y - outlinePoint.y;\n const distSq = dx * dx + dy * dy;\n if (distSq <= toleranceSq && distSq < bestDistSq) {\n bestDistSq = distSq;\n bestResult = { node, point: outlinePoint, param };\n }\n }\n\n if (bestResult) {\n targetNode = bestResult.node;\n snappedPoint = bestResult.point;\n this.previewTargetOutlineParam = bestResult.param;\n this.previewTargetNodeId = bestResult.node.id;\n\n if (this.sourcePoint) {\n snappedPoint = this.applyAxisAlignmentToPoint(snappedPoint, this.sourcePoint);\n const reprojected = bestResult.node.getClosestPointOnOutline(snappedPoint);\n snappedPoint = reprojected.point;\n this.previewTargetOutlineParam = reprojected.param;\n }\n }\n } else if (targetNode && this.isCompatibleTarget(targetNode)) {\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, targetNode.id);\n if (!forbidden) {\n const nearestAnchor = targetNode.getNearestAnchor(cursorPoint);\n if (nearestAnchor) {\n snappedPoint = nearestAnchor.point;\n this.previewTargetAnchorId = nearestAnchor.id;\n }\n }\n }\n\n if (targetNode) {\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, targetNode.id);\n this.setCursor(forbidden ? 'not-allowed' : 'crosshair');\n } else {\n this.setCursor('crosshair');\n }\n\n this.previewEndpoint = snappedPoint;\n if (this.sourceNode && !this.sourceAnchorId && !this.sourceOutlineParam) {\n this.sourcePoint = this.sourceNode.getConnectionPoint(this.previewEndpoint);\n } else if (this.sourceNode && this.sourceOutlineParam !== null) {\n this.sourcePoint = this.sourceNode.getConnectionPointAtOutlineParam(this.sourceOutlineParam);\n }\n\n this.emit('connectionMove', this.sourcePoint!, this.previewEndpoint);\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Remove editable polyline bend by double click.\n */\n handleDoubleClick(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n const radius = EDGE_CONTROL_POINT_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const radiusSq = radius * radius;\n const edges = [...this.renderer.edges.values()];\n\n for (let i = edges.length - 1; i >= 0; i--) {\n const edge = edges[i]!;\n if (edge.state !== 'selected' || !edge.hasEditableControlPoints()) {\n continue;\n }\n\n const cps = edge.controlPoints!;\n for (let i = 0; i < cps.length; i++) {\n const controlPoint = cps[i]!;\n const dx = point.x - controlPoint.x;\n const dy = point.y - controlPoint.y;\n if (dx * dx + dy * dy > radiusSq) {\n continue;\n }\n\n const next = clonePoints(cps);\n next.splice(i, 1);\n edge.controlPoints = next.length > 0 ? next : undefined;\n if (\n this.activeControlPointDrag &&\n this.activeControlPointDrag.edge.id === edge.id &&\n this.activeControlPointDrag.index === i\n ) {\n this.activeControlPointDrag = null;\n }\n this.renderer.markDirty();\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Handle mouse up to complete or cancel connection\n */\n handleMouseUp(event: InputEvent): boolean {\n if (this.activeControlPointDrag) {\n this.activeControlPointDrag = null;\n this.renderer.markDirty();\n return true;\n }\n\n // Handle edge reconnection completion\n if (this.isReconnecting && this.reconnectingEdge) {\n const point = { x: event.worldX, y: event.worldY };\n let reconnected = false;\n\n let node = this.getNodeAtPoint(point, true);\n if (!node && this.attachToOutline && this.reconnectingTargetNodeId) {\n node = this.renderer.getNode(this.reconnectingTargetNodeId) ?? null;\n }\n if (node) {\n if (this.attachToOutline && this.reconnectingOutlineParam !== null) {\n const endpoint: EdgeEndpoint = {\n nodeId: node.id,\n outlineParam: this.reconnectingOutlineParam,\n };\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = endpoint;\n } else {\n this.reconnectingEdge.to = endpoint;\n }\n } else {\n const anchor = node.getNearestAnchor(point);\n const portId =\n this.reconnectingEdge.lockAnchors && anchor\n ? `${ANCHOR_PORT_PREFIX}${anchor.id}`\n : undefined;\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = { nodeId: node.id, portId };\n } else {\n this.reconnectingEdge.to = { nodeId: node.id, portId };\n }\n }\n reconnected = true;\n this.emit('edgeReconnect', this.reconnectingEdge, this.reconnectingEndpoint!);\n }\n\n if (!reconnected && this.originalEdgeEndpoint) {\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = this.originalEdgeEndpoint;\n } else {\n this.reconnectingEdge.to = this.originalEdgeEndpoint;\n }\n this.emit('edgeReconnect', this.reconnectingEdge, this.reconnectingEndpoint!);\n }\n\n this.resetReconnection();\n this.renderer.markDirty();\n return true;\n }\n\n if (!this.isConnecting) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n let createdEdge: Edge | null = null;\n\n let targetNode = this.getNodeAtPoint(point, false);\n if (!targetNode && this.attachToOutline && this.previewTargetNodeId) {\n targetNode = this.renderer.getNode(this.previewTargetNodeId) ?? null;\n }\n if (targetNode) {\n const allowed =\n !this._connectionValidator || this._connectionValidator(this.sourceNode!.id, targetNode.id);\n if (allowed) {\n let from: EdgeEndpoint;\n let to: EdgeEndpoint;\n if (this.attachToOutline) {\n const targetOutline = targetNode.getClosestPointOnOutline(point);\n from = {\n nodeId: this.sourceNode!.id,\n outlineParam: this.sourceOutlineParam ?? undefined,\n };\n to = {\n nodeId: targetNode.id,\n outlineParam: targetOutline.param,\n };\n } else {\n const nearestTargetAnchor = targetNode.getNearestAnchor(point);\n from = {\n nodeId: this.sourceNode!.id,\n portId: this.sourceAnchorId ? `${ANCHOR_PORT_PREFIX}${this.sourceAnchorId}` : undefined,\n };\n to = {\n nodeId: targetNode.id,\n portId: nearestTargetAnchor\n ? `${ANCHOR_PORT_PREFIX}${nearestTargetAnchor.id}`\n : undefined,\n };\n }\n createdEdge = this.createEdge(from, to);\n this.addEdge(createdEdge);\n this.emit('connect', createdEdge);\n }\n }\n\n this.emit('connectionEnd', createdEdge);\n this.reset();\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Cancel current connection\n */\n cancelConnection(): void {\n if (!this.isConnecting) {\n return;\n }\n\n this.emit('connectionEnd', null);\n this.reset();\n this.renderer.markDirty();\n }\n\n /**\n * Render connection preview\n */\n renderPreview(ctx: CanvasRenderingContext2D): void {\n // For reconnection, the actual edge follows the cursor, no separate preview needed\n if (this.isReconnecting && this.reconnectPoint) {\n if (!this.attachToOutline) {\n this.renderAnchorHighlights(ctx, this.reconnectPoint, true);\n }\n return;\n }\n\n if (!this.isConnecting || this.previewEndpoint === null) {\n return;\n }\n\n const start = this.sourcePoint!;\n const end = this.previewEndpoint;\n\n const fromDir =\n this.sourceOutlineParam !== null\n ? this.getDirectionFromOutlineParam(this.sourceOutlineParam, this.sourceNode!)\n : this.sourceAnchorId?.split(':')[0];\n const toDir =\n this.previewTargetOutlineParam !== null\n ? this.getDirectionFromOutlineParam(this.previewTargetOutlineParam, this.sourceNode!)\n : this.previewTargetAnchorId?.split(':')[0];\n\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.setLineDash([6, 4]);\n\n // Draw bezier curve for preview\n this.drawBezierPreview(ctx, start, end, fromDir, toDir);\n\n ctx.setLineDash([]);\n\n if (!this.attachToOutline) {\n this.renderAnchorHighlights(ctx, end, false);\n }\n }\n\n /**\n * Get control point offset based on direction\n */\n private getDirectionOffset(dir: string | undefined, distance: number): Point {\n const offset = Math.min(distance * 0.5, BEZIER_MAX_OFFSET);\n switch (dir) {\n case 'top':\n return { x: 0, y: -offset };\n case 'bottom':\n return { x: 0, y: offset };\n case 'left':\n return { x: -offset, y: 0 };\n case 'right':\n return { x: offset, y: 0 };\n default:\n return { x: 0, y: 0 };\n }\n }\n\n /**\n * Draw a Bézier curve preview between two points\n */\n private drawBezierPreview(\n ctx: CanvasRenderingContext2D,\n start: Point,\n end: Point,\n fromDir?: string,\n toDir?: string\n ): void {\n const dist = distance(start, end);\n\n ctx.beginPath();\n ctx.moveTo(start.x, start.y);\n\n // If directions are specified, use them for control points\n if (fromDir || toDir) {\n const fromOffset = this.getDirectionOffset(fromDir, dist);\n const toOffset = this.getDirectionOffset(toDir, dist);\n\n ctx.bezierCurveTo(\n start.x + fromOffset.x,\n start.y + fromOffset.y,\n end.x + toOffset.x,\n end.y + toOffset.y,\n end.x,\n end.y\n );\n } else {\n // Default behavior: auto-detect direction\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const offset = Math.min(Math.abs(dx), Math.abs(dy), BEZIER_MAX_OFFSET) * 0.5 + 50;\n\n if (Math.abs(dx) > Math.abs(dy)) {\n // Horizontal dominant\n const offsetX = offset * Math.sign(dx || 1);\n ctx.bezierCurveTo(start.x + offsetX, start.y, end.x - offsetX, end.y, end.x, end.y);\n } else {\n // Vertical dominant\n ctx.bezierCurveTo(\n start.x,\n start.y + offset * Math.sign(dy || 1),\n end.x,\n end.y - offset * Math.sign(dy || 1),\n end.x,\n end.y\n );\n }\n }\n\n ctx.stroke();\n }\n\n private isCompatibleTarget(_node: Node): boolean {\n // Self-loop edges are allowed.\n return true;\n }\n\n private setCursor(cursor: string): void {\n const canvas = this.renderer.getCanvas();\n if (canvas.style.cursor !== cursor) {\n canvas.style.cursor = cursor;\n }\n }\n\n private reset(): void {\n this.isConnecting = false;\n this.sourceNode = null;\n this.sourcePoint = null;\n this.previewEndpoint = null;\n this.sourceAnchorId = null;\n this.sourceOutlineParam = null;\n this.previewTargetOutlineParam = null;\n this.previewTargetNodeId = null;\n this.setCursor('');\n }\n\n private resetReconnection(): void {\n this.isReconnecting = false;\n if (this.reconnectingEdge) {\n this.reconnectingEdge.autoUpdateEndpoints = true;\n }\n this.reconnectingEdge = null;\n this.reconnectingEndpoint = null;\n this.originalEdgeEndpoint = null;\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n this.reconnectPoint = null;\n this.setCursor('');\n }\n\n /**\n * Render anchors when hovering a node (not connecting)\n */\n renderHoverAnchors(ctx: CanvasRenderingContext2D): void {\n if (this.isConnecting || this.isReconnecting) {\n return;\n }\n\n this.renderEditablePolylineControls(ctx);\n\n if (this.attachToOutline) {\n return;\n }\n\n if (!this.hoverNodeId) {\n return;\n }\n\n const node = this.renderer.getNode(this.hoverNodeId);\n if (!node) {\n return;\n }\n\n const anchors = node.getAnchors();\n if (anchors.length === 0) {\n return;\n }\n\n ctx.save();\n ctx.setLineDash([]);\n\n for (const anchor of anchors) {\n const isHovered = anchor.id === this.hoverAnchorId;\n const radius = isHovered ? ANCHOR_POINT_HOVER_RADIUS : ANCHOR_POINT_RADIUS;\n\n // Draw anchor circle\n ctx.fillStyle = '#3b82f6';\n ctx.beginPath();\n ctx.arc(anchor.point.x, anchor.point.y, radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Draw white plus on hover\n if (isHovered) {\n this.drawPlus(radius, ctx, anchor);\n }\n }\n\n ctx.restore();\n }\n\n private tryStartEditableControlInteraction(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n const pointRadius = EDGE_CONTROL_POINT_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const addRadius = EDGE_ADD_CONTROL_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const pointRadiusSq = pointRadius * pointRadius;\n const addRadiusSq = addRadius * addRadius;\n const edges = [...this.renderer.edges.values()];\n\n for (let i = edges.length - 1; i >= 0; i--) {\n const edge = edges[i]!;\n if (edge.state !== 'selected' || !edge.isEditablePolyline()) {\n continue;\n }\n\n const controlPoints = edge.getEditableControlPoints();\n if (controlPoints.length === 0) continue;\n\n for (let i = 0; i < controlPoints.length; i++) {\n const dx = point.x - controlPoints[i]!.x;\n const dy = point.y - controlPoints[i]!.y;\n if (dx * dx + dy * dy > pointRadiusSq) {\n continue;\n }\n\n if (!edge.controlPoints || edge.controlPoints.length === 0) {\n edge.controlPoints = controlPoints;\n }\n this.activeControlPointDrag = { edge, index: i };\n this.renderer.markDirty();\n return true;\n }\n\n const insertControls = this.getInsertControls(edge);\n for (const insertControl of insertControls) {\n const dx = point.x - insertControl.point.x;\n const dy = point.y - insertControl.point.y;\n if (dx * dx + dy * dy > addRadiusSq) {\n continue;\n }\n\n const materialized = edge.controlPoints ? clonePoints(edge.controlPoints) : clonePoints(controlPoints);\n materialized.splice(insertControl.index, 0, this.snapPoint(insertControl.point));\n edge.controlPoints = materialized;\n this.activeControlPointDrag = { edge, index: insertControl.index };\n this.renderer.markDirty();\n return true;\n }\n }\n\n return false;\n }\n\n private renderEditablePolylineControls(ctx: CanvasRenderingContext2D): void {\n const pointRadius = EDGE_CONTROL_POINT_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const addRadius = EDGE_ADD_CONTROL_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n\n ctx.save();\n ctx.setLineDash([]);\n\n for (const edge of this.renderer.edges.values()) {\n if (edge.state !== 'selected' || !edge.isEditablePolyline()) {\n continue;\n }\n\n const controlPoints = edge.getEditableControlPoints();\n const insertControls = this.getInsertControls(edge);\n for (const insertControl of insertControls) {\n this.drawAddControl(ctx, insertControl.point, addRadius);\n }\n\n for (const point of controlPoints) {\n this.drawControlPoint(ctx, point, pointRadius);\n }\n }\n\n ctx.restore();\n }\n\n private getInsertControls(edge: Edge): { point: Point; index: number }[] {\n const vertices = edge.getPathVertices();\n const controls: { point: Point; index: number }[] = [];\n for (let i = 0; i < vertices.length - 1; i++) {\n const start = vertices[i]!;\n const end = vertices[i + 1]!;\n controls.push({\n point: {\n x: (start.x + end.x) / 2,\n y: (start.y + end.y) / 2,\n },\n index: i,\n });\n }\n return controls;\n }\n\n private drawControlPoint(ctx: CanvasRenderingContext2D, point: Point, radius: number): void {\n ctx.beginPath();\n ctx.arc(point.x, point.y, radius, 0, Math.PI * 2);\n ctx.fillStyle = '#3b82f6';\n ctx.fill();\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2 / Math.max(this.renderer.zoom, 0.0001);\n ctx.stroke();\n }\n\n private drawAddControl(ctx: CanvasRenderingContext2D, point: Point, radius: number): void {\n ctx.beginPath();\n ctx.arc(point.x, point.y, radius, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 1.5 / Math.max(this.renderer.zoom, 0.0001);\n ctx.stroke();\n\n const plusSize = radius * 0.7;\n ctx.beginPath();\n ctx.moveTo(point.x - plusSize, point.y);\n ctx.lineTo(point.x + plusSize, point.y);\n ctx.moveTo(point.x, point.y - plusSize);\n ctx.lineTo(point.x, point.y + plusSize);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 1.5 / Math.max(this.renderer.zoom, 0.0001);\n ctx.stroke();\n }\n\n private snapPoint(point: Point): Point {\n if (!this.snapToGrid) {\n return point;\n }\n return {\n x: Math.round(point.x / this.gridSize) * this.gridSize,\n y: Math.round(point.y / this.gridSize) * this.gridSize,\n };\n }\n\n private applyAxisMagnet(edge: Edge, controlPoints: Point[], index: number, point: Point): Point {\n const vertices = [edge.startPoint, ...controlPoints, edge.endPoint];\n const prev = vertices[index];\n const next = vertices[index + 2];\n if (!prev || !next) {\n return point;\n }\n\n const tolerance = EDGE_AXIS_MAGNET_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n let x = point.x;\n let y = point.y;\n\n const xCandidates = [prev.x, next.x];\n const yCandidates = [prev.y, next.y];\n\n let closestXDist = Infinity;\n for (const candidate of xCandidates) {\n const dist = Math.abs(point.x - candidate);\n if (dist <= tolerance && dist < closestXDist) {\n closestXDist = dist;\n x = candidate;\n }\n }\n\n let closestYDist = Infinity;\n for (const candidate of yCandidates) {\n const dist = Math.abs(point.y - candidate);\n if (dist <= tolerance && dist < closestYDist) {\n closestYDist = dist;\n y = candidate;\n }\n }\n\n return { x, y };\n }\n\n private drawPlus(\n radius: number,\n ctx: CanvasRenderingContext2D,\n anchor: { id: AnchorId; point: Point }\n ): void {\n const plusSize = radius * 0.5;\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n ctx.moveTo(anchor.point.x - plusSize, anchor.point.y);\n ctx.lineTo(anchor.point.x + plusSize, anchor.point.y);\n ctx.moveTo(anchor.point.x, anchor.point.y - plusSize);\n ctx.lineTo(anchor.point.x, anchor.point.y + plusSize);\n ctx.stroke();\n return;\n }\n\n private renderAnchorHighlights(\n ctx: CanvasRenderingContext2D,\n point: Point,\n reconnecting: boolean\n ): void {\n const node = this.getNodeAtPoint(point, reconnecting);\n if (!node) {\n return;\n }\n\n // Check if connection to this target is allowed\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, node.id);\n\n const anchors = node.getAnchors();\n const nearest = node.getNearestAnchor(point);\n if (anchors.length === 0) {\n return;\n }\n\n ctx.save();\n ctx.setLineDash([]);\n\n const fillColor = forbidden ? '#ef4444' : '#3b82f6';\n\n for (const anchor of anchors) {\n const isNearest = nearest && anchor.id === nearest.id;\n const radius = isNearest ? ANCHOR_POINT_HOVER_RADIUS : ANCHOR_POINT_RADIUS;\n\n // Draw anchor circle\n ctx.fillStyle = fillColor;\n ctx.beginPath();\n ctx.arc(anchor.point.x, anchor.point.y, radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Draw white plus/cross on nearest\n if (isNearest) {\n if (forbidden) {\n this.drawCross(radius, ctx, anchor);\n } else {\n this.drawPlus(radius, ctx, anchor);\n }\n }\n }\n\n ctx.restore();\n }\n\n private drawCross(\n radius: number,\n ctx: CanvasRenderingContext2D,\n anchor: { id: AnchorId; point: Point }\n ): void {\n const size = radius * 0.4;\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n ctx.moveTo(anchor.point.x - size, anchor.point.y - size);\n ctx.lineTo(anchor.point.x + size, anchor.point.y + size);\n ctx.moveTo(anchor.point.x + size, anchor.point.y - size);\n ctx.lineTo(anchor.point.x - size, anchor.point.y + size);\n ctx.stroke();\n }\n\n private getNodeAtPoint(point: Point, reconnecting: boolean): Node | null {\n const nodes = Array.from(this.renderer.nodes.values());\n for (let i = nodes.length - 1; i >= 0; i--) {\n const node = nodes[i]!;\n if (!node.visible || !node.hitTest(point)) {\n continue;\n }\n\n if (reconnecting) {\n return node;\n }\n\n if (this.isCompatibleTarget(node)) {\n return node;\n }\n }\n\n return null;\n }\n\n private updateHover(point: Point): void {\n if (this.hoverDisabled) {\n return;\n }\n\n const node = this.getNodeAtPoint(point, false);\n const prevNodeId = this.hoverNodeId;\n const prevAnchorId = this.hoverAnchorId;\n\n if (!node) {\n this.hoverNodeId = null;\n this.hoverAnchorId = null;\n } else {\n this.hoverNodeId = node.id;\n const anchor = this.getAnchorAtPoint(node, point);\n this.hoverAnchorId = anchor?.id ?? null;\n }\n\n if (prevNodeId !== this.hoverNodeId || prevAnchorId !== this.hoverAnchorId) {\n this.renderer.markDirty();\n }\n }\n\n private getAnchorAtPoint(node: Node, point: Point): { id: string; point: Point } | null {\n // Get only port-side anchors if attachToOutline is disabled and node has ports\n const anchorIds = !this.attachToOutline && node.ports.length > 0\n ? node.getPortAnchorIds()\n : null;\n \n const anchors = node.getAnchors();\n if (anchors.length === 0) {\n return null;\n }\n\n const radius = ANCHOR_POINT_HITBOX_RADIUS;\n const radiusSq = radius * radius;\n let closest: { id: string; point: Point } | null = null;\n let minDist = Infinity;\n\n for (const anchor of anchors) {\n // Skip anchors not on port sides when in port mode\n if (anchorIds && !anchorIds.includes(anchor.id)) {\n continue;\n }\n const dx = point.x - anchor.point.x;\n const dy = point.y - anchor.point.y;\n const dist = dx * dx + dy * dy;\n if (dist <= radiusSq && dist < minDist) {\n minDist = dist;\n closest = { id: anchor.id, point: anchor.point };\n }\n }\n\n return closest;\n }\n}\n","import type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { Node } from '@/elements/Node';\nimport type { StyleManager } from '@/styles/StyleManager';\n\n/**\n * Shallow compare two objects\n */\nexport function shallowEqual<T extends object>(a: T, b: T): boolean {\n if (a === b) {\n return true;\n }\n\n const aKeys = Object.keys(a as Record<string, unknown>);\n const bKeys = Object.keys(b as Record<string, unknown>);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (const key of aKeys) {\n const aValue = (a as Record<string, unknown>)[key];\n const bValue = (b as Record<string, unknown>)[key];\n\n if (Array.isArray(aValue) && Array.isArray(bValue)) {\n if (aValue.length !== bValue.length) {\n return false;\n }\n for (let i = 0; i < aValue.length; i++) {\n if (aValue[i] !== bValue[i]) {\n return false;\n }\n }\n continue;\n }\n\n if (aValue !== bValue) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Apply StyleManager to all elements\n */\nexport function applyStyleManagerToElements(\n styleManager: StyleManager | null | undefined,\n groups: Iterable<Group>,\n edges: Iterable<Edge>,\n nodes: Iterable<Node>\n): void {\n if (!styleManager) {\n return;\n }\n\n for (const group of groups) {\n group.applyStyleManager(styleManager);\n }\n\n for (const edge of edges) {\n edge.applyStyleManager(styleManager);\n }\n\n for (const node of nodes) {\n node.applyStyleManager(styleManager);\n }\n}\n","import type { Bounds, Point, TextStyle } from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport { shallowEqual } from '@/utils/style';\n\nexport interface TextLabelOptions {\n text: string;\n editableText?: string;\n style?: TextStyle;\n maxWidth?: number;\n padding?: number;\n margin?: number;\n styleClass?: string;\n onChange?: () => void;\n}\n\nconst DEFAULT_STYLE: Required<TextStyle> = {\n font: '14px sans-serif',\n fontSize: 14,\n fontFamily: 'sans-serif',\n fontWeight: 'normal',\n color: '#000000',\n opacity: 1,\n align: 'center',\n baseline: 'middle',\n};\n\n/**\n * Text label for nodes and edges\n */\nexport class TextLabel {\n private _text: string;\n private _editableText?: string;\n private _style: TextStyle;\n private _localStyle: TextStyle;\n private _maxWidth?: number;\n private _autoMaxWidth?: number;\n private _padding: number;\n private _margin: number;\n private _lines: string[] = [];\n private _measuredWidth = 0;\n private _measuredHeight = 0;\n private _styleClass?: string;\n private _onChange?: () => void;\n private _measureDirty = true;\n\n constructor(options: TextLabelOptions) {\n this._text = options.text;\n this._editableText = options.editableText;\n this._localStyle = { ...options.style };\n this._style = { ...DEFAULT_STYLE, ...options.style };\n this._maxWidth = options.maxWidth;\n this._padding = options.padding ?? 8;\n this._margin = Number.isFinite(options.margin) ? Math.max(0, options.margin ?? 0) : 0;\n this._styleClass = options.styleClass;\n this._onChange = options.onChange;\n }\n\n /**\n * Label text\n */\n get text(): string {\n return this._text;\n }\n\n set text(value: string) {\n if (this._text !== value) {\n this._text = value;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n /**\n * Editable text shown in inline editor instead of display text.\n * When set, double-click editing will use this value.\n */\n get editableText(): string | undefined {\n return this._editableText;\n }\n\n set editableText(value: string | undefined) {\n if (this._editableText !== value) {\n this._editableText = value;\n this._onChange?.();\n }\n }\n\n /**\n * Text style\n */\n get style(): TextStyle {\n return this._style;\n }\n\n set style(value: TextStyle) {\n this._localStyle = { ...value };\n this._style = { ...DEFAULT_STYLE, ...value };\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n\n /**\n * Style class name for StyleManager\n */\n get styleClass(): string | undefined {\n return this._styleClass;\n }\n\n set styleClass(value: string | undefined) {\n if (this._styleClass !== value) {\n this._styleClass = value;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n /**\n * Maximum width for text wrapping\n */\n get maxWidth(): number | undefined {\n return this._maxWidth;\n }\n\n set maxWidth(value: number | undefined) {\n if (this._maxWidth === value) {\n return;\n }\n this._maxWidth = value;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n\n /**\n * Internal max width used for automatic wrapping by container elements.\n */\n setAutoMaxWidth(value: number | undefined): void {\n if (this._autoMaxWidth === value) {\n return;\n }\n this._autoMaxWidth = value;\n this._lines = [];\n this._measureDirty = true;\n }\n\n /**\n * Label padding\n */\n get padding(): number {\n return this._padding;\n }\n\n set padding(value: number) {\n const next = Number.isFinite(value) ? Math.max(0, value) : this._padding;\n if (this._padding !== next) {\n this._padding = next;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n /**\n * Label margin\n */\n get margin(): number {\n return this._margin;\n }\n\n set margin(value: number) {\n const next = Number.isFinite(value) ? Math.max(0, value) : this._margin;\n if (this._margin !== next) {\n this._margin = next;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getTextStyle(this._styleClass);\n const mergedStyle = { ...baseStyle, ...this._localStyle };\n if (!shallowEqual(this._style, mergedStyle)) {\n this._style = mergedStyle;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n setOnChange(handler?: () => void): void {\n this._onChange = handler;\n }\n\n /**\n * Measured width after layout\n */\n get measuredWidth(): number {\n return this._measuredWidth;\n }\n\n /**\n * Measured height after layout\n */\n get measuredHeight(): number {\n return this._measuredHeight;\n }\n\n /**\n * Get wrapped lines for export. Uses ctx to measure and wrap by words.\n * Call with maxWidth = inner bounds width (e.g. bounds.width - margin*2).\n */\n getWrappedLines(ctx: CanvasRenderingContext2D, maxWidth: number): string[] {\n this.setAutoMaxWidth(maxWidth);\n this.measure(ctx);\n return this._lines;\n }\n\n /**\n * Measure and layout text, returns dimensions\n */\n measure(ctx: CanvasRenderingContext2D): { width: number; height: number } {\n if (!this._measureDirty && this._lines.length > 0) {\n return {\n width: this._measuredWidth,\n height: this._measuredHeight,\n };\n }\n\n this.applyStyle(ctx);\n\n const lineHeight = (this._style.fontSize ?? 14) * 1.2;\n\n const effectiveMaxWidth = this._maxWidth ?? this._autoMaxWidth;\n\n if (effectiveMaxWidth !== undefined) {\n const maxWidth = Math.max(0, effectiveMaxWidth - this._margin * 2);\n this._lines = this.wrapText(ctx, this._text, Math.max(0, maxWidth - this._padding * 2));\n } else {\n this._lines = this._text.split('\\n');\n }\n\n // Calculate dimensions\n let maxLineWidth = 0;\n for (const line of this._lines) {\n const metrics = ctx.measureText(line);\n maxLineWidth = Math.max(maxLineWidth, metrics.width);\n }\n\n this._measuredWidth = maxLineWidth + this._padding * 2 + this._margin * 2;\n this._measuredHeight = this._lines.length * lineHeight + this._padding * 2 + this._margin * 2;\n this._measureDirty = false;\n\n return {\n width: this._measuredWidth,\n height: this._measuredHeight,\n };\n }\n\n /**\n * Render the label within bounds\n */\n render(ctx: CanvasRenderingContext2D, bounds: Bounds, alignOverride?: 'left' | 'center' | 'right'): void {\n if (this._lines.length === 0) {\n this.measure(ctx);\n }\n\n this.applyStyle(ctx);\n\n const align = alignOverride ?? this._style.align ?? 'center';\n if (alignOverride) {\n ctx.textAlign = align;\n }\n\n const lineHeight = (this._style.fontSize ?? 14) * 1.2;\n const totalHeight = this._lines.length * lineHeight;\n\n const margin = this._margin;\n const innerBounds: Bounds = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n\n // Calculate starting position based on alignment\n let x: number;\n switch (align) {\n case 'left':\n x = innerBounds.x + this._padding;\n break;\n case 'right':\n x = innerBounds.x + innerBounds.width - this._padding;\n break;\n default:\n x = innerBounds.x + innerBounds.width / 2;\n }\n\n const startY = innerBounds.y + (innerBounds.height - totalHeight) / 2 + lineHeight / 2;\n\n ctx.fillStyle = this._style.color ?? '#000000';\n\n for (let i = 0; i < this._lines.length; i++) {\n const line = this._lines[i]!;\n const y = startY + i * lineHeight;\n ctx.fillText(line, x, y);\n }\n }\n\n /**\n * Render at a specific point (for edge labels)\n */\n renderAt(ctx: CanvasRenderingContext2D, point: Point): void {\n if (this._lines.length === 0) {\n this.measure(ctx);\n }\n\n this.applyStyle(ctx);\n\n const lineHeight = (this._style.fontSize ?? 14) * 1.2;\n const totalHeight = this._lines.length * lineHeight;\n const startY = point.y - totalHeight / 2 + lineHeight / 2;\n\n ctx.fillStyle = this._style.color ?? '#000000';\n\n for (let i = 0; i < this._lines.length; i++) {\n const line = this._lines[i]!;\n const y = startY + i * lineHeight;\n ctx.fillText(line, point.x, y);\n }\n }\n\n private applyStyle(ctx: CanvasRenderingContext2D): void {\n const fontSize = this._style.fontSize ?? 14;\n const fontFamily = this._style.fontFamily ?? 'sans-serif';\n const fontWeight = this._style.fontWeight ?? 'normal';\n\n // Always construct font from individual properties to ensure fontSize changes are applied\n ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n ctx.textAlign = this._style.align ?? 'center';\n ctx.textBaseline = this._style.baseline ?? 'middle';\n }\n\n private wrapText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number): string[] {\n const lines: string[] = [];\n const paragraphs = text.split('\\n');\n\n for (const paragraph of paragraphs) {\n const words = paragraph.split(' ');\n let currentLine = '';\n\n for (const word of words) {\n const testLine = currentLine.length > 0 ? `${currentLine} ${word}` : word;\n const metrics = ctx.measureText(testLine);\n\n if (metrics.width > maxWidth && currentLine.length > 0) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine = testLine;\n }\n }\n\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n }\n\n return lines.length > 0 ? lines : [''];\n }\n}\n","import { TextLabel } from '@/elements/TextLabel';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { Node } from '@/elements/Node';\nimport type {\n ArrowMarkerConfig,\n ArrowType,\n Command,\n EdgeLabelBackground,\n EdgePathType,\n EdgeStyle,\n ElementStyle,\n NodeStyle,\n Point,\n TextStyle,\n} from '@/types';\n\nexport interface LabelSnapshot {\n text: string;\n editableText?: string;\n style?: TextStyle;\n styleClass?: string;\n maxWidth?: number;\n}\n\nexport interface NodeSnapshot {\n style: NodeStyle;\n styleClass?: string;\n label?: LabelSnapshot;\n cornerRadius?: number;\n showPortsAlways: boolean;\n}\n\nexport interface EdgeSnapshot {\n style: EdgeStyle;\n styleClass?: string;\n label?: LabelSnapshot;\n labelOffset: number;\n labelBackground?: EdgeLabelBackground;\n startMarker?: ArrowMarkerConfig;\n endMarker?: ArrowMarkerConfig;\n arrowType: ArrowType;\n type: EdgePathType;\n controlPoints?: Point[];\n}\n\nexport interface GroupSnapshot {\n style: ElementStyle;\n styleClass?: string;\n label?: string;\n padding: number;\n}\n\nconst cloneValue = <T>(value: T): T => {\n if (value === undefined) {\n return value;\n }\n return JSON.parse(JSON.stringify(value)) as T;\n};\n\nconst snapshotLabel = (label?: TextLabel): LabelSnapshot | undefined => {\n if (!label) {\n return undefined;\n }\n return {\n text: label.text,\n editableText: label.editableText,\n style: cloneValue(label.style),\n styleClass: label.styleClass,\n maxWidth: label.maxWidth,\n };\n};\n\nconst applyLabelSnapshot = (\n current: TextLabel | undefined,\n snapshot?: LabelSnapshot\n): TextLabel | undefined => {\n if (!snapshot) {\n return undefined;\n }\n if (current) {\n current.text = snapshot.text;\n current.editableText = snapshot.editableText;\n current.style = snapshot.style ?? {};\n current.styleClass = snapshot.styleClass;\n current.maxWidth = snapshot.maxWidth;\n return current;\n }\n return new TextLabel({\n text: snapshot.text,\n editableText: snapshot.editableText,\n style: snapshot.style,\n styleClass: snapshot.styleClass,\n maxWidth: snapshot.maxWidth,\n });\n};\n\nexport const createNodeSnapshot = (node: Node): NodeSnapshot => {\n const cornerRadius =\n 'cornerRadius' in node ? (node as { cornerRadius: number }).cornerRadius : undefined;\n return {\n style: cloneValue(node.styleOverrides as NodeStyle),\n styleClass: node.styleClass,\n label: snapshotLabel(node.label),\n cornerRadius,\n showPortsAlways: node.showPortsAlways,\n };\n};\n\nexport const createEdgeSnapshot = (edge: Edge): EdgeSnapshot => {\n return {\n style: cloneValue(edge.styleOverrides as EdgeStyle),\n styleClass: edge.styleClass,\n label: snapshotLabel(edge.label),\n labelOffset: edge.labelOffset,\n labelBackground: cloneValue(edge.labelBackground),\n startMarker: cloneValue(edge.startMarker),\n endMarker: cloneValue(edge.endMarker),\n arrowType: edge.arrowType,\n type: edge.type,\n controlPoints: cloneValue(edge.controlPoints),\n };\n};\n\nexport const createGroupSnapshot = (group: Group): GroupSnapshot => {\n return {\n style: cloneValue(group.styleOverrides),\n styleClass: group.styleClass,\n label: group.label,\n padding: group.padding,\n };\n};\n\n/**\n * Command for moving nodes\n */\nexport class MoveNodesCommand implements Command {\n private readonly nodePositions: Map<\n string,\n { before: { x: number; y: number }; after: { x: number; y: number } }\n >;\n private readonly getNode: (id: string) => { x: number; y: number } | undefined;\n\n constructor(\n getNode: (id: string) => { x: number; y: number } | undefined,\n nodePositions: Map<\n string,\n { before: { x: number; y: number }; after: { x: number; y: number } }\n >\n ) {\n this.getNode = getNode;\n this.nodePositions = new Map(nodePositions);\n }\n\n execute(): void {\n for (const [id, pos] of this.nodePositions) {\n const node = this.getNode(id);\n if (node !== undefined) {\n node.x = pos.after.x;\n node.y = pos.after.y;\n }\n }\n }\n\n undo(): void {\n for (const [id, pos] of this.nodePositions) {\n const node = this.getNode(id);\n if (node !== undefined) {\n node.x = pos.before.x;\n node.y = pos.before.y;\n }\n }\n }\n}\n\n/**\n * Command for adding a node\n */\nexport class AddNodeCommand implements Command {\n private readonly nodeId: string;\n private readonly addNode: () => void;\n private readonly removeNode: (id: string) => void;\n\n constructor(nodeId: string, addNode: () => void, removeNode: (id: string) => void) {\n this.nodeId = nodeId;\n this.addNode = addNode;\n this.removeNode = removeNode;\n }\n\n execute(): void {\n this.addNode();\n }\n\n undo(): void {\n this.removeNode(this.nodeId);\n }\n}\n\n/**\n * Command for removing a node\n */\nexport class RemoveNodeCommand implements Command {\n private readonly nodeId: string;\n private readonly addNode: () => void;\n private readonly removeNode: (id: string) => void;\n\n constructor(nodeId: string, addNode: () => void, removeNode: (id: string) => void) {\n this.nodeId = nodeId;\n this.addNode = addNode;\n this.removeNode = removeNode;\n }\n\n execute(): void {\n this.removeNode(this.nodeId);\n }\n\n undo(): void {\n this.addNode();\n }\n}\n\n/**\n * Composite command for grouping multiple commands\n */\nexport class CompositeCommand implements Command {\n private readonly commands: Command[];\n\n constructor(commands: Command[]) {\n this.commands = [...commands];\n }\n\n execute(): void {\n for (const command of this.commands) {\n command.execute();\n }\n }\n\n undo(): void {\n // Undo in reverse order\n for (let i = this.commands.length - 1; i >= 0; i--) {\n this.commands[i]!.undo();\n }\n }\n}\n\n/**\n * Command for changing node properties\n */\nexport class ChangeNodePropertiesCommand implements Command {\n private readonly getNode: (id: string) => Node | undefined;\n private readonly nodeId: string;\n private before: NodeSnapshot;\n private after: NodeSnapshot;\n\n constructor(\n getNode: (id: string) => Node | undefined,\n nodeId: string,\n before: NodeSnapshot,\n after: NodeSnapshot\n ) {\n this.getNode = getNode;\n this.nodeId = nodeId;\n this.before = cloneValue(before);\n this.after = cloneValue(after);\n }\n\n execute(): void {\n const node = this.getNode(this.nodeId);\n if (!node) {\n return;\n }\n node.style = cloneValue(this.after.style ?? {});\n node.styleClass = this.after.styleClass;\n node.label = applyLabelSnapshot(node.label, this.after.label);\n node.showPortsAlways = this.after.showPortsAlways;\n if (this.after.cornerRadius !== undefined && 'cornerRadius' in node) {\n (node as { cornerRadius: number }).cornerRadius = this.after.cornerRadius;\n }\n }\n\n undo(): void {\n const node = this.getNode(this.nodeId);\n if (!node) {\n return;\n }\n node.style = cloneValue(this.before.style ?? {});\n node.styleClass = this.before.styleClass;\n node.label = applyLabelSnapshot(node.label, this.before.label);\n node.showPortsAlways = this.before.showPortsAlways;\n if (this.before.cornerRadius !== undefined && 'cornerRadius' in node) {\n (node as { cornerRadius: number }).cornerRadius = this.before.cornerRadius;\n }\n }\n}\n\n/**\n * Command for changing edge properties\n */\nexport class ChangeEdgePropertiesCommand implements Command {\n private readonly getEdge: (id: string) => Edge | undefined;\n private readonly edgeId: string;\n private before: EdgeSnapshot;\n private after: EdgeSnapshot;\n\n constructor(\n getEdge: (id: string) => Edge | undefined,\n edgeId: string,\n before: EdgeSnapshot,\n after: EdgeSnapshot\n ) {\n this.getEdge = getEdge;\n this.edgeId = edgeId;\n this.before = cloneValue(before);\n this.after = cloneValue(after);\n }\n\n execute(): void {\n const edge = this.getEdge(this.edgeId);\n if (!edge) {\n return;\n }\n edge.type = this.after.type;\n edge.controlPoints = cloneValue(this.after.controlPoints);\n edge.arrowType = this.after.arrowType;\n edge.startMarker = cloneValue(this.after.startMarker);\n edge.endMarker = cloneValue(this.after.endMarker);\n edge.labelOffset = this.after.labelOffset;\n edge.labelBackground = cloneValue(this.after.labelBackground);\n edge.style = cloneValue(this.after.style ?? {});\n edge.styleClass = this.after.styleClass;\n edge.label = applyLabelSnapshot(edge.label, this.after.label);\n }\n\n undo(): void {\n const edge = this.getEdge(this.edgeId);\n if (!edge) {\n return;\n }\n edge.type = this.before.type;\n edge.controlPoints = cloneValue(this.before.controlPoints);\n edge.arrowType = this.before.arrowType;\n edge.startMarker = cloneValue(this.before.startMarker);\n edge.endMarker = cloneValue(this.before.endMarker);\n edge.labelOffset = this.before.labelOffset;\n edge.labelBackground = cloneValue(this.before.labelBackground);\n edge.style = cloneValue(this.before.style ?? {});\n edge.styleClass = this.before.styleClass;\n edge.label = applyLabelSnapshot(edge.label, this.before.label);\n }\n}\n\n/**\n * Command for changing group properties\n */\nexport class ChangeGroupPropertiesCommand implements Command {\n private readonly getGroup: (id: string) => Group | undefined;\n private readonly groupId: string;\n private before: GroupSnapshot;\n private after: GroupSnapshot;\n\n constructor(\n getGroup: (id: string) => Group | undefined,\n groupId: string,\n before: GroupSnapshot,\n after: GroupSnapshot\n ) {\n this.getGroup = getGroup;\n this.groupId = groupId;\n this.before = cloneValue(before);\n this.after = cloneValue(after);\n }\n\n execute(): void {\n const group = this.getGroup(this.groupId);\n if (!group) {\n return;\n }\n group.style = cloneValue(this.after.style ?? {});\n group.styleClass = this.after.styleClass;\n group.label = this.after.label;\n group.padding = this.after.padding;\n }\n\n undo(): void {\n const group = this.getGroup(this.groupId);\n if (!group) {\n return;\n }\n group.style = cloneValue(this.before.style ?? {});\n group.styleClass = this.before.styleClass;\n group.label = this.before.label;\n group.padding = this.before.padding;\n }\n}\n\n/**\n * Command for removing a node from groups\n */\nexport class RemoveNodeFromGroupsCommand implements Command {\n private readonly getGroup: (id: string) => Group | undefined;\n private readonly getNode: (id: string) => Node | undefined;\n private readonly nodeId: string;\n private readonly groupIds: string[];\n\n constructor(\n getGroup: (id: string) => Group | undefined,\n getNode: (id: string) => Node | undefined,\n nodeId: string,\n groupIds: string[]\n ) {\n this.getGroup = getGroup;\n this.getNode = getNode;\n this.nodeId = nodeId;\n this.groupIds = [...groupIds];\n }\n\n execute(): void {\n for (const groupId of this.groupIds) {\n const group = this.getGroup(groupId);\n if (group) {\n group.removeChild(this.nodeId);\n }\n }\n }\n\n undo(): void {\n const node = this.getNode(this.nodeId);\n if (!node) {\n return;\n }\n for (const groupId of this.groupIds) {\n const group = this.getGroup(groupId);\n if (group) {\n if (!group.hasChild(this.nodeId)) {\n group.addChild(node);\n }\n }\n }\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { Command } from '@/types';\n\n/**\n * History events\n */\nexport interface HistoryEvents {\n change: [canUndo: boolean, canRedo: boolean];\n undo: [command: Command];\n redo: [command: Command];\n}\n\nexport interface HistoryManagerOptions {\n maxSize?: number;\n}\n\n/**\n * Manages undo/redo history using command pattern\n */\nexport class HistoryManager extends EventEmitter<HistoryEvents> {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxSize: number;\n\n constructor(options: HistoryManagerOptions = {}) {\n super();\n this.maxSize = options.maxSize ?? 100;\n }\n\n /**\n * Check if undo is available\n */\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n /**\n * Check if redo is available\n */\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n /**\n * Number of commands in undo stack\n */\n get undoCount(): number {\n return this.undoStack.length;\n }\n\n /**\n * Number of commands in redo stack\n */\n get redoCount(): number {\n return this.redoStack.length;\n }\n\n /**\n * Execute a command and add to history\n */\n execute(command: Command): void {\n command.execute();\n this.undoStack.push(command);\n\n // Clear redo stack on new command\n this.redoStack = [];\n\n // Limit stack size\n if (this.undoStack.length > this.maxSize) {\n this.undoStack.shift();\n }\n\n this.emitChange();\n }\n\n /**\n * Undo the last command\n */\n undo(): boolean {\n const command = this.undoStack.pop();\n if (command === undefined) {\n return false;\n }\n\n command.undo();\n this.redoStack.push(command);\n this.emit('undo', command);\n this.emitChange();\n\n return true;\n }\n\n /**\n * Redo the last undone command\n */\n redo(): boolean {\n const command = this.redoStack.pop();\n if (command === undefined) {\n return false;\n }\n\n command.execute();\n this.undoStack.push(command);\n this.emit('redo', command);\n this.emitChange();\n\n return true;\n }\n\n /**\n * Clear all history\n */\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.emitChange();\n }\n\n /**\n * Handle keyboard shortcuts.\n * Uses event.code for letter keys to work with any keyboard layout (e.g. Russian).\n */\n handleKeyDown(event: KeyboardEvent): boolean {\n const isCtrlOrMeta = event.ctrlKey || event.metaKey;\n const key = event.code.startsWith('Key')\n ? event.code.slice(3).toLowerCase()\n : event.key.toLowerCase();\n\n if (isCtrlOrMeta && key === 'z' && !event.shiftKey) {\n event.preventDefault();\n return this.undo();\n }\n\n if (isCtrlOrMeta && (key === 'y' || (key === 'z' && event.shiftKey))) {\n event.preventDefault();\n return this.redo();\n }\n\n return false;\n }\n\n private emitChange(): void {\n this.emit('change', this.canUndo, this.canRedo);\n }\n}\n\nexport {\n MoveNodesCommand,\n AddNodeCommand,\n RemoveNodeCommand,\n CompositeCommand,\n ChangeNodePropertiesCommand,\n ChangeEdgePropertiesCommand,\n ChangeGroupPropertiesCommand,\n RemoveNodeFromGroupsCommand,\n createNodeSnapshot,\n createEdgeSnapshot,\n createGroupSnapshot,\n} from './history/commands';\n","import type { Bounds, ElementState, ElementStyle, Point, Size } from '@/types';\n\nlet nextId = 1;\n\n/**\n * Generate a unique element ID\n */\nexport function generateId(prefix = 'el'): string {\n return `${prefix}_${nextId++}`;\n}\n\n/**\n * Reset ID counter (for testing)\n */\nexport function resetIdCounter(): void {\n nextId = 1;\n}\n\n/**\n * Abstract base class for all diagram elements\n */\nexport abstract class Element {\n readonly id: string;\n protected _x: number;\n protected _y: number;\n protected _width: number;\n protected _height: number;\n protected _state: ElementState = 'normal';\n protected _style: ElementStyle;\n protected _styleClass?: string;\n protected _dirty = true;\n protected _visible = true;\n private _dirtyListener?: () => void;\n\n /**\n * Custom data attached to this element\n */\n data: Record<string, unknown> = {};\n\n protected constructor(options: {\n id?: string;\n x: number;\n y: number;\n width: number;\n height: number;\n style?: ElementStyle;\n styleClass?: string;\n }) {\n this.id = options.id ?? generateId();\n this._x = options.x;\n this._y = options.y;\n this._width = options.width;\n this._height = options.height;\n this._style = options.style ?? {};\n this._styleClass = options.styleClass;\n }\n\n /**\n * X position in world coordinates\n */\n get x(): number {\n return this._x;\n }\n\n set x(value: number) {\n if (this._x !== value) {\n this._x = value;\n this.markDirty();\n }\n }\n\n /**\n * Y position in world coordinates\n */\n get y(): number {\n return this._y;\n }\n\n set y(value: number) {\n if (this._y !== value) {\n this._y = value;\n this.markDirty();\n }\n }\n\n /**\n * Position as Point\n */\n get position(): Point {\n return { x: this._x, y: this._y };\n }\n\n set position(value: Point) {\n const changed = this._x !== value.x || this._y !== value.y;\n this._x = value.x;\n this._y = value.y;\n if (changed) {\n this.markDirty();\n }\n }\n\n /**\n * Width of the element\n */\n get width(): number {\n return this._width;\n }\n\n set width(value: number) {\n if (this._width !== value) {\n this._width = value;\n this.markDirty();\n }\n }\n\n /**\n * Height of the element\n */\n get height(): number {\n return this._height;\n }\n\n set height(value: number) {\n if (this._height !== value) {\n this._height = value;\n this.markDirty();\n }\n }\n\n /**\n * Size as Size object\n */\n get size(): Size {\n return { width: this._width, height: this._height };\n }\n\n set size(value: Size) {\n const changed = this._width !== value.width || this._height !== value.height;\n this._width = value.width;\n this._height = value.height;\n if (changed) {\n this.markDirty();\n }\n }\n\n /**\n * Current interaction state\n */\n get state(): ElementState {\n return this._state;\n }\n\n set state(value: ElementState) {\n if (this._state !== value) {\n this._state = value;\n this.markDirty();\n }\n }\n\n /**\n * Style properties\n */\n get style(): ElementStyle {\n return this._style;\n }\n\n set style(value: ElementStyle) {\n this._style = value;\n this.markDirty();\n }\n\n /**\n * Raw style overrides (without theme/class merge)\n */\n get styleOverrides(): ElementStyle {\n return this._style;\n }\n\n /**\n * Clear raw style overrides\n */\n clearStyleOverrides(): void {\n if (Object.keys(this._style).length === 0) {\n return;\n }\n this._style = {};\n this.markDirty();\n }\n\n /**\n * Style class name for StyleManager\n */\n get styleClass(): string | undefined {\n return this._styleClass;\n }\n\n set styleClass(value: string | undefined) {\n if (this._styleClass !== value) {\n this._styleClass = value;\n this.markDirty();\n }\n }\n\n /**\n * Whether the element needs to be re-rendered\n */\n get dirty(): boolean {\n return this._dirty;\n }\n\n /**\n * Whether the element is visible\n */\n get visible(): boolean {\n return this._visible;\n }\n\n set visible(value: boolean) {\n if (this._visible !== value) {\n this._visible = value;\n this.markDirty();\n }\n }\n\n /**\n * Mark this element as needing re-render\n */\n markDirty(): void {\n this._dirty = true;\n this._dirtyListener?.();\n }\n\n /**\n * Clear the dirty flag after rendering\n */\n clearDirty(): void {\n this._dirty = false;\n }\n\n /**\n * Register a dirty listener (used by DiagramRenderer)\n */\n setDirtyListener(listener?: () => void): void {\n this._dirtyListener = listener;\n }\n\n /**\n * Get the bounding box of this element\n */\n getBounds(): Bounds {\n return {\n x: this._x,\n y: this._y,\n width: this._width,\n height: this._height,\n };\n }\n\n /**\n * Get the center point of this element\n */\n getCenter(): Point {\n return {\n x: this._x + this._width / 2,\n y: this._y + this._height / 2,\n };\n }\n\n /**\n * Test if a point is within this element\n * @param point - Point in world coordinates\n */\n abstract hitTest(point: Point): boolean;\n\n /**\n * Render this element to the canvas\n * @param ctx - Canvas rendering context\n */\n abstract render(ctx: CanvasRenderingContext2D): void;\n}\n","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions } from './PathStrategy';\nimport { distanceToSegment } from '@/utils/geometry';\n\n/**\n * Straight line path strategy\n */\nexport class StraightPathStrategy implements PathStrategy {\n calculatePath(\n from: Point,\n to: Point,\n _fromDir?: string,\n _toDir?: string,\n _options?: PathStrategyOptions\n ): Point[] {\n return [from, to];\n }\n\n hitTest(point: Point, path: Point[], tolerance: number): boolean {\n if (path.length < 2) {\n return false;\n }\n return distanceToSegment(point, path[0]!, path[1]!) <= tolerance;\n }\n}\n","export type Direction = 'top' | 'right' | 'bottom' | 'left' | undefined;\n\nexport function isHorizontal(dir?: string): boolean {\n return dir === 'left' || dir === 'right';\n}\n\nexport function isVertical(dir?: string): boolean {\n return dir === 'top' || dir === 'bottom';\n}\n\nexport function isOppositeDirections(fromDir?: string, toDir?: string): boolean {\n return (\n (fromDir === 'left' && toDir === 'right') ||\n (fromDir === 'right' && toDir === 'left') ||\n (fromDir === 'top' && toDir === 'bottom') ||\n (fromDir === 'bottom' && toDir === 'top')\n );\n}\n\nexport function directionToVector(dir?: string): { x: number; y: number } {\n switch (dir) {\n case 'top':\n return { x: 0, y: -1 };\n case 'bottom':\n return { x: 0, y: 1 };\n case 'left':\n return { x: -1, y: 0 };\n case 'right':\n return { x: 1, y: 0 };\n default:\n return { x: 0, y: 0 };\n }\n}\n","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions, PathObstacle } from './PathStrategy';\nimport { distance, distanceToSegment } from '@/utils/geometry';\nimport { isHorizontal, isVertical, isOppositeDirections } from '@/utils/direction';\n\nconst MIN_SEGMENT_LENGTH = 20;\nconst SELF_LOOP_MIN_DISTANCE = 1;\nconst SELF_LOOP_OFFSET = 42;\nconst SELF_LOOP_SPREAD = 20;\nconst CORNER_BYPASS_DISTANCE = 220;\nconst CORNER_BYPASS_CLEARANCE = 34;\nconst OPPOSITE_BYPASS_DISTANCE = 280;\nconst OPPOSITE_BYPASS_CLEARANCE = 36;\nconst OPPOSITE_BYPASS_ARC = 48;\nconst OBSTACLE_ROUTING_DISTANCE = 1200;\nconst OBSTACLE_MARGIN = 12;\nconst ROUTE_EXIT_DISTANCE = 32;\nconst TURN_PENALTY = 70;\nconst FIRST_VERTICAL_PENALTY = 28;\n\nfunction expandObstacles(obstacles: PathObstacle[], margin: number): PathObstacle[] {\n return obstacles.map((obstacle) => ({\n ...obstacle,\n x: obstacle.x - margin,\n y: obstacle.y - margin,\n width: obstacle.width + margin * 2,\n height: obstacle.height + margin * 2,\n }));\n}\n\nfunction pointInsideObstacle(point: Point, obstacle: PathObstacle): boolean {\n return (\n point.x >= obstacle.x &&\n point.x <= obstacle.x + obstacle.width &&\n point.y >= obstacle.y &&\n point.y <= obstacle.y + obstacle.height\n );\n}\n\nfunction segmentIntersectsExpandedObstacle(a: Point, b: Point, obstacle: PathObstacle): boolean {\n const minX = obstacle.x;\n const maxX = obstacle.x + obstacle.width;\n const minY = obstacle.y;\n const maxY = obstacle.y + obstacle.height;\n\n if (Math.abs(a.x - b.x) < 0.001) {\n const x = a.x;\n const y1 = Math.min(a.y, b.y);\n const y2 = Math.max(a.y, b.y);\n return x >= minX && x <= maxX && y2 >= minY && y1 <= maxY;\n }\n\n if (Math.abs(a.y - b.y) < 0.001) {\n const y = a.y;\n const x1 = Math.min(a.x, b.x);\n const x2 = Math.max(a.x, b.x);\n return y >= minY && y <= maxY && x2 >= minX && x1 <= maxX;\n }\n\n return false;\n}\n\nfunction simplifyPath(path: Point[]): Point[] {\n const out: Point[] = [];\n for (const point of path) {\n const prev = out[out.length - 1];\n if (!prev || Math.abs(prev.x - point.x) > 0.001 || Math.abs(prev.y - point.y) > 0.001) {\n out.push(point);\n }\n }\n return out;\n}\n\nfunction manhattan(a: Point, b: Point): number {\n return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n}\n\nfunction moveByDir(point: Point, dir: string | undefined, distance: number): Point {\n switch (dir) {\n case 'top':\n return { x: point.x, y: point.y - distance };\n case 'bottom':\n return { x: point.x, y: point.y + distance };\n case 'left':\n return { x: point.x - distance, y: point.y };\n case 'right':\n return { x: point.x + distance, y: point.y };\n default:\n return point;\n }\n}\n\nfunction inferDir(from: Point, to: Point): string {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n // Prefer horizontal decisions when comparable.\n if (Math.abs(dx) >= Math.abs(dy)) {\n return dx >= 0 ? 'right' : 'left';\n }\n return dy >= 0 ? 'bottom' : 'top';\n}\n\nfunction oppositeDir(dir: string): string {\n switch (dir) {\n case 'left':\n return 'right';\n case 'right':\n return 'left';\n case 'top':\n return 'bottom';\n case 'bottom':\n return 'top';\n default:\n return dir;\n }\n}\n\nfunction buildRoutedPolyline(\n from: Point,\n to: Point,\n fromDir: string | undefined,\n toDir: string | undefined,\n obstacles: PathObstacle[]\n): Point[] | null {\n if (obstacles.length === 0) {\n return null;\n }\n\n const effectiveFromDir = fromDir ?? inferDir(from, to);\n const effectiveToDir = toDir ?? oppositeDir(effectiveFromDir);\n\n const startExit = moveByDir(from, effectiveFromDir, ROUTE_EXIT_DISTANCE);\n const endEntry = moveByDir(to, effectiveToDir, ROUTE_EXIT_DISTANCE);\n const expanded = expandObstacles(obstacles, OBSTACLE_MARGIN);\n\n const xs = new Set<number>([startExit.x, endEntry.x]);\n const ys = new Set<number>([startExit.y, endEntry.y]);\n for (const obstacle of expanded) {\n xs.add(obstacle.x - 1);\n xs.add(obstacle.x + obstacle.width + 1);\n ys.add(obstacle.y - 1);\n ys.add(obstacle.y + obstacle.height + 1);\n }\n\n type GraphNode = { x: number; y: number };\n const nodes: GraphNode[] = [];\n const nodeIndex = new Map<string, number>();\n const nodeKey = (x: number, y: number): string => `${x}|${y}`;\n const addNode = (x: number, y: number): void => {\n const key = nodeKey(x, y);\n if (nodeIndex.has(key)) return;\n const point = { x, y };\n if (expanded.some((obstacle) => pointInsideObstacle(point, obstacle))) {\n return;\n }\n nodeIndex.set(key, nodes.length);\n nodes.push(point);\n };\n\n for (const x of xs) {\n for (const y of ys) {\n addNode(x, y);\n }\n }\n addNode(startExit.x, startExit.y);\n addNode(endEntry.x, endEntry.y);\n\n const startIdx = nodeIndex.get(nodeKey(startExit.x, startExit.y));\n const goalIdx = nodeIndex.get(nodeKey(endEntry.x, endEntry.y));\n if (startIdx == null || goalIdx == null) {\n return null;\n }\n\n const edges = new Map<number, Array<{ to: number; dir: 'h' | 'v'; length: number }>>();\n const pushEdge = (a: number, b: number, dir: 'h' | 'v', length: number): void => {\n const list = edges.get(a) ?? [];\n list.push({ to: b, dir, length });\n edges.set(a, list);\n };\n\n const byX = new Map<number, number[]>();\n const byY = new Map<number, number[]>();\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!;\n const xsList = byX.get(node.x) ?? [];\n xsList.push(i);\n byX.set(node.x, xsList);\n const ysList = byY.get(node.y) ?? [];\n ysList.push(i);\n byY.set(node.y, ysList);\n }\n\n for (const list of byX.values()) {\n list.sort((a, b) => nodes[a]!.y - nodes[b]!.y);\n for (let i = 1; i < list.length; i++) {\n const a = nodes[list[i - 1]!]!;\n const b = nodes[list[i]!]!;\n if (!expanded.some((obstacle) => segmentIntersectsExpandedObstacle(a, b, obstacle))) {\n const length = manhattan(a, b);\n pushEdge(list[i - 1]!, list[i]!, 'v', length);\n pushEdge(list[i]!, list[i - 1]!, 'v', length);\n }\n }\n }\n for (const list of byY.values()) {\n list.sort((a, b) => nodes[a]!.x - nodes[b]!.x);\n for (let i = 1; i < list.length; i++) {\n const a = nodes[list[i - 1]!]!;\n const b = nodes[list[i]!]!;\n if (!expanded.some((obstacle) => segmentIntersectsExpandedObstacle(a, b, obstacle))) {\n const length = manhattan(a, b);\n pushEdge(list[i - 1]!, list[i]!, 'h', length);\n pushEdge(list[i]!, list[i - 1]!, 'h', length);\n }\n }\n }\n\n type DirState = 'h' | 'v' | 's';\n type QueueState = { node: number; dir: DirState; g: number; f: number; key: string };\n const makeStateKey = (node: number, dir: DirState): string => `${node}:${dir}`;\n const open: QueueState[] = [];\n const best = new Map<string, number>();\n const prev = new Map<string, string>();\n const startKey = makeStateKey(startIdx, 's');\n best.set(startKey, 0);\n open.push({\n node: startIdx,\n dir: 's',\n g: 0,\n f: manhattan(nodes[startIdx]!, nodes[goalIdx]!),\n key: startKey,\n });\n\n let goalKey: string | null = null;\n while (open.length > 0) {\n let bestIdx = 0;\n for (let i = 1; i < open.length; i++) {\n if (open[i]!.f < open[bestIdx]!.f) bestIdx = i;\n }\n const current = open.splice(bestIdx, 1)[0]!;\n if (current.node === goalIdx) {\n goalKey = current.key;\n break;\n }\n\n for (const edge of edges.get(current.node) ?? []) {\n const nextDir = edge.dir;\n let stepCost = edge.length;\n if (current.dir !== 's' && current.dir !== nextDir) {\n stepCost += TURN_PENALTY;\n }\n if (current.dir === 's' && nextDir === 'v') {\n stepCost += FIRST_VERTICAL_PENALTY;\n }\n const nextG = current.g + stepCost;\n const nextKey = makeStateKey(edge.to, nextDir);\n if (nextG >= (best.get(nextKey) ?? Infinity)) {\n continue;\n }\n best.set(nextKey, nextG);\n prev.set(nextKey, current.key);\n const h = manhattan(nodes[edge.to]!, nodes[goalIdx]!);\n open.push({ node: edge.to, dir: nextDir, g: nextG, f: nextG + h, key: nextKey });\n }\n }\n\n if (!goalKey) {\n return null;\n }\n\n const routed: Point[] = [];\n let cursor: string | undefined = goalKey;\n while (cursor) {\n const [nodePart] = cursor.split(':');\n const node = nodes[Number(nodePart)]!;\n routed.push({ x: node.x, y: node.y });\n cursor = prev.get(cursor);\n }\n routed.reverse();\n\n const internal = simplifyPath(routed).filter(\n (_, idx, arr) => idx !== 0 && idx !== arr.length - 1\n );\n return simplifyPath([from, startExit, ...internal, endEntry, to]);\n}\n\n/**\n * Polyline path strategy\n */\nexport class PolylinePathStrategy implements PathStrategy {\n calculatePath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string,\n _options?: PathStrategyOptions\n ): Point[] {\n const controlPoints = _options?.controlPoints;\n if (_options?.editablePolyline) {\n if (controlPoints && controlPoints.length > 0) {\n return [from, ...controlPoints, to];\n }\n return [from, { x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 }, to];\n }\n\n const dist = distance(from, to);\n const selfLoop = _options?.selfLoop ?? false;\n const obstacles = _options?.obstacles ?? [];\n\n if (!selfLoop && dist < OBSTACLE_ROUTING_DISTANCE) {\n const routed = buildRoutedPolyline(from, to, fromDir, toDir, obstacles);\n if (routed) {\n return routed;\n }\n }\n\n if (selfLoop && dist < SELF_LOOP_MIN_DISTANCE && (fromDir || toDir)) {\n const dir = fromDir ?? toDir;\n switch (dir) {\n case 'bottom':\n return [\n from,\n { x: from.x - SELF_LOOP_SPREAD, y: from.y + SELF_LOOP_OFFSET },\n { x: from.x + SELF_LOOP_SPREAD, y: from.y + SELF_LOOP_OFFSET },\n to,\n ];\n case 'left':\n return [\n from,\n { x: from.x - SELF_LOOP_OFFSET, y: from.y + SELF_LOOP_SPREAD },\n { x: from.x - SELF_LOOP_OFFSET, y: from.y - SELF_LOOP_SPREAD },\n to,\n ];\n case 'right':\n return [\n from,\n { x: from.x + SELF_LOOP_OFFSET, y: from.y - SELF_LOOP_SPREAD },\n { x: from.x + SELF_LOOP_OFFSET, y: from.y + SELF_LOOP_SPREAD },\n to,\n ];\n case 'top':\n default:\n return [\n from,\n { x: from.x + SELF_LOOP_SPREAD, y: from.y - SELF_LOOP_OFFSET },\n { x: from.x - SELF_LOOP_SPREAD, y: from.y - SELF_LOOP_OFFSET },\n to,\n ];\n }\n }\n\n if (\n selfLoop &&\n dist < OPPOSITE_BYPASS_DISTANCE &&\n fromDir &&\n toDir &&\n isOppositeDirections(fromDir, toDir)\n ) {\n if (isHorizontal(fromDir) && isHorizontal(toDir)) {\n const fromStepX =\n fromDir === 'left' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const toStepX = toDir === 'left' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const sideY = from.x <= to.x ? -1 : 1;\n const outerY = from.y + sideY * OPPOSITE_BYPASS_ARC;\n return [\n from,\n { x: from.x + fromStepX, y: from.y },\n { x: from.x + fromStepX, y: outerY },\n { x: to.x + toStepX, y: outerY },\n { x: to.x + toStepX, y: to.y },\n to,\n ];\n }\n if (isVertical(fromDir) && isVertical(toDir)) {\n const fromStepY =\n fromDir === 'top' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const toStepY = toDir === 'top' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const sideX = from.y <= to.y ? 1 : -1;\n const outerX = from.x + sideX * OPPOSITE_BYPASS_ARC;\n return [\n from,\n { x: from.x, y: from.y + fromStepY },\n { x: outerX, y: from.y + fromStepY },\n { x: outerX, y: to.y + toStepY },\n { x: to.x, y: to.y + toStepY },\n to,\n ];\n }\n }\n\n if (\n selfLoop &&\n dist < CORNER_BYPASS_DISTANCE &&\n fromDir &&\n toDir &&\n ((isHorizontal(fromDir) && isVertical(toDir)) || (isVertical(fromDir) && isHorizontal(toDir)))\n ) {\n const fromOuter = {\n x:\n from.x +\n (fromDir === 'left'\n ? -CORNER_BYPASS_CLEARANCE\n : fromDir === 'right'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n y:\n from.y +\n (fromDir === 'top'\n ? -CORNER_BYPASS_CLEARANCE\n : fromDir === 'bottom'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n };\n const toOuter = {\n x:\n to.x +\n (toDir === 'left'\n ? -CORNER_BYPASS_CLEARANCE\n : toDir === 'right'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n y:\n to.y +\n (toDir === 'top'\n ? -CORNER_BYPASS_CLEARANCE\n : toDir === 'bottom'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n };\n const corner = isHorizontal(fromDir)\n ? { x: fromOuter.x, y: toOuter.y }\n : { x: toOuter.x, y: fromOuter.y };\n return [from, fromOuter, corner, toOuter, to];\n }\n\n // If directions are specified, route accordingly\n if (fromDir || toDir) {\n return this.calculateDirectedPath(from, to, fromDir, toDir);\n }\n\n // Default behavior: auto-detect direction\n const midX = (from.x + to.x) / 2;\n\n // Horizontal-first routing\n if (Math.abs(to.x - from.x) > Math.abs(to.y - from.y)) {\n return [from, { x: midX, y: from.y }, { x: midX, y: to.y }, to];\n }\n\n // Vertical-first routing\n const midY = (from.y + to.y) / 2;\n return [from, { x: from.x, y: midY }, { x: to.x, y: midY }, to];\n }\n\n private calculateDirectedPath(from: Point, to: Point, fromDir?: string, toDir?: string): Point[] {\n const points: Point[] = [from];\n\n // Determine first segment based on fromDir\n const fromHorizontal = fromDir === 'left' || fromDir === 'right';\n const fromVertical = fromDir === 'top' || fromDir === 'bottom';\n const toHorizontal = toDir === 'left' || toDir === 'right';\n const toVertical = toDir === 'top' || toDir === 'bottom';\n\n if (fromVertical && toVertical) {\n // Both vertical: route with horizontal middle segment\n const midY = (from.y + to.y) / 2;\n const exitY =\n fromDir === 'top'\n ? Math.min(from.y - MIN_SEGMENT_LENGTH, midY)\n : Math.max(from.y + MIN_SEGMENT_LENGTH, midY);\n const entryY =\n toDir === 'top'\n ? Math.min(to.y - MIN_SEGMENT_LENGTH, midY)\n : Math.max(to.y + MIN_SEGMENT_LENGTH, midY);\n\n if (Math.abs(exitY - entryY) < 1) {\n points.push({ x: from.x, y: exitY });\n points.push({ x: to.x, y: exitY });\n } else {\n points.push({ x: from.x, y: exitY });\n points.push({ x: to.x, y: exitY });\n }\n } else if (fromHorizontal && toHorizontal) {\n // Both horizontal: route with vertical middle segment\n const midX = (from.x + to.x) / 2;\n const exitX =\n fromDir === 'left'\n ? Math.min(from.x - MIN_SEGMENT_LENGTH, midX)\n : Math.max(from.x + MIN_SEGMENT_LENGTH, midX);\n const entryX =\n toDir === 'left'\n ? Math.min(to.x - MIN_SEGMENT_LENGTH, midX)\n : Math.max(to.x + MIN_SEGMENT_LENGTH, midX);\n\n if (Math.abs(exitX - entryX) < 1) {\n points.push({ x: exitX, y: from.y });\n points.push({ x: exitX, y: to.y });\n } else {\n points.push({ x: exitX, y: from.y });\n points.push({ x: exitX, y: to.y });\n }\n } else if (fromVertical && toHorizontal) {\n // From vertical to horizontal\n points.push({ x: from.x, y: to.y });\n } else if (fromHorizontal && toVertical) {\n // From horizontal to vertical\n points.push({ x: to.x, y: from.y });\n } else {\n // Fallback: one corner\n const midX = (from.x + to.x) / 2;\n points.push({ x: midX, y: from.y });\n points.push({ x: midX, y: to.y });\n }\n\n points.push(to);\n return points;\n }\n\n hitTest(point: Point, path: Point[], tolerance: number): boolean {\n for (let i = 1; i < path.length; i++) {\n if (distanceToSegment(point, path[i - 1]!, path[i]!) <= tolerance) {\n return true;\n }\n }\n return false;\n }\n}\n","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions } from './PathStrategy';\nimport { bezierPoint, distance, distanceToSegment } from '@/utils/geometry';\nimport { BEZIER_MAX_OFFSET } from '@/constants';\nimport {\n isHorizontal,\n isVertical,\n isOppositeDirections,\n directionToVector as dirToVector,\n} from '@/utils/direction';\n\nconst SELF_LOOP_MIN_DISTANCE = 1;\nconst SELF_LOOP_OFFSET = 90;\nconst SELF_LOOP_SPREAD = 50;\nconst CORNER_BYPASS_DISTANCE = 220;\nconst CORNER_BYPASS_CLEARANCE = 80;\nconst OPPOSITE_BYPASS_DISTANCE = 280;\nconst OPPOSITE_BYPASS_CLEARANCE = 90;\nconst OPPOSITE_BYPASS_ARC = 120;\n\n/**\n * Get control point offset based on direction\n */\nfunction getDirectionOffset(dir: string | undefined, distance: number): Point {\n const offset = Math.min(distance * 0.5, BEZIER_MAX_OFFSET);\n switch (dir) {\n case 'top':\n return { x: 0, y: -offset };\n case 'bottom':\n return { x: 0, y: offset };\n case 'left':\n return { x: -offset, y: 0 };\n case 'right':\n return { x: offset, y: 0 };\n default:\n return { x: 0, y: 0 };\n }\n}\n\nfunction createSelfLoopPath(point: Point, dir?: string): Point[] {\n switch (dir) {\n case 'bottom':\n return [\n point,\n { x: point.x - SELF_LOOP_SPREAD, y: point.y + SELF_LOOP_OFFSET },\n { x: point.x + SELF_LOOP_SPREAD, y: point.y + SELF_LOOP_OFFSET },\n point,\n ];\n case 'left':\n return [\n point,\n { x: point.x - SELF_LOOP_OFFSET, y: point.y + SELF_LOOP_SPREAD },\n { x: point.x - SELF_LOOP_OFFSET, y: point.y - SELF_LOOP_SPREAD },\n point,\n ];\n case 'right':\n return [\n point,\n { x: point.x + SELF_LOOP_OFFSET, y: point.y - SELF_LOOP_SPREAD },\n { x: point.x + SELF_LOOP_OFFSET, y: point.y + SELF_LOOP_SPREAD },\n point,\n ];\n case 'top':\n default:\n return [\n point,\n { x: point.x + SELF_LOOP_SPREAD, y: point.y - SELF_LOOP_OFFSET },\n { x: point.x - SELF_LOOP_SPREAD, y: point.y - SELF_LOOP_OFFSET },\n point,\n ];\n }\n}\n\nfunction createOppositeBypassPath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string\n): Point[] | null {\n if (!fromDir || !toDir || !isOppositeDirections(fromDir, toDir)) {\n return null;\n }\n\n const fromOut = dirToVector(fromDir);\n const toOut = dirToVector(toDir);\n\n if (isHorizontal(fromDir) && isHorizontal(toDir)) {\n // left<->right: arc above/below node instead of crossing through center.\n const sideY = from.x <= to.x ? -1 : 1;\n return [\n from,\n {\n x: from.x + fromOut.x * OPPOSITE_BYPASS_CLEARANCE,\n y: from.y + sideY * OPPOSITE_BYPASS_ARC,\n },\n {\n x: to.x + toOut.x * OPPOSITE_BYPASS_CLEARANCE,\n y: to.y + sideY * OPPOSITE_BYPASS_ARC,\n },\n to,\n ];\n }\n\n if (isVertical(fromDir) && isVertical(toDir)) {\n // top<->bottom: arc left/right from node instead of crossing through center.\n const sideX = from.y <= to.y ? 1 : -1;\n return [\n from,\n {\n x: from.x + sideX * OPPOSITE_BYPASS_ARC,\n y: from.y + fromOut.y * OPPOSITE_BYPASS_CLEARANCE,\n },\n {\n x: to.x + sideX * OPPOSITE_BYPASS_ARC,\n y: to.y + toOut.y * OPPOSITE_BYPASS_CLEARANCE,\n },\n to,\n ];\n }\n\n return null;\n}\n\nfunction createCornerBypassPath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string\n): Point[] | null {\n if (!fromDir || !toDir) return null;\n const orthogonal =\n (isHorizontal(fromDir) && isVertical(toDir)) || (isVertical(fromDir) && isHorizontal(toDir));\n if (!orthogonal) return null;\n\n const fromOut = dirToVector(fromDir);\n const toOut = dirToVector(toDir);\n const fromOuter = {\n x: from.x + fromOut.x * CORNER_BYPASS_CLEARANCE,\n y: from.y + fromOut.y * CORNER_BYPASS_CLEARANCE,\n };\n const toOuter = {\n x: to.x + toOut.x * CORNER_BYPASS_CLEARANCE,\n y: to.y + toOut.y * CORNER_BYPASS_CLEARANCE,\n };\n // Single cubic bezier: smooth outer detour without a middle kink.\n return [from, fromOuter, toOuter, to];\n}\n\n/**\n * Bezier curve path strategy\n */\nexport class BezierPathStrategy implements PathStrategy {\n calculatePath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string,\n options?: PathStrategyOptions\n ): Point[] {\n const dist = distance(from, to);\n const loopDir = fromDir ?? toDir;\n const selfLoop = options?.selfLoop ?? false;\n\n // For self-loop edges, build an explicit outer loop so the edge\n // does not pass under the node it is attached to.\n if (selfLoop && dist < SELF_LOOP_MIN_DISTANCE && loopDir) {\n return createSelfLoopPath(from, loopDir);\n }\n\n if (selfLoop && dist < OPPOSITE_BYPASS_DISTANCE) {\n const oppositeBypass = createOppositeBypassPath(from, to, fromDir, toDir);\n if (oppositeBypass) {\n return oppositeBypass;\n }\n }\n\n if (selfLoop && dist < CORNER_BYPASS_DISTANCE) {\n const cornerBypass = createCornerBypassPath(from, to, fromDir, toDir);\n if (cornerBypass) {\n return cornerBypass;\n }\n }\n\n const controlPoints = options?.controlPoints;\n if (controlPoints && controlPoints.length > 0) {\n if (controlPoints.length >= 3 && controlPoints.length % 3 === 0) {\n return [from, ...controlPoints];\n }\n if (controlPoints.length === 2) {\n return [from, controlPoints[0]!, controlPoints[1]!, to];\n }\n }\n\n // If directions are specified, use them for control points\n if (fromDir || toDir) {\n const fromOffset = getDirectionOffset(fromDir, dist);\n const toOffset = getDirectionOffset(toDir, dist);\n\n return [\n from,\n { x: from.x + fromOffset.x, y: from.y + fromOffset.y },\n { x: to.x + toOffset.x, y: to.y + toOffset.y },\n to,\n ];\n }\n\n // Default behavior: auto-detect direction\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const offset = Math.min(Math.abs(dx), Math.abs(dy), BEZIER_MAX_OFFSET) * 0.5 + 50;\n\n if (Math.abs(dx) > Math.abs(dy)) {\n // Horizontal dominant\n const offsetX = offset * Math.sign(dx || 1);\n return [from, { x: from.x + offsetX, y: from.y }, { x: to.x - offsetX, y: to.y }, to];\n } else {\n // Vertical dominant\n const offsetY = offset * Math.sign(dy || 1);\n return [from, { x: from.x, y: from.y + offsetY }, { x: to.x, y: to.y - offsetY }, to];\n }\n }\n\n hitTest(point: Point, path: Point[], tolerance: number): boolean {\n if (path.length < 4) {\n return false;\n }\n\n // Sample bezier curve and check distance to segments\n const samples = 20;\n const points: Point[] = [];\n\n for (let i = 0; i <= samples; i++) {\n const t = i / samples;\n points.push(bezierPoint(path[0]!, path[1]!, path[2]!, path[3]!, t));\n }\n\n for (let i = 1; i < points.length; i++) {\n if (distanceToSegment(point, points[i - 1]!, points[i]!) <= tolerance) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { Element, generateId } from './Element';\nimport { TextLabel, type TextLabelOptions } from './TextLabel';\nimport type {\n ArrowType,\n ArrowMarkerConfig,\n EdgeEndpoint,\n EdgePathType,\n EdgeStyle,\n EdgeLabelBackground,\n Point,\n} from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport { shallowEqual } from '@/utils/style';\nimport { bezierPoint, drawRoundedRectPath } from '@/utils/geometry';\nimport {\n type PathStrategy,\n type PathStrategyOptions,\n StraightPathStrategy,\n PolylinePathStrategy,\n BezierPathStrategy,\n} from './paths';\nimport {\n EDGE_HANDLE_RADIUS,\n ARROW_SIZE,\n ARROW_ANGLE,\n MARKER_SIZES,\n EDGE_LABEL_BACKGROUND_PADDING,\n EDGE_LABEL_BACKGROUND_RADIUS,\n DEFAULT_SELECTION_COLOR,\n DEFAULT_HOVER_COLOR,\n} from '@/constants';\n\nexport interface EdgeOptions {\n id?: string;\n from: EdgeEndpoint;\n to: EdgeEndpoint;\n type?: EdgePathType;\n controlPoints?: Point[];\n arrowType?: ArrowType;\n startMarker?: ArrowMarkerConfig;\n endMarker?: ArrowMarkerConfig;\n style?: EdgeStyle;\n styleClass?: string;\n label?: string | TextLabelOptions;\n labelOffset?: number;\n labelBackground?: EdgeLabelBackground;\n lockAnchors?: boolean;\n}\n\nconst DEFAULT_EDGE_STYLE: EdgeStyle = {\n strokeColor: '#666666',\n strokeWidth: 2,\n opacity: 1,\n};\n\nexport type { PathStrategy };\n\n/**\n * Connection edge between nodes\n */\nexport class Edge extends Element {\n private _from: EdgeEndpoint;\n private _to: EdgeEndpoint;\n private _type: EdgePathType;\n private _arrowType: ArrowType;\n private _startMarker?: ArrowMarkerConfig;\n private _endMarker?: ArrowMarkerConfig;\n private _edgeStyle: EdgeStyle;\n private _label?: TextLabel;\n private _labelOffset: number;\n private _labelBackground?: EdgeLabelBackground;\n private _path: Point[] = [];\n private _pathStrategy: PathStrategy;\n private _autoUpdateEndpoints = true;\n private _lockAnchors: boolean;\n private _controlPoints?: Point[];\n private _pathOptions?: PathStrategyOptions;\n\n // Cached positions for rendering\n private _fromPoint: Point = { x: 0, y: 0 };\n private _toPoint: Point = { x: 0, y: 0 };\n private _fromDir?: string;\n private _toDir?: string;\n\n constructor(options: EdgeOptions) {\n super({\n id: options.id ?? generateId('edge'),\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n style: options.style,\n styleClass: options.styleClass,\n });\n\n this._from = options.from;\n this._to = options.to;\n this._type = options.type ?? 'straight';\n this._arrowType = options.arrowType ?? 'single';\n this._controlPoints = options.controlPoints;\n this._startMarker = options.startMarker;\n this._endMarker = options.endMarker;\n this._edgeStyle = { ...DEFAULT_EDGE_STYLE, ...options.style };\n this._pathStrategy = this.getPathStrategy(this._type);\n this._lockAnchors = options.lockAnchors ?? true;\n this._labelOffset = options.labelOffset ?? 0;\n this._labelBackground = options.labelBackground;\n\n if (options.label !== undefined) {\n if (typeof options.label === 'string') {\n this._label = new TextLabel({\n text: options.label,\n onChange: (): void => this.markDirty(),\n });\n } else {\n this._label = new TextLabel({ ...options.label, onChange: (): void => this.markDirty() });\n }\n }\n }\n\n /**\n * Source endpoint\n */\n get from(): EdgeEndpoint {\n return this._from;\n }\n\n set from(value: EdgeEndpoint) {\n this._from = value;\n this.markDirty();\n }\n\n /**\n * Target endpoint\n */\n get to(): EdgeEndpoint {\n return this._to;\n }\n\n set to(value: EdgeEndpoint) {\n this._to = value;\n this.markDirty();\n }\n\n /**\n * Edge type\n */\n get type(): EdgePathType {\n return this._type;\n }\n\n set type(value: EdgePathType) {\n if (this._type !== value) {\n this._type = value;\n this._pathStrategy = this.getPathStrategy(value);\n if (value !== 'editable-polyline' && this._controlPoints?.length) {\n this.controlPoints = undefined;\n }\n this.markDirty();\n }\n }\n\n /**\n * Arrow type (legacy)\n */\n get arrowType(): ArrowType {\n return this._arrowType;\n }\n\n set arrowType(value: ArrowType) {\n if (this._arrowType !== value) {\n this._arrowType = value;\n this.markDirty();\n }\n }\n\n /**\n * Start marker configuration\n */\n get startMarker(): ArrowMarkerConfig | undefined {\n return this._startMarker;\n }\n\n set startMarker(value: ArrowMarkerConfig | undefined) {\n this._startMarker = value;\n this.markDirty();\n }\n\n /**\n * End marker configuration\n */\n get endMarker(): ArrowMarkerConfig | undefined {\n return this._endMarker;\n }\n\n set endMarker(value: ArrowMarkerConfig | undefined) {\n this._endMarker = value;\n this.markDirty();\n }\n\n /**\n * Label offset from center of path\n */\n get labelOffset(): number {\n return this._labelOffset;\n }\n\n set labelOffset(value: number) {\n if (this._labelOffset !== value) {\n this._labelOffset = value;\n this.markDirty();\n }\n }\n\n /**\n * Label background configuration\n */\n get labelBackground(): EdgeLabelBackground | undefined {\n return this._labelBackground;\n }\n\n set labelBackground(value: EdgeLabelBackground | undefined) {\n this._labelBackground = value;\n this.markDirty();\n }\n\n /**\n * Control points for custom paths.\n * For bezier format: [cp1, cp2, end, cp1, cp2, end, ...]\n * For editable-polyline: [point1, point2, ...]\n */\n get controlPoints(): Point[] | undefined {\n return this._controlPoints;\n }\n\n set controlPoints(value: Point[] | undefined) {\n this._controlPoints = value;\n this.recalculatePath();\n }\n\n /**\n * Whether this edge uses editable polyline controls.\n */\n isEditablePolyline(): boolean {\n return this._type === 'editable-polyline';\n }\n\n /**\n * Whether this edge has editable control points (editable-polyline with non-empty controlPoints).\n */\n hasEditableControlPoints(): boolean {\n return this.isEditablePolyline() && !!this._controlPoints?.length;\n }\n\n /**\n * Returns path vertices for editable polyline: [startPoint, ...controlPoints, endPoint].\n * Requires endpoints to be updated (startPoint/endPoint valid).\n */\n getPathVertices(): Point[] {\n const cps = this._controlPoints && this._controlPoints.length > 0\n ? this._controlPoints\n : this.getEditableControlPoints();\n return [this._fromPoint, ...cps, this._toPoint];\n }\n\n /**\n * Returns current editable control points.\n * For a fresh editable-polyline edge, exposes a virtual midpoint handle.\n */\n getEditableControlPoints(): Point[] {\n if (!this.isEditablePolyline()) {\n return [];\n }\n if (this._controlPoints && this._controlPoints.length > 0) {\n return this._controlPoints.map((point) => ({ ...point }));\n }\n return [\n {\n x: (this._fromPoint.x + this._toPoint.x) / 2,\n y: (this._fromPoint.y + this._toPoint.y) / 2,\n },\n ];\n }\n\n /**\n * Edge style\n */\n override get style(): EdgeStyle {\n return this._edgeStyle;\n }\n\n override set style(value: EdgeStyle) {\n this._edgeStyle = { ...DEFAULT_EDGE_STYLE, ...value };\n this._style = value;\n this.markDirty();\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getEdgeStyle(this._state, this._styleClass);\n let mergedStyle: EdgeStyle = { ...baseStyle, ...this._style };\n\n if (this._state !== 'normal') {\n const normalStyle = styleManager.getEdgeStyle('normal', this._styleClass);\n if (\n mergedStyle.strokeColor === baseStyle.strokeColor &&\n normalStyle.strokeColor !== undefined\n ) {\n mergedStyle = { ...mergedStyle, strokeColor: normalStyle.strokeColor };\n }\n }\n\n if (!shallowEqual(this._edgeStyle, mergedStyle)) {\n this._edgeStyle = mergedStyle;\n this.markDirty();\n }\n\n if (this._label) {\n this._label.applyStyleManager(styleManager);\n }\n }\n\n /**\n * Edge label\n */\n get label(): TextLabel | undefined {\n return this._label;\n }\n\n set label(value: TextLabel | string | undefined) {\n if (value === undefined) {\n this._label = undefined;\n } else if (typeof value === 'string') {\n this._label = new TextLabel({ text: value, onChange: (): void => this.markDirty() });\n } else {\n this._label = value;\n this._label.setOnChange((): void => this.markDirty());\n }\n this.markDirty();\n }\n\n /**\n * Current path points\n */\n get path(): readonly Point[] {\n return this._path;\n }\n\n /**\n * Auto-update endpoints from connected nodes\n */\n get autoUpdateEndpoints(): boolean {\n return this._autoUpdateEndpoints;\n }\n\n set autoUpdateEndpoints(value: boolean) {\n this._autoUpdateEndpoints = value;\n }\n\n /**\n * Whether to lock edge endpoints to anchor points\n */\n get lockAnchors(): boolean {\n return this._lockAnchors;\n }\n\n set lockAnchors(value: boolean) {\n this._lockAnchors = value;\n }\n\n /**\n * Get start point position (for handle rendering)\n */\n get startPoint(): Point {\n return this._fromPoint;\n }\n\n /**\n * Get end point position (for handle rendering)\n */\n get endPoint(): Point {\n return this._toPoint;\n }\n\n /**\n * Check if a point hits the start handle\n */\n hitTestStartHandle(point: Point, handleRadius = 8): boolean {\n const dx = point.x - this._fromPoint.x;\n const dy = point.y - this._fromPoint.y;\n return dx * dx + dy * dy <= handleRadius * handleRadius;\n }\n\n /**\n * Check if a point hits the end handle\n */\n hitTestEndHandle(point: Point, handleRadius = 8): boolean {\n const dx = point.x - this._toPoint.x;\n const dy = point.y - this._toPoint.y;\n return dx * dx + dy * dy <= handleRadius * handleRadius;\n }\n\n /**\n * Update edge endpoints from node positions\n * Called by DiagramRenderer when nodes move\n * @param fromPoint Start point\n * @param toPoint End point\n * @param fromDir Direction at start point (top, right, bottom, left)\n * @param toDir Direction at end point (top, right, bottom, left)\n */\n updateEndpoints(\n fromPoint: Point,\n toPoint: Point,\n fromDir?: string,\n toDir?: string,\n options?: PathStrategyOptions\n ): void {\n this._fromPoint = fromPoint;\n this._toPoint = toPoint;\n this._fromDir = fromDir;\n this._toDir = toDir;\n this._pathOptions = options;\n this.recalculatePath();\n }\n\n /**\n * Recalculate the path between endpoints\n */\n recalculatePath(): void {\n this._path = this._pathStrategy.calculatePath(\n this._fromPoint,\n this._toPoint,\n this._fromDir,\n this._toDir,\n {\n ...this._pathOptions,\n controlPoints: this._controlPoints,\n editablePolyline: this.isEditablePolyline(),\n selfLoop: this._from.nodeId === this._to.nodeId,\n }\n );\n this.updateBounds();\n this.markDirty();\n }\n\n private updateBounds(): void {\n if (this._path.length === 0) {\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const point of this._path) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n\n this._x = minX;\n this._y = minY;\n this._width = maxX - minX;\n this._height = maxY - minY;\n }\n\n hitTest(point: Point): boolean {\n const tolerance = Math.max((this._edgeStyle.strokeWidth ?? 2) * 2, 8);\n return this._pathStrategy.hitTest(point, this._path, tolerance);\n }\n\n /**\n * Hit test with explicit tolerance (world units)\n */\n hitTestWithTolerance(point: Point, tolerance: number): boolean {\n return this._pathStrategy.hitTest(point, this._path, tolerance);\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n if (this._path.length < 2) {\n return;\n }\n\n if (this._state === 'selected' || this._state === 'hover') {\n this.renderHighlight(ctx);\n }\n\n this.applyStyle(ctx);\n this.renderPath(ctx);\n this.renderArrows(ctx);\n this.renderLabel(ctx);\n // Note: handles are rendered separately via renderHandles() to appear on top of nodes\n }\n\n /**\n * Render drag handles when selected\n * Called separately after nodes to ensure handles appear on top\n */\n renderHandles(ctx: CanvasRenderingContext2D): void {\n if (this._state !== 'selected') {\n return;\n }\n\n this.renderHandle(ctx, this._fromPoint);\n this.renderHandle(ctx, this._toPoint);\n }\n\n private renderHandle(ctx: CanvasRenderingContext2D, point: Point): void {\n ctx.beginPath();\n ctx.arc(point.x, point.y, EDGE_HANDLE_RADIUS, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n\n private applyStyle(ctx: CanvasRenderingContext2D): void {\n const style = this._edgeStyle;\n\n ctx.strokeStyle = style.strokeColor ?? '#666666';\n ctx.lineWidth = style.strokeWidth ?? 2;\n const baseOpacity = style.opacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n\n this.applyLineDash(ctx, style);\n\n if (style.lineCap !== undefined) {\n ctx.lineCap = style.lineCap;\n }\n\n if (style.lineJoin !== undefined) {\n ctx.lineJoin = style.lineJoin;\n }\n }\n\n private renderHighlight(ctx: CanvasRenderingContext2D): void {\n const style = this._edgeStyle;\n ctx.save();\n ctx.strokeStyle = this._state === 'selected' ? DEFAULT_SELECTION_COLOR : DEFAULT_HOVER_COLOR;\n ctx.lineWidth = (style.strokeWidth ?? 2) + (this._state === 'selected' ? 1 : 0);\n ctx.globalAlpha = 1;\n\n this.applyLineDash(ctx, style);\n\n if (style.lineCap !== undefined) {\n ctx.lineCap = style.lineCap;\n }\n\n if (style.lineJoin !== undefined) {\n ctx.lineJoin = style.lineJoin;\n }\n\n this.renderPath(ctx);\n ctx.restore();\n }\n\n private renderPath(ctx: CanvasRenderingContext2D): void {\n const path = this._path;\n if (path.length < 2) return;\n\n // Calculate how much to shorten the line at each end for markers\n const startOffset =\n this._startMarker && this._startMarker.type !== 'none'\n ? this.getMarkerLength(this._startMarker)\n : 0;\n const endOffset =\n this._endMarker && this._endMarker.type !== 'none'\n ? this.getMarkerLength(this._endMarker)\n : 0;\n\n // Get shortened start point\n const start = path[0]!;\n const startNext = path[1]!;\n const startAngle = Math.atan2(startNext.y - start.y, startNext.x - start.x);\n const shortenedStart = {\n x: start.x + startOffset * Math.cos(startAngle),\n y: start.y + startOffset * Math.sin(startAngle),\n };\n\n // Get shortened end point\n const end = path[path.length - 1]!;\n const endPrev = path[path.length - 2]!;\n const endAngle = Math.atan2(end.y - endPrev.y, end.x - endPrev.x);\n const shortenedEnd = {\n x: end.x - endOffset * Math.cos(endAngle),\n y: end.y - endOffset * Math.sin(endAngle),\n };\n\n ctx.beginPath();\n ctx.moveTo(shortenedStart.x, shortenedStart.y);\n\n if (this._type === 'bezier' && path.length >= 4) {\n for (let i = 1; i + 2 < path.length; i += 3) {\n const cp1 = path[i]!;\n const cp2 = path[i + 1]!;\n const end = i + 2 === path.length - 1 ? shortenedEnd : path[i + 2]!;\n ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);\n }\n } else {\n for (let i = 1; i < path.length - 1; i++) {\n ctx.lineTo(path[i]!.x, path[i]!.y);\n }\n ctx.lineTo(shortenedEnd.x, shortenedEnd.y);\n }\n\n ctx.stroke();\n }\n\n private renderArrows(ctx: CanvasRenderingContext2D): void {\n const path = this._path;\n if (path.length < 2) {\n return;\n }\n\n // Use new marker system if configured, otherwise fall back to legacy arrowType\n const hasNewMarkers = this._startMarker !== undefined || this._endMarker !== undefined;\n\n if (hasNewMarkers) {\n // End marker\n if (this._endMarker && this._endMarker.type !== 'none') {\n const points = this.getMarkerPoints('end');\n if (points) {\n this.drawMarker(ctx, points.from, points.to, this._endMarker);\n }\n }\n\n // Start marker\n if (this._startMarker && this._startMarker.type !== 'none') {\n const points = this.getMarkerPoints('start');\n if (points) {\n this.drawMarker(ctx, points.from, points.to, this._startMarker);\n }\n }\n } else {\n // Legacy arrow type support\n if (this._arrowType === 'none') {\n return;\n }\n\n // Target arrow\n const endPoints = this.getMarkerPoints('end');\n if (endPoints) {\n this.drawArrowHead(ctx, endPoints.from, endPoints.to);\n }\n\n // Source arrow (for double)\n if (this._arrowType === 'double') {\n const startPoints = this.getMarkerPoints('start');\n if (startPoints) {\n this.drawArrowHead(ctx, startPoints.from, startPoints.to);\n }\n }\n }\n }\n\n private getMarkerPoints(position: 'start' | 'end'): { from: Point; to: Point } | null {\n const path = this._path;\n if (path.length < 2) {\n return null;\n }\n\n if (this._type === 'bezier' && path.length >= 4) {\n const start = path[0]!;\n const cp1 = path[1]!;\n const cp2 = path[2]!;\n const end = path[3]!;\n const epsilon = 0.001;\n\n const isSame = (a: Point, b: Point): boolean =>\n Math.abs(a.x - b.x) < epsilon && Math.abs(a.y - b.y) < epsilon;\n\n if (position === 'end') {\n const endIndex = path.length - 1;\n const endPoint = path[endIndex]!;\n let from = path[endIndex - 1] ?? cp2;\n if (isSame(from, endPoint)) {\n from = path[endIndex - 2] ?? cp1;\n if (isSame(from, endPoint)) {\n from = start;\n }\n }\n return { from, to: endPoint };\n }\n\n let next = cp1;\n if (isSame(next, start)) {\n next = cp2;\n if (isSame(next, start)) {\n next = end;\n }\n }\n return { from: next, to: start };\n }\n\n if (position === 'end') {\n return { from: path[path.length - 2]!, to: path[path.length - 1]! };\n }\n\n return { from: path[1]!, to: path[0]! };\n }\n\n /**\n * Get the length of a marker (how much to shorten the line)\n */\n private getMarkerLength(config: ArrowMarkerConfig): number {\n const size = config.size ?? MARKER_SIZES[config.type] ?? ARROW_SIZE;\n switch (config.type) {\n case 'arrow':\n // Arrow length is size * cos(ARROW_ANGLE) for the back of the triangle\n return size * Math.cos(ARROW_ANGLE);\n case 'open':\n // Do not shorten line for open arrow\n return 0;\n case 'diamond':\n return size; // Diamond length is full size\n case 'circle':\n return size * 2; // Circle diameter\n default:\n return 0;\n }\n }\n\n private drawMarker(\n ctx: CanvasRenderingContext2D,\n from: Point,\n to: Point,\n config: ArrowMarkerConfig\n ): void {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const size = config.size ?? MARKER_SIZES[config.type] ?? ARROW_SIZE;\n const strokeColor = config.strokeColor ?? (ctx.strokeStyle as string);\n const fillColor = config.fillColor ?? strokeColor;\n const fillOpacity = config.fillOpacity ?? 1;\n\n ctx.save();\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n ctx.strokeStyle = strokeColor;\n\n switch (config.type) {\n case 'arrow':\n this.drawArrowMarker(ctx, to, angle, size, fillColor, fillOpacity);\n break;\n case 'open':\n this.drawOpenArrowMarker(ctx, to, angle, size);\n break;\n case 'diamond':\n this.drawDiamondMarker(ctx, to, angle, size, fillColor, fillOpacity);\n break;\n case 'circle':\n this.drawCircleMarker(ctx, to, angle, size, fillColor, fillOpacity);\n break;\n }\n\n ctx.restore();\n }\n\n private drawArrowMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number,\n fillColor: string,\n fillOpacity: number\n ): void {\n const x1 = to.x - size * Math.cos(angle - ARROW_ANGLE);\n const y1 = to.y - size * Math.sin(angle - ARROW_ANGLE);\n const x2 = to.x - size * Math.cos(angle + ARROW_ANGLE);\n const y2 = to.y - size * Math.sin(angle + ARROW_ANGLE);\n\n ctx.beginPath();\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.closePath();\n ctx.globalAlpha = fillOpacity;\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.globalAlpha = 1;\n ctx.stroke();\n }\n\n private drawOpenArrowMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number\n ): void {\n const x1 = to.x - size * Math.cos(angle - ARROW_ANGLE);\n const y1 = to.y - size * Math.sin(angle - ARROW_ANGLE);\n const x2 = to.x - size * Math.cos(angle + ARROW_ANGLE);\n const y2 = to.y - size * Math.sin(angle + ARROW_ANGLE);\n\n ctx.beginPath();\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(x1, y1);\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n\n private drawDiamondMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number,\n fillColor: string,\n fillOpacity: number\n ): void {\n const halfLength = size / 2;\n const halfWidth = size * 0.3;\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n // Diamond points relative to the tip\n const points = [\n { x: to.x, y: to.y }, // tip\n {\n x: to.x - halfLength * cos + halfWidth * sin,\n y: to.y - halfLength * sin - halfWidth * cos,\n },\n { x: to.x - size * cos, y: to.y - size * sin }, // back\n {\n x: to.x - halfLength * cos - halfWidth * sin,\n y: to.y - halfLength * sin + halfWidth * cos,\n },\n ];\n\n ctx.beginPath();\n ctx.moveTo(points[0]!.x, points[0]!.y);\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i]!.x, points[i]!.y);\n }\n ctx.closePath();\n\n ctx.globalAlpha = fillOpacity;\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.globalAlpha = 1;\n ctx.stroke();\n }\n\n private drawCircleMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number,\n fillColor: string,\n fillOpacity: number\n ): void {\n // Offset circle center back along the path so it doesn't overlap node\n const cx = to.x - size * Math.cos(angle);\n const cy = to.y - size * Math.sin(angle);\n\n ctx.beginPath();\n ctx.arc(cx, cy, size, 0, Math.PI * 2);\n\n ctx.globalAlpha = fillOpacity;\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.globalAlpha = 1;\n ctx.stroke();\n }\n\n private drawArrowHead(ctx: CanvasRenderingContext2D, from: Point, to: Point): void {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n\n ctx.save();\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n ctx.beginPath();\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(\n to.x - ARROW_SIZE * Math.cos(angle - ARROW_ANGLE),\n to.y - ARROW_SIZE * Math.sin(angle - ARROW_ANGLE)\n );\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(\n to.x - ARROW_SIZE * Math.cos(angle + ARROW_ANGLE),\n to.y - ARROW_SIZE * Math.sin(angle + ARROW_ANGLE)\n );\n ctx.stroke();\n ctx.restore();\n }\n\n private renderLabel(ctx: CanvasRenderingContext2D): void {\n if (this._label === undefined || this._path.length < 2) {\n return;\n }\n\n // Calculate midpoint of path with offset\n const midpoint = this.getPathMidpoint();\n const labelPosition = {\n x: midpoint.x,\n y: midpoint.y + this._labelOffset,\n };\n\n const labelOpacity = this._label.style.opacity ?? 1;\n\n // Draw background for label\n this._label.measure(ctx);\n const labelWidth = this._label.measuredWidth;\n const labelHeight = this._label.measuredHeight;\n\n const bgPadding = this._labelBackground?.padding ?? EDGE_LABEL_BACKGROUND_PADDING;\n const bgColor = this._labelBackground?.color ?? '#ffffff';\n const bgOpacity = this._labelBackground?.opacity ?? 1;\n const bgRadius = this._labelBackground?.borderRadius ?? EDGE_LABEL_BACKGROUND_RADIUS;\n\n const bgX = labelPosition.x - labelWidth / 2 - bgPadding;\n const bgY = labelPosition.y - labelHeight / 2 - bgPadding;\n const bgWidth = labelWidth + bgPadding * 2;\n const bgHeight = labelHeight + bgPadding * 2;\n\n ctx.fillStyle = bgColor;\n ctx.globalAlpha = bgOpacity;\n\n if (bgRadius > 0) {\n this.drawRoundedRect(ctx, bgX, bgY, bgWidth, bgHeight, bgRadius);\n ctx.fill();\n } else {\n ctx.fillRect(bgX, bgY, bgWidth, bgHeight);\n }\n\n ctx.globalAlpha = labelOpacity;\n this._label.renderAt(ctx, labelPosition);\n ctx.globalAlpha = 1;\n }\n\n private drawRoundedRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number\n ): void {\n drawRoundedRectPath(ctx, x, y, width, height, radius);\n }\n\n private getPathMidpoint(): Point {\n const path = this._path;\n\n if (this._type === 'bezier' && path.length >= 4) {\n const samples: Point[] = [];\n const steps = 20;\n for (let i = 1; i + 2 < path.length; i += 3) {\n const p0 = path[i - 1]!;\n const p1 = path[i]!;\n const p2 = path[i + 1]!;\n const p3 = path[i + 2]!;\n for (let s = 0; s <= steps; s++) {\n const t = s / steps;\n if (samples.length > 0 && t === 0) {\n continue;\n }\n samples.push(bezierPoint(p0, p1, p2, p3, t));\n }\n }\n\n return this.getPolylineMidpoint(samples);\n }\n\n // For straight/polyline, find midpoint of total length\n return this.getPolylineMidpoint(path);\n }\n\n /**\n * Get world position of label center along path.\n */\n getLabelPosition(): Point | null {\n if (this._path.length < 2) {\n return null;\n }\n\n const midpoint = this.getPathMidpoint();\n return {\n x: midpoint.x,\n y: midpoint.y + this._labelOffset,\n };\n }\n\n private getPolylineMidpoint(path: Point[]): Point {\n if (path.length === 0) {\n return { x: 0, y: 0 };\n }\n if (path.length === 1) {\n return path[0]!;\n }\n\n let totalLength = 0;\n const segments: { start: Point; end: Point; length: number }[] = [];\n\n for (let i = 1; i < path.length; i++) {\n const start = path[i - 1]!;\n const end = path[i]!;\n const length = Math.sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2);\n segments.push({ start, end, length });\n totalLength += length;\n }\n\n const halfLength = totalLength / 2;\n let accumulated = 0;\n\n for (const seg of segments) {\n if (accumulated + seg.length >= halfLength) {\n const t = (halfLength - accumulated) / seg.length;\n return {\n x: seg.start.x + t * (seg.end.x - seg.start.x),\n y: seg.start.y + t * (seg.end.y - seg.start.y),\n };\n }\n accumulated += seg.length;\n }\n\n return path[0]!;\n }\n\n private getPathStrategy(type: EdgePathType): PathStrategy {\n switch (type) {\n case 'straight':\n return new StraightPathStrategy();\n case 'polyline':\n return new PolylinePathStrategy();\n case 'editable-polyline':\n return new PolylinePathStrategy();\n case 'bezier':\n return new BezierPathStrategy();\n default:\n return new StraightPathStrategy();\n }\n }\n\n private applyLineDash(ctx: CanvasRenderingContext2D, style: EdgeStyle): void {\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n } else {\n ctx.lineDashOffset = 0;\n }\n }\n}\n","import type { Point } from '@/types';\n\nexport interface LabelEditorState {\n kind: 'node' | 'edge';\n id: string;\n textarea: HTMLTextAreaElement;\n cleanup: () => void;\n}\n\nexport type LabelCommitCallback = (kind: 'node' | 'edge', id: string, value: string) => void;\n\n/**\n * Manages inline label editing for nodes and edges\n */\nexport class LabelEditor {\n private state: LabelEditorState | null = null;\n\n /**\n * Check if editor is currently active\n */\n get isActive(): boolean {\n return this.state !== null;\n }\n\n /**\n * Get current editor state\n */\n get currentState(): Readonly<LabelEditorState> | null {\n return this.state;\n }\n\n /**\n * Start editing a label\n */\n start(\n kind: 'node' | 'edge',\n id: string,\n text: string,\n worldPosition: Point,\n worldToScreen: (x: number, y: number) => Point,\n onCommit: LabelCommitCallback\n ): void {\n this.finish(true);\n\n const screenPoint = worldToScreen(worldPosition.x, worldPosition.y);\n const textarea = this.createTextarea(text, screenPoint);\n const { cleanup } = this.setupEventHandlers(textarea, onCommit);\n\n document.body.appendChild(textarea);\n textarea.focus();\n textarea.select();\n\n this.state = { kind, id, textarea, cleanup };\n }\n\n /**\n * Finish editing\n * @param commit - Whether to commit the changes\n * @param onCommit - Callback to invoke if committing\n */\n finish(commit: boolean, onCommit?: LabelCommitCallback): void {\n if (!this.state) {\n return;\n }\n\n const { kind, id, textarea, cleanup } = this.state;\n this.state = null;\n const value = textarea.value;\n cleanup();\n\n if (commit && onCommit) {\n onCommit(kind, id, value);\n }\n }\n\n private createTextarea(text: string, screenPoint: Point): HTMLTextAreaElement {\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.rows = 1;\n textarea.spellcheck = false;\n textarea.setAttribute('aria-label', 'Edit label');\n\n // Position and styling\n textarea.style.cssText = `\n position: fixed;\n left: ${screenPoint.x}px;\n top: ${screenPoint.y}px;\n transform: translate(-50%, -50%);\n z-index: 10001;\n min-width: 120px;\n max-width: 420px;\n min-height: 30px;\n padding: 6px 8px;\n border: 1px solid #6366f1;\n border-radius: 6px;\n box-shadow: 0 8px 18px rgba(15, 23, 42, 0.15);\n background: #ffffff;\n color: #0f172a;\n font: 14px sans-serif;\n line-height: 1.4;\n resize: none;\n overflow: hidden;\n `;\n\n this.resizeTextarea(textarea);\n\n return textarea;\n }\n\n private resizeTextarea(textarea: HTMLTextAreaElement): void {\n textarea.style.height = 'auto';\n textarea.style.height = `${Math.max(30, textarea.scrollHeight)}px`;\n }\n\n private setupEventHandlers(\n textarea: HTMLTextAreaElement,\n onCommit: LabelCommitCallback\n ): { cleanup: () => void; commit: () => void } {\n const commit = (): void => this.finish(true, onCommit);\n const cancel = (): void => this.finish(false);\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.preventDefault();\n cancel();\n return;\n }\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n commit();\n }\n };\n\n const handleBlur = (): void => commit();\n const handleInput = (): void => this.resizeTextarea(textarea);\n\n textarea.addEventListener('keydown', handleKeyDown);\n textarea.addEventListener('blur', handleBlur);\n textarea.addEventListener('input', handleInput);\n\n const cleanup = (): void => {\n textarea.removeEventListener('keydown', handleKeyDown);\n textarea.removeEventListener('blur', handleBlur);\n textarea.removeEventListener('input', handleInput);\n textarea.remove();\n };\n\n return { cleanup, commit };\n }\n}\n","import { InputHandler } from '@/events/InputHandler';\nimport type {\n InputEvent,\n WheelInputEvent,\n PanInputEvent,\n PinchInputEvent,\n} from '@/events/InputHandler';\nimport type { DiagramRenderer, OverlayDragSession } from './DiagramRenderer';\nimport { SelectionManager } from './SelectionManager';\nimport { DragManager } from './DragManager';\nimport { ResizeManager } from './ResizeManager';\nimport { NavigationManager } from './NavigationManager';\nimport { ConnectionManager } from './ConnectionManager';\nimport {\n ChangeEdgePropertiesCommand,\n ChangeGroupPropertiesCommand,\n ChangeNodePropertiesCommand,\n HistoryManager,\n MoveNodesCommand,\n RemoveNodeFromGroupsCommand,\n createEdgeSnapshot,\n createGroupSnapshot,\n createNodeSnapshot,\n} from './HistoryManager';\nimport type { Bounds, EdgeEndpoint, Point, SerializedEdge, SerializedNode } from '@/types';\nimport { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { Node } from '@/elements/Node';\nimport { CompositeCommand } from './history/commands';\nimport { LabelEditor } from './LabelEditor';\nimport { shallowEqual } from '@/utils/style';\nimport { mergeBounds } from '@/utils/geometry';\n\nexport interface InteractionKeymap {\n deleteKeys: string[];\n copyKey: string;\n pasteKey: string;\n undoKey: string;\n redoKey: string;\n}\n\nexport interface InteractionManagerOptions {\n renderer: DiagramRenderer;\n createEdge?: (from: EdgeEndpoint, to: EdgeEndpoint) => Edge;\n nodeFactory?: (data: SerializedNode) => Node;\n edgeFactory?: (data: SerializedEdge) => Edge;\n snapToGrid?: boolean;\n gridSize?: number;\n alignToNodes?: boolean;\n /** When true, edges can be attached anywhere on the shape outline (not just ports) */\n attachToOutline?: boolean;\n keymap?: Partial<InteractionKeymap>;\n}\n\nconst DEFAULT_KEYMAP: InteractionKeymap = {\n deleteKeys: ['Delete', 'Backspace'],\n copyKey: 'c',\n pasteKey: 'v',\n undoKey: 'z',\n redoKey: 'y',\n};\n\nexport class InteractionManager {\n private readonly renderer: DiagramRenderer;\n private inputHandler: InputHandler;\n private readonly selectionManager: SelectionManager;\n private readonly dragManager: DragManager;\n private readonly resizeManager: ResizeManager;\n private readonly navigationManager: NavigationManager;\n private readonly connectionManager: ConnectionManager;\n private readonly historyManager: HistoryManager;\n private keymap: InteractionKeymap;\n private overlayCleanup: (() => void) | null = null;\n\n private dragStartPositions = new Map<string, { x: number; y: number }>();\n private reconnectOrigins = new Map<\n string,\n { endpoint: 'start' | 'end'; original: EdgeEndpoint }\n >();\n\n private clipboard: {\n nodes: SerializedNode[];\n edges: SerializedEdge[];\n } | null = null;\n\n private pendingPropertyChanges = new Map<\n string,\n {\n kind: 'node' | 'edge' | 'group';\n id: string;\n before:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>;\n after:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>;\n timerId: number;\n }\n >();\n private propertyChangeDebounceMs = 350;\n private labelEditor = new LabelEditor();\n private scrollbarDragState: { axis: 'horizontal' | 'vertical'; pointerOffset: number } | null =\n null;\n private handledScrollbarMouseDown = false;\n private overlayDragSession: OverlayDragSession | null = null;\n private handledOverlayMouseDown = false;\n\n constructor(options: InteractionManagerOptions) {\n this.renderer = options.renderer;\n this.inputHandler = new InputHandler({\n canvas: this.renderer.getCanvas(),\n screenToWorld: (x, y): { x: number; y: number } => this.renderer.screenToWorld(x, y),\n });\n\n this.selectionManager = new SelectionManager(this.renderer);\n this.dragManager = new DragManager({\n renderer: this.renderer,\n selectionManager: this.selectionManager,\n snapToGrid: options.snapToGrid ?? this.renderer.snapToGrid,\n gridSize: options.gridSize ?? 20,\n alignToNodes: options.alignToNodes ?? true,\n });\n this.resizeManager = new ResizeManager({\n renderer: this.renderer,\n selectionManager: this.selectionManager,\n snapToGrid: options.snapToGrid ?? this.renderer.snapToGrid,\n gridSize: options.gridSize ?? 20,\n });\n this.navigationManager = new NavigationManager({ renderer: this.renderer });\n this.historyManager = new HistoryManager();\n\n this.keymap = { ...DEFAULT_KEYMAP, ...options.keymap };\n\n const attachToOutline = options.attachToOutline ?? false;\n this.renderer.attachToOutline = attachToOutline;\n this.connectionManager = new ConnectionManager({\n renderer: this.renderer,\n createEdge:\n options.createEdge ??\n ((from, to): Edge => new Edge({ from, to, type: 'bezier', arrowType: 'single' })),\n snapToGrid: options.snapToGrid ?? this.renderer.snapToGrid,\n gridSize: options.gridSize ?? 20,\n attachToOutline,\n addEdge: (edge): void => {\n this.historyManager.execute({\n execute: (): void => this.renderer.addEdge(edge),\n undo: (): void => {\n this.renderer.removeEdge(edge.id);\n },\n });\n },\n });\n\n this.setupEvents(options);\n }\n\n get selection(): SelectionManager {\n return this.selectionManager;\n }\n\n get drag(): DragManager {\n return this.dragManager;\n }\n\n get resize(): ResizeManager {\n return this.resizeManager;\n }\n\n get navigation(): NavigationManager {\n return this.navigationManager;\n }\n\n get connection(): ConnectionManager {\n return this.connectionManager;\n }\n\n get history(): HistoryManager {\n return this.historyManager;\n }\n\n changeNodeProperties(nodeId: string, apply: (node: Node) => void): void {\n const node = this.renderer.getNode(nodeId);\n if (!node) {\n return;\n }\n const before = createNodeSnapshot(node);\n apply(node);\n const after = createNodeSnapshot(node);\n if (shallowEqual(before, after)) {\n return;\n }\n this.queuePropertyChange('node', nodeId, before, after);\n }\n\n changeEdgeProperties(edgeId: string, apply: (edge: Edge) => void): void {\n const edge = this.renderer.getEdge(edgeId);\n if (!edge) {\n return;\n }\n const before = createEdgeSnapshot(edge);\n apply(edge);\n const after = createEdgeSnapshot(edge);\n if (shallowEqual(before, after)) {\n return;\n }\n this.queuePropertyChange('edge', edgeId, before, after);\n }\n\n changeGroupProperties(groupId: string, apply: (group: Group) => void): void {\n const group = this.renderer.getGroup(groupId);\n if (!group) {\n return;\n }\n const before = createGroupSnapshot(group);\n apply(group);\n const after = createGroupSnapshot(group);\n if (shallowEqual(before, after)) {\n return;\n }\n this.queuePropertyChange('group', groupId, before, after);\n }\n\n removeNodeFromGroups(nodeId: string, groupIds?: string[]): void {\n const node = this.renderer.getNode(nodeId);\n if (!node) {\n return;\n }\n const groups =\n groupIds ??\n Array.from(this.renderer.groups.values())\n .filter((group) => group.hasChild(nodeId))\n .map((group) => group.id);\n if (groups.length === 0) {\n return;\n }\n this.historyManager.execute(\n new RemoveNodeFromGroupsCommand(\n (id) => this.renderer.getGroup(id),\n (id) => this.renderer.getNode(id),\n nodeId,\n groups\n )\n );\n }\n\n deleteByIds(ids: string[]): void {\n if (ids.length === 0) {\n return;\n }\n\n const command = this.buildDeleteCommand(ids);\n this.historyManager.execute(command);\n this.selectionManager.clearSelection();\n this.renderer.markDirty();\n }\n\n zoomToSelection(padding = 50): void {\n const bounds = this.getSelectionBounds();\n if (bounds) {\n this.navigationManager.zoomToSelection(bounds, padding);\n }\n }\n\n destroy(): void {\n this.labelEditor.finish(false);\n if (this.overlayDragSession) {\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n }\n if (this.scrollbarDragState) {\n this.renderer.setScrollbarActiveAxis(null);\n this.scrollbarDragState = null;\n }\n this.renderer.clearScrollbarHover();\n this.inputHandler.destroy();\n this.overlayCleanup?.();\n this.overlayCleanup = null;\n }\n\n private setupEvents(options: InteractionManagerOptions): void {\n this.overlayCleanup = this.renderer.addOverlayRenderer((ctx) => {\n this.selectionManager.renderSelectionRect(ctx);\n this.dragManager.renderAlignmentGuides(ctx);\n this.connectionManager.renderPreview(ctx);\n this.connectionManager.renderHoverAnchors(ctx);\n for (const id of this.selectionManager.selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n node.renderResizeHandles(ctx);\n }\n }\n });\n\n this.inputHandler.on('mousedown', (event) => this.handleMouseDown(event));\n this.inputHandler.on('mousemove', (event) => this.handleMouseMove(event));\n this.inputHandler.on('mouseup', (event) => this.handleMouseUp(event));\n this.inputHandler.on('click', (event) => this.handleClick(event));\n this.inputHandler.on('dblclick', (event) => this.handleDoubleClick(event));\n this.inputHandler.on('wheel', (event) => this.handleWheel(event));\n this.inputHandler.on('pan', (event) => this.handlePan(event));\n this.inputHandler.on('pinch', (event) => this.handlePinch(event));\n this.inputHandler.on('keydown', (event) => this.handleKeyDown(event, options));\n this.inputHandler.on('keyup', (event) => this.handleKeyUp(event));\n\n this.dragManager.on('dragstart', (nodeIds) => {\n this.connectionManager.disableHover();\n this.dragStartPositions.clear();\n for (const id of nodeIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n this.dragStartPositions.set(id, { x: node.x, y: node.y });\n }\n }\n });\n\n this.dragManager.on('dragend', (nodeIds) => {\n this.connectionManager.enableHover();\n\n const nodePositions = new Map<\n string,\n { before: { x: number; y: number }; after: { x: number; y: number } }\n >();\n for (const id of nodeIds) {\n const node = this.renderer.getNode(id);\n const before = this.dragStartPositions.get(id);\n if (!node || !before) continue;\n const after = { x: node.x, y: node.y };\n if (before.x !== after.x || before.y !== after.y) {\n nodePositions.set(id, { before, after });\n }\n }\n\n if (nodePositions.size > 0) {\n this.historyManager.execute(\n new MoveNodesCommand((id) => this.renderer.getNode(id), nodePositions)\n );\n }\n });\n\n this.connectionManager.on('edgeReconnectStart', (edge, endpoint, original) => {\n this.reconnectOrigins.set(edge.id, { endpoint, original: { ...original } });\n });\n\n this.connectionManager.on('edgeReconnect', (edge, endpoint) => {\n const origin = this.reconnectOrigins.get(edge.id);\n if (!origin || origin.endpoint !== endpoint) {\n return;\n }\n\n const before = origin.original;\n const after = endpoint === 'start' ? edge.from : edge.to;\n if (this.endpointsEqual(before, after)) {\n this.reconnectOrigins.delete(edge.id);\n return;\n }\n\n this.historyManager.execute({\n execute: () => {\n if (endpoint === 'start') {\n edge.from = { ...after };\n } else {\n edge.to = { ...after };\n }\n this.renderer.markDirty();\n },\n undo: () => {\n if (endpoint === 'start') {\n edge.from = { ...before };\n } else {\n edge.to = { ...before };\n }\n this.renderer.markDirty();\n },\n });\n this.reconnectOrigins.delete(edge.id);\n });\n\n this.historyManager.on('change', () => {\n this.renderer.markDirty();\n });\n }\n\n private handleMouseDown(event: InputEvent): void {\n this.handledScrollbarMouseDown = false;\n this.handledOverlayMouseDown = false;\n\n if (this.resizeManager.handleMouseDown(event)) {\n return;\n }\n if (this.connectionManager.tryStartReconnection(event)) {\n return;\n }\n if (this.connectionManager.tryStartConnectionAtPoint(event)) {\n return;\n }\n\n const overlayDrag = this.renderer.beginOverlayDrag(event.screenX, event.screenY);\n if (overlayDrag) {\n this.overlayDragSession = overlayDrag;\n this.handledOverlayMouseDown = true;\n return;\n }\n\n const scrollbarHit = this.renderer.hitTestScrollbarThumb(event.screenX, event.screenY);\n if (scrollbarHit) {\n this.scrollbarDragState = scrollbarHit;\n this.handledScrollbarMouseDown = true;\n this.renderer.setScrollbarActiveAxis(scrollbarHit.axis);\n this.renderer.notifyScrollbarInteraction();\n return;\n }\n\n if (this.renderer.clickScrollbarTrack(event.screenX, event.screenY)) {\n this.handledScrollbarMouseDown = true;\n return;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const hitElement = this.renderer.getElementAtPoint(point);\n\n if (hitElement === undefined && event.button === 0) {\n if (event.ctrlKey || event.metaKey) {\n this.selectionManager.startSelectionRect(point);\n return;\n }\n this.selectionManager.clearSelection();\n this.navigationManager.startPan(event);\n return;\n }\n\n if (this.navigationManager.handleMouseDown(event)) {\n return;\n }\n\n // Connection creation now starts from anchor points without modifiers\n\n if (this.dragManager.handleMouseDown(event)) {\n return;\n }\n }\n\n private handleMouseMove(event: InputEvent): void {\n if (event.originalEvent instanceof MouseEvent && event.originalEvent.buttons === 0) {\n if (this.overlayDragSession) {\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n }\n if (this.scrollbarDragState) {\n this.renderer.setScrollbarActiveAxis(null);\n this.scrollbarDragState = null;\n }\n if (this.navigationManager.panning) {\n this.navigationManager.handleMouseUp(event);\n }\n }\n\n const overScrollbar = this.renderer.updateScrollbarHover(event.screenX, event.screenY);\n\n if (this.overlayDragSession) {\n const moved = this.renderer.updateOverlayDrag(\n this.overlayDragSession,\n event.screenX,\n event.screenY\n );\n if (moved) {\n return;\n }\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n }\n\n if (this.scrollbarDragState) {\n const moved = this.renderer.dragScrollbarThumb(\n this.scrollbarDragState.axis,\n event.screenX,\n event.screenY,\n this.scrollbarDragState.pointerOffset\n );\n if (moved) {\n return;\n }\n this.renderer.setScrollbarActiveAxis(null);\n this.scrollbarDragState = null;\n }\n\n if (overScrollbar) {\n return;\n }\n\n if (this.resizeManager.handleMouseMove(event)) {\n return;\n }\n\n if (this.connectionManager.handleMouseMove(event)) {\n return;\n }\n\n if (this.dragManager.handleMouseMove(event)) {\n return;\n }\n\n if (this.selectionManager.selectionRectangle !== null) {\n this.selectionManager.updateSelectionRect({ x: event.worldX, y: event.worldY });\n return;\n }\n\n this.navigationManager.handleMouseMove(event);\n }\n\n private handleMouseUp(event: InputEvent): void {\n if (this.overlayDragSession) {\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n return;\n }\n\n if (this.scrollbarDragState) {\n this.scrollbarDragState = null;\n this.renderer.setScrollbarActiveAxis(null);\n return;\n }\n\n if (this.resizeManager.handleMouseUp()) {\n return;\n }\n\n if (this.connectionManager.handleMouseUp(event)) {\n return;\n }\n\n if (this.dragManager.handleMouseUp(event)) {\n return;\n }\n\n if (this.selectionManager.selectionRectangle !== null) {\n this.selectionManager.endSelectionRect();\n return;\n }\n\n this.navigationManager.handleMouseUp(event);\n }\n\n private handleClick(event: InputEvent): void {\n if (this.handledOverlayMouseDown) {\n this.handledOverlayMouseDown = false;\n return;\n }\n\n if (this.handledScrollbarMouseDown) {\n this.handledScrollbarMouseDown = false;\n return;\n }\n\n if (\n this.dragManager.handledMouseDown ||\n this.resizeManager.handledMouseDown ||\n this.connectionManager.connecting\n ) {\n return;\n }\n\n this.selectionManager.handleClick(event);\n }\n\n private handleDoubleClick(event: InputEvent): void {\n if (\n this.dragManager.handledMouseDown ||\n this.resizeManager.handledMouseDown ||\n this.connectionManager.connecting\n ) {\n return;\n }\n\n if (this.connectionManager.handleDoubleClick(event)) {\n return;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const edgeByLabel = this.getEdgeLabelAtPoint(point);\n if (edgeByLabel) {\n const labelPosition = edgeByLabel.getLabelPosition() ?? point;\n this.startLabelEdit('edge', edgeByLabel.id, edgeByLabel.label?.text ?? '', labelPosition);\n return;\n }\n\n const hitElement = this.renderer.getElementAtPoint(point);\n if (!hitElement) {\n this.labelEditor.finish(true, (kind, id, value) => this.handleLabelCommit(kind, id, value));\n return;\n }\n\n if ('typeName' in hitElement) {\n const editText = hitElement.label?.editableText ?? hitElement.label?.text ?? '';\n this.startLabelEdit('node', hitElement.id, editText, hitElement.getLabelPosition());\n return;\n }\n\n if ('from' in hitElement && 'to' in hitElement) {\n const labelPosition = hitElement.getLabelPosition() ?? point;\n this.startLabelEdit('edge', hitElement.id, hitElement.label?.text ?? '', labelPosition);\n }\n }\n\n private getEdgeLabelAtPoint(point: Point): Edge | null {\n const zoom = Math.max(this.renderer.zoom, 0.0001);\n const maxDistance = 28 / zoom;\n const maxDistanceSq = maxDistance * maxDistance;\n\n let closestEdge: Edge | null = null;\n let closestDistanceSq = Infinity;\n\n for (const edge of this.renderer.edges.values()) {\n if (!edge.visible || !edge.label) {\n continue;\n }\n\n const labelPosition = edge.getLabelPosition();\n if (!labelPosition) {\n continue;\n }\n\n const dx = point.x - labelPosition.x;\n const dy = point.y - labelPosition.y;\n const distanceSq = dx * dx + dy * dy;\n if (distanceSq > maxDistanceSq || distanceSq >= closestDistanceSq) {\n continue;\n }\n\n closestDistanceSq = distanceSq;\n closestEdge = edge;\n }\n\n return closestEdge;\n }\n\n private handleWheel(event: WheelInputEvent): void {\n this.navigationManager.handleWheel(event);\n }\n\n private handlePan(event: PanInputEvent): void {\n this.navigationManager.handlePanGesture(event);\n }\n\n private handlePinch(event: PinchInputEvent): void {\n this.navigationManager.handlePinch(event);\n }\n\n private handleKeyDown(event: KeyboardEvent, options: InteractionManagerOptions): void {\n const isCtrlOrMeta = event.ctrlKey || event.metaKey;\n // Use event.code for letter keys to work with any keyboard layout (e.g. Russian)\n const key = event.code.startsWith('Key')\n ? event.code.slice(3).toLowerCase()\n : event.key.toLowerCase();\n\n if (isCtrlOrMeta && (key === 'z' || key === 'y')) {\n this.flushPendingPropertyChanges();\n }\n\n if (this.historyManager.handleKeyDown(event)) {\n return;\n }\n\n this.navigationManager.handleKeyDown(event);\n\n if (this.handleViewportNavigationKey(event)) {\n return;\n }\n\n if (this.keymap.deleteKeys.includes(event.key)) {\n event.preventDefault();\n this.deleteSelection();\n return;\n }\n\n if (isCtrlOrMeta && key === this.keymap.copyKey) {\n event.preventDefault();\n this.copySelection();\n return;\n }\n\n if (isCtrlOrMeta && key === this.keymap.pasteKey) {\n event.preventDefault();\n this.pasteSelection(options);\n return;\n }\n }\n\n private handleKeyUp(event: KeyboardEvent): void {\n this.navigationManager.handleKeyUp(event);\n }\n\n private handleViewportNavigationKey(event: KeyboardEvent): boolean {\n switch (event.key) {\n case 'PageDown':\n event.preventDefault();\n this.renderer.scrollViewportBy(0, this.renderer.height * 0.8);\n return true;\n case 'PageUp':\n event.preventDefault();\n this.renderer.scrollViewportBy(0, -this.renderer.height * 0.8);\n return true;\n case 'Home':\n event.preventDefault();\n this.renderer.scrollViewportToStart();\n return true;\n case 'End':\n event.preventDefault();\n this.renderer.scrollViewportToEnd();\n return true;\n default:\n return false;\n }\n }\n\n private startLabelEdit(\n kind: 'node' | 'edge',\n id: string,\n text: string,\n worldPosition: Point\n ): void {\n this.labelEditor.start(\n kind,\n id,\n text,\n worldPosition,\n (x, y) => this.renderer.worldToScreen(x, y),\n (k, i, value) => this.handleLabelCommit(k, i, value)\n );\n }\n\n private handleLabelCommit(kind: 'node' | 'edge', id: string, nextValue: string): void {\n if (kind === 'node') {\n this.changeNodeProperties(id, (node) => {\n const value = nextValue.trim();\n if (value.length === 0) {\n node.label = undefined;\n return;\n }\n if (!node.label) {\n node.label = value;\n return;\n }\n if (node.label.editableText !== undefined) {\n node.label.editableText = value;\n node.label.text = value;\n } else {\n node.label.text = value;\n }\n });\n return;\n }\n\n this.changeEdgeProperties(id, (edge) => {\n const value = nextValue.trim();\n if (value.length === 0) {\n edge.label = undefined;\n return;\n }\n if (!edge.label) {\n edge.label = value;\n return;\n }\n edge.label.text = value;\n });\n }\n\n private queuePropertyChange(\n kind: 'node' | 'edge' | 'group',\n id: string,\n before:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>,\n after:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>\n ): void {\n const key = `${kind}:${id}`;\n const existing = this.pendingPropertyChanges.get(key);\n if (existing) {\n existing.after = after;\n window.clearTimeout(existing.timerId);\n existing.timerId = window.setTimeout(\n () => this.flushPendingPropertyChange(key),\n this.propertyChangeDebounceMs\n );\n return;\n }\n\n const timerId = window.setTimeout(\n () => this.flushPendingPropertyChange(key),\n this.propertyChangeDebounceMs\n );\n this.pendingPropertyChanges.set(key, { kind, id, before, after, timerId });\n }\n\n private flushPendingPropertyChanges(): void {\n const keys = Array.from(this.pendingPropertyChanges.keys());\n for (const key of keys) {\n this.flushPendingPropertyChange(key);\n }\n }\n\n private flushPendingPropertyChange(key: string): void {\n const pending = this.pendingPropertyChanges.get(key);\n if (!pending) {\n return;\n }\n window.clearTimeout(pending.timerId);\n this.pendingPropertyChanges.delete(key);\n if (shallowEqual(pending.before as object, pending.after as object)) {\n return;\n }\n\n switch (pending.kind) {\n case 'node':\n this.historyManager.execute(\n new ChangeNodePropertiesCommand(\n (id) => this.renderer.getNode(id),\n pending.id,\n pending.before as ReturnType<typeof createNodeSnapshot>,\n pending.after as ReturnType<typeof createNodeSnapshot>\n )\n );\n break;\n case 'edge':\n this.historyManager.execute(\n new ChangeEdgePropertiesCommand(\n (id) => this.renderer.getEdge(id),\n pending.id,\n pending.before as ReturnType<typeof createEdgeSnapshot>,\n pending.after as ReturnType<typeof createEdgeSnapshot>\n )\n );\n break;\n case 'group':\n this.historyManager.execute(\n new ChangeGroupPropertiesCommand(\n (id) => this.renderer.getGroup(id),\n pending.id,\n pending.before as ReturnType<typeof createGroupSnapshot>,\n pending.after as ReturnType<typeof createGroupSnapshot>\n )\n );\n break;\n }\n }\n\n private deleteSelection(): void {\n const selectedIds = Array.from(this.selectionManager.selectedIds);\n this.deleteByIds(selectedIds);\n }\n\n private buildDeleteCommand(selectedIds: string[]): CompositeCommand {\n const nodes: Node[] = [];\n const edges: Edge[] = [];\n const edgeIds = new Set<string>();\n const nodeIds = new Set<string>();\n const nodeGroupIds = new Map<string, string[]>();\n\n for (const id of selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n nodes.push(node);\n nodeIds.add(id);\n continue;\n }\n\n const edge = this.renderer.getEdge(id);\n if (edge && !edgeIds.has(edge.id)) {\n edgeIds.add(edge.id);\n edges.push(edge);\n }\n }\n\n if (nodeIds.size > 0) {\n for (const group of this.renderer.groups.values()) {\n for (const child of group.children) {\n if ('typeName' in child && nodeIds.has(child.id)) {\n const list = nodeGroupIds.get(child.id) ?? [];\n list.push(group.id);\n nodeGroupIds.set(child.id, list);\n }\n }\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (nodeIds.has(edge.from.nodeId) || nodeIds.has(edge.to.nodeId)) {\n if (!edgeIds.has(edge.id)) {\n edgeIds.add(edge.id);\n edges.push(edge);\n }\n }\n }\n\n return new CompositeCommand([\n {\n execute: (): void => {\n for (const edge of edges) {\n this.renderer.removeEdge(edge.id);\n }\n for (const node of nodes) {\n this.renderer.removeNode(node.id);\n }\n },\n undo: (): void => {\n for (const node of nodes) {\n this.renderer.addNode(node);\n }\n for (const node of nodes) {\n const groupIds = nodeGroupIds.get(node.id);\n if (!groupIds) {\n continue;\n }\n for (const groupId of groupIds) {\n const group = this.renderer.getGroup(groupId);\n if (group) {\n group.addChild(node);\n }\n }\n }\n for (const edge of edges) {\n this.renderer.addEdge(edge);\n }\n },\n },\n ]);\n }\n\n private copySelection(): void {\n const selectedIds = new Set(this.selectionManager.selectedIds);\n if (selectedIds.size === 0) {\n return;\n }\n\n const nodes: SerializedNode[] = [];\n const edges: SerializedEdge[] = [];\n const nodeIds = new Set<string>();\n\n for (const id of selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n nodes.push({\n id: node.id,\n type: node.typeName,\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n style: node.style,\n styleClass: node.styleClass,\n label: node.label?.text,\n labelStyleClass: node.label?.styleClass,\n ports: node.ports.map((port) => ({\n id: port.id,\n type: port.type,\n position: port.position,\n styleClass: port.styleClass,\n })),\n data: Object.keys(node.data).length > 0 ? node.data : undefined,\n });\n nodeIds.add(node.id);\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (nodeIds.has(edge.from.nodeId) && nodeIds.has(edge.to.nodeId)) {\n edges.push({\n id: edge.id,\n from: edge.from,\n to: edge.to,\n type: edge.type,\n controlPoints: edge.controlPoints,\n arrowType: edge.arrowType,\n style: edge.style,\n styleClass: edge.styleClass,\n label: edge.label?.text,\n labelStyleClass: edge.label?.styleClass,\n labelOffset: edge.labelOffset !== 0 ? edge.labelOffset : undefined,\n labelBackground: edge.labelBackground,\n data: Object.keys(edge.data).length > 0 ? edge.data : undefined,\n });\n }\n }\n\n this.clipboard = { nodes, edges };\n }\n\n private pasteSelection(options: InteractionManagerOptions): void {\n if (!this.clipboard || !options.nodeFactory || !options.edgeFactory) {\n return;\n }\n\n const offset: Point = { x: 20, y: 20 };\n const idMap = new Map<string, string>();\n const newNodes: Node[] = [];\n const newEdges: Edge[] = [];\n\n for (const nodeData of this.clipboard.nodes) {\n const newId = `${nodeData.id}_copy_${Date.now()}`;\n idMap.set(nodeData.id, newId);\n const copyData: SerializedNode = {\n ...nodeData,\n id: newId,\n x: nodeData.x + offset.x,\n y: nodeData.y + offset.y,\n };\n newNodes.push(options.nodeFactory(copyData));\n }\n\n for (const edgeData of this.clipboard.edges) {\n const fromNodeId = idMap.get(edgeData.from.nodeId);\n const toNodeId = idMap.get(edgeData.to.nodeId);\n if (!fromNodeId || !toNodeId) {\n continue;\n }\n const newId = `${edgeData.id}_copy_${Date.now()}`;\n const copyEdge: SerializedEdge = {\n ...edgeData,\n id: newId,\n from: { ...edgeData.from, nodeId: fromNodeId },\n to: { ...edgeData.to, nodeId: toNodeId },\n };\n newEdges.push(options.edgeFactory(copyEdge));\n }\n\n if (newNodes.length === 0 && newEdges.length === 0) {\n return;\n }\n\n this.historyManager.execute({\n execute: () => {\n for (const node of newNodes) {\n this.renderer.addNode(node);\n }\n for (const edge of newEdges) {\n this.renderer.addEdge(edge);\n }\n },\n undo: () => {\n for (const edge of newEdges) {\n this.renderer.removeEdge(edge.id);\n }\n for (const node of newNodes) {\n this.renderer.removeNode(node.id);\n }\n },\n });\n }\n\n private endpointsEqual(a: EdgeEndpoint, b: EdgeEndpoint): boolean {\n if (a.nodeId !== b.nodeId) return false;\n if ((a.portId ?? null) !== (b.portId ?? null)) return false;\n const aParam = a.outlineParam;\n const bParam = b.outlineParam;\n if (aParam === undefined && bParam === undefined) return true;\n if (aParam === undefined || bParam === undefined) return false;\n return Math.abs((aParam % 1) - (bParam % 1)) < 1e-9;\n }\n\n private getSelectionBounds(): Bounds | null {\n const sources: Bounds[] = [];\n for (const id of this.selectionManager.selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n sources.push(node.getBounds());\n }\n }\n return mergeBounds(sources);\n }\n}\n","import type { AnimationOptions } from '@/types';\n\nexport interface AnimationState {\n opacity: number;\n scale: number;\n highlight: number;\n}\n\ninterface ExitEntry {\n start: number;\n onComplete?: () => void;\n}\n\nconst DEFAULT_OPTIONS: Required<AnimationOptions> = {\n enabled: false,\n enterDuration: 200,\n exitDuration: 180,\n highlightDuration: 450,\n enterScale: 0.92,\n exitScale: 0.98,\n};\n\nexport class AnimationManager {\n private options: Required<AnimationOptions>;\n private enter = new Map<string, number>();\n private exit = new Map<string, ExitEntry>();\n private highlight = new Map<string, number>();\n\n constructor(options: AnimationOptions = {}) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n configure(options: AnimationOptions): void {\n this.options = { ...this.options, ...options };\n }\n\n get enabled(): boolean {\n return this.options.enabled;\n }\n\n registerEnter(id: string, now = performance.now()): void {\n if (!this.options.enabled) {\n return;\n }\n this.enter.set(id, now);\n }\n\n registerExit(id: string, onComplete?: () => void, now = performance.now()): void {\n if (!this.options.enabled) {\n onComplete?.();\n return;\n }\n if (this.exit.has(id)) {\n return;\n }\n this.exit.set(id, { start: now, onComplete });\n }\n\n registerHighlight(id: string, now = performance.now()): void {\n if (!this.options.enabled) {\n return;\n }\n this.highlight.set(id, now);\n }\n\n isExiting(id: string): boolean {\n return this.exit.has(id);\n }\n\n hasActive(): boolean {\n return this.enter.size > 0 || this.exit.size > 0 || this.highlight.size > 0;\n }\n\n update(now = performance.now()): boolean {\n if (!this.options.enabled) {\n return false;\n }\n\n let changed = false;\n\n for (const [id, start] of this.enter) {\n if (now - start >= this.options.enterDuration) {\n this.enter.delete(id);\n changed = true;\n }\n }\n\n for (const [id, entry] of this.exit) {\n if (now - entry.start >= this.options.exitDuration) {\n this.exit.delete(id);\n entry.onComplete?.();\n changed = true;\n }\n }\n\n for (const [id, start] of this.highlight) {\n if (now - start >= this.options.highlightDuration) {\n this.highlight.delete(id);\n changed = true;\n }\n }\n\n return changed;\n }\n\n getState(id: string, now = performance.now()): AnimationState {\n const enterStart = this.enter.get(id);\n const exitEntry = this.exit.get(id);\n const highlightStart = this.highlight.get(id);\n\n let opacity = 1;\n let scale = 1;\n let highlight = 0;\n\n if (enterStart !== undefined) {\n const progress = Math.min(1, Math.max(0, (now - enterStart) / this.options.enterDuration));\n opacity *= progress;\n scale *= this.lerp(this.options.enterScale, 1, progress);\n }\n\n if (exitEntry !== undefined) {\n const progress = Math.min(1, Math.max(0, (now - exitEntry.start) / this.options.exitDuration));\n opacity *= 1 - progress;\n scale *= this.lerp(1, this.options.exitScale, progress);\n }\n\n if (highlightStart !== undefined) {\n const progress = Math.min(1, Math.max(0, (now - highlightStart) / this.options.highlightDuration));\n highlight = 1 - progress;\n scale *= 1 + 0.03 * highlight;\n }\n\n return { opacity, scale, highlight };\n }\n\n private lerp(from: number, to: number, t: number): number {\n return from + (to - from) * t;\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { Point } from '@/types';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\n\nexport type ContextMenuIcon =\n | string\n | {\n type: 'text' | 'svg' | 'html';\n value: string;\n };\n\nexport interface ContextMenuItem {\n label?: string;\n icon?: ContextMenuIcon;\n action?: (target: ContextMenuTarget) => void;\n items?: ContextMenuItem[];\n enabled?: boolean;\n visible?: boolean;\n separator?: boolean;\n}\n\nexport type ContextMenuTarget =\n | {\n type: 'node';\n node: Node;\n point: Point;\n screenPoint: Point;\n originalEvent: MouseEvent;\n }\n | {\n type: 'edge';\n edge: Edge;\n point: Point;\n screenPoint: Point;\n originalEvent: MouseEvent;\n }\n | {\n type: 'canvas';\n point: Point;\n screenPoint: Point;\n originalEvent: MouseEvent;\n };\n\nexport type ContextMenuProvider = ContextMenuItem[] | ((target: ContextMenuTarget) => ContextMenuItem[]);\n\nexport interface ContextMenuConfig {\n node?: ContextMenuProvider;\n edge?: ContextMenuProvider;\n canvas?: ContextMenuProvider;\n}\n\nexport interface ContextMenuOptions {\n menu: ContextMenuConfig;\n container?: HTMLElement;\n className?: string;\n minWidth?: number;\n closeOnSelect?: boolean;\n}\n\nexport interface ContextMenuEvents {\n open: [target: ContextMenuTarget];\n close: [];\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<ContextMenuOptions, 'menu'>> = {\n container: document.body,\n className: '',\n minWidth: 180,\n closeOnSelect: true,\n};\n\nexport class ContextMenuManager extends EventEmitter<ContextMenuEvents> {\n private renderer: DiagramRenderer;\n private options: ContextMenuOptions;\n private menuElement: HTMLDivElement | null = null;\n private cleanupHandlers: Array<() => void> = [];\n\n constructor(renderer: DiagramRenderer, options: ContextMenuOptions) {\n super();\n this.renderer = renderer;\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.attachListeners();\n }\n\n setMenu(menu: ContextMenuConfig): void {\n this.options = { ...this.options, menu };\n }\n\n destroy(): void {\n this.close();\n for (const cleanup of this.cleanupHandlers) {\n cleanup();\n }\n this.cleanupHandlers = [];\n this.removeAllListeners();\n }\n\n private attachListeners(): void {\n const canvas = this.renderer.getCanvas();\n const handleContextMenu = (event: MouseEvent): void => {\n if (event.button !== 2) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n const screenPoint: Point = { x: event.clientX, y: event.clientY };\n const worldPoint = this.renderer.screenToWorld(screenPoint.x, screenPoint.y);\n const hit = this.renderer.getElementAtPoint(worldPoint);\n\n let target: ContextMenuTarget;\n if (hit && 'typeName' in hit) {\n target = {\n type: 'node',\n node: hit,\n point: worldPoint,\n screenPoint,\n originalEvent: event,\n };\n } else if (hit && 'from' in hit && 'to' in hit) {\n target = {\n type: 'edge',\n edge: hit,\n point: worldPoint,\n screenPoint,\n originalEvent: event,\n };\n } else {\n target = {\n type: 'canvas',\n point: worldPoint,\n screenPoint,\n originalEvent: event,\n };\n }\n\n const items = this.resolveItems(target);\n if (items.length === 0) {\n this.close();\n return;\n }\n\n this.open(target, items);\n };\n\n const handleGlobalClick = (event: MouseEvent): void => {\n if (!this.menuElement) {\n return;\n }\n if (event.target instanceof HTMLElement && this.menuElement.contains(event.target)) {\n return;\n }\n this.close();\n };\n\n const handleEscape = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n this.close();\n }\n };\n\n canvas.addEventListener('contextmenu', handleContextMenu, true);\n document.addEventListener('mousedown', handleGlobalClick);\n window.addEventListener('keydown', handleEscape);\n\n this.cleanupHandlers.push(() => canvas.removeEventListener('contextmenu', handleContextMenu, true));\n this.cleanupHandlers.push(() => document.removeEventListener('mousedown', handleGlobalClick));\n this.cleanupHandlers.push(() => window.removeEventListener('keydown', handleEscape));\n }\n\n private resolveItems(target: ContextMenuTarget): ContextMenuItem[] {\n const provider =\n target.type === 'node'\n ? this.options.menu.node\n : target.type === 'edge'\n ? this.options.menu.edge\n : this.options.menu.canvas;\n\n if (!provider) {\n return [];\n }\n return typeof provider === 'function' ? provider(target) : provider;\n }\n\n private open(target: ContextMenuTarget, items: ContextMenuItem[]): void {\n this.close();\n const menu = this.buildMenu(items, target);\n menu.style.minWidth = `${this.options.minWidth}px`;\n menu.style.left = `${target.screenPoint.x}px`;\n menu.style.top = `${target.screenPoint.y}px`;\n menu.className = `papirus-context-menu ${this.options.className}`.trim();\n\n this.options.container?.appendChild(menu);\n this.menuElement = menu;\n\n this.adjustPosition(menu);\n this.emit('open', target);\n }\n\n private close(): void {\n if (this.menuElement) {\n this.menuElement.remove();\n this.menuElement = null;\n this.emit('close');\n }\n }\n\n private buildMenu(items: ContextMenuItem[], target: ContextMenuTarget): HTMLDivElement {\n const container = document.createElement('div');\n container.style.position = 'fixed';\n container.style.zIndex = '10000';\n container.style.background = '#ffffff';\n container.style.border = '1px solid #e5e7eb';\n container.style.borderRadius = '8px';\n container.style.padding = '6px';\n container.style.boxShadow = '0 8px 20px rgba(15, 23, 42, 0.18)';\n container.style.fontFamily = 'system-ui, -apple-system, Segoe UI, sans-serif';\n container.style.fontSize = '14px';\n container.style.color = '#0f172a';\n\n const list = this.buildList(items, target);\n container.appendChild(list);\n return container;\n }\n\n private buildList(items: ContextMenuItem[], target: ContextMenuTarget): HTMLUListElement {\n const list = document.createElement('ul');\n list.style.listStyle = 'none';\n list.style.margin = '0';\n list.style.padding = '0';\n\n for (const item of items) {\n if (item.visible === false) {\n continue;\n }\n if (item.separator) {\n const separator = document.createElement('li');\n separator.style.listStyle = 'none';\n separator.style.margin = '6px 0';\n separator.style.borderTop = '1px solid #e5e7eb';\n list.appendChild(separator);\n continue;\n }\n const li = document.createElement('li');\n li.style.position = 'relative';\n li.style.display = 'flex';\n li.style.alignItems = 'center';\n li.style.gap = '8px';\n li.style.padding = '6px 10px';\n li.style.borderRadius = '6px';\n li.style.cursor = item.enabled === false ? 'not-allowed' : 'pointer';\n li.style.opacity = item.enabled === false ? '0.5' : '1';\n\n const label = document.createElement('span');\n label.textContent = item.label ?? '';\n\n const iconElement = this.createIconElement(item.icon);\n li.appendChild(iconElement);\n\n li.appendChild(label);\n\n if (item.items && item.items.length > 0) {\n const arrow = document.createElement('span');\n arrow.textContent = '›';\n arrow.style.marginLeft = 'auto';\n li.appendChild(arrow);\n\n const sub = this.buildList(item.items, target);\n sub.style.position = 'absolute';\n sub.style.left = '100%';\n sub.style.top = '0';\n sub.style.marginLeft = '6px';\n sub.style.background = '#ffffff';\n sub.style.border = '1px solid #e5e7eb';\n sub.style.borderRadius = '8px';\n sub.style.padding = '6px';\n sub.style.boxShadow = '0 8px 20px rgba(15, 23, 42, 0.16)';\n sub.style.display = 'none';\n li.appendChild(sub);\n\n let hideTimeout: number | null = null;\n const showSubmenu = (): void => {\n if (hideTimeout !== null) {\n window.clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n sub.style.display = 'block';\n };\n const scheduleHide = (): void => {\n if (hideTimeout !== null) {\n window.clearTimeout(hideTimeout);\n }\n hideTimeout = window.setTimeout(() => {\n hideTimeout = null;\n if (li.matches(':hover') || sub.matches(':hover')) {\n return;\n }\n sub.style.display = 'none';\n }, 150);\n };\n const hideSubmenu = (event: MouseEvent): void => {\n const related = event.relatedTarget;\n if (related instanceof HTMLElement && li.contains(related)) {\n return;\n }\n scheduleHide();\n };\n\n li.addEventListener('mouseenter', showSubmenu);\n li.addEventListener('mouseleave', hideSubmenu);\n sub.addEventListener('mouseenter', showSubmenu);\n sub.addEventListener('mouseleave', hideSubmenu);\n }\n\n li.addEventListener('mouseenter', () => {\n li.style.background = '#f1f5f9';\n });\n li.addEventListener('mouseleave', () => {\n li.style.background = 'transparent';\n });\n li.addEventListener('click', (event) => {\n event.stopPropagation();\n if (item.enabled === false) {\n return;\n }\n item.action?.(target);\n if (this.options.closeOnSelect) {\n this.close();\n }\n });\n\n list.appendChild(li);\n }\n\n return list;\n }\n\n private createIconElement(icon?: ContextMenuIcon): HTMLSpanElement {\n const iconEl = document.createElement('span');\n iconEl.style.width = '16px';\n iconEl.style.height = '16px';\n iconEl.style.display = 'inline-flex';\n iconEl.style.alignItems = 'center';\n iconEl.style.justifyContent = 'center';\n iconEl.style.textAlign = 'center';\n\n if (!icon) {\n iconEl.textContent = '';\n return iconEl;\n }\n\n if (typeof icon === 'string') {\n if (this.isSvgString(icon)) {\n iconEl.innerHTML = icon;\n } else {\n iconEl.classList.add('material-symbols-outlined');\n iconEl.style.fontSize = '16px';\n iconEl.textContent = icon;\n }\n return iconEl;\n }\n\n if (icon.type === 'svg' || icon.type === 'html') {\n iconEl.innerHTML = icon.value;\n } else {\n iconEl.classList.add('material-symbols-outlined');\n iconEl.style.fontSize = '16px';\n iconEl.textContent = icon.value;\n }\n\n return iconEl;\n }\n\n private isSvgString(value: string): boolean {\n const trimmed = value.trim();\n return trimmed.startsWith('<svg') || trimmed.includes('</svg>');\n }\n\n private adjustPosition(menu: HTMLDivElement): void {\n const rect = menu.getBoundingClientRect();\n const padding = 8;\n let left = rect.left;\n let top = rect.top;\n\n if (rect.right > window.innerWidth - padding) {\n left = Math.max(padding, window.innerWidth - rect.width - padding);\n }\n if (rect.bottom > window.innerHeight - padding) {\n top = Math.max(padding, window.innerHeight - rect.height - padding);\n }\n\n menu.style.left = `${left}px`;\n menu.style.top = `${top}px`;\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { PathObstacle } from '@/elements/paths';\nimport type { Bounds, DiagramOptions, Point, ScrollbarOptions, ViewportState } from '@/types';\nimport { InteractionManager } from './InteractionManager';\nimport type { InteractionManagerOptions } from './InteractionManager';\nimport { ANCHOR_PORT_PREFIX } from '@/constants';\nimport { drawRoundedRectPath } from '@/utils/geometry';\nimport { applyStyleManagerToElements } from '@/utils/style';\nimport { getContentBounds } from '@/utils/contentBounds';\nimport { AnimationManager } from './AnimationManager';\nimport { ContextMenuManager } from './ContextMenuManager';\n\n/**\n * Events emitted by DiagramRenderer\n */\nexport interface DiagramEvents {\n render: [];\n zoom: [zoom: number];\n pan: [offsetX: number, offsetY: number];\n select: [elementIds: string[]];\n nodeAdd: [node: Node];\n nodeRemove: [node: Node];\n edgeAdd: [edge: Edge];\n edgeRemove: [edge: Edge];\n}\n\nexport interface DiagramPlugin {\n name?: string;\n install(renderer: DiagramRenderer): void;\n destroy?(renderer: DiagramRenderer): void;\n}\n\nconst DEFAULT_SCROLLBAR_OPTIONS: ScrollbarOptions = {\n enabled: true,\n autoHide: false,\n autoHideDelay: 1200,\n fadeDuration: 220,\n thickness: 6,\n hoverThickness: 8,\n minThumbLength: 24,\n hitAreaPadding: 4,\n pageScrollRatio: 0.8,\n trackColor: '',\n thumbColor: '',\n thumbHoverColor: '',\n thumbActiveColor: '',\n};\n\nconst DEFAULT_OPTIONS: Required<Omit<DiagramOptions, 'scrollbar'>> = {\n width: 800,\n height: 600,\n backgroundColor: '#ffffff',\n retina: true,\n minZoom: 0.1,\n maxZoom: 5,\n initialZoom: 1,\n snapToGrid: false,\n scrollbarOverlay: true,\n animations: {\n enabled: false,\n },\n};\n\ninterface OverlayDragPlugin extends DiagramPlugin {\n beginOverlayDrag?(renderer: DiagramRenderer, screenX: number, screenY: number): unknown;\n updateOverlayDrag?(\n renderer: DiagramRenderer,\n screenX: number,\n screenY: number,\n payload: unknown\n ): boolean;\n endOverlayDrag?(renderer: DiagramRenderer, payload: unknown): void;\n}\n\nexport interface OverlayDragSession {\n plugin: OverlayDragPlugin;\n payload: unknown;\n}\n\ntype ScrollbarAxis = 'horizontal' | 'vertical';\n\ninterface ScrollbarTrackMetrics {\n trackX: number;\n trackY: number;\n trackLength: number;\n thickness: number;\n thumbLength: number;\n thumbOffset: number;\n maxScroll: number;\n}\n\ninterface ScrollbarMetrics {\n contentBounds: Bounds;\n viewportBounds: Bounds;\n thickness: number;\n horizontal: ScrollbarTrackMetrics | null;\n vertical: ScrollbarTrackMetrics | null;\n}\n\n/**\n * Main diagram renderer class\n * Manages canvas, coordinate system, and render loop\n */\nexport class DiagramRenderer extends EventEmitter<DiagramEvents> {\n private readonly canvas: HTMLCanvasElement;\n private readonly ctx: CanvasRenderingContext2D;\n private readonly options: Required<Omit<DiagramOptions, 'scrollbar'>>;\n private readonly scrollbar: ScrollbarOptions;\n private plugins: DiagramPlugin[] = [];\n private styleManager?: StyleManager;\n private underlayRenderers = new Set<(ctx: CanvasRenderingContext2D) => void>();\n private overlayRenderers = new Set<(ctx: CanvasRenderingContext2D) => void>();\n private interactionManager: InteractionManager | null = null;\n private contextMenuManager: ContextMenuManager | null = null;\n private readonly animationManager: AnimationManager;\n private frameTime = 0;\n private scrollbarHoveredAxis: ScrollbarAxis | null = null;\n private scrollbarActiveAxis: ScrollbarAxis | null = null;\n private scrollbarLastInteractionAt = 0;\n private lastScrollbarAlpha = -1;\n\n private _zoom = 1;\n private _offsetX = 0;\n private _offsetY = 0;\n private _dirty = true;\n private _styleDirty = true;\n private _destroyed = false;\n private _canvasRect: DOMRectReadOnly | null = null;\n private _nodeObstaclesCache: PathObstacle[] | null = null;\n\n private animationFrameId: number | null = null;\n private devicePixelRatio: number;\n\n private _nodes = new Map<string, Node>();\n private _edges = new Map<string, Edge>();\n private _groups = new Map<string, Group>();\n private _attachToOutline = false;\n /** Reverse index: nodeId -> edgeIds connected to this node */\n private _nodeEdgeIndex = new Map<string, Set<string>>();\n\n /** When true, ports and anchor points are hidden (attach anywhere on outline) */\n get attachToOutline(): boolean {\n return this._attachToOutline;\n }\n\n set attachToOutline(value: boolean) {\n if (this._attachToOutline !== value) {\n this._attachToOutline = value;\n this.markDirty();\n }\n }\n\n constructor(canvas: HTMLCanvasElement | string, options: DiagramOptions = {}) {\n super();\n this.canvas = this.resolveCanvas(canvas);\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.scrollbar = this.resolveScrollbarOptions(options);\n\n const ctx = this.canvas.getContext('2d');\n if (ctx === null) {\n throw new Error('Failed to get 2D rendering context');\n }\n this.ctx = ctx;\n\n this.devicePixelRatio = this.options.retina ? window.devicePixelRatio || 1 : 1;\n this._zoom = this.options.initialZoom;\n this.animationManager = new AnimationManager(this.options.animations);\n this.scrollbarLastInteractionAt = performance.now();\n\n this.setupCanvas();\n this.startRenderLoop();\n }\n\n /**\n * Current zoom level\n */\n get zoom(): number {\n return this._zoom;\n }\n\n set zoom(value: number) {\n const clampedZoom = Math.max(this.options.minZoom, Math.min(this.options.maxZoom, value));\n if (this._zoom !== clampedZoom) {\n this._zoom = clampedZoom;\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n this.emit('zoom', clampedZoom);\n }\n }\n\n /**\n * Horizontal offset (pan)\n */\n get offsetX(): number {\n return this._offsetX;\n }\n\n set offsetX(value: number) {\n if (this._offsetX !== value) {\n this._offsetX = value;\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n this.emit('pan', this._offsetX, this._offsetY);\n }\n }\n\n /**\n * Vertical offset (pan)\n */\n get offsetY(): number {\n return this._offsetY;\n }\n\n set offsetY(value: number) {\n if (this._offsetY !== value) {\n this._offsetY = value;\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n this.emit('pan', this._offsetX, this._offsetY);\n }\n }\n\n /**\n * Get viewport state\n */\n get viewport(): ViewportState {\n return {\n zoom: this._zoom,\n offsetX: this._offsetX,\n offsetY: this._offsetY,\n };\n }\n\n /**\n * Set viewport state\n */\n set viewport(state: ViewportState) {\n this._zoom = Math.max(this.options.minZoom, Math.min(this.options.maxZoom, state.zoom));\n this._offsetX = state.offsetX;\n this._offsetY = state.offsetY;\n this.markDirty();\n this.emit('zoom', this._zoom);\n this.emit('pan', this._offsetX, this._offsetY);\n }\n\n /**\n * All nodes in the diagram\n */\n get nodes(): ReadonlyMap<string, Node> {\n return this._nodes;\n }\n\n /**\n * All edges in the diagram\n */\n get edges(): ReadonlyMap<string, Edge> {\n return this._edges;\n }\n\n /**\n * All groups in the diagram\n */\n get groups(): ReadonlyMap<string, Group> {\n return this._groups;\n }\n\n /**\n * Canvas width in CSS pixels\n */\n get width(): number {\n return this.options.width;\n }\n\n /**\n * Canvas height in CSS pixels\n */\n get height(): number {\n return this.options.height;\n }\n\n /**\n * Snap-to-grid state\n */\n get snapToGrid(): boolean {\n return this.options.snapToGrid;\n }\n\n /**\n * Device pixel ratio used for rendering\n */\n get pixelRatio(): number {\n return this.devicePixelRatio;\n }\n\n /**\n * Access the underlying canvas element\n */\n getCanvas(): HTMLCanvasElement {\n return this.canvas;\n }\n\n /**\n * Access the rendering context (read-only usage)\n */\n getContext(): CanvasRenderingContext2D {\n return this.ctx;\n }\n\n /**\n * Set the StyleManager used for rendering\n */\n setStyleManager(styleManager: StyleManager | undefined): void {\n this.styleManager = styleManager;\n this._styleDirty = true;\n this.markDirty();\n }\n\n /**\n * Get current StyleManager\n */\n getStyleManager(): StyleManager | undefined {\n return this.styleManager;\n }\n\n /**\n * Mark styles as dirty (force re-apply on next render)\n */\n markStyleDirty(): void {\n this._styleDirty = true;\n }\n\n /**\n * Access animation manager\n */\n getAnimationManager(): AnimationManager {\n return this.animationManager;\n }\n\n /**\n * Resize the canvas\n */\n resize(width: number, height: number): void {\n this.options.width = width;\n this.options.height = height;\n this.setupCanvas();\n this.updateCanvasRect();\n this.markDirty();\n }\n\n /**\n * Register and install a plugin\n */\n use(plugin: DiagramPlugin): void {\n plugin.install(this);\n this.plugins.push(plugin);\n }\n\n /**\n * Enable built-in interaction handling\n */\n enableInteractions(\n options: Omit<InteractionManagerOptions, 'renderer'> = {}\n ): InteractionManager {\n if (this.interactionManager) {\n return this.interactionManager;\n }\n this.interactionManager = new InteractionManager({ renderer: this, ...options });\n return this.interactionManager;\n }\n\n /**\n * Disable interaction handling\n */\n disableInteractions(): void {\n this.interactionManager?.destroy();\n this.interactionManager = null;\n }\n\n /**\n * Enable context menu handling\n */\n enableContextMenu(\n options: ConstructorParameters<typeof ContextMenuManager>[1]\n ): ContextMenuManager {\n this.contextMenuManager?.destroy();\n this.contextMenuManager = new ContextMenuManager(this, options);\n return this.contextMenuManager;\n }\n\n /**\n * Disable context menu handling\n */\n disableContextMenu(): void {\n this.contextMenuManager?.destroy();\n this.contextMenuManager = null;\n }\n\n /**\n * Register an underlay renderer (called before elements)\n */\n addUnderlayRenderer(renderer: (ctx: CanvasRenderingContext2D) => void): () => void {\n this.underlayRenderers.add(renderer);\n this.markDirty();\n return () => {\n this.underlayRenderers.delete(renderer);\n this.markDirty();\n };\n }\n\n /**\n * Register an overlay renderer (called after main render)\n */\n addOverlayRenderer(renderer: (ctx: CanvasRenderingContext2D) => void): () => void {\n this.overlayRenderers.add(renderer);\n this.markDirty();\n return () => {\n this.overlayRenderers.delete(renderer);\n this.markDirty();\n };\n }\n\n /**\n * Convert screen coordinates to world coordinates\n */\n screenToWorld(screenX: number, screenY: number): Point {\n const rect = this._canvasRect ?? this.canvas.getBoundingClientRect();\n const scaleX = rect.width / this.options.width;\n const scaleY = rect.height / this.options.height;\n const canvasX = (screenX - rect.left) / scaleX;\n const canvasY = (screenY - rect.top) / scaleY;\n const x = (canvasX - this._offsetX) / this._zoom;\n const y = (canvasY - this._offsetY) / this._zoom;\n return { x, y };\n }\n\n /**\n * Convert world coordinates to screen coordinates\n */\n worldToScreen(worldX: number, worldY: number): Point {\n const rect = this._canvasRect ?? this.canvas.getBoundingClientRect();\n const scaleX = rect.width / this.options.width;\n const scaleY = rect.height / this.options.height;\n const x = (worldX * this._zoom + this._offsetX) * scaleX + rect.left;\n const y = (worldY * this._zoom + this._offsetY) * scaleY + rect.top;\n return { x, y };\n }\n\n /**\n * Add a node to the diagram\n */\n addNode(node: Node): void {\n node.setDirtyListener(() => this.markDirty());\n node.setAttachToOutlineGetter(() => this._attachToOutline);\n this._nodes.set(node.id, node);\n this._nodeObstaclesCache = null;\n this.animationManager.registerEnter(node.id);\n this.markDirty();\n this.emit('nodeAdd', node);\n }\n\n /**\n * Remove a node from the diagram\n */\n removeNode(nodeId: string): boolean {\n const node = this._nodes.get(nodeId);\n if (node === undefined) {\n return false;\n }\n\n // Collect connected edges first to avoid modifying Map while iterating\n const edgesToRemove: string[] = [];\n for (const edge of this._edges.values()) {\n if (edge.from.nodeId === nodeId || edge.to.nodeId === nodeId) {\n edgesToRemove.push(edge.id);\n }\n }\n\n if (this.animationManager.enabled && !this.animationManager.isExiting(nodeId)) {\n for (const edgeId of edgesToRemove) {\n this.removeEdge(edgeId);\n }\n this.animationManager.registerExit(nodeId, () => {\n this.removeNodeImmediate(nodeId);\n });\n this.markDirty();\n return true;\n }\n\n return this.removeNodeImmediate(nodeId);\n }\n\n /**\n * Get a node by ID\n */\n getNode(nodeId: string): Node | undefined {\n return this._nodes.get(nodeId);\n }\n\n /**\n * Add an edge to the diagram\n */\n addEdge(edge: Edge): void {\n edge.setDirtyListener(() => this.markDirty());\n this._edges.set(edge.id, edge);\n // Update reverse index\n this._updateEdgeIndex(edge.id, edge.from.nodeId, true);\n this._updateEdgeIndex(edge.id, edge.to.nodeId, true);\n this.animationManager.registerEnter(edge.id);\n this.markDirty();\n this.emit('edgeAdd', edge);\n }\n\n /**\n * Update edge reverse index\n */\n private _updateEdgeIndex(edgeId: string, nodeId: string, add: boolean): void {\n let edgeIds = this._nodeEdgeIndex.get(nodeId);\n if (!edgeIds) {\n edgeIds = new Set();\n this._nodeEdgeIndex.set(nodeId, edgeIds);\n }\n if (add) {\n edgeIds.add(edgeId);\n } else {\n edgeIds.delete(edgeId);\n if (edgeIds.size === 0) {\n this._nodeEdgeIndex.delete(nodeId);\n }\n }\n }\n\n /**\n * Remove an edge from the diagram\n */\n removeEdge(edgeId: string): boolean {\n const edge = this._edges.get(edgeId);\n if (edge === undefined) {\n return false;\n }\n\n if (this.animationManager.enabled && !this.animationManager.isExiting(edgeId)) {\n this.animationManager.registerExit(edgeId, () => {\n this.removeEdgeImmediate(edgeId);\n });\n this.markDirty();\n return true;\n }\n\n return this.removeEdgeImmediate(edgeId);\n }\n\n private removeNodeImmediate(nodeId: string): boolean {\n const node = this._nodes.get(nodeId);\n if (node === undefined) {\n return false;\n }\n\n // Use reverse index to find connected edges (O(1) instead of O(n))\n const edgesToRemove = this._nodeEdgeIndex.get(nodeId);\n if (edgesToRemove) {\n // Copy to array since removeEdgeImmediate will modify the index\n for (const edgeId of Array.from(edgesToRemove)) {\n this.removeEdgeImmediate(edgeId);\n }\n }\n\n for (const group of this._groups.values()) {\n group.removeChild(nodeId);\n }\n\n this._nodes.delete(nodeId);\n this._nodeObstaclesCache = null;\n node.setDirtyListener(undefined);\n node.setAttachToOutlineGetter(undefined);\n this.markDirty();\n this.emit('nodeRemove', node);\n return true;\n }\n\n private removeEdgeImmediate(edgeId: string): boolean {\n const edge = this._edges.get(edgeId);\n if (edge === undefined) {\n return false;\n }\n\n // Clean up reverse index\n this._updateEdgeIndex(edgeId, edge.from.nodeId, false);\n this._updateEdgeIndex(edgeId, edge.to.nodeId, false);\n\n this._edges.delete(edgeId);\n edge.setDirtyListener(undefined);\n this.markDirty();\n this.emit('edgeRemove', edge);\n return true;\n }\n\n /**\n * Get an edge by ID\n */\n getEdge(edgeId: string): Edge | undefined {\n return this._edges.get(edgeId);\n }\n\n /**\n * Add a group to the diagram\n */\n addGroup(group: Group): void {\n group.setDirtyListener(() => this.markDirty());\n this._groups.set(group.id, group);\n this.markDirty();\n }\n\n /**\n * Remove a group from the diagram\n */\n removeGroup(groupId: string): boolean {\n const group = this._groups.get(groupId);\n if (group === undefined) {\n return false;\n }\n this._groups.delete(groupId);\n group.setDirtyListener(undefined);\n this.markDirty();\n return true;\n }\n\n /**\n * Get a group by ID\n */\n getGroup(groupId: string): Group | undefined {\n return this._groups.get(groupId);\n }\n\n /**\n * Find element at a point (nodes, then edges, then groups)\n */\n getElementAtPoint(worldPoint: Point): Node | Edge | Group | undefined {\n // Check nodes first (front to back)\n const nodesArray = Array.from(this._nodes.values());\n for (let i = nodesArray.length - 1; i >= 0; i--) {\n const node = nodesArray[i]!;\n if (node.visible && node.hitTest(worldPoint)) {\n return node;\n }\n }\n\n // Check edges\n for (const edge of this._edges.values()) {\n if (!edge.visible) {\n continue;\n }\n\n const baseTolerance = Math.max((edge.style.strokeWidth ?? 2) * 2, 8);\n const tolerance = baseTolerance / Math.max(this._zoom, 0.0001);\n if (edge.hitTestWithTolerance(worldPoint, tolerance)) {\n return edge;\n }\n }\n\n // Check groups (back layer)\n for (const group of this._groups.values()) {\n if (group.visible && group.hitTest(worldPoint)) {\n return group;\n }\n }\n\n return undefined;\n }\n\n /**\n * Mark the diagram as needing re-render\n */\n markDirty(): void {\n this._dirty = true;\n }\n\n /**\n * Force an immediate render\n */\n render(): void {\n this.renderFrame(performance.now());\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this._destroyed = true;\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.disableInteractions();\n this.disableContextMenu();\n for (const plugin of this.plugins) {\n plugin.destroy?.(this);\n }\n this.plugins = [];\n this.removeAllListeners();\n for (const node of this._nodes.values()) {\n node.setDirtyListener(undefined);\n }\n for (const edge of this._edges.values()) {\n edge.setDirtyListener(undefined);\n }\n for (const group of this._groups.values()) {\n group.setDirtyListener(undefined);\n }\n this._nodes.clear();\n this._edges.clear();\n this._groups.clear();\n this._nodeEdgeIndex.clear();\n }\n\n /**\n * Clear all elements from the diagram\n */\n clear(): void {\n for (const node of this._nodes.values()) {\n node.setDirtyListener(undefined);\n }\n for (const edge of this._edges.values()) {\n edge.setDirtyListener(undefined);\n }\n for (const group of this._groups.values()) {\n group.setDirtyListener(undefined);\n }\n this._nodes.clear();\n this._edges.clear();\n this._groups.clear();\n this._nodeEdgeIndex.clear();\n this.markDirty();\n }\n\n private setupCanvas(): void {\n const { width, height } = this.options;\n this.devicePixelRatio = this.options.retina ? window.devicePixelRatio || 1 : 1;\n\n // Set display size\n this.canvas.style.width = `${width}px`;\n this.canvas.style.height = `${height}px`;\n\n // Set actual size for retina displays\n this.canvas.width = width * this.devicePixelRatio;\n this.canvas.height = height * this.devicePixelRatio;\n\n // Scale context for retina\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n this.ctx.scale(this.devicePixelRatio, this.devicePixelRatio);\n\n this.updateCanvasRect();\n }\n\n private updateCanvasRect(): void {\n this._canvasRect = this.canvas.getBoundingClientRect();\n }\n\n private resolveCanvas(canvas: HTMLCanvasElement | string): HTMLCanvasElement {\n if (typeof canvas !== 'string') {\n return canvas;\n }\n\n const element = document.querySelector(canvas);\n if (element instanceof HTMLCanvasElement) {\n return element;\n }\n\n throw new Error(`Canvas element not found for selector: ${canvas}`);\n }\n\n private startRenderLoop(): void {\n const loop = (): void => {\n if (this._destroyed) {\n return;\n }\n\n const now = performance.now();\n const animationChanged = this.animationManager.update(now);\n if (animationChanged || this.animationManager.hasActive()) {\n this._dirty = true;\n }\n if (this.scrollbar.enabled && this.scrollbar.autoHide) {\n const alpha = this.getScrollbarAlpha(now);\n if (Math.abs(alpha - this.lastScrollbarAlpha) > 0.001) {\n this._dirty = true;\n this.lastScrollbarAlpha = alpha;\n }\n }\n\n // Invalidate cached canvas rect every frame so that screenToWorld /\n // worldToScreen pick up layout changes (e.g. surrounding panels resized\n // or repositioned the canvas without changing its own dimensions).\n this._canvasRect = null;\n\n if (this._dirty) {\n this.renderFrame(now);\n this._dirty = false;\n }\n\n this.animationFrameId = requestAnimationFrame(loop);\n };\n\n this.animationFrameId = requestAnimationFrame(loop);\n }\n\n private renderFrame(now: number): void {\n this.frameTime = now;\n this._nodeObstaclesCache = null;\n const ctx = this.ctx;\n const { width, height, backgroundColor } = this.options;\n\n // Reset transform for clearing\n ctx.setTransform(this.devicePixelRatio, 0, 0, this.devicePixelRatio, 0, 0);\n\n // Clear canvas\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n\n // Apply viewport transform\n ctx.translate(this._offsetX, this._offsetY);\n ctx.scale(this._zoom, this._zoom);\n\n for (const underlayRenderer of this.underlayRenderers) {\n underlayRenderer(ctx);\n }\n\n // Apply styles from StyleManager before rendering (only if dirty)\n if (this.styleManager && this._styleDirty) {\n applyStyleManagerToElements(\n this.styleManager,\n this._groups.values(),\n this._edges.values(),\n this._nodes.values()\n );\n this._styleDirty = false;\n }\n\n // Update group bounds before rendering\n for (const group of this._groups.values()) {\n group.recalculateBounds();\n }\n\n // Render groups (back layer)\n for (const group of this._groups.values()) {\n if (group.visible) {\n this.renderElementWithAnimation(ctx, group, () => group.render(ctx));\n group.clearDirty();\n }\n }\n\n // Sync edge endpoints with node positions\n this.updateEdgeEndpoints();\n\n // Render nodes (middle layer)\n for (const node of this._nodes.values()) {\n if (node.visible) {\n this.renderElementWithAnimation(ctx, node, () => node.render(ctx));\n node.clearDirty();\n }\n }\n\n // Render edges above nodes so lines/markers stay visible over figures.\n for (const edge of this._edges.values()) {\n if (edge.visible) {\n this.renderElementWithAnimation(ctx, edge, () => edge.render(ctx));\n edge.clearDirty();\n }\n }\n\n // Render edge handles (topmost layer)\n for (const edge of this._edges.values()) {\n if (edge.visible) {\n edge.renderHandles(ctx);\n }\n }\n\n for (const overlayRenderer of this.overlayRenderers) {\n overlayRenderer(ctx);\n }\n\n this.renderScrollbars(ctx);\n this.emit('render');\n }\n\n private renderElementWithAnimation(\n ctx: CanvasRenderingContext2D,\n element: { id: string; getBounds: () => Bounds },\n renderFn: () => void\n ): void {\n if (!this.animationManager.enabled) {\n renderFn();\n return;\n }\n\n const state = this.animationManager.getState(element.id, this.frameTime);\n if (state.opacity <= 0) {\n return;\n }\n\n if (state.opacity !== 1 || state.scale !== 1) {\n const bounds = element.getBounds();\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n\n ctx.save();\n ctx.globalAlpha *= state.opacity;\n if (state.scale !== 1) {\n ctx.translate(cx, cy);\n ctx.scale(state.scale, state.scale);\n ctx.translate(-cx, -cy);\n }\n renderFn();\n ctx.restore();\n return;\n }\n\n renderFn();\n }\n\n /**\n * Update edge endpoints to reflect current node positions\n * Called during drag to keep control points in sync\n */\n updateEdgeEndpointsForDrag(): void {\n for (const edge of this._edges.values()) {\n if (!edge.autoUpdateEndpoints) {\n continue;\n }\n\n const fromNode = this._nodes.get(edge.from.nodeId);\n const toNode = this._nodes.get(edge.to.nodeId);\n if (fromNode === undefined || toNode === undefined) {\n continue;\n }\n\n let fromPoint: Point;\n let toPoint: Point;\n let fromDir: string | undefined;\n let toDir: string | undefined;\n\n if (edge.from.portId) {\n const anchorId = edge.from.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = fromNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n fromPoint = anchorPoint;\n fromDir = anchorId.split(':')[0];\n } else {\n fromPoint = fromNode.getCenter();\n }\n } else if (edge.from.outlineParam !== undefined) {\n fromPoint = fromNode.getConnectionPointAtOutlineParam(edge.from.outlineParam);\n fromDir = this.getDirectionFromOutlineParam(edge.from.outlineParam);\n } else {\n fromPoint = fromNode.getCenter();\n }\n\n if (edge.to.portId) {\n const anchorId = edge.to.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = toNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n toPoint = anchorPoint;\n toDir = anchorId.split(':')[0];\n } else {\n toPoint = toNode.getCenter();\n }\n } else if (edge.to.outlineParam !== undefined) {\n toPoint = toNode.getConnectionPointAtOutlineParam(edge.to.outlineParam);\n toDir = this.getDirectionFromOutlineParam(edge.to.outlineParam);\n } else {\n toPoint = toNode.getCenter();\n }\n\n edge.updateEndpoints(fromPoint, toPoint, fromDir, toDir);\n }\n }\n\n private updateEdgeEndpoints(): void {\n const obstacles = this.getNodeObstacles();\n\n for (const edge of this._edges.values()) {\n if (!edge.autoUpdateEndpoints) {\n continue;\n }\n\n const fromNode = this._nodes.get(edge.from.nodeId);\n const toNode = this._nodes.get(edge.to.nodeId);\n if (fromNode === undefined || toNode === undefined) {\n continue;\n }\n\n if (edge.lockAnchors && edge.from.outlineParam === undefined) {\n if (!edge.from.portId) {\n const anchor = fromNode.getNearestAnchor(toNode.getCenter());\n if (anchor) {\n edge.from = { ...edge.from, portId: `${ANCHOR_PORT_PREFIX}${anchor.id}` };\n }\n }\n }\n if (edge.lockAnchors && edge.to.outlineParam === undefined) {\n if (!edge.to.portId) {\n const anchor = toNode.getNearestAnchor(fromNode.getCenter());\n if (anchor) {\n edge.to = { ...edge.to, portId: `${ANCHOR_PORT_PREFIX}${anchor.id}` };\n }\n }\n }\n\n let fromPoint: Point;\n let toPoint: Point;\n let fromDir: string | undefined;\n let toDir: string | undefined;\n\n if (edge.from.portId) {\n const anchorId = edge.from.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = fromNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n fromPoint = anchorPoint;\n fromDir = anchorId.split(':')[0];\n } else {\n fromPoint = fromNode.getCenter();\n }\n } else if (edge.from.outlineParam !== undefined) {\n fromPoint = fromNode.getConnectionPointAtOutlineParam(edge.from.outlineParam);\n fromDir = this.getDirectionFromOutlineParam(edge.from.outlineParam);\n } else {\n fromPoint = fromNode.getCenter();\n }\n\n if (edge.to.portId) {\n const anchorId = edge.to.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = toNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n toPoint = anchorPoint;\n toDir = anchorId.split(':')[0];\n } else {\n toPoint = toNode.getCenter();\n }\n } else if (edge.to.outlineParam !== undefined) {\n toPoint = toNode.getConnectionPointAtOutlineParam(edge.to.outlineParam);\n toDir = this.getDirectionFromOutlineParam(edge.to.outlineParam);\n } else {\n toPoint = toNode.getCenter();\n }\n\n edge.updateEndpoints(fromPoint, toPoint, fromDir, toDir, { obstacles });\n }\n }\n\n private getNodeObstacles(): PathObstacle[] {\n if (this._nodeObstaclesCache !== null) {\n return this._nodeObstaclesCache;\n }\n\n this._nodeObstaclesCache = Array.from(this._nodes.values()).map((node) => ({\n x: node.x - 8,\n y: node.y - 8,\n width: node.width + 16,\n height: node.height + 16,\n role: 'other' as const,\n }));\n\n return this._nodeObstaclesCache;\n }\n\n private getDirectionFromOutlineParam(param: number): string {\n const p = ((param % 1) + 1) % 1;\n if (p < 0.25) return 'top';\n if (p < 0.5) return 'right';\n if (p < 0.75) return 'bottom';\n return 'left';\n }\n\n private renderScrollbars(ctx: CanvasRenderingContext2D): void {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return;\n }\n\n const alpha = this.getScrollbarAlpha(this.frameTime);\n this.lastScrollbarAlpha = alpha;\n if (alpha <= 0.001) {\n return;\n }\n\n const colors = this.resolveScrollbarColors();\n const drawRoundedRect = (x: number, y: number, w: number, h: number, r: number): void => {\n drawRoundedRectPath(ctx, x, y, w, h, r);\n };\n\n ctx.save();\n ctx.setTransform(this.devicePixelRatio, 0, 0, this.devicePixelRatio, 0, 0);\n ctx.globalAlpha = alpha;\n\n if (metrics.horizontal) {\n const isHovered = this.scrollbarHoveredAxis === 'horizontal';\n const isActive = this.scrollbarActiveAxis === 'horizontal';\n const thickness =\n isHovered || isActive ? this.scrollbar.hoverThickness : this.scrollbar.thickness;\n const trackY = metrics.horizontal.trackY + (metrics.horizontal.thickness - thickness) / 2;\n const radius = thickness / 2;\n const thumbColor = isActive\n ? colors.thumbActive\n : isHovered\n ? colors.thumbHover\n : colors.thumb;\n\n ctx.fillStyle = colors.track;\n drawRoundedRect(\n metrics.horizontal.trackX,\n trackY,\n metrics.horizontal.trackLength,\n thickness,\n radius\n );\n ctx.fill();\n\n ctx.fillStyle = thumbColor;\n drawRoundedRect(\n metrics.horizontal.trackX + metrics.horizontal.thumbOffset,\n trackY,\n metrics.horizontal.thumbLength,\n thickness,\n radius\n );\n ctx.fill();\n }\n\n if (metrics.vertical) {\n const isHovered = this.scrollbarHoveredAxis === 'vertical';\n const isActive = this.scrollbarActiveAxis === 'vertical';\n const thickness =\n isHovered || isActive ? this.scrollbar.hoverThickness : this.scrollbar.thickness;\n const trackX = metrics.vertical.trackX + (metrics.vertical.thickness - thickness) / 2;\n const radius = thickness / 2;\n const thumbColor = isActive\n ? colors.thumbActive\n : isHovered\n ? colors.thumbHover\n : colors.thumb;\n\n ctx.fillStyle = colors.track;\n drawRoundedRect(\n trackX,\n metrics.vertical.trackY,\n thickness,\n metrics.vertical.trackLength,\n radius\n );\n ctx.fill();\n\n ctx.fillStyle = thumbColor;\n drawRoundedRect(\n trackX,\n metrics.vertical.trackY + metrics.vertical.thumbOffset,\n thickness,\n metrics.vertical.thumbLength,\n radius\n );\n ctx.fill();\n }\n\n ctx.restore();\n }\n\n private getContentBounds(): Bounds | null {\n return getContentBounds({\n nodes: this._nodes.values(),\n edges: this._edges.values(),\n groups: this._groups.values(),\n });\n }\n\n private getViewportBounds(): Bounds {\n return {\n x: -this._offsetX / this._zoom,\n y: -this._offsetY / this._zoom,\n width: this.options.width / this._zoom,\n height: this.options.height / this._zoom,\n };\n }\n\n notifyScrollbarInteraction(): void {\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n }\n\n setScrollbarActiveAxis(axis: ScrollbarAxis | null): void {\n if (this.scrollbarActiveAxis === axis) {\n return;\n }\n this.scrollbarActiveAxis = axis;\n if (axis !== null) {\n this.notifyScrollbarInteraction();\n } else {\n this.markDirty();\n }\n }\n\n updateScrollbarHover(screenX: number, screenY: number): boolean {\n const axis = this.hitTestScrollbarArea(screenX, screenY);\n if (this.scrollbarHoveredAxis !== axis) {\n this.scrollbarHoveredAxis = axis;\n this.markDirty();\n if (axis !== null) {\n this.notifyScrollbarInteraction();\n }\n }\n return axis !== null;\n }\n\n clearScrollbarHover(): void {\n if (this.scrollbarHoveredAxis !== null) {\n this.scrollbarHoveredAxis = null;\n this.markDirty();\n }\n }\n\n hitTestScrollbarThumb(\n screenX: number,\n screenY: number\n ): { axis: ScrollbarAxis; pointerOffset: number } | null {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return null;\n }\n\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return null;\n }\n\n const { x, y } = localPoint;\n const hitPadding = this.scrollbar.hitAreaPadding;\n\n if (metrics.horizontal) {\n const thumbStartX = metrics.horizontal.trackX + metrics.horizontal.thumbOffset;\n if (\n x >= thumbStartX - hitPadding &&\n x <= thumbStartX + metrics.horizontal.thumbLength + hitPadding &&\n y >= metrics.horizontal.trackY - hitPadding &&\n y <= metrics.horizontal.trackY + metrics.horizontal.thickness + hitPadding\n ) {\n return {\n axis: 'horizontal',\n pointerOffset: x - thumbStartX,\n };\n }\n }\n\n if (metrics.vertical) {\n const thumbStartY = metrics.vertical.trackY + metrics.vertical.thumbOffset;\n if (\n x >= metrics.vertical.trackX - hitPadding &&\n x <= metrics.vertical.trackX + metrics.vertical.thickness + hitPadding &&\n y >= thumbStartY - hitPadding &&\n y <= thumbStartY + metrics.vertical.thumbLength + hitPadding\n ) {\n return {\n axis: 'vertical',\n pointerOffset: y - thumbStartY,\n };\n }\n }\n\n return null;\n }\n\n dragScrollbarThumb(\n axis: ScrollbarAxis,\n screenX: number,\n screenY: number,\n pointerOffset: number\n ): boolean {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return false;\n }\n\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return false;\n }\n\n if (axis === 'horizontal' && metrics.horizontal) {\n const travel = Math.max(0, metrics.horizontal.trackLength - metrics.horizontal.thumbLength);\n const desiredThumbOffset = localPoint.x - metrics.horizontal.trackX - pointerOffset;\n const clampedThumbOffset = Math.min(Math.max(desiredThumbOffset, 0), travel);\n const scrollX =\n travel > 0 && metrics.horizontal.maxScroll > 0\n ? (clampedThumbOffset / travel) * metrics.horizontal.maxScroll\n : 0;\n const viewportX = metrics.contentBounds.x + scrollX;\n this.offsetX = -viewportX * this._zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n if (axis === 'vertical' && metrics.vertical) {\n const travel = Math.max(0, metrics.vertical.trackLength - metrics.vertical.thumbLength);\n const desiredThumbOffset = localPoint.y - metrics.vertical.trackY - pointerOffset;\n const clampedThumbOffset = Math.min(Math.max(desiredThumbOffset, 0), travel);\n const scrollY =\n travel > 0 && metrics.vertical.maxScroll > 0\n ? (clampedThumbOffset / travel) * metrics.vertical.maxScroll\n : 0;\n const viewportY = metrics.contentBounds.y + scrollY;\n this.offsetY = -viewportY * this._zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n return false;\n }\n\n clickScrollbarTrack(screenX: number, screenY: number): boolean {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return false;\n }\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return false;\n }\n\n if (metrics.horizontal) {\n const { trackX, trackY, trackLength, thumbOffset, thumbLength, maxScroll } =\n metrics.horizontal;\n const inTrack =\n localPoint.x >= trackX &&\n localPoint.x <= trackX + trackLength &&\n localPoint.y >= trackY &&\n localPoint.y <= trackY + metrics.horizontal.thickness;\n if (inTrack) {\n const thumbStart = trackX + thumbOffset;\n const thumbEnd = thumbStart + thumbLength;\n if (localPoint.x < thumbStart || localPoint.x > thumbEnd) {\n const direction = localPoint.x < thumbStart ? -1 : 1;\n const step = metrics.viewportBounds.width * this.scrollbar.pageScrollRatio * direction;\n const currentScrollX = Math.min(\n Math.max(metrics.viewportBounds.x - metrics.contentBounds.x, 0),\n maxScroll\n );\n const nextScrollX = Math.min(Math.max(currentScrollX + step, 0), maxScroll);\n const viewportX = metrics.contentBounds.x + nextScrollX;\n this.offsetX = -viewportX * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n }\n }\n\n if (metrics.vertical) {\n const { trackX, trackY, trackLength, thumbOffset, thumbLength, maxScroll } = metrics.vertical;\n const inTrack =\n localPoint.x >= trackX &&\n localPoint.x <= trackX + metrics.vertical.thickness &&\n localPoint.y >= trackY &&\n localPoint.y <= trackY + trackLength;\n if (inTrack) {\n const thumbStart = trackY + thumbOffset;\n const thumbEnd = thumbStart + thumbLength;\n if (localPoint.y < thumbStart || localPoint.y > thumbEnd) {\n const direction = localPoint.y < thumbStart ? -1 : 1;\n const step = metrics.viewportBounds.height * this.scrollbar.pageScrollRatio * direction;\n const currentScrollY = Math.min(\n Math.max(metrics.viewportBounds.y - metrics.contentBounds.y, 0),\n maxScroll\n );\n const nextScrollY = Math.min(Math.max(currentScrollY + step, 0), maxScroll);\n const viewportY = metrics.contentBounds.y + nextScrollY;\n this.offsetY = -viewportY * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n }\n }\n\n return false;\n }\n\n scrollViewportBy(screenDx: number, screenDy: number): boolean {\n const scrollState = this.getScrollState();\n if (!scrollState) {\n return false;\n }\n const worldDx = screenDx / this.zoom;\n const worldDy = screenDy / this.zoom;\n const currentViewportX = scrollState.viewportBounds.x;\n const currentViewportY = scrollState.viewportBounds.y;\n const maxScrollX = Math.max(\n 0,\n scrollState.contentBounds.width - scrollState.viewportBounds.width\n );\n const maxScrollY = Math.max(\n 0,\n scrollState.contentBounds.height - scrollState.viewportBounds.height\n );\n const nextViewportX = Math.min(\n Math.max(currentViewportX + worldDx, scrollState.contentBounds.x),\n scrollState.contentBounds.x + maxScrollX\n );\n const nextViewportY = Math.min(\n Math.max(currentViewportY + worldDy, scrollState.contentBounds.y),\n scrollState.contentBounds.y + maxScrollY\n );\n\n this.offsetX = -nextViewportX * this.zoom;\n this.offsetY = -nextViewportY * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n scrollViewportToStart(): boolean {\n const scrollState = this.getScrollState();\n if (!scrollState) {\n return false;\n }\n this.offsetX = -scrollState.contentBounds.x * this.zoom;\n this.offsetY = -scrollState.contentBounds.y * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n scrollViewportToEnd(): boolean {\n const scrollState = this.getScrollState();\n if (!scrollState) {\n return false;\n }\n const maxScrollX = Math.max(\n 0,\n scrollState.contentBounds.width - scrollState.viewportBounds.width\n );\n const maxScrollY = Math.max(\n 0,\n scrollState.contentBounds.height - scrollState.viewportBounds.height\n );\n const targetViewportX = scrollState.contentBounds.x + maxScrollX;\n const targetViewportY = scrollState.contentBounds.y + maxScrollY;\n this.offsetX = -targetViewportX * this.zoom;\n this.offsetY = -targetViewportY * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n beginOverlayDrag(screenX: number, screenY: number): OverlayDragSession | null {\n for (const plugin of this.plugins) {\n const interactivePlugin = plugin as OverlayDragPlugin;\n if (!interactivePlugin.beginOverlayDrag) {\n continue;\n }\n const payload = interactivePlugin.beginOverlayDrag(this, screenX, screenY);\n if (payload !== null && payload !== undefined) {\n return { plugin: interactivePlugin, payload };\n }\n }\n return null;\n }\n\n updateOverlayDrag(session: OverlayDragSession, screenX: number, screenY: number): boolean {\n return session.plugin.updateOverlayDrag?.(this, screenX, screenY, session.payload) ?? false;\n }\n\n endOverlayDrag(session: OverlayDragSession): void {\n session.plugin.endOverlayDrag?.(this, session.payload);\n }\n\n screenToCanvas(screenX: number, screenY: number): Point | null {\n const rect = this._canvasRect ?? this.canvas.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) {\n return null;\n }\n\n const scaleX = rect.width / this.options.width;\n const scaleY = rect.height / this.options.height;\n return {\n x: (screenX - rect.left) / scaleX,\n y: (screenY - rect.top) / scaleY,\n };\n }\n\n private getScrollbarMetrics(): ScrollbarMetrics | null {\n if (!this.scrollbar.enabled) {\n return null;\n }\n\n const rawContentBounds = this.getContentBounds();\n if (!rawContentBounds) {\n return null;\n }\n\n const viewportBounds = this.getViewportBounds();\n const unionMinX = Math.min(rawContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(rawContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(\n rawContentBounds.x + rawContentBounds.width,\n viewportBounds.x + viewportBounds.width\n );\n const unionMaxY = Math.max(\n rawContentBounds.y + rawContentBounds.height,\n viewportBounds.y + viewportBounds.height\n );\n const contentBounds = {\n x: unionMinX,\n y: unionMinY,\n width: unionMaxX - unionMinX,\n height: unionMaxY - unionMinY,\n };\n\n const contentWidth = Math.max(contentBounds.width, 1);\n const contentHeight = Math.max(contentBounds.height, 1);\n const showHorizontal = contentWidth > viewportBounds.width + 0.01;\n const showVertical = contentHeight > viewportBounds.height + 0.01;\n if (!showHorizontal && !showVertical) {\n return null;\n }\n\n const { width, height } = this.options;\n const padding = 6;\n const thickness = this.scrollbar.thickness;\n const spacing = 4;\n const minThumbLength = this.scrollbar.minThumbLength;\n\n const availableWidth = width - padding * 2;\n const availableHeight = height - padding * 2;\n if (availableWidth <= 0 || availableHeight <= 0) {\n return null;\n }\n\n const horizontalTrackLength = Math.max(\n 0,\n availableWidth - (showVertical ? thickness + spacing : 0)\n );\n const verticalTrackLength = Math.max(\n 0,\n availableHeight - (showHorizontal ? thickness + spacing : 0)\n );\n\n const horizontalTrackX = padding;\n const horizontalTrackY = height - padding - thickness;\n const verticalTrackX = width - padding - thickness;\n const verticalTrackY = padding;\n\n let horizontal: ScrollbarTrackMetrics | null = null;\n if (showHorizontal && horizontalTrackLength > 0) {\n const maxScrollX = Math.max(0, contentWidth - viewportBounds.width);\n const scrollX = Math.min(Math.max(viewportBounds.x - contentBounds.x, 0), maxScrollX);\n const ratioX = viewportBounds.width / contentWidth;\n const thumbLength = Math.min(\n horizontalTrackLength,\n Math.max(minThumbLength, horizontalTrackLength * ratioX)\n );\n const travel = Math.max(0, horizontalTrackLength - thumbLength);\n const thumbOffset = maxScrollX > 0 ? (scrollX / maxScrollX) * travel : 0;\n horizontal = {\n trackX: horizontalTrackX,\n trackY: horizontalTrackY,\n trackLength: horizontalTrackLength,\n thickness,\n thumbLength,\n thumbOffset,\n maxScroll: maxScrollX,\n };\n }\n\n let vertical: ScrollbarTrackMetrics | null = null;\n if (showVertical && verticalTrackLength > 0) {\n const maxScrollY = Math.max(0, contentHeight - viewportBounds.height);\n const scrollY = Math.min(Math.max(viewportBounds.y - contentBounds.y, 0), maxScrollY);\n const ratioY = viewportBounds.height / contentHeight;\n const thumbLength = Math.min(\n verticalTrackLength,\n Math.max(minThumbLength, verticalTrackLength * ratioY)\n );\n const travel = Math.max(0, verticalTrackLength - thumbLength);\n const thumbOffset = maxScrollY > 0 ? (scrollY / maxScrollY) * travel : 0;\n vertical = {\n trackX: verticalTrackX,\n trackY: verticalTrackY,\n trackLength: verticalTrackLength,\n thickness,\n thumbLength,\n thumbOffset,\n maxScroll: maxScrollY,\n };\n }\n\n if (!horizontal && !vertical) {\n return null;\n }\n\n return {\n contentBounds,\n viewportBounds,\n thickness: this.scrollbar.thickness,\n horizontal,\n vertical,\n };\n }\n\n private resolveScrollbarOptions(options: DiagramOptions): ScrollbarOptions {\n const fallbackEnabled = options.scrollbarOverlay ?? DEFAULT_SCROLLBAR_OPTIONS.enabled;\n const resolved: ScrollbarOptions = {\n ...DEFAULT_SCROLLBAR_OPTIONS,\n enabled: fallbackEnabled,\n };\n if (typeof options.scrollbar === 'boolean') {\n resolved.enabled = options.scrollbar;\n return resolved;\n }\n if (options.scrollbar) {\n return { ...resolved, ...options.scrollbar };\n }\n return resolved;\n }\n\n private resolveScrollbarColors(): {\n track: string;\n thumb: string;\n thumbHover: string;\n thumbActive: string;\n } {\n const isDarkTheme = this.styleManager?.theme.name === 'dark';\n const fallback = isDarkTheme\n ? {\n track: 'rgba(148, 163, 184, 0.22)',\n thumb: 'rgba(226, 232, 240, 0.68)',\n thumbHover: 'rgba(226, 232, 240, 0.86)',\n thumbActive: 'rgba(248, 250, 252, 0.96)',\n }\n : {\n track: 'rgba(15, 23, 42, 0.16)',\n thumb: 'rgba(51, 65, 85, 0.7)',\n thumbHover: 'rgba(30, 41, 59, 0.82)',\n thumbActive: 'rgba(15, 23, 42, 0.9)',\n };\n\n return {\n track: this.scrollbar.trackColor || fallback.track,\n thumb: this.scrollbar.thumbColor || fallback.thumb,\n thumbHover: this.scrollbar.thumbHoverColor || fallback.thumbHover,\n thumbActive: this.scrollbar.thumbActiveColor || fallback.thumbActive,\n };\n }\n\n private getScrollbarAlpha(now: number): number {\n if (!this.scrollbar.autoHide) {\n return 1;\n }\n if (this.scrollbarActiveAxis !== null || this.scrollbarHoveredAxis !== null) {\n return 1;\n }\n const elapsed = now - this.scrollbarLastInteractionAt;\n if (elapsed <= this.scrollbar.autoHideDelay) {\n return 1;\n }\n if (this.scrollbar.fadeDuration <= 0) {\n return 0;\n }\n const fadeProgress = (elapsed - this.scrollbar.autoHideDelay) / this.scrollbar.fadeDuration;\n return Math.max(0, 1 - fadeProgress);\n }\n\n private hitTestScrollbarArea(screenX: number, screenY: number): ScrollbarAxis | null {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return null;\n }\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return null;\n }\n const hitPadding = this.scrollbar.hitAreaPadding;\n\n if (metrics.horizontal) {\n const inHorizontalTrack =\n localPoint.x >= metrics.horizontal.trackX - hitPadding &&\n localPoint.x <= metrics.horizontal.trackX + metrics.horizontal.trackLength + hitPadding &&\n localPoint.y >= metrics.horizontal.trackY - hitPadding &&\n localPoint.y <= metrics.horizontal.trackY + metrics.horizontal.thickness + hitPadding;\n if (inHorizontalTrack) {\n return 'horizontal';\n }\n }\n\n if (metrics.vertical) {\n const inVerticalTrack =\n localPoint.x >= metrics.vertical.trackX - hitPadding &&\n localPoint.x <= metrics.vertical.trackX + metrics.vertical.thickness + hitPadding &&\n localPoint.y >= metrics.vertical.trackY - hitPadding &&\n localPoint.y <= metrics.vertical.trackY + metrics.vertical.trackLength + hitPadding;\n if (inVerticalTrack) {\n return 'vertical';\n }\n }\n return null;\n }\n\n private getScrollState(): { contentBounds: Bounds; viewportBounds: Bounds } | null {\n const rawContentBounds = this.getContentBounds();\n if (!rawContentBounds) {\n return null;\n }\n const viewportBounds = this.getViewportBounds();\n const unionMinX = Math.min(rawContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(rawContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(\n rawContentBounds.x + rawContentBounds.width,\n viewportBounds.x + viewportBounds.width\n );\n const unionMaxY = Math.max(\n rawContentBounds.y + rawContentBounds.height,\n viewportBounds.y + viewportBounds.height\n );\n return {\n contentBounds: {\n x: unionMinX,\n y: unionMinY,\n width: unionMaxX - unionMinX,\n height: unionMaxY - unionMinY,\n },\n viewportBounds,\n };\n }\n}\n","import type { DiagramRenderer } from './DiagramRenderer';\nimport type { EdgePathType } from '@/types';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport { AnimationManager } from './AnimationManager';\n\nexport interface SearchManagerOptions {\n highlightColor?: string;\n currentColor?: string;\n highlightLineWidth?: number;\n currentLineWidth?: number;\n highlightPadding?: number;\n}\n\nexport interface SearchFindOptions {\n highlight?: boolean;\n caseSensitive?: boolean;\n highlightColor?: string;\n}\n\nexport interface SearchFilterOptions {\n nodeType?: string;\n edgeType?: EdgePathType;\n styleClass?: string;\n scope?: 'nodes' | 'edges' | 'all';\n predicate?: (element: Node | Edge) => boolean;\n}\n\nexport interface SearchMatch {\n id: string;\n type: 'node' | 'edge';\n label: string;\n}\n\nexport interface SearchResult {\n matches: SearchMatch[];\n nodes: Node[];\n edges: Edge[];\n}\n\nconst DEFAULT_OPTIONS: Required<SearchManagerOptions> = {\n highlightColor: '#f59e0b',\n currentColor: '#ef4444',\n highlightLineWidth: 2,\n currentLineWidth: 3,\n highlightPadding: 6,\n};\n\nexport class SearchManager {\n private renderer: DiagramRenderer;\n private options: Required<SearchManagerOptions>;\n private highlightIds = new Set<string>();\n private currentId: string | null = null;\n private overlayCleanup: (() => void) | null = null;\n private lastMatches: SearchMatch[] = [];\n private currentIndex = -1;\n private visibilityCache = new Map<string, boolean>();\n private filterActive = false;\n private animationManager?: AnimationManager;\n\n constructor(renderer: DiagramRenderer, options: SearchManagerOptions = {}) {\n this.renderer = renderer;\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.animationManager = renderer.getAnimationManager?.();\n this.overlayCleanup = this.renderer.addOverlayRenderer((ctx) => this.renderHighlights(ctx));\n }\n\n destroy(): void {\n this.overlayCleanup?.();\n this.overlayCleanup = null;\n this.highlightIds.clear();\n this.currentId = null;\n this.visibilityCache.clear();\n this.filterActive = false;\n }\n\n find(query: string, options: SearchFindOptions = {}): SearchResult {\n const caseSensitive = options.caseSensitive ?? false;\n const normalizedQuery = caseSensitive ? query : query.toLowerCase();\n\n const matches: SearchMatch[] = [];\n const nodes: Node[] = [];\n const edges: Edge[] = [];\n\n for (const node of this.renderer.nodes.values()) {\n const label = node.label?.text ?? '';\n if (!label) continue;\n const haystack = caseSensitive ? label : label.toLowerCase();\n if (haystack.includes(normalizedQuery)) {\n matches.push({ id: node.id, type: 'node', label });\n nodes.push(node);\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n const label = edge.label?.text ?? '';\n if (!label) continue;\n const haystack = caseSensitive ? label : label.toLowerCase();\n if (haystack.includes(normalizedQuery)) {\n matches.push({ id: edge.id, type: 'edge', label });\n edges.push(edge);\n }\n }\n\n this.lastMatches = matches;\n this.currentIndex = matches.length > 0 ? 0 : -1;\n this.currentId = matches.length > 0 ? matches[0]!.id : null;\n\n if (options.highlight ?? true) {\n this.setHighlights(matches.map((match) => match.id), options.highlightColor);\n }\n\n return { matches, nodes, edges };\n }\n\n next(): SearchMatch | null {\n if (this.lastMatches.length === 0) {\n return null;\n }\n this.currentIndex = (this.currentIndex + 1) % this.lastMatches.length;\n const match = this.lastMatches[this.currentIndex]!;\n this.currentId = match.id;\n this.animationManager?.registerHighlight(match.id);\n this.renderer.markDirty();\n return match;\n }\n\n previous(): SearchMatch | null {\n if (this.lastMatches.length === 0) {\n return null;\n }\n this.currentIndex =\n (this.currentIndex - 1 + this.lastMatches.length) % this.lastMatches.length;\n const match = this.lastMatches[this.currentIndex]!;\n this.currentId = match.id;\n this.animationManager?.registerHighlight(match.id);\n this.renderer.markDirty();\n return match;\n }\n\n clear(): void {\n this.clearHighlights();\n this.clearFilter();\n this.lastMatches = [];\n this.currentIndex = -1;\n this.currentId = null;\n }\n\n filter(options: SearchFilterOptions): void {\n if (!this.filterActive) {\n this.visibilityCache.clear();\n for (const node of this.renderer.nodes.values()) {\n this.visibilityCache.set(node.id, node.visible);\n }\n for (const edge of this.renderer.edges.values()) {\n this.visibilityCache.set(edge.id, edge.visible);\n }\n this.filterActive = true;\n }\n\n const scope = options.scope ?? 'all';\n\n for (const node of this.renderer.nodes.values()) {\n if (scope === 'edges') {\n continue;\n }\n node.visible = this.matchesNode(node, options);\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (scope === 'nodes') {\n continue;\n }\n const matchesEdge = this.matchesEdge(edge, options);\n const fromVisible = this.renderer.getNode(edge.from.nodeId)?.visible ?? true;\n const toVisible = this.renderer.getNode(edge.to.nodeId)?.visible ?? true;\n edge.visible = matchesEdge && fromVisible && toVisible;\n }\n\n this.renderer.markDirty();\n }\n\n clearFilter(): void {\n if (!this.filterActive) {\n return;\n }\n for (const node of this.renderer.nodes.values()) {\n const cached = this.visibilityCache.get(node.id);\n if (cached !== undefined) {\n node.visible = cached;\n }\n }\n for (const edge of this.renderer.edges.values()) {\n const cached = this.visibilityCache.get(edge.id);\n if (cached !== undefined) {\n edge.visible = cached;\n }\n }\n this.visibilityCache.clear();\n this.filterActive = false;\n this.renderer.markDirty();\n }\n\n private setHighlights(ids: string[], colorOverride?: string): void {\n this.highlightIds = new Set(ids);\n if (colorOverride) {\n this.options = { ...this.options, highlightColor: colorOverride };\n }\n for (const id of this.highlightIds) {\n this.animationManager?.registerHighlight(id);\n }\n this.renderer.markDirty();\n }\n\n private clearHighlights(): void {\n this.highlightIds.clear();\n this.renderer.markDirty();\n }\n\n private matchesNode(node: Node, options: SearchFilterOptions): boolean {\n if (options.nodeType) {\n const typeName = node.typeName;\n const className = node.constructor?.name ?? '';\n if (options.nodeType !== typeName && options.nodeType !== className) {\n return false;\n }\n }\n if (options.styleClass && node.styleClass !== options.styleClass) {\n return false;\n }\n return !(options.predicate && !options.predicate(node));\n\n }\n\n private matchesEdge(edge: Edge, options: SearchFilterOptions): boolean {\n if (options.edgeType && edge.type !== options.edgeType) {\n return false;\n }\n if (options.styleClass && edge.styleClass !== options.styleClass) {\n return false;\n }\n return !(options.predicate && !options.predicate(edge));\n\n }\n\n private renderHighlights(ctx: CanvasRenderingContext2D): void {\n if (this.highlightIds.size === 0) {\n return;\n }\n ctx.save();\n ctx.globalAlpha = 1;\n\n for (const id of this.highlightIds) {\n const node = this.renderer.getNode(id);\n if (node && node.visible) {\n this.renderNodeHighlight(ctx, node, id === this.currentId);\n continue;\n }\n const edge = this.renderer.getEdge(id);\n if (edge && edge.visible) {\n this.renderEdgeHighlight(ctx, edge, id === this.currentId);\n }\n }\n\n ctx.restore();\n }\n\n private renderNodeHighlight(\n ctx: CanvasRenderingContext2D,\n node: Node,\n isCurrent: boolean\n ): void {\n const bounds = node.getBounds();\n const padding = this.options.highlightPadding;\n const color = isCurrent ? this.options.currentColor : this.options.highlightColor;\n const width = isCurrent ? this.options.currentLineWidth : this.options.highlightLineWidth;\n ctx.strokeStyle = color;\n ctx.lineWidth = width;\n ctx.strokeRect(\n bounds.x - padding,\n bounds.y - padding,\n bounds.width + padding * 2,\n bounds.height + padding * 2\n );\n }\n\n private renderEdgeHighlight(\n ctx: CanvasRenderingContext2D,\n edge: Edge,\n isCurrent: boolean\n ): void {\n const path = edge.path;\n if (path.length < 2) {\n return;\n }\n const color = isCurrent ? this.options.currentColor : this.options.highlightColor;\n const width = isCurrent ? this.options.currentLineWidth : this.options.highlightLineWidth;\n ctx.strokeStyle = color;\n ctx.lineWidth = width;\n ctx.setLineDash([]);\n ctx.beginPath();\n ctx.moveTo(path[0]!.x, path[0]!.y);\n if (edge.type === 'bezier' && path.length >= 4) {\n for (let i = 1; i + 2 < path.length; i += 3) {\n const cp1 = path[i]!;\n const cp2 = path[i + 1]!;\n const end = path[i + 2]!;\n ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);\n }\n } else {\n for (let i = 1; i < path.length; i++) {\n ctx.lineTo(path[i]!.x, path[i]!.y);\n }\n }\n ctx.stroke();\n }\n}\n","import type { Point, PortPosition, PortType } from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport type { Node } from './Node';\n\nlet portIdCounter = 1;\n\n/**\n * Generate a unique port ID\n */\nfunction generatePortId(): string {\n return `port_${portIdCounter++}`;\n}\n\n/**\n * Reset port ID counter (for testing)\n */\nexport function resetPortIdCounter(): void {\n portIdCounter = 1;\n}\n\nexport interface PortOptions {\n id?: string;\n type: PortType;\n position: PortPosition | Point;\n radius?: number;\n color?: string;\n hoverColor?: string;\n styleClass?: string;\n}\n\n/**\n * Connection port on a node\n */\nexport class Port {\n readonly id: string;\n readonly type: PortType;\n private _styleClass?: string;\n private _position: PortPosition | Point;\n private _radius: number;\n private _color: string;\n private _hoverColor: string;\n private _hovered = false;\n private _hasCustomRadius: boolean;\n private _hasCustomColor: boolean;\n private _hasCustomHoverColor: boolean;\n\n constructor(options: PortOptions) {\n this.id = options.id ?? generatePortId();\n this.type = options.type;\n this._position = options.position;\n this._radius = options.radius ?? 6;\n this._color = options.color ?? '#666666';\n this._hoverColor = options.hoverColor ?? '#3b82f6';\n this._styleClass = options.styleClass;\n this._hasCustomRadius = options.radius !== undefined;\n this._hasCustomColor = options.color !== undefined;\n this._hasCustomHoverColor = options.hoverColor !== undefined;\n }\n\n /**\n * Port position (relative or absolute)\n */\n get position(): PortPosition | Point {\n return this._position;\n }\n\n set position(value: PortPosition | Point) {\n this._position = value;\n }\n\n /**\n * Style class name for StyleManager\n */\n get styleClass(): string | undefined {\n return this._styleClass;\n }\n\n set styleClass(value: string | undefined) {\n this._styleClass = value;\n }\n\n /**\n * Port radius for rendering and hit testing\n */\n get radius(): number {\n return this._radius;\n }\n\n set radius(value: number) {\n this._radius = value;\n }\n\n /**\n * Port color\n */\n get color(): string {\n return this._hovered ? this._hoverColor : this._color;\n }\n\n set color(value: string) {\n this._color = value;\n }\n\n /**\n * Whether the port is hovered\n */\n get hovered(): boolean {\n return this._hovered;\n }\n\n set hovered(value: boolean) {\n this._hovered = value;\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const style = styleManager.getPortStyle(this._hovered, this._styleClass);\n if (!this._hasCustomRadius) {\n this._radius = style.radius;\n }\n if (!this._hasCustomColor) {\n this._color = style.color;\n }\n if (!this._hasCustomHoverColor) {\n this._hoverColor = style.color;\n }\n }\n\n /**\n * Get the absolute position of this port relative to a node\n */\n getAbsolutePosition(node: Node): Point {\n if (typeof this._position === 'object') {\n // Custom position relative to node\n return {\n x: node.x + this._position.x,\n y: node.y + this._position.y,\n };\n }\n\n // Named position\n const bounds = node.getBounds();\n const centerX = bounds.x + bounds.width / 2;\n const centerY = bounds.y + bounds.height / 2;\n\n switch (this._position) {\n case 'top':\n return { x: centerX, y: bounds.y };\n case 'bottom':\n return { x: centerX, y: bounds.y + bounds.height };\n case 'left':\n return { x: bounds.x, y: centerY };\n case 'right':\n return { x: bounds.x + bounds.width, y: centerY };\n }\n }\n\n /**\n * Test if a point hits this port\n */\n hitTest(point: Point, node: Node): boolean {\n const pos = this.getAbsolutePosition(node);\n const dx = point.x - pos.x;\n const dy = point.y - pos.y;\n // Use larger hit area for easier interaction (2x visual radius)\n const hitRadius = this._radius * 2;\n return dx * dx + dy * dy <= hitRadius * hitRadius;\n }\n\n /**\n * Render the port\n */\n render(ctx: CanvasRenderingContext2D, node: Node): void {\n const pos = this.getAbsolutePosition(node);\n\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, this._radius, 0, Math.PI * 2);\n ctx.fillStyle = this.color;\n ctx.fill();\n\n // Draw outline\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n}\n","/**\n * LRU (Least Recently Used) cache implementation\n * Automatically evicts least recently used items when capacity is reached\n */\nexport class LRUCache<K, V> {\n private readonly cache = new Map<K, V>();\n private readonly maxSize: number;\n\n constructor(maxSize: number) {\n if (maxSize <= 0) {\n throw new Error('LRUCache maxSize must be positive');\n }\n this.maxSize = maxSize;\n }\n\n /**\n * Get value by key\n * Returns undefined if key doesn't exist\n */\n get(key: K): V | undefined {\n const value = this.cache.get(key);\n if (value === undefined) {\n return undefined;\n }\n // Move to end (most recently used)\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n /**\n * Set key-value pair\n * Evicts least recently used item if at capacity\n */\n set(key: K, value: V): void {\n // Delete existing entry to move it to end\n if (this.cache.has(key)) {\n this.cache.delete(key);\n } else if (this.cache.size >= this.maxSize) {\n // Evict least recently used (first item)\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * Check if key exists in cache\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * Delete key from cache\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get current size\n */\n size(): number {\n return this.cache.size;\n }\n\n /**\n * Get maximum capacity\n */\n capacity(): number {\n return this.maxSize;\n }\n}\n","import type { Bounds } from '@/types';\nimport { LRUCache } from '@/utils/LRUCache';\n\nexport type NodeImageCornerPlacement = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\nexport type NodeImageEdgePlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport function isCornerPlacement(\n placement: NodeImagePlacement\n): placement is NodeImageCornerPlacement {\n return (\n placement === 'top-left' ||\n placement === 'top-right' ||\n placement === 'bottom-left' ||\n placement === 'bottom-right'\n );\n}\n\nexport type NodeImageFit = 'contain' | 'cover' | 'stretch' | 'none';\nexport type NodeImagePlacement =\n | 'center'\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right';\n\nexport interface NodeImageOptions {\n source: string | HTMLImageElement;\n width?: number;\n height?: number;\n fit?: NodeImageFit;\n placement?: NodeImagePlacement;\n scaleWithBounds?: boolean;\n padding?: number;\n margin?: number;\n gap?: number;\n opacity?: number;\n strokeColor?: string;\n fillColor?: string;\n align?: 'left' | 'center' | 'right';\n verticalAlign?: 'top' | 'center' | 'bottom';\n offsetX?: number;\n offsetY?: number;\n}\n\n// LRU cache for fetched SVG content (limit 100 entries to prevent memory growth)\nconst svgTextCache = new LRUCache<string, Promise<string>>(100);\n\nfunction styleSetColor(style: string, key: 'stroke' | 'fill', color: string): string {\n const hasKey = new RegExp(`${key}\\\\s*:`).test(style);\n if (hasKey) {\n return style.replace(new RegExp(`${key}\\\\s*:[^;]+`), `${key}:${color}`);\n }\n const suffix = style.trim().endsWith(';') || style.trim() === '' ? '' : ';';\n return `${style}${suffix}${key}:${color};`;\n}\n\nfunction tintSvg(svgText: string, strokeColor?: string, fillColor?: string): string {\n if (!strokeColor && !fillColor) return svgText;\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(svgText, 'image/svg+xml');\n const root = doc.documentElement;\n if (!root || root.nodeName.toLowerCase() === 'parsererror') {\n return svgText;\n }\n\n const all = [root, ...Array.from(root.querySelectorAll('*'))] as Element[];\n for (const el of all) {\n const stroke = el.getAttribute('stroke');\n if (strokeColor && stroke !== null && stroke.toLowerCase() !== 'none') {\n el.setAttribute('stroke', strokeColor);\n }\n const fill = el.getAttribute('fill');\n if (fillColor && fill !== null && fill.toLowerCase() !== 'none') {\n el.setAttribute('fill', fillColor);\n }\n const style = el.getAttribute('style');\n if (style) {\n let next = style;\n if (strokeColor && /stroke\\s*:\\s*(?!none)/.test(style)) {\n next = styleSetColor(next, 'stroke', strokeColor);\n }\n if (fillColor && /fill\\s*:\\s*(?!none)/.test(style)) {\n next = styleSetColor(next, 'fill', fillColor);\n }\n if (next !== style) {\n el.setAttribute('style', next);\n }\n }\n }\n\n return new XMLSerializer().serializeToString(root);\n}\n\nfunction isSvgMarkup(value: string): boolean {\n const trimmed = value.trim().toLowerCase();\n return trimmed.startsWith('<svg') || trimmed.includes('<svg');\n}\n\nfunction svgToDataUrl(svg: string): string {\n const encoded = encodeURIComponent(svg)\n .replace(/%0A/g, '')\n .replace(/%0D/g, '')\n .replace(/%09/g, ' ')\n .replace(/%20/g, ' ');\n return `data:image/svg+xml;utf8,${encoded}`;\n}\n\n/**\n * Image helper for node rendering (supports images and inline SVG).\n */\nexport class NodeImage {\n private _options: NodeImageOptions;\n private _image: HTMLImageElement;\n private _loaded = false;\n private _naturalWidth = 0;\n private _naturalHeight = 0;\n private _onChange?: () => void;\n private _sourceVersion = 0;\n\n constructor(options: NodeImageOptions, onChange?: () => void) {\n this._options = { ...options };\n this._onChange = onChange;\n this._image = this.resolveImage(options.source);\n this.attachHandlers();\n void this.applySource(options.source);\n }\n\n get options(): NodeImageOptions {\n return this._options;\n }\n\n set options(value: NodeImageOptions) {\n this._options = { ...value };\n this.setSource(value.source);\n }\n\n get placement(): NodeImagePlacement {\n return this._options.placement ?? 'center';\n }\n\n get gap(): number {\n return this._options.gap ?? 6;\n }\n\n setSource(source: string | HTMLImageElement): void {\n this._loaded = false;\n this._naturalWidth = 0;\n this._naturalHeight = 0;\n this._image = this.resolveImage(source);\n this.attachHandlers();\n void this.applySource(source);\n this._onChange?.();\n }\n\n render(ctx: CanvasRenderingContext2D, bounds: Bounds): void {\n if (!this._loaded) {\n return;\n }\n\n const padding = this._options.padding ?? 8;\n const margin = Math.max(0, this._options.margin ?? 0);\n const fit = this._options.fit ?? 'none';\n const scaleWithBounds = this._options.scaleWithBounds ?? false;\n const opacity = this._options.opacity ?? 1;\n const align = this._options.align ?? 'center';\n const verticalAlign = this._options.verticalAlign ?? 'center';\n const offsetX = this._options.offsetX ?? 0;\n const offsetY = this._options.offsetY ?? 0;\n\n const innerBounds: Bounds = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n const availableWidth = Math.max(0, innerBounds.width - padding * 2);\n const availableHeight = Math.max(0, innerBounds.height - padding * 2);\n\n let drawWidth = this._options.width ?? this._naturalWidth;\n let drawHeight = this._options.height ?? this._naturalHeight;\n\n if (scaleWithBounds) {\n if (fit === 'contain' || fit === 'cover') {\n const scaleX = availableWidth / this._naturalWidth;\n const scaleY = availableHeight / this._naturalHeight;\n const scale = fit === 'contain' ? Math.min(scaleX, scaleY) : Math.max(scaleX, scaleY);\n drawWidth = this._naturalWidth * scale;\n drawHeight = this._naturalHeight * scale;\n } else if (fit === 'stretch') {\n drawWidth = availableWidth;\n drawHeight = availableHeight;\n }\n }\n\n const maxWidth = Math.max(0, availableWidth);\n const maxHeight = Math.max(0, availableHeight);\n drawWidth = Math.min(drawWidth, maxWidth);\n drawHeight = Math.min(drawHeight, maxHeight);\n\n let x = innerBounds.x + padding;\n let y = innerBounds.y + padding;\n\n if (align === 'center') {\n x = innerBounds.x + (innerBounds.width - drawWidth) / 2;\n } else if (align === 'right') {\n x = innerBounds.x + innerBounds.width - drawWidth - padding;\n }\n\n if (verticalAlign === 'center') {\n y = innerBounds.y + (innerBounds.height - drawHeight) / 2;\n } else if (verticalAlign === 'bottom') {\n y = innerBounds.y + innerBounds.height - drawHeight - padding;\n }\n\n ctx.save();\n ctx.globalAlpha = opacity;\n ctx.drawImage(this._image, x + offsetX, y + offsetY, drawWidth, drawHeight);\n ctx.restore();\n }\n\n getSize(): { width: number; height: number } {\n const width = this._options.width ?? this._naturalWidth;\n const height = this._options.height ?? this._naturalHeight;\n return { width, height };\n }\n\n private resolveImage(source: string | HTMLImageElement): HTMLImageElement {\n if (source instanceof HTMLImageElement) {\n return source;\n }\n\n const img = new Image();\n img.decoding = 'async';\n return img;\n }\n\n private async applySource(source: string | HTMLImageElement): Promise<void> {\n if (source instanceof HTMLImageElement) {\n return;\n }\n const version = ++this._sourceVersion;\n\n // Inline SVG markup source\n if (isSvgMarkup(source)) {\n const tinted = tintSvg(source, this._options.strokeColor, this._options.fillColor);\n if (version !== this._sourceVersion) return;\n this._image.src = svgToDataUrl(tinted);\n return;\n }\n\n // URL source with optional SVG tinting\n const shouldTint = !!this._options.strokeColor || !!this._options.fillColor;\n if (shouldTint && source.toLowerCase().endsWith('.svg')) {\n let svgPromise = svgTextCache.get(source);\n if (!svgPromise) {\n svgPromise = fetch(source).then((r) => (r.ok ? r.text() : ''));\n svgTextCache.set(source, svgPromise);\n }\n const svgText = await svgPromise;\n if (version !== this._sourceVersion) return;\n if (svgText) {\n const tinted = tintSvg(svgText, this._options.strokeColor, this._options.fillColor);\n this._image.src = svgToDataUrl(tinted);\n return;\n }\n }\n\n if (version !== this._sourceVersion) return;\n this._image.src = source;\n }\n\n private attachHandlers(): void {\n if (this._image.complete && this._image.naturalWidth > 0) {\n this._loaded = true;\n this._naturalWidth = this._image.naturalWidth;\n this._naturalHeight = this._image.naturalHeight;\n return;\n }\n\n this._image.onload = (): void => {\n this._loaded = true;\n this._naturalWidth = this._image.naturalWidth;\n this._naturalHeight = this._image.naturalHeight;\n this._onChange?.();\n };\n this._image.onerror = (): void => {\n this._loaded = false;\n this._onChange?.();\n };\n }\n}\n","import { Element, generateId } from './Element';\nimport { Port, type PortOptions } from './Port';\nimport { TextLabel, type TextLabelOptions } from './TextLabel';\nimport {\n NodeImage,\n type NodeImageOptions,\n type NodeImagePlacement,\n isCornerPlacement,\n} from './NodeImage';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport type { Bounds, LabelPlacement, NodeStyle, Point, Size } from '@/types';\nexport type { LabelPlacement } from '../types';\nimport { shallowEqual } from '@/utils/style';\nimport {\n DEFAULT_SELECTION_COLOR,\n NODE_HITBOX_PADDING,\n RESIZE_HANDLE_OFFSET,\n RESIZE_HANDLE_SIZE,\n} from '@/constants';\n\nexport interface NodeOptions {\n id?: string;\n x: number;\n y: number;\n width: number;\n height: number;\n style?: NodeStyle;\n styleClass?: string;\n label?: string | TextLabelOptions;\n labelPlacement?: LabelPlacement;\n icon?: NodeImageOptions;\n ports?: PortOptions[];\n showPortsAlways?: boolean;\n anchorPoints?: AnchorPointsConfig;\n resizeHandlesEnabled?: boolean;\n}\n\nexport type ResizeHandle = 'nw' | 'ne' | 'se' | 'sw';\nexport type AnchorId = `${'top' | 'right' | 'bottom' | 'left'}:${number}`;\n\n/**\n * Validate if a string is a valid AnchorId format\n */\nexport function isValidAnchorId(id: string): id is AnchorId {\n return /^(top|right|bottom|left):\\d+$/.test(id);\n}\n\nexport interface AnchorPointsConfig {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n}\n\nconst DEFAULT_NODE_STYLE: NodeStyle = {\n fillColor: '#ffffff',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 1,\n};\n\n/**\n * Abstract base class for diagram nodes\n */\nexport abstract class Node extends Element {\n protected _ports: Port[] = [];\n protected _label?: TextLabel;\n protected _icon?: NodeImage;\n protected _nodeStyle: NodeStyle;\n protected _showPortsAlways: boolean;\n protected _anchorPoints: Required<AnchorPointsConfig>;\n protected _defaultSize: Size;\n protected _labelPlacement: LabelPlacement;\n protected _resizeHandlesEnabled: boolean;\n private _attachToOutlineGetter?: () => boolean;\n private _anchorCache: { id: AnchorId; point: Point }[] | null = null;\n\n protected constructor(options: NodeOptions) {\n super({\n id: options.id ?? generateId('node'),\n x: options.x,\n y: options.y,\n width: options.width,\n height: options.height,\n style: options.style,\n styleClass: options.styleClass,\n });\n\n this._defaultSize = { width: options.width, height: options.height };\n this._nodeStyle = { ...DEFAULT_NODE_STYLE, ...options.style };\n this._showPortsAlways = options.showPortsAlways ?? false;\n this._anchorPoints = this.normalizeAnchorPoints(options.anchorPoints);\n this._labelPlacement = options.labelPlacement ?? 'auto';\n this._resizeHandlesEnabled = options.resizeHandlesEnabled ?? true;\n\n if (options.label !== undefined) {\n if (typeof options.label === 'string') {\n this._label = new TextLabel({\n text: options.label,\n onChange: (): void => this.markDirty(),\n });\n } else {\n this._label = new TextLabel({ ...options.label, onChange: (): void => this.markDirty() });\n }\n }\n\n if (options.icon !== undefined) {\n this._icon = new NodeImage(options.icon, () => this.markDirty());\n }\n\n if (options.ports !== undefined) {\n for (const portOptions of options.ports) {\n this.addPort(portOptions);\n }\n }\n }\n\n /**\n * Node style\n */\n override get style(): NodeStyle {\n return this._nodeStyle;\n }\n\n override set style(value: NodeStyle) {\n this._nodeStyle = { ...DEFAULT_NODE_STYLE, ...value };\n this._style = value;\n this.markDirty();\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getNodeStyle(this._state, this._styleClass);\n const mergedStyle = { ...baseStyle, ...this._style };\n if (!shallowEqual(this._nodeStyle, mergedStyle)) {\n this._nodeStyle = mergedStyle;\n this.markDirty();\n }\n\n if (this._label) {\n this._label.applyStyleManager(styleManager);\n }\n\n for (const port of this._ports) {\n port.applyStyleManager(styleManager);\n }\n }\n\n /**\n * Ports on this node\n */\n get ports(): readonly Port[] {\n return this._ports;\n }\n\n /**\n * Text label\n */\n get label(): TextLabel | undefined {\n return this._label;\n }\n\n set label(value: TextLabel | string | undefined) {\n if (value === undefined) {\n this._label = undefined;\n } else if (typeof value === 'string') {\n this._label = new TextLabel({ text: value, onChange: (): void => this.markDirty() });\n } else {\n this._label = value;\n this._label.setOnChange((): void => this.markDirty());\n }\n this.markDirty();\n }\n\n /**\n * Node icon/image\n */\n get icon(): NodeImage | undefined {\n return this._icon;\n }\n\n set icon(value: NodeImage | NodeImageOptions | undefined) {\n if (value === undefined) {\n this._icon = undefined;\n } else if (value instanceof NodeImage) {\n this._icon = value;\n } else {\n this._icon = new NodeImage(value, () => this.markDirty());\n }\n this.markDirty();\n }\n\n /**\n * Add a port to this node\n */\n addPort(options: PortOptions): Port {\n const port = new Port(options);\n this._ports.push(port);\n this.markDirty();\n return port;\n }\n\n /**\n * Remove a port by ID\n */\n removePort(portId: string): boolean {\n const index = this._ports.findIndex((p) => p.id === portId);\n if (index === -1) {\n return false;\n }\n this._ports.splice(index, 1);\n this.markDirty();\n return true;\n }\n\n /**\n * Get a port by ID\n */\n getPort(portId: string): Port | undefined {\n return this._ports.find((p) => p.id === portId);\n }\n\n /**\n * Get absolute position of a port\n */\n getPortPosition(portId: string): Point | undefined {\n const port = this.getPort(portId);\n if (port === undefined) {\n return undefined;\n }\n return port.getAbsolutePosition(this);\n }\n\n /**\n * Find port at a point\n */\n getPortAtPoint(point: Point): Port | undefined {\n for (const port of this._ports) {\n if (port.hitTest(point, this)) {\n return port;\n }\n }\n return undefined;\n }\n\n /**\n * Apply style to canvas context\n */\n protected applyStyle(ctx: CanvasRenderingContext2D): void {\n const style = this._nodeStyle;\n\n ctx.fillStyle = style.fillColor ?? '#ffffff';\n ctx.strokeStyle = style.strokeColor ?? '#333333';\n ctx.lineWidth = style.strokeWidth ?? 2;\n ctx.globalAlpha = style.opacity ?? 1;\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n }\n\n // Highlight for hover state only\n if (this._state === 'hover') {\n ctx.strokeStyle = '#6366f1';\n }\n }\n\n /**\n * Whether to always show ports\n */\n get showPortsAlways(): boolean {\n return this._showPortsAlways;\n }\n\n set showPortsAlways(value: boolean) {\n if (this._showPortsAlways !== value) {\n this._showPortsAlways = value;\n this.markDirty();\n }\n }\n\n /**\n * Mark this element as needing re-render and invalidate anchor cache\n */\n override markDirty(): void {\n super.markDirty();\n this.invalidateAnchorCache();\n }\n\n /**\n * Invalidate anchor cache\n */\n private invalidateAnchorCache(): void {\n this._anchorCache = null;\n }\n\n get resizeHandlesEnabled(): boolean {\n return this._resizeHandlesEnabled;\n }\n\n set resizeHandlesEnabled(value: boolean) {\n if (this._resizeHandlesEnabled !== value) {\n this._resizeHandlesEnabled = value;\n this.markDirty();\n }\n }\n\n /**\n * Anchor points configuration (per side)\n */\n get anchorPoints(): Required<AnchorPointsConfig> {\n return this._anchorPoints;\n }\n\n set anchorPoints(value: AnchorPointsConfig) {\n this._anchorPoints = this.normalizeAnchorPoints(value);\n this.markDirty();\n }\n\n /**\n * Label placement inside the node\n */\n get labelPlacement(): LabelPlacement {\n return this._labelPlacement;\n }\n\n set labelPlacement(value: LabelPlacement) {\n if (this._labelPlacement !== value) {\n this._labelPlacement = value;\n this.markDirty();\n }\n }\n\n /**\n * Default size (initial width/height)\n */\n get defaultSize(): Size {\n return { ...this._defaultSize };\n }\n\n /**\n * Set getter for attachToOutline (called by DiagramRenderer when node is added)\n */\n setAttachToOutlineGetter(getter: (() => boolean) | undefined): void {\n this._attachToOutlineGetter = getter;\n }\n\n /**\n * Render ports\n */\n protected renderPorts(ctx: CanvasRenderingContext2D): void {\n if (this._attachToOutlineGetter?.()) {\n return;\n }\n // Show ports when hovered, selected, dragging, or if showPortsAlways is set\n const shouldShow =\n this._showPortsAlways ||\n this._ports.some((port) => port.hovered) ||\n this._state === 'hover' ||\n this._state === 'selected' ||\n this._state === 'dragging';\n\n if (!shouldShow) {\n return;\n }\n\n for (const port of this._ports) {\n port.render(ctx, this);\n }\n }\n\n /**\n * Calculate layout for icon and label\n * Returns computed bounds for both elements\n */\n protected calculateContentLayout(\n bounds: Bounds,\n iconBoxSize?: Size,\n labelSize?: Size\n ): { iconBounds: Bounds; labelBounds: Bounds } {\n let iconBounds = bounds;\n let labelBounds = this.getLabelContainerBounds(bounds);\n\n if (this._icon && iconBoxSize) {\n iconBounds = this.getIconBounds(bounds, iconBoxSize, this._icon.placement);\n }\n\n if (\n this._icon &&\n this._label &&\n iconBoxSize &&\n labelSize &&\n this._labelPlacement === 'auto' &&\n this._icon.placement !== 'center'\n ) {\n const gap = this._icon.gap;\n const placement = this._icon.placement;\n\n if (isCornerPlacement(placement)) {\n iconBounds = this.getIconBounds(bounds, iconBoxSize, placement);\n labelBounds = this.getLabelContainerBounds(bounds);\n } else {\n const contentBounds = this.getLabelContainerBounds(bounds);\n switch (placement) {\n case 'top':\n iconBounds = {\n x: bounds.x,\n y: bounds.y,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n labelBounds = {\n x: contentBounds.x,\n y: contentBounds.y + iconBoxSize.height + gap,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n break;\n case 'bottom':\n iconBounds = {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n labelBounds = {\n x: contentBounds.x,\n y: contentBounds.y,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n break;\n case 'left':\n iconBounds = {\n x: bounds.x,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n labelBounds = {\n x: contentBounds.x + iconBoxSize.width + gap,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n break;\n case 'right':\n iconBounds = {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n labelBounds = {\n x: contentBounds.x,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n break;\n }\n }\n } else if (this._label && labelSize) {\n const autoBounds = this.getAutoLabelBounds(bounds, iconBoxSize);\n labelBounds = this.getLabelBounds(autoBounds, labelSize, this._labelPlacement);\n }\n\n return { iconBounds, labelBounds };\n }\n\n /**\n * Get label bounds and wrapped lines for SVG export. Replicates renderContents layout logic.\n * Returns the bounds passed to label.render() and the wrapped text lines, or null if no label.\n */\n getLabelBoundsForExport(\n ctx: CanvasRenderingContext2D\n ): { bounds: Bounds; lines: string[] } | null {\n if (!this._label) {\n return null;\n }\n\n const bounds = this.getBounds();\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n const autoBounds = this.getAutoLabelBounds(bounds, iconBoxSize);\n\n this._label.setAutoMaxWidth(autoBounds.width);\n const labelSize = this._label.measure(ctx);\n\n const { labelBounds } = this.calculateContentLayout(bounds, iconBoxSize, labelSize);\n\n const lines = this._label.getWrappedLines(ctx, Math.max(0, autoBounds.width));\n return { bounds: labelBounds, lines };\n }\n\n /**\n * Render label\n */\n protected renderLabel(ctx: CanvasRenderingContext2D, bounds: Bounds = this.getBounds()): void {\n if (this._label === undefined) {\n return;\n }\n\n const labelOpacity = this._label.style.opacity ?? 1;\n ctx.globalAlpha = labelOpacity;\n this._label.render(ctx, bounds);\n ctx.globalAlpha = 1;\n }\n\n /**\n * Get world position of label center.\n */\n getLabelPosition(): Point {\n const bounds = this.getBounds();\n const placement = this._labelPlacement === 'auto' ? 'center' : this._labelPlacement;\n\n switch (placement) {\n case 'top':\n return { x: bounds.x + bounds.width / 2, y: bounds.y };\n case 'bottom':\n return { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height };\n case 'left':\n return { x: bounds.x, y: bounds.y + bounds.height / 2 };\n case 'right':\n return { x: bounds.x + bounds.width, y: bounds.y + bounds.height / 2 };\n default:\n return { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height / 2 };\n }\n }\n\n /**\n * Render icon, label, and ports\n */\n protected renderContents(ctx: CanvasRenderingContext2D): void {\n // Reset dash settings so icon/label/ports render solid\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n\n let bounds = this.getBounds();\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n\n if (this._label) {\n this._label.setAutoMaxWidth(this.getAutoLabelBounds(bounds, iconBoxSize).width);\n }\n const labelSize = this._label ? this._label.measure(ctx) : undefined;\n\n if (labelSize || iconBoxSize) {\n this.ensureContentsFit(labelSize, iconBoxSize);\n // Re-measure after potential resize\n if (this._label && iconBoxSize) {\n bounds = this.getBounds();\n this._label.setAutoMaxWidth(this.getAutoLabelBounds(bounds, iconBoxSize).width);\n }\n }\n\n const { iconBounds, labelBounds } = this.calculateContentLayout(\n this.getBounds(),\n iconBoxSize,\n labelSize\n );\n\n if (this._icon) {\n this._icon.render(ctx, iconBounds);\n }\n\n this.renderLabel(ctx, labelBounds);\n this.renderPorts(ctx);\n }\n\n /**\n * Minimal size required to fit current contents\n */\n getContentMinSize(ctx: CanvasRenderingContext2D): Size {\n const bounds = this.getBounds();\n const labelSize = this._label ? this._label.measure(ctx) : undefined;\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n return this.calculateContentMinSize(labelSize, iconBoxSize, bounds);\n }\n\n /**\n * Render resize handles when selected\n */\n renderResizeHandles(ctx: CanvasRenderingContext2D): void {\n if (this._state !== 'selected' || !this._resizeHandlesEnabled) {\n return;\n }\n\n const bounds = this.getBounds();\n const offset = RESIZE_HANDLE_OFFSET;\n const size = RESIZE_HANDLE_SIZE;\n const half = size / 2;\n\n ctx.save();\n\n // Draw dashed selection rectangle\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 1;\n ctx.setLineDash([4, 4]);\n ctx.strokeRect(\n bounds.x - offset,\n bounds.y - offset,\n bounds.width + offset * 2,\n bounds.height + offset * 2\n );\n\n // Draw resize handles\n ctx.fillStyle = '#ffffff';\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([]);\n\n for (const handle of this.getResizeHandlePositions()) {\n ctx.beginPath();\n ctx.rect(handle.x - half, handle.y - half, size, size);\n ctx.fill();\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Hit test a resize handle\n */\n hitTestResizeHandle(point: Point): ResizeHandle | null {\n if (this._state !== 'selected') {\n return null;\n }\n\n const size = RESIZE_HANDLE_SIZE;\n const half = size / 2;\n\n for (const handle of this.getResizeHandlePositions()) {\n if (\n point.x >= handle.x - half &&\n point.x <= handle.x + half &&\n point.y >= handle.y - half &&\n point.y <= handle.y + half\n ) {\n return handle.type;\n }\n }\n\n return null;\n }\n\n /**\n * Default bounding box hit test\n */\n hitTest(point: Point): boolean {\n const bounds = this.getBounds();\n const padding = NODE_HITBOX_PADDING;\n return (\n point.x >= bounds.x - padding &&\n point.x <= bounds.x + bounds.width + padding &&\n point.y >= bounds.y - padding &&\n point.y <= bounds.y + bounds.height + padding\n );\n }\n\n /**\n * Get a connection point on the node boundary toward a target point,\n * snapped to nearest anchor point on the contour.\n */\n getConnectionPoint(target: Point): Point {\n const anchors = this.getAnchorsOnOutline();\n if (anchors.length === 0) {\n return this.getOutlinePointToward(target);\n }\n\n let closest = anchors[0]!;\n let minDist = (target.x - closest.point.x) ** 2 + (target.y - closest.point.y) ** 2;\n\n for (let i = 1; i < anchors.length; i++) {\n const anchor = anchors[i]!;\n const dist = (target.x - anchor.point.x) ** 2 + (target.y - anchor.point.y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n closest = anchor;\n }\n }\n\n return closest.point;\n }\n\n /**\n * Get all anchors on the outline\n */\n getAnchors(): { id: AnchorId; point: Point }[] {\n return this.getAnchorsOnOutline();\n }\n\n /**\n * Get all anchor points on the outline\n */\n getAnchorPoints(): Point[] {\n return this.getAnchorsOnOutline().map((anchor) => anchor.point);\n }\n\n /**\n * Get anchor IDs for sides that have ports\n */\n getPortAnchorIds(): string[] {\n const portSides = new Set<string>();\n for (const port of this._ports) {\n if (typeof port.position === 'string') {\n portSides.add(port.position);\n }\n }\n const anchors = this.getAnchorsOnOutline();\n return anchors\n .filter((anchor) => {\n const side = anchor.id.split(':')[0];\n return side && portSides.has(side);\n })\n .map((anchor) => anchor.id);\n }\n\n /**\n * Get nearest anchor that belongs to a port side\n */\n getNearestPortAnchor(target: Point): { id: AnchorId; point: Point } | null {\n const portAnchorIds = this.getPortAnchorIds();\n if (portAnchorIds.length === 0) {\n return null;\n }\n const anchors = this.getAnchorsOnOutline().filter((anchor) =>\n portAnchorIds.includes(anchor.id)\n );\n if (anchors.length === 0) {\n return null;\n }\n\n let closest = anchors[0]!;\n let minDist = (target.x - closest.point.x) ** 2 + (target.y - closest.point.y) ** 2;\n\n for (let i = 1; i < anchors.length; i++) {\n const anchor = anchors[i]!;\n const dist = (target.x - anchor.point.x) ** 2 + (target.y - anchor.point.y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n closest = anchor;\n }\n }\n\n return closest;\n }\n\n /**\n * Get nearest anchor to a target point\n */\n getNearestAnchor(target: Point): { id: AnchorId; point: Point } | null {\n const anchors = this.getAnchorsOnOutline();\n if (anchors.length === 0) {\n return null;\n }\n\n let closest = anchors[0]!;\n let minDist = (target.x - closest.point.x) ** 2 + (target.y - closest.point.y) ** 2;\n\n for (let i = 1; i < anchors.length; i++) {\n const anchor = anchors[i]!;\n const dist = (target.x - anchor.point.x) ** 2 + (target.y - anchor.point.y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n closest = anchor;\n }\n }\n\n return closest;\n }\n\n /**\n * Get anchor point by id\n */\n getAnchorPointById(anchorId: string): Point | null {\n if (!isValidAnchorId(anchorId)) {\n return null;\n }\n const anchors = this.getAnchorsOnOutline();\n const match = anchors.find((anchor) => anchor.id === anchorId);\n return match?.point ?? null;\n }\n\n /**\n * Get shape-specific bounds (can be overridden for non-rectangular shapes)\n */\n override getBounds(): Bounds {\n return {\n x: this._x,\n y: this._y,\n width: this._width,\n height: this._height,\n };\n }\n\n /**\n * Get the type name of this node\n */\n abstract get typeName(): string;\n\n /**\n * Get point on outline at normalized param (0-1 along perimeter).\n * Base implementation uses rectangular outline. Override for non-rectangular shapes.\n */\n getConnectionPointAtOutlineParam(param: number): Point {\n const bounds = this.getBounds();\n const { x, y, width: w, height: h } = bounds;\n const perimeter = 2 * (w + h);\n let s = (((param % 1) + 1) % 1) * perimeter;\n\n if (s < w) return { x: x + s, y };\n s -= w;\n if (s < h) return { x: x + w, y: y + s };\n s -= h;\n if (s < w) return { x: x + w - s, y: y + h };\n s -= w;\n return { x, y: y + h - s };\n }\n\n /**\n * Get closest point on outline and its param (0-1).\n * Base implementation uses rectangular outline. Override for non-rectangular shapes.\n */\n getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const bounds = this.getBounds();\n const { x, y, width: w, height: h } = bounds;\n const P = 2 * (w + h);\n\n const projectSegment = (\n ax: number,\n ay: number,\n bx: number,\n by: number,\n segLen: number,\n segStartParam: number\n ): { point: Point; param: number; distSq: number } => {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n let t = lenSq > 0 ? ((target.x - ax) * dx + (target.y - ay) * dy) / lenSq : 0;\n t = Math.max(0, Math.min(1, t));\n const px = ax + t * dx;\n const py = ay + t * dy;\n const distSq = (target.x - px) ** 2 + (target.y - py) ** 2;\n const param = segStartParam + (t * segLen) / P;\n return { point: { x: px, y: py }, param, distSq };\n };\n\n let best = projectSegment(x, y, x + w, y, w, 0);\n let r = projectSegment(x + w, y, x + w, y + h, h, w / P);\n if (r.distSq < best.distSq) best = r;\n r = projectSegment(x + w, y + h, x, y + h, w, (w + h) / P);\n if (r.distSq < best.distSq) best = r;\n r = projectSegment(x, y + h, x, y, h, (2 * w + h) / P);\n if (r.distSq < best.distSq) best = r;\n\n return { point: best.point, param: best.param };\n }\n\n /**\n * Get intersection point on the shape outline toward the target.\n * Override for non-rectangular shapes.\n */\n protected getOutlinePointToward(target: Point): Point {\n const bounds = this.getBounds();\n const center = this.getCenter();\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n\n if (dx === 0 && dy === 0) {\n return center;\n }\n\n const halfW = bounds.width / 2;\n const halfH = bounds.height / 2;\n\n const scaleX = halfW / Math.abs(dx);\n const scaleY = halfH / Math.abs(dy);\n const scale = Math.min(scaleX, scaleY);\n\n return {\n x: center.x + dx * scale,\n y: center.y + dy * scale,\n };\n }\n\n private getResizeHandlePositions(\n offset = RESIZE_HANDLE_OFFSET\n ): { type: ResizeHandle; x: number; y: number }[] {\n const { x, y, width, height } = this.getBounds();\n\n return [\n { type: 'nw', x: x - offset, y: y - offset },\n { type: 'ne', x: x + width + offset, y: y - offset },\n { type: 'se', x: x + width + offset, y: y + height + offset },\n { type: 'sw', x: x - offset, y: y + height + offset },\n ];\n }\n\n private ensureContentsFit(labelSize?: Size, iconBoxSize?: Size): void {\n const bounds = this.getBounds();\n const minSize = this.calculateContentMinSize(labelSize, iconBoxSize, bounds);\n\n if (minSize.width > bounds.width) {\n this.width = minSize.width;\n }\n if (minSize.height > bounds.height) {\n this.height = minSize.height;\n }\n }\n\n private calculateContentMinSize(\n labelSize: Size | undefined,\n iconBoxSize: Size | undefined,\n bounds: Bounds\n ): Size {\n let minWidth = 0;\n let minHeight = 0;\n\n const labelContainer = this.getLabelContainerBounds(bounds);\n const widthFactor = labelContainer.width > 0 ? bounds.width / labelContainer.width : 1;\n const heightFactor = labelContainer.height > 0 ? bounds.height / labelContainer.height : 1;\n\n if (labelSize) {\n minWidth = Math.max(minWidth, labelSize.width * widthFactor);\n minHeight = Math.max(minHeight, labelSize.height * heightFactor);\n }\n\n if (iconBoxSize) {\n minWidth = Math.max(minWidth, iconBoxSize.width);\n minHeight = Math.max(minHeight, iconBoxSize.height);\n }\n\n if (labelSize && iconBoxSize && this._icon) {\n const gap = this._icon.gap;\n const labelPlacement = this._labelPlacement === 'auto' ? 'center' : this._labelPlacement;\n const iconPlacement = this._icon.placement;\n\n if (this._labelPlacement === 'auto' && iconPlacement !== 'center') {\n if (isCornerPlacement(iconPlacement)) {\n // For corner placements, just ensure both fit (no stacking)\n minWidth = Math.max(minWidth, iconBoxSize.width, labelSize.width);\n minHeight = Math.max(minHeight, iconBoxSize.height, labelSize.height);\n } else if (iconPlacement === 'top' || iconPlacement === 'bottom') {\n minHeight = Math.max(minHeight, iconBoxSize.height + gap + labelSize.height);\n minWidth = Math.max(minWidth, iconBoxSize.width, labelSize.width);\n } else if (iconPlacement === 'left' || iconPlacement === 'right') {\n minWidth = Math.max(minWidth, iconBoxSize.width + gap + labelSize.width);\n minHeight = Math.max(minHeight, iconBoxSize.height, labelSize.height);\n }\n } else {\n const labelHorizontal = labelPlacement === 'left' || labelPlacement === 'right';\n const labelVertical = labelPlacement === 'top' || labelPlacement === 'bottom';\n const iconHorizontal = iconPlacement === 'left' || iconPlacement === 'right';\n const iconVertical = iconPlacement === 'top' || iconPlacement === 'bottom';\n const labelSharesIconAxis =\n (iconHorizontal && (labelPlacement === 'center' || labelPlacement === iconPlacement)) ||\n (iconVertical && (labelPlacement === 'center' || labelPlacement === iconPlacement));\n\n if (labelHorizontal && iconHorizontal && labelPlacement !== iconPlacement) {\n minWidth = Math.max(minWidth, iconBoxSize.width + gap + labelSize.width);\n }\n if (labelVertical && iconVertical && labelPlacement !== iconPlacement) {\n minHeight = Math.max(minHeight, iconBoxSize.height + gap + labelSize.height);\n }\n if (labelSharesIconAxis) {\n if (iconHorizontal) {\n minWidth = Math.max(minWidth, iconBoxSize.width + gap + labelSize.width);\n }\n if (iconVertical) {\n minHeight = Math.max(minHeight, iconBoxSize.height + gap + labelSize.height);\n }\n }\n }\n }\n\n return { width: minWidth, height: minHeight };\n }\n\n protected getLabelContainerBounds(bounds: Bounds): Bounds {\n return bounds;\n }\n\n private getAutoLabelBounds(bounds: Bounds, iconBoxSize?: Size): Bounds {\n const contentBounds = this.getLabelContainerBounds(bounds);\n if (!this._icon || !iconBoxSize || this._icon.placement === 'center') {\n return contentBounds;\n }\n\n const gap = this._icon.gap;\n if (isCornerPlacement(this._icon.placement)) {\n return contentBounds;\n }\n\n switch (this._icon.placement) {\n case 'left':\n return {\n x: contentBounds.x + iconBoxSize.width + gap,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n case 'right':\n return {\n x: contentBounds.x,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n case 'top':\n return {\n x: contentBounds.x,\n y: contentBounds.y + iconBoxSize.height + gap,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n case 'bottom':\n return {\n x: contentBounds.x,\n y: contentBounds.y,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n default:\n return contentBounds;\n }\n }\n\n private getLabelBounds(bounds: Bounds, labelSize: Size, placement: LabelPlacement): Bounds {\n const normalizedPlacement = placement === 'auto' ? 'center' : placement;\n const width = Math.min(labelSize.width, bounds.width);\n const height = Math.min(labelSize.height, bounds.height);\n\n let x = bounds.x + (bounds.width - width) / 2;\n let y = bounds.y + (bounds.height - height) / 2;\n\n switch (normalizedPlacement) {\n case 'top':\n y = bounds.y;\n break;\n case 'bottom':\n y = bounds.y + bounds.height - height;\n break;\n case 'left':\n x = bounds.x;\n break;\n case 'right':\n x = bounds.x + bounds.width - width;\n break;\n default:\n break;\n }\n\n return { x, y, width, height };\n }\n\n private getIconBoxSize(): Size | undefined {\n if (!this._icon) {\n return undefined;\n }\n\n const { width, height } = this._icon.getSize();\n if (width <= 0 || height <= 0) {\n return undefined;\n }\n\n const padding = this._icon.options.padding ?? 8;\n const margin = Math.max(0, this._icon.options.margin ?? 0);\n return {\n width: width + padding * 2 + margin * 2,\n height: height + padding * 2 + margin * 2,\n };\n }\n\n private getIconBounds(bounds: Bounds, iconBoxSize: Size, placement: NodeImagePlacement): Bounds {\n switch (placement) {\n case 'top':\n return {\n x: bounds.x,\n y: bounds.y,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n case 'bottom':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n case 'left':\n return {\n x: bounds.x,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n case 'right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n case 'top-left':\n return {\n x: bounds.x,\n y: bounds.y,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'top-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-left':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n default:\n return bounds;\n }\n }\n\n private normalizeAnchorPoints(config?: AnchorPointsConfig): Required<AnchorPointsConfig> {\n const normalize = (value: number | undefined): number => {\n if (value === undefined) return 1;\n if (!Number.isFinite(value)) return 1;\n return Math.max(0, Math.floor(value));\n };\n\n return {\n top: normalize(config?.top),\n right: normalize(config?.right),\n bottom: normalize(config?.bottom),\n left: normalize(config?.left),\n };\n }\n\n private getAnchorsOnOutline(): { id: AnchorId; point: Point }[] {\n if (this._anchorCache !== null) {\n return this._anchorCache;\n }\n\n const { top, right, bottom, left } = this._anchorPoints;\n const bounds = this.getBounds();\n const anchors: { id: AnchorId; point: Point }[] = [];\n\n const addPoints = (\n side: 'top' | 'right' | 'bottom' | 'left',\n count: number,\n cb: (t: number) => Point\n ): void => {\n if (count <= 0) return;\n for (let i = 0; i < count; i++) {\n const t = (i + 1) / (count + 1);\n const id: AnchorId = `${side}:${i}`;\n anchors.push({ id, point: cb(t) });\n }\n };\n\n addPoints('top', top, (t) => ({ x: bounds.x + bounds.width * t, y: bounds.y }));\n addPoints('bottom', bottom, (t) => ({\n x: bounds.x + bounds.width * t,\n y: bounds.y + bounds.height,\n }));\n addPoints('left', left, (t) => ({ x: bounds.x, y: bounds.y + bounds.height * t }));\n addPoints('right', right, (t) => ({\n x: bounds.x + bounds.width,\n y: bounds.y + bounds.height * t,\n }));\n\n if (anchors.length === 0) {\n this._anchorCache = [];\n return [];\n }\n\n const result = anchors.map((anchor) => ({\n id: anchor.id,\n point: this.getOutlinePointToward(anchor.point),\n }));\n this._anchorCache = result;\n return result;\n }\n}\n","import { Element, generateId } from './Element';\nimport type { Node } from './Node';\nimport type { Bounds, ElementStyle, Point } from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport { shallowEqual } from '@/utils/style';\nimport { pointInRect } from '@/utils/geometry';\n\nexport interface GroupOptions {\n id?: string;\n style?: ElementStyle;\n styleClass?: string;\n label?: string;\n padding?: number;\n}\n\nconst DEFAULT_GROUP_STYLE: ElementStyle = {\n fillColor: 'rgba(200, 200, 200, 0.2)',\n strokeColor: '#999999',\n strokeWidth: 1,\n lineDash: [8, 4],\n opacity: 1,\n};\n\n/**\n * Container for grouping nodes\n */\nexport class Group extends Element {\n private _children: (Node | Group)[] = [];\n private _label?: string;\n private _padding: number;\n private _groupStyle: ElementStyle;\n\n constructor(options: GroupOptions = {}) {\n super({\n id: options.id ?? generateId('group'),\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n style: options.style,\n styleClass: options.styleClass,\n });\n\n this._groupStyle = { ...DEFAULT_GROUP_STYLE, ...options.style };\n this._label = options.label;\n this._padding = options.padding ?? 20;\n }\n\n /**\n * Children of this group\n */\n get children(): readonly (Node | Group)[] {\n return this._children;\n }\n\n /**\n * Group label\n */\n get label(): string | undefined {\n return this._label;\n }\n\n set label(value: string | undefined) {\n this._label = value;\n this.markDirty();\n }\n\n /**\n * Padding around children\n */\n get padding(): number {\n return this._padding;\n }\n\n set padding(value: number) {\n if (this._padding !== value) {\n this._padding = value;\n this.recalculateBounds();\n }\n }\n\n /**\n * Group style\n */\n override get style(): ElementStyle {\n return this._groupStyle;\n }\n\n override set style(value: ElementStyle) {\n this._groupStyle = { ...DEFAULT_GROUP_STYLE, ...value };\n this._style = value;\n this.markDirty();\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getGroupStyle(false, this._styleClass);\n const mergedStyle = { ...baseStyle, ...this._style };\n if (!shallowEqual(this._groupStyle, mergedStyle)) {\n this._groupStyle = mergedStyle;\n this.markDirty();\n }\n }\n\n /**\n * Add a child to this group\n */\n addChild(child: Node | Group): void {\n if (!this._children.includes(child)) {\n this._children.push(child);\n this.recalculateBounds();\n }\n }\n\n /**\n * Remove a child from this group\n */\n removeChild(childId: string): boolean {\n const index = this._children.findIndex((c) => c.id === childId);\n if (index === -1) {\n return false;\n }\n this._children.splice(index, 1);\n this.recalculateBounds();\n return true;\n }\n\n /**\n * Check if a child is in this group (recursive)\n */\n hasChild(childId: string): boolean {\n for (const child of this._children) {\n if (child.id === childId) {\n return true;\n }\n if (child instanceof Group && child.hasChild(childId)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get all nested children (flattened)\n */\n getAllChildren(): (Node | Group)[] {\n const result: (Node | Group)[] = [];\n for (const child of this._children) {\n result.push(child);\n if (child instanceof Group) {\n result.push(...child.getAllChildren());\n }\n }\n return result;\n }\n\n /**\n * Recalculate bounds from children\n */\n recalculateBounds(): void {\n if (this._children.length === 0) {\n this._x = 0;\n this._y = 0;\n this._width = 0;\n this._height = 0;\n this.markDirty();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const child of this._children) {\n const bounds = child.getBounds();\n minX = Math.min(minX, bounds.x);\n minY = Math.min(minY, bounds.y);\n maxX = Math.max(maxX, bounds.x + bounds.width);\n maxY = Math.max(maxY, bounds.y + bounds.height);\n }\n\n this._x = minX - this._padding;\n this._y = minY - this._padding;\n this._width = maxX - minX + this._padding * 2;\n this._height = maxY - minY + this._padding * 2;\n\n this.markDirty();\n }\n\n hitTest(point: Point): boolean {\n const bounds = this.getBounds();\n return pointInRect(point, bounds);\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n if (this._children.length === 0) {\n return;\n }\n\n const { x, y, width, height } = this.getBounds();\n const style = this._groupStyle;\n\n // Draw background\n ctx.fillStyle = style.fillColor ?? 'rgba(200, 200, 200, 0.2)';\n ctx.globalAlpha = style.opacity ?? 1;\n ctx.fillRect(x, y, width, height);\n\n // Draw border\n ctx.strokeStyle = style.strokeColor ?? '#999999';\n ctx.lineWidth = style.strokeWidth ?? 1;\n\n if (this._state === 'selected') {\n ctx.lineWidth = Math.max(style.strokeWidth ?? 1, 2);\n }\n\n const lineDash = style.lineDash ?? [];\n ctx.setLineDash(lineDash.length > 0 ? lineDash : []);\n ctx.strokeRect(x, y, width, height);\n ctx.setLineDash([]);\n\n // Draw label\n if (this._label !== undefined) {\n ctx.fillStyle = '#666666';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n ctx.fillText(this._label, x + 8, y + 4);\n }\n\n ctx.globalAlpha = 1;\n\n // Render children\n for (const child of this._children) {\n if (child.visible) {\n child.render(ctx);\n }\n }\n }\n\n override getBounds(): Bounds {\n return {\n x: this._x,\n y: this._y,\n width: this._width,\n height: this._height,\n };\n }\n}\n","import { Node, type NodeOptions } from '../Node';\n\nexport interface RectangleNodeOptions extends NodeOptions {\n cornerRadius?: number;\n}\n\n/**\n * Rectangular node with optional rounded corners\n */\nexport class RectangleNode extends Node {\n private _cornerRadius: number;\n\n constructor(options: RectangleNodeOptions) {\n super(options);\n this._cornerRadius = options.cornerRadius ?? options.style?.cornerRadius ?? 0;\n }\n\n get typeName(): string {\n return 'rectangle';\n }\n\n /**\n * Corner radius for rounded rectangles\n */\n get cornerRadius(): number {\n return this._cornerRadius;\n }\n\n set cornerRadius(value: number) {\n if (this._cornerRadius !== value) {\n this._cornerRadius = value;\n this.markDirty();\n }\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const { x, y, width, height } = this.getBounds();\n const radius = Math.min(this._cornerRadius, width / 2, height / 2);\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.beginPath();\n\n if (radius > 0) {\n // Rounded rectangle\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.arcTo(x + width, y, x + width, y + radius, radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);\n ctx.lineTo(x + radius, y + height);\n ctx.arcTo(x, y + height, x, y + height - radius, radius);\n ctx.lineTo(x, y + radius);\n ctx.arcTo(x, y, x + radius, y, radius);\n } else {\n // Sharp rectangle\n ctx.rect(x, y, width, height);\n }\n\n ctx.closePath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n","import { Node, type NodeOptions } from '../Node';\nimport { NODE_HITBOX_PADDING } from '@/constants';\nimport type { Bounds, Point } from '@/types';\n\n/**\n * Ellipse/circle node\n */\nexport class CircleNode extends Node {\n constructor(options: NodeOptions) {\n super(options);\n }\n\n get typeName(): string {\n return 'circle';\n }\n\n /**\n * Horizontal radius\n */\n get radiusX(): number {\n return this._width / 2;\n }\n\n /**\n * Vertical radius\n */\n get radiusY(): number {\n return this._height / 2;\n }\n\n override hitTest(point: Point): boolean {\n const center = this.getCenter();\n const padding = NODE_HITBOX_PADDING;\n const rx = this._width / 2 + padding;\n const ry = this._height / 2 + padding;\n\n // Ellipse equation: (x-h)²/rx² + (y-k)²/ry² <= 1\n const dx = point.x - center.x;\n const dy = point.y - center.y;\n return (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry) <= 1;\n }\n\n override getConnectionPointAtOutlineParam(param: number): Point {\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const t = ((param % 1) + 1) % 1 * Math.PI * 2;\n const angle = Math.PI * 1.5 - t;\n return {\n x: center.x + rx * Math.cos(angle),\n y: center.y + ry * Math.sin(angle),\n };\n }\n\n override getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const point = this.getOutlinePointToward(target);\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const t = Math.atan2(\n (point.y - center.y) / ry,\n (point.x - center.x) / rx\n );\n const param = (Math.PI * 1.5 - t) / (Math.PI * 2);\n const normalizedParam = ((param % 1) + 1) % 1;\n return { point, param: normalizedParam };\n }\n\n protected override getOutlinePointToward(target: Point): Point {\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n\n if (dx === 0 && dy === 0) {\n return center;\n }\n\n const scale = 1 / Math.sqrt((dx * dx) / (rx * rx) + (dy * dy) / (ry * ry));\n return {\n x: center.x + dx * scale,\n y: center.y + dy * scale,\n };\n }\n\n protected override getLabelContainerBounds(bounds: Bounds): Bounds {\n const width = bounds.width / Math.SQRT2;\n const height = bounds.height / Math.SQRT2;\n return {\n x: bounds.x + (bounds.width - width) / 2,\n y: bounds.y + (bounds.height - height) / 2,\n width,\n height,\n };\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.beginPath();\n ctx.ellipse(center.x, center.y, rx, ry, 0, 0, Math.PI * 2);\n ctx.closePath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n","import { Node, type NodeOptions } from '../Node';\nimport { NODE_HITBOX_PADDING } from '@/constants';\nimport type { Bounds, Point } from '@/types';\n\n/**\n * Diamond/rhombus node for decision points\n */\nexport class DiamondNode extends Node {\n constructor(options: NodeOptions) {\n super(options);\n }\n\n get typeName(): string {\n return 'diamond';\n }\n\n override hitTest(point: Point): boolean {\n // Check if point is inside the diamond\n const center = this.getCenter();\n const padding = NODE_HITBOX_PADDING;\n const hw = this._width / 2 + padding;\n const hh = this._height / 2 + padding;\n\n // Use normalized distance formula for diamond/rhombus\n // Point is inside if |dx|/hw + |dy|/hh <= 1\n const dx = Math.abs(point.x - center.x);\n const dy = Math.abs(point.y - center.y);\n\n return dx / hw + dy / hh <= 1;\n }\n\n override getConnectionPointAtOutlineParam(param: number): Point {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\n const vertices: Point[] = [\n { x: center.x, y: center.y - hh },\n { x: center.x + hw, y: center.y },\n { x: center.x, y: center.y + hh },\n { x: center.x - hw, y: center.y },\n ];\n const segLen = Math.sqrt(hw * hw + hh * hh);\n const perimeter = 4 * segLen;\n let s = ((param % 1) + 1) % 1 * perimeter;\n\n for (let i = 0; i < 4; i++) {\n if (s < segLen) {\n const a = vertices[i]!;\n const b = vertices[(i + 1) % 4]!;\n const t = s / segLen;\n return {\n x: a.x + t * (b.x - a.x),\n y: a.y + t * (b.y - a.y),\n };\n }\n s -= segLen;\n }\n return vertices[0]!;\n }\n\n override getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\n const vertices: Point[] = [\n { x: center.x, y: center.y - hh },\n { x: center.x + hw, y: center.y },\n { x: center.x, y: center.y + hh },\n { x: center.x - hw, y: center.y },\n ];\n const segLen = Math.sqrt(hw * hw + hh * hh);\n const P = 4 * segLen;\n\n const projectSegment = (\n ax: number, ay: number, bx: number, by: number,\n segStartParam: number\n ): { point: Point; param: number; distSq: number } => {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n let t = lenSq > 0 ? ((target.x - ax) * dx + (target.y - ay) * dy) / lenSq : 0;\n t = Math.max(0, Math.min(1, t));\n const px = ax + t * dx;\n const py = ay + t * dy;\n const distSq = (target.x - px) ** 2 + (target.y - py) ** 2;\n const param = segStartParam + (t * segLen) / P;\n return { point: { x: px, y: py }, param, distSq };\n };\n\n let best = projectSegment(vertices[0]!.x, vertices[0]!.y, vertices[1]!.x, vertices[1]!.y, 0);\n for (let i = 1; i < 4; i++) {\n const a = vertices[i]!;\n const b = vertices[(i + 1) % 4]!;\n const r = projectSegment(a.x, a.y, b.x, b.y, (i * segLen) / P);\n if (r.distSq < best.distSq) best = r;\n }\n return { point: best.point, param: best.param };\n }\n\n protected override getOutlinePointToward(target: Point): Point {\n const center = this.getCenter();\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n const hw = this._width / 2;\n const hh = this._height / 2;\n\n if (dx === 0 && dy === 0) {\n return center;\n }\n\n const t = 1 / (Math.abs(dx) / hw + Math.abs(dy) / hh);\n return {\n x: center.x + dx * t,\n y: center.y + dy * t,\n };\n }\n\n protected override getLabelContainerBounds(bounds: Bounds): Bounds {\n const width = bounds.width / 2;\n const height = bounds.height / 2;\n return {\n x: bounds.x + (bounds.width - width) / 2,\n y: bounds.y + (bounds.height - height) / 2,\n width,\n height,\n };\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.beginPath();\n ctx.moveTo(center.x, center.y - hh); // Top\n ctx.lineTo(center.x + hw, center.y); // Right\n ctx.lineTo(center.x, center.y + hh); // Bottom\n ctx.lineTo(center.x - hw, center.y); // Left\n ctx.closePath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n","import { Node, type NodeOptions } from '../Node';\nimport { NODE_HITBOX_PADDING } from '@/constants';\nimport type { Point } from '@/types';\n\nconst OUTLINE_SAMPLE_COUNT = 64;\n\nexport interface CustomShapeNodeOptions extends NodeOptions {\n path: Path2D | ((width: number, height: number) => Path2D);\n /**\n * SVG path string for export. Required for correct SVG export of custom shapes.\n * Path coordinates are in local space (0,0 = top-left, width×height = node bounds).\n * If omitted, SVG export falls back to a rectangle.\n */\n svgPath?: string | ((width: number, height: number) => string);\n shapeType?: string;\n}\n\n/**\n * Node with custom Path2D shape\n */\nexport class CustomShapeNode extends Node {\n private _pathFactory: (width: number, height: number) => Path2D;\n private _svgPathFactory: ((width: number, height: number) => string) | null = null;\n private _shapeType?: string;\n private _cachedPath: Path2D | null = null;\n private _cachedWidth = 0;\n private _cachedHeight = 0;\n private _cachedOutline: { points: Point[]; lengths: number[]; totalLength: number } | null = null;\n\n constructor(options: CustomShapeNodeOptions) {\n super(options);\n\n if (options.path instanceof Path2D) {\n const staticPath = options.path;\n this._pathFactory = (): Path2D => staticPath;\n } else {\n this._pathFactory = options.path;\n }\n\n if (options.svgPath !== undefined) {\n if (typeof options.svgPath === 'string') {\n const staticSvg = options.svgPath;\n this._svgPathFactory = (): string => staticSvg;\n } else {\n this._svgPathFactory = options.svgPath;\n }\n }\n\n this._shapeType = options.shapeType;\n }\n\n get typeName(): string {\n return 'custom';\n }\n\n get shapeType(): string | undefined {\n return this._shapeType;\n }\n\n set shapeType(value: string | undefined) {\n if (this._shapeType !== value) {\n this._shapeType = value;\n this.markDirty();\n }\n }\n\n /**\n * Set a new path factory\n */\n setPathFactory(factory: (width: number, height: number) => Path2D): void {\n this._pathFactory = factory;\n this._cachedPath = null;\n this._cachedOutline = null;\n this.markDirty();\n }\n\n /**\n * Get the current path (cached)\n */\n getPath(): Path2D {\n if (\n this._cachedPath === null ||\n this._cachedWidth !== this._width ||\n this._cachedHeight !== this._height\n ) {\n this._cachedPath = this._pathFactory(this._width, this._height);\n this._cachedWidth = this._width;\n this._cachedHeight = this._height;\n this._cachedOutline = null;\n }\n return this._cachedPath;\n }\n\n /**\n * Get SVG path string for export. Returns null if svgPath was not provided.\n */\n getSvgPath(): string | null {\n if (this._svgPathFactory === null) {\n return null;\n }\n return this._svgPathFactory(this._width, this._height);\n }\n\n /**\n * Set SVG path for export. Call when shape changes.\n */\n setSvgPath(value: string | ((width: number, height: number) => string) | undefined): void {\n if (value === undefined) {\n this._svgPathFactory = null;\n } else if (typeof value === 'string') {\n this._svgPathFactory = (): string => value;\n } else {\n this._svgPathFactory = value;\n }\n this.markDirty();\n }\n\n private getOutlineSample(): { points: Point[]; lengths: number[]; totalLength: number } | null {\n this.getPath();\n if (\n this._cachedOutline !== null &&\n this._cachedWidth === this._width &&\n this._cachedHeight === this._height\n ) {\n return this._cachedOutline;\n }\n\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : null;\n const ctx = canvas?.getContext('2d');\n if (!ctx) {\n return null;\n }\n\n const path = this.getPath();\n const cx = this._width / 2;\n const cy = this._height / 2;\n const maxR = Math.max(this._width, this._height);\n\n const isInside = (lx: number, ly: number): boolean => ctx.isPointInPath(path, lx, ly);\n\n const getBoundaryPoint = (dx: number, dy: number): Point => {\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) return { x: cx, y: cy };\n const ux = dx / len;\n const uy = dy / len;\n let lo = 0;\n let hi = maxR;\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2;\n const px = cx + ux * mid;\n const py = cy + uy * mid;\n if (isInside(px, py)) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n const t = (lo + hi) / 2;\n return { x: cx + ux * t, y: cy + uy * t };\n };\n\n const points: Point[] = [];\n for (let i = 0; i < OUTLINE_SAMPLE_COUNT; i++) {\n const angle = (i / OUTLINE_SAMPLE_COUNT) * Math.PI * 2 - Math.PI / 2;\n const dx = Math.cos(angle);\n const dy = Math.sin(angle);\n points.push(getBoundaryPoint(dx, dy));\n }\n\n const lengths: number[] = [];\n let totalLength = 0;\n for (let i = 0; i < OUTLINE_SAMPLE_COUNT; i++) {\n const a = points[i]!;\n const b = points[(i + 1) % OUTLINE_SAMPLE_COUNT]!;\n const segLen = Math.hypot(b.x - a.x, b.y - a.y);\n lengths.push(segLen);\n totalLength += segLen;\n }\n\n this._cachedOutline = { points, lengths, totalLength };\n return this._cachedOutline;\n }\n\n private localToWorld(p: Point): Point {\n return { x: p.x + this._x, y: p.y + this._y };\n }\n\n override getConnectionPointAtOutlineParam(param: number): Point {\n const sample = this.getOutlineSample();\n if (!sample) return super.getConnectionPointAtOutlineParam(param);\n const { points, lengths, totalLength } = sample;\n let s = ((param % 1) + 1) % 1 * totalLength;\n\n for (let i = 0; i < OUTLINE_SAMPLE_COUNT; i++) {\n const segLen = lengths[i]!;\n if (s < segLen) {\n const a = points[i]!;\n const b = points[(i + 1) % OUTLINE_SAMPLE_COUNT]!;\n const t = segLen > 0 ? s / segLen : 0;\n const local = {\n x: a.x + t * (b.x - a.x),\n y: a.y + t * (b.y - a.y),\n };\n return this.localToWorld(local);\n }\n s -= segLen;\n }\n return this.localToWorld(points[0]!);\n }\n\n override getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const sample = this.getOutlineSample();\n if (!sample) return super.getClosestPointOnOutline(target);\n const { points, lengths, totalLength } = sample;\n const localTarget = { x: target.x - this._x, y: target.y - this._y };\n\n const projectSegment = (\n ax: number,\n ay: number,\n bx: number,\n by: number,\n segLen: number,\n segStartParam: number\n ): { point: Point; param: number; distSq: number } => {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n let t = lenSq > 0 ? ((localTarget.x - ax) * dx + (localTarget.y - ay) * dy) / lenSq : 0;\n t = Math.max(0, Math.min(1, t));\n const px = ax + t * dx;\n const py = ay + t * dy;\n const distSq = (localTarget.x - px) ** 2 + (localTarget.y - py) ** 2;\n const param = segStartParam + (segLen > 0 ? (t * segLen) / totalLength : 0);\n return { point: { x: px, y: py }, param, distSq };\n };\n\n let best = projectSegment(\n points[0]!.x,\n points[0]!.y,\n points[1]!.x,\n points[1]!.y,\n lengths[0]!,\n 0\n );\n let segStartParam = lengths[0]! / totalLength;\n\n for (let i = 1; i < OUTLINE_SAMPLE_COUNT; i++) {\n const a = points[i]!;\n const b = points[(i + 1) % OUTLINE_SAMPLE_COUNT]!;\n const segLen = lengths[i]!;\n const r = projectSegment(a.x, a.y, b.x, b.y, segLen, segStartParam);\n if (r.distSq < best.distSq) best = r;\n segStartParam += segLen / totalLength;\n }\n\n const param = ((best.param % 1) + 1) % 1;\n return { point: this.localToWorld(best.point), param };\n }\n\n protected override getOutlinePointToward(target: Point): Point {\n if (typeof document === 'undefined') {\n return super.getOutlinePointToward(target);\n }\n\n const center = this.getCenter();\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n\n if (Math.abs(dx) < 1e-9 && Math.abs(dy) < 1e-9) {\n return center;\n }\n\n const localCenter = { x: this._width / 2, y: this._height / 2 };\n const localDx = target.x - center.x;\n const localDy = target.y - center.y;\n\n const boundary = this.getBoundaryPointOnRay(localCenter.x, localCenter.y, localDx, localDy);\n return this.localToWorld(boundary);\n }\n\n private getBoundaryPointOnRay(ox: number, oy: number, dx: number, dy: number): Point {\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) return { x: ox, y: oy };\n const ux = dx / len;\n const uy = dy / len;\n const maxR = Math.max(this._width, this._height) * 2;\n const path = this.getPath();\n\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : null;\n const ctx = canvas?.getContext('2d');\n if (!ctx) return { x: ox, y: oy };\n const isInside = (lx: number, ly: number): boolean => ctx.isPointInPath(path, lx, ly);\n\n let lo = 0;\n let hi = maxR;\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2;\n const px = ox + ux * mid;\n const py = oy + uy * mid;\n if (isInside(px, py)) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n const t = (lo + hi) / 2;\n return { x: ox + ux * t, y: oy + uy * t };\n }\n\n override hitTest(point: Point): boolean {\n // Create an offscreen canvas for hit testing\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const ctx = canvas.getContext('2d');\n\n if (ctx === null) {\n // Fallback to bounding box\n return super.hitTest(point);\n }\n\n // Translate point to local coordinates\n const localX = point.x - this._x;\n const localY = point.y - this._y;\n\n const path = this.getPath();\n if (ctx.isPointInPath(path, localX, localY)) {\n return true;\n }\n\n ctx.lineWidth = NODE_HITBOX_PADDING * 2;\n return ctx.isPointInStroke(path, localX, localY);\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.save();\n ctx.translate(this._x, this._y);\n\n const path = this.getPath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill(path);\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke(path);\n\n ctx.restore();\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n\n/**\n * Helper function to create common shapes as Path2D\n */\nexport const ShapeFactories = {\n /**\n * Hexagon shape\n */\n hexagon: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const inset = width * 0.25;\n\n path.moveTo(inset, 0);\n path.lineTo(width - inset, 0);\n path.lineTo(width, height / 2);\n path.lineTo(width - inset, height);\n path.lineTo(inset, height);\n path.lineTo(0, height / 2);\n path.closePath();\n\n return path;\n },\n\n /**\n * Parallelogram shape\n */\n parallelogram: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const skew = width * 0.2;\n\n path.moveTo(skew, 0);\n path.lineTo(width, 0);\n path.lineTo(width - skew, height);\n path.lineTo(0, height);\n path.closePath();\n\n return path;\n },\n\n /**\n * Cylinder shape (for databases)\n */\n cylinder: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const ellipseHeight = height * 0.15;\n\n // Top ellipse\n path.ellipse(width / 2, ellipseHeight, width / 2, ellipseHeight, 0, 0, Math.PI * 2);\n\n // Body\n path.moveTo(0, ellipseHeight);\n path.lineTo(0, height - ellipseHeight);\n path.ellipse(width / 2, height - ellipseHeight, width / 2, ellipseHeight, 0, Math.PI, 0);\n path.lineTo(width, ellipseHeight);\n\n return path;\n },\n\n /**\n * Document shape\n */\n document: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const waveHeight = height * 0.1;\n\n path.moveTo(0, 0);\n path.lineTo(width, 0);\n path.lineTo(width, height - waveHeight);\n path.quadraticCurveTo(width * 0.75, height, width * 0.5, height - waveHeight);\n path.quadraticCurveTo(width * 0.25, height - waveHeight * 2, 0, height - waveHeight);\n path.closePath();\n\n return path;\n },\n\n /**\n * SVG path strings for export. Use with CustomShapeNodeOptions.svgPath.\n */\n svg: {\n hexagon: (w: number, h: number): string =>\n `M ${w * 0.25} 0 L ${w * 0.75} 0 L ${w} ${h / 2} L ${w * 0.75} ${h} L ${w * 0.25} ${h} L 0 ${h / 2} Z`,\n parallelogram: (w: number, h: number): string => {\n const skew = w * 0.2;\n return `M ${skew} 0 L ${w} 0 L ${w - skew} ${h} L 0 ${h} Z`;\n },\n cylinder: (w: number, h: number): string => {\n const eh = h * 0.15;\n const rx = w / 2;\n return `M 0 ${eh} L 0 ${h - eh} A ${rx} ${eh} 0 0 1 ${w} ${h - eh} L ${w} ${eh} A ${rx} ${eh} 0 0 1 0 ${eh} Z`;\n },\n document: (w: number, h: number): string => {\n const wh = h * 0.1;\n return `M 0 0 L ${w} 0 L ${w} ${h - wh} Q ${w * 0.75} ${h} ${w * 0.5} ${h - wh} Q ${w * 0.25} ${h - wh * 2} 0 ${h - wh} Z`;\n },\n /** Chamfered rectangle (cut corners) */\n chamfered: (w: number, h: number): string => {\n const cut = Math.max(6, Math.min(20, w * 0.18, h * 0.18));\n return `M ${cut} 0 L ${w - cut} 0 L ${w} ${cut} L ${w} ${h - cut} L ${w - cut} ${h} L ${cut} ${h} L 0 ${h - cut} L 0 ${cut} Z`;\n },\n },\n};\n","import type { EdgeStyle, ElementState, ElementStyle, NodeStyle, TextStyle } from '@/types';\n\n/**\n * Theme definition\n */\nexport interface Theme {\n name: string;\n colors: {\n background: string;\n grid: string;\n selection: string;\n connectionPreview: string;\n };\n node: {\n default: NodeStyle;\n hover: NodeStyle;\n selected: NodeStyle;\n dragging: NodeStyle;\n };\n edge: {\n default: EdgeStyle;\n hover: EdgeStyle;\n selected: EdgeStyle;\n };\n text: TextStyle;\n port: {\n default: { color: string; radius: number };\n hover: { color: string; radius: number };\n };\n group: {\n default: ElementStyle;\n selected: ElementStyle;\n };\n}\n\n/**\n * Style class definition\n */\nexport interface StyleClass {\n name: string;\n node?: Partial<NodeStyle>;\n edge?: Partial<EdgeStyle>;\n text?: Partial<TextStyle>;\n port?: Partial<{ color: string; radius: number }>;\n group?: Partial<ElementStyle>;\n}\n\nconst DEFAULT_THEME: Theme = {\n name: 'default',\n colors: {\n background: '#ffffff',\n grid: '#e5e5e5',\n selection: 'rgba(59, 130, 246, 0.1)',\n connectionPreview: '#3b82f6',\n },\n node: {\n default: {\n fillColor: '#ffffff',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n hover: {\n fillColor: '#f5f5f5',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n selected: {\n fillColor: '#ffffff',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n dragging: {\n fillColor: '#f0f0f0',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 0.8,\n cornerRadius: 4,\n },\n },\n edge: {\n default: {\n strokeColor: '#666666',\n strokeWidth: 2,\n opacity: 1,\n },\n hover: {\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n },\n selected: {\n strokeColor: '#3b82f6',\n strokeWidth: 3,\n opacity: 1,\n },\n },\n text: {\n font: '14px sans-serif',\n fontSize: 14,\n fontFamily: 'sans-serif',\n fontWeight: 'normal',\n color: '#333333',\n align: 'center',\n baseline: 'middle',\n },\n port: {\n default: { color: '#666666', radius: 6 },\n hover: { color: '#3b82f6', radius: 7 },\n },\n group: {\n default: {\n fillColor: 'rgba(200, 200, 200, 0.2)',\n strokeColor: '#999999',\n strokeWidth: 1,\n opacity: 1,\n },\n selected: {\n fillColor: 'rgba(59, 130, 246, 0.1)',\n strokeColor: '#3b82f6',\n strokeWidth: 2,\n opacity: 1,\n },\n },\n};\n\nconst DARK_THEME: Theme = {\n name: 'dark',\n colors: {\n background: '#1a1a1a',\n grid: '#333333',\n selection: 'rgba(99, 102, 241, 0.2)',\n connectionPreview: '#6366f1',\n },\n node: {\n default: {\n fillColor: '#2d2d2d',\n strokeColor: '#555555',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n hover: {\n fillColor: '#3d3d3d',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n selected: {\n fillColor: '#2d2d2d',\n strokeColor: '#555555',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n dragging: {\n fillColor: '#404040',\n strokeColor: '#555555',\n strokeWidth: 2,\n opacity: 0.8,\n cornerRadius: 4,\n },\n },\n edge: {\n default: {\n strokeColor: '#888888',\n strokeWidth: 2,\n opacity: 1,\n },\n hover: {\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n },\n selected: {\n strokeColor: '#818cf8',\n strokeWidth: 3,\n opacity: 1,\n },\n },\n text: {\n font: '14px sans-serif',\n fontSize: 14,\n fontFamily: 'sans-serif',\n fontWeight: 'normal',\n color: '#e0e0e0',\n align: 'center',\n baseline: 'middle',\n },\n port: {\n default: { color: '#888888', radius: 6 },\n hover: { color: '#6366f1', radius: 7 },\n },\n group: {\n default: {\n fillColor: 'rgba(100, 100, 100, 0.2)',\n strokeColor: '#666666',\n strokeWidth: 1,\n opacity: 1,\n },\n selected: {\n fillColor: 'rgba(99, 102, 241, 0.2)',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n },\n },\n};\n\n/**\n * Manages styles and themes\n */\nexport class StyleManager {\n private _theme: Theme;\n private _classes = new Map<string, StyleClass>();\n private _builtInThemes = new Map<string, Theme>([\n ['default', DEFAULT_THEME],\n ['dark', DARK_THEME],\n ]);\n\n constructor(theme?: Theme | string) {\n if (theme === undefined) {\n this._theme = DEFAULT_THEME;\n } else if (typeof theme === 'string') {\n this._theme = this._builtInThemes.get(theme) ?? DEFAULT_THEME;\n } else {\n this._theme = theme;\n }\n }\n\n /**\n * Current theme\n */\n get theme(): Theme {\n return this._theme;\n }\n\n /**\n * Set the current theme\n */\n setTheme(theme: Theme | string): void {\n if (typeof theme === 'string') {\n const builtIn = this._builtInThemes.get(theme);\n if (builtIn !== undefined) {\n this._theme = builtIn;\n }\n } else {\n this._theme = theme;\n }\n }\n\n /**\n * Register a custom theme\n */\n registerTheme(theme: Theme): void {\n this._builtInThemes.set(theme.name, theme);\n }\n\n /**\n * Get all available theme names\n */\n getThemeNames(): string[] {\n return Array.from(this._builtInThemes.keys());\n }\n\n /**\n * Register a style class\n */\n registerClass(styleClass: StyleClass): void {\n this._classes.set(styleClass.name, styleClass);\n }\n\n /**\n * Get a style class\n */\n getClass(name: string): StyleClass | undefined {\n return this._classes.get(name);\n }\n\n /**\n * Get all registered classes\n */\n getClasses(): StyleClass[] {\n return Array.from(this._classes.values());\n }\n\n /**\n * Get node style for a state\n */\n getNodeStyle(state: ElementState, className?: string): NodeStyle {\n const baseStyle = this.getBaseNodeStyle(state);\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.node !== undefined) {\n return { ...baseStyle, ...styleClass.node };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get edge style for a state\n */\n getEdgeStyle(state: ElementState, className?: string): EdgeStyle {\n const baseStyle = this.getBaseEdgeStyle(state);\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.edge !== undefined) {\n return { ...baseStyle, ...styleClass.edge };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get text style\n */\n getTextStyle(className?: string): TextStyle {\n const baseStyle = this._theme.text;\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.text !== undefined) {\n return { ...baseStyle, ...styleClass.text };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get group style for a state\n */\n getGroupStyle(selected: boolean, className?: string): ElementStyle {\n const baseStyle = selected ? this._theme.group.selected : this._theme.group.default;\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.group !== undefined) {\n return { ...baseStyle, ...styleClass.group };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get port style\n */\n getPortStyle(hovered: boolean, className?: string): { color: string; radius: number } {\n const baseStyle = hovered ? this._theme.port.hover : this._theme.port.default;\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.port !== undefined) {\n return { ...baseStyle, ...styleClass.port };\n }\n }\n\n return baseStyle;\n }\n\n private getBaseNodeStyle(state: ElementState): NodeStyle {\n switch (state) {\n case 'hover':\n return this._theme.node.hover;\n case 'selected':\n return this._theme.node.selected;\n case 'dragging':\n return this._theme.node.dragging;\n default:\n return this._theme.node.default;\n }\n }\n\n private getBaseEdgeStyle(state: ElementState): EdgeStyle {\n switch (state) {\n case 'hover':\n return this._theme.edge.hover;\n case 'selected':\n return this._theme.edge.selected;\n default:\n return this._theme.edge.default;\n }\n }\n}\n\n// Export default themes\nexport { DEFAULT_THEME, DARK_THEME };\n","/**\n * Omit properties from an object that have default values\n * @param obj - The object to filter\n * @param defaults - Default values to compare against\n * @returns New object with only non-default values\n */\nexport function omitDefaultValues<T extends Record<string, unknown>>(\n obj: T,\n defaults: Partial<T>\n): Partial<T> {\n const result: Partial<T> = {};\n\n for (const key of Object.keys(obj) as (keyof T)[]) {\n const objValue = obj[key];\n const defaultValue = defaults[key];\n\n // Skip if value equals default\n if (objValue === defaultValue) {\n continue;\n }\n\n // Handle arrays - compare by value\n if (Array.isArray(objValue) && Array.isArray(defaultValue)) {\n if (objValue.length === defaultValue.length) {\n const arraysEqual = objValue.every((val, idx) => val === defaultValue[idx]);\n if (arraysEqual) {\n continue;\n }\n }\n }\n\n // Handle objects - compare shallow\n if (\n typeof objValue === 'object' &&\n objValue !== null &&\n typeof defaultValue === 'object' &&\n defaultValue !== null\n ) {\n if (!Array.isArray(objValue) && !Array.isArray(defaultValue)) {\n const objKeys = Object.keys(objValue);\n const defaultKeys = Object.keys(defaultValue);\n if (objKeys.length === defaultKeys.length) {\n const objectsEqual = objKeys.every(\n (k) => (objValue as Record<string, unknown>)[k] === (defaultValue as Record<string, unknown>)[k]\n );\n if (objectsEqual) {\n continue;\n }\n }\n }\n }\n\n result[key] = objValue;\n }\n\n return result;\n}\n\n/**\n * Check if an object has any non-default values\n * @param obj - The object to check\n * @param defaults - Default values to compare against\n * @returns True if object has non-default values\n */\nexport function hasNonDefaultValues<T extends Record<string, unknown>>(\n obj: T,\n defaults: Partial<T>\n): boolean {\n return Object.keys(omitDefaultValues(obj, defaults)).length > 0;\n}\n\n/**\n * Omit undefined and null values from an object\n * @param obj - The object to filter\n * @returns New object with only defined values\n */\nexport function omitEmptyValues<T extends Record<string, unknown>>(\n obj: T\n): Partial<T> {\n const result: Partial<T> = {};\n\n for (const key of Object.keys(obj) as (keyof T)[]) {\n const value = obj[key];\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Omit empty arrays and empty objects from an object\n * @param obj - The object to filter\n * @returns New object with only non-empty values\n */\nexport function omitEmptyCollections<T extends Record<string, unknown>>(\n obj: T\n): Partial<T> {\n const result: Partial<T> = {};\n\n for (const key of Object.keys(obj) as (keyof T)[]) {\n const value = obj[key];\n if (value === undefined || value === null) {\n continue;\n }\n if (Array.isArray(value) && value.length === 0) {\n continue;\n }\n if (typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0) {\n continue;\n }\n result[key] = value;\n }\n\n return result;\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type {\n DiagramData,\n SerializedNode,\n SerializedEdge,\n SerializedGroup,\n SerializedPort,\n SerializedNodeIcon,\n SerializedAnchorPoints,\n SerializedTextLabel,\n} from '@/types';\nimport { omitDefaultValues, omitEmptyValues, hasNonDefaultValues } from './omitDefaults';\n\nconst SERIALIZER_VERSION = '1.1';\n\n/**\n * Validation error during deserialization\n */\nexport class SerializerValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SerializerValidationError';\n }\n}\n\nexport interface NodeFactory {\n (data: SerializedNode): Node;\n}\n\nexport interface EdgeFactory {\n (data: SerializedEdge): Edge;\n}\n\nexport interface GroupFactory {\n (data: SerializedGroup): Group;\n}\n\nexport interface SerializerOptions {\n nodeFactory: NodeFactory;\n edgeFactory: EdgeFactory;\n groupFactory?: GroupFactory;\n}\n\n/**\n * Serializes and deserializes diagram data\n */\nexport class Serializer {\n private renderer: DiagramRenderer;\n private readonly nodeFactory: NodeFactory;\n private readonly edgeFactory: EdgeFactory;\n private readonly groupFactory?: GroupFactory;\n\n constructor(renderer: DiagramRenderer, options: SerializerOptions) {\n this.renderer = renderer;\n this.nodeFactory = options.nodeFactory;\n this.edgeFactory = options.edgeFactory;\n this.groupFactory = options.groupFactory;\n }\n\n /**\n * Serialize the diagram to JSON-compatible data\n */\n serialize(): DiagramData {\n const styleManager = this.renderer.getStyleManager();\n const nodes: SerializedNode[] = [];\n const edges: SerializedEdge[] = [];\n const groups: SerializedGroup[] = [];\n\n // Serialize nodes\n for (const node of this.renderer.nodes.values()) {\n nodes.push(this.serializeNode(node));\n }\n\n // Serialize edges\n for (const edge of this.renderer.edges.values()) {\n edges.push(this.serializeEdge(edge));\n }\n\n // Serialize groups\n for (const group of this.renderer.groups.values()) {\n groups.push(this.serializeGroup(group));\n }\n\n return {\n version: SERIALIZER_VERSION,\n nodes,\n edges,\n groups,\n viewport: { ...this.renderer.viewport },\n theme: styleManager?.theme,\n styleClasses: styleManager?.getClasses(),\n };\n }\n\n /**\n * Serialize to JSON string\n */\n toJSON(pretty = false): string {\n const data = this.serialize();\n return pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);\n }\n\n /**\n * Deserialize data and populate the diagram\n */\n deserialize(data: DiagramData): void {\n // Validate data before deserialization\n this.validate(data);\n\n // Clear existing content\n this.clear();\n\n // Restore viewport\n this.renderer.viewport = data.viewport;\n\n // Restore theme and classes if available\n const styleManager = this.renderer.getStyleManager();\n if (styleManager && data.theme) {\n styleManager.setTheme(data.theme);\n }\n if (styleManager && data.styleClasses) {\n for (const styleClass of data.styleClasses) {\n styleManager.registerClass(styleClass);\n }\n }\n\n // Create nodes\n for (const nodeData of data.nodes) {\n const node = this.nodeFactory(nodeData);\n this.renderer.addNode(node);\n }\n\n // Create edges\n for (const edgeData of data.edges) {\n const edge = this.edgeFactory(edgeData);\n this.renderer.addEdge(edge);\n }\n\n // Create groups\n if (this.groupFactory !== undefined) {\n for (const groupData of data.groups) {\n const group = this.groupFactory(groupData);\n this.renderer.addGroup(group);\n }\n }\n\n this.renderer.markDirty();\n }\n\n /**\n * Validate diagram data before deserialization\n */\n private validate(data: DiagramData): void {\n if (!data.version) {\n throw new SerializerValidationError('Missing version field in diagram data');\n }\n\n if (!Array.isArray(data.nodes)) {\n throw new SerializerValidationError('Invalid or missing nodes array');\n }\n\n if (!Array.isArray(data.edges)) {\n throw new SerializerValidationError('Invalid or missing edges array');\n }\n\n // Build a set of node IDs for edge validation\n const nodeIds = new Set(data.nodes.map((n) => n.id));\n\n // Validate edges reference existing nodes\n for (const edge of data.edges) {\n if (!nodeIds.has(edge.from.nodeId)) {\n throw new SerializerValidationError(\n `Edge \"${edge.id}\" references non-existent source node \"${edge.from.nodeId}\"`\n );\n }\n if (!nodeIds.has(edge.to.nodeId)) {\n throw new SerializerValidationError(\n `Edge \"${edge.id}\" references non-existent target node \"${edge.to.nodeId}\"`\n );\n }\n }\n }\n\n /**\n * Parse JSON string and deserialize\n */\n fromJSON(json: string): void {\n const data = JSON.parse(json) as DiagramData;\n this.deserialize(data);\n }\n\n /**\n * Clear the diagram\n */\n clear(): void {\n // Remove all edges first (to avoid orphaned references)\n for (const edge of this.renderer.edges.values()) {\n this.renderer.removeEdge(edge.id);\n }\n\n // Remove all nodes\n for (const node of this.renderer.nodes.values()) {\n this.renderer.removeNode(node.id);\n }\n\n // Remove all groups\n for (const group of this.renderer.groups.values()) {\n this.renderer.removeGroup(group.id);\n }\n }\n\n private serializeNode(node: Node): SerializedNode {\n const ports: SerializedPort[] = node.ports.map((port) => ({\n id: port.id,\n type: port.type,\n position: port.position,\n styleClass: port.styleClass,\n }));\n\n // Serialize label - full TextLabel if it has more than just text\n let label: string | SerializedTextLabel | undefined;\n if (node.label) {\n const labelDefaults = { padding: 8, margin: 0, style: {}, maxWidth: undefined, styleClass: undefined };\n const labelData = {\n text: node.label.text,\n style: node.label.style,\n maxWidth: node.label.maxWidth,\n padding: node.label.padding,\n margin: node.label.margin,\n styleClass: node.label.styleClass,\n };\n const hasExtendedOptions = hasNonDefaultValues(labelData, labelDefaults);\n\n if (hasExtendedOptions) {\n label = omitEmptyValues({\n text: node.label.text,\n style: Object.keys(node.label.style).length > 0 ? node.label.style : undefined,\n maxWidth: node.label.maxWidth,\n padding: node.label.padding !== 8 ? node.label.padding : undefined,\n margin: node.label.margin !== 0 ? node.label.margin : undefined,\n styleClass: node.label.styleClass,\n }) as SerializedTextLabel | undefined;\n } else {\n label = node.label.text;\n }\n }\n\n // Serialize icon\n let icon: SerializedNodeIcon | undefined;\n if (node.icon) {\n const opts = node.icon.options;\n const source = typeof opts.source === 'string' ? opts.source : undefined;\n if (source) {\n icon = {\n source,\n width: opts.width,\n height: opts.height,\n fit: opts.fit,\n placement: opts.placement,\n scaleWithBounds: opts.scaleWithBounds,\n padding: opts.padding,\n margin: opts.margin,\n gap: opts.gap,\n opacity: opts.opacity,\n align: opts.align,\n verticalAlign: opts.verticalAlign,\n offsetX: opts.offsetX,\n offsetY: opts.offsetY,\n };\n }\n }\n\n // Serialize anchor points if non-default\n let anchorPoints: SerializedAnchorPoints | undefined;\n const ap = node.anchorPoints;\n const anchorDefaults = { top: 1, right: 1, bottom: 1, left: 1 };\n const anchorData = { top: ap.top, right: ap.right, bottom: ap.bottom, left: ap.left };\n if (hasNonDefaultValues(anchorData, anchorDefaults)) {\n anchorPoints = omitDefaultValues(anchorData, anchorDefaults);\n }\n\n return {\n id: node.id,\n type: node.typeName,\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n style: node.style,\n styleClass: node.styleClass,\n label,\n labelStyleClass: typeof label === 'string' ? node.label?.styleClass : undefined,\n labelPlacement: node.labelPlacement !== 'auto' ? node.labelPlacement : undefined,\n icon,\n anchorPoints,\n ports: ports.length > 0 ? ports : undefined,\n data: Object.keys(node.data).length > 0 ? node.data : undefined,\n };\n }\n\n private serializeEdge(edge: Edge): SerializedEdge {\n return {\n id: edge.id,\n from: edge.from,\n to: edge.to,\n type: edge.type,\n controlPoints: edge.controlPoints,\n arrowType: edge.arrowType,\n startMarker: edge.startMarker,\n endMarker: edge.endMarker,\n style: edge.style,\n styleClass: edge.styleClass,\n label: edge.label?.text,\n labelStyleClass: edge.label?.styleClass,\n labelOffset: edge.labelOffset !== 0 ? edge.labelOffset : undefined,\n labelBackground: edge.labelBackground,\n data: Object.keys(edge.data).length > 0 ? edge.data : undefined,\n };\n }\n\n private serializeGroup(group: Group): SerializedGroup {\n return {\n id: group.id,\n childIds: group.children.map((c) => c.id),\n style: group.style,\n styleClass: group.styleClass,\n label: group.label,\n data: Object.keys(group.data).length > 0 ? group.data : undefined,\n };\n }\n}\n","export function downloadBlob(filename: string, blob: Blob): void {\n const url = URL.createObjectURL(blob);\n\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n URL.revokeObjectURL(url);\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\n\nexport interface ElementIteratorOptions {\n /** Include only visible elements (default: false) */\n visibleOnly?: boolean;\n /** Include groups in iteration (default: true) */\n includeGroups?: boolean;\n /** Include edges in iteration (default: true) */\n includeEdges?: boolean;\n /** Include nodes in iteration (default: true) */\n includeNodes?: boolean;\n}\n\n/**\n * Get all diagram elements in render order (groups -> edges -> nodes)\n */\nexport function* getAllElements(\n renderer: DiagramRenderer,\n options: ElementIteratorOptions = {}\n): IterableIterator<Group | Edge | Node> {\n const {\n visibleOnly = false,\n includeGroups = true,\n includeEdges = true,\n includeNodes = true,\n } = options;\n\n if (includeGroups) {\n for (const group of renderer.groups.values()) {\n if (!visibleOnly || group.visible) {\n yield group;\n }\n }\n }\n\n if (includeEdges) {\n for (const edge of renderer.edges.values()) {\n if (!visibleOnly || edge.visible) {\n yield edge;\n }\n }\n }\n\n if (includeNodes) {\n for (const node of renderer.nodes.values()) {\n if (!visibleOnly || node.visible) {\n yield node;\n }\n }\n }\n}\n\n/**\n * Get only visible elements in render order\n */\nexport function* getVisibleElements(\n renderer: DiagramRenderer\n): IterableIterator<Group | Edge | Node> {\n yield* getAllElements(renderer, { visibleOnly: true });\n}\n\n/**\n * Get only nodes\n */\nexport function* getNodes(\n renderer: DiagramRenderer,\n options: { visibleOnly?: boolean } = {}\n): IterableIterator<Node> {\n const { visibleOnly = false } = options;\n for (const node of renderer.nodes.values()) {\n if (!visibleOnly || node.visible) {\n yield node;\n }\n }\n}\n\n/**\n * Get only edges\n */\nexport function* getEdges(\n renderer: DiagramRenderer,\n options: { visibleOnly?: boolean } = {}\n): IterableIterator<Edge> {\n const { visibleOnly = false } = options;\n for (const edge of renderer.edges.values()) {\n if (!visibleOnly || edge.visible) {\n yield edge;\n }\n }\n}\n\n/**\n * Get only groups\n */\nexport function* getGroups(\n renderer: DiagramRenderer,\n options: { visibleOnly?: boolean } = {}\n): IterableIterator<Group> {\n const { visibleOnly = false } = options;\n for (const group of renderer.groups.values()) {\n if (!visibleOnly || group.visible) {\n yield group;\n }\n }\n}\n\n/**\n * Apply a function to all elements\n */\nexport function forEachElement(\n renderer: DiagramRenderer,\n fn: (element: Group | Edge | Node) => void,\n options: ElementIteratorOptions = {}\n): void {\n for (const element of getAllElements(renderer, options)) {\n fn(element);\n }\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport { applyStyleManagerToElements } from './style';\nimport { getContentBounds } from './contentBounds';\nimport { downloadBlob } from './download';\nimport { getAllElements } from './elementIterator';\n\nexport interface ExportOptions {\n scale?: number;\n backgroundColor?: string;\n padding?: number;\n format?: 'png' | 'jpeg';\n quality?: number;\n}\n\n/**\n * Exports diagram to image formats\n */\nexport class ImageExporter {\n private renderer: DiagramRenderer;\n\n constructor(renderer: DiagramRenderer) {\n this.renderer = renderer;\n }\n\n /**\n * Export to PNG blob\n */\n async exportPNG(options: ExportOptions = {}): Promise<Blob> {\n return this.export({ ...options, format: 'png' });\n }\n\n /**\n * Export to JPEG blob\n */\n async exportJPEG(options: ExportOptions = {}): Promise<Blob> {\n return this.export({ ...options, format: 'jpeg' });\n }\n\n /**\n * Export to data URL\n */\n async exportDataURL(options: ExportOptions = {}): Promise<string> {\n const blob = await this.export(options);\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (): void => resolve(reader.result as string);\n reader.onerror = (): void => reject(new Error('Failed to read blob'));\n reader.readAsDataURL(blob);\n });\n }\n\n /**\n * Download as file\n */\n async download(filename: string, options: ExportOptions = {}): Promise<void> {\n const blob = await this.export(options);\n downloadBlob(filename, blob);\n }\n\n private async export(options: ExportOptions = {}): Promise<Blob> {\n const scale = options.scale ?? 2;\n const backgroundColor = options.backgroundColor ?? '#ffffff';\n const padding = options.padding ?? 20;\n const format = options.format ?? 'png';\n const quality = options.quality ?? 0.92;\n\n // Calculate content bounds\n const bounds = getContentBounds({ nodes: this.renderer.nodes.values() });\n if (bounds === null) {\n // Empty diagram, return small blank image\n return this.createBlankImage(100, 100, backgroundColor, format, quality);\n }\n\n // Calculate export dimensions\n const width = (bounds.width + padding * 2) * scale;\n const height = (bounds.height + padding * 2) * scale;\n\n // Create export canvas\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (ctx === null) {\n throw new Error('Failed to get canvas context');\n }\n\n // Fill background\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n\n // Apply transforms\n ctx.scale(scale, scale);\n ctx.translate(-bounds.x + padding, -bounds.y + padding);\n\n // Apply StyleManager if present before rendering\n applyStyleManagerToElements(\n this.renderer.getStyleManager(),\n this.renderer.groups.values(),\n this.renderer.edges.values(),\n this.renderer.nodes.values()\n );\n\n // Render elements (in correct order: groups -> edges -> nodes)\n for (const element of getAllElements(this.renderer, { visibleOnly: true })) {\n element.render(ctx);\n }\n\n // Convert to blob\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob !== null) {\n resolve(blob);\n } else {\n reject(new Error('Failed to create blob'));\n }\n },\n `image/${format}`,\n quality\n );\n });\n }\n\n private createBlankImage(\n width: number,\n height: number,\n backgroundColor: string,\n format: string,\n quality: number\n ): Promise<Blob> {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (ctx !== null) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n }\n\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob !== null) {\n resolve(blob);\n } else {\n reject(new Error('Failed to create blob'));\n }\n },\n `image/${format}`,\n quality\n );\n });\n }\n\n}\n","import type { ArrowMarkerConfig, Point } from '@/types';\nimport { ARROW_ANGLE } from '@/constants';\n\nexport interface MarkerPoints {\n /** Start point of marker (attached to edge) */\n from: Point;\n /** End point of marker (tip) */\n to: Point;\n}\n\n/**\n * Calculate marker points based on edge path\n */\nexport function calculateMarkerPoints(\n path: readonly Point[],\n position: 'start' | 'end',\n type: 'bezier' | 'straight' | 'polyline' | 'editable-polyline'\n): MarkerPoints | null {\n if (path.length < 2) {\n return null;\n }\n\n if (type === 'bezier' && path.length >= 4) {\n const epsilon = 0.001;\n const isSame = (a: Point, b: Point): boolean =>\n Math.abs(a.x - b.x) < epsilon && Math.abs(a.y - b.y) < epsilon;\n\n if (position === 'end') {\n const endIndex = path.length - 1;\n const endPoint = path[endIndex]!;\n let from = path[endIndex - 1]!;\n if (isSame(from, endPoint)) {\n from = path[endIndex - 2]!;\n if (isSame(from, endPoint)) {\n from = path[0]!;\n }\n }\n return { from, to: endPoint };\n }\n\n const start = path[0]!;\n let next = path[1]!;\n if (isSame(next, start)) {\n next = path[2]!;\n if (isSame(next, start)) {\n next = path[path.length - 1]!;\n }\n }\n return { from: next, to: start };\n }\n\n if (position === 'end') {\n return { from: path[path.length - 2]!, to: path[path.length - 1]! };\n }\n\n return { from: path[1]!, to: path[0]! };\n}\n\n/**\n * Calculate arrow marker vertex points\n */\nexport function calculateArrowMarkerPoints(\n to: Point,\n angle: number,\n size: number\n): { tip: Point; left: Point; right: Point } {\n const left = {\n x: to.x - size * Math.cos(angle - ARROW_ANGLE),\n y: to.y - size * Math.sin(angle - ARROW_ANGLE),\n };\n const right = {\n x: to.x - size * Math.cos(angle + ARROW_ANGLE),\n y: to.y - size * Math.sin(angle + ARROW_ANGLE),\n };\n return { tip: to, left, right };\n}\n\n/**\n * Calculate diamond marker vertex points\n */\nexport function calculateDiamondMarkerPoints(\n to: Point,\n angle: number,\n size: number\n): Point[] {\n const halfLength = size / 2;\n const halfWidth = size * 0.3;\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n return [\n { x: to.x, y: to.y }, // tip\n {\n x: to.x - halfLength * cos + halfWidth * sin,\n y: to.y - halfLength * sin - halfWidth * cos,\n },\n { x: to.x - size * cos, y: to.y - size * sin }, // back\n {\n x: to.x - halfLength * cos - halfWidth * sin,\n y: to.y - halfLength * sin + halfWidth * cos,\n },\n ];\n}\n\n/**\n * Calculate circle marker center\n */\nexport function calculateCircleMarkerCenter(\n to: Point,\n angle: number,\n size: number\n): Point {\n return {\n x: to.x - size * Math.cos(angle),\n y: to.y - size * Math.sin(angle),\n };\n}\n\n/**\n * Get marker length (how much to shorten the edge line)\n */\nexport function getMarkerLength(config: ArrowMarkerConfig): number {\n const size = config.size ?? 12;\n switch (config.type) {\n case 'arrow':\n return size * Math.cos(ARROW_ANGLE);\n case 'open':\n return 0;\n case 'diamond':\n return size;\n case 'circle':\n return size * 2;\n default:\n return 0;\n }\n}\n\n/**\n * Generate SVG path for arrow marker\n */\nexport function generateSvgArrowMarker(\n to: Point,\n angle: number,\n size: number,\n fill: string,\n fillOpacity: number,\n stroke: string\n): string {\n const { left, right } = calculateArrowMarkerPoints(to, angle, size);\n return `<path d=\"M ${to.x} ${to.y} L ${left.x} ${left.y} L ${right.x} ${right.y} Z\" fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"1\"/>`;\n}\n\n/**\n * Generate SVG path for open arrow marker\n */\nexport function generateSvgOpenArrowMarker(\n to: Point,\n angle: number,\n size: number,\n stroke: string\n): string {\n const { left, right } = calculateArrowMarkerPoints(to, angle, size);\n return `<path d=\"M ${to.x} ${to.y} L ${left.x} ${left.y} M ${to.x} ${to.y} L ${right.x} ${right.y}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>`;\n}\n\n/**\n * Generate SVG path for diamond marker\n */\nexport function generateSvgDiamondMarker(\n to: Point,\n angle: number,\n size: number,\n fill: string,\n fillOpacity: number,\n stroke: string\n): string {\n const points = calculateDiamondMarkerPoints(to, angle, size);\n return `<path d=\"M ${points[0]!.x} ${points[0]!.y} L ${points[1]!.x} ${points[1]!.y} L ${points[2]!.x} ${points[2]!.y} L ${points[3]!.x} ${points[3]!.y} Z\" fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"1\"/>`;\n}\n\n/**\n * Generate SVG circle marker\n */\nexport function generateSvgCircleMarker(\n to: Point,\n angle: number,\n size: number,\n fill: string,\n fillOpacity: number,\n stroke: string\n): string {\n const { x: cx, y: cy } = calculateCircleMarkerCenter(to, angle, size);\n return `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${size}\" fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"1\"/>`;\n}\n\n/**\n * Generate SVG path for any marker type\n */\nexport function generateSvgMarker(\n marker: ArrowMarkerConfig,\n from: Point,\n to: Point,\n edgeStroke: string\n): string {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const size = marker.size ?? 12;\n const stroke = marker.strokeColor ?? edgeStroke;\n const fill = marker.fillColor ?? stroke;\n const fillOpacity = marker.fillOpacity ?? 1;\n\n switch (marker.type) {\n case 'open':\n return generateSvgOpenArrowMarker(to, angle, size, stroke);\n case 'diamond':\n return generateSvgDiamondMarker(to, angle, size, fill, fillOpacity, stroke);\n case 'circle':\n return generateSvgCircleMarker(to, angle, size, fill, fillOpacity, stroke);\n case 'arrow':\n default:\n return generateSvgArrowMarker(to, angle, size, fill, fillOpacity, stroke);\n }\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Point } from '@/types';\nimport type { Edge } from '@/elements/Edge';\nimport type { Node } from '@/elements/Node';\nimport type { Group } from '@/elements/Group';\nimport type { ArrowMarkerConfig, TextStyle } from '@/types';\nimport type { NodeImageOptions, NodeImagePlacement } from '@/elements/NodeImage';\nimport { EDGE_LABEL_BACKGROUND_PADDING, EDGE_LABEL_BACKGROUND_RADIUS } from '@/constants';\nimport { applyStyleManagerToElements } from './style';\nimport { getContentBounds } from './contentBounds';\nimport { downloadBlob } from './download';\nimport { generateSvgMarker, calculateMarkerPoints } from './markers';\n\nexport interface SvgExportOptions {\n padding?: number;\n backgroundColor?: string;\n includeBackground?: boolean;\n /**\n * Global Y-offset override for edge labels in SVG export.\n * If omitted, exporter uses each edge's runtime labelOffset.\n */\n edgeLabelOffset?: number;\n}\n\n/**\n * Exports diagram to SVG\n */\nexport class SvgExporter {\n private renderer: DiagramRenderer;\n\n constructor(renderer: DiagramRenderer) {\n this.renderer = renderer;\n }\n\n exportSVG(options: SvgExportOptions = {}): string {\n const padding = options.padding ?? 20;\n const includeBackground = options.includeBackground ?? true;\n const backgroundColor = options.backgroundColor ?? '#ffffff';\n const edgeLabelOffset = options.edgeLabelOffset;\n\n const bounds = getContentBounds({\n nodes: this.renderer.nodes.values(),\n edges: this.renderer.edges.values(),\n groups: this.renderer.groups.values(),\n });\n if (bounds === null) {\n return this.createEmptySvg(100, 100, backgroundColor, includeBackground);\n }\n\n const width = bounds.width + padding * 2;\n const height = bounds.height + padding * 2;\n const offsetX = -bounds.x + padding;\n const offsetY = -bounds.y + padding;\n\n applyStyleManagerToElements(\n this.renderer.getStyleManager(),\n this.renderer.groups.values(),\n this.renderer.edges.values(),\n this.renderer.nodes.values()\n );\n\n const parts: string[] = [];\n const renderedEdges: string[] = [];\n parts.push(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">`\n );\n for (const edge of this.renderer.edges.values()) {\n if (edge.visible) {\n renderedEdges.push(this.renderEdge(edge, edgeLabelOffset));\n }\n }\n if (includeBackground) {\n parts.push(`<rect width=\"100%\" height=\"100%\" fill=\"${backgroundColor}\"/>`);\n }\n parts.push(`<g transform=\"translate(${offsetX}, ${offsetY})\">`);\n\n for (const group of this.renderer.groups.values()) {\n if (group.visible) {\n parts.push(this.renderGroup(group));\n }\n }\n\n for (const node of this.renderer.nodes.values()) {\n if (node.visible) {\n parts.push(this.renderNode(node));\n }\n }\n\n // Keep SVG layering aligned with canvas renderer: edges above nodes.\n parts.push(...renderedEdges);\n\n parts.push(`</g></svg>`);\n return parts.join('');\n }\n\n exportDataURL(options: SvgExportOptions = {}): string {\n const svg = this.exportSVG(options);\n const encoded = encodeURIComponent(svg);\n return `data:image/svg+xml;charset=utf-8,${encoded}`;\n }\n\n download(filename: string, options: SvgExportOptions = {}): void {\n const svg = this.exportSVG(options);\n const blob = new Blob([svg], { type: 'image/svg+xml' });\n downloadBlob(filename, blob);\n }\n\n private renderGroup(group: Group): string {\n const bounds = group.getBounds();\n const style = group.style;\n const fill = style.fillColor ?? 'rgba(200, 200, 200, 0.2)';\n const stroke = style.strokeColor ?? '#999999';\n const strokeWidth = style.strokeWidth ?? 1;\n const opacity = style.opacity ?? 1;\n\n const label = group.label\n ? `<text x=\"${bounds.x + 8}\" y=\"${bounds.y + 14}\" fill=\"#666666\" font-size=\"12\">${this.escapeText(\n group.label\n )}</text>`\n : '';\n\n return [\n `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`,\n ` fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" opacity=\"${opacity}\"`,\n ` stroke-dasharray=\"4 4\"/>`,\n label,\n ].join('');\n }\n\n private renderNode(node: Node): string {\n const bounds = node.getBounds();\n const style = node.style;\n const fill = style.fillColor ?? '#ffffff';\n const stroke = style.strokeColor ?? '#333333';\n const strokeWidth = style.strokeWidth ?? 2;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = (style.fillOpacity ?? 1) * baseOpacity;\n const strokeOpacity = (style.strokeOpacity ?? 1) * baseOpacity;\n const dash = style.lineDash?.length ? ` stroke-dasharray=\"${style.lineDash.join(' ')}\"` : '';\n const dashOffset =\n style.lineDashOffset !== undefined ? ` stroke-dashoffset=\"${style.lineDashOffset}\"` : '';\n\n let shape: string;\n switch (node.typeName) {\n case 'rectangle': {\n const radius = this.getNodeCornerRadius(node, bounds);\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\" rx=\"${radius}\" ry=\"${radius}\"`;\n break;\n }\n case 'circle': {\n const center = node.getCenter();\n shape = `<ellipse cx=\"${center.x}\" cy=\"${center.y}\" rx=\"${bounds.width / 2}\" ry=\"${bounds.height / 2}\"`;\n break;\n }\n case 'diamond': {\n const center = node.getCenter();\n const hw = bounds.width / 2;\n const hh = bounds.height / 2;\n const points = [\n `${center.x},${center.y - hh}`,\n `${center.x + hw},${center.y}`,\n `${center.x},${center.y + hh}`,\n `${center.x - hw},${center.y}`,\n ].join(' ');\n shape = `<polygon points=\"${points}\"`;\n break;\n }\n case 'custom': {\n const svgPath =\n 'getSvgPath' in node && typeof node.getSvgPath === 'function'\n ? (node as { getSvgPath: () => string | null }).getSvgPath()\n : null;\n if (svgPath) {\n shape = `<path d=\"${this.escapeAttribute(svgPath)}\" transform=\"translate(${bounds.x}, ${bounds.y})\"`;\n } else {\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`;\n }\n break;\n }\n default: {\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`;\n }\n }\n\n const label = this.renderNodeLabel(node, bounds);\n const icon = this.renderNodeIcon(node, bounds);\n\n return [\n `${shape} fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" stroke-opacity=\"${strokeOpacity}\"${dash}${dashOffset}/>`,\n icon,\n label,\n ].join('');\n }\n\n private renderEdge(edge: Edge, edgeLabelOffset?: number): string {\n const path = edge.path;\n if (path.length < 2) {\n return '';\n }\n\n const style = edge.style;\n const stroke = style.strokeColor ?? '#666666';\n const strokeWidth = style.strokeWidth ?? 2;\n const strokeOpacity = (style.strokeOpacity ?? 1) * (style.opacity ?? 1);\n const lineCap = style.lineCap ? ` stroke-linecap=\"${style.lineCap}\"` : '';\n const lineJoin = style.lineJoin ? ` stroke-linejoin=\"${style.lineJoin}\"` : '';\n const dashValues = style.flowDash ?? style.lineDash;\n const dash = dashValues ? ` stroke-dasharray=\"${dashValues.join(' ')}\"` : '';\n const dashOffset =\n style.lineDashOffset !== undefined ? ` stroke-dashoffset=\"${style.lineDashOffset}\"` : '';\n\n const d = this.buildPath(edge);\n const markerShapes = this.renderEdgeMarkers(edge, stroke);\n const label = this.renderEdgeLabel(edge, edgeLabelOffset);\n\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" stroke-opacity=\"${strokeOpacity}\" color=\"${stroke}\"${lineCap}${lineJoin}${dash}${dashOffset}/>${markerShapes}${label}`;\n }\n\n private renderEdgeLabel(edge: Edge, edgeLabelOffset?: number): string {\n if (!edge.label) {\n return '';\n }\n\n const labelPoint = this.getEdgeLabelPoint(edge, edgeLabelOffset);\n const text = this.renderTextLabel(edge.label.text, labelPoint, edge.label.style);\n const bg = this.renderEdgeLabelBackground(edge, labelPoint);\n return `${bg}${text}`;\n }\n\n private renderEdgeLabelBackground(edge: Edge, point: Point): string {\n if (!edge.label) {\n return '';\n }\n\n const metrics = this.measureTextLabel(edge.label.text, edge.label.style, edge.label.padding, edge.label.margin);\n const bgPadding = edge.labelBackground?.padding ?? EDGE_LABEL_BACKGROUND_PADDING;\n const bgColor = edge.labelBackground?.color ?? '#ffffff';\n const bgOpacity = edge.labelBackground?.opacity ?? 1;\n const bgRadius = edge.labelBackground?.borderRadius ?? EDGE_LABEL_BACKGROUND_RADIUS;\n\n const x = point.x - metrics.width / 2 - bgPadding;\n const y = point.y - metrics.height / 2 - bgPadding;\n const width = metrics.width + bgPadding * 2;\n const height = metrics.height + bgPadding * 2;\n const radius = Math.max(0, Math.min(bgRadius, width / 2, height / 2));\n\n if (radius <= 0) {\n return `<rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\" fill=\"${bgColor}\" fill-opacity=\"${bgOpacity}\"/>`;\n }\n\n return `<rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\" rx=\"${radius}\" ry=\"${radius}\" fill=\"${bgColor}\" fill-opacity=\"${bgOpacity}\"/>`;\n }\n\n private measureTextLabel(\n text: string,\n style: TextStyle = {},\n padding = 8,\n margin = 0\n ): { width: number; height: number } {\n const fontSize = style.fontSize ?? 14;\n const fontFamily = style.fontFamily ?? 'sans-serif';\n const fontWeight = style.fontWeight ?? 'normal';\n const lineHeight = fontSize * 1.2;\n const lines = text.split('\\n');\n let maxWidth = 0;\n\n if (typeof document !== 'undefined') {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n for (const line of lines) {\n maxWidth = Math.max(maxWidth, ctx.measureText(line).width);\n }\n }\n }\n\n if (maxWidth === 0) {\n const longestLine = lines.reduce((max, line) => (line.length > max.length ? line : max), '');\n maxWidth = longestLine.length * fontSize * 0.6;\n }\n\n const resolvedPadding = Math.max(0, padding);\n const resolvedMargin = Math.max(0, margin);\n return {\n width: maxWidth + resolvedPadding * 2 + resolvedMargin * 2,\n height: lines.length * lineHeight + resolvedPadding * 2 + resolvedMargin * 2,\n };\n }\n\n private resolveMarkerConfig(edge: Edge, side: 'start' | 'end'): ArrowMarkerConfig | null {\n const marker = side === 'start' ? edge.startMarker : edge.endMarker;\n if (marker && marker.type !== 'none') {\n return marker;\n }\n\n if (side === 'end') {\n return edge.arrowType === 'none' ? null : { type: 'arrow' };\n }\n\n return edge.arrowType === 'double' ? { type: 'arrow' } : null;\n }\n\n private renderEdgeMarkers(edge: Edge, edgeStroke: string): string {\n const startMarker = this.resolveMarkerConfig(edge, 'start');\n const endMarker = this.resolveMarkerConfig(edge, 'end');\n const parts: string[] = [];\n\n if (endMarker) {\n const points = this.getMarkerPoints(edge, 'end');\n if (points) {\n parts.push(this.renderMarkerShape(endMarker, points.from, points.to, edgeStroke));\n }\n }\n\n if (startMarker) {\n const points = this.getMarkerPoints(edge, 'start');\n if (points) {\n parts.push(this.renderMarkerShape(startMarker, points.from, points.to, edgeStroke));\n }\n }\n\n return parts.join('');\n }\n\n private getMarkerPoints(edge: Edge, position: 'start' | 'end'): { from: Point; to: Point } | null {\n return calculateMarkerPoints(edge.path, position, edge.type);\n }\n\n private renderMarkerShape(\n marker: ArrowMarkerConfig,\n from: Point,\n to: Point,\n edgeStroke: string\n ): string {\n return generateSvgMarker(marker, from, to, edgeStroke);\n }\n\n private buildPath(edge: Edge): string {\n const path = edge.path;\n if (edge.type === 'bezier' && path.length >= 4) {\n let d = `M ${path[0]!.x} ${path[0]!.y}`;\n for (let i = 1; i + 2 < path.length; i += 3) {\n d += ` C ${path[i]!.x} ${path[i]!.y} ${path[i + 1]!.x} ${path[i + 1]!.y} ${path[i + 2]!.x} ${path[i + 2]!.y}`;\n }\n return d;\n }\n\n let d = `M ${path[0]!.x} ${path[0]!.y}`;\n for (let i = 1; i < path.length; i++) {\n d += ` L ${path[i]!.x} ${path[i]!.y}`;\n }\n return d;\n }\n\n private getPathMidpoint(edge: Edge): Point {\n const path = edge.path;\n if (edge.type === 'bezier' && path.length >= 4) {\n const t = 0.5;\n const mt = 1 - t;\n return {\n x:\n mt * mt * mt * path[0]!.x +\n 3 * mt * mt * t * path[1]!.x +\n 3 * mt * t * t * path[2]!.x +\n t * t * t * path[3]!.x,\n y:\n mt * mt * mt * path[0]!.y +\n 3 * mt * mt * t * path[1]!.y +\n 3 * mt * t * t * path[2]!.y +\n t * t * t * path[3]!.y,\n };\n }\n\n let totalLength = 0;\n const segments: { start: Point; end: Point; length: number }[] = [];\n for (let i = 1; i < path.length; i++) {\n const start = path[i - 1]!;\n const end = path[i]!;\n const length = Math.hypot(end.x - start.x, end.y - start.y);\n segments.push({ start, end, length });\n totalLength += length;\n }\n\n const halfLength = totalLength / 2;\n let accumulated = 0;\n\n for (const seg of segments) {\n if (accumulated + seg.length >= halfLength) {\n const t = (halfLength - accumulated) / seg.length;\n return {\n x: seg.start.x + t * (seg.end.x - seg.start.x),\n y: seg.start.y + t * (seg.end.y - seg.start.y),\n };\n }\n accumulated += seg.length;\n }\n\n return path[0]!;\n }\n\n private getEdgeLabelPoint(edge: Edge, edgeLabelOffset?: number): Point {\n const midpoint = this.getPathMidpoint(edge);\n const effectiveOffset = edgeLabelOffset ?? edge.labelOffset ?? 0;\n return {\n x: midpoint.x,\n y: midpoint.y + effectiveOffset,\n };\n }\n\n private renderTextLabel(text: string, point: Point, style: TextStyle = {}): string {\n const fill = style.color ?? '#000000';\n const fontSize = style.fontSize ?? 14;\n const fontFamily = style.fontFamily ?? 'sans-serif';\n const fontWeight = style.fontWeight ?? 'normal';\n const opacity = style.opacity ?? 1;\n const anchor = style.align === 'left' ? 'start' : style.align === 'right' ? 'end' : 'middle';\n const baseline =\n style.baseline === 'top'\n ? 'text-before-edge'\n : style.baseline === 'bottom'\n ? 'text-after-edge'\n : 'middle';\n\n const lines = text.split('\\n');\n if (lines.length <= 1) {\n return `<text x=\"${point.x}\" y=\"${point.y}\" fill=\"${fill}\" fill-opacity=\"${opacity}\" font-size=\"${fontSize}\" font-family=\"${fontFamily}\" font-weight=\"${fontWeight}\" text-anchor=\"${anchor}\" dominant-baseline=\"${baseline}\">${this.escapeText(\n text\n )}</text>`;\n }\n\n const lineHeight = fontSize * 1.2;\n const startY = point.y - ((lines.length - 1) * lineHeight) / 2;\n const tspans = lines\n .map((line, index) => `<tspan x=\"${point.x}\" y=\"${startY + index * lineHeight}\">${this.escapeText(line)}</tspan>`)\n .join('');\n return `<text x=\"${point.x}\" y=\"${point.y}\" fill=\"${fill}\" fill-opacity=\"${opacity}\" font-size=\"${fontSize}\" font-family=\"${fontFamily}\" font-weight=\"${fontWeight}\" text-anchor=\"${anchor}\" dominant-baseline=\"${baseline}\">${tspans}</text>`;\n }\n\n private getMeasurementContext(): CanvasRenderingContext2D | null {\n if (typeof document === 'undefined') {\n return null;\n }\n const canvas = document.createElement('canvas');\n return canvas.getContext('2d');\n }\n\n private renderNodeLabel(node: Node, nodeBounds: { x: number; y: number; width: number; height: number }): string {\n const label = node.label;\n if (!label) {\n return '';\n }\n\n const style = label.style;\n const padding = Math.max(0, label.padding);\n const margin = Math.max(0, label.margin);\n const align = style.align ?? 'center';\n\n const ctx = this.getMeasurementContext();\n let bounds: { x: number; y: number; width: number; height: number };\n let lines: string[];\n\n if (ctx !== null) {\n const result = node.getLabelBoundsForExport(ctx);\n if (result) {\n bounds = result.bounds;\n lines = result.lines;\n } else {\n bounds = nodeBounds;\n lines = label.text.split('\\n');\n }\n } else {\n bounds = nodeBounds;\n lines = label.text.split('\\n');\n }\n\n const inner = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n\n let x = inner.x + inner.width / 2;\n if (align === 'left') {\n x = inner.x + padding;\n } else if (align === 'right') {\n x = inner.x + inner.width - padding;\n }\n\n const y = inner.y + inner.height / 2;\n\n return this.renderTextLabel(lines.join('\\n'), { x, y }, style);\n }\n\n private getNodeCornerRadius(node: Node, bounds: { width: number; height: number }): number {\n const rectangleRadius =\n 'cornerRadius' in node && typeof (node as { cornerRadius?: unknown }).cornerRadius === 'number'\n ? ((node as { cornerRadius: number }).cornerRadius ?? 0)\n : node.style.cornerRadius ?? 0;\n return Math.max(0, Math.min(rectangleRadius, bounds.width / 2, bounds.height / 2));\n }\n\n private renderNodeIcon(node: Node, nodeBounds: { x: number; y: number; width: number; height: number }): string {\n const icon = node.icon;\n if (!icon) {\n return '';\n }\n\n const opts = icon.options;\n const iconSize = icon.getSize();\n if (iconSize.width <= 0 || iconSize.height <= 0) {\n return '';\n }\n\n const iconBoxSize = this.getIconBoxSize(opts, iconSize);\n const iconBounds = this.getIconBounds(nodeBounds, iconBoxSize, opts.placement ?? 'center');\n const drawRect = this.getIconDrawRect(iconBounds, opts, iconSize);\n if (drawRect.width <= 0 || drawRect.height <= 0) {\n return '';\n }\n\n const href = this.resolveIconHref(opts);\n if (!href) {\n return '';\n }\n\n const opacity = opts.opacity ?? 1;\n return `<image href=\"${this.escapeAttribute(href)}\" x=\"${drawRect.x}\" y=\"${drawRect.y}\" width=\"${drawRect.width}\" height=\"${drawRect.height}\" opacity=\"${opacity}\" preserveAspectRatio=\"none\"/>`;\n }\n\n private getIconBoxSize(\n opts: NodeImageOptions,\n imageSize: { width: number; height: number }\n ): { width: number; height: number } {\n const padding = opts.padding ?? 8;\n const margin = Math.max(0, opts.margin ?? 0);\n return {\n width: imageSize.width + padding * 2 + margin * 2,\n height: imageSize.height + padding * 2 + margin * 2,\n };\n }\n\n private getIconBounds(\n bounds: { x: number; y: number; width: number; height: number },\n iconBoxSize: { width: number; height: number },\n placement: NodeImagePlacement\n ): { x: number; y: number; width: number; height: number } {\n switch (placement) {\n case 'top':\n return { x: bounds.x, y: bounds.y, width: bounds.width, height: iconBoxSize.height };\n case 'bottom':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n case 'left':\n return { x: bounds.x, y: bounds.y, width: iconBoxSize.width, height: bounds.height };\n case 'right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n case 'top-left':\n return { x: bounds.x, y: bounds.y, width: iconBoxSize.width, height: iconBoxSize.height };\n case 'top-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-left':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'center':\n default:\n return bounds;\n }\n }\n\n private getIconDrawRect(\n bounds: { x: number; y: number; width: number; height: number },\n opts: NodeImageOptions,\n imageSize: { width: number; height: number }\n ): { x: number; y: number; width: number; height: number } {\n const padding = opts.padding ?? 8;\n const margin = Math.max(0, opts.margin ?? 0);\n const fit = opts.fit ?? 'none';\n const scaleWithBounds = opts.scaleWithBounds ?? false;\n const align = opts.align ?? 'center';\n const verticalAlign = opts.verticalAlign ?? 'center';\n const offsetX = opts.offsetX ?? 0;\n const offsetY = opts.offsetY ?? 0;\n\n const innerBounds = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n const availableWidth = Math.max(0, innerBounds.width - padding * 2);\n const availableHeight = Math.max(0, innerBounds.height - padding * 2);\n\n let drawWidth = opts.width ?? imageSize.width;\n let drawHeight = opts.height ?? imageSize.height;\n\n if (scaleWithBounds) {\n if ((fit === 'contain' || fit === 'cover') && imageSize.width > 0 && imageSize.height > 0) {\n const scaleX = availableWidth / imageSize.width;\n const scaleY = availableHeight / imageSize.height;\n const scale = fit === 'contain' ? Math.min(scaleX, scaleY) : Math.max(scaleX, scaleY);\n drawWidth = imageSize.width * scale;\n drawHeight = imageSize.height * scale;\n } else if (fit === 'stretch') {\n drawWidth = availableWidth;\n drawHeight = availableHeight;\n }\n }\n\n drawWidth = Math.min(Math.max(0, drawWidth), Math.max(0, availableWidth));\n drawHeight = Math.min(Math.max(0, drawHeight), Math.max(0, availableHeight));\n\n let x = innerBounds.x + padding;\n let y = innerBounds.y + padding;\n\n if (align === 'center') {\n x = innerBounds.x + (innerBounds.width - drawWidth) / 2;\n } else if (align === 'right') {\n x = innerBounds.x + innerBounds.width - drawWidth - padding;\n }\n\n if (verticalAlign === 'center') {\n y = innerBounds.y + (innerBounds.height - drawHeight) / 2;\n } else if (verticalAlign === 'bottom') {\n y = innerBounds.y + innerBounds.height - drawHeight - padding;\n }\n\n return {\n x: x + offsetX,\n y: y + offsetY,\n width: drawWidth,\n height: drawHeight,\n };\n }\n\n private resolveIconHref(opts: NodeImageOptions): string {\n const source = opts.source;\n if (source instanceof HTMLImageElement) {\n return source.src;\n }\n\n if (!source) {\n return '';\n }\n\n if (this.isSvgMarkup(source)) {\n return this.svgToDataUrl(this.tintSvg(source, opts.strokeColor, opts.fillColor));\n }\n\n const shouldInlineSvg = source.toLowerCase().endsWith('.svg');\n if (shouldInlineSvg) {\n const svgText = this.readSvgFromUrlSync(source);\n if (svgText) {\n return this.svgToDataUrl(this.tintSvg(svgText, opts.strokeColor, opts.fillColor));\n }\n }\n\n return source;\n }\n\n private readSvgFromUrlSync(url: string): string | null {\n if (typeof XMLHttpRequest === 'undefined') {\n return null;\n }\n\n try {\n const xhr = new XMLHttpRequest();\n xhr.open('GET', url, false);\n xhr.send();\n if (xhr.status >= 200 && xhr.status < 300) {\n return xhr.responseText || null;\n }\n } catch {\n // Ignore and fallback to raw URL source.\n }\n\n return null;\n }\n\n private isSvgMarkup(value: string): boolean {\n const trimmed = value.trim().toLowerCase();\n return trimmed.startsWith('<svg') || trimmed.includes('<svg');\n }\n\n private styleSetColor(style: string, key: 'stroke' | 'fill', color: string): string {\n const hasKey = new RegExp(`${key}\\\\s*:`).test(style);\n if (hasKey) {\n return style.replace(new RegExp(`${key}\\\\s*:[^;]+`), `${key}:${color}`);\n }\n const suffix = style.trim().endsWith(';') || style.trim() === '' ? '' : ';';\n return `${style}${suffix}${key}:${color};`;\n }\n\n private tintSvg(svgText: string, strokeColor?: string, fillColor?: string): string {\n if (!strokeColor && !fillColor) return svgText;\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(svgText, 'image/svg+xml');\n const root = doc.documentElement;\n if (!root || root.nodeName.toLowerCase() === 'parsererror') {\n return svgText;\n }\n\n const all = [root, ...Array.from(root.querySelectorAll('*'))] as Element[];\n for (const el of all) {\n const stroke = el.getAttribute('stroke');\n if (strokeColor && stroke !== null && stroke.toLowerCase() !== 'none') {\n el.setAttribute('stroke', strokeColor);\n }\n const fill = el.getAttribute('fill');\n if (fillColor && fill !== null && fill.toLowerCase() !== 'none') {\n el.setAttribute('fill', fillColor);\n }\n const style = el.getAttribute('style');\n if (style) {\n let next = style;\n if (strokeColor && /stroke\\s*:\\s*(?!none)/.test(style)) {\n next = this.styleSetColor(next, 'stroke', strokeColor);\n }\n if (fillColor && /fill\\s*:\\s*(?!none)/.test(style)) {\n next = this.styleSetColor(next, 'fill', fillColor);\n }\n if (next !== style) {\n el.setAttribute('style', next);\n }\n }\n }\n\n return new XMLSerializer().serializeToString(root);\n }\n\n private svgToDataUrl(svg: string): string {\n const encoded = encodeURIComponent(svg)\n .replace(/%0A/g, '')\n .replace(/%0D/g, '')\n .replace(/%09/g, ' ')\n .replace(/%20/g, ' ');\n return `data:image/svg+xml;utf8,${encoded}`;\n }\n\n private escapeAttribute(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n }\n\n private createEmptySvg(width: number, height: number, backgroundColor: string, includeBackground: boolean): string {\n return [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">`,\n includeBackground ? `<rect width=\"100%\" height=\"100%\" fill=\"${backgroundColor}\"/>` : '',\n '</svg>',\n ].join('');\n }\n\n private escapeText(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n }\n}\n","import type { Node } from '@/elements/Node';\n\nexport interface GridLayoutOptions {\n columns?: number;\n rowGap?: number;\n columnGap?: number;\n startX?: number;\n startY?: number;\n}\n\n/**\n * Basic auto-layout utilities\n */\nexport class AutoLayout {\n applyGridLayout(nodes: Node[], options: GridLayoutOptions = {}): void {\n if (nodes.length === 0) return;\n\n const columns = options.columns ?? Math.ceil(Math.sqrt(nodes.length));\n const rowGap = options.rowGap ?? 40;\n const columnGap = options.columnGap ?? 40;\n const startX = options.startX ?? 0;\n const startY = options.startY ?? 0;\n\n let col = 0;\n let cursorX = startX;\n let cursorY = startY;\n let currentRowHeight = 0;\n\n for (const node of nodes) {\n node.x = cursorX;\n node.y = cursorY;\n currentRowHeight = Math.max(currentRowHeight, node.height);\n\n col += 1;\n if (col >= columns) {\n col = 0;\n cursorX = startX;\n cursorY += currentRowHeight + rowGap;\n currentRowHeight = 0;\n } else {\n cursorX += node.width + columnGap;\n }\n }\n }\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Point } from '@/types';\n\nexport interface AutoRoutingOptions {\n type?: 'straight' | 'polyline' | 'bezier';\n}\n\n/**\n * Basic edge auto-routing\n */\nexport class AutoRouting {\n apply(renderer: DiagramRenderer, options: AutoRoutingOptions = {}): void {\n const type = options.type ?? 'polyline';\n\n for (const edge of renderer.edges.values()) {\n edge.type = type;\n\n const fromNode = renderer.getNode(edge.from.nodeId);\n const toNode = renderer.getNode(edge.to.nodeId);\n if (!fromNode || !toNode) continue;\n\n const fromPoint: Point =\n edge.from.portId !== undefined\n ? fromNode.getPortPosition(edge.from.portId) ?? fromNode.getCenter()\n : fromNode.getCenter();\n const toPoint: Point =\n edge.to.portId !== undefined\n ? toNode.getPortPosition(edge.to.portId) ?? toNode.getCenter()\n : toNode.getCenter();\n\n edge.updateEndpoints(fromPoint, toPoint);\n }\n\n renderer.markDirty();\n }\n}\n","import type { Node } from '@/elements/Node';\n\nexport type AlignType = 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom';\nexport type DistributeType = 'horizontal' | 'vertical';\n\n/**\n * Align nodes by edge or center\n */\nexport function alignNodes(nodes: Node[], type: AlignType): void {\n if (nodes.length === 0) return;\n\n switch (type) {\n case 'left': {\n const minX = Math.min(...nodes.map((n) => n.x));\n for (const node of nodes) node.x = minX;\n break;\n }\n case 'center': {\n const centerX = Math.min(...nodes.map((n) => n.x + n.width / 2));\n for (const node of nodes) node.x = centerX - node.width / 2;\n break;\n }\n case 'right': {\n const maxX = Math.max(...nodes.map((n) => n.x + n.width));\n for (const node of nodes) node.x = maxX - node.width;\n break;\n }\n case 'top': {\n const minY = Math.min(...nodes.map((n) => n.y));\n for (const node of nodes) node.y = minY;\n break;\n }\n case 'middle': {\n const centerY = Math.min(...nodes.map((n) => n.y + n.height / 2));\n for (const node of nodes) node.y = centerY - node.height / 2;\n break;\n }\n case 'bottom': {\n const maxY = Math.max(...nodes.map((n) => n.y + n.height));\n for (const node of nodes) node.y = maxY - node.height;\n break;\n }\n }\n}\n\n/**\n * Distribute nodes evenly along axis\n */\nexport function distributeNodes(nodes: Node[], type: DistributeType): void {\n if (nodes.length < 3) return;\n\n if (type === 'horizontal') {\n const sorted = [...nodes].sort((a, b) => a.x - b.x);\n const minX = sorted[0]!.x;\n const maxX = sorted[sorted.length - 1]!.x + sorted[sorted.length - 1]!.width;\n const totalWidth = sorted.reduce((sum, n) => sum + n.width, 0);\n const gap = (maxX - minX - totalWidth) / (sorted.length - 1);\n\n let currentX = minX;\n for (const node of sorted) {\n node.x = currentX;\n currentX += node.width + gap;\n }\n } else {\n const sorted = [...nodes].sort((a, b) => a.y - b.y);\n const minY = sorted[0]!.y;\n const maxY = sorted[sorted.length - 1]!.y + sorted[sorted.length - 1]!.height;\n const totalHeight = sorted.reduce((sum, n) => sum + n.height, 0);\n const gap = (maxY - minY - totalHeight) / (sorted.length - 1);\n\n let currentY = minY;\n for (const node of sorted) {\n node.y = currentY;\n currentY += node.height + gap;\n }\n }\n}\n","import type { DiagramPlugin } from '../DiagramRenderer';\n\n/**\n * Base options for all overlays\n */\nexport interface BaseOverlayOptions {\n enabled?: boolean;\n}\n\n/**\n * Abstract base class for diagram overlays\n * Provides common destroy() and setEnabled() functionality\n */\nexport abstract class BaseOverlay implements DiagramPlugin {\n protected removeOverlay: (() => void) | null = null;\n protected enabled: boolean;\n\n protected constructor(enabled = true) {\n this.enabled = enabled;\n }\n\n abstract install(renderer: Parameters<DiagramPlugin['install']>[0]): void;\n\n destroy(): void {\n this.removeOverlay?.();\n this.removeOverlay = null;\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n}\n","import type { DiagramRenderer } from '../DiagramRenderer';\nimport { BaseOverlay, type BaseOverlayOptions } from './BaseOverlay';\n\nexport interface GridOverlayOptions extends BaseOverlayOptions {\n gridSize?: number;\n color?: string;\n}\n\nexport class GridOverlay extends BaseOverlay {\n private gridSize: number;\n private color: string;\n\n constructor(options: GridOverlayOptions = {}) {\n super(options.enabled ?? true);\n this.gridSize = options.gridSize ?? 20;\n this.color = options.color ?? '#e0e0e0';\n }\n\n setColor(color: string): void {\n this.color = color;\n }\n\n setGridSize(size: number): void {\n this.gridSize = size;\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addUnderlayRenderer((ctx) => {\n if (!this.enabled) {\n return;\n }\n\n const width = renderer.width;\n const height = renderer.height;\n const gridSize = this.gridSize;\n const color = this.color;\n\n const startX = Math.floor(-renderer.offsetX / renderer.zoom / gridSize) * gridSize;\n const startY = Math.floor(-renderer.offsetY / renderer.zoom / gridSize) * gridSize;\n const endX = Math.ceil((width - renderer.offsetX) / renderer.zoom / gridSize) * gridSize;\n const endY = Math.ceil((height - renderer.offsetY) / renderer.zoom / gridSize) * gridSize;\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1 / renderer.zoom;\n ctx.beginPath();\n\n for (let x = startX; x <= endX; x += gridSize) {\n ctx.moveTo(x, startY);\n ctx.lineTo(x, endY);\n }\n\n for (let y = startY; y <= endY; y += gridSize) {\n ctx.moveTo(startX, y);\n ctx.lineTo(endX, y);\n }\n\n ctx.stroke();\n });\n }\n}\n","import type { DiagramRenderer } from '../DiagramRenderer';\nimport { BaseOverlay, type BaseOverlayOptions } from './BaseOverlay';\n\nexport interface RulersOverlayOptions extends BaseOverlayOptions {\n thickness?: number;\n backgroundColor?: string;\n textColor?: string;\n tickColor?: string;\n}\n\nexport class RulersOverlay extends BaseOverlay {\n private readonly thickness: number;\n private readonly backgroundColor: string;\n private readonly textColor: string;\n private readonly tickColor: string;\n\n constructor(options: RulersOverlayOptions = {}) {\n super(options.enabled ?? true);\n this.thickness = options.thickness ?? 20;\n this.backgroundColor = options.backgroundColor ?? '#f4f4f5';\n this.textColor = options.textColor ?? '#52525b';\n this.tickColor = options.tickColor ?? '#a1a1aa';\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addOverlayRenderer((ctx) => {\n if (!this.enabled) return;\n\n const thickness = this.thickness;\n ctx.save();\n ctx.setTransform(renderer.pixelRatio, 0, 0, renderer.pixelRatio, 0, 0);\n\n ctx.fillStyle = this.backgroundColor;\n ctx.fillRect(0, 0, renderer.width, thickness);\n ctx.fillRect(0, 0, thickness, renderer.height);\n\n ctx.strokeStyle = this.tickColor;\n ctx.fillStyle = this.textColor;\n ctx.font = '10px sans-serif';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n const step = this.getTickStep(renderer.zoom);\n const worldLeft = -renderer.offsetX / renderer.zoom;\n const worldTop = -renderer.offsetY / renderer.zoom;\n const worldRight = worldLeft + renderer.width / renderer.zoom;\n const worldBottom = worldTop + renderer.height / renderer.zoom;\n\n ctx.beginPath();\n for (let x = Math.floor(worldLeft / step) * step; x <= worldRight; x += step) {\n const screenX = x * renderer.zoom + renderer.offsetX;\n ctx.moveTo(screenX, thickness);\n ctx.lineTo(screenX, thickness - 6);\n ctx.fillText(`${Math.round(x)}`, screenX + 2, 2);\n }\n\n for (let y = Math.floor(worldTop / step) * step; y <= worldBottom; y += step) {\n const screenY = y * renderer.zoom + renderer.offsetY;\n ctx.moveTo(thickness, screenY);\n ctx.lineTo(thickness - 6, screenY);\n ctx.save();\n ctx.translate(2, screenY + 2);\n ctx.rotate(-Math.PI / 2);\n ctx.fillText(`${Math.round(y)}`, 0, 0);\n ctx.restore();\n }\n\n ctx.stroke();\n ctx.restore();\n });\n }\n\n private getTickStep(zoom: number): number {\n const targetPx = 80;\n const rawStep = targetPx / zoom;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n if (normalized < 1.5) return magnitude;\n if (normalized < 3) return 2 * magnitude;\n if (normalized < 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n}\n","import type { DiagramRenderer } from '../DiagramRenderer';\nimport { BaseOverlay, type BaseOverlayOptions } from './BaseOverlay';\n\nexport interface GuidesOverlayOptions extends BaseOverlayOptions {\n vertical?: number[];\n horizontal?: number[];\n color?: string;\n lineWidth?: number;\n}\n\nexport class GuidesOverlay extends BaseOverlay {\n private vertical: number[];\n private horizontal: number[];\n private readonly color: string;\n private readonly lineWidth: number;\n\n constructor(options: GuidesOverlayOptions = {}) {\n super(options.enabled ?? true);\n this.vertical = options.vertical ?? [];\n this.horizontal = options.horizontal ?? [];\n this.color = options.color ?? 'rgba(59, 130, 246, 0.5)';\n this.lineWidth = options.lineWidth ?? 1;\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addOverlayRenderer((ctx) => {\n if (!this.enabled) return;\n\n ctx.save();\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.lineWidth / renderer.zoom;\n ctx.beginPath();\n\n const worldLeft = -renderer.offsetX / renderer.zoom;\n const worldTop = -renderer.offsetY / renderer.zoom;\n const worldRight = worldLeft + renderer.width / renderer.zoom;\n const worldBottom = worldTop + renderer.height / renderer.zoom;\n\n for (const x of this.vertical) {\n if (x < worldLeft || x > worldRight) continue;\n ctx.moveTo(x, worldTop);\n ctx.lineTo(x, worldBottom);\n }\n\n for (const y of this.horizontal) {\n if (y < worldTop || y > worldBottom) continue;\n ctx.moveTo(worldLeft, y);\n ctx.lineTo(worldRight, y);\n }\n\n ctx.stroke();\n ctx.restore();\n });\n }\n\n setGuides(vertical: number[], horizontal: number[]): void {\n this.vertical = vertical;\n this.horizontal = horizontal;\n }\n}\n","import type { DiagramPlugin, DiagramRenderer } from '../DiagramRenderer';\nimport type { Bounds } from '@/types';\nimport { getContentBounds } from '@/utils/contentBounds';\n\nexport type MiniMapAnchor = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n\nexport interface MiniMapOptions {\n enabled?: boolean;\n width?: number;\n height?: number;\n padding?: number;\n /** Отступ (в мировых координатах) вокруг контента — расширяет область, в пределах которой можно перемещать view. По умолчанию 0. */\n contentMargin?: number;\n backgroundColor?: string;\n borderColor?: string;\n viewportColor?: string;\n anchor?: MiniMapAnchor;\n}\n\ninterface MiniMapLayout {\n x: number;\n y: number;\n width: number;\n height: number;\n bounds: Bounds;\n scale: number;\n mapOffsetX: number;\n mapOffsetY: number;\n viewportBounds: Bounds;\n viewRect: Bounds;\n}\n\ninterface MiniMapDragPayload {\n pointerOffsetX: number;\n pointerOffsetY: number;\n}\n\nexport class MiniMap implements DiagramPlugin {\n private readonly options: Required<MiniMapOptions>;\n private removeOverlay: (() => void) | null = null;\n\n constructor(options: MiniMapOptions = {}) {\n this.options = {\n enabled: options.enabled ?? true,\n width: options.width ?? 180,\n height: options.height ?? 120,\n padding: options.padding ?? 12,\n contentMargin: options.contentMargin ?? 0,\n backgroundColor: options.backgroundColor ?? 'rgba(24, 24, 27, 0.5)',\n borderColor: options.borderColor ?? '#52525b',\n viewportColor: options.viewportColor ?? '#22c55e',\n anchor: options.anchor ?? 'bottom-right',\n };\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addOverlayRenderer((ctx) => {\n if (!this.options.enabled) return;\n const layout = this.computeLayout(renderer);\n if (!layout) return;\n const { x, y, width, height, bounds, scale, mapOffsetX, mapOffsetY, viewRect } = layout;\n\n ctx.save();\n ctx.setTransform(renderer.pixelRatio, 0, 0, renderer.pixelRatio, 0, 0);\n // MiniMap frame must remain solid even if main canvas rendered dashed edges before.\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n\n ctx.fillStyle = this.options.backgroundColor;\n ctx.fillRect(x, y, width, height);\n ctx.strokeStyle = this.options.borderColor;\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n\n ctx.save();\n ctx.translate(mapOffsetX, mapOffsetY);\n ctx.scale(scale, scale);\n ctx.translate(-bounds.x, -bounds.y);\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n\n ctx.strokeStyle = '#94a3b8';\n ctx.lineWidth = 1 / scale;\n\n for (const edge of renderer.edges.values()) {\n if (!edge.visible) continue;\n const path = edge.path;\n if (path.length < 2) continue;\n ctx.beginPath();\n ctx.moveTo(path[0]!.x, path[0]!.y);\n for (let i = 1; i < path.length; i++) {\n ctx.lineTo(path[i]!.x, path[i]!.y);\n }\n ctx.stroke();\n }\n\n for (const node of renderer.nodes.values()) {\n if (!node.visible) continue;\n const b = node.getBounds();\n ctx.fillStyle = '#e2e8f0';\n ctx.fillRect(b.x, b.y, b.width, b.height);\n }\n\n ctx.restore();\n\n if (viewRect.width < 0 || viewRect.height < 0) {\n ctx.restore();\n return;\n }\n\n ctx.strokeStyle = this.options.viewportColor;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n ctx.strokeRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);\n\n ctx.restore();\n });\n }\n\n destroy(): void {\n this.removeOverlay?.();\n this.removeOverlay = null;\n }\n\n setEnabled(enabled: boolean): void {\n this.options.enabled = enabled;\n }\n\n beginOverlayDrag(\n renderer: DiagramRenderer,\n screenX: number,\n screenY: number\n ): MiniMapDragPayload | null {\n if (!this.options.enabled) {\n return null;\n }\n const layout = this.computeLayout(renderer);\n if (!layout) {\n return null;\n }\n const point = renderer.screenToCanvas(screenX, screenY);\n if (!point) {\n return null;\n }\n\n const insideViewport =\n point.x >= layout.viewRect.x &&\n point.x <= layout.viewRect.x + layout.viewRect.width &&\n point.y >= layout.viewRect.y &&\n point.y <= layout.viewRect.y + layout.viewRect.height;\n if (!insideViewport) {\n return null;\n }\n\n return {\n pointerOffsetX: point.x - layout.viewRect.x,\n pointerOffsetY: point.y - layout.viewRect.y,\n };\n }\n\n updateOverlayDrag(\n renderer: DiagramRenderer,\n screenX: number,\n screenY: number,\n payload: unknown\n ): boolean {\n if (!this.options.enabled) {\n return false;\n }\n if (\n typeof payload !== 'object' ||\n payload === null ||\n !('pointerOffsetX' in payload) ||\n !('pointerOffsetY' in payload)\n ) {\n return false;\n }\n const dragPayload = payload as MiniMapDragPayload;\n const layout = this.computeLayout(renderer);\n if (!layout) {\n return false;\n }\n const point = renderer.screenToCanvas(screenX, screenY);\n if (!point) {\n return false;\n }\n\n const desiredViewX = point.x - dragPayload.pointerOffsetX;\n const desiredViewY = point.y - dragPayload.pointerOffsetY;\n const desiredViewportX = layout.bounds.x + (desiredViewX - layout.mapOffsetX) / layout.scale;\n const desiredViewportY = layout.bounds.y + (desiredViewY - layout.mapOffsetY) / layout.scale;\n const maxScrollX = Math.max(0, layout.bounds.width - layout.viewportBounds.width);\n const maxScrollY = Math.max(0, layout.bounds.height - layout.viewportBounds.height);\n const clampedViewportX = Math.min(\n Math.max(desiredViewportX, layout.bounds.x),\n layout.bounds.x + maxScrollX\n );\n const clampedViewportY = Math.min(\n Math.max(desiredViewportY, layout.bounds.y),\n layout.bounds.y + maxScrollY\n );\n\n renderer.offsetX = -clampedViewportX * renderer.zoom;\n renderer.offsetY = -clampedViewportY * renderer.zoom;\n return true;\n }\n\n private getViewportBounds(renderer: DiagramRenderer): Bounds {\n return {\n x: -renderer.offsetX / renderer.zoom,\n y: -renderer.offsetY / renderer.zoom,\n width: renderer.width / renderer.zoom,\n height: renderer.height / renderer.zoom,\n };\n }\n\n private computeLayout(renderer: DiagramRenderer): MiniMapLayout | null {\n const rawBounds = getContentBounds({\n nodes: renderer.nodes.values(),\n edges: renderer.edges.values(),\n groups: renderer.groups.values(),\n });\n if (!rawBounds) {\n return null;\n }\n\n const margin = this.options.contentMargin;\n const expandedContentBounds = {\n x: rawBounds.x - margin,\n y: rawBounds.y - margin,\n width: rawBounds.width + 2 * margin,\n height: rawBounds.height + 2 * margin,\n };\n\n const { width, height, padding, anchor } = this.options;\n const x =\n anchor === 'bottom-left' || anchor === 'top-left' ? padding : renderer.width - width - padding;\n const y =\n anchor === 'top-left' || anchor === 'top-right' ? padding : renderer.height - height - padding;\n\n const viewportBounds = this.getViewportBounds(renderer);\n const unionMinX = Math.min(expandedContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(expandedContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(\n expandedContentBounds.x + expandedContentBounds.width,\n viewportBounds.x + viewportBounds.width\n );\n const unionMaxY = Math.max(\n expandedContentBounds.y + expandedContentBounds.height,\n viewportBounds.y + viewportBounds.height\n );\n const bounds = {\n x: unionMinX,\n y: unionMinY,\n width: unionMaxX - unionMinX,\n height: unionMaxY - unionMinY,\n };\n\n const scale = Math.min(width / bounds.width, height / bounds.height);\n const mapOffsetX = x + (width - bounds.width * scale) / 2;\n const mapOffsetY = y + (height - bounds.height * scale) / 2;\n\n let viewX = mapOffsetX + (viewportBounds.x - bounds.x) * scale;\n let viewY = mapOffsetY + (viewportBounds.y - bounds.y) * scale;\n let viewW = viewportBounds.width * scale;\n let viewH = viewportBounds.height * scale;\n\n const minX = x;\n const minY = y;\n const maxX = x + width;\n const maxY = y + height;\n\n if (viewX < minX) {\n viewW -= minX - viewX;\n viewX = minX;\n }\n if (viewY < minY) {\n viewH -= minY - viewY;\n viewY = minY;\n }\n if (viewX + viewW > maxX) {\n viewW = maxX - viewX;\n }\n if (viewY + viewH > maxY) {\n viewH = maxY - viewY;\n }\n\n return {\n x,\n y,\n width,\n height,\n bounds,\n scale,\n mapOffsetX,\n mapOffsetY,\n viewportBounds,\n viewRect: {\n x: viewX,\n y: viewY,\n width: viewW,\n height: viewH,\n },\n };\n }\n}\n","import type { NodeStyle, EdgeStyle } from '@/types';\n\n/**\n * Apply node style to canvas context\n * Returns the base opacity for fill/stroke calculations\n */\nexport function applyNodeStyle(\n ctx: CanvasRenderingContext2D,\n style: NodeStyle,\n state: 'normal' | 'hover' | 'selected' | 'dragging'\n): number {\n ctx.fillStyle = style.fillColor ?? '#ffffff';\n ctx.strokeStyle = style.strokeColor ?? '#333333';\n ctx.lineWidth = style.strokeWidth ?? 2;\n\n const baseOpacity = style.opacity ?? 1;\n ctx.globalAlpha = baseOpacity;\n\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n }\n\n // Highlight for hover state\n if (state === 'hover') {\n ctx.strokeStyle = '#6366f1';\n }\n\n return baseOpacity;\n}\n\n/**\n * Apply fill and stroke with opacity\n */\nexport function renderFillAndStroke(\n ctx: CanvasRenderingContext2D,\n baseOpacity: number,\n fillOpacity = 1,\n strokeOpacity = 1\n): void {\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n ctx.globalAlpha = 1;\n}\n\n/**\n * Apply edge style to canvas context\n */\nexport function applyEdgeStyle(\n ctx: CanvasRenderingContext2D,\n style: EdgeStyle\n): number {\n ctx.strokeStyle = style.strokeColor ?? '#666666';\n ctx.lineWidth = style.strokeWidth ?? 2;\n\n const baseOpacity = style.opacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n }\n\n if (style.lineCap !== undefined) {\n ctx.lineCap = style.lineCap;\n }\n\n if (style.lineJoin !== undefined) {\n ctx.lineJoin = style.lineJoin;\n }\n\n return baseOpacity * strokeOpacity;\n}\n"],"names":["distance","i","point","SELF_LOOP_MIN_DISTANCE","SELF_LOOP_OFFSET","SELF_LOOP_SPREAD","CORNER_BYPASS_DISTANCE","CORNER_BYPASS_CLEARANCE","OPPOSITE_BYPASS_DISTANCE","OPPOSITE_BYPASS_CLEARANCE","OPPOSITE_BYPASS_ARC","dirToVector","end","angle","DEFAULT_OPTIONS","segStartParam","param","d"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"papirus.js","sources":["../src/events/EventEmitter.ts","../src/events/InputHandler.ts","../src/utils/geometry.ts","../src/constants.ts","../src/core/SelectionManager.ts","../src/core/DragManager.ts","../src/core/ResizeManager.ts","../src/utils/contentBounds.ts","../src/core/NavigationManager.ts","../src/core/ConnectionManager.ts","../src/utils/style.ts","../src/elements/TextLabel.ts","../src/core/history/commands.ts","../src/core/HistoryManager.ts","../src/elements/Element.ts","../src/elements/paths/StraightPathStrategy.ts","../src/utils/direction.ts","../src/elements/paths/PolylinePathStrategy.ts","../src/elements/paths/BezierPathStrategy.ts","../src/elements/Edge.ts","../src/core/LabelEditor.ts","../src/core/InteractionManager.ts","../src/core/AnimationManager.ts","../src/core/ContextMenuManager.ts","../src/core/DiagramRenderer.ts","../src/core/SearchManager.ts","../src/elements/Port.ts","../src/utils/LRUCache.ts","../src/elements/NodeImage.ts","../src/elements/Node.ts","../src/elements/Group.ts","../src/elements/nodes/RectangleNode.ts","../src/elements/nodes/CircleNode.ts","../src/elements/nodes/DiamondNode.ts","../src/elements/nodes/CustomShapeNode.ts","../src/styles/StyleManager.ts","../src/utils/omitDefaults.ts","../src/utils/Serializer.ts","../src/utils/download.ts","../src/utils/elementIterator.ts","../src/utils/ImageExporter.ts","../src/utils/markers.ts","../src/utils/SvgExporter.ts","../src/utils/AutoLayout.ts","../src/utils/AutoRouting.ts","../src/utils/AlignDistribute.ts","../src/core/overlays/BaseOverlay.ts","../src/core/overlays/GridOverlay.ts","../src/core/overlays/RulersOverlay.ts","../src/core/overlays/GuidesOverlay.ts","../src/core/overlays/MiniMap.ts","../src/utils/canvas.ts"],"sourcesContent":["/**\n * Type-safe event emitter with support for typed event maps\n */\nexport class EventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n private listeners = new Map<keyof TEvents, Set<(...args: unknown[]) => void>>();\n\n /**\n * Subscribe to an event\n * @param event - Event name\n * @param listener - Callback function\n * @returns Unsubscribe function\n */\n on<K extends keyof TEvents>(event: K, listener: (...args: TEvents[K]) => void): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n const listeners = this.listeners.get(event)!;\n listeners.add(listener as (...args: unknown[]) => void);\n\n return () => {\n this.off(event, listener);\n };\n }\n\n /**\n * Unsubscribe from an event\n * @param event - Event name\n * @param listener - Callback function to remove\n */\n off<K extends keyof TEvents>(event: K, listener: (...args: TEvents[K]) => void): void {\n const listeners = this.listeners.get(event);\n if (listeners !== undefined) {\n listeners.delete(listener as (...args: unknown[]) => void);\n }\n }\n\n /**\n * Subscribe to an event for a single emission\n * @param event - Event name\n * @param listener - Callback function\n * @returns Unsubscribe function\n */\n once<K extends keyof TEvents>(event: K, listener: (...args: TEvents[K]) => void): () => void {\n const wrapper = (...args: TEvents[K]): void => {\n this.off(event, wrapper);\n listener(...args);\n };\n return this.on(event, wrapper);\n }\n\n /**\n * Emit an event to all subscribers\n * @param event - Event name\n * @param args - Event arguments\n */\n emit<K extends keyof TEvents>(event: K, ...args: TEvents[K]): void {\n const listeners = this.listeners.get(event);\n if (listeners !== undefined) {\n for (const listener of listeners) {\n listener(...args);\n }\n }\n }\n\n /**\n * Remove all listeners for an event or all events\n * @param event - Optional event name. If not provided, removes all listeners\n */\n removeAllListeners<K extends keyof TEvents>(event?: K): void {\n if (event !== undefined) {\n this.listeners.delete(event);\n } else {\n this.listeners.clear();\n }\n }\n\n /**\n * Get the number of listeners for an event\n * @param event - Event name\n * @returns Number of listeners\n */\n listenerCount<K extends keyof TEvents>(event: K): number {\n const listeners = this.listeners.get(event);\n return listeners?.size ?? 0;\n }\n}\n","import { EventEmitter } from './EventEmitter';\nimport type { Point } from '@/types';\n\n/**\n * Input events\n */\nexport interface InputEvents {\n click: [event: InputEvent];\n dblclick: [event: InputEvent];\n mousedown: [event: InputEvent];\n mouseup: [event: InputEvent];\n mousemove: [event: InputEvent];\n wheel: [event: WheelInputEvent];\n pan: [event: PanInputEvent];\n pinch: [event: PinchInputEvent];\n keydown: [event: KeyboardEvent];\n keyup: [event: KeyboardEvent];\n}\n\n/**\n * Normalized input event\n */\nexport interface InputEvent {\n screenX: number;\n screenY: number;\n worldX: number;\n worldY: number;\n button: number;\n ctrlKey: boolean;\n shiftKey: boolean;\n altKey: boolean;\n metaKey: boolean;\n originalEvent: MouseEvent | TouchEvent;\n}\n\n/**\n * Wheel input event\n */\nexport interface WheelInputEvent extends InputEvent {\n deltaX: number;\n deltaY: number;\n deltaZ: number;\n originalEvent: WheelEvent;\n}\n\n/**\n * Pan gesture event (touch)\n */\nexport interface PanInputEvent extends InputEvent {\n deltaX: number;\n deltaY: number;\n}\n\n/**\n * Pinch gesture event (touch)\n */\nexport interface PinchInputEvent extends InputEvent {\n scale: number;\n}\n\nexport interface InputHandlerOptions {\n canvas: HTMLCanvasElement;\n screenToWorld: (screenX: number, screenY: number) => Point;\n}\n\n/**\n * Handles mouse, touch, and keyboard input\n * Normalizes events and converts coordinates\n */\nexport class InputHandler extends EventEmitter<InputEvents> {\n private readonly canvas: HTMLCanvasElement;\n private screenToWorld: (screenX: number, screenY: number) => Point;\n private boundHandlers = new Map<string, EventListener>();\n private lastTouchDistance: number | null = null;\n private lastTouchCenter: Point | null = null;\n\n constructor(options: InputHandlerOptions) {\n super();\n this.canvas = options.canvas;\n this.screenToWorld = options.screenToWorld;\n this.setupEventListeners();\n }\n\n /**\n * Update the coordinate transform function\n */\n setScreenToWorld(fn: (screenX: number, screenY: number) => Point): void {\n this.screenToWorld = fn;\n }\n\n /**\n * Clean up event listeners\n */\n destroy(): void {\n for (const [eventName, handler] of this.boundHandlers) {\n if (eventName.startsWith('key')) {\n window.removeEventListener(eventName, handler);\n } else {\n this.canvas.removeEventListener(eventName, handler);\n }\n }\n this.boundHandlers.clear();\n this.removeAllListeners();\n }\n\n private setupEventListeners(): void {\n // Mouse events\n this.addCanvasListener('click', this.handleClick.bind(this));\n this.addCanvasListener('dblclick', this.handleDblClick.bind(this));\n this.addCanvasListener('mousedown', this.handleMouseDown.bind(this));\n this.addCanvasListener('mouseup', this.handleMouseUp.bind(this));\n this.addCanvasListener('mousemove', this.handleMouseMove.bind(this));\n this.addCanvasListener('wheel', this.handleWheel.bind(this), { passive: false });\n\n // Touch events\n this.addCanvasListener('touchstart', this.handleTouchStart.bind(this));\n this.addCanvasListener('touchend', this.handleTouchEnd.bind(this));\n this.addCanvasListener('touchmove', this.handleTouchMove.bind(this));\n\n // Keyboard events (on window)\n this.addWindowListener('keydown', this.handleKeyDown.bind(this));\n this.addWindowListener('keyup', this.handleKeyUp.bind(this));\n\n // Prevent context menu on canvas\n this.addCanvasListener('contextmenu', (e) => e.preventDefault());\n }\n\n private addCanvasListener(\n eventName: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void {\n this.canvas.addEventListener(eventName, handler, options);\n this.boundHandlers.set(eventName, handler);\n }\n\n private addWindowListener(eventName: string, handler: EventListener): void {\n window.addEventListener(eventName, handler);\n this.boundHandlers.set(eventName, handler);\n }\n\n private handleClick(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('click', event);\n }\n\n private handleDblClick(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('dblclick', event);\n }\n\n private handleMouseDown(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('mousedown', event);\n }\n\n private handleMouseUp(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('mouseup', event);\n }\n\n private handleMouseMove(e: Event): void {\n const event = this.normalizeMouseEvent(e as MouseEvent);\n this.emit('mousemove', event);\n }\n\n private handleWheel(e: Event): void {\n e.preventDefault();\n const wheelEvent = e as WheelEvent;\n const baseEvent = this.normalizeMouseEvent(wheelEvent);\n const event: WheelInputEvent = {\n ...baseEvent,\n deltaX: wheelEvent.deltaX,\n deltaY: wheelEvent.deltaY,\n deltaZ: wheelEvent.deltaZ,\n originalEvent: wheelEvent,\n };\n this.emit('wheel', event);\n }\n\n private handleTouchStart(e: Event): void {\n const event = this.normalizeTouchEvent(e as TouchEvent);\n if (event !== null) {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length >= 2) {\n const { distance, center } = this.getTouchDistanceAndCenter(touchEvent);\n this.lastTouchDistance = distance;\n this.lastTouchCenter = center;\n return;\n }\n this.emit('mousedown', event);\n }\n }\n\n private handleTouchEnd(e: Event): void {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length < 2) {\n this.lastTouchDistance = null;\n this.lastTouchCenter = null;\n }\n\n const event = this.normalizeTouchEvent(touchEvent);\n if (event !== null) {\n this.emit('mouseup', event);\n }\n }\n\n private handleTouchMove(e: Event): void {\n const touchEvent = e as TouchEvent;\n if (touchEvent.touches.length >= 2) {\n const { distance, center } = this.getTouchDistanceAndCenter(touchEvent);\n if (this.lastTouchDistance !== null && this.lastTouchCenter !== null) {\n const deltaX = center.x - this.lastTouchCenter.x;\n const deltaY = center.y - this.lastTouchCenter.y;\n const scale = distance / this.lastTouchDistance;\n\n const worldPos = this.screenToWorld(center.x, center.y);\n const baseEvent: InputEvent = {\n screenX: center.x,\n screenY: center.y,\n worldX: worldPos.x,\n worldY: worldPos.y,\n button: 0,\n ctrlKey: touchEvent.ctrlKey,\n shiftKey: touchEvent.shiftKey,\n altKey: touchEvent.altKey,\n metaKey: touchEvent.metaKey,\n originalEvent: touchEvent,\n };\n\n if (deltaX !== 0 || deltaY !== 0) {\n this.emit('pan', { ...baseEvent, deltaX, deltaY });\n }\n if (scale !== 1) {\n this.emit('pinch', { ...baseEvent, scale });\n }\n }\n\n this.lastTouchDistance = distance;\n this.lastTouchCenter = center;\n return;\n }\n\n const event = this.normalizeTouchEvent(touchEvent);\n if (event !== null) {\n this.emit('mousemove', event);\n }\n }\n\n private handleKeyDown(e: Event): void {\n // Only handle if canvas has focus or no element is focused\n if (this.shouldHandleKeyboard()) {\n this.emit('keydown', e as KeyboardEvent);\n }\n }\n\n private handleKeyUp(e: Event): void {\n if (this.shouldHandleKeyboard()) {\n this.emit('keyup', e as KeyboardEvent);\n }\n }\n\n private shouldHandleKeyboard(): boolean {\n const active = document.activeElement;\n if (\n active === null ||\n active === document.body ||\n active === this.canvas ||\n active.tagName === 'CANVAS'\n ) {\n return true;\n }\n\n if (active instanceof HTMLElement) {\n if (active.isContentEditable) {\n return false;\n }\n\n const tag = active.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') {\n return false;\n }\n }\n\n return true;\n }\n\n private normalizeMouseEvent(e: MouseEvent): InputEvent {\n const worldPos = this.screenToWorld(e.clientX, e.clientY);\n return {\n screenX: e.clientX,\n screenY: e.clientY,\n worldX: worldPos.x,\n worldY: worldPos.y,\n button: e.button,\n ctrlKey: e.ctrlKey,\n shiftKey: e.shiftKey,\n altKey: e.altKey,\n metaKey: e.metaKey,\n originalEvent: e,\n };\n }\n\n private normalizeTouchEvent(e: TouchEvent): InputEvent | null {\n const touch = e.touches[0] ?? e.changedTouches[0];\n if (touch === undefined) {\n return null;\n }\n\n const worldPos = this.screenToWorld(touch.clientX, touch.clientY);\n return {\n screenX: touch.clientX,\n screenY: touch.clientY,\n worldX: worldPos.x,\n worldY: worldPos.y,\n button: 0,\n ctrlKey: e.ctrlKey,\n shiftKey: e.shiftKey,\n altKey: e.altKey,\n metaKey: e.metaKey,\n originalEvent: e,\n };\n }\n\n private getTouchDistanceAndCenter(event: TouchEvent): { distance: number; center: Point } {\n const [t1, t2] = [event.touches[0], event.touches[1]];\n if (!t1 || !t2) {\n return { distance: 0, center: { x: 0, y: 0 } };\n }\n\n const dx = t2.clientX - t1.clientX;\n const dy = t2.clientY - t1.clientY;\n const center = {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n };\n\n return { distance: Math.hypot(dx, dy), center };\n }\n}\n","import type { Bounds, Point } from '@/types';\n\n/**\n * Calculate distance between two points\n */\nexport function distance(p1: Point, p2: Point): number {\n const dx = p2.x - p1.x;\n const dy = p2.y - p1.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * Calculate distance from point to line segment\n */\nexport function distanceToSegment(point: Point, segStart: Point, segEnd: Point): number {\n const dx = segEnd.x - segStart.x;\n const dy = segEnd.y - segStart.y;\n const lengthSq = dx * dx + dy * dy;\n\n if (lengthSq === 0) {\n return distance(point, segStart);\n }\n\n let t = ((point.x - segStart.x) * dx + (point.y - segStart.y) * dy) / lengthSq;\n t = Math.max(0, Math.min(1, t));\n\n const projX = segStart.x + t * dx;\n const projY = segStart.y + t * dy;\n\n return distance(point, { x: projX, y: projY });\n}\n\n/**\n * Check if a point is inside a rectangle\n */\nexport function pointInRect(point: Point, rect: Bounds): boolean {\n return (\n point.x >= rect.x &&\n point.x <= rect.x + rect.width &&\n point.y >= rect.y &&\n point.y <= rect.y + rect.height\n );\n}\n\n/**\n * Check if two rectangles intersect\n */\nexport function rectsIntersect(a: Bounds, b: Bounds): boolean {\n return (\n a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y\n );\n}\n\n/**\n * Calculate the intersection of two rectangles\n */\nexport function rectIntersection(a: Bounds, b: Bounds): Bounds | null {\n const x = Math.max(a.x, b.x);\n const y = Math.max(a.y, b.y);\n const right = Math.min(a.x + a.width, b.x + b.width);\n const bottom = Math.min(a.y + a.height, b.y + b.height);\n\n if (right > x && bottom > y) {\n return { x, y, width: right - x, height: bottom - y };\n }\n\n return null;\n}\n\n/**\n * Calculate the union of two rectangles\n */\nexport function rectUnion(a: Bounds, b: Bounds): Bounds {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n const right = Math.max(a.x + a.width, b.x + b.width);\n const bottom = Math.max(a.y + a.height, b.y + b.height);\n\n return { x, y, width: right - x, height: bottom - y };\n}\n\n/**\n * Check if a point is inside an ellipse\n */\nexport function pointInEllipse(point: Point, center: Point, radiusX: number, radiusY: number): boolean {\n const dx = point.x - center.x;\n const dy = point.y - center.y;\n return (dx * dx) / (radiusX * radiusX) + (dy * dy) / (radiusY * radiusY) <= 1;\n}\n\n/**\n * Calculate angle between two points (in radians)\n */\nexport function angle(from: Point, to: Point): number {\n return Math.atan2(to.y - from.y, to.x - from.x);\n}\n\n/**\n * Rotate a point around a center\n */\nexport function rotatePoint(point: Point, center: Point, angleRad: number): Point {\n const cos = Math.cos(angleRad);\n const sin = Math.sin(angleRad);\n const dx = point.x - center.x;\n const dy = point.y - center.y;\n\n return {\n x: center.x + dx * cos - dy * sin,\n y: center.y + dx * sin + dy * cos,\n };\n}\n\n/**\n * Linear interpolation between two points\n */\nexport function lerp(a: Point, b: Point, t: number): Point {\n return {\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n };\n}\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/**\n * Snap a value to a grid\n */\nexport function snapToGrid(value: number, gridSize: number): number {\n return Math.round(value / gridSize) * gridSize;\n}\n\n/**\n * Snap a point to a grid\n */\nexport function snapPointToGrid(point: Point, gridSize: number): Point {\n return {\n x: snapToGrid(point.x, gridSize),\n y: snapToGrid(point.y, gridSize),\n };\n}\n\n/**\n * Expand bounds by a given amount\n */\nexport function expandBounds(bounds: Bounds, amount: number): Bounds {\n return {\n x: bounds.x - amount,\n y: bounds.y - amount,\n width: bounds.width + amount * 2,\n height: bounds.height + amount * 2,\n };\n}\n\n/**\n * Get center point of bounds\n */\nexport function boundsCenter(bounds: Bounds): Point {\n return {\n x: bounds.x + bounds.width / 2,\n y: bounds.y + bounds.height / 2,\n };\n}\n\n/**\n * Calculate control points for a cubic Bézier curve between two points\n * Returns array of 4 points: [start, control1, control2, end]\n */\nexport function calculateBezierControlPoints(\n from: Point,\n to: Point,\n maxOffset = 100,\n offsetFactor = 0.5\n): [Point, Point, Point, Point] {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const offset = Math.min(Math.abs(dx), Math.abs(dy), maxOffset) * offsetFactor;\n\n // Horizontal dominant\n if (Math.abs(dx) > Math.abs(dy)) {\n const offsetX = offset * Math.sign(dx || 1);\n return [\n from,\n { x: from.x + offsetX, y: from.y },\n { x: to.x - offsetX, y: to.y },\n to,\n ];\n }\n\n // Vertical dominant\n return [\n from,\n { x: from.x, y: from.y + offset * Math.sign(dy) },\n { x: to.x, y: to.y - offset * Math.sign(dy) },\n to,\n ];\n}\n\n/**\n * Calculate a point on a cubic Bézier curve at parameter t\n */\nexport function bezierPoint(p0: Point, p1: Point, p2: Point, p3: Point, t: number): Point {\n const mt = 1 - t;\n return {\n x: mt * mt * mt * p0.x + 3 * mt * mt * t * p1.x + 3 * mt * t * t * p2.x + t * t * t * p3.x,\n y: mt * mt * mt * p0.y + 3 * mt * mt * t * p1.y + 3 * mt * t * t * p2.y + t * t * t * p3.y,\n };\n}\n\n/**\n * Merge multiple bounds into a single bounding box.\n * Returns null if the iterable is empty.\n */\nexport function mergeBounds(\n sources: Iterable<{ x: number; y: number; width: number; height: number }>\n): Bounds | null {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let hasContent = false;\n\n for (const b of sources) {\n minX = Math.min(minX, b.x);\n minY = Math.min(minY, b.y);\n maxX = Math.max(maxX, b.x + b.width);\n maxY = Math.max(maxY, b.y + b.height);\n hasContent = true;\n }\n\n return hasContent ? { x: minX, y: minY, width: maxX - minX, height: maxY - minY } : null;\n}\n\n/**\n * Create a shallow copy of an array of points.\n */\nexport function clonePoints(points: Point[]): Point[] {\n return points.map((p) => ({ ...p }));\n}\n\n/**\n * Draw a rounded rectangle path\n */\nexport function drawRoundedRectPath(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number\n): void {\n const r = Math.min(radius, width / 2, height / 2);\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + r);\n ctx.lineTo(x + width, y + height - r);\n ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n ctx.lineTo(x + r, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n}\n","/**\n * Centralized constants for the diagram library\n */\n\n// Edge rendering\nexport const EDGE_HANDLE_RADIUS = 6;\nexport const EDGE_CONTROL_POINT_RADIUS = 6;\nexport const EDGE_ADD_CONTROL_RADIUS = 4;\nexport const ARROW_SIZE = 10;\nexport const ARROW_ANGLE = Math.PI / 6; // 30 degrees\n\n// Marker sizes\nexport const MARKER_SIZES: Record<string, number> = {\n arrow: 12,\n open: 12,\n diamond: 14,\n circle: 6,\n};\n\n// Edge label\nexport const EDGE_LABEL_BACKGROUND_PADDING = 4;\nexport const EDGE_LABEL_BACKGROUND_RADIUS = 2;\n\n// Resize handles\nexport const RESIZE_HANDLE_SIZE = 8;\nexport const RESIZE_HANDLE_OFFSET = 6;\n\n// Anchor points\nexport const ANCHOR_POINT_RADIUS = 4;\nexport const ANCHOR_POINT_HOVER_RADIUS = 6;\nexport const ANCHOR_POINT_HITBOX_RADIUS = 10;\nexport const NODE_HITBOX_PADDING = 10;\n\n// Anchor points\nexport const ANCHOR_PORT_PREFIX = 'anchor:';\n\n// Bezier curve calculation\nexport const BEZIER_MAX_OFFSET = 100;\n\n/** Screen distance (px) within which edge endpoint snaps to shape outline when attachToOutline */\nexport const OUTLINE_SNAP_SCREEN_TOLERANCE = 40;\n\n// Selection\nexport const SELECTION_RECT_MIN_SIZE = 1;\nexport const DEFAULT_SELECTION_COLOR = '#3b82f6';\nexport const DEFAULT_HOVER_COLOR = '#6366f1';\n\n// Drag\n/** Minimum distance (world units) to start a drag */\nexport const DRAG_START_THRESHOLD = 3;\n/** Screen tolerance for alignment guides when dragging */\nexport const ALIGNMENT_SCREEN_TOLERANCE = 8;\n\n// Editable polyline\n/** Max distance (world units) for control point to be considered orthogonal to endpoint */\nexport const EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE = 6;\n/** Screen tolerance for axis magnet when dragging editable polyline control points */\nexport const EDGE_AXIS_MAGNET_SCREEN_TOLERANCE = 10;\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { Bounds, Point } from '@/types';\nimport { rectsIntersect } from '@/utils/geometry';\nimport { SELECTION_RECT_MIN_SIZE, DEFAULT_SELECTION_COLOR } from '@/constants';\n\n/**\n * Selection events\n */\nexport interface SelectionEvents {\n select: [selectedIds: string[]];\n selectionStart: [point: Point];\n selectionMove: [bounds: Bounds];\n selectionEnd: [bounds: Bounds];\n}\n\n/**\n * Manages element selection\n */\nexport class SelectionManager extends EventEmitter<SelectionEvents> {\n private renderer: DiagramRenderer;\n private _selectedIds = new Set<string>();\n private selectionStart: Point | null = null;\n private selectionRect: Bounds | null = null;\n\n constructor(renderer: DiagramRenderer) {\n super();\n this.renderer = renderer;\n }\n\n /**\n * Currently selected element IDs\n */\n get selectedIds(): ReadonlySet<string> {\n return this._selectedIds;\n }\n\n /**\n * Current selection rectangle (during drag selection)\n */\n get selectionRectangle(): Bounds | null {\n return this.selectionRect;\n }\n\n /**\n * Check if an element is selected\n */\n isSelected(elementId: string): boolean {\n return this._selectedIds.has(elementId);\n }\n\n /**\n * Select a single element\n */\n select(elementId: string): void {\n this.clearSelection();\n this._selectedIds.add(elementId);\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Add element to selection\n */\n addToSelection(elementId: string): void {\n this._selectedIds.add(elementId);\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Remove element from selection\n */\n removeFromSelection(elementId: string): void {\n this._selectedIds.delete(elementId);\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Toggle element selection\n */\n toggleSelection(elementId: string): void {\n if (this._selectedIds.has(elementId)) {\n this._selectedIds.delete(elementId);\n } else {\n this._selectedIds.add(elementId);\n }\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Select multiple elements\n */\n selectMultiple(elementIds: string[]): void {\n this.clearSelection();\n for (const id of elementIds) {\n this._selectedIds.add(id);\n }\n this.updateElementStates();\n this.emitSelect();\n }\n\n /**\n * Clear all selections\n */\n clearSelection(): void {\n if (this._selectedIds.size > 0) {\n this._selectedIds.clear();\n this.updateElementStates();\n this.emitSelect();\n }\n }\n\n /**\n * Handle click event\n */\n handleClick(event: InputEvent): void {\n const point = { x: event.worldX, y: event.worldY };\n const element = this.renderer.getElementAtPoint(point);\n\n if (element === undefined) {\n if (!event.ctrlKey && !event.metaKey) {\n this.clearSelection();\n }\n return;\n }\n\n if (event.ctrlKey || event.metaKey) {\n this.toggleSelection(element.id);\n } else {\n this.select(element.id);\n }\n }\n\n /**\n * Start selection rectangle\n */\n startSelectionRect(point: Point): void {\n this.selectionStart = point;\n this.selectionRect = { x: point.x, y: point.y, width: 0, height: 0 };\n this.emit('selectionStart', point);\n }\n\n /**\n * Update selection rectangle\n */\n updateSelectionRect(point: Point): void {\n if (this.selectionStart === null) {\n return;\n }\n\n const x = Math.min(this.selectionStart.x, point.x);\n const y = Math.min(this.selectionStart.y, point.y);\n const width = Math.abs(point.x - this.selectionStart.x);\n const height = Math.abs(point.y - this.selectionStart.y);\n\n this.selectionRect = { x, y, width, height };\n this.emit('selectionMove', this.selectionRect);\n this.renderer.markDirty();\n }\n\n /**\n * End selection rectangle and select enclosed elements\n */\n endSelectionRect(): void {\n if (this.selectionRect === null) {\n return;\n }\n\n const rect = this.selectionRect;\n const selected: string[] = [];\n\n // Find nodes within selection rect\n for (const node of this.renderer.nodes.values()) {\n const bounds = node.getBounds();\n if (rectsIntersect(rect, bounds)) {\n selected.push(node.id);\n }\n }\n\n // Find groups within selection rect\n for (const group of this.renderer.groups.values()) {\n const bounds = group.getBounds();\n if (rectsIntersect(rect, bounds)) {\n selected.push(group.id);\n }\n }\n\n if (selected.length > 0) {\n this.selectMultiple(selected);\n }\n\n this.emit('selectionEnd', rect);\n this.selectionStart = null;\n this.selectionRect = null;\n this.renderer.markDirty();\n }\n\n /**\n * Cancel selection rectangle\n */\n cancelSelectionRect(): void {\n this.selectionStart = null;\n this.selectionRect = null;\n this.renderer.markDirty();\n }\n\n /**\n * Render selection rectangle\n */\n renderSelectionRect(ctx: CanvasRenderingContext2D): void {\n if (this.selectionRect === null) {\n return;\n }\n\n const { x, y, width, height } = this.selectionRect;\n\n // Skip if rectangle is too small (just started)\n if (width < SELECTION_RECT_MIN_SIZE && height < SELECTION_RECT_MIN_SIZE) {\n return;\n }\n\n ctx.fillStyle = 'rgba(59, 130, 246, 0.15)';\n ctx.fillRect(x, y, width, height);\n\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([5, 3]);\n ctx.strokeRect(x, y, width, height);\n ctx.setLineDash([]);\n }\n\n private updateElementStates(): void {\n const updateState = (elements: Iterable<{ id: string; state: string }>): void => {\n for (const element of elements) {\n if (this._selectedIds.has(element.id)) {\n element.state = 'selected';\n } else if (element.state === 'selected') {\n element.state = 'normal';\n }\n }\n };\n\n updateState(this.renderer.nodes.values());\n updateState(this.renderer.edges.values());\n updateState(this.renderer.groups.values());\n\n this.renderer.markDirty();\n this.renderer.markStyleDirty();\n }\n\n private emitSelect(): void {\n this.emit('select', Array.from(this._selectedIds));\n this.renderer.emit('select', Array.from(this._selectedIds));\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { SelectionManager } from './SelectionManager';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { Node } from '@/elements/Node';\nimport type { Bounds, Point } from '@/types';\nimport { ALIGNMENT_SCREEN_TOLERANCE, DRAG_START_THRESHOLD, EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE } from '@/constants';\nimport { distance, mergeBounds, clonePoints, rectsIntersect } from '@/utils/geometry';\n\ninterface AlignmentGuide {\n orientation: 'vertical' | 'horizontal';\n position: number;\n from: number;\n to: number;\n}\n\n/**\n * Drag events\n */\nexport interface DragEvents {\n dragstart: [nodeIds: string[], startPoint: Point];\n drag: [nodeIds: string[], currentPoint: Point, delta: Point];\n dragend: [nodeIds: string[], endPoint: Point];\n}\n\nexport interface DragManagerOptions {\n renderer: DiagramRenderer;\n selectionManager: SelectionManager;\n snapToGrid?: boolean;\n gridSize?: number;\n alignToNodes?: boolean;\n}\n\n/**\n * Manages node dragging\n */\nexport class DragManager extends EventEmitter<DragEvents> {\n private renderer: DiagramRenderer;\n private selectionManager: SelectionManager;\n private snapToGrid: boolean;\n private gridSize: number;\n private alignToNodes: boolean;\n\n private isDragging = false;\n private draggedNodes: Node[] = [];\n private dragStartPoint: Point | null = null;\n private lastDragPoint: Point | null = null;\n private initialPositions = new Map<string, Point>();\n private editableBendFollow = new Map<\n string,\n Array<{ edgeId: string; controlPointIndex: number; axis: 'vertical' | 'horizontal' }>\n >();\n /** Edges (editable-polyline) where both endpoints are in selection — control points follow delta */\n private editablePolylineFullyConnectedEdges = new Set<string>();\n /** Snapshot of control points at drag start for cancel/restore */\n private initialControlPointsForFullyConnected = new Map<string, Point[]>();\n private alignmentGuides: AlignmentGuide[] = [];\n private _handledMouseDown = false;\n private draggedGroupSelection = false;\n\n constructor(options: DragManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.selectionManager = options.selectionManager;\n this.snapToGrid = options.snapToGrid ?? false;\n this.gridSize = options.gridSize ?? 20;\n this.alignToNodes = options.alignToNodes ?? true;\n }\n\n /**\n * Check if currently dragging\n */\n get dragging(): boolean {\n return this.isDragging;\n }\n\n /**\n * Check if last mousedown was handled (for skipping click handling)\n */\n get handledMouseDown(): boolean {\n return this._handledMouseDown;\n }\n\n renderAlignmentGuides(ctx: CanvasRenderingContext2D): void {\n if (!this.alignToNodes || !this.isDragging || this.alignmentGuides.length === 0) {\n return;\n }\n\n const zoom = Math.max(this.renderer.zoom, 0.0001);\n ctx.save();\n ctx.setLineDash([6 / zoom, 4 / zoom]);\n ctx.strokeStyle = '#6366f1';\n ctx.lineWidth = 1.5 / zoom;\n\n for (const guide of this.alignmentGuides) {\n ctx.beginPath();\n if (guide.orientation === 'vertical') {\n ctx.moveTo(guide.position, guide.from);\n ctx.lineTo(guide.position, guide.to);\n } else {\n ctx.moveTo(guide.from, guide.position);\n ctx.lineTo(guide.to, guide.position);\n }\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Enable/disable snap to grid\n */\n setSnapToGrid(enabled: boolean, gridSize?: number): void {\n this.snapToGrid = enabled;\n if (gridSize !== undefined) {\n this.gridSize = gridSize;\n }\n }\n\n /**\n * Enable/disable smart alignment to other nodes while dragging.\n */\n setAlignmentEnabled(enabled: boolean): void {\n this.alignToNodes = enabled;\n if (!enabled && this.alignmentGuides.length > 0) {\n this.alignmentGuides = [];\n this.renderer.markDirty();\n }\n }\n\n /**\n * Handle mouse down - start potential drag\n */\n handleMouseDown(event: InputEvent): boolean {\n // Reset handledMouseDown at the start of new interaction\n this._handledMouseDown = false;\n\n const point = { x: event.worldX, y: event.worldY };\n const element = this.renderer.getElementAtPoint(point);\n\n if (element === undefined) {\n return false;\n }\n\n // Check if it's a node\n const node = this.renderer.getNode(element.id);\n const group = node === undefined ? this.renderer.getGroup(element.id) : undefined;\n const edge =\n node === undefined && group === undefined ? this.renderer.getEdge(element.id) : undefined;\n if (node === undefined && group === undefined && edge === undefined) {\n return false;\n }\n\n // Edge dragging: allow dragging selected nodes through edge hit area.\n // Useful for relation anchors that are hidden and hard to click directly.\n if (edge !== undefined) {\n if (edge.state !== 'selected') {\n return false;\n }\n const hasSelectedNodes = Array.from(this.selectionManager.selectedIds).some(\n (id) => this.renderer.getNode(id) !== undefined\n );\n if (!hasSelectedNodes) {\n return false;\n }\n this._handledMouseDown = true;\n this.dragStartPoint = point;\n this.lastDragPoint = point;\n this.draggedGroupSelection = false;\n this.draggedNodes = [];\n this.initialPositions.clear();\n for (const id of this.selectionManager.selectedIds) {\n const selectedNode = this.renderer.getNode(id);\n if (selectedNode !== undefined) {\n this.addDraggedNode(selectedNode);\n }\n }\n return this.draggedNodes.length > 0;\n }\n\n const targetId = node?.id ?? group!.id;\n\n // Handle selection based on modifier keys\n if (!this.selectionManager.isSelected(targetId)) {\n if (event.ctrlKey || event.metaKey) {\n // Ctrl+click on unselected: add to selection\n this.selectionManager.addToSelection(targetId);\n } else {\n // Regular click on unselected: select only this element\n this.selectionManager.select(targetId);\n }\n // Mark as handled since we changed selection\n this._handledMouseDown = true;\n }\n // If already selected - don't mark as handled yet\n // Let click event handle toggle (Ctrl+click) or re-select (regular click)\n // We'll mark as handled if actual drag starts\n\n // Prepare for drag\n this.dragStartPoint = point;\n this.lastDragPoint = point;\n this.draggedGroupSelection = false;\n\n // Get all selected nodes (expand groups to children)\n this.draggedNodes = [];\n for (const id of this.selectionManager.selectedIds) {\n const selectedNode = this.renderer.getNode(id);\n if (selectedNode !== undefined) {\n this.addDraggedNode(selectedNode);\n continue;\n }\n\n const selectedGroup = this.renderer.getGroup(id);\n if (selectedGroup !== undefined) {\n this.draggedGroupSelection = true;\n for (const child of selectedGroup.getAllChildren()) {\n const childNode = this.renderer.getNode(child.id);\n if (childNode) {\n this.addDraggedNode(childNode);\n }\n }\n }\n }\n\n return true;\n }\n\n /**\n * Handle mouse move - update drag\n */\n handleMouseMove(event: InputEvent): boolean {\n if (this.dragStartPoint === null) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n\n // Check if we've moved enough to start dragging\n if (!this.isDragging) {\n const dist = distance(point, this.dragStartPoint);\n\n if (dist < DRAG_START_THRESHOLD) {\n return false;\n }\n\n // Start dragging\n this.isDragging = true;\n this._handledMouseDown = true; // Mark as handled now that drag started\n this.buildEditableBendFollowBindings();\n this.alignmentGuides = [];\n for (const node of this.draggedNodes) {\n node.state = 'dragging';\n }\n this.emit(\n 'dragstart',\n this.draggedNodes.map((n) => n.id),\n this.dragStartPoint\n );\n }\n\n // Calculate total offset from drag start (not incremental delta)\n const totalDelta = {\n x: point.x - this.dragStartPoint.x,\n y: point.y - this.dragStartPoint.y,\n };\n\n // Delta from last point (for event)\n const delta = {\n x: point.x - this.lastDragPoint!.x,\n y: point.y - this.lastDragPoint!.y,\n };\n\n const alignedDelta = this.resolveAlignmentDelta(totalDelta);\n\n // Move nodes using initial position + total offset\n let firstDelta: Point | null = null;\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (initial === undefined) continue;\n const prevX = node.x;\n const prevY = node.y;\n\n let newX = initial.x + alignedDelta.x;\n let newY = initial.y + alignedDelta.y;\n\n if (this.snapToGrid) {\n newX = Math.round(newX / this.gridSize) * this.gridSize;\n newY = Math.round(newY / this.gridSize) * this.gridSize;\n }\n\n node.x = newX;\n node.y = newY;\n const dx = newX - prevX;\n const dy = newY - prevY;\n if (firstDelta === null) {\n firstDelta = { x: dx, y: dy };\n }\n this.followNearestEditableBend(node.id, dx, dy);\n }\n\n if (firstDelta !== null) {\n this.followEditableBendForFullyConnectedEdges(firstDelta.x, firstDelta.y);\n }\n this.emit(\n 'drag',\n this.draggedNodes.map((n) => n.id),\n point,\n delta\n );\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Handle mouse up - end drag\n */\n handleMouseUp(event: InputEvent): boolean {\n if (this.dragStartPoint === null) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const wasDragging = this.isDragging;\n\n if (this.isDragging) {\n // Restore selected state\n for (const node of this.draggedNodes) {\n node.state = 'selected';\n }\n this.emit(\n 'dragend',\n this.draggedNodes.map((n) => n.id),\n point\n );\n if (this.draggedGroupSelection) {\n this.selectionManager.clearSelection();\n }\n }\n\n this.reset();\n this.renderer.markDirty();\n\n return wasDragging;\n }\n\n /**\n * Cancel current drag operation\n */\n cancelDrag(): void {\n if (this.isDragging) {\n // Restore original positions\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (initial !== undefined) {\n node.x = initial.x;\n node.y = initial.y;\n }\n node.state = 'selected';\n }\n // Restore control points for fully-connected editable polyline edges\n for (const [edgeId, points] of this.initialControlPointsForFullyConnected) {\n const edge = this.renderer.getEdge(edgeId);\n if (edge) {\n edge.controlPoints = clonePoints(points);\n }\n }\n }\n\n this.reset();\n this.renderer.markDirty();\n }\n\n private addDraggedNode(node: Node): void {\n if (this.initialPositions.has(node.id)) {\n return;\n }\n this.draggedNodes.push(node);\n this.initialPositions.set(node.id, { x: node.x, y: node.y });\n }\n\n private reset(): void {\n this.isDragging = false;\n this.draggedNodes = [];\n this.dragStartPoint = null;\n this.lastDragPoint = null;\n this.initialPositions.clear();\n this.editableBendFollow.clear();\n this.editablePolylineFullyConnectedEdges.clear();\n this.initialControlPointsForFullyConnected.clear();\n this.alignmentGuides = [];\n this.draggedGroupSelection = false;\n // Note: _handledMouseDown is reset at the start of next handleMouseDown\n // to prevent click handler from firing after mouseup\n }\n\n private buildEditableBendFollowBindings(): void {\n this.editableBendFollow.clear();\n this.editablePolylineFullyConnectedEdges.clear();\n this.initialControlPointsForFullyConnected.clear();\n const draggedIds = new Set(this.draggedNodes.map((node) => node.id));\n const nodeBindings = new Map<string, Array<{ edgeId: string; controlPointIndex: number; axis: 'vertical' | 'horizontal' }>>();\n\n // Single pass: collect fully-connected edges and single-node bindings\n for (const edge of this.renderer.edges.values()) {\n if (!edge.hasEditableControlPoints()) {\n continue;\n }\n\n const isFromDragged = draggedIds.has(edge.from.nodeId);\n const isToDragged = draggedIds.has(edge.to.nodeId);\n\n if (isFromDragged && isToDragged) {\n this.editablePolylineFullyConnectedEdges.add(edge.id);\n this.initialControlPointsForFullyConnected.set(edge.id, clonePoints(edge.controlPoints!));\n continue;\n }\n\n for (const node of this.draggedNodes) {\n const isFrom = edge.from.nodeId === node.id;\n const isTo = edge.to.nodeId === node.id;\n if (!isFrom && !isTo) {\n continue;\n }\n\n const oppositeNodeId = isFrom ? edge.to.nodeId : edge.from.nodeId;\n if (draggedIds.has(oppositeNodeId)) {\n continue;\n }\n\n const controlPointIndex = isFrom ? 0 : edge.controlPoints!.length - 1;\n const nearestPoint = edge.controlPoints![controlPointIndex]!;\n const endpoint = isFrom ? edge.startPoint : edge.endPoint;\n const deltaX = Math.abs(nearestPoint.x - endpoint.x);\n const deltaY = Math.abs(nearestPoint.y - endpoint.y);\n\n if (deltaX <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE && deltaY <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE) {\n continue;\n }\n\n let axis: 'vertical' | 'horizontal' | null = null;\n if (deltaX <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE || deltaX <= deltaY) {\n axis = 'vertical';\n } else if (deltaY <= EDITABLE_POLYLINE_ORTHOGONAL_TOLERANCE || deltaY < deltaX) {\n axis = 'horizontal';\n }\n\n if (!axis) {\n continue;\n }\n\n const bindings = nodeBindings.get(node.id) ?? [];\n bindings.push({ edgeId: edge.id, controlPointIndex, axis });\n nodeBindings.set(node.id, bindings);\n }\n }\n\n for (const [nodeId, bindings] of nodeBindings) {\n if (bindings.length > 0) {\n this.editableBendFollow.set(nodeId, bindings);\n }\n }\n }\n\n private followNearestEditableBend(nodeId: string, deltaX: number, deltaY: number): void {\n const bindings = this.editableBendFollow.get(nodeId);\n if (!bindings || bindings.length === 0) {\n return;\n }\n\n for (const binding of bindings) {\n const edge = this.renderer.getEdge(binding.edgeId);\n if (!edge?.controlPoints) {\n continue;\n }\n if (binding.controlPointIndex < 0 || binding.controlPointIndex >= edge.controlPoints.length) {\n continue;\n }\n\n const nextControlPoints = [...edge.controlPoints];\n const point = { ...nextControlPoints[binding.controlPointIndex]! };\n if (binding.axis === 'vertical' && deltaX !== 0) {\n point.x += deltaX;\n } else if (binding.axis === 'horizontal' && deltaY !== 0) {\n point.y += deltaY;\n } else {\n continue;\n }\n nextControlPoints[binding.controlPointIndex] = point;\n edge.controlPoints = nextControlPoints;\n }\n }\n\n /**\n * For editable-polyline edges where both endpoints are dragged:\n * move all control points by the same delta to preserve relative positions.\n */\n private followEditableBendForFullyConnectedEdges(deltaX: number, deltaY: number): void {\n if (deltaX === 0 && deltaY === 0) {\n return;\n }\n for (const edgeId of this.editablePolylineFullyConnectedEdges) {\n const edge = this.renderer.getEdge(edgeId);\n if (!edge?.controlPoints || edge.controlPoints.length === 0) {\n continue;\n }\n const nextControlPoints = edge.controlPoints.map((p) => ({\n x: p.x + deltaX,\n y: p.y + deltaY,\n }));\n edge.controlPoints = nextControlPoints;\n }\n }\n\n private resolveAlignmentDelta(totalDelta: Point): Point {\n this.alignmentGuides = [];\n if (!this.alignToNodes) {\n return totalDelta;\n }\n if (this.draggedNodes.length === 0) {\n return totalDelta;\n }\n\n const draggedBounds = this.getDraggedBounds(totalDelta);\n if (!draggedBounds) {\n return totalDelta;\n }\n\n const tolerance = ALIGNMENT_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n const draggedIds = new Set(this.draggedNodes.map((node) => node.id));\n const searchPadding = tolerance * 2;\n const searchBounds: Bounds = {\n x: draggedBounds.x - searchPadding,\n y: draggedBounds.y - searchPadding,\n width: draggedBounds.width + searchPadding * 2,\n height: draggedBounds.height + searchPadding * 2,\n };\n\n const movingXLines = [\n { key: 'start', value: draggedBounds.x },\n { key: 'center', value: draggedBounds.x + draggedBounds.width / 2 },\n { key: 'end', value: draggedBounds.x + draggedBounds.width },\n ];\n const movingYLines = [\n { key: 'start', value: draggedBounds.y },\n { key: 'center', value: draggedBounds.y + draggedBounds.height / 2 },\n { key: 'end', value: draggedBounds.y + draggedBounds.height },\n ];\n\n let bestVertical: {\n offset: number;\n x: number;\n fromY: number;\n toY: number;\n distance: number;\n } | null = null;\n let bestHorizontal: {\n offset: number;\n y: number;\n fromX: number;\n toX: number;\n distance: number;\n } | null = null;\n\n for (const node of this.renderer.nodes.values()) {\n if (!node.visible || draggedIds.has(node.id)) {\n continue;\n }\n const bounds = node.getBounds();\n if (!rectsIntersect(searchBounds, bounds)) {\n continue;\n }\n const targetXLines = [\n { key: 'start', value: bounds.x },\n { key: 'center', value: bounds.x + bounds.width / 2 },\n { key: 'end', value: bounds.x + bounds.width },\n ];\n const targetYLines = [\n { key: 'start', value: bounds.y },\n { key: 'center', value: bounds.y + bounds.height / 2 },\n { key: 'end', value: bounds.y + bounds.height },\n ];\n\n for (const moving of movingXLines) {\n for (const target of targetXLines) {\n if (moving.key !== target.key) {\n continue;\n }\n const dist = Math.abs(moving.value - target.value);\n if (dist > tolerance) {\n continue;\n }\n if (!bestVertical || dist < bestVertical.distance) {\n bestVertical = {\n offset: target.value - moving.value,\n x: target.value,\n fromY: Math.min(draggedBounds.y, bounds.y),\n toY: Math.max(draggedBounds.y + draggedBounds.height, bounds.y + bounds.height),\n distance: dist,\n };\n }\n }\n }\n\n for (const moving of movingYLines) {\n for (const target of targetYLines) {\n if (moving.key !== target.key) {\n continue;\n }\n const dist = Math.abs(moving.value - target.value);\n if (dist > tolerance) {\n continue;\n }\n if (!bestHorizontal || dist < bestHorizontal.distance) {\n bestHorizontal = {\n offset: target.value - moving.value,\n y: target.value,\n fromX: Math.min(draggedBounds.x, bounds.x),\n toX: Math.max(draggedBounds.x + draggedBounds.width, bounds.x + bounds.width),\n distance: dist,\n };\n }\n }\n }\n }\n\n const result = { ...totalDelta };\n if (bestVertical) {\n result.x += bestVertical.offset;\n this.alignmentGuides.push({\n orientation: 'vertical',\n position: bestVertical.x,\n from: bestVertical.fromY,\n to: bestVertical.toY,\n });\n }\n if (bestHorizontal) {\n result.y += bestHorizontal.offset;\n this.alignmentGuides.push({\n orientation: 'horizontal',\n position: bestHorizontal.y,\n from: bestHorizontal.fromX,\n to: bestHorizontal.toX,\n });\n }\n\n return result;\n }\n\n private getDraggedBounds(delta: Point): Bounds | null {\n const sources: Bounds[] = [];\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (!initial) continue;\n sources.push({\n x: initial.x + delta.x,\n y: initial.y + delta.y,\n width: node.width,\n height: node.height,\n });\n }\n return mergeBounds(sources);\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { SelectionManager } from './SelectionManager';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { Bounds, Point } from '@/types';\nimport type { ResizeHandle } from '@/elements/Node';\nimport { distance } from '@/utils/geometry';\n\n/**\n * Resize events\n */\nexport interface ResizeEvents {\n resizeStart: [nodeId: string, handle: ResizeHandle, startBounds: Bounds];\n resize: [nodeId: string, bounds: Bounds, delta: Point];\n resizeEnd: [nodeId: string, bounds: Bounds];\n}\n\nexport interface ResizeManagerOptions {\n renderer: DiagramRenderer;\n selectionManager: SelectionManager;\n snapToGrid?: boolean;\n gridSize?: number;\n minSize?: number;\n}\n\n/**\n * Manages node resizing via corner handles\n */\nexport class ResizeManager extends EventEmitter<ResizeEvents> {\n private renderer: DiagramRenderer;\n private selectionManager: SelectionManager;\n private snapToGrid: boolean;\n private gridSize: number;\n private readonly minSize: number;\n private minWidth: number;\n private minHeight: number;\n\n private isResizing = false;\n private resizedNodeId: string | null = null;\n private handle: ResizeHandle | null = null;\n private startPoint: Point | null = null;\n private startBounds: Bounds | null = null;\n private _handledMouseDown = false;\n\n constructor(options: ResizeManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.selectionManager = options.selectionManager;\n this.snapToGrid = options.snapToGrid ?? false;\n this.gridSize = options.gridSize ?? 20;\n this.minSize = options.minSize ?? 20;\n this.minWidth = this.minSize;\n this.minHeight = this.minSize;\n }\n\n /**\n * Check if currently resizing\n */\n get resizing(): boolean {\n return this.isResizing;\n }\n\n /**\n * Check if last mousedown was handled (for skipping click handling)\n */\n get handledMouseDown(): boolean {\n return this._handledMouseDown;\n }\n\n /**\n * Enable/disable snap to grid\n */\n setSnapToGrid(enabled: boolean, gridSize?: number): void {\n this.snapToGrid = enabled;\n if (gridSize !== undefined) {\n this.gridSize = gridSize;\n }\n }\n\n /**\n * Handle mouse down - start potential resize\n */\n handleMouseDown(event: InputEvent): boolean {\n this._handledMouseDown = false;\n\n const selectedIds = Array.from(this.selectionManager.selectedIds);\n if (selectedIds.length !== 1) {\n return false;\n }\n\n const node = this.renderer.getNode(selectedIds[0]!);\n if (!node) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const hit = node.hitTestResizeHandle(point);\n if (!hit) {\n return false;\n }\n\n this.resizedNodeId = node.id;\n this.handle = hit;\n this.startPoint = point;\n this.startBounds = node.getBounds();\n const contentMinSize = node.getContentMinSize(this.renderer.getContext());\n this.minWidth = Math.max(this.minSize, contentMinSize.width);\n this.minHeight = Math.max(this.minSize, contentMinSize.height);\n return true;\n }\n\n /**\n * Handle mouse move - update resize\n */\n handleMouseMove(event: InputEvent): boolean {\n if (!this.startPoint || !this.startBounds || !this.resizedNodeId || !this.handle) {\n return false;\n }\n\n const node = this.renderer.getNode(this.resizedNodeId);\n if (!node) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n\n if (!this.isResizing) {\n const dist = distance(point, this.startPoint);\n if (dist < 3) {\n return false;\n }\n this.isResizing = true;\n this._handledMouseDown = true;\n node.state = 'dragging';\n this.emit('resizeStart', node.id, this.handle, this.startBounds);\n }\n\n const bounds = this.calculateBounds(point);\n node.x = bounds.x;\n node.y = bounds.y;\n node.width = bounds.width;\n node.height = bounds.height;\n\n this.emit('resize', node.id, bounds, {\n x: bounds.x - this.startBounds.x,\n y: bounds.y - this.startBounds.y,\n });\n this.renderer.markDirty();\n return true;\n }\n\n /**\n * Handle mouse up - end resize\n */\n handleMouseUp(): boolean {\n if (!this.startPoint || !this.startBounds || !this.resizedNodeId) {\n return false;\n }\n\n const node = this.renderer.getNode(this.resizedNodeId);\n const wasResizing = this.isResizing;\n if (this.isResizing && node) {\n node.state = 'selected';\n this.emit('resizeEnd', node.id, node.getBounds());\n }\n\n this.reset();\n this.renderer.markDirty();\n return wasResizing;\n }\n\n /**\n * Cancel current resize operation\n */\n cancelResize(): void {\n if (this.isResizing && this.resizedNodeId && this.startBounds) {\n const node = this.renderer.getNode(this.resizedNodeId);\n if (node) {\n node.x = this.startBounds.x;\n node.y = this.startBounds.y;\n node.width = this.startBounds.width;\n node.height = this.startBounds.height;\n node.state = 'selected';\n }\n }\n\n this.reset();\n this.renderer.markDirty();\n }\n\n private calculateBounds(point: Point): Bounds {\n const start = this.startBounds!;\n const handle = this.handle!;\n const dx = point.x - this.startPoint!.x;\n const dy = point.y - this.startPoint!.y;\n\n let x = start.x;\n let y = start.y;\n let width = start.width;\n let height = start.height;\n\n if (handle.includes('e')) {\n width = start.width + dx;\n }\n if (handle.includes('s')) {\n height = start.height + dy;\n }\n if (handle.includes('w')) {\n x = start.x + dx;\n width = start.width - dx;\n }\n if (handle.includes('n')) {\n y = start.y + dy;\n height = start.height - dy;\n }\n\n ({ x, y, width, height } = this.applyMinSize(x, y, width, height, start, handle));\n\n if (this.snapToGrid) {\n const snap = (value: number): number => Math.round(value / this.gridSize) * this.gridSize;\n let right = x + width;\n let bottom = y + height;\n\n if (handle.includes('w')) {\n x = snap(x);\n }\n if (handle.includes('e')) {\n right = snap(right);\n }\n if (handle.includes('n')) {\n y = snap(y);\n }\n if (handle.includes('s')) {\n bottom = snap(bottom);\n }\n\n width = right - x;\n height = bottom - y;\n ({ x, y, width, height } = this.applyMinSize(x, y, width, height, start, handle));\n }\n\n return { x, y, width, height };\n }\n\n private applyMinSize(\n x: number,\n y: number,\n width: number,\n height: number,\n start: Bounds,\n handle: ResizeHandle\n ): Bounds {\n if (width < this.minWidth) {\n width = this.minWidth;\n if (handle.includes('w')) {\n x = start.x + start.width - this.minWidth;\n }\n }\n\n if (height < this.minHeight) {\n height = this.minHeight;\n if (handle.includes('n')) {\n y = start.y + start.height - this.minHeight;\n }\n }\n\n return { x, y, width, height };\n }\n\n private reset(): void {\n this.isResizing = false;\n this.resizedNodeId = null;\n this.handle = null;\n this.startPoint = null;\n this.startBounds = null;\n this.minWidth = this.minSize;\n this.minHeight = this.minSize;\n }\n}\n","import type { Bounds } from '@/types';\n\nexport interface BoundsSource {\n visible: boolean;\n getBounds(): Bounds;\n}\n\nexport interface ContentBoundsInput {\n nodes?: Iterable<BoundsSource>;\n edges?: Iterable<BoundsSource>;\n groups?: Iterable<BoundsSource>;\n includeInvisible?: boolean;\n}\n\nexport function getContentBounds({\n nodes,\n edges,\n groups,\n includeInvisible = false,\n}: ContentBoundsInput): Bounds | null {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let hasContent = false;\n\n const consider = (source: BoundsSource): void => {\n if (!includeInvisible && !source.visible) {\n return;\n }\n const bounds = source.getBounds();\n minX = Math.min(minX, bounds.x);\n minY = Math.min(minY, bounds.y);\n maxX = Math.max(maxX, bounds.x + bounds.width);\n maxY = Math.max(maxY, bounds.y + bounds.height);\n hasContent = true;\n };\n\n if (nodes) {\n for (const node of nodes) {\n consider(node);\n }\n }\n\n if (edges) {\n for (const edge of edges) {\n consider(edge);\n }\n }\n\n if (groups) {\n for (const group of groups) {\n consider(group);\n }\n }\n\n if (!hasContent) {\n return null;\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { InputEvent, WheelInputEvent, PanInputEvent, PinchInputEvent } from '@/events/InputHandler';\nimport type { Bounds, Point } from '@/types';\nimport { getContentBounds } from '@/utils/contentBounds';\n\n/**\n * Navigation events\n */\nexport interface NavigationEvents {\n panStart: [];\n pan: [offsetX: number, offsetY: number];\n panEnd: [];\n zoomChange: [zoom: number, center: Point];\n}\n\nexport interface NavigationManagerOptions {\n renderer: DiagramRenderer;\n zoomSensitivity?: number;\n panButton?: number;\n}\n\n/**\n * Manages canvas panning and zooming\n */\nexport class NavigationManager extends EventEmitter<NavigationEvents> {\n private renderer: DiagramRenderer;\n private readonly zoomSensitivity: number;\n private readonly panButton: number;\n\n private isPanning = false;\n private panStart: Point | null = null;\n private spacePressed = false;\n\n constructor(options: NavigationManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.zoomSensitivity = options.zoomSensitivity ?? 0.001;\n this.panButton = options.panButton ?? 1; // Middle mouse button\n }\n\n /**\n * Check if currently panning\n */\n get panning(): boolean {\n return this.isPanning;\n }\n\n /**\n * Handle wheel event for zooming\n */\n handleWheel(event: WheelInputEvent): void {\n const sensitivity = event.ctrlKey ? this.zoomSensitivity * 0.2 : this.zoomSensitivity;\n const zoomFactor = 1 - event.deltaY * sensitivity;\n const oldZoom = this.renderer.zoom;\n const oldOffsetX = this.renderer.offsetX;\n const oldOffsetY = this.renderer.offsetY;\n\n // World position under cursor (calculated with old zoom)\n const worldX = event.worldX;\n const worldY = event.worldY;\n\n // Apply new zoom\n this.renderer.zoom = oldZoom * zoomFactor;\n const actualNewZoom = this.renderer.zoom; // may be clamped by min/max\n\n // Adjust offset to keep cursor at same world position\n // Formula: newOffset = oldOffset + worldPos * (oldZoom - newZoom)\n this.renderer.offsetX = oldOffsetX + worldX * (oldZoom - actualNewZoom);\n this.renderer.offsetY = oldOffsetY + worldY * (oldZoom - actualNewZoom);\n\n this.emit('zoomChange', this.renderer.zoom, { x: worldX, y: worldY });\n }\n\n /**\n * Handle touch pan gesture\n */\n handlePanGesture(event: PanInputEvent): void {\n this.renderer.offsetX += event.deltaX;\n this.renderer.offsetY += event.deltaY;\n this.emit('pan', this.renderer.offsetX, this.renderer.offsetY);\n }\n\n /**\n * Handle touch pinch gesture\n */\n handlePinch(event: PinchInputEvent): void {\n const oldZoom = this.renderer.zoom;\n const oldOffsetX = this.renderer.offsetX;\n const oldOffsetY = this.renderer.offsetY;\n\n const worldX = event.worldX;\n const worldY = event.worldY;\n\n this.renderer.zoom = oldZoom * event.scale;\n const actualNewZoom = this.renderer.zoom;\n\n this.renderer.offsetX = oldOffsetX + worldX * (oldZoom - actualNewZoom);\n this.renderer.offsetY = oldOffsetY + worldY * (oldZoom - actualNewZoom);\n\n this.emit('zoomChange', this.renderer.zoom, { x: worldX, y: worldY });\n }\n\n /**\n * Handle mouse down for panning\n */\n handleMouseDown(event: InputEvent): boolean {\n // Middle mouse button or space+left click\n if (event.button === this.panButton || (this.spacePressed && event.button === 0)) {\n this.startPan(event);\n return true;\n }\n return false;\n }\n\n /**\n * Handle mouse move for panning\n */\n handleMouseMove(event: InputEvent): boolean {\n if (!this.isPanning || this.panStart === null) {\n return false;\n }\n\n const dx = event.screenX - this.panStart.x;\n const dy = event.screenY - this.panStart.y;\n\n this.renderer.offsetX += dx;\n this.renderer.offsetY += dy;\n\n this.panStart = { x: event.screenX, y: event.screenY };\n this.emit('pan', this.renderer.offsetX, this.renderer.offsetY);\n\n return true;\n }\n\n /**\n * Handle mouse up for panning\n */\n handleMouseUp(_event: InputEvent): boolean {\n if (!this.isPanning) {\n return false;\n }\n\n this.endPan();\n return true;\n }\n\n /**\n * Handle key down for space panning\n */\n handleKeyDown(event: KeyboardEvent): void {\n if (event.code === 'Space' && !this.spacePressed) {\n this.spacePressed = true;\n }\n }\n\n /**\n * Handle key up for space panning\n */\n handleKeyUp(event: KeyboardEvent): void {\n if (event.code === 'Space') {\n this.spacePressed = false;\n if (this.isPanning) {\n this.endPan();\n }\n }\n }\n\n /**\n * Set zoom level\n */\n setZoom(zoom: number, center?: Point): void {\n const centerPoint = center ?? {\n x: this.renderer.width / 2,\n y: this.renderer.height / 2,\n };\n\n const oldZoom = this.renderer.zoom;\n const oldOffsetX = this.renderer.offsetX;\n const oldOffsetY = this.renderer.offsetY;\n\n // Get world position at center point\n const worldPos = this.renderer.screenToWorld(centerPoint.x, centerPoint.y);\n\n // Apply new zoom\n this.renderer.zoom = zoom;\n const actualNewZoom = this.renderer.zoom; // may be clamped by min/max\n\n // Adjust offset to keep center point at same world position\n this.renderer.offsetX = oldOffsetX + worldPos.x * (oldZoom - actualNewZoom);\n this.renderer.offsetY = oldOffsetY + worldPos.y * (oldZoom - actualNewZoom);\n\n this.emit('zoomChange', this.renderer.zoom, centerPoint);\n }\n\n /**\n * Fit all content in view\n */\n fitToView(padding = 50): void {\n const bounds = getContentBounds({\n nodes: this.renderer.nodes.values(),\n includeInvisible: true,\n });\n if (bounds === null) {\n return;\n }\n\n this.zoomToRect(bounds, padding);\n }\n\n /**\n * Zoom to fit a specific rectangle\n */\n zoomToRect(rect: Bounds, padding = 50): void {\n const viewWidth = this.renderer.width - padding * 2;\n const viewHeight = this.renderer.height - padding * 2;\n\n const scaleX = viewWidth / rect.width;\n const scaleY = viewHeight / rect.height;\n const scale = Math.min(scaleX, scaleY, 1); // Don't zoom in beyond 100%\n\n this.renderer.zoom = scale;\n\n // Center the content\n const contentCenterX = rect.x + rect.width / 2;\n const contentCenterY = rect.y + rect.height / 2;\n\n this.renderer.offsetX = this.renderer.width / 2 - contentCenterX * scale;\n this.renderer.offsetY = this.renderer.height / 2 - contentCenterY * scale;\n\n this.emit('zoomChange', this.renderer.zoom, { x: contentCenterX, y: contentCenterY });\n }\n\n /**\n * Zoom to a selection bounds\n */\n zoomToSelection(bounds: Bounds, padding = 50): void {\n this.zoomToRect(bounds, padding);\n }\n\n /**\n * Reset view to default\n */\n resetView(): void {\n this.renderer.zoom = 1;\n this.renderer.offsetX = 0;\n this.renderer.offsetY = 0;\n this.emit('zoomChange', 1, { x: 0, y: 0 });\n }\n\n startPan(event: InputEvent): void {\n this.isPanning = true;\n this.panStart = { x: event.screenX, y: event.screenY };\n this.emit('panStart');\n }\n\n private endPan(): void {\n this.isPanning = false;\n this.panStart = null;\n this.emit('panEnd');\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { InputEvent } from '@/events/InputHandler';\nimport type { AnchorId, Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { EdgeEndpoint, Point } from '@/types';\nimport {\n ANCHOR_PORT_PREFIX,\n EDGE_AXIS_MAGNET_SCREEN_TOLERANCE,\n EDGE_ADD_CONTROL_RADIUS,\n EDGE_CONTROL_POINT_RADIUS,\n EDGE_HANDLE_RADIUS,\n OUTLINE_SNAP_SCREEN_TOLERANCE,\n ANCHOR_POINT_HITBOX_RADIUS,\n ANCHOR_POINT_HOVER_RADIUS,\n ANCHOR_POINT_RADIUS,\n BEZIER_MAX_OFFSET,\n} from '@/constants';\nimport { clonePoints, distance } from '@/utils/geometry';\n\n/**\n * Connection events\n */\nexport interface ConnectionEvents {\n connectionStart: [fromNode: Node];\n connectionMove: [fromPoint: Point, toPoint: Point];\n connectionEnd: [edge: Edge | null];\n connect: [edge: Edge];\n edgeReconnectStart: [edge: Edge, endpoint: 'start' | 'end', original: EdgeEndpoint];\n edgeReconnect: [edge: Edge, endpoint: 'start' | 'end'];\n}\n\nexport type ConnectionValidator = (sourceNodeId: string, targetNodeId: string) => boolean;\n\nexport interface ConnectionManagerOptions {\n renderer: DiagramRenderer;\n createEdge: (from: EdgeEndpoint, to: EdgeEndpoint) => Edge;\n addEdge?: (edge: Edge) => void;\n snapToGrid?: boolean;\n gridSize?: number;\n /** When true, edges can be attached anywhere on the shape outline (not just ports) */\n attachToOutline?: boolean;\n}\n\n/**\n * Manages port-to-port connection creation\n */\nexport class ConnectionManager extends EventEmitter<ConnectionEvents> {\n private renderer: DiagramRenderer;\n private readonly createEdge: (from: EdgeEndpoint, to: EdgeEndpoint) => Edge;\n private readonly addEdge: (edge: Edge) => void;\n private _connectionValidator: ConnectionValidator | null = null;\n\n private isConnecting = false;\n private sourceNode: Node | null = null;\n private sourcePoint: Point | null = null;\n private previewEndpoint: Point | null = null;\n private sourceAnchorId: string | null = null;\n private hoverNodeId: string | null = null;\n private hoverAnchorId: string | null = null;\n private hoverDisabled = false;\n private reconnectPoint: Point | null = null;\n private previewTargetAnchorId: string | null = null;\n private sourceOutlineParam: number | null = null;\n private previewTargetOutlineParam: number | null = null;\n private previewTargetNodeId: string | null = null;\n\n // Edge reconnection state\n private isReconnecting = false;\n private reconnectingEdge: Edge | null = null;\n private reconnectingEndpoint: 'start' | 'end' | null = null;\n private originalEdgeEndpoint: EdgeEndpoint | null = null;\n private reconnectingOutlineParam: number | null = null;\n private reconnectingTargetNodeId: string | null = null;\n private activeControlPointDrag: { edge: Edge; index: number } | null = null;\n private snapToGrid: boolean;\n private gridSize: number;\n private attachToOutline: boolean;\n\n constructor(options: ConnectionManagerOptions) {\n super();\n this.renderer = options.renderer;\n this.createEdge = options.createEdge;\n this.addEdge = options.addEdge ?? ((edge): void => this.renderer.addEdge(edge));\n this.snapToGrid = options.snapToGrid ?? false;\n this.gridSize = options.gridSize ?? 20;\n this.attachToOutline = options.attachToOutline ?? false;\n }\n\n /**\n * Enable/disable attach-to-outline mode (edges attach anywhere on shape contour)\n */\n setAttachToOutline(enabled: boolean): void {\n this.attachToOutline = enabled;\n this.renderer.attachToOutline = enabled;\n }\n\n /**\n * Enable/disable snap to grid for editable polyline control points.\n */\n setSnapToGrid(enabled: boolean, gridSize?: number): void {\n this.snapToGrid = enabled;\n if (gridSize !== undefined) {\n this.gridSize = gridSize;\n }\n }\n\n /**\n * Set a validator that determines whether a connection between two nodes is allowed.\n * When set, disallowed targets show forbidden styling and connections are blocked.\n */\n set connectionValidator(validator: ConnectionValidator | null) {\n this._connectionValidator = validator;\n }\n\n /**\n * Check if currently creating a connection\n */\n get connecting(): boolean {\n return this.isConnecting || this.isReconnecting;\n }\n\n /**\n * Check if currently reconnecting an edge\n */\n get reconnecting(): boolean {\n return this.isReconnecting;\n }\n\n /**\n * Get the edge being reconnected (to hide it during preview)\n */\n get reconnectingEdgeId(): string | null {\n return this.reconnectingEdge?.id ?? null;\n }\n\n /**\n * Current preview endpoint\n */\n get previewEnd(): Point | null {\n return this.previewEndpoint;\n }\n\n /**\n * Disable hover and clear state (used when dragging starts)\n */\n disableHover(): void {\n this.hoverDisabled = true;\n if (this.hoverNodeId !== null || this.hoverAnchorId !== null) {\n this.hoverNodeId = null;\n this.hoverAnchorId = null;\n this.renderer.markDirty();\n }\n }\n\n /**\n * Re-enable hover (used when dragging ends)\n */\n enableHover(): void {\n this.hoverDisabled = false;\n }\n\n /**\n * Try to start connection from a hovered anchor point.\n * When attachToOutline + Shift: start from anywhere on node outline.\n * Otherwise: requires clicking on an anchor/port so that node drag still works.\n */\n tryStartConnectionAtPoint(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n const node = this.getNodeAtPoint(point, false);\n if (!node) {\n return false;\n }\n\n if (this.attachToOutline && event.shiftKey) {\n const { point: outlinePoint, param } = node.getClosestPointOnOutline(point);\n this.sourceNode = node;\n this.isConnecting = true;\n this.sourceAnchorId = null;\n this.sourcePoint = outlinePoint;\n this.sourceOutlineParam = param;\n this.previewEndpoint = point;\n this.emit('connectionStart', node);\n this.renderer.markDirty();\n return true;\n }\n\n // Try to find anchor at point (for precise click on port)\n const hover = this.getAnchorAtPoint(node, point);\n if (hover) {\n this.sourceNode = node;\n this.isConnecting = true;\n this.sourceAnchorId = hover.id;\n this.sourcePoint = hover.point;\n this.previewEndpoint = point;\n if (this.attachToOutline) {\n const { param } = node.getClosestPointOnOutline(point);\n this.sourceOutlineParam = param;\n } else {\n this.sourceOutlineParam = null;\n }\n this.emit('connectionStart', node);\n this.renderer.markDirty();\n return true;\n }\n\n return false;\n }\n\n /**\n * Try to start edge reconnection from handle\n */\n tryStartReconnection(event: InputEvent): boolean {\n if (this.tryStartEditableControlInteraction(event)) {\n return true;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const handleRadius = EDGE_HANDLE_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n\n // Check selected edges for handle hit\n for (const edge of this.renderer.edges.values()) {\n if (edge.state !== 'selected') {\n continue;\n }\n\n if (edge.hitTestStartHandle(point, handleRadius)) {\n this.isReconnecting = true;\n this.reconnectingEdge = edge;\n this.reconnectingEdge.autoUpdateEndpoints = false;\n this.reconnectingEndpoint = 'start';\n this.originalEdgeEndpoint = { ...edge.from };\n this.emit('edgeReconnectStart', edge, 'start', this.originalEdgeEndpoint);\n // Update edge to follow cursor immediately\n this.updateReconnectingEdge(point);\n return true;\n }\n\n if (edge.hitTestEndHandle(point, handleRadius)) {\n this.isReconnecting = true;\n this.reconnectingEdge = edge;\n this.reconnectingEdge.autoUpdateEndpoints = false;\n this.reconnectingEndpoint = 'end';\n this.originalEdgeEndpoint = { ...edge.to };\n this.emit('edgeReconnectStart', edge, 'end', this.originalEdgeEndpoint);\n // Update edge to follow cursor immediately\n this.updateReconnectingEdge(point);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Update the reconnecting edge to follow cursor\n */\n private updateReconnectingEdge(point: Point): void {\n if (!this.reconnectingEdge) return;\n\n const edge = this.reconnectingEdge;\n const fromNode = this.renderer.getNode(edge.from.nodeId);\n const toNode = this.renderer.getNode(edge.to.nodeId);\n\n let snappedPoint = point;\n let snappedDir: string | undefined;\n let targetNode = this.getNodeAtPoint(point, true);\n\n if (this.attachToOutline) {\n const tolerance = OUTLINE_SNAP_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n const toleranceSq = tolerance * tolerance;\n let bestDistSq = Infinity;\n let bestResult: { node: Node; point: Point; param: number } | null = null;\n\n for (const node of this.renderer.nodes.values()) {\n if (!node.visible) continue;\n const { point: outlinePoint, param } = node.getClosestPointOnOutline(point);\n const dx = point.x - outlinePoint.x;\n const dy = point.y - outlinePoint.y;\n const distSq = dx * dx + dy * dy;\n if (distSq <= toleranceSq && distSq < bestDistSq) {\n bestDistSq = distSq;\n bestResult = { node, point: outlinePoint, param };\n }\n }\n\n if (bestResult) {\n targetNode = bestResult.node;\n snappedPoint = bestResult.point;\n this.reconnectingOutlineParam = bestResult.param;\n this.reconnectingTargetNodeId = bestResult.node.id;\n snappedDir = this.getDirectionFromOutlineParam(bestResult.param, bestResult.node);\n\n const otherNode = this.reconnectingEndpoint === 'start' ? toNode : fromNode;\n if (otherNode) {\n const alignRef = edge.isEditablePolyline()\n ? this.getNearestBendPointForAxisAlignment(edge, this.reconnectingEndpoint!)\n : this.reconnectingEndpoint === 'start'\n ? this.getTargetPointForReconnect(edge, toNode!, 'to', snappedPoint)\n : this.getTargetPointForReconnect(edge, fromNode!, 'from', snappedPoint);\n snappedPoint = this.applyAxisAlignmentToPoint(snappedPoint, alignRef);\n const reprojected = targetNode.getClosestPointOnOutline(snappedPoint);\n snappedPoint = reprojected.point;\n this.reconnectingOutlineParam = reprojected.param;\n snappedDir = this.getDirectionFromOutlineParam(reprojected.param, targetNode);\n }\n } else {\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n }\n } else if (targetNode) {\n const nearestAnchor = targetNode.getNearestAnchor(point);\n if (nearestAnchor) {\n snappedPoint = nearestAnchor.point;\n snappedDir = nearestAnchor.id.split(':')[0];\n }\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n } else {\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n }\n\n this.reconnectPoint = snappedPoint;\n\n if (this.reconnectingEndpoint === 'start') {\n if (toNode) {\n const target = this.getTargetPointForReconnect(edge, toNode, 'to', snappedPoint);\n const toDir = this.getTargetDirForReconnect(edge, toNode, 'to');\n edge.updateEndpoints(snappedPoint, target, snappedDir, toDir);\n }\n } else {\n if (fromNode) {\n const start = this.getTargetPointForReconnect(edge, fromNode, 'from', snappedPoint);\n const fromDir = this.getTargetDirForReconnect(edge, fromNode, 'from');\n edge.updateEndpoints(start, snappedPoint, fromDir, snappedDir);\n }\n }\n\n this.renderer.markDirty();\n }\n\n private getTargetPointForReconnect(\n edge: Edge,\n node: Node,\n endpoint: 'from' | 'to',\n fallbackPoint: Point\n ): Point {\n const ep = endpoint === 'from' ? edge.from : edge.to;\n if (this.attachToOutline && ep.outlineParam !== undefined) {\n return node.getConnectionPointAtOutlineParam(ep.outlineParam);\n }\n const anchorId = ep.portId?.replace(ANCHOR_PORT_PREFIX, '');\n if (anchorId) {\n return node.getAnchorPointById(anchorId) ?? node.getConnectionPoint(fallbackPoint);\n }\n return node.getConnectionPoint(fallbackPoint);\n }\n\n private getTargetDirForReconnect(\n edge: Edge,\n node: Node,\n endpoint: 'from' | 'to'\n ): string | undefined {\n const ep = endpoint === 'from' ? edge.from : edge.to;\n if (this.attachToOutline && ep.outlineParam !== undefined) {\n return this.getDirectionFromOutlineParam(ep.outlineParam, node);\n }\n const anchorId = ep.portId?.replace(ANCHOR_PORT_PREFIX, '');\n return anchorId?.split(':')[0];\n }\n\n private getDirectionFromOutlineParam(param: number, _node: Node): string {\n const p = ((param % 1) + 1) % 1;\n if (p < 0.25) return 'top';\n if (p < 0.5) return 'right';\n if (p < 0.75) return 'bottom';\n return 'left';\n }\n\n /**\n * For editable polyline: return the nearest bend point for axis alignment.\n * When reconnecting 'end', use last control point (or start). When reconnecting 'start', use first control point (or end).\n */\n private getNearestBendPointForAxisAlignment(edge: Edge, endpoint: 'start' | 'end'): Point {\n const cps = edge.isEditablePolyline()\n ? (edge.controlPoints ?? edge.getEditableControlPoints())\n : [];\n if (endpoint === 'end') {\n return cps.length > 0 ? cps[cps.length - 1]! : edge.startPoint;\n }\n return cps.length > 0 ? cps[0]! : edge.endPoint;\n }\n\n /**\n * When attachToOutline: snap moving point to horizontal/vertical alignment with fixed point.\n */\n private applyAxisAlignmentToPoint(moving: Point, fixed: Point): Point {\n const tolerance = EDGE_AXIS_MAGNET_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n let x = moving.x;\n let y = moving.y;\n if (Math.abs(moving.x - fixed.x) <= tolerance) {\n x = fixed.x;\n }\n if (Math.abs(moving.y - fixed.y) <= tolerance) {\n y = fixed.y;\n }\n return { x, y };\n }\n\n /**\n * Handle mouse move during connection\n */\n handleMouseMove(event: InputEvent): boolean {\n if (this.activeControlPointDrag) {\n const controlPoints = this.activeControlPointDrag.edge.controlPoints\n ? [...this.activeControlPointDrag.edge.controlPoints]\n : this.activeControlPointDrag.edge.getEditableControlPoints();\n if (this.activeControlPointDrag.index < controlPoints.length) {\n const rawPoint = this.snapPoint({ x: event.worldX, y: event.worldY });\n const magnetized = this.applyAxisMagnet(\n this.activeControlPointDrag.edge,\n controlPoints,\n this.activeControlPointDrag.index,\n rawPoint\n );\n controlPoints[this.activeControlPointDrag.index] = magnetized;\n this.activeControlPointDrag.edge.controlPoints = controlPoints;\n }\n return true;\n }\n\n // Handle edge reconnection\n if (this.isReconnecting && this.reconnectingEdge) {\n const point = { x: event.worldX, y: event.worldY };\n\n // Update edge to follow cursor\n this.updateReconnectingEdge(point);\n\n return true;\n }\n\n if (!this.isConnecting) {\n this.updateHover({ x: event.worldX, y: event.worldY });\n return false;\n }\n\n const cursorPoint = { x: event.worldX, y: event.worldY };\n\n let snappedPoint = cursorPoint;\n this.previewTargetAnchorId = null;\n this.previewTargetOutlineParam = null;\n this.previewTargetNodeId = null;\n let targetNode = this.getNodeAtPoint(cursorPoint, false);\n\n if (this.attachToOutline) {\n const tolerance = OUTLINE_SNAP_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n const toleranceSq = tolerance * tolerance;\n let bestDistSq = Infinity;\n let bestResult: { node: Node; point: Point; param: number } | null = null;\n\n for (const node of this.renderer.nodes.values()) {\n if (!node.visible || !this.isCompatibleTarget(node)) continue;\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, node.id);\n if (forbidden) continue;\n\n const { point: outlinePoint, param } = node.getClosestPointOnOutline(cursorPoint);\n const dx = cursorPoint.x - outlinePoint.x;\n const dy = cursorPoint.y - outlinePoint.y;\n const distSq = dx * dx + dy * dy;\n if (distSq <= toleranceSq && distSq < bestDistSq) {\n bestDistSq = distSq;\n bestResult = { node, point: outlinePoint, param };\n }\n }\n\n if (bestResult) {\n targetNode = bestResult.node;\n snappedPoint = bestResult.point;\n this.previewTargetOutlineParam = bestResult.param;\n this.previewTargetNodeId = bestResult.node.id;\n\n if (this.sourcePoint) {\n snappedPoint = this.applyAxisAlignmentToPoint(snappedPoint, this.sourcePoint);\n const reprojected = bestResult.node.getClosestPointOnOutline(snappedPoint);\n snappedPoint = reprojected.point;\n this.previewTargetOutlineParam = reprojected.param;\n }\n }\n } else if (targetNode && this.isCompatibleTarget(targetNode)) {\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, targetNode.id);\n if (!forbidden) {\n const nearestAnchor = targetNode.getNearestAnchor(cursorPoint);\n if (nearestAnchor) {\n snappedPoint = nearestAnchor.point;\n this.previewTargetAnchorId = nearestAnchor.id;\n }\n }\n }\n\n if (targetNode) {\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, targetNode.id);\n this.setCursor(forbidden ? 'not-allowed' : 'crosshair');\n } else {\n this.setCursor('crosshair');\n }\n\n this.previewEndpoint = snappedPoint;\n if (this.sourceNode && !this.sourceAnchorId && !this.sourceOutlineParam) {\n this.sourcePoint = this.sourceNode.getConnectionPoint(this.previewEndpoint);\n } else if (this.sourceNode && this.sourceOutlineParam !== null) {\n this.sourcePoint = this.sourceNode.getConnectionPointAtOutlineParam(this.sourceOutlineParam);\n }\n\n this.emit('connectionMove', this.sourcePoint!, this.previewEndpoint);\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Remove editable polyline bend by double click.\n */\n handleDoubleClick(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n const radius = EDGE_CONTROL_POINT_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const radiusSq = radius * radius;\n const edges = [...this.renderer.edges.values()];\n\n for (let i = edges.length - 1; i >= 0; i--) {\n const edge = edges[i]!;\n if (edge.state !== 'selected' || !edge.hasEditableControlPoints()) {\n continue;\n }\n\n const cps = edge.controlPoints!;\n for (let i = 0; i < cps.length; i++) {\n const controlPoint = cps[i]!;\n const dx = point.x - controlPoint.x;\n const dy = point.y - controlPoint.y;\n if (dx * dx + dy * dy > radiusSq) {\n continue;\n }\n\n const next = clonePoints(cps);\n next.splice(i, 1);\n edge.controlPoints = next.length > 0 ? next : undefined;\n if (\n this.activeControlPointDrag &&\n this.activeControlPointDrag.edge.id === edge.id &&\n this.activeControlPointDrag.index === i\n ) {\n this.activeControlPointDrag = null;\n }\n this.renderer.markDirty();\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Handle mouse up to complete or cancel connection\n */\n handleMouseUp(event: InputEvent): boolean {\n if (this.activeControlPointDrag) {\n this.activeControlPointDrag = null;\n this.renderer.markDirty();\n return true;\n }\n\n // Handle edge reconnection completion\n if (this.isReconnecting && this.reconnectingEdge) {\n const point = { x: event.worldX, y: event.worldY };\n let reconnected = false;\n\n let node = this.getNodeAtPoint(point, true);\n if (!node && this.attachToOutline && this.reconnectingTargetNodeId) {\n node = this.renderer.getNode(this.reconnectingTargetNodeId) ?? null;\n }\n if (node) {\n if (this.attachToOutline && this.reconnectingOutlineParam !== null) {\n const endpoint: EdgeEndpoint = {\n nodeId: node.id,\n outlineParam: this.reconnectingOutlineParam,\n };\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = endpoint;\n } else {\n this.reconnectingEdge.to = endpoint;\n }\n } else {\n const anchor = node.getNearestAnchor(point);\n const portId =\n this.reconnectingEdge.lockAnchors && anchor\n ? `${ANCHOR_PORT_PREFIX}${anchor.id}`\n : undefined;\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = { nodeId: node.id, portId };\n } else {\n this.reconnectingEdge.to = { nodeId: node.id, portId };\n }\n }\n reconnected = true;\n this.emit('edgeReconnect', this.reconnectingEdge, this.reconnectingEndpoint!);\n }\n\n if (!reconnected && this.originalEdgeEndpoint) {\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = this.originalEdgeEndpoint;\n } else {\n this.reconnectingEdge.to = this.originalEdgeEndpoint;\n }\n this.emit('edgeReconnect', this.reconnectingEdge, this.reconnectingEndpoint!);\n }\n\n this.resetReconnection();\n this.renderer.markDirty();\n return true;\n }\n\n if (!this.isConnecting) {\n return false;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n let createdEdge: Edge | null = null;\n\n let targetNode = this.getNodeAtPoint(point, false);\n if (!targetNode && this.attachToOutline && this.previewTargetNodeId) {\n targetNode = this.renderer.getNode(this.previewTargetNodeId) ?? null;\n }\n if (targetNode) {\n const allowed =\n !this._connectionValidator || this._connectionValidator(this.sourceNode!.id, targetNode.id);\n if (allowed) {\n let from: EdgeEndpoint;\n let to: EdgeEndpoint;\n if (this.attachToOutline) {\n const targetOutline = targetNode.getClosestPointOnOutline(point);\n from = {\n nodeId: this.sourceNode!.id,\n outlineParam: this.sourceOutlineParam ?? undefined,\n };\n to = {\n nodeId: targetNode.id,\n outlineParam: targetOutline.param,\n };\n } else {\n const nearestTargetAnchor = targetNode.getNearestAnchor(point);\n from = {\n nodeId: this.sourceNode!.id,\n portId: this.sourceAnchorId ? `${ANCHOR_PORT_PREFIX}${this.sourceAnchorId}` : undefined,\n };\n to = {\n nodeId: targetNode.id,\n portId: nearestTargetAnchor\n ? `${ANCHOR_PORT_PREFIX}${nearestTargetAnchor.id}`\n : undefined,\n };\n }\n createdEdge = this.createEdge(from, to);\n this.addEdge(createdEdge);\n this.emit('connect', createdEdge);\n }\n }\n\n this.emit('connectionEnd', createdEdge);\n this.reset();\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Cancel current connection\n */\n cancelConnection(): void {\n if (!this.isConnecting) {\n return;\n }\n\n this.emit('connectionEnd', null);\n this.reset();\n this.renderer.markDirty();\n }\n\n /**\n * Render connection preview\n */\n renderPreview(ctx: CanvasRenderingContext2D): void {\n // For reconnection, the actual edge follows the cursor, no separate preview needed\n if (this.isReconnecting && this.reconnectPoint) {\n if (!this.attachToOutline) {\n this.renderAnchorHighlights(ctx, this.reconnectPoint, true);\n }\n return;\n }\n\n if (!this.isConnecting || this.previewEndpoint === null) {\n return;\n }\n\n const start = this.sourcePoint!;\n const end = this.previewEndpoint;\n\n const fromDir =\n this.sourceOutlineParam !== null\n ? this.getDirectionFromOutlineParam(this.sourceOutlineParam, this.sourceNode!)\n : this.sourceAnchorId?.split(':')[0];\n const toDir =\n this.previewTargetOutlineParam !== null\n ? this.getDirectionFromOutlineParam(this.previewTargetOutlineParam, this.sourceNode!)\n : this.previewTargetAnchorId?.split(':')[0];\n\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 2;\n ctx.setLineDash([6, 4]);\n\n // Draw bezier curve for preview\n this.drawBezierPreview(ctx, start, end, fromDir, toDir);\n\n ctx.setLineDash([]);\n\n if (!this.attachToOutline) {\n this.renderAnchorHighlights(ctx, end, false);\n }\n }\n\n /**\n * Get control point offset based on direction\n */\n private getDirectionOffset(dir: string | undefined, distance: number): Point {\n const offset = Math.min(distance * 0.5, BEZIER_MAX_OFFSET);\n switch (dir) {\n case 'top':\n return { x: 0, y: -offset };\n case 'bottom':\n return { x: 0, y: offset };\n case 'left':\n return { x: -offset, y: 0 };\n case 'right':\n return { x: offset, y: 0 };\n default:\n return { x: 0, y: 0 };\n }\n }\n\n /**\n * Draw a Bézier curve preview between two points\n */\n private drawBezierPreview(\n ctx: CanvasRenderingContext2D,\n start: Point,\n end: Point,\n fromDir?: string,\n toDir?: string\n ): void {\n const dist = distance(start, end);\n\n ctx.beginPath();\n ctx.moveTo(start.x, start.y);\n\n // If directions are specified, use them for control points\n if (fromDir || toDir) {\n const fromOffset = this.getDirectionOffset(fromDir, dist);\n const toOffset = this.getDirectionOffset(toDir, dist);\n\n ctx.bezierCurveTo(\n start.x + fromOffset.x,\n start.y + fromOffset.y,\n end.x + toOffset.x,\n end.y + toOffset.y,\n end.x,\n end.y\n );\n } else {\n // Default behavior: auto-detect direction\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const offset = Math.min(Math.abs(dx), Math.abs(dy), BEZIER_MAX_OFFSET) * 0.5 + 50;\n\n if (Math.abs(dx) > Math.abs(dy)) {\n // Horizontal dominant\n const offsetX = offset * Math.sign(dx || 1);\n ctx.bezierCurveTo(start.x + offsetX, start.y, end.x - offsetX, end.y, end.x, end.y);\n } else {\n // Vertical dominant\n ctx.bezierCurveTo(\n start.x,\n start.y + offset * Math.sign(dy || 1),\n end.x,\n end.y - offset * Math.sign(dy || 1),\n end.x,\n end.y\n );\n }\n }\n\n ctx.stroke();\n }\n\n private isCompatibleTarget(_node: Node): boolean {\n // Self-loop edges are allowed.\n return true;\n }\n\n private setCursor(cursor: string): void {\n const canvas = this.renderer.getCanvas();\n if (canvas.style.cursor !== cursor) {\n canvas.style.cursor = cursor;\n }\n }\n\n private reset(): void {\n this.isConnecting = false;\n this.sourceNode = null;\n this.sourcePoint = null;\n this.previewEndpoint = null;\n this.sourceAnchorId = null;\n this.sourceOutlineParam = null;\n this.previewTargetOutlineParam = null;\n this.previewTargetNodeId = null;\n this.setCursor('');\n }\n\n private resetReconnection(): void {\n this.isReconnecting = false;\n if (this.reconnectingEdge) {\n this.reconnectingEdge.autoUpdateEndpoints = true;\n }\n this.reconnectingEdge = null;\n this.reconnectingEndpoint = null;\n this.originalEdgeEndpoint = null;\n this.reconnectingOutlineParam = null;\n this.reconnectingTargetNodeId = null;\n this.reconnectPoint = null;\n this.setCursor('');\n }\n\n /**\n * Render anchors when hovering a node (not connecting)\n */\n renderHoverAnchors(ctx: CanvasRenderingContext2D): void {\n if (this.isConnecting || this.isReconnecting) {\n return;\n }\n\n this.renderEditablePolylineControls(ctx);\n\n if (this.attachToOutline) {\n return;\n }\n\n if (!this.hoverNodeId) {\n return;\n }\n\n const node = this.renderer.getNode(this.hoverNodeId);\n if (!node) {\n return;\n }\n\n const anchors = node.getAnchors();\n if (anchors.length === 0) {\n return;\n }\n\n ctx.save();\n ctx.setLineDash([]);\n\n for (const anchor of anchors) {\n const isHovered = anchor.id === this.hoverAnchorId;\n const radius = isHovered ? ANCHOR_POINT_HOVER_RADIUS : ANCHOR_POINT_RADIUS;\n\n // Draw anchor circle\n ctx.fillStyle = '#3b82f6';\n ctx.beginPath();\n ctx.arc(anchor.point.x, anchor.point.y, radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Draw white plus on hover\n if (isHovered) {\n this.drawPlus(radius, ctx, anchor);\n }\n }\n\n ctx.restore();\n }\n\n private tryStartEditableControlInteraction(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n const pointRadius = EDGE_CONTROL_POINT_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const addRadius = EDGE_ADD_CONTROL_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const pointRadiusSq = pointRadius * pointRadius;\n const addRadiusSq = addRadius * addRadius;\n const edges = [...this.renderer.edges.values()];\n\n for (let i = edges.length - 1; i >= 0; i--) {\n const edge = edges[i]!;\n if (edge.state !== 'selected' || !edge.isEditablePolyline()) {\n continue;\n }\n\n const controlPoints = edge.getEditableControlPoints();\n if (controlPoints.length === 0) continue;\n\n for (let i = 0; i < controlPoints.length; i++) {\n const dx = point.x - controlPoints[i]!.x;\n const dy = point.y - controlPoints[i]!.y;\n if (dx * dx + dy * dy > pointRadiusSq) {\n continue;\n }\n\n if (!edge.controlPoints || edge.controlPoints.length === 0) {\n edge.controlPoints = controlPoints;\n }\n this.activeControlPointDrag = { edge, index: i };\n this.renderer.markDirty();\n return true;\n }\n\n const insertControls = this.getInsertControls(edge);\n for (const insertControl of insertControls) {\n const dx = point.x - insertControl.point.x;\n const dy = point.y - insertControl.point.y;\n if (dx * dx + dy * dy > addRadiusSq) {\n continue;\n }\n\n const materialized = edge.controlPoints ? clonePoints(edge.controlPoints) : clonePoints(controlPoints);\n materialized.splice(insertControl.index, 0, this.snapPoint(insertControl.point));\n edge.controlPoints = materialized;\n this.activeControlPointDrag = { edge, index: insertControl.index };\n this.renderer.markDirty();\n return true;\n }\n }\n\n return false;\n }\n\n private renderEditablePolylineControls(ctx: CanvasRenderingContext2D): void {\n const pointRadius = EDGE_CONTROL_POINT_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n const addRadius = EDGE_ADD_CONTROL_RADIUS / Math.max(this.renderer.zoom, 0.0001);\n\n ctx.save();\n ctx.setLineDash([]);\n\n for (const edge of this.renderer.edges.values()) {\n if (edge.state !== 'selected' || !edge.isEditablePolyline()) {\n continue;\n }\n\n const controlPoints = edge.getEditableControlPoints();\n const insertControls = this.getInsertControls(edge);\n for (const insertControl of insertControls) {\n this.drawAddControl(ctx, insertControl.point, addRadius);\n }\n\n for (const point of controlPoints) {\n this.drawControlPoint(ctx, point, pointRadius);\n }\n }\n\n ctx.restore();\n }\n\n private getInsertControls(edge: Edge): { point: Point; index: number }[] {\n const vertices = edge.getPathVertices();\n const controls: { point: Point; index: number }[] = [];\n for (let i = 0; i < vertices.length - 1; i++) {\n const start = vertices[i]!;\n const end = vertices[i + 1]!;\n controls.push({\n point: {\n x: (start.x + end.x) / 2,\n y: (start.y + end.y) / 2,\n },\n index: i,\n });\n }\n return controls;\n }\n\n private drawControlPoint(ctx: CanvasRenderingContext2D, point: Point, radius: number): void {\n ctx.beginPath();\n ctx.arc(point.x, point.y, radius, 0, Math.PI * 2);\n ctx.fillStyle = '#3b82f6';\n ctx.fill();\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2 / Math.max(this.renderer.zoom, 0.0001);\n ctx.stroke();\n }\n\n private drawAddControl(ctx: CanvasRenderingContext2D, point: Point, radius: number): void {\n ctx.beginPath();\n ctx.arc(point.x, point.y, radius, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 1.5 / Math.max(this.renderer.zoom, 0.0001);\n ctx.stroke();\n\n const plusSize = radius * 0.7;\n ctx.beginPath();\n ctx.moveTo(point.x - plusSize, point.y);\n ctx.lineTo(point.x + plusSize, point.y);\n ctx.moveTo(point.x, point.y - plusSize);\n ctx.lineTo(point.x, point.y + plusSize);\n ctx.strokeStyle = '#3b82f6';\n ctx.lineWidth = 1.5 / Math.max(this.renderer.zoom, 0.0001);\n ctx.stroke();\n }\n\n private snapPoint(point: Point): Point {\n if (!this.snapToGrid) {\n return point;\n }\n return {\n x: Math.round(point.x / this.gridSize) * this.gridSize,\n y: Math.round(point.y / this.gridSize) * this.gridSize,\n };\n }\n\n private applyAxisMagnet(edge: Edge, controlPoints: Point[], index: number, point: Point): Point {\n const vertices = [edge.startPoint, ...controlPoints, edge.endPoint];\n const prev = vertices[index];\n const next = vertices[index + 2];\n if (!prev || !next) {\n return point;\n }\n\n const tolerance = EDGE_AXIS_MAGNET_SCREEN_TOLERANCE / Math.max(this.renderer.zoom, 0.0001);\n let x = point.x;\n let y = point.y;\n\n const xCandidates = [prev.x, next.x];\n const yCandidates = [prev.y, next.y];\n\n let closestXDist = Infinity;\n for (const candidate of xCandidates) {\n const dist = Math.abs(point.x - candidate);\n if (dist <= tolerance && dist < closestXDist) {\n closestXDist = dist;\n x = candidate;\n }\n }\n\n let closestYDist = Infinity;\n for (const candidate of yCandidates) {\n const dist = Math.abs(point.y - candidate);\n if (dist <= tolerance && dist < closestYDist) {\n closestYDist = dist;\n y = candidate;\n }\n }\n\n return { x, y };\n }\n\n private drawPlus(\n radius: number,\n ctx: CanvasRenderingContext2D,\n anchor: { id: AnchorId; point: Point }\n ): void {\n const plusSize = radius * 0.5;\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n ctx.moveTo(anchor.point.x - plusSize, anchor.point.y);\n ctx.lineTo(anchor.point.x + plusSize, anchor.point.y);\n ctx.moveTo(anchor.point.x, anchor.point.y - plusSize);\n ctx.lineTo(anchor.point.x, anchor.point.y + plusSize);\n ctx.stroke();\n return;\n }\n\n private renderAnchorHighlights(\n ctx: CanvasRenderingContext2D,\n point: Point,\n reconnecting: boolean\n ): void {\n const node = this.getNodeAtPoint(point, reconnecting);\n if (!node) {\n return;\n }\n\n // Check if connection to this target is allowed\n const forbidden =\n this._connectionValidator &&\n this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, node.id);\n\n const anchors = node.getAnchors();\n const nearest = node.getNearestAnchor(point);\n if (anchors.length === 0) {\n return;\n }\n\n ctx.save();\n ctx.setLineDash([]);\n\n const fillColor = forbidden ? '#ef4444' : '#3b82f6';\n\n for (const anchor of anchors) {\n const isNearest = nearest && anchor.id === nearest.id;\n const radius = isNearest ? ANCHOR_POINT_HOVER_RADIUS : ANCHOR_POINT_RADIUS;\n\n // Draw anchor circle\n ctx.fillStyle = fillColor;\n ctx.beginPath();\n ctx.arc(anchor.point.x, anchor.point.y, radius, 0, Math.PI * 2);\n ctx.fill();\n\n // Draw white plus/cross on nearest\n if (isNearest) {\n if (forbidden) {\n this.drawCross(radius, ctx, anchor);\n } else {\n this.drawPlus(radius, ctx, anchor);\n }\n }\n }\n\n ctx.restore();\n }\n\n private drawCross(\n radius: number,\n ctx: CanvasRenderingContext2D,\n anchor: { id: AnchorId; point: Point }\n ): void {\n const size = radius * 0.4;\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n ctx.moveTo(anchor.point.x - size, anchor.point.y - size);\n ctx.lineTo(anchor.point.x + size, anchor.point.y + size);\n ctx.moveTo(anchor.point.x + size, anchor.point.y - size);\n ctx.lineTo(anchor.point.x - size, anchor.point.y + size);\n ctx.stroke();\n }\n\n private getNodeAtPoint(point: Point, reconnecting: boolean): Node | null {\n const nodes = Array.from(this.renderer.nodes.values());\n for (let i = nodes.length - 1; i >= 0; i--) {\n const node = nodes[i]!;\n if (!node.visible || !node.hitTest(point)) {\n continue;\n }\n\n if (reconnecting) {\n return node;\n }\n\n if (this.isCompatibleTarget(node)) {\n return node;\n }\n }\n\n return null;\n }\n\n private updateHover(point: Point): void {\n if (this.hoverDisabled) {\n return;\n }\n\n const node = this.getNodeAtPoint(point, false);\n const prevNodeId = this.hoverNodeId;\n const prevAnchorId = this.hoverAnchorId;\n\n if (!node) {\n this.hoverNodeId = null;\n this.hoverAnchorId = null;\n } else {\n this.hoverNodeId = node.id;\n const anchor = this.getAnchorAtPoint(node, point);\n this.hoverAnchorId = anchor?.id ?? null;\n }\n\n if (prevNodeId !== this.hoverNodeId || prevAnchorId !== this.hoverAnchorId) {\n this.renderer.markDirty();\n }\n }\n\n private getAnchorAtPoint(node: Node, point: Point): { id: string; point: Point } | null {\n // Get only port-side anchors if attachToOutline is disabled and node has ports\n const anchorIds = !this.attachToOutline && node.ports.length > 0\n ? node.getPortAnchorIds()\n : null;\n \n const anchors = node.getAnchors();\n if (anchors.length === 0) {\n return null;\n }\n\n const radius = ANCHOR_POINT_HITBOX_RADIUS;\n const radiusSq = radius * radius;\n let closest: { id: string; point: Point } | null = null;\n let minDist = Infinity;\n\n for (const anchor of anchors) {\n // Skip anchors not on port sides when in port mode\n if (anchorIds && !anchorIds.includes(anchor.id)) {\n continue;\n }\n const dx = point.x - anchor.point.x;\n const dy = point.y - anchor.point.y;\n const dist = dx * dx + dy * dy;\n if (dist <= radiusSq && dist < minDist) {\n minDist = dist;\n closest = { id: anchor.id, point: anchor.point };\n }\n }\n\n return closest;\n }\n}\n","import type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { Node } from '@/elements/Node';\nimport type { StyleManager } from '@/styles/StyleManager';\n\n/**\n * Shallow compare two objects\n */\nexport function shallowEqual<T extends object>(a: T, b: T): boolean {\n if (a === b) {\n return true;\n }\n\n const aKeys = Object.keys(a as Record<string, unknown>);\n const bKeys = Object.keys(b as Record<string, unknown>);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (const key of aKeys) {\n const aValue = (a as Record<string, unknown>)[key];\n const bValue = (b as Record<string, unknown>)[key];\n\n if (Array.isArray(aValue) && Array.isArray(bValue)) {\n if (aValue.length !== bValue.length) {\n return false;\n }\n for (let i = 0; i < aValue.length; i++) {\n if (aValue[i] !== bValue[i]) {\n return false;\n }\n }\n continue;\n }\n\n if (aValue !== bValue) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Apply StyleManager to all elements\n */\nexport function applyStyleManagerToElements(\n styleManager: StyleManager | null | undefined,\n groups: Iterable<Group>,\n edges: Iterable<Edge>,\n nodes: Iterable<Node>\n): void {\n if (!styleManager) {\n return;\n }\n\n for (const group of groups) {\n group.applyStyleManager(styleManager);\n }\n\n for (const edge of edges) {\n edge.applyStyleManager(styleManager);\n }\n\n for (const node of nodes) {\n node.applyStyleManager(styleManager);\n }\n}\n","import type { Bounds, Point, TextStyle } from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport { shallowEqual } from '@/utils/style';\n\nexport interface TextLabelOptions {\n text: string;\n editableText?: string;\n style?: TextStyle;\n maxWidth?: number;\n padding?: number;\n margin?: number;\n styleClass?: string;\n onChange?: () => void;\n}\n\nconst DEFAULT_STYLE: Required<TextStyle> = {\n font: '14px sans-serif',\n fontSize: 14,\n fontFamily: 'sans-serif',\n fontWeight: 'normal',\n color: '#000000',\n opacity: 1,\n align: 'center',\n baseline: 'middle',\n};\n\n/**\n * Text label for nodes and edges\n */\nexport class TextLabel {\n private _text: string;\n private _editableText?: string;\n private _style: TextStyle;\n private _localStyle: TextStyle;\n private _maxWidth?: number;\n private _autoMaxWidth?: number;\n private _padding: number;\n private _margin: number;\n private _lines: string[] = [];\n private _measuredWidth = 0;\n private _measuredHeight = 0;\n private _styleClass?: string;\n private _onChange?: () => void;\n private _measureDirty = true;\n\n constructor(options: TextLabelOptions) {\n this._text = options.text ?? '';\n this._editableText = options.editableText;\n this._localStyle = { ...options.style };\n this._style = { ...DEFAULT_STYLE, ...options.style };\n this._maxWidth = options.maxWidth;\n this._padding = options.padding ?? 8;\n this._margin = Number.isFinite(options.margin) ? Math.max(0, options.margin ?? 0) : 0;\n this._styleClass = options.styleClass;\n this._onChange = options.onChange;\n }\n\n /**\n * Label text\n */\n get text(): string {\n return this._text;\n }\n\n set text(value: string) {\n const next = value ?? '';\n if (this._text !== next) {\n this._text = next;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n /**\n * Editable text shown in inline editor instead of display text.\n * When set, double-click editing will use this value.\n */\n get editableText(): string | undefined {\n return this._editableText;\n }\n\n set editableText(value: string | undefined) {\n if (this._editableText !== value) {\n this._editableText = value;\n this._onChange?.();\n }\n }\n\n /**\n * Text style\n */\n get style(): TextStyle {\n return this._style;\n }\n\n set style(value: TextStyle) {\n this._localStyle = { ...value };\n this._style = { ...DEFAULT_STYLE, ...value };\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n\n /**\n * Style class name for StyleManager\n */\n get styleClass(): string | undefined {\n return this._styleClass;\n }\n\n set styleClass(value: string | undefined) {\n if (this._styleClass !== value) {\n this._styleClass = value;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n /**\n * Maximum width for text wrapping\n */\n get maxWidth(): number | undefined {\n return this._maxWidth;\n }\n\n set maxWidth(value: number | undefined) {\n if (this._maxWidth === value) {\n return;\n }\n this._maxWidth = value;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n\n /**\n * Internal max width used for automatic wrapping by container elements.\n */\n setAutoMaxWidth(value: number | undefined): void {\n if (this._autoMaxWidth === value) {\n return;\n }\n this._autoMaxWidth = value;\n this._lines = [];\n this._measureDirty = true;\n }\n\n /**\n * Label padding\n */\n get padding(): number {\n return this._padding;\n }\n\n set padding(value: number) {\n const next = Number.isFinite(value) ? Math.max(0, value) : this._padding;\n if (this._padding !== next) {\n this._padding = next;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n /**\n * Label margin\n */\n get margin(): number {\n return this._margin;\n }\n\n set margin(value: number) {\n const next = Number.isFinite(value) ? Math.max(0, value) : this._margin;\n if (this._margin !== next) {\n this._margin = next;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getTextStyle(this._styleClass);\n const mergedStyle = { ...baseStyle, ...this._localStyle };\n if (!shallowEqual(this._style, mergedStyle)) {\n this._style = mergedStyle;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n }\n\n setOnChange(handler?: () => void): void {\n this._onChange = handler;\n }\n\n /**\n * Measured width after layout\n */\n get measuredWidth(): number {\n return this._measuredWidth;\n }\n\n /**\n * Measured height after layout\n */\n get measuredHeight(): number {\n return this._measuredHeight;\n }\n\n /**\n * Get wrapped lines for export. Uses ctx to measure and wrap by words.\n * Call with maxWidth = inner bounds width (e.g. bounds.width - margin*2).\n */\n getWrappedLines(ctx: CanvasRenderingContext2D, maxWidth: number): string[] {\n this.setAutoMaxWidth(maxWidth);\n this.measure(ctx);\n return this._lines;\n }\n\n /**\n * Measure and layout text, returns dimensions\n */\n measure(ctx: CanvasRenderingContext2D): { width: number; height: number } {\n if (!this._measureDirty && this._lines.length > 0) {\n return {\n width: this._measuredWidth,\n height: this._measuredHeight,\n };\n }\n\n this.applyStyle(ctx);\n\n const lineHeight = (this._style.fontSize ?? 14) * 1.2;\n\n const effectiveMaxWidth = this._maxWidth ?? this._autoMaxWidth;\n\n const text = this._text ?? '';\n if (effectiveMaxWidth !== undefined) {\n const maxWidth = Math.max(0, effectiveMaxWidth - this._margin * 2);\n this._lines = this.wrapText(ctx, text, Math.max(0, maxWidth - this._padding * 2));\n } else {\n this._lines = text.split('\\n');\n }\n\n // Calculate dimensions\n let maxLineWidth = 0;\n for (const line of this._lines) {\n const metrics = ctx.measureText(line);\n maxLineWidth = Math.max(maxLineWidth, metrics.width);\n }\n\n this._measuredWidth = maxLineWidth + this._padding * 2 + this._margin * 2;\n this._measuredHeight = this._lines.length * lineHeight + this._padding * 2 + this._margin * 2;\n this._measureDirty = false;\n\n return {\n width: this._measuredWidth,\n height: this._measuredHeight,\n };\n }\n\n /**\n * Render the label within bounds\n */\n render(ctx: CanvasRenderingContext2D, bounds: Bounds, alignOverride?: 'left' | 'center' | 'right'): void {\n if (this._lines.length === 0) {\n this.measure(ctx);\n }\n\n this.applyStyle(ctx);\n\n const align = alignOverride ?? this._style.align ?? 'center';\n if (alignOverride) {\n ctx.textAlign = align;\n }\n\n const lineHeight = (this._style.fontSize ?? 14) * 1.2;\n const totalHeight = this._lines.length * lineHeight;\n\n const margin = this._margin;\n const innerBounds: Bounds = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n\n // Calculate starting position based on alignment\n let x: number;\n switch (align) {\n case 'left':\n x = innerBounds.x + this._padding;\n break;\n case 'right':\n x = innerBounds.x + innerBounds.width - this._padding;\n break;\n default:\n x = innerBounds.x + innerBounds.width / 2;\n }\n\n const startY = innerBounds.y + (innerBounds.height - totalHeight) / 2 + lineHeight / 2;\n\n ctx.fillStyle = this._style.color ?? '#000000';\n\n for (let i = 0; i < this._lines.length; i++) {\n const line = this._lines[i]!;\n const y = startY + i * lineHeight;\n ctx.fillText(line, x, y);\n }\n }\n\n /**\n * Render at a specific point (for edge labels)\n */\n renderAt(ctx: CanvasRenderingContext2D, point: Point): void {\n if (this._lines.length === 0) {\n this.measure(ctx);\n }\n\n this.applyStyle(ctx);\n\n const lineHeight = (this._style.fontSize ?? 14) * 1.2;\n const totalHeight = this._lines.length * lineHeight;\n const startY = point.y - totalHeight / 2 + lineHeight / 2;\n\n ctx.fillStyle = this._style.color ?? '#000000';\n\n for (let i = 0; i < this._lines.length; i++) {\n const line = this._lines[i]!;\n const y = startY + i * lineHeight;\n ctx.fillText(line, point.x, y);\n }\n }\n\n private applyStyle(ctx: CanvasRenderingContext2D): void {\n const fontSize = this._style.fontSize ?? 14;\n const fontFamily = this._style.fontFamily ?? 'sans-serif';\n const fontWeight = this._style.fontWeight ?? 'normal';\n\n // Always construct font from individual properties to ensure fontSize changes are applied\n ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n ctx.textAlign = this._style.align ?? 'center';\n ctx.textBaseline = this._style.baseline ?? 'middle';\n }\n\n private wrapText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number): string[] {\n const lines: string[] = [];\n const paragraphs = text.split('\\n');\n\n for (const paragraph of paragraphs) {\n const words = paragraph.split(' ');\n let currentLine = '';\n\n for (const word of words) {\n const testLine = currentLine.length > 0 ? `${currentLine} ${word}` : word;\n const metrics = ctx.measureText(testLine);\n\n if (metrics.width > maxWidth && currentLine.length > 0) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine = testLine;\n }\n }\n\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n }\n\n return lines.length > 0 ? lines : [''];\n }\n}\n","import { TextLabel } from '@/elements/TextLabel';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { Node } from '@/elements/Node';\nimport type {\n ArrowMarkerConfig,\n ArrowType,\n Command,\n EdgeLabelBackground,\n EdgePathType,\n EdgeStyle,\n ElementStyle,\n NodeStyle,\n Point,\n TextStyle,\n} from '@/types';\n\nexport interface LabelSnapshot {\n text: string;\n editableText?: string;\n style?: TextStyle;\n styleClass?: string;\n maxWidth?: number;\n}\n\nexport interface NodeSnapshot {\n style: NodeStyle;\n styleClass?: string;\n label?: LabelSnapshot;\n cornerRadius?: number;\n showPortsAlways: boolean;\n}\n\nexport interface EdgeSnapshot {\n style: EdgeStyle;\n styleClass?: string;\n label?: LabelSnapshot;\n labelOffset: number;\n labelBackground?: EdgeLabelBackground;\n startMarker?: ArrowMarkerConfig;\n endMarker?: ArrowMarkerConfig;\n arrowType: ArrowType;\n type: EdgePathType;\n controlPoints?: Point[];\n}\n\nexport interface GroupSnapshot {\n style: ElementStyle;\n styleClass?: string;\n label?: string;\n padding: number;\n}\n\nconst cloneValue = <T>(value: T): T => {\n if (value === undefined) {\n return value;\n }\n return JSON.parse(JSON.stringify(value)) as T;\n};\n\nconst snapshotLabel = (label?: TextLabel): LabelSnapshot | undefined => {\n if (!label) {\n return undefined;\n }\n return {\n text: label.text,\n editableText: label.editableText,\n style: cloneValue(label.style),\n styleClass: label.styleClass,\n maxWidth: label.maxWidth,\n };\n};\n\nconst applyLabelSnapshot = (\n current: TextLabel | undefined,\n snapshot?: LabelSnapshot\n): TextLabel | undefined => {\n if (!snapshot) {\n return undefined;\n }\n if (current) {\n current.text = snapshot.text;\n current.editableText = snapshot.editableText;\n current.style = snapshot.style ?? {};\n current.styleClass = snapshot.styleClass;\n current.maxWidth = snapshot.maxWidth;\n return current;\n }\n return new TextLabel({\n text: snapshot.text,\n editableText: snapshot.editableText,\n style: snapshot.style,\n styleClass: snapshot.styleClass,\n maxWidth: snapshot.maxWidth,\n });\n};\n\nexport const createNodeSnapshot = (node: Node): NodeSnapshot => {\n const cornerRadius =\n 'cornerRadius' in node ? (node as { cornerRadius: number }).cornerRadius : undefined;\n return {\n style: cloneValue(node.styleOverrides as NodeStyle),\n styleClass: node.styleClass,\n label: snapshotLabel(node.label),\n cornerRadius,\n showPortsAlways: node.showPortsAlways,\n };\n};\n\nexport const createEdgeSnapshot = (edge: Edge): EdgeSnapshot => {\n return {\n style: cloneValue(edge.styleOverrides as EdgeStyle),\n styleClass: edge.styleClass,\n label: snapshotLabel(edge.label),\n labelOffset: edge.labelOffset,\n labelBackground: cloneValue(edge.labelBackground),\n startMarker: cloneValue(edge.startMarker),\n endMarker: cloneValue(edge.endMarker),\n arrowType: edge.arrowType,\n type: edge.type,\n controlPoints: cloneValue(edge.controlPoints),\n };\n};\n\nexport const createGroupSnapshot = (group: Group): GroupSnapshot => {\n return {\n style: cloneValue(group.styleOverrides),\n styleClass: group.styleClass,\n label: group.label,\n padding: group.padding,\n };\n};\n\n/**\n * Command for moving nodes\n */\nexport class MoveNodesCommand implements Command {\n private readonly nodePositions: Map<\n string,\n { before: { x: number; y: number }; after: { x: number; y: number } }\n >;\n private readonly getNode: (id: string) => { x: number; y: number } | undefined;\n\n constructor(\n getNode: (id: string) => { x: number; y: number } | undefined,\n nodePositions: Map<\n string,\n { before: { x: number; y: number }; after: { x: number; y: number } }\n >\n ) {\n this.getNode = getNode;\n this.nodePositions = new Map(nodePositions);\n }\n\n execute(): void {\n for (const [id, pos] of this.nodePositions) {\n const node = this.getNode(id);\n if (node !== undefined) {\n node.x = pos.after.x;\n node.y = pos.after.y;\n }\n }\n }\n\n undo(): void {\n for (const [id, pos] of this.nodePositions) {\n const node = this.getNode(id);\n if (node !== undefined) {\n node.x = pos.before.x;\n node.y = pos.before.y;\n }\n }\n }\n}\n\n/**\n * Command for adding a node\n */\nexport class AddNodeCommand implements Command {\n private readonly nodeId: string;\n private readonly addNode: () => void;\n private readonly removeNode: (id: string) => void;\n\n constructor(nodeId: string, addNode: () => void, removeNode: (id: string) => void) {\n this.nodeId = nodeId;\n this.addNode = addNode;\n this.removeNode = removeNode;\n }\n\n execute(): void {\n this.addNode();\n }\n\n undo(): void {\n this.removeNode(this.nodeId);\n }\n}\n\n/**\n * Command for removing a node\n */\nexport class RemoveNodeCommand implements Command {\n private readonly nodeId: string;\n private readonly addNode: () => void;\n private readonly removeNode: (id: string) => void;\n\n constructor(nodeId: string, addNode: () => void, removeNode: (id: string) => void) {\n this.nodeId = nodeId;\n this.addNode = addNode;\n this.removeNode = removeNode;\n }\n\n execute(): void {\n this.removeNode(this.nodeId);\n }\n\n undo(): void {\n this.addNode();\n }\n}\n\n/**\n * Composite command for grouping multiple commands\n */\nexport class CompositeCommand implements Command {\n private readonly commands: Command[];\n\n constructor(commands: Command[]) {\n this.commands = [...commands];\n }\n\n execute(): void {\n for (const command of this.commands) {\n command.execute();\n }\n }\n\n undo(): void {\n // Undo in reverse order\n for (let i = this.commands.length - 1; i >= 0; i--) {\n this.commands[i]!.undo();\n }\n }\n}\n\n/**\n * Command for changing node properties\n */\nexport class ChangeNodePropertiesCommand implements Command {\n private readonly getNode: (id: string) => Node | undefined;\n private readonly nodeId: string;\n private before: NodeSnapshot;\n private after: NodeSnapshot;\n\n constructor(\n getNode: (id: string) => Node | undefined,\n nodeId: string,\n before: NodeSnapshot,\n after: NodeSnapshot\n ) {\n this.getNode = getNode;\n this.nodeId = nodeId;\n this.before = cloneValue(before);\n this.after = cloneValue(after);\n }\n\n execute(): void {\n const node = this.getNode(this.nodeId);\n if (!node) {\n return;\n }\n node.style = cloneValue(this.after.style ?? {});\n node.styleClass = this.after.styleClass;\n node.label = applyLabelSnapshot(node.label, this.after.label);\n node.showPortsAlways = this.after.showPortsAlways;\n if (this.after.cornerRadius !== undefined && 'cornerRadius' in node) {\n (node as { cornerRadius: number }).cornerRadius = this.after.cornerRadius;\n }\n }\n\n undo(): void {\n const node = this.getNode(this.nodeId);\n if (!node) {\n return;\n }\n node.style = cloneValue(this.before.style ?? {});\n node.styleClass = this.before.styleClass;\n node.label = applyLabelSnapshot(node.label, this.before.label);\n node.showPortsAlways = this.before.showPortsAlways;\n if (this.before.cornerRadius !== undefined && 'cornerRadius' in node) {\n (node as { cornerRadius: number }).cornerRadius = this.before.cornerRadius;\n }\n }\n}\n\n/**\n * Command for changing edge properties\n */\nexport class ChangeEdgePropertiesCommand implements Command {\n private readonly getEdge: (id: string) => Edge | undefined;\n private readonly edgeId: string;\n private before: EdgeSnapshot;\n private after: EdgeSnapshot;\n\n constructor(\n getEdge: (id: string) => Edge | undefined,\n edgeId: string,\n before: EdgeSnapshot,\n after: EdgeSnapshot\n ) {\n this.getEdge = getEdge;\n this.edgeId = edgeId;\n this.before = cloneValue(before);\n this.after = cloneValue(after);\n }\n\n execute(): void {\n const edge = this.getEdge(this.edgeId);\n if (!edge) {\n return;\n }\n edge.type = this.after.type;\n edge.controlPoints = cloneValue(this.after.controlPoints);\n edge.arrowType = this.after.arrowType;\n edge.startMarker = cloneValue(this.after.startMarker);\n edge.endMarker = cloneValue(this.after.endMarker);\n edge.labelOffset = this.after.labelOffset;\n edge.labelBackground = cloneValue(this.after.labelBackground);\n edge.style = cloneValue(this.after.style ?? {});\n edge.styleClass = this.after.styleClass;\n edge.label = applyLabelSnapshot(edge.label, this.after.label);\n }\n\n undo(): void {\n const edge = this.getEdge(this.edgeId);\n if (!edge) {\n return;\n }\n edge.type = this.before.type;\n edge.controlPoints = cloneValue(this.before.controlPoints);\n edge.arrowType = this.before.arrowType;\n edge.startMarker = cloneValue(this.before.startMarker);\n edge.endMarker = cloneValue(this.before.endMarker);\n edge.labelOffset = this.before.labelOffset;\n edge.labelBackground = cloneValue(this.before.labelBackground);\n edge.style = cloneValue(this.before.style ?? {});\n edge.styleClass = this.before.styleClass;\n edge.label = applyLabelSnapshot(edge.label, this.before.label);\n }\n}\n\n/**\n * Command for changing group properties\n */\nexport class ChangeGroupPropertiesCommand implements Command {\n private readonly getGroup: (id: string) => Group | undefined;\n private readonly groupId: string;\n private before: GroupSnapshot;\n private after: GroupSnapshot;\n\n constructor(\n getGroup: (id: string) => Group | undefined,\n groupId: string,\n before: GroupSnapshot,\n after: GroupSnapshot\n ) {\n this.getGroup = getGroup;\n this.groupId = groupId;\n this.before = cloneValue(before);\n this.after = cloneValue(after);\n }\n\n execute(): void {\n const group = this.getGroup(this.groupId);\n if (!group) {\n return;\n }\n group.style = cloneValue(this.after.style ?? {});\n group.styleClass = this.after.styleClass;\n group.label = this.after.label;\n group.padding = this.after.padding;\n }\n\n undo(): void {\n const group = this.getGroup(this.groupId);\n if (!group) {\n return;\n }\n group.style = cloneValue(this.before.style ?? {});\n group.styleClass = this.before.styleClass;\n group.label = this.before.label;\n group.padding = this.before.padding;\n }\n}\n\n/**\n * Command for removing a node from groups\n */\nexport class RemoveNodeFromGroupsCommand implements Command {\n private readonly getGroup: (id: string) => Group | undefined;\n private readonly getNode: (id: string) => Node | undefined;\n private readonly nodeId: string;\n private readonly groupIds: string[];\n\n constructor(\n getGroup: (id: string) => Group | undefined,\n getNode: (id: string) => Node | undefined,\n nodeId: string,\n groupIds: string[]\n ) {\n this.getGroup = getGroup;\n this.getNode = getNode;\n this.nodeId = nodeId;\n this.groupIds = [...groupIds];\n }\n\n execute(): void {\n for (const groupId of this.groupIds) {\n const group = this.getGroup(groupId);\n if (group) {\n group.removeChild(this.nodeId);\n }\n }\n }\n\n undo(): void {\n const node = this.getNode(this.nodeId);\n if (!node) {\n return;\n }\n for (const groupId of this.groupIds) {\n const group = this.getGroup(groupId);\n if (group) {\n if (!group.hasChild(this.nodeId)) {\n group.addChild(node);\n }\n }\n }\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { Command } from '@/types';\n\n/**\n * History events\n */\nexport interface HistoryEvents {\n change: [canUndo: boolean, canRedo: boolean];\n undo: [command: Command];\n redo: [command: Command];\n}\n\nexport interface HistoryManagerOptions {\n maxSize?: number;\n}\n\n/**\n * Manages undo/redo history using command pattern\n */\nexport class HistoryManager extends EventEmitter<HistoryEvents> {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxSize: number;\n\n constructor(options: HistoryManagerOptions = {}) {\n super();\n this.maxSize = options.maxSize ?? 100;\n }\n\n /**\n * Check if undo is available\n */\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n /**\n * Check if redo is available\n */\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n /**\n * Number of commands in undo stack\n */\n get undoCount(): number {\n return this.undoStack.length;\n }\n\n /**\n * Number of commands in redo stack\n */\n get redoCount(): number {\n return this.redoStack.length;\n }\n\n /**\n * Execute a command and add to history\n */\n execute(command: Command): void {\n command.execute();\n this.undoStack.push(command);\n\n // Clear redo stack on new command\n this.redoStack = [];\n\n // Limit stack size\n if (this.undoStack.length > this.maxSize) {\n this.undoStack.shift();\n }\n\n this.emitChange();\n }\n\n /**\n * Undo the last command\n */\n undo(): boolean {\n const command = this.undoStack.pop();\n if (command === undefined) {\n return false;\n }\n\n command.undo();\n this.redoStack.push(command);\n this.emit('undo', command);\n this.emitChange();\n\n return true;\n }\n\n /**\n * Redo the last undone command\n */\n redo(): boolean {\n const command = this.redoStack.pop();\n if (command === undefined) {\n return false;\n }\n\n command.execute();\n this.undoStack.push(command);\n this.emit('redo', command);\n this.emitChange();\n\n return true;\n }\n\n /**\n * Clear all history\n */\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.emitChange();\n }\n\n /**\n * Handle keyboard shortcuts.\n * Uses event.code for letter keys to work with any keyboard layout (e.g. Russian).\n */\n handleKeyDown(event: KeyboardEvent): boolean {\n const isCtrlOrMeta = event.ctrlKey || event.metaKey;\n const key = event.code.startsWith('Key')\n ? event.code.slice(3).toLowerCase()\n : event.key.toLowerCase();\n\n if (isCtrlOrMeta && key === 'z' && !event.shiftKey) {\n event.preventDefault();\n return this.undo();\n }\n\n if (isCtrlOrMeta && (key === 'y' || (key === 'z' && event.shiftKey))) {\n event.preventDefault();\n return this.redo();\n }\n\n return false;\n }\n\n private emitChange(): void {\n this.emit('change', this.canUndo, this.canRedo);\n }\n}\n\nexport {\n MoveNodesCommand,\n AddNodeCommand,\n RemoveNodeCommand,\n CompositeCommand,\n ChangeNodePropertiesCommand,\n ChangeEdgePropertiesCommand,\n ChangeGroupPropertiesCommand,\n RemoveNodeFromGroupsCommand,\n createNodeSnapshot,\n createEdgeSnapshot,\n createGroupSnapshot,\n} from './history/commands';\n","import type { Bounds, ElementState, ElementStyle, Point, Size } from '@/types';\n\nlet nextId = 1;\n\n/**\n * Generate a unique element ID\n */\nexport function generateId(prefix = 'el'): string {\n return `${prefix}_${nextId++}`;\n}\n\n/**\n * Reset ID counter (for testing)\n */\nexport function resetIdCounter(): void {\n nextId = 1;\n}\n\n/**\n * Abstract base class for all diagram elements\n */\nexport abstract class Element {\n readonly id: string;\n protected _x: number;\n protected _y: number;\n protected _width: number;\n protected _height: number;\n protected _state: ElementState = 'normal';\n protected _style: ElementStyle;\n protected _styleClass?: string;\n protected _dirty = true;\n protected _visible = true;\n private _dirtyListener?: () => void;\n\n /**\n * Custom data attached to this element\n */\n data: Record<string, unknown> = {};\n\n protected constructor(options: {\n id?: string;\n x: number;\n y: number;\n width: number;\n height: number;\n style?: ElementStyle;\n styleClass?: string;\n }) {\n this.id = options.id ?? generateId();\n this._x = options.x;\n this._y = options.y;\n this._width = options.width;\n this._height = options.height;\n this._style = options.style ?? {};\n this._styleClass = options.styleClass;\n }\n\n /**\n * X position in world coordinates\n */\n get x(): number {\n return this._x;\n }\n\n set x(value: number) {\n if (this._x !== value) {\n this._x = value;\n this.markDirty();\n }\n }\n\n /**\n * Y position in world coordinates\n */\n get y(): number {\n return this._y;\n }\n\n set y(value: number) {\n if (this._y !== value) {\n this._y = value;\n this.markDirty();\n }\n }\n\n /**\n * Position as Point\n */\n get position(): Point {\n return { x: this._x, y: this._y };\n }\n\n set position(value: Point) {\n const changed = this._x !== value.x || this._y !== value.y;\n this._x = value.x;\n this._y = value.y;\n if (changed) {\n this.markDirty();\n }\n }\n\n /**\n * Width of the element\n */\n get width(): number {\n return this._width;\n }\n\n set width(value: number) {\n if (this._width !== value) {\n this._width = value;\n this.markDirty();\n }\n }\n\n /**\n * Height of the element\n */\n get height(): number {\n return this._height;\n }\n\n set height(value: number) {\n if (this._height !== value) {\n this._height = value;\n this.markDirty();\n }\n }\n\n /**\n * Size as Size object\n */\n get size(): Size {\n return { width: this._width, height: this._height };\n }\n\n set size(value: Size) {\n const changed = this._width !== value.width || this._height !== value.height;\n this._width = value.width;\n this._height = value.height;\n if (changed) {\n this.markDirty();\n }\n }\n\n /**\n * Current interaction state\n */\n get state(): ElementState {\n return this._state;\n }\n\n set state(value: ElementState) {\n if (this._state !== value) {\n this._state = value;\n this.markDirty();\n }\n }\n\n /**\n * Style properties\n */\n get style(): ElementStyle {\n return this._style;\n }\n\n set style(value: ElementStyle) {\n this._style = value;\n this.markDirty();\n }\n\n /**\n * Raw style overrides (without theme/class merge)\n */\n get styleOverrides(): ElementStyle {\n return this._style;\n }\n\n /**\n * Clear raw style overrides\n */\n clearStyleOverrides(): void {\n if (Object.keys(this._style).length === 0) {\n return;\n }\n this._style = {};\n this.markDirty();\n }\n\n /**\n * Style class name for StyleManager\n */\n get styleClass(): string | undefined {\n return this._styleClass;\n }\n\n set styleClass(value: string | undefined) {\n if (this._styleClass !== value) {\n this._styleClass = value;\n this.markDirty();\n }\n }\n\n /**\n * Whether the element needs to be re-rendered\n */\n get dirty(): boolean {\n return this._dirty;\n }\n\n /**\n * Whether the element is visible\n */\n get visible(): boolean {\n return this._visible;\n }\n\n set visible(value: boolean) {\n if (this._visible !== value) {\n this._visible = value;\n this.markDirty();\n }\n }\n\n /**\n * Mark this element as needing re-render\n */\n markDirty(): void {\n this._dirty = true;\n this._dirtyListener?.();\n }\n\n /**\n * Clear the dirty flag after rendering\n */\n clearDirty(): void {\n this._dirty = false;\n }\n\n /**\n * Register a dirty listener (used by DiagramRenderer)\n */\n setDirtyListener(listener?: () => void): void {\n this._dirtyListener = listener;\n }\n\n /**\n * Get the bounding box of this element\n */\n getBounds(): Bounds {\n return {\n x: this._x,\n y: this._y,\n width: this._width,\n height: this._height,\n };\n }\n\n /**\n * Get the center point of this element\n */\n getCenter(): Point {\n return {\n x: this._x + this._width / 2,\n y: this._y + this._height / 2,\n };\n }\n\n /**\n * Test if a point is within this element\n * @param point - Point in world coordinates\n */\n abstract hitTest(point: Point): boolean;\n\n /**\n * Render this element to the canvas\n * @param ctx - Canvas rendering context\n */\n abstract render(ctx: CanvasRenderingContext2D): void;\n}\n","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions } from './PathStrategy';\nimport { distanceToSegment } from '@/utils/geometry';\n\n/**\n * Straight line path strategy\n */\nexport class StraightPathStrategy implements PathStrategy {\n calculatePath(\n from: Point,\n to: Point,\n _fromDir?: string,\n _toDir?: string,\n _options?: PathStrategyOptions\n ): Point[] {\n return [from, to];\n }\n\n hitTest(point: Point, path: Point[], tolerance: number): boolean {\n if (path.length < 2) {\n return false;\n }\n return distanceToSegment(point, path[0]!, path[1]!) <= tolerance;\n }\n}\n","export type Direction = 'top' | 'right' | 'bottom' | 'left' | undefined;\n\nexport function isHorizontal(dir?: string): boolean {\n return dir === 'left' || dir === 'right';\n}\n\nexport function isVertical(dir?: string): boolean {\n return dir === 'top' || dir === 'bottom';\n}\n\nexport function isOppositeDirections(fromDir?: string, toDir?: string): boolean {\n return (\n (fromDir === 'left' && toDir === 'right') ||\n (fromDir === 'right' && toDir === 'left') ||\n (fromDir === 'top' && toDir === 'bottom') ||\n (fromDir === 'bottom' && toDir === 'top')\n );\n}\n\nexport function directionToVector(dir?: string): { x: number; y: number } {\n switch (dir) {\n case 'top':\n return { x: 0, y: -1 };\n case 'bottom':\n return { x: 0, y: 1 };\n case 'left':\n return { x: -1, y: 0 };\n case 'right':\n return { x: 1, y: 0 };\n default:\n return { x: 0, y: 0 };\n }\n}\n","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions, PathObstacle } from './PathStrategy';\nimport { distance, distanceToSegment } from '@/utils/geometry';\nimport { isHorizontal, isVertical, isOppositeDirections } from '@/utils/direction';\n\nconst MIN_SEGMENT_LENGTH = 20;\nconst SELF_LOOP_MIN_DISTANCE = 1;\nconst SELF_LOOP_OFFSET = 42;\nconst SELF_LOOP_SPREAD = 20;\nconst CORNER_BYPASS_DISTANCE = 220;\nconst CORNER_BYPASS_CLEARANCE = 34;\nconst OPPOSITE_BYPASS_DISTANCE = 280;\nconst OPPOSITE_BYPASS_CLEARANCE = 36;\nconst OPPOSITE_BYPASS_ARC = 48;\nconst OBSTACLE_ROUTING_DISTANCE = 1200;\nconst OBSTACLE_MARGIN = 12;\nconst ROUTE_EXIT_DISTANCE = 32;\nconst TURN_PENALTY = 70;\nconst FIRST_VERTICAL_PENALTY = 28;\n\nfunction expandObstacles(obstacles: PathObstacle[], margin: number): PathObstacle[] {\n return obstacles.map((obstacle) => ({\n ...obstacle,\n x: obstacle.x - margin,\n y: obstacle.y - margin,\n width: obstacle.width + margin * 2,\n height: obstacle.height + margin * 2,\n }));\n}\n\nfunction pointInsideObstacle(point: Point, obstacle: PathObstacle): boolean {\n return (\n point.x >= obstacle.x &&\n point.x <= obstacle.x + obstacle.width &&\n point.y >= obstacle.y &&\n point.y <= obstacle.y + obstacle.height\n );\n}\n\nfunction segmentIntersectsExpandedObstacle(a: Point, b: Point, obstacle: PathObstacle): boolean {\n const minX = obstacle.x;\n const maxX = obstacle.x + obstacle.width;\n const minY = obstacle.y;\n const maxY = obstacle.y + obstacle.height;\n\n if (Math.abs(a.x - b.x) < 0.001) {\n const x = a.x;\n const y1 = Math.min(a.y, b.y);\n const y2 = Math.max(a.y, b.y);\n return x >= minX && x <= maxX && y2 >= minY && y1 <= maxY;\n }\n\n if (Math.abs(a.y - b.y) < 0.001) {\n const y = a.y;\n const x1 = Math.min(a.x, b.x);\n const x2 = Math.max(a.x, b.x);\n return y >= minY && y <= maxY && x2 >= minX && x1 <= maxX;\n }\n\n return false;\n}\n\nfunction simplifyPath(path: Point[]): Point[] {\n const out: Point[] = [];\n for (const point of path) {\n const prev = out[out.length - 1];\n if (!prev || Math.abs(prev.x - point.x) > 0.001 || Math.abs(prev.y - point.y) > 0.001) {\n out.push(point);\n }\n }\n return out;\n}\n\nfunction manhattan(a: Point, b: Point): number {\n return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n}\n\nfunction moveByDir(point: Point, dir: string | undefined, distance: number): Point {\n switch (dir) {\n case 'top':\n return { x: point.x, y: point.y - distance };\n case 'bottom':\n return { x: point.x, y: point.y + distance };\n case 'left':\n return { x: point.x - distance, y: point.y };\n case 'right':\n return { x: point.x + distance, y: point.y };\n default:\n return point;\n }\n}\n\nfunction inferDir(from: Point, to: Point): string {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n // Prefer horizontal decisions when comparable.\n if (Math.abs(dx) >= Math.abs(dy)) {\n return dx >= 0 ? 'right' : 'left';\n }\n return dy >= 0 ? 'bottom' : 'top';\n}\n\nfunction oppositeDir(dir: string): string {\n switch (dir) {\n case 'left':\n return 'right';\n case 'right':\n return 'left';\n case 'top':\n return 'bottom';\n case 'bottom':\n return 'top';\n default:\n return dir;\n }\n}\n\nfunction buildRoutedPolyline(\n from: Point,\n to: Point,\n fromDir: string | undefined,\n toDir: string | undefined,\n obstacles: PathObstacle[]\n): Point[] | null {\n if (obstacles.length === 0) {\n return null;\n }\n\n const effectiveFromDir = fromDir ?? inferDir(from, to);\n const effectiveToDir = toDir ?? oppositeDir(effectiveFromDir);\n\n const startExit = moveByDir(from, effectiveFromDir, ROUTE_EXIT_DISTANCE);\n const endEntry = moveByDir(to, effectiveToDir, ROUTE_EXIT_DISTANCE);\n const expanded = expandObstacles(obstacles, OBSTACLE_MARGIN);\n\n const xs = new Set<number>([startExit.x, endEntry.x]);\n const ys = new Set<number>([startExit.y, endEntry.y]);\n for (const obstacle of expanded) {\n xs.add(obstacle.x - 1);\n xs.add(obstacle.x + obstacle.width + 1);\n ys.add(obstacle.y - 1);\n ys.add(obstacle.y + obstacle.height + 1);\n }\n\n type GraphNode = { x: number; y: number };\n const nodes: GraphNode[] = [];\n const nodeIndex = new Map<string, number>();\n const nodeKey = (x: number, y: number): string => `${x}|${y}`;\n const addNode = (x: number, y: number): void => {\n const key = nodeKey(x, y);\n if (nodeIndex.has(key)) return;\n const point = { x, y };\n if (expanded.some((obstacle) => pointInsideObstacle(point, obstacle))) {\n return;\n }\n nodeIndex.set(key, nodes.length);\n nodes.push(point);\n };\n\n for (const x of xs) {\n for (const y of ys) {\n addNode(x, y);\n }\n }\n addNode(startExit.x, startExit.y);\n addNode(endEntry.x, endEntry.y);\n\n const startIdx = nodeIndex.get(nodeKey(startExit.x, startExit.y));\n const goalIdx = nodeIndex.get(nodeKey(endEntry.x, endEntry.y));\n if (startIdx == null || goalIdx == null) {\n return null;\n }\n\n const edges = new Map<number, Array<{ to: number; dir: 'h' | 'v'; length: number }>>();\n const pushEdge = (a: number, b: number, dir: 'h' | 'v', length: number): void => {\n const list = edges.get(a) ?? [];\n list.push({ to: b, dir, length });\n edges.set(a, list);\n };\n\n const byX = new Map<number, number[]>();\n const byY = new Map<number, number[]>();\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!;\n const xsList = byX.get(node.x) ?? [];\n xsList.push(i);\n byX.set(node.x, xsList);\n const ysList = byY.get(node.y) ?? [];\n ysList.push(i);\n byY.set(node.y, ysList);\n }\n\n for (const list of byX.values()) {\n list.sort((a, b) => nodes[a]!.y - nodes[b]!.y);\n for (let i = 1; i < list.length; i++) {\n const a = nodes[list[i - 1]!]!;\n const b = nodes[list[i]!]!;\n if (!expanded.some((obstacle) => segmentIntersectsExpandedObstacle(a, b, obstacle))) {\n const length = manhattan(a, b);\n pushEdge(list[i - 1]!, list[i]!, 'v', length);\n pushEdge(list[i]!, list[i - 1]!, 'v', length);\n }\n }\n }\n for (const list of byY.values()) {\n list.sort((a, b) => nodes[a]!.x - nodes[b]!.x);\n for (let i = 1; i < list.length; i++) {\n const a = nodes[list[i - 1]!]!;\n const b = nodes[list[i]!]!;\n if (!expanded.some((obstacle) => segmentIntersectsExpandedObstacle(a, b, obstacle))) {\n const length = manhattan(a, b);\n pushEdge(list[i - 1]!, list[i]!, 'h', length);\n pushEdge(list[i]!, list[i - 1]!, 'h', length);\n }\n }\n }\n\n type DirState = 'h' | 'v' | 's';\n type QueueState = { node: number; dir: DirState; g: number; f: number; key: string };\n const makeStateKey = (node: number, dir: DirState): string => `${node}:${dir}`;\n const open: QueueState[] = [];\n const best = new Map<string, number>();\n const prev = new Map<string, string>();\n const startKey = makeStateKey(startIdx, 's');\n best.set(startKey, 0);\n open.push({\n node: startIdx,\n dir: 's',\n g: 0,\n f: manhattan(nodes[startIdx]!, nodes[goalIdx]!),\n key: startKey,\n });\n\n let goalKey: string | null = null;\n while (open.length > 0) {\n let bestIdx = 0;\n for (let i = 1; i < open.length; i++) {\n if (open[i]!.f < open[bestIdx]!.f) bestIdx = i;\n }\n const current = open.splice(bestIdx, 1)[0]!;\n if (current.node === goalIdx) {\n goalKey = current.key;\n break;\n }\n\n for (const edge of edges.get(current.node) ?? []) {\n const nextDir = edge.dir;\n let stepCost = edge.length;\n if (current.dir !== 's' && current.dir !== nextDir) {\n stepCost += TURN_PENALTY;\n }\n if (current.dir === 's' && nextDir === 'v') {\n stepCost += FIRST_VERTICAL_PENALTY;\n }\n const nextG = current.g + stepCost;\n const nextKey = makeStateKey(edge.to, nextDir);\n if (nextG >= (best.get(nextKey) ?? Infinity)) {\n continue;\n }\n best.set(nextKey, nextG);\n prev.set(nextKey, current.key);\n const h = manhattan(nodes[edge.to]!, nodes[goalIdx]!);\n open.push({ node: edge.to, dir: nextDir, g: nextG, f: nextG + h, key: nextKey });\n }\n }\n\n if (!goalKey) {\n return null;\n }\n\n const routed: Point[] = [];\n let cursor: string | undefined = goalKey;\n while (cursor) {\n const [nodePart] = cursor.split(':');\n const node = nodes[Number(nodePart)]!;\n routed.push({ x: node.x, y: node.y });\n cursor = prev.get(cursor);\n }\n routed.reverse();\n\n const internal = simplifyPath(routed).filter(\n (_, idx, arr) => idx !== 0 && idx !== arr.length - 1\n );\n return simplifyPath([from, startExit, ...internal, endEntry, to]);\n}\n\n/**\n * Polyline path strategy\n */\nexport class PolylinePathStrategy implements PathStrategy {\n calculatePath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string,\n _options?: PathStrategyOptions\n ): Point[] {\n const controlPoints = _options?.controlPoints;\n if (_options?.editablePolyline) {\n if (controlPoints && controlPoints.length > 0) {\n return [from, ...controlPoints, to];\n }\n return [from, { x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 }, to];\n }\n\n const dist = distance(from, to);\n const selfLoop = _options?.selfLoop ?? false;\n const obstacles = _options?.obstacles ?? [];\n\n if (!selfLoop && dist < OBSTACLE_ROUTING_DISTANCE) {\n const routed = buildRoutedPolyline(from, to, fromDir, toDir, obstacles);\n if (routed) {\n return routed;\n }\n }\n\n if (selfLoop && dist < SELF_LOOP_MIN_DISTANCE && (fromDir || toDir)) {\n const dir = fromDir ?? toDir;\n switch (dir) {\n case 'bottom':\n return [\n from,\n { x: from.x - SELF_LOOP_SPREAD, y: from.y + SELF_LOOP_OFFSET },\n { x: from.x + SELF_LOOP_SPREAD, y: from.y + SELF_LOOP_OFFSET },\n to,\n ];\n case 'left':\n return [\n from,\n { x: from.x - SELF_LOOP_OFFSET, y: from.y + SELF_LOOP_SPREAD },\n { x: from.x - SELF_LOOP_OFFSET, y: from.y - SELF_LOOP_SPREAD },\n to,\n ];\n case 'right':\n return [\n from,\n { x: from.x + SELF_LOOP_OFFSET, y: from.y - SELF_LOOP_SPREAD },\n { x: from.x + SELF_LOOP_OFFSET, y: from.y + SELF_LOOP_SPREAD },\n to,\n ];\n case 'top':\n default:\n return [\n from,\n { x: from.x + SELF_LOOP_SPREAD, y: from.y - SELF_LOOP_OFFSET },\n { x: from.x - SELF_LOOP_SPREAD, y: from.y - SELF_LOOP_OFFSET },\n to,\n ];\n }\n }\n\n if (\n selfLoop &&\n dist < OPPOSITE_BYPASS_DISTANCE &&\n fromDir &&\n toDir &&\n isOppositeDirections(fromDir, toDir)\n ) {\n if (isHorizontal(fromDir) && isHorizontal(toDir)) {\n const fromStepX =\n fromDir === 'left' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const toStepX = toDir === 'left' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const sideY = from.x <= to.x ? -1 : 1;\n const outerY = from.y + sideY * OPPOSITE_BYPASS_ARC;\n return [\n from,\n { x: from.x + fromStepX, y: from.y },\n { x: from.x + fromStepX, y: outerY },\n { x: to.x + toStepX, y: outerY },\n { x: to.x + toStepX, y: to.y },\n to,\n ];\n }\n if (isVertical(fromDir) && isVertical(toDir)) {\n const fromStepY =\n fromDir === 'top' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const toStepY = toDir === 'top' ? -OPPOSITE_BYPASS_CLEARANCE : OPPOSITE_BYPASS_CLEARANCE;\n const sideX = from.y <= to.y ? 1 : -1;\n const outerX = from.x + sideX * OPPOSITE_BYPASS_ARC;\n return [\n from,\n { x: from.x, y: from.y + fromStepY },\n { x: outerX, y: from.y + fromStepY },\n { x: outerX, y: to.y + toStepY },\n { x: to.x, y: to.y + toStepY },\n to,\n ];\n }\n }\n\n if (\n selfLoop &&\n dist < CORNER_BYPASS_DISTANCE &&\n fromDir &&\n toDir &&\n ((isHorizontal(fromDir) && isVertical(toDir)) || (isVertical(fromDir) && isHorizontal(toDir)))\n ) {\n const fromOuter = {\n x:\n from.x +\n (fromDir === 'left'\n ? -CORNER_BYPASS_CLEARANCE\n : fromDir === 'right'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n y:\n from.y +\n (fromDir === 'top'\n ? -CORNER_BYPASS_CLEARANCE\n : fromDir === 'bottom'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n };\n const toOuter = {\n x:\n to.x +\n (toDir === 'left'\n ? -CORNER_BYPASS_CLEARANCE\n : toDir === 'right'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n y:\n to.y +\n (toDir === 'top'\n ? -CORNER_BYPASS_CLEARANCE\n : toDir === 'bottom'\n ? CORNER_BYPASS_CLEARANCE\n : 0),\n };\n const corner = isHorizontal(fromDir)\n ? { x: fromOuter.x, y: toOuter.y }\n : { x: toOuter.x, y: fromOuter.y };\n return [from, fromOuter, corner, toOuter, to];\n }\n\n // If directions are specified, route accordingly\n if (fromDir || toDir) {\n return this.calculateDirectedPath(from, to, fromDir, toDir);\n }\n\n // Default behavior: auto-detect direction\n const midX = (from.x + to.x) / 2;\n\n // Horizontal-first routing\n if (Math.abs(to.x - from.x) > Math.abs(to.y - from.y)) {\n return [from, { x: midX, y: from.y }, { x: midX, y: to.y }, to];\n }\n\n // Vertical-first routing\n const midY = (from.y + to.y) / 2;\n return [from, { x: from.x, y: midY }, { x: to.x, y: midY }, to];\n }\n\n private calculateDirectedPath(from: Point, to: Point, fromDir?: string, toDir?: string): Point[] {\n const points: Point[] = [from];\n\n // Determine first segment based on fromDir\n const fromHorizontal = fromDir === 'left' || fromDir === 'right';\n const fromVertical = fromDir === 'top' || fromDir === 'bottom';\n const toHorizontal = toDir === 'left' || toDir === 'right';\n const toVertical = toDir === 'top' || toDir === 'bottom';\n\n if (fromVertical && toVertical) {\n // Both vertical: route with horizontal middle segment\n const midY = (from.y + to.y) / 2;\n const exitY =\n fromDir === 'top'\n ? Math.min(from.y - MIN_SEGMENT_LENGTH, midY)\n : Math.max(from.y + MIN_SEGMENT_LENGTH, midY);\n const entryY =\n toDir === 'top'\n ? Math.min(to.y - MIN_SEGMENT_LENGTH, midY)\n : Math.max(to.y + MIN_SEGMENT_LENGTH, midY);\n\n if (Math.abs(exitY - entryY) < 1) {\n points.push({ x: from.x, y: exitY });\n points.push({ x: to.x, y: exitY });\n } else {\n points.push({ x: from.x, y: exitY });\n points.push({ x: to.x, y: exitY });\n }\n } else if (fromHorizontal && toHorizontal) {\n // Both horizontal: route with vertical middle segment\n const midX = (from.x + to.x) / 2;\n const exitX =\n fromDir === 'left'\n ? Math.min(from.x - MIN_SEGMENT_LENGTH, midX)\n : Math.max(from.x + MIN_SEGMENT_LENGTH, midX);\n const entryX =\n toDir === 'left'\n ? Math.min(to.x - MIN_SEGMENT_LENGTH, midX)\n : Math.max(to.x + MIN_SEGMENT_LENGTH, midX);\n\n if (Math.abs(exitX - entryX) < 1) {\n points.push({ x: exitX, y: from.y });\n points.push({ x: exitX, y: to.y });\n } else {\n points.push({ x: exitX, y: from.y });\n points.push({ x: exitX, y: to.y });\n }\n } else if (fromVertical && toHorizontal) {\n // From vertical to horizontal\n points.push({ x: from.x, y: to.y });\n } else if (fromHorizontal && toVertical) {\n // From horizontal to vertical\n points.push({ x: to.x, y: from.y });\n } else {\n // Fallback: one corner\n const midX = (from.x + to.x) / 2;\n points.push({ x: midX, y: from.y });\n points.push({ x: midX, y: to.y });\n }\n\n points.push(to);\n return points;\n }\n\n hitTest(point: Point, path: Point[], tolerance: number): boolean {\n for (let i = 1; i < path.length; i++) {\n if (distanceToSegment(point, path[i - 1]!, path[i]!) <= tolerance) {\n return true;\n }\n }\n return false;\n }\n}\n","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions } from './PathStrategy';\nimport { bezierPoint, distance, distanceToSegment } from '@/utils/geometry';\nimport { BEZIER_MAX_OFFSET } from '@/constants';\nimport {\n isHorizontal,\n isVertical,\n isOppositeDirections,\n directionToVector as dirToVector,\n} from '@/utils/direction';\n\nconst SELF_LOOP_MIN_DISTANCE = 1;\nconst SELF_LOOP_OFFSET = 90;\nconst SELF_LOOP_SPREAD = 50;\nconst CORNER_BYPASS_DISTANCE = 220;\nconst CORNER_BYPASS_CLEARANCE = 80;\nconst OPPOSITE_BYPASS_DISTANCE = 280;\nconst OPPOSITE_BYPASS_CLEARANCE = 90;\nconst OPPOSITE_BYPASS_ARC = 120;\n\n/**\n * Get control point offset based on direction\n */\nfunction getDirectionOffset(dir: string | undefined, distance: number): Point {\n const offset = Math.min(distance * 0.5, BEZIER_MAX_OFFSET);\n switch (dir) {\n case 'top':\n return { x: 0, y: -offset };\n case 'bottom':\n return { x: 0, y: offset };\n case 'left':\n return { x: -offset, y: 0 };\n case 'right':\n return { x: offset, y: 0 };\n default:\n return { x: 0, y: 0 };\n }\n}\n\nfunction createSelfLoopPath(point: Point, dir?: string): Point[] {\n switch (dir) {\n case 'bottom':\n return [\n point,\n { x: point.x - SELF_LOOP_SPREAD, y: point.y + SELF_LOOP_OFFSET },\n { x: point.x + SELF_LOOP_SPREAD, y: point.y + SELF_LOOP_OFFSET },\n point,\n ];\n case 'left':\n return [\n point,\n { x: point.x - SELF_LOOP_OFFSET, y: point.y + SELF_LOOP_SPREAD },\n { x: point.x - SELF_LOOP_OFFSET, y: point.y - SELF_LOOP_SPREAD },\n point,\n ];\n case 'right':\n return [\n point,\n { x: point.x + SELF_LOOP_OFFSET, y: point.y - SELF_LOOP_SPREAD },\n { x: point.x + SELF_LOOP_OFFSET, y: point.y + SELF_LOOP_SPREAD },\n point,\n ];\n case 'top':\n default:\n return [\n point,\n { x: point.x + SELF_LOOP_SPREAD, y: point.y - SELF_LOOP_OFFSET },\n { x: point.x - SELF_LOOP_SPREAD, y: point.y - SELF_LOOP_OFFSET },\n point,\n ];\n }\n}\n\nfunction createOppositeBypassPath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string\n): Point[] | null {\n if (!fromDir || !toDir || !isOppositeDirections(fromDir, toDir)) {\n return null;\n }\n\n const fromOut = dirToVector(fromDir);\n const toOut = dirToVector(toDir);\n\n if (isHorizontal(fromDir) && isHorizontal(toDir)) {\n // left<->right: arc above/below node instead of crossing through center.\n const sideY = from.x <= to.x ? -1 : 1;\n return [\n from,\n {\n x: from.x + fromOut.x * OPPOSITE_BYPASS_CLEARANCE,\n y: from.y + sideY * OPPOSITE_BYPASS_ARC,\n },\n {\n x: to.x + toOut.x * OPPOSITE_BYPASS_CLEARANCE,\n y: to.y + sideY * OPPOSITE_BYPASS_ARC,\n },\n to,\n ];\n }\n\n if (isVertical(fromDir) && isVertical(toDir)) {\n // top<->bottom: arc left/right from node instead of crossing through center.\n const sideX = from.y <= to.y ? 1 : -1;\n return [\n from,\n {\n x: from.x + sideX * OPPOSITE_BYPASS_ARC,\n y: from.y + fromOut.y * OPPOSITE_BYPASS_CLEARANCE,\n },\n {\n x: to.x + sideX * OPPOSITE_BYPASS_ARC,\n y: to.y + toOut.y * OPPOSITE_BYPASS_CLEARANCE,\n },\n to,\n ];\n }\n\n return null;\n}\n\nfunction createCornerBypassPath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string\n): Point[] | null {\n if (!fromDir || !toDir) return null;\n const orthogonal =\n (isHorizontal(fromDir) && isVertical(toDir)) || (isVertical(fromDir) && isHorizontal(toDir));\n if (!orthogonal) return null;\n\n const fromOut = dirToVector(fromDir);\n const toOut = dirToVector(toDir);\n const fromOuter = {\n x: from.x + fromOut.x * CORNER_BYPASS_CLEARANCE,\n y: from.y + fromOut.y * CORNER_BYPASS_CLEARANCE,\n };\n const toOuter = {\n x: to.x + toOut.x * CORNER_BYPASS_CLEARANCE,\n y: to.y + toOut.y * CORNER_BYPASS_CLEARANCE,\n };\n // Single cubic bezier: smooth outer detour without a middle kink.\n return [from, fromOuter, toOuter, to];\n}\n\n/**\n * Bezier curve path strategy\n */\nexport class BezierPathStrategy implements PathStrategy {\n calculatePath(\n from: Point,\n to: Point,\n fromDir?: string,\n toDir?: string,\n options?: PathStrategyOptions\n ): Point[] {\n const dist = distance(from, to);\n const loopDir = fromDir ?? toDir;\n const selfLoop = options?.selfLoop ?? false;\n\n // For self-loop edges, build an explicit outer loop so the edge\n // does not pass under the node it is attached to.\n if (selfLoop && dist < SELF_LOOP_MIN_DISTANCE && loopDir) {\n return createSelfLoopPath(from, loopDir);\n }\n\n if (selfLoop && dist < OPPOSITE_BYPASS_DISTANCE) {\n const oppositeBypass = createOppositeBypassPath(from, to, fromDir, toDir);\n if (oppositeBypass) {\n return oppositeBypass;\n }\n }\n\n if (selfLoop && dist < CORNER_BYPASS_DISTANCE) {\n const cornerBypass = createCornerBypassPath(from, to, fromDir, toDir);\n if (cornerBypass) {\n return cornerBypass;\n }\n }\n\n const controlPoints = options?.controlPoints;\n if (controlPoints && controlPoints.length > 0) {\n if (controlPoints.length >= 3 && controlPoints.length % 3 === 0) {\n return [from, ...controlPoints];\n }\n if (controlPoints.length === 2) {\n return [from, controlPoints[0]!, controlPoints[1]!, to];\n }\n }\n\n // If directions are specified, use them for control points\n if (fromDir || toDir) {\n const fromOffset = getDirectionOffset(fromDir, dist);\n const toOffset = getDirectionOffset(toDir, dist);\n\n return [\n from,\n { x: from.x + fromOffset.x, y: from.y + fromOffset.y },\n { x: to.x + toOffset.x, y: to.y + toOffset.y },\n to,\n ];\n }\n\n // Default behavior: auto-detect direction\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const offset = Math.min(Math.abs(dx), Math.abs(dy), BEZIER_MAX_OFFSET) * 0.5 + 50;\n\n if (Math.abs(dx) > Math.abs(dy)) {\n // Horizontal dominant\n const offsetX = offset * Math.sign(dx || 1);\n return [from, { x: from.x + offsetX, y: from.y }, { x: to.x - offsetX, y: to.y }, to];\n } else {\n // Vertical dominant\n const offsetY = offset * Math.sign(dy || 1);\n return [from, { x: from.x, y: from.y + offsetY }, { x: to.x, y: to.y - offsetY }, to];\n }\n }\n\n hitTest(point: Point, path: Point[], tolerance: number): boolean {\n if (path.length < 4) {\n return false;\n }\n\n // Sample bezier curve and check distance to segments\n const samples = 20;\n const points: Point[] = [];\n\n for (let i = 0; i <= samples; i++) {\n const t = i / samples;\n points.push(bezierPoint(path[0]!, path[1]!, path[2]!, path[3]!, t));\n }\n\n for (let i = 1; i < points.length; i++) {\n if (distanceToSegment(point, points[i - 1]!, points[i]!) <= tolerance) {\n return true;\n }\n }\n\n return false;\n }\n}\n","import { Element, generateId } from './Element';\nimport { TextLabel, type TextLabelOptions } from './TextLabel';\nimport type {\n ArrowType,\n ArrowMarkerConfig,\n EdgeEndpoint,\n EdgePathType,\n EdgeStyle,\n EdgeLabelBackground,\n Point,\n} from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport { shallowEqual } from '@/utils/style';\nimport { bezierPoint, drawRoundedRectPath } from '@/utils/geometry';\nimport {\n type PathStrategy,\n type PathStrategyOptions,\n StraightPathStrategy,\n PolylinePathStrategy,\n BezierPathStrategy,\n} from './paths';\nimport {\n EDGE_HANDLE_RADIUS,\n ARROW_SIZE,\n ARROW_ANGLE,\n MARKER_SIZES,\n EDGE_LABEL_BACKGROUND_PADDING,\n EDGE_LABEL_BACKGROUND_RADIUS,\n DEFAULT_SELECTION_COLOR,\n DEFAULT_HOVER_COLOR,\n} from '@/constants';\n\nexport interface EdgeOptions {\n id?: string;\n from: EdgeEndpoint;\n to: EdgeEndpoint;\n type?: EdgePathType;\n controlPoints?: Point[];\n arrowType?: ArrowType;\n startMarker?: ArrowMarkerConfig;\n endMarker?: ArrowMarkerConfig;\n style?: EdgeStyle;\n styleClass?: string;\n label?: string | TextLabelOptions;\n labelOffset?: number;\n labelBackground?: EdgeLabelBackground;\n lockAnchors?: boolean;\n}\n\nconst DEFAULT_EDGE_STYLE: EdgeStyle = {\n strokeColor: '#666666',\n strokeWidth: 2,\n opacity: 1,\n};\n\nexport type { PathStrategy };\n\n/**\n * Connection edge between nodes\n */\nexport class Edge extends Element {\n private _from: EdgeEndpoint;\n private _to: EdgeEndpoint;\n private _type: EdgePathType;\n private _arrowType: ArrowType;\n private _startMarker?: ArrowMarkerConfig;\n private _endMarker?: ArrowMarkerConfig;\n private _edgeStyle: EdgeStyle;\n private _label?: TextLabel;\n private _labelOffset: number;\n private _labelBackground?: EdgeLabelBackground;\n private _path: Point[] = [];\n private _pathStrategy: PathStrategy;\n private _autoUpdateEndpoints = true;\n private _lockAnchors: boolean;\n private _controlPoints?: Point[];\n private _pathOptions?: PathStrategyOptions;\n\n // Cached positions for rendering\n private _fromPoint: Point = { x: 0, y: 0 };\n private _toPoint: Point = { x: 0, y: 0 };\n private _fromDir?: string;\n private _toDir?: string;\n\n constructor(options: EdgeOptions) {\n super({\n id: options.id ?? generateId('edge'),\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n style: options.style,\n styleClass: options.styleClass,\n });\n\n this._from = options.from;\n this._to = options.to;\n this._type = options.type ?? 'straight';\n this._arrowType = options.arrowType ?? 'single';\n this._controlPoints = options.controlPoints;\n this._startMarker = options.startMarker;\n this._endMarker = options.endMarker;\n this._edgeStyle = { ...DEFAULT_EDGE_STYLE, ...options.style };\n this._pathStrategy = this.getPathStrategy(this._type);\n this._lockAnchors = options.lockAnchors ?? true;\n this._labelOffset = options.labelOffset ?? 0;\n this._labelBackground = options.labelBackground;\n\n if (options.label !== undefined) {\n if (typeof options.label === 'string') {\n this._label = new TextLabel({\n text: options.label,\n onChange: (): void => this.markDirty(),\n });\n } else {\n this._label = new TextLabel({ ...options.label, onChange: (): void => this.markDirty() });\n }\n }\n }\n\n /**\n * Source endpoint\n */\n get from(): EdgeEndpoint {\n return this._from;\n }\n\n set from(value: EdgeEndpoint) {\n this._from = value;\n this.markDirty();\n }\n\n /**\n * Target endpoint\n */\n get to(): EdgeEndpoint {\n return this._to;\n }\n\n set to(value: EdgeEndpoint) {\n this._to = value;\n this.markDirty();\n }\n\n /**\n * Edge type\n */\n get type(): EdgePathType {\n return this._type;\n }\n\n set type(value: EdgePathType) {\n if (this._type !== value) {\n this._type = value;\n this._pathStrategy = this.getPathStrategy(value);\n if (value !== 'editable-polyline' && this._controlPoints?.length) {\n this.controlPoints = undefined;\n }\n this.markDirty();\n }\n }\n\n /**\n * Arrow type (legacy)\n */\n get arrowType(): ArrowType {\n return this._arrowType;\n }\n\n set arrowType(value: ArrowType) {\n if (this._arrowType !== value) {\n this._arrowType = value;\n this.markDirty();\n }\n }\n\n /**\n * Start marker configuration\n */\n get startMarker(): ArrowMarkerConfig | undefined {\n return this._startMarker;\n }\n\n set startMarker(value: ArrowMarkerConfig | undefined) {\n this._startMarker = value;\n this.markDirty();\n }\n\n /**\n * End marker configuration\n */\n get endMarker(): ArrowMarkerConfig | undefined {\n return this._endMarker;\n }\n\n set endMarker(value: ArrowMarkerConfig | undefined) {\n this._endMarker = value;\n this.markDirty();\n }\n\n /**\n * Label offset from center of path\n */\n get labelOffset(): number {\n return this._labelOffset;\n }\n\n set labelOffset(value: number) {\n if (this._labelOffset !== value) {\n this._labelOffset = value;\n this.markDirty();\n }\n }\n\n /**\n * Label background configuration\n */\n get labelBackground(): EdgeLabelBackground | undefined {\n return this._labelBackground;\n }\n\n set labelBackground(value: EdgeLabelBackground | undefined) {\n this._labelBackground = value;\n this.markDirty();\n }\n\n /**\n * Control points for custom paths.\n * For bezier format: [cp1, cp2, end, cp1, cp2, end, ...]\n * For editable-polyline: [point1, point2, ...]\n */\n get controlPoints(): Point[] | undefined {\n return this._controlPoints;\n }\n\n set controlPoints(value: Point[] | undefined) {\n this._controlPoints = value;\n this.recalculatePath();\n }\n\n /**\n * Whether this edge uses editable polyline controls.\n */\n isEditablePolyline(): boolean {\n return this._type === 'editable-polyline';\n }\n\n /**\n * Whether this edge has editable control points (editable-polyline with non-empty controlPoints).\n */\n hasEditableControlPoints(): boolean {\n return this.isEditablePolyline() && !!this._controlPoints?.length;\n }\n\n /**\n * Returns path vertices for editable polyline: [startPoint, ...controlPoints, endPoint].\n * Requires endpoints to be updated (startPoint/endPoint valid).\n */\n getPathVertices(): Point[] {\n const cps = this._controlPoints && this._controlPoints.length > 0\n ? this._controlPoints\n : this.getEditableControlPoints();\n return [this._fromPoint, ...cps, this._toPoint];\n }\n\n /**\n * Returns current editable control points.\n * For a fresh editable-polyline edge, exposes a virtual midpoint handle.\n */\n getEditableControlPoints(): Point[] {\n if (!this.isEditablePolyline()) {\n return [];\n }\n if (this._controlPoints && this._controlPoints.length > 0) {\n return this._controlPoints.map((point) => ({ ...point }));\n }\n return [\n {\n x: (this._fromPoint.x + this._toPoint.x) / 2,\n y: (this._fromPoint.y + this._toPoint.y) / 2,\n },\n ];\n }\n\n /**\n * Edge style\n */\n override get style(): EdgeStyle {\n return this._edgeStyle;\n }\n\n override set style(value: EdgeStyle) {\n this._edgeStyle = { ...DEFAULT_EDGE_STYLE, ...value };\n this._style = value;\n this.markDirty();\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getEdgeStyle(this._state, this._styleClass);\n let mergedStyle: EdgeStyle = { ...baseStyle, ...this._style };\n\n if (this._state !== 'normal') {\n const normalStyle = styleManager.getEdgeStyle('normal', this._styleClass);\n if (\n mergedStyle.strokeColor === baseStyle.strokeColor &&\n normalStyle.strokeColor !== undefined\n ) {\n mergedStyle = { ...mergedStyle, strokeColor: normalStyle.strokeColor };\n }\n }\n\n if (!shallowEqual(this._edgeStyle, mergedStyle)) {\n this._edgeStyle = mergedStyle;\n this.markDirty();\n }\n\n if (this._label) {\n this._label.applyStyleManager(styleManager);\n }\n }\n\n /**\n * Edge label\n */\n get label(): TextLabel | undefined {\n return this._label;\n }\n\n set label(value: TextLabel | string | undefined) {\n if (value === undefined) {\n this._label = undefined;\n } else if (typeof value === 'string') {\n this._label = new TextLabel({ text: value, onChange: (): void => this.markDirty() });\n } else {\n this._label = value;\n this._label.setOnChange((): void => this.markDirty());\n }\n this.markDirty();\n }\n\n /**\n * Current path points\n */\n get path(): readonly Point[] {\n return this._path;\n }\n\n /**\n * Auto-update endpoints from connected nodes\n */\n get autoUpdateEndpoints(): boolean {\n return this._autoUpdateEndpoints;\n }\n\n set autoUpdateEndpoints(value: boolean) {\n this._autoUpdateEndpoints = value;\n }\n\n /**\n * Whether to lock edge endpoints to anchor points\n */\n get lockAnchors(): boolean {\n return this._lockAnchors;\n }\n\n set lockAnchors(value: boolean) {\n this._lockAnchors = value;\n }\n\n /**\n * Get start point position (for handle rendering)\n */\n get startPoint(): Point {\n return this._fromPoint;\n }\n\n /**\n * Get end point position (for handle rendering)\n */\n get endPoint(): Point {\n return this._toPoint;\n }\n\n /**\n * Check if a point hits the start handle\n */\n hitTestStartHandle(point: Point, handleRadius = 8): boolean {\n const dx = point.x - this._fromPoint.x;\n const dy = point.y - this._fromPoint.y;\n return dx * dx + dy * dy <= handleRadius * handleRadius;\n }\n\n /**\n * Check if a point hits the end handle\n */\n hitTestEndHandle(point: Point, handleRadius = 8): boolean {\n const dx = point.x - this._toPoint.x;\n const dy = point.y - this._toPoint.y;\n return dx * dx + dy * dy <= handleRadius * handleRadius;\n }\n\n /**\n * Update edge endpoints from node positions\n * Called by DiagramRenderer when nodes move\n * @param fromPoint Start point\n * @param toPoint End point\n * @param fromDir Direction at start point (top, right, bottom, left)\n * @param toDir Direction at end point (top, right, bottom, left)\n */\n updateEndpoints(\n fromPoint: Point,\n toPoint: Point,\n fromDir?: string,\n toDir?: string,\n options?: PathStrategyOptions\n ): void {\n this._fromPoint = fromPoint;\n this._toPoint = toPoint;\n this._fromDir = fromDir;\n this._toDir = toDir;\n this._pathOptions = options;\n this.recalculatePath();\n }\n\n /**\n * Recalculate the path between endpoints\n */\n recalculatePath(): void {\n this._path = this._pathStrategy.calculatePath(\n this._fromPoint,\n this._toPoint,\n this._fromDir,\n this._toDir,\n {\n ...this._pathOptions,\n controlPoints: this._controlPoints,\n editablePolyline: this.isEditablePolyline(),\n selfLoop: this._from.nodeId === this._to.nodeId,\n }\n );\n this.updateBounds();\n this.markDirty();\n }\n\n private updateBounds(): void {\n if (this._path.length === 0) {\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const point of this._path) {\n minX = Math.min(minX, point.x);\n minY = Math.min(minY, point.y);\n maxX = Math.max(maxX, point.x);\n maxY = Math.max(maxY, point.y);\n }\n\n this._x = minX;\n this._y = minY;\n this._width = maxX - minX;\n this._height = maxY - minY;\n }\n\n hitTest(point: Point): boolean {\n const tolerance = Math.max((this._edgeStyle.strokeWidth ?? 2) * 2, 8);\n return this._pathStrategy.hitTest(point, this._path, tolerance);\n }\n\n /**\n * Hit test with explicit tolerance (world units)\n */\n hitTestWithTolerance(point: Point, tolerance: number): boolean {\n return this._pathStrategy.hitTest(point, this._path, tolerance);\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n if (this._path.length < 2) {\n return;\n }\n\n if (this._state === 'selected' || this._state === 'hover') {\n this.renderHighlight(ctx);\n }\n\n this.applyStyle(ctx);\n this.renderPath(ctx);\n this.renderArrows(ctx);\n this.renderLabel(ctx);\n // Note: handles are rendered separately via renderHandles() to appear on top of nodes\n }\n\n /**\n * Render drag handles when selected\n * Called separately after nodes to ensure handles appear on top\n */\n renderHandles(ctx: CanvasRenderingContext2D): void {\n if (this._state !== 'selected') {\n return;\n }\n\n this.renderHandle(ctx, this._fromPoint);\n this.renderHandle(ctx, this._toPoint);\n }\n\n private renderHandle(ctx: CanvasRenderingContext2D, point: Point): void {\n ctx.beginPath();\n ctx.arc(point.x, point.y, EDGE_HANDLE_RADIUS, 0, Math.PI * 2);\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n\n private applyStyle(ctx: CanvasRenderingContext2D): void {\n const style = this._edgeStyle;\n\n ctx.strokeStyle = style.strokeColor ?? '#666666';\n ctx.lineWidth = style.strokeWidth ?? 2;\n const baseOpacity = style.opacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n\n this.applyLineDash(ctx, style);\n\n if (style.lineCap !== undefined) {\n ctx.lineCap = style.lineCap;\n }\n\n if (style.lineJoin !== undefined) {\n ctx.lineJoin = style.lineJoin;\n }\n }\n\n private renderHighlight(ctx: CanvasRenderingContext2D): void {\n const style = this._edgeStyle;\n ctx.save();\n ctx.strokeStyle = this._state === 'selected' ? DEFAULT_SELECTION_COLOR : DEFAULT_HOVER_COLOR;\n ctx.lineWidth = (style.strokeWidth ?? 2) + (this._state === 'selected' ? 1 : 0);\n ctx.globalAlpha = 1;\n\n this.applyLineDash(ctx, style);\n\n if (style.lineCap !== undefined) {\n ctx.lineCap = style.lineCap;\n }\n\n if (style.lineJoin !== undefined) {\n ctx.lineJoin = style.lineJoin;\n }\n\n this.renderPath(ctx);\n ctx.restore();\n }\n\n private renderPath(ctx: CanvasRenderingContext2D): void {\n const path = this._path;\n if (path.length < 2) return;\n\n // Calculate how much to shorten the line at each end for markers\n const startOffset =\n this._startMarker && this._startMarker.type !== 'none'\n ? this.getMarkerLength(this._startMarker)\n : 0;\n const endOffset =\n this._endMarker && this._endMarker.type !== 'none'\n ? this.getMarkerLength(this._endMarker)\n : 0;\n\n // Get shortened start point\n const start = path[0]!;\n const startNext = path[1]!;\n const startAngle = Math.atan2(startNext.y - start.y, startNext.x - start.x);\n const shortenedStart = {\n x: start.x + startOffset * Math.cos(startAngle),\n y: start.y + startOffset * Math.sin(startAngle),\n };\n\n // Get shortened end point\n const end = path[path.length - 1]!;\n const endPrev = path[path.length - 2]!;\n const endAngle = Math.atan2(end.y - endPrev.y, end.x - endPrev.x);\n const shortenedEnd = {\n x: end.x - endOffset * Math.cos(endAngle),\n y: end.y - endOffset * Math.sin(endAngle),\n };\n\n ctx.beginPath();\n ctx.moveTo(shortenedStart.x, shortenedStart.y);\n\n if (this._type === 'bezier' && path.length >= 4) {\n for (let i = 1; i + 2 < path.length; i += 3) {\n const cp1 = path[i]!;\n const cp2 = path[i + 1]!;\n const end = i + 2 === path.length - 1 ? shortenedEnd : path[i + 2]!;\n ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);\n }\n } else {\n for (let i = 1; i < path.length - 1; i++) {\n ctx.lineTo(path[i]!.x, path[i]!.y);\n }\n ctx.lineTo(shortenedEnd.x, shortenedEnd.y);\n }\n\n ctx.stroke();\n }\n\n private renderArrows(ctx: CanvasRenderingContext2D): void {\n const path = this._path;\n if (path.length < 2) {\n return;\n }\n\n // Use new marker system if configured, otherwise fall back to legacy arrowType\n const hasNewMarkers = this._startMarker !== undefined || this._endMarker !== undefined;\n\n if (hasNewMarkers) {\n // End marker\n if (this._endMarker && this._endMarker.type !== 'none') {\n const points = this.getMarkerPoints('end');\n if (points) {\n this.drawMarker(ctx, points.from, points.to, this._endMarker);\n }\n }\n\n // Start marker\n if (this._startMarker && this._startMarker.type !== 'none') {\n const points = this.getMarkerPoints('start');\n if (points) {\n this.drawMarker(ctx, points.from, points.to, this._startMarker);\n }\n }\n } else {\n // Legacy arrow type support\n if (this._arrowType === 'none') {\n return;\n }\n\n // Target arrow\n const endPoints = this.getMarkerPoints('end');\n if (endPoints) {\n this.drawArrowHead(ctx, endPoints.from, endPoints.to);\n }\n\n // Source arrow (for double)\n if (this._arrowType === 'double') {\n const startPoints = this.getMarkerPoints('start');\n if (startPoints) {\n this.drawArrowHead(ctx, startPoints.from, startPoints.to);\n }\n }\n }\n }\n\n private getMarkerPoints(position: 'start' | 'end'): { from: Point; to: Point } | null {\n const path = this._path;\n if (path.length < 2) {\n return null;\n }\n\n if (this._type === 'bezier' && path.length >= 4) {\n const start = path[0]!;\n const cp1 = path[1]!;\n const cp2 = path[2]!;\n const end = path[3]!;\n const epsilon = 0.001;\n\n const isSame = (a: Point, b: Point): boolean =>\n Math.abs(a.x - b.x) < epsilon && Math.abs(a.y - b.y) < epsilon;\n\n if (position === 'end') {\n const endIndex = path.length - 1;\n const endPoint = path[endIndex]!;\n let from = path[endIndex - 1] ?? cp2;\n if (isSame(from, endPoint)) {\n from = path[endIndex - 2] ?? cp1;\n if (isSame(from, endPoint)) {\n from = start;\n }\n }\n return { from, to: endPoint };\n }\n\n let next = cp1;\n if (isSame(next, start)) {\n next = cp2;\n if (isSame(next, start)) {\n next = end;\n }\n }\n return { from: next, to: start };\n }\n\n if (position === 'end') {\n return { from: path[path.length - 2]!, to: path[path.length - 1]! };\n }\n\n return { from: path[1]!, to: path[0]! };\n }\n\n /**\n * Get the length of a marker (how much to shorten the line)\n */\n private getMarkerLength(config: ArrowMarkerConfig): number {\n const size = config.size ?? MARKER_SIZES[config.type] ?? ARROW_SIZE;\n switch (config.type) {\n case 'arrow':\n // Arrow length is size * cos(ARROW_ANGLE) for the back of the triangle\n return size * Math.cos(ARROW_ANGLE);\n case 'open':\n // Do not shorten line for open arrow\n return 0;\n case 'diamond':\n return size; // Diamond length is full size\n case 'circle':\n return size * 2; // Circle diameter\n default:\n return 0;\n }\n }\n\n private drawMarker(\n ctx: CanvasRenderingContext2D,\n from: Point,\n to: Point,\n config: ArrowMarkerConfig\n ): void {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const size = config.size ?? MARKER_SIZES[config.type] ?? ARROW_SIZE;\n const strokeColor = config.strokeColor ?? (ctx.strokeStyle as string);\n const fillColor = config.fillColor ?? strokeColor;\n const fillOpacity = config.fillOpacity ?? 1;\n\n ctx.save();\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n ctx.strokeStyle = strokeColor;\n\n switch (config.type) {\n case 'arrow':\n this.drawArrowMarker(ctx, to, angle, size, fillColor, fillOpacity);\n break;\n case 'open':\n this.drawOpenArrowMarker(ctx, to, angle, size);\n break;\n case 'diamond':\n this.drawDiamondMarker(ctx, to, angle, size, fillColor, fillOpacity);\n break;\n case 'circle':\n this.drawCircleMarker(ctx, to, angle, size, fillColor, fillOpacity);\n break;\n }\n\n ctx.restore();\n }\n\n private drawArrowMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number,\n fillColor: string,\n fillOpacity: number\n ): void {\n const x1 = to.x - size * Math.cos(angle - ARROW_ANGLE);\n const y1 = to.y - size * Math.sin(angle - ARROW_ANGLE);\n const x2 = to.x - size * Math.cos(angle + ARROW_ANGLE);\n const y2 = to.y - size * Math.sin(angle + ARROW_ANGLE);\n\n ctx.beginPath();\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.closePath();\n ctx.globalAlpha = fillOpacity;\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.globalAlpha = 1;\n ctx.stroke();\n }\n\n private drawOpenArrowMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number\n ): void {\n const x1 = to.x - size * Math.cos(angle - ARROW_ANGLE);\n const y1 = to.y - size * Math.sin(angle - ARROW_ANGLE);\n const x2 = to.x - size * Math.cos(angle + ARROW_ANGLE);\n const y2 = to.y - size * Math.sin(angle + ARROW_ANGLE);\n\n ctx.beginPath();\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(x1, y1);\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n\n private drawDiamondMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number,\n fillColor: string,\n fillOpacity: number\n ): void {\n const halfLength = size / 2;\n const halfWidth = size * 0.3;\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n // Diamond points relative to the tip\n const points = [\n { x: to.x, y: to.y }, // tip\n {\n x: to.x - halfLength * cos + halfWidth * sin,\n y: to.y - halfLength * sin - halfWidth * cos,\n },\n { x: to.x - size * cos, y: to.y - size * sin }, // back\n {\n x: to.x - halfLength * cos - halfWidth * sin,\n y: to.y - halfLength * sin + halfWidth * cos,\n },\n ];\n\n ctx.beginPath();\n ctx.moveTo(points[0]!.x, points[0]!.y);\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i]!.x, points[i]!.y);\n }\n ctx.closePath();\n\n ctx.globalAlpha = fillOpacity;\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.globalAlpha = 1;\n ctx.stroke();\n }\n\n private drawCircleMarker(\n ctx: CanvasRenderingContext2D,\n to: Point,\n angle: number,\n size: number,\n fillColor: string,\n fillOpacity: number\n ): void {\n // Offset circle center back along the path so it doesn't overlap node\n const cx = to.x - size * Math.cos(angle);\n const cy = to.y - size * Math.sin(angle);\n\n ctx.beginPath();\n ctx.arc(cx, cy, size, 0, Math.PI * 2);\n\n ctx.globalAlpha = fillOpacity;\n ctx.fillStyle = fillColor;\n ctx.fill();\n ctx.globalAlpha = 1;\n ctx.stroke();\n }\n\n private drawArrowHead(ctx: CanvasRenderingContext2D, from: Point, to: Point): void {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n\n ctx.save();\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n ctx.beginPath();\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(\n to.x - ARROW_SIZE * Math.cos(angle - ARROW_ANGLE),\n to.y - ARROW_SIZE * Math.sin(angle - ARROW_ANGLE)\n );\n ctx.moveTo(to.x, to.y);\n ctx.lineTo(\n to.x - ARROW_SIZE * Math.cos(angle + ARROW_ANGLE),\n to.y - ARROW_SIZE * Math.sin(angle + ARROW_ANGLE)\n );\n ctx.stroke();\n ctx.restore();\n }\n\n private renderLabel(ctx: CanvasRenderingContext2D): void {\n if (this._label === undefined || this._path.length < 2) {\n return;\n }\n\n // Calculate midpoint of path with offset\n const midpoint = this.getPathMidpoint();\n const labelPosition = {\n x: midpoint.x,\n y: midpoint.y + this._labelOffset,\n };\n\n const labelOpacity = this._label.style.opacity ?? 1;\n\n // Draw background for label\n this._label.measure(ctx);\n const labelWidth = this._label.measuredWidth;\n const labelHeight = this._label.measuredHeight;\n\n const bgPadding = this._labelBackground?.padding ?? EDGE_LABEL_BACKGROUND_PADDING;\n const bgColor = this._labelBackground?.color ?? '#ffffff';\n const bgOpacity = this._labelBackground?.opacity ?? 1;\n const bgRadius = this._labelBackground?.borderRadius ?? EDGE_LABEL_BACKGROUND_RADIUS;\n\n const bgX = labelPosition.x - labelWidth / 2 - bgPadding;\n const bgY = labelPosition.y - labelHeight / 2 - bgPadding;\n const bgWidth = labelWidth + bgPadding * 2;\n const bgHeight = labelHeight + bgPadding * 2;\n\n ctx.fillStyle = bgColor;\n ctx.globalAlpha = bgOpacity;\n\n if (bgRadius > 0) {\n this.drawRoundedRect(ctx, bgX, bgY, bgWidth, bgHeight, bgRadius);\n ctx.fill();\n } else {\n ctx.fillRect(bgX, bgY, bgWidth, bgHeight);\n }\n\n ctx.globalAlpha = labelOpacity;\n this._label.renderAt(ctx, labelPosition);\n ctx.globalAlpha = 1;\n }\n\n private drawRoundedRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number\n ): void {\n drawRoundedRectPath(ctx, x, y, width, height, radius);\n }\n\n private getPathMidpoint(): Point {\n const path = this._path;\n\n if (this._type === 'bezier' && path.length >= 4) {\n const samples: Point[] = [];\n const steps = 20;\n for (let i = 1; i + 2 < path.length; i += 3) {\n const p0 = path[i - 1]!;\n const p1 = path[i]!;\n const p2 = path[i + 1]!;\n const p3 = path[i + 2]!;\n for (let s = 0; s <= steps; s++) {\n const t = s / steps;\n if (samples.length > 0 && t === 0) {\n continue;\n }\n samples.push(bezierPoint(p0, p1, p2, p3, t));\n }\n }\n\n return this.getPolylineMidpoint(samples);\n }\n\n // For straight/polyline, find midpoint of total length\n return this.getPolylineMidpoint(path);\n }\n\n /**\n * Get world position of label center along path.\n */\n getLabelPosition(): Point | null {\n if (this._path.length < 2) {\n return null;\n }\n\n const midpoint = this.getPathMidpoint();\n return {\n x: midpoint.x,\n y: midpoint.y + this._labelOffset,\n };\n }\n\n private getPolylineMidpoint(path: Point[]): Point {\n if (path.length === 0) {\n return { x: 0, y: 0 };\n }\n if (path.length === 1) {\n return path[0]!;\n }\n\n let totalLength = 0;\n const segments: { start: Point; end: Point; length: number }[] = [];\n\n for (let i = 1; i < path.length; i++) {\n const start = path[i - 1]!;\n const end = path[i]!;\n const length = Math.sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2);\n segments.push({ start, end, length });\n totalLength += length;\n }\n\n const halfLength = totalLength / 2;\n let accumulated = 0;\n\n for (const seg of segments) {\n if (accumulated + seg.length >= halfLength) {\n const t = (halfLength - accumulated) / seg.length;\n return {\n x: seg.start.x + t * (seg.end.x - seg.start.x),\n y: seg.start.y + t * (seg.end.y - seg.start.y),\n };\n }\n accumulated += seg.length;\n }\n\n return path[0]!;\n }\n\n private getPathStrategy(type: EdgePathType): PathStrategy {\n switch (type) {\n case 'straight':\n return new StraightPathStrategy();\n case 'polyline':\n return new PolylinePathStrategy();\n case 'editable-polyline':\n return new PolylinePathStrategy();\n case 'bezier':\n return new BezierPathStrategy();\n default:\n return new StraightPathStrategy();\n }\n }\n\n private applyLineDash(ctx: CanvasRenderingContext2D, style: EdgeStyle): void {\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n } else {\n ctx.lineDashOffset = 0;\n }\n }\n}\n","import type { Point } from '@/types';\n\nexport interface LabelEditorState {\n kind: 'node' | 'edge';\n id: string;\n textarea: HTMLTextAreaElement;\n cleanup: () => void;\n}\n\nexport type LabelCommitCallback = (kind: 'node' | 'edge', id: string, value: string) => void;\n\n/**\n * Manages inline label editing for nodes and edges\n */\nexport class LabelEditor {\n private state: LabelEditorState | null = null;\n\n /**\n * Check if editor is currently active\n */\n get isActive(): boolean {\n return this.state !== null;\n }\n\n /**\n * Get current editor state\n */\n get currentState(): Readonly<LabelEditorState> | null {\n return this.state;\n }\n\n /**\n * Start editing a label\n */\n start(\n kind: 'node' | 'edge',\n id: string,\n text: string,\n worldPosition: Point,\n worldToScreen: (x: number, y: number) => Point,\n onCommit: LabelCommitCallback\n ): void {\n this.finish(true);\n\n const screenPoint = worldToScreen(worldPosition.x, worldPosition.y);\n const textarea = this.createTextarea(text, screenPoint);\n const { cleanup } = this.setupEventHandlers(textarea, onCommit);\n\n document.body.appendChild(textarea);\n textarea.focus();\n textarea.select();\n\n this.state = { kind, id, textarea, cleanup };\n }\n\n /**\n * Finish editing\n * @param commit - Whether to commit the changes\n * @param onCommit - Callback to invoke if committing\n */\n finish(commit: boolean, onCommit?: LabelCommitCallback): void {\n if (!this.state) {\n return;\n }\n\n const { kind, id, textarea, cleanup } = this.state;\n this.state = null;\n const value = textarea.value;\n cleanup();\n\n if (commit && onCommit) {\n onCommit(kind, id, value);\n }\n }\n\n private createTextarea(text: string, screenPoint: Point): HTMLTextAreaElement {\n const textarea = document.createElement('textarea');\n textarea.value = text;\n textarea.rows = 1;\n textarea.spellcheck = false;\n textarea.setAttribute('aria-label', 'Edit label');\n\n // Position and styling\n textarea.style.cssText = `\n position: fixed;\n left: ${screenPoint.x}px;\n top: ${screenPoint.y}px;\n transform: translate(-50%, -50%);\n z-index: 10001;\n min-width: 120px;\n max-width: 420px;\n min-height: 30px;\n padding: 6px 8px;\n border: 1px solid #6366f1;\n border-radius: 6px;\n box-shadow: 0 8px 18px rgba(15, 23, 42, 0.15);\n background: #ffffff;\n color: #0f172a;\n font: 14px sans-serif;\n line-height: 1.4;\n resize: none;\n overflow: hidden;\n `;\n\n this.resizeTextarea(textarea);\n\n return textarea;\n }\n\n private resizeTextarea(textarea: HTMLTextAreaElement): void {\n textarea.style.height = 'auto';\n textarea.style.height = `${Math.max(30, textarea.scrollHeight)}px`;\n }\n\n private setupEventHandlers(\n textarea: HTMLTextAreaElement,\n onCommit: LabelCommitCallback\n ): { cleanup: () => void; commit: () => void } {\n const commit = (): void => this.finish(true, onCommit);\n const cancel = (): void => this.finish(false);\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n e.preventDefault();\n cancel();\n return;\n }\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n commit();\n }\n };\n\n const handleBlur = (): void => commit();\n const handleInput = (): void => this.resizeTextarea(textarea);\n\n textarea.addEventListener('keydown', handleKeyDown);\n textarea.addEventListener('blur', handleBlur);\n textarea.addEventListener('input', handleInput);\n\n const cleanup = (): void => {\n textarea.removeEventListener('keydown', handleKeyDown);\n textarea.removeEventListener('blur', handleBlur);\n textarea.removeEventListener('input', handleInput);\n textarea.remove();\n };\n\n return { cleanup, commit };\n }\n}\n","import { InputHandler } from '@/events/InputHandler';\nimport type {\n InputEvent,\n WheelInputEvent,\n PanInputEvent,\n PinchInputEvent,\n} from '@/events/InputHandler';\nimport type { DiagramRenderer, OverlayDragSession } from './DiagramRenderer';\nimport { SelectionManager } from './SelectionManager';\nimport { DragManager } from './DragManager';\nimport { ResizeManager } from './ResizeManager';\nimport { NavigationManager } from './NavigationManager';\nimport { ConnectionManager } from './ConnectionManager';\nimport {\n ChangeEdgePropertiesCommand,\n ChangeGroupPropertiesCommand,\n ChangeNodePropertiesCommand,\n HistoryManager,\n MoveNodesCommand,\n RemoveNodeFromGroupsCommand,\n createEdgeSnapshot,\n createGroupSnapshot,\n createNodeSnapshot,\n} from './HistoryManager';\nimport type { Bounds, EdgeEndpoint, Point, SerializedEdge, SerializedNode } from '@/types';\nimport { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { Node } from '@/elements/Node';\nimport { CompositeCommand } from './history/commands';\nimport { LabelEditor } from './LabelEditor';\nimport { shallowEqual } from '@/utils/style';\nimport { mergeBounds } from '@/utils/geometry';\n\nexport interface InteractionKeymap {\n deleteKeys: string[];\n copyKey: string;\n pasteKey: string;\n undoKey: string;\n redoKey: string;\n}\n\nexport interface InteractionManagerOptions {\n renderer: DiagramRenderer;\n createEdge?: (from: EdgeEndpoint, to: EdgeEndpoint) => Edge;\n nodeFactory?: (data: SerializedNode) => Node;\n edgeFactory?: (data: SerializedEdge) => Edge;\n snapToGrid?: boolean;\n gridSize?: number;\n alignToNodes?: boolean;\n /** When true, edges can be attached anywhere on the shape outline (not just ports) */\n attachToOutline?: boolean;\n keymap?: Partial<InteractionKeymap>;\n}\n\nconst DEFAULT_KEYMAP: InteractionKeymap = {\n deleteKeys: ['Delete', 'Backspace'],\n copyKey: 'c',\n pasteKey: 'v',\n undoKey: 'z',\n redoKey: 'y',\n};\n\nexport class InteractionManager {\n private readonly renderer: DiagramRenderer;\n private inputHandler: InputHandler;\n private readonly selectionManager: SelectionManager;\n private readonly dragManager: DragManager;\n private readonly resizeManager: ResizeManager;\n private readonly navigationManager: NavigationManager;\n private readonly connectionManager: ConnectionManager;\n private readonly historyManager: HistoryManager;\n private keymap: InteractionKeymap;\n private overlayCleanup: (() => void) | null = null;\n\n private dragStartPositions = new Map<string, { x: number; y: number }>();\n private reconnectOrigins = new Map<\n string,\n { endpoint: 'start' | 'end'; original: EdgeEndpoint }\n >();\n\n private clipboard: {\n nodes: SerializedNode[];\n edges: SerializedEdge[];\n } | null = null;\n\n private pendingPropertyChanges = new Map<\n string,\n {\n kind: 'node' | 'edge' | 'group';\n id: string;\n before:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>;\n after:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>;\n timerId: number;\n }\n >();\n private propertyChangeDebounceMs = 350;\n private labelEditor = new LabelEditor();\n private scrollbarDragState: { axis: 'horizontal' | 'vertical'; pointerOffset: number } | null =\n null;\n private handledScrollbarMouseDown = false;\n private overlayDragSession: OverlayDragSession | null = null;\n private handledOverlayMouseDown = false;\n\n constructor(options: InteractionManagerOptions) {\n this.renderer = options.renderer;\n this.inputHandler = new InputHandler({\n canvas: this.renderer.getCanvas(),\n screenToWorld: (x, y): { x: number; y: number } => this.renderer.screenToWorld(x, y),\n });\n\n this.selectionManager = new SelectionManager(this.renderer);\n this.dragManager = new DragManager({\n renderer: this.renderer,\n selectionManager: this.selectionManager,\n snapToGrid: options.snapToGrid ?? this.renderer.snapToGrid,\n gridSize: options.gridSize ?? 20,\n alignToNodes: options.alignToNodes ?? true,\n });\n this.resizeManager = new ResizeManager({\n renderer: this.renderer,\n selectionManager: this.selectionManager,\n snapToGrid: options.snapToGrid ?? this.renderer.snapToGrid,\n gridSize: options.gridSize ?? 20,\n });\n this.navigationManager = new NavigationManager({ renderer: this.renderer });\n this.historyManager = new HistoryManager();\n\n this.keymap = { ...DEFAULT_KEYMAP, ...options.keymap };\n\n const attachToOutline = options.attachToOutline ?? false;\n this.renderer.attachToOutline = attachToOutline;\n this.connectionManager = new ConnectionManager({\n renderer: this.renderer,\n createEdge:\n options.createEdge ??\n ((from, to): Edge => new Edge({ from, to, type: 'bezier', arrowType: 'single' })),\n snapToGrid: options.snapToGrid ?? this.renderer.snapToGrid,\n gridSize: options.gridSize ?? 20,\n attachToOutline,\n addEdge: (edge): void => {\n this.historyManager.execute({\n execute: (): void => this.renderer.addEdge(edge),\n undo: (): void => {\n this.renderer.removeEdge(edge.id);\n },\n });\n },\n });\n\n this.setupEvents(options);\n }\n\n get selection(): SelectionManager {\n return this.selectionManager;\n }\n\n get drag(): DragManager {\n return this.dragManager;\n }\n\n get resize(): ResizeManager {\n return this.resizeManager;\n }\n\n get navigation(): NavigationManager {\n return this.navigationManager;\n }\n\n get connection(): ConnectionManager {\n return this.connectionManager;\n }\n\n get history(): HistoryManager {\n return this.historyManager;\n }\n\n changeNodeProperties(nodeId: string, apply: (node: Node) => void): void {\n const node = this.renderer.getNode(nodeId);\n if (!node) {\n return;\n }\n const before = createNodeSnapshot(node);\n apply(node);\n const after = createNodeSnapshot(node);\n if (shallowEqual(before, after)) {\n return;\n }\n this.queuePropertyChange('node', nodeId, before, after);\n }\n\n changeEdgeProperties(edgeId: string, apply: (edge: Edge) => void): void {\n const edge = this.renderer.getEdge(edgeId);\n if (!edge) {\n return;\n }\n const before = createEdgeSnapshot(edge);\n apply(edge);\n const after = createEdgeSnapshot(edge);\n if (shallowEqual(before, after)) {\n return;\n }\n this.queuePropertyChange('edge', edgeId, before, after);\n }\n\n changeGroupProperties(groupId: string, apply: (group: Group) => void): void {\n const group = this.renderer.getGroup(groupId);\n if (!group) {\n return;\n }\n const before = createGroupSnapshot(group);\n apply(group);\n const after = createGroupSnapshot(group);\n if (shallowEqual(before, after)) {\n return;\n }\n this.queuePropertyChange('group', groupId, before, after);\n }\n\n removeNodeFromGroups(nodeId: string, groupIds?: string[]): void {\n const node = this.renderer.getNode(nodeId);\n if (!node) {\n return;\n }\n const groups =\n groupIds ??\n Array.from(this.renderer.groups.values())\n .filter((group) => group.hasChild(nodeId))\n .map((group) => group.id);\n if (groups.length === 0) {\n return;\n }\n this.historyManager.execute(\n new RemoveNodeFromGroupsCommand(\n (id) => this.renderer.getGroup(id),\n (id) => this.renderer.getNode(id),\n nodeId,\n groups\n )\n );\n }\n\n deleteByIds(ids: string[]): void {\n if (ids.length === 0) {\n return;\n }\n\n const command = this.buildDeleteCommand(ids);\n this.historyManager.execute(command);\n this.selectionManager.clearSelection();\n this.renderer.markDirty();\n }\n\n zoomToSelection(padding = 50): void {\n const bounds = this.getSelectionBounds();\n if (bounds) {\n this.navigationManager.zoomToSelection(bounds, padding);\n }\n }\n\n destroy(): void {\n this.labelEditor.finish(false);\n if (this.overlayDragSession) {\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n }\n if (this.scrollbarDragState) {\n this.renderer.setScrollbarActiveAxis(null);\n this.scrollbarDragState = null;\n }\n this.renderer.clearScrollbarHover();\n this.inputHandler.destroy();\n this.overlayCleanup?.();\n this.overlayCleanup = null;\n }\n\n private setupEvents(options: InteractionManagerOptions): void {\n this.overlayCleanup = this.renderer.addOverlayRenderer((ctx) => {\n this.selectionManager.renderSelectionRect(ctx);\n this.dragManager.renderAlignmentGuides(ctx);\n this.connectionManager.renderPreview(ctx);\n this.connectionManager.renderHoverAnchors(ctx);\n for (const id of this.selectionManager.selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n node.renderResizeHandles(ctx);\n }\n }\n });\n\n this.inputHandler.on('mousedown', (event) => this.handleMouseDown(event));\n this.inputHandler.on('mousemove', (event) => this.handleMouseMove(event));\n this.inputHandler.on('mouseup', (event) => this.handleMouseUp(event));\n this.inputHandler.on('click', (event) => this.handleClick(event));\n this.inputHandler.on('dblclick', (event) => this.handleDoubleClick(event));\n this.inputHandler.on('wheel', (event) => this.handleWheel(event));\n this.inputHandler.on('pan', (event) => this.handlePan(event));\n this.inputHandler.on('pinch', (event) => this.handlePinch(event));\n this.inputHandler.on('keydown', (event) => this.handleKeyDown(event, options));\n this.inputHandler.on('keyup', (event) => this.handleKeyUp(event));\n\n this.dragManager.on('dragstart', (nodeIds) => {\n this.connectionManager.disableHover();\n this.dragStartPositions.clear();\n for (const id of nodeIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n this.dragStartPositions.set(id, { x: node.x, y: node.y });\n }\n }\n });\n\n this.dragManager.on('dragend', (nodeIds) => {\n this.connectionManager.enableHover();\n\n const nodePositions = new Map<\n string,\n { before: { x: number; y: number }; after: { x: number; y: number } }\n >();\n for (const id of nodeIds) {\n const node = this.renderer.getNode(id);\n const before = this.dragStartPositions.get(id);\n if (!node || !before) continue;\n const after = { x: node.x, y: node.y };\n if (before.x !== after.x || before.y !== after.y) {\n nodePositions.set(id, { before, after });\n }\n }\n\n if (nodePositions.size > 0) {\n this.historyManager.execute(\n new MoveNodesCommand((id) => this.renderer.getNode(id), nodePositions)\n );\n }\n });\n\n this.connectionManager.on('edgeReconnectStart', (edge, endpoint, original) => {\n this.reconnectOrigins.set(edge.id, { endpoint, original: { ...original } });\n });\n\n this.connectionManager.on('edgeReconnect', (edge, endpoint) => {\n const origin = this.reconnectOrigins.get(edge.id);\n if (!origin || origin.endpoint !== endpoint) {\n return;\n }\n\n const before = origin.original;\n const after = endpoint === 'start' ? edge.from : edge.to;\n if (this.endpointsEqual(before, after)) {\n this.reconnectOrigins.delete(edge.id);\n return;\n }\n\n this.historyManager.execute({\n execute: () => {\n if (endpoint === 'start') {\n edge.from = { ...after };\n } else {\n edge.to = { ...after };\n }\n this.renderer.markDirty();\n },\n undo: () => {\n if (endpoint === 'start') {\n edge.from = { ...before };\n } else {\n edge.to = { ...before };\n }\n this.renderer.markDirty();\n },\n });\n this.reconnectOrigins.delete(edge.id);\n });\n\n this.historyManager.on('change', () => {\n this.renderer.markDirty();\n });\n }\n\n private handleMouseDown(event: InputEvent): void {\n this.handledScrollbarMouseDown = false;\n this.handledOverlayMouseDown = false;\n\n if (this.resizeManager.handleMouseDown(event)) {\n return;\n }\n if (this.connectionManager.tryStartReconnection(event)) {\n return;\n }\n if (this.connectionManager.tryStartConnectionAtPoint(event)) {\n return;\n }\n\n const overlayDrag = this.renderer.beginOverlayDrag(event.screenX, event.screenY);\n if (overlayDrag) {\n this.overlayDragSession = overlayDrag;\n this.handledOverlayMouseDown = true;\n return;\n }\n\n const scrollbarHit = this.renderer.hitTestScrollbarThumb(event.screenX, event.screenY);\n if (scrollbarHit) {\n this.scrollbarDragState = scrollbarHit;\n this.handledScrollbarMouseDown = true;\n this.renderer.setScrollbarActiveAxis(scrollbarHit.axis);\n this.renderer.notifyScrollbarInteraction();\n return;\n }\n\n if (this.renderer.clickScrollbarTrack(event.screenX, event.screenY)) {\n this.handledScrollbarMouseDown = true;\n return;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const hitElement = this.renderer.getElementAtPoint(point);\n\n if (hitElement === undefined && event.button === 0) {\n if (event.ctrlKey || event.metaKey) {\n this.selectionManager.startSelectionRect(point);\n return;\n }\n this.selectionManager.clearSelection();\n this.navigationManager.startPan(event);\n return;\n }\n\n if (this.navigationManager.handleMouseDown(event)) {\n return;\n }\n\n // Connection creation now starts from anchor points without modifiers\n\n if (this.dragManager.handleMouseDown(event)) {\n return;\n }\n }\n\n private handleMouseMove(event: InputEvent): void {\n if (event.originalEvent instanceof MouseEvent && event.originalEvent.buttons === 0) {\n if (this.overlayDragSession) {\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n }\n if (this.scrollbarDragState) {\n this.renderer.setScrollbarActiveAxis(null);\n this.scrollbarDragState = null;\n }\n if (this.navigationManager.panning) {\n this.navigationManager.handleMouseUp(event);\n }\n }\n\n const overScrollbar = this.renderer.updateScrollbarHover(event.screenX, event.screenY);\n\n if (this.overlayDragSession) {\n const moved = this.renderer.updateOverlayDrag(\n this.overlayDragSession,\n event.screenX,\n event.screenY\n );\n if (moved) {\n return;\n }\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n }\n\n if (this.scrollbarDragState) {\n const moved = this.renderer.dragScrollbarThumb(\n this.scrollbarDragState.axis,\n event.screenX,\n event.screenY,\n this.scrollbarDragState.pointerOffset\n );\n if (moved) {\n return;\n }\n this.renderer.setScrollbarActiveAxis(null);\n this.scrollbarDragState = null;\n }\n\n if (overScrollbar) {\n return;\n }\n\n if (this.resizeManager.handleMouseMove(event)) {\n return;\n }\n\n if (this.connectionManager.handleMouseMove(event)) {\n return;\n }\n\n if (this.dragManager.handleMouseMove(event)) {\n return;\n }\n\n if (this.selectionManager.selectionRectangle !== null) {\n this.selectionManager.updateSelectionRect({ x: event.worldX, y: event.worldY });\n return;\n }\n\n this.navigationManager.handleMouseMove(event);\n }\n\n private handleMouseUp(event: InputEvent): void {\n if (this.overlayDragSession) {\n this.renderer.endOverlayDrag(this.overlayDragSession);\n this.overlayDragSession = null;\n return;\n }\n\n if (this.scrollbarDragState) {\n this.scrollbarDragState = null;\n this.renderer.setScrollbarActiveAxis(null);\n return;\n }\n\n if (this.resizeManager.handleMouseUp()) {\n return;\n }\n\n if (this.connectionManager.handleMouseUp(event)) {\n return;\n }\n\n if (this.dragManager.handleMouseUp(event)) {\n return;\n }\n\n if (this.selectionManager.selectionRectangle !== null) {\n this.selectionManager.endSelectionRect();\n return;\n }\n\n this.navigationManager.handleMouseUp(event);\n }\n\n private handleClick(event: InputEvent): void {\n if (this.handledOverlayMouseDown) {\n this.handledOverlayMouseDown = false;\n return;\n }\n\n if (this.handledScrollbarMouseDown) {\n this.handledScrollbarMouseDown = false;\n return;\n }\n\n if (\n this.dragManager.handledMouseDown ||\n this.resizeManager.handledMouseDown ||\n this.connectionManager.connecting\n ) {\n return;\n }\n\n this.selectionManager.handleClick(event);\n }\n\n private handleDoubleClick(event: InputEvent): void {\n if (\n this.dragManager.handledMouseDown ||\n this.resizeManager.handledMouseDown ||\n this.connectionManager.connecting\n ) {\n return;\n }\n\n if (this.connectionManager.handleDoubleClick(event)) {\n return;\n }\n\n const point = { x: event.worldX, y: event.worldY };\n const edgeByLabel = this.getEdgeLabelAtPoint(point);\n if (edgeByLabel) {\n const labelPosition = edgeByLabel.getLabelPosition() ?? point;\n this.startLabelEdit('edge', edgeByLabel.id, edgeByLabel.label?.text ?? '', labelPosition);\n return;\n }\n\n const hitElement = this.renderer.getElementAtPoint(point);\n if (!hitElement) {\n this.labelEditor.finish(true, (kind, id, value) => this.handleLabelCommit(kind, id, value));\n return;\n }\n\n if ('typeName' in hitElement) {\n const editText = hitElement.label?.editableText ?? hitElement.label?.text ?? '';\n this.startLabelEdit('node', hitElement.id, editText, hitElement.getLabelPosition());\n return;\n }\n\n if ('from' in hitElement && 'to' in hitElement) {\n const labelPosition = hitElement.getLabelPosition() ?? point;\n this.startLabelEdit('edge', hitElement.id, hitElement.label?.text ?? '', labelPosition);\n }\n }\n\n private getEdgeLabelAtPoint(point: Point): Edge | null {\n const zoom = Math.max(this.renderer.zoom, 0.0001);\n const maxDistance = 28 / zoom;\n const maxDistanceSq = maxDistance * maxDistance;\n\n let closestEdge: Edge | null = null;\n let closestDistanceSq = Infinity;\n\n for (const edge of this.renderer.edges.values()) {\n if (!edge.visible || !edge.label) {\n continue;\n }\n\n const labelPosition = edge.getLabelPosition();\n if (!labelPosition) {\n continue;\n }\n\n const dx = point.x - labelPosition.x;\n const dy = point.y - labelPosition.y;\n const distanceSq = dx * dx + dy * dy;\n if (distanceSq > maxDistanceSq || distanceSq >= closestDistanceSq) {\n continue;\n }\n\n closestDistanceSq = distanceSq;\n closestEdge = edge;\n }\n\n return closestEdge;\n }\n\n private handleWheel(event: WheelInputEvent): void {\n this.navigationManager.handleWheel(event);\n }\n\n private handlePan(event: PanInputEvent): void {\n this.navigationManager.handlePanGesture(event);\n }\n\n private handlePinch(event: PinchInputEvent): void {\n this.navigationManager.handlePinch(event);\n }\n\n private handleKeyDown(event: KeyboardEvent, options: InteractionManagerOptions): void {\n const isCtrlOrMeta = event.ctrlKey || event.metaKey;\n // Use event.code for letter keys to work with any keyboard layout (e.g. Russian)\n const key = event.code.startsWith('Key')\n ? event.code.slice(3).toLowerCase()\n : event.key.toLowerCase();\n\n if (isCtrlOrMeta && (key === 'z' || key === 'y')) {\n this.flushPendingPropertyChanges();\n }\n\n if (this.historyManager.handleKeyDown(event)) {\n return;\n }\n\n this.navigationManager.handleKeyDown(event);\n\n if (this.handleViewportNavigationKey(event)) {\n return;\n }\n\n if (this.keymap.deleteKeys.includes(event.key)) {\n event.preventDefault();\n this.deleteSelection();\n return;\n }\n\n if (isCtrlOrMeta && key === this.keymap.copyKey) {\n event.preventDefault();\n this.copySelection();\n return;\n }\n\n if (isCtrlOrMeta && key === this.keymap.pasteKey) {\n event.preventDefault();\n this.pasteSelection(options);\n return;\n }\n }\n\n private handleKeyUp(event: KeyboardEvent): void {\n this.navigationManager.handleKeyUp(event);\n }\n\n private handleViewportNavigationKey(event: KeyboardEvent): boolean {\n switch (event.key) {\n case 'PageDown':\n event.preventDefault();\n this.renderer.scrollViewportBy(0, this.renderer.height * 0.8);\n return true;\n case 'PageUp':\n event.preventDefault();\n this.renderer.scrollViewportBy(0, -this.renderer.height * 0.8);\n return true;\n case 'Home':\n event.preventDefault();\n this.renderer.scrollViewportToStart();\n return true;\n case 'End':\n event.preventDefault();\n this.renderer.scrollViewportToEnd();\n return true;\n default:\n return false;\n }\n }\n\n private startLabelEdit(\n kind: 'node' | 'edge',\n id: string,\n text: string,\n worldPosition: Point\n ): void {\n this.labelEditor.start(\n kind,\n id,\n text,\n worldPosition,\n (x, y) => this.renderer.worldToScreen(x, y),\n (k, i, value) => this.handleLabelCommit(k, i, value)\n );\n }\n\n private handleLabelCommit(kind: 'node' | 'edge', id: string, nextValue: string): void {\n if (kind === 'node') {\n this.changeNodeProperties(id, (node) => {\n const value = nextValue.trim();\n if (value.length === 0) {\n node.label = undefined;\n return;\n }\n if (!node.label) {\n node.label = value;\n return;\n }\n if (node.label.editableText !== undefined) {\n node.label.editableText = value;\n node.label.text = value;\n } else {\n node.label.text = value;\n }\n });\n return;\n }\n\n this.changeEdgeProperties(id, (edge) => {\n const value = nextValue.trim();\n if (value.length === 0) {\n edge.label = undefined;\n return;\n }\n if (!edge.label) {\n edge.label = value;\n return;\n }\n edge.label.text = value;\n });\n }\n\n private queuePropertyChange(\n kind: 'node' | 'edge' | 'group',\n id: string,\n before:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>,\n after:\n | ReturnType<typeof createNodeSnapshot>\n | ReturnType<typeof createEdgeSnapshot>\n | ReturnType<typeof createGroupSnapshot>\n ): void {\n const key = `${kind}:${id}`;\n const existing = this.pendingPropertyChanges.get(key);\n if (existing) {\n existing.after = after;\n window.clearTimeout(existing.timerId);\n existing.timerId = window.setTimeout(\n () => this.flushPendingPropertyChange(key),\n this.propertyChangeDebounceMs\n );\n return;\n }\n\n const timerId = window.setTimeout(\n () => this.flushPendingPropertyChange(key),\n this.propertyChangeDebounceMs\n );\n this.pendingPropertyChanges.set(key, { kind, id, before, after, timerId });\n }\n\n private flushPendingPropertyChanges(): void {\n const keys = Array.from(this.pendingPropertyChanges.keys());\n for (const key of keys) {\n this.flushPendingPropertyChange(key);\n }\n }\n\n private flushPendingPropertyChange(key: string): void {\n const pending = this.pendingPropertyChanges.get(key);\n if (!pending) {\n return;\n }\n window.clearTimeout(pending.timerId);\n this.pendingPropertyChanges.delete(key);\n if (shallowEqual(pending.before as object, pending.after as object)) {\n return;\n }\n\n switch (pending.kind) {\n case 'node':\n this.historyManager.execute(\n new ChangeNodePropertiesCommand(\n (id) => this.renderer.getNode(id),\n pending.id,\n pending.before as ReturnType<typeof createNodeSnapshot>,\n pending.after as ReturnType<typeof createNodeSnapshot>\n )\n );\n break;\n case 'edge':\n this.historyManager.execute(\n new ChangeEdgePropertiesCommand(\n (id) => this.renderer.getEdge(id),\n pending.id,\n pending.before as ReturnType<typeof createEdgeSnapshot>,\n pending.after as ReturnType<typeof createEdgeSnapshot>\n )\n );\n break;\n case 'group':\n this.historyManager.execute(\n new ChangeGroupPropertiesCommand(\n (id) => this.renderer.getGroup(id),\n pending.id,\n pending.before as ReturnType<typeof createGroupSnapshot>,\n pending.after as ReturnType<typeof createGroupSnapshot>\n )\n );\n break;\n }\n }\n\n private deleteSelection(): void {\n const selectedIds = Array.from(this.selectionManager.selectedIds);\n this.deleteByIds(selectedIds);\n }\n\n private buildDeleteCommand(selectedIds: string[]): CompositeCommand {\n const nodes: Node[] = [];\n const edges: Edge[] = [];\n const edgeIds = new Set<string>();\n const nodeIds = new Set<string>();\n const nodeGroupIds = new Map<string, string[]>();\n\n for (const id of selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n nodes.push(node);\n nodeIds.add(id);\n continue;\n }\n\n const edge = this.renderer.getEdge(id);\n if (edge && !edgeIds.has(edge.id)) {\n edgeIds.add(edge.id);\n edges.push(edge);\n }\n }\n\n if (nodeIds.size > 0) {\n for (const group of this.renderer.groups.values()) {\n for (const child of group.children) {\n if ('typeName' in child && nodeIds.has(child.id)) {\n const list = nodeGroupIds.get(child.id) ?? [];\n list.push(group.id);\n nodeGroupIds.set(child.id, list);\n }\n }\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (nodeIds.has(edge.from.nodeId) || nodeIds.has(edge.to.nodeId)) {\n if (!edgeIds.has(edge.id)) {\n edgeIds.add(edge.id);\n edges.push(edge);\n }\n }\n }\n\n return new CompositeCommand([\n {\n execute: (): void => {\n for (const edge of edges) {\n this.renderer.removeEdge(edge.id);\n }\n for (const node of nodes) {\n this.renderer.removeNode(node.id);\n }\n },\n undo: (): void => {\n for (const node of nodes) {\n this.renderer.addNode(node);\n }\n for (const node of nodes) {\n const groupIds = nodeGroupIds.get(node.id);\n if (!groupIds) {\n continue;\n }\n for (const groupId of groupIds) {\n const group = this.renderer.getGroup(groupId);\n if (group) {\n group.addChild(node);\n }\n }\n }\n for (const edge of edges) {\n this.renderer.addEdge(edge);\n }\n },\n },\n ]);\n }\n\n private copySelection(): void {\n const selectedIds = new Set(this.selectionManager.selectedIds);\n if (selectedIds.size === 0) {\n return;\n }\n\n const nodes: SerializedNode[] = [];\n const edges: SerializedEdge[] = [];\n const nodeIds = new Set<string>();\n\n for (const id of selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n nodes.push({\n id: node.id,\n type: node.typeName,\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n style: node.style,\n styleClass: node.styleClass,\n label: node.label?.text,\n labelStyleClass: node.label?.styleClass,\n ports: node.ports.map((port) => ({\n id: port.id,\n type: port.type,\n position: port.position,\n styleClass: port.styleClass,\n })),\n data: Object.keys(node.data).length > 0 ? node.data : undefined,\n });\n nodeIds.add(node.id);\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (nodeIds.has(edge.from.nodeId) && nodeIds.has(edge.to.nodeId)) {\n edges.push({\n id: edge.id,\n from: edge.from,\n to: edge.to,\n type: edge.type,\n controlPoints: edge.controlPoints,\n arrowType: edge.arrowType,\n style: edge.style,\n styleClass: edge.styleClass,\n label: edge.label?.text,\n labelStyleClass: edge.label?.styleClass,\n labelOffset: edge.labelOffset !== 0 ? edge.labelOffset : undefined,\n labelBackground: edge.labelBackground,\n data: Object.keys(edge.data).length > 0 ? edge.data : undefined,\n });\n }\n }\n\n this.clipboard = { nodes, edges };\n }\n\n private pasteSelection(options: InteractionManagerOptions): void {\n if (!this.clipboard || !options.nodeFactory || !options.edgeFactory) {\n return;\n }\n\n const offset: Point = { x: 20, y: 20 };\n const idMap = new Map<string, string>();\n const newNodes: Node[] = [];\n const newEdges: Edge[] = [];\n\n for (const nodeData of this.clipboard.nodes) {\n const newId = `${nodeData.id}_copy_${Date.now()}`;\n idMap.set(nodeData.id, newId);\n const copyData: SerializedNode = {\n ...nodeData,\n id: newId,\n x: nodeData.x + offset.x,\n y: nodeData.y + offset.y,\n };\n newNodes.push(options.nodeFactory(copyData));\n }\n\n for (const edgeData of this.clipboard.edges) {\n const fromNodeId = idMap.get(edgeData.from.nodeId);\n const toNodeId = idMap.get(edgeData.to.nodeId);\n if (!fromNodeId || !toNodeId) {\n continue;\n }\n const newId = `${edgeData.id}_copy_${Date.now()}`;\n const copyEdge: SerializedEdge = {\n ...edgeData,\n id: newId,\n from: { ...edgeData.from, nodeId: fromNodeId },\n to: { ...edgeData.to, nodeId: toNodeId },\n };\n newEdges.push(options.edgeFactory(copyEdge));\n }\n\n if (newNodes.length === 0 && newEdges.length === 0) {\n return;\n }\n\n this.historyManager.execute({\n execute: () => {\n for (const node of newNodes) {\n this.renderer.addNode(node);\n }\n for (const edge of newEdges) {\n this.renderer.addEdge(edge);\n }\n },\n undo: () => {\n for (const edge of newEdges) {\n this.renderer.removeEdge(edge.id);\n }\n for (const node of newNodes) {\n this.renderer.removeNode(node.id);\n }\n },\n });\n }\n\n private endpointsEqual(a: EdgeEndpoint, b: EdgeEndpoint): boolean {\n if (a.nodeId !== b.nodeId) return false;\n if ((a.portId ?? null) !== (b.portId ?? null)) return false;\n const aParam = a.outlineParam;\n const bParam = b.outlineParam;\n if (aParam === undefined && bParam === undefined) return true;\n if (aParam === undefined || bParam === undefined) return false;\n return Math.abs((aParam % 1) - (bParam % 1)) < 1e-9;\n }\n\n private getSelectionBounds(): Bounds | null {\n const sources: Bounds[] = [];\n for (const id of this.selectionManager.selectedIds) {\n const node = this.renderer.getNode(id);\n if (node) {\n sources.push(node.getBounds());\n }\n }\n return mergeBounds(sources);\n }\n}\n","import type { AnimationOptions } from '@/types';\n\nexport interface AnimationState {\n opacity: number;\n scale: number;\n highlight: number;\n}\n\ninterface ExitEntry {\n start: number;\n onComplete?: () => void;\n}\n\nconst DEFAULT_OPTIONS: Required<AnimationOptions> = {\n enabled: false,\n enterDuration: 200,\n exitDuration: 180,\n highlightDuration: 450,\n enterScale: 0.92,\n exitScale: 0.98,\n};\n\nexport class AnimationManager {\n private options: Required<AnimationOptions>;\n private enter = new Map<string, number>();\n private exit = new Map<string, ExitEntry>();\n private highlight = new Map<string, number>();\n\n constructor(options: AnimationOptions = {}) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n configure(options: AnimationOptions): void {\n this.options = { ...this.options, ...options };\n }\n\n get enabled(): boolean {\n return this.options.enabled;\n }\n\n registerEnter(id: string, now = performance.now()): void {\n if (!this.options.enabled) {\n return;\n }\n this.enter.set(id, now);\n }\n\n registerExit(id: string, onComplete?: () => void, now = performance.now()): void {\n if (!this.options.enabled) {\n onComplete?.();\n return;\n }\n if (this.exit.has(id)) {\n return;\n }\n this.exit.set(id, { start: now, onComplete });\n }\n\n registerHighlight(id: string, now = performance.now()): void {\n if (!this.options.enabled) {\n return;\n }\n this.highlight.set(id, now);\n }\n\n isExiting(id: string): boolean {\n return this.exit.has(id);\n }\n\n hasActive(): boolean {\n return this.enter.size > 0 || this.exit.size > 0 || this.highlight.size > 0;\n }\n\n update(now = performance.now()): boolean {\n if (!this.options.enabled) {\n return false;\n }\n\n let changed = false;\n\n for (const [id, start] of this.enter) {\n if (now - start >= this.options.enterDuration) {\n this.enter.delete(id);\n changed = true;\n }\n }\n\n for (const [id, entry] of this.exit) {\n if (now - entry.start >= this.options.exitDuration) {\n this.exit.delete(id);\n entry.onComplete?.();\n changed = true;\n }\n }\n\n for (const [id, start] of this.highlight) {\n if (now - start >= this.options.highlightDuration) {\n this.highlight.delete(id);\n changed = true;\n }\n }\n\n return changed;\n }\n\n getState(id: string, now = performance.now()): AnimationState {\n const enterStart = this.enter.get(id);\n const exitEntry = this.exit.get(id);\n const highlightStart = this.highlight.get(id);\n\n let opacity = 1;\n let scale = 1;\n let highlight = 0;\n\n if (enterStart !== undefined) {\n const progress = Math.min(1, Math.max(0, (now - enterStart) / this.options.enterDuration));\n opacity *= progress;\n scale *= this.lerp(this.options.enterScale, 1, progress);\n }\n\n if (exitEntry !== undefined) {\n const progress = Math.min(1, Math.max(0, (now - exitEntry.start) / this.options.exitDuration));\n opacity *= 1 - progress;\n scale *= this.lerp(1, this.options.exitScale, progress);\n }\n\n if (highlightStart !== undefined) {\n const progress = Math.min(1, Math.max(0, (now - highlightStart) / this.options.highlightDuration));\n highlight = 1 - progress;\n scale *= 1 + 0.03 * highlight;\n }\n\n return { opacity, scale, highlight };\n }\n\n private lerp(from: number, to: number, t: number): number {\n return from + (to - from) * t;\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { DiagramRenderer } from './DiagramRenderer';\nimport type { Point } from '@/types';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\n\nexport type ContextMenuIcon =\n | string\n | {\n type: 'text' | 'svg' | 'html';\n value: string;\n };\n\nexport interface ContextMenuItem {\n label?: string;\n icon?: ContextMenuIcon;\n action?: (target: ContextMenuTarget) => void;\n items?: ContextMenuItem[];\n enabled?: boolean;\n visible?: boolean;\n separator?: boolean;\n}\n\nexport type ContextMenuTarget =\n | {\n type: 'node';\n node: Node;\n point: Point;\n screenPoint: Point;\n originalEvent: MouseEvent;\n }\n | {\n type: 'edge';\n edge: Edge;\n point: Point;\n screenPoint: Point;\n originalEvent: MouseEvent;\n }\n | {\n type: 'canvas';\n point: Point;\n screenPoint: Point;\n originalEvent: MouseEvent;\n };\n\nexport type ContextMenuProvider = ContextMenuItem[] | ((target: ContextMenuTarget) => ContextMenuItem[]);\n\nexport interface ContextMenuConfig {\n node?: ContextMenuProvider;\n edge?: ContextMenuProvider;\n canvas?: ContextMenuProvider;\n}\n\nexport interface ContextMenuOptions {\n menu: ContextMenuConfig;\n container?: HTMLElement;\n className?: string;\n minWidth?: number;\n closeOnSelect?: boolean;\n}\n\nexport interface ContextMenuEvents {\n open: [target: ContextMenuTarget];\n close: [];\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<ContextMenuOptions, 'menu'>> = {\n container: document.body,\n className: '',\n minWidth: 180,\n closeOnSelect: true,\n};\n\nexport class ContextMenuManager extends EventEmitter<ContextMenuEvents> {\n private renderer: DiagramRenderer;\n private options: ContextMenuOptions;\n private menuElement: HTMLDivElement | null = null;\n private cleanupHandlers: Array<() => void> = [];\n\n constructor(renderer: DiagramRenderer, options: ContextMenuOptions) {\n super();\n this.renderer = renderer;\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.attachListeners();\n }\n\n setMenu(menu: ContextMenuConfig): void {\n this.options = { ...this.options, menu };\n }\n\n destroy(): void {\n this.close();\n for (const cleanup of this.cleanupHandlers) {\n cleanup();\n }\n this.cleanupHandlers = [];\n this.removeAllListeners();\n }\n\n private attachListeners(): void {\n const canvas = this.renderer.getCanvas();\n const handleContextMenu = (event: MouseEvent): void => {\n if (event.button !== 2) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n const screenPoint: Point = { x: event.clientX, y: event.clientY };\n const worldPoint = this.renderer.screenToWorld(screenPoint.x, screenPoint.y);\n const hit = this.renderer.getElementAtPoint(worldPoint);\n\n let target: ContextMenuTarget;\n if (hit && 'typeName' in hit) {\n target = {\n type: 'node',\n node: hit,\n point: worldPoint,\n screenPoint,\n originalEvent: event,\n };\n } else if (hit && 'from' in hit && 'to' in hit) {\n target = {\n type: 'edge',\n edge: hit,\n point: worldPoint,\n screenPoint,\n originalEvent: event,\n };\n } else {\n target = {\n type: 'canvas',\n point: worldPoint,\n screenPoint,\n originalEvent: event,\n };\n }\n\n const items = this.resolveItems(target);\n if (items.length === 0) {\n this.close();\n return;\n }\n\n this.open(target, items);\n };\n\n const handleGlobalClick = (event: MouseEvent): void => {\n if (!this.menuElement) {\n return;\n }\n if (event.target instanceof HTMLElement && this.menuElement.contains(event.target)) {\n return;\n }\n this.close();\n };\n\n const handleEscape = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') {\n this.close();\n }\n };\n\n canvas.addEventListener('contextmenu', handleContextMenu, true);\n document.addEventListener('mousedown', handleGlobalClick);\n window.addEventListener('keydown', handleEscape);\n\n this.cleanupHandlers.push(() => canvas.removeEventListener('contextmenu', handleContextMenu, true));\n this.cleanupHandlers.push(() => document.removeEventListener('mousedown', handleGlobalClick));\n this.cleanupHandlers.push(() => window.removeEventListener('keydown', handleEscape));\n }\n\n private resolveItems(target: ContextMenuTarget): ContextMenuItem[] {\n const provider =\n target.type === 'node'\n ? this.options.menu.node\n : target.type === 'edge'\n ? this.options.menu.edge\n : this.options.menu.canvas;\n\n if (!provider) {\n return [];\n }\n return typeof provider === 'function' ? provider(target) : provider;\n }\n\n private open(target: ContextMenuTarget, items: ContextMenuItem[]): void {\n this.close();\n const menu = this.buildMenu(items, target);\n menu.style.minWidth = `${this.options.minWidth}px`;\n menu.style.left = `${target.screenPoint.x}px`;\n menu.style.top = `${target.screenPoint.y}px`;\n menu.className = `papirus-context-menu ${this.options.className}`.trim();\n\n this.options.container?.appendChild(menu);\n this.menuElement = menu;\n\n this.adjustPosition(menu);\n this.emit('open', target);\n }\n\n private close(): void {\n if (this.menuElement) {\n this.menuElement.remove();\n this.menuElement = null;\n this.emit('close');\n }\n }\n\n private buildMenu(items: ContextMenuItem[], target: ContextMenuTarget): HTMLDivElement {\n const container = document.createElement('div');\n container.style.position = 'fixed';\n container.style.zIndex = '10000';\n container.style.background = '#ffffff';\n container.style.border = '1px solid #e5e7eb';\n container.style.borderRadius = '8px';\n container.style.padding = '6px';\n container.style.boxShadow = '0 8px 20px rgba(15, 23, 42, 0.18)';\n container.style.fontFamily = 'system-ui, -apple-system, Segoe UI, sans-serif';\n container.style.fontSize = '14px';\n container.style.color = '#0f172a';\n\n const list = this.buildList(items, target);\n container.appendChild(list);\n return container;\n }\n\n private buildList(items: ContextMenuItem[], target: ContextMenuTarget): HTMLUListElement {\n const list = document.createElement('ul');\n list.style.listStyle = 'none';\n list.style.margin = '0';\n list.style.padding = '0';\n\n for (const item of items) {\n if (item.visible === false) {\n continue;\n }\n if (item.separator) {\n const separator = document.createElement('li');\n separator.style.listStyle = 'none';\n separator.style.margin = '6px 0';\n separator.style.borderTop = '1px solid #e5e7eb';\n list.appendChild(separator);\n continue;\n }\n const li = document.createElement('li');\n li.style.position = 'relative';\n li.style.display = 'flex';\n li.style.alignItems = 'center';\n li.style.gap = '8px';\n li.style.padding = '6px 10px';\n li.style.borderRadius = '6px';\n li.style.cursor = item.enabled === false ? 'not-allowed' : 'pointer';\n li.style.opacity = item.enabled === false ? '0.5' : '1';\n\n const label = document.createElement('span');\n label.textContent = item.label ?? '';\n\n const iconElement = this.createIconElement(item.icon);\n li.appendChild(iconElement);\n\n li.appendChild(label);\n\n if (item.items && item.items.length > 0) {\n const arrow = document.createElement('span');\n arrow.textContent = '›';\n arrow.style.marginLeft = 'auto';\n li.appendChild(arrow);\n\n const sub = this.buildList(item.items, target);\n sub.style.position = 'absolute';\n sub.style.left = '100%';\n sub.style.top = '0';\n sub.style.marginLeft = '6px';\n sub.style.background = '#ffffff';\n sub.style.border = '1px solid #e5e7eb';\n sub.style.borderRadius = '8px';\n sub.style.padding = '6px';\n sub.style.boxShadow = '0 8px 20px rgba(15, 23, 42, 0.16)';\n sub.style.display = 'none';\n li.appendChild(sub);\n\n let hideTimeout: number | null = null;\n const showSubmenu = (): void => {\n if (hideTimeout !== null) {\n window.clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n sub.style.display = 'block';\n };\n const scheduleHide = (): void => {\n if (hideTimeout !== null) {\n window.clearTimeout(hideTimeout);\n }\n hideTimeout = window.setTimeout(() => {\n hideTimeout = null;\n if (li.matches(':hover') || sub.matches(':hover')) {\n return;\n }\n sub.style.display = 'none';\n }, 150);\n };\n const hideSubmenu = (event: MouseEvent): void => {\n const related = event.relatedTarget;\n if (related instanceof HTMLElement && li.contains(related)) {\n return;\n }\n scheduleHide();\n };\n\n li.addEventListener('mouseenter', showSubmenu);\n li.addEventListener('mouseleave', hideSubmenu);\n sub.addEventListener('mouseenter', showSubmenu);\n sub.addEventListener('mouseleave', hideSubmenu);\n }\n\n li.addEventListener('mouseenter', () => {\n li.style.background = '#f1f5f9';\n });\n li.addEventListener('mouseleave', () => {\n li.style.background = 'transparent';\n });\n li.addEventListener('click', (event) => {\n event.stopPropagation();\n if (item.enabled === false) {\n return;\n }\n item.action?.(target);\n if (this.options.closeOnSelect) {\n this.close();\n }\n });\n\n list.appendChild(li);\n }\n\n return list;\n }\n\n private createIconElement(icon?: ContextMenuIcon): HTMLSpanElement {\n const iconEl = document.createElement('span');\n iconEl.style.width = '16px';\n iconEl.style.height = '16px';\n iconEl.style.display = 'inline-flex';\n iconEl.style.alignItems = 'center';\n iconEl.style.justifyContent = 'center';\n iconEl.style.textAlign = 'center';\n\n if (!icon) {\n iconEl.textContent = '';\n return iconEl;\n }\n\n if (typeof icon === 'string') {\n if (this.isSvgString(icon)) {\n iconEl.innerHTML = icon;\n } else {\n iconEl.classList.add('material-symbols-outlined');\n iconEl.style.fontSize = '16px';\n iconEl.textContent = icon;\n }\n return iconEl;\n }\n\n if (icon.type === 'svg' || icon.type === 'html') {\n iconEl.innerHTML = icon.value;\n } else {\n iconEl.classList.add('material-symbols-outlined');\n iconEl.style.fontSize = '16px';\n iconEl.textContent = icon.value;\n }\n\n return iconEl;\n }\n\n private isSvgString(value: string): boolean {\n const trimmed = value.trim();\n return trimmed.startsWith('<svg') || trimmed.includes('</svg>');\n }\n\n private adjustPosition(menu: HTMLDivElement): void {\n const rect = menu.getBoundingClientRect();\n const padding = 8;\n let left = rect.left;\n let top = rect.top;\n\n if (rect.right > window.innerWidth - padding) {\n left = Math.max(padding, window.innerWidth - rect.width - padding);\n }\n if (rect.bottom > window.innerHeight - padding) {\n top = Math.max(padding, window.innerHeight - rect.height - padding);\n }\n\n menu.style.left = `${left}px`;\n menu.style.top = `${top}px`;\n }\n}\n","import { EventEmitter } from '@/events/EventEmitter';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type { PathObstacle } from '@/elements/paths';\nimport type { Bounds, DiagramOptions, Point, ScrollbarOptions, ViewportState } from '@/types';\nimport { InteractionManager } from './InteractionManager';\nimport type { InteractionManagerOptions } from './InteractionManager';\nimport { ANCHOR_PORT_PREFIX } from '@/constants';\nimport { drawRoundedRectPath } from '@/utils/geometry';\nimport { applyStyleManagerToElements } from '@/utils/style';\nimport { getContentBounds } from '@/utils/contentBounds';\nimport { AnimationManager } from './AnimationManager';\nimport { ContextMenuManager } from './ContextMenuManager';\n\n/**\n * Events emitted by DiagramRenderer\n */\nexport interface DiagramEvents {\n render: [];\n zoom: [zoom: number];\n pan: [offsetX: number, offsetY: number];\n select: [elementIds: string[]];\n nodeAdd: [node: Node];\n nodeRemove: [node: Node];\n edgeAdd: [edge: Edge];\n edgeRemove: [edge: Edge];\n}\n\nexport interface DiagramPlugin {\n name?: string;\n install(renderer: DiagramRenderer): void;\n destroy?(renderer: DiagramRenderer): void;\n}\n\nconst DEFAULT_SCROLLBAR_OPTIONS: ScrollbarOptions = {\n enabled: true,\n autoHide: false,\n autoHideDelay: 1200,\n fadeDuration: 220,\n thickness: 6,\n hoverThickness: 8,\n minThumbLength: 24,\n hitAreaPadding: 4,\n pageScrollRatio: 0.8,\n trackColor: '',\n thumbColor: '',\n thumbHoverColor: '',\n thumbActiveColor: '',\n};\n\nconst DEFAULT_OPTIONS: Required<Omit<DiagramOptions, 'scrollbar'>> = {\n width: 800,\n height: 600,\n backgroundColor: '#ffffff',\n retina: true,\n minZoom: 0.1,\n maxZoom: 5,\n initialZoom: 1,\n snapToGrid: false,\n scrollbarOverlay: true,\n animations: {\n enabled: false,\n },\n};\n\ninterface OverlayDragPlugin extends DiagramPlugin {\n beginOverlayDrag?(renderer: DiagramRenderer, screenX: number, screenY: number): unknown;\n updateOverlayDrag?(\n renderer: DiagramRenderer,\n screenX: number,\n screenY: number,\n payload: unknown\n ): boolean;\n endOverlayDrag?(renderer: DiagramRenderer, payload: unknown): void;\n}\n\nexport interface OverlayDragSession {\n plugin: OverlayDragPlugin;\n payload: unknown;\n}\n\ntype ScrollbarAxis = 'horizontal' | 'vertical';\n\ninterface ScrollbarTrackMetrics {\n trackX: number;\n trackY: number;\n trackLength: number;\n thickness: number;\n thumbLength: number;\n thumbOffset: number;\n maxScroll: number;\n}\n\ninterface ScrollbarMetrics {\n contentBounds: Bounds;\n viewportBounds: Bounds;\n thickness: number;\n horizontal: ScrollbarTrackMetrics | null;\n vertical: ScrollbarTrackMetrics | null;\n}\n\n/**\n * Main diagram renderer class\n * Manages canvas, coordinate system, and render loop\n */\nexport class DiagramRenderer extends EventEmitter<DiagramEvents> {\n private readonly canvas: HTMLCanvasElement;\n private readonly ctx: CanvasRenderingContext2D;\n private readonly options: Required<Omit<DiagramOptions, 'scrollbar'>>;\n private readonly scrollbar: ScrollbarOptions;\n private plugins: DiagramPlugin[] = [];\n private styleManager?: StyleManager;\n private underlayRenderers = new Set<(ctx: CanvasRenderingContext2D) => void>();\n private overlayRenderers = new Set<(ctx: CanvasRenderingContext2D) => void>();\n private interactionManager: InteractionManager | null = null;\n private contextMenuManager: ContextMenuManager | null = null;\n private readonly animationManager: AnimationManager;\n private frameTime = 0;\n private scrollbarHoveredAxis: ScrollbarAxis | null = null;\n private scrollbarActiveAxis: ScrollbarAxis | null = null;\n private scrollbarLastInteractionAt = 0;\n private lastScrollbarAlpha = -1;\n\n private _zoom = 1;\n private _offsetX = 0;\n private _offsetY = 0;\n private _dirty = true;\n private _styleDirty = true;\n private _destroyed = false;\n private _canvasRect: DOMRectReadOnly | null = null;\n private _nodeObstaclesCache: PathObstacle[] | null = null;\n\n private animationFrameId: number | null = null;\n private devicePixelRatio: number;\n\n private _nodes = new Map<string, Node>();\n private _edges = new Map<string, Edge>();\n private _groups = new Map<string, Group>();\n private _attachToOutline = false;\n /** Reverse index: nodeId -> edgeIds connected to this node */\n private _nodeEdgeIndex = new Map<string, Set<string>>();\n\n /** When true, ports and anchor points are hidden (attach anywhere on outline) */\n get attachToOutline(): boolean {\n return this._attachToOutline;\n }\n\n set attachToOutline(value: boolean) {\n if (this._attachToOutline !== value) {\n this._attachToOutline = value;\n this.markDirty();\n }\n }\n\n constructor(canvas: HTMLCanvasElement | string, options: DiagramOptions = {}) {\n super();\n this.canvas = this.resolveCanvas(canvas);\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.scrollbar = this.resolveScrollbarOptions(options);\n\n const ctx = this.canvas.getContext('2d');\n if (ctx === null) {\n throw new Error('Failed to get 2D rendering context');\n }\n this.ctx = ctx;\n\n this.devicePixelRatio = this.options.retina ? window.devicePixelRatio || 1 : 1;\n this._zoom = this.options.initialZoom;\n this.animationManager = new AnimationManager(this.options.animations);\n this.scrollbarLastInteractionAt = performance.now();\n\n this.setupCanvas();\n this.startRenderLoop();\n }\n\n /**\n * Current zoom level\n */\n get zoom(): number {\n return this._zoom;\n }\n\n set zoom(value: number) {\n const clampedZoom = Math.max(this.options.minZoom, Math.min(this.options.maxZoom, value));\n if (this._zoom !== clampedZoom) {\n this._zoom = clampedZoom;\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n this.emit('zoom', clampedZoom);\n }\n }\n\n /**\n * Horizontal offset (pan)\n */\n get offsetX(): number {\n return this._offsetX;\n }\n\n set offsetX(value: number) {\n if (this._offsetX !== value) {\n this._offsetX = value;\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n this.emit('pan', this._offsetX, this._offsetY);\n }\n }\n\n /**\n * Vertical offset (pan)\n */\n get offsetY(): number {\n return this._offsetY;\n }\n\n set offsetY(value: number) {\n if (this._offsetY !== value) {\n this._offsetY = value;\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n this.emit('pan', this._offsetX, this._offsetY);\n }\n }\n\n /**\n * Get viewport state\n */\n get viewport(): ViewportState {\n return {\n zoom: this._zoom,\n offsetX: this._offsetX,\n offsetY: this._offsetY,\n };\n }\n\n /**\n * Set viewport state\n */\n set viewport(state: ViewportState) {\n this._zoom = Math.max(this.options.minZoom, Math.min(this.options.maxZoom, state.zoom));\n this._offsetX = state.offsetX;\n this._offsetY = state.offsetY;\n this.markDirty();\n this.emit('zoom', this._zoom);\n this.emit('pan', this._offsetX, this._offsetY);\n }\n\n /**\n * All nodes in the diagram\n */\n get nodes(): ReadonlyMap<string, Node> {\n return this._nodes;\n }\n\n /**\n * All edges in the diagram\n */\n get edges(): ReadonlyMap<string, Edge> {\n return this._edges;\n }\n\n /**\n * All groups in the diagram\n */\n get groups(): ReadonlyMap<string, Group> {\n return this._groups;\n }\n\n /**\n * Canvas width in CSS pixels\n */\n get width(): number {\n return this.options.width;\n }\n\n /**\n * Canvas height in CSS pixels\n */\n get height(): number {\n return this.options.height;\n }\n\n /**\n * Snap-to-grid state\n */\n get snapToGrid(): boolean {\n return this.options.snapToGrid;\n }\n\n /**\n * Device pixel ratio used for rendering\n */\n get pixelRatio(): number {\n return this.devicePixelRatio;\n }\n\n /**\n * Access the underlying canvas element\n */\n getCanvas(): HTMLCanvasElement {\n return this.canvas;\n }\n\n /**\n * Access the rendering context (read-only usage)\n */\n getContext(): CanvasRenderingContext2D {\n return this.ctx;\n }\n\n /**\n * Set the StyleManager used for rendering\n */\n setStyleManager(styleManager: StyleManager | undefined): void {\n this.styleManager = styleManager;\n this._styleDirty = true;\n this.markDirty();\n }\n\n /**\n * Get current StyleManager\n */\n getStyleManager(): StyleManager | undefined {\n return this.styleManager;\n }\n\n /**\n * Mark styles as dirty (force re-apply on next render)\n */\n markStyleDirty(): void {\n this._styleDirty = true;\n }\n\n /**\n * Access animation manager\n */\n getAnimationManager(): AnimationManager {\n return this.animationManager;\n }\n\n /**\n * Resize the canvas\n */\n resize(width: number, height: number): void {\n this.options.width = width;\n this.options.height = height;\n this.setupCanvas();\n this.updateCanvasRect();\n this.markDirty();\n }\n\n /**\n * Register and install a plugin\n */\n use(plugin: DiagramPlugin): void {\n plugin.install(this);\n this.plugins.push(plugin);\n }\n\n /**\n * Enable built-in interaction handling\n */\n enableInteractions(\n options: Omit<InteractionManagerOptions, 'renderer'> = {}\n ): InteractionManager {\n if (this.interactionManager) {\n return this.interactionManager;\n }\n this.interactionManager = new InteractionManager({ renderer: this, ...options });\n return this.interactionManager;\n }\n\n /**\n * Disable interaction handling\n */\n disableInteractions(): void {\n this.interactionManager?.destroy();\n this.interactionManager = null;\n }\n\n /**\n * Enable context menu handling\n */\n enableContextMenu(\n options: ConstructorParameters<typeof ContextMenuManager>[1]\n ): ContextMenuManager {\n this.contextMenuManager?.destroy();\n this.contextMenuManager = new ContextMenuManager(this, options);\n return this.contextMenuManager;\n }\n\n /**\n * Disable context menu handling\n */\n disableContextMenu(): void {\n this.contextMenuManager?.destroy();\n this.contextMenuManager = null;\n }\n\n /**\n * Register an underlay renderer (called before elements)\n */\n addUnderlayRenderer(renderer: (ctx: CanvasRenderingContext2D) => void): () => void {\n this.underlayRenderers.add(renderer);\n this.markDirty();\n return () => {\n this.underlayRenderers.delete(renderer);\n this.markDirty();\n };\n }\n\n /**\n * Register an overlay renderer (called after main render)\n */\n addOverlayRenderer(renderer: (ctx: CanvasRenderingContext2D) => void): () => void {\n this.overlayRenderers.add(renderer);\n this.markDirty();\n return () => {\n this.overlayRenderers.delete(renderer);\n this.markDirty();\n };\n }\n\n /**\n * Convert screen coordinates to world coordinates\n */\n screenToWorld(screenX: number, screenY: number): Point {\n const rect = this._canvasRect ?? this.canvas.getBoundingClientRect();\n const scaleX = rect.width / this.options.width;\n const scaleY = rect.height / this.options.height;\n const canvasX = (screenX - rect.left) / scaleX;\n const canvasY = (screenY - rect.top) / scaleY;\n const x = (canvasX - this._offsetX) / this._zoom;\n const y = (canvasY - this._offsetY) / this._zoom;\n return { x, y };\n }\n\n /**\n * Convert world coordinates to screen coordinates\n */\n worldToScreen(worldX: number, worldY: number): Point {\n const rect = this._canvasRect ?? this.canvas.getBoundingClientRect();\n const scaleX = rect.width / this.options.width;\n const scaleY = rect.height / this.options.height;\n const x = (worldX * this._zoom + this._offsetX) * scaleX + rect.left;\n const y = (worldY * this._zoom + this._offsetY) * scaleY + rect.top;\n return { x, y };\n }\n\n /**\n * Add a node to the diagram\n */\n addNode(node: Node): void {\n node.setDirtyListener(() => this.markDirty());\n node.setAttachToOutlineGetter(() => this._attachToOutline);\n this._nodes.set(node.id, node);\n this._nodeObstaclesCache = null;\n this.animationManager.registerEnter(node.id);\n this.markDirty();\n this.emit('nodeAdd', node);\n }\n\n /**\n * Remove a node from the diagram\n */\n removeNode(nodeId: string): boolean {\n const node = this._nodes.get(nodeId);\n if (node === undefined) {\n return false;\n }\n\n // Collect connected edges first to avoid modifying Map while iterating\n const edgesToRemove: string[] = [];\n for (const edge of this._edges.values()) {\n if (edge.from.nodeId === nodeId || edge.to.nodeId === nodeId) {\n edgesToRemove.push(edge.id);\n }\n }\n\n if (this.animationManager.enabled && !this.animationManager.isExiting(nodeId)) {\n for (const edgeId of edgesToRemove) {\n this.removeEdge(edgeId);\n }\n this.animationManager.registerExit(nodeId, () => {\n this.removeNodeImmediate(nodeId);\n });\n this.markDirty();\n return true;\n }\n\n return this.removeNodeImmediate(nodeId);\n }\n\n /**\n * Get a node by ID\n */\n getNode(nodeId: string): Node | undefined {\n return this._nodes.get(nodeId);\n }\n\n /**\n * Add an edge to the diagram\n */\n addEdge(edge: Edge): void {\n edge.setDirtyListener(() => this.markDirty());\n this._edges.set(edge.id, edge);\n // Update reverse index\n this._updateEdgeIndex(edge.id, edge.from.nodeId, true);\n this._updateEdgeIndex(edge.id, edge.to.nodeId, true);\n this.animationManager.registerEnter(edge.id);\n this.markDirty();\n this.emit('edgeAdd', edge);\n }\n\n /**\n * Update edge reverse index\n */\n private _updateEdgeIndex(edgeId: string, nodeId: string, add: boolean): void {\n let edgeIds = this._nodeEdgeIndex.get(nodeId);\n if (!edgeIds) {\n edgeIds = new Set();\n this._nodeEdgeIndex.set(nodeId, edgeIds);\n }\n if (add) {\n edgeIds.add(edgeId);\n } else {\n edgeIds.delete(edgeId);\n if (edgeIds.size === 0) {\n this._nodeEdgeIndex.delete(nodeId);\n }\n }\n }\n\n /**\n * Remove an edge from the diagram\n */\n removeEdge(edgeId: string): boolean {\n const edge = this._edges.get(edgeId);\n if (edge === undefined) {\n return false;\n }\n\n if (this.animationManager.enabled && !this.animationManager.isExiting(edgeId)) {\n this.animationManager.registerExit(edgeId, () => {\n this.removeEdgeImmediate(edgeId);\n });\n this.markDirty();\n return true;\n }\n\n return this.removeEdgeImmediate(edgeId);\n }\n\n private removeNodeImmediate(nodeId: string): boolean {\n const node = this._nodes.get(nodeId);\n if (node === undefined) {\n return false;\n }\n\n // Use reverse index to find connected edges (O(1) instead of O(n))\n const edgesToRemove = this._nodeEdgeIndex.get(nodeId);\n if (edgesToRemove) {\n // Copy to array since removeEdgeImmediate will modify the index\n for (const edgeId of Array.from(edgesToRemove)) {\n this.removeEdgeImmediate(edgeId);\n }\n }\n\n for (const group of this._groups.values()) {\n group.removeChild(nodeId);\n }\n\n this._nodes.delete(nodeId);\n this._nodeObstaclesCache = null;\n node.setDirtyListener(undefined);\n node.setAttachToOutlineGetter(undefined);\n this.markDirty();\n this.emit('nodeRemove', node);\n return true;\n }\n\n private removeEdgeImmediate(edgeId: string): boolean {\n const edge = this._edges.get(edgeId);\n if (edge === undefined) {\n return false;\n }\n\n // Clean up reverse index\n this._updateEdgeIndex(edgeId, edge.from.nodeId, false);\n this._updateEdgeIndex(edgeId, edge.to.nodeId, false);\n\n this._edges.delete(edgeId);\n edge.setDirtyListener(undefined);\n this.markDirty();\n this.emit('edgeRemove', edge);\n return true;\n }\n\n /**\n * Get an edge by ID\n */\n getEdge(edgeId: string): Edge | undefined {\n return this._edges.get(edgeId);\n }\n\n /**\n * Add a group to the diagram\n */\n addGroup(group: Group): void {\n group.setDirtyListener(() => this.markDirty());\n this._groups.set(group.id, group);\n this.markDirty();\n }\n\n /**\n * Remove a group from the diagram\n */\n removeGroup(groupId: string): boolean {\n const group = this._groups.get(groupId);\n if (group === undefined) {\n return false;\n }\n this._groups.delete(groupId);\n group.setDirtyListener(undefined);\n this.markDirty();\n return true;\n }\n\n /**\n * Get a group by ID\n */\n getGroup(groupId: string): Group | undefined {\n return this._groups.get(groupId);\n }\n\n /**\n * Find element at a point (nodes, then edges, then groups)\n */\n getElementAtPoint(worldPoint: Point): Node | Edge | Group | undefined {\n // Check nodes first (front to back)\n const nodesArray = Array.from(this._nodes.values());\n for (let i = nodesArray.length - 1; i >= 0; i--) {\n const node = nodesArray[i]!;\n if (node.visible && node.hitTest(worldPoint)) {\n return node;\n }\n }\n\n // Check edges\n for (const edge of this._edges.values()) {\n if (!edge.visible) {\n continue;\n }\n\n const baseTolerance = Math.max((edge.style.strokeWidth ?? 2) * 2, 8);\n const tolerance = baseTolerance / Math.max(this._zoom, 0.0001);\n if (edge.hitTestWithTolerance(worldPoint, tolerance)) {\n return edge;\n }\n }\n\n // Check groups (back layer)\n for (const group of this._groups.values()) {\n if (group.visible && group.hitTest(worldPoint)) {\n return group;\n }\n }\n\n return undefined;\n }\n\n /**\n * Mark the diagram as needing re-render\n */\n markDirty(): void {\n this._dirty = true;\n }\n\n /**\n * Force an immediate render\n */\n render(): void {\n this.renderFrame(performance.now());\n }\n\n /**\n * Clean up resources\n */\n destroy(): void {\n this._destroyed = true;\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n this.disableInteractions();\n this.disableContextMenu();\n for (const plugin of this.plugins) {\n plugin.destroy?.(this);\n }\n this.plugins = [];\n this.removeAllListeners();\n for (const node of this._nodes.values()) {\n node.setDirtyListener(undefined);\n }\n for (const edge of this._edges.values()) {\n edge.setDirtyListener(undefined);\n }\n for (const group of this._groups.values()) {\n group.setDirtyListener(undefined);\n }\n this._nodes.clear();\n this._edges.clear();\n this._groups.clear();\n this._nodeEdgeIndex.clear();\n }\n\n /**\n * Clear all elements from the diagram\n */\n clear(): void {\n for (const node of this._nodes.values()) {\n node.setDirtyListener(undefined);\n }\n for (const edge of this._edges.values()) {\n edge.setDirtyListener(undefined);\n }\n for (const group of this._groups.values()) {\n group.setDirtyListener(undefined);\n }\n this._nodes.clear();\n this._edges.clear();\n this._groups.clear();\n this._nodeEdgeIndex.clear();\n this.markDirty();\n }\n\n private setupCanvas(): void {\n const { width, height } = this.options;\n this.devicePixelRatio = this.options.retina ? window.devicePixelRatio || 1 : 1;\n\n // Set display size\n this.canvas.style.width = `${width}px`;\n this.canvas.style.height = `${height}px`;\n\n // Set actual size for retina displays\n this.canvas.width = width * this.devicePixelRatio;\n this.canvas.height = height * this.devicePixelRatio;\n\n // Scale context for retina\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n this.ctx.scale(this.devicePixelRatio, this.devicePixelRatio);\n\n this.updateCanvasRect();\n }\n\n private updateCanvasRect(): void {\n this._canvasRect = this.canvas.getBoundingClientRect();\n }\n\n private resolveCanvas(canvas: HTMLCanvasElement | string): HTMLCanvasElement {\n if (typeof canvas !== 'string') {\n return canvas;\n }\n\n const element = document.querySelector(canvas);\n if (element instanceof HTMLCanvasElement) {\n return element;\n }\n\n throw new Error(`Canvas element not found for selector: ${canvas}`);\n }\n\n private startRenderLoop(): void {\n const loop = (): void => {\n if (this._destroyed) {\n return;\n }\n\n const now = performance.now();\n const animationChanged = this.animationManager.update(now);\n if (animationChanged || this.animationManager.hasActive()) {\n this._dirty = true;\n }\n if (this.scrollbar.enabled && this.scrollbar.autoHide) {\n const alpha = this.getScrollbarAlpha(now);\n if (Math.abs(alpha - this.lastScrollbarAlpha) > 0.001) {\n this._dirty = true;\n this.lastScrollbarAlpha = alpha;\n }\n }\n\n // Invalidate cached canvas rect every frame so that screenToWorld /\n // worldToScreen pick up layout changes (e.g. surrounding panels resized\n // or repositioned the canvas without changing its own dimensions).\n this._canvasRect = null;\n\n if (this._dirty) {\n this.renderFrame(now);\n this._dirty = false;\n }\n\n this.animationFrameId = requestAnimationFrame(loop);\n };\n\n this.animationFrameId = requestAnimationFrame(loop);\n }\n\n private renderFrame(now: number): void {\n this.frameTime = now;\n this._nodeObstaclesCache = null;\n const ctx = this.ctx;\n const { width, height, backgroundColor } = this.options;\n\n // Reset transform for clearing\n ctx.setTransform(this.devicePixelRatio, 0, 0, this.devicePixelRatio, 0, 0);\n\n // Clear canvas\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n\n // Apply viewport transform\n ctx.translate(this._offsetX, this._offsetY);\n ctx.scale(this._zoom, this._zoom);\n\n for (const underlayRenderer of this.underlayRenderers) {\n underlayRenderer(ctx);\n }\n\n // Apply styles from StyleManager before rendering (only if dirty)\n if (this.styleManager && this._styleDirty) {\n applyStyleManagerToElements(\n this.styleManager,\n this._groups.values(),\n this._edges.values(),\n this._nodes.values()\n );\n this._styleDirty = false;\n }\n\n // Update group bounds before rendering\n for (const group of this._groups.values()) {\n group.recalculateBounds();\n }\n\n // Render groups (back layer)\n for (const group of this._groups.values()) {\n if (group.visible) {\n this.renderElementWithAnimation(ctx, group, () => group.render(ctx));\n group.clearDirty();\n }\n }\n\n // Sync edge endpoints with node positions\n this.updateEdgeEndpoints();\n\n // Render nodes (middle layer)\n for (const node of this._nodes.values()) {\n if (node.visible) {\n this.renderElementWithAnimation(ctx, node, () => node.render(ctx));\n node.clearDirty();\n }\n }\n\n // Render edges above nodes so lines/markers stay visible over figures.\n for (const edge of this._edges.values()) {\n if (edge.visible) {\n this.renderElementWithAnimation(ctx, edge, () => edge.render(ctx));\n edge.clearDirty();\n }\n }\n\n // Render edge handles (topmost layer)\n for (const edge of this._edges.values()) {\n if (edge.visible) {\n edge.renderHandles(ctx);\n }\n }\n\n for (const overlayRenderer of this.overlayRenderers) {\n overlayRenderer(ctx);\n }\n\n this.renderScrollbars(ctx);\n this.emit('render');\n }\n\n private renderElementWithAnimation(\n ctx: CanvasRenderingContext2D,\n element: { id: string; getBounds: () => Bounds },\n renderFn: () => void\n ): void {\n if (!this.animationManager.enabled) {\n renderFn();\n return;\n }\n\n const state = this.animationManager.getState(element.id, this.frameTime);\n if (state.opacity <= 0) {\n return;\n }\n\n if (state.opacity !== 1 || state.scale !== 1) {\n const bounds = element.getBounds();\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n\n ctx.save();\n ctx.globalAlpha *= state.opacity;\n if (state.scale !== 1) {\n ctx.translate(cx, cy);\n ctx.scale(state.scale, state.scale);\n ctx.translate(-cx, -cy);\n }\n renderFn();\n ctx.restore();\n return;\n }\n\n renderFn();\n }\n\n /**\n * Update edge endpoints to reflect current node positions\n * Called during drag to keep control points in sync\n */\n updateEdgeEndpointsForDrag(): void {\n for (const edge of this._edges.values()) {\n if (!edge.autoUpdateEndpoints) {\n continue;\n }\n\n const fromNode = this._nodes.get(edge.from.nodeId);\n const toNode = this._nodes.get(edge.to.nodeId);\n if (fromNode === undefined || toNode === undefined) {\n continue;\n }\n\n let fromPoint: Point;\n let toPoint: Point;\n let fromDir: string | undefined;\n let toDir: string | undefined;\n\n if (edge.from.portId) {\n const anchorId = edge.from.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = fromNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n fromPoint = anchorPoint;\n fromDir = anchorId.split(':')[0];\n } else {\n fromPoint = fromNode.getCenter();\n }\n } else if (edge.from.outlineParam !== undefined) {\n fromPoint = fromNode.getConnectionPointAtOutlineParam(edge.from.outlineParam);\n fromDir = this.getDirectionFromOutlineParam(edge.from.outlineParam);\n } else {\n fromPoint = fromNode.getCenter();\n }\n\n if (edge.to.portId) {\n const anchorId = edge.to.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = toNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n toPoint = anchorPoint;\n toDir = anchorId.split(':')[0];\n } else {\n toPoint = toNode.getCenter();\n }\n } else if (edge.to.outlineParam !== undefined) {\n toPoint = toNode.getConnectionPointAtOutlineParam(edge.to.outlineParam);\n toDir = this.getDirectionFromOutlineParam(edge.to.outlineParam);\n } else {\n toPoint = toNode.getCenter();\n }\n\n edge.updateEndpoints(fromPoint, toPoint, fromDir, toDir);\n }\n }\n\n private updateEdgeEndpoints(): void {\n const obstacles = this.getNodeObstacles();\n\n for (const edge of this._edges.values()) {\n if (!edge.autoUpdateEndpoints) {\n continue;\n }\n\n const fromNode = this._nodes.get(edge.from.nodeId);\n const toNode = this._nodes.get(edge.to.nodeId);\n if (fromNode === undefined || toNode === undefined) {\n continue;\n }\n\n if (edge.lockAnchors && edge.from.outlineParam === undefined) {\n if (!edge.from.portId) {\n const anchor = fromNode.getNearestAnchor(toNode.getCenter());\n if (anchor) {\n edge.from = { ...edge.from, portId: `${ANCHOR_PORT_PREFIX}${anchor.id}` };\n }\n }\n }\n if (edge.lockAnchors && edge.to.outlineParam === undefined) {\n if (!edge.to.portId) {\n const anchor = toNode.getNearestAnchor(fromNode.getCenter());\n if (anchor) {\n edge.to = { ...edge.to, portId: `${ANCHOR_PORT_PREFIX}${anchor.id}` };\n }\n }\n }\n\n let fromPoint: Point;\n let toPoint: Point;\n let fromDir: string | undefined;\n let toDir: string | undefined;\n\n if (edge.from.portId) {\n const anchorId = edge.from.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = fromNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n fromPoint = anchorPoint;\n fromDir = anchorId.split(':')[0];\n } else {\n fromPoint = fromNode.getCenter();\n }\n } else if (edge.from.outlineParam !== undefined) {\n fromPoint = fromNode.getConnectionPointAtOutlineParam(edge.from.outlineParam);\n fromDir = this.getDirectionFromOutlineParam(edge.from.outlineParam);\n } else {\n fromPoint = fromNode.getCenter();\n }\n\n if (edge.to.portId) {\n const anchorId = edge.to.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = toNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n toPoint = anchorPoint;\n toDir = anchorId.split(':')[0];\n } else {\n toPoint = toNode.getCenter();\n }\n } else if (edge.to.outlineParam !== undefined) {\n toPoint = toNode.getConnectionPointAtOutlineParam(edge.to.outlineParam);\n toDir = this.getDirectionFromOutlineParam(edge.to.outlineParam);\n } else {\n toPoint = toNode.getCenter();\n }\n\n edge.updateEndpoints(fromPoint, toPoint, fromDir, toDir, { obstacles });\n }\n }\n\n private getNodeObstacles(): PathObstacle[] {\n if (this._nodeObstaclesCache !== null) {\n return this._nodeObstaclesCache;\n }\n\n this._nodeObstaclesCache = Array.from(this._nodes.values()).map((node) => ({\n x: node.x - 8,\n y: node.y - 8,\n width: node.width + 16,\n height: node.height + 16,\n role: 'other' as const,\n }));\n\n return this._nodeObstaclesCache;\n }\n\n private getDirectionFromOutlineParam(param: number): string {\n const p = ((param % 1) + 1) % 1;\n if (p < 0.25) return 'top';\n if (p < 0.5) return 'right';\n if (p < 0.75) return 'bottom';\n return 'left';\n }\n\n private renderScrollbars(ctx: CanvasRenderingContext2D): void {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return;\n }\n\n const alpha = this.getScrollbarAlpha(this.frameTime);\n this.lastScrollbarAlpha = alpha;\n if (alpha <= 0.001) {\n return;\n }\n\n const colors = this.resolveScrollbarColors();\n const drawRoundedRect = (x: number, y: number, w: number, h: number, r: number): void => {\n drawRoundedRectPath(ctx, x, y, w, h, r);\n };\n\n ctx.save();\n ctx.setTransform(this.devicePixelRatio, 0, 0, this.devicePixelRatio, 0, 0);\n ctx.globalAlpha = alpha;\n\n if (metrics.horizontal) {\n const isHovered = this.scrollbarHoveredAxis === 'horizontal';\n const isActive = this.scrollbarActiveAxis === 'horizontal';\n const thickness =\n isHovered || isActive ? this.scrollbar.hoverThickness : this.scrollbar.thickness;\n const trackY = metrics.horizontal.trackY + (metrics.horizontal.thickness - thickness) / 2;\n const radius = thickness / 2;\n const thumbColor = isActive\n ? colors.thumbActive\n : isHovered\n ? colors.thumbHover\n : colors.thumb;\n\n ctx.fillStyle = colors.track;\n drawRoundedRect(\n metrics.horizontal.trackX,\n trackY,\n metrics.horizontal.trackLength,\n thickness,\n radius\n );\n ctx.fill();\n\n ctx.fillStyle = thumbColor;\n drawRoundedRect(\n metrics.horizontal.trackX + metrics.horizontal.thumbOffset,\n trackY,\n metrics.horizontal.thumbLength,\n thickness,\n radius\n );\n ctx.fill();\n }\n\n if (metrics.vertical) {\n const isHovered = this.scrollbarHoveredAxis === 'vertical';\n const isActive = this.scrollbarActiveAxis === 'vertical';\n const thickness =\n isHovered || isActive ? this.scrollbar.hoverThickness : this.scrollbar.thickness;\n const trackX = metrics.vertical.trackX + (metrics.vertical.thickness - thickness) / 2;\n const radius = thickness / 2;\n const thumbColor = isActive\n ? colors.thumbActive\n : isHovered\n ? colors.thumbHover\n : colors.thumb;\n\n ctx.fillStyle = colors.track;\n drawRoundedRect(\n trackX,\n metrics.vertical.trackY,\n thickness,\n metrics.vertical.trackLength,\n radius\n );\n ctx.fill();\n\n ctx.fillStyle = thumbColor;\n drawRoundedRect(\n trackX,\n metrics.vertical.trackY + metrics.vertical.thumbOffset,\n thickness,\n metrics.vertical.thumbLength,\n radius\n );\n ctx.fill();\n }\n\n ctx.restore();\n }\n\n private getContentBounds(): Bounds | null {\n return getContentBounds({\n nodes: this._nodes.values(),\n edges: this._edges.values(),\n groups: this._groups.values(),\n });\n }\n\n private getViewportBounds(): Bounds {\n return {\n x: -this._offsetX / this._zoom,\n y: -this._offsetY / this._zoom,\n width: this.options.width / this._zoom,\n height: this.options.height / this._zoom,\n };\n }\n\n notifyScrollbarInteraction(): void {\n this.scrollbarLastInteractionAt = performance.now();\n this.markDirty();\n }\n\n setScrollbarActiveAxis(axis: ScrollbarAxis | null): void {\n if (this.scrollbarActiveAxis === axis) {\n return;\n }\n this.scrollbarActiveAxis = axis;\n if (axis !== null) {\n this.notifyScrollbarInteraction();\n } else {\n this.markDirty();\n }\n }\n\n updateScrollbarHover(screenX: number, screenY: number): boolean {\n const axis = this.hitTestScrollbarArea(screenX, screenY);\n if (this.scrollbarHoveredAxis !== axis) {\n this.scrollbarHoveredAxis = axis;\n this.markDirty();\n if (axis !== null) {\n this.notifyScrollbarInteraction();\n }\n }\n return axis !== null;\n }\n\n clearScrollbarHover(): void {\n if (this.scrollbarHoveredAxis !== null) {\n this.scrollbarHoveredAxis = null;\n this.markDirty();\n }\n }\n\n hitTestScrollbarThumb(\n screenX: number,\n screenY: number\n ): { axis: ScrollbarAxis; pointerOffset: number } | null {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return null;\n }\n\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return null;\n }\n\n const { x, y } = localPoint;\n const hitPadding = this.scrollbar.hitAreaPadding;\n\n if (metrics.horizontal) {\n const thumbStartX = metrics.horizontal.trackX + metrics.horizontal.thumbOffset;\n if (\n x >= thumbStartX - hitPadding &&\n x <= thumbStartX + metrics.horizontal.thumbLength + hitPadding &&\n y >= metrics.horizontal.trackY - hitPadding &&\n y <= metrics.horizontal.trackY + metrics.horizontal.thickness + hitPadding\n ) {\n return {\n axis: 'horizontal',\n pointerOffset: x - thumbStartX,\n };\n }\n }\n\n if (metrics.vertical) {\n const thumbStartY = metrics.vertical.trackY + metrics.vertical.thumbOffset;\n if (\n x >= metrics.vertical.trackX - hitPadding &&\n x <= metrics.vertical.trackX + metrics.vertical.thickness + hitPadding &&\n y >= thumbStartY - hitPadding &&\n y <= thumbStartY + metrics.vertical.thumbLength + hitPadding\n ) {\n return {\n axis: 'vertical',\n pointerOffset: y - thumbStartY,\n };\n }\n }\n\n return null;\n }\n\n dragScrollbarThumb(\n axis: ScrollbarAxis,\n screenX: number,\n screenY: number,\n pointerOffset: number\n ): boolean {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return false;\n }\n\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return false;\n }\n\n if (axis === 'horizontal' && metrics.horizontal) {\n const travel = Math.max(0, metrics.horizontal.trackLength - metrics.horizontal.thumbLength);\n const desiredThumbOffset = localPoint.x - metrics.horizontal.trackX - pointerOffset;\n const clampedThumbOffset = Math.min(Math.max(desiredThumbOffset, 0), travel);\n const scrollX =\n travel > 0 && metrics.horizontal.maxScroll > 0\n ? (clampedThumbOffset / travel) * metrics.horizontal.maxScroll\n : 0;\n const viewportX = metrics.contentBounds.x + scrollX;\n this.offsetX = -viewportX * this._zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n if (axis === 'vertical' && metrics.vertical) {\n const travel = Math.max(0, metrics.vertical.trackLength - metrics.vertical.thumbLength);\n const desiredThumbOffset = localPoint.y - metrics.vertical.trackY - pointerOffset;\n const clampedThumbOffset = Math.min(Math.max(desiredThumbOffset, 0), travel);\n const scrollY =\n travel > 0 && metrics.vertical.maxScroll > 0\n ? (clampedThumbOffset / travel) * metrics.vertical.maxScroll\n : 0;\n const viewportY = metrics.contentBounds.y + scrollY;\n this.offsetY = -viewportY * this._zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n return false;\n }\n\n clickScrollbarTrack(screenX: number, screenY: number): boolean {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return false;\n }\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return false;\n }\n\n if (metrics.horizontal) {\n const { trackX, trackY, trackLength, thumbOffset, thumbLength, maxScroll } =\n metrics.horizontal;\n const inTrack =\n localPoint.x >= trackX &&\n localPoint.x <= trackX + trackLength &&\n localPoint.y >= trackY &&\n localPoint.y <= trackY + metrics.horizontal.thickness;\n if (inTrack) {\n const thumbStart = trackX + thumbOffset;\n const thumbEnd = thumbStart + thumbLength;\n if (localPoint.x < thumbStart || localPoint.x > thumbEnd) {\n const direction = localPoint.x < thumbStart ? -1 : 1;\n const step = metrics.viewportBounds.width * this.scrollbar.pageScrollRatio * direction;\n const currentScrollX = Math.min(\n Math.max(metrics.viewportBounds.x - metrics.contentBounds.x, 0),\n maxScroll\n );\n const nextScrollX = Math.min(Math.max(currentScrollX + step, 0), maxScroll);\n const viewportX = metrics.contentBounds.x + nextScrollX;\n this.offsetX = -viewportX * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n }\n }\n\n if (metrics.vertical) {\n const { trackX, trackY, trackLength, thumbOffset, thumbLength, maxScroll } = metrics.vertical;\n const inTrack =\n localPoint.x >= trackX &&\n localPoint.x <= trackX + metrics.vertical.thickness &&\n localPoint.y >= trackY &&\n localPoint.y <= trackY + trackLength;\n if (inTrack) {\n const thumbStart = trackY + thumbOffset;\n const thumbEnd = thumbStart + thumbLength;\n if (localPoint.y < thumbStart || localPoint.y > thumbEnd) {\n const direction = localPoint.y < thumbStart ? -1 : 1;\n const step = metrics.viewportBounds.height * this.scrollbar.pageScrollRatio * direction;\n const currentScrollY = Math.min(\n Math.max(metrics.viewportBounds.y - metrics.contentBounds.y, 0),\n maxScroll\n );\n const nextScrollY = Math.min(Math.max(currentScrollY + step, 0), maxScroll);\n const viewportY = metrics.contentBounds.y + nextScrollY;\n this.offsetY = -viewportY * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n }\n }\n\n return false;\n }\n\n scrollViewportBy(screenDx: number, screenDy: number): boolean {\n const scrollState = this.getScrollState();\n if (!scrollState) {\n return false;\n }\n const worldDx = screenDx / this.zoom;\n const worldDy = screenDy / this.zoom;\n const currentViewportX = scrollState.viewportBounds.x;\n const currentViewportY = scrollState.viewportBounds.y;\n const maxScrollX = Math.max(\n 0,\n scrollState.contentBounds.width - scrollState.viewportBounds.width\n );\n const maxScrollY = Math.max(\n 0,\n scrollState.contentBounds.height - scrollState.viewportBounds.height\n );\n const nextViewportX = Math.min(\n Math.max(currentViewportX + worldDx, scrollState.contentBounds.x),\n scrollState.contentBounds.x + maxScrollX\n );\n const nextViewportY = Math.min(\n Math.max(currentViewportY + worldDy, scrollState.contentBounds.y),\n scrollState.contentBounds.y + maxScrollY\n );\n\n this.offsetX = -nextViewportX * this.zoom;\n this.offsetY = -nextViewportY * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n scrollViewportToStart(): boolean {\n const scrollState = this.getScrollState();\n if (!scrollState) {\n return false;\n }\n this.offsetX = -scrollState.contentBounds.x * this.zoom;\n this.offsetY = -scrollState.contentBounds.y * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n scrollViewportToEnd(): boolean {\n const scrollState = this.getScrollState();\n if (!scrollState) {\n return false;\n }\n const maxScrollX = Math.max(\n 0,\n scrollState.contentBounds.width - scrollState.viewportBounds.width\n );\n const maxScrollY = Math.max(\n 0,\n scrollState.contentBounds.height - scrollState.viewportBounds.height\n );\n const targetViewportX = scrollState.contentBounds.x + maxScrollX;\n const targetViewportY = scrollState.contentBounds.y + maxScrollY;\n this.offsetX = -targetViewportX * this.zoom;\n this.offsetY = -targetViewportY * this.zoom;\n this.notifyScrollbarInteraction();\n return true;\n }\n\n beginOverlayDrag(screenX: number, screenY: number): OverlayDragSession | null {\n for (const plugin of this.plugins) {\n const interactivePlugin = plugin as OverlayDragPlugin;\n if (!interactivePlugin.beginOverlayDrag) {\n continue;\n }\n const payload = interactivePlugin.beginOverlayDrag(this, screenX, screenY);\n if (payload !== null && payload !== undefined) {\n return { plugin: interactivePlugin, payload };\n }\n }\n return null;\n }\n\n updateOverlayDrag(session: OverlayDragSession, screenX: number, screenY: number): boolean {\n return session.plugin.updateOverlayDrag?.(this, screenX, screenY, session.payload) ?? false;\n }\n\n endOverlayDrag(session: OverlayDragSession): void {\n session.plugin.endOverlayDrag?.(this, session.payload);\n }\n\n screenToCanvas(screenX: number, screenY: number): Point | null {\n const rect = this._canvasRect ?? this.canvas.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) {\n return null;\n }\n\n const scaleX = rect.width / this.options.width;\n const scaleY = rect.height / this.options.height;\n return {\n x: (screenX - rect.left) / scaleX,\n y: (screenY - rect.top) / scaleY,\n };\n }\n\n private getScrollbarMetrics(): ScrollbarMetrics | null {\n if (!this.scrollbar.enabled) {\n return null;\n }\n\n const rawContentBounds = this.getContentBounds();\n if (!rawContentBounds) {\n return null;\n }\n\n const viewportBounds = this.getViewportBounds();\n const unionMinX = Math.min(rawContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(rawContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(\n rawContentBounds.x + rawContentBounds.width,\n viewportBounds.x + viewportBounds.width\n );\n const unionMaxY = Math.max(\n rawContentBounds.y + rawContentBounds.height,\n viewportBounds.y + viewportBounds.height\n );\n const contentBounds = {\n x: unionMinX,\n y: unionMinY,\n width: unionMaxX - unionMinX,\n height: unionMaxY - unionMinY,\n };\n\n const contentWidth = Math.max(contentBounds.width, 1);\n const contentHeight = Math.max(contentBounds.height, 1);\n const showHorizontal = contentWidth > viewportBounds.width + 0.01;\n const showVertical = contentHeight > viewportBounds.height + 0.01;\n if (!showHorizontal && !showVertical) {\n return null;\n }\n\n const { width, height } = this.options;\n const padding = 6;\n const thickness = this.scrollbar.thickness;\n const spacing = 4;\n const minThumbLength = this.scrollbar.minThumbLength;\n\n const availableWidth = width - padding * 2;\n const availableHeight = height - padding * 2;\n if (availableWidth <= 0 || availableHeight <= 0) {\n return null;\n }\n\n const horizontalTrackLength = Math.max(\n 0,\n availableWidth - (showVertical ? thickness + spacing : 0)\n );\n const verticalTrackLength = Math.max(\n 0,\n availableHeight - (showHorizontal ? thickness + spacing : 0)\n );\n\n const horizontalTrackX = padding;\n const horizontalTrackY = height - padding - thickness;\n const verticalTrackX = width - padding - thickness;\n const verticalTrackY = padding;\n\n let horizontal: ScrollbarTrackMetrics | null = null;\n if (showHorizontal && horizontalTrackLength > 0) {\n const maxScrollX = Math.max(0, contentWidth - viewportBounds.width);\n const scrollX = Math.min(Math.max(viewportBounds.x - contentBounds.x, 0), maxScrollX);\n const ratioX = viewportBounds.width / contentWidth;\n const thumbLength = Math.min(\n horizontalTrackLength,\n Math.max(minThumbLength, horizontalTrackLength * ratioX)\n );\n const travel = Math.max(0, horizontalTrackLength - thumbLength);\n const thumbOffset = maxScrollX > 0 ? (scrollX / maxScrollX) * travel : 0;\n horizontal = {\n trackX: horizontalTrackX,\n trackY: horizontalTrackY,\n trackLength: horizontalTrackLength,\n thickness,\n thumbLength,\n thumbOffset,\n maxScroll: maxScrollX,\n };\n }\n\n let vertical: ScrollbarTrackMetrics | null = null;\n if (showVertical && verticalTrackLength > 0) {\n const maxScrollY = Math.max(0, contentHeight - viewportBounds.height);\n const scrollY = Math.min(Math.max(viewportBounds.y - contentBounds.y, 0), maxScrollY);\n const ratioY = viewportBounds.height / contentHeight;\n const thumbLength = Math.min(\n verticalTrackLength,\n Math.max(minThumbLength, verticalTrackLength * ratioY)\n );\n const travel = Math.max(0, verticalTrackLength - thumbLength);\n const thumbOffset = maxScrollY > 0 ? (scrollY / maxScrollY) * travel : 0;\n vertical = {\n trackX: verticalTrackX,\n trackY: verticalTrackY,\n trackLength: verticalTrackLength,\n thickness,\n thumbLength,\n thumbOffset,\n maxScroll: maxScrollY,\n };\n }\n\n if (!horizontal && !vertical) {\n return null;\n }\n\n return {\n contentBounds,\n viewportBounds,\n thickness: this.scrollbar.thickness,\n horizontal,\n vertical,\n };\n }\n\n private resolveScrollbarOptions(options: DiagramOptions): ScrollbarOptions {\n const fallbackEnabled = options.scrollbarOverlay ?? DEFAULT_SCROLLBAR_OPTIONS.enabled;\n const resolved: ScrollbarOptions = {\n ...DEFAULT_SCROLLBAR_OPTIONS,\n enabled: fallbackEnabled,\n };\n if (typeof options.scrollbar === 'boolean') {\n resolved.enabled = options.scrollbar;\n return resolved;\n }\n if (options.scrollbar) {\n return { ...resolved, ...options.scrollbar };\n }\n return resolved;\n }\n\n private resolveScrollbarColors(): {\n track: string;\n thumb: string;\n thumbHover: string;\n thumbActive: string;\n } {\n const isDarkTheme = this.styleManager?.theme.name === 'dark';\n const fallback = isDarkTheme\n ? {\n track: 'rgba(148, 163, 184, 0.22)',\n thumb: 'rgba(226, 232, 240, 0.68)',\n thumbHover: 'rgba(226, 232, 240, 0.86)',\n thumbActive: 'rgba(248, 250, 252, 0.96)',\n }\n : {\n track: 'rgba(15, 23, 42, 0.16)',\n thumb: 'rgba(51, 65, 85, 0.7)',\n thumbHover: 'rgba(30, 41, 59, 0.82)',\n thumbActive: 'rgba(15, 23, 42, 0.9)',\n };\n\n return {\n track: this.scrollbar.trackColor || fallback.track,\n thumb: this.scrollbar.thumbColor || fallback.thumb,\n thumbHover: this.scrollbar.thumbHoverColor || fallback.thumbHover,\n thumbActive: this.scrollbar.thumbActiveColor || fallback.thumbActive,\n };\n }\n\n private getScrollbarAlpha(now: number): number {\n if (!this.scrollbar.autoHide) {\n return 1;\n }\n if (this.scrollbarActiveAxis !== null || this.scrollbarHoveredAxis !== null) {\n return 1;\n }\n const elapsed = now - this.scrollbarLastInteractionAt;\n if (elapsed <= this.scrollbar.autoHideDelay) {\n return 1;\n }\n if (this.scrollbar.fadeDuration <= 0) {\n return 0;\n }\n const fadeProgress = (elapsed - this.scrollbar.autoHideDelay) / this.scrollbar.fadeDuration;\n return Math.max(0, 1 - fadeProgress);\n }\n\n private hitTestScrollbarArea(screenX: number, screenY: number): ScrollbarAxis | null {\n const metrics = this.getScrollbarMetrics();\n if (!metrics) {\n return null;\n }\n const localPoint = this.screenToCanvas(screenX, screenY);\n if (!localPoint) {\n return null;\n }\n const hitPadding = this.scrollbar.hitAreaPadding;\n\n if (metrics.horizontal) {\n const inHorizontalTrack =\n localPoint.x >= metrics.horizontal.trackX - hitPadding &&\n localPoint.x <= metrics.horizontal.trackX + metrics.horizontal.trackLength + hitPadding &&\n localPoint.y >= metrics.horizontal.trackY - hitPadding &&\n localPoint.y <= metrics.horizontal.trackY + metrics.horizontal.thickness + hitPadding;\n if (inHorizontalTrack) {\n return 'horizontal';\n }\n }\n\n if (metrics.vertical) {\n const inVerticalTrack =\n localPoint.x >= metrics.vertical.trackX - hitPadding &&\n localPoint.x <= metrics.vertical.trackX + metrics.vertical.thickness + hitPadding &&\n localPoint.y >= metrics.vertical.trackY - hitPadding &&\n localPoint.y <= metrics.vertical.trackY + metrics.vertical.trackLength + hitPadding;\n if (inVerticalTrack) {\n return 'vertical';\n }\n }\n return null;\n }\n\n private getScrollState(): { contentBounds: Bounds; viewportBounds: Bounds } | null {\n const rawContentBounds = this.getContentBounds();\n if (!rawContentBounds) {\n return null;\n }\n const viewportBounds = this.getViewportBounds();\n const unionMinX = Math.min(rawContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(rawContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(\n rawContentBounds.x + rawContentBounds.width,\n viewportBounds.x + viewportBounds.width\n );\n const unionMaxY = Math.max(\n rawContentBounds.y + rawContentBounds.height,\n viewportBounds.y + viewportBounds.height\n );\n return {\n contentBounds: {\n x: unionMinX,\n y: unionMinY,\n width: unionMaxX - unionMinX,\n height: unionMaxY - unionMinY,\n },\n viewportBounds,\n };\n }\n}\n","import type { DiagramRenderer } from './DiagramRenderer';\nimport type { EdgePathType } from '@/types';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport { AnimationManager } from './AnimationManager';\n\nexport interface SearchManagerOptions {\n highlightColor?: string;\n currentColor?: string;\n highlightLineWidth?: number;\n currentLineWidth?: number;\n highlightPadding?: number;\n}\n\nexport interface SearchFindOptions {\n highlight?: boolean;\n caseSensitive?: boolean;\n highlightColor?: string;\n}\n\nexport interface SearchFilterOptions {\n nodeType?: string;\n edgeType?: EdgePathType;\n styleClass?: string;\n scope?: 'nodes' | 'edges' | 'all';\n predicate?: (element: Node | Edge) => boolean;\n}\n\nexport interface SearchMatch {\n id: string;\n type: 'node' | 'edge';\n label: string;\n}\n\nexport interface SearchResult {\n matches: SearchMatch[];\n nodes: Node[];\n edges: Edge[];\n}\n\nconst DEFAULT_OPTIONS: Required<SearchManagerOptions> = {\n highlightColor: '#f59e0b',\n currentColor: '#ef4444',\n highlightLineWidth: 2,\n currentLineWidth: 3,\n highlightPadding: 6,\n};\n\nexport class SearchManager {\n private renderer: DiagramRenderer;\n private options: Required<SearchManagerOptions>;\n private highlightIds = new Set<string>();\n private currentId: string | null = null;\n private overlayCleanup: (() => void) | null = null;\n private lastMatches: SearchMatch[] = [];\n private currentIndex = -1;\n private visibilityCache = new Map<string, boolean>();\n private filterActive = false;\n private animationManager?: AnimationManager;\n\n constructor(renderer: DiagramRenderer, options: SearchManagerOptions = {}) {\n this.renderer = renderer;\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.animationManager = renderer.getAnimationManager?.();\n this.overlayCleanup = this.renderer.addOverlayRenderer((ctx) => this.renderHighlights(ctx));\n }\n\n destroy(): void {\n this.overlayCleanup?.();\n this.overlayCleanup = null;\n this.highlightIds.clear();\n this.currentId = null;\n this.visibilityCache.clear();\n this.filterActive = false;\n }\n\n find(query: string, options: SearchFindOptions = {}): SearchResult {\n const caseSensitive = options.caseSensitive ?? false;\n const normalizedQuery = caseSensitive ? query : query.toLowerCase();\n\n const matches: SearchMatch[] = [];\n const nodes: Node[] = [];\n const edges: Edge[] = [];\n\n for (const node of this.renderer.nodes.values()) {\n const label = node.label?.text ?? '';\n if (!label) continue;\n const haystack = caseSensitive ? label : label.toLowerCase();\n if (haystack.includes(normalizedQuery)) {\n matches.push({ id: node.id, type: 'node', label });\n nodes.push(node);\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n const label = edge.label?.text ?? '';\n if (!label) continue;\n const haystack = caseSensitive ? label : label.toLowerCase();\n if (haystack.includes(normalizedQuery)) {\n matches.push({ id: edge.id, type: 'edge', label });\n edges.push(edge);\n }\n }\n\n this.lastMatches = matches;\n this.currentIndex = matches.length > 0 ? 0 : -1;\n this.currentId = matches.length > 0 ? matches[0]!.id : null;\n\n if (options.highlight ?? true) {\n this.setHighlights(matches.map((match) => match.id), options.highlightColor);\n }\n\n return { matches, nodes, edges };\n }\n\n next(): SearchMatch | null {\n if (this.lastMatches.length === 0) {\n return null;\n }\n this.currentIndex = (this.currentIndex + 1) % this.lastMatches.length;\n const match = this.lastMatches[this.currentIndex]!;\n this.currentId = match.id;\n this.animationManager?.registerHighlight(match.id);\n this.renderer.markDirty();\n return match;\n }\n\n previous(): SearchMatch | null {\n if (this.lastMatches.length === 0) {\n return null;\n }\n this.currentIndex =\n (this.currentIndex - 1 + this.lastMatches.length) % this.lastMatches.length;\n const match = this.lastMatches[this.currentIndex]!;\n this.currentId = match.id;\n this.animationManager?.registerHighlight(match.id);\n this.renderer.markDirty();\n return match;\n }\n\n clear(): void {\n this.clearHighlights();\n this.clearFilter();\n this.lastMatches = [];\n this.currentIndex = -1;\n this.currentId = null;\n }\n\n filter(options: SearchFilterOptions): void {\n if (!this.filterActive) {\n this.visibilityCache.clear();\n for (const node of this.renderer.nodes.values()) {\n this.visibilityCache.set(node.id, node.visible);\n }\n for (const edge of this.renderer.edges.values()) {\n this.visibilityCache.set(edge.id, edge.visible);\n }\n this.filterActive = true;\n }\n\n const scope = options.scope ?? 'all';\n\n for (const node of this.renderer.nodes.values()) {\n if (scope === 'edges') {\n continue;\n }\n node.visible = this.matchesNode(node, options);\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (scope === 'nodes') {\n continue;\n }\n const matchesEdge = this.matchesEdge(edge, options);\n const fromVisible = this.renderer.getNode(edge.from.nodeId)?.visible ?? true;\n const toVisible = this.renderer.getNode(edge.to.nodeId)?.visible ?? true;\n edge.visible = matchesEdge && fromVisible && toVisible;\n }\n\n this.renderer.markDirty();\n }\n\n clearFilter(): void {\n if (!this.filterActive) {\n return;\n }\n for (const node of this.renderer.nodes.values()) {\n const cached = this.visibilityCache.get(node.id);\n if (cached !== undefined) {\n node.visible = cached;\n }\n }\n for (const edge of this.renderer.edges.values()) {\n const cached = this.visibilityCache.get(edge.id);\n if (cached !== undefined) {\n edge.visible = cached;\n }\n }\n this.visibilityCache.clear();\n this.filterActive = false;\n this.renderer.markDirty();\n }\n\n private setHighlights(ids: string[], colorOverride?: string): void {\n this.highlightIds = new Set(ids);\n if (colorOverride) {\n this.options = { ...this.options, highlightColor: colorOverride };\n }\n for (const id of this.highlightIds) {\n this.animationManager?.registerHighlight(id);\n }\n this.renderer.markDirty();\n }\n\n private clearHighlights(): void {\n this.highlightIds.clear();\n this.renderer.markDirty();\n }\n\n private matchesNode(node: Node, options: SearchFilterOptions): boolean {\n if (options.nodeType) {\n const typeName = node.typeName;\n const className = node.constructor?.name ?? '';\n if (options.nodeType !== typeName && options.nodeType !== className) {\n return false;\n }\n }\n if (options.styleClass && node.styleClass !== options.styleClass) {\n return false;\n }\n return !(options.predicate && !options.predicate(node));\n\n }\n\n private matchesEdge(edge: Edge, options: SearchFilterOptions): boolean {\n if (options.edgeType && edge.type !== options.edgeType) {\n return false;\n }\n if (options.styleClass && edge.styleClass !== options.styleClass) {\n return false;\n }\n return !(options.predicate && !options.predicate(edge));\n\n }\n\n private renderHighlights(ctx: CanvasRenderingContext2D): void {\n if (this.highlightIds.size === 0) {\n return;\n }\n ctx.save();\n ctx.globalAlpha = 1;\n\n for (const id of this.highlightIds) {\n const node = this.renderer.getNode(id);\n if (node && node.visible) {\n this.renderNodeHighlight(ctx, node, id === this.currentId);\n continue;\n }\n const edge = this.renderer.getEdge(id);\n if (edge && edge.visible) {\n this.renderEdgeHighlight(ctx, edge, id === this.currentId);\n }\n }\n\n ctx.restore();\n }\n\n private renderNodeHighlight(\n ctx: CanvasRenderingContext2D,\n node: Node,\n isCurrent: boolean\n ): void {\n const bounds = node.getBounds();\n const padding = this.options.highlightPadding;\n const color = isCurrent ? this.options.currentColor : this.options.highlightColor;\n const width = isCurrent ? this.options.currentLineWidth : this.options.highlightLineWidth;\n ctx.strokeStyle = color;\n ctx.lineWidth = width;\n ctx.strokeRect(\n bounds.x - padding,\n bounds.y - padding,\n bounds.width + padding * 2,\n bounds.height + padding * 2\n );\n }\n\n private renderEdgeHighlight(\n ctx: CanvasRenderingContext2D,\n edge: Edge,\n isCurrent: boolean\n ): void {\n const path = edge.path;\n if (path.length < 2) {\n return;\n }\n const color = isCurrent ? this.options.currentColor : this.options.highlightColor;\n const width = isCurrent ? this.options.currentLineWidth : this.options.highlightLineWidth;\n ctx.strokeStyle = color;\n ctx.lineWidth = width;\n ctx.setLineDash([]);\n ctx.beginPath();\n ctx.moveTo(path[0]!.x, path[0]!.y);\n if (edge.type === 'bezier' && path.length >= 4) {\n for (let i = 1; i + 2 < path.length; i += 3) {\n const cp1 = path[i]!;\n const cp2 = path[i + 1]!;\n const end = path[i + 2]!;\n ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);\n }\n } else {\n for (let i = 1; i < path.length; i++) {\n ctx.lineTo(path[i]!.x, path[i]!.y);\n }\n }\n ctx.stroke();\n }\n}\n","import type { Point, PortPosition, PortType } from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport type { Node } from './Node';\n\nlet portIdCounter = 1;\n\n/**\n * Generate a unique port ID\n */\nfunction generatePortId(): string {\n return `port_${portIdCounter++}`;\n}\n\n/**\n * Reset port ID counter (for testing)\n */\nexport function resetPortIdCounter(): void {\n portIdCounter = 1;\n}\n\nexport interface PortOptions {\n id?: string;\n type: PortType;\n position: PortPosition | Point;\n radius?: number;\n color?: string;\n hoverColor?: string;\n styleClass?: string;\n}\n\n/**\n * Connection port on a node\n */\nexport class Port {\n readonly id: string;\n readonly type: PortType;\n private _styleClass?: string;\n private _position: PortPosition | Point;\n private _radius: number;\n private _color: string;\n private _hoverColor: string;\n private _hovered = false;\n private _hasCustomRadius: boolean;\n private _hasCustomColor: boolean;\n private _hasCustomHoverColor: boolean;\n\n constructor(options: PortOptions) {\n this.id = options.id ?? generatePortId();\n this.type = options.type;\n this._position = options.position;\n this._radius = options.radius ?? 6;\n this._color = options.color ?? '#666666';\n this._hoverColor = options.hoverColor ?? '#3b82f6';\n this._styleClass = options.styleClass;\n this._hasCustomRadius = options.radius !== undefined;\n this._hasCustomColor = options.color !== undefined;\n this._hasCustomHoverColor = options.hoverColor !== undefined;\n }\n\n /**\n * Port position (relative or absolute)\n */\n get position(): PortPosition | Point {\n return this._position;\n }\n\n set position(value: PortPosition | Point) {\n this._position = value;\n }\n\n /**\n * Style class name for StyleManager\n */\n get styleClass(): string | undefined {\n return this._styleClass;\n }\n\n set styleClass(value: string | undefined) {\n this._styleClass = value;\n }\n\n /**\n * Port radius for rendering and hit testing\n */\n get radius(): number {\n return this._radius;\n }\n\n set radius(value: number) {\n this._radius = value;\n }\n\n /**\n * Port color\n */\n get color(): string {\n return this._hovered ? this._hoverColor : this._color;\n }\n\n set color(value: string) {\n this._color = value;\n }\n\n /**\n * Whether the port is hovered\n */\n get hovered(): boolean {\n return this._hovered;\n }\n\n set hovered(value: boolean) {\n this._hovered = value;\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const style = styleManager.getPortStyle(this._hovered, this._styleClass);\n if (!this._hasCustomRadius) {\n this._radius = style.radius;\n }\n if (!this._hasCustomColor) {\n this._color = style.color;\n }\n if (!this._hasCustomHoverColor) {\n this._hoverColor = style.color;\n }\n }\n\n /**\n * Get the absolute position of this port relative to a node\n */\n getAbsolutePosition(node: Node): Point {\n if (typeof this._position === 'object') {\n // Custom position relative to node\n return {\n x: node.x + this._position.x,\n y: node.y + this._position.y,\n };\n }\n\n // Named position\n const bounds = node.getBounds();\n const centerX = bounds.x + bounds.width / 2;\n const centerY = bounds.y + bounds.height / 2;\n\n switch (this._position) {\n case 'top':\n return { x: centerX, y: bounds.y };\n case 'bottom':\n return { x: centerX, y: bounds.y + bounds.height };\n case 'left':\n return { x: bounds.x, y: centerY };\n case 'right':\n return { x: bounds.x + bounds.width, y: centerY };\n }\n }\n\n /**\n * Test if a point hits this port\n */\n hitTest(point: Point, node: Node): boolean {\n const pos = this.getAbsolutePosition(node);\n const dx = point.x - pos.x;\n const dy = point.y - pos.y;\n // Use larger hit area for easier interaction (2x visual radius)\n const hitRadius = this._radius * 2;\n return dx * dx + dy * dy <= hitRadius * hitRadius;\n }\n\n /**\n * Render the port\n */\n render(ctx: CanvasRenderingContext2D, node: Node): void {\n const pos = this.getAbsolutePosition(node);\n\n ctx.beginPath();\n ctx.arc(pos.x, pos.y, this._radius, 0, Math.PI * 2);\n ctx.fillStyle = this.color;\n ctx.fill();\n\n // Draw outline\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2;\n ctx.stroke();\n }\n}\n","/**\n * LRU (Least Recently Used) cache implementation\n * Automatically evicts least recently used items when capacity is reached\n */\nexport class LRUCache<K, V> {\n private readonly cache = new Map<K, V>();\n private readonly maxSize: number;\n\n constructor(maxSize: number) {\n if (maxSize <= 0) {\n throw new Error('LRUCache maxSize must be positive');\n }\n this.maxSize = maxSize;\n }\n\n /**\n * Get value by key\n * Returns undefined if key doesn't exist\n */\n get(key: K): V | undefined {\n const value = this.cache.get(key);\n if (value === undefined) {\n return undefined;\n }\n // Move to end (most recently used)\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n\n /**\n * Set key-value pair\n * Evicts least recently used item if at capacity\n */\n set(key: K, value: V): void {\n // Delete existing entry to move it to end\n if (this.cache.has(key)) {\n this.cache.delete(key);\n } else if (this.cache.size >= this.maxSize) {\n // Evict least recently used (first item)\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== undefined) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n\n /**\n * Check if key exists in cache\n */\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n /**\n * Delete key from cache\n */\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get current size\n */\n size(): number {\n return this.cache.size;\n }\n\n /**\n * Get maximum capacity\n */\n capacity(): number {\n return this.maxSize;\n }\n}\n","import type { Bounds } from '@/types';\nimport { LRUCache } from '@/utils/LRUCache';\n\nexport type NodeImageCornerPlacement = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\nexport type NodeImageEdgePlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport function isCornerPlacement(\n placement: NodeImagePlacement\n): placement is NodeImageCornerPlacement {\n return (\n placement === 'top-left' ||\n placement === 'top-right' ||\n placement === 'bottom-left' ||\n placement === 'bottom-right'\n );\n}\n\nexport type NodeImageFit = 'contain' | 'cover' | 'stretch' | 'none';\nexport type NodeImagePlacement =\n | 'center'\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-left'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-right';\n\nexport interface NodeImageOptions {\n source: string | HTMLImageElement;\n width?: number;\n height?: number;\n fit?: NodeImageFit;\n placement?: NodeImagePlacement;\n scaleWithBounds?: boolean;\n padding?: number;\n margin?: number;\n gap?: number;\n opacity?: number;\n strokeColor?: string;\n fillColor?: string;\n align?: 'left' | 'center' | 'right';\n verticalAlign?: 'top' | 'center' | 'bottom';\n offsetX?: number;\n offsetY?: number;\n}\n\n// LRU cache for fetched SVG content (limit 100 entries to prevent memory growth)\nconst svgTextCache = new LRUCache<string, Promise<string>>(100);\n\nfunction styleSetColor(style: string, key: 'stroke' | 'fill', color: string): string {\n const hasKey = new RegExp(`${key}\\\\s*:`).test(style);\n if (hasKey) {\n return style.replace(new RegExp(`${key}\\\\s*:[^;]+`), `${key}:${color}`);\n }\n const suffix = style.trim().endsWith(';') || style.trim() === '' ? '' : ';';\n return `${style}${suffix}${key}:${color};`;\n}\n\nfunction tintSvg(svgText: string, strokeColor?: string, fillColor?: string): string {\n if (!strokeColor && !fillColor) return svgText;\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(svgText, 'image/svg+xml');\n const root = doc.documentElement;\n if (!root || root.nodeName.toLowerCase() === 'parsererror') {\n return svgText;\n }\n\n const all = [root, ...Array.from(root.querySelectorAll('*'))] as Element[];\n for (const el of all) {\n const stroke = el.getAttribute('stroke');\n if (strokeColor && stroke !== null && stroke.toLowerCase() !== 'none') {\n el.setAttribute('stroke', strokeColor);\n }\n const fill = el.getAttribute('fill');\n if (fillColor && fill !== null && fill.toLowerCase() !== 'none') {\n el.setAttribute('fill', fillColor);\n }\n const style = el.getAttribute('style');\n if (style) {\n let next = style;\n if (strokeColor && /stroke\\s*:\\s*(?!none)/.test(style)) {\n next = styleSetColor(next, 'stroke', strokeColor);\n }\n if (fillColor && /fill\\s*:\\s*(?!none)/.test(style)) {\n next = styleSetColor(next, 'fill', fillColor);\n }\n if (next !== style) {\n el.setAttribute('style', next);\n }\n }\n }\n\n return new XMLSerializer().serializeToString(root);\n}\n\nfunction isSvgMarkup(value: string): boolean {\n const trimmed = value.trim().toLowerCase();\n return trimmed.startsWith('<svg') || trimmed.includes('<svg');\n}\n\nfunction svgToDataUrl(svg: string): string {\n const encoded = encodeURIComponent(svg)\n .replace(/%0A/g, '')\n .replace(/%0D/g, '')\n .replace(/%09/g, ' ')\n .replace(/%20/g, ' ');\n return `data:image/svg+xml;utf8,${encoded}`;\n}\n\n/**\n * Image helper for node rendering (supports images and inline SVG).\n */\nexport class NodeImage {\n private _options: NodeImageOptions;\n private _image: HTMLImageElement;\n private _loaded = false;\n private _naturalWidth = 0;\n private _naturalHeight = 0;\n private _onChange?: () => void;\n private _sourceVersion = 0;\n\n constructor(options: NodeImageOptions, onChange?: () => void) {\n this._options = { ...options };\n this._onChange = onChange;\n this._image = this.resolveImage(options.source);\n this.attachHandlers();\n void this.applySource(options.source);\n }\n\n get options(): NodeImageOptions {\n return this._options;\n }\n\n set options(value: NodeImageOptions) {\n this._options = { ...value };\n this.setSource(value.source);\n }\n\n get placement(): NodeImagePlacement {\n return this._options.placement ?? 'center';\n }\n\n get gap(): number {\n return this._options.gap ?? 6;\n }\n\n setSource(source: string | HTMLImageElement): void {\n this._loaded = false;\n this._naturalWidth = 0;\n this._naturalHeight = 0;\n this._image = this.resolveImage(source);\n this.attachHandlers();\n void this.applySource(source);\n this._onChange?.();\n }\n\n render(ctx: CanvasRenderingContext2D, bounds: Bounds): void {\n if (!this._loaded) {\n return;\n }\n\n const padding = this._options.padding ?? 8;\n const margin = Math.max(0, this._options.margin ?? 0);\n const fit = this._options.fit ?? 'none';\n const scaleWithBounds = this._options.scaleWithBounds ?? false;\n const opacity = this._options.opacity ?? 1;\n const align = this._options.align ?? 'center';\n const verticalAlign = this._options.verticalAlign ?? 'center';\n const offsetX = this._options.offsetX ?? 0;\n const offsetY = this._options.offsetY ?? 0;\n\n const innerBounds: Bounds = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n const availableWidth = Math.max(0, innerBounds.width - padding * 2);\n const availableHeight = Math.max(0, innerBounds.height - padding * 2);\n\n let drawWidth = this._options.width ?? this._naturalWidth;\n let drawHeight = this._options.height ?? this._naturalHeight;\n\n if (scaleWithBounds) {\n if (fit === 'contain' || fit === 'cover') {\n const scaleX = availableWidth / this._naturalWidth;\n const scaleY = availableHeight / this._naturalHeight;\n const scale = fit === 'contain' ? Math.min(scaleX, scaleY) : Math.max(scaleX, scaleY);\n drawWidth = this._naturalWidth * scale;\n drawHeight = this._naturalHeight * scale;\n } else if (fit === 'stretch') {\n drawWidth = availableWidth;\n drawHeight = availableHeight;\n }\n }\n\n const maxWidth = Math.max(0, availableWidth);\n const maxHeight = Math.max(0, availableHeight);\n drawWidth = Math.min(drawWidth, maxWidth);\n drawHeight = Math.min(drawHeight, maxHeight);\n\n let x = innerBounds.x + padding;\n let y = innerBounds.y + padding;\n\n if (align === 'center') {\n x = innerBounds.x + (innerBounds.width - drawWidth) / 2;\n } else if (align === 'right') {\n x = innerBounds.x + innerBounds.width - drawWidth - padding;\n }\n\n if (verticalAlign === 'center') {\n y = innerBounds.y + (innerBounds.height - drawHeight) / 2;\n } else if (verticalAlign === 'bottom') {\n y = innerBounds.y + innerBounds.height - drawHeight - padding;\n }\n\n ctx.save();\n ctx.globalAlpha = opacity;\n ctx.drawImage(this._image, x + offsetX, y + offsetY, drawWidth, drawHeight);\n ctx.restore();\n }\n\n getSize(): { width: number; height: number } {\n const width = this._options.width ?? this._naturalWidth;\n const height = this._options.height ?? this._naturalHeight;\n return { width, height };\n }\n\n private resolveImage(source: string | HTMLImageElement): HTMLImageElement {\n if (source instanceof HTMLImageElement) {\n return source;\n }\n\n const img = new Image();\n img.decoding = 'async';\n return img;\n }\n\n private async applySource(source: string | HTMLImageElement): Promise<void> {\n if (source instanceof HTMLImageElement) {\n return;\n }\n const version = ++this._sourceVersion;\n\n // Inline SVG markup source\n if (isSvgMarkup(source)) {\n const tinted = tintSvg(source, this._options.strokeColor, this._options.fillColor);\n if (version !== this._sourceVersion) return;\n this._image.src = svgToDataUrl(tinted);\n return;\n }\n\n // URL source with optional SVG tinting\n const shouldTint = !!this._options.strokeColor || !!this._options.fillColor;\n if (shouldTint && source.toLowerCase().endsWith('.svg')) {\n let svgPromise = svgTextCache.get(source);\n if (!svgPromise) {\n svgPromise = fetch(source).then((r) => (r.ok ? r.text() : ''));\n svgTextCache.set(source, svgPromise);\n }\n const svgText = await svgPromise;\n if (version !== this._sourceVersion) return;\n if (svgText) {\n const tinted = tintSvg(svgText, this._options.strokeColor, this._options.fillColor);\n this._image.src = svgToDataUrl(tinted);\n return;\n }\n }\n\n if (version !== this._sourceVersion) return;\n this._image.src = source;\n }\n\n private attachHandlers(): void {\n if (this._image.complete && this._image.naturalWidth > 0) {\n this._loaded = true;\n this._naturalWidth = this._image.naturalWidth;\n this._naturalHeight = this._image.naturalHeight;\n return;\n }\n\n this._image.onload = (): void => {\n this._loaded = true;\n this._naturalWidth = this._image.naturalWidth;\n this._naturalHeight = this._image.naturalHeight;\n this._onChange?.();\n };\n this._image.onerror = (): void => {\n this._loaded = false;\n this._onChange?.();\n };\n }\n}\n","import { Element, generateId } from './Element';\nimport { Port, type PortOptions } from './Port';\nimport { TextLabel, type TextLabelOptions } from './TextLabel';\nimport {\n NodeImage,\n type NodeImageOptions,\n type NodeImagePlacement,\n isCornerPlacement,\n} from './NodeImage';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport type { Bounds, LabelPlacement, NodeStyle, Point, Size } from '@/types';\nexport type { LabelPlacement } from '../types';\nimport { shallowEqual } from '@/utils/style';\nimport {\n DEFAULT_SELECTION_COLOR,\n NODE_HITBOX_PADDING,\n RESIZE_HANDLE_OFFSET,\n RESIZE_HANDLE_SIZE,\n} from '@/constants';\n\nexport interface NodeOptions {\n id?: string;\n x: number;\n y: number;\n width: number;\n height: number;\n style?: NodeStyle;\n styleClass?: string;\n label?: string | TextLabelOptions;\n labelPlacement?: LabelPlacement;\n icon?: NodeImageOptions;\n ports?: PortOptions[];\n showPortsAlways?: boolean;\n anchorPoints?: AnchorPointsConfig;\n resizeHandlesEnabled?: boolean;\n}\n\nexport type ResizeHandle = 'nw' | 'ne' | 'se' | 'sw';\nexport type AnchorId = `${'top' | 'right' | 'bottom' | 'left'}:${number}`;\n\n/**\n * Validate if a string is a valid AnchorId format\n */\nexport function isValidAnchorId(id: string): id is AnchorId {\n return /^(top|right|bottom|left):\\d+$/.test(id);\n}\n\nexport interface AnchorPointsConfig {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n}\n\nconst DEFAULT_NODE_STYLE: NodeStyle = {\n fillColor: '#ffffff',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 1,\n};\n\n/**\n * Abstract base class for diagram nodes\n */\nexport abstract class Node extends Element {\n protected _ports: Port[] = [];\n protected _label?: TextLabel;\n protected _icon?: NodeImage;\n protected _nodeStyle: NodeStyle;\n protected _showPortsAlways: boolean;\n protected _anchorPoints: Required<AnchorPointsConfig>;\n protected _defaultSize: Size;\n protected _labelPlacement: LabelPlacement;\n protected _resizeHandlesEnabled: boolean;\n private _attachToOutlineGetter?: () => boolean;\n private _anchorCache: { id: AnchorId; point: Point }[] | null = null;\n\n protected constructor(options: NodeOptions) {\n super({\n id: options.id ?? generateId('node'),\n x: options.x,\n y: options.y,\n width: options.width,\n height: options.height,\n style: options.style,\n styleClass: options.styleClass,\n });\n\n this._defaultSize = { width: options.width, height: options.height };\n this._nodeStyle = { ...DEFAULT_NODE_STYLE, ...options.style };\n this._showPortsAlways = options.showPortsAlways ?? false;\n this._anchorPoints = this.normalizeAnchorPoints(options.anchorPoints);\n this._labelPlacement = options.labelPlacement ?? 'auto';\n this._resizeHandlesEnabled = options.resizeHandlesEnabled ?? true;\n\n if (options.label !== undefined) {\n if (typeof options.label === 'string') {\n this._label = new TextLabel({\n text: options.label,\n onChange: (): void => this.markDirty(),\n });\n } else {\n this._label = new TextLabel({ ...options.label, onChange: (): void => this.markDirty() });\n }\n }\n\n if (options.icon !== undefined) {\n this._icon = new NodeImage(options.icon, () => this.markDirty());\n }\n\n if (options.ports !== undefined) {\n for (const portOptions of options.ports) {\n this.addPort(portOptions);\n }\n }\n }\n\n /**\n * Node style\n */\n override get style(): NodeStyle {\n return this._nodeStyle;\n }\n\n override set style(value: NodeStyle) {\n this._nodeStyle = { ...DEFAULT_NODE_STYLE, ...value };\n this._style = value;\n this.markDirty();\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getNodeStyle(this._state, this._styleClass);\n const mergedStyle = { ...baseStyle, ...this._style };\n if (!shallowEqual(this._nodeStyle, mergedStyle)) {\n this._nodeStyle = mergedStyle;\n this.markDirty();\n }\n\n if (this._label) {\n this._label.applyStyleManager(styleManager);\n }\n\n for (const port of this._ports) {\n port.applyStyleManager(styleManager);\n }\n }\n\n /**\n * Ports on this node\n */\n get ports(): readonly Port[] {\n return this._ports;\n }\n\n /**\n * Text label\n */\n get label(): TextLabel | undefined {\n return this._label;\n }\n\n set label(value: TextLabel | string | undefined) {\n if (value === undefined) {\n this._label = undefined;\n } else if (typeof value === 'string') {\n this._label = new TextLabel({ text: value, onChange: (): void => this.markDirty() });\n } else {\n this._label = value;\n this._label.setOnChange((): void => this.markDirty());\n }\n this.markDirty();\n }\n\n /**\n * Node icon/image\n */\n get icon(): NodeImage | undefined {\n return this._icon;\n }\n\n set icon(value: NodeImage | NodeImageOptions | undefined) {\n if (value === undefined) {\n this._icon = undefined;\n } else if (value instanceof NodeImage) {\n this._icon = value;\n } else {\n this._icon = new NodeImage(value, () => this.markDirty());\n }\n this.markDirty();\n }\n\n /**\n * Add a port to this node\n */\n addPort(options: PortOptions): Port {\n const port = new Port(options);\n this._ports.push(port);\n this.markDirty();\n return port;\n }\n\n /**\n * Remove a port by ID\n */\n removePort(portId: string): boolean {\n const index = this._ports.findIndex((p) => p.id === portId);\n if (index === -1) {\n return false;\n }\n this._ports.splice(index, 1);\n this.markDirty();\n return true;\n }\n\n /**\n * Get a port by ID\n */\n getPort(portId: string): Port | undefined {\n return this._ports.find((p) => p.id === portId);\n }\n\n /**\n * Get absolute position of a port\n */\n getPortPosition(portId: string): Point | undefined {\n const port = this.getPort(portId);\n if (port === undefined) {\n return undefined;\n }\n return port.getAbsolutePosition(this);\n }\n\n /**\n * Find port at a point\n */\n getPortAtPoint(point: Point): Port | undefined {\n for (const port of this._ports) {\n if (port.hitTest(point, this)) {\n return port;\n }\n }\n return undefined;\n }\n\n /**\n * Apply style to canvas context\n */\n protected applyStyle(ctx: CanvasRenderingContext2D): void {\n const style = this._nodeStyle;\n\n ctx.fillStyle = style.fillColor ?? '#ffffff';\n ctx.strokeStyle = style.strokeColor ?? '#333333';\n ctx.lineWidth = style.strokeWidth ?? 2;\n ctx.globalAlpha = style.opacity ?? 1;\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n }\n\n // Highlight for hover state only\n if (this._state === 'hover') {\n ctx.strokeStyle = '#6366f1';\n }\n }\n\n /**\n * Whether to always show ports\n */\n get showPortsAlways(): boolean {\n return this._showPortsAlways;\n }\n\n set showPortsAlways(value: boolean) {\n if (this._showPortsAlways !== value) {\n this._showPortsAlways = value;\n this.markDirty();\n }\n }\n\n /**\n * Mark this element as needing re-render and invalidate anchor cache\n */\n override markDirty(): void {\n super.markDirty();\n this.invalidateAnchorCache();\n }\n\n /**\n * Invalidate anchor cache\n */\n private invalidateAnchorCache(): void {\n this._anchorCache = null;\n }\n\n get resizeHandlesEnabled(): boolean {\n return this._resizeHandlesEnabled;\n }\n\n set resizeHandlesEnabled(value: boolean) {\n if (this._resizeHandlesEnabled !== value) {\n this._resizeHandlesEnabled = value;\n this.markDirty();\n }\n }\n\n /**\n * Anchor points configuration (per side)\n */\n get anchorPoints(): Required<AnchorPointsConfig> {\n return this._anchorPoints;\n }\n\n set anchorPoints(value: AnchorPointsConfig) {\n this._anchorPoints = this.normalizeAnchorPoints(value);\n this.markDirty();\n }\n\n /**\n * Label placement inside the node\n */\n get labelPlacement(): LabelPlacement {\n return this._labelPlacement;\n }\n\n set labelPlacement(value: LabelPlacement) {\n if (this._labelPlacement !== value) {\n this._labelPlacement = value;\n this.markDirty();\n }\n }\n\n /**\n * Default size (initial width/height)\n */\n get defaultSize(): Size {\n return { ...this._defaultSize };\n }\n\n /**\n * Set getter for attachToOutline (called by DiagramRenderer when node is added)\n */\n setAttachToOutlineGetter(getter: (() => boolean) | undefined): void {\n this._attachToOutlineGetter = getter;\n }\n\n /**\n * Render ports\n */\n protected renderPorts(ctx: CanvasRenderingContext2D): void {\n if (this._attachToOutlineGetter?.()) {\n return;\n }\n // Show ports when hovered, selected, dragging, or if showPortsAlways is set\n const shouldShow =\n this._showPortsAlways ||\n this._ports.some((port) => port.hovered) ||\n this._state === 'hover' ||\n this._state === 'selected' ||\n this._state === 'dragging';\n\n if (!shouldShow) {\n return;\n }\n\n for (const port of this._ports) {\n port.render(ctx, this);\n }\n }\n\n /**\n * Calculate layout for icon and label\n * Returns computed bounds for both elements\n */\n protected calculateContentLayout(\n bounds: Bounds,\n iconBoxSize?: Size,\n labelSize?: Size\n ): { iconBounds: Bounds; labelBounds: Bounds } {\n let iconBounds = bounds;\n let labelBounds = this.getLabelContainerBounds(bounds);\n\n if (this._icon && iconBoxSize) {\n iconBounds = this.getIconBounds(bounds, iconBoxSize, this._icon.placement);\n }\n\n if (\n this._icon &&\n this._label &&\n iconBoxSize &&\n labelSize &&\n this._labelPlacement === 'auto' &&\n this._icon.placement !== 'center'\n ) {\n const gap = this._icon.gap;\n const placement = this._icon.placement;\n\n if (isCornerPlacement(placement)) {\n iconBounds = this.getIconBounds(bounds, iconBoxSize, placement);\n labelBounds = this.getLabelContainerBounds(bounds);\n } else {\n const contentBounds = this.getLabelContainerBounds(bounds);\n switch (placement) {\n case 'top':\n iconBounds = {\n x: bounds.x,\n y: bounds.y,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n labelBounds = {\n x: contentBounds.x,\n y: contentBounds.y + iconBoxSize.height + gap,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n break;\n case 'bottom':\n iconBounds = {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n labelBounds = {\n x: contentBounds.x,\n y: contentBounds.y,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n break;\n case 'left':\n iconBounds = {\n x: bounds.x,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n labelBounds = {\n x: contentBounds.x + iconBoxSize.width + gap,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n break;\n case 'right':\n iconBounds = {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n labelBounds = {\n x: contentBounds.x,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n break;\n }\n }\n } else if (this._label && labelSize) {\n const autoBounds = this.getAutoLabelBounds(bounds, iconBoxSize);\n labelBounds = this.getLabelBounds(autoBounds, labelSize, this._labelPlacement);\n }\n\n return { iconBounds, labelBounds };\n }\n\n /**\n * Get label bounds and wrapped lines for SVG export. Replicates renderContents layout logic.\n * Returns the bounds passed to label.render() and the wrapped text lines, or null if no label.\n */\n getLabelBoundsForExport(\n ctx: CanvasRenderingContext2D\n ): { bounds: Bounds; lines: string[] } | null {\n if (!this._label) {\n return null;\n }\n\n const bounds = this.getBounds();\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n const autoBounds = this.getAutoLabelBounds(bounds, iconBoxSize);\n\n this._label.setAutoMaxWidth(autoBounds.width);\n const labelSize = this._label.measure(ctx);\n\n const { labelBounds } = this.calculateContentLayout(bounds, iconBoxSize, labelSize);\n\n const lines = this._label.getWrappedLines(ctx, Math.max(0, autoBounds.width));\n return { bounds: labelBounds, lines };\n }\n\n /**\n * Render label\n */\n protected renderLabel(ctx: CanvasRenderingContext2D, bounds: Bounds = this.getBounds()): void {\n if (this._label === undefined) {\n return;\n }\n\n const labelOpacity = this._label.style.opacity ?? 1;\n ctx.globalAlpha = labelOpacity;\n this._label.render(ctx, bounds);\n ctx.globalAlpha = 1;\n }\n\n /**\n * Get world position of label center.\n */\n getLabelPosition(): Point {\n const bounds = this.getBounds();\n const placement = this._labelPlacement === 'auto' ? 'center' : this._labelPlacement;\n\n switch (placement) {\n case 'top':\n return { x: bounds.x + bounds.width / 2, y: bounds.y };\n case 'bottom':\n return { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height };\n case 'left':\n return { x: bounds.x, y: bounds.y + bounds.height / 2 };\n case 'right':\n return { x: bounds.x + bounds.width, y: bounds.y + bounds.height / 2 };\n default:\n return { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height / 2 };\n }\n }\n\n /**\n * Render icon, label, and ports\n */\n protected renderContents(ctx: CanvasRenderingContext2D): void {\n // Reset dash settings so icon/label/ports render solid\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n\n let bounds = this.getBounds();\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n\n if (this._label) {\n this._label.setAutoMaxWidth(this.getAutoLabelBounds(bounds, iconBoxSize).width);\n }\n const labelSize = this._label ? this._label.measure(ctx) : undefined;\n\n if (labelSize || iconBoxSize) {\n this.ensureContentsFit(labelSize, iconBoxSize);\n // Re-measure after potential resize\n if (this._label && iconBoxSize) {\n bounds = this.getBounds();\n this._label.setAutoMaxWidth(this.getAutoLabelBounds(bounds, iconBoxSize).width);\n }\n }\n\n const { iconBounds, labelBounds } = this.calculateContentLayout(\n this.getBounds(),\n iconBoxSize,\n labelSize\n );\n\n if (this._icon) {\n this._icon.render(ctx, iconBounds);\n }\n\n this.renderLabel(ctx, labelBounds);\n this.renderPorts(ctx);\n }\n\n /**\n * Minimal size required to fit current contents\n */\n getContentMinSize(ctx: CanvasRenderingContext2D): Size {\n const bounds = this.getBounds();\n const labelSize = this._label ? this._label.measure(ctx) : undefined;\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n return this.calculateContentMinSize(labelSize, iconBoxSize, bounds);\n }\n\n /**\n * Render resize handles when selected\n */\n renderResizeHandles(ctx: CanvasRenderingContext2D): void {\n if (this._state !== 'selected' || !this._resizeHandlesEnabled) {\n return;\n }\n\n const bounds = this.getBounds();\n const offset = RESIZE_HANDLE_OFFSET;\n const size = RESIZE_HANDLE_SIZE;\n const half = size / 2;\n\n ctx.save();\n\n // Draw dashed selection rectangle\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 1;\n ctx.setLineDash([4, 4]);\n ctx.strokeRect(\n bounds.x - offset,\n bounds.y - offset,\n bounds.width + offset * 2,\n bounds.height + offset * 2\n );\n\n // Draw resize handles\n ctx.fillStyle = '#ffffff';\n ctx.strokeStyle = DEFAULT_SELECTION_COLOR;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([]);\n\n for (const handle of this.getResizeHandlePositions()) {\n ctx.beginPath();\n ctx.rect(handle.x - half, handle.y - half, size, size);\n ctx.fill();\n ctx.stroke();\n }\n\n ctx.restore();\n }\n\n /**\n * Hit test a resize handle\n */\n hitTestResizeHandle(point: Point): ResizeHandle | null {\n if (this._state !== 'selected') {\n return null;\n }\n\n const size = RESIZE_HANDLE_SIZE;\n const half = size / 2;\n\n for (const handle of this.getResizeHandlePositions()) {\n if (\n point.x >= handle.x - half &&\n point.x <= handle.x + half &&\n point.y >= handle.y - half &&\n point.y <= handle.y + half\n ) {\n return handle.type;\n }\n }\n\n return null;\n }\n\n /**\n * Default bounding box hit test\n */\n hitTest(point: Point): boolean {\n const bounds = this.getBounds();\n const padding = NODE_HITBOX_PADDING;\n return (\n point.x >= bounds.x - padding &&\n point.x <= bounds.x + bounds.width + padding &&\n point.y >= bounds.y - padding &&\n point.y <= bounds.y + bounds.height + padding\n );\n }\n\n /**\n * Get a connection point on the node boundary toward a target point,\n * snapped to nearest anchor point on the contour.\n */\n getConnectionPoint(target: Point): Point {\n const anchors = this.getAnchorsOnOutline();\n if (anchors.length === 0) {\n return this.getOutlinePointToward(target);\n }\n\n let closest = anchors[0]!;\n let minDist = (target.x - closest.point.x) ** 2 + (target.y - closest.point.y) ** 2;\n\n for (let i = 1; i < anchors.length; i++) {\n const anchor = anchors[i]!;\n const dist = (target.x - anchor.point.x) ** 2 + (target.y - anchor.point.y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n closest = anchor;\n }\n }\n\n return closest.point;\n }\n\n /**\n * Get all anchors on the outline\n */\n getAnchors(): { id: AnchorId; point: Point }[] {\n return this.getAnchorsOnOutline();\n }\n\n /**\n * Get all anchor points on the outline\n */\n getAnchorPoints(): Point[] {\n return this.getAnchorsOnOutline().map((anchor) => anchor.point);\n }\n\n /**\n * Get anchor IDs for sides that have ports\n */\n getPortAnchorIds(): string[] {\n const portSides = new Set<string>();\n for (const port of this._ports) {\n if (typeof port.position === 'string') {\n portSides.add(port.position);\n }\n }\n const anchors = this.getAnchorsOnOutline();\n return anchors\n .filter((anchor) => {\n const side = anchor.id.split(':')[0];\n return side && portSides.has(side);\n })\n .map((anchor) => anchor.id);\n }\n\n /**\n * Get nearest anchor that belongs to a port side\n */\n getNearestPortAnchor(target: Point): { id: AnchorId; point: Point } | null {\n const portAnchorIds = this.getPortAnchorIds();\n if (portAnchorIds.length === 0) {\n return null;\n }\n const anchors = this.getAnchorsOnOutline().filter((anchor) =>\n portAnchorIds.includes(anchor.id)\n );\n if (anchors.length === 0) {\n return null;\n }\n\n let closest = anchors[0]!;\n let minDist = (target.x - closest.point.x) ** 2 + (target.y - closest.point.y) ** 2;\n\n for (let i = 1; i < anchors.length; i++) {\n const anchor = anchors[i]!;\n const dist = (target.x - anchor.point.x) ** 2 + (target.y - anchor.point.y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n closest = anchor;\n }\n }\n\n return closest;\n }\n\n /**\n * Get nearest anchor to a target point\n */\n getNearestAnchor(target: Point): { id: AnchorId; point: Point } | null {\n const anchors = this.getAnchorsOnOutline();\n if (anchors.length === 0) {\n return null;\n }\n\n let closest = anchors[0]!;\n let minDist = (target.x - closest.point.x) ** 2 + (target.y - closest.point.y) ** 2;\n\n for (let i = 1; i < anchors.length; i++) {\n const anchor = anchors[i]!;\n const dist = (target.x - anchor.point.x) ** 2 + (target.y - anchor.point.y) ** 2;\n if (dist < minDist) {\n minDist = dist;\n closest = anchor;\n }\n }\n\n return closest;\n }\n\n /**\n * Get anchor point by id\n */\n getAnchorPointById(anchorId: string): Point | null {\n if (!isValidAnchorId(anchorId)) {\n return null;\n }\n const anchors = this.getAnchorsOnOutline();\n const match = anchors.find((anchor) => anchor.id === anchorId);\n return match?.point ?? null;\n }\n\n /**\n * Get shape-specific bounds (can be overridden for non-rectangular shapes)\n */\n override getBounds(): Bounds {\n return {\n x: this._x,\n y: this._y,\n width: this._width,\n height: this._height,\n };\n }\n\n /**\n * Get the type name of this node\n */\n abstract get typeName(): string;\n\n /**\n * Get point on outline at normalized param (0-1 along perimeter).\n * Base implementation uses rectangular outline. Override for non-rectangular shapes.\n */\n getConnectionPointAtOutlineParam(param: number): Point {\n const bounds = this.getBounds();\n const { x, y, width: w, height: h } = bounds;\n const perimeter = 2 * (w + h);\n let s = (((param % 1) + 1) % 1) * perimeter;\n\n if (s < w) return { x: x + s, y };\n s -= w;\n if (s < h) return { x: x + w, y: y + s };\n s -= h;\n if (s < w) return { x: x + w - s, y: y + h };\n s -= w;\n return { x, y: y + h - s };\n }\n\n /**\n * Get closest point on outline and its param (0-1).\n * Base implementation uses rectangular outline. Override for non-rectangular shapes.\n */\n getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const bounds = this.getBounds();\n const { x, y, width: w, height: h } = bounds;\n const P = 2 * (w + h);\n\n const projectSegment = (\n ax: number,\n ay: number,\n bx: number,\n by: number,\n segLen: number,\n segStartParam: number\n ): { point: Point; param: number; distSq: number } => {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n let t = lenSq > 0 ? ((target.x - ax) * dx + (target.y - ay) * dy) / lenSq : 0;\n t = Math.max(0, Math.min(1, t));\n const px = ax + t * dx;\n const py = ay + t * dy;\n const distSq = (target.x - px) ** 2 + (target.y - py) ** 2;\n const param = segStartParam + (t * segLen) / P;\n return { point: { x: px, y: py }, param, distSq };\n };\n\n let best = projectSegment(x, y, x + w, y, w, 0);\n let r = projectSegment(x + w, y, x + w, y + h, h, w / P);\n if (r.distSq < best.distSq) best = r;\n r = projectSegment(x + w, y + h, x, y + h, w, (w + h) / P);\n if (r.distSq < best.distSq) best = r;\n r = projectSegment(x, y + h, x, y, h, (2 * w + h) / P);\n if (r.distSq < best.distSq) best = r;\n\n return { point: best.point, param: best.param };\n }\n\n /**\n * Get intersection point on the shape outline toward the target.\n * Override for non-rectangular shapes.\n */\n protected getOutlinePointToward(target: Point): Point {\n const bounds = this.getBounds();\n const center = this.getCenter();\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n\n if (dx === 0 && dy === 0) {\n return center;\n }\n\n const halfW = bounds.width / 2;\n const halfH = bounds.height / 2;\n\n const scaleX = halfW / Math.abs(dx);\n const scaleY = halfH / Math.abs(dy);\n const scale = Math.min(scaleX, scaleY);\n\n return {\n x: center.x + dx * scale,\n y: center.y + dy * scale,\n };\n }\n\n private getResizeHandlePositions(\n offset = RESIZE_HANDLE_OFFSET\n ): { type: ResizeHandle; x: number; y: number }[] {\n const { x, y, width, height } = this.getBounds();\n\n return [\n { type: 'nw', x: x - offset, y: y - offset },\n { type: 'ne', x: x + width + offset, y: y - offset },\n { type: 'se', x: x + width + offset, y: y + height + offset },\n { type: 'sw', x: x - offset, y: y + height + offset },\n ];\n }\n\n private ensureContentsFit(labelSize?: Size, iconBoxSize?: Size): void {\n const bounds = this.getBounds();\n const minSize = this.calculateContentMinSize(labelSize, iconBoxSize, bounds);\n\n if (minSize.width > bounds.width) {\n this.width = minSize.width;\n }\n if (minSize.height > bounds.height) {\n this.height = minSize.height;\n }\n }\n\n private calculateContentMinSize(\n labelSize: Size | undefined,\n iconBoxSize: Size | undefined,\n bounds: Bounds\n ): Size {\n let minWidth = 0;\n let minHeight = 0;\n\n const labelContainer = this.getLabelContainerBounds(bounds);\n const widthFactor = labelContainer.width > 0 ? bounds.width / labelContainer.width : 1;\n const heightFactor = labelContainer.height > 0 ? bounds.height / labelContainer.height : 1;\n\n if (labelSize) {\n minWidth = Math.max(minWidth, labelSize.width * widthFactor);\n minHeight = Math.max(minHeight, labelSize.height * heightFactor);\n }\n\n if (iconBoxSize) {\n minWidth = Math.max(minWidth, iconBoxSize.width);\n minHeight = Math.max(minHeight, iconBoxSize.height);\n }\n\n if (labelSize && iconBoxSize && this._icon) {\n const gap = this._icon.gap;\n const labelPlacement = this._labelPlacement === 'auto' ? 'center' : this._labelPlacement;\n const iconPlacement = this._icon.placement;\n\n if (this._labelPlacement === 'auto' && iconPlacement !== 'center') {\n if (isCornerPlacement(iconPlacement)) {\n // For corner placements, just ensure both fit (no stacking)\n minWidth = Math.max(minWidth, iconBoxSize.width, labelSize.width);\n minHeight = Math.max(minHeight, iconBoxSize.height, labelSize.height);\n } else if (iconPlacement === 'top' || iconPlacement === 'bottom') {\n minHeight = Math.max(minHeight, iconBoxSize.height + gap + labelSize.height);\n minWidth = Math.max(minWidth, iconBoxSize.width, labelSize.width);\n } else if (iconPlacement === 'left' || iconPlacement === 'right') {\n minWidth = Math.max(minWidth, iconBoxSize.width + gap + labelSize.width);\n minHeight = Math.max(minHeight, iconBoxSize.height, labelSize.height);\n }\n } else {\n const labelHorizontal = labelPlacement === 'left' || labelPlacement === 'right';\n const labelVertical = labelPlacement === 'top' || labelPlacement === 'bottom';\n const iconHorizontal = iconPlacement === 'left' || iconPlacement === 'right';\n const iconVertical = iconPlacement === 'top' || iconPlacement === 'bottom';\n const labelSharesIconAxis =\n (iconHorizontal && (labelPlacement === 'center' || labelPlacement === iconPlacement)) ||\n (iconVertical && (labelPlacement === 'center' || labelPlacement === iconPlacement));\n\n if (labelHorizontal && iconHorizontal && labelPlacement !== iconPlacement) {\n minWidth = Math.max(minWidth, iconBoxSize.width + gap + labelSize.width);\n }\n if (labelVertical && iconVertical && labelPlacement !== iconPlacement) {\n minHeight = Math.max(minHeight, iconBoxSize.height + gap + labelSize.height);\n }\n if (labelSharesIconAxis) {\n if (iconHorizontal) {\n minWidth = Math.max(minWidth, iconBoxSize.width + gap + labelSize.width);\n }\n if (iconVertical) {\n minHeight = Math.max(minHeight, iconBoxSize.height + gap + labelSize.height);\n }\n }\n }\n }\n\n return { width: minWidth, height: minHeight };\n }\n\n protected getLabelContainerBounds(bounds: Bounds): Bounds {\n return bounds;\n }\n\n private getAutoLabelBounds(bounds: Bounds, iconBoxSize?: Size): Bounds {\n const contentBounds = this.getLabelContainerBounds(bounds);\n if (!this._icon || !iconBoxSize || this._icon.placement === 'center') {\n return contentBounds;\n }\n\n const gap = this._icon.gap;\n if (isCornerPlacement(this._icon.placement)) {\n return contentBounds;\n }\n\n switch (this._icon.placement) {\n case 'left':\n return {\n x: contentBounds.x + iconBoxSize.width + gap,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n case 'right':\n return {\n x: contentBounds.x,\n y: contentBounds.y,\n width: Math.max(0, contentBounds.width - iconBoxSize.width - gap),\n height: contentBounds.height,\n };\n case 'top':\n return {\n x: contentBounds.x,\n y: contentBounds.y + iconBoxSize.height + gap,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n case 'bottom':\n return {\n x: contentBounds.x,\n y: contentBounds.y,\n width: contentBounds.width,\n height: Math.max(0, contentBounds.height - iconBoxSize.height - gap),\n };\n default:\n return contentBounds;\n }\n }\n\n private getLabelBounds(bounds: Bounds, labelSize: Size, placement: LabelPlacement): Bounds {\n const normalizedPlacement = placement === 'auto' ? 'center' : placement;\n const width = Math.min(labelSize.width, bounds.width);\n const height = Math.min(labelSize.height, bounds.height);\n\n let x = bounds.x + (bounds.width - width) / 2;\n let y = bounds.y + (bounds.height - height) / 2;\n\n switch (normalizedPlacement) {\n case 'top':\n y = bounds.y;\n break;\n case 'bottom':\n y = bounds.y + bounds.height - height;\n break;\n case 'left':\n x = bounds.x;\n break;\n case 'right':\n x = bounds.x + bounds.width - width;\n break;\n default:\n break;\n }\n\n return { x, y, width, height };\n }\n\n private getIconBoxSize(): Size | undefined {\n if (!this._icon) {\n return undefined;\n }\n\n const { width, height } = this._icon.getSize();\n if (width <= 0 || height <= 0) {\n return undefined;\n }\n\n const padding = this._icon.options.padding ?? 8;\n const margin = Math.max(0, this._icon.options.margin ?? 0);\n return {\n width: width + padding * 2 + margin * 2,\n height: height + padding * 2 + margin * 2,\n };\n }\n\n private getIconBounds(bounds: Bounds, iconBoxSize: Size, placement: NodeImagePlacement): Bounds {\n switch (placement) {\n case 'top':\n return {\n x: bounds.x,\n y: bounds.y,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n case 'bottom':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n case 'left':\n return {\n x: bounds.x,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n case 'right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n case 'top-left':\n return {\n x: bounds.x,\n y: bounds.y,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'top-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-left':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n default:\n return bounds;\n }\n }\n\n private normalizeAnchorPoints(config?: AnchorPointsConfig): Required<AnchorPointsConfig> {\n const normalize = (value: number | undefined): number => {\n if (value === undefined) return 1;\n if (!Number.isFinite(value)) return 1;\n return Math.max(0, Math.floor(value));\n };\n\n return {\n top: normalize(config?.top),\n right: normalize(config?.right),\n bottom: normalize(config?.bottom),\n left: normalize(config?.left),\n };\n }\n\n private getAnchorsOnOutline(): { id: AnchorId; point: Point }[] {\n if (this._anchorCache !== null) {\n return this._anchorCache;\n }\n\n const { top, right, bottom, left } = this._anchorPoints;\n const bounds = this.getBounds();\n const anchors: { id: AnchorId; point: Point }[] = [];\n\n const addPoints = (\n side: 'top' | 'right' | 'bottom' | 'left',\n count: number,\n cb: (t: number) => Point\n ): void => {\n if (count <= 0) return;\n for (let i = 0; i < count; i++) {\n const t = (i + 1) / (count + 1);\n const id: AnchorId = `${side}:${i}`;\n anchors.push({ id, point: cb(t) });\n }\n };\n\n addPoints('top', top, (t) => ({ x: bounds.x + bounds.width * t, y: bounds.y }));\n addPoints('bottom', bottom, (t) => ({\n x: bounds.x + bounds.width * t,\n y: bounds.y + bounds.height,\n }));\n addPoints('left', left, (t) => ({ x: bounds.x, y: bounds.y + bounds.height * t }));\n addPoints('right', right, (t) => ({\n x: bounds.x + bounds.width,\n y: bounds.y + bounds.height * t,\n }));\n\n if (anchors.length === 0) {\n this._anchorCache = [];\n return [];\n }\n\n const result = anchors.map((anchor) => ({\n id: anchor.id,\n point: this.getOutlinePointToward(anchor.point),\n }));\n this._anchorCache = result;\n return result;\n }\n}\n","import { Element, generateId } from './Element';\nimport type { Node } from './Node';\nimport type { Bounds, ElementStyle, Point } from '@/types';\nimport type { StyleManager } from '@/styles/StyleManager';\nimport { shallowEqual } from '@/utils/style';\nimport { pointInRect } from '@/utils/geometry';\n\nexport interface GroupOptions {\n id?: string;\n style?: ElementStyle;\n styleClass?: string;\n label?: string;\n padding?: number;\n}\n\nconst DEFAULT_GROUP_STYLE: ElementStyle = {\n fillColor: 'rgba(200, 200, 200, 0.2)',\n strokeColor: '#999999',\n strokeWidth: 1,\n lineDash: [8, 4],\n opacity: 1,\n};\n\n/**\n * Container for grouping nodes\n */\nexport class Group extends Element {\n private _children: (Node | Group)[] = [];\n private _label?: string;\n private _padding: number;\n private _groupStyle: ElementStyle;\n\n constructor(options: GroupOptions = {}) {\n super({\n id: options.id ?? generateId('group'),\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n style: options.style,\n styleClass: options.styleClass,\n });\n\n this._groupStyle = { ...DEFAULT_GROUP_STYLE, ...options.style };\n this._label = options.label;\n this._padding = options.padding ?? 20;\n }\n\n /**\n * Children of this group\n */\n get children(): readonly (Node | Group)[] {\n return this._children;\n }\n\n /**\n * Group label\n */\n get label(): string | undefined {\n return this._label;\n }\n\n set label(value: string | undefined) {\n this._label = value;\n this.markDirty();\n }\n\n /**\n * Padding around children\n */\n get padding(): number {\n return this._padding;\n }\n\n set padding(value: number) {\n if (this._padding !== value) {\n this._padding = value;\n this.recalculateBounds();\n }\n }\n\n /**\n * Group style\n */\n override get style(): ElementStyle {\n return this._groupStyle;\n }\n\n override set style(value: ElementStyle) {\n this._groupStyle = { ...DEFAULT_GROUP_STYLE, ...value };\n this._style = value;\n this.markDirty();\n }\n\n applyStyleManager(styleManager: StyleManager): void {\n const baseStyle = styleManager.getGroupStyle(false, this._styleClass);\n const mergedStyle = { ...baseStyle, ...this._style };\n if (!shallowEqual(this._groupStyle, mergedStyle)) {\n this._groupStyle = mergedStyle;\n this.markDirty();\n }\n }\n\n /**\n * Add a child to this group\n */\n addChild(child: Node | Group): void {\n if (!this._children.includes(child)) {\n this._children.push(child);\n this.recalculateBounds();\n }\n }\n\n /**\n * Remove a child from this group\n */\n removeChild(childId: string): boolean {\n const index = this._children.findIndex((c) => c.id === childId);\n if (index === -1) {\n return false;\n }\n this._children.splice(index, 1);\n this.recalculateBounds();\n return true;\n }\n\n /**\n * Check if a child is in this group (recursive)\n */\n hasChild(childId: string): boolean {\n for (const child of this._children) {\n if (child.id === childId) {\n return true;\n }\n if (child instanceof Group && child.hasChild(childId)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Get all nested children (flattened)\n */\n getAllChildren(): (Node | Group)[] {\n const result: (Node | Group)[] = [];\n for (const child of this._children) {\n result.push(child);\n if (child instanceof Group) {\n result.push(...child.getAllChildren());\n }\n }\n return result;\n }\n\n /**\n * Recalculate bounds from children\n */\n recalculateBounds(): void {\n if (this._children.length === 0) {\n this._x = 0;\n this._y = 0;\n this._width = 0;\n this._height = 0;\n this.markDirty();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const child of this._children) {\n const bounds = child.getBounds();\n minX = Math.min(minX, bounds.x);\n minY = Math.min(minY, bounds.y);\n maxX = Math.max(maxX, bounds.x + bounds.width);\n maxY = Math.max(maxY, bounds.y + bounds.height);\n }\n\n this._x = minX - this._padding;\n this._y = minY - this._padding;\n this._width = maxX - minX + this._padding * 2;\n this._height = maxY - minY + this._padding * 2;\n\n this.markDirty();\n }\n\n hitTest(point: Point): boolean {\n const bounds = this.getBounds();\n return pointInRect(point, bounds);\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n if (this._children.length === 0) {\n return;\n }\n\n const { x, y, width, height } = this.getBounds();\n const style = this._groupStyle;\n\n // Draw background\n ctx.fillStyle = style.fillColor ?? 'rgba(200, 200, 200, 0.2)';\n ctx.globalAlpha = style.opacity ?? 1;\n ctx.fillRect(x, y, width, height);\n\n // Draw border\n ctx.strokeStyle = style.strokeColor ?? '#999999';\n ctx.lineWidth = style.strokeWidth ?? 1;\n\n if (this._state === 'selected') {\n ctx.lineWidth = Math.max(style.strokeWidth ?? 1, 2);\n }\n\n const lineDash = style.lineDash ?? [];\n ctx.setLineDash(lineDash.length > 0 ? lineDash : []);\n ctx.strokeRect(x, y, width, height);\n ctx.setLineDash([]);\n\n // Draw label\n if (this._label !== undefined) {\n ctx.fillStyle = '#666666';\n ctx.font = '12px sans-serif';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n ctx.fillText(this._label, x + 8, y + 4);\n }\n\n ctx.globalAlpha = 1;\n\n // Render children\n for (const child of this._children) {\n if (child.visible) {\n child.render(ctx);\n }\n }\n }\n\n override getBounds(): Bounds {\n return {\n x: this._x,\n y: this._y,\n width: this._width,\n height: this._height,\n };\n }\n}\n","import { Node, type NodeOptions } from '../Node';\n\nexport interface RectangleNodeOptions extends NodeOptions {\n cornerRadius?: number;\n}\n\n/**\n * Rectangular node with optional rounded corners\n */\nexport class RectangleNode extends Node {\n private _cornerRadius: number;\n\n constructor(options: RectangleNodeOptions) {\n super(options);\n this._cornerRadius = options.cornerRadius ?? options.style?.cornerRadius ?? 0;\n }\n\n get typeName(): string {\n return 'rectangle';\n }\n\n /**\n * Corner radius for rounded rectangles\n */\n get cornerRadius(): number {\n return this._cornerRadius;\n }\n\n set cornerRadius(value: number) {\n if (this._cornerRadius !== value) {\n this._cornerRadius = value;\n this.markDirty();\n }\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const { x, y, width, height } = this.getBounds();\n const radius = Math.min(this._cornerRadius, width / 2, height / 2);\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.beginPath();\n\n if (radius > 0) {\n // Rounded rectangle\n ctx.moveTo(x + radius, y);\n ctx.lineTo(x + width - radius, y);\n ctx.arcTo(x + width, y, x + width, y + radius, radius);\n ctx.lineTo(x + width, y + height - radius);\n ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);\n ctx.lineTo(x + radius, y + height);\n ctx.arcTo(x, y + height, x, y + height - radius, radius);\n ctx.lineTo(x, y + radius);\n ctx.arcTo(x, y, x + radius, y, radius);\n } else {\n // Sharp rectangle\n ctx.rect(x, y, width, height);\n }\n\n ctx.closePath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n","import { Node, type NodeOptions } from '../Node';\nimport { NODE_HITBOX_PADDING } from '@/constants';\nimport type { Bounds, Point } from '@/types';\n\n/**\n * Ellipse/circle node\n */\nexport class CircleNode extends Node {\n constructor(options: NodeOptions) {\n super(options);\n }\n\n get typeName(): string {\n return 'circle';\n }\n\n /**\n * Horizontal radius\n */\n get radiusX(): number {\n return this._width / 2;\n }\n\n /**\n * Vertical radius\n */\n get radiusY(): number {\n return this._height / 2;\n }\n\n override hitTest(point: Point): boolean {\n const center = this.getCenter();\n const padding = NODE_HITBOX_PADDING;\n const rx = this._width / 2 + padding;\n const ry = this._height / 2 + padding;\n\n // Ellipse equation: (x-h)²/rx² + (y-k)²/ry² <= 1\n const dx = point.x - center.x;\n const dy = point.y - center.y;\n return (dx * dx) / (rx * rx) + (dy * dy) / (ry * ry) <= 1;\n }\n\n override getConnectionPointAtOutlineParam(param: number): Point {\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const t = ((param % 1) + 1) % 1 * Math.PI * 2;\n const angle = Math.PI * 1.5 - t;\n return {\n x: center.x + rx * Math.cos(angle),\n y: center.y + ry * Math.sin(angle),\n };\n }\n\n override getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const point = this.getOutlinePointToward(target);\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const t = Math.atan2(\n (point.y - center.y) / ry,\n (point.x - center.x) / rx\n );\n const param = (Math.PI * 1.5 - t) / (Math.PI * 2);\n const normalizedParam = ((param % 1) + 1) % 1;\n return { point, param: normalizedParam };\n }\n\n protected override getOutlinePointToward(target: Point): Point {\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n\n if (dx === 0 && dy === 0) {\n return center;\n }\n\n const scale = 1 / Math.sqrt((dx * dx) / (rx * rx) + (dy * dy) / (ry * ry));\n return {\n x: center.x + dx * scale,\n y: center.y + dy * scale,\n };\n }\n\n protected override getLabelContainerBounds(bounds: Bounds): Bounds {\n const width = bounds.width / Math.SQRT2;\n const height = bounds.height / Math.SQRT2;\n return {\n x: bounds.x + (bounds.width - width) / 2,\n y: bounds.y + (bounds.height - height) / 2,\n width,\n height,\n };\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const center = this.getCenter();\n const rx = this._width / 2;\n const ry = this._height / 2;\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.beginPath();\n ctx.ellipse(center.x, center.y, rx, ry, 0, 0, Math.PI * 2);\n ctx.closePath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n","import { Node, type NodeOptions } from '../Node';\nimport { NODE_HITBOX_PADDING } from '@/constants';\nimport type { Bounds, Point } from '@/types';\n\n/**\n * Diamond/rhombus node for decision points\n */\nexport class DiamondNode extends Node {\n constructor(options: NodeOptions) {\n super(options);\n }\n\n get typeName(): string {\n return 'diamond';\n }\n\n override hitTest(point: Point): boolean {\n // Check if point is inside the diamond\n const center = this.getCenter();\n const padding = NODE_HITBOX_PADDING;\n const hw = this._width / 2 + padding;\n const hh = this._height / 2 + padding;\n\n // Use normalized distance formula for diamond/rhombus\n // Point is inside if |dx|/hw + |dy|/hh <= 1\n const dx = Math.abs(point.x - center.x);\n const dy = Math.abs(point.y - center.y);\n\n return dx / hw + dy / hh <= 1;\n }\n\n override getConnectionPointAtOutlineParam(param: number): Point {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\n const vertices: Point[] = [\n { x: center.x, y: center.y - hh },\n { x: center.x + hw, y: center.y },\n { x: center.x, y: center.y + hh },\n { x: center.x - hw, y: center.y },\n ];\n const segLen = Math.sqrt(hw * hw + hh * hh);\n const perimeter = 4 * segLen;\n let s = ((param % 1) + 1) % 1 * perimeter;\n\n for (let i = 0; i < 4; i++) {\n if (s < segLen) {\n const a = vertices[i]!;\n const b = vertices[(i + 1) % 4]!;\n const t = s / segLen;\n return {\n x: a.x + t * (b.x - a.x),\n y: a.y + t * (b.y - a.y),\n };\n }\n s -= segLen;\n }\n return vertices[0]!;\n }\n\n override getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\n const vertices: Point[] = [\n { x: center.x, y: center.y - hh },\n { x: center.x + hw, y: center.y },\n { x: center.x, y: center.y + hh },\n { x: center.x - hw, y: center.y },\n ];\n const segLen = Math.sqrt(hw * hw + hh * hh);\n const P = 4 * segLen;\n\n const projectSegment = (\n ax: number, ay: number, bx: number, by: number,\n segStartParam: number\n ): { point: Point; param: number; distSq: number } => {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n let t = lenSq > 0 ? ((target.x - ax) * dx + (target.y - ay) * dy) / lenSq : 0;\n t = Math.max(0, Math.min(1, t));\n const px = ax + t * dx;\n const py = ay + t * dy;\n const distSq = (target.x - px) ** 2 + (target.y - py) ** 2;\n const param = segStartParam + (t * segLen) / P;\n return { point: { x: px, y: py }, param, distSq };\n };\n\n let best = projectSegment(vertices[0]!.x, vertices[0]!.y, vertices[1]!.x, vertices[1]!.y, 0);\n for (let i = 1; i < 4; i++) {\n const a = vertices[i]!;\n const b = vertices[(i + 1) % 4]!;\n const r = projectSegment(a.x, a.y, b.x, b.y, (i * segLen) / P);\n if (r.distSq < best.distSq) best = r;\n }\n return { point: best.point, param: best.param };\n }\n\n protected override getOutlinePointToward(target: Point): Point {\n const center = this.getCenter();\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n const hw = this._width / 2;\n const hh = this._height / 2;\n\n if (dx === 0 && dy === 0) {\n return center;\n }\n\n const t = 1 / (Math.abs(dx) / hw + Math.abs(dy) / hh);\n return {\n x: center.x + dx * t,\n y: center.y + dy * t,\n };\n }\n\n protected override getLabelContainerBounds(bounds: Bounds): Bounds {\n const width = bounds.width / 2;\n const height = bounds.height / 2;\n return {\n x: bounds.x + (bounds.width - width) / 2,\n y: bounds.y + (bounds.height - height) / 2,\n width,\n height,\n };\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.beginPath();\n ctx.moveTo(center.x, center.y - hh); // Top\n ctx.lineTo(center.x + hw, center.y); // Right\n ctx.lineTo(center.x, center.y + hh); // Bottom\n ctx.lineTo(center.x - hw, center.y); // Left\n ctx.closePath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n","import { Node, type NodeOptions } from '../Node';\nimport { NODE_HITBOX_PADDING } from '@/constants';\nimport type { Point } from '@/types';\n\nconst OUTLINE_SAMPLE_COUNT = 64;\n\nexport interface CustomShapeNodeOptions extends NodeOptions {\n path: Path2D | ((width: number, height: number) => Path2D);\n /**\n * SVG path string for export. Required for correct SVG export of custom shapes.\n * Path coordinates are in local space (0,0 = top-left, width×height = node bounds).\n * If omitted, SVG export falls back to a rectangle.\n */\n svgPath?: string | ((width: number, height: number) => string);\n shapeType?: string;\n}\n\n/**\n * Node with custom Path2D shape\n */\nexport class CustomShapeNode extends Node {\n private _pathFactory: (width: number, height: number) => Path2D;\n private _svgPathFactory: ((width: number, height: number) => string) | null = null;\n private _shapeType?: string;\n private _cachedPath: Path2D | null = null;\n private _cachedWidth = 0;\n private _cachedHeight = 0;\n private _cachedOutline: { points: Point[]; lengths: number[]; totalLength: number } | null = null;\n\n constructor(options: CustomShapeNodeOptions) {\n super(options);\n\n if (options.path instanceof Path2D) {\n const staticPath = options.path;\n this._pathFactory = (): Path2D => staticPath;\n } else {\n this._pathFactory = options.path;\n }\n\n if (options.svgPath !== undefined) {\n if (typeof options.svgPath === 'string') {\n const staticSvg = options.svgPath;\n this._svgPathFactory = (): string => staticSvg;\n } else {\n this._svgPathFactory = options.svgPath;\n }\n }\n\n this._shapeType = options.shapeType;\n }\n\n get typeName(): string {\n return 'custom';\n }\n\n get shapeType(): string | undefined {\n return this._shapeType;\n }\n\n set shapeType(value: string | undefined) {\n if (this._shapeType !== value) {\n this._shapeType = value;\n this.markDirty();\n }\n }\n\n /**\n * Set a new path factory\n */\n setPathFactory(factory: (width: number, height: number) => Path2D): void {\n this._pathFactory = factory;\n this._cachedPath = null;\n this._cachedOutline = null;\n this.markDirty();\n }\n\n /**\n * Get the current path (cached)\n */\n getPath(): Path2D {\n if (\n this._cachedPath === null ||\n this._cachedWidth !== this._width ||\n this._cachedHeight !== this._height\n ) {\n this._cachedPath = this._pathFactory(this._width, this._height);\n this._cachedWidth = this._width;\n this._cachedHeight = this._height;\n this._cachedOutline = null;\n }\n return this._cachedPath;\n }\n\n /**\n * Get SVG path string for export. Returns null if svgPath was not provided.\n */\n getSvgPath(): string | null {\n if (this._svgPathFactory === null) {\n return null;\n }\n return this._svgPathFactory(this._width, this._height);\n }\n\n /**\n * Set SVG path for export. Call when shape changes.\n */\n setSvgPath(value: string | ((width: number, height: number) => string) | undefined): void {\n if (value === undefined) {\n this._svgPathFactory = null;\n } else if (typeof value === 'string') {\n this._svgPathFactory = (): string => value;\n } else {\n this._svgPathFactory = value;\n }\n this.markDirty();\n }\n\n private getOutlineSample(): { points: Point[]; lengths: number[]; totalLength: number } | null {\n this.getPath();\n if (\n this._cachedOutline !== null &&\n this._cachedWidth === this._width &&\n this._cachedHeight === this._height\n ) {\n return this._cachedOutline;\n }\n\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : null;\n const ctx = canvas?.getContext('2d');\n if (!ctx) {\n return null;\n }\n\n const path = this.getPath();\n const cx = this._width / 2;\n const cy = this._height / 2;\n const maxR = Math.max(this._width, this._height);\n\n const isInside = (lx: number, ly: number): boolean => ctx.isPointInPath(path, lx, ly);\n\n const getBoundaryPoint = (dx: number, dy: number): Point => {\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) return { x: cx, y: cy };\n const ux = dx / len;\n const uy = dy / len;\n let lo = 0;\n let hi = maxR;\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2;\n const px = cx + ux * mid;\n const py = cy + uy * mid;\n if (isInside(px, py)) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n const t = (lo + hi) / 2;\n return { x: cx + ux * t, y: cy + uy * t };\n };\n\n const points: Point[] = [];\n for (let i = 0; i < OUTLINE_SAMPLE_COUNT; i++) {\n const angle = (i / OUTLINE_SAMPLE_COUNT) * Math.PI * 2 - Math.PI / 2;\n const dx = Math.cos(angle);\n const dy = Math.sin(angle);\n points.push(getBoundaryPoint(dx, dy));\n }\n\n const lengths: number[] = [];\n let totalLength = 0;\n for (let i = 0; i < OUTLINE_SAMPLE_COUNT; i++) {\n const a = points[i]!;\n const b = points[(i + 1) % OUTLINE_SAMPLE_COUNT]!;\n const segLen = Math.hypot(b.x - a.x, b.y - a.y);\n lengths.push(segLen);\n totalLength += segLen;\n }\n\n this._cachedOutline = { points, lengths, totalLength };\n return this._cachedOutline;\n }\n\n private localToWorld(p: Point): Point {\n return { x: p.x + this._x, y: p.y + this._y };\n }\n\n override getConnectionPointAtOutlineParam(param: number): Point {\n const sample = this.getOutlineSample();\n if (!sample) return super.getConnectionPointAtOutlineParam(param);\n const { points, lengths, totalLength } = sample;\n let s = ((param % 1) + 1) % 1 * totalLength;\n\n for (let i = 0; i < OUTLINE_SAMPLE_COUNT; i++) {\n const segLen = lengths[i]!;\n if (s < segLen) {\n const a = points[i]!;\n const b = points[(i + 1) % OUTLINE_SAMPLE_COUNT]!;\n const t = segLen > 0 ? s / segLen : 0;\n const local = {\n x: a.x + t * (b.x - a.x),\n y: a.y + t * (b.y - a.y),\n };\n return this.localToWorld(local);\n }\n s -= segLen;\n }\n return this.localToWorld(points[0]!);\n }\n\n override getClosestPointOnOutline(target: Point): { point: Point; param: number } {\n const sample = this.getOutlineSample();\n if (!sample) return super.getClosestPointOnOutline(target);\n const { points, lengths, totalLength } = sample;\n const localTarget = { x: target.x - this._x, y: target.y - this._y };\n\n const projectSegment = (\n ax: number,\n ay: number,\n bx: number,\n by: number,\n segLen: number,\n segStartParam: number\n ): { point: Point; param: number; distSq: number } => {\n const dx = bx - ax;\n const dy = by - ay;\n const lenSq = dx * dx + dy * dy;\n let t = lenSq > 0 ? ((localTarget.x - ax) * dx + (localTarget.y - ay) * dy) / lenSq : 0;\n t = Math.max(0, Math.min(1, t));\n const px = ax + t * dx;\n const py = ay + t * dy;\n const distSq = (localTarget.x - px) ** 2 + (localTarget.y - py) ** 2;\n const param = segStartParam + (segLen > 0 ? (t * segLen) / totalLength : 0);\n return { point: { x: px, y: py }, param, distSq };\n };\n\n let best = projectSegment(\n points[0]!.x,\n points[0]!.y,\n points[1]!.x,\n points[1]!.y,\n lengths[0]!,\n 0\n );\n let segStartParam = lengths[0]! / totalLength;\n\n for (let i = 1; i < OUTLINE_SAMPLE_COUNT; i++) {\n const a = points[i]!;\n const b = points[(i + 1) % OUTLINE_SAMPLE_COUNT]!;\n const segLen = lengths[i]!;\n const r = projectSegment(a.x, a.y, b.x, b.y, segLen, segStartParam);\n if (r.distSq < best.distSq) best = r;\n segStartParam += segLen / totalLength;\n }\n\n const param = ((best.param % 1) + 1) % 1;\n return { point: this.localToWorld(best.point), param };\n }\n\n protected override getOutlinePointToward(target: Point): Point {\n if (typeof document === 'undefined') {\n return super.getOutlinePointToward(target);\n }\n\n const center = this.getCenter();\n const dx = target.x - center.x;\n const dy = target.y - center.y;\n\n if (Math.abs(dx) < 1e-9 && Math.abs(dy) < 1e-9) {\n return center;\n }\n\n const localCenter = { x: this._width / 2, y: this._height / 2 };\n const localDx = target.x - center.x;\n const localDy = target.y - center.y;\n\n const boundary = this.getBoundaryPointOnRay(localCenter.x, localCenter.y, localDx, localDy);\n return this.localToWorld(boundary);\n }\n\n private getBoundaryPointOnRay(ox: number, oy: number, dx: number, dy: number): Point {\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) return { x: ox, y: oy };\n const ux = dx / len;\n const uy = dy / len;\n const maxR = Math.max(this._width, this._height) * 2;\n const path = this.getPath();\n\n const canvas = typeof document !== 'undefined' ? document.createElement('canvas') : null;\n const ctx = canvas?.getContext('2d');\n if (!ctx) return { x: ox, y: oy };\n const isInside = (lx: number, ly: number): boolean => ctx.isPointInPath(path, lx, ly);\n\n let lo = 0;\n let hi = maxR;\n for (let i = 0; i < 20; i++) {\n const mid = (lo + hi) / 2;\n const px = ox + ux * mid;\n const py = oy + uy * mid;\n if (isInside(px, py)) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n const t = (lo + hi) / 2;\n return { x: ox + ux * t, y: oy + uy * t };\n }\n\n override hitTest(point: Point): boolean {\n // Create an offscreen canvas for hit testing\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const ctx = canvas.getContext('2d');\n\n if (ctx === null) {\n // Fallback to bounding box\n return super.hitTest(point);\n }\n\n // Translate point to local coordinates\n const localX = point.x - this._x;\n const localY = point.y - this._y;\n\n const path = this.getPath();\n if (ctx.isPointInPath(path, localX, localY)) {\n return true;\n }\n\n ctx.lineWidth = NODE_HITBOX_PADDING * 2;\n return ctx.isPointInStroke(path, localX, localY);\n }\n\n render(ctx: CanvasRenderingContext2D): void {\n const style = this.style;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = style.fillOpacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n\n this.applyStyle(ctx);\n\n ctx.save();\n ctx.translate(this._x, this._y);\n\n const path = this.getPath();\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill(path);\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke(path);\n\n ctx.restore();\n ctx.globalAlpha = 1;\n\n this.renderContents(ctx);\n }\n}\n\n/**\n * Helper function to create common shapes as Path2D\n */\nexport const ShapeFactories = {\n /**\n * Hexagon shape\n */\n hexagon: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const inset = width * 0.25;\n\n path.moveTo(inset, 0);\n path.lineTo(width - inset, 0);\n path.lineTo(width, height / 2);\n path.lineTo(width - inset, height);\n path.lineTo(inset, height);\n path.lineTo(0, height / 2);\n path.closePath();\n\n return path;\n },\n\n /**\n * Parallelogram shape\n */\n parallelogram: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const skew = width * 0.2;\n\n path.moveTo(skew, 0);\n path.lineTo(width, 0);\n path.lineTo(width - skew, height);\n path.lineTo(0, height);\n path.closePath();\n\n return path;\n },\n\n /**\n * Cylinder shape (for databases)\n */\n cylinder: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const ellipseHeight = height * 0.15;\n\n // Top ellipse\n path.ellipse(width / 2, ellipseHeight, width / 2, ellipseHeight, 0, 0, Math.PI * 2);\n\n // Body\n path.moveTo(0, ellipseHeight);\n path.lineTo(0, height - ellipseHeight);\n path.ellipse(width / 2, height - ellipseHeight, width / 2, ellipseHeight, 0, Math.PI, 0);\n path.lineTo(width, ellipseHeight);\n\n return path;\n },\n\n /**\n * Document shape\n */\n document: (width: number, height: number): Path2D => {\n const path = new Path2D();\n const waveHeight = height * 0.1;\n\n path.moveTo(0, 0);\n path.lineTo(width, 0);\n path.lineTo(width, height - waveHeight);\n path.quadraticCurveTo(width * 0.75, height, width * 0.5, height - waveHeight);\n path.quadraticCurveTo(width * 0.25, height - waveHeight * 2, 0, height - waveHeight);\n path.closePath();\n\n return path;\n },\n\n /**\n * SVG path strings for export. Use with CustomShapeNodeOptions.svgPath.\n */\n svg: {\n hexagon: (w: number, h: number): string =>\n `M ${w * 0.25} 0 L ${w * 0.75} 0 L ${w} ${h / 2} L ${w * 0.75} ${h} L ${w * 0.25} ${h} L 0 ${h / 2} Z`,\n parallelogram: (w: number, h: number): string => {\n const skew = w * 0.2;\n return `M ${skew} 0 L ${w} 0 L ${w - skew} ${h} L 0 ${h} Z`;\n },\n cylinder: (w: number, h: number): string => {\n const eh = h * 0.15;\n const rx = w / 2;\n return `M 0 ${eh} L 0 ${h - eh} A ${rx} ${eh} 0 0 1 ${w} ${h - eh} L ${w} ${eh} A ${rx} ${eh} 0 0 1 0 ${eh} Z`;\n },\n document: (w: number, h: number): string => {\n const wh = h * 0.1;\n return `M 0 0 L ${w} 0 L ${w} ${h - wh} Q ${w * 0.75} ${h} ${w * 0.5} ${h - wh} Q ${w * 0.25} ${h - wh * 2} 0 ${h - wh} Z`;\n },\n /** Chamfered rectangle (cut corners) */\n chamfered: (w: number, h: number): string => {\n const cut = Math.max(6, Math.min(20, w * 0.18, h * 0.18));\n return `M ${cut} 0 L ${w - cut} 0 L ${w} ${cut} L ${w} ${h - cut} L ${w - cut} ${h} L ${cut} ${h} L 0 ${h - cut} L 0 ${cut} Z`;\n },\n },\n};\n","import type { EdgeStyle, ElementState, ElementStyle, NodeStyle, TextStyle } from '@/types';\n\n/**\n * Theme definition\n */\nexport interface Theme {\n name: string;\n colors: {\n background: string;\n grid: string;\n selection: string;\n connectionPreview: string;\n };\n node: {\n default: NodeStyle;\n hover: NodeStyle;\n selected: NodeStyle;\n dragging: NodeStyle;\n };\n edge: {\n default: EdgeStyle;\n hover: EdgeStyle;\n selected: EdgeStyle;\n };\n text: TextStyle;\n port: {\n default: { color: string; radius: number };\n hover: { color: string; radius: number };\n };\n group: {\n default: ElementStyle;\n selected: ElementStyle;\n };\n}\n\n/**\n * Style class definition\n */\nexport interface StyleClass {\n name: string;\n node?: Partial<NodeStyle>;\n edge?: Partial<EdgeStyle>;\n text?: Partial<TextStyle>;\n port?: Partial<{ color: string; radius: number }>;\n group?: Partial<ElementStyle>;\n}\n\nconst DEFAULT_THEME: Theme = {\n name: 'default',\n colors: {\n background: '#ffffff',\n grid: '#e5e5e5',\n selection: 'rgba(59, 130, 246, 0.1)',\n connectionPreview: '#3b82f6',\n },\n node: {\n default: {\n fillColor: '#ffffff',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n hover: {\n fillColor: '#f5f5f5',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n selected: {\n fillColor: '#ffffff',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n dragging: {\n fillColor: '#f0f0f0',\n strokeColor: '#333333',\n strokeWidth: 2,\n opacity: 0.8,\n cornerRadius: 4,\n },\n },\n edge: {\n default: {\n strokeColor: '#666666',\n strokeWidth: 2,\n opacity: 1,\n },\n hover: {\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n },\n selected: {\n strokeColor: '#3b82f6',\n strokeWidth: 3,\n opacity: 1,\n },\n },\n text: {\n font: '14px sans-serif',\n fontSize: 14,\n fontFamily: 'sans-serif',\n fontWeight: 'normal',\n color: '#333333',\n align: 'center',\n baseline: 'middle',\n },\n port: {\n default: { color: '#666666', radius: 6 },\n hover: { color: '#3b82f6', radius: 7 },\n },\n group: {\n default: {\n fillColor: 'rgba(200, 200, 200, 0.2)',\n strokeColor: '#999999',\n strokeWidth: 1,\n opacity: 1,\n },\n selected: {\n fillColor: 'rgba(59, 130, 246, 0.1)',\n strokeColor: '#3b82f6',\n strokeWidth: 2,\n opacity: 1,\n },\n },\n};\n\nconst DARK_THEME: Theme = {\n name: 'dark',\n colors: {\n background: '#1a1a1a',\n grid: '#333333',\n selection: 'rgba(99, 102, 241, 0.2)',\n connectionPreview: '#6366f1',\n },\n node: {\n default: {\n fillColor: '#2d2d2d',\n strokeColor: '#555555',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n hover: {\n fillColor: '#3d3d3d',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n selected: {\n fillColor: '#2d2d2d',\n strokeColor: '#555555',\n strokeWidth: 2,\n opacity: 1,\n cornerRadius: 4,\n },\n dragging: {\n fillColor: '#404040',\n strokeColor: '#555555',\n strokeWidth: 2,\n opacity: 0.8,\n cornerRadius: 4,\n },\n },\n edge: {\n default: {\n strokeColor: '#888888',\n strokeWidth: 2,\n opacity: 1,\n },\n hover: {\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n },\n selected: {\n strokeColor: '#818cf8',\n strokeWidth: 3,\n opacity: 1,\n },\n },\n text: {\n font: '14px sans-serif',\n fontSize: 14,\n fontFamily: 'sans-serif',\n fontWeight: 'normal',\n color: '#e0e0e0',\n align: 'center',\n baseline: 'middle',\n },\n port: {\n default: { color: '#888888', radius: 6 },\n hover: { color: '#6366f1', radius: 7 },\n },\n group: {\n default: {\n fillColor: 'rgba(100, 100, 100, 0.2)',\n strokeColor: '#666666',\n strokeWidth: 1,\n opacity: 1,\n },\n selected: {\n fillColor: 'rgba(99, 102, 241, 0.2)',\n strokeColor: '#6366f1',\n strokeWidth: 2,\n opacity: 1,\n },\n },\n};\n\n/**\n * Manages styles and themes\n */\nexport class StyleManager {\n private _theme: Theme;\n private _classes = new Map<string, StyleClass>();\n private _builtInThemes = new Map<string, Theme>([\n ['default', DEFAULT_THEME],\n ['dark', DARK_THEME],\n ]);\n\n constructor(theme?: Theme | string) {\n if (theme === undefined) {\n this._theme = DEFAULT_THEME;\n } else if (typeof theme === 'string') {\n this._theme = this._builtInThemes.get(theme) ?? DEFAULT_THEME;\n } else {\n this._theme = theme;\n }\n }\n\n /**\n * Current theme\n */\n get theme(): Theme {\n return this._theme;\n }\n\n /**\n * Set the current theme\n */\n setTheme(theme: Theme | string): void {\n if (typeof theme === 'string') {\n const builtIn = this._builtInThemes.get(theme);\n if (builtIn !== undefined) {\n this._theme = builtIn;\n }\n } else {\n this._theme = theme;\n }\n }\n\n /**\n * Register a custom theme\n */\n registerTheme(theme: Theme): void {\n this._builtInThemes.set(theme.name, theme);\n }\n\n /**\n * Get all available theme names\n */\n getThemeNames(): string[] {\n return Array.from(this._builtInThemes.keys());\n }\n\n /**\n * Register a style class\n */\n registerClass(styleClass: StyleClass): void {\n this._classes.set(styleClass.name, styleClass);\n }\n\n /**\n * Get a style class\n */\n getClass(name: string): StyleClass | undefined {\n return this._classes.get(name);\n }\n\n /**\n * Get all registered classes\n */\n getClasses(): StyleClass[] {\n return Array.from(this._classes.values());\n }\n\n /**\n * Get node style for a state\n */\n getNodeStyle(state: ElementState, className?: string): NodeStyle {\n const baseStyle = this.getBaseNodeStyle(state);\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.node !== undefined) {\n return { ...baseStyle, ...styleClass.node };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get edge style for a state\n */\n getEdgeStyle(state: ElementState, className?: string): EdgeStyle {\n const baseStyle = this.getBaseEdgeStyle(state);\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.edge !== undefined) {\n return { ...baseStyle, ...styleClass.edge };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get text style\n */\n getTextStyle(className?: string): TextStyle {\n const baseStyle = this._theme.text;\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.text !== undefined) {\n return { ...baseStyle, ...styleClass.text };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get group style for a state\n */\n getGroupStyle(selected: boolean, className?: string): ElementStyle {\n const baseStyle = selected ? this._theme.group.selected : this._theme.group.default;\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.group !== undefined) {\n return { ...baseStyle, ...styleClass.group };\n }\n }\n\n return baseStyle;\n }\n\n /**\n * Get port style\n */\n getPortStyle(hovered: boolean, className?: string): { color: string; radius: number } {\n const baseStyle = hovered ? this._theme.port.hover : this._theme.port.default;\n\n if (className !== undefined) {\n const styleClass = this._classes.get(className);\n if (styleClass?.port !== undefined) {\n return { ...baseStyle, ...styleClass.port };\n }\n }\n\n return baseStyle;\n }\n\n private getBaseNodeStyle(state: ElementState): NodeStyle {\n switch (state) {\n case 'hover':\n return this._theme.node.hover;\n case 'selected':\n return this._theme.node.selected;\n case 'dragging':\n return this._theme.node.dragging;\n default:\n return this._theme.node.default;\n }\n }\n\n private getBaseEdgeStyle(state: ElementState): EdgeStyle {\n switch (state) {\n case 'hover':\n return this._theme.edge.hover;\n case 'selected':\n return this._theme.edge.selected;\n default:\n return this._theme.edge.default;\n }\n }\n}\n\n// Export default themes\nexport { DEFAULT_THEME, DARK_THEME };\n","/**\n * Omit properties from an object that have default values\n * @param obj - The object to filter\n * @param defaults - Default values to compare against\n * @returns New object with only non-default values\n */\nexport function omitDefaultValues<T extends Record<string, unknown>>(\n obj: T,\n defaults: Partial<T>\n): Partial<T> {\n const result: Partial<T> = {};\n\n for (const key of Object.keys(obj) as (keyof T)[]) {\n const objValue = obj[key];\n const defaultValue = defaults[key];\n\n // Skip if value equals default\n if (objValue === defaultValue) {\n continue;\n }\n\n // Handle arrays - compare by value\n if (Array.isArray(objValue) && Array.isArray(defaultValue)) {\n if (objValue.length === defaultValue.length) {\n const arraysEqual = objValue.every((val, idx) => val === defaultValue[idx]);\n if (arraysEqual) {\n continue;\n }\n }\n }\n\n // Handle objects - compare shallow\n if (\n typeof objValue === 'object' &&\n objValue !== null &&\n typeof defaultValue === 'object' &&\n defaultValue !== null\n ) {\n if (!Array.isArray(objValue) && !Array.isArray(defaultValue)) {\n const objKeys = Object.keys(objValue);\n const defaultKeys = Object.keys(defaultValue);\n if (objKeys.length === defaultKeys.length) {\n const objectsEqual = objKeys.every(\n (k) => (objValue as Record<string, unknown>)[k] === (defaultValue as Record<string, unknown>)[k]\n );\n if (objectsEqual) {\n continue;\n }\n }\n }\n }\n\n result[key] = objValue;\n }\n\n return result;\n}\n\n/**\n * Check if an object has any non-default values\n * @param obj - The object to check\n * @param defaults - Default values to compare against\n * @returns True if object has non-default values\n */\nexport function hasNonDefaultValues<T extends Record<string, unknown>>(\n obj: T,\n defaults: Partial<T>\n): boolean {\n return Object.keys(omitDefaultValues(obj, defaults)).length > 0;\n}\n\n/**\n * Omit undefined and null values from an object\n * @param obj - The object to filter\n * @returns New object with only defined values\n */\nexport function omitEmptyValues<T extends Record<string, unknown>>(\n obj: T\n): Partial<T> {\n const result: Partial<T> = {};\n\n for (const key of Object.keys(obj) as (keyof T)[]) {\n const value = obj[key];\n if (value !== undefined && value !== null) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Omit empty arrays and empty objects from an object\n * @param obj - The object to filter\n * @returns New object with only non-empty values\n */\nexport function omitEmptyCollections<T extends Record<string, unknown>>(\n obj: T\n): Partial<T> {\n const result: Partial<T> = {};\n\n for (const key of Object.keys(obj) as (keyof T)[]) {\n const value = obj[key];\n if (value === undefined || value === null) {\n continue;\n }\n if (Array.isArray(value) && value.length === 0) {\n continue;\n }\n if (typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0) {\n continue;\n }\n result[key] = value;\n }\n\n return result;\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\nimport type {\n DiagramData,\n SerializedNode,\n SerializedEdge,\n SerializedGroup,\n SerializedPort,\n SerializedNodeIcon,\n SerializedAnchorPoints,\n SerializedTextLabel,\n} from '@/types';\nimport { omitDefaultValues, omitEmptyValues, hasNonDefaultValues } from './omitDefaults';\n\nconst SERIALIZER_VERSION = '1.1';\n\n/**\n * Validation error during deserialization\n */\nexport class SerializerValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SerializerValidationError';\n }\n}\n\nexport interface NodeFactory {\n (data: SerializedNode): Node;\n}\n\nexport interface EdgeFactory {\n (data: SerializedEdge): Edge;\n}\n\nexport interface GroupFactory {\n (data: SerializedGroup): Group;\n}\n\nexport interface SerializerOptions {\n nodeFactory: NodeFactory;\n edgeFactory: EdgeFactory;\n groupFactory?: GroupFactory;\n}\n\n/**\n * Serializes and deserializes diagram data\n */\nexport class Serializer {\n private renderer: DiagramRenderer;\n private readonly nodeFactory: NodeFactory;\n private readonly edgeFactory: EdgeFactory;\n private readonly groupFactory?: GroupFactory;\n\n constructor(renderer: DiagramRenderer, options: SerializerOptions) {\n this.renderer = renderer;\n this.nodeFactory = options.nodeFactory;\n this.edgeFactory = options.edgeFactory;\n this.groupFactory = options.groupFactory;\n }\n\n /**\n * Serialize the diagram to JSON-compatible data\n */\n serialize(): DiagramData {\n const styleManager = this.renderer.getStyleManager();\n const nodes: SerializedNode[] = [];\n const edges: SerializedEdge[] = [];\n const groups: SerializedGroup[] = [];\n\n // Serialize nodes\n for (const node of this.renderer.nodes.values()) {\n nodes.push(this.serializeNode(node));\n }\n\n // Serialize edges\n for (const edge of this.renderer.edges.values()) {\n edges.push(this.serializeEdge(edge));\n }\n\n // Serialize groups\n for (const group of this.renderer.groups.values()) {\n groups.push(this.serializeGroup(group));\n }\n\n return {\n version: SERIALIZER_VERSION,\n nodes,\n edges,\n groups,\n viewport: { ...this.renderer.viewport },\n theme: styleManager?.theme,\n styleClasses: styleManager?.getClasses(),\n };\n }\n\n /**\n * Serialize to JSON string\n */\n toJSON(pretty = false): string {\n const data = this.serialize();\n return pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);\n }\n\n /**\n * Deserialize data and populate the diagram\n */\n deserialize(data: DiagramData): void {\n // Validate data before deserialization\n this.validate(data);\n\n // Clear existing content\n this.clear();\n\n // Restore viewport\n this.renderer.viewport = data.viewport;\n\n // Restore theme and classes if available\n const styleManager = this.renderer.getStyleManager();\n if (styleManager && data.theme) {\n styleManager.setTheme(data.theme);\n }\n if (styleManager && data.styleClasses) {\n for (const styleClass of data.styleClasses) {\n styleManager.registerClass(styleClass);\n }\n }\n\n // Create nodes\n for (const nodeData of data.nodes) {\n const node = this.nodeFactory(nodeData);\n this.renderer.addNode(node);\n }\n\n // Create edges\n for (const edgeData of data.edges) {\n const edge = this.edgeFactory(edgeData);\n this.renderer.addEdge(edge);\n }\n\n // Create groups\n if (this.groupFactory !== undefined) {\n for (const groupData of data.groups) {\n const group = this.groupFactory(groupData);\n this.renderer.addGroup(group);\n }\n }\n\n this.renderer.markDirty();\n }\n\n /**\n * Validate diagram data before deserialization\n */\n private validate(data: DiagramData): void {\n if (!data.version) {\n throw new SerializerValidationError('Missing version field in diagram data');\n }\n\n if (!Array.isArray(data.nodes)) {\n throw new SerializerValidationError('Invalid or missing nodes array');\n }\n\n if (!Array.isArray(data.edges)) {\n throw new SerializerValidationError('Invalid or missing edges array');\n }\n\n // Build a set of node IDs for edge validation\n const nodeIds = new Set(data.nodes.map((n) => n.id));\n\n // Validate edges reference existing nodes\n for (const edge of data.edges) {\n if (!nodeIds.has(edge.from.nodeId)) {\n throw new SerializerValidationError(\n `Edge \"${edge.id}\" references non-existent source node \"${edge.from.nodeId}\"`\n );\n }\n if (!nodeIds.has(edge.to.nodeId)) {\n throw new SerializerValidationError(\n `Edge \"${edge.id}\" references non-existent target node \"${edge.to.nodeId}\"`\n );\n }\n }\n }\n\n /**\n * Parse JSON string and deserialize\n */\n fromJSON(json: string): void {\n const data = JSON.parse(json) as DiagramData;\n this.deserialize(data);\n }\n\n /**\n * Clear the diagram\n */\n clear(): void {\n // Remove all edges first (to avoid orphaned references)\n for (const edge of this.renderer.edges.values()) {\n this.renderer.removeEdge(edge.id);\n }\n\n // Remove all nodes\n for (const node of this.renderer.nodes.values()) {\n this.renderer.removeNode(node.id);\n }\n\n // Remove all groups\n for (const group of this.renderer.groups.values()) {\n this.renderer.removeGroup(group.id);\n }\n }\n\n private serializeNode(node: Node): SerializedNode {\n const ports: SerializedPort[] = node.ports.map((port) => ({\n id: port.id,\n type: port.type,\n position: port.position,\n styleClass: port.styleClass,\n }));\n\n // Serialize label - full TextLabel if it has more than just text\n let label: string | SerializedTextLabel | undefined;\n if (node.label) {\n const labelDefaults = { padding: 8, margin: 0, style: {}, maxWidth: undefined, styleClass: undefined };\n const labelData = {\n text: node.label.text,\n style: node.label.style,\n maxWidth: node.label.maxWidth,\n padding: node.label.padding,\n margin: node.label.margin,\n styleClass: node.label.styleClass,\n };\n const hasExtendedOptions = hasNonDefaultValues(labelData, labelDefaults);\n\n if (hasExtendedOptions) {\n label = omitEmptyValues({\n text: node.label.text,\n style: Object.keys(node.label.style).length > 0 ? node.label.style : undefined,\n maxWidth: node.label.maxWidth,\n padding: node.label.padding !== 8 ? node.label.padding : undefined,\n margin: node.label.margin !== 0 ? node.label.margin : undefined,\n styleClass: node.label.styleClass,\n }) as SerializedTextLabel | undefined;\n } else {\n label = node.label.text;\n }\n }\n\n // Serialize icon\n let icon: SerializedNodeIcon | undefined;\n if (node.icon) {\n const opts = node.icon.options;\n const source = typeof opts.source === 'string' ? opts.source : undefined;\n if (source) {\n icon = {\n source,\n width: opts.width,\n height: opts.height,\n fit: opts.fit,\n placement: opts.placement,\n scaleWithBounds: opts.scaleWithBounds,\n padding: opts.padding,\n margin: opts.margin,\n gap: opts.gap,\n opacity: opts.opacity,\n align: opts.align,\n verticalAlign: opts.verticalAlign,\n offsetX: opts.offsetX,\n offsetY: opts.offsetY,\n };\n }\n }\n\n // Serialize anchor points if non-default\n let anchorPoints: SerializedAnchorPoints | undefined;\n const ap = node.anchorPoints;\n const anchorDefaults = { top: 1, right: 1, bottom: 1, left: 1 };\n const anchorData = { top: ap.top, right: ap.right, bottom: ap.bottom, left: ap.left };\n if (hasNonDefaultValues(anchorData, anchorDefaults)) {\n anchorPoints = omitDefaultValues(anchorData, anchorDefaults);\n }\n\n return {\n id: node.id,\n type: node.typeName,\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n style: node.style,\n styleClass: node.styleClass,\n label,\n labelStyleClass: typeof label === 'string' ? node.label?.styleClass : undefined,\n labelPlacement: node.labelPlacement !== 'auto' ? node.labelPlacement : undefined,\n icon,\n anchorPoints,\n ports: ports.length > 0 ? ports : undefined,\n data: Object.keys(node.data).length > 0 ? node.data : undefined,\n };\n }\n\n private serializeEdge(edge: Edge): SerializedEdge {\n return {\n id: edge.id,\n from: edge.from,\n to: edge.to,\n type: edge.type,\n controlPoints: edge.controlPoints,\n arrowType: edge.arrowType,\n startMarker: edge.startMarker,\n endMarker: edge.endMarker,\n style: edge.style,\n styleClass: edge.styleClass,\n label: edge.label?.text,\n labelStyleClass: edge.label?.styleClass,\n labelOffset: edge.labelOffset !== 0 ? edge.labelOffset : undefined,\n labelBackground: edge.labelBackground,\n data: Object.keys(edge.data).length > 0 ? edge.data : undefined,\n };\n }\n\n private serializeGroup(group: Group): SerializedGroup {\n return {\n id: group.id,\n childIds: group.children.map((c) => c.id),\n style: group.style,\n styleClass: group.styleClass,\n label: group.label,\n data: Object.keys(group.data).length > 0 ? group.data : undefined,\n };\n }\n}\n","export function downloadBlob(filename: string, blob: Blob): void {\n const url = URL.createObjectURL(blob);\n\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n URL.revokeObjectURL(url);\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Node } from '@/elements/Node';\nimport type { Edge } from '@/elements/Edge';\nimport type { Group } from '@/elements/Group';\n\nexport interface ElementIteratorOptions {\n /** Include only visible elements (default: false) */\n visibleOnly?: boolean;\n /** Include groups in iteration (default: true) */\n includeGroups?: boolean;\n /** Include edges in iteration (default: true) */\n includeEdges?: boolean;\n /** Include nodes in iteration (default: true) */\n includeNodes?: boolean;\n}\n\n/**\n * Get all diagram elements in render order (groups -> edges -> nodes)\n */\nexport function* getAllElements(\n renderer: DiagramRenderer,\n options: ElementIteratorOptions = {}\n): IterableIterator<Group | Edge | Node> {\n const {\n visibleOnly = false,\n includeGroups = true,\n includeEdges = true,\n includeNodes = true,\n } = options;\n\n if (includeGroups) {\n for (const group of renderer.groups.values()) {\n if (!visibleOnly || group.visible) {\n yield group;\n }\n }\n }\n\n if (includeEdges) {\n for (const edge of renderer.edges.values()) {\n if (!visibleOnly || edge.visible) {\n yield edge;\n }\n }\n }\n\n if (includeNodes) {\n for (const node of renderer.nodes.values()) {\n if (!visibleOnly || node.visible) {\n yield node;\n }\n }\n }\n}\n\n/**\n * Get only visible elements in render order\n */\nexport function* getVisibleElements(\n renderer: DiagramRenderer\n): IterableIterator<Group | Edge | Node> {\n yield* getAllElements(renderer, { visibleOnly: true });\n}\n\n/**\n * Get only nodes\n */\nexport function* getNodes(\n renderer: DiagramRenderer,\n options: { visibleOnly?: boolean } = {}\n): IterableIterator<Node> {\n const { visibleOnly = false } = options;\n for (const node of renderer.nodes.values()) {\n if (!visibleOnly || node.visible) {\n yield node;\n }\n }\n}\n\n/**\n * Get only edges\n */\nexport function* getEdges(\n renderer: DiagramRenderer,\n options: { visibleOnly?: boolean } = {}\n): IterableIterator<Edge> {\n const { visibleOnly = false } = options;\n for (const edge of renderer.edges.values()) {\n if (!visibleOnly || edge.visible) {\n yield edge;\n }\n }\n}\n\n/**\n * Get only groups\n */\nexport function* getGroups(\n renderer: DiagramRenderer,\n options: { visibleOnly?: boolean } = {}\n): IterableIterator<Group> {\n const { visibleOnly = false } = options;\n for (const group of renderer.groups.values()) {\n if (!visibleOnly || group.visible) {\n yield group;\n }\n }\n}\n\n/**\n * Apply a function to all elements\n */\nexport function forEachElement(\n renderer: DiagramRenderer,\n fn: (element: Group | Edge | Node) => void,\n options: ElementIteratorOptions = {}\n): void {\n for (const element of getAllElements(renderer, options)) {\n fn(element);\n }\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport { applyStyleManagerToElements } from './style';\nimport { getContentBounds } from './contentBounds';\nimport { downloadBlob } from './download';\nimport { getAllElements } from './elementIterator';\n\nexport interface ExportOptions {\n scale?: number;\n backgroundColor?: string;\n padding?: number;\n format?: 'png' | 'jpeg';\n quality?: number;\n}\n\n/**\n * Exports diagram to image formats\n */\nexport class ImageExporter {\n private renderer: DiagramRenderer;\n\n constructor(renderer: DiagramRenderer) {\n this.renderer = renderer;\n }\n\n /**\n * Export to PNG blob\n */\n async exportPNG(options: ExportOptions = {}): Promise<Blob> {\n return this.export({ ...options, format: 'png' });\n }\n\n /**\n * Export to JPEG blob\n */\n async exportJPEG(options: ExportOptions = {}): Promise<Blob> {\n return this.export({ ...options, format: 'jpeg' });\n }\n\n /**\n * Export to data URL\n */\n async exportDataURL(options: ExportOptions = {}): Promise<string> {\n const blob = await this.export(options);\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (): void => resolve(reader.result as string);\n reader.onerror = (): void => reject(new Error('Failed to read blob'));\n reader.readAsDataURL(blob);\n });\n }\n\n /**\n * Download as file\n */\n async download(filename: string, options: ExportOptions = {}): Promise<void> {\n const blob = await this.export(options);\n downloadBlob(filename, blob);\n }\n\n private async export(options: ExportOptions = {}): Promise<Blob> {\n const scale = options.scale ?? 2;\n const backgroundColor = options.backgroundColor ?? '#ffffff';\n const padding = options.padding ?? 20;\n const format = options.format ?? 'png';\n const quality = options.quality ?? 0.92;\n\n // Calculate content bounds\n const bounds = getContentBounds({ nodes: this.renderer.nodes.values() });\n if (bounds === null) {\n // Empty diagram, return small blank image\n return this.createBlankImage(100, 100, backgroundColor, format, quality);\n }\n\n // Calculate export dimensions\n const width = (bounds.width + padding * 2) * scale;\n const height = (bounds.height + padding * 2) * scale;\n\n // Create export canvas\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (ctx === null) {\n throw new Error('Failed to get canvas context');\n }\n\n // Fill background\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n\n // Apply transforms\n ctx.scale(scale, scale);\n ctx.translate(-bounds.x + padding, -bounds.y + padding);\n\n // Apply StyleManager if present before rendering\n applyStyleManagerToElements(\n this.renderer.getStyleManager(),\n this.renderer.groups.values(),\n this.renderer.edges.values(),\n this.renderer.nodes.values()\n );\n\n // Render elements (in correct order: groups -> edges -> nodes)\n for (const element of getAllElements(this.renderer, { visibleOnly: true })) {\n element.render(ctx);\n }\n\n // Convert to blob\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob !== null) {\n resolve(blob);\n } else {\n reject(new Error('Failed to create blob'));\n }\n },\n `image/${format}`,\n quality\n );\n });\n }\n\n private createBlankImage(\n width: number,\n height: number,\n backgroundColor: string,\n format: string,\n quality: number\n ): Promise<Blob> {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext('2d');\n if (ctx !== null) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n }\n\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob !== null) {\n resolve(blob);\n } else {\n reject(new Error('Failed to create blob'));\n }\n },\n `image/${format}`,\n quality\n );\n });\n }\n\n}\n","import type { ArrowMarkerConfig, Point } from '@/types';\nimport { ARROW_ANGLE } from '@/constants';\n\nexport interface MarkerPoints {\n /** Start point of marker (attached to edge) */\n from: Point;\n /** End point of marker (tip) */\n to: Point;\n}\n\n/**\n * Calculate marker points based on edge path\n */\nexport function calculateMarkerPoints(\n path: readonly Point[],\n position: 'start' | 'end',\n type: 'bezier' | 'straight' | 'polyline' | 'editable-polyline'\n): MarkerPoints | null {\n if (path.length < 2) {\n return null;\n }\n\n if (type === 'bezier' && path.length >= 4) {\n const epsilon = 0.001;\n const isSame = (a: Point, b: Point): boolean =>\n Math.abs(a.x - b.x) < epsilon && Math.abs(a.y - b.y) < epsilon;\n\n if (position === 'end') {\n const endIndex = path.length - 1;\n const endPoint = path[endIndex]!;\n let from = path[endIndex - 1]!;\n if (isSame(from, endPoint)) {\n from = path[endIndex - 2]!;\n if (isSame(from, endPoint)) {\n from = path[0]!;\n }\n }\n return { from, to: endPoint };\n }\n\n const start = path[0]!;\n let next = path[1]!;\n if (isSame(next, start)) {\n next = path[2]!;\n if (isSame(next, start)) {\n next = path[path.length - 1]!;\n }\n }\n return { from: next, to: start };\n }\n\n if (position === 'end') {\n return { from: path[path.length - 2]!, to: path[path.length - 1]! };\n }\n\n return { from: path[1]!, to: path[0]! };\n}\n\n/**\n * Calculate arrow marker vertex points\n */\nexport function calculateArrowMarkerPoints(\n to: Point,\n angle: number,\n size: number\n): { tip: Point; left: Point; right: Point } {\n const left = {\n x: to.x - size * Math.cos(angle - ARROW_ANGLE),\n y: to.y - size * Math.sin(angle - ARROW_ANGLE),\n };\n const right = {\n x: to.x - size * Math.cos(angle + ARROW_ANGLE),\n y: to.y - size * Math.sin(angle + ARROW_ANGLE),\n };\n return { tip: to, left, right };\n}\n\n/**\n * Calculate diamond marker vertex points\n */\nexport function calculateDiamondMarkerPoints(\n to: Point,\n angle: number,\n size: number\n): Point[] {\n const halfLength = size / 2;\n const halfWidth = size * 0.3;\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n return [\n { x: to.x, y: to.y }, // tip\n {\n x: to.x - halfLength * cos + halfWidth * sin,\n y: to.y - halfLength * sin - halfWidth * cos,\n },\n { x: to.x - size * cos, y: to.y - size * sin }, // back\n {\n x: to.x - halfLength * cos - halfWidth * sin,\n y: to.y - halfLength * sin + halfWidth * cos,\n },\n ];\n}\n\n/**\n * Calculate circle marker center\n */\nexport function calculateCircleMarkerCenter(\n to: Point,\n angle: number,\n size: number\n): Point {\n return {\n x: to.x - size * Math.cos(angle),\n y: to.y - size * Math.sin(angle),\n };\n}\n\n/**\n * Get marker length (how much to shorten the edge line)\n */\nexport function getMarkerLength(config: ArrowMarkerConfig): number {\n const size = config.size ?? 12;\n switch (config.type) {\n case 'arrow':\n return size * Math.cos(ARROW_ANGLE);\n case 'open':\n return 0;\n case 'diamond':\n return size;\n case 'circle':\n return size * 2;\n default:\n return 0;\n }\n}\n\n/**\n * Generate SVG path for arrow marker\n */\nexport function generateSvgArrowMarker(\n to: Point,\n angle: number,\n size: number,\n fill: string,\n fillOpacity: number,\n stroke: string\n): string {\n const { left, right } = calculateArrowMarkerPoints(to, angle, size);\n return `<path d=\"M ${to.x} ${to.y} L ${left.x} ${left.y} L ${right.x} ${right.y} Z\" fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"1\"/>`;\n}\n\n/**\n * Generate SVG path for open arrow marker\n */\nexport function generateSvgOpenArrowMarker(\n to: Point,\n angle: number,\n size: number,\n stroke: string\n): string {\n const { left, right } = calculateArrowMarkerPoints(to, angle, size);\n return `<path d=\"M ${to.x} ${to.y} L ${left.x} ${left.y} M ${to.x} ${to.y} L ${right.x} ${right.y}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>`;\n}\n\n/**\n * Generate SVG path for diamond marker\n */\nexport function generateSvgDiamondMarker(\n to: Point,\n angle: number,\n size: number,\n fill: string,\n fillOpacity: number,\n stroke: string\n): string {\n const points = calculateDiamondMarkerPoints(to, angle, size);\n return `<path d=\"M ${points[0]!.x} ${points[0]!.y} L ${points[1]!.x} ${points[1]!.y} L ${points[2]!.x} ${points[2]!.y} L ${points[3]!.x} ${points[3]!.y} Z\" fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"1\"/>`;\n}\n\n/**\n * Generate SVG circle marker\n */\nexport function generateSvgCircleMarker(\n to: Point,\n angle: number,\n size: number,\n fill: string,\n fillOpacity: number,\n stroke: string\n): string {\n const { x: cx, y: cy } = calculateCircleMarkerCenter(to, angle, size);\n return `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${size}\" fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"1\"/>`;\n}\n\n/**\n * Generate SVG path for any marker type\n */\nexport function generateSvgMarker(\n marker: ArrowMarkerConfig,\n from: Point,\n to: Point,\n edgeStroke: string\n): string {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const size = marker.size ?? 12;\n const stroke = marker.strokeColor ?? edgeStroke;\n const fill = marker.fillColor ?? stroke;\n const fillOpacity = marker.fillOpacity ?? 1;\n\n switch (marker.type) {\n case 'open':\n return generateSvgOpenArrowMarker(to, angle, size, stroke);\n case 'diamond':\n return generateSvgDiamondMarker(to, angle, size, fill, fillOpacity, stroke);\n case 'circle':\n return generateSvgCircleMarker(to, angle, size, fill, fillOpacity, stroke);\n case 'arrow':\n default:\n return generateSvgArrowMarker(to, angle, size, fill, fillOpacity, stroke);\n }\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Point } from '@/types';\nimport type { Edge } from '@/elements/Edge';\nimport type { Node } from '@/elements/Node';\nimport type { Group } from '@/elements/Group';\nimport type { ArrowMarkerConfig, TextStyle } from '@/types';\nimport type { NodeImageOptions, NodeImagePlacement } from '@/elements/NodeImage';\nimport { EDGE_LABEL_BACKGROUND_PADDING, EDGE_LABEL_BACKGROUND_RADIUS } from '@/constants';\nimport { applyStyleManagerToElements } from './style';\nimport { getContentBounds } from './contentBounds';\nimport { downloadBlob } from './download';\nimport { generateSvgMarker, calculateMarkerPoints } from './markers';\n\nexport interface SvgExportOptions {\n padding?: number;\n backgroundColor?: string;\n includeBackground?: boolean;\n /**\n * Global Y-offset override for edge labels in SVG export.\n * If omitted, exporter uses each edge's runtime labelOffset.\n */\n edgeLabelOffset?: number;\n}\n\n/**\n * Exports diagram to SVG\n */\nexport class SvgExporter {\n private renderer: DiagramRenderer;\n\n constructor(renderer: DiagramRenderer) {\n this.renderer = renderer;\n }\n\n exportSVG(options: SvgExportOptions = {}): string {\n const padding = options.padding ?? 20;\n const includeBackground = options.includeBackground ?? true;\n const backgroundColor = options.backgroundColor ?? '#ffffff';\n const edgeLabelOffset = options.edgeLabelOffset;\n\n const bounds = getContentBounds({\n nodes: this.renderer.nodes.values(),\n edges: this.renderer.edges.values(),\n groups: this.renderer.groups.values(),\n });\n if (bounds === null) {\n return this.createEmptySvg(100, 100, backgroundColor, includeBackground);\n }\n\n const width = bounds.width + padding * 2;\n const height = bounds.height + padding * 2;\n const offsetX = -bounds.x + padding;\n const offsetY = -bounds.y + padding;\n\n applyStyleManagerToElements(\n this.renderer.getStyleManager(),\n this.renderer.groups.values(),\n this.renderer.edges.values(),\n this.renderer.nodes.values()\n );\n\n const parts: string[] = [];\n const renderedEdges: string[] = [];\n parts.push(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">`\n );\n for (const edge of this.renderer.edges.values()) {\n if (edge.visible) {\n renderedEdges.push(this.renderEdge(edge, edgeLabelOffset));\n }\n }\n if (includeBackground) {\n parts.push(`<rect width=\"100%\" height=\"100%\" fill=\"${backgroundColor}\"/>`);\n }\n parts.push(`<g transform=\"translate(${offsetX}, ${offsetY})\">`);\n\n for (const group of this.renderer.groups.values()) {\n if (group.visible) {\n parts.push(this.renderGroup(group));\n }\n }\n\n for (const node of this.renderer.nodes.values()) {\n if (node.visible) {\n parts.push(this.renderNode(node));\n }\n }\n\n // Keep SVG layering aligned with canvas renderer: edges above nodes.\n parts.push(...renderedEdges);\n\n parts.push(`</g></svg>`);\n return parts.join('');\n }\n\n exportDataURL(options: SvgExportOptions = {}): string {\n const svg = this.exportSVG(options);\n const encoded = encodeURIComponent(svg);\n return `data:image/svg+xml;charset=utf-8,${encoded}`;\n }\n\n download(filename: string, options: SvgExportOptions = {}): void {\n const svg = this.exportSVG(options);\n const blob = new Blob([svg], { type: 'image/svg+xml' });\n downloadBlob(filename, blob);\n }\n\n private renderGroup(group: Group): string {\n const bounds = group.getBounds();\n const style = group.style;\n const fill = style.fillColor ?? 'rgba(200, 200, 200, 0.2)';\n const stroke = style.strokeColor ?? '#999999';\n const strokeWidth = style.strokeWidth ?? 1;\n const opacity = style.opacity ?? 1;\n\n const label = group.label\n ? `<text x=\"${bounds.x + 8}\" y=\"${bounds.y + 14}\" fill=\"#666666\" font-size=\"12\">${this.escapeText(\n group.label\n )}</text>`\n : '';\n\n return [\n `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`,\n ` fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" opacity=\"${opacity}\"`,\n ` stroke-dasharray=\"4 4\"/>`,\n label,\n ].join('');\n }\n\n private renderNode(node: Node): string {\n const bounds = node.getBounds();\n const style = node.style;\n const fill = style.fillColor ?? '#ffffff';\n const stroke = style.strokeColor ?? '#333333';\n const strokeWidth = style.strokeWidth ?? 2;\n const baseOpacity = style.opacity ?? 1;\n const fillOpacity = (style.fillOpacity ?? 1) * baseOpacity;\n const strokeOpacity = (style.strokeOpacity ?? 1) * baseOpacity;\n const dash = style.lineDash?.length ? ` stroke-dasharray=\"${style.lineDash.join(' ')}\"` : '';\n const dashOffset =\n style.lineDashOffset !== undefined ? ` stroke-dashoffset=\"${style.lineDashOffset}\"` : '';\n\n let shape: string;\n switch (node.typeName) {\n case 'rectangle': {\n const radius = this.getNodeCornerRadius(node, bounds);\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\" rx=\"${radius}\" ry=\"${radius}\"`;\n break;\n }\n case 'circle': {\n const center = node.getCenter();\n shape = `<ellipse cx=\"${center.x}\" cy=\"${center.y}\" rx=\"${bounds.width / 2}\" ry=\"${bounds.height / 2}\"`;\n break;\n }\n case 'diamond': {\n const center = node.getCenter();\n const hw = bounds.width / 2;\n const hh = bounds.height / 2;\n const points = [\n `${center.x},${center.y - hh}`,\n `${center.x + hw},${center.y}`,\n `${center.x},${center.y + hh}`,\n `${center.x - hw},${center.y}`,\n ].join(' ');\n shape = `<polygon points=\"${points}\"`;\n break;\n }\n case 'custom': {\n const svgPath =\n 'getSvgPath' in node && typeof node.getSvgPath === 'function'\n ? (node as { getSvgPath: () => string | null }).getSvgPath()\n : null;\n if (svgPath) {\n shape = `<path d=\"${this.escapeAttribute(svgPath)}\" transform=\"translate(${bounds.x}, ${bounds.y})\"`;\n } else {\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`;\n }\n break;\n }\n default: {\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`;\n }\n }\n\n const label = this.renderNodeLabel(node, bounds);\n const icon = this.renderNodeIcon(node, bounds);\n\n return [\n `${shape} fill=\"${fill}\" fill-opacity=\"${fillOpacity}\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" stroke-opacity=\"${strokeOpacity}\"${dash}${dashOffset}/>`,\n icon,\n label,\n ].join('');\n }\n\n private renderEdge(edge: Edge, edgeLabelOffset?: number): string {\n const path = edge.path;\n if (path.length < 2) {\n return '';\n }\n\n const style = edge.style;\n const stroke = style.strokeColor ?? '#666666';\n const strokeWidth = style.strokeWidth ?? 2;\n const strokeOpacity = (style.strokeOpacity ?? 1) * (style.opacity ?? 1);\n const lineCap = style.lineCap ? ` stroke-linecap=\"${style.lineCap}\"` : '';\n const lineJoin = style.lineJoin ? ` stroke-linejoin=\"${style.lineJoin}\"` : '';\n const dashValues = style.flowDash ?? style.lineDash;\n const dash = dashValues ? ` stroke-dasharray=\"${dashValues.join(' ')}\"` : '';\n const dashOffset =\n style.lineDashOffset !== undefined ? ` stroke-dashoffset=\"${style.lineDashOffset}\"` : '';\n\n const d = this.buildPath(edge);\n const markerShapes = this.renderEdgeMarkers(edge, stroke);\n const label = this.renderEdgeLabel(edge, edgeLabelOffset);\n\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" stroke-opacity=\"${strokeOpacity}\" color=\"${stroke}\"${lineCap}${lineJoin}${dash}${dashOffset}/>${markerShapes}${label}`;\n }\n\n private renderEdgeLabel(edge: Edge, edgeLabelOffset?: number): string {\n if (!edge.label) {\n return '';\n }\n\n const labelPoint = this.getEdgeLabelPoint(edge, edgeLabelOffset);\n const text = this.renderTextLabel(edge.label.text, labelPoint, edge.label.style);\n const bg = this.renderEdgeLabelBackground(edge, labelPoint);\n return `${bg}${text}`;\n }\n\n private renderEdgeLabelBackground(edge: Edge, point: Point): string {\n if (!edge.label) {\n return '';\n }\n\n const metrics = this.measureTextLabel(edge.label.text, edge.label.style, edge.label.padding, edge.label.margin);\n const bgPadding = edge.labelBackground?.padding ?? EDGE_LABEL_BACKGROUND_PADDING;\n const bgColor = edge.labelBackground?.color ?? '#ffffff';\n const bgOpacity = edge.labelBackground?.opacity ?? 1;\n const bgRadius = edge.labelBackground?.borderRadius ?? EDGE_LABEL_BACKGROUND_RADIUS;\n\n const x = point.x - metrics.width / 2 - bgPadding;\n const y = point.y - metrics.height / 2 - bgPadding;\n const width = metrics.width + bgPadding * 2;\n const height = metrics.height + bgPadding * 2;\n const radius = Math.max(0, Math.min(bgRadius, width / 2, height / 2));\n\n if (radius <= 0) {\n return `<rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\" fill=\"${bgColor}\" fill-opacity=\"${bgOpacity}\"/>`;\n }\n\n return `<rect x=\"${x}\" y=\"${y}\" width=\"${width}\" height=\"${height}\" rx=\"${radius}\" ry=\"${radius}\" fill=\"${bgColor}\" fill-opacity=\"${bgOpacity}\"/>`;\n }\n\n private measureTextLabel(\n text: string,\n style: TextStyle = {},\n padding = 8,\n margin = 0\n ): { width: number; height: number } {\n const fontSize = style.fontSize ?? 14;\n const fontFamily = style.fontFamily ?? 'sans-serif';\n const fontWeight = style.fontWeight ?? 'normal';\n const lineHeight = fontSize * 1.2;\n const lines = text.split('\\n');\n let maxWidth = 0;\n\n if (typeof document !== 'undefined') {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n for (const line of lines) {\n maxWidth = Math.max(maxWidth, ctx.measureText(line).width);\n }\n }\n }\n\n if (maxWidth === 0) {\n const longestLine = lines.reduce((max, line) => (line.length > max.length ? line : max), '');\n maxWidth = longestLine.length * fontSize * 0.6;\n }\n\n const resolvedPadding = Math.max(0, padding);\n const resolvedMargin = Math.max(0, margin);\n return {\n width: maxWidth + resolvedPadding * 2 + resolvedMargin * 2,\n height: lines.length * lineHeight + resolvedPadding * 2 + resolvedMargin * 2,\n };\n }\n\n private resolveMarkerConfig(edge: Edge, side: 'start' | 'end'): ArrowMarkerConfig | null {\n const marker = side === 'start' ? edge.startMarker : edge.endMarker;\n if (marker && marker.type !== 'none') {\n return marker;\n }\n\n if (side === 'end') {\n return edge.arrowType === 'none' ? null : { type: 'arrow' };\n }\n\n return edge.arrowType === 'double' ? { type: 'arrow' } : null;\n }\n\n private renderEdgeMarkers(edge: Edge, edgeStroke: string): string {\n const startMarker = this.resolveMarkerConfig(edge, 'start');\n const endMarker = this.resolveMarkerConfig(edge, 'end');\n const parts: string[] = [];\n\n if (endMarker) {\n const points = this.getMarkerPoints(edge, 'end');\n if (points) {\n parts.push(this.renderMarkerShape(endMarker, points.from, points.to, edgeStroke));\n }\n }\n\n if (startMarker) {\n const points = this.getMarkerPoints(edge, 'start');\n if (points) {\n parts.push(this.renderMarkerShape(startMarker, points.from, points.to, edgeStroke));\n }\n }\n\n return parts.join('');\n }\n\n private getMarkerPoints(edge: Edge, position: 'start' | 'end'): { from: Point; to: Point } | null {\n return calculateMarkerPoints(edge.path, position, edge.type);\n }\n\n private renderMarkerShape(\n marker: ArrowMarkerConfig,\n from: Point,\n to: Point,\n edgeStroke: string\n ): string {\n return generateSvgMarker(marker, from, to, edgeStroke);\n }\n\n private buildPath(edge: Edge): string {\n const path = edge.path;\n if (edge.type === 'bezier' && path.length >= 4) {\n let d = `M ${path[0]!.x} ${path[0]!.y}`;\n for (let i = 1; i + 2 < path.length; i += 3) {\n d += ` C ${path[i]!.x} ${path[i]!.y} ${path[i + 1]!.x} ${path[i + 1]!.y} ${path[i + 2]!.x} ${path[i + 2]!.y}`;\n }\n return d;\n }\n\n let d = `M ${path[0]!.x} ${path[0]!.y}`;\n for (let i = 1; i < path.length; i++) {\n d += ` L ${path[i]!.x} ${path[i]!.y}`;\n }\n return d;\n }\n\n private getPathMidpoint(edge: Edge): Point {\n const path = edge.path;\n if (edge.type === 'bezier' && path.length >= 4) {\n const t = 0.5;\n const mt = 1 - t;\n return {\n x:\n mt * mt * mt * path[0]!.x +\n 3 * mt * mt * t * path[1]!.x +\n 3 * mt * t * t * path[2]!.x +\n t * t * t * path[3]!.x,\n y:\n mt * mt * mt * path[0]!.y +\n 3 * mt * mt * t * path[1]!.y +\n 3 * mt * t * t * path[2]!.y +\n t * t * t * path[3]!.y,\n };\n }\n\n let totalLength = 0;\n const segments: { start: Point; end: Point; length: number }[] = [];\n for (let i = 1; i < path.length; i++) {\n const start = path[i - 1]!;\n const end = path[i]!;\n const length = Math.hypot(end.x - start.x, end.y - start.y);\n segments.push({ start, end, length });\n totalLength += length;\n }\n\n const halfLength = totalLength / 2;\n let accumulated = 0;\n\n for (const seg of segments) {\n if (accumulated + seg.length >= halfLength) {\n const t = (halfLength - accumulated) / seg.length;\n return {\n x: seg.start.x + t * (seg.end.x - seg.start.x),\n y: seg.start.y + t * (seg.end.y - seg.start.y),\n };\n }\n accumulated += seg.length;\n }\n\n return path[0]!;\n }\n\n private getEdgeLabelPoint(edge: Edge, edgeLabelOffset?: number): Point {\n const midpoint = this.getPathMidpoint(edge);\n const effectiveOffset = edgeLabelOffset ?? edge.labelOffset ?? 0;\n return {\n x: midpoint.x,\n y: midpoint.y + effectiveOffset,\n };\n }\n\n private renderTextLabel(text: string, point: Point, style: TextStyle = {}): string {\n const fill = style.color ?? '#000000';\n const fontSize = style.fontSize ?? 14;\n const fontFamily = style.fontFamily ?? 'sans-serif';\n const fontWeight = style.fontWeight ?? 'normal';\n const opacity = style.opacity ?? 1;\n const anchor = style.align === 'left' ? 'start' : style.align === 'right' ? 'end' : 'middle';\n const baseline =\n style.baseline === 'top'\n ? 'text-before-edge'\n : style.baseline === 'bottom'\n ? 'text-after-edge'\n : 'middle';\n\n const lines = text.split('\\n');\n if (lines.length <= 1) {\n return `<text x=\"${point.x}\" y=\"${point.y}\" fill=\"${fill}\" fill-opacity=\"${opacity}\" font-size=\"${fontSize}\" font-family=\"${fontFamily}\" font-weight=\"${fontWeight}\" text-anchor=\"${anchor}\" dominant-baseline=\"${baseline}\">${this.escapeText(\n text\n )}</text>`;\n }\n\n const lineHeight = fontSize * 1.2;\n const startY = point.y - ((lines.length - 1) * lineHeight) / 2;\n const tspans = lines\n .map((line, index) => `<tspan x=\"${point.x}\" y=\"${startY + index * lineHeight}\">${this.escapeText(line)}</tspan>`)\n .join('');\n return `<text x=\"${point.x}\" y=\"${point.y}\" fill=\"${fill}\" fill-opacity=\"${opacity}\" font-size=\"${fontSize}\" font-family=\"${fontFamily}\" font-weight=\"${fontWeight}\" text-anchor=\"${anchor}\" dominant-baseline=\"${baseline}\">${tspans}</text>`;\n }\n\n private getMeasurementContext(): CanvasRenderingContext2D | null {\n if (typeof document === 'undefined') {\n return null;\n }\n const canvas = document.createElement('canvas');\n return canvas.getContext('2d');\n }\n\n private renderNodeLabel(node: Node, nodeBounds: { x: number; y: number; width: number; height: number }): string {\n const label = node.label;\n if (!label) {\n return '';\n }\n\n const style = label.style;\n const padding = Math.max(0, label.padding);\n const margin = Math.max(0, label.margin);\n const align = style.align ?? 'center';\n\n const ctx = this.getMeasurementContext();\n let bounds: { x: number; y: number; width: number; height: number };\n let lines: string[];\n\n if (ctx !== null) {\n const result = node.getLabelBoundsForExport(ctx);\n if (result) {\n bounds = result.bounds;\n lines = result.lines;\n } else {\n bounds = nodeBounds;\n lines = label.text.split('\\n');\n }\n } else {\n bounds = nodeBounds;\n lines = label.text.split('\\n');\n }\n\n const inner = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n\n let x = inner.x + inner.width / 2;\n if (align === 'left') {\n x = inner.x + padding;\n } else if (align === 'right') {\n x = inner.x + inner.width - padding;\n }\n\n const y = inner.y + inner.height / 2;\n\n return this.renderTextLabel(lines.join('\\n'), { x, y }, style);\n }\n\n private getNodeCornerRadius(node: Node, bounds: { width: number; height: number }): number {\n const rectangleRadius =\n 'cornerRadius' in node && typeof (node as { cornerRadius?: unknown }).cornerRadius === 'number'\n ? ((node as { cornerRadius: number }).cornerRadius ?? 0)\n : node.style.cornerRadius ?? 0;\n return Math.max(0, Math.min(rectangleRadius, bounds.width / 2, bounds.height / 2));\n }\n\n private renderNodeIcon(node: Node, nodeBounds: { x: number; y: number; width: number; height: number }): string {\n const icon = node.icon;\n if (!icon) {\n return '';\n }\n\n const opts = icon.options;\n const iconSize = icon.getSize();\n if (iconSize.width <= 0 || iconSize.height <= 0) {\n return '';\n }\n\n const iconBoxSize = this.getIconBoxSize(opts, iconSize);\n const iconBounds = this.getIconBounds(nodeBounds, iconBoxSize, opts.placement ?? 'center');\n const drawRect = this.getIconDrawRect(iconBounds, opts, iconSize);\n if (drawRect.width <= 0 || drawRect.height <= 0) {\n return '';\n }\n\n const href = this.resolveIconHref(opts);\n if (!href) {\n return '';\n }\n\n const opacity = opts.opacity ?? 1;\n return `<image href=\"${this.escapeAttribute(href)}\" x=\"${drawRect.x}\" y=\"${drawRect.y}\" width=\"${drawRect.width}\" height=\"${drawRect.height}\" opacity=\"${opacity}\" preserveAspectRatio=\"none\"/>`;\n }\n\n private getIconBoxSize(\n opts: NodeImageOptions,\n imageSize: { width: number; height: number }\n ): { width: number; height: number } {\n const padding = opts.padding ?? 8;\n const margin = Math.max(0, opts.margin ?? 0);\n return {\n width: imageSize.width + padding * 2 + margin * 2,\n height: imageSize.height + padding * 2 + margin * 2,\n };\n }\n\n private getIconBounds(\n bounds: { x: number; y: number; width: number; height: number },\n iconBoxSize: { width: number; height: number },\n placement: NodeImagePlacement\n ): { x: number; y: number; width: number; height: number } {\n switch (placement) {\n case 'top':\n return { x: bounds.x, y: bounds.y, width: bounds.width, height: iconBoxSize.height };\n case 'bottom':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: bounds.width,\n height: iconBoxSize.height,\n };\n case 'left':\n return { x: bounds.x, y: bounds.y, width: iconBoxSize.width, height: bounds.height };\n case 'right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: bounds.height,\n };\n case 'top-left':\n return { x: bounds.x, y: bounds.y, width: iconBoxSize.width, height: iconBoxSize.height };\n case 'top-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-left':\n return {\n x: bounds.x,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'bottom-right':\n return {\n x: bounds.x + bounds.width - iconBoxSize.width,\n y: bounds.y + bounds.height - iconBoxSize.height,\n width: iconBoxSize.width,\n height: iconBoxSize.height,\n };\n case 'center':\n default:\n return bounds;\n }\n }\n\n private getIconDrawRect(\n bounds: { x: number; y: number; width: number; height: number },\n opts: NodeImageOptions,\n imageSize: { width: number; height: number }\n ): { x: number; y: number; width: number; height: number } {\n const padding = opts.padding ?? 8;\n const margin = Math.max(0, opts.margin ?? 0);\n const fit = opts.fit ?? 'none';\n const scaleWithBounds = opts.scaleWithBounds ?? false;\n const align = opts.align ?? 'center';\n const verticalAlign = opts.verticalAlign ?? 'center';\n const offsetX = opts.offsetX ?? 0;\n const offsetY = opts.offsetY ?? 0;\n\n const innerBounds = {\n x: bounds.x + margin,\n y: bounds.y + margin,\n width: Math.max(0, bounds.width - margin * 2),\n height: Math.max(0, bounds.height - margin * 2),\n };\n const availableWidth = Math.max(0, innerBounds.width - padding * 2);\n const availableHeight = Math.max(0, innerBounds.height - padding * 2);\n\n let drawWidth = opts.width ?? imageSize.width;\n let drawHeight = opts.height ?? imageSize.height;\n\n if (scaleWithBounds) {\n if ((fit === 'contain' || fit === 'cover') && imageSize.width > 0 && imageSize.height > 0) {\n const scaleX = availableWidth / imageSize.width;\n const scaleY = availableHeight / imageSize.height;\n const scale = fit === 'contain' ? Math.min(scaleX, scaleY) : Math.max(scaleX, scaleY);\n drawWidth = imageSize.width * scale;\n drawHeight = imageSize.height * scale;\n } else if (fit === 'stretch') {\n drawWidth = availableWidth;\n drawHeight = availableHeight;\n }\n }\n\n drawWidth = Math.min(Math.max(0, drawWidth), Math.max(0, availableWidth));\n drawHeight = Math.min(Math.max(0, drawHeight), Math.max(0, availableHeight));\n\n let x = innerBounds.x + padding;\n let y = innerBounds.y + padding;\n\n if (align === 'center') {\n x = innerBounds.x + (innerBounds.width - drawWidth) / 2;\n } else if (align === 'right') {\n x = innerBounds.x + innerBounds.width - drawWidth - padding;\n }\n\n if (verticalAlign === 'center') {\n y = innerBounds.y + (innerBounds.height - drawHeight) / 2;\n } else if (verticalAlign === 'bottom') {\n y = innerBounds.y + innerBounds.height - drawHeight - padding;\n }\n\n return {\n x: x + offsetX,\n y: y + offsetY,\n width: drawWidth,\n height: drawHeight,\n };\n }\n\n private resolveIconHref(opts: NodeImageOptions): string {\n const source = opts.source;\n if (source instanceof HTMLImageElement) {\n return source.src;\n }\n\n if (!source) {\n return '';\n }\n\n if (this.isSvgMarkup(source)) {\n return this.svgToDataUrl(this.tintSvg(source, opts.strokeColor, opts.fillColor));\n }\n\n const shouldInlineSvg = source.toLowerCase().endsWith('.svg');\n if (shouldInlineSvg) {\n const svgText = this.readSvgFromUrlSync(source);\n if (svgText) {\n return this.svgToDataUrl(this.tintSvg(svgText, opts.strokeColor, opts.fillColor));\n }\n }\n\n return source;\n }\n\n private readSvgFromUrlSync(url: string): string | null {\n if (typeof XMLHttpRequest === 'undefined') {\n return null;\n }\n\n try {\n const xhr = new XMLHttpRequest();\n xhr.open('GET', url, false);\n xhr.send();\n if (xhr.status >= 200 && xhr.status < 300) {\n return xhr.responseText || null;\n }\n } catch {\n // Ignore and fallback to raw URL source.\n }\n\n return null;\n }\n\n private isSvgMarkup(value: string): boolean {\n const trimmed = value.trim().toLowerCase();\n return trimmed.startsWith('<svg') || trimmed.includes('<svg');\n }\n\n private styleSetColor(style: string, key: 'stroke' | 'fill', color: string): string {\n const hasKey = new RegExp(`${key}\\\\s*:`).test(style);\n if (hasKey) {\n return style.replace(new RegExp(`${key}\\\\s*:[^;]+`), `${key}:${color}`);\n }\n const suffix = style.trim().endsWith(';') || style.trim() === '' ? '' : ';';\n return `${style}${suffix}${key}:${color};`;\n }\n\n private tintSvg(svgText: string, strokeColor?: string, fillColor?: string): string {\n if (!strokeColor && !fillColor) return svgText;\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(svgText, 'image/svg+xml');\n const root = doc.documentElement;\n if (!root || root.nodeName.toLowerCase() === 'parsererror') {\n return svgText;\n }\n\n const all = [root, ...Array.from(root.querySelectorAll('*'))] as Element[];\n for (const el of all) {\n const stroke = el.getAttribute('stroke');\n if (strokeColor && stroke !== null && stroke.toLowerCase() !== 'none') {\n el.setAttribute('stroke', strokeColor);\n }\n const fill = el.getAttribute('fill');\n if (fillColor && fill !== null && fill.toLowerCase() !== 'none') {\n el.setAttribute('fill', fillColor);\n }\n const style = el.getAttribute('style');\n if (style) {\n let next = style;\n if (strokeColor && /stroke\\s*:\\s*(?!none)/.test(style)) {\n next = this.styleSetColor(next, 'stroke', strokeColor);\n }\n if (fillColor && /fill\\s*:\\s*(?!none)/.test(style)) {\n next = this.styleSetColor(next, 'fill', fillColor);\n }\n if (next !== style) {\n el.setAttribute('style', next);\n }\n }\n }\n\n return new XMLSerializer().serializeToString(root);\n }\n\n private svgToDataUrl(svg: string): string {\n const encoded = encodeURIComponent(svg)\n .replace(/%0A/g, '')\n .replace(/%0D/g, '')\n .replace(/%09/g, ' ')\n .replace(/%20/g, ' ');\n return `data:image/svg+xml;utf8,${encoded}`;\n }\n\n private escapeAttribute(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/\"/g, '"')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n }\n\n private createEmptySvg(width: number, height: number, backgroundColor: string, includeBackground: boolean): string {\n return [\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">`,\n includeBackground ? `<rect width=\"100%\" height=\"100%\" fill=\"${backgroundColor}\"/>` : '',\n '</svg>',\n ].join('');\n }\n\n private escapeText(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n }\n}\n","import type { Node } from '@/elements/Node';\n\nexport interface GridLayoutOptions {\n columns?: number;\n rowGap?: number;\n columnGap?: number;\n startX?: number;\n startY?: number;\n}\n\n/**\n * Basic auto-layout utilities\n */\nexport class AutoLayout {\n applyGridLayout(nodes: Node[], options: GridLayoutOptions = {}): void {\n if (nodes.length === 0) return;\n\n const columns = options.columns ?? Math.ceil(Math.sqrt(nodes.length));\n const rowGap = options.rowGap ?? 40;\n const columnGap = options.columnGap ?? 40;\n const startX = options.startX ?? 0;\n const startY = options.startY ?? 0;\n\n let col = 0;\n let cursorX = startX;\n let cursorY = startY;\n let currentRowHeight = 0;\n\n for (const node of nodes) {\n node.x = cursorX;\n node.y = cursorY;\n currentRowHeight = Math.max(currentRowHeight, node.height);\n\n col += 1;\n if (col >= columns) {\n col = 0;\n cursorX = startX;\n cursorY += currentRowHeight + rowGap;\n currentRowHeight = 0;\n } else {\n cursorX += node.width + columnGap;\n }\n }\n }\n}\n","import type { DiagramRenderer } from '@/core/DiagramRenderer';\nimport type { Point } from '@/types';\n\nexport interface AutoRoutingOptions {\n type?: 'straight' | 'polyline' | 'bezier';\n}\n\n/**\n * Basic edge auto-routing\n */\nexport class AutoRouting {\n apply(renderer: DiagramRenderer, options: AutoRoutingOptions = {}): void {\n const type = options.type ?? 'polyline';\n\n for (const edge of renderer.edges.values()) {\n edge.type = type;\n\n const fromNode = renderer.getNode(edge.from.nodeId);\n const toNode = renderer.getNode(edge.to.nodeId);\n if (!fromNode || !toNode) continue;\n\n const fromPoint: Point =\n edge.from.portId !== undefined\n ? fromNode.getPortPosition(edge.from.portId) ?? fromNode.getCenter()\n : fromNode.getCenter();\n const toPoint: Point =\n edge.to.portId !== undefined\n ? toNode.getPortPosition(edge.to.portId) ?? toNode.getCenter()\n : toNode.getCenter();\n\n edge.updateEndpoints(fromPoint, toPoint);\n }\n\n renderer.markDirty();\n }\n}\n","import type { Node } from '@/elements/Node';\n\nexport type AlignType = 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom';\nexport type DistributeType = 'horizontal' | 'vertical';\n\n/**\n * Align nodes by edge or center\n */\nexport function alignNodes(nodes: Node[], type: AlignType): void {\n if (nodes.length === 0) return;\n\n switch (type) {\n case 'left': {\n const minX = Math.min(...nodes.map((n) => n.x));\n for (const node of nodes) node.x = minX;\n break;\n }\n case 'center': {\n const centerX = Math.min(...nodes.map((n) => n.x + n.width / 2));\n for (const node of nodes) node.x = centerX - node.width / 2;\n break;\n }\n case 'right': {\n const maxX = Math.max(...nodes.map((n) => n.x + n.width));\n for (const node of nodes) node.x = maxX - node.width;\n break;\n }\n case 'top': {\n const minY = Math.min(...nodes.map((n) => n.y));\n for (const node of nodes) node.y = minY;\n break;\n }\n case 'middle': {\n const centerY = Math.min(...nodes.map((n) => n.y + n.height / 2));\n for (const node of nodes) node.y = centerY - node.height / 2;\n break;\n }\n case 'bottom': {\n const maxY = Math.max(...nodes.map((n) => n.y + n.height));\n for (const node of nodes) node.y = maxY - node.height;\n break;\n }\n }\n}\n\n/**\n * Distribute nodes evenly along axis\n */\nexport function distributeNodes(nodes: Node[], type: DistributeType): void {\n if (nodes.length < 3) return;\n\n if (type === 'horizontal') {\n const sorted = [...nodes].sort((a, b) => a.x - b.x);\n const minX = sorted[0]!.x;\n const maxX = sorted[sorted.length - 1]!.x + sorted[sorted.length - 1]!.width;\n const totalWidth = sorted.reduce((sum, n) => sum + n.width, 0);\n const gap = (maxX - minX - totalWidth) / (sorted.length - 1);\n\n let currentX = minX;\n for (const node of sorted) {\n node.x = currentX;\n currentX += node.width + gap;\n }\n } else {\n const sorted = [...nodes].sort((a, b) => a.y - b.y);\n const minY = sorted[0]!.y;\n const maxY = sorted[sorted.length - 1]!.y + sorted[sorted.length - 1]!.height;\n const totalHeight = sorted.reduce((sum, n) => sum + n.height, 0);\n const gap = (maxY - minY - totalHeight) / (sorted.length - 1);\n\n let currentY = minY;\n for (const node of sorted) {\n node.y = currentY;\n currentY += node.height + gap;\n }\n }\n}\n","import type { DiagramPlugin } from '../DiagramRenderer';\n\n/**\n * Base options for all overlays\n */\nexport interface BaseOverlayOptions {\n enabled?: boolean;\n}\n\n/**\n * Abstract base class for diagram overlays\n * Provides common destroy() and setEnabled() functionality\n */\nexport abstract class BaseOverlay implements DiagramPlugin {\n protected removeOverlay: (() => void) | null = null;\n protected enabled: boolean;\n\n protected constructor(enabled = true) {\n this.enabled = enabled;\n }\n\n abstract install(renderer: Parameters<DiagramPlugin['install']>[0]): void;\n\n destroy(): void {\n this.removeOverlay?.();\n this.removeOverlay = null;\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n }\n}\n","import type { DiagramRenderer } from '../DiagramRenderer';\nimport { BaseOverlay, type BaseOverlayOptions } from './BaseOverlay';\n\nexport interface GridOverlayOptions extends BaseOverlayOptions {\n gridSize?: number;\n color?: string;\n}\n\nexport class GridOverlay extends BaseOverlay {\n private gridSize: number;\n private color: string;\n\n constructor(options: GridOverlayOptions = {}) {\n super(options.enabled ?? true);\n this.gridSize = options.gridSize ?? 20;\n this.color = options.color ?? '#e0e0e0';\n }\n\n setColor(color: string): void {\n this.color = color;\n }\n\n setGridSize(size: number): void {\n this.gridSize = size;\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addUnderlayRenderer((ctx) => {\n if (!this.enabled) {\n return;\n }\n\n const width = renderer.width;\n const height = renderer.height;\n const gridSize = this.gridSize;\n const color = this.color;\n\n const startX = Math.floor(-renderer.offsetX / renderer.zoom / gridSize) * gridSize;\n const startY = Math.floor(-renderer.offsetY / renderer.zoom / gridSize) * gridSize;\n const endX = Math.ceil((width - renderer.offsetX) / renderer.zoom / gridSize) * gridSize;\n const endY = Math.ceil((height - renderer.offsetY) / renderer.zoom / gridSize) * gridSize;\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1 / renderer.zoom;\n ctx.beginPath();\n\n for (let x = startX; x <= endX; x += gridSize) {\n ctx.moveTo(x, startY);\n ctx.lineTo(x, endY);\n }\n\n for (let y = startY; y <= endY; y += gridSize) {\n ctx.moveTo(startX, y);\n ctx.lineTo(endX, y);\n }\n\n ctx.stroke();\n });\n }\n}\n","import type { DiagramRenderer } from '../DiagramRenderer';\nimport { BaseOverlay, type BaseOverlayOptions } from './BaseOverlay';\n\nexport interface RulersOverlayOptions extends BaseOverlayOptions {\n thickness?: number;\n backgroundColor?: string;\n textColor?: string;\n tickColor?: string;\n}\n\nexport class RulersOverlay extends BaseOverlay {\n private readonly thickness: number;\n private readonly backgroundColor: string;\n private readonly textColor: string;\n private readonly tickColor: string;\n\n constructor(options: RulersOverlayOptions = {}) {\n super(options.enabled ?? true);\n this.thickness = options.thickness ?? 20;\n this.backgroundColor = options.backgroundColor ?? '#f4f4f5';\n this.textColor = options.textColor ?? '#52525b';\n this.tickColor = options.tickColor ?? '#a1a1aa';\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addOverlayRenderer((ctx) => {\n if (!this.enabled) return;\n\n const thickness = this.thickness;\n ctx.save();\n ctx.setTransform(renderer.pixelRatio, 0, 0, renderer.pixelRatio, 0, 0);\n\n ctx.fillStyle = this.backgroundColor;\n ctx.fillRect(0, 0, renderer.width, thickness);\n ctx.fillRect(0, 0, thickness, renderer.height);\n\n ctx.strokeStyle = this.tickColor;\n ctx.fillStyle = this.textColor;\n ctx.font = '10px sans-serif';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n\n const step = this.getTickStep(renderer.zoom);\n const worldLeft = -renderer.offsetX / renderer.zoom;\n const worldTop = -renderer.offsetY / renderer.zoom;\n const worldRight = worldLeft + renderer.width / renderer.zoom;\n const worldBottom = worldTop + renderer.height / renderer.zoom;\n\n ctx.beginPath();\n for (let x = Math.floor(worldLeft / step) * step; x <= worldRight; x += step) {\n const screenX = x * renderer.zoom + renderer.offsetX;\n ctx.moveTo(screenX, thickness);\n ctx.lineTo(screenX, thickness - 6);\n ctx.fillText(`${Math.round(x)}`, screenX + 2, 2);\n }\n\n for (let y = Math.floor(worldTop / step) * step; y <= worldBottom; y += step) {\n const screenY = y * renderer.zoom + renderer.offsetY;\n ctx.moveTo(thickness, screenY);\n ctx.lineTo(thickness - 6, screenY);\n ctx.save();\n ctx.translate(2, screenY + 2);\n ctx.rotate(-Math.PI / 2);\n ctx.fillText(`${Math.round(y)}`, 0, 0);\n ctx.restore();\n }\n\n ctx.stroke();\n ctx.restore();\n });\n }\n\n private getTickStep(zoom: number): number {\n const targetPx = 80;\n const rawStep = targetPx / zoom;\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n if (normalized < 1.5) return magnitude;\n if (normalized < 3) return 2 * magnitude;\n if (normalized < 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n}\n","import type { DiagramRenderer } from '../DiagramRenderer';\nimport { BaseOverlay, type BaseOverlayOptions } from './BaseOverlay';\n\nexport interface GuidesOverlayOptions extends BaseOverlayOptions {\n vertical?: number[];\n horizontal?: number[];\n color?: string;\n lineWidth?: number;\n}\n\nexport class GuidesOverlay extends BaseOverlay {\n private vertical: number[];\n private horizontal: number[];\n private readonly color: string;\n private readonly lineWidth: number;\n\n constructor(options: GuidesOverlayOptions = {}) {\n super(options.enabled ?? true);\n this.vertical = options.vertical ?? [];\n this.horizontal = options.horizontal ?? [];\n this.color = options.color ?? 'rgba(59, 130, 246, 0.5)';\n this.lineWidth = options.lineWidth ?? 1;\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addOverlayRenderer((ctx) => {\n if (!this.enabled) return;\n\n ctx.save();\n ctx.strokeStyle = this.color;\n ctx.lineWidth = this.lineWidth / renderer.zoom;\n ctx.beginPath();\n\n const worldLeft = -renderer.offsetX / renderer.zoom;\n const worldTop = -renderer.offsetY / renderer.zoom;\n const worldRight = worldLeft + renderer.width / renderer.zoom;\n const worldBottom = worldTop + renderer.height / renderer.zoom;\n\n for (const x of this.vertical) {\n if (x < worldLeft || x > worldRight) continue;\n ctx.moveTo(x, worldTop);\n ctx.lineTo(x, worldBottom);\n }\n\n for (const y of this.horizontal) {\n if (y < worldTop || y > worldBottom) continue;\n ctx.moveTo(worldLeft, y);\n ctx.lineTo(worldRight, y);\n }\n\n ctx.stroke();\n ctx.restore();\n });\n }\n\n setGuides(vertical: number[], horizontal: number[]): void {\n this.vertical = vertical;\n this.horizontal = horizontal;\n }\n}\n","import type { DiagramPlugin, DiagramRenderer } from '../DiagramRenderer';\nimport type { Bounds } from '@/types';\nimport { getContentBounds } from '@/utils/contentBounds';\n\nexport type MiniMapAnchor = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n\nexport interface MiniMapOptions {\n enabled?: boolean;\n width?: number;\n height?: number;\n padding?: number;\n /** Отступ (в мировых координатах) вокруг контента — расширяет область, в пределах которой можно перемещать view. По умолчанию 0. */\n contentMargin?: number;\n backgroundColor?: string;\n borderColor?: string;\n viewportColor?: string;\n anchor?: MiniMapAnchor;\n}\n\ninterface MiniMapLayout {\n x: number;\n y: number;\n width: number;\n height: number;\n bounds: Bounds;\n scale: number;\n mapOffsetX: number;\n mapOffsetY: number;\n viewportBounds: Bounds;\n viewRect: Bounds;\n}\n\ninterface MiniMapDragPayload {\n pointerOffsetX: number;\n pointerOffsetY: number;\n}\n\nexport class MiniMap implements DiagramPlugin {\n private readonly options: Required<MiniMapOptions>;\n private removeOverlay: (() => void) | null = null;\n\n constructor(options: MiniMapOptions = {}) {\n this.options = {\n enabled: options.enabled ?? true,\n width: options.width ?? 180,\n height: options.height ?? 120,\n padding: options.padding ?? 12,\n contentMargin: options.contentMargin ?? 0,\n backgroundColor: options.backgroundColor ?? 'rgba(24, 24, 27, 0.5)',\n borderColor: options.borderColor ?? '#52525b',\n viewportColor: options.viewportColor ?? '#22c55e',\n anchor: options.anchor ?? 'bottom-right',\n };\n }\n\n install(renderer: DiagramRenderer): void {\n this.removeOverlay = renderer.addOverlayRenderer((ctx) => {\n if (!this.options.enabled) return;\n const layout = this.computeLayout(renderer);\n if (!layout) return;\n const { x, y, width, height, bounds, scale, mapOffsetX, mapOffsetY, viewRect } = layout;\n\n ctx.save();\n ctx.setTransform(renderer.pixelRatio, 0, 0, renderer.pixelRatio, 0, 0);\n // MiniMap frame must remain solid even if main canvas rendered dashed edges before.\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n\n ctx.fillStyle = this.options.backgroundColor;\n ctx.fillRect(x, y, width, height);\n ctx.strokeStyle = this.options.borderColor;\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n\n ctx.save();\n ctx.translate(mapOffsetX, mapOffsetY);\n ctx.scale(scale, scale);\n ctx.translate(-bounds.x, -bounds.y);\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n\n ctx.strokeStyle = '#94a3b8';\n ctx.lineWidth = 1 / scale;\n\n for (const edge of renderer.edges.values()) {\n if (!edge.visible) continue;\n const path = edge.path;\n if (path.length < 2) continue;\n ctx.beginPath();\n ctx.moveTo(path[0]!.x, path[0]!.y);\n for (let i = 1; i < path.length; i++) {\n ctx.lineTo(path[i]!.x, path[i]!.y);\n }\n ctx.stroke();\n }\n\n for (const node of renderer.nodes.values()) {\n if (!node.visible) continue;\n const b = node.getBounds();\n ctx.fillStyle = '#e2e8f0';\n ctx.fillRect(b.x, b.y, b.width, b.height);\n }\n\n ctx.restore();\n\n if (viewRect.width < 0 || viewRect.height < 0) {\n ctx.restore();\n return;\n }\n\n ctx.strokeStyle = this.options.viewportColor;\n ctx.lineWidth = 1.5;\n ctx.setLineDash([]);\n ctx.lineDashOffset = 0;\n ctx.strokeRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);\n\n ctx.restore();\n });\n }\n\n destroy(): void {\n this.removeOverlay?.();\n this.removeOverlay = null;\n }\n\n setEnabled(enabled: boolean): void {\n this.options.enabled = enabled;\n }\n\n beginOverlayDrag(\n renderer: DiagramRenderer,\n screenX: number,\n screenY: number\n ): MiniMapDragPayload | null {\n if (!this.options.enabled) {\n return null;\n }\n const layout = this.computeLayout(renderer);\n if (!layout) {\n return null;\n }\n const point = renderer.screenToCanvas(screenX, screenY);\n if (!point) {\n return null;\n }\n\n const insideViewport =\n point.x >= layout.viewRect.x &&\n point.x <= layout.viewRect.x + layout.viewRect.width &&\n point.y >= layout.viewRect.y &&\n point.y <= layout.viewRect.y + layout.viewRect.height;\n if (!insideViewport) {\n return null;\n }\n\n return {\n pointerOffsetX: point.x - layout.viewRect.x,\n pointerOffsetY: point.y - layout.viewRect.y,\n };\n }\n\n updateOverlayDrag(\n renderer: DiagramRenderer,\n screenX: number,\n screenY: number,\n payload: unknown\n ): boolean {\n if (!this.options.enabled) {\n return false;\n }\n if (\n typeof payload !== 'object' ||\n payload === null ||\n !('pointerOffsetX' in payload) ||\n !('pointerOffsetY' in payload)\n ) {\n return false;\n }\n const dragPayload = payload as MiniMapDragPayload;\n const layout = this.computeLayout(renderer);\n if (!layout) {\n return false;\n }\n const point = renderer.screenToCanvas(screenX, screenY);\n if (!point) {\n return false;\n }\n\n const desiredViewX = point.x - dragPayload.pointerOffsetX;\n const desiredViewY = point.y - dragPayload.pointerOffsetY;\n const desiredViewportX = layout.bounds.x + (desiredViewX - layout.mapOffsetX) / layout.scale;\n const desiredViewportY = layout.bounds.y + (desiredViewY - layout.mapOffsetY) / layout.scale;\n const maxScrollX = Math.max(0, layout.bounds.width - layout.viewportBounds.width);\n const maxScrollY = Math.max(0, layout.bounds.height - layout.viewportBounds.height);\n const clampedViewportX = Math.min(\n Math.max(desiredViewportX, layout.bounds.x),\n layout.bounds.x + maxScrollX\n );\n const clampedViewportY = Math.min(\n Math.max(desiredViewportY, layout.bounds.y),\n layout.bounds.y + maxScrollY\n );\n\n renderer.offsetX = -clampedViewportX * renderer.zoom;\n renderer.offsetY = -clampedViewportY * renderer.zoom;\n return true;\n }\n\n private getViewportBounds(renderer: DiagramRenderer): Bounds {\n return {\n x: -renderer.offsetX / renderer.zoom,\n y: -renderer.offsetY / renderer.zoom,\n width: renderer.width / renderer.zoom,\n height: renderer.height / renderer.zoom,\n };\n }\n\n private computeLayout(renderer: DiagramRenderer): MiniMapLayout | null {\n const rawBounds = getContentBounds({\n nodes: renderer.nodes.values(),\n edges: renderer.edges.values(),\n groups: renderer.groups.values(),\n });\n if (!rawBounds) {\n return null;\n }\n\n const margin = this.options.contentMargin;\n const expandedContentBounds = {\n x: rawBounds.x - margin,\n y: rawBounds.y - margin,\n width: rawBounds.width + 2 * margin,\n height: rawBounds.height + 2 * margin,\n };\n\n const { width, height, padding, anchor } = this.options;\n const x =\n anchor === 'bottom-left' || anchor === 'top-left' ? padding : renderer.width - width - padding;\n const y =\n anchor === 'top-left' || anchor === 'top-right' ? padding : renderer.height - height - padding;\n\n const viewportBounds = this.getViewportBounds(renderer);\n const unionMinX = Math.min(expandedContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(expandedContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(\n expandedContentBounds.x + expandedContentBounds.width,\n viewportBounds.x + viewportBounds.width\n );\n const unionMaxY = Math.max(\n expandedContentBounds.y + expandedContentBounds.height,\n viewportBounds.y + viewportBounds.height\n );\n const bounds = {\n x: unionMinX,\n y: unionMinY,\n width: unionMaxX - unionMinX,\n height: unionMaxY - unionMinY,\n };\n\n const scale = Math.min(width / bounds.width, height / bounds.height);\n const mapOffsetX = x + (width - bounds.width * scale) / 2;\n const mapOffsetY = y + (height - bounds.height * scale) / 2;\n\n let viewX = mapOffsetX + (viewportBounds.x - bounds.x) * scale;\n let viewY = mapOffsetY + (viewportBounds.y - bounds.y) * scale;\n let viewW = viewportBounds.width * scale;\n let viewH = viewportBounds.height * scale;\n\n const minX = x;\n const minY = y;\n const maxX = x + width;\n const maxY = y + height;\n\n if (viewX < minX) {\n viewW -= minX - viewX;\n viewX = minX;\n }\n if (viewY < minY) {\n viewH -= minY - viewY;\n viewY = minY;\n }\n if (viewX + viewW > maxX) {\n viewW = maxX - viewX;\n }\n if (viewY + viewH > maxY) {\n viewH = maxY - viewY;\n }\n\n return {\n x,\n y,\n width,\n height,\n bounds,\n scale,\n mapOffsetX,\n mapOffsetY,\n viewportBounds,\n viewRect: {\n x: viewX,\n y: viewY,\n width: viewW,\n height: viewH,\n },\n };\n }\n}\n","import type { NodeStyle, EdgeStyle } from '@/types';\n\n/**\n * Apply node style to canvas context\n * Returns the base opacity for fill/stroke calculations\n */\nexport function applyNodeStyle(\n ctx: CanvasRenderingContext2D,\n style: NodeStyle,\n state: 'normal' | 'hover' | 'selected' | 'dragging'\n): number {\n ctx.fillStyle = style.fillColor ?? '#ffffff';\n ctx.strokeStyle = style.strokeColor ?? '#333333';\n ctx.lineWidth = style.strokeWidth ?? 2;\n\n const baseOpacity = style.opacity ?? 1;\n ctx.globalAlpha = baseOpacity;\n\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n }\n\n // Highlight for hover state\n if (state === 'hover') {\n ctx.strokeStyle = '#6366f1';\n }\n\n return baseOpacity;\n}\n\n/**\n * Apply fill and stroke with opacity\n */\nexport function renderFillAndStroke(\n ctx: CanvasRenderingContext2D,\n baseOpacity: number,\n fillOpacity = 1,\n strokeOpacity = 1\n): void {\n ctx.globalAlpha = baseOpacity * fillOpacity;\n ctx.fill();\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n ctx.stroke();\n ctx.globalAlpha = 1;\n}\n\n/**\n * Apply edge style to canvas context\n */\nexport function applyEdgeStyle(\n ctx: CanvasRenderingContext2D,\n style: EdgeStyle\n): number {\n ctx.strokeStyle = style.strokeColor ?? '#666666';\n ctx.lineWidth = style.strokeWidth ?? 2;\n\n const baseOpacity = style.opacity ?? 1;\n const strokeOpacity = style.strokeOpacity ?? 1;\n ctx.globalAlpha = baseOpacity * strokeOpacity;\n\n if (style.lineDash !== undefined && style.lineDash.length > 0) {\n ctx.setLineDash(style.lineDash);\n } else {\n ctx.setLineDash([]);\n }\n\n if (style.lineDashOffset !== undefined) {\n ctx.lineDashOffset = style.lineDashOffset;\n }\n\n if (style.lineCap !== undefined) {\n ctx.lineCap = style.lineCap;\n }\n\n if (style.lineJoin !== undefined) {\n ctx.lineJoin = style.lineJoin;\n }\n\n return baseOpacity * strokeOpacity;\n}\n"],"names":["distance","i","point","SELF_LOOP_MIN_DISTANCE","SELF_LOOP_OFFSET","SELF_LOOP_SPREAD","CORNER_BYPASS_DISTANCE","CORNER_BYPASS_CLEARANCE","OPPOSITE_BYPASS_DISTANCE","OPPOSITE_BYPASS_CLEARANCE","OPPOSITE_BYPASS_ARC","dirToVector","end","angle","DEFAULT_OPTIONS","segStartParam","param","d"],"mappings":"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"}
|