@linkurious/ogma-react
Version:
A light adaptation of Ogma for React application
561 lines (560 loc) • 15.7 kB
JavaScript
import U, { createContext as K, useContext as V, memo as j, forwardRef as E, useRef as x, useState as f, useImperativeHandle as C, useEffect as l, useLayoutEffect as Y, useCallback as J } from "react";
import Q from "@linkurious/ogma";
import { renderToString as I } from "react-dom/server";
import { createPortal as _ } from "react-dom";
const W = K(null), y = () => {
const e = V(W);
if (!e) throw new Error("useOgma must be used within an OgmaProvider");
return e.ogma;
};
function q(e, n) {
Object.keys(e).forEach((o) => {
const t = e[o];
t && n(o, t);
});
}
function X(e) {
return e.startsWith("on") && e.length > 2 ? e[2].toLowerCase() + e.substring(3) : null;
}
const M = {}, Z = (e, n) => {
const {
options: o = M,
children: t,
graph: r,
onReady: s,
theme: a,
className: d = "ogma-container"
} = e, c = x({}), [i, b] = f(!1), [u, O] = f(), [L, S] = f(null), [v, H] = f(), [G, g] = f(M), [w, N] = f();
return C(n, () => u, [u]), l(() => {
if (!L) return;
const h = new Q({
container: L,
graph: r,
options: o
});
a && (N(a), h.styles.setTheme(a)), O(h), b(!0), s && s(h);
}, [L]), Y(() => {
const h = () => u == null ? void 0 : u.view.forceResize();
return h(), window.addEventListener("resize", h), () => window.removeEventListener("resize", h);
}, []), l(() => {
u && (r && r !== v && (H(r), u.setGraph(r)), o && G !== o && (g(o), u.setOptions(o)));
}, [r, o]), l(() => {
u && a && a !== w && (N(a), u.styles.setTheme(a));
}, [a]), l(() => {
if (!u) return;
const h = {};
Object.keys(e).forEach((m) => {
if (!m.startsWith("on")) return;
const P = X(m), z = e[m];
P && typeof z == "function" && (h[P] = z);
}), q(c.current, (m, T) => {
h[m] || (u.events.off(T), delete c.current[m]);
}), q(h, (m, T) => {
const P = c.current[m];
P && P !== T && u.events.off(P), (!P || P !== T) && (u.events.on(m, T), c.current[m] = T);
});
}, [e]), /* @__PURE__ */ U.createElement(
"div",
{
style: { width: "100%", height: "100%" },
className: d,
ref: (h) => S(h)
},
u && /* @__PURE__ */ U.createElement(
W.Provider,
{
value: {
ogma: u
}
},
i && t
)
);
}, He = j(E(Z));
function Ge(e, n, o) {
return J(n, o || []);
}
const p = E(
({ selector: e, attributes: n }, o) => {
const t = y(), [r, s] = f();
return C(o, () => r, [r]), l(() => {
const a = e ? t.styles.addNodeRule(e, n) : t.styles.addNodeRule(n);
return s(a), () => {
a.destroy(), s(void 0);
};
}, [e, n]), null;
}
), ee = ({
attributes: e,
fullOverwrite: n
}) => {
const o = y();
return l(() => (o.styles.setHoveredNodeAttributes(e, n), () => {
o.styles.setHoveredNodeAttributes(null);
}), [e, n]), null;
}, te = ({
attributes: e,
fullOverwrite: n
}) => {
const o = y();
return l(() => (o.styles.setSelectedNodeAttributes(e, n), () => {
o.styles.setSelectedNodeAttributes(null);
}), [e, n]), null;
}, Re = Object.assign(p, {
Hovered: ee,
Selected: te
}), ne = E(
({ selector: e, attributes: n }, o) => {
const t = y(), [r, s] = f();
return C(o, () => r, [r]), l(() => {
const a = e ? t.styles.addEdgeRule(e, n) : t.styles.addEdgeRule(n);
return s(a), () => {
a.destroy(), s(void 0);
};
}, [e, n]), null;
}
), oe = ({
attributes: e,
fullOverwrite: n
}) => {
const o = y();
return l(() => (o.styles.setHoveredEdgeAttributes(e, n), () => {
o.styles.setHoveredEdgeAttributes(null);
}), [e, n]), null;
}, se = ({
attributes: e,
fullOverwrite: n
}) => {
const o = y();
return l(() => (o.styles.setSelectedEdgeAttributes(e, n), () => {
o.styles.setSelectedEdgeAttributes(null);
}), [e, n]), null;
}, $e = Object.assign(ne, {
Hovered: oe,
Selected: se
}), re = ({
name: e,
edgeAttributes: n,
edgeDependencies: o,
edgeOutput: t,
nodeAttributes: r,
nodeDependencies: s,
nodeOutput: a
}, d) => {
const c = y(), [i, b] = f(
null
);
return C(d, () => i, [
i
]), l(() => {
const u = {
edgeAttributes: n,
edgeDependencies: o,
edgeOutput: t,
nodeAttributes: r,
nodeDependencies: s,
nodeOutput: a
};
async function O() {
const L = c.styles.createClass({ name: e, ...u });
await c.view.afterNextFrame(), b(L);
}
return O(), () => {
async function L() {
const S = c.styles.getClass(e);
S && await S.destroy(), b(null);
}
L();
};
}, []), l(() => {
i && i.update({
edgeAttributes: n,
edgeDependencies: o,
edgeOutput: t,
nodeAttributes: r,
nodeDependencies: s,
nodeOutput: a
});
}, [
n,
o,
t,
r,
s,
a
]), null;
}, ie = (e, n) => e.name === n.name && e.edgeAttributes === n.edgeAttributes && e.edgeDependencies === n.edgeDependencies && e.edgeOutput === n.edgeOutput && e.nodeAttributes === n.nodeAttributes && e.nodeDependencies === n.nodeDependencies && e.nodeOutput === n.nodeOutput, Ae = j(E(re), ie);
function R(e, n, o) {
n === e.isEnabled() && (n ? e.disable(o) : e.enable(o));
}
function $(e, n, o) {
const t = ({ target: i }) => {
i === n && e.onEnabled && e.onEnabled(n);
}, r = ({ target: i }) => {
i === n && e.onDisabled && e.onDisabled(n);
}, s = ({ target: i }) => {
i === n && e.onUpdated && e.onUpdated(n);
}, a = ({
target: i,
index: b
}) => {
i === n && e.onSetIndex && e.onSetIndex(n, b);
}, d = ({
target: i
}) => {
i === n && (e.onDestroyed && e.onDestroyed(n), o.events.off(t).off(r).off(s).off(a).off(d));
};
return o.events.on("transformationEnabled", t).on("transformationDisabled", r).on("transformationDestroyed", d).on("transformationSetIndex", a).on("transformationRefresh", s), () => {
o.events.off(t).off(r).off(s).off(a).off(d);
};
}
function le(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addNodeGrouping({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled]), l(() => {
t == null || t.setOptions(e);
}, [
e.groupIdFunction,
e.groupSelfLoopEdges,
e.edgeGenerator,
e.nodeGenerator,
e.groupEdges,
e.padding,
e.selector,
e.showContents,
e.separateEdgesByDirection
]), null;
}
const Fe = E(le);
function ae(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addEdgeGrouping({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled]), l(() => {
t == null || t.setOptions(e);
}, [
e.selector,
e.generator,
e.groupIdFunction,
e.separateEdgesByDirection
]), null;
}
const De = E(ae);
function de(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addNodeCollapsing({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled]), l(() => {
t == null || t.setOptions(e);
}, [e.edgeGenerator, e.selector]), null;
}
const ke = E(de);
function ce(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addNeighborMerging({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled]), l(() => {
t == null || t.setOptions(e);
}, [e.dataFunction, e.selector]), null;
}
const Ie = E(ce);
function ue(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addNeighborGeneration({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled]), l(() => {
t == null || t.setOptions(e);
}, [
e.edgeGenerator,
e.nodeGenerator,
e.neighborIdFunction,
e.selector
]), null;
}
const _e = E(ue);
function fe(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addEdgeFilter({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled, e.duration]), l(() => {
t == null || t.setOptions(e);
}, [e.criteria]), null;
}
const ze = E(fe);
function ge(e, n) {
const o = y(), [t, r] = f();
return C(n, () => t, [t]), l(() => {
const s = o.transformations.addNodeFilter({
...e,
enabled: !e.disabled
});
return $(e, s, o), r(s), () => {
s.destroy(), r(void 0);
};
}, []), l(() => {
t && R(t, !!e.disabled, e.duration);
}, [e.disabled, e.duration]), l(() => {
t == null || t.setOptions(e);
}, [e.criteria]), null;
}
const Ue = E(ge);
function B(e, n, o, t) {
return typeof o == "string" ? o : typeof o == "function" ? I(o(e, n)) : I(t);
}
function A(e, n) {
return typeof e == "function" ? e(n) : e;
}
const F = (e, n) => `${e} ${e}--${n}`;
function me(e = "×", n) {
if (e) {
const o = typeof e == "string" ? e : I(e);
return `<div class=${n}>${o}</div>`;
}
return "";
}
function ye(e, n, o, t) {
const { width: r, height: s } = t.view.getSize(), { x: a, y: d } = t.view.graphToScreenCoordinates(e);
let c = n;
const { width: i, height: b } = o;
return n === "left" && a - i < 0 ? c = "right" : n === "right" && a + i > r ? c = "left" : n === "bottom" && d + b > s ? c = "top" : n === "top" && d - b < 0 && (c = "bottom"), c === "right" || c === "left" ? d + b / 2 > s ? c = "top" : d - b / 2 < 0 && (c = "bottom") : a + i / 2 > r ? c = "left" : a - i / 2 < 0 && (c = "right"), c;
}
function he() {
}
const D = { x: -9999, y: -9999 }, be = "ogma-popup--content", ve = "ogma-popup--close", Ee = "ogma-popup--body", Ce = "ogma-popup", Se = ({
content: e,
position: n,
children: o,
isOpen: t = !0,
closeButton: r,
onClose: s = he,
placement: a = "top",
popupClass: d = Ce,
closeButtonClass: c = ve,
contentClass: i = be,
popupBodyClass: b = Ee,
size: u,
closeOnEsc: O = !0
}, L) => {
const S = y(), [v, H] = f(null);
if (C(L, () => v, [v]), l(() => {
let g = null, w = null, N = null;
if (t) {
const h = A(n, S) || D;
if (g = S.layers.addOverlay({
position: h || D,
element: `<div class="${F(d, a)}"/>
<div class="${b}">
${me(r, c)}
<div class="${i} "></div>
</div>
</div>`,
size: u || { width: "auto", height: "auto" },
scaled: !1
}), N = (m) => {
const T = g == null ? void 0 : g.element.querySelector(
`.${c}`
);
m.target && T.contains(m.target) && (m.stopPropagation(), m.preventDefault(), s());
}, w = ({ code: m }) => {
m === 27 && s();
}, O && S.events.on("keyup", w), g.element.addEventListener("click", N), H(g), e && !o) {
const m = g.element.querySelector(
`.${i}`
), T = B(S, h, e, o);
m && (m.innerHTML = T);
}
H(g);
}
return () => {
g && (N && g.element.removeEventListener("click", N), w && S.events.off(w), g.destroy(), H(null));
};
}, [t, S]), l(() => {
if (v && v.element) {
const g = A(n, S) || D;
if (v.setPosition(g), v.element.className = F(d, a), e && !o) {
const w = v.element.querySelector(`.${i}`);
w && (w.innerHTML = typeof e == "string" ? e : "");
}
t ? v.show() : v.hide();
}
}, [v, n, t, a, d, e, o]), !v || !t) return null;
const G = v.element.querySelector(`.${i}`);
return G && o ? _(o, G) : null;
}, qe = E(Se), we = ({
tooltipClass: e = "ogma-tooltip",
placement: n = "right",
position: o,
size: t = { width: "auto", height: "auto" },
children: r,
content: s,
visible: a = !0
}, d) => {
const c = y(), [i, b] = f(), [u, O] = f(), [L, S] = f(""), [v, H] = f(), G = x(0);
return C(d, () => i, [i]), l(() => {
const w = `<div class="${F(e, n)}"><div class="${e}--content" /></div>`, N = { x: -9999, y: -9999 };
O(N);
const h = c.layers.addOverlay({
position: N,
element: w,
scaled: !1,
size: t
});
return b(h), () => {
h.destroy();
};
}, []), l(() => {
const g = B(c, u, s, r);
if (i) {
g !== L && (i.element.firstElementChild.innerHTML = g, S(g), H({
width: i.element.offsetWidth,
height: i.element.offsetHeight
}));
const w = A(o, c);
u !== w && O(w), a ? i.show() : i.hide();
}
return G.current = requestAnimationFrame(() => {
i && i.element && u && v && (i.element.className = F(
e,
ye(u, n, v, c)
), i.setPosition(u));
}), () => cancelAnimationFrame(G.current);
}, [r, s, o, a]), null;
}, Me = E(we), Le = ({
noClear: e = !1,
isStatic: n = !1,
render: o,
index: t,
visible: r = !0
}, s) => {
const a = y(), [d, c] = f(null);
return C(s, () => d, [d]), l(() => {
const i = a.layers.addCanvasLayer(
o,
{ isStatic: n, noClear: e },
t
);
return c(i), () => {
i && (i.destroy(), c(null));
};
}, []), l(() => {
d && (t !== void 0 && isFinite(t) && d.moveTo(t), r ? d.show() : d.hide());
}, [d, t, r]), null;
}, je = E(Le), k = { x: -9999, y: -9999 }, xe = E(
({ position: e, children: n, className: o = "", size: t, scaled: r }, s) => {
const a = y(), [d, c] = f(null);
return C(s, () => d, [d]), l(() => {
const i = A(e, a) || k, b = document.createElement("div");
b.className = o;
const u = a.layers.addOverlay({
position: i || k,
element: b,
size: t || { width: "auto", height: "auto" },
scaled: r
});
return c(u), () => {
d && (d.destroy(), c(null));
};
}, []), l(() => {
if (d) {
const i = A(e, a) || k;
o && (d.element.className = o), d.setPosition(i);
}
}, [e, o]), d ? _(n, d.element) : null;
}
), We = E(
({ children: e, className: n = "", index: o }, t) => {
const r = y(), [s, a] = f(null);
return C(t, () => s, [s]), l(() => {
const d = document.createElement("div");
d.className = n;
const c = r.layers.addLayer(d, o);
return a(c), () => {
s && (s.destroy(), a(null));
};
}, []), l(() => {
s && (s.element.className = n);
}, [n]), s ? _(e, s.element) : null;
}
);
function Be({ enabled: e = !1, ...n }) {
const o = y();
return l(() => {
e ? o.geo.enable(n) : o.geo.disable();
}, [e]), null;
}
export {
je as CanvasLayer,
ze as EdgeFilter,
De as EdgeGrouping,
$e as EdgeStyle,
$e as EdgeStyleRule,
Be as Geo,
We as Layer,
_e as NeighborGeneration,
Ie as NeighborMerging,
ke as NodeCollapsing,
de as NodeCollapsingComponent,
Ue as NodeFilter,
Fe as NodeGrouping,
Re as NodeStyle,
Re as NodeStyleRule,
He as Ogma,
xe as Overlay,
qe as Popup,
Ae as StyleClass,
Me as Tooltip,
q as forEachEventHandler,
X as getEventNameFromProp,
Ge as useEvent,
y as useOgma
};
//# sourceMappingURL=index.mjs.map