UNPKG

@jalez/react-flow-automated-layout

Version:

A React library for automated layout of nested node graphs with parent-child relationships using React Flow

1,479 lines (1,478 loc) 43.2 kB
import Pe, { createContext as De, useContext as Me, useState as C, useEffect as ee, useRef as ue, useCallback as te } from "react"; import { Position as I, useReactFlow as Be, useNodes as Ie, useEdges as We, useOnSelectionChange as Fe, ControlButton as P, Controls as ze } from "@xyflow/react"; import he from "@dagrejs/dagre"; var se = { exports: {} }, Q = {}; /** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var fe; function He() { if (fe) return Q; fe = 1; var n = Symbol.for("react.transitional.element"), o = Symbol.for("react.fragment"); function r(c, s, a) { var d = null; if (a !== void 0 && (d = "" + a), s.key !== void 0 && (d = "" + s.key), "key" in s) { a = {}; for (var l in s) l !== "key" && (a[l] = s[l]); } else a = s; return s = a.ref, { $$typeof: n, type: c, key: d, ref: s !== void 0 ? s : null, props: a }; } return Q.Fragment = o, Q.jsx = r, Q.jsxs = r, Q; } var K = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var pe; function Ue() { return pe || (pe = 1, process.env.NODE_ENV !== "production" && function() { function n(t) { if (t == null) return null; if (typeof t == "function") return t.$$typeof === N ? null : t.displayName || t.name || null; if (typeof t == "string") return t; switch (t) { case v: return "Fragment"; case j: return "Profiler"; case f: return "StrictMode"; case y: return "Suspense"; case R: return "SuspenseList"; case G: return "Activity"; } if (typeof t == "object") switch (typeof t.tag == "number" && console.error( "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." ), t.$$typeof) { case E: return "Portal"; case g: return (t.displayName || "Context") + ".Provider"; case b: return (t._context.displayName || "Context") + ".Consumer"; case x: var w = t.render; return t = t.displayName, t || (t = w.displayName || w.name || "", t = t !== "" ? "ForwardRef(" + t + ")" : "ForwardRef"), t; case L: return w = t.displayName || null, w !== null ? w : n(t.type) || "Memo"; case B: w = t._payload, t = t._init; try { return n(t(w)); } catch { } } return null; } function o(t) { return "" + t; } function r(t) { try { o(t); var w = !1; } catch { w = !0; } if (w) { w = console; var k = w.error, O = typeof Symbol == "function" && Symbol.toStringTag && t[Symbol.toStringTag] || t.constructor.name || "Object"; return k.call( w, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", O ), o(t); } } function c(t) { if (t === v) return "<>"; if (typeof t == "object" && t !== null && t.$$typeof === B) return "<...>"; try { var w = n(t); return w ? "<" + w + ">" : "<...>"; } catch { return "<...>"; } } function s() { var t = _.A; return t === null ? null : t.getOwner(); } function a() { return Error("react-stack-top-frame"); } function d(t) { if (D.call(t, "key")) { var w = Object.getOwnPropertyDescriptor(t, "key").get; if (w && w.isReactWarning) return !1; } return t.key !== void 0; } function l(t, w) { function k() { $ || ($ = !0, console.error( "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", w )); } k.isReactWarning = !0, Object.defineProperty(t, "key", { get: k, configurable: !0 }); } function u() { var t = n(this.type); return V[t] || (V[t] = !0, console.error( "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release." )), t = this.props.ref, t !== void 0 ? t : null; } function h(t, w, k, O, M, A, X, Z) { return k = A.ref, t = { $$typeof: T, type: t, key: w, props: A, _owner: M }, (k !== void 0 ? k : null) !== null ? Object.defineProperty(t, "ref", { enumerable: !1, get: u }) : Object.defineProperty(t, "ref", { enumerable: !1, value: null }), t._store = {}, Object.defineProperty(t._store, "validated", { configurable: !1, enumerable: !1, writable: !0, value: 0 }), Object.defineProperty(t, "_debugInfo", { configurable: !1, enumerable: !1, writable: !0, value: null }), Object.defineProperty(t, "_debugStack", { configurable: !1, enumerable: !1, writable: !0, value: X }), Object.defineProperty(t, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: Z }), Object.freeze && (Object.freeze(t.props), Object.freeze(t)), t; } function i(t, w, k, O, M, A, X, Z) { var S = w.children; if (S !== void 0) if (O) if (Y(S)) { for (O = 0; O < S.length; O++) m(S[O]); Object.freeze && Object.freeze(S); } else console.error( "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead." ); else m(S); if (D.call(w, "key")) { S = n(t); var W = Object.keys(w).filter(function(ne) { return ne !== "key"; }); O = 0 < W.length ? "{key: someKey, " + W.join(": ..., ") + ": ...}" : "{key: someKey}", H[S + O] || (W = 0 < W.length ? "{" + W.join(": ..., ") + ": ...}" : "{}", console.error( `A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`, O, S, W, S ), H[S + O] = !0); } if (S = null, k !== void 0 && (r(k), S = "" + k), d(w) && (r(w.key), S = "" + w.key), "key" in w) { k = {}; for (var U in w) U !== "key" && (k[U] = w[U]); } else k = w; return S && l( k, typeof t == "function" ? t.displayName || t.name || "Unknown" : t ), h( t, S, A, M, s(), k, X, Z ); } function m(t) { typeof t == "object" && t !== null && t.$$typeof === T && t._store && (t._store.validated = 1); } var p = Pe, T = Symbol.for("react.transitional.element"), E = Symbol.for("react.portal"), v = Symbol.for("react.fragment"), f = Symbol.for("react.strict_mode"), j = Symbol.for("react.profiler"), b = Symbol.for("react.consumer"), g = Symbol.for("react.context"), x = Symbol.for("react.forward_ref"), y = Symbol.for("react.suspense"), R = Symbol.for("react.suspense_list"), L = Symbol.for("react.memo"), B = Symbol.for("react.lazy"), G = Symbol.for("react.activity"), N = Symbol.for("react.client.reference"), _ = p.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, D = Object.prototype.hasOwnProperty, Y = Array.isArray, F = console.createTask ? console.createTask : function() { return null; }; p = { "react-stack-bottom-frame": function(t) { return t(); } }; var $, V = {}, J = p["react-stack-bottom-frame"].bind( p, a )(), q = F(c(a)), H = {}; K.Fragment = v, K.jsx = function(t, w, k, O, M) { var A = 1e4 > _.recentlyCreatedOwnerStacks++; return i( t, w, k, !1, O, M, A ? Error("react-stack-top-frame") : J, A ? F(c(t)) : q ); }, K.jsxs = function(t, w, k, O, M) { var A = 1e4 > _.recentlyCreatedOwnerStacks++; return i( t, w, k, !0, O, M, A ? Error("react-stack-top-frame") : J, A ? F(c(t)) : q ); }; }()), K; } var ge; function Ge() { return ge || (ge = 1, process.env.NODE_ENV === "production" ? se.exports = He() : se.exports = Ue()), se.exports; } var e = Ge(); const Ee = De(void 0); function re() { const n = Me(Ee); if (n === void 0) throw new Error("useLayoutContext must be used within a LayoutProvider"); return n; } const Ye = (n) => { switch (n) { case "DOWN": return "TB"; case "RIGHT": return "LR"; case "UP": return "BT"; case "LEFT": return "RL"; default: return "TB"; } }, xe = (n) => { switch (n) { case "TB": return "DOWN"; case "LR": return "RIGHT"; case "BT": return "UP"; case "RL": return "LEFT"; default: return "DOWN"; } }, $e = { enabled: !0, padding: { horizontal: 80, vertical: 48 }, respectHeaderHeight: !0, minWidth: 200, minHeight: 100 }, Ve = (n) => { switch (n) { case "DOWN": return I.Bottom; case "RIGHT": return I.Right; case "UP": return I.Top; case "LEFT": return I.Left; default: return I.Bottom; } }, Je = (n) => { switch (n) { case "DOWN": return I.Top; case "RIGHT": return I.Left; case "UP": return I.Bottom; case "LEFT": return I.Right; default: return I.Top; } }; function qe(n, o, r) { if (r) return { nodes: n, edges: o }; const c = n.filter((d) => !d.hidden), s = new Set(c.map((d) => d.id)), a = o.filter( (d) => s.has(d.source) && s.has(d.target) ); return { nodes: c, edges: a }; } const Xe = 172, Ze = 36, oe = async (n, o, r, c = 0, s = 50, a = 50, d = Xe, l = Ze, u = !1) => { const h = new he.graphlib.Graph().setDefaultEdgeLabel(() => ({})); h.setGraph({ rankdir: r, marginx: c, marginy: c, nodesep: s, ranksep: a, edgesep: Math.max(20, s / 4), //When we have siblings, we want their top edges to be aligned ranker: "tight-tree" }); const i = u ? n : n.filter((f) => !f.hidden); if (i.length === 0) return { nodes: [], edges: [], width: 0, height: 0 }; i.forEach((f) => { var g, x; const j = Number((g = f.style) == null ? void 0 : g.width) || d, b = Number((x = f.style) == null ? void 0 : x.height) || l; h.setNode(f.id, { width: j, height: b }); }), o.forEach((f) => { const j = f.sourceHandle, b = f.targetHandle; let g = {}; j === "right" && b === "left" ? g = { constraint: !1, minlen: 1 } : j === "bottom" && b === "top" ? g = { constraint: !0, minlen: 1 } : g = { constraint: !0, minlen: 2 }, h.setEdge(f.source, f.target, g); }), he.layout(h); const m = h.graph().width || 0, p = h.graph().height || 0, T = Ve(xe(r)), E = Je(xe(r)); return { nodes: i.map((f) => { var L; const j = h.node(f.id), { width: b, height: g } = j, x = { ...f, sourcePosition: T, targetPosition: E, selected: !1 }, y = j.x, R = j.y; switch ((L = f.data) == null ? void 0 : L.positionType) { case "center": x.position = { x: y, y: R }; break; case "topRight": x.position = { x: y + b / 2, y: R - g / 2 }; break; case "bottomLeft": x.position = { x: y - b / 2, y: R + g / 2 }; break; case "bottomRight": x.position = { x: y + b / 2, y: R + g / 2 }; break; case "topLeft": default: x.position = { x: y - b / 2, y: R - g / 2 }; } return x; }), edges: o, width: m, height: p }; }, Qe = { calculate: async (n, o, r) => { const c = r.nodes || n, s = r.edges || o, d = r.dagreDirection || typeof r.direction == "string" && (r.direction === "RIGHT" || r.direction === "LEFT" ? "LR" : "TB") || "TB", l = r.margin ?? (typeof r.padding == "number" ? r.padding : 0), u = r.nodeSpacing ?? 50, h = r.layerSpacing ?? 50, i = r.nodeWidth ?? 172, m = r.nodeHeight ?? 36, p = r.layoutHidden ?? !1; return oe( c, s, d, l, u, h, i, m, p ); } }, Ke = { dagre: Qe }; function et({ initialDirection: n = "DOWN", initialAlgorithm: o = "layered", initialAutoLayout: r = !0, initialPadding: c = 50, initialSpacing: s = { node: 50, layer: 50 }, initialNodeDimensions: a = { width: 172, height: 36 }, initialParentResizingOptions: d, includeHidden: l = !1, layoutEngines: u }) { const [h, i] = C(n), [m, p] = C(o), [T, E] = C(r), [v, f] = C(!1), [j, b] = C(l), [g, x] = C({ ...Ke, ...u }), [y, R] = C({}), [L, B] = C(c), [G, N] = C(s.node || 150), [_, D] = C(s.layer || 180), [Y, F] = C(a.width || 100), [$, V] = C(a.height || 100), [J, q] = C({ ...$e, ...d, enabled: r }), [H, t] = C([]); return { // State direction: h, algorithm: m, autoLayout: T, layoutInProgress: v, layoutHidden: j, layoutEngines: g, layoutEngineOptions: y, padding: L, nodeSpacing: G, layerSpacing: _, nodeWidth: Y, nodeHeight: $, parentResizingOptions: J, selectedNodes: H, // Setters setDirection: i, setAlgorithm: p, setAutoLayout: E, setLayoutInProgress: f, setLayoutHidden: b, setLayoutEngines: x, setLayoutEngineOptions: R, setPadding: B, setNodeSpacing: N, setLayerSpacing: D, setNodeWidth: F, setNodeHeight: V, setParentResizingOptionsState: q, setSelectedNodes: t }; } function tt({ nodes: n, externalNodeIdWithNode: o, externalNodeParentIdMapWithChildIdSet: r, noParentKey: c = "no-parent" }) { const [s, a] = C(/* @__PURE__ */ new Map()), [d, l] = C(/* @__PURE__ */ new Map()), [u, h] = C({}), [i, m] = C(n.length), [p, T] = C(!1), E = o || s, v = r || d, f = E.size; return ee(() => { if (!o || !r) { const j = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map(); n.forEach((g) => { var y; j.set(g.id, g); const x = g.parentId || c; b.has(x) || b.set(x, /* @__PURE__ */ new Set()), (y = b.get(x)) == null || y.add(g.id); }), o || a(j), r || l(b); } }, [n, o, r, c]), ee(() => { n.length !== i && m(n.length); }, [n]), ee(() => { E.size > 0 && v.size > 0 && !p && T(!0); }, [E, v, p]), ee(() => { const j = {}; v.forEach((g, x) => { j[x] = g.size; }); let b = !1; for (const g in j) if (!u.hasOwnProperty(g) || j[g] !== u[g]) { b = !0; break; } b && h(j); }, [v]), { nodeIdWithNode: E, nodeParentIdMapWithChildIdSet: v, numberOfNodes: f, nodesLength: i, childrenInitialized: p, parentChildStructure: u }; } function rt({ nodes: n, edges: o, selectedNodes: r, layoutHidden: c, calculateLayout: s, updateNodes: a, updateEdges: d, setLayoutInProgress: l, setNodeSpacing: u, setLayerSpacing: h }) { const i = Be(), m = ue(null), p = ue(null); return { applyLayout: te(async (E = [], v = []) => { m.current && m.current.abort(); const f = new AbortController(); m.current = f; const j = E.length > 0 ? E : n, b = v.length > 0 ? v : o; if (j.length === 0) return { nodes: j, edges: b }; try { if (l(!0), f.signal.aborted) return { nodes: j, edges: b }; const { nodes: g, edges: x } = qe(j, b, c), y = await s(g, x, r, f.signal); return f.signal.aborted ? { nodes: j, edges: b } : (m.current === f && (a ? a(y.nodes) : i != null && i.setNodes && i.setNodes(y.nodes), d ? d(y.edges) : i != null && i.setEdges && i.setEdges(y.edges), p.current && (p.current.node !== void 0 && u(p.current.node), p.current.layer !== void 0 && h(p.current.layer), p.current = null)), y); } catch (g) { return f.signal.aborted || console.error("Error applying layout:", g), { nodes: j, edges: b }; } finally { m.current === f && (l(!1), m.current = null); } }, [ n, o, r, s, a, d, i, c, l, u, h ]), pendingSpacingUpdateRef: p }; } const nt = (n, o, r = "no-parent") => { const c = /* @__PURE__ */ new Set(), s = /* @__PURE__ */ new Map(); n.forEach((l, u) => { const h = o.get(u); h && s.set(u, { id: u, node: h, children: [], depth: 0 }); }); const a = (l, u) => { if (c.has(l) || !n.has(l) || !o.get(l)) return null; c.add(l); const i = s.get(l); i.depth = u; const m = n.get(l) || /* @__PURE__ */ new Set(); for (const p of m) if (n.has(p) && o.get(p)) { const E = a(p, u + 1); E && i.children.push(E); } return i; }, d = []; return n.forEach((l, u) => { const h = o.get(u); if (h) { const i = h.parentId; if (!i || i === r) { const m = a(u, 0); m && d.push(m); } } }), d; }; function ye(n, o, r = "no-parent") { const c = []; let s = n; const a = /* @__PURE__ */ new Set(); for (; s && s !== r; ) { if (a.has(s)) { console.warn(`Cycle detected in ancestor path for node ${n}`); break; } a.add(s), c.push(s); const d = o.get(s); if (!d || !d.parentId) { s = r; break; } s = d.parentId; } return s === r && c.push(r), c; } function st(n, o, r, c = "no-parent") { const s = ye(n, r, c), a = ye(o, r, c), d = new Set(a); let l = null, u = -1; for (let p = 0; p < s.length; p++) if (d.has(s[p])) { l = s[p], u = p; break; } if (!l) return { lca: null, sourceChild: null, targetChild: null }; const h = a.indexOf(l), i = u > 0 ? s[u - 1] : n, m = h > 0 ? a[h - 1] : o; return { lca: l, sourceChild: i, targetChild: m }; } function ve(n, o, r = "no-parent") { const c = /* @__PURE__ */ new Map(); for (const s of n) { const { lca: a, sourceChild: d, targetChild: l } = st( s.source, s.target, o, r ); if (a && d && l && d !== l) { const u = JSON.parse(JSON.stringify(s)); u.source = d, u.target = l, u.id = `temp_${u.id}_${a}`, u.data = { ...u.data, isTemporary: !0, originalSource: s.source, originalTarget: s.target }, c.has(a) || c.set(a, []), c.get(a).push(u); } } return c; } const ce = 10, Te = async (n, o, r, c, s, a = ce, d = 50, l = 50, u = 172, h = 36, i = oe, m = !1, p = "no-parent") => { const T = ve(s, c, p), { updatedNodes: E } = await ae( n, o, r, c, s, a, d, l, u, h, i, m, T ), v = c.get(n); if (!v) return { updatedNodes: E, updatedEdges: s }; const { updatedNodes: f } = await Te( v.parentId || p, o, r, c, s, a, d, l, u, h, i, m, p ); return { updatedNodes: [...f, ...E], updatedEdges: s // Always return original edges unchanged }; }, ae = async (n, o, r, c, s, a = ce, d = 50, l = 50, u = 172, h = 36, i = oe, m = !1, p = /* @__PURE__ */ new Map()) => { const T = r.get(n); if (!T || T.size === 0) return { updatedNodes: [] }; const E = []; if (T.forEach((R) => { const L = c.get(R); L && E.push(L); }), E.length === 0) return { updatedNodes: [] }; let v = o; const f = c.get(n); f && f.data.layoutDirection && (v = f.data.layoutDirection); const j = p.get(n) || [], { nodes: b, edges: g, width: x, height: y } = await i( E, j, // Only use temporary edges for layout v, a, d, l, u, h, m ); return f && x && y && ot(f, x, y), { updatedNodes: [...b], udpatedParentNode: f || void 0 }; }, ot = (n, o, r) => (n.style || (n.style = {}), n.width = o, n.height = r, n.measured = { width: o, height: r }, n.style.width = o, n.style.height = r, n), it = async (n, o, r, c, s, a = ce, d = 50, l = 50, u = 172, h = 36, i = oe, m = !1, p = "no-parent") => { let T = []; const E = ve(s, c, p), v = /* @__PURE__ */ new Map(); let f = 0; const j = (g, x) => { x > f && (f = x); for (const y of g) v.has(x) || v.set(x, []), v.get(x).push(y.id), y.children.length > 0 && j(y.children, x + 1); }; j(n, 0); for (let g = f; g >= 0; g--) { const x = v.get(g) || [], y = await Promise.all(x.map( (R) => ae( R, o, r, c, s, // Pass original edges (only used for returning) a, d, l, u, h, i, m, E // Pass the global temporary edges map ) )); for (const { updatedNodes: R } of y) T = [...R, ...T]; } const { updatedNodes: b } = await ae( p, o, r, c, s, // Pass original edges (only used for returning) a, d, l, u, h, i, m, E // Process root-level temporary edges ); return T = [...b, ...T], { updatedNodes: T, updatedEdges: s // Always return original edges unchanged }; }, at = (n, o, r, c = "no-parent") => { const s = n.map((h) => h.id), a = n.map((h) => { var i; return ((i = r.get(h.id)) == null ? void 0 : i.parentId) || h.parentId; }).filter((h) => !!h), l = Array.from( /* @__PURE__ */ new Set([...s, ...a]) ).filter((h) => o.has(h)), u = l.filter((h) => { const i = r.get(h); return i ? !i.parentId || !l.includes(i.parentId) : !0; }); return u.length === 0 ? [c] : u; }, ct = async (n, o, r) => { const { dagreDirection: c, nodeParentIdMapWithChildIdSet: s, nodeIdWithNode: a, nodes: d, edges: l, margin: u, nodeSpacing: h, layerSpacing: i, nodeWidth: m, nodeHeight: p, layoutHidden: T = !1, noParentKey: E = "no-parent" } = o, v = at( n, s, a, E ); if (v.length === 0) return { nodes: d, edges: l }; const f = /* @__PURE__ */ new Map(), j = /* @__PURE__ */ new Map(); if (r != null && r.aborted) return { nodes: d, edges: l }; (await Promise.all( v.map(async (y) => r != null && r.aborted ? { updatedNodes: [], updatedEdges: [] } : Te( y, c, s, a, l, u, h, i, m, p, void 0, T )) )).forEach(({ updatedNodes: y, updatedEdges: R }) => { y.forEach((L) => { f.set(L.id, L); }), R.forEach((L) => { j.set(L.id, L); }); }); const g = d.map( (y) => f.has(y.id) ? f.get(y.id) : y ), x = l.map( (y) => j.has(y.id) ? j.get(y.id) : y ); return { nodes: g, edges: x }; }, lt = (n, o, r, c, s, a, d, l, u = 172, h = 36, i = !1, m = "no-parent") => ({ calculateLayout: te(async (T, E, v, f) => { if (!(n[r] || n.dagre)) return console.error(`Layout engine "${r}" not found`), { nodes: T, edges: E }; const b = i ? T : T.filter((N) => !N.hidden), g = new Set(b.map((N) => N.id)), x = i ? E : E.filter( (N) => g.has(N.source) && g.has(N.target) ), y = Ye(o), R = c.padding.horizontal; let L = [], B = []; if (v && v.length > 0) { const N = i ? v : v.filter((D) => !D.hidden), _ = await ct( N, { dagreDirection: y, nodeParentIdMapWithChildIdSet: s, nodeIdWithNode: a, nodes: b, edges: x, margin: R, nodeSpacing: d, layerSpacing: l, nodeWidth: u, nodeHeight: h, layoutHidden: i, noParentKey: m }, f ); L = _.nodes, B = _.edges; } else { if (f != null && f.aborted) return { nodes: T, edges: E }; const N = nt(s, a, m), _ = await it( N, y, s, a, x, R, d, l, u, h, void 0, i, m ); L = _.updatedNodes, B = _.updatedEdges; } return { nodes: T.map((N) => !i && N.hidden ? N : L.find((D) => D.id === N.id) || N), edges: B }; }, [ r, o, n, c.padding.horizontal, s, a, d, l, u, h, i, m ]) }); function ft({ children: n, initialDirection: o = "DOWN", initialAlgorithm: r = "layered", initialAutoLayout: c = !0, initialPadding: s = 50, initialSpacing: a = { node: 50, layer: 50 }, initialNodeDimensions: d = { width: 172, height: 36 }, initialParentResizingOptions: l, includeHidden: u = !1, layoutEngines: h, updateNodes: i, updateEdges: m, nodeParentIdMapWithChildIdSet: p, nodeIdWithNode: T, noParentKey: E = "no-parent", disableAutoLayoutEffect: v = !1 }) { const f = Ie(), j = We(), { direction: b, algorithm: g, autoLayout: x, layoutInProgress: y, layoutHidden: R, layoutEngines: L, layoutEngineOptions: B, padding: G, nodeSpacing: N, layerSpacing: _, nodeWidth: D, nodeHeight: Y, parentResizingOptions: F, selectedNodes: $, setDirection: V, setAlgorithm: J, setAutoLayout: q, setLayoutInProgress: H, setLayoutHidden: t, setLayoutEngines: w, setLayoutEngineOptions: k, setPadding: O, setNodeSpacing: M, setLayerSpacing: A, setNodeWidth: X, setNodeHeight: Z, setParentResizingOptionsState: S, setSelectedNodes: W } = et({ initialDirection: o, initialAlgorithm: r, initialAutoLayout: c, initialPadding: s, initialSpacing: a, initialNodeDimensions: d, initialParentResizingOptions: l, includeHidden: u, layoutEngines: h }), { nodeIdWithNode: U, nodeParentIdMapWithChildIdSet: ne, numberOfNodes: ke, nodesLength: Re, childrenInitialized: le, parentChildStructure: Ne } = tt({ nodes: f, externalNodeIdWithNode: T, externalNodeParentIdMapWithChildIdSet: p, noParentKey: E }), Le = te(({ nodes: z }) => { W(z); }, [W]); Fe({ onChange: Le }); const { calculateLayout: Ce } = lt( L, b, g, F, ne, U, N, _, D, Y, R, E ), { applyLayout: de } = rt({ nodes: f, edges: j, selectedNodes: $, layoutHidden: R, calculateLayout: Ce, updateNodes: i, updateEdges: m, setLayoutInProgress: H, setNodeSpacing: M, setLayerSpacing: A }), Se = te((z, ie) => { w((Ae) => ({ ...Ae, [z]: ie })); }, [w]), Oe = te((z) => { S((ie) => ({ ...ie, ...z, enabled: x })); }, [x, S]); ee(() => { var z; v || U.has((z = f[f.length - 1]) == null ? void 0 : z.id) && le && x && de(); }, [le, x, b, ke, N, _, Ne, Re]); const _e = { direction: b, algorithm: g, autoLayout: x, layoutInProgress: y, padding: G, nodeSpacing: N, layerSpacing: _, nodeWidth: D, nodeHeight: Y, layoutHidden: R, parentResizingOptions: F, layoutEngines: L, layoutEngineOptions: B, nodeParentIdMapWithChildIdSet: ne, nodeIdWithNode: U, noParentKey: E, updateNodes: i, updateEdges: m, setDirection: V, setAlgorithm: J, setAutoLayout: q, setLayoutInProgress: H, setPadding: O, setNodeSpacing: M, setLayerSpacing: A, setNodeWidth: X, setNodeHeight: Z, setLayoutHidden: t, setParentResizingOptions: Oe, setLayoutEngineOptions: k, applyLayout: de, clearLayoutCache: () => { }, registerLayoutEngine: Se }; return /* @__PURE__ */ e.jsx(Ee.Provider, { value: _e, children: n }); } const me = ({ compact: n = !1 }) => { const { direction: o, setDirection: r, clearLayoutCache: c } = re(), s = (a) => { r(a), c && c(); }; return n ? /* @__PURE__ */ e.jsx( P, { onClick: () => s(o === "DOWN" ? "RIGHT" : "DOWN"), title: `Switch to ${o === "DOWN" ? "horizontal" : "vertical"} layout`, children: /* @__PURE__ */ e.jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: o === "DOWN" ? ( // Horizontal layout icon /* @__PURE__ */ e.jsx("path", { d: "M4 12h16M16 6l6 6-6 6" }) ) : ( // Vertical layout icon /* @__PURE__ */ e.jsx("path", { d: "M12 4v16M6 16l6 6 6-6" }) ) }) } ) : /* @__PURE__ */ e.jsxs(e.Fragment, { children: [ /* @__PURE__ */ e.jsx( P, { onClick: () => s("DOWN"), className: o === "DOWN" ? "selected" : "", title: "Top to Bottom", children: /* @__PURE__ */ e.jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: /* @__PURE__ */ e.jsx("path", { d: "M12 4v16M6 16l6 6 6-6" }) }) } ), /* @__PURE__ */ e.jsx( P, { onClick: () => s("RIGHT"), className: o === "RIGHT" ? "selected" : "", title: "Left to Right", children: /* @__PURE__ */ e.jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: /* @__PURE__ */ e.jsx("path", { d: "M4 12h16M16 6l6 6-6 6" }) }) } ), /* @__PURE__ */ e.jsx( P, { onClick: () => s("LEFT"), className: o === "LEFT" ? "selected" : "", title: "Right to Left", children: /* @__PURE__ */ e.jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: /* @__PURE__ */ e.jsx("path", { d: "M20 12H4M8 6L2 12l6 6" }) }) } ), /* @__PURE__ */ e.jsx( P, { onClick: () => s("UP"), className: o === "UP" ? "selected" : "", title: "Bottom to Top", children: /* @__PURE__ */ e.jsx("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: /* @__PURE__ */ e.jsx("path", { d: "M12 20V4M6 8l6-6 6 6" }) }) } ) ] }); }, we = ({ compact: n = !1 }) => { const { nodeSpacing: o, layerSpacing: r, setNodeSpacing: c, setLayerSpacing: s, clearLayoutCache: a } = re(), [d, l] = C(!1), u = (i) => { c(i), a && a(); }, h = (i) => { s(i), a && a(); }; return n ? /* @__PURE__ */ e.jsxs("div", { style: { position: "relative" }, children: [ /* @__PURE__ */ e.jsx( P, { onClick: () => l(!d), title: "Adjust node and layer spacing", children: /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: [ /* @__PURE__ */ e.jsx("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("path", { d: "M7 10v4M17 10v4M10 7h4M10 17h4" }) ] }) } ), d && /* @__PURE__ */ e.jsxs( "div", { className: "react-flow-spacing-dropdown", style: { position: "absolute", right: "0", top: "100%", marginTop: "8px", background: "white", border: "1px solid #ddd", borderRadius: "4px", padding: "8px", boxShadow: "0 2px 10px rgba(0,0,0,0.1)", zIndex: 10, minWidth: "200px" }, children: [ /* @__PURE__ */ e.jsxs("div", { style: { marginBottom: "12px" }, children: [ /* @__PURE__ */ e.jsxs("div", { style: { fontWeight: "bold", marginBottom: "4px" }, children: [ "Node Spacing: ", o, "px" ] }), /* @__PURE__ */ e.jsx("div", { style: { display: "flex", gap: "4px" }, children: [50, 100, 150, 200].map((i) => /* @__PURE__ */ e.jsx( "button", { onClick: () => u(i), style: { background: o === i ? "#0041d0" : "#f5f5f5", color: o === i ? "white" : "inherit", border: "1px solid #ddd", borderRadius: "4px", padding: "4px 8px", cursor: "pointer" }, children: i }, i )) }) ] }), /* @__PURE__ */ e.jsxs("div", { children: [ /* @__PURE__ */ e.jsxs("div", { style: { fontWeight: "bold", marginBottom: "4px" }, children: [ "Layer Spacing: ", r, "px" ] }), /* @__PURE__ */ e.jsx("div", { style: { display: "flex", gap: "4px" }, children: [50, 100, 150, 200].map((i) => /* @__PURE__ */ e.jsx( "button", { onClick: () => h(i), style: { background: r === i ? "#0041d0" : "#f5f5f5", color: r === i ? "white" : "inherit", border: "1px solid #ddd", borderRadius: "4px", padding: "4px 8px", cursor: "pointer" }, children: i }, i )) }) ] }), /* @__PURE__ */ e.jsx("div", { style: { marginTop: "12px", textAlign: "right" }, children: /* @__PURE__ */ e.jsx( "button", { onClick: () => l(!1), style: { background: "#f5f5f5", border: "1px solid #ddd", borderRadius: "4px", padding: "4px 8px", cursor: "pointer" }, children: "Close" } ) }) ] } ) ] }) : /* @__PURE__ */ e.jsxs("div", { className: "spacing-controls", children: [ /* @__PURE__ */ e.jsxs( P, { onClick: () => u(Math.max(50, o - 25)), title: "Decrease node spacing", children: [ /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: [ /* @__PURE__ */ e.jsx("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("line", { x1: "7", y1: "10", x2: "7", y2: "14" }), /* @__PURE__ */ e.jsx("line", { x1: "17", y1: "10", x2: "17", y2: "14" }), /* @__PURE__ */ e.jsx("line", { x1: "10", y1: "7", x2: "14", y2: "7" }), /* @__PURE__ */ e.jsx("line", { x1: "10", y1: "17", x2: "14", y2: "17" }) ] }), /* @__PURE__ */ e.jsx("span", { style: { marginLeft: "4px" }, children: "-" }) ] } ), /* @__PURE__ */ e.jsxs("div", { style: { display: "inline-flex", alignItems: "center", padding: "5px 10px", fontSize: "12px", background: "#f8f8f8", borderRadius: "4px", margin: "0 4px", border: "1px solid #ddd" }, children: [ o, "px" ] }), /* @__PURE__ */ e.jsxs( P, { onClick: () => u(Math.min(300, o + 25)), title: "Increase node spacing", children: [ /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: [ /* @__PURE__ */ e.jsx("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ e.jsx("line", { x1: "7", y1: "10", x2: "7", y2: "14" }), /* @__PURE__ */ e.jsx("line", { x1: "17", y1: "10", x2: "17", y2: "14" }), /* @__PURE__ */ e.jsx("line", { x1: "10", y1: "7", x2: "14", y2: "7" }), /* @__PURE__ */ e.jsx("line", { x1: "10", y1: "17", x2: "14", y2: "17" }) ] }), /* @__PURE__ */ e.jsx("span", { style: { marginLeft: "4px" }, children: "+" }) ] } ), /* @__PURE__ */ e.jsx("div", { style: { display: "inline-block", width: "1px", height: "24px", background: "#ddd", margin: "0 10px" } }), /* @__PURE__ */ e.jsxs( P, { onClick: () => h(Math.max(50, r - 25)), title: "Decrease layer spacing", children: [ /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: [ /* @__PURE__ */ e.jsx("line", { x1: "4", y1: "6", x2: "20", y2: "6" }), /* @__PURE__ */ e.jsx("line", { x1: "4", y1: "12", x2: "20", y2: "12" }), /* @__PURE__ */ e.jsx("line", { x1: "4", y1: "18", x2: "20", y2: "18" }) ] }), /* @__PURE__ */ e.jsx("span", { style: { marginLeft: "4px" }, children: "-" }) ] } ), /* @__PURE__ */ e.jsxs("div", { style: { display: "inline-flex", alignItems: "center", padding: "5px 10px", fontSize: "12px", background: "#f8f8f8", borderRadius: "4px", margin: "0 4px", border: "1px solid #ddd" }, children: [ r, "px" ] }), /* @__PURE__ */ e.jsxs( P, { onClick: () => h(Math.min(300, r + 25)), title: "Increase layer spacing", children: [ /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "2", fill: "none", children: [ /* @__PURE__ */ e.jsx("line", { x1: "4", y1: "6", x2: "20", y2: "6" }), /* @__PURE__ */ e.jsx("line", { x1: "4", y1: "12", x2: "20", y2: "12" }), /* @__PURE__ */ e.jsx("line", { x1: "4", y1: "18", x2: "20", y2: "18" }) ] }), /* @__PURE__ */ e.jsx("span", { style: { marginLeft: "4px" }, children: "+" }) ] } ) ] }); }, je = ({ compact: n = !1 }) => { const { autoLayout: o, setAutoLayout: r } = re(), c = () => { r(!o); }; return /* @__PURE__ */ e.jsx( P, { onClick: c, className: o ? "selected" : "", title: o ? "Disable automatic layout" : "Enable automatic layout", style: { color: o ? "green" : "inherit" }, children: n ? /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "1.5", fill: "none", children: [ /* @__PURE__ */ e.jsx("rect", { x: "4", y: "4", width: "4", height: "4", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "4", y: "16", width: "4", height: "4", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "16", y: "10", width: "4", height: "4", rx: "1" }), /* @__PURE__ */ e.jsxs(e.Fragment, { children: [ /* @__PURE__ */ e.jsx("path", { d: "M8 6c6 0 3 8 8 6" }), /* @__PURE__ */ e.jsx("path", { d: "M8 18c3-3 2-8 6-6" }) ] }) ] }) : /* @__PURE__ */ e.jsxs(e.Fragment, { children: [ "Auto-Layout ", o ? "ON" : "OFF" ] }) } ); }, be = ({ compact: n = !1 }) => { const { layoutInProgress: o, setLayoutInProgress: r, applyLayout: c } = re(), s = async () => { if (!o) try { r(!0), await c(); } catch (a) { console.error("Error applying layout:", a); } }; return /* @__PURE__ */ e.jsxs( P, { onClick: s, title: "Apply layout", disabled: o, style: { color: o ? "#999" : "#000" }, children: [ /* @__PURE__ */ e.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", stroke: "currentColor", strokeWidth: "1.5", fill: "none", children: [ /* @__PURE__ */ e.jsx("rect", { x: "3", y: "3", width: "5", height: "5", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "16", y: "3", width: "5", height: "5", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "3", y: "16", width: "5", height: "5", rx: "1" }), /* @__PURE__ */ e.jsx("rect", { x: "16", y: "16", width: "5", height: "5", rx: "1" }), /* @__PURE__ */ e.jsx("path", { d: "M8 5.5h8M5.5 8v8M18.5 8v8M8 18.5h8" }), /* @__PURE__ */ e.jsx("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ e.jsx("path", { d: "M11 10.5v3l2-1.5z", fill: "currentColor" }) ] }), !n && /* @__PURE__ */ e.jsx("span", { style: { marginLeft: "4px" }, children: "Apply Layout" }) ] } ); }, pt = ({ showDirectionControls: n = !0, showSpacingControls: o = !0, showAutoLayoutToggle: r = !0, showApplyLayoutButton: c = !0, // Enable by default standalone: s = !1, position: a = "top-right" }) => { const d = re(), { autoLayout: l } = d; return s ? /* @__PURE__ */ e.jsxs(ze, { position: a, showZoom: !1, showFitView: !1, showInteractive: !1, children: [ c && !l && /* @__PURE__ */ e.jsx( be, { compact: !0 } ), n && /* @__PURE__ */ e.jsx( me, { compact: !0 } ), o && /* @__PURE__ */ e.jsx( we, { compact: !0 } ), r && /* @__PURE__ */ e.jsx( je, { compact: !0 } ) ] }) : /* @__PURE__ */ e.jsxs(e.Fragment, { children: [ c && !l && /* @__PURE__ */ e.jsx( be, { compact: !0 } ), n && /* @__PURE__ */ e.jsx( me, { compact: !0 } ), o && /* @__PURE__ */ e.jsx( we, { compact: !0 } ), r && /* @__PURE__ */ e.jsx( je, { compact: !0 } ) ] }); }; export { je as AutoLayoutToggle, Qe as DagreEngine, me as DirectionControls, pt as LayoutControls, ft as LayoutProvider, we as SpacingControls, Ke as engines, re as useLayoutContext };