canvas/dist/core/index.mjs.map
2026-03-11 18:42:08 -07:00

1 line
No EOL
345 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"version":3,"sources":["../../src/core/graph-store.ts","../../src/core/graph-position.ts","../../src/utils/debug.ts","../../src/utils/mutation-queue.ts","../../src/core/perf.ts","../../src/core/graph-derived.ts","../../src/core/viewport-store.ts","../../src/core/selection-store.ts","../../src/utils/layout.ts","../../src/core/group-store.ts","../../src/core/history-store.ts","../../src/core/history-actions.ts","../../src/core/graph-mutations.ts","../../src/core/graph-mutations-edges.ts","../../src/core/reduced-motion-store.ts","../../src/core/graph-mutations-advanced.ts","../../src/core/sync-store.ts","../../src/core/interaction-store.ts","../../src/core/locked-node-store.ts","../../src/core/node-type-registry.tsx","../../src/core/toast-store.ts","../../src/core/snap-store.ts","../../src/core/event-types.ts","../../src/core/action-types.ts","../../src/core/settings-state-types.ts","../../src/core/actions-node.ts","../../src/core/actions-viewport.ts","../../src/core/built-in-actions.ts","../../src/core/action-registry.ts","../../src/core/action-executor.ts","../../src/core/settings-store.ts","../../src/core/settings-presets.ts","../../src/core/canvas-serializer.ts","../../src/core/clipboard-store.ts","../../src/core/virtualization-store.ts","../../src/core/spatial-index.ts","../../src/core/canvas-api.ts","../../src/core/port-types.ts","../../src/core/input-classifier.ts","../../src/core/input-store.ts","../../src/core/selection-path-store.ts","../../src/core/search-store.ts","../../src/core/gesture-rules-defaults.ts","../../src/core/gesture-rules.ts","../../src/core/gesture-rule-store.ts","../../src/core/external-keyboard-store.ts","../../src/core/plugin-types.ts","../../src/gestures/types.ts","../../src/gestures/dispatcher.ts","../../src/commands/registry.ts","../../src/utils/edge-path-registry.ts","../../src/core/plugin-registry.ts"],"sourcesContent":["/**\n * Graph state management — core atoms\n *\n * Foundation atoms for the Graphology + Jotai graph system.\n * Position, derived, and mutation atoms live in their own modules.\n *\n * @see ./graph-position.ts — position atoms\n * @see ./graph-derived.ts — read-only UI derivation atoms\n * @see ./graph-mutations.ts — write atoms (CRUD, split/merge, DB sync)\n */\n\nimport { atom } from 'jotai';\nimport Graph from 'graphology';\n// --- Graph Configuration ---\n\nexport const graphOptions = {\n type: 'directed',\n multi: true,\n allowSelfLoops: true\n};\n\n// --- Core Graph Atoms ---\n\n/**\n * Currently active graph ID\n */\nexport const currentGraphIdAtom = atom(null);\n\n/**\n * Main graph instance\n */\nexport const graphAtom = atom(new Graph(graphOptions));\n\n/**\n * Version counter to trigger re-renders\n */\nexport const graphUpdateVersionAtom = atom(0);\n\n// --- Edge Creation State ---\n\nexport const edgeCreationAtom = atom({\n isCreating: false,\n sourceNodeId: null,\n sourceNodePosition: null,\n targetPosition: null,\n hoveredTargetNodeId: null,\n sourceHandle: null,\n targetHandle: null,\n sourcePort: null,\n targetPort: null,\n snappedTargetPosition: null\n});\n\n// --- Drag State ---\n\nexport const draggingNodeIdAtom = atom(null);\nexport const preDragNodeAttributesAtom = atom(null);","/**\n * Graph position management\n *\n * Per-node position atoms derived from Graphology.\n * Structural equality caching prevents unnecessary re-renders.\n */\n\nimport { atom } from 'jotai';\nimport { atomFamily } from 'jotai-family';\nimport Graph from 'graphology';\nimport { graphAtom, graphUpdateVersionAtom, graphOptions } from './graph-store';\nimport { createDebug } from '../utils/debug';\nimport { clearAllPendingMutations } from '../utils/mutation-queue';\nimport { canvasMark } from './perf';\nconst debug = createDebug('graph:position');\n\n// --- Position Cache ---\n\n/**\n * Cache for the previous position values, scoped per Graph instance via WeakMap.\n * Enables structural equality — only notify dependents when x/y actually changed.\n */\nconst _positionCacheByGraph = new WeakMap();\nfunction getPositionCache(graph) {\n let cache = _positionCacheByGraph.get(graph);\n if (!cache) {\n cache = new Map();\n _positionCacheByGraph.set(graph, cache);\n }\n return cache;\n}\n\n// --- Position Atoms ---\n\n/**\n * Counter to trigger edge re-renders when positions change\n */\nexport const nodePositionUpdateCounterAtom = atom(0);\n\n/**\n * Per-node position atoms - derived from Graphology (single source of truth)\n * These are read-only atoms that derive position from the graph.\n */\nexport const nodePositionAtomFamily = atomFamily(nodeId => atom(get => {\n get(nodePositionUpdateCounterAtom); // Invalidation trigger for fine-grained updates\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) {\n return {\n x: 0,\n y: 0\n };\n }\n const x = graph.getNodeAttribute(nodeId, 'x');\n const y = graph.getNodeAttribute(nodeId, 'y');\n\n // Structural equality: return the same reference if position unchanged\n const cache = getPositionCache(graph);\n const prev = cache.get(nodeId);\n if (prev && prev.x === x && prev.y === y) {\n return prev;\n }\n const pos = {\n x,\n y\n };\n cache.set(nodeId, pos);\n return pos;\n}));\n\n/**\n * Update a node's position\n */\nexport const updateNodePositionAtom = atom(null, (get, set, {\n nodeId,\n position\n}) => {\n const end = canvasMark('drag-frame');\n const graph = get(graphAtom);\n if (graph.hasNode(nodeId)) {\n debug('Updating node %s position to %o', nodeId, position);\n graph.setNodeAttribute(nodeId, 'x', position.x);\n graph.setNodeAttribute(nodeId, 'y', position.y);\n // Position atom is derived - no need to set it, just trigger re-read\n set(nodePositionUpdateCounterAtom, c => c + 1);\n }\n end();\n});\n\n/**\n * Cleanup position atom for a deleted node\n * Note: Position atoms are now derived, so cleanup is optional but helps memory\n */\nexport const cleanupNodePositionAtom = atom(null, (get, _set, nodeId) => {\n nodePositionAtomFamily.remove(nodeId);\n const graph = get(graphAtom);\n getPositionCache(graph).delete(nodeId);\n debug('Removed position atom for node: %s', nodeId);\n});\n\n/**\n * Cleanup all position atoms (used when switching graphs)\n * Note: Position atoms are now derived, so cleanup is optional but helps memory\n */\nexport const cleanupAllNodePositionsAtom = atom(null, (get, _set) => {\n const graph = get(graphAtom);\n const nodeIds = graph.nodes();\n nodeIds.forEach(nodeId => {\n nodePositionAtomFamily.remove(nodeId);\n });\n _positionCacheByGraph.delete(graph);\n debug('Removed %d position atoms', nodeIds.length);\n});\n\n/**\n * Clear graph when switching to a new graph\n */\nexport const clearGraphOnSwitchAtom = atom(null, (get, set) => {\n debug('Clearing graph for switch');\n set(cleanupAllNodePositionsAtom);\n clearAllPendingMutations();\n const emptyGraph = new Graph(graphOptions);\n set(graphAtom, emptyGraph);\n set(graphUpdateVersionAtom, v => v + 1);\n});","/**\n * Debug utility for @blinksgg/canvas\n *\n * Uses the `debug` package with `canvas:*` namespaces.\n * Enable in browser: `localStorage.debug = 'canvas:*'`\n * Enable in Node: `DEBUG=canvas:* node ...`\n *\n * Log levels:\n * debug('message') — verbose trace (blue)\n * debug.warn('message') — warnings (yellow, always stderr)\n * debug.error('message') — errors (red, always stderr)\n */\n\nimport debugFactory from 'debug';\nconst NAMESPACE = 'canvas';\n/**\n * Create a debug logger for a specific module.\n *\n * @example\n * ```ts\n * const debug = createDebug('graph');\n * debug('loaded %d nodes', count); // canvas:graph\n * debug.warn('node %s not found', id); // canvas:graph:warn\n * debug.error('sync failed: %O', err); // canvas:graph:error\n * ```\n */\nexport function createDebug(module) {\n const base = debugFactory(`${NAMESPACE}:${module}`);\n const warn = debugFactory(`${NAMESPACE}:${module}:warn`);\n const error = debugFactory(`${NAMESPACE}:${module}:error`);\n\n // Warnings and errors always log (even without DEBUG=canvas:*)\n warn.enabled = true;\n error.enabled = true;\n\n // Color hints: warn = yellow, error = red\n warn.log = console.warn.bind(console);\n error.log = console.error.bind(console);\n\n // Build the debugger with warn/error sub-loggers\n const debugFn = Object.assign(base, {\n warn,\n error\n });\n return debugFn;\n}\n\n// Pre-configured debug loggers\nexport const debug = {\n graph: {\n node: createDebug('graph:node'),\n edge: createDebug('graph:edge'),\n sync: createDebug('graph:sync')\n },\n ui: {\n selection: createDebug('ui:selection'),\n drag: createDebug('ui:drag'),\n resize: createDebug('ui:resize')\n },\n sync: {\n status: createDebug('sync:status'),\n mutations: createDebug('sync:mutations'),\n queue: createDebug('sync:queue')\n },\n viewport: createDebug('viewport')\n};","/**\n * Mutation queue for tracking pending node updates\n *\n * Prevents race conditions during rapid drag operations.\n */\n\n/**\n * Global map to track pending mutations per node\n */\nexport const pendingNodeMutations = new Map();\n\n/**\n * Get or create pending mutation state for a node\n */\nexport function getPendingState(nodeId) {\n let state = pendingNodeMutations.get(nodeId);\n if (!state) {\n state = {\n inFlight: false,\n queuedPosition: null,\n queuedUiProperties: null,\n graphId: null\n };\n pendingNodeMutations.set(nodeId, state);\n }\n return state;\n}\n\n/**\n * Clear pending state for a node\n */\nexport function clearPendingState(nodeId) {\n pendingNodeMutations.delete(nodeId);\n}\n\n/**\n * Clear all pending mutation state (used on graph switch)\n */\nexport function clearAllPendingMutations() {\n pendingNodeMutations.clear();\n}\n\n/**\n * Check if any node has pending mutations\n */\nexport function hasPendingMutations() {\n for (const state of pendingNodeMutations.values()) {\n if (state.inFlight || state.queuedPosition !== null || state.queuedUiProperties !== null) {\n return true;\n }\n }\n return false;\n}","/**\n * Performance Instrumentation\n *\n * Opt-in performance.mark / performance.measure wrappers for DevTools profiling.\n * All marks are prefixed with \"canvas:\" for easy filtering.\n *\n * Usage:\n * const end = canvasMark('drag-frame');\n * // ... work ...\n * end(); // calls performance.measure automatically\n */\n\nimport { atom } from 'jotai';\n\n/**\n * Whether performance instrumentation is enabled.\n * Off by default — set to true to see marks in DevTools Performance tab.\n */\nexport const perfEnabledAtom = atom(false);\n\n// Module-level flag mirrored from atom for zero-overhead checks in hot paths.\n// Updated by `setPerfEnabled`.\nlet _enabled = false;\n\n/**\n * Imperatively set perf instrumentation on/off.\n * Useful from devtools console: `window.__canvasPerf?.(true)`.\n */\nexport function setPerfEnabled(enabled) {\n _enabled = enabled;\n}\n\n// Expose on window for easy devtools access\nif (typeof window !== 'undefined') {\n window.__canvasPerf = setPerfEnabled;\n}\n\n/**\n * Start a performance mark. Returns a function that, when called,\n * creates a measure from the mark to the current time.\n *\n * When instrumentation is disabled, returns a no-op (zero overhead).\n */\nexport function canvasMark(name) {\n if (!_enabled) return _noop;\n const markName = `canvas:${name}`;\n try {\n performance.mark(markName);\n } catch {\n return _noop;\n }\n return () => {\n try {\n performance.measure(`canvas:${name}`, markName);\n } catch {\n // mark may have been cleared\n }\n };\n}\nfunction _noop() {}\n\n/**\n * Measure a synchronous function call.\n */\nexport function canvasWrap(name, fn) {\n const end = canvasMark(name);\n try {\n return fn();\n } finally {\n end();\n }\n}","/**\n * Graph derived atoms\n *\n * Read-only UI atoms derived from the Graphology graph.\n * Provides node/edge state for rendering with structural equality caching.\n */\n\nimport { atom } from 'jotai';\nimport { atomFamily } from 'jotai-family';\nimport { graphAtom, graphUpdateVersionAtom, currentGraphIdAtom, edgeCreationAtom, draggingNodeIdAtom } from './graph-store';\nimport { nodePositionAtomFamily } from './graph-position';\nimport { panAtom, zoomAtom, viewportRectAtom } from './viewport-store';\nimport { collapsedGroupsAtom, collapsedEdgeRemapAtom } from './group-store';\n\n// --- Derived Node Atoms ---\n\n/**\n * Highest z-index among nodes\n */\nexport const highestZIndexAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n let maxZ = 0;\n graph.forEachNode((_node, attributes) => {\n if (attributes.zIndex > maxZ) {\n maxZ = attributes.zIndex;\n }\n });\n return maxZ;\n});\n\n/**\n * All UI nodes with current positions\n *\n * Uses structural equality: if every entry is reference-equal to the\n * previous result, the same array is returned to avoid downstream re-renders.\n */\nconst _prevUiNodesByGraph = new WeakMap();\nexport const uiNodesAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n const currentDraggingId = get(draggingNodeIdAtom);\n const collapsed = get(collapsedGroupsAtom);\n const nodes = [];\n graph.forEachNode((nodeId, attributes) => {\n // Skip nodes whose parent (or ancestor) is collapsed\n if (collapsed.size > 0) {\n let current = nodeId;\n let hidden = false;\n while (true) {\n if (!graph.hasNode(current)) break;\n const pid = graph.getNodeAttributes(current).parentId;\n if (!pid) break;\n if (collapsed.has(pid)) {\n hidden = true;\n break;\n }\n current = pid;\n }\n if (hidden) return;\n }\n const position = get(nodePositionAtomFamily(nodeId));\n nodes.push({\n ...attributes,\n id: nodeId,\n position,\n isDragging: nodeId === currentDraggingId\n });\n });\n\n // Structural equality: return previous array if length and entries match\n const prev = _prevUiNodesByGraph.get(graph) ?? [];\n if (nodes.length === prev.length && nodes.every((n, i) => n.id === prev[i].id && n.position === prev[i].position && n.isDragging === prev[i].isDragging)) {\n return prev;\n }\n _prevUiNodesByGraph.set(graph, nodes);\n return nodes;\n});\n\n/**\n * All node keys\n */\nexport const nodeKeysAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return graph.nodes();\n});\n\n/**\n * Per-node UI state\n */\nexport const nodeFamilyAtom = atomFamily(nodeId => atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) {\n return null;\n }\n const attributes = graph.getNodeAttributes(nodeId);\n const position = get(nodePositionAtomFamily(nodeId));\n const currentDraggingId = get(draggingNodeIdAtom);\n return {\n ...attributes,\n id: nodeId,\n position,\n isDragging: nodeId === currentDraggingId\n };\n}), (a, b) => a === b);\n\n// --- Derived Edge Atoms ---\n\n/**\n * All edge keys\n */\nexport const edgeKeysAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return graph.edges();\n});\n\n/**\n * Edge keys including temp edge during creation\n */\nexport const edgeKeysWithTempEdgeAtom = atom(get => {\n const keys = get(edgeKeysAtom);\n const edgeCreation = get(edgeCreationAtom);\n if (edgeCreation.isCreating) {\n return [...keys, 'temp-creating-edge'];\n }\n return keys;\n});\n\n/**\n * Per-edge UI state\n *\n * Structural equality cache: stores previous result per edge key.\n * Returns previous object when all fields match — prevents downstream re-renders.\n */\nconst _edgeCacheByGraph = new WeakMap();\nfunction getEdgeCache(graph) {\n let cache = _edgeCacheByGraph.get(graph);\n if (!cache) {\n cache = new Map();\n _edgeCacheByGraph.set(graph, cache);\n }\n return cache;\n}\nexport const edgeFamilyAtom = atomFamily(key => atom(get => {\n // Position reactivity flows through nodePositionAtomFamily(sourceId/targetId)\n // with structural equality caching — only connected edges re-render on drag.\n // graphUpdateVersionAtom handles non-position attribute changes (label, color)\n // and is NOT bumped during drag, so it won't cause O(E) re-renders.\n get(graphUpdateVersionAtom);\n if (key === 'temp-creating-edge') {\n const edgeCreationState = get(edgeCreationAtom);\n const graph = get(graphAtom);\n if (edgeCreationState.isCreating && edgeCreationState.sourceNodeId && edgeCreationState.targetPosition) {\n const sourceNodeAttrs = graph.getNodeAttributes(edgeCreationState.sourceNodeId);\n const sourceNodePosition = get(nodePositionAtomFamily(edgeCreationState.sourceNodeId));\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n const viewportRect = get(viewportRectAtom);\n if (sourceNodeAttrs && viewportRect) {\n const mouseX = edgeCreationState.targetPosition.x - viewportRect.left;\n const mouseY = edgeCreationState.targetPosition.y - viewportRect.top;\n const worldTargetX = (mouseX - pan.x) / zoom;\n const worldTargetY = (mouseY - pan.y) / zoom;\n const tempEdge = {\n key: 'temp-creating-edge',\n sourceId: edgeCreationState.sourceNodeId,\n targetId: 'temp-cursor',\n sourcePosition: sourceNodePosition,\n targetPosition: {\n x: worldTargetX,\n y: worldTargetY\n },\n sourceNodeSize: sourceNodeAttrs.size,\n sourceNodeWidth: sourceNodeAttrs.width,\n sourceNodeHeight: sourceNodeAttrs.height,\n targetNodeSize: 0,\n targetNodeWidth: 0,\n targetNodeHeight: 0,\n type: 'dashed',\n color: '#FF9800',\n weight: 2,\n label: undefined,\n dbData: {\n id: 'temp-creating-edge',\n graph_id: get(currentGraphIdAtom) || '',\n source_node_id: edgeCreationState.sourceNodeId,\n target_node_id: 'temp-cursor',\n edge_type: 'temp',\n filter_condition: null,\n ui_properties: null,\n data: null,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n }\n };\n return tempEdge;\n }\n }\n return null;\n }\n const graph = get(graphAtom);\n if (!graph.hasEdge(key)) {\n getEdgeCache(graph).delete(key);\n return null;\n }\n const sourceId = graph.source(key);\n const targetId = graph.target(key);\n const attributes = graph.getEdgeAttributes(key);\n\n // Re-route edges through collapsed groups: if a source/target is inside\n // a collapsed group, use the group node's position and dimensions instead\n const remap = get(collapsedEdgeRemapAtom);\n const effectiveSourceId = remap.get(sourceId) ?? sourceId;\n const effectiveTargetId = remap.get(targetId) ?? targetId;\n if (!graph.hasNode(effectiveSourceId) || !graph.hasNode(effectiveTargetId)) {\n getEdgeCache(graph).delete(key);\n return null;\n }\n const sourceAttributes = graph.getNodeAttributes(effectiveSourceId);\n const targetAttributes = graph.getNodeAttributes(effectiveTargetId);\n const sourcePosition = get(nodePositionAtomFamily(effectiveSourceId));\n const targetPosition = get(nodePositionAtomFamily(effectiveTargetId));\n if (sourceAttributes && targetAttributes) {\n const next = {\n ...attributes,\n key,\n sourceId: effectiveSourceId,\n targetId: effectiveTargetId,\n sourcePosition,\n targetPosition,\n sourceNodeSize: sourceAttributes.size,\n targetNodeSize: targetAttributes.size,\n sourceNodeWidth: sourceAttributes.width ?? sourceAttributes.size,\n sourceNodeHeight: sourceAttributes.height ?? sourceAttributes.size,\n targetNodeWidth: targetAttributes.width ?? targetAttributes.size,\n targetNodeHeight: targetAttributes.height ?? targetAttributes.size\n };\n\n // Structural equality: return cached object if all fields match\n const edgeCache = getEdgeCache(graph);\n const prev = edgeCache.get(key);\n if (prev && prev.sourcePosition === next.sourcePosition && prev.targetPosition === next.targetPosition && prev.sourceId === next.sourceId && prev.targetId === next.targetId && prev.type === next.type && prev.color === next.color && prev.weight === next.weight && prev.label === next.label && prev.sourceNodeSize === next.sourceNodeSize && prev.targetNodeSize === next.targetNodeSize && prev.sourceNodeWidth === next.sourceNodeWidth && prev.sourceNodeHeight === next.sourceNodeHeight && prev.targetNodeWidth === next.targetNodeWidth && prev.targetNodeHeight === next.targetNodeHeight) {\n return prev;\n }\n edgeCache.set(key, next);\n return next;\n }\n getEdgeCache(graph).delete(key);\n return null;\n}), (a, b) => a === b);","/**\n * Viewport state management\n *\n * Manages pan, zoom, and viewport rect for the canvas.\n */\n\nimport { atom } from 'jotai';\n// --- Core Viewport Atoms ---\n\n/**\n * Current zoom level (1 = 100%)\n */\nexport const zoomAtom = atom(1);\n\n/**\n * Current pan offset in pixels\n */\nexport const panAtom = atom({\n x: 0,\n y: 0\n});\n\n/**\n * Viewport DOM rect (set by the Viewport component)\n */\nexport const viewportRectAtom = atom(null);\n\n// --- Coordinate Conversion ---\n\n/**\n * Convert screen coordinates to world coordinates\n */\nexport const screenToWorldAtom = atom(get => {\n return (screenX, screenY) => {\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n const rect = get(viewportRectAtom);\n if (!rect) {\n return {\n x: screenX,\n y: screenY\n };\n }\n const relativeX = screenX - rect.left;\n const relativeY = screenY - rect.top;\n return {\n x: (relativeX - pan.x) / zoom,\n y: (relativeY - pan.y) / zoom\n };\n };\n});\n\n/**\n * Convert world coordinates to screen coordinates\n */\nexport const worldToScreenAtom = atom(get => {\n return (worldX, worldY) => {\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n const rect = get(viewportRectAtom);\n if (!rect) {\n return {\n x: worldX,\n y: worldY\n };\n }\n return {\n x: worldX * zoom + pan.x + rect.left,\n y: worldY * zoom + pan.y + rect.top\n };\n };\n});\n\n// --- Viewport Actions ---\n\n/**\n * Set zoom level with optional center point\n */\nexport const setZoomAtom = atom(null, (get, set, {\n zoom,\n centerX,\n centerY\n}) => {\n const currentZoom = get(zoomAtom);\n const pan = get(panAtom);\n const rect = get(viewportRectAtom);\n\n // Clamp zoom\n const newZoom = Math.max(0.1, Math.min(5, zoom));\n if (centerX !== undefined && centerY !== undefined && rect) {\n // Zoom towards the center point\n const relativeX = centerX - rect.left;\n const relativeY = centerY - rect.top;\n const worldX = (relativeX - pan.x) / currentZoom;\n const worldY = (relativeY - pan.y) / currentZoom;\n const newPanX = relativeX - worldX * newZoom;\n const newPanY = relativeY - worldY * newZoom;\n set(panAtom, {\n x: newPanX,\n y: newPanY\n });\n }\n set(zoomAtom, newZoom);\n});\n\n/**\n * Reset viewport to default state\n */\nexport const resetViewportAtom = atom(null, (_get, set) => {\n set(zoomAtom, 1);\n set(panAtom, {\n x: 0,\n y: 0\n });\n});\n\n// =============================================================================\n// Headless Layout Atoms\n// Fit-to-bounds and center-on-node without React hooks\n// =============================================================================\n\nimport { graphAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { uiNodesAtom } from './graph-derived';\nimport { selectedNodeIdsAtom } from './selection-store';\nimport { calculateBounds, FitToBoundsMode } from '../utils/layout';\n\n/**\n * Write atom: fit viewport to show all nodes or selection.\n * Pure Jotai — no React required.\n */\nexport const fitToBoundsAtom = atom(null, (get, set, {\n mode,\n padding = 20\n}) => {\n const normalizedMode = typeof mode === 'string' ? mode === 'graph' ? FitToBoundsMode.Graph : FitToBoundsMode.Selection : mode;\n const viewportSize = get(viewportRectAtom);\n if (!viewportSize || viewportSize.width <= 0 || viewportSize.height <= 0) return;\n\n // Force position counter read so bounds are fresh\n get(nodePositionUpdateCounterAtom);\n let bounds;\n if (normalizedMode === FitToBoundsMode.Graph) {\n const graph = get(graphAtom);\n const nodes = graph.nodes().map(node => {\n const attrs = graph.getNodeAttributes(node);\n return {\n x: attrs.x,\n y: attrs.y,\n width: attrs.width || 500,\n height: attrs.height || 500\n };\n });\n bounds = calculateBounds(nodes);\n } else {\n const selectedIds = get(selectedNodeIdsAtom);\n const allNodes = get(uiNodesAtom);\n const selectedNodes = allNodes.filter(n => selectedIds.has(n.id)).map(n => ({\n x: n.position.x,\n y: n.position.y,\n width: n.width ?? 500,\n height: n.height ?? 500\n }));\n bounds = calculateBounds(selectedNodes);\n }\n if (bounds.width <= 0 || bounds.height <= 0) return;\n const maxHPad = Math.max(0, viewportSize.width / 2 - 1);\n const maxVPad = Math.max(0, viewportSize.height / 2 - 1);\n const safePadding = Math.max(0, Math.min(padding, maxHPad, maxVPad));\n const effW = Math.max(1, viewportSize.width - 2 * safePadding);\n const effH = Math.max(1, viewportSize.height - 2 * safePadding);\n const scale = Math.min(effW / bounds.width, effH / bounds.height);\n if (scale <= 0 || !isFinite(scale)) return;\n set(zoomAtom, scale);\n const scaledW = bounds.width * scale;\n const scaledH = bounds.height * scale;\n const startX = safePadding + (effW - scaledW) / 2;\n const startY = safePadding + (effH - scaledH) / 2;\n set(panAtom, {\n x: startX - bounds.x * scale,\n y: startY - bounds.y * scale\n });\n});\n\n/**\n * Write atom: center viewport on a specific node.\n */\nexport const centerOnNodeAtom = atom(null, (get, set, nodeId) => {\n const nodes = get(uiNodesAtom);\n const node = nodes.find(n => n.id === nodeId);\n if (!node) return;\n const {\n x,\n y,\n width = 200,\n height = 100\n } = node;\n const zoom = get(zoomAtom);\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const rect = get(viewportRectAtom);\n const halfWidth = rect ? rect.width / 2 : 400;\n const halfHeight = rect ? rect.height / 2 : 300;\n set(panAtom, {\n x: halfWidth - centerX * zoom,\n y: halfHeight - centerY * zoom\n });\n});\n\n// =============================================================================\n// Zoom Transition State\n// When zooming in on a node past a threshold, trigger a fade transition\n// =============================================================================\n\n/** The zoom level at which we start the transition (zoom in) */\nexport const ZOOM_TRANSITION_THRESHOLD = 3.5;\n\n/** The zoom level at which we exit transition mode (zoom out) */\nexport const ZOOM_EXIT_THRESHOLD = 2.0;\n\n/** The node ID that's currently being zoomed into (center of viewport) */\nexport const zoomFocusNodeIdAtom = atom(null);\n\n/** Transition progress: 0 = normal view, 1 = fully transitioned to locked view */\nexport const zoomTransitionProgressAtom = atom(0);\n\n/** Computed: whether we're in a zoom transition */\nexport const isZoomTransitioningAtom = atom(get => {\n const progress = get(zoomTransitionProgressAtom);\n return progress > 0 && progress < 1;\n});\n\n// --- Zoom Animation Target ---\n\n/** Current zoom animation target, or null when idle */\nexport const zoomAnimationTargetAtom = atom(null);\n\n/**\n * Write atom: start an animated zoom-to-node transition.\n * Sets the animation target; the actual animation loop runs in useZoomTransition hook.\n */\nexport const animateZoomToNodeAtom = atom(null, (get, set, {\n nodeId,\n targetZoom,\n duration = 300\n}) => {\n const nodes = get(uiNodesAtom);\n const node = nodes.find(n => n.id === nodeId);\n if (!node) return;\n const {\n x,\n y,\n width = 200,\n height = 100\n } = node;\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n const rect = get(viewportRectAtom);\n const halfWidth = rect ? rect.width / 2 : 400;\n const halfHeight = rect ? rect.height / 2 : 300;\n const finalZoom = targetZoom ?? get(zoomAtom);\n const targetPan = {\n x: halfWidth - centerX * finalZoom,\n y: halfHeight - centerY * finalZoom\n };\n set(zoomFocusNodeIdAtom, nodeId);\n set(zoomAnimationTargetAtom, {\n targetZoom: finalZoom,\n targetPan,\n startZoom: get(zoomAtom),\n startPan: {\n ...get(panAtom)\n },\n duration,\n startTime: performance.now()\n });\n});\n\n/**\n * Write atom: start an animated fit-to-bounds transition.\n * Computes the target viewport, then animates to it.\n */\nexport const animateFitToBoundsAtom = atom(null, (get, set, {\n mode,\n padding = 20,\n duration = 300\n}) => {\n const viewportSize = get(viewportRectAtom);\n if (!viewportSize || viewportSize.width <= 0 || viewportSize.height <= 0) return;\n get(nodePositionUpdateCounterAtom);\n let bounds;\n if (mode === 'graph') {\n const graph = get(graphAtom);\n const nodes = graph.nodes().map(node => {\n const attrs = graph.getNodeAttributes(node);\n return {\n x: attrs.x,\n y: attrs.y,\n width: attrs.width || 500,\n height: attrs.height || 500\n };\n });\n bounds = calculateBounds(nodes);\n } else {\n const selectedIds = get(selectedNodeIdsAtom);\n const allNodes = get(uiNodesAtom);\n const selectedNodes = allNodes.filter(n => selectedIds.has(n.id)).map(n => ({\n x: n.position.x,\n y: n.position.y,\n width: n.width ?? 500,\n height: n.height ?? 500\n }));\n bounds = calculateBounds(selectedNodes);\n }\n if (bounds.width <= 0 || bounds.height <= 0) return;\n const safePadding = Math.max(0, Math.min(padding, viewportSize.width / 2 - 1, viewportSize.height / 2 - 1));\n const effW = Math.max(1, viewportSize.width - 2 * safePadding);\n const effH = Math.max(1, viewportSize.height - 2 * safePadding);\n const scale = Math.min(effW / bounds.width, effH / bounds.height);\n if (scale <= 0 || !isFinite(scale)) return;\n const scaledW = bounds.width * scale;\n const scaledH = bounds.height * scale;\n const startX = safePadding + (effW - scaledW) / 2;\n const startY = safePadding + (effH - scaledH) / 2;\n const targetPan = {\n x: startX - bounds.x * scale,\n y: startY - bounds.y * scale\n };\n set(zoomAnimationTargetAtom, {\n targetZoom: scale,\n targetPan,\n startZoom: get(zoomAtom),\n startPan: {\n ...get(panAtom)\n },\n duration,\n startTime: performance.now()\n });\n});","/**\n * Selection state management\n *\n * Manages node and edge selection state.\n */\n\nimport { atom } from 'jotai';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('selection');\n\n// --- Core Selection Atoms ---\n\n/**\n * Set of currently selected node IDs\n */\nexport const selectedNodeIdsAtom = atom(new Set());\n\n/**\n * Currently selected edge ID (only one edge can be selected at a time)\n */\nexport const selectedEdgeIdAtom = atom(null);\n\n// --- Selection Actions ---\n\n/**\n * Handle node pointer down with shift-click support for multi-select\n */\n\nexport const handleNodePointerDownSelectionAtom = atom(null, (get, set, {\n nodeId,\n isShiftPressed\n}) => {\n const currentSelection = get(selectedNodeIdsAtom);\n debug('handleNodePointerDownSelection: nodeId=%s, shift=%s, current=%o', nodeId, isShiftPressed, Array.from(currentSelection));\n\n // Clear edge selection when selecting a node\n set(selectedEdgeIdAtom, null);\n if (isShiftPressed) {\n const newSelection = new Set(currentSelection);\n if (newSelection.has(nodeId)) {\n newSelection.delete(nodeId);\n } else {\n newSelection.add(nodeId);\n }\n debug('Shift-click, setting selection to: %o', Array.from(newSelection));\n set(selectedNodeIdsAtom, newSelection);\n } else {\n // Only change selection if node is NOT already selected\n // This allows multi-node drag to work\n if (!currentSelection.has(nodeId)) {\n debug('Node not in selection, selecting: %s', nodeId);\n set(selectedNodeIdsAtom, new Set([nodeId]));\n } else {\n debug('Node already selected, preserving multi-select');\n }\n }\n});\n\n/**\n * Select a single node, clearing any previous selection\n */\nexport const selectSingleNodeAtom = atom(null, (get, set, nodeId) => {\n debug('selectSingleNode: %s', nodeId);\n set(selectedEdgeIdAtom, null);\n if (nodeId === null || nodeId === undefined) {\n debug('Clearing selection');\n set(selectedNodeIdsAtom, new Set());\n } else {\n const currentSelection = get(selectedNodeIdsAtom);\n if (currentSelection.has(nodeId) && currentSelection.size === 1) {\n return; // Already the only selection\n }\n set(selectedNodeIdsAtom, new Set([nodeId]));\n }\n});\n\n/**\n * Toggle a node in/out of selection\n */\nexport const toggleNodeInSelectionAtom = atom(null, (get, set, nodeId) => {\n const currentSelection = get(selectedNodeIdsAtom);\n const newSelection = new Set(currentSelection);\n if (newSelection.has(nodeId)) {\n newSelection.delete(nodeId);\n } else {\n newSelection.add(nodeId);\n }\n set(selectedNodeIdsAtom, newSelection);\n});\n\n/**\n * Clear all node selection\n */\nexport const clearSelectionAtom = atom(null, (_get, set) => {\n debug('clearSelection');\n set(selectedNodeIdsAtom, new Set());\n});\n\n/**\n * Add multiple nodes to selection\n */\nexport const addNodesToSelectionAtom = atom(null, (get, set, nodeIds) => {\n const currentSelection = get(selectedNodeIdsAtom);\n const newSelection = new Set(currentSelection);\n for (const nodeId of nodeIds) {\n newSelection.add(nodeId);\n }\n set(selectedNodeIdsAtom, newSelection);\n});\n\n/**\n * Remove multiple nodes from selection\n */\nexport const removeNodesFromSelectionAtom = atom(null, (get, set, nodeIds) => {\n const currentSelection = get(selectedNodeIdsAtom);\n const newSelection = new Set(currentSelection);\n for (const nodeId of nodeIds) {\n newSelection.delete(nodeId);\n }\n set(selectedNodeIdsAtom, newSelection);\n});\n\n/**\n * Select an edge (clears node selection)\n */\nexport const selectEdgeAtom = atom(null, (get, set, edgeId) => {\n set(selectedEdgeIdAtom, edgeId);\n if (edgeId !== null) {\n set(selectedNodeIdsAtom, new Set());\n }\n});\n\n/**\n * Clear edge selection\n */\nexport const clearEdgeSelectionAtom = atom(null, (_get, set) => {\n set(selectedEdgeIdAtom, null);\n});\n\n// --- Keyboard Focus ---\n\n/**\n * The node that has keyboard focus (distinct from selection).\n * Used for arrow key navigation between nodes.\n * null means no node has keyboard focus.\n */\nexport const focusedNodeIdAtom = atom(null);\n\n/**\n * Set keyboard focus to a node, or clear focus with null\n */\nexport const setFocusedNodeAtom = atom(null, (_get, set, nodeId) => {\n set(focusedNodeIdAtom, nodeId);\n});\n\n/**\n * Whether a node currently has keyboard focus\n */\nexport const hasFocusedNodeAtom = atom(get => get(focusedNodeIdAtom) !== null);\n\n// --- Derived Atoms ---\n\n/**\n * Count of selected nodes\n */\nexport const selectedNodesCountAtom = atom(get => get(selectedNodeIdsAtom).size);\n\n/**\n * Whether any node is selected\n */\nexport const hasSelectionAtom = atom(get => get(selectedNodeIdsAtom).size > 0);","/**\n * Layout utilities for canvas operations.\n *\n * Provides geometry calculations, bounds computation, and node overlap detection.\n */\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Rectangle with position and dimensions\n */\n\n/**\n * Node with position and dimensions (alias for geometry functions)\n */\n\n/**\n * Extended bounds with computed edges\n */\n\n/**\n * Mode for fitToBounds operation\n */\nexport let FitToBoundsMode = /*#__PURE__*/function (FitToBoundsMode) {\n /** Fit all nodes in the graph */\n FitToBoundsMode[\"Graph\"] = \"graph\";\n /** Fit only selected nodes */\n FitToBoundsMode[\"Selection\"] = \"selection\";\n return FitToBoundsMode;\n}({});\n\n// ============================================================\n// Bounds Calculation\n// ============================================================\n\n/**\n * Calculate the bounding rectangle that contains all nodes.\n *\n * @param nodes - Array of rectangles (nodes with x, y, width, height)\n * @returns Bounding rectangle containing all nodes\n *\n * @example\n * const bounds = calculateBounds([\n * { x: 0, y: 0, width: 100, height: 100 },\n * { x: 200, y: 150, width: 100, height: 100 },\n * ]);\n * // bounds = { x: 0, y: 0, width: 300, height: 250 }\n */\nexport const calculateBounds = nodes => {\n if (nodes.length === 0) {\n return {\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n }\n const minX = Math.min(...nodes.map(node => node.x));\n const minY = Math.min(...nodes.map(node => node.y));\n const maxX = Math.max(...nodes.map(node => node.x + node.width));\n const maxY = Math.max(...nodes.map(node => node.y + node.height));\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n};\n\n// ============================================================\n// Node Geometry\n// ============================================================\n\n/**\n * Get the center point of a node.\n */\nexport function getNodeCenter(node) {\n return {\n x: node.x + node.width / 2,\n y: node.y + node.height / 2\n };\n}\n\n/**\n * Set a node's position based on center coordinates.\n * Returns a new node object with updated position.\n */\nexport function setNodeCenter(node, centerX, centerY) {\n return {\n ...node,\n x: centerX - node.width / 2,\n y: centerY - node.height / 2\n };\n}\n\n/**\n * Check if two nodes overlap.\n */\nexport function checkNodesOverlap(node1, node2) {\n const center1 = getNodeCenter(node1);\n const center2 = getNodeCenter(node2);\n const dx = Math.abs(center1.x - center2.x);\n const dy = Math.abs(center1.y - center2.y);\n const minDistanceX = (node1.width + node2.width) / 2;\n const minDistanceY = (node1.height + node2.height) / 2;\n return dx < minDistanceX && dy < minDistanceY;\n}\n\n/**\n * Get the bounding box of a node.\n */\nexport function getNodeBounds(node) {\n return {\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n left: node.x,\n right: node.x + node.width,\n top: node.y,\n bottom: node.y + node.height\n };\n}\n\n/**\n * Check if two nodes are within a certain distance of each other.\n */\nexport function areNodesClose(node1, node2, threshold = 200) {\n const center1 = getNodeCenter(node1);\n const center2 = getNodeCenter(node2);\n const distance = Math.sqrt(Math.pow(center1.x - center2.x, 2) + Math.pow(center1.y - center2.y, 2));\n return distance <= threshold;\n}","/**\n * Group Store\n *\n * Manages node grouping/nesting: parent-child relationships,\n * collapse/expand state, and group membership operations.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { pushHistoryAtom } from './history-store';\n// =============================================================================\n// Collapse State\n// =============================================================================\n\n/**\n * Set of group node IDs that are currently collapsed.\n * Collapsed groups hide their children from uiNodesAtom.\n */\nexport const collapsedGroupsAtom = atom(new Set());\n\n/**\n * Toggle a group's collapsed state\n */\nexport const toggleGroupCollapseAtom = atom(null, (get, set, groupId) => {\n const current = get(collapsedGroupsAtom);\n const next = new Set(current);\n if (next.has(groupId)) {\n next.delete(groupId);\n } else {\n next.add(groupId);\n }\n set(collapsedGroupsAtom, next);\n});\n\n/**\n * Collapse a group\n */\nexport const collapseGroupAtom = atom(null, (get, set, groupId) => {\n const current = get(collapsedGroupsAtom);\n if (!current.has(groupId)) {\n const next = new Set(current);\n next.add(groupId);\n set(collapsedGroupsAtom, next);\n }\n});\n\n/**\n * Expand a group\n */\nexport const expandGroupAtom = atom(null, (get, set, groupId) => {\n const current = get(collapsedGroupsAtom);\n if (current.has(groupId)) {\n const next = new Set(current);\n next.delete(groupId);\n set(collapsedGroupsAtom, next);\n }\n});\n\n// =============================================================================\n// Parent/Child Queries\n// =============================================================================\n\n/**\n * Get children of a group node (reads from graph attributes)\n */\nexport const nodeChildrenAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return parentId => {\n const children = [];\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === parentId) {\n children.push(nodeId);\n }\n });\n return children;\n };\n});\n\n/**\n * Get the parent ID of a node\n */\nexport const nodeParentAtom = atom(get => {\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n return nodeId => {\n if (!graph.hasNode(nodeId)) return undefined;\n return graph.getNodeAttribute(nodeId, 'parentId');\n };\n});\n\n/**\n * Check if a node is a group (has any children)\n */\nexport const isGroupNodeAtom = atom(get => {\n const getChildren = get(nodeChildrenAtom);\n return nodeId => getChildren(nodeId).length > 0;\n});\n\n/**\n * Get count of children for a group node\n */\nexport const groupChildCountAtom = atom(get => {\n const getChildren = get(nodeChildrenAtom);\n return groupId => getChildren(groupId).length;\n});\n\n// =============================================================================\n// Group Membership Operations\n// =============================================================================\n\n/**\n * Set a node's parent (move into a group)\n */\nexport const setNodeParentAtom = atom(null, (get, set, {\n nodeId,\n parentId\n}) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) return;\n\n // Prevent circular grouping\n if (parentId) {\n if (parentId === nodeId) return;\n // Check if parentId is a descendant of nodeId\n let current = parentId;\n while (current) {\n if (current === nodeId) return; // Circular!\n if (!graph.hasNode(current)) break;\n current = graph.getNodeAttribute(current, 'parentId');\n }\n }\n graph.setNodeAttribute(nodeId, 'parentId', parentId);\n set(graphUpdateVersionAtom, v => v + 1);\n});\n\n/**\n * Move multiple nodes into a group\n */\nexport const moveNodesToGroupAtom = atom(null, (get, set, {\n nodeIds,\n groupId\n}) => {\n for (const nodeId of nodeIds) {\n set(setNodeParentAtom, {\n nodeId,\n parentId: groupId\n });\n }\n});\n\n/**\n * Remove a node from its group (set parentId to undefined)\n */\nexport const removeFromGroupAtom = atom(null, (get, set, nodeId) => {\n set(setNodeParentAtom, {\n nodeId,\n parentId: undefined\n });\n});\n\n/**\n * Create a group from selected nodes:\n * 1. Create a new \"group\" type node at the bounding box center\n * 2. Set all selected nodes as children\n * Returns the new group node ID (set via callback since node creation is async)\n */\nexport const groupSelectedNodesAtom = atom(null, (get, set, {\n nodeIds,\n groupNodeId\n}) => {\n set(pushHistoryAtom, `Group ${nodeIds.length} nodes`);\n const graph = get(graphAtom);\n\n // Compute bounding box of selected nodes\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const nodeId of nodeIds) {\n if (!graph.hasNode(nodeId)) continue;\n const attrs = graph.getNodeAttributes(nodeId);\n minX = Math.min(minX, attrs.x);\n minY = Math.min(minY, attrs.y);\n maxX = Math.max(maxX, attrs.x + (attrs.width || 200));\n maxY = Math.max(maxY, attrs.y + (attrs.height || 100));\n }\n\n // Position group node at bounding box origin with padding\n const padding = 20;\n if (graph.hasNode(groupNodeId)) {\n graph.setNodeAttribute(groupNodeId, 'x', minX - padding);\n graph.setNodeAttribute(groupNodeId, 'y', minY - padding - 30); // extra for header\n graph.setNodeAttribute(groupNodeId, 'width', maxX - minX + 2 * padding);\n graph.setNodeAttribute(groupNodeId, 'height', maxY - minY + 2 * padding + 30);\n }\n\n // Set parent for all nodes\n for (const nodeId of nodeIds) {\n if (nodeId !== groupNodeId && graph.hasNode(nodeId)) {\n graph.setNodeAttribute(nodeId, 'parentId', groupNodeId);\n }\n }\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n});\n\n/**\n * Ungroup: remove parent from all children of a group node\n */\nexport const ungroupNodesAtom = atom(null, (get, set, groupId) => {\n set(pushHistoryAtom, 'Ungroup nodes');\n const graph = get(graphAtom);\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === groupId) {\n graph.setNodeAttribute(nodeId, 'parentId', undefined);\n }\n });\n set(graphUpdateVersionAtom, v => v + 1);\n});\n\n// =============================================================================\n// Drag-to-Nest\n// =============================================================================\n\n/**\n * Nest dragged nodes into a target group node.\n * Sets parentId for each dragged node, then auto-resizes the target.\n */\nexport const nestNodesOnDropAtom = atom(null, (get, set, {\n nodeIds,\n targetId\n}) => {\n set(pushHistoryAtom, 'Nest nodes');\n for (const nodeId of nodeIds) {\n if (nodeId === targetId) continue;\n set(setNodeParentAtom, {\n nodeId,\n parentId: targetId\n });\n }\n set(autoResizeGroupAtom, targetId);\n});\n\n// =============================================================================\n// Descendants Helper\n// =============================================================================\n\n/**\n * Recursively collects all descendant node IDs of a group node.\n * Used by useNodeDrag to move all children when dragging a group.\n */\nexport function getNodeDescendants(graph, groupId) {\n const descendants = [];\n const stack = [groupId];\n while (stack.length > 0) {\n const current = stack.pop();\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === current) {\n descendants.push(nodeId);\n stack.push(nodeId);\n }\n });\n }\n return descendants;\n}\n\n// =============================================================================\n// Edge Re-routing for Collapsed Groups\n// =============================================================================\n\n/**\n * Derived: maps each collapsed node to its outermost collapsed ancestor.\n * Used by visibleEdgeKeysAtom and edgeFamilyAtom to re-route edges\n * from hidden children to their visible group node.\n *\n * Only nodes that are inside a collapsed group appear in this map.\n * The value is always a visible group node (the outermost collapsed ancestor).\n */\nexport const collapsedEdgeRemapAtom = atom(get => {\n const collapsed = get(collapsedGroupsAtom);\n if (collapsed.size === 0) return new Map();\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n const remap = new Map();\n for (const nodeId of graph.nodes()) {\n let current = nodeId;\n let outermost = null;\n while (true) {\n if (!graph.hasNode(current)) break;\n const parent = graph.getNodeAttribute(current, 'parentId');\n if (!parent) break;\n if (collapsed.has(parent)) outermost = parent;\n current = parent;\n }\n if (outermost) remap.set(nodeId, outermost);\n }\n return remap;\n});\n\n// =============================================================================\n// Group Auto-resize\n// =============================================================================\n\n/**\n * Write atom: recomputes a group node's position and dimensions\n * to contain all its direct children with padding.\n */\nexport const autoResizeGroupAtom = atom(null, (get, set, groupId) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(groupId)) return;\n const children = [];\n graph.forEachNode((nodeId, attrs) => {\n if (attrs.parentId === groupId) {\n children.push(nodeId);\n }\n });\n if (children.length === 0) return;\n const padding = 20;\n const headerHeight = 30;\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const childId of children) {\n const attrs = graph.getNodeAttributes(childId);\n minX = Math.min(minX, attrs.x);\n minY = Math.min(minY, attrs.y);\n maxX = Math.max(maxX, attrs.x + (attrs.width || 200));\n maxY = Math.max(maxY, attrs.y + (attrs.height || 100));\n }\n graph.setNodeAttribute(groupId, 'x', minX - padding);\n graph.setNodeAttribute(groupId, 'y', minY - padding - headerHeight);\n graph.setNodeAttribute(groupId, 'width', maxX - minX + 2 * padding);\n graph.setNodeAttribute(groupId, 'height', maxY - minY + 2 * padding + headerHeight);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n});\n\n// =============================================================================\n// Visibility Helper\n// =============================================================================\n\n/**\n * Check if a node should be hidden because it's inside a collapsed group.\n * Walks up the parent chain — if ANY ancestor is collapsed, the node is hidden.\n */\nexport function isNodeCollapsed(nodeId, getParentId, collapsed) {\n let current = nodeId;\n while (true) {\n const parentId = getParentId(current);\n if (!parentId) return false;\n if (collapsed.has(parentId)) return true;\n current = parentId;\n }\n}","/**\n * Canvas History Store — v2\n *\n * Delta-based undo/redo — replaces full-graph JSON.stringify snapshots.\n *\n * Performance improvement:\n * - Before: O(N) per operation (deep-clone all nodes + edges)\n * - After: O(1) for moves, O(K) for batch operations\n *\n * Each history entry stores forward + reverse deltas, not full snapshots.\n * Falls back to full snapshot for complex operations (graph import).\n *\n * Pure delta functions are in ./history-actions.ts\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { createDebug } from '../utils/debug';\n\n// Re-export types for backward compat\n\n// Re-export pure functions for backward compat\nexport { applyDelta, invertDelta, createSnapshot } from './history-actions';\nimport { applyDelta, invertDelta, createSnapshot } from './history-actions';\nconst debug = createDebug('history');\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/** Maximum number of history entries to keep */\nconst MAX_HISTORY_SIZE = 50;\n\n// =============================================================================\n// Atoms\n// =============================================================================\n\nexport const historyStateAtom = atom({\n past: [],\n future: [],\n isApplying: false\n});\nexport const canUndoAtom = atom(get => {\n const history = get(historyStateAtom);\n return history.past.length > 0 && !history.isApplying;\n});\nexport const canRedoAtom = atom(get => {\n const history = get(historyStateAtom);\n return history.future.length > 0 && !history.isApplying;\n});\nexport const undoCountAtom = atom(get => get(historyStateAtom).past.length);\nexport const redoCountAtom = atom(get => get(historyStateAtom).future.length);\n\n// =============================================================================\n// Push Delta (replaces pushHistoryAtom's full-snapshot approach)\n// =============================================================================\n\n/**\n * Push a delta to history. Call AFTER making the change.\n * The delta describes what changed; the reverse is auto-computed.\n */\nexport const pushDeltaAtom = atom(null, (get, set, delta) => {\n const history = get(historyStateAtom);\n if (history.isApplying) return;\n const {\n label,\n ...cleanDelta\n } = delta;\n const entry = {\n forward: cleanDelta,\n reverse: invertDelta(cleanDelta),\n timestamp: Date.now(),\n label\n };\n const newPast = [...history.past, entry];\n if (newPast.length > MAX_HISTORY_SIZE) newPast.shift();\n set(historyStateAtom, {\n past: newPast,\n future: [],\n // Clear redo stack\n isApplying: false\n });\n debug('Pushed delta: %s (past: %d)', label || delta.type, newPast.length);\n});\n\n/**\n * Legacy: Push a full-graph snapshot to history.\n * Use for complex operations where computing deltas is impractical.\n * Call BEFORE making changes.\n */\nexport const pushHistoryAtom = atom(null, (get, set, label) => {\n const history = get(historyStateAtom);\n if (history.isApplying) return;\n const graph = get(graphAtom);\n const snapshot = createSnapshot(graph, label);\n\n // Store as a full-snapshot delta\n const forward = {\n type: 'full-snapshot',\n nodes: snapshot.nodes,\n edges: snapshot.edges\n };\n const entry = {\n forward,\n reverse: forward,\n // For full snapshots, reverse IS the current state\n timestamp: Date.now(),\n label\n };\n const newPast = [...history.past, entry];\n if (newPast.length > MAX_HISTORY_SIZE) newPast.shift();\n set(historyStateAtom, {\n past: newPast,\n future: [],\n isApplying: false\n });\n debug('Pushed snapshot: %s (past: %d)', label || 'unnamed', newPast.length);\n});\n\n// =============================================================================\n// Undo / Redo\n// =============================================================================\n\nexport const undoAtom = atom(null, (get, set) => {\n const history = get(historyStateAtom);\n if (history.past.length === 0 || history.isApplying) return false;\n set(historyStateAtom, {\n ...history,\n isApplying: true\n });\n try {\n const graph = get(graphAtom);\n const newPast = [...history.past];\n const entry = newPast.pop();\n\n // For full-snapshot entries, save current state before restoring\n let forwardForRedo = entry.forward;\n if (entry.reverse.type === 'full-snapshot') {\n const currentSnapshot = createSnapshot(graph, 'current');\n forwardForRedo = {\n type: 'full-snapshot',\n nodes: currentSnapshot.nodes,\n edges: currentSnapshot.edges\n };\n }\n const structuralChange = applyDelta(graph, entry.reverse);\n if (structuralChange) {\n set(graphAtom, graph);\n set(graphUpdateVersionAtom, v => v + 1);\n }\n set(nodePositionUpdateCounterAtom, c => c + 1);\n const redoEntry = {\n forward: forwardForRedo,\n reverse: entry.reverse,\n timestamp: entry.timestamp,\n label: entry.label\n };\n set(historyStateAtom, {\n past: newPast,\n future: [redoEntry, ...history.future],\n isApplying: false\n });\n debug('Undo: %s (past: %d, future: %d)', entry.label, newPast.length, history.future.length + 1);\n return true;\n } catch (error) {\n debug.error('Undo failed: %O', error);\n set(historyStateAtom, {\n ...history,\n isApplying: false\n });\n return false;\n }\n});\nexport const redoAtom = atom(null, (get, set) => {\n const history = get(historyStateAtom);\n if (history.future.length === 0 || history.isApplying) return false;\n set(historyStateAtom, {\n ...history,\n isApplying: true\n });\n try {\n const graph = get(graphAtom);\n const newFuture = [...history.future];\n const entry = newFuture.shift();\n\n // For full-snapshot entries, save current state before restoring\n let reverseForUndo = entry.reverse;\n if (entry.forward.type === 'full-snapshot') {\n const currentSnapshot = createSnapshot(graph, 'current');\n reverseForUndo = {\n type: 'full-snapshot',\n nodes: currentSnapshot.nodes,\n edges: currentSnapshot.edges\n };\n }\n const structuralChange = applyDelta(graph, entry.forward);\n if (structuralChange) {\n set(graphAtom, graph);\n set(graphUpdateVersionAtom, v => v + 1);\n }\n set(nodePositionUpdateCounterAtom, c => c + 1);\n const undoEntry = {\n forward: entry.forward,\n reverse: reverseForUndo,\n timestamp: entry.timestamp,\n label: entry.label\n };\n set(historyStateAtom, {\n past: [...history.past, undoEntry],\n future: newFuture,\n isApplying: false\n });\n debug('Redo: %s (past: %d, future: %d)', entry.label, history.past.length + 1, newFuture.length);\n return true;\n } catch (error) {\n debug.error('Redo failed: %O', error);\n set(historyStateAtom, {\n ...history,\n isApplying: false\n });\n return false;\n }\n});\nexport const clearHistoryAtom = atom(null, (_get, set) => {\n set(historyStateAtom, {\n past: [],\n future: [],\n isApplying: false\n });\n debug('History cleared');\n});\nexport const historyLabelsAtom = atom(get => {\n const history = get(historyStateAtom);\n return {\n past: history.past.map(e => e.label || 'Unnamed'),\n future: history.future.map(e => e.label || 'Unnamed')\n };\n});","/**\n * History Actions — Pure delta functions\n *\n * applyDelta, invertDelta, createSnapshot extracted from history-store.ts.\n * These are pure functions operating on Graphology graphs and delta objects.\n */\n\n// =============================================================================\n// Delta Application\n// =============================================================================\n\n/**\n * Apply a delta to the graph in-place.\n * Returns true if graph structure changed (needs version bump).\n */\nexport function applyDelta(graph, delta) {\n switch (delta.type) {\n case 'move-node':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.setNodeAttribute(delta.nodeId, 'x', delta.to.x);\n graph.setNodeAttribute(delta.nodeId, 'y', delta.to.y);\n return false; // Position change, not structural\n }\n case 'resize-node':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.setNodeAttribute(delta.nodeId, 'width', delta.to.width);\n graph.setNodeAttribute(delta.nodeId, 'height', delta.to.height);\n return false;\n }\n case 'add-node':\n {\n if (graph.hasNode(delta.nodeId)) return false;\n graph.addNode(delta.nodeId, delta.attributes);\n return true;\n }\n case 'remove-node':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.dropNode(delta.nodeId); // Also removes connected edges\n return true;\n }\n case 'add-edge':\n {\n if (graph.hasEdge(delta.edgeId)) return false;\n if (!graph.hasNode(delta.source) || !graph.hasNode(delta.target)) return false;\n graph.addEdgeWithKey(delta.edgeId, delta.source, delta.target, delta.attributes);\n return true;\n }\n case 'remove-edge':\n {\n if (!graph.hasEdge(delta.edgeId)) return false;\n graph.dropEdge(delta.edgeId);\n return true;\n }\n case 'update-node-attr':\n {\n if (!graph.hasNode(delta.nodeId)) return false;\n graph.setNodeAttribute(delta.nodeId, delta.key, delta.to);\n return false;\n }\n case 'batch':\n {\n let structuralChange = false;\n for (const d of delta.deltas) {\n if (applyDelta(graph, d)) structuralChange = true;\n }\n return structuralChange;\n }\n case 'full-snapshot':\n {\n // Full graph restore — clear and rebuild\n graph.clear();\n for (const node of delta.nodes) {\n graph.addNode(node.id, node.attributes);\n }\n for (const edge of delta.edges) {\n if (graph.hasNode(edge.source) && graph.hasNode(edge.target)) {\n graph.addEdgeWithKey(edge.id, edge.source, edge.target, edge.attributes);\n }\n }\n return true;\n }\n }\n}\n\n/**\n * Invert a delta (for creating reverse operations).\n */\nexport function invertDelta(delta) {\n switch (delta.type) {\n case 'move-node':\n return {\n ...delta,\n from: delta.to,\n to: delta.from\n };\n case 'resize-node':\n return {\n ...delta,\n from: delta.to,\n to: delta.from\n };\n case 'add-node':\n return {\n type: 'remove-node',\n nodeId: delta.nodeId,\n attributes: delta.attributes,\n connectedEdges: []\n };\n case 'remove-node':\n {\n // Restore node AND its connected edges\n const batch = [{\n type: 'add-node',\n nodeId: delta.nodeId,\n attributes: delta.attributes\n }, ...delta.connectedEdges.map(e => ({\n type: 'add-edge',\n edgeId: e.id,\n source: e.source,\n target: e.target,\n attributes: e.attributes\n }))];\n return batch.length === 1 ? batch[0] : {\n type: 'batch',\n deltas: batch\n };\n }\n case 'add-edge':\n return {\n type: 'remove-edge',\n edgeId: delta.edgeId,\n source: delta.source,\n target: delta.target,\n attributes: delta.attributes\n };\n case 'remove-edge':\n return {\n type: 'add-edge',\n edgeId: delta.edgeId,\n source: delta.source,\n target: delta.target,\n attributes: delta.attributes\n };\n case 'update-node-attr':\n return {\n ...delta,\n from: delta.to,\n to: delta.from\n };\n case 'batch':\n return {\n type: 'batch',\n deltas: delta.deltas.map(invertDelta).reverse()\n };\n case 'full-snapshot':\n // Can't invert a full snapshot — caller handles this\n return delta;\n }\n}\n\n// =============================================================================\n// Helper: Create full snapshot (for complex operations)\n// =============================================================================\n\nexport function createSnapshot(graph, label) {\n const nodes = [];\n const edges = [];\n graph.forEachNode((nodeId, attributes) => {\n nodes.push({\n id: nodeId,\n attributes: {\n ...attributes\n }\n });\n });\n graph.forEachEdge((edgeId, attributes, source, target) => {\n edges.push({\n id: edgeId,\n source,\n target,\n attributes: {\n ...attributes\n }\n });\n });\n return {\n timestamp: Date.now(),\n label,\n nodes,\n edges\n };\n}","/**\n * Graph mutations\n *\n * Write atoms for graph CRUD operations, drag lifecycle,\n * edge animations, split/merge, and DB sync.\n */\n\nimport { atom } from 'jotai';\nimport Graph from 'graphology';\nimport { graphAtom, graphUpdateVersionAtom, graphOptions, currentGraphIdAtom, draggingNodeIdAtom, preDragNodeAttributesAtom } from './graph-store';\nimport { nodePositionAtomFamily, nodePositionUpdateCounterAtom, cleanupNodePositionAtom } from './graph-position';\nimport { highestZIndexAtom } from './graph-derived';\nimport { autoResizeGroupAtom } from './group-store';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('graph:mutations');\n\n// --- Node Action Atoms ---\n\n/**\n * Start dragging a node\n */\nexport const startNodeDragAtom = atom(null, (get, set, {\n nodeId\n}) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) return;\n const currentAttributes = graph.getNodeAttributes(nodeId);\n set(preDragNodeAttributesAtom, JSON.parse(JSON.stringify(currentAttributes)));\n const currentHighestZIndex = get(highestZIndexAtom);\n const newZIndex = currentHighestZIndex + 1;\n graph.setNodeAttribute(nodeId, 'zIndex', newZIndex);\n set(draggingNodeIdAtom, nodeId);\n});\n\n/**\n * End dragging a node\n */\nexport const endNodeDragAtom = atom(null, (get, set, _payload) => {\n const currentDraggingId = get(draggingNodeIdAtom);\n if (currentDraggingId) {\n debug('Node %s drag ended', currentDraggingId);\n\n // Auto-resize parent group if the dragged node belongs to one\n const graph = get(graphAtom);\n if (graph.hasNode(currentDraggingId)) {\n const parentId = graph.getNodeAttribute(currentDraggingId, 'parentId');\n if (parentId) {\n set(autoResizeGroupAtom, parentId);\n }\n }\n }\n set(draggingNodeIdAtom, null);\n set(preDragNodeAttributesAtom, null);\n});\n\n/**\n * Optimistically delete a node from local graph\n */\nexport const optimisticDeleteNodeAtom = atom(null, (get, set, {\n nodeId\n}) => {\n const graph = get(graphAtom);\n if (graph.hasNode(nodeId)) {\n graph.dropNode(nodeId);\n set(cleanupNodePositionAtom, nodeId);\n set(graphAtom, graph.copy());\n debug('Optimistically deleted node %s', nodeId);\n }\n});\n\n/**\n * Optimistically delete an edge from local graph\n */\nexport const optimisticDeleteEdgeAtom = atom(null, (get, set, {\n edgeKey\n}) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(edgeKey)) {\n graph.dropEdge(edgeKey);\n set(graphAtom, graph.copy());\n debug('Optimistically deleted edge %s', edgeKey);\n }\n});\n\n// --- Local Graph Mutations ---\n\n/**\n * Add a node directly to local graph\n */\nexport const addNodeToLocalGraphAtom = atom(null, (get, set, newNode) => {\n const graph = get(graphAtom);\n if (graph.hasNode(newNode.id)) {\n debug('Node %s already exists, skipping', newNode.id);\n return;\n }\n const uiProps = newNode.ui_properties || {};\n const attributes = {\n x: typeof uiProps.x === 'number' ? uiProps.x : Math.random() * 800,\n y: typeof uiProps.y === 'number' ? uiProps.y : Math.random() * 600,\n size: typeof uiProps.size === 'number' ? uiProps.size : 15,\n width: typeof uiProps.width === 'number' ? uiProps.width : 500,\n height: typeof uiProps.height === 'number' ? uiProps.height : 500,\n color: typeof uiProps.color === 'string' ? uiProps.color : '#ccc',\n label: newNode.label || newNode.node_type || newNode.id,\n zIndex: typeof uiProps.zIndex === 'number' ? uiProps.zIndex : 0,\n dbData: newNode\n };\n debug('Adding node %s to local graph at (%d, %d)', newNode.id, attributes.x, attributes.y);\n graph.addNode(newNode.id, attributes);\n // Position is derived from graph - just update graph and trigger re-render\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n});\n\n// Re-export all edge and advanced atoms for backward compat\nexport { swapEdgeAtomicAtom, departingEdgesAtom, EDGE_ANIMATION_DURATION, removeEdgeWithAnimationAtom, editingEdgeLabelAtom, updateEdgeLabelAtom } from './graph-mutations-edges';\nexport { dropTargetNodeIdAtom, splitNodeAtom, mergeNodesAtom } from './graph-mutations-advanced';\n\n// --- DB Sync Atom ---\n\n/**\n * Load/sync graph data from database\n * Merges DB data with local state, preserving positions during drag\n */\nexport const loadGraphFromDbAtom = atom(null, (get, set, fetchedNodes, fetchedEdges) => {\n debug('========== START SYNC ==========');\n debug('Fetched nodes: %d, edges: %d', fetchedNodes.length, fetchedEdges.length);\n const currentGraphId = get(currentGraphIdAtom);\n\n // Validate data belongs to current graph\n if (fetchedNodes.length > 0 && fetchedNodes[0].graph_id !== currentGraphId) {\n debug('Skipping sync - data belongs to different graph');\n return;\n }\n const existingGraph = get(graphAtom);\n const isDragging = get(draggingNodeIdAtom) !== null;\n if (isDragging) {\n debug('Skipping sync - drag in progress');\n return;\n }\n\n // Detect graph switch\n const existingNodeIds = new Set(existingGraph.nodes());\n const fetchedNodeIds = new Set(fetchedNodes.map(n => n.id));\n const hasAnyCommonNodes = Array.from(existingNodeIds).some(id => fetchedNodeIds.has(id));\n let graph;\n if (hasAnyCommonNodes && existingNodeIds.size > 0) {\n debug('Merging DB data into existing graph');\n graph = existingGraph.copy();\n } else {\n debug('Creating fresh graph (graph switch detected)');\n graph = new Graph(graphOptions);\n }\n const fetchedEdgeIds = new Set(fetchedEdges.map(e => e.id));\n\n // Remove deleted nodes\n if (hasAnyCommonNodes && existingNodeIds.size > 0) {\n graph.forEachNode(nodeId => {\n if (!fetchedNodeIds.has(nodeId)) {\n debug('Removing deleted node: %s', nodeId);\n graph.dropNode(nodeId);\n nodePositionAtomFamily.remove(nodeId);\n }\n });\n }\n\n // Merge/add nodes\n fetchedNodes.forEach(node => {\n const uiProps = node.ui_properties || {};\n const newX = typeof uiProps.x === 'number' ? uiProps.x : Math.random() * 800;\n const newY = typeof uiProps.y === 'number' ? uiProps.y : Math.random() * 600;\n if (graph.hasNode(node.id)) {\n const currentAttrs = graph.getNodeAttributes(node.id);\n const attributes = {\n x: newX,\n y: newY,\n size: typeof uiProps.size === 'number' ? uiProps.size : currentAttrs.size,\n width: typeof uiProps.width === 'number' ? uiProps.width : currentAttrs.width ?? 500,\n height: typeof uiProps.height === 'number' ? uiProps.height : currentAttrs.height ?? 500,\n color: typeof uiProps.color === 'string' ? uiProps.color : currentAttrs.color,\n label: node.label || node.node_type || node.id,\n zIndex: typeof uiProps.zIndex === 'number' ? uiProps.zIndex : currentAttrs.zIndex,\n dbData: node\n };\n graph.replaceNodeAttributes(node.id, attributes);\n } else {\n const attributes = {\n x: newX,\n y: newY,\n size: typeof uiProps.size === 'number' ? uiProps.size : 15,\n width: typeof uiProps.width === 'number' ? uiProps.width : 500,\n height: typeof uiProps.height === 'number' ? uiProps.height : 500,\n color: typeof uiProps.color === 'string' ? uiProps.color : '#ccc',\n label: node.label || node.node_type || node.id,\n zIndex: typeof uiProps.zIndex === 'number' ? uiProps.zIndex : 0,\n dbData: node\n };\n graph.addNode(node.id, attributes);\n }\n });\n\n // Remove deleted edges\n graph.forEachEdge(edgeId => {\n if (!fetchedEdgeIds.has(edgeId)) {\n debug('Removing deleted edge: %s', edgeId);\n graph.dropEdge(edgeId);\n }\n });\n\n // Merge/add edges\n fetchedEdges.forEach(edge => {\n if (graph.hasNode(edge.source_node_id) && graph.hasNode(edge.target_node_id)) {\n const uiProps = edge.ui_properties || {};\n const attributes = {\n type: typeof uiProps.style === 'string' ? uiProps.style : 'solid',\n color: typeof uiProps.color === 'string' ? uiProps.color : '#999',\n label: edge.edge_type ?? undefined,\n weight: typeof uiProps.weight === 'number' ? uiProps.weight : 1,\n dbData: edge\n };\n if (graph.hasEdge(edge.id)) {\n graph.replaceEdgeAttributes(edge.id, attributes);\n } else {\n try {\n graph.addEdgeWithKey(edge.id, edge.source_node_id, edge.target_node_id, attributes);\n } catch (e) {\n debug('Failed to add edge %s: %o', edge.id, e);\n }\n }\n }\n });\n set(graphAtom, graph);\n set(graphUpdateVersionAtom, v => v + 1);\n debug('========== SYNC COMPLETE ==========');\n debug('Final graph: %d nodes, %d edges', graph.order, graph.size);\n});","/**\n * Graph Mutations — Edge Operations\n *\n * Edge CRUD, atomic swap, animation, and label editing atoms.\n * Split from graph-mutations.ts for modularity.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { edgeFamilyAtom } from './graph-derived';\nimport { createDebug } from '../utils/debug';\nimport { prefersReducedMotionAtom } from './reduced-motion-store';\nconst debug = createDebug('graph:mutations:edges');\n\n// --- Edge CRUD ---\n\n/**\n * Add an edge directly to local graph\n */\nexport const addEdgeToLocalGraphAtom = atom(null, (get, set, newEdge) => {\n const graph = get(graphAtom);\n if (graph.hasNode(newEdge.source_node_id) && graph.hasNode(newEdge.target_node_id)) {\n const uiProps = newEdge.ui_properties || {};\n const attributes = {\n type: typeof uiProps.style === 'string' ? uiProps.style : 'solid',\n color: typeof uiProps.color === 'string' ? uiProps.color : '#999',\n label: newEdge.edge_type ?? undefined,\n weight: typeof uiProps.weight === 'number' ? uiProps.weight : 1,\n dbData: newEdge\n };\n if (!graph.hasEdge(newEdge.id)) {\n try {\n debug('Adding edge %s to local graph', newEdge.id);\n graph.addEdgeWithKey(newEdge.id, newEdge.source_node_id, newEdge.target_node_id, attributes);\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n } catch (e) {\n debug('Failed to add edge %s: %o', newEdge.id, e);\n }\n }\n }\n});\n\n/**\n * Remove an edge from local graph\n */\nexport const removeEdgeFromLocalGraphAtom = atom(null, (get, set, edgeId) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(edgeId)) {\n graph.dropEdge(edgeId);\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n }\n});\n\n/**\n * Atomic swap of temp edge with real edge (prevents render flash)\n */\nexport const swapEdgeAtomicAtom = atom(null, (get, set, {\n tempEdgeId,\n newEdge\n}) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(tempEdgeId)) {\n graph.dropEdge(tempEdgeId);\n }\n if (graph.hasNode(newEdge.source_node_id) && graph.hasNode(newEdge.target_node_id)) {\n const uiProps = newEdge.ui_properties || {};\n const attributes = {\n type: typeof uiProps.style === 'string' ? uiProps.style : 'solid',\n color: typeof uiProps.color === 'string' ? uiProps.color : '#999',\n label: newEdge.edge_type ?? undefined,\n weight: typeof uiProps.weight === 'number' ? uiProps.weight : 1,\n dbData: newEdge\n };\n if (!graph.hasEdge(newEdge.id)) {\n try {\n debug('Atomically swapping temp edge %s with real edge %s', tempEdgeId, newEdge.id);\n graph.addEdgeWithKey(newEdge.id, newEdge.source_node_id, newEdge.target_node_id, attributes);\n } catch (e) {\n debug('Failed to add edge %s: %o', newEdge.id, e);\n }\n }\n }\n set(graphAtom, graph.copy());\n set(graphUpdateVersionAtom, v => v + 1);\n});\n\n// --- Edge Animation State ---\n\n/**\n * Departing edges: snapshots of edges that have been removed from the graph\n * but are still being rendered with an exit animation.\n */\nexport const departingEdgesAtom = atom(new Map());\n\n/**\n * Edge animation duration in milliseconds\n */\nexport const EDGE_ANIMATION_DURATION = 300;\n\n/**\n * Remove an edge with a fade-out animation.\n * Snapshots the edge state, removes it from the graph, then cleans up\n * the departing entry after the animation duration.\n */\nexport const removeEdgeWithAnimationAtom = atom(null, (get, set, edgeKey) => {\n const edgeState = get(edgeFamilyAtom(edgeKey));\n if (edgeState) {\n const departing = new Map(get(departingEdgesAtom));\n departing.set(edgeKey, edgeState);\n set(departingEdgesAtom, departing);\n set(removeEdgeFromLocalGraphAtom, edgeKey);\n const duration = get(prefersReducedMotionAtom) ? 0 : EDGE_ANIMATION_DURATION;\n setTimeout(() => {\n const current = new Map(get(departingEdgesAtom));\n current.delete(edgeKey);\n set(departingEdgesAtom, current);\n }, duration);\n }\n});\n\n// --- Edge Label Editing ---\n\n/**\n * Edge key currently being edited (label inline editing).\n * null when no edge label is being edited.\n */\nexport const editingEdgeLabelAtom = atom(null);\n\n/**\n * Update an edge's label attribute\n */\nexport const updateEdgeLabelAtom = atom(null, (get, set, {\n edgeKey,\n label\n}) => {\n const graph = get(graphAtom);\n if (graph.hasEdge(edgeKey)) {\n graph.setEdgeAttribute(edgeKey, 'label', label || undefined);\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n }\n});","/**\n * Reduced Motion Store\n *\n * Tracks the user's `prefers-reduced-motion` OS setting.\n * When enabled, animations (inertia, layout transitions, edge fades)\n * should be skipped or set to instant.\n */\n\nimport { atom } from 'jotai';\n\n/**\n * Whether the user prefers reduced motion.\n * Initialized from `matchMedia` and updated on changes.\n *\n * Components/hooks should read this atom to skip animations:\n * - Pan/zoom inertia → stop immediately\n * - Layout transitions → apply positions instantly\n * - Edge fade animations → duration = 0\n */\nexport const prefersReducedMotionAtom = atom(typeof window !== 'undefined' && typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-reduced-motion: reduce)').matches : false);\n\n/**\n * Effect atom: subscribes to matchMedia changes.\n * Mount this once in CanvasProvider via useAtom.\n */\nexport const watchReducedMotionAtom = atom(null, (_get, set) => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return;\n const mql = window.matchMedia('(prefers-reduced-motion: reduce)');\n const handler = e => {\n set(prefersReducedMotionAtom, e.matches);\n };\n\n // Sync initial state\n set(prefersReducedMotionAtom, mql.matches);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n});","/**\n * Graph Mutations — Advanced Operations\n *\n * Split/merge node atoms and drop-target state.\n * Split from graph-mutations.ts for modularity.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom, currentGraphIdAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { pushHistoryAtom } from './history-store';\nimport { createDebug } from '../utils/debug';\nimport { addEdgeToLocalGraphAtom } from './graph-mutations-edges';\nimport { addNodeToLocalGraphAtom, optimisticDeleteNodeAtom } from './graph-mutations';\nconst debug = createDebug('graph:mutations:advanced');\n\n// --- Drop Target ---\n\n/**\n * ID of the node currently being hovered over as a drop target during drag.\n * Used by drag-to-nest: when a dragged node is released over a target,\n * the dragged node becomes a child of the target.\n */\nexport const dropTargetNodeIdAtom = atom(null);\n\n// --- Split Node ---\n\n/**\n * Split a node into two copies: original stays at position1, clone at position2.\n * All incident edges are duplicated so both copies have the same connections.\n */\nexport const splitNodeAtom = atom(null, (get, set, {\n nodeId,\n position1,\n position2\n}) => {\n const graph = get(graphAtom);\n if (!graph.hasNode(nodeId)) return;\n const attrs = graph.getNodeAttributes(nodeId);\n const graphId = get(currentGraphIdAtom) || attrs.dbData.graph_id;\n\n // Snapshot for undo (must be before any mutations)\n set(pushHistoryAtom, 'Split node');\n\n // Move original to position1 (before addNodeToLocalGraphAtom which calls graph.copy())\n graph.setNodeAttribute(nodeId, 'x', position1.x);\n graph.setNodeAttribute(nodeId, 'y', position1.y);\n\n // Collect edges before addNodeToLocalGraphAtom replaces graph ref\n const edges = [];\n graph.forEachEdge(nodeId, (_key, eAttrs, source, target) => {\n edges.push({\n source,\n target,\n attrs: eAttrs\n });\n });\n\n // Create clone\n const cloneId = `split-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n const cloneDbNode = {\n ...attrs.dbData,\n id: cloneId,\n graph_id: graphId,\n ui_properties: {\n ...(attrs.dbData.ui_properties || {}),\n x: position2.x,\n y: position2.y\n },\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n };\n set(addNodeToLocalGraphAtom, cloneDbNode);\n\n // Duplicate all edges to clone\n for (const edge of edges) {\n const newSource = edge.source === nodeId ? cloneId : edge.source;\n const newTarget = edge.target === nodeId ? cloneId : edge.target;\n set(addEdgeToLocalGraphAtom, {\n ...edge.attrs.dbData,\n id: `split-e-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n source_node_id: newSource,\n target_node_id: newTarget\n });\n }\n set(graphUpdateVersionAtom, v => v + 1);\n set(nodePositionUpdateCounterAtom, c => c + 1);\n debug('Split node %s → clone %s', nodeId, cloneId);\n});\n\n// --- Merge Nodes ---\n\n/**\n * Merge multiple nodes into one. The first node in the array survives.\n * Edges from doomed nodes are re-routed to the survivor.\n * Edges between merged nodes are discarded (would be self-loops).\n */\nexport const mergeNodesAtom = atom(null, (get, set, {\n nodeIds\n}) => {\n if (nodeIds.length < 2) return;\n const graph = get(graphAtom);\n const [survivorId, ...doomed] = nodeIds;\n if (!graph.hasNode(survivorId)) return;\n\n // Snapshot for undo (must be before any mutations)\n set(pushHistoryAtom, `Merge ${nodeIds.length} nodes`);\n const doomedSet = new Set(doomed);\n for (const doomedId of doomed) {\n if (!graph.hasNode(doomedId)) continue;\n\n // Collect edges before deletion (dropNode removes them)\n const edges = [];\n graph.forEachEdge(doomedId, (_key, eAttrs, source, target) => {\n edges.push({\n source,\n target,\n attrs: eAttrs\n });\n });\n for (const edge of edges) {\n const newSource = doomedSet.has(edge.source) ? survivorId : edge.source;\n const newTarget = doomedSet.has(edge.target) ? survivorId : edge.target;\n // Skip self-loops (edges between merged nodes)\n if (newSource === newTarget) continue;\n set(addEdgeToLocalGraphAtom, {\n ...edge.attrs.dbData,\n id: `merge-e-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n source_node_id: newSource,\n target_node_id: newTarget\n });\n }\n\n // Delete doomed node (auto-removes its original edges)\n set(optimisticDeleteNodeAtom, {\n nodeId: doomedId\n });\n }\n set(graphUpdateVersionAtom, v => v + 1);\n debug('Merged nodes %o → survivor %s', nodeIds, survivorId);\n});","/**\n * Sync state management\n *\n * Tracks sync status, pending mutations, and mutation queue for retry.\n */\n\nimport { atom } from 'jotai';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('sync');\n\n// --- Core State Atoms ---\n\n/**\n * Current sync status\n */\nexport const syncStatusAtom = atom('synced');\n\n/**\n * Number of pending (in-flight) mutations\n */\nexport const pendingMutationsCountAtom = atom(0);\n\n/**\n * Network online status\n */\nexport const isOnlineAtom = atom(typeof navigator !== 'undefined' ? navigator.onLine : true);\n\n/**\n * Last sync error message\n */\nexport const lastSyncErrorAtom = atom(null);\n\n/**\n * Last successful sync timestamp\n */\nexport const lastSyncTimeAtom = atom(Date.now());\n\n/**\n * Queued mutations for retry\n */\nexport const mutationQueueAtom = atom([]);\n\n// --- Derived State ---\n\n/**\n * Combined sync state for easy consumption\n */\nexport const syncStateAtom = atom(get => ({\n status: get(syncStatusAtom),\n pendingMutations: get(pendingMutationsCountAtom),\n lastError: get(lastSyncErrorAtom),\n lastSyncTime: get(lastSyncTimeAtom),\n isOnline: get(isOnlineAtom),\n queuedMutations: get(mutationQueueAtom).length\n}));\n\n// --- Mutation Tracking Actions ---\n\n/**\n * Start tracking a mutation (increment counter)\n */\nexport const startMutationAtom = atom(null, (get, set) => {\n const currentCount = get(pendingMutationsCountAtom);\n const newCount = currentCount + 1;\n set(pendingMutationsCountAtom, newCount);\n debug('Mutation started. Pending count: %d -> %d', currentCount, newCount);\n if (newCount > 0 && get(syncStatusAtom) !== 'syncing') {\n set(syncStatusAtom, 'syncing');\n debug('Status -> syncing');\n }\n});\n\n/**\n * Complete a mutation (decrement counter)\n */\nexport const completeMutationAtom = atom(null, (get, set, success = true) => {\n const currentCount = get(pendingMutationsCountAtom);\n const newCount = Math.max(0, currentCount - 1);\n set(pendingMutationsCountAtom, newCount);\n debug('Mutation completed (success: %s). Pending count: %d -> %d', success, currentCount, newCount);\n if (success) {\n set(lastSyncTimeAtom, Date.now());\n if (newCount === 0) {\n set(lastSyncErrorAtom, null);\n }\n }\n\n // Update status if no more pending mutations\n if (newCount === 0) {\n const isOnline = get(isOnlineAtom);\n const hasError = get(lastSyncErrorAtom) !== null;\n if (hasError) {\n set(syncStatusAtom, 'error');\n debug('Status -> error');\n } else if (!isOnline) {\n set(syncStatusAtom, 'offline');\n debug('Status -> offline');\n } else {\n set(syncStatusAtom, 'synced');\n debug('Status -> synced');\n }\n }\n});\n\n/**\n * Track a mutation error\n */\nexport const trackMutationErrorAtom = atom(null, (_get, set, error) => {\n set(lastSyncErrorAtom, error);\n debug('Mutation failed: %s', error);\n});\n\n// --- Network Status ---\n\n/**\n * Set online/offline status\n */\nexport const setOnlineStatusAtom = atom(null, (get, set, isOnline) => {\n set(isOnlineAtom, isOnline);\n const pendingCount = get(pendingMutationsCountAtom);\n const hasError = get(lastSyncErrorAtom) !== null;\n const queueLength = get(mutationQueueAtom).length;\n if (pendingCount === 0) {\n if (hasError || queueLength > 0) {\n set(syncStatusAtom, 'error');\n } else {\n set(syncStatusAtom, isOnline ? 'synced' : 'offline');\n }\n }\n});\n\n// --- Mutation Queue ---\n\n/**\n * Add a mutation to the retry queue\n */\nexport const queueMutationAtom = atom(null, (get, set, mutation) => {\n const queue = get(mutationQueueAtom);\n const newMutation = {\n ...mutation,\n id: crypto.randomUUID(),\n timestamp: Date.now(),\n retryCount: 0,\n maxRetries: mutation.maxRetries ?? 3\n };\n const newQueue = [...queue, newMutation];\n set(mutationQueueAtom, newQueue);\n debug('Queued mutation: %s. Queue size: %d', mutation.type, newQueue.length);\n if (get(pendingMutationsCountAtom) === 0) {\n set(syncStatusAtom, 'error');\n }\n return newMutation.id;\n});\n\n/**\n * Remove a mutation from the queue\n */\nexport const dequeueMutationAtom = atom(null, (get, set, mutationId) => {\n const queue = get(mutationQueueAtom);\n const newQueue = queue.filter(m => m.id !== mutationId);\n set(mutationQueueAtom, newQueue);\n debug('Dequeued mutation: %s. Queue size: %d', mutationId, newQueue.length);\n if (newQueue.length === 0 && get(pendingMutationsCountAtom) === 0 && get(lastSyncErrorAtom) === null) {\n set(syncStatusAtom, get(isOnlineAtom) ? 'synced' : 'offline');\n }\n});\n\n/**\n * Increment retry count for a mutation\n */\nexport const incrementRetryCountAtom = atom(null, (get, set, mutationId) => {\n const queue = get(mutationQueueAtom);\n const newQueue = queue.map(m => m.id === mutationId ? {\n ...m,\n retryCount: m.retryCount + 1\n } : m);\n set(mutationQueueAtom, newQueue);\n});\n\n/**\n * Get the next mutation to retry\n */\nexport const getNextQueuedMutationAtom = atom(get => {\n const queue = get(mutationQueueAtom);\n return queue.find(m => m.retryCount < m.maxRetries) ?? null;\n});\n\n/**\n * Clear all queued mutations\n */\nexport const clearMutationQueueAtom = atom(null, (get, set) => {\n set(mutationQueueAtom, []);\n debug('Cleared mutation queue');\n if (get(pendingMutationsCountAtom) === 0 && get(lastSyncErrorAtom) === null) {\n set(syncStatusAtom, get(isOnlineAtom) ? 'synced' : 'offline');\n }\n});","/**\n * Interaction Store\n *\n * Manages canvas interaction modes (picking nodes, points, etc.)\n * and visual feedback during interactions.\n */\n\nimport { atom } from 'jotai';\n\n// =============================================================================\n// Input Mode Types\n// =============================================================================\n\n/**\n * A selectable option for 'select' type inputs.\n */\n\n/**\n * Input mode - controls how canvas interactions are routed.\n * When not 'normal', canvas clicks are intercepted for special handling.\n */\n\n// =============================================================================\n// Feedback Types\n// =============================================================================\n\n/**\n * Visual feedback state for the canvas overlay.\n */\n\n// =============================================================================\n// Input Mode Atoms\n// =============================================================================\n\n/**\n * Current input mode - controls how canvas interactions are routed.\n */\nexport const inputModeAtom = atom({\n type: 'normal'\n});\n\n/**\n * Keyboard interaction mode for arrow/space/enter behavior.\n */\nexport const keyboardInteractionModeAtom = atom('navigate');\n\n/**\n * Visual feedback state for overlays during interaction.\n */\nexport const interactionFeedbackAtom = atom(null);\n\n/**\n * Resolver for pending input values (used by command systems).\n */\nexport const pendingInputResolverAtom = atom(null);\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Reset input mode to normal.\n */\nexport const resetInputModeAtom = atom(null, (_get, set) => {\n set(inputModeAtom, {\n type: 'normal'\n });\n set(interactionFeedbackAtom, null);\n set(pendingInputResolverAtom, null);\n});\n\n/**\n * Reset keyboard interaction mode back to navigation.\n */\nexport const resetKeyboardInteractionModeAtom = atom(null, (_get, set) => {\n set(keyboardInteractionModeAtom, 'navigate');\n});\n\n/**\n * Set keyboard interaction mode explicitly.\n */\nexport const setKeyboardInteractionModeAtom = atom(null, (_get, set, mode) => {\n set(keyboardInteractionModeAtom, mode);\n});\n\n/**\n * Set input mode for picking a node.\n */\nexport const startPickNodeAtom = atom(null, (_get, set, options) => {\n set(inputModeAtom, {\n type: 'pickNode',\n ...options\n });\n});\n\n/**\n * Set input mode for picking multiple nodes.\n */\nexport const startPickNodesAtom = atom(null, (_get, set, options) => {\n set(inputModeAtom, {\n type: 'pickNodes',\n ...options\n });\n});\n\n/**\n * Set input mode for picking a point on the canvas.\n */\nexport const startPickPointAtom = atom(null, (_get, set, options) => {\n set(inputModeAtom, {\n type: 'pickPoint',\n ...options\n });\n});\n\n/**\n * Provide input value (called when user picks a node/point).\n */\nexport const provideInputAtom = atom(null, (get, set, value) => {\n set(pendingInputResolverAtom, value);\n // Input mode is typically reset by the consumer after receiving the value\n});\n\n/**\n * Update feedback during interaction.\n */\nexport const updateInteractionFeedbackAtom = atom(null, (get, set, feedback) => {\n const current = get(interactionFeedbackAtom);\n set(interactionFeedbackAtom, {\n ...current,\n ...feedback\n });\n});\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether canvas is in a picking mode (not normal).\n */\nexport const isPickingModeAtom = atom(get => {\n const mode = get(inputModeAtom);\n return mode.type !== 'normal';\n});\n\n/**\n * Whether currently picking a node.\n */\nexport const isPickNodeModeAtom = atom(get => {\n const mode = get(inputModeAtom);\n return mode.type === 'pickNode' || mode.type === 'pickNodes';\n});","/**\n * Locked Node Store\n *\n * Manages \"locking\" onto a node for detailed viewing/editing.\n * Triple-click on a node locks it, showing additional panels/pages.\n */\n\nimport { atom } from 'jotai';\nimport { uiNodesAtom } from './graph-derived';\n\n// =============================================================================\n// Locked Node Atoms\n// =============================================================================\n\n/**\n * Currently locked node ID (null = no node locked).\n */\nexport const lockedNodeIdAtom = atom(null);\n\n/**\n * Full node data for the locked node.\n */\nexport const lockedNodeDataAtom = atom(get => {\n const id = get(lockedNodeIdAtom);\n if (!id) return null;\n const nodes = get(uiNodesAtom);\n return nodes.find(n => n.id === id) || null;\n});\n\n/**\n * Current page index for locked node (0-based).\n */\nexport const lockedNodePageIndexAtom = atom(0);\n\n/**\n * Total number of pages available (set by app).\n */\nexport const lockedNodePageCountAtom = atom(1);\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Lock onto a node (typically triggered by triple-click).\n * @param nodeId - The node ID to lock onto\n * @param nodeData - Optional node data (for app compatibility, not used internally)\n */\nexport const lockNodeAtom = atom(null, (_get, set, payload) => {\n set(lockedNodeIdAtom, payload.nodeId);\n set(lockedNodePageIndexAtom, 0); // Reset to first page\n});\n\n/**\n * Unlock the currently locked node.\n */\nexport const unlockNodeAtom = atom(null, (_get, set) => {\n set(lockedNodeIdAtom, null);\n});\n\n/**\n * Navigate to next page in locked node view.\n */\nexport const nextLockedPageAtom = atom(null, (get, set) => {\n const current = get(lockedNodePageIndexAtom);\n const pageCount = get(lockedNodePageCountAtom);\n set(lockedNodePageIndexAtom, (current + 1) % pageCount);\n});\n\n/**\n * Navigate to previous page in locked node view.\n */\nexport const prevLockedPageAtom = atom(null, (get, set) => {\n const current = get(lockedNodePageIndexAtom);\n const pageCount = get(lockedNodePageCountAtom);\n set(lockedNodePageIndexAtom, (current - 1 + pageCount) % pageCount);\n});\n\n/**\n * Go to specific page by index.\n */\nexport const goToLockedPageAtom = atom(null, (get, set, index) => {\n const pageCount = get(lockedNodePageCountAtom);\n if (index >= 0 && index < pageCount) {\n set(lockedNodePageIndexAtom, index);\n }\n});\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether a node is currently locked.\n */\nexport const hasLockedNodeAtom = atom(get => get(lockedNodeIdAtom) !== null);","import { c as _c } from \"react/compiler-runtime\";\n/**\n * Node Type Registry\n *\n * Maps node types to their UI components.\n * Apps register their custom node components here.\n */\n\nimport React from 'react';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Props passed to node type components.\n */\n\n/**\n * A component that renders a specific node type.\n */\nimport { jsxs as _jsxs, jsx as _jsx } from \"react/jsx-runtime\";\n// =============================================================================\n// Registry\n// =============================================================================\n\nconst nodeTypeRegistry = new Map();\n\n/**\n * Register a component for a node type.\n *\n * @example\n * ```tsx\n * registerNodeType('widget', WidgetNodeComponent);\n * registerNodeType('data-source', DataSourceNodeComponent);\n * ```\n */\nexport function registerNodeType(nodeType, component) {\n nodeTypeRegistry.set(nodeType, component);\n}\n\n/**\n * Register multiple node types at once.\n *\n * @example\n * ```tsx\n * registerNodeTypes({\n * 'widget': WidgetNodeComponent,\n * 'data-source': DataSourceNodeComponent,\n * 'puck': PuckNodeComponent,\n * });\n * ```\n */\nexport function registerNodeTypes(types) {\n for (const [nodeType, component] of Object.entries(types)) {\n nodeTypeRegistry.set(nodeType, component);\n }\n}\n\n/**\n * Unregister a node type component.\n * Returns true if the type was registered and removed.\n */\nexport function unregisterNodeType(nodeType) {\n return nodeTypeRegistry.delete(nodeType);\n}\n\n/**\n * Get the component for a node type.\n * Returns undefined if no component is registered.\n */\nexport function getNodeTypeComponent(nodeType) {\n if (!nodeType) return undefined;\n return nodeTypeRegistry.get(nodeType);\n}\n\n/**\n * Check if a node type has a registered component.\n */\nexport function hasNodeTypeComponent(nodeType) {\n if (!nodeType) return false;\n return nodeTypeRegistry.has(nodeType);\n}\n\n/**\n * Get all registered node types.\n */\nexport function getRegisteredNodeTypes() {\n return Array.from(nodeTypeRegistry.keys());\n}\n\n/**\n * Clear all registered node types.\n * Useful for testing.\n */\nexport function clearNodeTypeRegistry() {\n nodeTypeRegistry.clear();\n}\n\n// =============================================================================\n// Default Fallback Component\n// =============================================================================\n\n/**\n * Default fallback component for unknown node types.\n */\nexport const FallbackNodeTypeComponent = t0 => {\n const $ = _c(11);\n const {\n nodeData\n } = t0;\n let t1;\n if ($[0] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t1 = {\n padding: \"12px\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n color: \"#666\",\n fontSize: \"12px\"\n };\n $[0] = t1;\n } else {\n t1 = $[0];\n }\n const t2 = nodeData.dbData.node_type || \"none\";\n let t3;\n if ($[1] !== t2) {\n t3 = /*#__PURE__*/_jsxs(\"div\", {\n children: [\"Unknown type: \", t2]\n });\n $[1] = t2;\n $[2] = t3;\n } else {\n t3 = $[2];\n }\n let t4;\n if ($[3] === Symbol.for(\"react.memo_cache_sentinel\")) {\n t4 = {\n marginTop: \"4px\",\n opacity: 0.7\n };\n $[3] = t4;\n } else {\n t4 = $[3];\n }\n let t5;\n if ($[4] !== nodeData.id) {\n t5 = nodeData.id.substring(0, 8);\n $[4] = nodeData.id;\n $[5] = t5;\n } else {\n t5 = $[5];\n }\n let t6;\n if ($[6] !== t5) {\n t6 = /*#__PURE__*/_jsx(\"div\", {\n style: t4,\n children: t5\n });\n $[6] = t5;\n $[7] = t6;\n } else {\n t6 = $[7];\n }\n let t7;\n if ($[8] !== t3 || $[9] !== t6) {\n t7 = /*#__PURE__*/_jsxs(\"div\", {\n style: t1,\n children: [t3, t6]\n });\n $[8] = t3;\n $[9] = t6;\n $[10] = t7;\n } else {\n t7 = $[10];\n }\n return t7;\n};","/**\n * Toast Store\n *\n * Lightweight toast notification system for canvas operations.\n * Shows brief, non-interactive messages (e.g., \"Undo: Split node\").\n */\n\nimport { atom } from 'jotai';\n/** Current visible toast, or null */\nexport const canvasToastAtom = atom(null);\n\n/** Show a toast message that auto-clears after 2 seconds */\nexport const showToastAtom = atom(null, (_get, set, message) => {\n const id = `toast-${Date.now()}`;\n set(canvasToastAtom, {\n id,\n message,\n timestamp: Date.now()\n });\n setTimeout(() => {\n set(canvasToastAtom, current => current?.id === id ? null : current);\n }, 2000);\n});","/**\n * Snap-to-Grid Store\n *\n * Optional grid snapping for node positioning.\n * When enabled, nodes snap to the nearest grid point during drag.\n */\n\nimport { atom } from 'jotai';\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/** Whether grid snapping is enabled */\nexport const snapEnabledAtom = atom(false);\n\n/** Grid size in pixels (default: 20) */\nexport const snapGridSizeAtom = atom(20);\n\n/** Whether snap is temporarily disabled (e.g. holding modifier key) */\nexport const snapTemporaryDisableAtom = atom(false);\n\n// =============================================================================\n// Derived\n// =============================================================================\n\n/** Whether snapping is currently active (enabled AND not temporarily disabled) */\nexport const isSnappingActiveAtom = atom(get => {\n return get(snapEnabledAtom) && !get(snapTemporaryDisableAtom);\n});\n\n// =============================================================================\n// Snap Functions (pure — no atoms, usable anywhere)\n// =============================================================================\n\n/**\n * Snap a position to the nearest grid point.\n */\nexport function snapToGrid(pos, gridSize) {\n return {\n x: Math.round(pos.x / gridSize) * gridSize,\n y: Math.round(pos.y / gridSize) * gridSize\n };\n}\n\n/**\n * Snap a position if snapping is active, otherwise return as-is.\n */\nexport function conditionalSnap(pos, gridSize, isActive) {\n return isActive ? snapToGrid(pos, gridSize) : pos;\n}\n\n/**\n * Get snap guide lines for the current position.\n * Returns the X and Y grid lines closest to the position.\n */\nexport function getSnapGuides(pos, gridSize, tolerance = 5) {\n const snappedX = Math.round(pos.x / gridSize) * gridSize;\n const snappedY = Math.round(pos.y / gridSize) * gridSize;\n return {\n x: Math.abs(pos.x - snappedX) < tolerance ? snappedX : null,\n y: Math.abs(pos.y - snappedY) < tolerance ? snappedY : null\n };\n}\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/** Toggle snap on/off */\nexport const toggleSnapAtom = atom(null, (get, set) => {\n set(snapEnabledAtom, !get(snapEnabledAtom));\n});\n\n/** Set grid size */\nexport const setGridSizeAtom = atom(null, (_get, set, size) => {\n set(snapGridSizeAtom, Math.max(5, Math.min(200, size)));\n});\n\n// =============================================================================\n// Alignment Guides (node-to-node snapping)\n// =============================================================================\n\n/** Whether node alignment guides are enabled */\nexport const snapAlignmentEnabledAtom = atom(true);\n\n/** Toggle alignment guides on/off */\nexport const toggleAlignmentGuidesAtom = atom(null, (get, set) => {\n set(snapAlignmentEnabledAtom, !get(snapAlignmentEnabledAtom));\n});\n\n/** Active alignment guides during drag — written by useNodeDrag, read by AlignmentGuides */\n\nexport const alignmentGuidesAtom = atom({\n verticalGuides: [],\n horizontalGuides: []\n});\n\n/** Clear alignment guides (call on drag end) */\nexport const clearAlignmentGuidesAtom = atom(null, (_get, set) => {\n set(alignmentGuidesAtom, {\n verticalGuides: [],\n horizontalGuides: []\n });\n});\n\n// =============================================================================\n// Alignment Functions (pure — no atoms, usable anywhere)\n// =============================================================================\n\n/**\n * Find alignment guides for a dragged node against a set of other nodes.\n * Checks center-X, left-edge, right-edge, center-Y, top-edge, bottom-edge.\n *\n * Returns arrays of X and Y world coordinates where guides should be drawn.\n *\n * @param dragged - The node being dragged (current position)\n * @param others - Other nodes to check alignment against\n * @param tolerance - Max distance in px to trigger a guide (default: 5)\n */\nexport function findAlignmentGuides(dragged, others, tolerance = 5) {\n const verticals = new Set();\n const horizontals = new Set();\n const dragCX = dragged.x + dragged.width / 2;\n const dragCY = dragged.y + dragged.height / 2;\n const dragRight = dragged.x + dragged.width;\n const dragBottom = dragged.y + dragged.height;\n for (const other of others) {\n const otherCX = other.x + other.width / 2;\n const otherCY = other.y + other.height / 2;\n const otherRight = other.x + other.width;\n const otherBottom = other.y + other.height;\n\n // Vertical guides (X alignment)\n if (Math.abs(dragCX - otherCX) < tolerance) verticals.add(otherCX); // center-center\n if (Math.abs(dragged.x - other.x) < tolerance) verticals.add(other.x); // left-left\n if (Math.abs(dragRight - otherRight) < tolerance) verticals.add(otherRight); // right-right\n if (Math.abs(dragged.x - otherRight) < tolerance) verticals.add(otherRight); // left-right\n if (Math.abs(dragRight - other.x) < tolerance) verticals.add(other.x); // right-left\n if (Math.abs(dragCX - other.x) < tolerance) verticals.add(other.x); // center-left\n if (Math.abs(dragCX - otherRight) < tolerance) verticals.add(otherRight); // center-right\n\n // Horizontal guides (Y alignment)\n if (Math.abs(dragCY - otherCY) < tolerance) horizontals.add(otherCY); // center-center\n if (Math.abs(dragged.y - other.y) < tolerance) horizontals.add(other.y); // top-top\n if (Math.abs(dragBottom - otherBottom) < tolerance) horizontals.add(otherBottom); // bottom-bottom\n if (Math.abs(dragged.y - otherBottom) < tolerance) horizontals.add(otherBottom); // top-bottom\n if (Math.abs(dragBottom - other.y) < tolerance) horizontals.add(other.y); // bottom-top\n if (Math.abs(dragCY - other.y) < tolerance) horizontals.add(other.y); // center-top\n if (Math.abs(dragCY - otherBottom) < tolerance) horizontals.add(otherBottom); // center-bottom\n }\n return {\n verticalGuides: Array.from(verticals),\n horizontalGuides: Array.from(horizontals)\n };\n}","/**\n * Canvas Event Types\n *\n * Type definitions for configurable canvas events.\n *\n * Extracted from settings-types.ts in v1.9.0.\n *\n * @since 1.9.0\n */\n\n// =============================================================================\n// Canvas Events\n// =============================================================================\n\n/**\n * All configurable canvas events that can trigger actions.\n */\nexport let CanvasEventType = /*#__PURE__*/function (CanvasEventType) {\n // Node events\n CanvasEventType[\"NodeClick\"] = \"node:click\";\n CanvasEventType[\"NodeDoubleClick\"] = \"node:double-click\";\n CanvasEventType[\"NodeTripleClick\"] = \"node:triple-click\";\n CanvasEventType[\"NodeRightClick\"] = \"node:right-click\";\n CanvasEventType[\"NodeLongPress\"] = \"node:long-press\";\n // Edge events\n CanvasEventType[\"EdgeClick\"] = \"edge:click\";\n CanvasEventType[\"EdgeDoubleClick\"] = \"edge:double-click\";\n CanvasEventType[\"EdgeRightClick\"] = \"edge:right-click\";\n // Background events\n CanvasEventType[\"BackgroundClick\"] = \"background:click\";\n CanvasEventType[\"BackgroundDoubleClick\"] = \"background:double-click\";\n CanvasEventType[\"BackgroundRightClick\"] = \"background:right-click\";\n CanvasEventType[\"BackgroundLongPress\"] = \"background:long-press\";\n return CanvasEventType;\n}({});\n\n/**\n * Metadata for each event type (for UI display).\n */\n\n/**\n * Registry of all event type metadata.\n */\nexport const EVENT_TYPE_INFO = {\n [CanvasEventType.NodeClick]: {\n type: CanvasEventType.NodeClick,\n label: 'Click Node',\n description: 'Triggered when clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeDoubleClick]: {\n type: CanvasEventType.NodeDoubleClick,\n label: 'Double-click Node',\n description: 'Triggered when double-clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeTripleClick]: {\n type: CanvasEventType.NodeTripleClick,\n label: 'Triple-click Node',\n description: 'Triggered when triple-clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeRightClick]: {\n type: CanvasEventType.NodeRightClick,\n label: 'Right-click Node',\n description: 'Triggered when right-clicking on a node',\n category: 'node'\n },\n [CanvasEventType.NodeLongPress]: {\n type: CanvasEventType.NodeLongPress,\n label: 'Long-press Node',\n description: 'Triggered when long-pressing on a node (mobile/touch)',\n category: 'node'\n },\n [CanvasEventType.EdgeClick]: {\n type: CanvasEventType.EdgeClick,\n label: 'Click Edge',\n description: 'Triggered when clicking on an edge',\n category: 'edge'\n },\n [CanvasEventType.EdgeDoubleClick]: {\n type: CanvasEventType.EdgeDoubleClick,\n label: 'Double-click Edge',\n description: 'Triggered when double-clicking on an edge',\n category: 'edge'\n },\n [CanvasEventType.EdgeRightClick]: {\n type: CanvasEventType.EdgeRightClick,\n label: 'Right-click Edge',\n description: 'Triggered when right-clicking on an edge',\n category: 'edge'\n },\n [CanvasEventType.BackgroundClick]: {\n type: CanvasEventType.BackgroundClick,\n label: 'Click Background',\n description: 'Triggered when clicking on the canvas background',\n category: 'background'\n },\n [CanvasEventType.BackgroundDoubleClick]: {\n type: CanvasEventType.BackgroundDoubleClick,\n label: 'Double-click Background',\n description: 'Triggered when double-clicking on the canvas background',\n category: 'background'\n },\n [CanvasEventType.BackgroundRightClick]: {\n type: CanvasEventType.BackgroundRightClick,\n label: 'Right-click Background',\n description: 'Triggered when right-clicking on the canvas background',\n category: 'background'\n },\n [CanvasEventType.BackgroundLongPress]: {\n type: CanvasEventType.BackgroundLongPress,\n label: 'Long-press Background',\n description: 'Triggered when long-pressing on the canvas background (mobile/touch)',\n category: 'background'\n }\n};","/**\n * Canvas Action Types\n *\n * Action category enum, built-in action IDs, and action definition interfaces.\n *\n * Extracted from settings-types.ts in v1.9.0.\n *\n * @since 1.9.0\n */\n\n// =============================================================================\n// Action Categories\n// =============================================================================\n\n/**\n * Categories for grouping actions in the UI.\n */\nexport let ActionCategory = /*#__PURE__*/function (ActionCategory) {\n /** No action / disabled */\n ActionCategory[\"None\"] = \"none\";\n /** Selection-related actions */\n ActionCategory[\"Selection\"] = \"selection\";\n /** Viewport/navigation actions */\n ActionCategory[\"Viewport\"] = \"viewport\";\n /** Node manipulation actions */\n ActionCategory[\"Node\"] = \"node\";\n /** Layout and arrangement actions */\n ActionCategory[\"Layout\"] = \"layout\";\n /** History actions (undo/redo) */\n ActionCategory[\"History\"] = \"history\";\n /** User-defined custom actions */\n ActionCategory[\"Custom\"] = \"custom\";\n return ActionCategory;\n}({});\n\n// =============================================================================\n// Built-in Action IDs\n// =============================================================================\n\n/**\n * IDs for all built-in actions.\n * Using const assertion for type safety while allowing string comparison.\n */\nexport const BuiltInActionId = {\n // None\n None: 'none',\n // Selection\n SelectNode: 'select-node',\n SelectEdge: 'select-edge',\n AddToSelection: 'add-to-selection',\n ClearSelection: 'clear-selection',\n DeleteSelected: 'delete-selected',\n // Viewport\n FitToView: 'fit-to-view',\n FitAllToView: 'fit-all-to-view',\n CenterOnNode: 'center-on-node',\n ResetViewport: 'reset-viewport',\n // Node\n LockNode: 'lock-node',\n UnlockNode: 'unlock-node',\n ToggleLock: 'toggle-lock',\n OpenContextMenu: 'open-context-menu',\n SplitNode: 'split-node',\n GroupNodes: 'group-nodes',\n MergeNodes: 'merge-nodes',\n // Layout\n ApplyForceLayout: 'apply-force-layout',\n // History\n Undo: 'undo',\n Redo: 'redo',\n // Creation\n CreateNode: 'create-node'\n};\n\n// =============================================================================\n// Action Context\n// =============================================================================\n\n/**\n * Context passed to action handlers when executing.\n */\n\n/**\n * Options for creating an ActionContext via the context builder helpers.\n */\n\n// =============================================================================\n// Action Helpers\n// =============================================================================\n\n/**\n * Helper functions provided to action handlers.\n */\n\n// =============================================================================\n// Action Definition\n// =============================================================================\n\n/**\n * Full definition of an action that can be triggered by events.\n */","/**\n * Canvas Settings State Types\n *\n * Event-action mappings, presets, persisted state, and default mappings.\n *\n * Extracted from settings-types.ts in v1.9.0.\n *\n * @since 1.9.0\n */\n\nimport { CanvasEventType } from './event-types';\nimport { BuiltInActionId } from './action-types';\n\n// =============================================================================\n// Event-Action Mappings\n// =============================================================================\n\n/**\n * Mapping of events to action IDs.\n */\n\n// =============================================================================\n// Presets\n// =============================================================================\n\n/**\n * A settings preset with a name and full event-action mappings.\n */\n\n// =============================================================================\n// Persisted State\n// =============================================================================\n\n/**\n * The full settings state that gets persisted to localStorage.\n */\n\n// =============================================================================\n// Default Mappings\n// =============================================================================\n\n/**\n * Default event-action mappings (the \"Default\" preset).\n */\nexport const DEFAULT_MAPPINGS = {\n [CanvasEventType.NodeClick]: BuiltInActionId.None,\n [CanvasEventType.NodeDoubleClick]: BuiltInActionId.FitToView,\n [CanvasEventType.NodeTripleClick]: BuiltInActionId.ToggleLock,\n [CanvasEventType.NodeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.NodeLongPress]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.EdgeClick]: BuiltInActionId.SelectEdge,\n [CanvasEventType.EdgeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.EdgeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.BackgroundClick]: BuiltInActionId.ClearSelection,\n [CanvasEventType.BackgroundDoubleClick]: BuiltInActionId.FitAllToView,\n [CanvasEventType.BackgroundRightClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundLongPress]: BuiltInActionId.CreateNode\n};","/**\n * Node & Selection Actions\n *\n * Registration functions for node-related and selection-related built-in actions.\n */\n\nimport { ActionCategory, BuiltInActionId } from './settings-types';\nimport { registerAction } from './action-registry';\nexport function registerSelectionActions() {\n registerAction({\n id: BuiltInActionId.SelectNode,\n label: 'Select Node',\n description: 'Select this node (replacing current selection)',\n category: ActionCategory.Selection,\n icon: 'pointer',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.selectNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.SelectEdge,\n label: 'Select Edge',\n description: 'Select this edge',\n category: ActionCategory.Selection,\n icon: 'git-commit',\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.edgeId) {\n helpers.selectEdge(context.edgeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.AddToSelection,\n label: 'Add to Selection',\n description: 'Add this node to the current selection',\n category: ActionCategory.Selection,\n icon: 'plus-square',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.addToSelection(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ClearSelection,\n label: 'Clear Selection',\n description: 'Deselect all nodes',\n category: ActionCategory.Selection,\n icon: 'x-square',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n helpers.clearSelection();\n }\n });\n registerAction({\n id: BuiltInActionId.DeleteSelected,\n label: 'Delete Selected',\n description: 'Delete all selected nodes',\n category: ActionCategory.Selection,\n icon: 'trash-2',\n isBuiltIn: true,\n handler: async (_context, helpers) => {\n const selectedIds = helpers.getSelectedNodeIds();\n for (const nodeId of selectedIds) {\n await helpers.deleteNode(nodeId);\n }\n }\n });\n}\nexport function registerNodeActions() {\n registerAction({\n id: BuiltInActionId.LockNode,\n label: 'Lock Node',\n description: 'Prevent this node from being moved',\n category: ActionCategory.Node,\n icon: 'lock',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.lockNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.UnlockNode,\n label: 'Unlock Node',\n description: 'Allow this node to be moved',\n category: ActionCategory.Node,\n icon: 'unlock',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.unlockNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ToggleLock,\n label: 'Toggle Lock',\n description: 'Toggle whether this node can be moved',\n category: ActionCategory.Node,\n icon: 'lock',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.toggleLock(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.OpenContextMenu,\n label: 'Open Context Menu',\n description: 'Show the context menu for this node',\n category: ActionCategory.Node,\n icon: 'more-vertical',\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (helpers.openContextMenu) {\n helpers.openContextMenu(context.screenPosition, context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.CreateNode,\n label: 'Create Node',\n description: 'Create a new node at this position',\n category: ActionCategory.Node,\n icon: 'plus',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.createNode) {\n await helpers.createNode(context.worldPosition);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.SplitNode,\n label: 'Split Node',\n description: 'Split a node into two separate nodes',\n category: ActionCategory.Node,\n icon: 'split',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.splitNode && context.nodeId) {\n await helpers.splitNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.GroupNodes,\n label: 'Group Nodes',\n description: 'Group selected nodes into a parent container',\n category: ActionCategory.Node,\n icon: 'group',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.groupNodes) {\n await helpers.groupNodes(context.selectedNodeIds ?? helpers.getSelectedNodeIds());\n }\n }\n });\n registerAction({\n id: BuiltInActionId.MergeNodes,\n label: 'Merge Nodes',\n description: 'Merge selected nodes into one',\n category: ActionCategory.Node,\n icon: 'merge',\n isBuiltIn: true,\n handler: async (context, helpers) => {\n if (helpers.mergeNodes) {\n await helpers.mergeNodes(context.selectedNodeIds ?? helpers.getSelectedNodeIds());\n }\n }\n });\n}","/**\n * Viewport Actions\n *\n * Registration functions for viewport-related built-in actions.\n */\n\nimport { ActionCategory, BuiltInActionId } from './settings-types';\nimport { registerAction } from './action-registry';\nexport function registerViewportActions() {\n registerAction({\n id: BuiltInActionId.FitToView,\n label: 'Fit to View',\n description: 'Zoom and pan to fit this node in view',\n category: ActionCategory.Viewport,\n icon: 'maximize-2',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.centerOnNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.FitAllToView,\n label: 'Fit All to View',\n description: 'Zoom and pan to fit all nodes in view',\n category: ActionCategory.Viewport,\n icon: 'maximize',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n helpers.fitToBounds('graph');\n }\n });\n registerAction({\n id: BuiltInActionId.CenterOnNode,\n label: 'Center on Node',\n description: 'Center the viewport on this node',\n category: ActionCategory.Viewport,\n icon: 'crosshair',\n requiresNode: true,\n isBuiltIn: true,\n handler: (context, helpers) => {\n if (context.nodeId) {\n helpers.centerOnNode(context.nodeId);\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ResetViewport,\n label: 'Reset Viewport',\n description: 'Reset zoom to 100% and center on origin',\n category: ActionCategory.Viewport,\n icon: 'home',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n helpers.resetViewport();\n }\n });\n}\nexport function registerHistoryActions() {\n registerAction({\n id: BuiltInActionId.Undo,\n label: 'Undo',\n description: 'Undo the last action',\n category: ActionCategory.History,\n icon: 'undo-2',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n if (helpers.canUndo()) {\n helpers.undo();\n }\n }\n });\n registerAction({\n id: BuiltInActionId.Redo,\n label: 'Redo',\n description: 'Redo the last undone action',\n category: ActionCategory.History,\n icon: 'redo-2',\n isBuiltIn: true,\n handler: (_context, helpers) => {\n if (helpers.canRedo()) {\n helpers.redo();\n }\n }\n });\n registerAction({\n id: BuiltInActionId.ApplyForceLayout,\n label: 'Apply Force Layout',\n description: 'Automatically arrange nodes using force-directed layout',\n category: ActionCategory.Layout,\n icon: 'layout-grid',\n isBuiltIn: true,\n handler: async (_context, helpers) => {\n await helpers.applyForceLayout();\n }\n });\n}","/**\n * Built-in Actions\n *\n * All default action definitions. Registered automatically when\n * action-registry.ts is imported.\n *\n * Actions are split into separate modules:\n * - actions-node.ts — Selection and Node actions\n * - actions-viewport.ts — Viewport, History, and Layout actions\n */\n\nimport { BuiltInActionId, ActionCategory } from './settings-types';\nimport { registerAction } from './action-registry';\nimport { registerSelectionActions, registerNodeActions } from './actions-node';\nimport { registerViewportActions, registerHistoryActions } from './actions-viewport';\n\n/**\n * Register all built-in actions.\n * Called automatically when action-registry is imported.\n */\nexport function registerBuiltInActions() {\n // None - do nothing\n registerAction({\n id: BuiltInActionId.None,\n label: 'None',\n description: 'Do nothing',\n category: ActionCategory.None,\n icon: 'ban',\n isBuiltIn: true,\n handler: () => {\n // Intentionally empty\n }\n });\n registerSelectionActions();\n registerNodeActions();\n registerViewportActions();\n registerHistoryActions();\n}","/**\n * Action Registry\n *\n * Extensible registry for actions that can be triggered by canvas events.\n * Similar pattern to node-type-registry.ts - apps can register custom actions.\n */\n\nimport { ActionCategory } from './settings-types';\n\n// =============================================================================\n// Registry Storage\n// =============================================================================\n\nconst actionRegistry = new Map();\n\n// =============================================================================\n// Registry Functions\n// =============================================================================\n\n/**\n * Register a new action.\n * If an action with the same ID exists, it will be overwritten.\n */\nexport function registerAction(action) {\n actionRegistry.set(action.id, action);\n}\n\n/**\n * Get an action by ID.\n */\nexport function getAction(id) {\n return actionRegistry.get(id);\n}\n\n/**\n * Check if an action exists.\n */\nexport function hasAction(id) {\n return actionRegistry.has(id);\n}\n\n/**\n * Get all registered actions.\n */\nexport function getAllActions() {\n return Array.from(actionRegistry.values());\n}\n\n/**\n * Get actions by category.\n */\nexport function getActionsByCategory(category) {\n return getAllActions().filter(action => action.category === category);\n}\n\n/**\n * Unregister an action (mainly for custom actions).\n */\nexport function unregisterAction(id) {\n return actionRegistry.delete(id);\n}\n\n/**\n * Clear all actions (mainly for testing).\n */\nexport function clearActions() {\n actionRegistry.clear();\n}\n\n// =============================================================================\n// Built-in Actions — registered on first import\n// =============================================================================\n\nimport { registerBuiltInActions } from './built-in-actions';\nregisterBuiltInActions();\n\n// =============================================================================\n// Export Action Utilities\n// =============================================================================\n\n/**\n * Get all action categories with their actions, for UI rendering.\n */\nexport function getActionsByCategories() {\n const categoryLabels = {\n [ActionCategory.None]: 'None',\n [ActionCategory.Selection]: 'Selection',\n [ActionCategory.Viewport]: 'Viewport',\n [ActionCategory.Node]: 'Node',\n [ActionCategory.Layout]: 'Layout',\n [ActionCategory.History]: 'History',\n [ActionCategory.Custom]: 'Custom'\n };\n const categoryOrder = [ActionCategory.None, ActionCategory.Selection, ActionCategory.Viewport, ActionCategory.Node, ActionCategory.Layout, ActionCategory.History, ActionCategory.Custom];\n return categoryOrder.map(category => ({\n category,\n label: categoryLabels[category],\n actions: getActionsByCategory(category)\n })).filter(group => group.actions.length > 0);\n}","/**\n * Action Executor\n *\n * Executes actions by ID with the provided context and helpers.\n * This is the core execution logic, separate from React hooks.\n */\n\nimport { getAction } from './action-registry';\nimport { BuiltInActionId } from './settings-types';\nimport { selectedNodeIdsAtom, selectSingleNodeAtom, addNodesToSelectionAtom, clearSelectionAtom, selectEdgeAtom, clearEdgeSelectionAtom } from './selection-store';\nimport { resetViewportAtom, fitToBoundsAtom, centerOnNodeAtom } from './viewport-store';\nimport { lockedNodeIdAtom, lockNodeAtom, unlockNodeAtom } from './locked-node-store';\nimport { canUndoAtom, canRedoAtom, undoAtom, redoAtom } from './history-store';\nimport { FitToBoundsMode } from '../utils/layout';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('actions');\n\n// =============================================================================\n// Execution Result\n// =============================================================================\n\n// =============================================================================\n// Execute Action\n// =============================================================================\n\n/**\n * Execute an action by its ID.\n *\n * @param actionId - The ID of the action to execute\n * @param context - The context of the triggering event\n * @param helpers - Helper functions for manipulating canvas state\n * @returns Promise resolving to the execution result\n */\nexport async function executeAction(actionId, context, helpers) {\n // None action is a no-op\n if (actionId === BuiltInActionId.None) {\n return {\n success: true,\n actionId\n };\n }\n const action = getAction(actionId);\n if (!action) {\n debug.warn('Action not found: %s', actionId);\n return {\n success: false,\n actionId,\n error: new Error(`Action not found: ${actionId}`)\n };\n }\n\n // Check if action requires a node but none was provided\n if (action.requiresNode && !context.nodeId) {\n debug.warn('Action %s requires a node context', actionId);\n return {\n success: false,\n actionId,\n error: new Error(`Action ${actionId} requires a node context`)\n };\n }\n try {\n const result = action.handler(context, helpers);\n\n // Handle both sync and async handlers\n if (result instanceof Promise) {\n await result;\n }\n return {\n success: true,\n actionId\n };\n } catch (error) {\n debug.error('Error executing action %s: %O', actionId, error);\n return {\n success: false,\n actionId,\n error: error instanceof Error ? error : new Error(String(error))\n };\n }\n}\n\n// =============================================================================\n// Context Builder Helpers\n// =============================================================================\n\n/**\n * Create an ActionContext from a mouse event.\n */\nexport function createActionContext(eventType, screenEvent, worldPosition, options) {\n return {\n eventType,\n nodeId: options?.nodeId,\n nodeData: options?.nodeData,\n edgeId: options?.edgeId,\n edgeData: options?.edgeData,\n worldPosition,\n screenPosition: {\n x: screenEvent.clientX,\n y: screenEvent.clientY\n },\n modifiers: {\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n }\n };\n}\n\n/**\n * Create an ActionContext from a React mouse event.\n */\nexport function createActionContextFromReactEvent(eventType, event, worldPosition, options) {\n return {\n eventType,\n nodeId: options?.nodeId,\n nodeData: options?.nodeData,\n edgeId: options?.edgeId,\n edgeData: options?.edgeData,\n worldPosition,\n screenPosition: {\n x: event.clientX,\n y: event.clientY\n },\n modifiers: {\n shift: event.shiftKey,\n ctrl: event.ctrlKey,\n alt: event.altKey,\n meta: event.metaKey\n }\n };\n}\n\n/**\n * Create an ActionContext from a touch event (for long-press).\n */\nexport function createActionContextFromTouchEvent(eventType, touch, worldPosition, options) {\n return {\n eventType,\n nodeId: options?.nodeId,\n nodeData: options?.nodeData,\n edgeId: options?.edgeId,\n edgeData: options?.edgeData,\n worldPosition,\n screenPosition: {\n x: touch.clientX,\n y: touch.clientY\n },\n modifiers: {\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n }\n };\n}\n\n// =============================================================================\n// Headless Action Helpers Builder\n// =============================================================================\n\n/**\n * Build ActionHelpers from a raw Jotai store.\n * No React required — works in tests, CLI tools, and non-React integrations.\n */\nexport function buildActionHelpers(store, options = {}) {\n return {\n selectNode: nodeId => store.set(selectSingleNodeAtom, nodeId),\n addToSelection: nodeId => store.set(addNodesToSelectionAtom, [nodeId]),\n clearSelection: () => store.set(clearSelectionAtom),\n getSelectedNodeIds: () => Array.from(store.get(selectedNodeIdsAtom)),\n fitToBounds: (mode, padding) => {\n const fitMode = mode === 'graph' ? FitToBoundsMode.Graph : FitToBoundsMode.Selection;\n store.set(fitToBoundsAtom, {\n mode: fitMode,\n padding\n });\n },\n centerOnNode: nodeId => store.set(centerOnNodeAtom, nodeId),\n resetViewport: () => store.set(resetViewportAtom),\n lockNode: nodeId => store.set(lockNodeAtom, {\n nodeId\n }),\n unlockNode: _nodeId => store.set(unlockNodeAtom),\n toggleLock: nodeId => {\n const currentLockedId = store.get(lockedNodeIdAtom);\n if (currentLockedId === nodeId) {\n store.set(unlockNodeAtom);\n } else {\n store.set(lockNodeAtom, {\n nodeId\n });\n }\n },\n deleteNode: async nodeId => {\n if (options.onDeleteNode) {\n await options.onDeleteNode(nodeId);\n } else {\n debug.warn('deleteNode called but onDeleteNode callback not provided');\n }\n },\n isNodeLocked: nodeId => store.get(lockedNodeIdAtom) === nodeId,\n applyForceLayout: async () => {\n if (options.onApplyForceLayout) {\n await options.onApplyForceLayout();\n } else {\n debug.warn('applyForceLayout called but onApplyForceLayout callback not provided');\n }\n },\n undo: () => store.set(undoAtom),\n redo: () => store.set(redoAtom),\n canUndo: () => store.get(canUndoAtom),\n canRedo: () => store.get(canRedoAtom),\n selectEdge: edgeId => store.set(selectEdgeAtom, edgeId),\n clearEdgeSelection: () => store.set(clearEdgeSelectionAtom),\n openContextMenu: options.onOpenContextMenu,\n createNode: options.onCreateNode\n };\n}","/**\n * Canvas Settings Store\n *\n * Jotai atoms for managing canvas settings with localStorage persistence.\n * Uses atomWithStorage for automatic sync across tabs.\n *\n * Built-in presets and utility functions are in ./settings-presets.ts\n */\n\nimport { atom } from 'jotai';\nimport { atomWithStorage } from 'jotai/utils';\nimport { CanvasEventType, DEFAULT_MAPPINGS } from './settings-types';\nimport { createDebug } from '../utils/debug';\n\n// Re-export presets and utility for backward compat\nexport { BUILT_IN_PRESETS, getActionForEvent } from './settings-presets';\nimport { BUILT_IN_PRESETS } from './settings-presets';\nconst debug = createDebug('settings');\n\n// =============================================================================\n// Default State\n// =============================================================================\n\nconst DEFAULT_STATE = {\n mappings: DEFAULT_MAPPINGS,\n activePresetId: 'default',\n customPresets: [],\n isPanelOpen: false,\n virtualizationEnabled: true\n};\n\n// =============================================================================\n// Main Settings Atom (persisted)\n// =============================================================================\n\n/**\n * The main settings atom, persisted to localStorage.\n * All settings state is stored in a single atom for atomic updates.\n */\nexport const canvasSettingsAtom = atomWithStorage('@blinksgg/canvas/settings', DEFAULT_STATE);\n\n// =============================================================================\n// Derived Read-Only Atoms\n// =============================================================================\n\n/**\n * Current event-action mappings.\n */\nexport const eventMappingsAtom = atom(get => get(canvasSettingsAtom).mappings);\n\n/**\n * Currently active preset ID (null if mappings have been modified).\n */\nexport const activePresetIdAtom = atom(get => get(canvasSettingsAtom).activePresetId);\n\n/**\n * All presets (built-in + custom).\n */\nexport const allPresetsAtom = atom(get => {\n const state = get(canvasSettingsAtom);\n return [...BUILT_IN_PRESETS, ...state.customPresets];\n});\n\n/**\n * The currently active preset (if any).\n */\nexport const activePresetAtom = atom(get => {\n const presetId = get(activePresetIdAtom);\n if (!presetId) return null;\n const allPresets = get(allPresetsAtom);\n return allPresets.find(p => p.id === presetId) || null;\n});\n\n/**\n * Whether the settings panel is open.\n */\nexport const isPanelOpenAtom = atom(get => get(canvasSettingsAtom).isPanelOpen);\n\n/**\n * Whether viewport virtualization is enabled.\n * When true, only visible nodes/edges are rendered (better performance for large graphs).\n */\nexport const virtualizationEnabledAtom = atom(get => get(canvasSettingsAtom).virtualizationEnabled ?? true);\n\n/**\n * Whether current mappings differ from the active preset.\n */\nexport const hasUnsavedChangesAtom = atom(get => {\n const state = get(canvasSettingsAtom);\n const activePreset = get(activePresetAtom);\n if (!activePreset) return true;\n\n // Compare mappings\n const events = Object.values(CanvasEventType);\n return events.some(event => state.mappings[event] !== activePreset.mappings[event]);\n});\n\n// =============================================================================\n// Action Atoms (write-only)\n// =============================================================================\n\n/**\n * Set a single event-action mapping.\n */\nexport const setEventMappingAtom = atom(null, (get, set, {\n event,\n actionId\n}) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n mappings: {\n ...current.mappings,\n [event]: actionId\n },\n // Clear active preset since mappings have changed\n activePresetId: null\n });\n});\n\n/**\n * Apply a preset (copies its mappings to current).\n */\nexport const applyPresetAtom = atom(null, (get, set, presetId) => {\n const allPresets = get(allPresetsAtom);\n const preset = allPresets.find(p => p.id === presetId);\n if (!preset) {\n debug.warn('Preset not found: %s', presetId);\n return;\n }\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n mappings: {\n ...preset.mappings\n },\n activePresetId: presetId\n });\n});\n\n/**\n * Save current mappings as a new custom preset.\n */\nexport const saveAsPresetAtom = atom(null, (get, set, {\n name,\n description\n}) => {\n const current = get(canvasSettingsAtom);\n\n // Generate unique ID\n const id = `custom-${Date.now()}`;\n const newPreset = {\n id,\n name,\n description,\n mappings: {\n ...current.mappings\n },\n isBuiltIn: false\n };\n set(canvasSettingsAtom, {\n ...current,\n customPresets: [...current.customPresets, newPreset],\n activePresetId: id\n });\n return id;\n});\n\n/**\n * Update an existing custom preset with current mappings.\n */\nexport const updatePresetAtom = atom(null, (get, set, presetId) => {\n const current = get(canvasSettingsAtom);\n\n // Can only update custom presets\n const presetIndex = current.customPresets.findIndex(p => p.id === presetId);\n if (presetIndex === -1) {\n debug.warn('Cannot update preset: %s (not found or built-in)', presetId);\n return;\n }\n const updatedPresets = [...current.customPresets];\n updatedPresets[presetIndex] = {\n ...updatedPresets[presetIndex],\n mappings: {\n ...current.mappings\n }\n };\n set(canvasSettingsAtom, {\n ...current,\n customPresets: updatedPresets,\n activePresetId: presetId\n });\n});\n\n/**\n * Delete a custom preset.\n */\nexport const deletePresetAtom = atom(null, (get, set, presetId) => {\n const current = get(canvasSettingsAtom);\n\n // Can only delete custom presets\n const newCustomPresets = current.customPresets.filter(p => p.id !== presetId);\n if (newCustomPresets.length === current.customPresets.length) {\n debug.warn('Cannot delete preset: %s (not found or built-in)', presetId);\n return;\n }\n\n // If we deleted the active preset, switch to default\n const newActiveId = current.activePresetId === presetId ? 'default' : current.activePresetId;\n\n // If switching to default, also reset mappings\n const newMappings = newActiveId === 'default' ? DEFAULT_MAPPINGS : current.mappings;\n set(canvasSettingsAtom, {\n ...current,\n customPresets: newCustomPresets,\n activePresetId: newActiveId,\n mappings: newMappings\n });\n});\n\n/**\n * Reset to default settings.\n */\nexport const resetSettingsAtom = atom(null, (get, set) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n mappings: DEFAULT_MAPPINGS,\n activePresetId: 'default'\n });\n});\n\n/**\n * Toggle the settings panel open/closed.\n */\nexport const togglePanelAtom = atom(null, (get, set) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n isPanelOpen: !current.isPanelOpen\n });\n});\n\n/**\n * Set the panel open state directly.\n */\nexport const setPanelOpenAtom = atom(null, (get, set, isOpen) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n isPanelOpen: isOpen\n });\n});\n\n/**\n * Set virtualization enabled/disabled.\n */\nexport const setVirtualizationEnabledAtom = atom(null, (get, set, enabled) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n virtualizationEnabled: enabled\n });\n});\n\n/**\n * Toggle virtualization on/off.\n */\nexport const toggleVirtualizationAtom = atom(null, (get, set) => {\n const current = get(canvasSettingsAtom);\n set(canvasSettingsAtom, {\n ...current,\n virtualizationEnabled: !(current.virtualizationEnabled ?? true)\n });\n});","/**\n * Settings Presets & Utilities\n *\n * Built-in presets and utility functions extracted from settings-store.ts.\n */\n\nimport { CanvasEventType, DEFAULT_MAPPINGS, BuiltInActionId } from './settings-types';\n\n// =============================================================================\n// Built-in Presets\n// =============================================================================\n\nexport const BUILT_IN_PRESETS = [{\n id: 'default',\n name: 'Default',\n description: 'Standard canvas interactions',\n isBuiltIn: true,\n mappings: DEFAULT_MAPPINGS\n}, {\n id: 'minimal',\n name: 'Minimal',\n description: 'Only essential selection and context menu actions',\n isBuiltIn: true,\n mappings: {\n [CanvasEventType.NodeClick]: BuiltInActionId.None,\n [CanvasEventType.NodeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.NodeTripleClick]: BuiltInActionId.None,\n [CanvasEventType.NodeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.NodeLongPress]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.EdgeClick]: BuiltInActionId.SelectEdge,\n [CanvasEventType.EdgeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.EdgeRightClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundClick]: BuiltInActionId.ClearSelection,\n [CanvasEventType.BackgroundDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundRightClick]: BuiltInActionId.None,\n [CanvasEventType.BackgroundLongPress]: BuiltInActionId.None\n }\n}, {\n id: 'power-user',\n name: 'Power User',\n description: 'Quick actions for experienced users',\n isBuiltIn: true,\n mappings: {\n [CanvasEventType.NodeClick]: BuiltInActionId.None,\n [CanvasEventType.NodeDoubleClick]: BuiltInActionId.ToggleLock,\n [CanvasEventType.NodeTripleClick]: BuiltInActionId.DeleteSelected,\n [CanvasEventType.NodeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.NodeLongPress]: BuiltInActionId.AddToSelection,\n [CanvasEventType.EdgeClick]: BuiltInActionId.SelectEdge,\n [CanvasEventType.EdgeDoubleClick]: BuiltInActionId.None,\n [CanvasEventType.EdgeRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.BackgroundClick]: BuiltInActionId.ClearSelection,\n [CanvasEventType.BackgroundDoubleClick]: BuiltInActionId.CreateNode,\n [CanvasEventType.BackgroundRightClick]: BuiltInActionId.OpenContextMenu,\n [CanvasEventType.BackgroundLongPress]: BuiltInActionId.ApplyForceLayout\n }\n}];\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Get the action ID for a specific event from mappings.\n */\nexport function getActionForEvent(mappings, event) {\n return mappings[event] || BuiltInActionId.None;\n}","/**\n * Canvas Serializer\n *\n * JSON export/import of the full canvas state: nodes, edges, positions,\n * groups, and viewport. Enables copy-paste between canvases, file-based\n * backup, and template workflows.\n *\n * All functions are pure and operate on a Jotai store — no React required.\n *\n * @since 1.3.0\n */\n\nimport Graph from 'graphology';\nimport { graphAtom, graphUpdateVersionAtom, graphOptions } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { zoomAtom, panAtom } from './viewport-store';\nimport { collapsedGroupsAtom } from './group-store';\n// =============================================================================\n// Snapshot Schema\n// =============================================================================\n\n/** Version of the snapshot schema. Bump on breaking format changes. */\nexport const SNAPSHOT_VERSION = 1;\n\n/**\n * Serialized node — portable representation of a single canvas node.\n */\n\n/**\n * Serialized edge — portable representation of a single canvas edge.\n */\n\n/**\n * Serialized group relationship.\n */\n\n/**\n * Complete canvas snapshot — portable JSON schema.\n */\n\n/**\n * Options for importing a snapshot.\n */\n\n/**\n * Result of snapshot validation.\n */\n\n// =============================================================================\n// Export\n// =============================================================================\n\n/**\n * Export the current canvas state to a portable JSON snapshot.\n *\n * Reads the Graphology graph, all node positions, group state, and viewport\n * from the given Jotai store.\n */\nexport function exportGraph(store, metadata) {\n const graph = store.get(graphAtom);\n const zoom = store.get(zoomAtom);\n const pan = store.get(panAtom);\n const collapsed = store.get(collapsedGroupsAtom);\n const nodes = [];\n const groups = [];\n const seenGroupParents = new Set();\n graph.forEachNode((nodeId, attrs) => {\n const a = attrs;\n nodes.push({\n id: nodeId,\n position: {\n x: a.x,\n y: a.y\n },\n dimensions: {\n width: a.width,\n height: a.height\n },\n size: a.size,\n color: a.color,\n zIndex: a.zIndex,\n label: a.label,\n parentId: a.parentId,\n dbData: a.dbData\n });\n if (a.parentId) {\n const key = `${nodeId}:${a.parentId}`;\n if (!seenGroupParents.has(key)) {\n seenGroupParents.add(key);\n groups.push({\n nodeId,\n parentId: a.parentId,\n isCollapsed: collapsed.has(a.parentId)\n });\n }\n }\n });\n const edges = [];\n graph.forEachEdge((key, attrs, source, target) => {\n const a = attrs;\n edges.push({\n key,\n sourceId: source,\n targetId: target,\n attributes: {\n weight: a.weight,\n type: a.type,\n color: a.color,\n label: a.label\n },\n dbData: a.dbData\n });\n });\n return {\n version: SNAPSHOT_VERSION,\n exportedAt: new Date().toISOString(),\n nodes,\n edges,\n groups,\n viewport: {\n zoom,\n pan: {\n ...pan\n }\n },\n metadata\n };\n}\n\n// =============================================================================\n// Import\n// =============================================================================\n\n/**\n * Import a snapshot into the Jotai store, rebuilding the full graph state.\n */\nexport function importGraph(store, snapshot, options = {}) {\n const {\n clearExisting = true,\n offsetPosition,\n remapIds = false\n } = options;\n\n // Build ID remap table if needed\n const idMap = new Map();\n if (remapIds) {\n for (const node of snapshot.nodes) {\n idMap.set(node.id, crypto.randomUUID());\n }\n for (const edge of snapshot.edges) {\n idMap.set(edge.key, crypto.randomUUID());\n }\n }\n const remap = id => idMap.get(id) ?? id;\n\n // Clear or reuse graph\n let graph;\n if (clearExisting) {\n graph = new Graph(graphOptions);\n } else {\n graph = store.get(graphAtom);\n }\n\n // Offset helper\n const ox = offsetPosition?.x ?? 0;\n const oy = offsetPosition?.y ?? 0;\n\n // Add nodes\n for (const node of snapshot.nodes) {\n const nodeId = remap(node.id);\n const parentId = node.parentId ? remap(node.parentId) : undefined;\n const dbData = remapIds ? {\n ...node.dbData,\n id: nodeId\n } : node.dbData;\n const attrs = {\n x: node.position.x + ox,\n y: node.position.y + oy,\n width: node.dimensions.width,\n height: node.dimensions.height,\n size: node.size,\n color: node.color,\n zIndex: node.zIndex,\n label: node.label,\n parentId,\n dbData\n };\n graph.addNode(nodeId, attrs);\n }\n\n // Add edges\n for (const edge of snapshot.edges) {\n const edgeKey = remap(edge.key);\n const sourceId = remap(edge.sourceId);\n const targetId = remap(edge.targetId);\n\n // Skip edges whose endpoints don't exist\n if (!graph.hasNode(sourceId) || !graph.hasNode(targetId)) continue;\n const dbData = remapIds ? {\n ...edge.dbData,\n id: edgeKey,\n source_node_id: sourceId,\n target_node_id: targetId\n } : edge.dbData;\n const attrs = {\n weight: edge.attributes.weight,\n type: edge.attributes.type,\n color: edge.attributes.color,\n label: edge.attributes.label,\n dbData\n };\n graph.addEdgeWithKey(edgeKey, sourceId, targetId, attrs);\n }\n\n // Apply graph to store\n store.set(graphAtom, graph);\n store.set(graphUpdateVersionAtom, v => v + 1);\n store.set(nodePositionUpdateCounterAtom, c => c + 1);\n\n // Restore collapsed groups\n const collapsedSet = new Set();\n for (const group of snapshot.groups) {\n if (group.isCollapsed) {\n collapsedSet.add(remap(group.parentId));\n }\n }\n store.set(collapsedGroupsAtom, collapsedSet);\n\n // Restore viewport\n store.set(zoomAtom, snapshot.viewport.zoom);\n store.set(panAtom, {\n ...snapshot.viewport.pan\n });\n}\n\n// =============================================================================\n// Validation\n// =============================================================================\n\n/**\n * Validate that an unknown value conforms to the CanvasSnapshot schema.\n * Performs runtime type checks on all required fields.\n */\nexport function validateSnapshot(data) {\n const errors = [];\n if (!data || typeof data !== 'object') {\n return {\n valid: false,\n errors: ['Snapshot must be a non-null object']\n };\n }\n const obj = data;\n\n // Version\n if (obj.version !== SNAPSHOT_VERSION) {\n errors.push(`Expected version ${SNAPSHOT_VERSION}, got ${String(obj.version)}`);\n }\n\n // exportedAt\n if (typeof obj.exportedAt !== 'string') {\n errors.push('Missing or invalid \"exportedAt\" (expected ISO string)');\n }\n\n // nodes\n if (!Array.isArray(obj.nodes)) {\n errors.push('Missing or invalid \"nodes\" (expected array)');\n } else {\n for (let i = 0; i < obj.nodes.length; i++) {\n const node = obj.nodes[i];\n if (!node || typeof node !== 'object') {\n errors.push(`nodes[${i}]: expected object`);\n continue;\n }\n if (typeof node.id !== 'string') errors.push(`nodes[${i}]: missing \"id\"`);\n if (!node.position || typeof node.position !== 'object') errors.push(`nodes[${i}]: missing \"position\"`);\n if (!node.dimensions || typeof node.dimensions !== 'object') errors.push(`nodes[${i}]: missing \"dimensions\"`);\n if (!node.dbData || typeof node.dbData !== 'object') errors.push(`nodes[${i}]: missing \"dbData\"`);\n }\n }\n\n // edges\n if (!Array.isArray(obj.edges)) {\n errors.push('Missing or invalid \"edges\" (expected array)');\n } else {\n for (let i = 0; i < obj.edges.length; i++) {\n const edge = obj.edges[i];\n if (!edge || typeof edge !== 'object') {\n errors.push(`edges[${i}]: expected object`);\n continue;\n }\n if (typeof edge.key !== 'string') errors.push(`edges[${i}]: missing \"key\"`);\n if (typeof edge.sourceId !== 'string') errors.push(`edges[${i}]: missing \"sourceId\"`);\n if (typeof edge.targetId !== 'string') errors.push(`edges[${i}]: missing \"targetId\"`);\n if (!edge.dbData || typeof edge.dbData !== 'object') errors.push(`edges[${i}]: missing \"dbData\"`);\n }\n }\n\n // groups\n if (!Array.isArray(obj.groups)) {\n errors.push('Missing or invalid \"groups\" (expected array)');\n }\n\n // viewport\n if (!obj.viewport || typeof obj.viewport !== 'object') {\n errors.push('Missing or invalid \"viewport\" (expected object)');\n } else {\n const vp = obj.viewport;\n if (typeof vp.zoom !== 'number') errors.push('viewport: missing \"zoom\"');\n if (!vp.pan || typeof vp.pan !== 'object') errors.push('viewport: missing \"pan\"');\n }\n return {\n valid: errors.length === 0,\n errors\n };\n}","/**\n * Clipboard state management\n *\n * Provides copy/cut/paste operations for nodes and edges.\n * Uses local-first approach - pasted nodes exist only in local graph until saved.\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom } from './graph-store';\nimport { addNodeToLocalGraphAtom, optimisticDeleteNodeAtom } from './graph-mutations';\nimport { addEdgeToLocalGraphAtom } from './graph-mutations-edges';\nimport { selectedNodeIdsAtom, addNodesToSelectionAtom, clearSelectionAtom } from './selection-store';\nimport { pushHistoryAtom } from './history-store';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('clipboard');\n\n// --- Types ---\n\n// --- Constants ---\n\n/** Default offset when pasting (diagonal from original) */\nexport const PASTE_OFFSET = {\n x: 50,\n y: 50\n};\n\n// --- Core Atoms ---\n\n/**\n * Clipboard data storage\n */\nexport const clipboardAtom = atom(null);\n\n/**\n * Whether clipboard has content\n */\nexport const hasClipboardContentAtom = atom(get => get(clipboardAtom) !== null);\n\n/**\n * Number of nodes in clipboard\n */\nexport const clipboardNodeCountAtom = atom(get => {\n const clipboard = get(clipboardAtom);\n return clipboard?.nodes.length ?? 0;\n});\n\n// --- Helper Functions ---\n\n/**\n * Calculate bounding box of nodes\n */\nfunction calculateBounds(nodes) {\n if (nodes.length === 0) {\n return {\n minX: 0,\n minY: 0,\n maxX: 0,\n maxY: 0\n };\n }\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const node of nodes) {\n minX = Math.min(minX, node.attrs.x);\n minY = Math.min(minY, node.attrs.y);\n maxX = Math.max(maxX, node.attrs.x + node.attrs.width);\n maxY = Math.max(maxY, node.attrs.y + node.attrs.height);\n }\n return {\n minX,\n minY,\n maxX,\n maxY\n };\n}\n\n/**\n * Generate a new unique ID for pasted nodes\n */\nfunction generatePasteId(index) {\n return `paste-${Date.now()}-${index}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n// --- Action Atoms ---\n\n/**\n * Copy selected nodes and their internal edges to clipboard\n */\nexport const copyToClipboardAtom = atom(null, (get, set, nodeIds) => {\n const selectedIds = nodeIds ?? Array.from(get(selectedNodeIdsAtom));\n if (selectedIds.length === 0) {\n debug('Nothing to copy - no nodes selected');\n return;\n }\n const graph = get(graphAtom);\n const selectedSet = new Set(selectedIds);\n const nodes = [];\n const edges = [];\n\n // Collect node data\n for (const nodeId of selectedIds) {\n if (!graph.hasNode(nodeId)) {\n debug('Node %s not found in graph, skipping', nodeId);\n continue;\n }\n const attrs = graph.getNodeAttributes(nodeId);\n nodes.push({\n attrs: {\n ...attrs\n },\n dbData: {\n ...attrs.dbData\n }\n });\n }\n\n // Collect edges where BOTH source and target are in selection\n graph.forEachEdge((edgeKey, attrs, source, target) => {\n if (selectedSet.has(source) && selectedSet.has(target)) {\n edges.push({\n source,\n target,\n attrs: {\n ...attrs\n },\n dbData: {\n ...attrs.dbData\n }\n });\n }\n });\n const bounds = calculateBounds(nodes);\n const clipboardData = {\n nodes,\n edges,\n bounds,\n timestamp: Date.now()\n };\n set(clipboardAtom, clipboardData);\n debug('Copied %d nodes and %d edges to clipboard', nodes.length, edges.length);\n});\n\n/**\n * Cut selected nodes (copy + delete from graph)\n * Pushes history for undo support.\n */\nexport const cutToClipboardAtom = atom(null, (get, set, nodeIds) => {\n const selectedIds = nodeIds ?? Array.from(get(selectedNodeIdsAtom));\n if (selectedIds.length === 0) return;\n\n // First copy to clipboard\n set(copyToClipboardAtom, selectedIds);\n\n // Push history so entire cut is undoable\n set(pushHistoryAtom, 'Cut nodes');\n\n // Delete each selected node (also removes connected edges)\n for (const nodeId of selectedIds) {\n set(optimisticDeleteNodeAtom, {\n nodeId\n });\n }\n set(clearSelectionAtom);\n debug('Cut %d nodes — copied to clipboard and deleted from graph', selectedIds.length);\n});\n\n/**\n * Paste clipboard content at an offset from original position\n */\nexport const pasteFromClipboardAtom = atom(null, (get, set, offset) => {\n const clipboard = get(clipboardAtom);\n if (!clipboard || clipboard.nodes.length === 0) {\n debug('Nothing to paste - clipboard empty');\n return [];\n }\n const pasteOffset = offset ?? PASTE_OFFSET;\n const graph = get(graphAtom);\n\n // Push history for undo support\n set(pushHistoryAtom, 'Paste nodes');\n\n // Map old IDs to new IDs\n const idMap = new Map();\n const newNodeIds = [];\n\n // Create new nodes\n for (let i = 0; i < clipboard.nodes.length; i++) {\n const nodeData = clipboard.nodes[i];\n const newId = generatePasteId(i);\n idMap.set(nodeData.dbData.id, newId);\n newNodeIds.push(newId);\n\n // Create new DBGraphNode with offset position\n const newDbNode = {\n ...nodeData.dbData,\n id: newId,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n ui_properties: {\n ...(nodeData.dbData.ui_properties || {}),\n x: nodeData.attrs.x + pasteOffset.x,\n y: nodeData.attrs.y + pasteOffset.y\n }\n };\n debug('Pasting node %s -> %s at (%d, %d)', nodeData.dbData.id, newId, nodeData.attrs.x + pasteOffset.x, nodeData.attrs.y + pasteOffset.y);\n set(addNodeToLocalGraphAtom, newDbNode);\n }\n\n // Create new edges with remapped IDs\n for (const edgeData of clipboard.edges) {\n const newSourceId = idMap.get(edgeData.source);\n const newTargetId = idMap.get(edgeData.target);\n if (!newSourceId || !newTargetId) {\n debug('Edge %s: source or target not found in id map, skipping', edgeData.dbData.id);\n continue;\n }\n const newEdgeId = generatePasteId(clipboard.edges.indexOf(edgeData) + clipboard.nodes.length);\n const newDbEdge = {\n ...edgeData.dbData,\n id: newEdgeId,\n source_node_id: newSourceId,\n target_node_id: newTargetId,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n };\n debug('Pasting edge %s -> %s (from %s to %s)', edgeData.dbData.id, newEdgeId, newSourceId, newTargetId);\n set(addEdgeToLocalGraphAtom, newDbEdge);\n }\n\n // Select the newly pasted nodes\n set(clearSelectionAtom);\n set(addNodesToSelectionAtom, newNodeIds);\n debug('Pasted %d nodes and %d edges', newNodeIds.length, clipboard.edges.length);\n return newNodeIds;\n});\n\n/**\n * Duplicate selected nodes in place with offset\n * Shorthand for copy + paste\n */\nexport const duplicateSelectionAtom = atom(null, (get, set) => {\n set(copyToClipboardAtom);\n return set(pasteFromClipboardAtom);\n});\n\n/**\n * Clear clipboard content\n */\nexport const clearClipboardAtom = atom(null, (_get, set) => {\n set(clipboardAtom, null);\n debug('Clipboard cleared');\n});","/**\n * Virtualization state management\n *\n * Provides viewport-based culling to only render visible nodes and edges.\n * Uses a SpatialGrid index for O(visible) node lookups instead of O(N) scans.\n * Improves performance for large graphs (100+ nodes).\n */\n\nimport { atom } from 'jotai';\nimport { graphAtom, graphUpdateVersionAtom, edgeCreationAtom } from './graph-store';\nimport { nodePositionUpdateCounterAtom } from './graph-position';\nimport { nodeKeysAtom, edgeKeysAtom } from './graph-derived';\nimport { panAtom, zoomAtom, viewportRectAtom } from './viewport-store';\nimport { virtualizationEnabledAtom } from './settings-store';\nimport { collapsedEdgeRemapAtom } from './group-store';\nimport { SpatialGrid } from './spatial-index';\nimport { canvasMark } from './perf';\n\n// --- Configuration ---\n\n/**\n * Buffer in world-space pixels beyond viewport edges.\n * Nodes within this buffer are still rendered for smooth panning.\n */\nexport const VIRTUALIZATION_BUFFER = 200;\n\n// Re-export for backwards compatibility\nexport { virtualizationEnabledAtom } from './settings-store';\n\n// --- Spatial Index ---\n\n/**\n * Spatial grid index rebuilt on graph structure changes.\n * Incrementally updated on position changes via the update path.\n */\nexport const spatialIndexAtom = atom(get => {\n get(graphUpdateVersionAtom);\n get(nodePositionUpdateCounterAtom);\n const graph = get(graphAtom);\n const grid = new SpatialGrid(500);\n graph.forEachNode((nodeId, attrs) => {\n const a = attrs;\n grid.insert(nodeId, a.x, a.y, a.width || 200, a.height || 100);\n });\n return grid;\n});\n\n// --- Visible Bounds ---\n\n/**\n * Calculate visible bounds in world coordinates.\n * Includes buffer for smooth panning.\n */\nexport const visibleBoundsAtom = atom(get => {\n const viewport = get(viewportRectAtom);\n const pan = get(panAtom);\n const zoom = get(zoomAtom);\n if (!viewport || zoom === 0) {\n return null;\n }\n const buffer = VIRTUALIZATION_BUFFER;\n return {\n minX: (-buffer - pan.x) / zoom,\n minY: (-buffer - pan.y) / zoom,\n maxX: (viewport.width + buffer - pan.x) / zoom,\n maxY: (viewport.height + buffer - pan.y) / zoom\n };\n});\n\n// --- Node Visibility ---\n\n/**\n * Node keys filtered to only those visible in viewport.\n * Uses SpatialGrid.query() for O(visible) performance when enabled.\n * Falls back to all nodes when virtualization disabled or bounds unavailable.\n */\nexport const visibleNodeKeysAtom = atom(get => {\n const end = canvasMark('virtualization-cull');\n const enabled = get(virtualizationEnabledAtom);\n const allKeys = get(nodeKeysAtom);\n if (!enabled) {\n end();\n return allKeys;\n }\n const bounds = get(visibleBoundsAtom);\n if (!bounds) {\n end();\n return allKeys;\n }\n const grid = get(spatialIndexAtom);\n const visibleSet = grid.query(bounds);\n\n // Return keys in original order (preserves rendering order)\n const result = allKeys.filter(k => visibleSet.has(k));\n end();\n return result;\n});\n\n// --- Edge Visibility ---\n\n/**\n * Edge keys filtered to only those where both endpoints are visible.\n * Temp edge during creation is always included.\n *\n * When groups are collapsed, edges to/from collapsed children are re-routed\n * to the group node. Internal edges (both endpoints in the same collapsed group)\n * are hidden.\n */\nexport const visibleEdgeKeysAtom = atom(get => {\n const enabled = get(virtualizationEnabledAtom);\n const allEdgeKeys = get(edgeKeysAtom);\n const edgeCreation = get(edgeCreationAtom);\n const remap = get(collapsedEdgeRemapAtom);\n\n // Always include temp edge if creating\n const tempEdgeKey = edgeCreation.isCreating ? 'temp-creating-edge' : null;\n\n // Depend on graph changes\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n\n // Filter edges: resolve effective endpoints through remap\n const filteredEdges = allEdgeKeys.filter(edgeKey => {\n const source = graph.source(edgeKey);\n const target = graph.target(edgeKey);\n const effectiveSource = remap.get(source) ?? source;\n const effectiveTarget = remap.get(target) ?? target;\n\n // Hide internal edges (both endpoints map to the same collapsed group)\n if (effectiveSource === effectiveTarget) return false;\n return true;\n });\n if (!enabled) {\n return tempEdgeKey ? [...filteredEdges, tempEdgeKey] : filteredEdges;\n }\n\n // Get visible node set for O(1) lookup\n const visibleNodeKeys = get(visibleNodeKeysAtom);\n const visibleNodeSet = new Set(visibleNodeKeys);\n const visibleEdges = filteredEdges.filter(edgeKey => {\n const source = graph.source(edgeKey);\n const target = graph.target(edgeKey);\n const effectiveSource = remap.get(source) ?? source;\n const effectiveTarget = remap.get(target) ?? target;\n\n // Edge visible if both effective endpoints are visible\n return visibleNodeSet.has(effectiveSource) && visibleNodeSet.has(effectiveTarget);\n });\n return tempEdgeKey ? [...visibleEdges, tempEdgeKey] : visibleEdges;\n});\n\n// --- Metrics ---\n\n/**\n * Virtualization metrics for debugging/monitoring.\n */\nexport const virtualizationMetricsAtom = atom(get => {\n const enabled = get(virtualizationEnabledAtom);\n const totalNodes = get(nodeKeysAtom).length;\n const totalEdges = get(edgeKeysAtom).length;\n const visibleNodes = get(visibleNodeKeysAtom).length;\n const visibleEdges = get(visibleEdgeKeysAtom).length;\n const bounds = get(visibleBoundsAtom);\n return {\n enabled,\n totalNodes,\n totalEdges,\n visibleNodes,\n visibleEdges,\n culledNodes: totalNodes - visibleNodes,\n culledEdges: totalEdges - visibleEdges,\n bounds\n };\n});","/**\n * Spatial Grid Index\n *\n * Fixed-cell grid for O(visible + bucket) viewport culling.\n * Replaces the O(N) linear scan in visibleNodeKeysAtom.\n *\n * Default cell size is 500 world-space pixels — chosen to balance\n * bucket count vs. false positives for typical node sizes (200500px).\n */\n\nexport class SpatialGrid {\n /** cell key → set of node IDs in that cell */\n cells = new Map();\n /** node ID → entry data (for update/remove) */\n entries = new Map();\n constructor(cellSize = 500) {\n this.cellSize = cellSize;\n }\n\n /** Number of tracked entries */\n get size() {\n return this.entries.size;\n }\n cellKey(cx, cy) {\n return `${cx},${cy}`;\n }\n getCellRange(x, y, w, h) {\n const cs = this.cellSize;\n return {\n minCX: Math.floor(x / cs),\n minCY: Math.floor(y / cs),\n maxCX: Math.floor((x + w) / cs),\n maxCY: Math.floor((y + h) / cs)\n };\n }\n\n /**\n * Insert a node into the index.\n * If the node already exists, it is updated.\n */\n insert(id, x, y, width, height) {\n if (this.entries.has(id)) {\n this.update(id, x, y, width, height);\n return;\n }\n const entry = {\n id,\n x,\n y,\n width,\n height\n };\n this.entries.set(id, entry);\n const {\n minCX,\n minCY,\n maxCX,\n maxCY\n } = this.getCellRange(x, y, width, height);\n for (let cx = minCX; cx <= maxCX; cx++) {\n for (let cy = minCY; cy <= maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n let cell = this.cells.get(key);\n if (!cell) {\n cell = new Set();\n this.cells.set(key, cell);\n }\n cell.add(id);\n }\n }\n }\n\n /**\n * Update a node's position/dimensions.\n */\n update(id, x, y, width, height) {\n const prev = this.entries.get(id);\n if (!prev) {\n this.insert(id, x, y, width, height);\n return;\n }\n\n // Quick check: if cell range didn't change, just update entry\n const prevRange = this.getCellRange(prev.x, prev.y, prev.width, prev.height);\n const newRange = this.getCellRange(x, y, width, height);\n prev.x = x;\n prev.y = y;\n prev.width = width;\n prev.height = height;\n if (prevRange.minCX === newRange.minCX && prevRange.minCY === newRange.minCY && prevRange.maxCX === newRange.maxCX && prevRange.maxCY === newRange.maxCY) {\n return; // Same cells, no grid update needed\n }\n\n // Remove from old cells\n for (let cx = prevRange.minCX; cx <= prevRange.maxCX; cx++) {\n for (let cy = prevRange.minCY; cy <= prevRange.maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n const cell = this.cells.get(key);\n if (cell) {\n cell.delete(id);\n if (cell.size === 0) this.cells.delete(key);\n }\n }\n }\n\n // Add to new cells\n for (let cx = newRange.minCX; cx <= newRange.maxCX; cx++) {\n for (let cy = newRange.minCY; cy <= newRange.maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n let cell = this.cells.get(key);\n if (!cell) {\n cell = new Set();\n this.cells.set(key, cell);\n }\n cell.add(id);\n }\n }\n }\n\n /**\n * Remove a node from the index.\n */\n remove(id) {\n const entry = this.entries.get(id);\n if (!entry) return;\n const {\n minCX,\n minCY,\n maxCX,\n maxCY\n } = this.getCellRange(entry.x, entry.y, entry.width, entry.height);\n for (let cx = minCX; cx <= maxCX; cx++) {\n for (let cy = minCY; cy <= maxCY; cy++) {\n const key = this.cellKey(cx, cy);\n const cell = this.cells.get(key);\n if (cell) {\n cell.delete(id);\n if (cell.size === 0) this.cells.delete(key);\n }\n }\n }\n this.entries.delete(id);\n }\n\n /**\n * Query all node IDs whose bounding box overlaps the given bounds.\n * Returns a Set for O(1) membership checks.\n */\n query(bounds) {\n const result = new Set();\n const {\n minCX,\n minCY,\n maxCX,\n maxCY\n } = this.getCellRange(bounds.minX, bounds.minY, bounds.maxX - bounds.minX, bounds.maxY - bounds.minY);\n for (let cx = minCX; cx <= maxCX; cx++) {\n for (let cy = minCY; cy <= maxCY; cy++) {\n const cell = this.cells.get(this.cellKey(cx, cy));\n if (!cell) continue;\n for (const id of cell) {\n if (result.has(id)) continue;\n\n // AABB intersection test against actual entry bounds\n const entry = this.entries.get(id);\n const entryRight = entry.x + entry.width;\n const entryBottom = entry.y + entry.height;\n if (entry.x <= bounds.maxX && entryRight >= bounds.minX && entry.y <= bounds.maxY && entryBottom >= bounds.minY) {\n result.add(id);\n }\n }\n }\n }\n return result;\n }\n\n /**\n * Clear all entries.\n */\n clear() {\n this.cells.clear();\n this.entries.clear();\n }\n\n /**\n * Check if a node is tracked.\n */\n has(id) {\n return this.entries.has(id);\n }\n}","/**\n * Headless Canvas API\n *\n * A pure Jotai store-based API for controlling the canvas without React.\n * Satisfies Principle 6: \"Fully controllable headless API\".\n *\n * @example\n * ```ts\n * import { createStore } from 'jotai';\n * import { createCanvasAPI } from '@blinksgg/canvas/core';\n *\n * const store = createStore();\n * const api = createCanvasAPI(store);\n *\n * api.selectNode('node-1');\n * api.fitToBounds('graph', 20);\n * api.undo();\n * ```\n */\n\nimport { executeAction, buildActionHelpers } from './action-executor';\nimport { exportGraph, importGraph, validateSnapshot } from './canvas-serializer';\nimport { eventMappingsAtom, getActionForEvent } from './settings-store';\nimport { selectedNodeIdsAtom, selectSingleNodeAtom, addNodesToSelectionAtom, clearSelectionAtom, selectEdgeAtom, clearEdgeSelectionAtom, selectedEdgeIdAtom } from './selection-store';\nimport { zoomAtom, panAtom, resetViewportAtom, fitToBoundsAtom, centerOnNodeAtom } from './viewport-store';\nimport { graphAtom } from './graph-store';\nimport { nodeKeysAtom, edgeKeysAtom } from './graph-derived';\nimport { addNodeToLocalGraphAtom, optimisticDeleteNodeAtom, optimisticDeleteEdgeAtom } from './graph-mutations';\nimport { addEdgeToLocalGraphAtom } from './graph-mutations-edges';\nimport { undoAtom, redoAtom, canUndoAtom, canRedoAtom, pushHistoryAtom, clearHistoryAtom } from './history-store';\nimport { copyToClipboardAtom, cutToClipboardAtom, pasteFromClipboardAtom, duplicateSelectionAtom, clipboardAtom } from './clipboard-store';\nimport { snapEnabledAtom, snapGridSizeAtom, toggleSnapAtom } from './snap-store';\nimport { virtualizationEnabledAtom, visibleNodeKeysAtom, visibleEdgeKeysAtom } from './virtualization-store';\nimport { FitToBoundsMode } from '../utils/layout';\n/**\n * Create a headless canvas API from a Jotai store.\n * All canvas operations available without React.\n */\nexport function createCanvasAPI(store, options = {}) {\n const helpers = buildActionHelpers(store, options);\n const api = {\n // Selection\n selectNode: id => store.set(selectSingleNodeAtom, id),\n addToSelection: ids => store.set(addNodesToSelectionAtom, ids),\n clearSelection: () => store.set(clearSelectionAtom),\n getSelectedNodeIds: () => Array.from(store.get(selectedNodeIdsAtom)),\n selectEdge: edgeId => store.set(selectEdgeAtom, edgeId),\n clearEdgeSelection: () => store.set(clearEdgeSelectionAtom),\n getSelectedEdgeId: () => store.get(selectedEdgeIdAtom),\n // Viewport\n getZoom: () => store.get(zoomAtom),\n setZoom: zoom => store.set(zoomAtom, zoom),\n getPan: () => store.get(panAtom),\n setPan: pan => store.set(panAtom, pan),\n resetViewport: () => store.set(resetViewportAtom),\n fitToBounds: (mode, padding) => {\n const fitMode = mode === 'graph' ? FitToBoundsMode.Graph : FitToBoundsMode.Selection;\n store.set(fitToBoundsAtom, {\n mode: fitMode,\n padding\n });\n },\n centerOnNode: nodeId => store.set(centerOnNodeAtom, nodeId),\n // Graph\n addNode: node => store.set(addNodeToLocalGraphAtom, node),\n removeNode: nodeId => store.set(optimisticDeleteNodeAtom, {\n nodeId\n }),\n addEdge: edge => store.set(addEdgeToLocalGraphAtom, edge),\n removeEdge: edgeKey => store.set(optimisticDeleteEdgeAtom, {\n edgeKey\n }),\n getNodeKeys: () => store.get(nodeKeysAtom),\n getEdgeKeys: () => store.get(edgeKeysAtom),\n getNodeAttributes: id => {\n const graph = store.get(graphAtom);\n return graph.hasNode(id) ? graph.getNodeAttributes(id) : undefined;\n },\n // History\n undo: () => store.set(undoAtom),\n redo: () => store.set(redoAtom),\n canUndo: () => store.get(canUndoAtom),\n canRedo: () => store.get(canRedoAtom),\n recordSnapshot: label => store.set(pushHistoryAtom, label),\n clearHistory: () => store.set(clearHistoryAtom),\n // Clipboard\n copy: () => store.set(copyToClipboardAtom),\n cut: () => store.set(cutToClipboardAtom),\n paste: () => store.set(pasteFromClipboardAtom),\n duplicate: () => store.set(duplicateSelectionAtom),\n hasClipboardContent: () => store.get(clipboardAtom) !== null,\n // Snap\n isSnapEnabled: () => store.get(snapEnabledAtom),\n toggleSnap: () => store.set(toggleSnapAtom),\n getSnapGridSize: () => store.get(snapGridSizeAtom),\n // Virtualization\n isVirtualizationEnabled: () => store.get(virtualizationEnabledAtom),\n getVisibleNodeKeys: () => store.get(visibleNodeKeysAtom),\n getVisibleEdgeKeys: () => store.get(visibleEdgeKeysAtom),\n // Actions\n executeAction: (actionId, context) => executeAction(actionId, context, helpers),\n executeEventAction: (event, context) => {\n const mappings = store.get(eventMappingsAtom);\n const actionId = getActionForEvent(mappings, event);\n return executeAction(actionId, context, helpers);\n },\n // Serialization\n exportSnapshot: metadata => exportGraph(store, metadata),\n importSnapshot: (snapshot, options) => importGraph(store, snapshot, options),\n validateSnapshot: data => validateSnapshot(data)\n };\n return api;\n}","/**\n * Port Types\n *\n * Defines types for node connection ports/handles.\n * Ports are per-node-instance configurable connection points.\n */\n\n// --- Port Position Types ---\n\n/**\n * Side of a node where a port can be placed.\n */\n\n/**\n * Type of port connection behavior.\n * - 'input': Can only receive connections\n * - 'output': Can only send connections\n * - 'bidirectional': Can both send and receive connections\n */\n\n// --- Port Definition ---\n\n/**\n * Definition of a single port on a node.\n * Stored in node's ui_properties.ports array.\n */\n\n// --- Node Ports Configuration ---\n\n/**\n * Configuration for all ports on a node.\n * Stored in node's ui_properties.ports.\n */\n\n// --- Port Connection State ---\n\n/**\n * Represents a connection to a specific port.\n * Used in edge attributes to specify which ports are connected.\n */\n\n/**\n * Extended edge attributes with port information.\n * These are stored alongside existing edge attributes.\n */\n\n// --- Port Position Calculation ---\n\n/**\n * Calculated world-space position of a port.\n */\n\n/**\n * Calculate the world-space position of a port on a node.\n *\n * @param nodeX Node's x position\n * @param nodeY Node's y position\n * @param nodeWidth Node's width\n * @param nodeHeight Node's height\n * @param port The port definition\n * @returns World-space coordinates of the port\n */\nexport function calculatePortPosition(nodeX, nodeY, nodeWidth, nodeHeight, port) {\n switch (port.side) {\n case 'left':\n return {\n x: nodeX,\n y: nodeY + nodeHeight * port.position\n };\n case 'right':\n return {\n x: nodeX + nodeWidth,\n y: nodeY + nodeHeight * port.position\n };\n case 'top':\n return {\n x: nodeX + nodeWidth * port.position,\n y: nodeY\n };\n case 'bottom':\n return {\n x: nodeX + nodeWidth * port.position,\n y: nodeY + nodeHeight\n };\n }\n}\n\n// --- Default Port Configuration ---\n\n/**\n * Default port for nodes without explicit port configuration.\n * A single bidirectional port centered on the right side.\n */\nexport const DEFAULT_PORT = {\n id: 'default',\n type: 'bidirectional',\n side: 'right',\n position: 0.5\n};\n\n/**\n * Get the ports configuration for a node.\n * Returns default port if no explicit configuration exists.\n *\n * @param ports Optional ports array from node's ui_properties\n * @returns Array of port definitions\n */\nexport function getNodePorts(ports) {\n if (ports && ports.length > 0) {\n return ports;\n }\n return [DEFAULT_PORT];\n}\n\n// --- Port Validation ---\n\n/**\n * Check if a port can accept a new connection.\n *\n * @param port The port definition\n * @param currentConnections Number of existing connections to this port\n * @param isSource Whether this port would be the source of the connection\n * @returns true if the connection is allowed\n */\nexport function canPortAcceptConnection(port, currentConnections, isSource) {\n // Check type compatibility\n if (isSource && port.type === 'input') {\n return false; // Input ports can't be sources\n }\n if (!isSource && port.type === 'output') {\n return false; // Output ports can't be targets\n }\n\n // Check connection limit\n if (port.maxConnections !== undefined && currentConnections >= port.maxConnections) {\n return false;\n }\n return true;\n}\n\n/**\n * Check if two ports can be connected.\n *\n * @param sourcePort The source port\n * @param targetPort The target port\n * @returns true if the connection is valid\n */\nexport function arePortsCompatible(sourcePort, targetPort) {\n // Source must allow outgoing connections\n if (sourcePort.type === 'input') {\n return false;\n }\n\n // Target must allow incoming connections\n if (targetPort.type === 'output') {\n return false;\n }\n return true;\n}","/**\n * Input Classifier\n *\n * Classifies pointer events into input sources (finger, pencil, mouse)\n * and extracts stylus-specific data (pressure, tilt).\n *\n * This is the foundation of the touch-first input architecture:\n * - Pencil draws/selects\n * - Fingers navigate (pan/zoom)\n * - Mouse does both\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Input device type */\n\n/** Classified pointer with source-specific metadata */\n\n/** Capabilities detected for the current device */\n\n// =============================================================================\n// Classification\n// =============================================================================\n\n/**\n * Classify a PointerEvent into an InputSource with metadata.\n *\n * Uses `PointerEvent.pointerType` as the primary signal:\n * - 'pen' → pencil (Apple Pencil, Surface Pen, Wacom, etc.)\n * - 'touch' → finger\n * - 'mouse' → mouse\n *\n * Falls back to 'mouse' for unknown pointer types.\n */\nexport function classifyPointer(e) {\n const source = pointerTypeToSource(e.pointerType);\n return {\n source,\n pointerId: e.pointerId,\n pressure: e.pressure,\n tiltX: e.tiltX,\n tiltY: e.tiltY,\n isPrimary: e.isPrimary,\n rawPointerType: e.pointerType\n };\n}\n\n/**\n * Map PointerEvent.pointerType string to InputSource.\n */\nfunction pointerTypeToSource(pointerType) {\n switch (pointerType) {\n case 'pen':\n return 'pencil';\n case 'touch':\n return 'finger';\n case 'mouse':\n return 'mouse';\n default:\n // Unknown pointer types (e.g. future devices) default to mouse behavior\n return 'mouse';\n }\n}\n\n// =============================================================================\n// Device Capability Detection\n// =============================================================================\n\n/**\n * Detect input capabilities of the current device.\n *\n * Uses media queries and navigator APIs for initial detection.\n * Note: `hasStylus` starts as false and is set to true on first pen event\n * (there's no reliable way to detect stylus support without an event).\n */\nexport function detectInputCapabilities() {\n if (typeof window === 'undefined') {\n // SSR: assume desktop defaults\n return {\n hasTouch: false,\n hasStylus: false,\n hasMouse: true,\n hasCoarsePointer: false\n };\n }\n const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n\n // matchMedia for pointer capabilities\n const supportsMatchMedia = typeof window.matchMedia === 'function';\n const hasCoarsePointer = supportsMatchMedia ? window.matchMedia('(pointer: coarse)').matches : false;\n const hasFinePointer = supportsMatchMedia ? window.matchMedia('(pointer: fine)').matches : true;\n\n // Heuristic: if we have both coarse and fine, likely a tablet with stylus support\n // But we won't confirm stylus until we see a pen event\n const hasMouse = hasFinePointer || !hasTouch;\n return {\n hasTouch,\n hasStylus: false,\n // Set to true on first pen event\n hasMouse,\n hasCoarsePointer\n };\n}\n\n// =============================================================================\n// Gesture Threshold Helpers\n// =============================================================================\n\n/** Threshold values per input source */\n\n/**\n * Get gesture thresholds appropriate for the given input source.\n *\n * Fingers need larger thresholds (imprecise, large contact area).\n * Stylus is the most precise.\n * Mouse is in between.\n */\nexport function getGestureThresholds(source) {\n switch (source) {\n case 'finger':\n return {\n dragThreshold: 10,\n tapThreshold: 10,\n longPressDuration: 600,\n longPressMoveLimit: 10\n };\n case 'pencil':\n return {\n dragThreshold: 2,\n tapThreshold: 3,\n longPressDuration: 500,\n longPressMoveLimit: 5\n };\n case 'mouse':\n return {\n dragThreshold: 3,\n tapThreshold: 5,\n longPressDuration: 0,\n // Mouse uses right-click instead\n longPressMoveLimit: 0\n };\n }\n}\n\n// =============================================================================\n// Hit Target Helpers\n// =============================================================================\n\n/** Minimum interactive target sizes per Apple HIG / Material Design */\nexport const HIT_TARGET_SIZES = {\n /** Minimum touch target (Apple HIG: 44pt) */\n finger: 44,\n /** Stylus target (precise, can use smaller targets) */\n pencil: 24,\n /** Mouse target (hover-discoverable, smallest) */\n mouse: 16\n};\n\n/**\n * Get the appropriate hit target size for the current input source.\n * Used to size invisible padding around small visual elements\n * (resize handles, ports, edge connection handles).\n */\nexport function getHitTargetSize(source) {\n return HIT_TARGET_SIZES[source];\n}","/**\n * Input Store\n *\n * Jotai atoms tracking active pointers, input sources, and device capabilities.\n * Components read these atoms to adapt behavior per input source.\n *\n * Key derived atoms:\n * - `primaryInputSourceAtom` — the last-used input source ('finger' | 'pencil' | 'mouse')\n * - `isStylusActiveAtom` — true when a pen pointer is currently down\n * - `isMultiTouchAtom` — true when 2+ fingers are touching\n */\n\nimport { atom } from 'jotai';\nimport { detectInputCapabilities } from './input-classifier';\n\n// =============================================================================\n// Core Atoms\n// =============================================================================\n\n/**\n * Map of all currently active (down) pointers.\n * Updated on pointer down/up/cancel events.\n */\nexport const activePointersAtom = atom(new Map());\n\n/**\n * The primary/last-used input source.\n * Updated whenever a pointer goes down — the most recent source wins.\n * Defaults to 'mouse' on desktop, 'finger' on mobile.\n */\nexport const primaryInputSourceAtom = atom('mouse');\n\n/**\n * Device input capabilities.\n * Initialized once on mount, updated when stylus is first detected.\n */\nexport const inputCapabilitiesAtom = atom(detectInputCapabilities());\n\n// =============================================================================\n// Derived Atoms\n// =============================================================================\n\n/**\n * Whether a stylus/pen is currently touching the screen.\n * When true, finger touches should be routed to pan/zoom only (palm rejection).\n */\nexport const isStylusActiveAtom = atom(get => {\n const pointers = get(activePointersAtom);\n for (const [, pointer] of pointers) {\n if (pointer.source === 'pencil') return true;\n }\n return false;\n});\n\n/**\n * Whether multiple fingers are currently touching.\n * When true, the gesture is likely a pinch or two-finger pan.\n */\nexport const isMultiTouchAtom = atom(get => {\n const pointers = get(activePointersAtom);\n let fingerCount = 0;\n for (const [, pointer] of pointers) {\n if (pointer.source === 'finger') fingerCount++;\n }\n return fingerCount > 1;\n});\n\n/**\n * Count of active finger pointers.\n */\nexport const fingerCountAtom = atom(get => {\n const pointers = get(activePointersAtom);\n let count = 0;\n for (const [, pointer] of pointers) {\n if (pointer.source === 'finger') count++;\n }\n return count;\n});\n\n/**\n * Whether the device primarily uses touch (tablet/phone).\n * Used for showing/hiding touch-specific UI (e.g., ViewportControls).\n */\nexport const isTouchDeviceAtom = atom(get => {\n const caps = get(inputCapabilitiesAtom);\n return caps.hasTouch;\n});\n\n// =============================================================================\n// Action Atoms\n// =============================================================================\n\n/**\n * Register a pointer down event.\n * Updates active pointers and primary input source.\n */\nexport const pointerDownAtom = atom(null, (get, set, pointer) => {\n const pointers = new Map(get(activePointersAtom));\n pointers.set(pointer.pointerId, pointer);\n set(activePointersAtom, pointers);\n set(primaryInputSourceAtom, pointer.source);\n\n // Auto-detect stylus capability on first pen event\n if (pointer.source === 'pencil') {\n const caps = get(inputCapabilitiesAtom);\n if (!caps.hasStylus) {\n set(inputCapabilitiesAtom, {\n ...caps,\n hasStylus: true\n });\n }\n }\n});\n\n/**\n * Unregister a pointer up/cancel event.\n */\nexport const pointerUpAtom = atom(null, (get, set, pointerId) => {\n const pointers = new Map(get(activePointersAtom));\n pointers.delete(pointerId);\n set(activePointersAtom, pointers);\n});\n\n/**\n * Clear all active pointers.\n * Call on blur or visibility change to prevent stuck pointers.\n */\nexport const clearPointersAtom = atom(null, (_get, set) => {\n set(activePointersAtom, new Map());\n});","/**\n * Selection Path Store\n *\n * Manages the active lasso/rect selection path during drag operations.\n * The gesture resolver already returns 'lasso-select' and 'rect-select' intents;\n * this store tracks the drawn path and resolves which nodes fall inside it.\n */\n\nimport { atom } from 'jotai';\nimport { uiNodesAtom } from './graph-derived';\nimport { selectedNodeIdsAtom } from './selection-store';\n\n// --- Types ---\n\n// --- Core Atoms ---\n\n/** The active selection path, or null when not selecting */\nexport const selectionPathAtom = atom(null);\n\n/** Whether a selection drag is currently in progress */\nexport const isSelectingAtom = atom(get => get(selectionPathAtom) !== null);\n\n// --- Actions ---\n\n/** Start a new selection path */\nexport const startSelectionAtom = atom(null, (_get, set, {\n type,\n point\n}) => {\n set(selectionPathAtom, {\n type,\n points: [point]\n });\n});\n\n/** Add a point to the current selection path */\nexport const updateSelectionAtom = atom(null, (get, set, point) => {\n const current = get(selectionPathAtom);\n if (!current) return;\n if (current.type === 'rect') {\n // For rect, keep only start point + current point\n set(selectionPathAtom, {\n ...current,\n points: [current.points[0], point]\n });\n } else {\n // For lasso, append the point\n set(selectionPathAtom, {\n ...current,\n points: [...current.points, point]\n });\n }\n});\n\n/** Cancel the active selection drag without changing selection. */\nexport const cancelSelectionAtom = atom(null, (_get, set) => {\n set(selectionPathAtom, null);\n});\n\n/** End selection: compute intersecting nodes, update selection, clear path */\nexport const endSelectionAtom = atom(null, (get, set) => {\n const path = get(selectionPathAtom);\n if (!path || path.points.length < 2) {\n set(selectionPathAtom, null);\n return;\n }\n const nodes = get(uiNodesAtom);\n const selectedIds = [];\n if (path.type === 'rect') {\n const [p1, p2] = [path.points[0], path.points[path.points.length - 1]];\n const minX = Math.min(p1.x, p2.x);\n const maxX = Math.max(p1.x, p2.x);\n const minY = Math.min(p1.y, p2.y);\n const maxY = Math.max(p1.y, p2.y);\n for (const node of nodes) {\n // AABB intersection: node overlaps selection rect\n const nodeRight = node.position.x + (node.width ?? 200);\n const nodeBottom = node.position.y + (node.height ?? 100);\n if (node.position.x < maxX && nodeRight > minX && node.position.y < maxY && nodeBottom > minY) {\n selectedIds.push(node.id);\n }\n }\n } else {\n // Lasso: point-in-polygon test on node center\n const polygon = path.points;\n for (const node of nodes) {\n const cx = node.position.x + (node.width ?? 200) / 2;\n const cy = node.position.y + (node.height ?? 100) / 2;\n if (pointInPolygon(cx, cy, polygon)) {\n selectedIds.push(node.id);\n }\n }\n }\n\n // Set selection to the intersecting nodes\n set(selectedNodeIdsAtom, new Set(selectedIds));\n set(selectionPathAtom, null);\n});\n\n// --- Derived: selection rect bounds (for rendering) ---\n\n/** For rect mode, compute the bounding box */\nexport const selectionRectAtom = atom(get => {\n const path = get(selectionPathAtom);\n if (!path || path.type !== 'rect' || path.points.length < 2) return null;\n const [p1, p2] = [path.points[0], path.points[path.points.length - 1]];\n return {\n x: Math.min(p1.x, p2.x),\n y: Math.min(p1.y, p2.y),\n width: Math.abs(p2.x - p1.x),\n height: Math.abs(p2.y - p1.y)\n };\n});\n\n// --- Utilities ---\n\n/**\n * Ray-casting point-in-polygon test.\n * Returns true if (px, py) is inside the polygon defined by points.\n */\nexport function pointInPolygon(px, py, polygon) {\n let inside = false;\n const n = polygon.length;\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = polygon[i].x;\n const yi = polygon[i].y;\n const xj = polygon[j].x;\n const yj = polygon[j].y;\n if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}","/**\n * Search Store\n *\n * Node and edge search with fuzzy multi-token matching.\n * Provides text search across node labels/types/IDs and edge labels/types\n * with result navigation and visual filter mode.\n */\n\nimport { atom } from 'jotai';\nimport { uiNodesAtom } from './graph-derived';\nimport { graphAtom, graphUpdateVersionAtom } from './graph-store';\nimport { centerOnNodeAtom } from './viewport-store';\nimport { selectSingleNodeAtom } from './selection-store';\n\n// =============================================================================\n// Search Query\n// =============================================================================\n\n/**\n * Current search query string.\n * Empty string = no active search.\n */\nexport const searchQueryAtom = atom('');\n\n/**\n * Set search query\n */\nexport const setSearchQueryAtom = atom(null, (_get, set, query) => {\n set(searchQueryAtom, query);\n set(highlightedSearchIndexAtom, 0);\n});\n\n/**\n * Clear search\n */\nexport const clearSearchAtom = atom(null, (_get, set) => {\n set(searchQueryAtom, '');\n set(highlightedSearchIndexAtom, 0);\n});\n\n// =============================================================================\n// Fuzzy Matching\n// =============================================================================\n\n/**\n * Check if ALL tokens in the query appear (in any order) within the haystack.\n * Tokens are split by whitespace. Each token must match as a substring.\n *\n * @example\n * fuzzyMatch(\"inp typ\", \"Input Type Node\") → true\n * fuzzyMatch(\"xyz\", \"Input Type Node\") → false\n */\nexport function fuzzyMatch(query, ...haystacks) {\n const tokens = query.toLowerCase().split(/\\s+/).filter(Boolean);\n if (tokens.length === 0) return false;\n const combined = haystacks.join(' ').toLowerCase();\n return tokens.every(token => combined.includes(token));\n}\n\n// =============================================================================\n// Node Search Results\n// =============================================================================\n\n/**\n * Derived: set of node IDs matching the current search query.\n * Uses fuzzy multi-token matching on label, node_type, and id.\n */\nexport const searchResultsAtom = atom(get => {\n const query = get(searchQueryAtom).trim();\n if (!query) return new Set();\n const nodes = get(uiNodesAtom);\n const matches = new Set();\n for (const node of nodes) {\n if (fuzzyMatch(query, node.label || '', node.dbData.node_type || '', node.id)) {\n matches.add(node.id);\n }\n }\n return matches;\n});\n\n/**\n * Derived: ordered array of matching node IDs (for navigation)\n */\nexport const searchResultsArrayAtom = atom(get => {\n return Array.from(get(searchResultsAtom));\n});\n\n/**\n * Derived: count of search results\n */\nexport const searchResultCountAtom = atom(get => {\n return get(searchResultsAtom).size;\n});\n\n// =============================================================================\n// Edge Search Results\n// =============================================================================\n\n/**\n * Derived: set of edge keys matching the current search query.\n * Matches on edge label, edge_type, and edge id.\n */\nexport const searchEdgeResultsAtom = atom(get => {\n const query = get(searchQueryAtom).trim();\n if (!query) return new Set();\n\n // Depend on graph version for reactivity\n get(graphUpdateVersionAtom);\n const graph = get(graphAtom);\n const matches = new Set();\n graph.forEachEdge((edgeKey, attrs) => {\n const label = attrs.label || '';\n const edgeType = attrs.dbData?.edge_type || '';\n if (fuzzyMatch(query, label, edgeType, edgeKey)) {\n matches.add(edgeKey);\n }\n });\n return matches;\n});\n\n/**\n * Derived: count of matching edges\n */\nexport const searchEdgeResultCountAtom = atom(get => {\n return get(searchEdgeResultsAtom).size;\n});\n\n// =============================================================================\n// Combined\n// =============================================================================\n\n/**\n * Whether a search filter is currently active\n */\nexport const isFilterActiveAtom = atom(get => {\n return get(searchQueryAtom).trim().length > 0;\n});\n\n/**\n * Total count of matching nodes + edges\n */\nexport const searchTotalResultCountAtom = atom(get => {\n return get(searchResultCountAtom) + get(searchEdgeResultCountAtom);\n});\n\n// =============================================================================\n// Result Navigation\n// =============================================================================\n\n/**\n * Index of the currently highlighted search result\n */\nexport const highlightedSearchIndexAtom = atom(0);\n\n/**\n * Navigate to the next search result\n */\nexport const nextSearchResultAtom = atom(null, (get, set) => {\n const results = get(searchResultsArrayAtom);\n if (results.length === 0) return;\n const currentIndex = get(highlightedSearchIndexAtom);\n const nextIndex = (currentIndex + 1) % results.length;\n set(highlightedSearchIndexAtom, nextIndex);\n const nodeId = results[nextIndex];\n set(centerOnNodeAtom, nodeId);\n set(selectSingleNodeAtom, nodeId);\n});\n\n/**\n * Navigate to the previous search result\n */\nexport const prevSearchResultAtom = atom(null, (get, set) => {\n const results = get(searchResultsArrayAtom);\n if (results.length === 0) return;\n const currentIndex = get(highlightedSearchIndexAtom);\n const prevIndex = (currentIndex - 1 + results.length) % results.length;\n set(highlightedSearchIndexAtom, prevIndex);\n const nodeId = results[prevIndex];\n set(centerOnNodeAtom, nodeId);\n set(selectSingleNodeAtom, nodeId);\n});\n\n/**\n * Get the currently highlighted node ID\n */\nexport const highlightedSearchNodeIdAtom = atom(get => {\n const results = get(searchResultsArrayAtom);\n if (results.length === 0) return null;\n const index = get(highlightedSearchIndexAtom);\n return results[index] ?? null;\n});","/**\n * Gesture Rules — Defaults, Labels & Merge\n *\n * Default gesture rule definitions and merge utilities.\n * Split from gesture-rules.ts for modularity.\n */\n\n// =============================================================================\n// Label Generation\n// =============================================================================\n\nconst MODIFIER_KEYS = ['shift', 'ctrl', 'alt', 'meta'];\nconst SOURCE_LABELS = {\n mouse: 'Mouse',\n pencil: 'Pencil',\n finger: 'Touch'\n};\nconst GESTURE_LABELS = {\n tap: 'Tap',\n 'double-tap': 'Double-tap',\n 'triple-tap': 'Triple-tap',\n drag: 'Drag',\n 'long-press': 'Long-press',\n 'right-click': 'Right-click',\n pinch: 'Pinch',\n scroll: 'Scroll'\n};\nconst TARGET_LABELS = {\n node: 'node',\n edge: 'edge',\n port: 'port',\n 'resize-handle': 'resize handle',\n background: 'background'\n};\nconst BUTTON_LABELS = {\n 0: 'Left',\n 1: 'Middle',\n 2: 'Right'\n};\n\n/**\n * Generate a human-readable label from a gesture pattern.\n */\nexport function formatRuleLabel(pattern) {\n const parts = [];\n\n // Modifiers first\n if (pattern.modifiers) {\n const mods = MODIFIER_KEYS.filter(k => pattern.modifiers[k]).map(k => k.charAt(0).toUpperCase() + k.slice(1));\n if (mods.length) parts.push(mods.join('+'));\n }\n\n // Button (only for non-left)\n if (pattern.button !== undefined && pattern.button !== 0) {\n parts.push(BUTTON_LABELS[pattern.button]);\n }\n\n // Source\n if (pattern.source) {\n parts.push(SOURCE_LABELS[pattern.source]);\n }\n\n // Gesture\n if (pattern.gesture) {\n parts.push(GESTURE_LABELS[pattern.gesture] ?? pattern.gesture);\n }\n\n // Target\n if (pattern.target) {\n parts.push('on ' + (TARGET_LABELS[pattern.target] ?? pattern.target));\n }\n if (parts.length === 0) return 'Any gesture';\n\n // Join with spaces, but use \" + \" before gesture if modifiers present\n if (pattern.modifiers) {\n const modCount = MODIFIER_KEYS.filter(k => pattern.modifiers[k]).length;\n if (modCount > 0 && parts.length > modCount) {\n const modPart = parts.slice(0, 1).join('');\n const rest = parts.slice(1).join(' ').toLowerCase();\n return `${modPart} + ${rest}`;\n }\n }\n return parts.join(' ');\n}\n\n// =============================================================================\n// Merge Utilities\n// =============================================================================\n\n/**\n * Merge consumer-provided rules with defaults.\n * Consumer rules override defaults with the same ID.\n * Consumer rules without matching IDs are appended.\n */\nexport function mergeRules(defaults, overrides) {\n const overrideMap = new Map(overrides.map(r => [r.id, r]));\n const result = [];\n\n // Apply overrides to matching defaults\n for (const rule of defaults) {\n const override = overrideMap.get(rule.id);\n if (override) {\n result.push(override);\n overrideMap.delete(rule.id);\n } else {\n result.push(rule);\n }\n }\n\n // Append remaining overrides (new rules)\n for (const rule of overrideMap.values()) {\n result.push(rule);\n }\n return result;\n}\n\n// =============================================================================\n// Default Rules\n// =============================================================================\n\n/**\n * Default gesture rules that replicate the current canvas behavior.\n */\nexport const DEFAULT_GESTURE_RULES = [\n// ── Tap gestures ──────────────────────────────────────────────\n{\n id: 'tap-node',\n pattern: {\n gesture: 'tap',\n target: 'node'\n },\n actionId: 'select-node'\n}, {\n id: 'tap-edge',\n pattern: {\n gesture: 'tap',\n target: 'edge'\n },\n actionId: 'select-edge'\n}, {\n id: 'tap-port',\n pattern: {\n gesture: 'tap',\n target: 'port'\n },\n actionId: 'select-node'\n}, {\n id: 'tap-bg',\n pattern: {\n gesture: 'tap',\n target: 'background'\n },\n actionId: 'clear-selection'\n},\n// ── Double-tap ────────────────────────────────────────────────\n{\n id: 'dtap-node',\n pattern: {\n gesture: 'double-tap',\n target: 'node'\n },\n actionId: 'fit-to-view'\n}, {\n id: 'dtap-bg',\n pattern: {\n gesture: 'double-tap',\n target: 'background'\n },\n actionId: 'fit-all-to-view'\n},\n// ── Triple-tap ────────────────────────────────────────────────\n{\n id: 'ttap-node',\n pattern: {\n gesture: 'triple-tap',\n target: 'node'\n },\n actionId: 'toggle-lock'\n},\n// ── Left-button drag ──────────────────────────────────────────\n{\n id: 'drag-node',\n pattern: {\n gesture: 'drag',\n target: 'node'\n },\n actionId: 'move-node'\n}, {\n id: 'drag-port',\n pattern: {\n gesture: 'drag',\n target: 'port'\n },\n actionId: 'create-edge'\n}, {\n id: 'drag-bg-finger',\n pattern: {\n gesture: 'drag',\n target: 'background',\n source: 'finger'\n },\n actionId: 'pan'\n}, {\n id: 'drag-bg-mouse',\n pattern: {\n gesture: 'drag',\n target: 'background',\n source: 'mouse'\n },\n actionId: 'pan'\n}, {\n id: 'drag-bg-pencil',\n pattern: {\n gesture: 'drag',\n target: 'background',\n source: 'pencil'\n },\n actionId: 'lasso-select'\n},\n// ── Shift+drag overrides ──────────────────────────────────────\n{\n id: 'shift-drag-bg',\n pattern: {\n gesture: 'drag',\n target: 'background',\n modifiers: {\n shift: true\n }\n },\n actionId: 'rect-select'\n},\n// ── Right-click tap (context menu) ────────────────────────────\n{\n id: 'rc-node',\n pattern: {\n gesture: 'tap',\n target: 'node',\n button: 2\n },\n actionId: 'open-context-menu'\n}, {\n id: 'rc-edge',\n pattern: {\n gesture: 'tap',\n target: 'edge',\n button: 2\n },\n actionId: 'open-context-menu'\n}, {\n id: 'rc-bg',\n pattern: {\n gesture: 'tap',\n target: 'background',\n button: 2\n },\n actionId: 'open-context-menu'\n},\n// ── Long-press ────────────────────────────────────────────────\n{\n id: 'lp-node',\n pattern: {\n gesture: 'long-press',\n target: 'node'\n },\n actionId: 'open-context-menu'\n}, {\n id: 'lp-bg-finger',\n pattern: {\n gesture: 'long-press',\n target: 'background',\n source: 'finger'\n },\n actionId: 'create-node'\n},\n// ── Right-button drag (defaults to none — consumers override) ─\n{\n id: 'rdrag-node',\n pattern: {\n gesture: 'drag',\n target: 'node',\n button: 2\n },\n actionId: 'none'\n}, {\n id: 'rdrag-bg',\n pattern: {\n gesture: 'drag',\n target: 'background',\n button: 2\n },\n actionId: 'none'\n},\n// ── Middle-button drag (defaults to none) ─────────────────────\n{\n id: 'mdrag-node',\n pattern: {\n gesture: 'drag',\n target: 'node',\n button: 1\n },\n actionId: 'none'\n}, {\n id: 'mdrag-bg',\n pattern: {\n gesture: 'drag',\n target: 'background',\n button: 1\n },\n actionId: 'none'\n},\n// ── Zoom ──────────────────────────────────────────────────────\n{\n id: 'pinch-bg',\n pattern: {\n gesture: 'pinch',\n target: 'background'\n },\n actionId: 'zoom'\n}, {\n id: 'scroll-any',\n pattern: {\n gesture: 'scroll'\n },\n actionId: 'zoom'\n},\n// ── Split ─────────────────────────────────────────────────────\n{\n id: 'pinch-node',\n pattern: {\n gesture: 'pinch',\n target: 'node'\n },\n actionId: 'split-node'\n}];","/**\n * Gesture Rules — Composable Event System\n *\n * A rule-based gesture resolution engine where ANY combination of\n * (button x modifier x source x gesture x target) can be mapped to any action.\n *\n * Resolution works by scoring each rule's pattern against the current gesture\n * descriptor. The most specific match wins, with automatic fallback to\n * less-specific rules.\n *\n * Types are in ./gesture-rules-types.ts\n * Defaults + labels + merge are in ./gesture-rules-defaults.ts\n */\n\n// Re-export all types for backward compat\n\n// Re-export defaults, labels, merge for backward compat\nexport { DEFAULT_GESTURE_RULES, mergeRules, formatRuleLabel } from './gesture-rules-defaults';\n\n// Re-export the index type\n\n// =============================================================================\n// Specificity Scoring\n// =============================================================================\n\nconst MODIFIER_KEYS = ['shift', 'ctrl', 'alt', 'meta'];\n\n/**\n * Calculate how specifically a pattern matches a descriptor.\n *\n * Returns -1 if the pattern does NOT match.\n * Returns 0+ for a match, where higher = more specific.\n *\n * Scoring:\n * gesture: +32 (most important dimension)\n * target: +16\n * modifiers: +8 per matching modifier flag\n * source: +4\n * button: +2\n */\nexport function matchSpecificity(pattern, desc) {\n let score = 0;\n if (pattern.gesture !== undefined) {\n if (pattern.gesture !== desc.gesture) return -1;\n score += 32;\n }\n if (pattern.target !== undefined) {\n if (pattern.target !== desc.target) return -1;\n score += 16;\n }\n if (pattern.source !== undefined) {\n if (pattern.source !== desc.source) return -1;\n score += 4;\n }\n if (pattern.button !== undefined) {\n if (pattern.button !== (desc.button ?? 0)) return -1;\n score += 2;\n }\n if (pattern.modifiers !== undefined) {\n const dm = desc.modifiers ?? {};\n for (const key of MODIFIER_KEYS) {\n const required = pattern.modifiers[key];\n if (required === undefined) continue;\n const actual = dm[key] ?? false;\n if (required !== actual) return -1;\n score += 8;\n }\n }\n return score;\n}\n\n// =============================================================================\n// Resolver\n// =============================================================================\n\n/** Sentinel rule for palm-rejected gestures */\nconst PALM_REJECTION_RULE = {\n id: '__palm-rejection__',\n pattern: {},\n actionId: 'none',\n label: 'Palm rejection'\n};\n\n/**\n * Resolve a gesture descriptor against a rule set.\n *\n * 1. Apply palm rejection (finger + stylus active → remap)\n * 2. Score every rule against the (possibly transformed) descriptor\n * 3. Pick highest specificity; break ties with rule.priority\n * 4. Return resolved action or null if no match\n */\nexport function resolveGesture(desc, rules, options) {\n const palmRejection = options?.palmRejection !== false;\n\n // Palm rejection: when stylus is active, finger touches become\n // navigation-only (taps → none, drags on nodes → pan)\n if (palmRejection && desc.isStylusActive && desc.source === 'finger') {\n if (desc.gesture === 'tap' || desc.gesture === 'long-press' || desc.gesture === 'double-tap' || desc.gesture === 'triple-tap') {\n return {\n actionId: 'none',\n rule: PALM_REJECTION_RULE,\n score: Infinity\n };\n }\n if (desc.gesture === 'drag' && desc.target !== 'background') {\n // Re-resolve as background pan\n return resolveGesture({\n ...desc,\n target: 'background',\n isStylusActive: false\n }, rules, {\n palmRejection: false\n });\n }\n }\n let best = null;\n for (const rule of rules) {\n const specificity = matchSpecificity(rule.pattern, desc);\n if (specificity < 0) continue;\n\n // Combine specificity with priority for final score\n const effectiveScore = specificity * 1000 + (rule.priority ?? 0);\n if (!best || effectiveScore > best.score) {\n best = {\n actionId: rule.actionId,\n rule,\n score: effectiveScore\n };\n }\n }\n return best;\n}\n\n// =============================================================================\n// Rule Index (for fast lookup)\n// =============================================================================\n\nexport function buildRuleIndex(rules) {\n const buckets = new Map();\n const wildcardRules = [];\n for (const rule of rules) {\n const key = rule.pattern.gesture;\n if (key === undefined) {\n wildcardRules.push(rule);\n } else {\n const bucket = buckets.get(key);\n if (bucket) {\n bucket.push(rule);\n } else {\n buckets.set(key, [rule]);\n }\n }\n }\n\n // Pre-concatenate wildcard rules into each gesture bucket\n const index = new Map();\n if (wildcardRules.length > 0) {\n for (const [key, bucket] of buckets) {\n index.set(key, bucket.concat(wildcardRules));\n }\n index.set('__wildcard__', wildcardRules);\n } else {\n for (const [key, bucket] of buckets) {\n index.set(key, bucket);\n }\n }\n return index;\n}\n\n/**\n * Resolve using an indexed rule set (faster for large rule sets).\n */\nexport function resolveGestureIndexed(desc, index, options) {\n const rules = index.get(desc.gesture) ?? index.get('__wildcard__') ?? [];\n return resolveGesture(desc, rules, options);\n}","/**\n * Gesture Rule Store\n *\n * Jotai atoms for managing gesture rules with localStorage persistence.\n * Provides CRUD operations and an indexed lookup for fast resolution.\n */\n\nimport { atom } from 'jotai';\nimport { atomWithStorage } from 'jotai/utils';\nimport { DEFAULT_GESTURE_RULES, buildRuleIndex, mergeRules } from './gesture-rules';\n\n// =============================================================================\n// Persisted State\n// =============================================================================\n\nconst DEFAULT_RULE_STATE = {\n customRules: [],\n palmRejection: true\n};\n\n/**\n * Persisted gesture rule settings.\n * Only stores user customizations — defaults are applied at runtime.\n */\nexport const gestureRuleSettingsAtom = atomWithStorage('canvas-gesture-rules', DEFAULT_RULE_STATE);\n\n// =============================================================================\n// Runtime Rules (merged defaults + custom)\n// =============================================================================\n\n/**\n * Consumer-provided rule overrides (set via Canvas props).\n * These are NOT persisted — they come from the component tree.\n */\nexport const consumerGestureRulesAtom = atom([]);\n\n/**\n * The effective rule set: defaults + persisted custom + consumer overrides.\n * Consumer rules take highest priority (applied last).\n */\nexport const gestureRulesAtom = atom(get => {\n const settings = get(gestureRuleSettingsAtom);\n const consumerRules = get(consumerGestureRulesAtom);\n\n // Layer 1: Start with defaults\n // Layer 2: Apply persisted user customizations\n let rules = mergeRules(DEFAULT_GESTURE_RULES, settings.customRules);\n // Layer 3: Apply consumer-provided overrides\n if (consumerRules.length > 0) {\n rules = mergeRules(rules, consumerRules);\n }\n return rules;\n});\n\n/**\n * Indexed rule set for fast resolution.\n * Recomputes only when rules change.\n */\nexport const gestureRuleIndexAtom = atom(get => {\n return buildRuleIndex(get(gestureRulesAtom));\n});\n\n/**\n * Palm rejection toggle.\n */\nexport const palmRejectionEnabledAtom = atom(get => get(gestureRuleSettingsAtom).palmRejection, (get, set, enabled) => {\n const current = get(gestureRuleSettingsAtom);\n set(gestureRuleSettingsAtom, {\n ...current,\n palmRejection: enabled\n });\n});\n\n// =============================================================================\n// CRUD Atoms\n// =============================================================================\n\n/**\n * Add or replace a custom gesture rule.\n * If a rule with the same ID exists, it's replaced.\n */\nexport const addGestureRuleAtom = atom(null, (get, set, rule) => {\n const current = get(gestureRuleSettingsAtom);\n const existing = current.customRules.findIndex(r => r.id === rule.id);\n const newRules = [...current.customRules];\n if (existing >= 0) {\n newRules[existing] = rule;\n } else {\n newRules.push(rule);\n }\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: newRules\n });\n});\n\n/**\n * Remove a custom gesture rule by ID.\n */\nexport const removeGestureRuleAtom = atom(null, (get, set, ruleId) => {\n const current = get(gestureRuleSettingsAtom);\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: current.customRules.filter(r => r.id !== ruleId)\n });\n});\n\n/**\n * Update an existing custom gesture rule.\n */\nexport const updateGestureRuleAtom = atom(null, (get, set, {\n id,\n updates\n}) => {\n const current = get(gestureRuleSettingsAtom);\n const index = current.customRules.findIndex(r => r.id === id);\n if (index < 0) return;\n const newRules = [...current.customRules];\n newRules[index] = {\n ...newRules[index],\n ...updates\n };\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: newRules\n });\n});\n\n/**\n * Reset all custom rules (revert to defaults).\n */\nexport const resetGestureRulesAtom = atom(null, (get, set) => {\n const current = get(gestureRuleSettingsAtom);\n set(gestureRuleSettingsAtom, {\n ...current,\n customRules: []\n });\n});","/**\n * External Keyboard Store\n *\n * Detects whether an external keyboard is connected to a touch device.\n * When detected, modifier-key actions become available via keyboard\n * shortcuts, so the TouchActionButton can be hidden.\n *\n * Detection: On touch devices, the first physical key event (not\n * on-screen keyboard) sets `hasExternalKeyboardAtom` to true.\n * Only meaningful when `isTouchDeviceAtom` is true — on desktop,\n * keyboard is always assumed.\n */\n\nimport { atom } from 'jotai';\n\n/**\n * Whether an external keyboard has been detected on a touch device.\n * Set to true on first `keydown` event on a touch-capable device.\n */\nexport const hasExternalKeyboardAtom = atom(false);\n\n/**\n * Effect atom: listens for keydown events on touch devices.\n * Once detected, stops listening (permanent for the session).\n */\nexport const watchExternalKeyboardAtom = atom(null, (get, set) => {\n if (typeof window === 'undefined') return;\n const handler = e => {\n // Ignore virtual keyboard keys (typically modifier-only events)\n // A real keyboard sends identifiable key values\n if (e.key && e.key.length === 1 || ['Tab', 'Escape', 'Enter', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {\n set(hasExternalKeyboardAtom, true);\n window.removeEventListener('keydown', handler);\n }\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n});","/**\n * Plugin Types\n *\n * Type definitions for the canvas plugin system.\n * A plugin is a declarative manifest that bundles registrations\n * across all canvas subsystems (node types, commands, actions,\n * gesture contexts, edge calculators).\n */\n\n// =============================================================================\n// Plugin Definition\n// =============================================================================\n\n/**\n * A canvas plugin bundles registrations across all subsystems.\n *\n * @example\n * ```ts\n * const myPlugin: CanvasPlugin = {\n * id: 'my-plugin',\n * name: 'My Plugin',\n * nodeTypes: { 'custom-node': CustomNodeComponent },\n * commands: [myCommand],\n * gestureContexts: [myGestureContext],\n * };\n * ```\n */\n\n// =============================================================================\n// Plugin Context\n// =============================================================================\n\n/**\n * Context passed to plugin lifecycle hooks.\n */\n\n// =============================================================================\n// Plugin State\n// =============================================================================\n\n/** Internal state for a registered plugin */\n\n// =============================================================================\n// Errors\n// =============================================================================\n\nexport class PluginError extends Error {\n constructor(message, pluginId, code) {\n super(`[Plugin \"${pluginId}\"] ${message}`);\n this.pluginId = pluginId;\n this.code = code;\n this.name = 'PluginError';\n }\n}","/**\n * Gesture System v2 — Core Types\n *\n * Single source of truth for every type in the gesture pipeline.\n * No runtime code — pure type definitions.\n */\n\n// =============================================================================\n// Layer 1: Normalize\n// =============================================================================\n\nexport const NO_MODIFIERS = Object.freeze({\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n});\nexport const NO_HELD_KEYS = Object.freeze({\n byKey: Object.freeze({}),\n byCode: Object.freeze({})\n});\n\n// =============================================================================\n// Layer 2: Recognize\n// =============================================================================\n\n// =============================================================================\n// Layer 2: Timed State\n// =============================================================================\n\n// =============================================================================\n// Layer 3: Resolve\n// =============================================================================\n\n// =============================================================================\n// Layer 4: Dispatch\n// =============================================================================\n\n/**\n * Action handler. Simple function form fires only on 'start' and 'instant'.\n * Object form routes each phase to a dedicated method.\n */\n\nexport function isKeyInputEvent(event) {\n return event.kind === 'key';\n}\nexport function isPointerGestureEvent(event) {\n return event.kind !== 'key';\n}\n\n// =============================================================================\n// Re-exports for convenience\n// =============================================================================","/**\n * Layer 4: Gesture Dispatcher\n *\n * Routes resolved actions to registered handlers, respecting input phase.\n * Simple function handlers fire only on pointer 'start'/'instant' and key 'down'.\n * Object handlers route each phase to a dedicated method.\n */\n\nimport { isKeyInputEvent } from './types';\n\n// =============================================================================\n// Action Registry\n// =============================================================================\n\nconst handlers = new Map();\n\n/**\n * Register an action handler. Overwrites any existing handler for the same ID.\n */\nexport function registerAction(actionId, handler) {\n handlers.set(actionId, handler);\n}\n\n/**\n * Remove a registered action handler.\n */\nexport function unregisterAction(actionId) {\n handlers.delete(actionId);\n}\n\n/**\n * Get a registered handler (for testing/introspection).\n */\nexport function getHandler(actionId) {\n return handlers.get(actionId);\n}\n\n/**\n * Clear all registered handlers (for testing).\n */\nexport function clearHandlers() {\n handlers.clear();\n}\n\n// =============================================================================\n// Dispatch\n// =============================================================================\n\n/**\n * Dispatch a resolved gesture event to its action handler.\n *\n * Returns true if a handler was found and invoked, false otherwise.\n * The 'none' action ID is always a no-op — it means the binding\n * intentionally blocks the gesture without executing anything.\n */\nexport function dispatch(event, resolution) {\n if (resolution.actionId === 'none') return true;\n const handler = handlers.get(resolution.actionId);\n if (!handler) return false;\n if (typeof handler === 'function') {\n // Simple handler: fire on pointer start/instant and key down.\n if (isKeyInputEvent(event) && event.phase === 'down' || !isKeyInputEvent(event) && (event.phase === 'start' || event.phase === 'instant')) {\n handler(event);\n }\n return true;\n }\n\n // Phase-aware handler\n routePhase(handler, event.phase, event);\n return true;\n}\nfunction routePhase(handler, phase, event) {\n if (isKeyInputEvent(event)) {\n routeKeyPhase(handler, phase, event);\n return;\n }\n switch (phase) {\n case 'start':\n handler.onStart?.(event);\n break;\n case 'move':\n handler.onMove?.(event);\n break;\n case 'end':\n handler.onEnd?.(event);\n break;\n case 'instant':\n handler.onInstant?.(event);\n break;\n case 'cancel':\n handler.onCancel?.(event);\n break;\n }\n}\nfunction routeKeyPhase(handler, phase, event) {\n switch (phase) {\n case 'down':\n handler.onDown?.(event);\n break;\n case 'up':\n handler.onUp?.(event);\n break;\n }\n}","/**\n * Command Registry\n *\n * Singleton class for managing all available commands.\n * Commands can be registered by the canvas package (built-ins)\n * or by consuming apps (custom commands).\n */\n\n/**\n * Command Registry - Singleton class for managing all available commands.\n *\n * Usage:\n * ```typescript\n * import { commandRegistry } from '@blinksgg/canvas';\n *\n * // Register a command\n * commandRegistry.register(myCommand);\n *\n * // Get a command by name or alias\n * const cmd = commandRegistry.get('createNode'); // or 'cn'\n *\n * // Search commands\n * const results = commandRegistry.search('node');\n * ```\n */\nclass CommandRegistry {\n commands = new Map();\n aliases = new Map(); // alias -> command name\n\n /**\n * Register a command with the registry.\n * @param command The command definition to register\n * @throws Error if command name or alias already exists\n */\n register(command) {\n if (this.commands.has(command.name)) {\n throw new Error(`Command \"${command.name}\" is already registered`);\n }\n this.commands.set(command.name, command);\n\n // Register aliases\n if (command.aliases) {\n for (const alias of command.aliases) {\n if (this.aliases.has(alias)) {\n throw new Error(`Alias \"${alias}\" is already registered for command \"${this.aliases.get(alias)}\"`);\n }\n if (this.commands.has(alias)) {\n throw new Error(`Alias \"${alias}\" conflicts with existing command name`);\n }\n this.aliases.set(alias, command.name);\n }\n }\n }\n\n /**\n * Unregister a command by name.\n * @param name The command name to remove\n */\n unregister(name) {\n const command = this.commands.get(name);\n if (command) {\n // Remove aliases\n if (command.aliases) {\n for (const alias of command.aliases) {\n this.aliases.delete(alias);\n }\n }\n this.commands.delete(name);\n }\n }\n\n /**\n * Get a command by name or alias.\n * @param nameOrAlias Command name or alias\n * @returns The command definition or undefined if not found\n */\n get(nameOrAlias) {\n // Check if it's a direct command name\n const direct = this.commands.get(nameOrAlias);\n if (direct) return direct;\n\n // Check if it's an alias\n const commandName = this.aliases.get(nameOrAlias);\n if (commandName) {\n return this.commands.get(commandName);\n }\n return undefined;\n }\n\n /**\n * Check if a command exists by name or alias.\n * @param nameOrAlias Command name or alias\n */\n has(nameOrAlias) {\n return this.commands.has(nameOrAlias) || this.aliases.has(nameOrAlias);\n }\n\n /**\n * Search for commands matching a query.\n * Searches command names, aliases, and descriptions.\n * @param query Search query (case-insensitive)\n * @returns Array of matching commands, sorted by relevance\n */\n search(query) {\n if (!query.trim()) {\n return this.all();\n }\n const lowerQuery = query.toLowerCase().trim();\n const results = [];\n const commands = Array.from(this.commands.values());\n for (const command of commands) {\n let score = 0;\n\n // Exact name match (highest priority)\n if (command.name.toLowerCase() === lowerQuery) {\n score = 100;\n }\n // Name starts with query\n else if (command.name.toLowerCase().startsWith(lowerQuery)) {\n score = 80;\n }\n // Name contains query\n else if (command.name.toLowerCase().includes(lowerQuery)) {\n score = 60;\n }\n // Alias exact match\n else if (command.aliases?.some(a => a.toLowerCase() === lowerQuery)) {\n score = 90;\n }\n // Alias starts with query\n else if (command.aliases?.some(a => a.toLowerCase().startsWith(lowerQuery))) {\n score = 70;\n }\n // Alias contains query\n else if (command.aliases?.some(a => a.toLowerCase().includes(lowerQuery))) {\n score = 50;\n }\n // Description contains query\n else if (command.description.toLowerCase().includes(lowerQuery)) {\n score = 30;\n }\n if (score > 0) {\n results.push({\n command,\n score\n });\n }\n }\n\n // Sort by score (descending), then alphabetically\n return results.sort((a, b) => b.score - a.score || a.command.name.localeCompare(b.command.name)).map(r => r.command);\n }\n\n /**\n * Get all registered commands.\n * @returns Array of all commands, sorted alphabetically by name\n */\n all() {\n return Array.from(this.commands.values()).sort((a, b) => a.name.localeCompare(b.name));\n }\n\n /**\n * Get commands by category.\n * @param category The category to filter by\n * @returns Array of commands in the category\n */\n byCategory(category) {\n return this.all().filter(cmd => cmd.category === category);\n }\n\n /**\n * Get all available categories.\n * @returns Array of unique categories\n */\n categories() {\n const categories = new Set();\n const commands = Array.from(this.commands.values());\n for (const command of commands) {\n categories.add(command.category);\n }\n return Array.from(categories).sort();\n }\n\n /**\n * Get the count of registered commands.\n */\n get size() {\n return this.commands.size;\n }\n\n /**\n * Clear all registered commands.\n * Useful for testing.\n */\n clear() {\n this.commands.clear();\n this.aliases.clear();\n }\n\n /**\n * Get a serializable list of commands for API responses.\n */\n toJSON() {\n return this.all().map(cmd => ({\n name: cmd.name,\n aliases: cmd.aliases || [],\n description: cmd.description,\n category: cmd.category,\n inputs: cmd.inputs.map(input => ({\n name: input.name,\n type: input.type,\n prompt: input.prompt,\n required: input.required !== false\n }))\n }));\n }\n}\n\n// Singleton instance\nexport const commandRegistry = new CommandRegistry();\n\n// Default export for convenience\nexport default commandRegistry;\n\n// Helper function for registering commands\nexport function registerCommand(command) {\n commandRegistry.register(command);\n}","/**\n * Edge Path Registry\n *\n * Extensible registry for custom edge path calculators.\n * Built-in calculators are resolved first, then custom ones.\n * Used by the plugin system to allow plugins to add new edge path types.\n */\n\nimport { getEdgePathCalculator as getBuiltInCalculator } from './edge-path-calculators';\nconst customCalculators = new Map();\n\n/**\n * Register a custom edge path calculator.\n * Custom calculators take precedence over built-in ones with the same name.\n */\nexport function registerEdgePathCalculator(name, calculator) {\n customCalculators.set(name, calculator);\n}\n\n/**\n * Unregister a custom edge path calculator.\n */\nexport function unregisterEdgePathCalculator(name) {\n return customCalculators.delete(name);\n}\n\n/**\n * Get an edge path calculator by name.\n * Checks custom calculators first, then falls back to built-in ones.\n */\nexport function resolveEdgePathCalculator(name) {\n return customCalculators.get(name) ?? getBuiltInCalculator(name);\n}\n\n/**\n * Check if a custom calculator is registered.\n */\nexport function hasCustomEdgePathCalculator(name) {\n return customCalculators.has(name);\n}\n\n/**\n * Get all registered custom calculator names.\n */\nexport function getCustomEdgePathCalculatorNames() {\n return Array.from(customCalculators.keys());\n}\n\n/**\n * Clear all custom calculators. Mainly for testing.\n */\nexport function clearCustomEdgePathCalculators() {\n customCalculators.clear();\n}","/**\n * Plugin Registry\n *\n * Central registry for canvas plugins. Handles:\n * - Registration with dependency resolution\n * - Conflict detection across all subsystems\n * - Atomic registration (all-or-nothing)\n * - Cleanup on unregister\n */\n\nimport { PluginError } from './plugin-types';\nimport { registerNodeTypes, unregisterNodeType } from './node-type-registry';\nimport { registerAction as registerEventAction, unregisterAction as unregisterEventAction } from './action-registry';\nimport { registerAction as registerGestureAction, unregisterAction as unregisterGestureAction } from '../gestures/dispatcher';\nimport { commandRegistry } from '../commands/registry';\nimport { registerEdgePathCalculator, unregisterEdgePathCalculator } from '../utils/edge-path-registry';\nimport { createDebug } from '../utils/debug';\nconst debug = createDebug('plugins');\n\n// =============================================================================\n// Registry\n// =============================================================================\n\nconst plugins = new Map();\n\n/**\n * Register a plugin. All capabilities are registered atomically.\n *\n * @throws {PluginError} ALREADY_REGISTERED — plugin ID already in use\n * @throws {PluginError} MISSING_DEPENDENCY — required plugin not registered\n * @throws {PluginError} CONFLICT — duplicate node type, action, command, or calculator\n *\n * @example\n * ```ts\n * registerPlugin({\n * id: 'my-plugin',\n * name: 'My Plugin',\n * nodeTypes: { 'custom': CustomNode },\n * commands: [myCommand],\n * });\n * ```\n */\nexport function registerPlugin(plugin) {\n debug('Registering plugin: %s', plugin.id);\n\n // 1. Check not already registered\n if (plugins.has(plugin.id)) {\n throw new PluginError('Plugin is already registered', plugin.id, 'ALREADY_REGISTERED');\n }\n\n // 2. Check dependencies\n if (plugin.dependencies) {\n for (const depId of plugin.dependencies) {\n if (!plugins.has(depId)) {\n throw new PluginError(`Missing dependency: \"${depId}\"`, plugin.id, 'MISSING_DEPENDENCY');\n }\n }\n }\n\n // 3. Check for conflicts before registering anything\n detectConflicts(plugin);\n\n // 4. Register all capabilities\n const cleanups = [];\n try {\n // Node types\n if (plugin.nodeTypes) {\n const nodeTypeNames = Object.keys(plugin.nodeTypes);\n registerNodeTypes(plugin.nodeTypes);\n cleanups.push(() => {\n for (const name of nodeTypeNames) {\n unregisterNodeType(name);\n }\n });\n }\n\n // Edge path calculators\n if (plugin.edgePathCalculators) {\n for (const [name, calc] of Object.entries(plugin.edgePathCalculators)) {\n registerEdgePathCalculator(name, calc);\n cleanups.push(() => unregisterEdgePathCalculator(name));\n }\n }\n\n // Gesture action handlers\n if (plugin.actionHandlers) {\n for (const [actionId, handler] of Object.entries(plugin.actionHandlers)) {\n registerGestureAction(actionId, handler);\n cleanups.push(() => unregisterGestureAction(actionId));\n }\n }\n\n // Gesture contexts are stored on the plugin — consumers read them\n // via getPluginGestureContexts() and merge them into the mapping index.\n\n // Commands\n if (plugin.commands) {\n for (const cmd of plugin.commands) {\n commandRegistry.register(cmd);\n cleanups.push(() => commandRegistry.unregister(cmd.name));\n }\n }\n\n // Event-action definitions\n if (plugin.actions) {\n for (const action of plugin.actions) {\n registerEventAction(action);\n cleanups.push(() => unregisterEventAction(action.id));\n }\n }\n\n // 5. Lifecycle hook\n let lifecycleCleanup = null;\n if (plugin.onRegister) {\n const ctx = makePluginContext(plugin.id);\n try {\n const result = plugin.onRegister(ctx);\n if (typeof result === 'function') {\n lifecycleCleanup = result;\n }\n } catch (err) {\n // Rollback all registrations on lifecycle error\n for (const cleanup of cleanups.reverse()) {\n try {\n cleanup();\n } catch {/* swallow cleanup errors */}\n }\n throw new PluginError(`onRegister failed: ${err instanceof Error ? err.message : String(err)}`, plugin.id, 'LIFECYCLE_ERROR');\n }\n }\n\n // 6. Store registration\n plugins.set(plugin.id, {\n plugin,\n cleanup: () => {\n for (const cleanup of cleanups.reverse()) {\n try {\n cleanup();\n } catch {/* swallow cleanup errors */}\n }\n if (lifecycleCleanup) {\n try {\n lifecycleCleanup();\n } catch {/* swallow */}\n }\n },\n registeredAt: Date.now()\n });\n debug('Plugin registered: %s (%d node types, %d commands, %d actions)', plugin.id, Object.keys(plugin.nodeTypes ?? {}).length, plugin.commands?.length ?? 0, plugin.actions?.length ?? 0);\n } catch (err) {\n if (err instanceof PluginError) throw err;\n // Rollback on unexpected error\n for (const cleanup of cleanups.reverse()) {\n try {\n cleanup();\n } catch {/* swallow */}\n }\n throw err;\n }\n}\n\n/**\n * Unregister a plugin and clean up all its registrations.\n *\n * @throws {PluginError} NOT_FOUND — plugin not registered\n * @throws {PluginError} CONFLICT — other plugins depend on this one\n */\nexport function unregisterPlugin(pluginId) {\n const registration = plugins.get(pluginId);\n if (!registration) {\n throw new PluginError('Plugin is not registered', pluginId, 'NOT_FOUND');\n }\n\n // Check no other plugin depends on this one\n for (const [otherId, other] of plugins) {\n if (other.plugin.dependencies?.includes(pluginId)) {\n throw new PluginError(`Cannot unregister: plugin \"${otherId}\" depends on it`, pluginId, 'CONFLICT');\n }\n }\n\n // Run cleanup\n if (registration.cleanup) {\n registration.cleanup();\n }\n plugins.delete(pluginId);\n debug('Plugin unregistered: %s', pluginId);\n}\n\n// =============================================================================\n// Queries\n// =============================================================================\n\n/** Get a registered plugin by ID */\nexport function getPlugin(id) {\n return plugins.get(id)?.plugin;\n}\n\n/** Check if a plugin is registered */\nexport function hasPlugin(id) {\n return plugins.has(id);\n}\n\n/** Get all registered plugins */\nexport function getAllPlugins() {\n return Array.from(plugins.values()).map(r => r.plugin);\n}\n\n/** Get all registered plugin IDs */\nexport function getPluginIds() {\n return Array.from(plugins.keys());\n}\n\n/**\n * Get all gesture contexts contributed by plugins.\n * Used by GestureProvider to merge plugin contexts into the mapping index.\n */\nexport function getPluginGestureContexts() {\n const contexts = [];\n for (const registration of plugins.values()) {\n if (registration.plugin.gestureContexts) {\n contexts.push(...registration.plugin.gestureContexts);\n }\n }\n return contexts;\n}\n\n/** Clear all plugins. Mainly for testing. */\nexport function clearPlugins() {\n // Unregister in reverse order (respect dependencies)\n const ids = Array.from(plugins.keys()).reverse();\n for (const id of ids) {\n const reg = plugins.get(id);\n if (reg?.cleanup) {\n try {\n reg.cleanup();\n } catch {/* swallow */}\n }\n plugins.delete(id);\n }\n debug('All plugins cleared');\n}\n\n// =============================================================================\n// Conflict Detection\n// =============================================================================\n\nfunction detectConflicts(plugin) {\n // Check command name conflicts\n if (plugin.commands) {\n for (const cmd of plugin.commands) {\n if (commandRegistry.has(cmd.name)) {\n throw new PluginError(`Command \"${cmd.name}\" is already registered`, plugin.id, 'CONFLICT');\n }\n }\n }\n\n // Check edge path calculator conflicts\n if (plugin.edgePathCalculators) {\n for (const name of Object.keys(plugin.edgePathCalculators)) {\n // Built-in types are fine to shadow (plugin overrides)\n // Only conflict with other plugins\n for (const [otherId, other] of plugins) {\n if (other.plugin.edgePathCalculators?.[name]) {\n throw new PluginError(`Edge path calculator \"${name}\" already registered by plugin \"${otherId}\"`, plugin.id, 'CONFLICT');\n }\n }\n }\n }\n\n // Check node type conflicts between plugins\n if (plugin.nodeTypes) {\n for (const nodeType of Object.keys(plugin.nodeTypes)) {\n for (const [otherId, other] of plugins) {\n if (other.plugin.nodeTypes?.[nodeType]) {\n throw new PluginError(`Node type \"${nodeType}\" already registered by plugin \"${otherId}\"`, plugin.id, 'CONFLICT');\n }\n }\n }\n }\n\n // Check action handler conflicts between plugins\n if (plugin.actionHandlers) {\n for (const actionId of Object.keys(plugin.actionHandlers)) {\n for (const [otherId, other] of plugins) {\n if (other.plugin.actionHandlers?.[actionId]) {\n throw new PluginError(`Action handler \"${actionId}\" already registered by plugin \"${otherId}\"`, plugin.id, 'CONFLICT');\n }\n }\n }\n }\n}\n\n// =============================================================================\n// Internal Helpers\n// =============================================================================\n\nfunction makePluginContext(pluginId) {\n return {\n pluginId,\n getPlugin,\n hasPlugin\n };\n}"],"mappings":"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","names":["atom","Graph","atom","debug","atom","Graph","atom","atomFamily","atom","atom","debug","atom","FitToBoundsMode","atom","atom","atom","debug","atom","atom","atom","atomFamily","graph","atom","Graph","atom","atom","debug","atom","atom","debug","atom","debug","atom","Graph","atom","debug","atom","atom","atom","atom","atom","atom","CanvasEventType","ActionCategory","debug","atom","debug","atom","Graph","Graph","atom","debug","atom","calculateBounds","atom","atom","options","atom","atom","atom","atom","atom","atom","MODIFIER_KEYS","atom","atomWithStorage","atomWithStorage","atom","atom","registerAction","unregisterAction","debug","registerAction","unregisterAction"]}