force-3d-graph 1.3.6 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/force-3d-graph.js +773 -585
- package/dist/force-3d-graph.js.map +1 -1
- package/dist/force-3d-graph.umd.cjs +154 -71
- package/dist/force-3d-graph.umd.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/force-3d-graph.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var l = (h, e, s) =>
|
|
4
|
-
import * as
|
|
5
|
-
import { EventDispatcher as
|
|
1
|
+
var it = Object.defineProperty;
|
|
2
|
+
var ot = (h, e, s) => e in h ? it(h, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : h[e] = s;
|
|
3
|
+
var l = (h, e, s) => ot(h, typeof e != "symbol" ? e + "" : e, s);
|
|
4
|
+
import * as x from "three";
|
|
5
|
+
import { EventDispatcher as nt, Vector3 as S, MOUSE as j, TOUCH as $, Spherical as Se, Quaternion as ze, Vector2 as k, Ray as at, Plane as rt, MathUtils as lt } from "three";
|
|
6
6
|
const P = {
|
|
7
7
|
backgroundColor: 657930,
|
|
8
8
|
cameraPosition: { x: 0, y: 0, z: 80 },
|
|
@@ -32,8 +32,8 @@ const P = {
|
|
|
32
32
|
targetFPS: 60,
|
|
33
33
|
maxVisibleNodes: 1e4
|
|
34
34
|
};
|
|
35
|
-
var
|
|
36
|
-
function
|
|
35
|
+
var _ = /* @__PURE__ */ ((h) => (h[h.HIGH = 0] = "HIGH", h[h.MEDIUM = 1] = "MEDIUM", h[h.LOW = 2] = "LOW", h))(_ || {});
|
|
36
|
+
function ct() {
|
|
37
37
|
const h = document.createElement("div");
|
|
38
38
|
return h.id = "force-graph-3d-container", h.style.cssText = `
|
|
39
39
|
width: 100%;
|
|
@@ -44,84 +44,84 @@ function dt() {
|
|
|
44
44
|
overflow: hidden;
|
|
45
45
|
`, document.body.appendChild(h), h;
|
|
46
46
|
}
|
|
47
|
-
function
|
|
48
|
-
return h && h instanceof HTMLElement ? h : (console.warn("[ForceGraph3D] No container provided, creating one automatically"),
|
|
47
|
+
function dt(h) {
|
|
48
|
+
return h && h instanceof HTMLElement ? h : (console.warn("[ForceGraph3D] No container provided, creating one automatically"), ct());
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function ke(h) {
|
|
51
51
|
const e = h.getBoundingClientRect();
|
|
52
52
|
return {
|
|
53
53
|
width: e.width || window.innerWidth,
|
|
54
54
|
height: e.height || window.innerHeight
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
function
|
|
57
|
+
function Fe(h) {
|
|
58
58
|
if (!h || typeof h != "object")
|
|
59
59
|
return console.warn("[ForceGraph3D] Invalid node: must be an object"), !1;
|
|
60
60
|
const e = h;
|
|
61
|
-
return typeof e.id != "string" || e.id.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node: id must be a non-empty string"), !1) : typeof e.label != "string" ? (console.warn("[ForceGraph3D] Invalid node: label must be a string"), !1) : e.color !== void 0 && typeof e.color != "number" ? (console.warn("[ForceGraph3D] Invalid node: color must be a number (hex)"), !1) : e.position !== void 0 && !
|
|
61
|
+
return typeof e.id != "string" || e.id.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node: id must be a non-empty string"), !1) : typeof e.label != "string" ? (console.warn("[ForceGraph3D] Invalid node: label must be a string"), !1) : e.color !== void 0 && typeof e.color != "number" ? (console.warn("[ForceGraph3D] Invalid node: color must be a number (hex)"), !1) : e.position !== void 0 && !pt(e.position) ? (console.warn("[ForceGraph3D] Invalid node: position must have x, y, z numbers"), !1) : !0;
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function De(h) {
|
|
64
64
|
if (!h || typeof h != "object")
|
|
65
65
|
return console.warn("[ForceGraph3D] Invalid edge: must be an object"), !1;
|
|
66
66
|
const e = h;
|
|
67
67
|
return typeof e.source != "string" || e.source.trim() === "" ? (console.warn("[ForceGraph3D] Invalid edge: source must be a non-empty string"), !1) : typeof e.target != "string" || e.target.trim() === "" ? (console.warn("[ForceGraph3D] Invalid edge: target must be a non-empty string"), !1) : !0;
|
|
68
68
|
}
|
|
69
|
-
function
|
|
69
|
+
function ht(h) {
|
|
70
70
|
return typeof h != "string" || h.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node ID: must be a non-empty string"), !1) : !0;
|
|
71
71
|
}
|
|
72
|
-
function
|
|
72
|
+
function pt(h) {
|
|
73
73
|
if (!h || typeof h != "object") return !1;
|
|
74
74
|
const e = h;
|
|
75
75
|
return typeof e.x == "number" && typeof e.y == "number" && typeof e.z == "number";
|
|
76
76
|
}
|
|
77
|
-
function
|
|
77
|
+
function Dt(h, e) {
|
|
78
78
|
return h === e ? `${h}-${e}` : h < e ? `${h}-${e}` : `${e}-${h}`;
|
|
79
79
|
}
|
|
80
|
-
const
|
|
81
|
-
class
|
|
80
|
+
const Te = { type: "change" }, le = { type: "start" }, Pe = { type: "end" }, Q = new at(), Le = new rt(), gt = Math.cos(70 * lt.DEG2RAD);
|
|
81
|
+
class ut extends nt {
|
|
82
82
|
constructor(e, s) {
|
|
83
|
-
super(), this.object = e, this.domElement = s, this.domElement.style.touchAction = "none", this.enabled = !0, this.target = new S(), this.cursor = new S(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT:
|
|
83
|
+
super(), this.object = e, this.domElement = s, this.domElement.style.touchAction = "none", this.enabled = !0, this.target = new S(), this.cursor = new S(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT: j.ROTATE, MIDDLE: j.DOLLY, RIGHT: j.PAN }, this.touches = { ONE: $.ROTATE, TWO: $.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this.getPolarAngle = function() {
|
|
84
84
|
return r.phi;
|
|
85
85
|
}, this.getAzimuthalAngle = function() {
|
|
86
86
|
return r.theta;
|
|
87
87
|
}, this.getDistance = function() {
|
|
88
88
|
return this.object.position.distanceTo(this.target);
|
|
89
|
-
}, this.listenToKeyEvents = function(
|
|
90
|
-
|
|
89
|
+
}, this.listenToKeyEvents = function(a) {
|
|
90
|
+
a.addEventListener("keydown", ae), this._domElementKeyEvents = a;
|
|
91
91
|
}, this.stopListenToKeyEvents = function() {
|
|
92
|
-
this._domElementKeyEvents.removeEventListener("keydown",
|
|
92
|
+
this._domElementKeyEvents.removeEventListener("keydown", ae), this._domElementKeyEvents = null;
|
|
93
93
|
}, this.saveState = function() {
|
|
94
94
|
t.target0.copy(t.target), t.position0.copy(t.object.position), t.zoom0 = t.object.zoom;
|
|
95
95
|
}, this.reset = function() {
|
|
96
|
-
t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(
|
|
96
|
+
t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(Te), t.update(), o = i.NONE;
|
|
97
97
|
}, this.update = function() {
|
|
98
|
-
const
|
|
99
|
-
return function(
|
|
100
|
-
const
|
|
101
|
-
|
|
98
|
+
const a = new S(), g = new ze().setFromUnitVectors(e.up, new S(0, 1, 0)), v = g.clone().invert(), M = new S(), C = new ze(), F = new S(), z = 2 * Math.PI;
|
|
99
|
+
return function(st = null) {
|
|
100
|
+
const Ne = t.object.position;
|
|
101
|
+
a.copy(Ne).sub(t.target), a.applyQuaternion(g), r.setFromVector3(a), t.autoRotate && o === i.NONE && Y(He(st)), t.enableDamping ? (r.theta += d.theta * t.dampingFactor, r.phi += d.phi * t.dampingFactor) : (r.theta += d.theta, r.phi += d.phi);
|
|
102
102
|
let R = t.minAzimuthAngle, I = t.maxAzimuthAngle;
|
|
103
|
-
isFinite(R) && isFinite(I) && (R < -Math.PI ? R += z : R > Math.PI && (R -= z), I < -Math.PI ? I += z : I > Math.PI && (I -= z), R <= I ? r.theta = Math.max(R, Math.min(I, r.theta)) : r.theta = r.theta > (R + I) / 2 ? Math.max(R, r.theta) : Math.min(I, r.theta)), r.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, r.phi)), r.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(p, t.dampingFactor) : t.target.add(p), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && D || t.object.isOrthographicCamera ? r.radius =
|
|
104
|
-
let
|
|
103
|
+
isFinite(R) && isFinite(I) && (R < -Math.PI ? R += z : R > Math.PI && (R -= z), I < -Math.PI ? I += z : I > Math.PI && (I -= z), R <= I ? r.theta = Math.max(R, Math.min(I, r.theta)) : r.theta = r.theta > (R + I) / 2 ? Math.max(R, r.theta) : Math.min(I, r.theta)), r.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, r.phi)), r.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(p, t.dampingFactor) : t.target.add(p), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && D || t.object.isOrthographicCamera ? r.radius = oe(r.radius) : r.radius = oe(r.radius * c), a.setFromSpherical(r), a.applyQuaternion(v), Ne.copy(t.target).add(a), t.object.lookAt(t.target), t.enableDamping === !0 ? (d.theta *= 1 - t.dampingFactor, d.phi *= 1 - t.dampingFactor, p.multiplyScalar(1 - t.dampingFactor)) : (d.set(0, 0, 0), p.set(0, 0, 0));
|
|
104
|
+
let re = !1;
|
|
105
105
|
if (t.zoomToCursor && D) {
|
|
106
|
-
let
|
|
106
|
+
let K = null;
|
|
107
107
|
if (t.object.isPerspectiveCamera) {
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
t.object.position.addScaledVector(
|
|
108
|
+
const U = a.length();
|
|
109
|
+
K = oe(U * c);
|
|
110
|
+
const Z = U - K;
|
|
111
|
+
t.object.position.addScaledVector(G, Z), t.object.updateMatrixWorld();
|
|
112
112
|
} else if (t.object.isOrthographicCamera) {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
113
|
+
const U = new S(T.x, T.y, 0);
|
|
114
|
+
U.unproject(t.object), t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / c)), t.object.updateProjectionMatrix(), re = !0;
|
|
115
|
+
const Z = new S(T.x, T.y, 0);
|
|
116
|
+
Z.unproject(t.object), t.object.position.sub(Z).add(U), t.object.updateMatrixWorld(), K = a.length();
|
|
117
117
|
} else
|
|
118
118
|
console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), t.zoomToCursor = !1;
|
|
119
|
-
|
|
120
|
-
} else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom /
|
|
121
|
-
return
|
|
119
|
+
K !== null && (this.screenSpacePanning ? t.target.set(0, 0, -1).transformDirection(t.object.matrix).multiplyScalar(K).add(t.object.position) : (Q.origin.copy(t.object.position), Q.direction.set(0, 0, -1).transformDirection(t.object.matrix), Math.abs(t.object.up.dot(Q.direction)) < gt ? e.lookAt(t.target) : (Le.setFromNormalAndCoplanarPoint(t.object.up, t.target), Q.intersectPlane(Le, t.target))));
|
|
120
|
+
} else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / c)), t.object.updateProjectionMatrix(), re = !0);
|
|
121
|
+
return c = 1, D = !1, re || M.distanceToSquared(t.object.position) > n || 8 * (1 - C.dot(t.object.quaternion)) > n || F.distanceToSquared(t.target) > 0 ? (t.dispatchEvent(Te), M.copy(t.object.position), C.copy(t.object.quaternion), F.copy(t.target), !0) : !1;
|
|
122
122
|
};
|
|
123
123
|
}(), this.dispose = function() {
|
|
124
|
-
t.domElement.removeEventListener("contextmenu",
|
|
124
|
+
t.domElement.removeEventListener("contextmenu", Ee), t.domElement.removeEventListener("pointerdown", ve), t.domElement.removeEventListener("pointercancel", B), t.domElement.removeEventListener("wheel", we), t.domElement.removeEventListener("pointermove", ne), t.domElement.removeEventListener("pointerup", B), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", ae), t._domElementKeyEvents = null);
|
|
125
125
|
};
|
|
126
126
|
const t = this, i = {
|
|
127
127
|
NONE: -1,
|
|
@@ -134,174 +134,174 @@ class ft extends at {
|
|
|
134
134
|
TOUCH_DOLLY_ROTATE: 6
|
|
135
135
|
};
|
|
136
136
|
let o = i.NONE;
|
|
137
|
-
const
|
|
138
|
-
let
|
|
139
|
-
const p = new S(),
|
|
137
|
+
const n = 1e-6, r = new Se(), d = new Se();
|
|
138
|
+
let c = 1;
|
|
139
|
+
const p = new S(), f = new k(), m = new k(), u = new k(), y = new k(), b = new k(), w = new k(), N = new k(), O = new k(), L = new k(), G = new S(), T = new k();
|
|
140
140
|
let D = !1;
|
|
141
|
-
const E = [],
|
|
142
|
-
let
|
|
143
|
-
function
|
|
144
|
-
return
|
|
141
|
+
const E = [], V = {};
|
|
142
|
+
let te = !1;
|
|
143
|
+
function He(a) {
|
|
144
|
+
return a !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * a : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
|
|
145
145
|
}
|
|
146
|
-
function
|
|
147
|
-
const g = Math.abs(
|
|
146
|
+
function q(a) {
|
|
147
|
+
const g = Math.abs(a * 0.01);
|
|
148
148
|
return Math.pow(0.95, t.zoomSpeed * g);
|
|
149
149
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
150
|
+
function Y(a) {
|
|
151
|
+
d.theta -= a;
|
|
152
152
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
153
|
+
function W(a) {
|
|
154
|
+
d.phi -= a;
|
|
155
155
|
}
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
return function(v,
|
|
159
|
-
|
|
156
|
+
const ce = function() {
|
|
157
|
+
const a = new S();
|
|
158
|
+
return function(v, M) {
|
|
159
|
+
a.setFromMatrixColumn(M, 0), a.multiplyScalar(-v), p.add(a);
|
|
160
160
|
};
|
|
161
|
-
}(),
|
|
162
|
-
const
|
|
163
|
-
return function(v,
|
|
164
|
-
t.screenSpacePanning === !0 ?
|
|
161
|
+
}(), de = function() {
|
|
162
|
+
const a = new S();
|
|
163
|
+
return function(v, M) {
|
|
164
|
+
t.screenSpacePanning === !0 ? a.setFromMatrixColumn(M, 1) : (a.setFromMatrixColumn(M, 0), a.crossVectors(t.object.up, a)), a.multiplyScalar(v), p.add(a);
|
|
165
165
|
};
|
|
166
|
-
}(),
|
|
167
|
-
const
|
|
168
|
-
return function(v,
|
|
166
|
+
}(), H = function() {
|
|
167
|
+
const a = new S();
|
|
168
|
+
return function(v, M) {
|
|
169
169
|
const C = t.domElement;
|
|
170
170
|
if (t.object.isPerspectiveCamera) {
|
|
171
171
|
const F = t.object.position;
|
|
172
|
-
|
|
173
|
-
let z =
|
|
174
|
-
z *= Math.tan(t.object.fov / 2 * Math.PI / 180),
|
|
175
|
-
} else t.object.isOrthographicCamera ? (
|
|
172
|
+
a.copy(F).sub(t.target);
|
|
173
|
+
let z = a.length();
|
|
174
|
+
z *= Math.tan(t.object.fov / 2 * Math.PI / 180), ce(2 * v * z / C.clientHeight, t.object.matrix), de(2 * M * z / C.clientHeight, t.object.matrix);
|
|
175
|
+
} else t.object.isOrthographicCamera ? (ce(v * (t.object.right - t.object.left) / t.object.zoom / C.clientWidth, t.object.matrix), de(M * (t.object.top - t.object.bottom) / t.object.zoom / C.clientHeight, t.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), t.enablePan = !1);
|
|
176
176
|
};
|
|
177
177
|
}();
|
|
178
|
-
function
|
|
179
|
-
t.object.isPerspectiveCamera || t.object.isOrthographicCamera ?
|
|
178
|
+
function se(a) {
|
|
179
|
+
t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? c /= a : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
|
|
180
180
|
}
|
|
181
|
-
function
|
|
182
|
-
t.object.isPerspectiveCamera || t.object.isOrthographicCamera ?
|
|
181
|
+
function he(a) {
|
|
182
|
+
t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? c *= a : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
|
|
183
183
|
}
|
|
184
|
-
function
|
|
184
|
+
function ie(a, g) {
|
|
185
185
|
if (!t.zoomToCursor)
|
|
186
186
|
return;
|
|
187
187
|
D = !0;
|
|
188
|
-
const v = t.domElement.getBoundingClientRect(),
|
|
189
|
-
T.x =
|
|
188
|
+
const v = t.domElement.getBoundingClientRect(), M = a - v.left, C = g - v.top, F = v.width, z = v.height;
|
|
189
|
+
T.x = M / F * 2 - 1, T.y = -(C / z) * 2 + 1, G.set(T.x, T.y, 1).unproject(t.object).sub(t.object.position).normalize();
|
|
190
190
|
}
|
|
191
|
-
function
|
|
192
|
-
return Math.max(t.minDistance, Math.min(t.maxDistance,
|
|
191
|
+
function oe(a) {
|
|
192
|
+
return Math.max(t.minDistance, Math.min(t.maxDistance, a));
|
|
193
193
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
194
|
+
function pe(a) {
|
|
195
|
+
f.set(a.clientX, a.clientY);
|
|
196
196
|
}
|
|
197
|
-
function
|
|
198
|
-
|
|
197
|
+
function Ae(a) {
|
|
198
|
+
ie(a.clientX, a.clientX), N.set(a.clientX, a.clientY);
|
|
199
199
|
}
|
|
200
|
-
function
|
|
201
|
-
|
|
200
|
+
function ge(a) {
|
|
201
|
+
y.set(a.clientX, a.clientY);
|
|
202
202
|
}
|
|
203
|
-
function
|
|
204
|
-
m.set(
|
|
203
|
+
function je(a) {
|
|
204
|
+
m.set(a.clientX, a.clientY), u.subVectors(m, f).multiplyScalar(t.rotateSpeed);
|
|
205
205
|
const g = t.domElement;
|
|
206
|
-
|
|
206
|
+
Y(2 * Math.PI * u.x / g.clientHeight), W(2 * Math.PI * u.y / g.clientHeight), f.copy(m), t.update();
|
|
207
207
|
}
|
|
208
|
-
function
|
|
209
|
-
O.set(
|
|
208
|
+
function $e(a) {
|
|
209
|
+
O.set(a.clientX, a.clientY), L.subVectors(O, N), L.y > 0 ? se(q(L.y)) : L.y < 0 && he(q(L.y)), N.copy(O), t.update();
|
|
210
210
|
}
|
|
211
|
-
function
|
|
212
|
-
b.set(
|
|
211
|
+
function Ge(a) {
|
|
212
|
+
b.set(a.clientX, a.clientY), w.subVectors(b, y).multiplyScalar(t.panSpeed), H(w.x, w.y), y.copy(b), t.update();
|
|
213
213
|
}
|
|
214
|
-
function
|
|
215
|
-
|
|
214
|
+
function Ye(a) {
|
|
215
|
+
ie(a.clientX, a.clientY), a.deltaY < 0 ? he(q(a.deltaY)) : a.deltaY > 0 && se(q(a.deltaY)), t.update();
|
|
216
216
|
}
|
|
217
|
-
function
|
|
217
|
+
function Be(a) {
|
|
218
218
|
let g = !1;
|
|
219
|
-
switch (
|
|
219
|
+
switch (a.code) {
|
|
220
220
|
case t.keys.UP:
|
|
221
|
-
|
|
221
|
+
a.ctrlKey || a.metaKey || a.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(0, t.keyPanSpeed), g = !0;
|
|
222
222
|
break;
|
|
223
223
|
case t.keys.BOTTOM:
|
|
224
|
-
|
|
224
|
+
a.ctrlKey || a.metaKey || a.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(0, -t.keyPanSpeed), g = !0;
|
|
225
225
|
break;
|
|
226
226
|
case t.keys.LEFT:
|
|
227
|
-
|
|
227
|
+
a.ctrlKey || a.metaKey || a.shiftKey ? Y(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(t.keyPanSpeed, 0), g = !0;
|
|
228
228
|
break;
|
|
229
229
|
case t.keys.RIGHT:
|
|
230
|
-
|
|
230
|
+
a.ctrlKey || a.metaKey || a.shiftKey ? Y(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(-t.keyPanSpeed, 0), g = !0;
|
|
231
231
|
break;
|
|
232
232
|
}
|
|
233
|
-
g && (
|
|
233
|
+
g && (a.preventDefault(), t.update());
|
|
234
234
|
}
|
|
235
|
-
function
|
|
235
|
+
function ue(a) {
|
|
236
236
|
if (E.length === 1)
|
|
237
|
-
|
|
237
|
+
f.set(a.pageX, a.pageY);
|
|
238
238
|
else {
|
|
239
|
-
const g =
|
|
240
|
-
|
|
239
|
+
const g = A(a), v = 0.5 * (a.pageX + g.x), M = 0.5 * (a.pageY + g.y);
|
|
240
|
+
f.set(v, M);
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
-
function
|
|
243
|
+
function fe(a) {
|
|
244
244
|
if (E.length === 1)
|
|
245
|
-
|
|
245
|
+
y.set(a.pageX, a.pageY);
|
|
246
246
|
else {
|
|
247
|
-
const g =
|
|
248
|
-
|
|
247
|
+
const g = A(a), v = 0.5 * (a.pageX + g.x), M = 0.5 * (a.pageY + g.y);
|
|
248
|
+
y.set(v, M);
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
-
function
|
|
252
|
-
const g =
|
|
251
|
+
function me(a) {
|
|
252
|
+
const g = A(a), v = a.pageX - g.x, M = a.pageY - g.y, C = Math.sqrt(v * v + M * M);
|
|
253
253
|
N.set(0, C);
|
|
254
254
|
}
|
|
255
|
-
function
|
|
256
|
-
t.enableZoom &&
|
|
255
|
+
function Ke(a) {
|
|
256
|
+
t.enableZoom && me(a), t.enablePan && fe(a);
|
|
257
257
|
}
|
|
258
|
-
function
|
|
259
|
-
t.enableZoom &&
|
|
258
|
+
function Ue(a) {
|
|
259
|
+
t.enableZoom && me(a), t.enableRotate && ue(a);
|
|
260
260
|
}
|
|
261
|
-
function
|
|
261
|
+
function ye(a) {
|
|
262
262
|
if (E.length == 1)
|
|
263
|
-
m.set(
|
|
263
|
+
m.set(a.pageX, a.pageY);
|
|
264
264
|
else {
|
|
265
|
-
const v =
|
|
266
|
-
m.set(
|
|
265
|
+
const v = A(a), M = 0.5 * (a.pageX + v.x), C = 0.5 * (a.pageY + v.y);
|
|
266
|
+
m.set(M, C);
|
|
267
267
|
}
|
|
268
|
-
u.subVectors(m,
|
|
268
|
+
u.subVectors(m, f).multiplyScalar(t.rotateSpeed);
|
|
269
269
|
const g = t.domElement;
|
|
270
|
-
|
|
270
|
+
Y(2 * Math.PI * u.x / g.clientHeight), W(2 * Math.PI * u.y / g.clientHeight), f.copy(m);
|
|
271
271
|
}
|
|
272
|
-
function
|
|
272
|
+
function xe(a) {
|
|
273
273
|
if (E.length === 1)
|
|
274
|
-
b.set(
|
|
274
|
+
b.set(a.pageX, a.pageY);
|
|
275
275
|
else {
|
|
276
|
-
const g =
|
|
277
|
-
b.set(v,
|
|
276
|
+
const g = A(a), v = 0.5 * (a.pageX + g.x), M = 0.5 * (a.pageY + g.y);
|
|
277
|
+
b.set(v, M);
|
|
278
278
|
}
|
|
279
|
-
|
|
279
|
+
w.subVectors(b, y).multiplyScalar(t.panSpeed), H(w.x, w.y), y.copy(b);
|
|
280
280
|
}
|
|
281
|
-
function
|
|
282
|
-
const g =
|
|
283
|
-
O.set(0, C), L.set(0, Math.pow(O.y / N.y, t.zoomSpeed)),
|
|
284
|
-
const F = (
|
|
285
|
-
|
|
281
|
+
function be(a) {
|
|
282
|
+
const g = A(a), v = a.pageX - g.x, M = a.pageY - g.y, C = Math.sqrt(v * v + M * M);
|
|
283
|
+
O.set(0, C), L.set(0, Math.pow(O.y / N.y, t.zoomSpeed)), se(L.y), N.copy(O);
|
|
284
|
+
const F = (a.pageX + g.x) * 0.5, z = (a.pageY + g.y) * 0.5;
|
|
285
|
+
ie(F, z);
|
|
286
286
|
}
|
|
287
|
-
function
|
|
288
|
-
t.enableZoom &&
|
|
287
|
+
function _e(a) {
|
|
288
|
+
t.enableZoom && be(a), t.enablePan && xe(a);
|
|
289
289
|
}
|
|
290
|
-
function
|
|
291
|
-
t.enableZoom &&
|
|
290
|
+
function Xe(a) {
|
|
291
|
+
t.enableZoom && be(a), t.enableRotate && ye(a);
|
|
292
292
|
}
|
|
293
|
-
function
|
|
294
|
-
t.enabled !== !1 && (E.length === 0 && (t.domElement.setPointerCapture(
|
|
293
|
+
function ve(a) {
|
|
294
|
+
t.enabled !== !1 && (E.length === 0 && (t.domElement.setPointerCapture(a.pointerId), t.domElement.addEventListener("pointermove", ne), t.domElement.addEventListener("pointerup", B)), et(a), a.pointerType === "touch" ? Qe(a) : Ve(a));
|
|
295
295
|
}
|
|
296
|
-
function
|
|
297
|
-
t.enabled !== !1 && (
|
|
296
|
+
function ne(a) {
|
|
297
|
+
t.enabled !== !1 && (a.pointerType === "touch" ? Je(a) : qe(a));
|
|
298
298
|
}
|
|
299
|
-
function
|
|
300
|
-
|
|
299
|
+
function B(a) {
|
|
300
|
+
tt(a), E.length === 0 && (t.domElement.releasePointerCapture(a.pointerId), t.domElement.removeEventListener("pointermove", ne), t.domElement.removeEventListener("pointerup", B)), t.dispatchEvent(Pe), o = i.NONE;
|
|
301
301
|
}
|
|
302
|
-
function
|
|
302
|
+
function Ve(a) {
|
|
303
303
|
let g;
|
|
304
|
-
switch (
|
|
304
|
+
switch (a.button) {
|
|
305
305
|
case 0:
|
|
306
306
|
g = t.mouseButtons.LEFT;
|
|
307
307
|
break;
|
|
@@ -315,57 +315,57 @@ class ft extends at {
|
|
|
315
315
|
g = -1;
|
|
316
316
|
}
|
|
317
317
|
switch (g) {
|
|
318
|
-
case
|
|
318
|
+
case j.DOLLY:
|
|
319
319
|
if (t.enableZoom === !1) return;
|
|
320
|
-
|
|
320
|
+
Ae(a), o = i.DOLLY;
|
|
321
321
|
break;
|
|
322
|
-
case
|
|
323
|
-
if (
|
|
322
|
+
case j.ROTATE:
|
|
323
|
+
if (a.ctrlKey || a.metaKey || a.shiftKey) {
|
|
324
324
|
if (t.enablePan === !1) return;
|
|
325
|
-
|
|
325
|
+
ge(a), o = i.PAN;
|
|
326
326
|
} else {
|
|
327
327
|
if (t.enableRotate === !1) return;
|
|
328
|
-
|
|
328
|
+
pe(a), o = i.ROTATE;
|
|
329
329
|
}
|
|
330
330
|
break;
|
|
331
|
-
case
|
|
332
|
-
if (
|
|
331
|
+
case j.PAN:
|
|
332
|
+
if (a.ctrlKey || a.metaKey || a.shiftKey) {
|
|
333
333
|
if (t.enableRotate === !1) return;
|
|
334
|
-
|
|
334
|
+
pe(a), o = i.ROTATE;
|
|
335
335
|
} else {
|
|
336
336
|
if (t.enablePan === !1) return;
|
|
337
|
-
|
|
337
|
+
ge(a), o = i.PAN;
|
|
338
338
|
}
|
|
339
339
|
break;
|
|
340
340
|
default:
|
|
341
341
|
o = i.NONE;
|
|
342
342
|
}
|
|
343
|
-
o !== i.NONE && t.dispatchEvent(
|
|
343
|
+
o !== i.NONE && t.dispatchEvent(le);
|
|
344
344
|
}
|
|
345
|
-
function
|
|
345
|
+
function qe(a) {
|
|
346
346
|
switch (o) {
|
|
347
347
|
case i.ROTATE:
|
|
348
348
|
if (t.enableRotate === !1) return;
|
|
349
|
-
|
|
349
|
+
je(a);
|
|
350
350
|
break;
|
|
351
351
|
case i.DOLLY:
|
|
352
352
|
if (t.enableZoom === !1) return;
|
|
353
|
-
|
|
353
|
+
$e(a);
|
|
354
354
|
break;
|
|
355
355
|
case i.PAN:
|
|
356
356
|
if (t.enablePan === !1) return;
|
|
357
|
-
|
|
357
|
+
Ge(a);
|
|
358
358
|
break;
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
|
-
function we(
|
|
362
|
-
t.enabled === !1 || t.enableZoom === !1 || o !== i.NONE || (
|
|
361
|
+
function we(a) {
|
|
362
|
+
t.enabled === !1 || t.enableZoom === !1 || o !== i.NONE || (a.preventDefault(), t.dispatchEvent(le), Ye(We(a)), t.dispatchEvent(Pe));
|
|
363
363
|
}
|
|
364
|
-
function
|
|
365
|
-
const g =
|
|
366
|
-
clientX:
|
|
367
|
-
clientY:
|
|
368
|
-
deltaY:
|
|
364
|
+
function We(a) {
|
|
365
|
+
const g = a.deltaMode, v = {
|
|
366
|
+
clientX: a.clientX,
|
|
367
|
+
clientY: a.clientY,
|
|
368
|
+
deltaY: a.deltaY
|
|
369
369
|
};
|
|
370
370
|
switch (g) {
|
|
371
371
|
case 1:
|
|
@@ -375,28 +375,28 @@ class ft extends at {
|
|
|
375
375
|
v.deltaY *= 100;
|
|
376
376
|
break;
|
|
377
377
|
}
|
|
378
|
-
return
|
|
378
|
+
return a.ctrlKey && !te && (v.deltaY *= 10), v;
|
|
379
379
|
}
|
|
380
|
-
function
|
|
381
|
-
|
|
380
|
+
function Ze(a) {
|
|
381
|
+
a.key === "Control" && (te = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
|
|
382
382
|
}
|
|
383
|
-
function
|
|
384
|
-
|
|
383
|
+
function Me(a) {
|
|
384
|
+
a.key === "Control" && (te = !1, document.removeEventListener("keyup", Me, { passive: !0, capture: !0 }));
|
|
385
385
|
}
|
|
386
|
-
function
|
|
387
|
-
t.enabled === !1 || t.enablePan === !1 ||
|
|
386
|
+
function ae(a) {
|
|
387
|
+
t.enabled === !1 || t.enablePan === !1 || Be(a);
|
|
388
388
|
}
|
|
389
|
-
function
|
|
390
|
-
switch (
|
|
389
|
+
function Qe(a) {
|
|
390
|
+
switch (Ce(a), E.length) {
|
|
391
391
|
case 1:
|
|
392
392
|
switch (t.touches.ONE) {
|
|
393
|
-
case
|
|
393
|
+
case $.ROTATE:
|
|
394
394
|
if (t.enableRotate === !1) return;
|
|
395
|
-
|
|
395
|
+
ue(a), o = i.TOUCH_ROTATE;
|
|
396
396
|
break;
|
|
397
|
-
case
|
|
397
|
+
case $.PAN:
|
|
398
398
|
if (t.enablePan === !1) return;
|
|
399
|
-
|
|
399
|
+
fe(a), o = i.TOUCH_PAN;
|
|
400
400
|
break;
|
|
401
401
|
default:
|
|
402
402
|
o = i.NONE;
|
|
@@ -404,13 +404,13 @@ class ft extends at {
|
|
|
404
404
|
break;
|
|
405
405
|
case 2:
|
|
406
406
|
switch (t.touches.TWO) {
|
|
407
|
-
case
|
|
407
|
+
case $.DOLLY_PAN:
|
|
408
408
|
if (t.enableZoom === !1 && t.enablePan === !1) return;
|
|
409
|
-
|
|
409
|
+
Ke(a), o = i.TOUCH_DOLLY_PAN;
|
|
410
410
|
break;
|
|
411
|
-
case
|
|
411
|
+
case $.DOLLY_ROTATE:
|
|
412
412
|
if (t.enableZoom === !1 && t.enableRotate === !1) return;
|
|
413
|
-
|
|
413
|
+
Ue(a), o = i.TOUCH_DOLLY_ROTATE;
|
|
414
414
|
break;
|
|
415
415
|
default:
|
|
416
416
|
o = i.NONE;
|
|
@@ -419,56 +419,56 @@ class ft extends at {
|
|
|
419
419
|
default:
|
|
420
420
|
o = i.NONE;
|
|
421
421
|
}
|
|
422
|
-
o !== i.NONE && t.dispatchEvent(
|
|
422
|
+
o !== i.NONE && t.dispatchEvent(le);
|
|
423
423
|
}
|
|
424
|
-
function
|
|
425
|
-
switch (
|
|
424
|
+
function Je(a) {
|
|
425
|
+
switch (Ce(a), o) {
|
|
426
426
|
case i.TOUCH_ROTATE:
|
|
427
427
|
if (t.enableRotate === !1) return;
|
|
428
|
-
|
|
428
|
+
ye(a), t.update();
|
|
429
429
|
break;
|
|
430
430
|
case i.TOUCH_PAN:
|
|
431
431
|
if (t.enablePan === !1) return;
|
|
432
|
-
|
|
432
|
+
xe(a), t.update();
|
|
433
433
|
break;
|
|
434
434
|
case i.TOUCH_DOLLY_PAN:
|
|
435
435
|
if (t.enableZoom === !1 && t.enablePan === !1) return;
|
|
436
|
-
|
|
436
|
+
_e(a), t.update();
|
|
437
437
|
break;
|
|
438
438
|
case i.TOUCH_DOLLY_ROTATE:
|
|
439
439
|
if (t.enableZoom === !1 && t.enableRotate === !1) return;
|
|
440
|
-
|
|
440
|
+
Xe(a), t.update();
|
|
441
441
|
break;
|
|
442
442
|
default:
|
|
443
443
|
o = i.NONE;
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
|
-
function
|
|
447
|
-
t.enabled !== !1 &&
|
|
446
|
+
function Ee(a) {
|
|
447
|
+
t.enabled !== !1 && a.preventDefault();
|
|
448
448
|
}
|
|
449
|
-
function
|
|
450
|
-
E.push(
|
|
449
|
+
function et(a) {
|
|
450
|
+
E.push(a.pointerId);
|
|
451
451
|
}
|
|
452
|
-
function
|
|
453
|
-
delete
|
|
452
|
+
function tt(a) {
|
|
453
|
+
delete V[a.pointerId];
|
|
454
454
|
for (let g = 0; g < E.length; g++)
|
|
455
|
-
if (E[g] ==
|
|
455
|
+
if (E[g] == a.pointerId) {
|
|
456
456
|
E.splice(g, 1);
|
|
457
457
|
return;
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
|
-
function
|
|
461
|
-
let g =
|
|
462
|
-
g === void 0 && (g = new k(),
|
|
460
|
+
function Ce(a) {
|
|
461
|
+
let g = V[a.pointerId];
|
|
462
|
+
g === void 0 && (g = new k(), V[a.pointerId] = g), g.set(a.pageX, a.pageY);
|
|
463
463
|
}
|
|
464
|
-
function
|
|
465
|
-
const g =
|
|
466
|
-
return
|
|
464
|
+
function A(a) {
|
|
465
|
+
const g = a.pointerId === E[0] ? E[1] : E[0];
|
|
466
|
+
return V[g];
|
|
467
467
|
}
|
|
468
|
-
t.domElement.addEventListener("contextmenu",
|
|
468
|
+
t.domElement.addEventListener("contextmenu", Ee), t.domElement.addEventListener("pointerdown", ve), t.domElement.addEventListener("pointercancel", B), t.domElement.addEventListener("wheel", we, { passive: !1 }), document.addEventListener("keydown", Ze, { passive: !0, capture: !0 }), this.update();
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
|
-
class
|
|
471
|
+
class ft {
|
|
472
472
|
constructor(e, s) {
|
|
473
473
|
l(this, "scene");
|
|
474
474
|
l(this, "camera");
|
|
@@ -476,42 +476,42 @@ class mt {
|
|
|
476
476
|
l(this, "controls");
|
|
477
477
|
l(this, "container");
|
|
478
478
|
l(this, "resizeHandler");
|
|
479
|
-
this.container = e, this.scene = new
|
|
479
|
+
this.container = e, this.scene = new x.Scene(), this.scene.background = new x.Color(
|
|
480
480
|
s.backgroundColor ?? 657930
|
|
481
481
|
);
|
|
482
|
-
const { width: t, height: i } =
|
|
483
|
-
this.camera = new
|
|
484
|
-
const
|
|
485
|
-
this.camera.position.set(
|
|
482
|
+
const { width: t, height: i } = ke(e), o = s.cameraFov ?? 75;
|
|
483
|
+
this.camera = new x.PerspectiveCamera(o, t / i, 0.1, 2e3);
|
|
484
|
+
const n = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
|
|
485
|
+
this.camera.position.set(n.x, n.y, n.z), this.renderer = new x.WebGLRenderer({
|
|
486
486
|
antialias: !0,
|
|
487
487
|
alpha: !0,
|
|
488
488
|
powerPreference: "high-performance"
|
|
489
|
-
}), this.renderer.setSize(t, i), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping =
|
|
489
|
+
}), this.renderer.setSize(t, i), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = x.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = x.PCFSoftShadowMap, e.appendChild(this.renderer.domElement), this.controls = new ut(this.camera, this.renderer.domElement), this.controls.enableDamping = !0, this.controls.dampingFactor = 0.05, this.controls.rotateSpeed = 0.8, this.controls.zoomSpeed = 1.2, this.controls.minDistance = 10, this.controls.maxDistance = 2e3, this.setupLighting(), this.resizeHandler = this.onWindowResize.bind(this), window.addEventListener("resize", this.resizeHandler);
|
|
490
490
|
}
|
|
491
491
|
/**
|
|
492
492
|
* Sets up scene lighting for gradient glass on dark background
|
|
493
493
|
*/
|
|
494
494
|
setupLighting() {
|
|
495
|
-
const e = new
|
|
495
|
+
const e = new x.AmbientLight(16777215, 0.4);
|
|
496
496
|
this.scene.add(e);
|
|
497
|
-
const s = new
|
|
497
|
+
const s = new x.DirectionalLight(16777215, 0.9);
|
|
498
498
|
s.position.set(50, 60, 40), s.castShadow = !0, s.shadow.mapSize.width = 1024, s.shadow.mapSize.height = 1024, this.scene.add(s);
|
|
499
|
-
const t = new
|
|
499
|
+
const t = new x.DirectionalLight(16773344, 0.4);
|
|
500
500
|
t.position.set(-50, 30, -40), this.scene.add(t);
|
|
501
|
-
const i = new
|
|
501
|
+
const i = new x.DirectionalLight(16777215, 0.3);
|
|
502
502
|
i.position.set(0, -30, -50), this.scene.add(i);
|
|
503
|
-
const o = new
|
|
503
|
+
const o = new x.PointLight(16750950, 0.5, 150);
|
|
504
504
|
o.position.set(40, 20, 40), this.scene.add(o);
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
const r = new
|
|
505
|
+
const n = new x.PointLight(16764057, 0.4, 150);
|
|
506
|
+
n.position.set(-40, -20, 40), this.scene.add(n);
|
|
507
|
+
const r = new x.PointLight(6724095, 0.2, 100);
|
|
508
508
|
r.position.set(0, 40, -40), this.scene.add(r);
|
|
509
509
|
}
|
|
510
510
|
/**
|
|
511
511
|
* Handle window resize
|
|
512
512
|
*/
|
|
513
513
|
onWindowResize() {
|
|
514
|
-
const { width: e, height: s } =
|
|
514
|
+
const { width: e, height: s } = ke(this.container);
|
|
515
515
|
this.camera.aspect = e / s, this.camera.updateProjectionMatrix(), this.renderer.setSize(e, s);
|
|
516
516
|
}
|
|
517
517
|
/**
|
|
@@ -546,7 +546,7 @@ class mt {
|
|
|
546
546
|
* Gets the camera's forward direction
|
|
547
547
|
*/
|
|
548
548
|
getCameraDirection() {
|
|
549
|
-
const e = new
|
|
549
|
+
const e = new x.Vector3();
|
|
550
550
|
return this.camera.getWorldDirection(e), e;
|
|
551
551
|
}
|
|
552
552
|
/**
|
|
@@ -559,7 +559,7 @@ class mt {
|
|
|
559
559
|
}
|
|
560
560
|
}
|
|
561
561
|
}
|
|
562
|
-
const
|
|
562
|
+
const X = class X {
|
|
563
563
|
constructor(e, s) {
|
|
564
564
|
l(this, "sceneManager");
|
|
565
565
|
l(this, "nodeFactory");
|
|
@@ -578,18 +578,18 @@ const V = class V {
|
|
|
578
578
|
* Call this before adding nodes in bulk.
|
|
579
579
|
*/
|
|
580
580
|
static setExpectedNodeCount(e) {
|
|
581
|
-
|
|
581
|
+
X.expectedNodeCount = e;
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
584
|
* Adds a node to the graph
|
|
585
585
|
* @returns true if added, false if node already exists or invalid
|
|
586
586
|
*/
|
|
587
587
|
addNode(e, s = 0) {
|
|
588
|
-
if (!
|
|
588
|
+
if (!Fe(e))
|
|
589
589
|
return !1;
|
|
590
590
|
if (this.nodes.has(e.id))
|
|
591
591
|
return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`), !1;
|
|
592
|
-
const t = Math.max(50, Math.cbrt(
|
|
592
|
+
const t = Math.max(50, Math.cbrt(X.expectedNodeCount) * 10), i = e.position ?? {
|
|
593
593
|
x: (Math.random() - 0.5) * t,
|
|
594
594
|
y: (Math.random() - 0.5) * t,
|
|
595
595
|
z: (Math.random() - 0.5) * t
|
|
@@ -598,11 +598,11 @@ const V = class V {
|
|
|
598
598
|
position: i,
|
|
599
599
|
velocity: { x: 0, y: 0, z: 0 },
|
|
600
600
|
mass: 1
|
|
601
|
-
},
|
|
601
|
+
}, n = this.nodeFactory.createNode(
|
|
602
602
|
{ ...e, position: i },
|
|
603
603
|
s
|
|
604
604
|
);
|
|
605
|
-
return this.sceneManager.add(
|
|
605
|
+
return this.sceneManager.add(n.group), this.nodes.set(e.id, o), this.nodeObjects.set(e.id, n), !0;
|
|
606
606
|
}
|
|
607
607
|
/**
|
|
608
608
|
* Removes a node from the graph
|
|
@@ -693,16 +693,23 @@ const V = class V {
|
|
|
693
693
|
}
|
|
694
694
|
};
|
|
695
695
|
// Scale spawn volume with expected graph size
|
|
696
|
-
l(
|
|
697
|
-
let
|
|
698
|
-
class
|
|
696
|
+
l(X, "expectedNodeCount", 100);
|
|
697
|
+
let ee = X;
|
|
698
|
+
class mt {
|
|
699
699
|
constructor(e, s, t) {
|
|
700
700
|
l(this, "sceneManager");
|
|
701
701
|
l(this, "nodeManager");
|
|
702
702
|
l(this, "edgeFactory");
|
|
703
|
+
// Full relationship list (includes duplicates between same pair)
|
|
703
704
|
l(this, "edges", []);
|
|
705
|
+
// One visual line per directed pair (source -> target)
|
|
704
706
|
l(this, "edgeObjects", []);
|
|
707
|
+
// Tracks which directed pairs currently have at least one relationship
|
|
705
708
|
l(this, "edgeKeySet", /* @__PURE__ */ new Set());
|
|
709
|
+
// Maps directed pair key to the relationship list for that pair
|
|
710
|
+
l(this, "edgeGroups", /* @__PURE__ */ new Map());
|
|
711
|
+
// Maps directed pair key to the corresponding visual line
|
|
712
|
+
l(this, "edgeObjectMap", /* @__PURE__ */ new Map());
|
|
706
713
|
l(this, "highlightedEdgeKey", null);
|
|
707
714
|
this.sceneManager = e, this.nodeManager = s, this.edgeFactory = t;
|
|
708
715
|
}
|
|
@@ -710,68 +717,92 @@ class yt {
|
|
|
710
717
|
* Checks if an edge exists
|
|
711
718
|
*/
|
|
712
719
|
hasEdge(e, s) {
|
|
713
|
-
const t =
|
|
720
|
+
const t = this.createDirectedEdgeKey(e, s);
|
|
714
721
|
return this.edgeKeySet.has(t);
|
|
715
722
|
}
|
|
716
723
|
/**
|
|
717
724
|
* Adds an edge to the graph
|
|
718
|
-
* @returns true if added, false if
|
|
725
|
+
* @returns true if added, false if invalid or nodes don't exist
|
|
719
726
|
*/
|
|
720
727
|
addEdge(e) {
|
|
721
|
-
if (!
|
|
728
|
+
if (!De(e))
|
|
722
729
|
return !1;
|
|
723
730
|
if (!this.nodeManager.hasNode(e.source))
|
|
724
731
|
return console.warn(`[ForceGraph3D] Source node "${e.source}" does not exist`), !1;
|
|
725
732
|
if (!this.nodeManager.hasNode(e.target))
|
|
726
733
|
return console.warn(`[ForceGraph3D] Target node "${e.target}" does not exist`), !1;
|
|
727
|
-
const s =
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
734
|
+
const s = this.nodeManager.getNode(e.source), t = this.nodeManager.getNode(e.target), i = this.createDirectedEdgeKey(e.source, e.target);
|
|
735
|
+
this.edges.push(e);
|
|
736
|
+
const o = this.edgeGroups.get(i);
|
|
737
|
+
if (o) {
|
|
738
|
+
o.push(e);
|
|
739
|
+
const r = this.edgeObjectMap.get(i);
|
|
740
|
+
return r && this.updateEdgeUserData(r, o, s, t), !0;
|
|
741
|
+
}
|
|
742
|
+
const n = this.edgeFactory.createEdge(
|
|
731
743
|
e,
|
|
744
|
+
s,
|
|
732
745
|
t,
|
|
733
|
-
|
|
734
|
-
t.position
|
|
735
|
-
i.position
|
|
746
|
+
s.position,
|
|
747
|
+
t.position
|
|
736
748
|
);
|
|
737
|
-
return this.sceneManager.add(
|
|
749
|
+
return this.sceneManager.add(n.line), this.edgeGroups.set(i, [e]), this.edgeObjectMap.set(i, n), this.edgeObjects.push(n), this.edgeKeySet.add(i), this.updateEdgeUserData(n, [e], s, t), !0;
|
|
738
750
|
}
|
|
739
751
|
/**
|
|
740
752
|
* Removes an edge from the graph
|
|
753
|
+
* Removes one relationship instance for source -> target.
|
|
741
754
|
* @returns true if removed, false if not found
|
|
742
755
|
*/
|
|
743
756
|
removeEdge(e, s) {
|
|
744
|
-
const t =
|
|
757
|
+
const t = this.createDirectedEdgeKey(e, s);
|
|
745
758
|
if (!this.edgeKeySet.has(t))
|
|
746
759
|
return !1;
|
|
747
760
|
const i = this.edges.findIndex(
|
|
748
|
-
(
|
|
761
|
+
(c) => c.source === e && c.target === s
|
|
749
762
|
);
|
|
750
763
|
if (i === -1)
|
|
751
764
|
return !1;
|
|
752
|
-
const o = this.
|
|
753
|
-
|
|
765
|
+
const o = this.edges[i];
|
|
766
|
+
this.edges.splice(i, 1);
|
|
767
|
+
const n = this.edgeGroups.get(t);
|
|
768
|
+
if (!n)
|
|
769
|
+
return !0;
|
|
770
|
+
const r = n.findIndex((c) => c === o);
|
|
771
|
+
if (r !== -1)
|
|
772
|
+
n.splice(r, 1);
|
|
773
|
+
else {
|
|
774
|
+
const c = n.findIndex((p) => p.source === e && p.target === s);
|
|
775
|
+
c !== -1 && n.splice(c, 1);
|
|
776
|
+
}
|
|
777
|
+
const d = this.edgeObjectMap.get(t);
|
|
778
|
+
if (!d)
|
|
779
|
+
return !0;
|
|
780
|
+
if (n.length === 0) {
|
|
781
|
+
this.sceneManager.remove(d.line), this.edgeFactory.disposeEdge(d);
|
|
782
|
+
const c = this.edgeObjects.findIndex((p) => p === d);
|
|
783
|
+
c !== -1 && this.edgeObjects.splice(c, 1), this.edgeGroups.delete(t), this.edgeObjectMap.delete(t), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null);
|
|
784
|
+
} else {
|
|
785
|
+
const c = this.nodeManager.getNode(e), p = this.nodeManager.getNode(s);
|
|
786
|
+
c && p && this.updateEdgeUserData(d, n, c, p);
|
|
787
|
+
}
|
|
788
|
+
return !0;
|
|
754
789
|
}
|
|
755
790
|
/**
|
|
756
791
|
* Highlights an edge
|
|
757
792
|
*/
|
|
758
793
|
highlightEdge(e, s) {
|
|
759
|
-
const t =
|
|
794
|
+
const t = this.createDirectedEdgeKey(e, s);
|
|
760
795
|
this.highlightedEdgeKey && this.highlightedEdgeKey !== t && this.unhighlightCurrentEdge();
|
|
761
|
-
const i = this.
|
|
762
|
-
|
|
763
|
-
);
|
|
764
|
-
i !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[i]), this.highlightedEdgeKey = t);
|
|
796
|
+
const i = this.edgeObjectMap.get(t);
|
|
797
|
+
i && (this.edgeFactory.highlightEdge(i), this.highlightedEdgeKey = t);
|
|
765
798
|
}
|
|
766
799
|
/**
|
|
767
800
|
* Unhighlights the currently highlighted edge
|
|
768
801
|
*/
|
|
769
802
|
unhighlightCurrentEdge() {
|
|
770
803
|
if (!this.highlightedEdgeKey) return;
|
|
771
|
-
const e = this.
|
|
772
|
-
|
|
773
|
-
);
|
|
774
|
-
e !== -1 && this.edgeFactory.unhighlightEdge(this.edgeObjects[e]), this.highlightedEdgeKey = null;
|
|
804
|
+
const e = this.edgeObjectMap.get(this.highlightedEdgeKey);
|
|
805
|
+
e && this.edgeFactory.unhighlightEdge(e), this.highlightedEdgeKey = null;
|
|
775
806
|
}
|
|
776
807
|
/**
|
|
777
808
|
* Removes all edges connected to a node
|
|
@@ -803,12 +834,12 @@ class yt {
|
|
|
803
834
|
* Updates all edge positions based on current node positions
|
|
804
835
|
*/
|
|
805
836
|
updateEdgePositions() {
|
|
806
|
-
this.edgeObjects.forEach((e
|
|
807
|
-
const
|
|
808
|
-
|
|
837
|
+
this.edgeObjects.forEach((e) => {
|
|
838
|
+
const s = this.nodeManager.getNode(e.source), t = this.nodeManager.getNode(e.target);
|
|
839
|
+
s && t && this.edgeFactory.updateEdgePositions(
|
|
809
840
|
e,
|
|
810
|
-
|
|
811
|
-
|
|
841
|
+
s.position,
|
|
842
|
+
t.position
|
|
812
843
|
);
|
|
813
844
|
});
|
|
814
845
|
}
|
|
@@ -836,7 +867,29 @@ class yt {
|
|
|
836
867
|
clear() {
|
|
837
868
|
this.edgeObjects.forEach((e) => {
|
|
838
869
|
this.sceneManager.remove(e.line), this.edgeFactory.disposeEdge(e);
|
|
839
|
-
}), this.edges = [], this.edgeObjects = [], this.edgeKeySet.clear(), this.highlightedEdgeKey = null;
|
|
870
|
+
}), this.edges = [], this.edgeObjects = [], this.edgeKeySet.clear(), this.edgeGroups.clear(), this.edgeObjectMap.clear(), this.highlightedEdgeKey = null;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Creates a directed key (source -> target)
|
|
874
|
+
*/
|
|
875
|
+
createDirectedEdgeKey(e, s) {
|
|
876
|
+
return `${e}->${s}`;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Syncs relationship metadata to the line for hover/click UI
|
|
880
|
+
*/
|
|
881
|
+
updateEdgeUserData(e, s, t, i) {
|
|
882
|
+
const o = s[0];
|
|
883
|
+
e.line.userData = {
|
|
884
|
+
...e.line.userData,
|
|
885
|
+
source: e.source,
|
|
886
|
+
target: e.target,
|
|
887
|
+
edge: o,
|
|
888
|
+
relationships: [...s],
|
|
889
|
+
relationshipCount: s.length,
|
|
890
|
+
sourceNode: t,
|
|
891
|
+
targetNode: i
|
|
892
|
+
};
|
|
840
893
|
}
|
|
841
894
|
/**
|
|
842
895
|
* Dispose resources
|
|
@@ -845,7 +898,7 @@ class yt {
|
|
|
845
898
|
this.clear();
|
|
846
899
|
}
|
|
847
900
|
}
|
|
848
|
-
class
|
|
901
|
+
class Re {
|
|
849
902
|
constructor(e, s, t = {}) {
|
|
850
903
|
l(this, "nodes");
|
|
851
904
|
l(this, "edges");
|
|
@@ -885,8 +938,8 @@ class Ie {
|
|
|
885
938
|
let s = 0, t = null;
|
|
886
939
|
for (const [i, o] of e) {
|
|
887
940
|
o > s && (s = o, t = i);
|
|
888
|
-
const
|
|
889
|
-
|
|
941
|
+
const n = this.nodes.get(i);
|
|
942
|
+
n && (n.mass = 1 + Math.log2(1 + o));
|
|
890
943
|
}
|
|
891
944
|
if (console.log(`[ForceGraph3D] Hub detected: id="${t}", degree=${s}, threshold=10`), t && s > 10) {
|
|
892
945
|
this.pinnedNodeId = t;
|
|
@@ -918,13 +971,13 @@ class Ie {
|
|
|
918
971
|
const e = Array.from(this.nodes.values()), s = e.length, t = this.getEffectiveRepulsion();
|
|
919
972
|
for (let i = 0; i < s; i++) {
|
|
920
973
|
const o = e[i];
|
|
921
|
-
for (let
|
|
922
|
-
const r = e[
|
|
923
|
-
let
|
|
924
|
-
if (
|
|
925
|
-
|
|
926
|
-
const m = Math.sqrt(
|
|
927
|
-
o.velocity.x -=
|
|
974
|
+
for (let n = i + 1; n < s; n++) {
|
|
975
|
+
const r = e[n], d = r.position.x - o.position.x, c = r.position.y - o.position.y, p = r.position.z - o.position.z;
|
|
976
|
+
let f = d * d + c * c + p * p;
|
|
977
|
+
if (f > this.REPULSION_CUTOFF_SQ) continue;
|
|
978
|
+
f < 0.01 && (f = 0.01);
|
|
979
|
+
const m = Math.sqrt(f), u = t * this.alpha / f, y = d / m * u, b = c / m * u, w = p / m * u;
|
|
980
|
+
o.velocity.x -= y / o.mass, o.velocity.y -= b / o.mass, o.velocity.z -= w / o.mass, r.velocity.x += y / r.mass, r.velocity.y += b / r.mass, r.velocity.z += w / r.mass;
|
|
928
981
|
}
|
|
929
982
|
}
|
|
930
983
|
}
|
|
@@ -932,7 +985,7 @@ class Ie {
|
|
|
932
985
|
* Barnes-Hut approximation - O(n log n)
|
|
933
986
|
*/
|
|
934
987
|
calculateRepulsionBarnesHut() {
|
|
935
|
-
const e = Array.from(this.nodes.values()), s = new
|
|
988
|
+
const e = Array.from(this.nodes.values()), s = new yt(e);
|
|
936
989
|
for (const t of e)
|
|
937
990
|
this.calculateForceFromOctree(t, s.root);
|
|
938
991
|
}
|
|
@@ -945,26 +998,26 @@ class Ie {
|
|
|
945
998
|
return;
|
|
946
999
|
}
|
|
947
1000
|
if (s.mass === 0) return;
|
|
948
|
-
const t = s.centerOfMass.x - e.position.x, i = s.centerOfMass.y - e.position.y, o = s.centerOfMass.z - e.position.z,
|
|
949
|
-
if (
|
|
950
|
-
const r = Math.sqrt(
|
|
1001
|
+
const t = s.centerOfMass.x - e.position.x, i = s.centerOfMass.y - e.position.y, o = s.centerOfMass.z - e.position.z, n = t * t + i * i + o * o;
|
|
1002
|
+
if (n > this.REPULSION_CUTOFF_SQ) return;
|
|
1003
|
+
const r = Math.sqrt(n), d = this.getEffectiveRepulsion();
|
|
951
1004
|
if (r > 0 && s.size / r < this.barnesHutTheta) {
|
|
952
|
-
const
|
|
1005
|
+
const c = Math.max(n, 0.01), p = d * this.alpha * s.mass / c;
|
|
953
1006
|
e.velocity.x -= t / r * p / e.mass, e.velocity.y -= i / r * p / e.mass, e.velocity.z -= o / r * p / e.mass;
|
|
954
1007
|
} else
|
|
955
|
-
for (const
|
|
956
|
-
|
|
1008
|
+
for (const c of s.children)
|
|
1009
|
+
c && this.calculateForceFromOctree(e, c);
|
|
957
1010
|
}
|
|
958
1011
|
/**
|
|
959
1012
|
* Apply repulsion between two nodes (with cutoff)
|
|
960
1013
|
*/
|
|
961
1014
|
applyRepulsionBetween(e, s) {
|
|
962
1015
|
const t = s.position.x - e.position.x, i = s.position.y - e.position.y, o = s.position.z - e.position.z;
|
|
963
|
-
let
|
|
964
|
-
if (
|
|
965
|
-
|
|
966
|
-
const r = Math.sqrt(
|
|
967
|
-
e.velocity.x -= t / r *
|
|
1016
|
+
let n = t * t + i * i + o * o;
|
|
1017
|
+
if (n > this.REPULSION_CUTOFF_SQ) return;
|
|
1018
|
+
n < 0.01 && (n = 0.01);
|
|
1019
|
+
const r = Math.sqrt(n), c = this.getEffectiveRepulsion() * this.alpha / n;
|
|
1020
|
+
e.velocity.x -= t / r * c / e.mass, e.velocity.y -= i / r * c / e.mass, e.velocity.z -= o / r * c / e.mass;
|
|
968
1021
|
}
|
|
969
1022
|
/**
|
|
970
1023
|
* Calculate attraction forces along edges
|
|
@@ -974,10 +1027,10 @@ class Ie {
|
|
|
974
1027
|
for (const t of this.edges) {
|
|
975
1028
|
const i = this.nodes.get(t.source), o = this.nodes.get(t.target);
|
|
976
1029
|
if (!i || !o) continue;
|
|
977
|
-
const
|
|
978
|
-
if (
|
|
979
|
-
const
|
|
980
|
-
i.velocity.x += m / i.mass, i.velocity.y += u / i.mass, i.velocity.z +=
|
|
1030
|
+
const n = o.position.x - i.position.x, r = o.position.y - i.position.y, d = o.position.z - i.position.z, c = Math.sqrt(n * n + r * r + d * d);
|
|
1031
|
+
if (c < 0.01) continue;
|
|
1032
|
+
const f = (c - 15) * this.attractionStrength * s * this.alpha, m = n / c * f, u = r / c * f, y = d / c * f;
|
|
1033
|
+
i.velocity.x += m / i.mass, i.velocity.y += u / i.mass, i.velocity.z += y / i.mass, o.velocity.x -= m / o.mass, o.velocity.y -= u / o.mass, o.velocity.z -= y / o.mass;
|
|
981
1034
|
}
|
|
982
1035
|
}
|
|
983
1036
|
/**
|
|
@@ -1034,7 +1087,7 @@ class Ie {
|
|
|
1034
1087
|
e.repulsionStrength !== void 0 && (this.repulsionStrength = e.repulsionStrength), e.attractionStrength !== void 0 && (this.attractionStrength = e.attractionStrength), e.damping !== void 0 && (this.damping = e.damping);
|
|
1035
1088
|
}
|
|
1036
1089
|
}
|
|
1037
|
-
class
|
|
1090
|
+
class yt {
|
|
1038
1091
|
constructor(e) {
|
|
1039
1092
|
l(this, "root");
|
|
1040
1093
|
const s = this.calculateBounds(e);
|
|
@@ -1070,54 +1123,54 @@ class xt {
|
|
|
1070
1123
|
};
|
|
1071
1124
|
if (e.length === 1 || t > 20) {
|
|
1072
1125
|
let u = 0;
|
|
1073
|
-
const
|
|
1126
|
+
const y = { x: 0, y: 0, z: 0 };
|
|
1074
1127
|
for (const b of e)
|
|
1075
|
-
u += b.mass,
|
|
1076
|
-
return u > 0 && (
|
|
1128
|
+
u += b.mass, y.x += b.position.x * b.mass, y.y += b.position.y * b.mass, y.z += b.position.z * b.mass;
|
|
1129
|
+
return u > 0 && (y.x /= u, y.y /= u, y.z /= u), {
|
|
1077
1130
|
bounds: s,
|
|
1078
1131
|
size: i,
|
|
1079
|
-
centerOfMass:
|
|
1132
|
+
centerOfMass: y,
|
|
1080
1133
|
mass: u,
|
|
1081
1134
|
isLeaf: !0,
|
|
1082
1135
|
node: e[0],
|
|
1083
1136
|
children: []
|
|
1084
1137
|
};
|
|
1085
1138
|
}
|
|
1086
|
-
const o = (s.min.x + s.max.x) / 2,
|
|
1139
|
+
const o = (s.min.x + s.max.x) / 2, n = (s.min.y + s.max.y) / 2, r = (s.min.z + s.max.z) / 2, d = [[], [], [], [], [], [], [], []];
|
|
1087
1140
|
for (const u of e) {
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
}
|
|
1091
|
-
const
|
|
1092
|
-
{ min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: o, y:
|
|
1093
|
-
{ min: { x: o, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y:
|
|
1094
|
-
{ min: { x: s.min.x, y:
|
|
1095
|
-
{ min: { x: o, y:
|
|
1096
|
-
{ min: { x: s.min.x, y: s.min.y, z: r }, max: { x: o, y:
|
|
1097
|
-
{ min: { x: o, y: s.min.y, z: r }, max: { x: s.max.x, y:
|
|
1098
|
-
{ min: { x: s.min.x, y:
|
|
1099
|
-
{ min: { x: o, y:
|
|
1141
|
+
const y = (u.position.x >= o ? 1 : 0) + (u.position.y >= n ? 2 : 0) + (u.position.z >= r ? 4 : 0);
|
|
1142
|
+
d[y].push(u);
|
|
1143
|
+
}
|
|
1144
|
+
const c = [
|
|
1145
|
+
{ min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: o, y: n, z: r } },
|
|
1146
|
+
{ min: { x: o, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: n, z: r } },
|
|
1147
|
+
{ min: { x: s.min.x, y: n, z: s.min.z }, max: { x: o, y: s.max.y, z: r } },
|
|
1148
|
+
{ min: { x: o, y: n, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
|
|
1149
|
+
{ min: { x: s.min.x, y: s.min.y, z: r }, max: { x: o, y: n, z: s.max.z } },
|
|
1150
|
+
{ min: { x: o, y: s.min.y, z: r }, max: { x: s.max.x, y: n, z: s.max.z } },
|
|
1151
|
+
{ min: { x: s.min.x, y: n, z: r }, max: { x: o, y: s.max.y, z: s.max.z } },
|
|
1152
|
+
{ min: { x: o, y: n, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
|
|
1100
1153
|
], p = [];
|
|
1101
|
-
let
|
|
1154
|
+
let f = 0;
|
|
1102
1155
|
const m = { x: 0, y: 0, z: 0 };
|
|
1103
1156
|
for (let u = 0; u < 8; u++)
|
|
1104
|
-
if (
|
|
1105
|
-
const
|
|
1106
|
-
p.push(
|
|
1157
|
+
if (d[u].length > 0) {
|
|
1158
|
+
const y = this.buildTree(d[u], c[u], t + 1);
|
|
1159
|
+
p.push(y), f += y.mass, m.x += y.centerOfMass.x * y.mass, m.y += y.centerOfMass.y * y.mass, m.z += y.centerOfMass.z * y.mass;
|
|
1107
1160
|
} else
|
|
1108
1161
|
p.push(null);
|
|
1109
|
-
return
|
|
1162
|
+
return f > 0 && (m.x /= f, m.y /= f, m.z /= f), {
|
|
1110
1163
|
bounds: s,
|
|
1111
1164
|
size: i,
|
|
1112
1165
|
centerOfMass: m,
|
|
1113
|
-
mass:
|
|
1166
|
+
mass: f,
|
|
1114
1167
|
isLeaf: !1,
|
|
1115
1168
|
node: null,
|
|
1116
1169
|
children: p
|
|
1117
1170
|
};
|
|
1118
1171
|
}
|
|
1119
1172
|
}
|
|
1120
|
-
class
|
|
1173
|
+
class xt {
|
|
1121
1174
|
constructor(e, s, t, i = 60) {
|
|
1122
1175
|
l(this, "sceneManager");
|
|
1123
1176
|
l(this, "animationId", null);
|
|
@@ -1182,7 +1235,7 @@ class bt {
|
|
|
1182
1235
|
this.stop();
|
|
1183
1236
|
}
|
|
1184
1237
|
}
|
|
1185
|
-
class
|
|
1238
|
+
class bt {
|
|
1186
1239
|
constructor() {
|
|
1187
1240
|
l(this, "envMap", null);
|
|
1188
1241
|
l(this, "materialCache", /* @__PURE__ */ new Map());
|
|
@@ -1223,7 +1276,7 @@ class vt {
|
|
|
1223
1276
|
for (const i of t) {
|
|
1224
1277
|
const o = document.createElement("canvas");
|
|
1225
1278
|
o.width = 256, o.height = 256;
|
|
1226
|
-
const
|
|
1279
|
+
const n = o.getContext("2d"), r = n.createRadialGradient(
|
|
1227
1280
|
256 / 2,
|
|
1228
1281
|
256 / 2,
|
|
1229
1282
|
0,
|
|
@@ -1231,15 +1284,15 @@ class vt {
|
|
|
1231
1284
|
256 / 2,
|
|
1232
1285
|
256 * 0.8
|
|
1233
1286
|
);
|
|
1234
|
-
r.addColorStop(0, i.colors[0]), r.addColorStop(0.5, i.colors[1]), r.addColorStop(1, i.colors[2]),
|
|
1235
|
-
const
|
|
1236
|
-
for (let
|
|
1287
|
+
r.addColorStop(0, i.colors[0]), r.addColorStop(0.5, i.colors[1]), r.addColorStop(1, i.colors[2]), n.fillStyle = r, n.fillRect(0, 0, 256, 256);
|
|
1288
|
+
const d = n.getImageData(0, 0, 256, 256);
|
|
1289
|
+
for (let c = 0; c < d.data.length; c += 4) {
|
|
1237
1290
|
const p = (Math.random() - 0.5) * 5;
|
|
1238
|
-
|
|
1291
|
+
d.data[c] = Math.min(255, Math.max(0, d.data[c] + p)), d.data[c + 1] = Math.min(255, Math.max(0, d.data[c + 1] + p)), d.data[c + 2] = Math.min(255, Math.max(0, d.data[c + 2] + p));
|
|
1239
1292
|
}
|
|
1240
|
-
|
|
1293
|
+
n.putImageData(d, 0, 0), s.push(o);
|
|
1241
1294
|
}
|
|
1242
|
-
this.envMap = new
|
|
1295
|
+
this.envMap = new x.CubeTexture(s.map((i) => {
|
|
1243
1296
|
const o = new Image();
|
|
1244
1297
|
return o.src = i.toDataURL(), o;
|
|
1245
1298
|
})), this.envMap.needsUpdate = !0;
|
|
@@ -1258,11 +1311,11 @@ class vt {
|
|
|
1258
1311
|
const t = "glass-single";
|
|
1259
1312
|
if (this.materialCache.has(t))
|
|
1260
1313
|
return this.materialCache.get(t).clone();
|
|
1261
|
-
const i = new
|
|
1314
|
+
const i = new x.Color(16750950), o = new x.ShaderMaterial({
|
|
1262
1315
|
uniforms: {
|
|
1263
1316
|
uColor: { value: i },
|
|
1264
1317
|
uEnvMap: { value: this.envMap },
|
|
1265
|
-
uGlowColor: { value: new
|
|
1318
|
+
uGlowColor: { value: new x.Color(16777215) },
|
|
1266
1319
|
uGlowIntensity: { value: 0.8 },
|
|
1267
1320
|
uReflectivity: { value: 0.4 },
|
|
1268
1321
|
uFresnelPower: { value: 2.5 }
|
|
@@ -1328,9 +1381,9 @@ class vt {
|
|
|
1328
1381
|
}
|
|
1329
1382
|
`,
|
|
1330
1383
|
transparent: !0,
|
|
1331
|
-
side:
|
|
1384
|
+
side: x.FrontSide,
|
|
1332
1385
|
depthWrite: !0,
|
|
1333
|
-
blending:
|
|
1386
|
+
blending: x.NormalBlending
|
|
1334
1387
|
});
|
|
1335
1388
|
return this.materialCache.set(t, o), o.clone();
|
|
1336
1389
|
}
|
|
@@ -1338,7 +1391,7 @@ class vt {
|
|
|
1338
1391
|
* Creates material for edges (light color for dark background)
|
|
1339
1392
|
*/
|
|
1340
1393
|
createEdgeMaterial(e = 6710886, s = 0.4) {
|
|
1341
|
-
return new
|
|
1394
|
+
return new x.LineBasicMaterial({
|
|
1342
1395
|
color: e,
|
|
1343
1396
|
transparent: !0,
|
|
1344
1397
|
opacity: s,
|
|
@@ -1349,7 +1402,7 @@ class vt {
|
|
|
1349
1402
|
* Creates highlighted edge material
|
|
1350
1403
|
*/
|
|
1351
1404
|
createHighlightedEdgeMaterial() {
|
|
1352
|
-
return new
|
|
1405
|
+
return new x.LineBasicMaterial({
|
|
1353
1406
|
color: 16750950,
|
|
1354
1407
|
// Tangerine highlight
|
|
1355
1408
|
transparent: !1,
|
|
@@ -1363,10 +1416,10 @@ class vt {
|
|
|
1363
1416
|
createLabelMaterial(e, s = 24) {
|
|
1364
1417
|
const t = document.createElement("canvas"), i = t.getContext("2d");
|
|
1365
1418
|
i.font = `600 ${s}px Inter, -apple-system, sans-serif`;
|
|
1366
|
-
const
|
|
1367
|
-
t.width = Math.max(128,
|
|
1368
|
-
const r = new
|
|
1369
|
-
return r.needsUpdate = !0, new
|
|
1419
|
+
const n = i.measureText(e).width;
|
|
1420
|
+
t.width = Math.max(128, n + 24), t.height = s + 20, i.clearRect(0, 0, t.width, t.height), i.font = `600 ${s}px Inter, -apple-system, sans-serif`, i.textAlign = "center", i.textBaseline = "middle", i.shadowColor = "rgba(0, 0, 0, 0.8)", i.shadowBlur = 4, i.shadowOffsetX = 1, i.shadowOffsetY = 1, i.fillStyle = "rgba(255, 255, 255, 0.95)", i.fillText(e, t.width / 2, t.height / 2);
|
|
1421
|
+
const r = new x.CanvasTexture(t);
|
|
1422
|
+
return r.needsUpdate = !0, new x.SpriteMaterial({
|
|
1370
1423
|
map: r,
|
|
1371
1424
|
transparent: !0,
|
|
1372
1425
|
depthTest: !1,
|
|
@@ -1386,7 +1439,7 @@ class vt {
|
|
|
1386
1439
|
this.materialCache.forEach((e) => e.dispose()), this.materialCache.clear(), this.envMap && this.envMap.dispose();
|
|
1387
1440
|
}
|
|
1388
1441
|
}
|
|
1389
|
-
class
|
|
1442
|
+
class vt {
|
|
1390
1443
|
constructor(e, s = 2, t = [32, 16, 8], i = 16750950) {
|
|
1391
1444
|
l(this, "materialFactory");
|
|
1392
1445
|
l(this, "geometryCache", /* @__PURE__ */ new Map());
|
|
@@ -1403,7 +1456,7 @@ class Mt {
|
|
|
1403
1456
|
const t = `lod-${s}`;
|
|
1404
1457
|
this.geometryCache.set(
|
|
1405
1458
|
t,
|
|
1406
|
-
new
|
|
1459
|
+
new x.SphereGeometry(this.nodeRadius, e, e)
|
|
1407
1460
|
);
|
|
1408
1461
|
});
|
|
1409
1462
|
}
|
|
@@ -1418,21 +1471,21 @@ class Mt {
|
|
|
1418
1471
|
* Creates a node visual (glass ball + label)
|
|
1419
1472
|
*/
|
|
1420
1473
|
createNode(e, s = 0) {
|
|
1421
|
-
const t = new
|
|
1474
|
+
const t = new x.Group();
|
|
1422
1475
|
t.name = `node-${e.id}`, t.userData = { nodeId: e.id, nodeData: e };
|
|
1423
1476
|
const i = this.getGeometry(s), o = this.materialFactory.createGlassMaterial(
|
|
1424
1477
|
e.color ?? this.defaultNodeColor
|
|
1425
|
-
),
|
|
1426
|
-
|
|
1427
|
-
const r = this.materialFactory.createLabelMaterial(e.label),
|
|
1428
|
-
return
|
|
1478
|
+
), n = new x.Mesh(i, o);
|
|
1479
|
+
n.castShadow = !0, n.receiveShadow = !0, t.add(n);
|
|
1480
|
+
const r = this.materialFactory.createLabelMaterial(e.label), d = new x.Sprite(r);
|
|
1481
|
+
return d.position.y = this.nodeRadius + 1.5, d.scale.set(4, 1, 1), t.add(d), e.position && t.position.set(
|
|
1429
1482
|
e.position.x,
|
|
1430
1483
|
e.position.y,
|
|
1431
1484
|
e.position.z
|
|
1432
1485
|
), {
|
|
1433
1486
|
group: t,
|
|
1434
|
-
sphere:
|
|
1435
|
-
label:
|
|
1487
|
+
sphere: n,
|
|
1488
|
+
label: d,
|
|
1436
1489
|
lodLevel: s
|
|
1437
1490
|
};
|
|
1438
1491
|
}
|
|
@@ -1448,19 +1501,19 @@ class Mt {
|
|
|
1448
1501
|
* Updates the color of a node
|
|
1449
1502
|
*/
|
|
1450
1503
|
updateNodeColor(e, s) {
|
|
1451
|
-
e.sphere.material instanceof
|
|
1504
|
+
e.sphere.material instanceof x.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(s);
|
|
1452
1505
|
}
|
|
1453
1506
|
/**
|
|
1454
1507
|
* Updates the label of a node
|
|
1455
1508
|
*/
|
|
1456
1509
|
updateNodeLabel(e, s) {
|
|
1457
|
-
e.label.material instanceof
|
|
1510
|
+
e.label.material instanceof x.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose()), e.label.material = this.materialFactory.createLabelMaterial(s);
|
|
1458
1511
|
}
|
|
1459
1512
|
/**
|
|
1460
1513
|
* Disposes a node's resources
|
|
1461
1514
|
*/
|
|
1462
1515
|
disposeNode(e) {
|
|
1463
|
-
e.sphere.material instanceof
|
|
1516
|
+
e.sphere.material instanceof x.Material && e.sphere.material.dispose(), e.label.material instanceof x.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose());
|
|
1464
1517
|
}
|
|
1465
1518
|
/**
|
|
1466
1519
|
* Dispose factory resources
|
|
@@ -1497,7 +1550,7 @@ class wt {
|
|
|
1497
1550
|
* Creates an edge line between two positions
|
|
1498
1551
|
*/
|
|
1499
1552
|
createEdge(e, s, t, i, o) {
|
|
1500
|
-
const
|
|
1553
|
+
const n = new x.BufferGeometry(), r = new Float32Array([
|
|
1501
1554
|
i.x,
|
|
1502
1555
|
i.y,
|
|
1503
1556
|
i.z,
|
|
@@ -1505,16 +1558,16 @@ class wt {
|
|
|
1505
1558
|
o.y,
|
|
1506
1559
|
o.z
|
|
1507
1560
|
]);
|
|
1508
|
-
|
|
1509
|
-
const
|
|
1510
|
-
return
|
|
1561
|
+
n.setAttribute("position", new x.BufferAttribute(r, 3));
|
|
1562
|
+
const d = this.getDefaultMaterial().clone(), c = new x.Line(n, d);
|
|
1563
|
+
return c.name = `edge-${e.source}-${e.target}`, c.userData = {
|
|
1511
1564
|
source: e.source,
|
|
1512
1565
|
target: e.target,
|
|
1513
1566
|
edge: e,
|
|
1514
1567
|
sourceNode: s,
|
|
1515
1568
|
targetNode: t
|
|
1516
|
-
},
|
|
1517
|
-
line:
|
|
1569
|
+
}, c.frustumCulled = !0, {
|
|
1570
|
+
line: c,
|
|
1518
1571
|
source: e.source,
|
|
1519
1572
|
target: e.target
|
|
1520
1573
|
};
|
|
@@ -1523,13 +1576,13 @@ class wt {
|
|
|
1523
1576
|
* Highlights an edge
|
|
1524
1577
|
*/
|
|
1525
1578
|
highlightEdge(e) {
|
|
1526
|
-
e.line.material instanceof
|
|
1579
|
+
e.line.material instanceof x.Material && e.line.material.dispose(), e.line.material = this.getHighlightMaterial().clone();
|
|
1527
1580
|
}
|
|
1528
1581
|
/**
|
|
1529
1582
|
* Resets an edge to default appearance
|
|
1530
1583
|
*/
|
|
1531
1584
|
unhighlightEdge(e) {
|
|
1532
|
-
e.line.material instanceof
|
|
1585
|
+
e.line.material instanceof x.Material && e.line.material.dispose(), e.line.material = this.getDefaultMaterial().clone();
|
|
1533
1586
|
}
|
|
1534
1587
|
/**
|
|
1535
1588
|
* Updates an edge's positions
|
|
@@ -1542,7 +1595,7 @@ class wt {
|
|
|
1542
1595
|
* Disposes an edge's resources
|
|
1543
1596
|
*/
|
|
1544
1597
|
disposeEdge(e) {
|
|
1545
|
-
e.line.geometry.dispose(), e.line.material instanceof
|
|
1598
|
+
e.line.geometry.dispose(), e.line.material instanceof x.Material && e.line.material.dispose();
|
|
1546
1599
|
}
|
|
1547
1600
|
/**
|
|
1548
1601
|
* Dispose factory resources
|
|
@@ -1551,7 +1604,7 @@ class wt {
|
|
|
1551
1604
|
this.defaultMaterial && this.defaultMaterial.dispose(), this.highlightMaterial && this.highlightMaterial.dispose();
|
|
1552
1605
|
}
|
|
1553
1606
|
}
|
|
1554
|
-
class
|
|
1607
|
+
class Mt {
|
|
1555
1608
|
constructor(e, s = [50, 100, 200], t = !0) {
|
|
1556
1609
|
l(this, "camera");
|
|
1557
1610
|
l(this, "lodDistances");
|
|
@@ -1563,9 +1616,9 @@ class Et {
|
|
|
1563
1616
|
*/
|
|
1564
1617
|
getLODLevel(e) {
|
|
1565
1618
|
if (!this.enabled)
|
|
1566
|
-
return
|
|
1619
|
+
return _.HIGH;
|
|
1567
1620
|
const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y, i = e.z - this.camera.position.z, o = Math.sqrt(s * s + t * t + i * i);
|
|
1568
|
-
return o < this.lodDistances[0] ?
|
|
1621
|
+
return o < this.lodDistances[0] ? _.HIGH : o < this.lodDistances[1] ? _.MEDIUM : _.LOW;
|
|
1569
1622
|
}
|
|
1570
1623
|
/**
|
|
1571
1624
|
* Checks if a node should be visible based on distance
|
|
@@ -1587,13 +1640,13 @@ class Et {
|
|
|
1587
1640
|
this.enabled = e;
|
|
1588
1641
|
}
|
|
1589
1642
|
}
|
|
1590
|
-
class
|
|
1643
|
+
class Et {
|
|
1591
1644
|
constructor(e, s = !0) {
|
|
1592
1645
|
l(this, "camera");
|
|
1593
1646
|
l(this, "frustum");
|
|
1594
1647
|
l(this, "projScreenMatrix");
|
|
1595
1648
|
l(this, "enabled");
|
|
1596
|
-
this.camera = e, this.frustum = new
|
|
1649
|
+
this.camera = e, this.frustum = new x.Frustum(), this.projScreenMatrix = new x.Matrix4(), this.enabled = s;
|
|
1597
1650
|
}
|
|
1598
1651
|
/**
|
|
1599
1652
|
* Updates the frustum from the camera
|
|
@@ -1609,7 +1662,7 @@ class Ct {
|
|
|
1609
1662
|
*/
|
|
1610
1663
|
isPointVisible(e) {
|
|
1611
1664
|
if (!this.enabled) return !0;
|
|
1612
|
-
const s = new
|
|
1665
|
+
const s = new x.Vector3(e.x, e.y, e.z);
|
|
1613
1666
|
return this.frustum.containsPoint(s);
|
|
1614
1667
|
}
|
|
1615
1668
|
/**
|
|
@@ -1617,8 +1670,8 @@ class Ct {
|
|
|
1617
1670
|
*/
|
|
1618
1671
|
isSphereVisible(e, s) {
|
|
1619
1672
|
if (!this.enabled) return !0;
|
|
1620
|
-
const t = new
|
|
1621
|
-
new
|
|
1673
|
+
const t = new x.Sphere(
|
|
1674
|
+
new x.Vector3(e.x, e.y, e.z),
|
|
1622
1675
|
s
|
|
1623
1676
|
);
|
|
1624
1677
|
return this.frustum.intersectsSphere(t);
|
|
@@ -1628,14 +1681,14 @@ class Ct {
|
|
|
1628
1681
|
*/
|
|
1629
1682
|
isLineVisible(e, s) {
|
|
1630
1683
|
if (!this.enabled) return !0;
|
|
1631
|
-
const t = new
|
|
1684
|
+
const t = new x.Vector3(e.x, e.y, e.z), i = new x.Vector3(s.x, s.y, s.z);
|
|
1632
1685
|
if (this.frustum.containsPoint(t) || this.frustum.containsPoint(i))
|
|
1633
1686
|
return !0;
|
|
1634
|
-
const o = new
|
|
1687
|
+
const o = new x.Vector3(
|
|
1635
1688
|
(e.x + s.x) / 2,
|
|
1636
1689
|
(e.y + s.y) / 2,
|
|
1637
1690
|
(e.z + s.z) / 2
|
|
1638
|
-
),
|
|
1691
|
+
), n = o.distanceTo(t), r = new x.Sphere(o, n);
|
|
1639
1692
|
return this.frustum.intersectsSphere(r);
|
|
1640
1693
|
}
|
|
1641
1694
|
/**
|
|
@@ -1645,7 +1698,7 @@ class Ct {
|
|
|
1645
1698
|
this.enabled = e;
|
|
1646
1699
|
}
|
|
1647
1700
|
}
|
|
1648
|
-
class
|
|
1701
|
+
class Ct {
|
|
1649
1702
|
constructor(e, s) {
|
|
1650
1703
|
l(this, "sceneManager");
|
|
1651
1704
|
l(this, "raycaster");
|
|
@@ -1659,7 +1712,7 @@ class Nt {
|
|
|
1659
1712
|
l(this, "hoveredEdgeKey", null);
|
|
1660
1713
|
l(this, "nodeObjects", []);
|
|
1661
1714
|
l(this, "edgeObjects", []);
|
|
1662
|
-
this.sceneManager = e, this.container = s, this.raycaster = new
|
|
1715
|
+
this.sceneManager = e, this.container = s, this.raycaster = new x.Raycaster(), this.raycaster.params.Line = { threshold: 1.5 }, this.mouse = new x.Vector2(), this.handleClick = this.handleClick.bind(this), this.handleMouseMove = this.handleMouseMove.bind(this), s.addEventListener("click", this.handleClick), s.addEventListener("mousemove", this.handleMouseMove);
|
|
1663
1716
|
}
|
|
1664
1717
|
/**
|
|
1665
1718
|
* Updates the list of node objects to raycast against
|
|
@@ -1748,13 +1801,17 @@ class Nt {
|
|
|
1748
1801
|
const t = this.raycaster.intersectObjects(this.edgeObjects, !1);
|
|
1749
1802
|
if (t.length > 0) {
|
|
1750
1803
|
const i = t[0].object, o = i.userData;
|
|
1751
|
-
if (o != null && o.edge && (o != null && o.sourceNode) && (o != null && o.targetNode))
|
|
1804
|
+
if (o != null && o.edge && (o != null && o.sourceNode) && (o != null && o.targetNode)) {
|
|
1805
|
+
const n = Array.isArray(o.relationships) ? o.relationships : [o.edge];
|
|
1752
1806
|
return {
|
|
1753
1807
|
edge: o.edge,
|
|
1808
|
+
relationships: n,
|
|
1809
|
+
relationshipCount: typeof o.relationshipCount == "number" ? o.relationshipCount : n.length,
|
|
1754
1810
|
sourceNode: o.sourceNode,
|
|
1755
1811
|
targetNode: o.targetNode,
|
|
1756
1812
|
edgeLine: i
|
|
1757
1813
|
};
|
|
1814
|
+
}
|
|
1758
1815
|
}
|
|
1759
1816
|
return null;
|
|
1760
1817
|
}
|
|
@@ -1767,11 +1824,11 @@ class Nt {
|
|
|
1767
1824
|
this.mouse.x = (e - t.left) / t.width * 2 - 1, this.mouse.y = -((s - t.top) / t.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
|
|
1768
1825
|
const i = this.raycaster.intersectObjects(this.nodeObjects, !0);
|
|
1769
1826
|
if (i.length > 0) {
|
|
1770
|
-
let
|
|
1771
|
-
for (;
|
|
1772
|
-
if ((o =
|
|
1773
|
-
return
|
|
1774
|
-
|
|
1827
|
+
let n = i[0].object;
|
|
1828
|
+
for (; n; ) {
|
|
1829
|
+
if ((o = n.userData) != null && o.nodeId)
|
|
1830
|
+
return n.userData.nodeId;
|
|
1831
|
+
n = n.parent;
|
|
1775
1832
|
}
|
|
1776
1833
|
}
|
|
1777
1834
|
return null;
|
|
@@ -1783,7 +1840,7 @@ class Nt {
|
|
|
1783
1840
|
this.container.removeEventListener("click", this.handleClick), this.container.removeEventListener("mousemove", this.handleMouseMove);
|
|
1784
1841
|
}
|
|
1785
1842
|
}
|
|
1786
|
-
class
|
|
1843
|
+
class Nt {
|
|
1787
1844
|
constructor(e) {
|
|
1788
1845
|
l(this, "container");
|
|
1789
1846
|
l(this, "panel", null);
|
|
@@ -1806,17 +1863,15 @@ class St {
|
|
|
1806
1863
|
width: 280px;
|
|
1807
1864
|
max-height: 80vh;
|
|
1808
1865
|
overflow-y: auto;
|
|
1809
|
-
background: rgba(
|
|
1866
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1810
1867
|
backdrop-filter: blur(20px);
|
|
1811
1868
|
-webkit-backdrop-filter: blur(20px);
|
|
1812
|
-
border: 1px solid rgba(255, 255, 255, 0.
|
|
1813
|
-
border-radius:
|
|
1869
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
1870
|
+
border-radius: 12px;
|
|
1814
1871
|
padding: 24px;
|
|
1815
1872
|
color: white;
|
|
1816
|
-
font-family:
|
|
1817
|
-
box-shadow:
|
|
1818
|
-
0 8px 32px rgba(0, 0, 0, 0.4),
|
|
1819
|
-
inset 0 0 0 1px rgba(255, 255, 255, 0.05);
|
|
1873
|
+
font-family: inherit;
|
|
1874
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
1820
1875
|
z-index: 1000;
|
|
1821
1876
|
opacity: 0;
|
|
1822
1877
|
pointer-events: none;
|
|
@@ -1860,8 +1915,8 @@ class St {
|
|
|
1860
1915
|
this.onExpand(this.currentNodeId, r);
|
|
1861
1916
|
}
|
|
1862
1917
|
});
|
|
1863
|
-
const
|
|
1864
|
-
|
|
1918
|
+
const n = this.panel.querySelector('[data-action="close"]');
|
|
1919
|
+
n && n.addEventListener("click", () => {
|
|
1865
1920
|
this.hide();
|
|
1866
1921
|
}), this.panel.style.opacity = "1", this.panel.style.pointerEvents = "auto", this.panel.style.transform = "translateY(-50%) translateX(0)", this.visible = !0;
|
|
1867
1922
|
}
|
|
@@ -1874,8 +1929,8 @@ class St {
|
|
|
1874
1929
|
<style>
|
|
1875
1930
|
.force-graph-panel h2 {
|
|
1876
1931
|
margin: 0 0 16px 0;
|
|
1877
|
-
font-size:
|
|
1878
|
-
font-weight:
|
|
1932
|
+
font-size: 19px;
|
|
1933
|
+
font-weight: 650;
|
|
1879
1934
|
letter-spacing: -0.5px;
|
|
1880
1935
|
display: flex;
|
|
1881
1936
|
align-items: center;
|
|
@@ -1893,13 +1948,13 @@ class St {
|
|
|
1893
1948
|
height: 12px;
|
|
1894
1949
|
border-radius: 50%;
|
|
1895
1950
|
background: ${t};
|
|
1896
|
-
box-shadow: 0 0
|
|
1951
|
+
box-shadow: 0 0 12px ${t}80;
|
|
1897
1952
|
}
|
|
1898
1953
|
.force-graph-panel .info-row {
|
|
1899
1954
|
display: flex;
|
|
1900
1955
|
justify-content: space-between;
|
|
1901
1956
|
padding: 8px 0;
|
|
1902
|
-
border-bottom: 1px solid rgba(255, 255, 255, 0.
|
|
1957
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
1903
1958
|
font-size: 13px;
|
|
1904
1959
|
}
|
|
1905
1960
|
.force-graph-panel .info-row:last-child {
|
|
@@ -1919,19 +1974,24 @@ class St {
|
|
|
1919
1974
|
}
|
|
1920
1975
|
.force-graph-panel .neighbors-section {
|
|
1921
1976
|
margin-top: 16px;
|
|
1977
|
+
padding: 10px;
|
|
1978
|
+
background: rgba(255, 255, 255, 0.04);
|
|
1979
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
1980
|
+
border-radius: 10px;
|
|
1922
1981
|
}
|
|
1923
1982
|
.force-graph-panel .neighbors-title {
|
|
1924
1983
|
font-size: 12px;
|
|
1925
1984
|
text-transform: uppercase;
|
|
1926
1985
|
letter-spacing: 1px;
|
|
1927
|
-
color: rgba(255, 255, 255, 0.
|
|
1986
|
+
color: rgba(255, 255, 255, 0.55);
|
|
1928
1987
|
margin-bottom: 8px;
|
|
1929
1988
|
}
|
|
1930
1989
|
.force-graph-panel .neighbor-chip {
|
|
1931
1990
|
display: inline-block;
|
|
1932
1991
|
padding: 4px 10px;
|
|
1933
1992
|
margin: 2px;
|
|
1934
|
-
background: rgba(255, 255, 255, 0.
|
|
1993
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1994
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
1935
1995
|
border-radius: 12px;
|
|
1936
1996
|
font-size: 12px;
|
|
1937
1997
|
}
|
|
@@ -1941,7 +2001,7 @@ class St {
|
|
|
1941
2001
|
}
|
|
1942
2002
|
.force-graph-panel .depth-label {
|
|
1943
2003
|
font-size: 12px;
|
|
1944
|
-
color: rgba(255, 255, 255, 0.
|
|
2004
|
+
color: rgba(255, 255, 255, 0.65);
|
|
1945
2005
|
margin-bottom: 6px;
|
|
1946
2006
|
text-transform: uppercase;
|
|
1947
2007
|
letter-spacing: 0.5px;
|
|
@@ -1949,9 +2009,9 @@ class St {
|
|
|
1949
2009
|
.force-graph-panel select {
|
|
1950
2010
|
width: 100%;
|
|
1951
2011
|
padding: 8px 12px;
|
|
1952
|
-
background: rgba(255, 255, 255, 0.
|
|
1953
|
-
border: 1px solid rgba(255, 255, 255, 0.
|
|
1954
|
-
border-radius:
|
|
2012
|
+
background: rgba(255, 255, 255, 0.08);
|
|
2013
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
2014
|
+
border-radius: 8px;
|
|
1955
2015
|
color: white;
|
|
1956
2016
|
font-size: 13px;
|
|
1957
2017
|
cursor: pointer;
|
|
@@ -1959,10 +2019,11 @@ class St {
|
|
|
1959
2019
|
transition: all 0.2s ease;
|
|
1960
2020
|
}
|
|
1961
2021
|
.force-graph-panel select:hover {
|
|
1962
|
-
background: rgba(255, 255, 255, 0.
|
|
2022
|
+
background: rgba(255, 255, 255, 0.12);
|
|
1963
2023
|
}
|
|
1964
2024
|
.force-graph-panel select:focus {
|
|
1965
|
-
border-color: rgba(
|
|
2025
|
+
border-color: rgba(255, 153, 102, 0.5);
|
|
2026
|
+
box-shadow: 0 0 20px rgba(255, 153, 102, 0.15);
|
|
1966
2027
|
}
|
|
1967
2028
|
.force-graph-panel .btn-row {
|
|
1968
2029
|
display: flex;
|
|
@@ -1972,28 +2033,33 @@ class St {
|
|
|
1972
2033
|
.force-graph-panel button {
|
|
1973
2034
|
flex: 1;
|
|
1974
2035
|
padding: 10px 16px;
|
|
1975
|
-
border:
|
|
2036
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
1976
2037
|
border-radius: 8px;
|
|
1977
2038
|
font-size: 13px;
|
|
1978
|
-
font-weight:
|
|
2039
|
+
font-weight: 600;
|
|
1979
2040
|
cursor: pointer;
|
|
1980
2041
|
transition: all 0.2s ease;
|
|
1981
2042
|
}
|
|
1982
2043
|
.force-graph-panel .btn-expand {
|
|
1983
|
-
background: linear-gradient(135deg,
|
|
2044
|
+
background: linear-gradient(135deg, rgba(255, 153, 102, 0.3), rgba(255, 102, 153, 0.2));
|
|
2045
|
+
border-color: rgba(255, 153, 102, 0.35);
|
|
1984
2046
|
color: white;
|
|
1985
2047
|
}
|
|
1986
2048
|
.force-graph-panel .btn-expand:hover {
|
|
1987
2049
|
transform: translateY(-1px);
|
|
1988
|
-
box-shadow: 0
|
|
2050
|
+
box-shadow: 0 0 15px rgba(255, 153, 102, 0.2);
|
|
1989
2051
|
}
|
|
1990
2052
|
.force-graph-panel .btn-close {
|
|
1991
|
-
background: rgba(255, 255, 255, 0.
|
|
2053
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1992
2054
|
color: rgba(255, 255, 255, 0.8);
|
|
1993
2055
|
}
|
|
1994
2056
|
.force-graph-panel .btn-close:hover {
|
|
1995
|
-
background: rgba(255, 255, 255, 0.
|
|
2057
|
+
background: rgba(255, 255, 255, 0.12);
|
|
1996
2058
|
}
|
|
2059
|
+
.force-graph-panel::-webkit-scrollbar { width: 6px; }
|
|
2060
|
+
.force-graph-panel::-webkit-scrollbar-track { background: transparent; }
|
|
2061
|
+
.force-graph-panel::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 3px; }
|
|
2062
|
+
.force-graph-panel::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.25); }
|
|
1997
2063
|
</style>
|
|
1998
2064
|
|
|
1999
2065
|
<h2>
|
|
@@ -2069,7 +2135,7 @@ class St {
|
|
|
2069
2135
|
this.panel && this.panel.parentNode && this.panel.parentNode.removeChild(this.panel), this.panel = null;
|
|
2070
2136
|
}
|
|
2071
2137
|
}
|
|
2072
|
-
class
|
|
2138
|
+
class St {
|
|
2073
2139
|
constructor(e) {
|
|
2074
2140
|
l(this, "container");
|
|
2075
2141
|
l(this, "panel", null);
|
|
@@ -2092,17 +2158,15 @@ class zt {
|
|
|
2092
2158
|
width: 300px;
|
|
2093
2159
|
max-height: 80vh;
|
|
2094
2160
|
overflow-y: auto;
|
|
2095
|
-
background: rgba(
|
|
2161
|
+
background: rgba(255, 255, 255, 0.08);
|
|
2096
2162
|
backdrop-filter: blur(20px);
|
|
2097
2163
|
-webkit-backdrop-filter: blur(20px);
|
|
2098
|
-
border: 1px solid rgba(255, 255, 255, 0.
|
|
2099
|
-
border-radius:
|
|
2164
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
2165
|
+
border-radius: 12px;
|
|
2100
2166
|
padding: 24px;
|
|
2101
2167
|
color: white;
|
|
2102
|
-
font-family:
|
|
2103
|
-
box-shadow:
|
|
2104
|
-
0 8px 32px rgba(0, 0, 0, 0.4),
|
|
2105
|
-
inset 0 0 0 1px rgba(255, 255, 255, 0.05);
|
|
2168
|
+
font-family: inherit;
|
|
2169
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
2106
2170
|
z-index: 1000;
|
|
2107
2171
|
opacity: 0;
|
|
2108
2172
|
pointer-events: none;
|
|
@@ -2130,29 +2194,34 @@ class zt {
|
|
|
2130
2194
|
/**
|
|
2131
2195
|
* Shows the panel with edge/relationship information
|
|
2132
2196
|
*/
|
|
2133
|
-
show(e, s, t) {
|
|
2197
|
+
show(e, s, t, i = [e]) {
|
|
2134
2198
|
if (!this.panel) return;
|
|
2135
2199
|
this.currentEdgeKey = `${e.source}-${e.target}`;
|
|
2136
|
-
let
|
|
2137
|
-
this.panelTemplate ?
|
|
2138
|
-
const
|
|
2139
|
-
|
|
2200
|
+
let o;
|
|
2201
|
+
this.panelTemplate ? o = this.panelTemplate(e, s, t) : o = this.generateDefaultContent(e, s, t, i), this.panel.innerHTML = o;
|
|
2202
|
+
const n = this.panel.querySelector('[data-action="close"]');
|
|
2203
|
+
n && n.addEventListener("click", () => {
|
|
2140
2204
|
this.hide(), this.onClose && this.onClose();
|
|
2141
2205
|
});
|
|
2142
|
-
const
|
|
2143
|
-
|
|
2206
|
+
const r = this.panel.querySelector('[data-action="goto-source"]');
|
|
2207
|
+
r && this.onNodeClick && r.addEventListener("click", () => {
|
|
2144
2208
|
this.onNodeClick && this.onNodeClick(e.source);
|
|
2145
2209
|
});
|
|
2146
|
-
const
|
|
2147
|
-
|
|
2210
|
+
const d = this.panel.querySelector('[data-action="goto-target"]');
|
|
2211
|
+
d && this.onNodeClick && d.addEventListener("click", () => {
|
|
2148
2212
|
this.onNodeClick && this.onNodeClick(e.target);
|
|
2149
2213
|
}), this.panel.style.opacity = "1", this.panel.style.pointerEvents = "auto", this.panel.style.transform = "translateY(-50%) translateX(0)", this.visible = !0;
|
|
2150
2214
|
}
|
|
2151
2215
|
/**
|
|
2152
2216
|
* Generates default panel content
|
|
2153
2217
|
*/
|
|
2154
|
-
generateDefaultContent(e, s, t) {
|
|
2155
|
-
const
|
|
2218
|
+
generateDefaultContent(e, s, t, i = [e]) {
|
|
2219
|
+
const o = s.color ? `#${s.color.toString(16).padStart(6, "0")}` : "#ff9966", n = t.color ? `#${t.color.toString(16).padStart(6, "0")}` : "#ff9966", r = this.getRelationshipLabel(e), d = i.length > 0 ? i : [e], c = this.summarizeRelationships(d), p = c.slice(0, 10).map((m) => `
|
|
2220
|
+
<div class="relationship-item">
|
|
2221
|
+
<span class="relationship-item-label">${this.escapeHtml(m.label)}</span>
|
|
2222
|
+
<span class="relationship-item-count">${m.count}</span>
|
|
2223
|
+
</div>
|
|
2224
|
+
`).join(""), f = c.length - Math.min(c.length, 10);
|
|
2156
2225
|
return `
|
|
2157
2226
|
<style>
|
|
2158
2227
|
.force-graph-edge-panel .panel-header {
|
|
@@ -2162,28 +2231,72 @@ class zt {
|
|
|
2162
2231
|
margin-bottom: 20px;
|
|
2163
2232
|
}
|
|
2164
2233
|
.force-graph-edge-panel .panel-title {
|
|
2165
|
-
font-size:
|
|
2234
|
+
font-size: 12px;
|
|
2166
2235
|
text-transform: uppercase;
|
|
2167
2236
|
letter-spacing: 1px;
|
|
2168
|
-
color: rgba(255, 255, 255, 0.
|
|
2237
|
+
color: rgba(255, 255, 255, 0.55);
|
|
2169
2238
|
margin: 0;
|
|
2170
2239
|
}
|
|
2171
2240
|
.force-graph-edge-panel .relationship-section {
|
|
2172
|
-
background: rgba(255, 255, 255, 0.
|
|
2241
|
+
background: rgba(255, 255, 255, 0.04);
|
|
2242
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
2173
2243
|
border-radius: 12px;
|
|
2174
2244
|
padding: 16px;
|
|
2175
2245
|
text-align: center;
|
|
2176
|
-
margin-bottom:
|
|
2246
|
+
margin-bottom: 14px;
|
|
2177
2247
|
}
|
|
2178
2248
|
.force-graph-edge-panel .relationship-label {
|
|
2179
2249
|
font-size: 18px;
|
|
2180
2250
|
font-weight: 600;
|
|
2181
|
-
color:
|
|
2251
|
+
color: rgba(255, 153, 102, 0.95);
|
|
2182
2252
|
letter-spacing: 0.5px;
|
|
2183
2253
|
}
|
|
2254
|
+
.force-graph-edge-panel .relationship-count {
|
|
2255
|
+
margin-top: 6px;
|
|
2256
|
+
font-size: 11px;
|
|
2257
|
+
text-transform: uppercase;
|
|
2258
|
+
letter-spacing: 0.8px;
|
|
2259
|
+
color: rgba(255, 255, 255, 0.6);
|
|
2260
|
+
}
|
|
2261
|
+
.force-graph-edge-panel .relationship-list {
|
|
2262
|
+
margin-bottom: 16px;
|
|
2263
|
+
max-height: 190px;
|
|
2264
|
+
overflow-y: auto;
|
|
2265
|
+
padding-right: 4px;
|
|
2266
|
+
}
|
|
2267
|
+
.force-graph-edge-panel .relationship-item {
|
|
2268
|
+
display: flex;
|
|
2269
|
+
justify-content: space-between;
|
|
2270
|
+
gap: 12px;
|
|
2271
|
+
padding: 8px 10px;
|
|
2272
|
+
background: rgba(255, 255, 255, 0.04);
|
|
2273
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
2274
|
+
border-radius: 8px;
|
|
2275
|
+
margin-bottom: 6px;
|
|
2276
|
+
}
|
|
2277
|
+
.force-graph-edge-panel .relationship-item-label {
|
|
2278
|
+
font-size: 12px;
|
|
2279
|
+
color: rgba(255, 255, 255, 0.88);
|
|
2280
|
+
overflow: hidden;
|
|
2281
|
+
text-overflow: ellipsis;
|
|
2282
|
+
white-space: nowrap;
|
|
2283
|
+
}
|
|
2284
|
+
.force-graph-edge-panel .relationship-item-count {
|
|
2285
|
+
font-size: 12px;
|
|
2286
|
+
font-weight: 700;
|
|
2287
|
+
color: rgba(255, 153, 102, 0.95);
|
|
2288
|
+
min-width: 24px;
|
|
2289
|
+
text-align: right;
|
|
2290
|
+
}
|
|
2291
|
+
.force-graph-edge-panel .relationship-more {
|
|
2292
|
+
font-size: 11px;
|
|
2293
|
+
color: rgba(255, 255, 255, 0.45);
|
|
2294
|
+
text-align: center;
|
|
2295
|
+
margin-top: 2px;
|
|
2296
|
+
}
|
|
2184
2297
|
.force-graph-edge-panel .node-card {
|
|
2185
|
-
background: rgba(255, 255, 255, 0.
|
|
2186
|
-
border: 1px solid rgba(255, 255, 255, 0.
|
|
2298
|
+
background: rgba(255, 255, 255, 0.06);
|
|
2299
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
2187
2300
|
border-radius: 12px;
|
|
2188
2301
|
padding: 14px;
|
|
2189
2302
|
margin-bottom: 12px;
|
|
@@ -2192,8 +2305,9 @@ class zt {
|
|
|
2192
2305
|
}
|
|
2193
2306
|
.force-graph-edge-panel .node-card:hover {
|
|
2194
2307
|
background: rgba(255, 255, 255, 0.1);
|
|
2195
|
-
border-color: rgba(255,
|
|
2308
|
+
border-color: rgba(255, 153, 102, 0.35);
|
|
2196
2309
|
transform: translateX(4px);
|
|
2310
|
+
box-shadow: 0 0 15px rgba(255, 153, 102, 0.15);
|
|
2197
2311
|
}
|
|
2198
2312
|
.force-graph-edge-panel .node-card-header {
|
|
2199
2313
|
display: flex;
|
|
@@ -2230,18 +2344,18 @@ class zt {
|
|
|
2230
2344
|
.force-graph-edge-panel .btn-close {
|
|
2231
2345
|
width: 100%;
|
|
2232
2346
|
padding: 12px 16px;
|
|
2233
|
-
border:
|
|
2347
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
2234
2348
|
border-radius: 8px;
|
|
2235
2349
|
font-size: 13px;
|
|
2236
|
-
font-weight:
|
|
2350
|
+
font-weight: 600;
|
|
2237
2351
|
cursor: pointer;
|
|
2238
2352
|
transition: all 0.2s ease;
|
|
2239
|
-
background: rgba(255, 255, 255, 0.
|
|
2353
|
+
background: rgba(255, 255, 255, 0.08);
|
|
2240
2354
|
color: rgba(255, 255, 255, 0.8);
|
|
2241
2355
|
margin-top: 16px;
|
|
2242
2356
|
}
|
|
2243
2357
|
.force-graph-edge-panel .btn-close:hover {
|
|
2244
|
-
background: rgba(255, 255, 255, 0.
|
|
2358
|
+
background: rgba(255, 255, 255, 0.12);
|
|
2245
2359
|
}
|
|
2246
2360
|
.force-graph-edge-panel .hint-text {
|
|
2247
2361
|
font-size: 11px;
|
|
@@ -2249,6 +2363,10 @@ class zt {
|
|
|
2249
2363
|
text-align: center;
|
|
2250
2364
|
margin-top: 8px;
|
|
2251
2365
|
}
|
|
2366
|
+
.force-graph-edge-panel .relationship-list::-webkit-scrollbar { width: 6px; }
|
|
2367
|
+
.force-graph-edge-panel .relationship-list::-webkit-scrollbar-track { background: transparent; }
|
|
2368
|
+
.force-graph-edge-panel .relationship-list::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 3px; }
|
|
2369
|
+
.force-graph-edge-panel .relationship-list::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.25); }
|
|
2252
2370
|
</style>
|
|
2253
2371
|
|
|
2254
2372
|
<div class="panel-header">
|
|
@@ -2256,13 +2374,19 @@ class zt {
|
|
|
2256
2374
|
</div>
|
|
2257
2375
|
|
|
2258
2376
|
<div class="relationship-section">
|
|
2259
|
-
<span class="relationship-label">${this.escapeHtml(
|
|
2377
|
+
<span class="relationship-label">${this.escapeHtml(r)}</span>
|
|
2378
|
+
<div class="relationship-count">${d.length} relationships</div>
|
|
2379
|
+
</div>
|
|
2380
|
+
|
|
2381
|
+
<div class="relationship-list">
|
|
2382
|
+
${p}
|
|
2383
|
+
${f > 0 ? `<div class="relationship-more">+ ${f} more</div>` : ""}
|
|
2260
2384
|
</div>
|
|
2261
2385
|
|
|
2262
2386
|
<div class="node-card" data-action="goto-source" title="Click to focus on ${this.escapeHtml(s.label)}">
|
|
2263
2387
|
<div class="node-type">Source</div>
|
|
2264
2388
|
<div class="node-card-header">
|
|
2265
|
-
<span class="color-dot" style="background: ${
|
|
2389
|
+
<span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
|
|
2266
2390
|
<span class="node-label">${this.escapeHtml(s.label)}</span>
|
|
2267
2391
|
</div>
|
|
2268
2392
|
</div>
|
|
@@ -2272,7 +2396,7 @@ class zt {
|
|
|
2272
2396
|
<div class="node-card" data-action="goto-target" title="Click to focus on ${this.escapeHtml(t.label)}">
|
|
2273
2397
|
<div class="node-type">Target</div>
|
|
2274
2398
|
<div class="node-card-header">
|
|
2275
|
-
<span class="color-dot" style="background: ${
|
|
2399
|
+
<span class="color-dot" style="background: ${n}; box-shadow: 0 0 8px ${n}80;"></span>
|
|
2276
2400
|
<span class="node-label">${this.escapeHtml(t.label)}</span>
|
|
2277
2401
|
</div>
|
|
2278
2402
|
</div>
|
|
@@ -2289,6 +2413,17 @@ class zt {
|
|
|
2289
2413
|
const s = document.createElement("div");
|
|
2290
2414
|
return s.textContent = e, s.innerHTML;
|
|
2291
2415
|
}
|
|
2416
|
+
getRelationshipLabel(e) {
|
|
2417
|
+
return e.relationship || e.label || "connected to";
|
|
2418
|
+
}
|
|
2419
|
+
summarizeRelationships(e) {
|
|
2420
|
+
const s = /* @__PURE__ */ new Map();
|
|
2421
|
+
for (const t of e) {
|
|
2422
|
+
const i = this.getRelationshipLabel(t);
|
|
2423
|
+
s.set(i, (s.get(i) || 0) + 1);
|
|
2424
|
+
}
|
|
2425
|
+
return Array.from(s.entries()).map(([t, i]) => ({ label: t, count: i })).sort((t, i) => i.count - t.count);
|
|
2426
|
+
}
|
|
2292
2427
|
/**
|
|
2293
2428
|
* Hides the panel
|
|
2294
2429
|
*/
|
|
@@ -2314,7 +2449,7 @@ class zt {
|
|
|
2314
2449
|
this.panel && this.panel.parentNode && this.panel.parentNode.removeChild(this.panel), this.panel = null;
|
|
2315
2450
|
}
|
|
2316
2451
|
}
|
|
2317
|
-
class
|
|
2452
|
+
class zt {
|
|
2318
2453
|
constructor() {
|
|
2319
2454
|
l(this, "tooltip", null);
|
|
2320
2455
|
l(this, "visible", !1);
|
|
@@ -2361,28 +2496,51 @@ class kt {
|
|
|
2361
2496
|
positionTooltip(e, s) {
|
|
2362
2497
|
if (!this.tooltip) return;
|
|
2363
2498
|
const t = this.tooltip.getBoundingClientRect(), i = window.innerWidth, o = window.innerHeight;
|
|
2364
|
-
let
|
|
2365
|
-
|
|
2499
|
+
let n = e + 15, r = s + 15;
|
|
2500
|
+
n + t.width > i - 10 && (n = e - t.width - 15), r + t.height > o - 10 && (r = s - t.height - 15), n < 10 && (n = 10), r < 10 && (r = 10), this.tooltip.style.left = `${n}px`, this.tooltip.style.top = `${r}px`;
|
|
2366
2501
|
}
|
|
2367
2502
|
/**
|
|
2368
2503
|
* Shows the tooltip with edge info
|
|
2369
2504
|
*/
|
|
2370
|
-
show(e, s, t, i, o) {
|
|
2505
|
+
show(e, s, t, i, o, n = [e]) {
|
|
2371
2506
|
if (!this.tooltip) return;
|
|
2372
|
-
const
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2507
|
+
const r = n.length > 0 ? n : [e], d = this.summarizeRelationships(r), c = r.length;
|
|
2508
|
+
if (c <= 1) {
|
|
2509
|
+
const p = this.getRelationshipLabel(r[0]);
|
|
2510
|
+
this.tooltip.innerHTML = `
|
|
2511
|
+
<div style="display: flex; flex-direction: column; gap: 4px;">
|
|
2512
|
+
<div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
|
|
2513
|
+
<span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(s.label)}</span>
|
|
2514
|
+
</div>
|
|
2515
|
+
<div style="color: rgba(255, 255, 255, 0.6); font-style: italic; font-size: 12px; padding-left: 8px;">
|
|
2516
|
+
↳ ${this.escapeHtml(p)}
|
|
2517
|
+
</div>
|
|
2518
|
+
<div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
|
|
2519
|
+
<span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
|
|
2520
|
+
</div>
|
|
2380
2521
|
</div>
|
|
2381
|
-
|
|
2382
|
-
|
|
2522
|
+
`;
|
|
2523
|
+
} else {
|
|
2524
|
+
const p = d.slice(0, 4), f = d.length - p.length, m = p.map((u) => `<div style="display:flex; justify-content:space-between; gap:10px; font-size:12px; color: rgba(255,255,255,0.8);">
|
|
2525
|
+
<span style="overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">${this.escapeHtml(u.label)}</span>
|
|
2526
|
+
<span style="color: rgba(255,153,102,0.9); font-weight:600;">${u.count}</span>
|
|
2527
|
+
</div>`).join("");
|
|
2528
|
+
this.tooltip.innerHTML = `
|
|
2529
|
+
<div style="display:flex; flex-direction:column; gap:8px; min-width:220px;">
|
|
2530
|
+
<div style="font-size:13px; font-weight:600; color:#ff9966;">
|
|
2531
|
+
${this.escapeHtml(s.label)} → ${this.escapeHtml(t.label)}
|
|
2532
|
+
</div>
|
|
2533
|
+
<div style="font-size:11px; letter-spacing:0.4px; text-transform:uppercase; color: rgba(255,255,255,0.6);">
|
|
2534
|
+
${c} relationships
|
|
2535
|
+
</div>
|
|
2536
|
+
<div style="display:flex; flex-direction:column; gap:4px;">
|
|
2537
|
+
${m}
|
|
2538
|
+
</div>
|
|
2539
|
+
${f > 0 ? `<div style="font-size:11px; color: rgba(255,255,255,0.45);">+ ${f} more</div>` : ""}
|
|
2383
2540
|
</div>
|
|
2384
|
-
|
|
2385
|
-
|
|
2541
|
+
`;
|
|
2542
|
+
}
|
|
2543
|
+
this.positionTooltip(i, o), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
|
|
2386
2544
|
}
|
|
2387
2545
|
/**
|
|
2388
2546
|
* Updates tooltip position (called externally on mouse move)
|
|
@@ -2409,6 +2567,17 @@ class kt {
|
|
|
2409
2567
|
const s = document.createElement("div");
|
|
2410
2568
|
return s.textContent = e, s.innerHTML;
|
|
2411
2569
|
}
|
|
2570
|
+
getRelationshipLabel(e) {
|
|
2571
|
+
return e.relationship || e.label || "connected to";
|
|
2572
|
+
}
|
|
2573
|
+
summarizeRelationships(e) {
|
|
2574
|
+
const s = /* @__PURE__ */ new Map();
|
|
2575
|
+
for (const t of e) {
|
|
2576
|
+
const i = this.getRelationshipLabel(t);
|
|
2577
|
+
s.set(i, (s.get(i) || 0) + 1);
|
|
2578
|
+
}
|
|
2579
|
+
return Array.from(s.entries()).map(([t, i]) => ({ label: t, count: i })).sort((t, i) => i.count - t.count);
|
|
2580
|
+
}
|
|
2412
2581
|
/**
|
|
2413
2582
|
* Dispose the tooltip
|
|
2414
2583
|
*/
|
|
@@ -2416,7 +2585,7 @@ class kt {
|
|
|
2416
2585
|
this.tooltip && this.tooltip.parentNode && this.tooltip.parentNode.removeChild(this.tooltip), this.tooltip = null;
|
|
2417
2586
|
}
|
|
2418
2587
|
}
|
|
2419
|
-
class
|
|
2588
|
+
class kt {
|
|
2420
2589
|
constructor(e, s) {
|
|
2421
2590
|
l(this, "container");
|
|
2422
2591
|
l(this, "searchContainer", null);
|
|
@@ -2561,24 +2730,24 @@ class Tt {
|
|
|
2561
2730
|
}
|
|
2562
2731
|
let i = "";
|
|
2563
2732
|
s.length > 0 && (i += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((o) => {
|
|
2564
|
-
const
|
|
2733
|
+
const n = o.type || "Node";
|
|
2565
2734
|
i += `
|
|
2566
2735
|
<div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.id)}">
|
|
2567
2736
|
<div class="f3d-result-label">${this.escapeHtml(o.label)}</div>
|
|
2568
|
-
<div class="f3d-result-type">${this.escapeHtml(
|
|
2737
|
+
<div class="f3d-result-type">${this.escapeHtml(n)}</div>
|
|
2569
2738
|
</div>
|
|
2570
2739
|
`;
|
|
2571
|
-
}), s.length > 10 && (i += `<div class="f3d-no-results">+ ${s.length - 10} more nodes</div>`)), t.length > 0 && (i += '<div class="f3d-search-section-header">Relationships</div>', t.slice(0, 5).forEach(({ edge: o, sourceNode:
|
|
2740
|
+
}), s.length > 10 && (i += `<div class="f3d-no-results">+ ${s.length - 10} more nodes</div>`)), t.length > 0 && (i += '<div class="f3d-search-section-header">Relationships</div>', t.slice(0, 5).forEach(({ edge: o, sourceNode: n, targetNode: r }) => {
|
|
2572
2741
|
i += `
|
|
2573
2742
|
<div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.source)}">
|
|
2574
|
-
<div class="f3d-result-label">${this.escapeHtml(
|
|
2743
|
+
<div class="f3d-result-label">${this.escapeHtml(n.label)} → ${this.escapeHtml(r.label)}</div>
|
|
2575
2744
|
<div class="f3d-result-relationship">${this.escapeHtml(o.relationship || "connected")}</div>
|
|
2576
2745
|
</div>
|
|
2577
2746
|
`;
|
|
2578
2747
|
}), t.length > 5 && (i += `<div class="f3d-no-results">+ ${t.length - 5} more relationships</div>`)), this.searchResults.innerHTML = i, this.searchResults.style.display = "block", this.searchResults.querySelectorAll(".f3d-search-result-item").forEach((o) => {
|
|
2579
2748
|
o.addEventListener("click", () => {
|
|
2580
|
-
const
|
|
2581
|
-
|
|
2749
|
+
const n = o.dataset.nodeId;
|
|
2750
|
+
n && (this.onResultClick(n), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
|
|
2582
2751
|
});
|
|
2583
2752
|
});
|
|
2584
2753
|
}
|
|
@@ -2590,7 +2759,7 @@ class Tt {
|
|
|
2590
2759
|
this.searchContainer && this.searchContainer.parentNode && this.searchContainer.parentNode.removeChild(this.searchContainer);
|
|
2591
2760
|
}
|
|
2592
2761
|
}
|
|
2593
|
-
class
|
|
2762
|
+
class Tt {
|
|
2594
2763
|
constructor(e, s) {
|
|
2595
2764
|
l(this, "container");
|
|
2596
2765
|
l(this, "toggleContainer", null);
|
|
@@ -2682,7 +2851,7 @@ class Pt {
|
|
|
2682
2851
|
this.toggleContainer && this.toggleContainer.parentNode && this.toggleContainer.parentNode.removeChild(this.toggleContainer);
|
|
2683
2852
|
}
|
|
2684
2853
|
}
|
|
2685
|
-
class
|
|
2854
|
+
class Pt {
|
|
2686
2855
|
constructor(e) {
|
|
2687
2856
|
l(this, "container");
|
|
2688
2857
|
l(this, "legendContainer", null);
|
|
@@ -2765,7 +2934,7 @@ class Lt {
|
|
|
2765
2934
|
this.legendContainer && this.legendContainer.parentNode && this.legendContainer.parentNode.removeChild(this.legendContainer);
|
|
2766
2935
|
}
|
|
2767
2936
|
}
|
|
2768
|
-
const
|
|
2937
|
+
const Lt = {
|
|
2769
2938
|
backgroundColor: "#0a0a0a",
|
|
2770
2939
|
gridColor: "rgba(255, 255, 255, 0.03)",
|
|
2771
2940
|
nodeRadius: 24,
|
|
@@ -2778,7 +2947,7 @@ const Rt = {
|
|
|
2778
2947
|
damping: 0.85
|
|
2779
2948
|
// Fast energy dissipation
|
|
2780
2949
|
};
|
|
2781
|
-
class
|
|
2950
|
+
class Rt {
|
|
2782
2951
|
constructor(e, s = {}) {
|
|
2783
2952
|
l(this, "container");
|
|
2784
2953
|
l(this, "canvas");
|
|
@@ -2805,7 +2974,7 @@ class It {
|
|
|
2805
2974
|
l(this, "isSimulating", !0);
|
|
2806
2975
|
// Resize handler
|
|
2807
2976
|
l(this, "resizeHandler");
|
|
2808
|
-
this.container = e, this.options = { ...
|
|
2977
|
+
this.container = e, this.options = { ...Lt, ...s }, this.canvas = document.createElement("canvas"), this.canvas.style.position = "absolute", this.canvas.style.top = "0", this.canvas.style.left = "0", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.cursor = "grab", e.appendChild(this.canvas);
|
|
2809
2978
|
const t = this.canvas.getContext("2d");
|
|
2810
2979
|
if (!t)
|
|
2811
2980
|
throw new Error("Failed to get 2D context");
|
|
@@ -2818,21 +2987,21 @@ class It {
|
|
|
2818
2987
|
setupInteractions() {
|
|
2819
2988
|
this.canvas.addEventListener("wheel", (e) => {
|
|
2820
2989
|
e.preventDefault();
|
|
2821
|
-
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = e.deltaY > 0 ? 0.9 : 1.1,
|
|
2822
|
-
this.transform.x = t - (t - this.transform.x) * r, this.transform.y = i - (i - this.transform.y) * r, this.transform.scale =
|
|
2990
|
+
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = e.deltaY > 0 ? 0.9 : 1.1, n = Math.max(0.1, Math.min(5, this.transform.scale * o)), r = n / this.transform.scale;
|
|
2991
|
+
this.transform.x = t - (t - this.transform.x) * r, this.transform.y = i - (i - this.transform.y) * r, this.transform.scale = n;
|
|
2823
2992
|
}), this.canvas.addEventListener("mousedown", (e) => {
|
|
2824
|
-
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i),
|
|
2825
|
-
this.dragStartPos = { x: e.clientX, y: e.clientY },
|
|
2993
|
+
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i), n = this.findNodeAt(o.x, o.y);
|
|
2994
|
+
this.dragStartPos = { x: e.clientX, y: e.clientY }, n ? (this.isDragging = !0, this.draggedNode = n, this.canvas.style.cursor = "grabbing", this.isSimulating = !0) : (this.isPanning = !0, this.canvas.style.cursor = "grabbing"), this.lastMousePos = { x: e.clientX, y: e.clientY };
|
|
2826
2995
|
}), this.canvas.addEventListener("mousemove", (e) => {
|
|
2827
2996
|
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i);
|
|
2828
2997
|
if (this.isDragging && this.draggedNode)
|
|
2829
2998
|
this.draggedNode.x = o.x, this.draggedNode.y = o.y, this.draggedNode.vx = 0, this.draggedNode.vy = 0;
|
|
2830
2999
|
else if (this.isPanning) {
|
|
2831
|
-
const
|
|
2832
|
-
this.transform.x +=
|
|
3000
|
+
const n = e.clientX - this.lastMousePos.x, r = e.clientY - this.lastMousePos.y;
|
|
3001
|
+
this.transform.x += n, this.transform.y += r, this.lastMousePos = { x: e.clientX, y: e.clientY };
|
|
2833
3002
|
} else {
|
|
2834
|
-
const
|
|
2835
|
-
if (
|
|
3003
|
+
const n = this.findNodeAt(o.x, o.y);
|
|
3004
|
+
if (n !== this.hoveredNode && (this.hoveredNode = n, n ? (this.hoveredEdge && (this.hoveredEdge = null, this.options.onEdgeHover && this.options.onEdgeHover(null)), this.canvas.style.cursor = "pointer", this.options.onNodeHover && this.options.onNodeHover(n.data)) : this.options.onNodeHover && this.options.onNodeHover(null)), !n) {
|
|
2836
3005
|
const r = this.findEdgeAt(o.x, o.y);
|
|
2837
3006
|
r !== this.hoveredEdge && (this.hoveredEdge = r, this.canvas.style.cursor = r ? "pointer" : "grab", this.options.onEdgeHover && this.options.onEdgeHover(r ? r.data : null, e));
|
|
2838
3007
|
}
|
|
@@ -2842,7 +3011,7 @@ class It {
|
|
|
2842
3011
|
if (this.isDragging && this.draggedNode)
|
|
2843
3012
|
i && this.options.onNodeClick && (this.selectedNode = this.draggedNode, this.options.onNodeClick(this.draggedNode.data));
|
|
2844
3013
|
else if (i) {
|
|
2845
|
-
const o = this.canvas.getBoundingClientRect(),
|
|
3014
|
+
const o = this.canvas.getBoundingClientRect(), n = this.screenToWorld(e.clientX - o.left, e.clientY - o.top), r = this.findEdgeAt(n.x, n.y);
|
|
2846
3015
|
r && this.options.onEdgeClick && this.options.onEdgeClick(r.data);
|
|
2847
3016
|
}
|
|
2848
3017
|
this.isDragging = !1, this.isPanning = !1, this.draggedNode = null, this.canvas.style.cursor = this.hoveredNode ? "pointer" : "grab";
|
|
@@ -2866,12 +3035,12 @@ class It {
|
|
|
2866
3035
|
}
|
|
2867
3036
|
findEdgeAt(e, s) {
|
|
2868
3037
|
for (const i of this.edges) {
|
|
2869
|
-
const o = this.nodes.get(i.source),
|
|
2870
|
-
if (!o || !
|
|
2871
|
-
const r =
|
|
2872
|
-
if (
|
|
2873
|
-
const p = Math.max(0, Math.min(1, ((e - o.x) * r + (s - o.y) *
|
|
2874
|
-
if (Math.sqrt(u * u +
|
|
3038
|
+
const o = this.nodes.get(i.source), n = this.nodes.get(i.target);
|
|
3039
|
+
if (!o || !n) continue;
|
|
3040
|
+
const r = n.x - o.x, d = n.y - o.y, c = r * r + d * d;
|
|
3041
|
+
if (c === 0) continue;
|
|
3042
|
+
const p = Math.max(0, Math.min(1, ((e - o.x) * r + (s - o.y) * d) / c)), f = o.x + p * r, m = o.y + p * d, u = e - f, y = s - m;
|
|
3043
|
+
if (Math.sqrt(u * u + y * y) < 12)
|
|
2875
3044
|
return i;
|
|
2876
3045
|
}
|
|
2877
3046
|
return null;
|
|
@@ -2888,29 +3057,29 @@ class It {
|
|
|
2888
3057
|
const t = 60, i = 5;
|
|
2889
3058
|
let o = 0;
|
|
2890
3059
|
for (let r = 0; r < s; r++)
|
|
2891
|
-
for (let
|
|
2892
|
-
const
|
|
2893
|
-
let
|
|
3060
|
+
for (let d = r + 1; d < s; d++) {
|
|
3061
|
+
const c = e[r], p = e[d];
|
|
3062
|
+
let f = p.x - c.x, m = p.y - c.y, u = Math.sqrt(f * f + m * m);
|
|
2894
3063
|
if (u < t * 3) {
|
|
2895
3064
|
u < 1 && (u = 1);
|
|
2896
|
-
const
|
|
2897
|
-
|
|
3065
|
+
const y = this.options.repulsionStrength / (u * u), b = f / u * y, w = m / u * y;
|
|
3066
|
+
c.vx -= b, c.vy -= w, p.vx += b, p.vy += w;
|
|
2898
3067
|
}
|
|
2899
3068
|
}
|
|
2900
|
-
const
|
|
3069
|
+
const n = 80;
|
|
2901
3070
|
for (const r of this.edges) {
|
|
2902
|
-
const
|
|
2903
|
-
if (!
|
|
2904
|
-
let p =
|
|
3071
|
+
const d = this.nodes.get(r.source), c = this.nodes.get(r.target);
|
|
3072
|
+
if (!d || !c) continue;
|
|
3073
|
+
let p = c.x - d.x, f = c.y - d.y, m = Math.sqrt(p * p + f * f);
|
|
2905
3074
|
m < 1 && (m = 1);
|
|
2906
|
-
const
|
|
2907
|
-
|
|
3075
|
+
const y = (m - n) * this.options.attractionStrength, b = p / m * y, w = f / m * y;
|
|
3076
|
+
d.vx += b, d.vy += w, c.vx -= b, c.vy -= w;
|
|
2908
3077
|
}
|
|
2909
3078
|
for (const r of e) {
|
|
2910
3079
|
if (this.draggedNode === r) continue;
|
|
2911
3080
|
r.vx *= this.options.damping, r.vy *= this.options.damping;
|
|
2912
|
-
const
|
|
2913
|
-
|
|
3081
|
+
const d = Math.sqrt(r.vx * r.vx + r.vy * r.vy);
|
|
3082
|
+
d > i && (r.vx = r.vx / d * i, r.vy = r.vy / d * i), r.x += r.vx, r.y += r.vy, o += r.vx * r.vx + r.vy * r.vy;
|
|
2914
3083
|
}
|
|
2915
3084
|
o < 0.01 && !this.draggedNode && (this.isSimulating = !1);
|
|
2916
3085
|
}
|
|
@@ -2919,49 +3088,49 @@ class It {
|
|
|
2919
3088
|
e.fillStyle = this.options.backgroundColor, e.fillRect(0, 0, s, t), this.renderGrid(s, t), e.save(), e.translate(this.transform.x, this.transform.y), e.scale(this.transform.scale, this.transform.scale), this.renderEdges(), this.renderNodes(), e.restore();
|
|
2920
3089
|
}
|
|
2921
3090
|
renderGrid(e, s) {
|
|
2922
|
-
const t = this.ctx, i = 40 * this.transform.scale, o = 1.5,
|
|
3091
|
+
const t = this.ctx, i = 40 * this.transform.scale, o = 1.5, n = this.transform.x % i, r = this.transform.y % i;
|
|
2923
3092
|
t.fillStyle = this.options.gridColor;
|
|
2924
|
-
for (let
|
|
2925
|
-
for (let
|
|
2926
|
-
t.beginPath(), t.arc(
|
|
3093
|
+
for (let d = n; d < e; d += i)
|
|
3094
|
+
for (let c = r; c < s; c += i)
|
|
3095
|
+
t.beginPath(), t.arc(d, c, o, 0, Math.PI * 2), t.fill();
|
|
2927
3096
|
}
|
|
2928
3097
|
renderEdges() {
|
|
2929
3098
|
const e = this.ctx;
|
|
2930
3099
|
for (const s of this.edges) {
|
|
2931
3100
|
const t = this.nodes.get(s.source), i = this.nodes.get(s.target);
|
|
2932
3101
|
if (!t || !i) continue;
|
|
2933
|
-
const o = s === this.hoveredEdge,
|
|
2934
|
-
o ? (
|
|
3102
|
+
const o = s === this.hoveredEdge, n = e.createLinearGradient(t.x, t.y, i.x, i.y);
|
|
3103
|
+
o ? (n.addColorStop(0, "rgba(255, 153, 102, 0.8)"), n.addColorStop(0.5, "rgba(255, 255, 255, 0.5)"), n.addColorStop(1, "rgba(102, 153, 255, 0.8)"), e.lineWidth = 3) : (n.addColorStop(0, "rgba(255, 153, 102, 0.3)"), n.addColorStop(0.5, "rgba(255, 255, 255, 0.15)"), n.addColorStop(1, "rgba(102, 153, 255, 0.3)"), e.lineWidth = 1.5), e.beginPath(), e.moveTo(t.x, t.y), e.lineTo(i.x, i.y), e.strokeStyle = n, e.stroke();
|
|
2935
3104
|
}
|
|
2936
3105
|
}
|
|
2937
3106
|
renderNodes() {
|
|
2938
3107
|
const e = this.ctx;
|
|
2939
3108
|
for (const s of this.nodes.values()) {
|
|
2940
|
-
const t = s === this.hoveredNode, i = s === this.selectedNode, o = this.hoveredEdge && (s.data.id === this.hoveredEdge.source || s.data.id === this.hoveredEdge.target),
|
|
3109
|
+
const t = s === this.hoveredNode, i = s === this.selectedNode, o = this.hoveredEdge && (s.data.id === this.hoveredEdge.source || s.data.id === this.hoveredEdge.target), n = s.radius * (t ? 1.1 : 1);
|
|
2941
3110
|
if (t || i || o) {
|
|
2942
|
-
const
|
|
3111
|
+
const y = e.createRadialGradient(
|
|
2943
3112
|
s.x,
|
|
2944
3113
|
s.y,
|
|
2945
|
-
|
|
3114
|
+
n * 0.5,
|
|
2946
3115
|
s.x,
|
|
2947
3116
|
s.y,
|
|
2948
|
-
|
|
3117
|
+
n * 2
|
|
2949
3118
|
), b = t || i ? 0.4 : 0.25;
|
|
2950
|
-
|
|
3119
|
+
y.addColorStop(0, `rgba(255, 153, 102, ${b})`), y.addColorStop(1, "rgba(255, 153, 102, 0)"), e.fillStyle = y, e.beginPath(), e.arc(s.x, s.y, n * 2, 0, Math.PI * 2), e.fill();
|
|
2951
3120
|
}
|
|
2952
3121
|
const r = e.createRadialGradient(
|
|
2953
|
-
s.x -
|
|
2954
|
-
s.y -
|
|
3122
|
+
s.x - n * 0.3,
|
|
3123
|
+
s.y - n * 0.3,
|
|
2955
3124
|
0,
|
|
2956
3125
|
s.x,
|
|
2957
3126
|
s.y,
|
|
2958
|
-
|
|
2959
|
-
),
|
|
2960
|
-
r.addColorStop(0, `rgba(${Math.min(255,
|
|
2961
|
-
const
|
|
3127
|
+
n
|
|
3128
|
+
), d = s.color >> 16 & 255, c = s.color >> 8 & 255, p = s.color & 255;
|
|
3129
|
+
r.addColorStop(0, `rgba(${Math.min(255, d + 60)}, ${Math.min(255, c + 60)}, ${Math.min(255, p + 60)}, 0.95)`), r.addColorStop(0.7, `rgba(${d}, ${c}, ${p}, 0.9)`), r.addColorStop(1, `rgba(${Math.max(0, d - 40)}, ${Math.max(0, c - 40)}, ${Math.max(0, p - 40)}, 0.85)`), e.beginPath(), e.arc(s.x, s.y, n, 0, Math.PI * 2), e.fillStyle = r, e.fill(), e.strokeStyle = "rgba(255, 255, 255, 0.2)", e.lineWidth = 1, e.stroke(), e.beginPath(), e.arc(s.x - n * 0.25, s.y - n * 0.25, n * 0.3, 0, Math.PI * 2), e.fillStyle = "rgba(255, 255, 255, 0.15)", e.fill(), e.fillStyle = "white", e.font = "600 11px Inter, -apple-system, BlinkMacSystemFont, sans-serif", e.textAlign = "center", e.textBaseline = "middle";
|
|
3130
|
+
const f = n * 1.6;
|
|
2962
3131
|
let m = s.label, u = e.measureText(m).width;
|
|
2963
|
-
if (u >
|
|
2964
|
-
for (; u >
|
|
3132
|
+
if (u > f) {
|
|
3133
|
+
for (; u > f && m.length > 3; )
|
|
2965
3134
|
m = m.slice(0, -1), u = e.measureText(m + "...").width;
|
|
2966
3135
|
m += "...";
|
|
2967
3136
|
}
|
|
@@ -3064,11 +3233,11 @@ class It {
|
|
|
3064
3233
|
focusOnNode(e) {
|
|
3065
3234
|
const s = this.nodes.get(e);
|
|
3066
3235
|
if (!s) return;
|
|
3067
|
-
const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale, i = this.canvas.height / 2 / (window.devicePixelRatio || 1) - s.y * this.transform.scale, o = this.transform.x,
|
|
3068
|
-
const p = performance.now() -
|
|
3069
|
-
this.transform.x = o + (t - o) * m, this.transform.y =
|
|
3236
|
+
const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale, i = this.canvas.height / 2 / (window.devicePixelRatio || 1) - s.y * this.transform.scale, o = this.transform.x, n = this.transform.y, r = 500, d = performance.now(), c = () => {
|
|
3237
|
+
const p = performance.now() - d, f = Math.min(p / r, 1), m = 1 - Math.pow(1 - f, 3);
|
|
3238
|
+
this.transform.x = o + (t - o) * m, this.transform.y = n + (i - n) * m, f < 1 ? requestAnimationFrame(c) : this.selectedNode = s;
|
|
3070
3239
|
};
|
|
3071
|
-
|
|
3240
|
+
c();
|
|
3072
3241
|
}
|
|
3073
3242
|
/**
|
|
3074
3243
|
* Updates node positions from 3D data
|
|
@@ -3146,7 +3315,7 @@ class Ht {
|
|
|
3146
3315
|
l(this, "devControls", null);
|
|
3147
3316
|
l(this, "viewMode", "3d");
|
|
3148
3317
|
l(this, "graphData", null);
|
|
3149
|
-
this.options = { ...P, ...s }, this.container =
|
|
3318
|
+
this.options = { ...P, ...s }, this.container = dt(e), this.materialFactory = new bt(), this.nodeFactory = new vt(
|
|
3150
3319
|
this.materialFactory,
|
|
3151
3320
|
this.options.nodeRadius ?? P.nodeRadius,
|
|
3152
3321
|
this.options.lodSegments ?? P.lodSegments,
|
|
@@ -3155,14 +3324,14 @@ class Ht {
|
|
|
3155
3324
|
this.materialFactory,
|
|
3156
3325
|
this.options.edgeColor ?? P.edgeColor,
|
|
3157
3326
|
this.options.edgeOpacity ?? P.edgeOpacity
|
|
3158
|
-
), this.sceneManager = new
|
|
3327
|
+
), this.sceneManager = new ft(this.container, this.options), this.lodManager = new Mt(
|
|
3159
3328
|
this.sceneManager.camera,
|
|
3160
3329
|
this.options.lodDistances ?? P.lodDistances,
|
|
3161
3330
|
this.options.enableLOD ?? P.enableLOD
|
|
3162
|
-
), this.frustumCuller = new
|
|
3331
|
+
), this.frustumCuller = new Et(
|
|
3163
3332
|
this.sceneManager.camera,
|
|
3164
3333
|
this.options.enableEdgeCulling ?? P.enableEdgeCulling
|
|
3165
|
-
), this.nodeManager = new
|
|
3334
|
+
), this.nodeManager = new ee(this.sceneManager, this.nodeFactory), this.edgeManager = new mt(this.sceneManager, this.nodeManager, this.edgeFactory), this.graphEngine = new Re(
|
|
3166
3335
|
this.nodeManager.getAllNodes(),
|
|
3167
3336
|
this.edgeManager.getAllEdges(),
|
|
3168
3337
|
{
|
|
@@ -3172,16 +3341,16 @@ class Ht {
|
|
|
3172
3341
|
useBarnesHut: this.options.useBarnesHut,
|
|
3173
3342
|
barnesHutTheta: this.options.barnesHutTheta
|
|
3174
3343
|
}
|
|
3175
|
-
), this.rendererManager = new
|
|
3344
|
+
), this.rendererManager = new xt(
|
|
3176
3345
|
this.sceneManager,
|
|
3177
3346
|
() => this.onSimulate(),
|
|
3178
3347
|
() => this.onRender(),
|
|
3179
3348
|
this.options.targetFPS ?? P.targetFPS
|
|
3180
|
-
), this.raycasterManager = new
|
|
3349
|
+
), this.raycasterManager = new Ct(this.sceneManager, this.container), this.panelManager = new Nt(this.container), this.edgePanelManager = new St(this.container), this.edgeTooltipManager = new zt(), this.edgePanelManager.setNodeClickCallback((t) => {
|
|
3181
3350
|
this.edgePanelManager.hide(), this.focusOnNode(t), setTimeout(() => {
|
|
3182
3351
|
this.showNodePanel(t);
|
|
3183
3352
|
}, 400);
|
|
3184
|
-
}), this.options.showSearch !== !1 && (this.searchManager = new
|
|
3353
|
+
}), this.options.showSearch !== !1 && (this.searchManager = new kt(this.container, {
|
|
3185
3354
|
placeholder: this.options.searchPlaceholder,
|
|
3186
3355
|
onSearch: (t) => ({
|
|
3187
3356
|
nodeResults: this.searchNodes(t),
|
|
@@ -3192,12 +3361,12 @@ class Ht {
|
|
|
3192
3361
|
this.showNodePanel(t);
|
|
3193
3362
|
}, 400);
|
|
3194
3363
|
}
|
|
3195
|
-
})), this.options.showViewToggle !== !1 && (this.viewMode = this.options.initialViewMode || "3d", this.viewToggleManager = new
|
|
3364
|
+
})), this.options.showViewToggle !== !1 && (this.viewMode = this.options.initialViewMode || "3d", this.viewToggleManager = new Tt(this.container, {
|
|
3196
3365
|
initialMode: this.viewMode,
|
|
3197
3366
|
onViewChange: (t) => {
|
|
3198
3367
|
this.switchView(t);
|
|
3199
3368
|
}
|
|
3200
|
-
})), this.options.showLegend !== !1 && (this.legendManager = new
|
|
3369
|
+
})), this.options.showLegend !== !1 && (this.legendManager = new Pt(this.container), this.updateLegendCounts()), this.setupCallbacks(), this.rendererManager.start(), this.initialized = !0, this.emit("ready");
|
|
3201
3370
|
}
|
|
3202
3371
|
/**
|
|
3203
3372
|
* Sets up internal callbacks
|
|
@@ -3220,7 +3389,14 @@ class Ht {
|
|
|
3220
3389
|
if (e) {
|
|
3221
3390
|
this.edgeManager.highlightEdge(e.edge.source, e.edge.target);
|
|
3222
3391
|
const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, i = s.top + s.height / 2;
|
|
3223
|
-
this.edgeTooltipManager.show(
|
|
3392
|
+
this.edgeTooltipManager.show(
|
|
3393
|
+
e.edge,
|
|
3394
|
+
e.sourceNode,
|
|
3395
|
+
e.targetNode,
|
|
3396
|
+
t,
|
|
3397
|
+
i,
|
|
3398
|
+
e.relationships
|
|
3399
|
+
), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
|
|
3224
3400
|
} else
|
|
3225
3401
|
this.edgeManager.unhighlightCurrentEdge(), this.edgeTooltipManager.hide(), this.options.onEdgeHover && this.options.onEdgeHover(null, null, null), this.emit("edgeHover", null, null, null);
|
|
3226
3402
|
}
|
|
@@ -3236,7 +3412,7 @@ class Ht {
|
|
|
3236
3412
|
* Handles edge click
|
|
3237
3413
|
*/
|
|
3238
3414
|
onEdgeClick(e) {
|
|
3239
|
-
this.panelManager.hide(), this.edgeTooltipManager.hide(), this.edgeManager.highlightEdge(e.edge.source, e.edge.target), this.edgePanelManager.show(e.edge, e.sourceNode, e.targetNode), this.focusOnEdge(e.edge.source, e.edge.target), this.emit("edgeClick", e.edge, e.sourceNode, e.targetNode);
|
|
3415
|
+
this.panelManager.hide(), this.edgeTooltipManager.hide(), this.edgeManager.highlightEdge(e.edge.source, e.edge.target), this.edgePanelManager.show(e.edge, e.sourceNode, e.targetNode, e.relationships), this.focusOnEdge(e.edge.source, e.edge.target), this.emit("edgeClick", e.edge, e.sourceNode, e.targetNode);
|
|
3240
3416
|
}
|
|
3241
3417
|
/**
|
|
3242
3418
|
* Called every simulation step
|
|
@@ -3269,8 +3445,8 @@ class Ht {
|
|
|
3269
3445
|
* Sets the graph data
|
|
3270
3446
|
*/
|
|
3271
3447
|
setData(e) {
|
|
3272
|
-
var
|
|
3273
|
-
const s = (
|
|
3448
|
+
var n;
|
|
3449
|
+
const s = (n = e.data) != null && n.nodes ? e.data : e, i = (s.edges || s.links || []).map((r) => ({
|
|
3274
3450
|
...r,
|
|
3275
3451
|
relationship: r.relationship || r.label || "related_to"
|
|
3276
3452
|
})), o = {
|
|
@@ -3278,14 +3454,14 @@ class Ht {
|
|
|
3278
3454
|
edges: i
|
|
3279
3455
|
};
|
|
3280
3456
|
if (this.graphData = o, this.edgeManager.clear(), this.nodeManager.clear(), o.nodes && Array.isArray(o.nodes)) {
|
|
3281
|
-
|
|
3457
|
+
ee.setExpectedNodeCount(o.nodes.length);
|
|
3282
3458
|
for (const r of o.nodes)
|
|
3283
3459
|
this.addNode(r);
|
|
3284
3460
|
}
|
|
3285
3461
|
if (o.edges && Array.isArray(o.edges))
|
|
3286
3462
|
for (const r of o.edges)
|
|
3287
3463
|
this.addEdge(r);
|
|
3288
|
-
this.graphEngine = new
|
|
3464
|
+
this.graphEngine = new Re(
|
|
3289
3465
|
this.nodeManager.getAllNodes(),
|
|
3290
3466
|
this.edgeManager.getAllEdges(),
|
|
3291
3467
|
{
|
|
@@ -3302,7 +3478,7 @@ class Ht {
|
|
|
3302
3478
|
* @returns true if added, false if node already exists or invalid
|
|
3303
3479
|
*/
|
|
3304
3480
|
addNode(e) {
|
|
3305
|
-
if (!
|
|
3481
|
+
if (!Fe(e))
|
|
3306
3482
|
return !1;
|
|
3307
3483
|
const s = this.nodeManager.addNode(e);
|
|
3308
3484
|
return s && (this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.addNode(e), this.options.onNodeAdd && this.options.onNodeAdd(e), this.emit("nodeAdd", e), this.updateLegendCounts()), s;
|
|
@@ -3312,7 +3488,7 @@ class Ht {
|
|
|
3312
3488
|
* @returns true if removed, false if not found
|
|
3313
3489
|
*/
|
|
3314
3490
|
removeNode(e) {
|
|
3315
|
-
if (!
|
|
3491
|
+
if (!ht(e))
|
|
3316
3492
|
return !1;
|
|
3317
3493
|
this.edgeManager.removeEdgesForNode(e);
|
|
3318
3494
|
const s = this.nodeManager.removeNode(e);
|
|
@@ -3326,10 +3502,10 @@ class Ht {
|
|
|
3326
3502
|
}
|
|
3327
3503
|
/**
|
|
3328
3504
|
* Adds an edge to the graph
|
|
3329
|
-
* @returns true if added, false if
|
|
3505
|
+
* @returns true if added, false if invalid or nodes don't exist
|
|
3330
3506
|
*/
|
|
3331
3507
|
addEdge(e) {
|
|
3332
|
-
if (!
|
|
3508
|
+
if (!De(e))
|
|
3333
3509
|
return !1;
|
|
3334
3510
|
const s = this.edgeManager.addEdge(e);
|
|
3335
3511
|
return s && (this.graphEngine.setEdges(this.edgeManager.getAllEdges()), this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.addEdge(e), this.options.onEdgeAdd && this.options.onEdgeAdd(e), this.emit("edgeAdd", e), this.updateLegendCounts()), s;
|
|
@@ -3355,11 +3531,11 @@ class Ht {
|
|
|
3355
3531
|
try {
|
|
3356
3532
|
const o = await i(e, s);
|
|
3357
3533
|
if (o.nodes && Array.isArray(o.nodes))
|
|
3358
|
-
for (const
|
|
3359
|
-
this.addNode(
|
|
3534
|
+
for (const n of o.nodes)
|
|
3535
|
+
this.addNode(n);
|
|
3360
3536
|
if (o.edges && Array.isArray(o.edges))
|
|
3361
|
-
for (const
|
|
3362
|
-
this.addEdge(
|
|
3537
|
+
for (const n of o.edges)
|
|
3538
|
+
this.addEdge(n);
|
|
3363
3539
|
return this.panelManager.hide(), this.emit("expand", e, o), !0;
|
|
3364
3540
|
} catch (o) {
|
|
3365
3541
|
return console.error("[ForceGraph3D] Error expanding node:", o), !1;
|
|
@@ -3409,13 +3585,13 @@ class Ht {
|
|
|
3409
3585
|
console.warn(`[ForceGraph3D] Node "${e}" not found`);
|
|
3410
3586
|
return;
|
|
3411
3587
|
}
|
|
3412
|
-
const i = t.position, o = this.sceneManager.camera,
|
|
3588
|
+
const i = t.position, o = this.sceneManager.camera, n = this.sceneManager.controls, r = o.position.clone().sub(n.target).normalize(), d = {
|
|
3413
3589
|
x: i.x + r.x * s,
|
|
3414
3590
|
y: i.y + r.y * s,
|
|
3415
3591
|
z: i.z + r.z * s
|
|
3416
|
-
},
|
|
3417
|
-
const
|
|
3418
|
-
o.position.x =
|
|
3592
|
+
}, c = { x: o.position.x, y: o.position.y, z: o.position.z }, p = { x: n.target.x, y: n.target.y, z: n.target.z }, f = 800, m = performance.now(), u = () => {
|
|
3593
|
+
const y = performance.now() - m, b = Math.min(y / f, 1), w = 1 - Math.pow(1 - b, 3);
|
|
3594
|
+
o.position.x = c.x + (d.x - c.x) * w, o.position.y = c.y + (d.y - c.y) * w, o.position.z = c.z + (d.z - c.z) * w, n.target.x = p.x + (i.x - p.x) * w, n.target.y = p.y + (i.y - p.y) * w, n.target.z = p.z + (i.z - p.z) * w, n.update(), b < 1 && requestAnimationFrame(u);
|
|
3419
3595
|
};
|
|
3420
3596
|
u();
|
|
3421
3597
|
}
|
|
@@ -3429,19 +3605,19 @@ class Ht {
|
|
|
3429
3605
|
console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);
|
|
3430
3606
|
return;
|
|
3431
3607
|
}
|
|
3432
|
-
const
|
|
3608
|
+
const n = this.sceneManager.camera, r = this.sceneManager.controls, d = {
|
|
3433
3609
|
x: (i.position.x + o.position.x) / 2,
|
|
3434
3610
|
y: (i.position.y + o.position.y) / 2,
|
|
3435
3611
|
z: (i.position.z + o.position.z) / 2
|
|
3436
|
-
},
|
|
3437
|
-
x:
|
|
3438
|
-
y:
|
|
3439
|
-
z:
|
|
3440
|
-
},
|
|
3612
|
+
}, c = o.position.x - i.position.x, p = o.position.y - i.position.y, f = o.position.z - i.position.z, m = Math.sqrt(c * c + p * p + f * f), u = Math.max(m * t, 40), y = n.position.clone().sub(r.target).normalize(), b = {
|
|
3613
|
+
x: d.x + y.x * u,
|
|
3614
|
+
y: d.y + y.y * u,
|
|
3615
|
+
z: d.z + y.z * u
|
|
3616
|
+
}, w = { x: n.position.x, y: n.position.y, z: n.position.z }, N = { x: r.target.x, y: r.target.y, z: r.target.z }, O = 800, L = performance.now(), G = () => {
|
|
3441
3617
|
const T = performance.now() - L, D = Math.min(T / O, 1), E = 1 - Math.pow(1 - D, 3);
|
|
3442
|
-
|
|
3618
|
+
n.position.x = w.x + (b.x - w.x) * E, n.position.y = w.y + (b.y - w.y) * E, n.position.z = w.z + (b.z - w.z) * E, r.target.x = N.x + (d.x - N.x) * E, r.target.y = N.y + (d.y - N.y) * E, r.target.z = N.z + (d.z - N.z) * E, r.update(), D < 1 && requestAnimationFrame(G);
|
|
3443
3619
|
};
|
|
3444
|
-
|
|
3620
|
+
G();
|
|
3445
3621
|
}
|
|
3446
3622
|
/**
|
|
3447
3623
|
* Shows the info panel for a specific node
|
|
@@ -3464,9 +3640,9 @@ class Ht {
|
|
|
3464
3640
|
return [];
|
|
3465
3641
|
const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), i = [];
|
|
3466
3642
|
return t.forEach((o) => {
|
|
3467
|
-
var
|
|
3468
|
-
const
|
|
3469
|
-
(
|
|
3643
|
+
var c, p, f;
|
|
3644
|
+
const n = (c = o.label) == null ? void 0 : c.toLowerCase().includes(s), r = (p = o.id) == null ? void 0 : p.toLowerCase().includes(s), d = (f = o.type) == null ? void 0 : f.toLowerCase().includes(s);
|
|
3645
|
+
(n || r || d) && i.push(o);
|
|
3470
3646
|
}), i;
|
|
3471
3647
|
}
|
|
3472
3648
|
/**
|
|
@@ -3478,10 +3654,10 @@ class Ht {
|
|
|
3478
3654
|
if (!e || e.trim() === "")
|
|
3479
3655
|
return [];
|
|
3480
3656
|
const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), i = [];
|
|
3481
|
-
for (const
|
|
3482
|
-
if ((o =
|
|
3483
|
-
const
|
|
3484
|
-
|
|
3657
|
+
for (const n of t)
|
|
3658
|
+
if ((o = n.relationship) == null ? void 0 : o.toLowerCase().includes(s)) {
|
|
3659
|
+
const d = this.nodeManager.getNode(n.source), c = this.nodeManager.getNode(n.target);
|
|
3660
|
+
d && c && i.push({ edge: n, sourceNode: d, targetNode: c });
|
|
3485
3661
|
}
|
|
3486
3662
|
return i;
|
|
3487
3663
|
}
|
|
@@ -3514,7 +3690,7 @@ class Ht {
|
|
|
3514
3690
|
* Switches between 2D and 3D view modes
|
|
3515
3691
|
*/
|
|
3516
3692
|
switchView(e) {
|
|
3517
|
-
this.viewMode !== e && (this.viewMode = e, this.panelManager.hide(), this.edgePanelManager.hide(), this.edgeTooltipManager.hide(), e === "2d" ? (this.sceneManager.renderer.domElement.style.display = "none", this.rendererManager.stop(), this.forceGraph2D ? (this.forceGraph2D.show(), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())) : (this.forceGraph2D = new
|
|
3693
|
+
this.viewMode !== e && (this.viewMode = e, this.panelManager.hide(), this.edgePanelManager.hide(), this.edgeTooltipManager.hide(), e === "2d" ? (this.sceneManager.renderer.domElement.style.display = "none", this.rendererManager.stop(), this.forceGraph2D ? (this.forceGraph2D.show(), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())) : (this.forceGraph2D = new Rt(this.container, {
|
|
3518
3694
|
backgroundColor: "#0a0a0a",
|
|
3519
3695
|
nodeRadius: 24,
|
|
3520
3696
|
onNodeClick: (s) => {
|
|
@@ -3526,19 +3702,31 @@ class Ht {
|
|
|
3526
3702
|
onEdgeHover: (s, t) => {
|
|
3527
3703
|
if (s && t) {
|
|
3528
3704
|
const i = this.nodeManager.getNode(s.source), o = this.nodeManager.getNode(s.target);
|
|
3529
|
-
i && o
|
|
3530
|
-
s
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3705
|
+
if (i && o) {
|
|
3706
|
+
const n = this.edgeManager.getAllEdges().filter((r) => r.source === s.source && r.target === s.target);
|
|
3707
|
+
this.edgeTooltipManager.show(
|
|
3708
|
+
s,
|
|
3709
|
+
i,
|
|
3710
|
+
o,
|
|
3711
|
+
t.clientX,
|
|
3712
|
+
t.clientY,
|
|
3713
|
+
n.length > 0 ? n : [s]
|
|
3714
|
+
);
|
|
3715
|
+
}
|
|
3536
3716
|
} else
|
|
3537
3717
|
this.edgeTooltipManager.hide();
|
|
3538
3718
|
},
|
|
3539
3719
|
onEdgeClick: (s) => {
|
|
3540
3720
|
const t = this.nodeManager.getNode(s.source), i = this.nodeManager.getNode(s.target);
|
|
3541
|
-
t && i
|
|
3721
|
+
if (t && i) {
|
|
3722
|
+
const o = this.edgeManager.getAllEdges().filter((n) => n.source === s.source && n.target === s.target);
|
|
3723
|
+
this.edgePanelManager.show(
|
|
3724
|
+
s,
|
|
3725
|
+
t,
|
|
3726
|
+
i,
|
|
3727
|
+
o.length > 0 ? o : [s]
|
|
3728
|
+
);
|
|
3729
|
+
}
|
|
3542
3730
|
}
|
|
3543
3731
|
}), this.graphData && (this.forceGraph2D.setData(this.graphData), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())))) : (this.forceGraph2D && this.forceGraph2D.hide(), this.sceneManager.renderer.domElement.style.display = "block", this.rendererManager.start()), this.emit("viewChange", e));
|
|
3544
3732
|
}
|
|
@@ -3639,8 +3827,8 @@ class Ht {
|
|
|
3639
3827
|
const i = parseFloat(t.value) / 100;
|
|
3640
3828
|
this.setPhysicsParams({ damping: i }), this.devControls.querySelector("#dev-damping-val").textContent = i.toFixed(2);
|
|
3641
3829
|
}), setInterval(() => {
|
|
3642
|
-
const i = this.devControls.querySelector("#dev-node-count"), o = this.devControls.querySelector("#dev-edge-count"),
|
|
3643
|
-
i && (i.textContent = this.getNodeCount().toString()), o && (o.textContent = this.getEdgeCount().toString()),
|
|
3830
|
+
const i = this.devControls.querySelector("#dev-node-count"), o = this.devControls.querySelector("#dev-edge-count"), n = this.devControls.querySelector("#dev-fps");
|
|
3831
|
+
i && (i.textContent = this.getNodeCount().toString()), o && (o.textContent = this.getEdgeCount().toString()), n && (n.textContent = this.rendererManager.getFPS().toString());
|
|
3644
3832
|
}, 500);
|
|
3645
3833
|
}
|
|
3646
3834
|
/**
|
|
@@ -3650,7 +3838,7 @@ class Ht {
|
|
|
3650
3838
|
this.rendererManager.dispose(), this.panelManager.dispose(), this.raycasterManager.dispose(), this.edgeTooltipManager.dispose(), this.searchManager && this.searchManager.dispose(), this.viewToggleManager && this.viewToggleManager.dispose(), this.legendManager && this.legendManager.dispose(), this.forceGraph2D && this.forceGraph2D.dispose(), this.edgeManager.dispose(), this.nodeManager.dispose(), this.nodeFactory.dispose(), this.materialFactory.dispose(), this.sceneManager.dispose(), this.devControls && this.devControls.parentNode && this.devControls.parentNode.removeChild(this.devControls), this.eventCallbacks.clear(), this.initialized = !1;
|
|
3651
3839
|
}
|
|
3652
3840
|
}
|
|
3653
|
-
const
|
|
3841
|
+
const Ie = [
|
|
3654
3842
|
"Alpha",
|
|
3655
3843
|
"Beta",
|
|
3656
3844
|
"Gamma",
|
|
@@ -3681,7 +3869,7 @@ const Oe = [
|
|
|
3681
3869
|
"Link",
|
|
3682
3870
|
"Point",
|
|
3683
3871
|
"Vertex"
|
|
3684
|
-
],
|
|
3872
|
+
], J = [
|
|
3685
3873
|
"connects to",
|
|
3686
3874
|
"links with",
|
|
3687
3875
|
"relates to",
|
|
@@ -3692,7 +3880,7 @@ const Oe = [
|
|
|
3692
3880
|
"partners with",
|
|
3693
3881
|
"collaborates with",
|
|
3694
3882
|
"supports"
|
|
3695
|
-
],
|
|
3883
|
+
], Oe = [
|
|
3696
3884
|
16777215,
|
|
3697
3885
|
// White
|
|
3698
3886
|
16750950,
|
|
@@ -3707,11 +3895,11 @@ const Oe = [
|
|
|
3707
3895
|
function At(h = 30) {
|
|
3708
3896
|
const e = [], s = [];
|
|
3709
3897
|
for (let i = 0; i < h; i++) {
|
|
3710
|
-
const o = i <
|
|
3898
|
+
const o = i < Ie.length ? Ie[i] : `Node ${i + 1}`;
|
|
3711
3899
|
e.push({
|
|
3712
3900
|
id: `node-${i}`,
|
|
3713
3901
|
label: o,
|
|
3714
|
-
color:
|
|
3902
|
+
color: Oe[i % Oe.length],
|
|
3715
3903
|
position: {
|
|
3716
3904
|
x: (Math.random() - 0.5) * 60,
|
|
3717
3905
|
y: (Math.random() - 0.5) * 60,
|
|
@@ -3724,21 +3912,21 @@ function At(h = 30) {
|
|
|
3724
3912
|
s.push({
|
|
3725
3913
|
source: `node-${i}`,
|
|
3726
3914
|
target: `node-${o}`,
|
|
3727
|
-
relationship:
|
|
3915
|
+
relationship: J[Math.floor(Math.random() * J.length)]
|
|
3728
3916
|
});
|
|
3729
3917
|
}
|
|
3730
3918
|
const t = Math.floor(h * 0.5);
|
|
3731
3919
|
for (let i = 0; i < t; i++) {
|
|
3732
3920
|
const o = Math.floor(Math.random() * h);
|
|
3733
|
-
let
|
|
3734
|
-
o ===
|
|
3735
|
-
const r = `node-${o}`,
|
|
3921
|
+
let n = Math.floor(Math.random() * h);
|
|
3922
|
+
o === n && (n = (n + 1) % h);
|
|
3923
|
+
const r = `node-${o}`, d = `node-${n}`;
|
|
3736
3924
|
s.some(
|
|
3737
|
-
(p) => p.source === r && p.target ===
|
|
3925
|
+
(p) => p.source === r && p.target === d || p.source === d && p.target === r
|
|
3738
3926
|
) || s.push({
|
|
3739
3927
|
source: r,
|
|
3740
|
-
target:
|
|
3741
|
-
relationship:
|
|
3928
|
+
target: d,
|
|
3929
|
+
relationship: J[Math.floor(Math.random() * J.length)]
|
|
3742
3930
|
});
|
|
3743
3931
|
}
|
|
3744
3932
|
return { nodes: e, edges: s };
|
|
@@ -3752,19 +3940,19 @@ function jt(h = 1e3) {
|
|
|
3752
3940
|
z: (Math.random() - 0.5) * 200
|
|
3753
3941
|
});
|
|
3754
3942
|
for (let o = 0; o < h; o++) {
|
|
3755
|
-
const
|
|
3943
|
+
const n = i[o % t];
|
|
3756
3944
|
e.push({
|
|
3757
3945
|
id: `node-${o}`,
|
|
3758
3946
|
label: `N${o}`,
|
|
3759
3947
|
position: {
|
|
3760
|
-
x:
|
|
3761
|
-
y:
|
|
3762
|
-
z:
|
|
3948
|
+
x: n.x + (Math.random() - 0.5) * 40,
|
|
3949
|
+
y: n.y + (Math.random() - 0.5) * 40,
|
|
3950
|
+
z: n.z + (Math.random() - 0.5) * 40
|
|
3763
3951
|
}
|
|
3764
3952
|
});
|
|
3765
3953
|
}
|
|
3766
3954
|
for (let o = 1; o < h; o++) {
|
|
3767
|
-
const
|
|
3955
|
+
const n = Math.floor(o / 50) * 50, r = n === 0 ? Math.floor(Math.random() * o) : n + Math.floor(Math.random() * Math.min(o - n, 50));
|
|
3768
3956
|
s.push({
|
|
3769
3957
|
source: `node-${o}`,
|
|
3770
3958
|
target: `node-${Math.min(r, o - 1)}`,
|
|
@@ -3772,9 +3960,9 @@ function jt(h = 1e3) {
|
|
|
3772
3960
|
});
|
|
3773
3961
|
}
|
|
3774
3962
|
for (let o = 1; o < t; o++) {
|
|
3775
|
-
const
|
|
3963
|
+
const n = o * 50, r = (o - 1) * 50 + Math.floor(Math.random() * 50);
|
|
3776
3964
|
s.push({
|
|
3777
|
-
source: `node-${
|
|
3965
|
+
source: `node-${n}`,
|
|
3778
3966
|
target: `node-${r}`,
|
|
3779
3967
|
relationship: "bridges to"
|
|
3780
3968
|
});
|
|
@@ -3784,11 +3972,11 @@ function jt(h = 1e3) {
|
|
|
3784
3972
|
export {
|
|
3785
3973
|
P as DEFAULT_OPTIONS,
|
|
3786
3974
|
Ht as ForceGraph3D,
|
|
3787
|
-
|
|
3788
|
-
|
|
3975
|
+
_ as LODLevel,
|
|
3976
|
+
Dt as createEdgeKey,
|
|
3789
3977
|
jt as generateLargeSampleData,
|
|
3790
3978
|
At as generateSampleData,
|
|
3791
|
-
|
|
3792
|
-
|
|
3979
|
+
De as validateEdgeData,
|
|
3980
|
+
Fe as validateNodeData
|
|
3793
3981
|
};
|
|
3794
3982
|
//# sourceMappingURL=force-3d-graph.js.map
|