@ngroznykh/papirus 0.1.0

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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/README.ru.md +178 -0
  4. package/dist/constants.d.ts +21 -0
  5. package/dist/constants.d.ts.map +1 -0
  6. package/dist/core/AnimationManager.d.ts +24 -0
  7. package/dist/core/AnimationManager.d.ts.map +1 -0
  8. package/dist/core/ConnectionManager.d.ts +139 -0
  9. package/dist/core/ConnectionManager.d.ts.map +1 -0
  10. package/dist/core/ContextMenuManager.d.ts +72 -0
  11. package/dist/core/ContextMenuManager.d.ts.map +1 -0
  12. package/dist/core/DiagramRenderer.d.ts +230 -0
  13. package/dist/core/DiagramRenderer.d.ts.map +1 -0
  14. package/dist/core/DragManager.d.ts +67 -0
  15. package/dist/core/DragManager.d.ts.map +1 -0
  16. package/dist/core/HistoryManager.d.ts +61 -0
  17. package/dist/core/HistoryManager.d.ts.map +1 -0
  18. package/dist/core/InteractionManager.d.ts +78 -0
  19. package/dist/core/InteractionManager.d.ts.map +1 -0
  20. package/dist/core/NavigationManager.d.ts +89 -0
  21. package/dist/core/NavigationManager.d.ts.map +1 -0
  22. package/dist/core/ResizeManager.d.ts +72 -0
  23. package/dist/core/ResizeManager.d.ts.map +1 -0
  24. package/dist/core/SearchManager.d.ts +61 -0
  25. package/dist/core/SearchManager.d.ts.map +1 -0
  26. package/dist/core/SelectionManager.d.ts +86 -0
  27. package/dist/core/SelectionManager.d.ts.map +1 -0
  28. package/dist/core/history/commands.d.ts +140 -0
  29. package/dist/core/history/commands.d.ts.map +1 -0
  30. package/dist/core/overlays/BaseOverlay.d.ts +20 -0
  31. package/dist/core/overlays/BaseOverlay.d.ts.map +1 -0
  32. package/dist/core/overlays/GridOverlay.d.ts +15 -0
  33. package/dist/core/overlays/GridOverlay.d.ts.map +1 -0
  34. package/dist/core/overlays/GuidesOverlay.d.ts +18 -0
  35. package/dist/core/overlays/GuidesOverlay.d.ts.map +1 -0
  36. package/dist/core/overlays/MiniMap.d.ts +22 -0
  37. package/dist/core/overlays/MiniMap.d.ts.map +1 -0
  38. package/dist/core/overlays/RulersOverlay.d.ts +18 -0
  39. package/dist/core/overlays/RulersOverlay.d.ts.map +1 -0
  40. package/dist/elements/Edge.d.ts +182 -0
  41. package/dist/elements/Edge.d.ts.map +1 -0
  42. package/dist/elements/Element.d.ts +131 -0
  43. package/dist/elements/Element.d.ts.map +1 -0
  44. package/dist/elements/Group.d.ts +65 -0
  45. package/dist/elements/Group.d.ts.map +1 -0
  46. package/dist/elements/Node.d.ts +188 -0
  47. package/dist/elements/Node.d.ts.map +1 -0
  48. package/dist/elements/NodeImage.d.ts +51 -0
  49. package/dist/elements/NodeImage.d.ts.map +1 -0
  50. package/dist/elements/Port.d.ts +72 -0
  51. package/dist/elements/Port.d.ts.map +1 -0
  52. package/dist/elements/TextLabel.d.ts +85 -0
  53. package/dist/elements/TextLabel.d.ts.map +1 -0
  54. package/dist/elements/nodes/CircleNode.d.ts +21 -0
  55. package/dist/elements/nodes/CircleNode.d.ts.map +1 -0
  56. package/dist/elements/nodes/CustomShapeNode.d.ts +48 -0
  57. package/dist/elements/nodes/CustomShapeNode.d.ts.map +1 -0
  58. package/dist/elements/nodes/DiamondNode.d.ts +13 -0
  59. package/dist/elements/nodes/DiamondNode.d.ts.map +1 -0
  60. package/dist/elements/nodes/RectangleNode.d.ts +19 -0
  61. package/dist/elements/nodes/RectangleNode.d.ts.map +1 -0
  62. package/dist/elements/paths/BezierPathStrategy.d.ts +10 -0
  63. package/dist/elements/paths/BezierPathStrategy.d.ts.map +1 -0
  64. package/dist/elements/paths/PathStrategy.d.ts +12 -0
  65. package/dist/elements/paths/PathStrategy.d.ts.map +1 -0
  66. package/dist/elements/paths/PolylinePathStrategy.d.ts +11 -0
  67. package/dist/elements/paths/PolylinePathStrategy.d.ts.map +1 -0
  68. package/dist/elements/paths/StraightPathStrategy.d.ts +10 -0
  69. package/dist/elements/paths/StraightPathStrategy.d.ts.map +1 -0
  70. package/dist/elements/paths/index.d.ts +5 -0
  71. package/dist/elements/paths/index.d.ts.map +1 -0
  72. package/dist/events/EventEmitter.d.ts +46 -0
  73. package/dist/events/EventEmitter.d.ts.map +1 -0
  74. package/dist/events/InputHandler.d.ts +97 -0
  75. package/dist/events/InputHandler.d.ts.map +1 -0
  76. package/dist/index.d.ts +71 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/papirus.js +8419 -0
  79. package/dist/papirus.js.map +1 -0
  80. package/dist/styles/StyleManager.d.ts +119 -0
  81. package/dist/styles/StyleManager.d.ts.map +1 -0
  82. package/dist/types.d.ts +329 -0
  83. package/dist/types.d.ts.map +1 -0
  84. package/dist/utils/AlignDistribute.d.ts +12 -0
  85. package/dist/utils/AlignDistribute.d.ts.map +1 -0
  86. package/dist/utils/AutoLayout.d.ts +15 -0
  87. package/dist/utils/AutoLayout.d.ts.map +1 -0
  88. package/dist/utils/AutoRouting.d.ts +11 -0
  89. package/dist/utils/AutoRouting.d.ts.map +1 -0
  90. package/dist/utils/ImageExporter.d.ts +34 -0
  91. package/dist/utils/ImageExporter.d.ts.map +1 -0
  92. package/dist/utils/Serializer.d.ts +63 -0
  93. package/dist/utils/Serializer.d.ts.map +1 -0
  94. package/dist/utils/SvgExporter.d.ts +26 -0
  95. package/dist/utils/SvgExporter.d.ts.map +1 -0
  96. package/dist/utils/applyStyleManager.d.ts +6 -0
  97. package/dist/utils/applyStyleManager.d.ts.map +1 -0
  98. package/dist/utils/contentBounds.d.ts +13 -0
  99. package/dist/utils/contentBounds.d.ts.map +1 -0
  100. package/dist/utils/download.d.ts +2 -0
  101. package/dist/utils/download.d.ts.map +1 -0
  102. package/dist/utils/geometry.d.ts +71 -0
  103. package/dist/utils/geometry.d.ts.map +1 -0
  104. package/dist/utils/style.d.ts +2 -0
  105. package/dist/utils/style.d.ts.map +1 -0
  106. package/package.json +69 -0
@@ -0,0 +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/elements/paths/PolylinePathStrategy.ts","../src/elements/paths/BezierPathStrategy.ts","../src/elements/Edge.ts","../src/core/InteractionManager.ts","../src/utils/applyStyleManager.ts","../src/core/AnimationManager.ts","../src/core/ContextMenuManager.ts","../src/core/DiagramRenderer.ts","../src/core/SearchManager.ts","../src/elements/Port.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/Serializer.ts","../src/utils/download.ts","../src/utils/ImageExporter.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"],"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 * Centralized constants for the diagram library\n */\n\n// Edge rendering\nexport const EDGE_HANDLE_RADIUS = 6;\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// Selection\nexport const SELECTION_RECT_MIN_SIZE = 1;\nexport const DEFAULT_SELECTION_COLOR = '#3b82f6';\nexport const DEFAULT_HOVER_COLOR = '#6366f1';\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 }\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 { Point } from '@/types';\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}\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\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 _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 }\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 /**\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 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 = 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 dx = point.x - this.dragStartPoint.x;\n const dy = point.y - this.dragStartPoint.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance < 3) {\n return false;\n }\n\n // Start dragging\n this.isDragging = true;\n this._handledMouseDown = true; // Mark as handled now that drag started\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 // Move nodes using initial position + total offset\n for (const node of this.draggedNodes) {\n const initial = this.initialPositions.get(node.id);\n if (initial === undefined) continue;\n\n let newX = initial.x + totalDelta.x;\n let newY = initial.y + totalDelta.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 }\n\n this.lastDragPoint = point;\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 }\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.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","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';\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 dx = point.x - this.startPoint.x;\n const dy = point.y - this.startPoint.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n if (distance < 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 { ANCHOR_PORT_PREFIX, EDGE_HANDLE_RADIUS, ANCHOR_POINT_RADIUS, ANCHOR_POINT_HOVER_RADIUS, ANCHOR_POINT_HITBOX_RADIUS, BEZIER_MAX_OFFSET } from '@/constants';\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}\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\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\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 }\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 * Handle mouse down on a node\n */\n handleNodeMouseDown(event: InputEvent, node: Node): boolean {\n this.sourceNode = node;\n this.isConnecting = true;\n const target = { x: event.worldX, y: event.worldY };\n const anchor = node.getNearestAnchor(target);\n this.sourceAnchorId = anchor?.id ?? null;\n this.sourcePoint = anchor?.point ?? node.getConnectionPoint(target);\n this.previewEndpoint = target;\n\n this.emit('connectionStart', node);\n return true;\n }\n\n /**\n * Check if mouse is over a port and start connection\n */\n tryStartConnection(event: InputEvent): boolean {\n const point = { x: event.worldX, y: event.worldY };\n\n // First check if clicking on edge handle for reconnection\n if (this.tryStartReconnection(event)) {\n return true;\n }\n\n const node = this.getNodeAtPoint(point, false);\n if (node) {\n return this.handleNodeMouseDown(event, node);\n }\n\n return false;\n }\n\n /**\n * Try to start connection from a hovered anchor point\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 const hover = this.getAnchorAtPoint(node, point);\n if (!hover) {\n return false;\n }\n\n this.sourceNode = node;\n this.isConnecting = true;\n this.sourceAnchorId = hover.id;\n this.sourcePoint = hover.point;\n this.previewEndpoint = point;\n\n this.emit('connectionStart', node);\n this.renderer.markDirty();\n return true;\n }\n\n /**\n * Try to start edge reconnection from handle\n */\n tryStartReconnection(event: InputEvent): boolean {\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 // Try to snap to nearest anchor point on target node\n let snappedPoint = point;\n let snappedDir: string | undefined;\n const targetNode = this.getNodeAtPoint(point, true);\n if (targetNode) {\n const nearestAnchor = targetNode.getNearestAnchor(point);\n if (nearestAnchor) {\n snappedPoint = nearestAnchor.point;\n snappedDir = nearestAnchor.id.split(':')[0];\n }\n }\n\n this.reconnectPoint = snappedPoint;\n\n if (this.reconnectingEndpoint === 'start') {\n if (toNode) {\n const toAnchorId = edge.to.portId?.replace(ANCHOR_PORT_PREFIX, '');\n const target = toAnchorId\n ? toNode.getAnchorPointById(toAnchorId) ?? toNode.getConnectionPoint(snappedPoint)\n : toNode.getConnectionPoint(snappedPoint);\n const toDir = toAnchorId?.split(':')[0];\n edge.updateEndpoints(snappedPoint, target, snappedDir, toDir);\n }\n } else {\n if (fromNode) {\n const fromAnchorId = edge.from.portId?.replace(ANCHOR_PORT_PREFIX, '');\n const start = fromAnchorId\n ? fromNode.getAnchorPointById(fromAnchorId) ?? fromNode.getConnectionPoint(snappedPoint)\n : fromNode.getConnectionPoint(snappedPoint);\n const fromDir = fromAnchorId?.split(':')[0];\n edge.updateEndpoints(start, snappedPoint, fromDir, snappedDir);\n }\n }\n\n this.renderer.markDirty();\n }\n\n /**\n * Handle mouse move during connection\n */\n handleMouseMove(event: InputEvent): boolean {\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 // Try to snap to nearest anchor point on target node\n let snappedPoint = cursorPoint;\n this.previewTargetAnchorId = null;\n const targetNode = this.getNodeAtPoint(cursorPoint, false);\n if (targetNode && this.isCompatibleTarget(targetNode)) {\n const forbidden = this._connectionValidator && this.sourceNode &&\n !this._connectionValidator(this.sourceNode.id, targetNode.id);\n if (forbidden) {\n this.setCursor('not-allowed');\n } else {\n this.setCursor('crosshair');\n const nearestAnchor = targetNode.getNearestAnchor(cursorPoint);\n if (nearestAnchor) {\n snappedPoint = nearestAnchor.point;\n this.previewTargetAnchorId = nearestAnchor.id;\n }\n }\n } else {\n this.setCursor('crosshair');\n }\n\n this.previewEndpoint = snappedPoint;\n // Only update source point if we didn't start from a specific anchor\n if (this.sourceNode && !this.sourceAnchorId) {\n this.sourcePoint = this.sourceNode.getConnectionPoint(this.previewEndpoint);\n }\n\n this.emit(\n 'connectionMove',\n this.sourcePoint!,\n this.previewEndpoint\n );\n this.renderer.markDirty();\n\n return true;\n }\n\n /**\n * Get the node ID at the other end of the reconnecting edge\n */\n private getOtherNodeId(): string | null {\n if (!this.reconnectingEdge) return null;\n return this.reconnectingEndpoint === 'start'\n ? this.reconnectingEdge.to.nodeId\n : this.reconnectingEdge.from.nodeId;\n }\n\n /**\n * Handle mouse up to complete or cancel connection\n */\n handleMouseUp(event: InputEvent): boolean {\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 const node = this.getNodeAtPoint(point, true);\n if (node) {\n const anchor = node.getNearestAnchor(point);\n // Update the edge endpoint\n if (this.reconnectingEndpoint === 'start') {\n this.reconnectingEdge.from = {\n nodeId: node.id,\n portId:\n this.reconnectingEdge.lockAnchors && anchor\n ? `${ANCHOR_PORT_PREFIX}${anchor.id}`\n : undefined,\n };\n } else {\n this.reconnectingEdge.to = {\n nodeId: node.id,\n portId:\n this.reconnectingEdge.lockAnchors && anchor\n ? `${ANCHOR_PORT_PREFIX}${anchor.id}`\n : undefined,\n };\n }\n reconnected = true;\n this.emit('edgeReconnect', this.reconnectingEdge, this.reconnectingEndpoint!);\n }\n\n // If not dropped on valid port, restore original endpoint\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 // Emit to trigger updateEdgePaths and restore original position\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 // Check if we're over a valid target node\n const targetNode = this.getNodeAtPoint(point, false);\n if (targetNode) {\n // Check validator if set\n const allowed = !this._connectionValidator ||\n this._connectionValidator(this.sourceNode!.id, targetNode.id);\n if (allowed) {\n // Create the edge\n const targetAnchor = targetNode.getNearestAnchor(point);\n const from: EdgeEndpoint = {\n nodeId: this.sourceNode!.id,\n portId: this.sourceAnchorId ? `${ANCHOR_PORT_PREFIX}${this.sourceAnchorId}` : undefined,\n };\n const to: EdgeEndpoint = {\n nodeId: targetNode.id,\n portId: targetAnchor ? `${ANCHOR_PORT_PREFIX}${targetAnchor.id}` : 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 this.renderAnchorHighlights(ctx, this.reconnectPoint, true);\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 // Extract directions from anchor IDs\n const fromDir = this.sourceAnchorId?.split(':')[0];\n const toDir = 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 this.renderAnchorHighlights(ctx, end, false);\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 dx = end.x - start.x;\n const dy = end.y - start.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\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, distance);\n const toOffset = this.getDirectionOffset(toDir, distance);\n\n ctx.bezierCurveTo(\n start.x + fromOffset.x, start.y + fromOffset.y,\n end.x + toOffset.x, end.y + toOffset.y,\n end.x, end.y\n );\n } else {\n // Default behavior: auto-detect direction\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(\n start.x + offsetX, start.y,\n end.x - offsetX, end.y,\n end.x, end.y\n );\n } else {\n // Vertical dominant\n ctx.bezierCurveTo(\n start.x, start.y + offset * Math.sign(dy || 1),\n end.x, end.y - offset * Math.sign(dy || 1),\n end.x, end.y\n );\n }\n }\n\n ctx.stroke();\n }\n\n private isCompatibleTarget(node: Node): boolean {\n // Can't connect to same node\n return node.id !== this.sourceNode?.id;\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.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.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 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 drawPlus(radius: number, ctx: CanvasRenderingContext2D, anchor: { id: AnchorId; point: Point }): 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(ctx: CanvasRenderingContext2D, point: Point, reconnecting: boolean): 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 = this._connectionValidator && 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(radius: number, ctx: CanvasRenderingContext2D, anchor: { id: AnchorId; point: Point }): 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 const otherId = this.getOtherNodeId();\n if (otherId && node.id === otherId) {\n continue;\n }\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 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 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","export 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","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 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 _style: TextStyle;\n private _localStyle: TextStyle;\n private _maxWidth?: number;\n private readonly _padding: number;\n private readonly _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._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 * 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 this._maxWidth = value;\n this._lines = [];\n this._measureDirty = true;\n this._onChange?.();\n }\n\n /**\n * Label padding\n */\n get padding(): number {\n return this._padding;\n }\n\n /**\n * Label margin\n */\n get margin(): number {\n return this._margin;\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 * 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 if (this._maxWidth !== undefined) {\n const maxWidth = Math.max(0, this._maxWidth - 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): 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\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 (this._style.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 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 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.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 style: snapshot.style,\n styleClass: snapshot.styleClass,\n maxWidth: snapshot.maxWidth,\n });\n};\n\nexport const createNodeSnapshot = (node: Node): NodeSnapshot => {\n const cornerRadius = '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 as ElementStyle),\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<string, { before: { x: number; y: number }; after: { x: number; y: number } }>;\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<string, { before: { x: number; y: number }; after: { x: number; y: number } }>\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 */\n handleKeyDown(event: KeyboardEvent): boolean {\n const isCtrlOrMeta = event.ctrlKey || event.metaKey;\n const key = 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","import type { Point } from '@/types';\nimport type { PathStrategy, PathStrategyOptions } from './PathStrategy';\nimport { distanceToSegment } from '@/utils/geometry';\n\nconst MIN_SEGMENT_LENGTH = 20;\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 // 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 = fromDir === 'top' ? Math.min(from.y - MIN_SEGMENT_LENGTH, midY) : Math.max(from.y + MIN_SEGMENT_LENGTH, midY);\n const entryY = toDir === 'top' ? Math.min(to.y - MIN_SEGMENT_LENGTH, midY) : 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 = fromDir === 'left' ? Math.min(from.x - MIN_SEGMENT_LENGTH, midX) : Math.max(from.x + MIN_SEGMENT_LENGTH, midX);\n const entryX = toDir === 'left' ? Math.min(to.x - MIN_SEGMENT_LENGTH, midX) : 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 {\n bezierPoint,\n distanceToSegment,\n} from '@/utils/geometry';\nimport { BEZIER_MAX_OFFSET } from '@/constants';\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\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 dx = to.x - from.x;\n const dy = to.y - from.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\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, distance);\n const toOffset = getDirectionOffset(toDir, distance);\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 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 [\n from,\n { x: from.x + offsetX, y: from.y },\n { x: to.x - offsetX, y: to.y },\n to,\n ];\n } else {\n // Vertical dominant\n const offsetY = offset * Math.sign(dy || 1);\n return [\n from,\n { x: from.x, y: from.y + offsetY },\n { x: to.x, y: to.y - offsetY },\n to,\n ];\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 } from '@/utils/geometry';\nimport {\n type PathStrategy,\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\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({ text: options.label, onChange: () => this.markDirty() });\n } else {\n this._label = new TextLabel({ ...options.label, onChange: () => 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 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 bezier paths.\n * Format: [cp1, cp2, end, cp1, cp2, end, ...]\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 * 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 (mergedStyle.strokeColor === baseStyle.strokeColor && normalStyle.strokeColor !== undefined) {\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: () => this.markDirty() });\n } else {\n this._label = value;\n this._label.setOnChange(() => 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 ): void {\n this._fromPoint = fromPoint;\n this._toPoint = toPoint;\n this._fromDir = fromDir;\n this._toDir = toDir;\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 controlPoints: this._controlPoints,\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\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 = this._startMarker && this._startMarker.type !== 'none'\n ? this.getMarkerLength(this._startMarker)\n : 0;\n const endOffset = 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 { x: to.x - halfLength * cos + halfWidth * sin, y: to.y - halfLength * sin - halfWidth * cos },\n { x: to.x - size * cos, y: to.y - size * sin }, // back\n { x: to.x - halfLength * cos - halfWidth * sin, y: to.y - halfLength * sin + halfWidth * cos },\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 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 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 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 '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 { InputHandler } from '@/events/InputHandler';\nimport type { InputEvent, WheelInputEvent, PanInputEvent, PinchInputEvent } from '@/events/InputHandler';\nimport type { DiagramRenderer } 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';\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 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\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 });\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 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 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 (JSON.stringify(before) === JSON.stringify(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 (JSON.stringify(before) === JSON.stringify(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 (JSON.stringify(before) === JSON.stringify(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.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.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('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 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 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 (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.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 (\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 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 const key = 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.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 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 (JSON.stringify(pending.before) === JSON.stringify(pending.after)) {\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 return a.nodeId === b.nodeId && (a.portId ?? null) === (b.portId ?? null);\n }\n\n private getSelectionBounds(): Bounds | null {\n const selected = Array.from(this.selectionManager.selectedIds);\n if (selected.length === 0) {\n return null;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let hasBounds = false;\n\n for (const id of selected) {\n const node = this.renderer.getNode(id);\n if (!node) continue;\n const bounds = node.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 hasBounds = true;\n }\n\n if (!hasBounds) {\n return null;\n }\n\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY,\n };\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\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 { 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 { Bounds, DiagramOptions, Point, ViewportState } from '@/types';\nimport { InteractionManager } from './InteractionManager';\nimport type { InteractionManagerOptions } from './InteractionManager';\nimport { ANCHOR_PORT_PREFIX } from '@/constants';\nimport { applyStyleManagerToElements } from '@/utils/applyStyleManager';\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_OPTIONS: Required<DiagramOptions> = {\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\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<DiagramOptions>;\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\n private _zoom = 1;\n private _offsetX = 0;\n private _offsetY = 0;\n private _dirty = true;\n private _destroyed = false;\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\n constructor(canvas: HTMLCanvasElement | string, options: DiagramOptions = {}) {\n super();\n this.canvas = this.resolveCanvas(canvas);\n this.options = { ...DEFAULT_OPTIONS, ...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\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.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.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.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.markDirty();\n }\n\n /**\n * Get current StyleManager\n */\n getStyleManager(): StyleManager | undefined {\n return this.styleManager;\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.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(options: Omit<InteractionManagerOptions, 'renderer'> = {}): 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(options: ConstructorParameters<typeof ContextMenuManager>[1]): 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.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.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 this._nodes.set(node.id, node);\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 this.animationManager.registerEnter(edge.id);\n this.markDirty();\n this.emit('edgeAdd', edge);\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 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 for (const edgeId of edgesToRemove) {\n this.removeEdgeImmediate(edgeId);\n }\n\n for (const group of this._groups.values()) {\n group.removeChild(nodeId);\n }\n\n this._nodes.delete(nodeId);\n node.setDirtyListener(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 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 }\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\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\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 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\n if (this.styleManager) {\n applyStyleManagerToElements(\n this.styleManager,\n this._groups.values(),\n this._edges.values(),\n this._nodes.values()\n );\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 edges (middle layer)\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 nodes (front 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 edge handles (topmost layer, so they're above nodes)\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 private updateEdgeEndpoints(): 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 if (edge.lockAnchors) {\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 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 = fromNode.getConnectionPoint(toNode.getCenter());\n let toPoint = toNode.getConnectionPoint(fromNode.getCenter());\n let fromDir: string | undefined;\n let toDir: string | undefined;\n\n if (edge.lockAnchors && edge.from.portId?.startsWith(ANCHOR_PORT_PREFIX)) {\n const anchorId = edge.from.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = fromNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n fromPoint = anchorPoint;\n // Extract direction from anchor ID (format: \"side:index\")\n fromDir = anchorId.split(':')[0];\n }\n }\n\n if (edge.lockAnchors && edge.to.portId?.startsWith(ANCHOR_PORT_PREFIX)) {\n const anchorId = edge.to.portId.slice(ANCHOR_PORT_PREFIX.length);\n const anchorPoint = toNode.getAnchorPointById(anchorId);\n if (anchorPoint) {\n toPoint = anchorPoint;\n // Extract direction from anchor ID (format: \"side:index\")\n toDir = anchorId.split(':')[0];\n }\n }\n edge.updateEndpoints(fromPoint, toPoint, fromDir, toDir);\n }\n }\n\n private renderScrollbars(ctx: CanvasRenderingContext2D): void {\n if (!this.options.scrollbarOverlay) {\n return;\n }\n\n const rawContentBounds = this.getContentBounds();\n if (!rawContentBounds) {\n return;\n }\n\n const viewportBounds = this.getViewportBounds();\n\n // Union of content and viewport to get the full scrollable area\n const unionMinX = Math.min(rawContentBounds.x, viewportBounds.x);\n const unionMinY = Math.min(rawContentBounds.y, viewportBounds.y);\n const unionMaxX = Math.max(rawContentBounds.x + rawContentBounds.width, viewportBounds.x + viewportBounds.width);\n const unionMaxY = Math.max(rawContentBounds.y + rawContentBounds.height, viewportBounds.y + viewportBounds.height);\n const contentBounds = { x: unionMinX, y: unionMinY, width: unionMaxX - unionMinX, height: unionMaxY - unionMinY };\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\n if (!showHorizontal && !showVertical) {\n return;\n }\n\n const { width, height } = this.options;\n const padding = 6;\n const thickness = 6;\n const spacing = 4;\n const minThumbLength = 24;\n const trackRadius = thickness / 2;\n\n const availableWidth = width - padding * 2;\n const availableHeight = height - padding * 2;\n if (availableWidth <= 0 || availableHeight <= 0) {\n return;\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 const drawRoundedRect = (x: number, y: number, w: number, h: number, r: number): void => {\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n ctx.lineTo(x + w, y + h - r);\n ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n ctx.lineTo(x + r, y + h);\n ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n };\n\n ctx.save();\n ctx.setTransform(this.devicePixelRatio, 0, 0, this.devicePixelRatio, 0, 0);\n ctx.globalAlpha = 0.75;\n\n const trackColor = 'rgba(15, 23, 42, 0.16)';\n const thumbColor = 'rgba(51, 65, 85, 0.7)';\n\n if (showHorizontal && horizontalTrackLength > 0) {\n const maxScrollX = Math.max(0, contentWidth - viewportBounds.width);\n const scrollX = Math.min(\n Math.max(viewportBounds.x - contentBounds.x, 0),\n maxScrollX\n );\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\n ctx.fillStyle = trackColor;\n drawRoundedRect(horizontalTrackX, horizontalTrackY, horizontalTrackLength, thickness, trackRadius);\n ctx.fill();\n\n ctx.fillStyle = thumbColor;\n drawRoundedRect(\n horizontalTrackX + thumbOffset,\n horizontalTrackY,\n thumbLength,\n thickness,\n trackRadius\n );\n ctx.fill();\n }\n\n if (showVertical && verticalTrackLength > 0) {\n const maxScrollY = Math.max(0, contentHeight - viewportBounds.height);\n const scrollY = Math.min(\n Math.max(viewportBounds.y - contentBounds.y, 0),\n maxScrollY\n );\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\n ctx.fillStyle = trackColor;\n drawRoundedRect(verticalTrackX, verticalTrackY, thickness, verticalTrackLength, trackRadius);\n ctx.fill();\n\n ctx.fillStyle = thumbColor;\n drawRoundedRect(\n verticalTrackX,\n verticalTrackY + thumbOffset,\n thickness,\n thumbLength,\n trackRadius\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}\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","import type { Bounds } from '@/types';\n\nexport type NodeImageCornerPlacement = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\nexport type NodeImageEdgePlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport function isCornerPlacement(placement: NodeImagePlacement): placement is NodeImageCornerPlacement {\n return placement === 'top-left' || placement === 'top-right' || placement === 'bottom-left' || placement === 'bottom-right';\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\nconst svgTextCache = new Map<string, Promise<string>>();\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 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 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 { NodeImage, type NodeImageOptions, type NodeImagePlacement, isCornerPlacement } 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}\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\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\n if (options.label !== undefined) {\n if (typeof options.label === 'string') {\n this._label = new TextLabel({ text: options.label, onChange: () => this.markDirty() });\n } else {\n this._label = new TextLabel({ ...options.label, onChange: () => 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: () => this.markDirty() });\n } else {\n this._label = value;\n this._label.setOnChange(() => 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 * 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 * Render ports\n */\n protected renderPorts(ctx: CanvasRenderingContext2D): void {\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 * 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 * 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 labelSize = this._label ? this._label.measure(ctx) : undefined;\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n\n if (labelSize || iconBoxSize) {\n this.ensureContentsFit(labelSize, iconBoxSize);\n bounds = this.getBounds();\n }\n\n let iconBounds = bounds;\n let labelBounds = 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 // For corner placements, icon goes in corner, label uses remaining space\n iconBounds = this.getIconBounds(bounds, iconBoxSize, placement);\n // Label gets full bounds (will be centered by default)\n labelBounds = bounds;\n } else {\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: bounds.x,\n y: bounds.y + iconBoxSize.height + gap,\n width: bounds.width,\n height: Math.max(0, bounds.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: bounds.x,\n y: bounds.y,\n width: bounds.width,\n height: Math.max(0, bounds.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: bounds.x + iconBoxSize.width + gap,\n y: bounds.y,\n width: Math.max(0, bounds.width - iconBoxSize.width - gap),\n height: bounds.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: bounds.x,\n y: bounds.y,\n width: Math.max(0, bounds.width - iconBoxSize.width - gap),\n height: bounds.height,\n };\n break;\n default:\n break;\n }\n }\n } else if (this._label && labelSize) {\n labelBounds = this.getLabelBounds(bounds, labelSize, this._labelPlacement);\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 labelSize = this._label ? this._label.measure(ctx) : undefined;\n const iconBoxSize = this._icon ? this.getIconBoxSize() : undefined;\n return this.calculateContentMinSize(labelSize, iconBoxSize);\n }\n\n /**\n * Render resize handles when selected\n */\n renderResizeHandles(ctx: CanvasRenderingContext2D): void {\n if (this._state !== 'selected') {\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 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 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(offset = RESIZE_HANDLE_OFFSET): { 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);\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(labelSize?: Size, iconBoxSize?: Size): Size {\n let minWidth = 0;\n let minHeight = 0;\n\n if (labelSize) {\n minWidth = Math.max(minWidth, labelSize.width);\n minHeight = Math.max(minHeight, labelSize.height);\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\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 }\n }\n\n return { width: minWidth, height: minHeight };\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 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) => ({ x: bounds.x + bounds.width * t, y: bounds.y + bounds.height }));\n addPoints('left', left, (t) => ({ x: bounds.x, y: bounds.y + bounds.height * t }));\n addPoints('right', right, (t) => ({ x: bounds.x + bounds.width, y: bounds.y + bounds.height * t }));\n\n if (anchors.length === 0) {\n return [];\n }\n\n return anchors.map((anchor) => ({\n id: anchor.id,\n point: this.getOutlinePointToward(anchor.point),\n }));\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 { 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 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 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 { 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 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 render(ctx: CanvasRenderingContext2D): void {\n const center = this.getCenter();\n const hw = this._width / 2;\n const hh = this._height / 2;\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.fill();\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\nexport interface CustomShapeNodeOptions extends NodeOptions {\n path: Path2D | ((width: number, height: number) => Path2D);\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 _cachedPath: Path2D | null = null;\n private _cachedWidth = 0;\n private _cachedHeight = 0;\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\n get typeName(): string {\n return 'custom';\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.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 }\n return this._cachedPath;\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 this.applyStyle(ctx);\n\n ctx.save();\n ctx.translate(this._x, this._y);\n\n const path = this.getPath();\n ctx.fill(path);\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","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","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';\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 hasExtendedOptions =\n node.label.styleClass !== undefined ||\n node.label.maxWidth !== undefined ||\n node.label.padding !== 8 ||\n node.label.margin !== 0 ||\n Object.keys(node.label.style).length > 0;\n\n if (hasExtendedOptions) {\n label = {\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 };\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 hasCustomAnchors = ap.top !== 1 || ap.right !== 1 || ap.bottom !== 1 || ap.left !== 1;\n if (hasCustomAnchors) {\n anchorPoints = {\n top: ap.top !== 1 ? ap.top : undefined,\n right: ap.right !== 1 ? ap.right : undefined,\n bottom: ap.bottom !== 1 ? ap.bottom : undefined,\n left: ap.left !== 1 ? ap.left : undefined,\n };\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 { applyStyleManagerToElements } from './applyStyleManager';\nimport { getContentBounds } from './contentBounds';\nimport { downloadBlob } from './download';\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)\n for (const group of this.renderer.groups.values()) {\n if (group.visible) {\n group.render(ctx);\n }\n }\n\n for (const edge of this.renderer.edges.values()) {\n if (edge.visible) {\n edge.render(ctx);\n }\n }\n\n for (const node of this.renderer.nodes.values()) {\n if (node.visible) {\n node.render(ctx);\n }\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 { 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 { TextStyle } from '@/types';\nimport { applyStyleManagerToElements } from './applyStyleManager';\nimport { getContentBounds } from './contentBounds';\nimport { downloadBlob } from './download';\n\nexport interface SvgExportOptions {\n padding?: number;\n backgroundColor?: string;\n includeBackground?: boolean;\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\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 parts.push(\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">`\n );\n parts.push(this.arrowDefs());\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 edge of this.renderer.edges.values()) {\n if (edge.visible) {\n parts.push(this.renderEdge(edge));\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 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 opacity = style.opacity ?? 1;\n\n let shape: string;\n switch (node.typeName) {\n case 'rectangle': {\n const radius = (style.cornerRadius ?? 0).toString();\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 default: {\n shape = `<rect x=\"${bounds.x}\" y=\"${bounds.y}\" width=\"${bounds.width}\" height=\"${bounds.height}\"`;\n }\n }\n\n const label = node.label\n ? this.renderTextLabel(node.label.text, node.getCenter(), node.label.style)\n : '';\n\n return [\n `${shape} fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" opacity=\"${opacity}\"/>`,\n label,\n ].join('');\n }\n\n private renderEdge(edge: Edge): 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 opacity = style.opacity ?? 1;\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 markerEnd = edge.arrowType === 'none' ? '' : ` marker-end=\"url(#arrow)\"`;\n const markerStart = edge.arrowType === 'double' ? ` marker-start=\"url(#arrow)\"` : '';\n\n const label = edge.label\n ? this.renderTextLabel(edge.label.text, this.getPathMidpoint(edge), edge.label.style)\n : '';\n\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${strokeWidth}\" opacity=\"${opacity}\" color=\"${stroke}\"${dash}${dashOffset}${markerStart}${markerEnd}/>${label}`;\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 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 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 return `<text x=\"${point.x}\" y=\"${point.y}\" fill=\"${fill}\" font-size=\"${fontSize}\" font-family=\"${fontFamily}\" font-weight=\"${fontWeight}\" text-anchor=\"${anchor}\" dominant-baseline=\"${baseline}\">${this.escapeText(\n text\n )}</text>`;\n }\n\n private arrowDefs(): string {\n return [\n '<defs>',\n '<marker id=\"arrow\" viewBox=\"0 0 10 10\" refX=\"10\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\">',\n '<path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"currentColor\"/>',\n '</marker>',\n '</defs>',\n ].join('');\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, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\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 backgroundColor?: string;\n borderColor?: string;\n viewportColor?: string;\n anchor?: MiniMapAnchor;\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 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 bounds = getContentBounds({\n nodes: renderer.nodes.values(),\n edges: renderer.edges.values(),\n groups: renderer.groups.values(),\n });\n if (!bounds) return;\n\n const { width, height, padding, anchor } = this.options;\n const x = anchor === 'bottom-left' || anchor === 'top-left'\n ? padding\n : renderer.width - width - padding;\n const y = anchor === 'top-left' || anchor === 'top-right'\n ? padding\n : renderer.height - height - padding;\n\n ctx.save();\n ctx.setTransform(renderer.pixelRatio, 0, 0, renderer.pixelRatio, 0, 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 const scale = Math.min(width / bounds.width, height / bounds.height);\n const offsetX = x + (width - bounds.width * scale) / 2;\n const offsetY = y + (height - bounds.height * scale) / 2;\n\n ctx.save();\n ctx.translate(offsetX, offsetY);\n ctx.scale(scale, scale);\n ctx.translate(-bounds.x, -bounds.y);\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 const viewBounds = this.getViewportBounds(renderer);\n let viewX = offsetX + (viewBounds.x - bounds.x) * scale;\n let viewY = offsetY + (viewBounds.y - bounds.y) * scale;\n let viewW = viewBounds.width * scale;\n let viewH = viewBounds.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 if (viewW < 0 || viewH < 0) {\n ctx.restore();\n return;\n }\n\n ctx.strokeStyle = this.options.viewportColor;\n ctx.lineWidth = 1.5;\n ctx.strokeRect(viewX, viewY, viewW, viewH);\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 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"],"names":["distance","point","end","angle","DEFAULT_OPTIONS","d"],"mappings":"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"}