dishui 0.0.60 → 0.0.61

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.
@@ -1 +1 @@
1
- {"version":3,"file":"FlowCanvas.js","names":[],"sources":["../../../../src/components/pro/Flow/FlowCanvas.tsx"],"sourcesContent":["import React, { useRef, useEffect, useCallback, useState } from 'react';\nimport { FederatedPointerEvent, Graphics } from 'pixi.js';\nimport { usePixiApp } from './hooks/usePixiApp';\nimport { useViewport } from './hooks/useViewport';\nimport { useFlowContext } from './context/FlowContext';\nimport { useFlowUI, type FocusOnRectOptions } from './context/FlowUIContext';\nimport { GridRenderer } from './canvas/GridRenderer';\nimport { SelectionOverlay } from './canvas/SelectionOverlay';\nimport { NodeRenderer } from './nodes/NodeRenderer';\nimport { EdgeRenderer } from './edges/EdgeRenderer';\nimport { LineRenderer } from './lines/LineRenderer';\nimport { FreehandTool } from './lines/FreehandTool';\nimport { GeometricLineTool } from './lines/GeometricLineTool';\nimport { isPointInNode, rectsOverlap, distToSegment, generateId } from './nodes/nodeUtils';\nimport { shapeDrawers } from './nodes/shapes';\nimport { findClosestHandle, findClosestHandleWorld, handleWorldPos, getHandlePositions } from './nodes/NodeHandles';\nimport { buildEdgePath, resolveEdgeEndpoints, linearizeSegments } from './edges/edgePaths';\nimport { computeAlignmentSnap, type AlignGuide } from './hooks/useAlignmentGuides';\nimport { AlignmentGuidesRenderer } from './canvas/AlignmentGuides';\nimport { getDocumentSlides, nextAnimIndex } from './nodes/animAnchors';\nimport { useDeleteSelection } from './hooks/useDeleteSelection';\nimport type { PixiApp } from './canvas/PixiApp';\nimport type { ViewportState, FlowNode, FlowEdge, FlowLine, FlowBezierControl } from './types';\n\nexport interface FlowCanvasProps {\n onPixiReady?: (pixi: PixiApp) => void;\n}\n\ntype ResizeHandle = 'nw' | 'ne' | 'se' | 'sw';\n\nconst RESIZE_CURSORS: Record<ResizeHandle, string> = {\n nw: 'nwse-resize', ne: 'nesw-resize',\n se: 'nwse-resize', sw: 'nesw-resize',\n};\n\n// Touch pointers have no hover and a ~40px contact patch, so hit radii tuned\n// for a mouse cursor (8-14px) are nearly impossible to land with a finger —\n// especially for connection handles, edge endpoints and waypoints, which sit on\n// exact coordinates. Coarse pointers (touch) get doubled screen-space radii.\nconst COARSE_POINTER = typeof window !== 'undefined'\n && typeof window.matchMedia === 'function'\n && window.matchMedia('(pointer: coarse)').matches;\nconst TOUCH_HIT_SCALE = COARSE_POINTER ? 2 : 1;\n\n/**\n * Press/tap hit radius in world units: `px` screen pixels converted by zoom,\n * capped in world space so a zoomed-out canvas doesn't get an absurd radius.\n */\nfunction hitRadius(zoom: number, px: number, worldCap: number): number {\n return Math.min((px * TOUCH_HIT_SCALE) / zoom, worldCap * TOUCH_HIT_SCALE);\n}\n\n// Rotation knob: stem rises above the node's top-center, ending in a knob that\n// can be dragged around the node center to rotate. Length/radius are SCREEN\n// pixels (like the other transform handles); hit tests convert via zoom.\nconst ROTATE_STEM = 26;\n\n/** Knob center in world coords for a node at the given zoom. */\nfunction rotationKnobPos(node: FlowNode, zoom: number): { x: number; y: number } {\n return { x: node.position.x + node.width / 2, y: node.position.y - ROTATE_STEM / zoom };\n}\n\n/** Placement magnet: snap a coordinate to the canvas grid (stamp placement). */\nfunction snapPlacement(value: number, gridSize: number, enabled: boolean): number {\n if (!enabled || !(gridSize > 0)) return value;\n return Math.round(value / gridSize) * gridSize;\n}\n\nfunction getResizeHandleAt(\n pt: { x: number; y: number }, node: FlowNode, threshold: number,\n): ResizeHandle | null {\n const { x, y } = node.position;\n const w = node.width, h = node.height;\n const defs: Array<[ResizeHandle, number, number]> = [\n ['nw', x, y], ['ne', x + w, y],\n ['se', x + w, y + h], ['sw', x, y + h],\n ];\n let best: ResizeHandle | null = null, bestD = threshold;\n for (const [pos, hx, hy] of defs) {\n const d = Math.hypot(pt.x - hx, pt.y - hy);\n if (d < bestD) { bestD = d; best = pos; }\n }\n return best;\n}\n\ninterface EdgeEndpointHit {\n edgeId: string;\n end: 'source' | 'target';\n worldX: number;\n worldY: number;\n}\n\nfunction findEdgeEndpointNear(\n wx: number, wy: number,\n edges: FlowEdge[],\n nodeMap: Map<string, FlowNode>,\n threshold: number,\n): EdgeEndpointHit | null {\n let best: EdgeEndpointHit | null = null;\n let bestD = threshold;\n for (const edge of edges) {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) continue;\n const dSrc = Math.hypot(wx - ep.sx, wy - ep.sy);\n if (dSrc < bestD) { bestD = dSrc; best = { edgeId: edge.id, end: 'source', worldX: ep.sx, worldY: ep.sy }; }\n const dTgt = Math.hypot(wx - ep.tx, wy - ep.ty);\n if (dTgt < bestD) { bestD = dTgt; best = { edgeId: edge.id, end: 'target', worldX: ep.tx, worldY: ep.ty }; }\n }\n return best;\n}\n\ninterface WaypointHit {\n edgeId: string;\n waypointIndex: number;\n wx: number;\n wy: number;\n}\n\ninterface BezierControlHit {\n edgeId: string;\n segmentIndex: number;\n controlEnd: 'c1' | 'c2';\n wx: number;\n wy: number;\n}\n\nfunction findWaypointNear(\n wx: number, wy: number,\n edges: FlowEdge[],\n threshold: number,\n): WaypointHit | null {\n let best: WaypointHit | null = null;\n let bestD = threshold;\n for (const edge of edges) {\n const wps = edge.data.waypoints;\n if (!wps) continue;\n for (let i = 0; i < wps.length; i++) {\n const d = Math.hypot(wx - wps[i].x, wy - wps[i].y);\n if (d < bestD) {\n bestD = d;\n best = { edgeId: edge.id, waypointIndex: i, wx: wps[i].x, wy: wps[i].y };\n }\n }\n }\n return best;\n}\n\nfunction findBezierControlNear(\n wx: number, wy: number,\n edges: FlowEdge[],\n nodeMap: Map<string, FlowNode>,\n threshold: number,\n): BezierControlHit | null {\n let best: BezierControlHit | null = null;\n let bestD = threshold;\n for (const edge of edges) {\n if (edge.type !== 'simplebezier') continue;\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) continue;\n const wps = edge.data.waypoints ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...wps, { x: ep.tx, y: ep.ty }];\n const ctrls = edge.data.bezierControls;\n const lastIdx = allPts.length - 2;\n for (let i = 0; i <= lastIdx; i++) {\n const a = allPts[i], b = allPts[i + 1];\n const ctrl = ctrls?.[i];\n const segDist = Math.hypot(b.x - a.x, b.y - a.y);\n const arm = Math.max(30, segDist * 0.3);\n const c1x = ctrl?.c1x ?? (i === 0 ? a.x + ep.snx * arm : a.x + (b.x - a.x) * 0.4);\n const c1y = ctrl?.c1y ?? (i === 0 ? a.y + ep.sny * arm : a.y);\n const c2x = ctrl?.c2x ?? (i === lastIdx ? b.x + ep.tnx * arm : b.x - (b.x - a.x) * 0.4);\n const c2y = ctrl?.c2y ?? (i === lastIdx ? b.y + ep.tny * arm : b.y);\n const d1 = Math.hypot(wx - c1x, wy - c1y);\n if (d1 < bestD) { bestD = d1; best = { edgeId: edge.id, segmentIndex: i, controlEnd: 'c1', wx: c1x, wy: c1y }; }\n const d2 = Math.hypot(wx - c2x, wy - c2y);\n if (d2 < bestD) { bestD = d2; best = { edgeId: edge.id, segmentIndex: i, controlEnd: 'c2', wx: c2x, wy: c2y }; }\n }\n }\n return best;\n}\n\nfunction findInsertionIndex(\n wx: number, wy: number,\n edge: FlowEdge,\n nodeMap: Map<string, FlowNode>,\n): number {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) return 0;\n const wps = edge.data.waypoints ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...wps, { x: ep.tx, y: ep.ty }];\n let bestD = Infinity, bestI = 0;\n for (let i = 0; i < allPts.length - 1; i++) {\n const d = distToSegment(wx, wy, allPts[i].x, allPts[i].y, allPts[i + 1].x, allPts[i + 1].y);\n if (d < bestD) { bestD = d; bestI = i; }\n }\n return bestI;\n}\n\nfunction applyResize(\n start: { x: number; y: number; w: number; h: number },\n handle: ResizeHandle, dx: number, dy: number, minSize = 24,\n): { x: number; y: number; w: number; h: number } {\n let { x, y, w, h } = { ...start };\n const ml = handle === 'nw' || handle === 'sw';\n const mr = handle === 'ne' || handle === 'se';\n const mt = handle === 'nw' || handle === 'ne';\n const mb = handle === 'sw' || handle === 'se';\n if (ml) { x += dx; w -= dx; }\n if (mr) { w += dx; }\n if (mt) { y += dy; h -= dy; }\n if (mb) { h += dy; }\n if (w < minSize) { if (ml) x = start.x + start.w - minSize; w = minSize; }\n if (h < minSize) { if (mt) y = start.y + start.h - minSize; h = minSize; }\n return { x, y, w, h };\n}\n\nfunction isPointNearEdgePath(\n wx: number, wy: number, edge: FlowEdge,\n nodeMap: Map<string, FlowNode>, threshold: number,\n): boolean {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) return false;\n const segs = buildEdgePath(edge.type, ep, edge.data.waypoints, edge.data.bezierControls);\n const pts = linearizeSegments(segs);\n for (let i = 0; i < pts.length - 1; i++) {\n if (distToSegment(wx, wy, pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y) < threshold) return true;\n }\n return false;\n}\n\nfunction isPointNearLine(\n wx: number, wy: number, line: FlowLine, threshold: number,\n): boolean {\n const pts = line.points;\n for (let i = 0; i < pts.length - 1; i++) {\n if (distToSegment(wx, wy, pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y) < threshold) return true;\n }\n return false;\n}\n\nexport default function FlowCanvas({ onPixiReady }: FlowCanvasProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const gridRef = useRef<GridRenderer | null>(null);\n // Latest theme-derived grid dot color; applied to the grid renderer whenever\n // it (re)initializes or the DishUI theme changes. Node/edge colors follow the\n // theme via `theme:*` tokens resolved in the render loop.\n const gridDotColorRef = useRef<number>(0xd1d5db);\n const handleThemeColors = useCallback((colors: { background: number; gridDot: number; nodeFill: string; nodeText: string }) => {\n gridDotColorRef.current = colors.gridDot;\n if (gridRef.current) gridRef.current.dotColor = colors.gridDot;\n }, []);\n const { pixiRef, readyRef } = usePixiApp(containerRef, handleThemeColors);\n const { setViewportInternal, viewportReqRef, viewport: uiViewport, autoFocus, showGrid, showAnchors, gridSize, toolMode, edgeType, focusOnRect, setFocusOnRect, pendingPlacement, setPendingPlacement, setContextMenu, beginNodeDrag, endNodeDrag, presentation, editingNodeId, setEditingNodeId, readOnly, placementSnap } = useFlowUI();\n const { currentCanvas, selection, setSelection, setDoc, currentCanvasId, pushCanvas, doc: flowDoc } = useFlowContext();\n const deleteSelected = useDeleteSelection();\n const deleteSelectedRef = useRef(deleteSelected);\n deleteSelectedRef.current = deleteSelected;\n const deleteButtonRef = useRef<HTMLButtonElement>(null);\n const readOnlyRef = useRef(readOnly);\n readOnlyRef.current = readOnly;\n // Latest placement-magnet toggle / grid size, readable from the mount-scoped\n // pointer handlers and render loop.\n const placementSnapRef = useRef(placementSnap);\n placementSnapRef.current = placementSnap;\n const gridSizeRef = useRef(gridSize);\n gridSizeRef.current = gridSize;\n const selectionRef = useRef<SelectionOverlay | null>(null);\n const nodeRendererRef = useRef<NodeRenderer | null>(null);\n const edgeRendererRef = useRef<EdgeRenderer | null>(null);\n const lineRendererRef = useRef<LineRenderer | null>(null);\n const freehandRef = useRef<FreehandTool | null>(null);\n const geoLineRef = useRef<GeometricLineTool | null>(null);\n const hoveredNodeRef = useRef<string | null>(null);\n const transformGfxRef = useRef<Graphics | null>(null);\n const handleHoverGfxRef = useRef<Graphics | null>(null);\n const alignGuidesRef = useRef<AlignmentGuidesRenderer | null>(null);\n const activeGuidesRef = useRef<AlignGuide[]>([]);\n const hoveredHandleRef = useRef<{ nodeId: string; handleId: string; wx: number; wy: number } | null>(null);\n const hoveredEdgeEndpointRef = useRef<EdgeEndpointHit | null>(null);\n const waypointDragRef = useRef<{\n active: boolean;\n edgeId: string;\n type: 'waypoint' | 'bezierC1' | 'bezierC2';\n index: number;\n } | null>(null);\n const edgeEditGfxRef = useRef<Graphics | null>(null);\n const lastClickRef = useRef<{ time: number; wx: number; wy: number }>({ time: 0, wx: 0, wy: 0 });\n const dblClickRef = useRef<{ time: number; wx: number; wy: number }>({ time: 0, wx: 0, wy: 0 });\n // Timestamp until which pointertap events are ignored — set after a multi-touch\n // gesture ends so lifting the last finger cannot register as an accidental tap\n // (e.g. placing a stamp or opening the label editor).\n const suppressTapUntilRef = useRef(0);\n const ghostGfxRef = useRef<Graphics | null>(null);\n const mouseWorldRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const interactiveCanvas = showAnchors || presentation\n ? currentCanvas\n : { ...currentCanvas, nodes: currentCanvas.nodes.filter(node => node.type !== 'animAnchor') };\n const canvasDataRef = useRef(interactiveCanvas);\n canvasDataRef.current = interactiveCanvas;\n const currentCanvasIdRef = useRef(currentCanvasId);\n currentCanvasIdRef.current = currentCanvasId;\n const selectionDataRef = useRef(selection);\n selectionDataRef.current = selection;\n const docRef = useRef(flowDoc);\n docRef.current = flowDoc;\n const toolModeRef = useRef(toolMode);\n toolModeRef.current = toolMode;\n const autoFocusRef = useRef(autoFocus);\n autoFocusRef.current = autoFocus;\n const focusOnRectRef = useRef(focusOnRect);\n focusOnRectRef.current = focusOnRect;\n const edgeTypeRef = useRef(edgeType);\n edgeTypeRef.current = edgeType;\n const showAnchorsRef = useRef(showAnchors);\n showAnchorsRef.current = showAnchors;\n const presentationRef = useRef(presentation);\n presentationRef.current = presentation;\n const pendingPlacementRef = useRef(pendingPlacement);\n pendingPlacementRef.current = pendingPlacement;\n const beginNodeDragRef = useRef(beginNodeDrag);\n beginNodeDragRef.current = beginNodeDrag;\n const endNodeDragRef = useRef(endNodeDrag);\n endNodeDragRef.current = endNodeDrag;\n\n const dragRef = useRef<{\n active: boolean;\n nodeIds: Set<string>;\n lineIds?: Set<string>;\n startWorld: { x: number; y: number };\n nodeStarts: Map<string, { x: number; y: number }>;\n linePointStarts?: Map<string, Array<{ x: number; y: number }>>;\n } | null>(null);\n\n const marqueeRef = useRef<{\n active: boolean;\n startScreen: { x: number; y: number };\n } | null>(null);\n\n const connectRef = useRef<{\n active: boolean;\n sourceNodeId: string;\n sourceHandleId: string;\n } | null>(null);\n\n // Active rotation-knob gesture: the knob above the selection's top-center is\n // dragged around the node center to adjust `data.rotation`.\n const rotateRef = useRef<{\n active: boolean;\n nodeId: string;\n cx: number;\n cy: number;\n startPointerAngle: number;\n startRotation: number;\n } | null>(null);\n const reconnectRef = useRef<{\n active: boolean;\n edgeId: string;\n movingEnd: 'source' | 'target';\n fixedNodeId: string;\n fixedHandleId: string | undefined;\n } | null>(null);\n const connectLineRef = useRef<Graphics | null>(null);\n\n const resizeRef = useRef<{\n active: boolean;\n nodeId: string;\n handle: ResizeHandle;\n startWorld: { x: number; y: number };\n startBounds: { x: number; y: number; w: number; h: number };\n childStarts: Map<string, { x: number; y: number; w: number; h: number }>;\n childLineStarts?: Map<string, Array<{ x: number; y: number }>>;\n } | null>(null);\n\n const lineDragRef = useRef<{\n active: boolean;\n lineIds: Set<string>;\n startWorld: { x: number; y: number };\n pointStarts: Map<string, Array<{ x: number; y: number }>>;\n } | null>(null);\n\n const vmViewportRef = useRef(uiViewport);\n const vpRafRef = useRef(0);\n const handleViewportChange = useCallback((v: ViewportState) => {\n vmViewportRef.current = v;\n if (!vpRafRef.current) {\n vpRafRef.current = requestAnimationFrame(() => {\n vpRafRef.current = 0;\n // VM → React: display-only update. Does NOT request a VM apply, so it\n // can never echo back and cause a feedback loop / jitter.\n setViewportInternal(vmViewportRef.current);\n });\n }\n }, [setViewportInternal]);\n\n const { vmRef, screenToWorld } = useViewport(pixiRef, handleViewportChange);\n const screenToWorldRef = useRef(screenToWorld);\n screenToWorldRef.current = screenToWorld;\n // `editing` holds the target; `editorPos` is the on-screen position (CSS px\n // relative to the canvas container) recomputed each frame so the input\n // tracks pan/zoom.\n const [editing, setEditing] = useState<{ kind: 'node' | 'edge' | 'line'; id: string; value: string } | null>(null);\n const [editorPos, setEditorPos] = useState<{ x: number; y: number } | null>(null);\n const editingRef = useRef(editing);\n editingRef.current = editing;\n\n // Stable trigger used from inside the pixi event handlers.\n const beginEditRef = useRef<(kind: 'node' | 'edge' | 'line', id: string, value: string) => void>(() => {});\n beginEditRef.current = (kind, id, value) => {\n setEditingNodeId(kind === 'node' ? id : null);\n setEditing({ kind, id, value });\n };\n\n const commitEdit = useCallback((value: string) => {\n const target = editingRef.current;\n if (!target) return;\n setDoc(prev => {\n const cid = currentCanvasIdRef.current;\n const canvas = prev.canvases[cid];\n if (!canvas) return prev;\n let next = canvas;\n if (target.kind === 'node') {\n next = { ...canvas, nodes: canvas.nodes.map(n => n.id === target.id ? { ...n, data: { ...n.data, label: value } } : n) };\n } else if (target.kind === 'edge') {\n next = { ...canvas, edges: canvas.edges.map(e => e.id === target.id ? { ...e, data: { ...e.data, labelText: value } } : e) };\n } else {\n // Lines have no label field today; ignore.\n return prev;\n }\n return { ...prev, canvases: { ...prev.canvases, [cid]: next } };\n });\n setEditing(null);\n setEditingNodeId(null);\n setEditorPos(null);\n }, [setDoc, setEditingNodeId]);\n\n const cancelEdit = useCallback(() => {\n setEditing(null);\n setEditingNodeId(null);\n setEditorPos(null);\n }, [setEditingNodeId]);\n\n useEffect(() => {\n if (!editingNodeId || editingRef.current?.id === editingNodeId) return;\n const node = canvasDataRef.current.nodes.find(item => item.id === editingNodeId);\n if (node) beginEditRef.current('node', node.id, node.data.label);\n }, [editingNodeId]);\n\n // Compute the on-screen editor position from the target's world-space center.\n useEffect(() => {\n if (!editing) return;\n const vm = vmRef.current;\n if (!vm) return;\n const canvas = canvasDataRef.current;\n let world: { x: number; y: number } | null = null;\n if (editing.kind === 'node') {\n const n = canvas.nodes.find(nn => nn.id === editing.id);\n if (n) world = { x: n.position.x + n.width / 2, y: n.position.y + n.height / 2 };\n } else if (editing.kind === 'edge') {\n const e = canvas.edges.find(ee => ee.id === editing.id);\n const nodeMap = new Map<string, FlowNode>();\n for (const nn of canvas.nodes) nodeMap.set(nn.id, nn);\n if (e) {\n const ep = resolveEdgeEndpoints(e, nodeMap);\n if (ep) {\n const segs = buildEdgePath(e.type, ep, e.data.waypoints, e.data.bezierControls);\n const pts = linearizeSegments(segs);\n const mid = pts[Math.floor(pts.length / 2)] ?? { x: (ep.sx + ep.tx) / 2, y: (ep.sy + ep.ty) / 2 };\n world = { x: mid.x, y: mid.y };\n }\n }\n }\n if (world) {\n const s = vm.worldToScreen(world.x, world.y);\n setEditorPos({ x: s.x, y: s.y });\n }\n }, [editing, vmRef]);\n\n // Apply EXTERNAL viewport commands (toolbar zoom buttons, minimap, outline\n // panel) → ViewportManager. Only runs when the external request counter\n // changes, so VM→React display updates are never echoed back (no jitter).\n const lastViewportReqRef = useRef(0);\n useEffect(() => {\n if (viewportReqRef.current === lastViewportReqRef.current) return;\n lastViewportReqRef.current = viewportReqRef.current;\n vmViewportRef.current = uiViewport;\n vmRef.current?.setState(uiViewport);\n }, [uiViewport, vmRef, viewportReqRef]);\n\n // Register focusOnRect implementation with ViewportManager\n useEffect(() => {\n setFocusOnRect((wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => {\n const vm = vmRef.current;\n const el = containerRef.current;\n if (!vm || !el) return;\n const screenW = el.clientWidth || 800;\n const screenH = el.clientHeight || 600;\n const pad = Math.max(0, options?.padding ?? 60);\n const availableW = Math.max(1, screenW - pad * 2);\n const availableH = Math.max(1, screenH - pad * 2);\n const zoom = options?.preserveZoom\n ? vm.state.zoom\n : Math.min(\n availableW / Math.max(ww, 1),\n availableH / Math.max(wh, 1),\n options?.maxZoom ?? 2,\n );\n const cx = wx + ww / 2;\n const cy = wy + wh / 2;\n const targetX = screenW / 2 - cx * zoom;\n const targetY = screenH / 2 - cy * zoom;\n vm.animateTo({ x: targetX, y: targetY, zoom }, options?.duration ?? 350);\n });\n }, [setFocusOnRect, vmRef]);\n\n const handleLineComplete = useCallback((line: FlowLine) => {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: { ...canvas, lines: [...canvas.lines, line] },\n },\n };\n });\n }, [setDoc, currentCanvasId]);\n const handleLineCompleteRef = useRef(handleLineComplete);\n handleLineCompleteRef.current = handleLineComplete;\n\n // Initialize PixiJS subsystems\n useEffect(() => {\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return;\n\n let cancelled = false;\n // Native touch gesture handlers (assigned once the stage is wired up; see\n // the NATIVE TOUCH GESTURES section inside waitForReady below).\n let touchStartHandler: ((e: TouchEvent) => void) | null = null;\n let touchMoveHandler: ((e: TouchEvent) => void) | null = null;\n let touchEndHandler: ((e: TouchEvent) => void) | null = null;\n const waitForReady = () => {\n if (cancelled) return;\n if (!readyRef.current) { setTimeout(waitForReady, 30); return; }\n\n gridRef.current = new GridRenderer(pixi.app.stage, gridSize, showGrid);\n gridRef.current.dotColor = gridDotColorRef.current;\n selectionRef.current = new SelectionOverlay(pixi.app.stage);\n nodeRendererRef.current = new NodeRenderer(pixi.world);\n edgeRendererRef.current = new EdgeRenderer(pixi.world);\n lineRendererRef.current = new LineRenderer(pixi.world);\n\n const connectLine = new Graphics();\n connectLine.label = 'connect-line';\n connectLine.visible = false;\n pixi.world.addChild(connectLine);\n connectLineRef.current = connectLine;\n\n const transformGfx = new Graphics();\n transformGfx.label = 'transform-handles';\n pixi.app.stage.addChild(transformGfx);\n transformGfxRef.current = transformGfx;\n\n const handleHoverGfx = new Graphics();\n handleHoverGfx.label = 'handle-hover';\n pixi.world.addChild(handleHoverGfx);\n handleHoverGfxRef.current = handleHoverGfx;\n\n const edgeEditGfx = new Graphics();\n edgeEditGfx.label = 'edge-edit-handles';\n pixi.world.addChild(edgeEditGfx);\n edgeEditGfxRef.current = edgeEditGfx;\n\n const ghostGfx = new Graphics();\n ghostGfx.label = 'ghost-placement';\n ghostGfx.alpha = 0.5;\n pixi.world.addChild(ghostGfx);\n ghostGfxRef.current = ghostGfx;\n\n alignGuidesRef.current = new AlignmentGuidesRenderer(pixi.world);\n\n freehandRef.current = new FreehandTool(pixi.app.stage, pixi.world, {\n onLineComplete: (line) => handleLineCompleteRef.current(line),\n screenToWorld: (sx, sy) => screenToWorldRef.current(sx, sy),\n });\n geoLineRef.current = new GeometricLineTool(pixi.app.stage, pixi.world, {\n onLineComplete: (line) => handleLineCompleteRef.current(line),\n screenToWorld: (sx, sy) => screenToWorldRef.current(sx, sy),\n });\n\n onPixiReady?.(pixi);\n const stage = pixi.app.stage;\n\n // ─── POINTER DOWN ───────────────────────────────────────\n stage.on('pointerdown', (e: FederatedPointerEvent) => {\n // Pixi interactions do not move DOM focus automatically. Explicitly\n // focus the canvas host so Mindmap Tab/Enter shortcuts are not handled\n // as focus navigation by a previously focused inspector control.\n containerRef.current?.focus({ preventScroll: true });\n // Multi-touch (pinch / two-finger pan): pointer interactions are\n // suppressed; the native touch handlers own the gesture.\n if (vmRef.current?.multiTouchActive) return;\n if (vmRef.current?.isPanning || vmRef.current?.isSpaceHeld) return;\n if (e.button !== 0) return;\n const mode = toolModeRef.current;\n if (mode === 'pan') {\n vmRef.current?.startPan(e.global.x, e.global.y);\n return;\n }\n if (mode === 'freehand' || mode === 'line' || mode === 'polyline' || mode === 'arrow') return;\n\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n const edges = canvasDataRef.current.edges;\n const lines = canvasDataRef.current.lines;\n const sel = selectionDataRef.current;\n const additive = e.metaKey || e.ctrlKey || e.shiftKey;\n const zoom = vmRef.current?.state.zoom ?? 1;\n\n // Pending placement has the highest priority: consume the press entirely\n // (no selection, no drag start). The stamp is created on pointertap so\n // that adding a second finger (pinch) can never drop an accidental stamp\n // on the first touch — important on capacitive screens.\n if (pendingPlacementRef.current) return;\n\n const now = Date.now();\n const lc = lastClickRef.current;\n const isDblClick = now - lc.time < 350 && Math.hypot(world.x - lc.wx, world.y - lc.wy) < 8 / zoom;\n lastClickRef.current = { time: now, wx: world.x, wy: world.y };\n\n // 0) Rotation knob (single-node selection, above the top-center)\n if (sel.nodeIds.size === 1 && !additive && mode === 'select' && !readOnlyRef.current) {\n const selNode = nodes.find(n => n.id === [...sel.nodeIds][0]);\n if (selNode) {\n const knob = rotationKnobPos(selNode, zoom);\n if (Math.hypot(world.x - knob.x, world.y - knob.y) < hitRadius(zoom, 12, 24)) {\n rotateRef.current = {\n active: true,\n nodeId: selNode.id,\n cx: selNode.position.x + selNode.width / 2,\n cy: selNode.position.y + selNode.height / 2,\n startPointerAngle: Math.atan2(world.y - (selNode.position.y + selNode.height / 2), world.x - (selNode.position.x + selNode.width / 2)),\n startRotation: selNode.data.rotation ?? 0,\n };\n beginNodeDragRef.current();\n return;\n }\n }\n }\n\n // 1) Resize handles (corners only, single-node selection, select mode)\n if (sel.nodeIds.size === 1 && !additive && mode === 'select') {\n const selNode = nodes.find(n => n.id === [...sel.nodeIds][0]);\n if (selNode) {\n const rh = getResizeHandleAt(world, selNode, hitRadius(zoom, 10, 16));\n if (rh) {\n const childStarts = new Map<string, { x: number; y: number; w: number; h: number }>();\n const childLineStarts = new Map<string, Array<{ x: number; y: number }>>();\n const isGeoGroup = selNode.type === 'geometryGroup';\n const isAnyGroup = isGeoGroup || selNode.type === 'flowGroup' || selNode.data.isGroup;\n const gx = selNode.position.x, gy = selNode.position.y;\n const gw = selNode.width, gh = selNode.height;\n for (const n of nodes) {\n if (n.id === selNode.id) continue;\n if (n.parentId === selNode.id) {\n childStarts.set(n.id, { x: n.position.x, y: n.position.y, w: n.width, h: n.height });\n } else if (isGeoGroup\n && n.position.x >= gx && n.position.y >= gy\n && n.position.x + n.width <= gx + gw\n && n.position.y + n.height <= gy + gh) {\n childStarts.set(n.id, { x: n.position.x, y: n.position.y, w: n.width, h: n.height });\n }\n }\n if (isAnyGroup) {\n for (const l of canvasDataRef.current.lines) {\n if (l.parentId === selNode.id) {\n childLineStarts.set(l.id, l.points.map(p => ({ ...p })));\n } else if (isGeoGroup && l.points.length > 0 && l.points.every(p =>\n p.x >= gx && p.x <= gx + gw && p.y >= gy && p.y <= gy + gh\n )) {\n childLineStarts.set(l.id, l.points.map(p => ({ ...p })));\n }\n }\n }\n resizeRef.current = {\n active: true, nodeId: selNode.id, handle: rh,\n startWorld: world,\n startBounds: { x: selNode.position.x, y: selNode.position.y, w: selNode.width, h: selNode.height },\n childStarts,\n childLineStarts: childLineStarts.size > 0 ? childLineStarts : undefined,\n };\n return;\n }\n }\n }\n\n // Hit test node — if the hit node is inside a group, redirect to the group\n let hitNode: FlowNode | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) { hitNode = nodes[i]; break; }\n }\n if (hitNode?.parentId) {\n const groupNode = nodes.find(n => n.id === hitNode!.parentId);\n if (groupNode) hitNode = groupNode;\n }\n\n // 2) Connection handle detection (works in both select and connect modes)\n if ((mode === 'select' || mode === 'connect') && (hitNode || COARSE_POINTER)) {\n // Touch: a finger often lands just outside a small node's bounds, so\n // with no direct node hit, scan every node's handles within the touch\n // radius (closest wins). Mouse keeps hit-node-only detection.\n const candidates = hitNode ? [hitNode] : nodes;\n const threshold = hitRadius(zoom, 14, 20);\n let bestNode: FlowNode | null = null;\n let bestHandle: ReturnType<typeof findClosestHandleWorld> = null;\n let bestDist = Infinity;\n for (const candidate of candidates) {\n const handles = getHandlePositions(candidate.width, candidate.height);\n const closest = findClosestHandleWorld(handles, candidate, world.x, world.y, threshold);\n if (!closest) continue;\n const wp = handleWorldPos(closest, candidate);\n const d = Math.hypot(world.x - wp.x, world.y - wp.y);\n if (d < bestDist) {\n bestDist = d;\n bestNode = candidate;\n bestHandle = closest;\n }\n }\n if (bestNode && bestHandle) {\n connectRef.current = { active: true, sourceNodeId: bestNode.id, sourceHandleId: bestHandle.id };\n return;\n }\n }\n\n // 3) Edge endpoint reconnection — only for SELECTED edges\n if ((mode === 'select' || mode === 'connect') && !additive && sel.edgeIds.size > 0) {\n const nodeMap = new Map<string, FlowNode>();\n for (const n of nodes) nodeMap.set(n.id, n);\n const selectedEdges = edges.filter(ed => sel.edgeIds.has(ed.id));\n const epHit = findEdgeEndpointNear(world.x, world.y, selectedEdges, nodeMap, hitRadius(zoom, 14, 20));\n if (epHit) {\n const edge = edges.find(ed => ed.id === epHit.edgeId);\n if (edge) {\n const fixedEnd = epHit.end === 'source' ? 'target' : 'source';\n reconnectRef.current = {\n active: true,\n edgeId: edge.id,\n movingEnd: epHit.end,\n fixedNodeId: fixedEnd === 'source' ? edge.source : edge.target,\n fixedHandleId: fixedEnd === 'source' ? edge.sourceHandle : edge.targetHandle,\n };\n return;\n }\n }\n }\n\n // 3.5) Waypoint / bezier control editing on selected edges\n if (mode === 'select' && sel.edgeIds.size > 0 && !hitNode) {\n const wmNodeMap = new Map<string, FlowNode>();\n for (const n of nodes) wmNodeMap.set(n.id, n);\n const selEdges = edges.filter(ed => sel.edgeIds.has(ed.id));\n const wpThreshold = hitRadius(zoom, 10, 14);\n\n const bzHit = findBezierControlNear(world.x, world.y, selEdges, wmNodeMap, wpThreshold);\n if (bzHit) {\n waypointDragRef.current = {\n active: true, edgeId: bzHit.edgeId,\n type: bzHit.controlEnd === 'c1' ? 'bezierC1' : 'bezierC2',\n index: bzHit.segmentIndex,\n };\n return;\n }\n\n const wpHit = findWaypointNear(world.x, world.y, selEdges, wpThreshold);\n if (wpHit) {\n if (isDblClick) {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(e => {\n if (e.id !== wpHit.edgeId) return e;\n const wps = [...(e.data.waypoints ?? [])];\n wps.splice(wpHit.waypointIndex, 1);\n const data = { ...e.data, waypoints: wps.length > 0 ? wps : undefined };\n if (e.type === 'simplebezier' && e.data.bezierControls) {\n const ctrls = [...e.data.bezierControls];\n ctrls.splice(wpHit.waypointIndex, 2, null);\n data.bezierControls = ctrls.some(c => c !== null) ? ctrls : undefined;\n }\n return { ...e, data };\n }),\n }},\n };\n });\n return;\n }\n waypointDragRef.current = { active: true, edgeId: wpHit.edgeId, type: 'waypoint', index: wpHit.waypointIndex };\n return;\n }\n\n if (isDblClick) {\n for (const edge of selEdges) {\n if (isPointNearEdgePath(world.x, world.y, edge, wmNodeMap, hitRadius(zoom, 8, 12))) {\n const insertIdx = findInsertionIndex(world.x, world.y, edge, wmNodeMap);\n const newWp = { x: world.x, y: world.y };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(e => {\n if (e.id !== edge.id) return e;\n const wps = [...(e.data.waypoints ?? [])];\n wps.splice(insertIdx, 0, newWp);\n const data = { ...e.data, waypoints: wps };\n if (e.type === 'simplebezier' && e.data.bezierControls) {\n const ctrls = [...e.data.bezierControls];\n while (ctrls.length < (e.data.waypoints ?? []).length + 1) ctrls.push(null);\n ctrls.splice(insertIdx, 1, null, null);\n data.bezierControls = ctrls;\n }\n return { ...e, data };\n }),\n }},\n };\n });\n waypointDragRef.current = { active: true, edgeId: edge.id, type: 'waypoint', index: insertIdx };\n return;\n }\n }\n }\n }\n\n // 4) Node body → select + drag\n if (hitNode && (mode === 'select' || mode === 'connect')) {\n if (!additive && !sel.nodeIds.has(hitNode.id)) {\n setSelection({ nodeIds: new Set([hitNode.id]), edgeIds: new Set(), lineIds: new Set() });\n } else if (additive) {\n setSelection(prev => {\n const ids = new Set(prev.nodeIds);\n if (ids.has(hitNode!.id)) ids.delete(hitNode!.id); else ids.add(hitNode!.id);\n return { nodeIds: ids, edgeIds: new Set(), lineIds: new Set() };\n });\n }\n if (autoFocusRef.current) {\n focusOnRectRef.current(\n hitNode.position.x,\n hitNode.position.y,\n hitNode.width,\n hitNode.height,\n { padding: 80, preserveZoom: true, duration: 280 },\n );\n }\n const dragIds = sel.nodeIds.has(hitNode.id)\n ? new Set(sel.nodeIds)\n : new Set([hitNode.id]);\n if (additive && !sel.nodeIds.has(hitNode.id)) dragIds.add(hitNode.id);\n // Include children of group nodes being dragged\n const dragLineIds = new Set<string>();\n for (const gId of [...dragIds]) {\n const gNode = nodes.find(nd => nd.id === gId);\n if (!gNode || (gNode.type !== 'flowGroup' && gNode.type !== 'geometryGroup' && !gNode.data.isGroup)) continue;\n const isGeo = gNode.type === 'geometryGroup';\n const gx = gNode.position.x, gy = gNode.position.y;\n const gw = gNode.width, gh = gNode.height;\n for (const n of nodes) {\n if (dragIds.has(n.id) || n.id === gId) continue;\n if (n.parentId === gId) { dragIds.add(n.id); continue; }\n if (isGeo\n && n.position.x >= gx && n.position.y >= gy\n && n.position.x + n.width <= gx + gw\n && n.position.y + n.height <= gy + gh) {\n dragIds.add(n.id);\n }\n }\n // Include child lines (by parentId)\n for (const l of canvasDataRef.current.lines) {\n if (l.parentId === gId) dragLineIds.add(l.id);\n }\n // Spatial containment for lines in geometryGroup\n if (isGeo) {\n for (const l of canvasDataRef.current.lines) {\n if (dragLineIds.has(l.id)) continue;\n if (l.points.length > 0 && l.points.every(p =>\n p.x >= gx && p.x <= gx + gw && p.y >= gy && p.y <= gy + gh\n )) {\n dragLineIds.add(l.id);\n }\n }\n }\n }\n const nodeStarts = new Map<string, { x: number; y: number }>();\n for (const n of nodes) { if (dragIds.has(n.id)) nodeStarts.set(n.id, { ...n.position }); }\n const linePointStarts = new Map<string, Array<{ x: number; y: number }>>();\n if (dragLineIds.size > 0) {\n for (const l of canvasDataRef.current.lines) {\n if (dragLineIds.has(l.id)) linePointStarts.set(l.id, l.points.map(p => ({ ...p })));\n }\n }\n dragRef.current = { active: true, nodeIds: dragIds, lineIds: dragLineIds.size > 0 ? dragLineIds : undefined, startWorld: world, nodeStarts, linePointStarts: linePointStarts.size > 0 ? linePointStarts : undefined };\n beginNodeDragRef.current();\n return;\n }\n\n // 5) Edge hit test → select edge\n const nodeMap2 = new Map<string, FlowNode>();\n for (const n of nodes) nodeMap2.set(n.id, n);\n const hitThreshold = hitRadius(zoom, 8, 12);\n for (const edge of edges) {\n if (isPointNearEdgePath(world.x, world.y, edge, nodeMap2, hitThreshold)) {\n if (additive) {\n setSelection(prev => {\n const ids = new Set(prev.edgeIds);\n if (ids.has(edge.id)) ids.delete(edge.id); else ids.add(edge.id);\n return { ...prev, edgeIds: ids };\n });\n } else {\n setSelection({ nodeIds: new Set(), edgeIds: new Set([edge.id]), lineIds: new Set() });\n }\n if (autoFocusRef.current) {\n const source = nodeMap2.get(edge.source);\n const target = nodeMap2.get(edge.target);\n if (source && target) {\n const minX = Math.min(source.position.x, target.position.x);\n const minY = Math.min(source.position.y, target.position.y);\n const maxX = Math.max(source.position.x + source.width, target.position.x + target.width);\n const maxY = Math.max(source.position.y + source.height, target.position.y + target.height);\n focusOnRectRef.current(minX, minY, maxX - minX, maxY - minY, {\n padding: 80,\n preserveZoom: true,\n duration: 280,\n });\n }\n }\n return;\n }\n }\n\n // 5) Line hit test → select + drag line\n for (const line of lines) {\n if (isPointNearLine(world.x, world.y, line, hitThreshold)) {\n const alreadySelected = sel.lineIds.has(line.id);\n if (additive) {\n setSelection(prev => {\n const ids = new Set(prev.lineIds);\n if (ids.has(line.id)) ids.delete(line.id); else ids.add(line.id);\n return { ...prev, lineIds: ids };\n });\n } else if (!alreadySelected) {\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set([line.id]) });\n }\n if (autoFocusRef.current && line.points.length > 0) {\n const xs = line.points.map(point => point.x);\n const ys = line.points.map(point => point.y);\n const minX = Math.min(...xs);\n const minY = Math.min(...ys);\n const maxX = Math.max(...xs);\n const maxY = Math.max(...ys);\n focusOnRectRef.current(minX, minY, Math.max(1, maxX - minX), Math.max(1, maxY - minY), {\n padding: 80,\n preserveZoom: true,\n duration: 280,\n });\n }\n // Start line drag\n const dragLineIds = alreadySelected ? new Set(sel.lineIds) : new Set([line.id]);\n const pointStarts = new Map<string, Array<{ x: number; y: number }>>();\n for (const l of lines) {\n if (dragLineIds.has(l.id)) pointStarts.set(l.id, l.points.map(p => ({ ...p })));\n }\n lineDragRef.current = { active: true, lineIds: dragLineIds, startWorld: world, pointStarts };\n return;\n }\n }\n\n // 6) Empty space → clear selection, start marquee\n if (!additive) {\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n }\n if (mode === 'select') {\n marqueeRef.current = { active: true, startScreen: { x: e.global.x, y: e.global.y } };\n }\n });\n\n // ─── POINTER MOVE ──────────────────────────────────────\n stage.on('globalpointermove', (e: FederatedPointerEvent) => {\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n mouseWorldRef.current = world;\n // While a multi-touch gesture is active, hover/drag updates are suppressed\n // (the native pinch/pan handlers own the pointer).\n if (vmRef.current?.multiTouchActive) return;\n\n const mode = toolModeRef.current;\n if (mode === 'freehand' || mode === 'line' || mode === 'polyline' || mode === 'arrow') return;\n\n const nodes = canvasDataRef.current.nodes;\n const edges = canvasDataRef.current.edges;\n const zoom = vmRef.current?.state.zoom ?? 1;\n const isIdle = !dragRef.current?.active && !connectRef.current?.active\n && !resizeRef.current?.active && !reconnectRef.current?.active\n && !waypointDragRef.current?.active && !lineDragRef.current?.active\n && !rotateRef.current?.active;\n\n // Hover tracking — redirect child hovers to parent group\n let hovered: string | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) {\n const n = nodes[i];\n hovered = n.parentId\n ? (nodes.find(g => g.id === n.parentId)?.id ?? n.id)\n : n.id;\n break;\n }\n }\n hoveredNodeRef.current = hovered;\n\n // Hover detection for connection handles and edge endpoints (when idle)\n if (isIdle && (mode === 'select' || mode === 'connect')) {\n const nodeMap = new Map<string, FlowNode>();\n for (const n of nodes) nodeMap.set(n.id, n);\n\n // Check edge endpoint hover — only for selected edges\n const sel = selectionDataRef.current;\n const selectedEdges = sel.edgeIds.size > 0 ? edges.filter(ed => sel.edgeIds.has(ed.id)) : [];\n const epHit = selectedEdges.length > 0\n ? findEdgeEndpointNear(world.x, world.y, selectedEdges, nodeMap, hitRadius(zoom, 12, 18))\n : null;\n hoveredEdgeEndpointRef.current = epHit;\n\n // Check connection handle hover on any node\n let foundHandle: typeof hoveredHandleRef.current = null;\n if (hovered) {\n const node = nodes.find(n => n.id === hovered);\n if (node) {\n const handles = getHandlePositions(node.width, node.height);\n const closest = findClosestHandleWorld(handles, node, world.x, world.y, hitRadius(zoom, 14, 20));\n if (closest) {\n const wp = handleWorldPos(closest, node);\n foundHandle = { nodeId: node.id, handleId: closest.id, wx: wp.x, wy: wp.y };\n }\n }\n }\n hoveredHandleRef.current = foundHandle;\n }\n\n // Cursor updates\n const el = containerRef.current;\n if (el && isIdle) {\n const sel = selectionDataRef.current;\n let cursor = '';\n if (hoveredEdgeEndpointRef.current) {\n cursor = 'crosshair';\n } else if (hoveredHandleRef.current) {\n cursor = 'crosshair';\n } else if (sel.edgeIds.size > 0 && mode === 'select') {\n const selEdgesForCursor = edges.filter(ed => sel.edgeIds.has(ed.id));\n const cursorNm = new Map<string, FlowNode>();\n for (const n of nodes) cursorNm.set(n.id, n);\n const wpThreshold = hitRadius(zoom, 10, 14);\n if (findWaypointNear(world.x, world.y, selEdgesForCursor, wpThreshold)\n || findBezierControlNear(world.x, world.y, selEdgesForCursor, cursorNm, wpThreshold)) {\n cursor = 'grab';\n }\n }\n if (!cursor && sel.nodeIds.size === 1 && mode === 'select') {\n const selNode = nodes.find(n => n.id === [...sel.nodeIds][0]);\n if (selNode) {\n const rh = getResizeHandleAt(world, selNode, hitRadius(zoom, 10, 16));\n if (rh) cursor = RESIZE_CURSORS[rh];\n else if (!readOnlyRef.current) {\n const knob = rotationKnobPos(selNode, zoom);\n if (Math.hypot(world.x - knob.x, world.y - knob.y) < hitRadius(zoom, 12, 24)) cursor = 'grab';\n }\n }\n }\n if (!cursor && mode === 'select') {\n const hoverLines = canvasDataRef.current.lines;\n const lineHitT = hitRadius(zoom, 8, 12);\n for (const ln of hoverLines) {\n if (isPointNearLine(world.x, world.y, ln, lineHitT)) {\n cursor = 'move';\n break;\n }\n }\n }\n el.style.cursor = cursor;\n }\n\n // Resize with alignment snapping\n if (resizeRef.current?.active) {\n const r = resizeRef.current;\n const dx = world.x - r.startWorld.x;\n const dy = world.y - r.startWorld.y;\n const nb = applyResize(r.startBounds, r.handle, dx, dy);\n const allNodes = canvasDataRef.current.nodes;\n const virtualNode: FlowNode = { id: r.nodeId, type: 'shapeRect', position: { x: nb.x, y: nb.y }, width: nb.w, height: nb.h, data: {} as any };\n const snap = computeAlignmentSnap([virtualNode], allNodes);\n nb.x += snap.dx; nb.y += snap.dy;\n if (r.handle === 'ne' || r.handle === 'se') nb.w += snap.dx;\n if (r.handle === 'se' || r.handle === 'sw') nb.h += snap.dy;\n activeGuidesRef.current = snap.guides;\n\n // Placement magnet: snap the moving edges to the canvas grid when no\n // alignment guide is active.\n if (placementSnapRef.current && gridSizeRef.current > 0 && snap.guides.length === 0) {\n const gs = gridSizeRef.current;\n if (r.handle === 'nw' || r.handle === 'sw') nb.x = Math.round(nb.x / gs) * gs;\n if (r.handle === 'nw' || r.handle === 'ne') nb.y = Math.round(nb.y / gs) * gs;\n if (r.handle === 'ne' || r.handle === 'se') nb.w = Math.round((nb.x + nb.w) / gs) * gs - nb.x;\n if (r.handle === 'se' || r.handle === 'sw') nb.h = Math.round((nb.y + nb.h) / gs) * gs - nb.y;\n }\n\n const ob = r.startBounds;\n const finalW = Math.max(nb.w, 24);\n const finalH = Math.max(nb.h, 24);\n const scaleX = ob.w > 0 ? finalW / ob.w : 1;\n const scaleY = ob.h > 0 ? finalH / ob.h : 1;\n\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n if (n.id === r.nodeId) {\n return { ...n, position: { x: nb.x, y: nb.y }, width: finalW, height: finalH };\n }\n const cs = r.childStarts.get(n.id);\n if (cs) {\n return {\n ...n,\n position: {\n x: nb.x + (cs.x - ob.x) * scaleX,\n y: nb.y + (cs.y - ob.y) * scaleY,\n },\n width: Math.max(cs.w * scaleX, 24),\n height: Math.max(cs.h * scaleY, 24),\n };\n }\n return n;\n }),\n lines: r.childLineStarts\n ? canvas.lines.map(l => {\n const pts = r.childLineStarts!.get(l.id);\n if (!pts) return l;\n return {\n ...l,\n points: pts.map(p => ({\n x: nb.x + (p.x - ob.x) * scaleX,\n y: nb.y + (p.y - ob.y) * scaleY,\n })),\n };\n })\n : canvas.lines,\n },\n },\n };\n });\n return;\n }\n\n // Rotation knob drag: angle follows the pointer around the node center.\n // Shift snaps to 15° steps; otherwise right angles get a gentle magnet.\n if (rotateRef.current?.active) {\n const rot = rotateRef.current;\n const angle = Math.atan2(world.y - rot.cy, world.x - rot.cx);\n const delta = (angle - rot.startPointerAngle) * 180 / Math.PI;\n let next = ((rot.startRotation + delta) % 360 + 360) % 360;\n if (e.shiftKey) {\n next = Math.round(next / 15) * 15 % 360;\n } else {\n const snap = Math.round(next / 45) * 45;\n if (Math.abs(next - snap) < 4) next = ((snap % 360) + 360) % 360;\n }\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: canvas.nodes.map(n =>\n n.id === rot.nodeId ? { ...n, data: { ...n.data, rotation: next } } : n,\n ),\n }},\n };\n });\n if (containerRef.current) containerRef.current.style.cursor = 'grabbing';\n return;\n }\n\n // Waypoint / bezier control drag\n if (waypointDragRef.current?.active) {\n const wpd = waypointDragRef.current;\n const wpNodes = canvasDataRef.current.nodes;\n const wpNm = new Map<string, FlowNode>();\n for (const nd of wpNodes) wpNm.set(nd.id, nd);\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(e => {\n if (e.id !== wpd.edgeId) return e;\n if (wpd.type === 'waypoint') {\n const wps = [...(e.data.waypoints ?? [])];\n if (wpd.index < wps.length) wps[wpd.index] = { x: world.x, y: world.y };\n return { ...e, data: { ...e.data, waypoints: wps } };\n }\n const ep = resolveEdgeEndpoints(e, wpNm);\n if (!ep) return e;\n const allWps = e.data.waypoints ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...allWps, { x: ep.tx, y: ep.ty }];\n const segCount = allPts.length - 1;\n const ctrls: Array<FlowBezierControl | null> = [...(e.data.bezierControls ?? [])];\n while (ctrls.length < segCount) ctrls.push(null);\n const si = wpd.index;\n if (si >= segCount) return e;\n const a = allPts[si], b = allPts[si + 1];\n const existing = ctrls[si];\n const segDist = Math.hypot(b.x - a.x, b.y - a.y);\n const arm = Math.max(30, segDist * 0.3);\n const lastSegIdx = segCount - 1;\n const defC1x = si === 0 ? a.x + ep.snx * arm : a.x + (b.x - a.x) * 0.4;\n const defC1y = si === 0 ? a.y + ep.sny * arm : a.y;\n const defC2x = si === lastSegIdx ? b.x + ep.tnx * arm : b.x - (b.x - a.x) * 0.4;\n const defC2y = si === lastSegIdx ? b.y + ep.tny * arm : b.y;\n if (wpd.type === 'bezierC1') {\n ctrls[si] = {\n c1x: world.x, c1y: world.y,\n c2x: existing?.c2x ?? defC2x, c2y: existing?.c2y ?? defC2y,\n };\n } else {\n ctrls[si] = {\n c1x: existing?.c1x ?? defC1x, c1y: existing?.c1y ?? defC1y,\n c2x: world.x, c2y: world.y,\n };\n }\n return { ...e, data: { ...e.data, bezierControls: ctrls } };\n }),\n }},\n };\n });\n return;\n }\n\n // Line drag\n if (lineDragRef.current?.active) {\n const ld = lineDragRef.current;\n const dx = world.x - ld.startWorld.x;\n const dy = world.y - ld.startWorld.y;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n lines: canvas.lines.map(l => {\n const starts = ld.pointStarts.get(l.id);\n if (!starts) return l;\n return { ...l, points: starts.map(p => ({ x: p.x + dx, y: p.y + dy })) };\n }),\n }},\n };\n });\n return;\n }\n\n // Node drag with alignment snapping\n if (dragRef.current?.active) {\n const drag = dragRef.current;\n const rawDx = world.x - drag.startWorld.x;\n const rawDy = world.y - drag.startWorld.y;\n // Placement magnet: pre-snap the raw delta to the canvas grid so the\n // first dragged node's top-left tracks the grid (alignment guides are\n // evaluated on the gridded position and win when they trigger).\n let dx = rawDx;\n let dy = rawDy;\n if (placementSnapRef.current && gridSizeRef.current > 0 && drag.nodeIds.size > 0) {\n const gs = gridSizeRef.current;\n const firstStart = drag.nodeStarts.values().next().value;\n if (firstStart) {\n dx = snapPlacement(firstStart.x + rawDx, gs, true) - firstStart.x;\n dy = snapPlacement(firstStart.y + rawDy, gs, true) - firstStart.y;\n }\n }\n const allNodes = canvasDataRef.current.nodes;\n const dragNodes = allNodes\n .filter(n => drag.nodeIds.has(n.id))\n .map(n => {\n const start = drag.nodeStarts.get(n.id)!;\n return { ...n, position: { x: start.x + dx, y: start.y + dy } };\n });\n const snap = computeAlignmentSnap(dragNodes, allNodes);\n dx += snap.dx;\n dy += snap.dy;\n activeGuidesRef.current = snap.guides;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n const start = drag.nodeStarts.get(n.id);\n if (!start) return n;\n return { ...n, position: { x: start.x + dx, y: start.y + dy } };\n }),\n lines: drag.linePointStarts\n ? canvas.lines.map(l => {\n const starts = drag.linePointStarts!.get(l.id);\n if (!starts) return l;\n return { ...l, points: starts.map(p => ({ x: p.x + dx, y: p.y + dy })) };\n })\n : canvas.lines,\n },\n },\n };\n });\n return;\n }\n\n // Marquee\n if (marqueeRef.current?.active && selectionRef.current) {\n const mx = Math.min(marqueeRef.current.startScreen.x, e.global.x);\n const my = Math.min(marqueeRef.current.startScreen.y, e.global.y);\n const mw = Math.abs(e.global.x - marqueeRef.current.startScreen.x);\n const mh = Math.abs(e.global.y - marqueeRef.current.startScreen.y);\n selectionRef.current.showMarquee(mx, my, mw, mh);\n }\n\n // Connect line preview — snaps to nearest handle on target node\n if (connectRef.current?.active && connectLineRef.current) {\n const srcNode = canvasDataRef.current.nodes.find(n => n.id === connectRef.current!.sourceNodeId);\n if (srcNode) {\n const handles = getHandlePositions(srcNode.width, srcNode.height);\n const handle = handles.find(h => h.id === connectRef.current!.sourceHandleId);\n if (handle) {\n const swp = handleWorldPos(handle, srcNode);\n const sx = swp.x;\n const sy = swp.y;\n let ex = world.x, ey = world.y;\n\n // Snap endpoint to closest handle if hovering over a different node\n const hovNode = hoveredNodeRef.current;\n if (hovNode && hovNode !== connectRef.current!.sourceNodeId) {\n const tNode = canvasDataRef.current.nodes.find(n => n.id === hovNode);\n if (tNode) {\n const tHandles = getHandlePositions(tNode.width, tNode.height);\n const snap = findClosestHandleWorld(tHandles, tNode, world.x, world.y, Infinity);\n if (snap) { const wp = handleWorldPos(snap, tNode); ex = wp.x; ey = wp.y; }\n }\n }\n\n const g = connectLineRef.current;\n g.clear();\n g.moveTo(sx, sy).lineTo(ex, ey)\n .stroke({ color: 0x3b82f6, width: 2, alpha: 0.6 });\n g.visible = true;\n }\n }\n }\n\n // Reconnect line preview — snaps to nearest handle on target node\n if (reconnectRef.current?.active && connectLineRef.current && !connectLineRef.current.destroyed) {\n const rc = reconnectRef.current;\n const fixedNode = canvasDataRef.current.nodes.find(n => n.id === rc.fixedNodeId);\n if (fixedNode) {\n const handles = getHandlePositions(fixedNode.width, fixedNode.height);\n const fh = handles.find(h => h.id === rc.fixedHandleId);\n const fwp = fh ? handleWorldPos(fh, fixedNode) : { x: fixedNode.position.x + fixedNode.width / 2, y: fixedNode.position.y + fixedNode.height / 2 };\n const fx = fwp.x, fy = fwp.y;\n let ex = world.x, ey = world.y;\n\n const hovNode = hoveredNodeRef.current;\n if (hovNode && hovNode !== rc.fixedNodeId) {\n const tNode = canvasDataRef.current.nodes.find(n => n.id === hovNode);\n if (tNode) {\n const tHandles = getHandlePositions(tNode.width, tNode.height);\n const snap = findClosestHandleWorld(tHandles, tNode, world.x, world.y, Infinity);\n if (snap) { const wp = handleWorldPos(snap, tNode); ex = wp.x; ey = wp.y; }\n }\n }\n\n const g = connectLineRef.current;\n g.clear();\n g.moveTo(fx, fy).lineTo(ex, ey)\n .stroke({ color: 0xf97316, width: 2, alpha: 0.7 });\n g.visible = true;\n }\n }\n });\n\n // ─── POINTER UP ────────────────────────────────────────\n const cleanupDrag = () => {\n activeGuidesRef.current = [];\n try { alignGuidesRef.current?.clear(); } catch { /* destroyed */ }\n try {\n const cl = connectLineRef.current;\n if (cl && !cl.destroyed) { cl.clear(); cl.visible = false; }\n } catch { /* destroyed */ }\n if (containerRef.current) containerRef.current.style.cursor = '';\n };\n\n stage.on('pointerup', (e: FederatedPointerEvent) => {\n cleanupDrag();\n\n if (rotateRef.current?.active) {\n rotateRef.current = null;\n endNodeDragRef.current();\n return;\n }\n\n if (waypointDragRef.current?.active) {\n waypointDragRef.current = null;\n return;\n }\n\n if (resizeRef.current?.active) {\n resizeRef.current = null;\n return;\n }\n\n if (lineDragRef.current?.active) {\n lineDragRef.current = null;\n return;\n }\n\n if (dragRef.current?.active) {\n dragRef.current = null;\n endNodeDragRef.current();\n }\n\n if (marqueeRef.current?.active) {\n const start = screenToWorldRef.current(marqueeRef.current.startScreen.x, marqueeRef.current.startScreen.y);\n const end = screenToWorldRef.current(e.global.x, e.global.y);\n const mx = Math.min(start.x, end.x), my = Math.min(start.y, end.y);\n const mw = Math.abs(end.x - start.x), mh = Math.abs(end.y - start.y);\n if (mw > 4 && mh > 4) {\n const hit = canvasDataRef.current.nodes.filter(n =>\n rectsOverlap(mx, my, mw, mh, n.position.x, n.position.y, n.width, n.height),\n );\n const hitLines = canvasDataRef.current.lines.filter(l => {\n if (l.points.length === 0) return false;\n return l.points.every(p => p.x >= mx && p.x <= mx + mw && p.y >= my && p.y <= my + mh);\n });\n setSelection({\n nodeIds: new Set(hit.map(n => n.id)),\n edgeIds: new Set(),\n lineIds: new Set(hitLines.map(l => l.id)),\n });\n }\n marqueeRef.current = null;\n selectionRef.current?.hideMarquee();\n }\n\n // Reconnection completion\n if (reconnectRef.current?.active) {\n const rcEdgeId = reconnectRef.current.edgeId;\n const rcMovingEnd = reconnectRef.current.movingEnd;\n const rcFixedNodeId = reconnectRef.current.fixedNodeId;\n reconnectRef.current = null;\n\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n // Touch: a finger release often lands just outside the target node's\n // bounds, so allow a small padded hit area when dropping a connection.\n const dropPad = COARSE_POINTER ? hitRadius(vmRef.current?.state.zoom ?? 1, 12, 24) : 0;\n let targetNode: FlowNode | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i], dropPad) && nodes[i].id !== rcFixedNodeId) {\n targetNode = nodes[i]; break;\n }\n }\n if (targetNode) {\n const tgtId = targetNode.id;\n const handles = getHandlePositions(targetNode.width, targetNode.height);\n const closest = findClosestHandleWorld(handles, targetNode, world.x, world.y, Infinity);\n const tgtHandleId = closest?.id;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(edge => {\n if (edge.id !== rcEdgeId) return edge;\n if (rcMovingEnd === 'source') {\n return { ...edge, source: tgtId, sourceHandle: tgtHandleId };\n } else {\n return { ...edge, target: tgtId, targetHandle: tgtHandleId };\n }\n }),\n },\n },\n };\n });\n }\n return;\n }\n\n // New connection completion\n if (connectRef.current?.active) {\n const srcNodeId = connectRef.current.sourceNodeId;\n const srcHandleId = connectRef.current.sourceHandleId;\n connectRef.current = null;\n\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n // Same touch-padded drop target as reconnection above.\n const dropPad = COARSE_POINTER ? hitRadius(vmRef.current?.state.zoom ?? 1, 12, 24) : 0;\n let targetNode: FlowNode | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i], dropPad) && nodes[i].id !== srcNodeId) {\n targetNode = nodes[i]; break;\n }\n }\n if (targetNode) {\n const tgtNodeId = targetNode.id;\n const handles = getHandlePositions(targetNode.width, targetNode.height);\n const closest = findClosestHandleWorld(handles, targetNode, world.x, world.y, Infinity);\n const tgtHandleId = closest?.id;\n const id = `edge_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;\n const eType = edgeTypeRef.current;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n if (canvas.edges.some(e =>\n e.source === srcNodeId && e.target === tgtNodeId\n && e.sourceHandle === srcHandleId && e.targetHandle === tgtHandleId\n )) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n edges: [...canvas.edges, {\n id,\n source: srcNodeId,\n target: tgtNodeId,\n sourceHandle: srcHandleId,\n targetHandle: tgtHandleId,\n type: eType as any,\n data: { strokeColor: 'theme:base-content', strokeWidth: 2, lineStyle: 'solid' as const, markerEnd: 'arrowclosed' as const },\n }],\n },\n },\n };\n });\n }\n }\n });\n\n stage.on('pointerupoutside', () => {\n cleanupDrag();\n if (dragRef.current?.active) endNodeDragRef.current();\n if (rotateRef.current?.active) endNodeDragRef.current();\n dragRef.current = null;\n rotateRef.current = null;\n resizeRef.current = null;\n marqueeRef.current = null;\n reconnectRef.current = null;\n connectRef.current = null;\n waypointDragRef.current = null;\n lineDragRef.current = null;\n selectionRef.current?.hideMarquee();\n });\n\n // ─── NATIVE TOUCH GESTURES (pinch zoom + two-finger pan) ───\n // Pixi delivers single-pointer events only; a real multi-touch gesture\n // needs native touch listeners. They live on the container (parent of the\n // Pixi canvas) so they also cover the whole interactive surface. While two\n // fingers are down, `multiTouchActive` suppresses all Pixi pointer\n // interactions so node drags/marquees/tap-to-place never fight the pinch.\n const touchEl = containerRef.current;\n let pinch: { dist: number; midX: number; midY: number } | null = null;\n const readPinch = (touches: TouchList) => {\n const rect = touchEl!.getBoundingClientRect();\n const ax = touches[0].clientX, ay = touches[0].clientY;\n const bx = touches[1].clientX, by = touches[1].clientY;\n return {\n dist: Math.hypot(bx - ax, by - ay),\n midX: (ax + bx) / 2 - rect.left,\n midY: (ay + by) / 2 - rect.top,\n };\n };\n const cancelPointerInteractions = () => {\n // Mirror the pointerupoutside cleanup: a finger that already started a\n // node drag / marquee / pan before the second finger landed must not\n // leave stale drag state behind.\n cleanupDrag();\n if (dragRef.current?.active) endNodeDragRef.current();\n if (rotateRef.current?.active) endNodeDragRef.current();\n dragRef.current = null;\n rotateRef.current = null;\n resizeRef.current = null;\n marqueeRef.current = null;\n reconnectRef.current = null;\n connectRef.current = null;\n waypointDragRef.current = null;\n lineDragRef.current = null;\n selectionRef.current?.hideMarquee();\n vmRef.current?.cancelPan();\n };\n const onTouchStart = (e: TouchEvent) => {\n if (e.touches.length < 2) return;\n const vm = vmRef.current;\n if (!vm) return;\n vm.multiTouchActive = true;\n cancelPointerInteractions();\n pinch = readPinch(e.touches);\n // Block the browser's own page zoom / scroll gesture on the canvas.\n e.preventDefault();\n };\n const onTouchMove = (e: TouchEvent) => {\n if (!pinch || e.touches.length < 2) return;\n e.preventDefault();\n const vm = vmRef.current;\n if (!vm) return;\n const next = readPinch(e.touches);\n const factor = next.dist / Math.max(1, pinch.dist);\n if (Number.isFinite(factor) && factor > 0) vm.zoomAt(next.midX, next.midY, factor);\n // Follow the midpoint so two-finger drag pans the canvas (map-style).\n vm.setState({\n x: vm.state.x + (next.midX - pinch.midX),\n y: vm.state.y + (next.midY - pinch.midY),\n });\n pinch = next;\n };\n const onTouchEnd = (e: TouchEvent) => {\n if (e.touches.length >= 2) {\n pinch = readPinch(e.touches);\n return;\n }\n // Fewer than two fingers left: stop pinching. Keep `multiTouchActive`\n // until ALL fingers lift so the remaining finger cannot start a marquee\n // or drag as a \"first touch\"; the flag clears on the final touchend.\n pinch = null;\n if (e.touches.length === 0) {\n const vm = vmRef.current;\n if (vm) vm.multiTouchActive = false;\n // Swallow the tap that the last finger's pointerup produces.\n suppressTapUntilRef.current = performance.now() + 350;\n }\n };\n touchEl?.addEventListener('touchstart', onTouchStart, { passive: false });\n touchEl?.addEventListener('touchmove', onTouchMove, { passive: false });\n touchEl?.addEventListener('touchend', onTouchEnd);\n touchEl?.addEventListener('touchcancel', onTouchEnd);\n touchStartHandler = onTouchStart;\n touchMoveHandler = onTouchMove;\n touchEndHandler = onTouchEnd;\n\n // ─── RIGHT-CLICK CONTEXT MENU ─────────────────────────\n stage.on('rightclick', (e: FederatedPointerEvent) => {\n e.preventDefault?.();\n // If the right button was used to pan (drawio-style right-drag), don't\n // open the context menu — only a stationary right-click should.\n if (vmRef.current?.didRightPan) return;\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n let hitNodeId: string | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) {\n hitNodeId = nodes[i].id;\n break;\n }\n }\n const native = (e as any).nativeEvent as MouseEvent | undefined;\n const cx = native?.clientX ?? e.global.x;\n const cy = native?.clientY ?? e.global.y;\n setContextMenu({ x: cx, y: cy, nodeId: hitNodeId });\n });\n\n // ─── TAP → PLACE STAMP / DOUBLE-CLICK → ENTER SUB-CANVAS / EDIT LABEL ────\n stage.on('pointertap', (e: FederatedPointerEvent) => {\n // Suppress taps that belong to (or immediately follow) a multi-touch\n // pinch/pan gesture.\n if (vmRef.current?.multiTouchActive) return;\n if (performance.now() < suppressTapUntilRef.current) return;\n if (e.button !== 0) return;\n const now = Date.now();\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n\n // Pending placement: stamp the new object at the tap position. Placement\n // lives here (on tap) instead of pointerdown so that adding a second\n // finger mid-gesture (pinch) never drops an accidental stamp.\n const pp = pendingPlacementRef.current;\n if (pp) {\n const newId = generateId('node');\n // Placement magnet: snap the stamp to the canvas grid when enabled\n // (alignment snapping below still wins when it triggers).\n const gs = gridSizeRef.current;\n const snapOn = placementSnapRef.current;\n const rawX = snapPlacement(world.x - pp.width / 2, gs, snapOn);\n const rawY = snapPlacement(world.y - pp.height / 2, gs, snapOn);\n const virtual: FlowNode = {\n id: '__ghost__', type: pp.type,\n position: { x: rawX, y: rawY },\n width: pp.width, height: pp.height, data: {} as any,\n };\n const snap = computeAlignmentSnap([virtual], canvasDataRef.current.nodes);\n const px = rawX + snap.dx;\n const py = rawY + snap.dy;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n const extraData: Record<string, any> = {};\n if (pp.type === 'animAnchor') extraData.animIndex = nextAnimIndex(prev);\n const highestZ = Math.max(\n 0,\n ...canvas.nodes.map(node => node.zIndex ?? 0),\n ...canvas.lines.map(line => line.zIndex ?? 0),\n );\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: [...canvas.nodes, {\n id: newId,\n type: pp.type,\n position: { x: px, y: py },\n width: pp.width,\n height: pp.height,\n zIndex: highestZ + 1,\n data: { ...pp.data, ...extraData },\n }],\n }},\n };\n });\n setSelection({ nodeIds: new Set([newId]), edgeIds: new Set(), lineIds: new Set() });\n if (autoFocusRef.current) {\n window.setTimeout(() => {\n focusOnRectRef.current(px, py, pp.width, pp.height, {\n padding: 80,\n preserveZoom: true,\n duration: 280,\n });\n }, 0);\n }\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n\n const last = dblClickRef.current;\n const dx = world.x - last.wx;\n const dy = world.y - last.wy;\n if (now - last.time < 400 && Math.abs(dx) < 10 && Math.abs(dy) < 10) {\n const nodes = canvasDataRef.current.nodes;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) {\n const node = nodes[i];\n const childId = node.data.childCanvasId;\n if (childId) {\n pushCanvas(childId);\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n // Double-click a shape → edit its label in place.\n beginEditRef.current('node', node.id, node.data.label ?? '');\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n }\n\n // Double-click an edge → edit its label.\n const edges = canvasDataRef.current.edges;\n const wmNodeMap = new Map<string, FlowNode>();\n for (const n of nodes) wmNodeMap.set(n.id, n);\n const zoom = vmRef.current?.state.zoom ?? 1;\n for (let i = edges.length - 1; i >= 0; i--) {\n if (isPointNearEdgePath(world.x, world.y, edges[i], wmNodeMap, hitRadius(zoom, 8, 12))) {\n beginEditRef.current('edge', edges[i].id, edges[i].data.labelText ?? '');\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n }\n }\n dblClickRef.current = { time: now, wx: world.x, wy: world.y };\n });\n\n // ─── RENDER LOOP ───────────────────────────────────\n let wasPanning = false;\n pixi.app.ticker.add((ticker) => {\n if (pixi.destroyed) return;\n const deltaMs = ticker.deltaMS;\n const screen = pixi.app.screen;\n const vp = vmRef.current?.state ?? { x: 0, y: 0, zoom: 1 };\n gridRef.current?.update(vp, screen.width, screen.height);\n\n // Show a grabbing cursor while panning (right-drag / middle / space).\n const panningNow = vmRef.current?.isPanning ?? false;\n if (panningNow !== wasPanning) {\n wasPanning = panningNow;\n if (containerRef.current) {\n containerRef.current.style.cursor = panningNow ? 'grabbing' : '';\n }\n }\n\n const cData = canvasDataRef.current;\n const sel = selectionDataRef.current;\n\n // Global (document-wide) animation-anchor sequence so sub-canvas badges\n // share one order and the presentation can drill in/out consistently.\n const slides = getDocumentSlides(docRef.current);\n const animSeqMap = new Map<string, number>();\n slides.forEach((s, i) => animSeqMap.set(s.node.id, i + 1));\n\n nodeRendererRef.current?.advanceAnimation(deltaMs);\n const activeSlide = presentationRef.current\n ? slides[presentationRef.current.current]\n : undefined;\n nodeRendererRef.current?.sync(cData.nodes, sel.nodeIds, hoveredNodeRef.current, animSeqMap, {\n showAnchors: showAnchorsRef.current,\n presentation: presentationRef.current !== null,\n presentationAnchorId: activeSlide?.node.id,\n presentationAnchorVisible: presentationRef.current?.showAnchor ?? false,\n });\n\n const nodeMap = new Map<string, FlowNode>();\n for (const n of cData.nodes) nodeMap.set(n.id, n);\n edgeRendererRef.current?.advanceAnimation(deltaMs);\n edgeRendererRef.current?.sync(cData.edges, nodeMap, sel.edgeIds, null, {\n presentation: presentationRef.current !== null,\n });\n\n lineRendererRef.current?.advanceAnimation(deltaMs);\n lineRendererRef.current?.sync(cData.lines, sel.lineIds);\n\n // Draw alignment guides in world space\n alignGuidesRef.current?.update(activeGuidesRef.current, screen.width, screen.height, vp);\n\n // Selection delete button (touch-friendly counterpart of the Delete\n // key): a DOM button pinned to the top-right of the selection's screen\n // bounding box, re-positioned every frame. Styles are written directly\n // to avoid per-frame React renders.\n const delBtn = deleteButtonRef.current;\n if (delBtn) {\n const hasSelection = sel.nodeIds.size > 0 || sel.edgeIds.size > 0 || sel.lineIds.size > 0;\n const showDelete = hasSelection && !readOnlyRef.current\n && !presentationRef.current && !pendingPlacementRef.current;\n let boundsEmpty = !showDelete;\n if (showDelete) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n const bump = (x: number, y: number, w: number, h: number) => {\n minX = Math.min(minX, x); minY = Math.min(minY, y);\n maxX = Math.max(maxX, x + w); maxY = Math.max(maxY, y + h);\n };\n for (const n of cData.nodes) {\n if (sel.nodeIds.has(n.id)) bump(n.position.x, n.position.y, n.width, n.height);\n }\n for (const e of cData.edges) {\n if (!sel.edgeIds.has(e.id)) continue;\n const s = nodeMap.get(e.source);\n const t = nodeMap.get(e.target);\n if (s) bump(s.position.x, s.position.y, s.width, s.height);\n if (t) bump(t.position.x, t.position.y, t.width, t.height);\n }\n for (const l of cData.lines) {\n if (!sel.lineIds.has(l.id)) continue;\n for (const p of l.points) bump(p.x, p.y, 0, 0);\n }\n if (minX === Infinity) {\n boundsEmpty = true;\n } else {\n const z = vp.zoom;\n const BTN_W = 66, BTN_H = 30, MARGIN = 6;\n let bx = maxX * z + vp.x + 8;\n let by = minY * z + vp.y - BTN_H - 6;\n if (bx + BTN_W > screen.width - MARGIN) bx = Math.max(MARGIN, screen.width - BTN_W - MARGIN);\n if (by < MARGIN) by = minY * z + vp.y + MARGIN;\n if (by + BTN_H > screen.height - MARGIN) by = Math.max(MARGIN, screen.height - BTN_H - MARGIN);\n delBtn.style.display = 'flex';\n delBtn.style.left = `${Math.round(bx)}px`;\n delBtn.style.top = `${Math.round(by)}px`;\n }\n }\n if (boundsEmpty && delBtn.style.display !== 'none') delBtn.style.display = 'none';\n }\n\n // Draw connection handle hover indicator (world space)\n const hhGfx = handleHoverGfxRef.current;\n if (hhGfx) {\n hhGfx.clear();\n const hh = hoveredHandleRef.current;\n if (hh) {\n hhGfx.circle(hh.wx, hh.wy, 10)\n .fill({ color: 0x3b82f6, alpha: 0.12 })\n .stroke({ color: 0x3b82f6, width: 1.5, alpha: 0.5 });\n hhGfx.circle(hh.wx, hh.wy, 4)\n .fill({ color: 0x3b82f6, alpha: 0.9 });\n }\n // Edge endpoint hover indicators\n const epHover = hoveredEdgeEndpointRef.current;\n if (epHover && !hh) {\n hhGfx.circle(epHover.worldX, epHover.worldY, 10)\n .fill({ color: 0xf97316, alpha: 0.12 })\n .stroke({ color: 0xf97316, width: 1.5, alpha: 0.5 });\n hhGfx.circle(epHover.worldX, epHover.worldY, 4)\n .fill({ color: 0xf97316, alpha: 0.9 });\n }\n }\n\n // Ghost placement preview — draw actual shape silhouette, with\n // alignment-guide snapping against existing nodes (same as dragging).\n const gGfx = ghostGfxRef.current;\n if (gGfx) {\n gGfx.clear();\n const pp = pendingPlacementRef.current;\n if (pp) {\n const mw = mouseWorldRef.current;\n // Same placement-magnet math as the stamping site so the ghost\n // preview lands exactly where the shape will be placed.\n const gs = gridSizeRef.current;\n const snapOn = placementSnapRef.current;\n const rawX = snapPlacement(mw.x - pp.width / 2, gs, snapOn);\n const rawY = snapPlacement(mw.y - pp.height / 2, gs, snapOn);\n const virtual: FlowNode = {\n id: '__ghost__', type: pp.type,\n position: { x: rawX, y: rawY },\n width: pp.width, height: pp.height, data: {} as any,\n };\n const snap = computeAlignmentSnap([virtual], cData.nodes);\n activeGuidesRef.current = snap.guides;\n gGfx.position.set(rawX + snap.dx, rawY + snap.dy);\n const drawFn = shapeDrawers[pp.type] ?? shapeDrawers.shapeRect;\n drawFn(gGfx, {\n width: pp.width, height: pp.height,\n fill: '#3b82f6', stroke: '#3b82f6',\n strokeWidth: 1.5, borderStyle: pp.data.borderStyle,\n });\n } else {\n gGfx.position.set(0, 0);\n // Only clear guides here if nothing else (drag/resize) owns them.\n if (!dragRef.current?.active && !resizeRef.current?.active) {\n activeGuidesRef.current = [];\n }\n }\n }\n\n // Draw edge edit handles (waypoints + bezier controls) in world space\n const eeGfx = edgeEditGfxRef.current;\n if (eeGfx) {\n eeGfx.clear();\n if (sel.edgeIds.size > 0 && toolModeRef.current === 'select') {\n const iz = 1 / vp.zoom;\n for (const edge of cData.edges) {\n if (!sel.edgeIds.has(edge.id)) continue;\n // Endpoint drag targets: always drawn on a selected edge so touch\n // users (no hover) can discover they can be dragged to reconnect.\n const dragEp = resolveEdgeEndpoints(edge, nodeMap);\n if (dragEp) {\n eeGfx.circle(dragEp.sx, dragEp.sy, 5 * iz)\n .fill({ color: 0xffffff })\n .stroke({ color: 0xf97316, width: 1.5 * iz });\n eeGfx.circle(dragEp.tx, dragEp.ty, 5 * iz)\n .fill({ color: 0xffffff })\n .stroke({ color: 0xf97316, width: 1.5 * iz });\n }\n const wps = edge.data.waypoints;\n if (wps) {\n for (const wp of wps) {\n eeGfx.circle(wp.x, wp.y, 5 * iz)\n .fill({ color: 0xffffff })\n .stroke({ color: 0x3b82f6, width: 1.5 * iz });\n }\n }\n if (edge.type === 'simplebezier') {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) continue;\n const allWps = wps ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...allWps, { x: ep.tx, y: ep.ty }];\n const controls = edge.data.bezierControls;\n const lastSegIdx = allPts.length - 2;\n for (let i = 0; i <= lastSegIdx; i++) {\n const a = allPts[i], b = allPts[i + 1];\n const ctrl = controls?.[i];\n const segDist = Math.hypot(b.x - a.x, b.y - a.y);\n const arm = Math.max(30, segDist * 0.3);\n const c1x = ctrl?.c1x ?? (i === 0 ? a.x + ep.snx * arm : a.x + (b.x - a.x) * 0.4);\n const c1y = ctrl?.c1y ?? (i === 0 ? a.y + ep.sny * arm : a.y);\n const c2x = ctrl?.c2x ?? (i === lastSegIdx ? b.x + ep.tnx * arm : b.x - (b.x - a.x) * 0.4);\n const c2y = ctrl?.c2y ?? (i === lastSegIdx ? b.y + ep.tny * arm : b.y);\n eeGfx.moveTo(a.x, a.y).lineTo(c1x, c1y).stroke({ color: 0x9ca3af, width: 1 * iz });\n eeGfx.moveTo(b.x, b.y).lineTo(c2x, c2y).stroke({ color: 0x9ca3af, width: 1 * iz });\n const cr = 4 * iz;\n eeGfx.circle(c1x, c1y, cr).fill({ color: 0xffffff }).stroke({ color: 0x3b82f6, width: 1.5 * iz });\n eeGfx.circle(c2x, c2y, cr).fill({ color: 0xffffff }).stroke({ color: 0x3b82f6, width: 1.5 * iz });\n }\n }\n }\n }\n }\n\n // Draw transform handles in screen space\n const tg = transformGfxRef.current;\n if (tg) {\n tg.clear();\n if (sel.nodeIds.size === 1 && toolModeRef.current === 'select') {\n const nodeId = [...sel.nodeIds][0];\n const node = cData.nodes.find(n => n.id === nodeId);\n if (node) {\n const z = vp.zoom;\n const sx = node.position.x * z + vp.x;\n const sy = node.position.y * z + vp.y;\n const sw = node.width * z;\n const sh = node.height * z;\n\n tg.rect(sx, sy, sw, sh).stroke({ color: 0x3b82f6, width: 1.5 });\n\n // Corner resize handles (squares)\n const hs = 7, h2 = hs / 2;\n const corners: Array<[number, number]> = [\n [sx, sy], [sx + sw, sy],\n [sx + sw, sy + sh], [sx, sy + sh],\n ];\n for (const [cx, cy] of corners) {\n tg.rect(cx - h2, cy - h2, hs, hs)\n .fill({ color: 0xffffff })\n .stroke({ color: 0x3b82f6, width: 1.5 });\n }\n\n // Midpoint connection handles (circles)\n const cr = 4;\n const midpoints: Array<[number, number]> = [\n [sx + sw / 2, sy], [sx + sw, sy + sh / 2],\n [sx + sw / 2, sy + sh], [sx, sy + sh / 2],\n ];\n for (const [cx, cy] of midpoints) {\n tg.circle(cx, cy, cr)\n .fill({ color: 0x3b82f6, alpha: 0.9 });\n }\n\n // Rotation knob: stem above the top-center ending in a knob;\n // drag it around the node center to rotate (Shift = 15° steps).\n if (!readOnlyRef.current) {\n const kx = sx + sw / 2;\n const kyKnob = sy - ROTATE_STEM;\n tg.moveTo(kx, sy).lineTo(kx, kyKnob)\n .stroke({ color: 0x3b82f6, width: 1.5, alpha: 0.85 });\n tg.circle(kx, kyKnob, 6)\n .fill({ color: 0xffffff })\n .stroke({ color: 0x3b82f6, width: 1.5 });\n tg.circle(kx, kyKnob, 2.5)\n .fill({ color: 0x3b82f6 });\n }\n }\n }\n }\n });\n };\n\n waitForReady();\n\n return () => {\n cancelled = true;\n // Remove stage event listeners to prevent duplicates on re-mount\n if (pixi && !pixi.destroyed) {\n try { pixi.app.stage.removeAllListeners(); } catch { /* already destroyed */ }\n }\n // Remove native touch gesture listeners\n const touchEl = containerRef.current;\n if (touchStartHandler) touchEl?.removeEventListener('touchstart', touchStartHandler);\n if (touchMoveHandler) touchEl?.removeEventListener('touchmove', touchMoveHandler);\n if (touchEndHandler) {\n touchEl?.removeEventListener('touchend', touchEndHandler);\n touchEl?.removeEventListener('touchcancel', touchEndHandler);\n }\n gridRef.current?.destroy();\n selectionRef.current?.destroy();\n nodeRendererRef.current?.destroy();\n edgeRendererRef.current?.destroy();\n lineRendererRef.current?.destroy();\n freehandRef.current?.destroy();\n geoLineRef.current?.destroy();\n connectLineRef.current?.destroy();\n if (transformGfxRef.current) { transformGfxRef.current.destroy(); transformGfxRef.current = null; }\n if (handleHoverGfxRef.current) { handleHoverGfxRef.current.destroy(); handleHoverGfxRef.current = null; }\n if (edgeEditGfxRef.current) { edgeEditGfxRef.current.destroy(); edgeEditGfxRef.current = null; }\n if (ghostGfxRef.current) { ghostGfxRef.current.destroy(); ghostGfxRef.current = null; }\n alignGuidesRef.current?.destroy();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pixiRef.current]);\n\n // Activate/deactivate line tools based on toolMode\n useEffect(() => {\n const freehand = freehandRef.current;\n const geo = geoLineRef.current;\n if (!freehand || !geo) return;\n\n freehand.deactivate();\n geo.deactivate();\n\n switch (toolMode) {\n case 'freehand': freehand.activate(); break;\n case 'line': geo.activate('straight'); break;\n case 'polyline': geo.activate('polyline'); break;\n case 'arrow': geo.activate('arrow'); break;\n }\n }, [toolMode]);\n\n useEffect(() => {\n if (gridRef.current) {\n gridRef.current.visible = showGrid;\n gridRef.current.gridSize = gridSize;\n }\n }, [showGrid, gridSize]);\n\n // Native, non-passive wheel listener: zoom the canvas and preventDefault() so\n // the browser's Ctrl/Cmd+wheel page zoom (and trackpad pinch) never fires.\n // Pixi's federated wheel event cannot reliably block that native gesture.\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const ZOOM_SENSITIVITY = 0.001;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const vm = vmRef.current;\n if (!vm) return;\n const rect = el.getBoundingClientRect();\n const sx = e.clientX - rect.left;\n const sy = e.clientY - rect.top;\n // ctrlKey is set for pinch-zoom gestures; scale it up for parity.\n const scale = e.ctrlKey ? 3 : 1;\n const delta = -e.deltaY * ZOOM_SENSITIVITY * scale;\n vm.zoomAt(sx, sy, 1 + delta);\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [vmRef]);\n\n return (\n <div style={{ position: 'relative', width: '100%', height: '100%' }}>\n <div\n ref={containerRef}\n className=\"flow-canvas-wrapper\"\n tabIndex={-1}\n onContextMenu={(e) => e.preventDefault()}\n />\n {editing && editorPos && (\n <input\n className=\"flow-label-editor\"\n autoFocus\n defaultValue={editing.value}\n style={{ left: editorPos.x, top: editorPos.y }}\n // Entering edit mode (double-click / Space) selects the whole label,\n // so typing immediately replaces it instead of appending.\n onFocus={(e) => e.currentTarget.select()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n commitEdit((e.target as HTMLInputElement).value);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancelEdit();\n }\n e.stopPropagation();\n }}\n onBlur={(e) => commitEdit(e.target.value)}\n onPointerDown={(e) => e.stopPropagation()}\n />\n )}\n {/* Virtual ESC: cancels continuous stamp placement — the touch-friendly\n counterpart of the physical Esc key (kept on desktop too). */}\n {pendingPlacement && !presentation && (\n <button\n type=\"button\"\n className=\"flow-esc-button\"\n onClick={() => setPendingPlacement(null)}\n title=\"取消连续放置 (Esc)\"\n >\n <span aria-hidden>⎋</span> 取消放置 (ESC)\n </button>\n )}\n {/* Selection delete: the touch-friendly counterpart of the Delete/\n Backspace key. Always mounted; the render loop toggles visibility and\n pins it to the selection's top-right corner every frame. */}\n <button\n ref={deleteButtonRef}\n type=\"button\"\n className=\"flow-delete-button\"\n style={{ display: 'none' }}\n onClick={() => deleteSelectedRef.current()}\n title=\"删除所选 (Delete)\"\n aria-label=\"删除所选\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 6h18\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n 删除\n </button>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FlowCanvas.js","names":[],"sources":["../../../../src/components/pro/Flow/FlowCanvas.tsx"],"sourcesContent":["import React, { useRef, useEffect, useCallback, useState } from 'react';\nimport { FederatedPointerEvent, Graphics } from 'pixi.js';\nimport { usePixiApp } from './hooks/usePixiApp';\nimport { useViewport } from './hooks/useViewport';\nimport { useFlowContext } from './context/FlowContext';\nimport { useFlowUI, type FocusOnRectOptions } from './context/FlowUIContext';\nimport { GridRenderer } from './canvas/GridRenderer';\nimport { SelectionOverlay } from './canvas/SelectionOverlay';\nimport { NodeRenderer } from './nodes/NodeRenderer';\nimport { EdgeRenderer } from './edges/EdgeRenderer';\nimport { LineRenderer } from './lines/LineRenderer';\nimport { FreehandTool } from './lines/FreehandTool';\nimport { GeometricLineTool } from './lines/GeometricLineTool';\nimport { isPointInNode, rectsOverlap, distToSegment, generateId } from './nodes/nodeUtils';\nimport { shapeDrawers } from './nodes/shapes';\nimport { findClosestHandle, findClosestHandleWorld, handleWorldPos, getHandlePositions } from './nodes/NodeHandles';\nimport { buildEdgePath, resolveEdgeEndpoints, linearizeSegments } from './edges/edgePaths';\nimport { computeAlignmentSnap, type AlignGuide } from './hooks/useAlignmentGuides';\nimport { AlignmentGuidesRenderer } from './canvas/AlignmentGuides';\nimport { getDocumentSlides, nextAnimIndex } from './nodes/animAnchors';\nimport { useDeleteSelection } from './hooks/useDeleteSelection';\nimport type { PixiApp } from './canvas/PixiApp';\nimport type { ViewportState, FlowNode, FlowEdge, FlowLine, FlowBezierControl } from './types';\n\nexport interface FlowCanvasProps {\n onPixiReady?: (pixi: PixiApp) => void;\n}\n\ntype ResizeHandle = 'nw' | 'ne' | 'se' | 'sw';\n\nconst RESIZE_CURSORS: Record<ResizeHandle, string> = {\n nw: 'nwse-resize', ne: 'nesw-resize',\n se: 'nwse-resize', sw: 'nesw-resize',\n};\n\n// Touch pointers have no hover and a ~40px contact patch, so hit radii tuned\n// for a mouse cursor (8-14px) are nearly impossible to land with a finger —\n// especially for connection handles, edge endpoints and waypoints, which sit on\n// exact coordinates. Coarse pointers (touch) get doubled screen-space radii.\nconst COARSE_POINTER = typeof window !== 'undefined'\n && typeof window.matchMedia === 'function'\n && window.matchMedia('(pointer: coarse)').matches;\nconst TOUCH_HIT_SCALE = COARSE_POINTER ? 2 : 1;\n\n/**\n * Press/tap hit radius in world units: `px` screen pixels converted by zoom,\n * capped in world space so a zoomed-out canvas doesn't get an absurd radius.\n */\nfunction hitRadius(zoom: number, px: number, worldCap: number): number {\n return Math.min((px * TOUCH_HIT_SCALE) / zoom, worldCap * TOUCH_HIT_SCALE);\n}\n\n// Rotation knob: stem rises above the node's top-center, ending in a knob that\n// can be dragged around the node center to rotate. Length/radius are SCREEN\n// pixels (like the other transform handles); hit tests convert via zoom.\nconst ROTATE_STEM = 26;\n\n/** Knob center in world coords for a node at the given zoom. */\nfunction rotationKnobPos(node: FlowNode, zoom: number): { x: number; y: number } {\n return { x: node.position.x + node.width / 2, y: node.position.y - ROTATE_STEM / zoom };\n}\n\n/** Placement magnet: snap a coordinate to the canvas grid (stamp placement). */\nfunction snapPlacement(value: number, gridSize: number, enabled: boolean): number {\n if (!enabled || !(gridSize > 0)) return value;\n return Math.round(value / gridSize) * gridSize;\n}\n\nfunction getResizeHandleAt(\n pt: { x: number; y: number }, node: FlowNode, threshold: number,\n): ResizeHandle | null {\n const { x, y } = node.position;\n const w = node.width, h = node.height;\n const defs: Array<[ResizeHandle, number, number]> = [\n ['nw', x, y], ['ne', x + w, y],\n ['se', x + w, y + h], ['sw', x, y + h],\n ];\n let best: ResizeHandle | null = null, bestD = threshold;\n for (const [pos, hx, hy] of defs) {\n const d = Math.hypot(pt.x - hx, pt.y - hy);\n if (d < bestD) { bestD = d; best = pos; }\n }\n return best;\n}\n\ninterface EdgeEndpointHit {\n edgeId: string;\n end: 'source' | 'target';\n worldX: number;\n worldY: number;\n}\n\nfunction findEdgeEndpointNear(\n wx: number, wy: number,\n edges: FlowEdge[],\n nodeMap: Map<string, FlowNode>,\n threshold: number,\n): EdgeEndpointHit | null {\n let best: EdgeEndpointHit | null = null;\n let bestD = threshold;\n for (const edge of edges) {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) continue;\n const dSrc = Math.hypot(wx - ep.sx, wy - ep.sy);\n if (dSrc < bestD) { bestD = dSrc; best = { edgeId: edge.id, end: 'source', worldX: ep.sx, worldY: ep.sy }; }\n const dTgt = Math.hypot(wx - ep.tx, wy - ep.ty);\n if (dTgt < bestD) { bestD = dTgt; best = { edgeId: edge.id, end: 'target', worldX: ep.tx, worldY: ep.ty }; }\n }\n return best;\n}\n\ninterface WaypointHit {\n edgeId: string;\n waypointIndex: number;\n wx: number;\n wy: number;\n}\n\ninterface BezierControlHit {\n edgeId: string;\n segmentIndex: number;\n controlEnd: 'c1' | 'c2';\n wx: number;\n wy: number;\n}\n\nfunction findWaypointNear(\n wx: number, wy: number,\n edges: FlowEdge[],\n threshold: number,\n): WaypointHit | null {\n let best: WaypointHit | null = null;\n let bestD = threshold;\n for (const edge of edges) {\n const wps = edge.data.waypoints;\n if (!wps) continue;\n for (let i = 0; i < wps.length; i++) {\n const d = Math.hypot(wx - wps[i].x, wy - wps[i].y);\n if (d < bestD) {\n bestD = d;\n best = { edgeId: edge.id, waypointIndex: i, wx: wps[i].x, wy: wps[i].y };\n }\n }\n }\n return best;\n}\n\nfunction findBezierControlNear(\n wx: number, wy: number,\n edges: FlowEdge[],\n nodeMap: Map<string, FlowNode>,\n threshold: number,\n): BezierControlHit | null {\n let best: BezierControlHit | null = null;\n let bestD = threshold;\n for (const edge of edges) {\n if (edge.type !== 'simplebezier') continue;\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) continue;\n const wps = edge.data.waypoints ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...wps, { x: ep.tx, y: ep.ty }];\n const ctrls = edge.data.bezierControls;\n const lastIdx = allPts.length - 2;\n for (let i = 0; i <= lastIdx; i++) {\n const a = allPts[i], b = allPts[i + 1];\n const ctrl = ctrls?.[i];\n const segDist = Math.hypot(b.x - a.x, b.y - a.y);\n const arm = Math.max(30, segDist * 0.3);\n const c1x = ctrl?.c1x ?? (i === 0 ? a.x + ep.snx * arm : a.x + (b.x - a.x) * 0.4);\n const c1y = ctrl?.c1y ?? (i === 0 ? a.y + ep.sny * arm : a.y);\n const c2x = ctrl?.c2x ?? (i === lastIdx ? b.x + ep.tnx * arm : b.x - (b.x - a.x) * 0.4);\n const c2y = ctrl?.c2y ?? (i === lastIdx ? b.y + ep.tny * arm : b.y);\n const d1 = Math.hypot(wx - c1x, wy - c1y);\n if (d1 < bestD) { bestD = d1; best = { edgeId: edge.id, segmentIndex: i, controlEnd: 'c1', wx: c1x, wy: c1y }; }\n const d2 = Math.hypot(wx - c2x, wy - c2y);\n if (d2 < bestD) { bestD = d2; best = { edgeId: edge.id, segmentIndex: i, controlEnd: 'c2', wx: c2x, wy: c2y }; }\n }\n }\n return best;\n}\n\nfunction findInsertionIndex(\n wx: number, wy: number,\n edge: FlowEdge,\n nodeMap: Map<string, FlowNode>,\n): number {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) return 0;\n const wps = edge.data.waypoints ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...wps, { x: ep.tx, y: ep.ty }];\n let bestD = Infinity, bestI = 0;\n for (let i = 0; i < allPts.length - 1; i++) {\n const d = distToSegment(wx, wy, allPts[i].x, allPts[i].y, allPts[i + 1].x, allPts[i + 1].y);\n if (d < bestD) { bestD = d; bestI = i; }\n }\n return bestI;\n}\n\nfunction applyResize(\n start: { x: number; y: number; w: number; h: number },\n handle: ResizeHandle, dx: number, dy: number, minSize = 24,\n): { x: number; y: number; w: number; h: number } {\n let { x, y, w, h } = { ...start };\n const ml = handle === 'nw' || handle === 'sw';\n const mr = handle === 'ne' || handle === 'se';\n const mt = handle === 'nw' || handle === 'ne';\n const mb = handle === 'sw' || handle === 'se';\n if (ml) { x += dx; w -= dx; }\n if (mr) { w += dx; }\n if (mt) { y += dy; h -= dy; }\n if (mb) { h += dy; }\n if (w < minSize) { if (ml) x = start.x + start.w - minSize; w = minSize; }\n if (h < minSize) { if (mt) y = start.y + start.h - minSize; h = minSize; }\n return { x, y, w, h };\n}\n\nfunction isPointNearEdgePath(\n wx: number, wy: number, edge: FlowEdge,\n nodeMap: Map<string, FlowNode>, threshold: number,\n): boolean {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) return false;\n const segs = buildEdgePath(edge.type, ep, edge.data.waypoints, edge.data.bezierControls);\n const pts = linearizeSegments(segs);\n for (let i = 0; i < pts.length - 1; i++) {\n if (distToSegment(wx, wy, pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y) < threshold) return true;\n }\n return false;\n}\n\nfunction isPointNearLine(\n wx: number, wy: number, line: FlowLine, threshold: number,\n): boolean {\n const pts = line.points;\n for (let i = 0; i < pts.length - 1; i++) {\n if (distToSegment(wx, wy, pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y) < threshold) return true;\n }\n return false;\n}\n\nexport default function FlowCanvas({ onPixiReady }: FlowCanvasProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const gridRef = useRef<GridRenderer | null>(null);\n // Latest theme-derived grid dot color; applied to the grid renderer whenever\n // it (re)initializes or the DishUI theme changes. Node/edge colors follow the\n // theme via `theme:*` tokens resolved in the render loop.\n const gridDotColorRef = useRef<number>(0xd1d5db);\n const handleThemeColors = useCallback((colors: { background: number; gridDot: number; nodeFill: string; nodeText: string }) => {\n gridDotColorRef.current = colors.gridDot;\n if (gridRef.current) gridRef.current.dotColor = colors.gridDot;\n }, []);\n const { pixiRef, readyRef } = usePixiApp(containerRef, handleThemeColors);\n const { setViewportInternal, viewportReqRef, viewport: uiViewport, autoFocus, showGrid, showAnchors, gridSize, toolMode, edgeType, focusOnRect, setFocusOnRect, pendingPlacement, setPendingPlacement, setContextMenu, beginNodeDrag, endNodeDrag, presentation, editingNodeId, setEditingNodeId, readOnly, placementSnap } = useFlowUI();\n const { currentCanvas, selection, setSelection, setDoc, currentCanvasId, pushCanvas, doc: flowDoc } = useFlowContext();\n const deleteSelected = useDeleteSelection();\n const deleteSelectedRef = useRef(deleteSelected);\n deleteSelectedRef.current = deleteSelected;\n const deleteButtonRef = useRef<HTMLButtonElement>(null);\n const readOnlyRef = useRef(readOnly);\n readOnlyRef.current = readOnly;\n // Latest placement-magnet toggle / grid size, readable from the mount-scoped\n // pointer handlers and render loop.\n const placementSnapRef = useRef(placementSnap);\n placementSnapRef.current = placementSnap;\n const gridSizeRef = useRef(gridSize);\n gridSizeRef.current = gridSize;\n const selectionRef = useRef<SelectionOverlay | null>(null);\n const nodeRendererRef = useRef<NodeRenderer | null>(null);\n const edgeRendererRef = useRef<EdgeRenderer | null>(null);\n const lineRendererRef = useRef<LineRenderer | null>(null);\n const freehandRef = useRef<FreehandTool | null>(null);\n const geoLineRef = useRef<GeometricLineTool | null>(null);\n const hoveredNodeRef = useRef<string | null>(null);\n const transformGfxRef = useRef<Graphics | null>(null);\n const handleHoverGfxRef = useRef<Graphics | null>(null);\n const alignGuidesRef = useRef<AlignmentGuidesRenderer | null>(null);\n const activeGuidesRef = useRef<AlignGuide[]>([]);\n const hoveredHandleRef = useRef<{ nodeId: string; handleId: string; wx: number; wy: number } | null>(null);\n const hoveredEdgeEndpointRef = useRef<EdgeEndpointHit | null>(null);\n const waypointDragRef = useRef<{\n active: boolean;\n edgeId: string;\n type: 'waypoint' | 'bezierC1' | 'bezierC2';\n index: number;\n } | null>(null);\n const edgeEditGfxRef = useRef<Graphics | null>(null);\n const lastClickRef = useRef<{ time: number; wx: number; wy: number }>({ time: 0, wx: 0, wy: 0 });\n const dblClickRef = useRef<{ time: number; wx: number; wy: number }>({ time: 0, wx: 0, wy: 0 });\n // Timestamp until which pointertap events are ignored — set after a multi-touch\n // gesture ends so lifting the last finger cannot register as an accidental tap\n // (e.g. placing a stamp or opening the label editor).\n const suppressTapUntilRef = useRef(0);\n const ghostGfxRef = useRef<Graphics | null>(null);\n const mouseWorldRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n\n const interactiveCanvas = showAnchors || presentation\n ? currentCanvas\n : { ...currentCanvas, nodes: currentCanvas.nodes.filter(node => node.type !== 'animAnchor') };\n const canvasDataRef = useRef(interactiveCanvas);\n canvasDataRef.current = interactiveCanvas;\n const currentCanvasIdRef = useRef(currentCanvasId);\n currentCanvasIdRef.current = currentCanvasId;\n const selectionDataRef = useRef(selection);\n selectionDataRef.current = selection;\n const docRef = useRef(flowDoc);\n docRef.current = flowDoc;\n const toolModeRef = useRef(toolMode);\n toolModeRef.current = toolMode;\n const autoFocusRef = useRef(autoFocus);\n autoFocusRef.current = autoFocus;\n const focusOnRectRef = useRef(focusOnRect);\n focusOnRectRef.current = focusOnRect;\n const edgeTypeRef = useRef(edgeType);\n edgeTypeRef.current = edgeType;\n const showAnchorsRef = useRef(showAnchors);\n showAnchorsRef.current = showAnchors;\n const presentationRef = useRef(presentation);\n presentationRef.current = presentation;\n const pendingPlacementRef = useRef(pendingPlacement);\n pendingPlacementRef.current = pendingPlacement;\n const beginNodeDragRef = useRef(beginNodeDrag);\n beginNodeDragRef.current = beginNodeDrag;\n const endNodeDragRef = useRef(endNodeDrag);\n endNodeDragRef.current = endNodeDrag;\n\n const dragRef = useRef<{\n active: boolean;\n nodeIds: Set<string>;\n lineIds?: Set<string>;\n startWorld: { x: number; y: number };\n nodeStarts: Map<string, { x: number; y: number }>;\n linePointStarts?: Map<string, Array<{ x: number; y: number }>>;\n } | null>(null);\n\n const marqueeRef = useRef<{\n active: boolean;\n startScreen: { x: number; y: number };\n } | null>(null);\n\n const connectRef = useRef<{\n active: boolean;\n sourceNodeId: string;\n sourceHandleId: string;\n } | null>(null);\n\n // Active rotation-knob gesture: the knob above the selection's top-center is\n // dragged around the node center to adjust `data.rotation`.\n const rotateRef = useRef<{\n active: boolean;\n nodeId: string;\n cx: number;\n cy: number;\n startPointerAngle: number;\n startRotation: number;\n } | null>(null);\n const reconnectRef = useRef<{\n active: boolean;\n edgeId: string;\n movingEnd: 'source' | 'target';\n fixedNodeId: string;\n fixedHandleId: string | undefined;\n } | null>(null);\n const connectLineRef = useRef<Graphics | null>(null);\n\n const resizeRef = useRef<{\n active: boolean;\n nodeId: string;\n handle: ResizeHandle;\n startWorld: { x: number; y: number };\n startBounds: { x: number; y: number; w: number; h: number };\n childStarts: Map<string, { x: number; y: number; w: number; h: number }>;\n childLineStarts?: Map<string, Array<{ x: number; y: number }>>;\n } | null>(null);\n\n const lineDragRef = useRef<{\n active: boolean;\n lineIds: Set<string>;\n startWorld: { x: number; y: number };\n pointStarts: Map<string, Array<{ x: number; y: number }>>;\n } | null>(null);\n\n const vmViewportRef = useRef(uiViewport);\n const vpRafRef = useRef(0);\n const handleViewportChange = useCallback((v: ViewportState) => {\n vmViewportRef.current = v;\n if (!vpRafRef.current) {\n vpRafRef.current = requestAnimationFrame(() => {\n vpRafRef.current = 0;\n // VM → React: display-only update. Does NOT request a VM apply, so it\n // can never echo back and cause a feedback loop / jitter.\n setViewportInternal(vmViewportRef.current);\n });\n }\n }, [setViewportInternal]);\n\n const { vmRef, screenToWorld } = useViewport(pixiRef, handleViewportChange);\n const screenToWorldRef = useRef(screenToWorld);\n screenToWorldRef.current = screenToWorld;\n // `editing` holds the target; `editorPos` is the on-screen position (CSS px\n // relative to the canvas container) recomputed each frame so the input\n // tracks pan/zoom.\n const [editing, setEditing] = useState<{ kind: 'node' | 'edge' | 'line'; id: string; value: string } | null>(null);\n const [editorPos, setEditorPos] = useState<{ x: number; y: number } | null>(null);\n const editingRef = useRef(editing);\n editingRef.current = editing;\n\n // Stable trigger used from inside the pixi event handlers.\n const beginEditRef = useRef<(kind: 'node' | 'edge' | 'line', id: string, value: string) => void>(() => {});\n beginEditRef.current = (kind, id, value) => {\n setEditingNodeId(kind === 'node' ? id : null);\n setEditing({ kind, id, value });\n };\n\n const commitEdit = useCallback((value: string) => {\n const target = editingRef.current;\n if (!target) return;\n setDoc(prev => {\n const cid = currentCanvasIdRef.current;\n const canvas = prev.canvases[cid];\n if (!canvas) return prev;\n let next = canvas;\n if (target.kind === 'node') {\n next = { ...canvas, nodes: canvas.nodes.map(n => n.id === target.id ? { ...n, data: { ...n.data, label: value } } : n) };\n } else if (target.kind === 'edge') {\n next = { ...canvas, edges: canvas.edges.map(e => e.id === target.id ? { ...e, data: { ...e.data, labelText: value } } : e) };\n } else {\n // Lines have no label field today; ignore.\n return prev;\n }\n return { ...prev, canvases: { ...prev.canvases, [cid]: next } };\n });\n setEditing(null);\n setEditingNodeId(null);\n setEditorPos(null);\n }, [setDoc, setEditingNodeId]);\n\n const cancelEdit = useCallback(() => {\n setEditing(null);\n setEditingNodeId(null);\n setEditorPos(null);\n }, [setEditingNodeId]);\n\n useEffect(() => {\n if (!editingNodeId || editingRef.current?.id === editingNodeId) return;\n const node = canvasDataRef.current.nodes.find(item => item.id === editingNodeId);\n if (node) beginEditRef.current('node', node.id, node.data.label);\n }, [editingNodeId]);\n\n // Compute the on-screen editor position from the target's world-space center.\n useEffect(() => {\n if (!editing) return;\n const vm = vmRef.current;\n if (!vm) return;\n const canvas = canvasDataRef.current;\n let world: { x: number; y: number } | null = null;\n if (editing.kind === 'node') {\n const n = canvas.nodes.find(nn => nn.id === editing.id);\n if (n) world = { x: n.position.x + n.width / 2, y: n.position.y + n.height / 2 };\n } else if (editing.kind === 'edge') {\n const e = canvas.edges.find(ee => ee.id === editing.id);\n const nodeMap = new Map<string, FlowNode>();\n for (const nn of canvas.nodes) nodeMap.set(nn.id, nn);\n if (e) {\n const ep = resolveEdgeEndpoints(e, nodeMap);\n if (ep) {\n const segs = buildEdgePath(e.type, ep, e.data.waypoints, e.data.bezierControls);\n const pts = linearizeSegments(segs);\n const mid = pts[Math.floor(pts.length / 2)] ?? { x: (ep.sx + ep.tx) / 2, y: (ep.sy + ep.ty) / 2 };\n world = { x: mid.x, y: mid.y };\n }\n }\n }\n if (world) {\n const s = vm.worldToScreen(world.x, world.y);\n setEditorPos({ x: s.x, y: s.y });\n }\n }, [editing, vmRef]);\n\n // Apply EXTERNAL viewport commands (toolbar zoom buttons, minimap, outline\n // panel) → ViewportManager. Only runs when the external request counter\n // changes, so VM→React display updates are never echoed back (no jitter).\n const lastViewportReqRef = useRef(0);\n useEffect(() => {\n if (viewportReqRef.current === lastViewportReqRef.current) return;\n lastViewportReqRef.current = viewportReqRef.current;\n vmViewportRef.current = uiViewport;\n vmRef.current?.setState(uiViewport);\n }, [uiViewport, vmRef, viewportReqRef]);\n\n // Register focusOnRect implementation with ViewportManager\n useEffect(() => {\n setFocusOnRect((wx: number, wy: number, ww: number, wh: number, options?: FocusOnRectOptions) => {\n const vm = vmRef.current;\n const el = containerRef.current;\n if (!vm || !el) return;\n const screenW = el.clientWidth || 800;\n const screenH = el.clientHeight || 600;\n const pad = Math.max(0, options?.padding ?? 60);\n const availableW = Math.max(1, screenW - pad * 2);\n const availableH = Math.max(1, screenH - pad * 2);\n const zoom = options?.preserveZoom\n ? vm.state.zoom\n : Math.min(\n availableW / Math.max(ww, 1),\n availableH / Math.max(wh, 1),\n options?.maxZoom ?? 2,\n );\n const cx = wx + ww / 2;\n const cy = wy + wh / 2;\n const targetX = screenW / 2 - cx * zoom;\n const targetY = screenH / 2 - cy * zoom;\n vm.animateTo({ x: targetX, y: targetY, zoom }, options?.duration ?? 350);\n });\n }, [setFocusOnRect, vmRef]);\n\n const handleLineComplete = useCallback((line: FlowLine) => {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: { ...canvas, lines: [...canvas.lines, line] },\n },\n };\n });\n }, [setDoc, currentCanvasId]);\n const handleLineCompleteRef = useRef(handleLineComplete);\n handleLineCompleteRef.current = handleLineComplete;\n\n // Initialize PixiJS subsystems\n useEffect(() => {\n const pixi = pixiRef.current;\n if (!pixi || pixi.destroyed) return;\n\n let cancelled = false;\n // Native touch gesture handlers (assigned once the stage is wired up; see\n // the NATIVE TOUCH GESTURES section inside waitForReady below).\n let touchStartHandler: ((e: TouchEvent) => void) | null = null;\n let touchMoveHandler: ((e: TouchEvent) => void) | null = null;\n let touchEndHandler: ((e: TouchEvent) => void) | null = null;\n const waitForReady = () => {\n if (cancelled) return;\n if (!readyRef.current) { setTimeout(waitForReady, 30); return; }\n\n gridRef.current = new GridRenderer(pixi.app.stage, gridSize, showGrid);\n gridRef.current.dotColor = gridDotColorRef.current;\n selectionRef.current = new SelectionOverlay(pixi.app.stage);\n nodeRendererRef.current = new NodeRenderer(pixi.world);\n edgeRendererRef.current = new EdgeRenderer(pixi.world);\n lineRendererRef.current = new LineRenderer(pixi.world);\n\n const connectLine = new Graphics();\n connectLine.label = 'connect-line';\n connectLine.visible = false;\n pixi.world.addChild(connectLine);\n connectLineRef.current = connectLine;\n\n const transformGfx = new Graphics();\n transformGfx.label = 'transform-handles';\n pixi.app.stage.addChild(transformGfx);\n transformGfxRef.current = transformGfx;\n\n const handleHoverGfx = new Graphics();\n handleHoverGfx.label = 'handle-hover';\n pixi.world.addChild(handleHoverGfx);\n handleHoverGfxRef.current = handleHoverGfx;\n\n const edgeEditGfx = new Graphics();\n edgeEditGfx.label = 'edge-edit-handles';\n pixi.world.addChild(edgeEditGfx);\n edgeEditGfxRef.current = edgeEditGfx;\n\n const ghostGfx = new Graphics();\n ghostGfx.label = 'ghost-placement';\n ghostGfx.alpha = 0.5;\n pixi.world.addChild(ghostGfx);\n ghostGfxRef.current = ghostGfx;\n\n alignGuidesRef.current = new AlignmentGuidesRenderer(pixi.world);\n\n freehandRef.current = new FreehandTool(pixi.app.stage, pixi.world, {\n onLineComplete: (line) => handleLineCompleteRef.current(line),\n screenToWorld: (sx, sy) => screenToWorldRef.current(sx, sy),\n });\n geoLineRef.current = new GeometricLineTool(pixi.app.stage, pixi.world, {\n onLineComplete: (line) => handleLineCompleteRef.current(line),\n screenToWorld: (sx, sy) => screenToWorldRef.current(sx, sy),\n });\n\n onPixiReady?.(pixi);\n const stage = pixi.app.stage;\n\n // ─── POINTER DOWN ───────────────────────────────────────\n stage.on('pointerdown', (e: FederatedPointerEvent) => {\n // Pixi interactions do not move DOM focus automatically. Explicitly\n // focus the canvas host so Mindmap Tab/Enter shortcuts are not handled\n // as focus navigation by a previously focused inspector control.\n containerRef.current?.focus({ preventScroll: true });\n // Multi-touch (pinch / two-finger pan): pointer interactions are\n // suppressed; the native touch handlers own the gesture.\n if (vmRef.current?.multiTouchActive) return;\n if (vmRef.current?.isPanning || vmRef.current?.isSpaceHeld) return;\n if (e.button !== 0) return;\n const mode = toolModeRef.current;\n if (mode === 'pan') {\n vmRef.current?.startPan(e.global.x, e.global.y);\n return;\n }\n if (mode === 'freehand' || mode === 'line' || mode === 'polyline' || mode === 'arrow') return;\n\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n const edges = canvasDataRef.current.edges;\n const lines = canvasDataRef.current.lines;\n const sel = selectionDataRef.current;\n const additive = e.metaKey || e.ctrlKey || e.shiftKey;\n const zoom = vmRef.current?.state.zoom ?? 1;\n\n // Pending placement has the highest priority: consume the press entirely\n // (no selection, no drag start). The stamp is created on pointertap so\n // that adding a second finger (pinch) can never drop an accidental stamp\n // on the first touch — important on capacitive screens.\n if (pendingPlacementRef.current) return;\n\n const now = Date.now();\n const lc = lastClickRef.current;\n const isDblClick = now - lc.time < 350 && Math.hypot(world.x - lc.wx, world.y - lc.wy) < 8 / zoom;\n lastClickRef.current = { time: now, wx: world.x, wy: world.y };\n\n // 0) Rotation knob (single-node selection, above the top-center)\n if (sel.nodeIds.size === 1 && !additive && mode === 'select' && !readOnlyRef.current) {\n const selNode = nodes.find(n => n.id === [...sel.nodeIds][0]);\n if (selNode) {\n const knob = rotationKnobPos(selNode, zoom);\n if (Math.hypot(world.x - knob.x, world.y - knob.y) < hitRadius(zoom, 12, 24)) {\n rotateRef.current = {\n active: true,\n nodeId: selNode.id,\n cx: selNode.position.x + selNode.width / 2,\n cy: selNode.position.y + selNode.height / 2,\n startPointerAngle: Math.atan2(world.y - (selNode.position.y + selNode.height / 2), world.x - (selNode.position.x + selNode.width / 2)),\n startRotation: selNode.data.rotation ?? 0,\n };\n beginNodeDragRef.current();\n return;\n }\n }\n }\n\n // 1) Resize handles (corners only, single-node selection, select mode)\n if (sel.nodeIds.size === 1 && !additive && mode === 'select') {\n const selNode = nodes.find(n => n.id === [...sel.nodeIds][0]);\n if (selNode) {\n const rh = getResizeHandleAt(world, selNode, hitRadius(zoom, 10, 16));\n if (rh) {\n const childStarts = new Map<string, { x: number; y: number; w: number; h: number }>();\n const childLineStarts = new Map<string, Array<{ x: number; y: number }>>();\n const isGeoGroup = selNode.type === 'geometryGroup';\n const isAnyGroup = isGeoGroup || selNode.type === 'flowGroup' || selNode.data.isGroup;\n const gx = selNode.position.x, gy = selNode.position.y;\n const gw = selNode.width, gh = selNode.height;\n for (const n of nodes) {\n if (n.id === selNode.id) continue;\n if (n.parentId === selNode.id) {\n childStarts.set(n.id, { x: n.position.x, y: n.position.y, w: n.width, h: n.height });\n } else if (isGeoGroup\n && n.position.x >= gx && n.position.y >= gy\n && n.position.x + n.width <= gx + gw\n && n.position.y + n.height <= gy + gh) {\n childStarts.set(n.id, { x: n.position.x, y: n.position.y, w: n.width, h: n.height });\n }\n }\n if (isAnyGroup) {\n for (const l of canvasDataRef.current.lines) {\n if (l.parentId === selNode.id) {\n childLineStarts.set(l.id, l.points.map(p => ({ ...p })));\n } else if (isGeoGroup && l.points.length > 0 && l.points.every(p =>\n p.x >= gx && p.x <= gx + gw && p.y >= gy && p.y <= gy + gh\n )) {\n childLineStarts.set(l.id, l.points.map(p => ({ ...p })));\n }\n }\n }\n resizeRef.current = {\n active: true, nodeId: selNode.id, handle: rh,\n startWorld: world,\n startBounds: { x: selNode.position.x, y: selNode.position.y, w: selNode.width, h: selNode.height },\n childStarts,\n childLineStarts: childLineStarts.size > 0 ? childLineStarts : undefined,\n };\n return;\n }\n }\n }\n\n // Hit test node — if the hit node is inside a group, redirect to the group\n let hitNode: FlowNode | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) { hitNode = nodes[i]; break; }\n }\n if (hitNode?.parentId) {\n const groupNode = nodes.find(n => n.id === hitNode!.parentId);\n if (groupNode) hitNode = groupNode;\n }\n\n // Touch taps produce no intermediate pointermove: refresh hover\n // tracking from the actual press, otherwise a stale hover keeps the\n // previous node's handle ring visible after the selection moves on.\n if (COARSE_POINTER) {\n hoveredNodeRef.current = hitNode\n ? (hitNode.parentId ? (nodes.find(g => g.id === hitNode.parentId)?.id ?? hitNode.id) : hitNode.id)\n : null;\n hoveredHandleRef.current = null;\n hoveredEdgeEndpointRef.current = null;\n }\n\n // 2) Connection handle detection (works in both select and connect modes)\n // A press well inside the node body belongs to the node (select / drag):\n // connection handles only own a ring along the border. Otherwise the\n // enlarged touch radius would swallow taps on small nodes (e.g. SVG\n // icon stamps, whose center sits within the touch radius of a handle).\n let deepInteriorPress = false;\n if (hitNode && mode === 'select') {\n const insideDist = Math.min(\n world.x - hitNode.position.x,\n hitNode.position.x + hitNode.width - world.x,\n world.y - hitNode.position.y,\n hitNode.position.y + hitNode.height - world.y,\n );\n deepInteriorPress = insideDist > Math.min(14, Math.min(hitNode.width, hitNode.height) * 0.3);\n }\n if ((mode === 'select' || mode === 'connect') && (hitNode || COARSE_POINTER) && !deepInteriorPress) {\n // Touch: a finger often lands just outside a small node's bounds, so\n // with no direct node hit, scan every node's handles within the touch\n // radius (closest wins). Mouse keeps hit-node-only detection.\n const candidates = hitNode ? [hitNode] : nodes;\n const threshold = hitRadius(zoom, 14, 20);\n let bestNode: FlowNode | null = null;\n let bestHandle: ReturnType<typeof findClosestHandleWorld> = null;\n let bestDist = Infinity;\n for (const candidate of candidates) {\n const handles = getHandlePositions(candidate.width, candidate.height);\n const closest = findClosestHandleWorld(handles, candidate, world.x, world.y, threshold);\n if (!closest) continue;\n const wp = handleWorldPos(closest, candidate);\n const d = Math.hypot(world.x - wp.x, world.y - wp.y);\n if (d < bestDist) {\n bestDist = d;\n bestNode = candidate;\n bestHandle = closest;\n }\n }\n if (bestNode && bestHandle) {\n connectRef.current = { active: true, sourceNodeId: bestNode.id, sourceHandleId: bestHandle.id };\n return;\n }\n }\n\n // 3) Edge endpoint reconnection — only for SELECTED edges\n if ((mode === 'select' || mode === 'connect') && !additive && sel.edgeIds.size > 0) {\n const nodeMap = new Map<string, FlowNode>();\n for (const n of nodes) nodeMap.set(n.id, n);\n const selectedEdges = edges.filter(ed => sel.edgeIds.has(ed.id));\n const epHit = findEdgeEndpointNear(world.x, world.y, selectedEdges, nodeMap, hitRadius(zoom, 14, 20));\n if (epHit) {\n const edge = edges.find(ed => ed.id === epHit.edgeId);\n if (edge) {\n const fixedEnd = epHit.end === 'source' ? 'target' : 'source';\n reconnectRef.current = {\n active: true,\n edgeId: edge.id,\n movingEnd: epHit.end,\n fixedNodeId: fixedEnd === 'source' ? edge.source : edge.target,\n fixedHandleId: fixedEnd === 'source' ? edge.sourceHandle : edge.targetHandle,\n };\n return;\n }\n }\n }\n\n // 3.5) Waypoint / bezier control editing on selected edges\n if (mode === 'select' && sel.edgeIds.size > 0 && !hitNode) {\n const wmNodeMap = new Map<string, FlowNode>();\n for (const n of nodes) wmNodeMap.set(n.id, n);\n const selEdges = edges.filter(ed => sel.edgeIds.has(ed.id));\n const wpThreshold = hitRadius(zoom, 10, 14);\n\n const bzHit = findBezierControlNear(world.x, world.y, selEdges, wmNodeMap, wpThreshold);\n if (bzHit) {\n waypointDragRef.current = {\n active: true, edgeId: bzHit.edgeId,\n type: bzHit.controlEnd === 'c1' ? 'bezierC1' : 'bezierC2',\n index: bzHit.segmentIndex,\n };\n return;\n }\n\n const wpHit = findWaypointNear(world.x, world.y, selEdges, wpThreshold);\n if (wpHit) {\n if (isDblClick) {\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(e => {\n if (e.id !== wpHit.edgeId) return e;\n const wps = [...(e.data.waypoints ?? [])];\n wps.splice(wpHit.waypointIndex, 1);\n const data = { ...e.data, waypoints: wps.length > 0 ? wps : undefined };\n if (e.type === 'simplebezier' && e.data.bezierControls) {\n const ctrls = [...e.data.bezierControls];\n ctrls.splice(wpHit.waypointIndex, 2, null);\n data.bezierControls = ctrls.some(c => c !== null) ? ctrls : undefined;\n }\n return { ...e, data };\n }),\n }},\n };\n });\n return;\n }\n waypointDragRef.current = { active: true, edgeId: wpHit.edgeId, type: 'waypoint', index: wpHit.waypointIndex };\n return;\n }\n\n if (isDblClick) {\n for (const edge of selEdges) {\n if (isPointNearEdgePath(world.x, world.y, edge, wmNodeMap, hitRadius(zoom, 8, 12))) {\n const insertIdx = findInsertionIndex(world.x, world.y, edge, wmNodeMap);\n const newWp = { x: world.x, y: world.y };\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(e => {\n if (e.id !== edge.id) return e;\n const wps = [...(e.data.waypoints ?? [])];\n wps.splice(insertIdx, 0, newWp);\n const data = { ...e.data, waypoints: wps };\n if (e.type === 'simplebezier' && e.data.bezierControls) {\n const ctrls = [...e.data.bezierControls];\n while (ctrls.length < (e.data.waypoints ?? []).length + 1) ctrls.push(null);\n ctrls.splice(insertIdx, 1, null, null);\n data.bezierControls = ctrls;\n }\n return { ...e, data };\n }),\n }},\n };\n });\n waypointDragRef.current = { active: true, edgeId: edge.id, type: 'waypoint', index: insertIdx };\n return;\n }\n }\n }\n }\n\n // 4) Node body → select + drag\n if (hitNode && (mode === 'select' || mode === 'connect')) {\n if (!additive && !sel.nodeIds.has(hitNode.id)) {\n setSelection({ nodeIds: new Set([hitNode.id]), edgeIds: new Set(), lineIds: new Set() });\n } else if (additive) {\n setSelection(prev => {\n const ids = new Set(prev.nodeIds);\n if (ids.has(hitNode!.id)) ids.delete(hitNode!.id); else ids.add(hitNode!.id);\n return { nodeIds: ids, edgeIds: new Set(), lineIds: new Set() };\n });\n }\n if (autoFocusRef.current) {\n focusOnRectRef.current(\n hitNode.position.x,\n hitNode.position.y,\n hitNode.width,\n hitNode.height,\n { padding: 80, preserveZoom: true, duration: 280 },\n );\n }\n const dragIds = sel.nodeIds.has(hitNode.id)\n ? new Set(sel.nodeIds)\n : new Set([hitNode.id]);\n if (additive && !sel.nodeIds.has(hitNode.id)) dragIds.add(hitNode.id);\n // Include children of group nodes being dragged\n const dragLineIds = new Set<string>();\n for (const gId of [...dragIds]) {\n const gNode = nodes.find(nd => nd.id === gId);\n if (!gNode || (gNode.type !== 'flowGroup' && gNode.type !== 'geometryGroup' && !gNode.data.isGroup)) continue;\n const isGeo = gNode.type === 'geometryGroup';\n const gx = gNode.position.x, gy = gNode.position.y;\n const gw = gNode.width, gh = gNode.height;\n for (const n of nodes) {\n if (dragIds.has(n.id) || n.id === gId) continue;\n if (n.parentId === gId) { dragIds.add(n.id); continue; }\n if (isGeo\n && n.position.x >= gx && n.position.y >= gy\n && n.position.x + n.width <= gx + gw\n && n.position.y + n.height <= gy + gh) {\n dragIds.add(n.id);\n }\n }\n // Include child lines (by parentId)\n for (const l of canvasDataRef.current.lines) {\n if (l.parentId === gId) dragLineIds.add(l.id);\n }\n // Spatial containment for lines in geometryGroup\n if (isGeo) {\n for (const l of canvasDataRef.current.lines) {\n if (dragLineIds.has(l.id)) continue;\n if (l.points.length > 0 && l.points.every(p =>\n p.x >= gx && p.x <= gx + gw && p.y >= gy && p.y <= gy + gh\n )) {\n dragLineIds.add(l.id);\n }\n }\n }\n }\n const nodeStarts = new Map<string, { x: number; y: number }>();\n for (const n of nodes) { if (dragIds.has(n.id)) nodeStarts.set(n.id, { ...n.position }); }\n const linePointStarts = new Map<string, Array<{ x: number; y: number }>>();\n if (dragLineIds.size > 0) {\n for (const l of canvasDataRef.current.lines) {\n if (dragLineIds.has(l.id)) linePointStarts.set(l.id, l.points.map(p => ({ ...p })));\n }\n }\n dragRef.current = { active: true, nodeIds: dragIds, lineIds: dragLineIds.size > 0 ? dragLineIds : undefined, startWorld: world, nodeStarts, linePointStarts: linePointStarts.size > 0 ? linePointStarts : undefined };\n beginNodeDragRef.current();\n return;\n }\n\n // 5) Edge hit test → select edge\n const nodeMap2 = new Map<string, FlowNode>();\n for (const n of nodes) nodeMap2.set(n.id, n);\n const hitThreshold = hitRadius(zoom, 8, 12);\n for (const edge of edges) {\n if (isPointNearEdgePath(world.x, world.y, edge, nodeMap2, hitThreshold)) {\n if (additive) {\n setSelection(prev => {\n const ids = new Set(prev.edgeIds);\n if (ids.has(edge.id)) ids.delete(edge.id); else ids.add(edge.id);\n return { ...prev, edgeIds: ids };\n });\n } else {\n setSelection({ nodeIds: new Set(), edgeIds: new Set([edge.id]), lineIds: new Set() });\n }\n if (autoFocusRef.current) {\n const source = nodeMap2.get(edge.source);\n const target = nodeMap2.get(edge.target);\n if (source && target) {\n const minX = Math.min(source.position.x, target.position.x);\n const minY = Math.min(source.position.y, target.position.y);\n const maxX = Math.max(source.position.x + source.width, target.position.x + target.width);\n const maxY = Math.max(source.position.y + source.height, target.position.y + target.height);\n focusOnRectRef.current(minX, minY, maxX - minX, maxY - minY, {\n padding: 80,\n preserveZoom: true,\n duration: 280,\n });\n }\n }\n return;\n }\n }\n\n // 5) Line hit test → select + drag line\n for (const line of lines) {\n if (isPointNearLine(world.x, world.y, line, hitThreshold)) {\n const alreadySelected = sel.lineIds.has(line.id);\n if (additive) {\n setSelection(prev => {\n const ids = new Set(prev.lineIds);\n if (ids.has(line.id)) ids.delete(line.id); else ids.add(line.id);\n return { ...prev, lineIds: ids };\n });\n } else if (!alreadySelected) {\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set([line.id]) });\n }\n if (autoFocusRef.current && line.points.length > 0) {\n const xs = line.points.map(point => point.x);\n const ys = line.points.map(point => point.y);\n const minX = Math.min(...xs);\n const minY = Math.min(...ys);\n const maxX = Math.max(...xs);\n const maxY = Math.max(...ys);\n focusOnRectRef.current(minX, minY, Math.max(1, maxX - minX), Math.max(1, maxY - minY), {\n padding: 80,\n preserveZoom: true,\n duration: 280,\n });\n }\n // Start line drag\n const dragLineIds = alreadySelected ? new Set(sel.lineIds) : new Set([line.id]);\n const pointStarts = new Map<string, Array<{ x: number; y: number }>>();\n for (const l of lines) {\n if (dragLineIds.has(l.id)) pointStarts.set(l.id, l.points.map(p => ({ ...p })));\n }\n lineDragRef.current = { active: true, lineIds: dragLineIds, startWorld: world, pointStarts };\n return;\n }\n }\n\n // 6) Empty space → clear selection, start marquee\n if (!additive) {\n setSelection({ nodeIds: new Set(), edgeIds: new Set(), lineIds: new Set() });\n }\n if (mode === 'select') {\n marqueeRef.current = { active: true, startScreen: { x: e.global.x, y: e.global.y } };\n }\n });\n\n // ─── POINTER MOVE ──────────────────────────────────────\n stage.on('globalpointermove', (e: FederatedPointerEvent) => {\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n mouseWorldRef.current = world;\n // While a multi-touch gesture is active, hover/drag updates are suppressed\n // (the native pinch/pan handlers own the pointer).\n if (vmRef.current?.multiTouchActive) return;\n\n const mode = toolModeRef.current;\n if (mode === 'freehand' || mode === 'line' || mode === 'polyline' || mode === 'arrow') return;\n\n const nodes = canvasDataRef.current.nodes;\n const edges = canvasDataRef.current.edges;\n const zoom = vmRef.current?.state.zoom ?? 1;\n const isIdle = !dragRef.current?.active && !connectRef.current?.active\n && !resizeRef.current?.active && !reconnectRef.current?.active\n && !waypointDragRef.current?.active && !lineDragRef.current?.active\n && !rotateRef.current?.active;\n\n // Hover tracking — redirect child hovers to parent group\n let hovered: string | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) {\n const n = nodes[i];\n hovered = n.parentId\n ? (nodes.find(g => g.id === n.parentId)?.id ?? n.id)\n : n.id;\n break;\n }\n }\n hoveredNodeRef.current = hovered;\n\n // Hover detection for connection handles and edge endpoints (when idle)\n if (isIdle && (mode === 'select' || mode === 'connect')) {\n const nodeMap = new Map<string, FlowNode>();\n for (const n of nodes) nodeMap.set(n.id, n);\n\n // Check edge endpoint hover — only for selected edges\n const sel = selectionDataRef.current;\n const selectedEdges = sel.edgeIds.size > 0 ? edges.filter(ed => sel.edgeIds.has(ed.id)) : [];\n const epHit = selectedEdges.length > 0\n ? findEdgeEndpointNear(world.x, world.y, selectedEdges, nodeMap, hitRadius(zoom, 12, 18))\n : null;\n hoveredEdgeEndpointRef.current = epHit;\n\n // Check connection handle hover on any node\n let foundHandle: typeof hoveredHandleRef.current = null;\n if (hovered) {\n const node = nodes.find(n => n.id === hovered);\n if (node) {\n const handles = getHandlePositions(node.width, node.height);\n const closest = findClosestHandleWorld(handles, node, world.x, world.y, hitRadius(zoom, 14, 20));\n if (closest) {\n const wp = handleWorldPos(closest, node);\n foundHandle = { nodeId: node.id, handleId: closest.id, wx: wp.x, wy: wp.y };\n }\n }\n }\n hoveredHandleRef.current = foundHandle;\n }\n\n // Cursor updates\n const el = containerRef.current;\n if (el && isIdle) {\n const sel = selectionDataRef.current;\n let cursor = '';\n if (hoveredEdgeEndpointRef.current) {\n cursor = 'crosshair';\n } else if (hoveredHandleRef.current) {\n cursor = 'crosshair';\n } else if (sel.edgeIds.size > 0 && mode === 'select') {\n const selEdgesForCursor = edges.filter(ed => sel.edgeIds.has(ed.id));\n const cursorNm = new Map<string, FlowNode>();\n for (const n of nodes) cursorNm.set(n.id, n);\n const wpThreshold = hitRadius(zoom, 10, 14);\n if (findWaypointNear(world.x, world.y, selEdgesForCursor, wpThreshold)\n || findBezierControlNear(world.x, world.y, selEdgesForCursor, cursorNm, wpThreshold)) {\n cursor = 'grab';\n }\n }\n if (!cursor && sel.nodeIds.size === 1 && mode === 'select') {\n const selNode = nodes.find(n => n.id === [...sel.nodeIds][0]);\n if (selNode) {\n const rh = getResizeHandleAt(world, selNode, hitRadius(zoom, 10, 16));\n if (rh) cursor = RESIZE_CURSORS[rh];\n else if (!readOnlyRef.current) {\n const knob = rotationKnobPos(selNode, zoom);\n if (Math.hypot(world.x - knob.x, world.y - knob.y) < hitRadius(zoom, 12, 24)) cursor = 'grab';\n }\n }\n }\n if (!cursor && mode === 'select') {\n const hoverLines = canvasDataRef.current.lines;\n const lineHitT = hitRadius(zoom, 8, 12);\n for (const ln of hoverLines) {\n if (isPointNearLine(world.x, world.y, ln, lineHitT)) {\n cursor = 'move';\n break;\n }\n }\n }\n el.style.cursor = cursor;\n }\n\n // Resize with alignment snapping\n if (resizeRef.current?.active) {\n const r = resizeRef.current;\n const dx = world.x - r.startWorld.x;\n const dy = world.y - r.startWorld.y;\n const nb = applyResize(r.startBounds, r.handle, dx, dy);\n const allNodes = canvasDataRef.current.nodes;\n const virtualNode: FlowNode = { id: r.nodeId, type: 'shapeRect', position: { x: nb.x, y: nb.y }, width: nb.w, height: nb.h, data: {} as any };\n const snap = computeAlignmentSnap([virtualNode], allNodes);\n nb.x += snap.dx; nb.y += snap.dy;\n if (r.handle === 'ne' || r.handle === 'se') nb.w += snap.dx;\n if (r.handle === 'se' || r.handle === 'sw') nb.h += snap.dy;\n activeGuidesRef.current = snap.guides;\n\n // Placement magnet: snap the moving edges to the canvas grid when no\n // alignment guide is active.\n if (placementSnapRef.current && gridSizeRef.current > 0 && snap.guides.length === 0) {\n const gs = gridSizeRef.current;\n if (r.handle === 'nw' || r.handle === 'sw') nb.x = Math.round(nb.x / gs) * gs;\n if (r.handle === 'nw' || r.handle === 'ne') nb.y = Math.round(nb.y / gs) * gs;\n if (r.handle === 'ne' || r.handle === 'se') nb.w = Math.round((nb.x + nb.w) / gs) * gs - nb.x;\n if (r.handle === 'se' || r.handle === 'sw') nb.h = Math.round((nb.y + nb.h) / gs) * gs - nb.y;\n }\n\n const ob = r.startBounds;\n const finalW = Math.max(nb.w, 24);\n const finalH = Math.max(nb.h, 24);\n const scaleX = ob.w > 0 ? finalW / ob.w : 1;\n const scaleY = ob.h > 0 ? finalH / ob.h : 1;\n\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n if (n.id === r.nodeId) {\n return { ...n, position: { x: nb.x, y: nb.y }, width: finalW, height: finalH };\n }\n const cs = r.childStarts.get(n.id);\n if (cs) {\n return {\n ...n,\n position: {\n x: nb.x + (cs.x - ob.x) * scaleX,\n y: nb.y + (cs.y - ob.y) * scaleY,\n },\n width: Math.max(cs.w * scaleX, 24),\n height: Math.max(cs.h * scaleY, 24),\n };\n }\n return n;\n }),\n lines: r.childLineStarts\n ? canvas.lines.map(l => {\n const pts = r.childLineStarts!.get(l.id);\n if (!pts) return l;\n return {\n ...l,\n points: pts.map(p => ({\n x: nb.x + (p.x - ob.x) * scaleX,\n y: nb.y + (p.y - ob.y) * scaleY,\n })),\n };\n })\n : canvas.lines,\n },\n },\n };\n });\n return;\n }\n\n // Rotation knob drag: angle follows the pointer around the node center.\n // Shift snaps to 15° steps; otherwise right angles get a gentle magnet.\n if (rotateRef.current?.active) {\n const rot = rotateRef.current;\n const angle = Math.atan2(world.y - rot.cy, world.x - rot.cx);\n const delta = (angle - rot.startPointerAngle) * 180 / Math.PI;\n let next = ((rot.startRotation + delta) % 360 + 360) % 360;\n if (e.shiftKey) {\n next = Math.round(next / 15) * 15 % 360;\n } else {\n const snap = Math.round(next / 45) * 45;\n if (Math.abs(next - snap) < 4) next = ((snap % 360) + 360) % 360;\n }\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: canvas.nodes.map(n =>\n n.id === rot.nodeId ? { ...n, data: { ...n.data, rotation: next } } : n,\n ),\n }},\n };\n });\n if (containerRef.current) containerRef.current.style.cursor = 'grabbing';\n return;\n }\n\n // Waypoint / bezier control drag\n if (waypointDragRef.current?.active) {\n const wpd = waypointDragRef.current;\n const wpNodes = canvasDataRef.current.nodes;\n const wpNm = new Map<string, FlowNode>();\n for (const nd of wpNodes) wpNm.set(nd.id, nd);\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(e => {\n if (e.id !== wpd.edgeId) return e;\n if (wpd.type === 'waypoint') {\n const wps = [...(e.data.waypoints ?? [])];\n if (wpd.index < wps.length) wps[wpd.index] = { x: world.x, y: world.y };\n return { ...e, data: { ...e.data, waypoints: wps } };\n }\n const ep = resolveEdgeEndpoints(e, wpNm);\n if (!ep) return e;\n const allWps = e.data.waypoints ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...allWps, { x: ep.tx, y: ep.ty }];\n const segCount = allPts.length - 1;\n const ctrls: Array<FlowBezierControl | null> = [...(e.data.bezierControls ?? [])];\n while (ctrls.length < segCount) ctrls.push(null);\n const si = wpd.index;\n if (si >= segCount) return e;\n const a = allPts[si], b = allPts[si + 1];\n const existing = ctrls[si];\n const segDist = Math.hypot(b.x - a.x, b.y - a.y);\n const arm = Math.max(30, segDist * 0.3);\n const lastSegIdx = segCount - 1;\n const defC1x = si === 0 ? a.x + ep.snx * arm : a.x + (b.x - a.x) * 0.4;\n const defC1y = si === 0 ? a.y + ep.sny * arm : a.y;\n const defC2x = si === lastSegIdx ? b.x + ep.tnx * arm : b.x - (b.x - a.x) * 0.4;\n const defC2y = si === lastSegIdx ? b.y + ep.tny * arm : b.y;\n if (wpd.type === 'bezierC1') {\n ctrls[si] = {\n c1x: world.x, c1y: world.y,\n c2x: existing?.c2x ?? defC2x, c2y: existing?.c2y ?? defC2y,\n };\n } else {\n ctrls[si] = {\n c1x: existing?.c1x ?? defC1x, c1y: existing?.c1y ?? defC1y,\n c2x: world.x, c2y: world.y,\n };\n }\n return { ...e, data: { ...e.data, bezierControls: ctrls } };\n }),\n }},\n };\n });\n return;\n }\n\n // Line drag\n if (lineDragRef.current?.active) {\n const ld = lineDragRef.current;\n const dx = world.x - ld.startWorld.x;\n const dy = world.y - ld.startWorld.y;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n lines: canvas.lines.map(l => {\n const starts = ld.pointStarts.get(l.id);\n if (!starts) return l;\n return { ...l, points: starts.map(p => ({ x: p.x + dx, y: p.y + dy })) };\n }),\n }},\n };\n });\n return;\n }\n\n // Node drag with alignment snapping\n if (dragRef.current?.active) {\n const drag = dragRef.current;\n const rawDx = world.x - drag.startWorld.x;\n const rawDy = world.y - drag.startWorld.y;\n // Placement magnet: pre-snap the raw delta to the canvas grid so the\n // first dragged node's top-left tracks the grid (alignment guides are\n // evaluated on the gridded position and win when they trigger).\n let dx = rawDx;\n let dy = rawDy;\n if (placementSnapRef.current && gridSizeRef.current > 0 && drag.nodeIds.size > 0) {\n const gs = gridSizeRef.current;\n const firstStart = drag.nodeStarts.values().next().value;\n if (firstStart) {\n dx = snapPlacement(firstStart.x + rawDx, gs, true) - firstStart.x;\n dy = snapPlacement(firstStart.y + rawDy, gs, true) - firstStart.y;\n }\n }\n const allNodes = canvasDataRef.current.nodes;\n const dragNodes = allNodes\n .filter(n => drag.nodeIds.has(n.id))\n .map(n => {\n const start = drag.nodeStarts.get(n.id)!;\n return { ...n, position: { x: start.x + dx, y: start.y + dy } };\n });\n const snap = computeAlignmentSnap(dragNodes, allNodes);\n dx += snap.dx;\n dy += snap.dy;\n activeGuidesRef.current = snap.guides;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: canvas.nodes.map(n => {\n const start = drag.nodeStarts.get(n.id);\n if (!start) return n;\n return { ...n, position: { x: start.x + dx, y: start.y + dy } };\n }),\n lines: drag.linePointStarts\n ? canvas.lines.map(l => {\n const starts = drag.linePointStarts!.get(l.id);\n if (!starts) return l;\n return { ...l, points: starts.map(p => ({ x: p.x + dx, y: p.y + dy })) };\n })\n : canvas.lines,\n },\n },\n };\n });\n return;\n }\n\n // Marquee\n if (marqueeRef.current?.active && selectionRef.current) {\n const mx = Math.min(marqueeRef.current.startScreen.x, e.global.x);\n const my = Math.min(marqueeRef.current.startScreen.y, e.global.y);\n const mw = Math.abs(e.global.x - marqueeRef.current.startScreen.x);\n const mh = Math.abs(e.global.y - marqueeRef.current.startScreen.y);\n selectionRef.current.showMarquee(mx, my, mw, mh);\n }\n\n // Connect line preview — snaps to nearest handle on target node\n if (connectRef.current?.active && connectLineRef.current) {\n const srcNode = canvasDataRef.current.nodes.find(n => n.id === connectRef.current!.sourceNodeId);\n if (srcNode) {\n const handles = getHandlePositions(srcNode.width, srcNode.height);\n const handle = handles.find(h => h.id === connectRef.current!.sourceHandleId);\n if (handle) {\n const swp = handleWorldPos(handle, srcNode);\n const sx = swp.x;\n const sy = swp.y;\n let ex = world.x, ey = world.y;\n\n // Snap endpoint to closest handle if hovering over a different node\n const hovNode = hoveredNodeRef.current;\n if (hovNode && hovNode !== connectRef.current!.sourceNodeId) {\n const tNode = canvasDataRef.current.nodes.find(n => n.id === hovNode);\n if (tNode) {\n const tHandles = getHandlePositions(tNode.width, tNode.height);\n const snap = findClosestHandleWorld(tHandles, tNode, world.x, world.y, Infinity);\n if (snap) { const wp = handleWorldPos(snap, tNode); ex = wp.x; ey = wp.y; }\n }\n }\n\n const g = connectLineRef.current;\n g.clear();\n g.moveTo(sx, sy).lineTo(ex, ey)\n .stroke({ color: 0x3b82f6, width: 2, alpha: 0.6 });\n g.visible = true;\n }\n }\n }\n\n // Reconnect line preview — snaps to nearest handle on target node\n if (reconnectRef.current?.active && connectLineRef.current && !connectLineRef.current.destroyed) {\n const rc = reconnectRef.current;\n const fixedNode = canvasDataRef.current.nodes.find(n => n.id === rc.fixedNodeId);\n if (fixedNode) {\n const handles = getHandlePositions(fixedNode.width, fixedNode.height);\n const fh = handles.find(h => h.id === rc.fixedHandleId);\n const fwp = fh ? handleWorldPos(fh, fixedNode) : { x: fixedNode.position.x + fixedNode.width / 2, y: fixedNode.position.y + fixedNode.height / 2 };\n const fx = fwp.x, fy = fwp.y;\n let ex = world.x, ey = world.y;\n\n const hovNode = hoveredNodeRef.current;\n if (hovNode && hovNode !== rc.fixedNodeId) {\n const tNode = canvasDataRef.current.nodes.find(n => n.id === hovNode);\n if (tNode) {\n const tHandles = getHandlePositions(tNode.width, tNode.height);\n const snap = findClosestHandleWorld(tHandles, tNode, world.x, world.y, Infinity);\n if (snap) { const wp = handleWorldPos(snap, tNode); ex = wp.x; ey = wp.y; }\n }\n }\n\n const g = connectLineRef.current;\n g.clear();\n g.moveTo(fx, fy).lineTo(ex, ey)\n .stroke({ color: 0xf97316, width: 2, alpha: 0.7 });\n g.visible = true;\n }\n }\n });\n\n // ─── POINTER UP ────────────────────────────────────────\n const cleanupDrag = () => {\n activeGuidesRef.current = [];\n try { alignGuidesRef.current?.clear(); } catch { /* destroyed */ }\n try {\n const cl = connectLineRef.current;\n if (cl && !cl.destroyed) { cl.clear(); cl.visible = false; }\n } catch { /* destroyed */ }\n if (containerRef.current) containerRef.current.style.cursor = '';\n };\n\n stage.on('pointerup', (e: FederatedPointerEvent) => {\n cleanupDrag();\n\n if (rotateRef.current?.active) {\n rotateRef.current = null;\n endNodeDragRef.current();\n return;\n }\n\n if (waypointDragRef.current?.active) {\n waypointDragRef.current = null;\n return;\n }\n\n if (resizeRef.current?.active) {\n resizeRef.current = null;\n return;\n }\n\n if (lineDragRef.current?.active) {\n lineDragRef.current = null;\n return;\n }\n\n if (dragRef.current?.active) {\n dragRef.current = null;\n endNodeDragRef.current();\n }\n\n if (marqueeRef.current?.active) {\n const start = screenToWorldRef.current(marqueeRef.current.startScreen.x, marqueeRef.current.startScreen.y);\n const end = screenToWorldRef.current(e.global.x, e.global.y);\n const mx = Math.min(start.x, end.x), my = Math.min(start.y, end.y);\n const mw = Math.abs(end.x - start.x), mh = Math.abs(end.y - start.y);\n if (mw > 4 && mh > 4) {\n const hit = canvasDataRef.current.nodes.filter(n =>\n rectsOverlap(mx, my, mw, mh, n.position.x, n.position.y, n.width, n.height),\n );\n const hitLines = canvasDataRef.current.lines.filter(l => {\n if (l.points.length === 0) return false;\n return l.points.every(p => p.x >= mx && p.x <= mx + mw && p.y >= my && p.y <= my + mh);\n });\n setSelection({\n nodeIds: new Set(hit.map(n => n.id)),\n edgeIds: new Set(),\n lineIds: new Set(hitLines.map(l => l.id)),\n });\n }\n marqueeRef.current = null;\n selectionRef.current?.hideMarquee();\n }\n\n // Reconnection completion\n if (reconnectRef.current?.active) {\n const rcEdgeId = reconnectRef.current.edgeId;\n const rcMovingEnd = reconnectRef.current.movingEnd;\n const rcFixedNodeId = reconnectRef.current.fixedNodeId;\n reconnectRef.current = null;\n\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n // Touch: a finger release often lands just outside the target node's\n // bounds, so allow a small padded hit area when dropping a connection.\n const dropPad = COARSE_POINTER ? hitRadius(vmRef.current?.state.zoom ?? 1, 12, 24) : 0;\n let targetNode: FlowNode | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i], dropPad) && nodes[i].id !== rcFixedNodeId) {\n targetNode = nodes[i]; break;\n }\n }\n if (targetNode) {\n const tgtId = targetNode.id;\n const handles = getHandlePositions(targetNode.width, targetNode.height);\n const closest = findClosestHandleWorld(handles, targetNode, world.x, world.y, Infinity);\n const tgtHandleId = closest?.id;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n edges: canvas.edges.map(edge => {\n if (edge.id !== rcEdgeId) return edge;\n if (rcMovingEnd === 'source') {\n return { ...edge, source: tgtId, sourceHandle: tgtHandleId };\n } else {\n return { ...edge, target: tgtId, targetHandle: tgtHandleId };\n }\n }),\n },\n },\n };\n });\n }\n return;\n }\n\n // New connection completion\n if (connectRef.current?.active) {\n const srcNodeId = connectRef.current.sourceNodeId;\n const srcHandleId = connectRef.current.sourceHandleId;\n connectRef.current = null;\n\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n // Same touch-padded drop target as reconnection above.\n const dropPad = COARSE_POINTER ? hitRadius(vmRef.current?.state.zoom ?? 1, 12, 24) : 0;\n let targetNode: FlowNode | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i], dropPad) && nodes[i].id !== srcNodeId) {\n targetNode = nodes[i]; break;\n }\n }\n if (targetNode) {\n const tgtNodeId = targetNode.id;\n const handles = getHandlePositions(targetNode.width, targetNode.height);\n const closest = findClosestHandleWorld(handles, targetNode, world.x, world.y, Infinity);\n const tgtHandleId = closest?.id;\n const id = `edge_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;\n const eType = edgeTypeRef.current;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n if (canvas.edges.some(e =>\n e.source === srcNodeId && e.target === tgtNodeId\n && e.sourceHandle === srcHandleId && e.targetHandle === tgtHandleId\n )) return prev;\n return {\n ...prev,\n canvases: {\n ...prev.canvases,\n [currentCanvasIdRef.current]: {\n ...canvas,\n edges: [...canvas.edges, {\n id,\n source: srcNodeId,\n target: tgtNodeId,\n sourceHandle: srcHandleId,\n targetHandle: tgtHandleId,\n type: eType as any,\n data: { strokeColor: 'theme:base-content', strokeWidth: 2, lineStyle: 'solid' as const, markerEnd: 'arrowclosed' as const },\n }],\n },\n },\n };\n });\n }\n }\n });\n\n stage.on('pointerupoutside', () => {\n cleanupDrag();\n if (dragRef.current?.active) endNodeDragRef.current();\n if (rotateRef.current?.active) endNodeDragRef.current();\n dragRef.current = null;\n rotateRef.current = null;\n resizeRef.current = null;\n marqueeRef.current = null;\n reconnectRef.current = null;\n connectRef.current = null;\n waypointDragRef.current = null;\n lineDragRef.current = null;\n hoveredNodeRef.current = null;\n hoveredHandleRef.current = null;\n hoveredEdgeEndpointRef.current = null;\n selectionRef.current?.hideMarquee();\n });\n\n // ─── NATIVE TOUCH GESTURES (pinch zoom + two-finger pan) ───\n // Pixi delivers single-pointer events only; a real multi-touch gesture\n // needs native touch listeners. They live on the container (parent of the\n // Pixi canvas) so they also cover the whole interactive surface. While two\n // fingers are down, `multiTouchActive` suppresses all Pixi pointer\n // interactions so node drags/marquees/tap-to-place never fight the pinch.\n const touchEl = containerRef.current;\n let pinch: { dist: number; midX: number; midY: number } | null = null;\n const readPinch = (touches: TouchList) => {\n const rect = touchEl!.getBoundingClientRect();\n const ax = touches[0].clientX, ay = touches[0].clientY;\n const bx = touches[1].clientX, by = touches[1].clientY;\n return {\n dist: Math.hypot(bx - ax, by - ay),\n midX: (ax + bx) / 2 - rect.left,\n midY: (ay + by) / 2 - rect.top,\n };\n };\n const cancelPointerInteractions = () => {\n // Mirror the pointerupoutside cleanup: a finger that already started a\n // node drag / marquee / pan before the second finger landed must not\n // leave stale drag state behind.\n cleanupDrag();\n if (dragRef.current?.active) endNodeDragRef.current();\n if (rotateRef.current?.active) endNodeDragRef.current();\n dragRef.current = null;\n rotateRef.current = null;\n resizeRef.current = null;\n marqueeRef.current = null;\n reconnectRef.current = null;\n connectRef.current = null;\n waypointDragRef.current = null;\n lineDragRef.current = null;\n hoveredNodeRef.current = null;\n hoveredHandleRef.current = null;\n hoveredEdgeEndpointRef.current = null;\n selectionRef.current?.hideMarquee();\n vmRef.current?.cancelPan();\n };\n const onTouchStart = (e: TouchEvent) => {\n if (e.touches.length < 2) return;\n const vm = vmRef.current;\n if (!vm) return;\n vm.multiTouchActive = true;\n cancelPointerInteractions();\n pinch = readPinch(e.touches);\n // Block the browser's own page zoom / scroll gesture on the canvas.\n e.preventDefault();\n };\n const onTouchMove = (e: TouchEvent) => {\n if (!pinch || e.touches.length < 2) return;\n e.preventDefault();\n const vm = vmRef.current;\n if (!vm) return;\n const next = readPinch(e.touches);\n const factor = next.dist / Math.max(1, pinch.dist);\n if (Number.isFinite(factor) && factor > 0) vm.zoomAt(next.midX, next.midY, factor);\n // Follow the midpoint so two-finger drag pans the canvas (map-style).\n vm.setState({\n x: vm.state.x + (next.midX - pinch.midX),\n y: vm.state.y + (next.midY - pinch.midY),\n });\n pinch = next;\n };\n const onTouchEnd = (e: TouchEvent) => {\n if (e.touches.length >= 2) {\n pinch = readPinch(e.touches);\n return;\n }\n // Fewer than two fingers left: stop pinching. Keep `multiTouchActive`\n // until ALL fingers lift so the remaining finger cannot start a marquee\n // or drag as a \"first touch\"; the flag clears on the final touchend.\n pinch = null;\n if (e.touches.length === 0) {\n const vm = vmRef.current;\n if (vm) vm.multiTouchActive = false;\n // Swallow the tap that the last finger's pointerup produces.\n suppressTapUntilRef.current = performance.now() + 350;\n }\n };\n touchEl?.addEventListener('touchstart', onTouchStart, { passive: false });\n touchEl?.addEventListener('touchmove', onTouchMove, { passive: false });\n touchEl?.addEventListener('touchend', onTouchEnd);\n touchEl?.addEventListener('touchcancel', onTouchEnd);\n touchStartHandler = onTouchStart;\n touchMoveHandler = onTouchMove;\n touchEndHandler = onTouchEnd;\n\n // ─── RIGHT-CLICK CONTEXT MENU ─────────────────────────\n stage.on('rightclick', (e: FederatedPointerEvent) => {\n e.preventDefault?.();\n // If the right button was used to pan (drawio-style right-drag), don't\n // open the context menu — only a stationary right-click should.\n if (vmRef.current?.didRightPan) return;\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n const nodes = canvasDataRef.current.nodes;\n let hitNodeId: string | null = null;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) {\n hitNodeId = nodes[i].id;\n break;\n }\n }\n const native = (e as any).nativeEvent as MouseEvent | undefined;\n const cx = native?.clientX ?? e.global.x;\n const cy = native?.clientY ?? e.global.y;\n setContextMenu({ x: cx, y: cy, nodeId: hitNodeId });\n });\n\n // ─── TAP → PLACE STAMP / DOUBLE-CLICK → ENTER SUB-CANVAS / EDIT LABEL ────\n stage.on('pointertap', (e: FederatedPointerEvent) => {\n // Suppress taps that belong to (or immediately follow) a multi-touch\n // pinch/pan gesture.\n if (vmRef.current?.multiTouchActive) return;\n if (performance.now() < suppressTapUntilRef.current) return;\n if (e.button !== 0) return;\n const now = Date.now();\n const world = screenToWorldRef.current(e.global.x, e.global.y);\n\n // Pending placement: stamp the new object at the tap position. Placement\n // lives here (on tap) instead of pointerdown so that adding a second\n // finger mid-gesture (pinch) never drops an accidental stamp.\n const pp = pendingPlacementRef.current;\n if (pp) {\n const newId = generateId('node');\n // Placement magnet: snap the stamp to the canvas grid when enabled\n // (alignment snapping below still wins when it triggers).\n const gs = gridSizeRef.current;\n const snapOn = placementSnapRef.current;\n const rawX = snapPlacement(world.x - pp.width / 2, gs, snapOn);\n const rawY = snapPlacement(world.y - pp.height / 2, gs, snapOn);\n const virtual: FlowNode = {\n id: '__ghost__', type: pp.type,\n position: { x: rawX, y: rawY },\n width: pp.width, height: pp.height, data: {} as any,\n };\n const snap = computeAlignmentSnap([virtual], canvasDataRef.current.nodes);\n const px = rawX + snap.dx;\n const py = rawY + snap.dy;\n setDoc(prev => {\n const canvas = prev.canvases[currentCanvasIdRef.current];\n if (!canvas) return prev;\n const extraData: Record<string, any> = {};\n if (pp.type === 'animAnchor') extraData.animIndex = nextAnimIndex(prev);\n const highestZ = Math.max(\n 0,\n ...canvas.nodes.map(node => node.zIndex ?? 0),\n ...canvas.lines.map(line => line.zIndex ?? 0),\n );\n return {\n ...prev,\n canvases: { ...prev.canvases, [currentCanvasIdRef.current]: {\n ...canvas,\n nodes: [...canvas.nodes, {\n id: newId,\n type: pp.type,\n position: { x: px, y: py },\n width: pp.width,\n height: pp.height,\n zIndex: highestZ + 1,\n data: { ...pp.data, ...extraData },\n }],\n }},\n };\n });\n setSelection({ nodeIds: new Set([newId]), edgeIds: new Set(), lineIds: new Set() });\n if (autoFocusRef.current) {\n window.setTimeout(() => {\n focusOnRectRef.current(px, py, pp.width, pp.height, {\n padding: 80,\n preserveZoom: true,\n duration: 280,\n });\n }, 0);\n }\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n\n const last = dblClickRef.current;\n const dx = world.x - last.wx;\n const dy = world.y - last.wy;\n if (now - last.time < 400 && Math.abs(dx) < 10 && Math.abs(dy) < 10) {\n const nodes = canvasDataRef.current.nodes;\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (isPointInNode(world.x, world.y, nodes[i])) {\n const node = nodes[i];\n const childId = node.data.childCanvasId;\n if (childId) {\n pushCanvas(childId);\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n // Double-click a shape → edit its label in place.\n beginEditRef.current('node', node.id, node.data.label ?? '');\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n }\n\n // Double-click an edge → edit its label.\n const edges = canvasDataRef.current.edges;\n const wmNodeMap = new Map<string, FlowNode>();\n for (const n of nodes) wmNodeMap.set(n.id, n);\n const zoom = vmRef.current?.state.zoom ?? 1;\n for (let i = edges.length - 1; i >= 0; i--) {\n if (isPointNearEdgePath(world.x, world.y, edges[i], wmNodeMap, hitRadius(zoom, 8, 12))) {\n beginEditRef.current('edge', edges[i].id, edges[i].data.labelText ?? '');\n dblClickRef.current = { time: 0, wx: 0, wy: 0 };\n return;\n }\n }\n }\n dblClickRef.current = { time: now, wx: world.x, wy: world.y };\n });\n\n // ─── RENDER LOOP ───────────────────────────────────\n let wasPanning = false;\n pixi.app.ticker.add((ticker) => {\n if (pixi.destroyed) return;\n const deltaMs = ticker.deltaMS;\n const screen = pixi.app.screen;\n const vp = vmRef.current?.state ?? { x: 0, y: 0, zoom: 1 };\n gridRef.current?.update(vp, screen.width, screen.height);\n\n // Show a grabbing cursor while panning (right-drag / middle / space).\n const panningNow = vmRef.current?.isPanning ?? false;\n if (panningNow !== wasPanning) {\n wasPanning = panningNow;\n if (containerRef.current) {\n containerRef.current.style.cursor = panningNow ? 'grabbing' : '';\n }\n }\n\n const cData = canvasDataRef.current;\n const sel = selectionDataRef.current;\n\n // Global (document-wide) animation-anchor sequence so sub-canvas badges\n // share one order and the presentation can drill in/out consistently.\n const slides = getDocumentSlides(docRef.current);\n const animSeqMap = new Map<string, number>();\n slides.forEach((s, i) => animSeqMap.set(s.node.id, i + 1));\n\n nodeRendererRef.current?.advanceAnimation(deltaMs);\n const activeSlide = presentationRef.current\n ? slides[presentationRef.current.current]\n : undefined;\n nodeRendererRef.current?.sync(cData.nodes, sel.nodeIds, hoveredNodeRef.current, animSeqMap, {\n showAnchors: showAnchorsRef.current,\n presentation: presentationRef.current !== null,\n presentationAnchorId: activeSlide?.node.id,\n presentationAnchorVisible: presentationRef.current?.showAnchor ?? false,\n });\n\n const nodeMap = new Map<string, FlowNode>();\n for (const n of cData.nodes) nodeMap.set(n.id, n);\n edgeRendererRef.current?.advanceAnimation(deltaMs);\n edgeRendererRef.current?.sync(cData.edges, nodeMap, sel.edgeIds, null, {\n presentation: presentationRef.current !== null,\n });\n\n lineRendererRef.current?.advanceAnimation(deltaMs);\n lineRendererRef.current?.sync(cData.lines, sel.lineIds);\n\n // Draw alignment guides in world space\n alignGuidesRef.current?.update(activeGuidesRef.current, screen.width, screen.height, vp);\n\n // Selection delete button (touch-friendly counterpart of the Delete\n // key): a DOM button pinned to the top-right of the selection's screen\n // bounding box, re-positioned every frame. Styles are written directly\n // to avoid per-frame React renders.\n const delBtn = deleteButtonRef.current;\n if (delBtn) {\n const hasSelection = sel.nodeIds.size > 0 || sel.edgeIds.size > 0 || sel.lineIds.size > 0;\n const showDelete = hasSelection && !readOnlyRef.current\n && !presentationRef.current && !pendingPlacementRef.current;\n let boundsEmpty = !showDelete;\n if (showDelete) {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n const bump = (x: number, y: number, w: number, h: number) => {\n minX = Math.min(minX, x); minY = Math.min(minY, y);\n maxX = Math.max(maxX, x + w); maxY = Math.max(maxY, y + h);\n };\n for (const n of cData.nodes) {\n if (sel.nodeIds.has(n.id)) bump(n.position.x, n.position.y, n.width, n.height);\n }\n for (const e of cData.edges) {\n if (!sel.edgeIds.has(e.id)) continue;\n const s = nodeMap.get(e.source);\n const t = nodeMap.get(e.target);\n if (s) bump(s.position.x, s.position.y, s.width, s.height);\n if (t) bump(t.position.x, t.position.y, t.width, t.height);\n }\n for (const l of cData.lines) {\n if (!sel.lineIds.has(l.id)) continue;\n for (const p of l.points) bump(p.x, p.y, 0, 0);\n }\n if (minX === Infinity) {\n boundsEmpty = true;\n } else {\n const z = vp.zoom;\n const BTN_W = 66, BTN_H = 30, MARGIN = 6;\n let bx = maxX * z + vp.x + 8;\n let by = minY * z + vp.y - BTN_H - 6;\n if (bx + BTN_W > screen.width - MARGIN) bx = Math.max(MARGIN, screen.width - BTN_W - MARGIN);\n if (by < MARGIN) by = minY * z + vp.y + MARGIN;\n if (by + BTN_H > screen.height - MARGIN) by = Math.max(MARGIN, screen.height - BTN_H - MARGIN);\n delBtn.style.display = 'flex';\n delBtn.style.left = `${Math.round(bx)}px`;\n delBtn.style.top = `${Math.round(by)}px`;\n }\n }\n if (boundsEmpty && delBtn.style.display !== 'none') delBtn.style.display = 'none';\n }\n\n // Draw connection handle hover indicator (world space)\n const hhGfx = handleHoverGfxRef.current;\n if (hhGfx) {\n hhGfx.clear();\n const hh = hoveredHandleRef.current;\n if (hh) {\n hhGfx.circle(hh.wx, hh.wy, 10)\n .fill({ color: 0x3b82f6, alpha: 0.12 })\n .stroke({ color: 0x3b82f6, width: 1.5, alpha: 0.5 });\n hhGfx.circle(hh.wx, hh.wy, 4)\n .fill({ color: 0x3b82f6, alpha: 0.9 });\n }\n // Edge endpoint hover indicators\n const epHover = hoveredEdgeEndpointRef.current;\n if (epHover && !hh) {\n hhGfx.circle(epHover.worldX, epHover.worldY, 10)\n .fill({ color: 0xf97316, alpha: 0.12 })\n .stroke({ color: 0xf97316, width: 1.5, alpha: 0.5 });\n hhGfx.circle(epHover.worldX, epHover.worldY, 4)\n .fill({ color: 0xf97316, alpha: 0.9 });\n }\n }\n\n // Ghost placement preview — draw actual shape silhouette, with\n // alignment-guide snapping against existing nodes (same as dragging).\n const gGfx = ghostGfxRef.current;\n if (gGfx) {\n gGfx.clear();\n const pp = pendingPlacementRef.current;\n if (pp) {\n const mw = mouseWorldRef.current;\n // Same placement-magnet math as the stamping site so the ghost\n // preview lands exactly where the shape will be placed.\n const gs = gridSizeRef.current;\n const snapOn = placementSnapRef.current;\n const rawX = snapPlacement(mw.x - pp.width / 2, gs, snapOn);\n const rawY = snapPlacement(mw.y - pp.height / 2, gs, snapOn);\n const virtual: FlowNode = {\n id: '__ghost__', type: pp.type,\n position: { x: rawX, y: rawY },\n width: pp.width, height: pp.height, data: {} as any,\n };\n const snap = computeAlignmentSnap([virtual], cData.nodes);\n activeGuidesRef.current = snap.guides;\n gGfx.position.set(rawX + snap.dx, rawY + snap.dy);\n const drawFn = shapeDrawers[pp.type] ?? shapeDrawers.shapeRect;\n drawFn(gGfx, {\n width: pp.width, height: pp.height,\n fill: '#3b82f6', stroke: '#3b82f6',\n strokeWidth: 1.5, borderStyle: pp.data.borderStyle,\n });\n } else {\n gGfx.position.set(0, 0);\n // Only clear guides here if nothing else (drag/resize) owns them.\n if (!dragRef.current?.active && !resizeRef.current?.active) {\n activeGuidesRef.current = [];\n }\n }\n }\n\n // Draw edge edit handles (waypoints + bezier controls) in world space\n const eeGfx = edgeEditGfxRef.current;\n if (eeGfx) {\n eeGfx.clear();\n if (sel.edgeIds.size > 0 && toolModeRef.current === 'select') {\n const iz = 1 / vp.zoom;\n for (const edge of cData.edges) {\n if (!sel.edgeIds.has(edge.id)) continue;\n // Endpoint drag targets: always drawn on a selected edge so touch\n // users (no hover) can discover they can be dragged to reconnect.\n const dragEp = resolveEdgeEndpoints(edge, nodeMap);\n if (dragEp) {\n eeGfx.circle(dragEp.sx, dragEp.sy, 5 * iz)\n .fill({ color: 0xffffff })\n .stroke({ color: 0xf97316, width: 1.5 * iz });\n eeGfx.circle(dragEp.tx, dragEp.ty, 5 * iz)\n .fill({ color: 0xffffff })\n .stroke({ color: 0xf97316, width: 1.5 * iz });\n }\n const wps = edge.data.waypoints;\n if (wps) {\n for (const wp of wps) {\n eeGfx.circle(wp.x, wp.y, 5 * iz)\n .fill({ color: 0xffffff })\n .stroke({ color: 0x3b82f6, width: 1.5 * iz });\n }\n }\n if (edge.type === 'simplebezier') {\n const ep = resolveEdgeEndpoints(edge, nodeMap);\n if (!ep) continue;\n const allWps = wps ?? [];\n const allPts = [{ x: ep.sx, y: ep.sy }, ...allWps, { x: ep.tx, y: ep.ty }];\n const controls = edge.data.bezierControls;\n const lastSegIdx = allPts.length - 2;\n for (let i = 0; i <= lastSegIdx; i++) {\n const a = allPts[i], b = allPts[i + 1];\n const ctrl = controls?.[i];\n const segDist = Math.hypot(b.x - a.x, b.y - a.y);\n const arm = Math.max(30, segDist * 0.3);\n const c1x = ctrl?.c1x ?? (i === 0 ? a.x + ep.snx * arm : a.x + (b.x - a.x) * 0.4);\n const c1y = ctrl?.c1y ?? (i === 0 ? a.y + ep.sny * arm : a.y);\n const c2x = ctrl?.c2x ?? (i === lastSegIdx ? b.x + ep.tnx * arm : b.x - (b.x - a.x) * 0.4);\n const c2y = ctrl?.c2y ?? (i === lastSegIdx ? b.y + ep.tny * arm : b.y);\n eeGfx.moveTo(a.x, a.y).lineTo(c1x, c1y).stroke({ color: 0x9ca3af, width: 1 * iz });\n eeGfx.moveTo(b.x, b.y).lineTo(c2x, c2y).stroke({ color: 0x9ca3af, width: 1 * iz });\n const cr = 4 * iz;\n eeGfx.circle(c1x, c1y, cr).fill({ color: 0xffffff }).stroke({ color: 0x3b82f6, width: 1.5 * iz });\n eeGfx.circle(c2x, c2y, cr).fill({ color: 0xffffff }).stroke({ color: 0x3b82f6, width: 1.5 * iz });\n }\n }\n }\n }\n }\n\n // Draw transform handles in screen space\n const tg = transformGfxRef.current;\n if (tg) {\n tg.clear();\n if (sel.nodeIds.size === 1 && toolModeRef.current === 'select') {\n const nodeId = [...sel.nodeIds][0];\n const node = cData.nodes.find(n => n.id === nodeId);\n if (node) {\n const z = vp.zoom;\n const sx = node.position.x * z + vp.x;\n const sy = node.position.y * z + vp.y;\n const sw = node.width * z;\n const sh = node.height * z;\n\n tg.rect(sx, sy, sw, sh).stroke({ color: 0x3b82f6, width: 1.5 });\n\n // Corner resize handles (squares)\n const hs = 7, h2 = hs / 2;\n const corners: Array<[number, number]> = [\n [sx, sy], [sx + sw, sy],\n [sx + sw, sy + sh], [sx, sy + sh],\n ];\n for (const [cx, cy] of corners) {\n tg.rect(cx - h2, cy - h2, hs, hs)\n .fill({ color: 0xffffff })\n .stroke({ color: 0x3b82f6, width: 1.5 });\n }\n\n // Midpoint connection handles (circles)\n const cr = 4;\n const midpoints: Array<[number, number]> = [\n [sx + sw / 2, sy], [sx + sw, sy + sh / 2],\n [sx + sw / 2, sy + sh], [sx, sy + sh / 2],\n ];\n for (const [cx, cy] of midpoints) {\n tg.circle(cx, cy, cr)\n .fill({ color: 0x3b82f6, alpha: 0.9 });\n }\n\n // Rotation knob: stem above the top-center ending in a knob;\n // drag it around the node center to rotate (Shift = 15° steps).\n if (!readOnlyRef.current) {\n const kx = sx + sw / 2;\n const kyKnob = sy - ROTATE_STEM;\n tg.moveTo(kx, sy).lineTo(kx, kyKnob)\n .stroke({ color: 0x3b82f6, width: 1.5, alpha: 0.85 });\n tg.circle(kx, kyKnob, 6)\n .fill({ color: 0xffffff })\n .stroke({ color: 0x3b82f6, width: 1.5 });\n tg.circle(kx, kyKnob, 2.5)\n .fill({ color: 0x3b82f6 });\n }\n }\n }\n }\n });\n };\n\n waitForReady();\n\n return () => {\n cancelled = true;\n // Remove stage event listeners to prevent duplicates on re-mount\n if (pixi && !pixi.destroyed) {\n try { pixi.app.stage.removeAllListeners(); } catch { /* already destroyed */ }\n }\n // Remove native touch gesture listeners\n const touchEl = containerRef.current;\n if (touchStartHandler) touchEl?.removeEventListener('touchstart', touchStartHandler);\n if (touchMoveHandler) touchEl?.removeEventListener('touchmove', touchMoveHandler);\n if (touchEndHandler) {\n touchEl?.removeEventListener('touchend', touchEndHandler);\n touchEl?.removeEventListener('touchcancel', touchEndHandler);\n }\n gridRef.current?.destroy();\n selectionRef.current?.destroy();\n nodeRendererRef.current?.destroy();\n edgeRendererRef.current?.destroy();\n lineRendererRef.current?.destroy();\n freehandRef.current?.destroy();\n geoLineRef.current?.destroy();\n connectLineRef.current?.destroy();\n if (transformGfxRef.current) { transformGfxRef.current.destroy(); transformGfxRef.current = null; }\n if (handleHoverGfxRef.current) { handleHoverGfxRef.current.destroy(); handleHoverGfxRef.current = null; }\n if (edgeEditGfxRef.current) { edgeEditGfxRef.current.destroy(); edgeEditGfxRef.current = null; }\n if (ghostGfxRef.current) { ghostGfxRef.current.destroy(); ghostGfxRef.current = null; }\n alignGuidesRef.current?.destroy();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pixiRef.current]);\n\n // Activate/deactivate line tools based on toolMode\n useEffect(() => {\n const freehand = freehandRef.current;\n const geo = geoLineRef.current;\n if (!freehand || !geo) return;\n\n freehand.deactivate();\n geo.deactivate();\n\n switch (toolMode) {\n case 'freehand': freehand.activate(); break;\n case 'line': geo.activate('straight'); break;\n case 'polyline': geo.activate('polyline'); break;\n case 'arrow': geo.activate('arrow'); break;\n }\n }, [toolMode]);\n\n useEffect(() => {\n if (gridRef.current) {\n gridRef.current.visible = showGrid;\n gridRef.current.gridSize = gridSize;\n }\n }, [showGrid, gridSize]);\n\n // Native, non-passive wheel listener: zoom the canvas and preventDefault() so\n // the browser's Ctrl/Cmd+wheel page zoom (and trackpad pinch) never fires.\n // Pixi's federated wheel event cannot reliably block that native gesture.\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const ZOOM_SENSITIVITY = 0.001;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const vm = vmRef.current;\n if (!vm) return;\n const rect = el.getBoundingClientRect();\n const sx = e.clientX - rect.left;\n const sy = e.clientY - rect.top;\n // ctrlKey is set for pinch-zoom gestures; scale it up for parity.\n const scale = e.ctrlKey ? 3 : 1;\n const delta = -e.deltaY * ZOOM_SENSITIVITY * scale;\n vm.zoomAt(sx, sy, 1 + delta);\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [vmRef]);\n\n return (\n <div style={{ position: 'relative', width: '100%', height: '100%' }}>\n <div\n ref={containerRef}\n className=\"flow-canvas-wrapper\"\n tabIndex={-1}\n onContextMenu={(e) => e.preventDefault()}\n />\n {editing && editorPos && (\n <input\n className=\"flow-label-editor\"\n autoFocus\n defaultValue={editing.value}\n style={{ left: editorPos.x, top: editorPos.y }}\n // Entering edit mode (double-click / Space) selects the whole label,\n // so typing immediately replaces it instead of appending.\n onFocus={(e) => e.currentTarget.select()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n commitEdit((e.target as HTMLInputElement).value);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancelEdit();\n }\n e.stopPropagation();\n }}\n onBlur={(e) => commitEdit(e.target.value)}\n onPointerDown={(e) => e.stopPropagation()}\n />\n )}\n {/* Virtual ESC: cancels continuous stamp placement — the touch-friendly\n counterpart of the physical Esc key (kept on desktop too). */}\n {pendingPlacement && !presentation && (\n <button\n type=\"button\"\n className=\"flow-esc-button\"\n onClick={() => setPendingPlacement(null)}\n title=\"取消连续放置 (Esc)\"\n >\n <span aria-hidden>⎋</span> 取消放置 (ESC)\n </button>\n )}\n {/* Selection delete: the touch-friendly counterpart of the Delete/\n Backspace key. Always mounted; the render loop toggles visibility and\n pins it to the selection's top-right corner every frame. */}\n <button\n ref={deleteButtonRef}\n type=\"button\"\n className=\"flow-delete-button\"\n style={{ display: 'none' }}\n onClick={() => deleteSelectedRef.current()}\n title=\"删除所选 (Delete)\"\n aria-label=\"删除所选\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 6h18\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n 删除\n </button>\n </div>\n );\n}\n"],"mappings":"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"}