"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/utils/index.ts var index_exports = {}; __export(index_exports, { FitToBoundsMode: () => FitToBoundsMode, areNodesClose: () => areNodesClose, bezierHorizontal: () => bezierHorizontal, bezierSmart: () => bezierSmart, bezierVertical: () => bezierVertical, calculateBounds: () => calculateBounds, checkNodesOverlap: () => checkNodesOverlap, clearCustomEdgePathCalculators: () => clearCustomEdgePathCalculators, clearPendingState: () => clearPendingState, createComponentRegistry: () => createComponentRegistry, createDebug: () => createDebug, createFallbackComponent: () => createFallbackComponent, debug: () => debug, defaultEdgePathCalculator: () => defaultEdgePathCalculator, getCustomEdgePathCalculatorNames: () => getCustomEdgePathCalculatorNames, getEdgePathCalculator: () => getEdgePathCalculator, getNodeBounds: () => getNodeBounds, getNodeCenter: () => getNodeCenter, getNodeGestureConfig: () => getNodeGestureConfig, getPendingState: () => getPendingState, getViewportGestureConfig: () => getViewportGestureConfig, hasCustomEdgePathCalculator: () => hasCustomEdgePathCalculator, hasPendingMutations: () => hasPendingMutations, hitTestNode: () => hitTestNode, hitTestPort: () => hitTestPort, pendingNodeMutations: () => pendingNodeMutations, registerEdgePathCalculator: () => registerEdgePathCalculator, resolveEdgePathCalculator: () => resolveEdgePathCalculator, setHitTestProvider: () => setHitTestProvider, setNodeCenter: () => setNodeCenter, smoothStep: () => smoothStep, stepHorizontal: () => stepHorizontal, stepSmart: () => stepSmart, stepVertical: () => stepVertical, straight: () => straight, unregisterEdgePathCalculator: () => unregisterEdgePathCalculator }); module.exports = __toCommonJS(index_exports); // src/utils/debug.ts var import_debug = __toESM(require("debug")); var NAMESPACE = "canvas"; function createDebug(module2) { const base = (0, import_debug.default)(`${NAMESPACE}:${module2}`); const warn = (0, import_debug.default)(`${NAMESPACE}:${module2}:warn`); const error = (0, import_debug.default)(`${NAMESPACE}:${module2}:error`); warn.enabled = true; error.enabled = true; warn.log = console.warn.bind(console); error.log = console.error.bind(console); const debugFn = Object.assign(base, { warn, error }); return debugFn; } var debug = { graph: { node: createDebug("graph:node"), edge: createDebug("graph:edge"), sync: createDebug("graph:sync") }, ui: { selection: createDebug("ui:selection"), drag: createDebug("ui:drag"), resize: createDebug("ui:resize") }, sync: { status: createDebug("sync:status"), mutations: createDebug("sync:mutations"), queue: createDebug("sync:queue") }, viewport: createDebug("viewport") }; // src/utils/gesture-configs.ts var fingerGestureConfig = { eventOptions: { passive: false, capture: false }, drag: { pointer: { touch: true, keys: false, capture: false, buttons: -1 }, filterTaps: true, tapsThreshold: 10, // Was 3 — too strict for fingers threshold: 10 // Was 3 — needs larger dead zone } }; var pencilGestureConfig = { eventOptions: { passive: false, capture: false }, drag: { pointer: { touch: true, keys: false, capture: false, buttons: -1 }, filterTaps: true, tapsThreshold: 3, threshold: 2 // Very precise — small dead zone } }; var mouseGestureConfig = { eventOptions: { passive: false, capture: false }, drag: { pointer: { touch: true, keys: false, capture: false, buttons: -1 }, filterTaps: true, tapsThreshold: 5, // Was 3 threshold: 3 } }; function getNodeGestureConfig(source) { switch (source) { case "finger": return fingerGestureConfig; case "pencil": return pencilGestureConfig; case "mouse": return mouseGestureConfig; } } function getViewportGestureConfig(source) { const base = getNodeGestureConfig(source); return { ...base, eventOptions: { passive: false }, pinch: { pointer: { touch: true } }, wheel: { eventOptions: { passive: false } } }; } // src/utils/mutation-queue.ts var pendingNodeMutations = /* @__PURE__ */ new Map(); function getPendingState(nodeId) { let state = pendingNodeMutations.get(nodeId); if (!state) { state = { inFlight: false, queuedPosition: null, queuedUiProperties: null, graphId: null }; pendingNodeMutations.set(nodeId, state); } return state; } function clearPendingState(nodeId) { pendingNodeMutations.delete(nodeId); } function hasPendingMutations() { for (const state of pendingNodeMutations.values()) { if (state.inFlight || state.queuedPosition !== null || state.queuedUiProperties !== null) { return true; } } return false; } // src/utils/component-registry.tsx var import_compiler_runtime = require("react/compiler-runtime"); var import_react = __toESM(require("react")); var import_jsx_runtime = require("react/jsx-runtime"); function createComponentRegistry({ registry, fallback, getDisplayName = (type) => `Memoized${type}Component` }) { const memoizedCache = /* @__PURE__ */ new Map(); const getComponent = (type) => { if (memoizedCache.has(type)) { return memoizedCache.get(type); } const LazyComponent = registry[type]; if (!LazyComponent) { return fallback || null; } function RegistryComponent(props) { const $ = (0, import_compiler_runtime.c)(2); let t0; if ($[0] !== props) { t0 = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LazyComponent, { ...props }); $[0] = props; $[1] = t0; } else { t0 = $[1]; } return t0; } RegistryComponent.displayName = getDisplayName(type); memoizedCache.set(type, RegistryComponent); return RegistryComponent; }; const getTypes = () => Object.keys(registry); const hasType = (type) => type in registry; return { getComponent, getTypes, hasType, Fallback: fallback || null }; } function createFallbackComponent(getMessage) { return function FallbackComponent(props) { const message = getMessage ? getMessage(props) : `Unsupported type: "${props.nodeData?.dbData?.node_type || "Unknown"}"`; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "10px", color: "orange" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: message }) }); }; } // src/utils/edge-path-calculators.ts var bezierHorizontal = ({ x1, y1, x2, y2 }) => { const dist = Math.abs(x2 - x1); const offset = Math.max(dist * 0.5, 50); const cp1x = x1 + offset; const cp1y = y1; const cp2x = x2 - offset; const cp2y = y2; const path = `M ${x1} ${y1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${x2} ${y2}`; const labelX = (x1 + x2) / 2; const labelY = (y1 + y2) / 2; return { path, labelX, labelY }; }; var bezierVertical = ({ x1, y1, x2, y2 }) => { const dist = Math.abs(y2 - y1); const offset = Math.max(dist * 0.5, 50); const cp1x = x1; const cp1y = y1 + offset; const cp2x = x2; const cp2y = y2 - offset; const path = `M ${x1} ${y1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${x2} ${y2}`; const labelX = (x1 + x2) / 2; const labelY = (y1 + y2) / 2; return { path, labelX, labelY }; }; var bezierSmart = (input) => { const { x1, y1, x2, y2 } = input; const dx = Math.abs(x2 - x1); const dy = Math.abs(y2 - y1); return dx > dy ? bezierHorizontal(input) : bezierVertical(input); }; var straight = ({ x1, y1, x2, y2 }) => { const path = `M ${x1} ${y1} L ${x2} ${y2}`; const labelX = (x1 + x2) / 2; const labelY = (y1 + y2) / 2; return { path, labelX, labelY }; }; var stepHorizontal = ({ x1, y1, x2, y2 }) => { const midX = (x1 + x2) / 2; const path = `M ${x1} ${y1} L ${midX} ${y1} L ${midX} ${y2} L ${x2} ${y2}`; const labelX = midX; const labelY = (y1 + y2) / 2; return { path, labelX, labelY }; }; var stepVertical = ({ x1, y1, x2, y2 }) => { const midY = (y1 + y2) / 2; const path = `M ${x1} ${y1} L ${x1} ${midY} L ${x2} ${midY} L ${x2} ${y2}`; const labelX = (x1 + x2) / 2; const labelY = midY; return { path, labelX, labelY }; }; var stepSmart = (input) => { const { x1, y1, x2, y2 } = input; const dx = Math.abs(x2 - x1); const dy = Math.abs(y2 - y1); return dx > dy ? stepHorizontal(input) : stepVertical(input); }; var smoothStep = ({ x1, y1, x2, y2 }) => { const midX = (x1 + x2) / 2; const radius = Math.min(20, Math.abs(x2 - x1) / 4, Math.abs(y2 - y1) / 2); if (radius < 5 || Math.abs(y2 - y1) < radius * 2) { return stepHorizontal({ x1, y1, x2, y2, sourceWidth: 0, sourceHeight: 0, targetWidth: 0, targetHeight: 0 }); } const yDir = y2 > y1 ? 1 : -1; const path = ` M ${x1} ${y1} L ${midX - radius} ${y1} Q ${midX} ${y1}, ${midX} ${y1 + radius * yDir} L ${midX} ${y2 - radius * yDir} Q ${midX} ${y2}, ${midX + radius} ${y2} L ${x2} ${y2} `.replace(/\s+/g, " ").trim(); const labelX = midX; const labelY = (y1 + y2) / 2; return { path, labelX, labelY }; }; function getEdgePathCalculator(type) { switch (type) { case "bezier": return bezierHorizontal; case "bezier-vertical": return bezierVertical; case "bezier-smart": return bezierSmart; case "straight": return straight; case "step": return stepHorizontal; case "step-vertical": return stepVertical; case "step-smart": return stepSmart; case "smooth-step": return smoothStep; default: return bezierHorizontal; } } var defaultEdgePathCalculator = bezierHorizontal; // src/utils/layout.ts var FitToBoundsMode = /* @__PURE__ */ (function(FitToBoundsMode2) { FitToBoundsMode2["Graph"] = "graph"; FitToBoundsMode2["Selection"] = "selection"; return FitToBoundsMode2; })({}); var calculateBounds = (nodes) => { if (nodes.length === 0) { return { x: 0, y: 0, width: 0, height: 0 }; } const minX = Math.min(...nodes.map((node) => node.x)); const minY = Math.min(...nodes.map((node) => node.y)); const maxX = Math.max(...nodes.map((node) => node.x + node.width)); const maxY = Math.max(...nodes.map((node) => node.y + node.height)); return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }; }; function getNodeCenter(node) { return { x: node.x + node.width / 2, y: node.y + node.height / 2 }; } function setNodeCenter(node, centerX, centerY) { return { ...node, x: centerX - node.width / 2, y: centerY - node.height / 2 }; } function checkNodesOverlap(node1, node2) { const center1 = getNodeCenter(node1); const center2 = getNodeCenter(node2); const dx = Math.abs(center1.x - center2.x); const dy = Math.abs(center1.y - center2.y); const minDistanceX = (node1.width + node2.width) / 2; const minDistanceY = (node1.height + node2.height) / 2; return dx < minDistanceX && dy < minDistanceY; } function getNodeBounds(node) { return { x: node.x, y: node.y, width: node.width, height: node.height, left: node.x, right: node.x + node.width, top: node.y, bottom: node.y + node.height }; } function areNodesClose(node1, node2, threshold = 200) { const center1 = getNodeCenter(node1); const center2 = getNodeCenter(node2); const distance = Math.sqrt(Math.pow(center1.x - center2.x, 2) + Math.pow(center1.y - center2.y, 2)); return distance <= threshold; } // src/utils/hit-test.ts var defaultProvider = { elementFromPoint: (x, y) => document.elementFromPoint(x, y), elementsFromPoint: (x, y) => document.elementsFromPoint(x, y) }; var _provider = defaultProvider; function setHitTestProvider(provider) { _provider = provider ?? defaultProvider; } function hitTestNode(screenX, screenY) { const element = _provider.elementFromPoint(screenX, screenY); const nodeElement = element?.closest("[data-node-id]") ?? null; const nodeId = nodeElement?.getAttribute("data-node-id") ?? null; return { nodeId, element: nodeElement }; } function hitTestPort(screenX, screenY) { const elements = _provider.elementsFromPoint(screenX, screenY); for (const el of elements) { const portElement = el.closest("[data-drag-port-id]"); if (portElement) { const portId = portElement.dataset.dragPortId; const portBar = portElement.closest("[data-port-bar]"); const nodeId = portBar?.dataset.nodeId; if (portId && nodeId) { return { nodeId, portId }; } } } return null; } // src/utils/edge-path-registry.ts var customCalculators = /* @__PURE__ */ new Map(); function registerEdgePathCalculator(name, calculator) { customCalculators.set(name, calculator); } function unregisterEdgePathCalculator(name) { return customCalculators.delete(name); } function resolveEdgePathCalculator(name) { return customCalculators.get(name) ?? getEdgePathCalculator(name); } function hasCustomEdgePathCalculator(name) { return customCalculators.has(name); } function getCustomEdgePathCalculatorNames() { return Array.from(customCalculators.keys()); } function clearCustomEdgePathCalculators() { customCalculators.clear(); } //# sourceMappingURL=index.js.map