@cocorof/graphier 1.3.3 → 1.4.1

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/index.js CHANGED
@@ -26,7 +26,10 @@ const DEFAULT_LAYOUT = {
26
26
  alphaDecay: "auto",
27
27
  velocityDecay: 0.4,
28
28
  settledThreshold: 5e-3,
29
- spreadFactor: "auto"
29
+ spreadFactor: "auto",
30
+ dimensions: 3,
31
+ clusterBy: null,
32
+ clusterStrength: 0.05
30
33
  };
31
34
  function hexToRgb(hex) {
32
35
  const c2 = hex.replace("#", "");
@@ -38,6 +41,14 @@ function rgbToHex(r, g, b) {
38
41
  const hex = clamp(r) << 16 | clamp(g) << 8 | clamp(b);
39
42
  return "#" + hex.toString(16).padStart(6, "0");
40
43
  }
44
+ function luminance(hex) {
45
+ const [r, g, b] = hexToRgb(hex);
46
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
47
+ }
48
+ function darken(hex, factor) {
49
+ const [r, g, b] = hexToRgb(hex);
50
+ return rgbToHex(r * factor, g * factor, b * factor);
51
+ }
41
52
  function brighten(hex, factor) {
42
53
  const [r, g, b] = hexToRgb(hex);
43
54
  const t = 1 - 1 / factor;
@@ -119,10 +130,40 @@ const minimal = {
119
130
  defaultLinkColor: "#444444",
120
131
  backgroundColor: "#1a1a2e"
121
132
  };
133
+ const paper = {
134
+ nodeColors: {},
135
+ // Bright (label / highlight) colors are auto-derived: on a light
136
+ // background resolveTheme darkens instead of whitening.
137
+ nodeColorsBright: {},
138
+ linkColors: {},
139
+ defaultNodeColor: "#64748b",
140
+ defaultLinkColor: "#b3bdcc",
141
+ backgroundColor: "#f6f7f9",
142
+ blending: "normal",
143
+ palette: [
144
+ "#2563eb",
145
+ // blue
146
+ "#d97706",
147
+ // amber
148
+ "#7c3aed",
149
+ // violet
150
+ "#db2777",
151
+ // pink
152
+ "#0891b2",
153
+ // cyan
154
+ "#16a34a",
155
+ // green
156
+ "#dc2626",
157
+ // red
158
+ "#475569"
159
+ // slate
160
+ ]
161
+ };
122
162
  const PRESETS = {
123
163
  celestial,
124
164
  neon,
125
- minimal
165
+ minimal,
166
+ paper
126
167
  };
127
168
  const DEFAULT_THEME = {
128
169
  nodeColors: celestial.nodeColors ?? {},
@@ -150,6 +191,8 @@ function resolveTheme(theme) {
150
191
  const defaultLinkColor = config.defaultLinkColor ?? DEFAULT_THEME.defaultLinkColor;
151
192
  const backgroundColor = config.backgroundColor ?? DEFAULT_THEME.backgroundColor;
152
193
  const palette = config.palette ?? DEFAULT_THEME.palette;
194
+ const isLight = luminance(backgroundColor) > 0.5;
195
+ const additiveEdges = config.blending ? config.blending === "additive" : !isLight;
153
196
  const autoAssigned = /* @__PURE__ */ new Map();
154
197
  let nextPaletteIdx = 0;
155
198
  function nodeColor(type) {
@@ -161,16 +204,24 @@ function resolveTheme(theme) {
161
204
  }
162
205
  return palette[autoAssigned.get(type)];
163
206
  }
207
+ const emphasize = (c2) => isLight ? darken(c2, 0.72) : brighten(c2, 1.5);
164
208
  function nodeColorBright(type) {
165
- if (!type) return brighten(defaultNodeColor, 1.5);
209
+ if (!type) return emphasize(defaultNodeColor);
166
210
  if (nodeColorsBright[type]) return nodeColorsBright[type];
167
- return brighten(nodeColor(type), 1.5);
211
+ return emphasize(nodeColor(type));
168
212
  }
169
213
  function linkColor(type) {
170
214
  if (!type) return defaultLinkColor;
171
215
  return linkColors[type] ?? defaultLinkColor;
172
216
  }
173
- return { nodeColor, nodeColorBright, linkColor, backgroundColor };
217
+ return {
218
+ nodeColor,
219
+ nodeColorBright,
220
+ linkColor,
221
+ backgroundColor,
222
+ isLight,
223
+ additiveEdges
224
+ };
174
225
  }
175
226
  function autoSpreadFactor(n) {
176
227
  if (n <= 500) return 1;
@@ -193,6 +244,8 @@ function resolveLayoutParams(nodeCount, config) {
193
244
  const postEvery = n > 5e4 ? 5 : n > 1e4 ? 3 : 2;
194
245
  const initialRadius2 = (500 + Math.min(n, 1e4) * 0.1) * spread;
195
246
  return {
247
+ dimensions: (config == null ? void 0 : config.dimensions) === 2 ? 2 : 3,
248
+ clusterStrength: (config == null ? void 0 : config.clusterStrength) ?? 0.05,
196
249
  charge,
197
250
  distanceMax,
198
251
  theta,
@@ -204,7 +257,7 @@ function resolveLayoutParams(nodeCount, config) {
204
257
  initialRadius: initialRadius2
205
258
  };
206
259
  }
207
- const WORKER_SOURCE = '(function(){"use strict";function At(t,n,i){var e,r=1;t==null&&(t=0),n==null&&(n=0),i==null&&(i=0);function s(){var a,o=e.length,h,u=0,c=0,l=0;for(a=0;a<o;++a)h=e[a],u+=h.x||0,c+=h.y||0,l+=h.z||0;for(u=(u/o-t)*r,c=(c/o-n)*r,l=(l/o-i)*r,a=0;a<o;++a)h=e[a],u&&(h.x-=u),c&&(h.y-=c),l&&(h.z-=l)}return s.initialize=function(a){e=a},s.x=function(a){return arguments.length?(t=+a,s):t},s.y=function(a){return arguments.length?(n=+a,s):n},s.z=function(a){return arguments.length?(i=+a,s):i},s.strength=function(a){return arguments.length?(r=+a,s):r},s}function $t(t){const n=+this._x.call(null,t);return et(this.cover(n),n,t)}function et(t,n,i){if(isNaN(n))return t;var e,r=t._root,s={data:i},a=t._x0,o=t._x1,h,u,c,l,v;if(!r)return t._root=s,t;for(;r.length;)if((c=n>=(h=(a+o)/2))?a=h:o=h,e=r,!(r=r[l=+c]))return e[l]=s,t;if(u=+t._x.call(null,r.data),n===u)return s.next=r,e?e[l]=s:t._root=s,t;do e=e?e[l]=new Array(2):t._root=new Array(2),(c=n>=(h=(a+o)/2))?a=h:o=h;while((l=+c)==(v=+(u>=h)));return e[v]=r,e[l]=s,t}function mt(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n);let e=1/0,r=-1/0;for(let s=0,a;s<n;++s)isNaN(a=+this._x.call(null,t[s]))||(i[s]=a,a<e&&(e=a),a>r&&(r=a));if(e>r)return this;this.cover(e).cover(r);for(let s=0;s<n;++s)et(this,i[s],t[s]);return this}function qt(t){if(isNaN(t=+t))return this;var n=this._x0,i=this._x1;if(isNaN(n))i=(n=Math.floor(t))+1;else{for(var e=i-n||1,r=this._root,s,a;n>t||t>=i;)switch(a=+(t<n),s=new Array(2),s[a]=r,r=s,e*=2,a){case 0:i=n+e;break;case 1:n=i-e;break}this._root&&this._root.length&&(this._root=r)}return this._x0=n,this._x1=i,this}function It(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function bt(t){return arguments.length?this.cover(+t[0][0]).cover(+t[1][0]):isNaN(this._x0)?void 0:[[this._x0],[this._x1]]}function j(t,n,i){this.node=t,this.x0=n,this.x1=i}function kt(t,n){var i,e=this._x0,r,s,a=this._x1,o=[],h=this._root,u,c;for(h&&o.push(new j(h,e,a)),n==null?n=1/0:(e=t-n,a=t+n);u=o.pop();)if(!(!(h=u.node)||(r=u.x0)>a||(s=u.x1)<e))if(h.length){var l=(r+s)/2;o.push(new j(h[1],l,s),new j(h[0],r,l)),(c=+(t>=l))&&(u=o[o.length-1],o[o.length-1]=o[o.length-1-c],o[o.length-1-c]=u)}else{var v=Math.abs(t-+this._x.call(null,h.data));v<n&&(n=v,e=t-v,a=t+v,i=h.data)}return i}function Dt(t){if(isNaN(h=+this._x.call(null,t)))return this;var n,i=this._root,e,r,s,a=this._x0,o=this._x1,h,u,c,l,v;if(!i)return this;if(i.length)for(;;){if((c=h>=(u=(a+o)/2))?a=u:o=u,n=i,!(i=i[l=+c]))return this;if(!i.length)break;n[l+1&1]&&(e=n,v=l)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[l]=s:delete n[l],(i=n[0]||n[1])&&i===(n[1]||n[0])&&!i.length&&(e?e[v]=i:this._root=i),this):(this._root=s,this)}function Et(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Tt(){return this._root}function jt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Pt(t){var n=[],i,e=this._root,r,s,a;for(e&&n.push(new j(e,this._x0,this._x1));i=n.pop();)if(!t(e=i.node,s=i.x0,a=i.x1)&&e.length){var o=(s+a)/2;(r=e[1])&&n.push(new j(r,o,a)),(r=e[0])&&n.push(new j(r,s,o))}return this}function Ft(t){var n=[],i=[],e;for(this._root&&n.push(new j(this._root,this._x0,this._x1));e=n.pop();){var r=e.node;if(r.length){var s,a=e.x0,o=e.x1,h=(a+o)/2;(s=r[0])&&n.push(new j(s,a,h)),(s=r[1])&&n.push(new j(s,h,o))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.x1);return this}function Ot(t){return t[0]}function St(t){return arguments.length?(this._x=t,this):this._x}function rt(t,n){var i=new G(n??Ot,NaN,NaN);return t==null?i:i.addAll(t)}function G(t,n,i){this._x=t,this._x0=n,this._x1=i,this._root=void 0}function st(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var k=rt.prototype=G.prototype;k.copy=function(){var t=new G(this._x,this._x0,this._x1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=st(n),t;for(i=[{source:n,target:t._root=new Array(2)}];n=i.pop();)for(var r=0;r<2;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(2)}):n.target[r]=st(e));return t},k.add=$t,k.addAll=mt,k.cover=qt,k.data=It,k.extent=bt,k.find=kt,k.remove=Dt,k.removeAll=Et,k.root=Tt,k.size=jt,k.visit=Pt,k.visitAfter=Ft,k.x=St;function Rt(t){const n=+this._x.call(null,t),i=+this._y.call(null,t);return at(this.cover(n,i),n,i,t)}function at(t,n,i,e){if(isNaN(n)||isNaN(i))return t;var r,s=t._root,a={data:e},o=t._x0,h=t._y0,u=t._x1,c=t._y1,l,v,y,_,N,p,f,d;if(!s)return t._root=a,t;for(;s.length;)if((N=n>=(l=(o+u)/2))?o=l:u=l,(p=i>=(v=(h+c)/2))?h=v:c=v,r=s,!(s=s[f=p<<1|N]))return r[f]=a,t;if(y=+t._x.call(null,s.data),_=+t._y.call(null,s.data),n===y&&i===_)return a.next=s,r?r[f]=a:t._root=a,t;do r=r?r[f]=new Array(4):t._root=new Array(4),(N=n>=(l=(o+u)/2))?o=l:u=l,(p=i>=(v=(h+c)/2))?h=v:c=v;while((f=p<<1|N)===(d=(_>=v)<<1|y>=l));return r[d]=s,r[f]=a,t}function Xt(t){var n,i,e=t.length,r,s,a=new Array(e),o=new Array(e),h=1/0,u=1/0,c=-1/0,l=-1/0;for(i=0;i<e;++i)isNaN(r=+this._x.call(null,n=t[i]))||isNaN(s=+this._y.call(null,n))||(a[i]=r,o[i]=s,r<h&&(h=r),r>c&&(c=r),s<u&&(u=s),s>l&&(l=s));if(h>c||u>l)return this;for(this.cover(h,u).cover(c,l),i=0;i<e;++i)at(this,a[i],o[i],t[i]);return this}function Bt(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var i=this._x0,e=this._y0,r=this._x1,s=this._y1;if(isNaN(i))r=(i=Math.floor(t))+1,s=(e=Math.floor(n))+1;else{for(var a=r-i||1,o=this._root,h,u;i>t||t>=r||e>n||n>=s;)switch(u=(n<e)<<1|t<i,h=new Array(4),h[u]=o,o=h,a*=2,u){case 0:r=i+a,s=e+a;break;case 1:i=r-a,s=e+a;break;case 2:r=i+a,e=s-a;break;case 3:i=r-a,e=s-a;break}this._root&&this._root.length&&(this._root=o)}return this._x0=i,this._y0=e,this._x1=r,this._y1=s,this}function Ct(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function Lt(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function I(t,n,i,e,r){this.node=t,this.x0=n,this.y0=i,this.x1=e,this.y1=r}function Yt(t,n,i){var e,r=this._x0,s=this._y0,a,o,h,u,c=this._x1,l=this._y1,v=[],y=this._root,_,N;for(y&&v.push(new I(y,r,s,c,l)),i==null?i=1/0:(r=t-i,s=n-i,c=t+i,l=n+i,i*=i);_=v.pop();)if(!(!(y=_.node)||(a=_.x0)>c||(o=_.y0)>l||(h=_.x1)<r||(u=_.y1)<s))if(y.length){var p=(a+h)/2,f=(o+u)/2;v.push(new I(y[3],p,f,h,u),new I(y[2],a,f,p,u),new I(y[1],p,o,h,f),new I(y[0],a,o,p,f)),(N=(n>=f)<<1|t>=p)&&(_=v[v.length-1],v[v.length-1]=v[v.length-1-N],v[v.length-1-N]=_)}else{var d=t-+this._x.call(null,y.data),w=n-+this._y.call(null,y.data),g=d*d+w*w;if(g<i){var x=Math.sqrt(i=g);r=t-x,s=n-x,c=t+x,l=n+x,e=y.data}}return e}function Ht(t){if(isNaN(c=+this._x.call(null,t))||isNaN(l=+this._y.call(null,t)))return this;var n,i=this._root,e,r,s,a=this._x0,o=this._y0,h=this._x1,u=this._y1,c,l,v,y,_,N,p,f;if(!i)return this;if(i.length)for(;;){if((_=c>=(v=(a+h)/2))?a=v:h=v,(N=l>=(y=(o+u)/2))?o=y:u=y,n=i,!(i=i[p=N<<1|_]))return this;if(!i.length)break;(n[p+1&3]||n[p+2&3]||n[p+3&3])&&(e=n,f=p)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[p]=s:delete n[p],(i=n[0]||n[1]||n[2]||n[3])&&i===(n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[f]=i:this._root=i),this):(this._root=s,this)}function Qt(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Wt(){return this._root}function Zt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Gt(t){var n=[],i,e=this._root,r,s,a,o,h;for(e&&n.push(new I(e,this._x0,this._y0,this._x1,this._y1));i=n.pop();)if(!t(e=i.node,s=i.x0,a=i.y0,o=i.x1,h=i.y1)&&e.length){var u=(s+o)/2,c=(a+h)/2;(r=e[3])&&n.push(new I(r,u,c,o,h)),(r=e[2])&&n.push(new I(r,s,c,u,h)),(r=e[1])&&n.push(new I(r,u,a,o,c)),(r=e[0])&&n.push(new I(r,s,a,u,c))}return this}function Jt(t){var n=[],i=[],e;for(this._root&&n.push(new I(this._root,this._x0,this._y0,this._x1,this._y1));e=n.pop();){var r=e.node;if(r.length){var s,a=e.x0,o=e.y0,h=e.x1,u=e.y1,c=(a+h)/2,l=(o+u)/2;(s=r[0])&&n.push(new I(s,a,o,c,l)),(s=r[1])&&n.push(new I(s,c,o,h,l)),(s=r[2])&&n.push(new I(s,a,l,c,u)),(s=r[3])&&n.push(new I(s,c,l,h,u))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.x1,e.y1);return this}function Kt(t){return t[0]}function Ut(t){return arguments.length?(this._x=t,this):this._x}function Vt(t){return t[1]}function tn(t){return arguments.length?(this._y=t,this):this._y}function ht(t,n,i){var e=new J(n??Kt,i??Vt,NaN,NaN,NaN,NaN);return t==null?e:e.addAll(t)}function J(t,n,i,e,r,s){this._x=t,this._y=n,this._x0=i,this._y0=e,this._x1=r,this._y1=s,this._root=void 0}function ot(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var b=ht.prototype=J.prototype;b.copy=function(){var t=new J(this._x,this._y,this._x0,this._y0,this._x1,this._y1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=ot(n),t;for(i=[{source:n,target:t._root=new Array(4)}];n=i.pop();)for(var r=0;r<4;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(4)}):n.target[r]=ot(e));return t},b.add=Rt,b.addAll=Xt,b.cover=Bt,b.data=Ct,b.extent=Lt,b.find=Yt,b.remove=Ht,b.removeAll=Qt,b.root=Wt,b.size=Zt,b.visit=Gt,b.visitAfter=Jt,b.x=Ut,b.y=tn;function nn(t){const n=+this._x.call(null,t),i=+this._y.call(null,t),e=+this._z.call(null,t);return ft(this.cover(n,i,e),n,i,e,t)}function ft(t,n,i,e,r){if(isNaN(n)||isNaN(i)||isNaN(e))return t;var s,a=t._root,o={data:r},h=t._x0,u=t._y0,c=t._z0,l=t._x1,v=t._y1,y=t._z1,_,N,p,f,d,w,g,x,M,z,A;if(!a)return t._root=o,t;for(;a.length;)if((g=n>=(_=(h+l)/2))?h=_:l=_,(x=i>=(N=(u+v)/2))?u=N:v=N,(M=e>=(p=(c+y)/2))?c=p:y=p,s=a,!(a=a[z=M<<2|x<<1|g]))return s[z]=o,t;if(f=+t._x.call(null,a.data),d=+t._y.call(null,a.data),w=+t._z.call(null,a.data),n===f&&i===d&&e===w)return o.next=a,s?s[z]=o:t._root=o,t;do s=s?s[z]=new Array(8):t._root=new Array(8),(g=n>=(_=(h+l)/2))?h=_:l=_,(x=i>=(N=(u+v)/2))?u=N:v=N,(M=e>=(p=(c+y)/2))?c=p:y=p;while((z=M<<2|x<<1|g)===(A=(w>=p)<<2|(d>=N)<<1|f>=_));return s[A]=a,s[z]=o,t}function en(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n),e=new Float64Array(n),r=new Float64Array(n);let s=1/0,a=1/0,o=1/0,h=-1/0,u=-1/0,c=-1/0;for(let l=0,v,y,_,N;l<n;++l)isNaN(y=+this._x.call(null,v=t[l]))||isNaN(_=+this._y.call(null,v))||isNaN(N=+this._z.call(null,v))||(i[l]=y,e[l]=_,r[l]=N,y<s&&(s=y),y>h&&(h=y),_<a&&(a=_),_>u&&(u=_),N<o&&(o=N),N>c&&(c=N));if(s>h||a>u||o>c)return this;this.cover(s,a,o).cover(h,u,c);for(let l=0;l<n;++l)ft(this,i[l],e[l],r[l],t[l]);return this}function rn(t,n,i){if(isNaN(t=+t)||isNaN(n=+n)||isNaN(i=+i))return this;var e=this._x0,r=this._y0,s=this._z0,a=this._x1,o=this._y1,h=this._z1;if(isNaN(e))a=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1,h=(s=Math.floor(i))+1;else{for(var u=a-e||1,c=this._root,l,v;e>t||t>=a||r>n||n>=o||s>i||i>=h;)switch(v=(i<s)<<2|(n<r)<<1|t<e,l=new Array(8),l[v]=c,c=l,u*=2,v){case 0:a=e+u,o=r+u,h=s+u;break;case 1:e=a-u,o=r+u,h=s+u;break;case 2:a=e+u,r=o-u,h=s+u;break;case 3:e=a-u,r=o-u,h=s+u;break;case 4:a=e+u,o=r+u,s=h-u;break;case 5:e=a-u,o=r+u,s=h-u;break;case 6:a=e+u,r=o-u,s=h-u;break;case 7:e=a-u,r=o-u,s=h-u;break}this._root&&this._root.length&&(this._root=c)}return this._x0=e,this._y0=r,this._z0=s,this._x1=a,this._y1=o,this._z1=h,this}function sn(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function an(t){return arguments.length?this.cover(+t[0][0],+t[0][1],+t[0][2]).cover(+t[1][0],+t[1][1],+t[1][2]):isNaN(this._x0)?void 0:[[this._x0,this._y0,this._z0],[this._x1,this._y1,this._z1]]}function $(t,n,i,e,r,s,a){this.node=t,this.x0=n,this.y0=i,this.z0=e,this.x1=r,this.y1=s,this.z1=a}function hn(t,n,i,e){var r,s=this._x0,a=this._y0,o=this._z0,h,u,c,l,v,y,_=this._x1,N=this._y1,p=this._z1,f=[],d=this._root,w,g;for(d&&f.push(new $(d,s,a,o,_,N,p)),e==null?e=1/0:(s=t-e,a=n-e,o=i-e,_=t+e,N=n+e,p=i+e,e*=e);w=f.pop();)if(!(!(d=w.node)||(h=w.x0)>_||(u=w.y0)>N||(c=w.z0)>p||(l=w.x1)<s||(v=w.y1)<a||(y=w.z1)<o))if(d.length){var x=(h+l)/2,M=(u+v)/2,z=(c+y)/2;f.push(new $(d[7],x,M,z,l,v,y),new $(d[6],h,M,z,x,v,y),new $(d[5],x,u,z,l,M,y),new $(d[4],h,u,z,x,M,y),new $(d[3],x,M,c,l,v,z),new $(d[2],h,M,c,x,v,z),new $(d[1],x,u,c,l,M,z),new $(d[0],h,u,c,x,M,z)),(g=(i>=z)<<2|(n>=M)<<1|t>=x)&&(w=f[f.length-1],f[f.length-1]=f[f.length-1-g],f[f.length-1-g]=w)}else{var A=t-+this._x.call(null,d.data),E=n-+this._y.call(null,d.data),T=i-+this._z.call(null,d.data),D=A*A+E*E+T*T;if(D<e){var m=Math.sqrt(e=D);s=t-m,a=n-m,o=i-m,_=t+m,N=n+m,p=i+m,r=d.data}}return r}const on=(t,n,i,e,r,s)=>Math.sqrt((t-e)**2+(n-r)**2+(i-s)**2);function fn(t,n,i,e){const r=[],s=t-e,a=n-e,o=i-e,h=t+e,u=n+e,c=i+e;return this.visit((l,v,y,_,N,p,f)=>{if(!l.length)do{const d=l.data;on(t,n,i,this._x(d),this._y(d),this._z(d))<=e&&r.push(d)}while(l=l.next);return v>h||y>u||_>c||N<s||p<a||f<o}),r}function un(t){if(isNaN(v=+this._x.call(null,t))||isNaN(y=+this._y.call(null,t))||isNaN(_=+this._z.call(null,t)))return this;var n,i=this._root,e,r,s,a=this._x0,o=this._y0,h=this._z0,u=this._x1,c=this._y1,l=this._z1,v,y,_,N,p,f,d,w,g,x,M;if(!i)return this;if(i.length)for(;;){if((d=v>=(N=(a+u)/2))?a=N:u=N,(w=y>=(p=(o+c)/2))?o=p:c=p,(g=_>=(f=(h+l)/2))?h=f:l=f,n=i,!(i=i[x=g<<2|w<<1|d]))return this;if(!i.length)break;(n[x+1&7]||n[x+2&7]||n[x+3&7]||n[x+4&7]||n[x+5&7]||n[x+6&7]||n[x+7&7])&&(e=n,M=x)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[x]=s:delete n[x],(i=n[0]||n[1]||n[2]||n[3]||n[4]||n[5]||n[6]||n[7])&&i===(n[7]||n[6]||n[5]||n[4]||n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[M]=i:this._root=i),this):(this._root=s,this)}function ln(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function cn(){return this._root}function _n(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function vn(t){var n=[],i,e=this._root,r,s,a,o,h,u,c;for(e&&n.push(new $(e,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));i=n.pop();)if(!t(e=i.node,s=i.x0,a=i.y0,o=i.z0,h=i.x1,u=i.y1,c=i.z1)&&e.length){var l=(s+h)/2,v=(a+u)/2,y=(o+c)/2;(r=e[7])&&n.push(new $(r,l,v,y,h,u,c)),(r=e[6])&&n.push(new $(r,s,v,y,l,u,c)),(r=e[5])&&n.push(new $(r,l,a,y,h,v,c)),(r=e[4])&&n.push(new $(r,s,a,y,l,v,c)),(r=e[3])&&n.push(new $(r,l,v,o,h,u,y)),(r=e[2])&&n.push(new $(r,s,v,o,l,u,y)),(r=e[1])&&n.push(new $(r,l,a,o,h,v,y)),(r=e[0])&&n.push(new $(r,s,a,o,l,v,y))}return this}function xn(t){var n=[],i=[],e;for(this._root&&n.push(new $(this._root,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));e=n.pop();){var r=e.node;if(r.length){var s,a=e.x0,o=e.y0,h=e.z0,u=e.x1,c=e.y1,l=e.z1,v=(a+u)/2,y=(o+c)/2,_=(h+l)/2;(s=r[0])&&n.push(new $(s,a,o,h,v,y,_)),(s=r[1])&&n.push(new $(s,v,o,h,u,y,_)),(s=r[2])&&n.push(new $(s,a,y,h,v,c,_)),(s=r[3])&&n.push(new $(s,v,y,h,u,c,_)),(s=r[4])&&n.push(new $(s,a,o,_,v,y,l)),(s=r[5])&&n.push(new $(s,v,o,_,u,y,l)),(s=r[6])&&n.push(new $(s,a,y,_,v,c,l)),(s=r[7])&&n.push(new $(s,v,y,_,u,c,l))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.z0,e.x1,e.y1,e.z1);return this}function yn(t){return t[0]}function pn(t){return arguments.length?(this._x=t,this):this._x}function gn(t){return t[1]}function wn(t){return arguments.length?(this._y=t,this):this._y}function dn(t){return t[2]}function Nn(t){return arguments.length?(this._z=t,this):this._z}function ut(t,n,i,e){var r=new K(n??yn,i??gn,e??dn,NaN,NaN,NaN,NaN,NaN,NaN);return t==null?r:r.addAll(t)}function K(t,n,i,e,r,s,a,o,h){this._x=t,this._y=n,this._z=i,this._x0=e,this._y0=r,this._z0=s,this._x1=a,this._y1=o,this._z1=h,this._root=void 0}function lt(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var q=ut.prototype=K.prototype;q.copy=function(){var t=new K(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=lt(n),t;for(i=[{source:n,target:t._root=new Array(8)}];n=i.pop();)for(var r=0;r<8;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(8)}):n.target[r]=lt(e));return t},q.add=nn,q.addAll=en,q.cover=rn,q.data=sn,q.extent=an,q.find=hn,q.findAllWithinRadius=fn,q.remove=un,q.removeAll=ln,q.root=cn,q.size=_n,q.visit=vn,q.visitAfter=xn,q.x=pn,q.y=wn,q.z=Nn;function R(t){return function(){return t}}function P(t){return(t()-.5)*1e-6}function Mn(t){return t.index}function ct(t,n){var i=t.get(n);if(!i)throw new Error("node not found: "+n);return i}function zn(t){var n=Mn,i=v,e,r=R(30),s,a,o,h,u,c,l=1;t==null&&(t=[]);function v(f){return 1/Math.min(h[f.source.index],h[f.target.index])}function y(f){for(var d=0,w=t.length;d<l;++d)for(var g=0,x,M,z,A=0,E=0,T=0,D,m;g<w;++g)x=t[g],M=x.source,z=x.target,A=z.x+z.vx-M.x-M.vx||P(c),o>1&&(E=z.y+z.vy-M.y-M.vy||P(c)),o>2&&(T=z.z+z.vz-M.z-M.vz||P(c)),D=Math.sqrt(A*A+E*E+T*T),D=(D-s[g])/D*f*e[g],A*=D,E*=D,T*=D,z.vx-=A*(m=u[g]),o>1&&(z.vy-=E*m),o>2&&(z.vz-=T*m),M.vx+=A*(m=1-m),o>1&&(M.vy+=E*m),o>2&&(M.vz+=T*m)}function _(){if(a){var f,d=a.length,w=t.length,g=new Map(a.map((M,z)=>[n(M,z,a),M])),x;for(f=0,h=new Array(d);f<w;++f)x=t[f],x.index=f,typeof x.source!="object"&&(x.source=ct(g,x.source)),typeof x.target!="object"&&(x.target=ct(g,x.target)),h[x.source.index]=(h[x.source.index]||0)+1,h[x.target.index]=(h[x.target.index]||0)+1;for(f=0,u=new Array(w);f<w;++f)x=t[f],u[f]=h[x.source.index]/(h[x.source.index]+h[x.target.index]);e=new Array(w),N(),s=new Array(w),p()}}function N(){if(a)for(var f=0,d=t.length;f<d;++f)e[f]=+i(t[f],f,t)}function p(){if(a)for(var f=0,d=t.length;f<d;++f)s[f]=+r(t[f],f,t)}return y.initialize=function(f,...d){a=f,c=d.find(w=>typeof w=="function")||Math.random,o=d.find(w=>[1,2,3].includes(w))||2,_()},y.links=function(f){return arguments.length?(t=f,_(),y):t},y.id=function(f){return arguments.length?(n=f,y):n},y.iterations=function(f){return arguments.length?(l=+f,y):l},y.strength=function(f){return arguments.length?(i=typeof f=="function"?f:R(+f),N(),y):i},y.distance=function(f){return arguments.length?(r=typeof f=="function"?f:R(+f),p(),y):r},y}var An={value:()=>{}};function _t(){for(var t=0,n=arguments.length,i={},e;t<n;++t){if(!(e=arguments[t]+"")||e in i||/[\\s.]/.test(e))throw new Error("illegal type: "+e);i[e]=[]}return new H(i)}function H(t){this._=t}function $n(t,n){return t.trim().split(/^|\\s+/).map(function(i){var e="",r=i.indexOf(".");if(r>=0&&(e=i.slice(r+1),i=i.slice(0,r)),i&&!n.hasOwnProperty(i))throw new Error("unknown type: "+i);return{type:i,name:e}})}H.prototype=_t.prototype={constructor:H,on:function(t,n){var i=this._,e=$n(t+"",i),r,s=-1,a=e.length;if(arguments.length<2){for(;++s<a;)if((r=(t=e[s]).type)&&(r=mn(i[r],t.name)))return r;return}if(n!=null&&typeof n!="function")throw new Error("invalid callback: "+n);for(;++s<a;)if(r=(t=e[s]).type)i[r]=vt(i[r],t.name,n);else if(n==null)for(r in i)i[r]=vt(i[r],t.name,null);return this},copy:function(){var t={},n=this._;for(var i in n)t[i]=n[i].slice();return new H(t)},call:function(t,n){if((r=arguments.length-2)>0)for(var i=new Array(r),e=0,r,s;e<r;++e)i[e]=arguments[e+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(s=this._[t],e=0,r=s.length;e<r;++e)s[e].value.apply(n,i)},apply:function(t,n,i){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var e=this._[t],r=0,s=e.length;r<s;++r)e[r].value.apply(n,i)}};function mn(t,n){for(var i=0,e=t.length,r;i<e;++i)if((r=t[i]).name===n)return r.value}function vt(t,n,i){for(var e=0,r=t.length;e<r;++e)if(t[e].name===n){t[e]=An,t=t.slice(0,e).concat(t.slice(e+1));break}return i!=null&&t.push({name:n,value:i}),t}var S=0,X=0,B=0,xt=1e3,Q,C,W=0,O=0,Z=0,L=typeof performance=="object"&&performance.now?performance:Date,yt=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function pt(){return O||(yt(qn),O=L.now()+Z)}function qn(){O=0}function U(){this._call=this._time=this._next=null}U.prototype=gt.prototype={constructor:U,restart:function(t,n,i){if(typeof t!="function")throw new TypeError("callback is not a function");i=(i==null?pt():+i)+(n==null?0:+n),!this._next&&C!==this&&(C?C._next=this:Q=this,C=this),this._call=t,this._time=i,V()},stop:function(){this._call&&(this._call=null,this._time=1/0,V())}};function gt(t,n,i){var e=new U;return e.restart(t,n,i),e}function In(){pt(),++S;for(var t=Q,n;t;)(n=O-t._time)>=0&&t._call.call(void 0,n),t=t._next;--S}function wt(){O=(W=L.now())+Z,S=X=0;try{In()}finally{S=0,kn(),O=0}}function bn(){var t=L.now(),n=t-W;n>xt&&(Z-=n,W=t)}function kn(){for(var t,n=Q,i,e=1/0;n;)n._call?(e>n._time&&(e=n._time),t=n,n=n._next):(i=n._next,n._next=null,n=t?t._next=i:Q=i);C=t,V(e)}function V(t){if(!S){X&&(X=clearTimeout(X));var n=t-O;n>24?(t<1/0&&(X=setTimeout(wt,t-L.now()-Z)),B&&(B=clearInterval(B))):(B||(W=L.now(),B=setInterval(bn,xt)),S=1,yt(wt))}}const Dn=1664525,En=1013904223,dt=4294967296;function Tn(){let t=1;return()=>(t=(Dn*t+En)%dt)/dt}var Nt=3;function tt(t){return t.x}function Mt(t){return t.y}function jn(t){return t.z}var Pn=10,Fn=Math.PI*(3-Math.sqrt(5)),On=Math.PI*20/(9+Math.sqrt(221));function Sn(t,n){n=n||2;var i=Math.min(Nt,Math.max(1,Math.round(n))),e,r=1,s=.001,a=1-Math.pow(s,1/300),o=0,h=.6,u=new Map,c=gt(y),l=_t("tick","end"),v=Tn();t==null&&(t=[]);function y(){_(),l.call("tick",e),r<s&&(c.stop(),l.call("end",e))}function _(f){var d,w=t.length,g;f===void 0&&(f=1);for(var x=0;x<f;++x)for(r+=(o-r)*a,u.forEach(function(M){M(r)}),d=0;d<w;++d)g=t[d],g.fx==null?g.x+=g.vx*=h:(g.x=g.fx,g.vx=0),i>1&&(g.fy==null?g.y+=g.vy*=h:(g.y=g.fy,g.vy=0)),i>2&&(g.fz==null?g.z+=g.vz*=h:(g.z=g.fz,g.vz=0));return e}function N(){for(var f=0,d=t.length,w;f<d;++f){if(w=t[f],w.index=f,w.fx!=null&&(w.x=w.fx),w.fy!=null&&(w.y=w.fy),w.fz!=null&&(w.z=w.fz),isNaN(w.x)||i>1&&isNaN(w.y)||i>2&&isNaN(w.z)){var g=Pn*(i>2?Math.cbrt(.5+f):i>1?Math.sqrt(.5+f):f),x=f*Fn,M=f*On;i===1?w.x=g:i===2?(w.x=g*Math.cos(x),w.y=g*Math.sin(x)):(w.x=g*Math.sin(x)*Math.cos(M),w.y=g*Math.cos(x),w.z=g*Math.sin(x)*Math.sin(M))}(isNaN(w.vx)||i>1&&isNaN(w.vy)||i>2&&isNaN(w.vz))&&(w.vx=0,i>1&&(w.vy=0),i>2&&(w.vz=0))}}function p(f){return f.initialize&&f.initialize(t,v,i),f}return N(),e={tick:_,restart:function(){return c.restart(y),e},stop:function(){return c.stop(),e},numDimensions:function(f){return arguments.length?(i=Math.min(Nt,Math.max(1,Math.round(f))),u.forEach(p),e):i},nodes:function(f){return arguments.length?(t=f,N(),u.forEach(p),e):t},alpha:function(f){return arguments.length?(r=+f,e):r},alphaMin:function(f){return arguments.length?(s=+f,e):s},alphaDecay:function(f){return arguments.length?(a=+f,e):+a},alphaTarget:function(f){return arguments.length?(o=+f,e):o},velocityDecay:function(f){return arguments.length?(h=1-f,e):1-h},randomSource:function(f){return arguments.length?(v=f,u.forEach(p),e):v},force:function(f,d){return arguments.length>1?(d==null?u.delete(f):u.set(f,p(d)),e):u.get(f)},find:function(){var f=Array.prototype.slice.call(arguments),d=f.shift()||0,w=(i>1?f.shift():null)||0,g=(i>2?f.shift():null)||0,x=f.shift()||1/0,M=0,z=t.length,A,E,T,D,m,zt;for(x*=x,M=0;M<z;++M)m=t[M],A=d-m.x,E=w-(m.y||0),T=g-(m.z||0),D=A*A+E*E+T*T,D<x&&(zt=m,x=D);return zt},on:function(f,d){return arguments.length>1?(l.on(f,d),e):l.on(f)}}}function Rn(){var t,n,i,e,r,s=R(-30),a,o=1,h=1/0,u=.81;function c(_){var N,p=t.length,f=(n===1?rt(t,tt):n===2?ht(t,tt,Mt):n===3?ut(t,tt,Mt,jn):null).visitAfter(v);for(r=_,N=0;N<p;++N)i=t[N],f.visit(y)}function l(){if(t){var _,N=t.length,p;for(a=new Array(N),_=0;_<N;++_)p=t[_],a[p.index]=+s(p,_,t)}}function v(_){var N=0,p,f,d=0,w,g,x,M,z=_.length;if(z){for(w=g=x=M=0;M<z;++M)(p=_[M])&&(f=Math.abs(p.value))&&(N+=p.value,d+=f,w+=f*(p.x||0),g+=f*(p.y||0),x+=f*(p.z||0));N*=Math.sqrt(4/z),_.x=w/d,n>1&&(_.y=g/d),n>2&&(_.z=x/d)}else{p=_,p.x=p.data.x,n>1&&(p.y=p.data.y),n>2&&(p.z=p.data.z);do N+=a[p.data.index];while(p=p.next)}_.value=N}function y(_,N,p,f,d){if(!_.value)return!0;var w=[p,f,d][n-1],g=_.x-i.x,x=n>1?_.y-i.y:0,M=n>2?_.z-i.z:0,z=w-N,A=g*g+x*x+M*M;if(z*z/u<A)return A<h&&(g===0&&(g=P(e),A+=g*g),n>1&&x===0&&(x=P(e),A+=x*x),n>2&&M===0&&(M=P(e),A+=M*M),A<o&&(A=Math.sqrt(o*A)),i.vx+=g*_.value*r/A,n>1&&(i.vy+=x*_.value*r/A),n>2&&(i.vz+=M*_.value*r/A)),!0;if(_.length||A>=h)return;(_.data!==i||_.next)&&(g===0&&(g=P(e),A+=g*g),n>1&&x===0&&(x=P(e),A+=x*x),n>2&&M===0&&(M=P(e),A+=M*M),A<o&&(A=Math.sqrt(o*A)));do _.data!==i&&(z=a[_.data.index]*r/A,i.vx+=g*z,n>1&&(i.vy+=x*z),n>2&&(i.vz+=M*z));while(_=_.next)}return c.initialize=function(_,...N){t=_,e=N.find(p=>typeof p=="function")||Math.random,n=N.find(p=>[1,2,3].includes(p))||2,l()},c.strength=function(_){return arguments.length?(s=typeof _=="function"?_:R(+_),l(),c):s},c.distanceMin=function(_){return arguments.length?(o=_*_,c):Math.sqrt(o)},c.distanceMax=function(_){return arguments.length?(h=_*_,c):Math.sqrt(h)},c.theta=function(_){return arguments.length?(u=_*_,c):Math.sqrt(u)},c}let F=null,Y=[],nt=0,it=!1;self.onmessage=t=>{const n=t.data;if(n.type==="init"){F&&F.stop(),it=!1,nt=0;const i=n.nodes.length,e=n.params,r=n.initialPositions??{};Y=n.nodes.map((a,o)=>{const h=r[a.id];if(h)return{id:a.id,index:o,x:h.x,y:h.y,z:h.z};const u=Math.random()*Math.PI*2,c=Math.acos(2*Math.random()-1),l=e.initialRadius*(.5+Math.random()*.5);return{id:a.id,index:o,x:l*Math.sin(c)*Math.cos(u),y:l*Math.sin(c)*Math.sin(u),z:l*Math.cos(c)}});const s=n.links.map(a=>({source:a.source,target:a.target}));F=Sn(Y,3).force("charge",Rn().strength(e.charge).distanceMax(e.distanceMax).theta(e.theta)).force("link",zn(s).id(a=>a.id).distance(e.linkDistance).strength(.2)).force("center",At()).alphaDecay(e.alphaDecay).velocityDecay(e.velocityDecay),F.on("tick",()=>{nt++;const a=F.alpha();if(nt%e.postEvery!==0&&a>e.settledThreshold)return;const o=new Float32Array(i*3);for(let h=0;h<i;h++)o[h*3]=Y[h].x||0,o[h*3+1]=Y[h].y||0,o[h*3+2]=Y[h].z||0;self.postMessage({type:"positions",positions:o.buffer,alpha:a},[o.buffer]),!it&&a<e.settledThreshold&&(it=!0,self.postMessage({type:"settled"}))})}n.type==="stop"&&F&&(F.stop(),F=null)}})();\n';
260
+ const WORKER_SOURCE = '(function(){"use strict";function At(t,n,i){var e,r=1;t==null&&(t=0),n==null&&(n=0),i==null&&(i=0);function s(){var o,u=e.length,h,f=0,l=0,c=0;for(o=0;o<u;++o)h=e[o],f+=h.x||0,l+=h.y||0,c+=h.z||0;for(f=(f/u-t)*r,l=(l/u-n)*r,c=(c/u-i)*r,o=0;o<u;++o)h=e[o],f&&(h.x-=f),l&&(h.y-=l),c&&(h.z-=c)}return s.initialize=function(o){e=o},s.x=function(o){return arguments.length?(t=+o,s):t},s.y=function(o){return arguments.length?(n=+o,s):n},s.z=function(o){return arguments.length?(i=+o,s):i},s.strength=function(o){return arguments.length?(r=+o,s):r},s}function $t(t){const n=+this._x.call(null,t);return et(this.cover(n),n,t)}function et(t,n,i){if(isNaN(n))return t;var e,r=t._root,s={data:i},o=t._x0,u=t._x1,h,f,l,c,v;if(!r)return t._root=s,t;for(;r.length;)if((l=n>=(h=(o+u)/2))?o=h:u=h,e=r,!(r=r[c=+l]))return e[c]=s,t;if(f=+t._x.call(null,r.data),n===f)return s.next=r,e?e[c]=s:t._root=s,t;do e=e?e[c]=new Array(2):t._root=new Array(2),(l=n>=(h=(o+u)/2))?o=h:u=h;while((c=+l)==(v=+(f>=h)));return e[v]=r,e[c]=s,t}function mt(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n);let e=1/0,r=-1/0;for(let s=0,o;s<n;++s)isNaN(o=+this._x.call(null,t[s]))||(i[s]=o,o<e&&(e=o),o>r&&(r=o));if(e>r)return this;this.cover(e).cover(r);for(let s=0;s<n;++s)et(this,i[s],t[s]);return this}function qt(t){if(isNaN(t=+t))return this;var n=this._x0,i=this._x1;if(isNaN(n))i=(n=Math.floor(t))+1;else{for(var e=i-n||1,r=this._root,s,o;n>t||t>=i;)switch(o=+(t<n),s=new Array(2),s[o]=r,r=s,e*=2,o){case 0:i=n+e;break;case 1:n=i-e;break}this._root&&this._root.length&&(this._root=r)}return this._x0=n,this._x1=i,this}function It(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function bt(t){return arguments.length?this.cover(+t[0][0]).cover(+t[1][0]):isNaN(this._x0)?void 0:[[this._x0],[this._x1]]}function P(t,n,i){this.node=t,this.x0=n,this.x1=i}function kt(t,n){var i,e=this._x0,r,s,o=this._x1,u=[],h=this._root,f,l;for(h&&u.push(new P(h,e,o)),n==null?n=1/0:(e=t-n,o=t+n);f=u.pop();)if(!(!(h=f.node)||(r=f.x0)>o||(s=f.x1)<e))if(h.length){var c=(r+s)/2;u.push(new P(h[1],c,s),new P(h[0],r,c)),(l=+(t>=c))&&(f=u[u.length-1],u[u.length-1]=u[u.length-1-l],u[u.length-1-l]=f)}else{var v=Math.abs(t-+this._x.call(null,h.data));v<n&&(n=v,e=t-v,o=t+v,i=h.data)}return i}function Dt(t){if(isNaN(h=+this._x.call(null,t)))return this;var n,i=this._root,e,r,s,o=this._x0,u=this._x1,h,f,l,c,v;if(!i)return this;if(i.length)for(;;){if((l=h>=(f=(o+u)/2))?o=f:u=f,n=i,!(i=i[c=+l]))return this;if(!i.length)break;n[c+1&1]&&(e=n,v=c)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[c]=s:delete n[c],(i=n[0]||n[1])&&i===(n[1]||n[0])&&!i.length&&(e?e[v]=i:this._root=i),this):(this._root=s,this)}function Et(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Tt(){return this._root}function jt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Pt(t){var n=[],i,e=this._root,r,s,o;for(e&&n.push(new P(e,this._x0,this._x1));i=n.pop();)if(!t(e=i.node,s=i.x0,o=i.x1)&&e.length){var u=(s+o)/2;(r=e[1])&&n.push(new P(r,u,o)),(r=e[0])&&n.push(new P(r,s,u))}return this}function Ft(t){var n=[],i=[],e;for(this._root&&n.push(new P(this._root,this._x0,this._x1));e=n.pop();){var r=e.node;if(r.length){var s,o=e.x0,u=e.x1,h=(o+u)/2;(s=r[0])&&n.push(new P(s,o,h)),(s=r[1])&&n.push(new P(s,h,u))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.x1);return this}function St(t){return t[0]}function Ot(t){return arguments.length?(this._x=t,this):this._x}function rt(t,n){var i=new G(n??St,NaN,NaN);return t==null?i:i.addAll(t)}function G(t,n,i){this._x=t,this._x0=n,this._x1=i,this._root=void 0}function st(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var k=rt.prototype=G.prototype;k.copy=function(){var t=new G(this._x,this._x0,this._x1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=st(n),t;for(i=[{source:n,target:t._root=new Array(2)}];n=i.pop();)for(var r=0;r<2;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(2)}):n.target[r]=st(e));return t},k.add=$t,k.addAll=mt,k.cover=qt,k.data=It,k.extent=bt,k.find=kt,k.remove=Dt,k.removeAll=Et,k.root=Tt,k.size=jt,k.visit=Pt,k.visitAfter=Ft,k.x=Ot;function Rt(t){const n=+this._x.call(null,t),i=+this._y.call(null,t);return ot(this.cover(n,i),n,i,t)}function ot(t,n,i,e){if(isNaN(n)||isNaN(i))return t;var r,s=t._root,o={data:e},u=t._x0,h=t._y0,f=t._x1,l=t._y1,c,v,y,_,g,x,a,N;if(!s)return t._root=o,t;for(;s.length;)if((g=n>=(c=(u+f)/2))?u=c:f=c,(x=i>=(v=(h+l)/2))?h=v:l=v,r=s,!(s=s[a=x<<1|g]))return r[a]=o,t;if(y=+t._x.call(null,s.data),_=+t._y.call(null,s.data),n===y&&i===_)return o.next=s,r?r[a]=o:t._root=o,t;do r=r?r[a]=new Array(4):t._root=new Array(4),(g=n>=(c=(u+f)/2))?u=c:f=c,(x=i>=(v=(h+l)/2))?h=v:l=v;while((a=x<<1|g)===(N=(_>=v)<<1|y>=c));return r[N]=s,r[a]=o,t}function Xt(t){var n,i,e=t.length,r,s,o=new Array(e),u=new Array(e),h=1/0,f=1/0,l=-1/0,c=-1/0;for(i=0;i<e;++i)isNaN(r=+this._x.call(null,n=t[i]))||isNaN(s=+this._y.call(null,n))||(o[i]=r,u[i]=s,r<h&&(h=r),r>l&&(l=r),s<f&&(f=s),s>c&&(c=s));if(h>l||f>c)return this;for(this.cover(h,f).cover(l,c),i=0;i<e;++i)ot(this,o[i],u[i],t[i]);return this}function Bt(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var i=this._x0,e=this._y0,r=this._x1,s=this._y1;if(isNaN(i))r=(i=Math.floor(t))+1,s=(e=Math.floor(n))+1;else{for(var o=r-i||1,u=this._root,h,f;i>t||t>=r||e>n||n>=s;)switch(f=(n<e)<<1|t<i,h=new Array(4),h[f]=u,u=h,o*=2,f){case 0:r=i+o,s=e+o;break;case 1:i=r-o,s=e+o;break;case 2:r=i+o,e=s-o;break;case 3:i=r-o,e=s-o;break}this._root&&this._root.length&&(this._root=u)}return this._x0=i,this._y0=e,this._x1=r,this._y1=s,this}function Ct(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function Lt(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function I(t,n,i,e,r){this.node=t,this.x0=n,this.y0=i,this.x1=e,this.y1=r}function Yt(t,n,i){var e,r=this._x0,s=this._y0,o,u,h,f,l=this._x1,c=this._y1,v=[],y=this._root,_,g;for(y&&v.push(new I(y,r,s,l,c)),i==null?i=1/0:(r=t-i,s=n-i,l=t+i,c=n+i,i*=i);_=v.pop();)if(!(!(y=_.node)||(o=_.x0)>l||(u=_.y0)>c||(h=_.x1)<r||(f=_.y1)<s))if(y.length){var x=(o+h)/2,a=(u+f)/2;v.push(new I(y[3],x,a,h,f),new I(y[2],o,a,x,f),new I(y[1],x,u,h,a),new I(y[0],o,u,x,a)),(g=(n>=a)<<1|t>=x)&&(_=v[v.length-1],v[v.length-1]=v[v.length-1-g],v[v.length-1-g]=_)}else{var N=t-+this._x.call(null,y.data),d=n-+this._y.call(null,y.data),w=N*N+d*d;if(w<i){var p=Math.sqrt(i=w);r=t-p,s=n-p,l=t+p,c=n+p,e=y.data}}return e}function Ht(t){if(isNaN(l=+this._x.call(null,t))||isNaN(c=+this._y.call(null,t)))return this;var n,i=this._root,e,r,s,o=this._x0,u=this._y0,h=this._x1,f=this._y1,l,c,v,y,_,g,x,a;if(!i)return this;if(i.length)for(;;){if((_=l>=(v=(o+h)/2))?o=v:h=v,(g=c>=(y=(u+f)/2))?u=y:f=y,n=i,!(i=i[x=g<<1|_]))return this;if(!i.length)break;(n[x+1&3]||n[x+2&3]||n[x+3&3])&&(e=n,a=x)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[x]=s:delete n[x],(i=n[0]||n[1]||n[2]||n[3])&&i===(n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[a]=i:this._root=i),this):(this._root=s,this)}function Qt(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function Wt(){return this._root}function Zt(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Gt(t){var n=[],i,e=this._root,r,s,o,u,h;for(e&&n.push(new I(e,this._x0,this._y0,this._x1,this._y1));i=n.pop();)if(!t(e=i.node,s=i.x0,o=i.y0,u=i.x1,h=i.y1)&&e.length){var f=(s+u)/2,l=(o+h)/2;(r=e[3])&&n.push(new I(r,f,l,u,h)),(r=e[2])&&n.push(new I(r,s,l,f,h)),(r=e[1])&&n.push(new I(r,f,o,u,l)),(r=e[0])&&n.push(new I(r,s,o,f,l))}return this}function Jt(t){var n=[],i=[],e;for(this._root&&n.push(new I(this._root,this._x0,this._y0,this._x1,this._y1));e=n.pop();){var r=e.node;if(r.length){var s,o=e.x0,u=e.y0,h=e.x1,f=e.y1,l=(o+h)/2,c=(u+f)/2;(s=r[0])&&n.push(new I(s,o,u,l,c)),(s=r[1])&&n.push(new I(s,l,u,h,c)),(s=r[2])&&n.push(new I(s,o,c,l,f)),(s=r[3])&&n.push(new I(s,l,c,h,f))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.x1,e.y1);return this}function Kt(t){return t[0]}function Ut(t){return arguments.length?(this._x=t,this):this._x}function Vt(t){return t[1]}function tn(t){return arguments.length?(this._y=t,this):this._y}function ht(t,n,i){var e=new J(n??Kt,i??Vt,NaN,NaN,NaN,NaN);return t==null?e:e.addAll(t)}function J(t,n,i,e,r,s){this._x=t,this._y=n,this._x0=i,this._y0=e,this._x1=r,this._y1=s,this._root=void 0}function at(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var b=ht.prototype=J.prototype;b.copy=function(){var t=new J(this._x,this._y,this._x0,this._y0,this._x1,this._y1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=at(n),t;for(i=[{source:n,target:t._root=new Array(4)}];n=i.pop();)for(var r=0;r<4;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(4)}):n.target[r]=at(e));return t},b.add=Rt,b.addAll=Xt,b.cover=Bt,b.data=Ct,b.extent=Lt,b.find=Yt,b.remove=Ht,b.removeAll=Qt,b.root=Wt,b.size=Zt,b.visit=Gt,b.visitAfter=Jt,b.x=Ut,b.y=tn;function nn(t){const n=+this._x.call(null,t),i=+this._y.call(null,t),e=+this._z.call(null,t);return ft(this.cover(n,i,e),n,i,e,t)}function ft(t,n,i,e,r){if(isNaN(n)||isNaN(i)||isNaN(e))return t;var s,o=t._root,u={data:r},h=t._x0,f=t._y0,l=t._z0,c=t._x1,v=t._y1,y=t._z1,_,g,x,a,N,d,w,p,M,z,A;if(!o)return t._root=u,t;for(;o.length;)if((w=n>=(_=(h+c)/2))?h=_:c=_,(p=i>=(g=(f+v)/2))?f=g:v=g,(M=e>=(x=(l+y)/2))?l=x:y=x,s=o,!(o=o[z=M<<2|p<<1|w]))return s[z]=u,t;if(a=+t._x.call(null,o.data),N=+t._y.call(null,o.data),d=+t._z.call(null,o.data),n===a&&i===N&&e===d)return u.next=o,s?s[z]=u:t._root=u,t;do s=s?s[z]=new Array(8):t._root=new Array(8),(w=n>=(_=(h+c)/2))?h=_:c=_,(p=i>=(g=(f+v)/2))?f=g:v=g,(M=e>=(x=(l+y)/2))?l=x:y=x;while((z=M<<2|p<<1|w)===(A=(d>=x)<<2|(N>=g)<<1|a>=_));return s[A]=o,s[z]=u,t}function en(t){Array.isArray(t)||(t=Array.from(t));const n=t.length,i=new Float64Array(n),e=new Float64Array(n),r=new Float64Array(n);let s=1/0,o=1/0,u=1/0,h=-1/0,f=-1/0,l=-1/0;for(let c=0,v,y,_,g;c<n;++c)isNaN(y=+this._x.call(null,v=t[c]))||isNaN(_=+this._y.call(null,v))||isNaN(g=+this._z.call(null,v))||(i[c]=y,e[c]=_,r[c]=g,y<s&&(s=y),y>h&&(h=y),_<o&&(o=_),_>f&&(f=_),g<u&&(u=g),g>l&&(l=g));if(s>h||o>f||u>l)return this;this.cover(s,o,u).cover(h,f,l);for(let c=0;c<n;++c)ft(this,i[c],e[c],r[c],t[c]);return this}function rn(t,n,i){if(isNaN(t=+t)||isNaN(n=+n)||isNaN(i=+i))return this;var e=this._x0,r=this._y0,s=this._z0,o=this._x1,u=this._y1,h=this._z1;if(isNaN(e))o=(e=Math.floor(t))+1,u=(r=Math.floor(n))+1,h=(s=Math.floor(i))+1;else{for(var f=o-e||1,l=this._root,c,v;e>t||t>=o||r>n||n>=u||s>i||i>=h;)switch(v=(i<s)<<2|(n<r)<<1|t<e,c=new Array(8),c[v]=l,l=c,f*=2,v){case 0:o=e+f,u=r+f,h=s+f;break;case 1:e=o-f,u=r+f,h=s+f;break;case 2:o=e+f,r=u-f,h=s+f;break;case 3:e=o-f,r=u-f,h=s+f;break;case 4:o=e+f,u=r+f,s=h-f;break;case 5:e=o-f,u=r+f,s=h-f;break;case 6:o=e+f,r=u-f,s=h-f;break;case 7:e=o-f,r=u-f,s=h-f;break}this._root&&this._root.length&&(this._root=l)}return this._x0=e,this._y0=r,this._z0=s,this._x1=o,this._y1=u,this._z1=h,this}function sn(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function on(t){return arguments.length?this.cover(+t[0][0],+t[0][1],+t[0][2]).cover(+t[1][0],+t[1][1],+t[1][2]):isNaN(this._x0)?void 0:[[this._x0,this._y0,this._z0],[this._x1,this._y1,this._z1]]}function $(t,n,i,e,r,s,o){this.node=t,this.x0=n,this.y0=i,this.z0=e,this.x1=r,this.y1=s,this.z1=o}function hn(t,n,i,e){var r,s=this._x0,o=this._y0,u=this._z0,h,f,l,c,v,y,_=this._x1,g=this._y1,x=this._z1,a=[],N=this._root,d,w;for(N&&a.push(new $(N,s,o,u,_,g,x)),e==null?e=1/0:(s=t-e,o=n-e,u=i-e,_=t+e,g=n+e,x=i+e,e*=e);d=a.pop();)if(!(!(N=d.node)||(h=d.x0)>_||(f=d.y0)>g||(l=d.z0)>x||(c=d.x1)<s||(v=d.y1)<o||(y=d.z1)<u))if(N.length){var p=(h+c)/2,M=(f+v)/2,z=(l+y)/2;a.push(new $(N[7],p,M,z,c,v,y),new $(N[6],h,M,z,p,v,y),new $(N[5],p,f,z,c,M,y),new $(N[4],h,f,z,p,M,y),new $(N[3],p,M,l,c,v,z),new $(N[2],h,M,l,p,v,z),new $(N[1],p,f,l,c,M,z),new $(N[0],h,f,l,p,M,z)),(w=(i>=z)<<2|(n>=M)<<1|t>=p)&&(d=a[a.length-1],a[a.length-1]=a[a.length-1-w],a[a.length-1-w]=d)}else{var A=t-+this._x.call(null,N.data),E=n-+this._y.call(null,N.data),T=i-+this._z.call(null,N.data),D=A*A+E*E+T*T;if(D<e){var m=Math.sqrt(e=D);s=t-m,o=n-m,u=i-m,_=t+m,g=n+m,x=i+m,r=N.data}}return r}const an=(t,n,i,e,r,s)=>Math.sqrt((t-e)**2+(n-r)**2+(i-s)**2);function fn(t,n,i,e){const r=[],s=t-e,o=n-e,u=i-e,h=t+e,f=n+e,l=i+e;return this.visit((c,v,y,_,g,x,a)=>{if(!c.length)do{const N=c.data;an(t,n,i,this._x(N),this._y(N),this._z(N))<=e&&r.push(N)}while(c=c.next);return v>h||y>f||_>l||g<s||x<o||a<u}),r}function un(t){if(isNaN(v=+this._x.call(null,t))||isNaN(y=+this._y.call(null,t))||isNaN(_=+this._z.call(null,t)))return this;var n,i=this._root,e,r,s,o=this._x0,u=this._y0,h=this._z0,f=this._x1,l=this._y1,c=this._z1,v,y,_,g,x,a,N,d,w,p,M;if(!i)return this;if(i.length)for(;;){if((N=v>=(g=(o+f)/2))?o=g:f=g,(d=y>=(x=(u+l)/2))?u=x:l=x,(w=_>=(a=(h+c)/2))?h=a:c=a,n=i,!(i=i[p=w<<2|d<<1|N]))return this;if(!i.length)break;(n[p+1&7]||n[p+2&7]||n[p+3&7]||n[p+4&7]||n[p+5&7]||n[p+6&7]||n[p+7&7])&&(e=n,M=p)}for(;i.data!==t;)if(r=i,!(i=i.next))return this;return(s=i.next)&&delete i.next,r?(s?r.next=s:delete r.next,this):n?(s?n[p]=s:delete n[p],(i=n[0]||n[1]||n[2]||n[3]||n[4]||n[5]||n[6]||n[7])&&i===(n[7]||n[6]||n[5]||n[4]||n[3]||n[2]||n[1]||n[0])&&!i.length&&(e?e[M]=i:this._root=i),this):(this._root=s,this)}function ln(t){for(var n=0,i=t.length;n<i;++n)this.remove(t[n]);return this}function cn(){return this._root}function _n(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function vn(t){var n=[],i,e=this._root,r,s,o,u,h,f,l;for(e&&n.push(new $(e,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));i=n.pop();)if(!t(e=i.node,s=i.x0,o=i.y0,u=i.z0,h=i.x1,f=i.y1,l=i.z1)&&e.length){var c=(s+h)/2,v=(o+f)/2,y=(u+l)/2;(r=e[7])&&n.push(new $(r,c,v,y,h,f,l)),(r=e[6])&&n.push(new $(r,s,v,y,c,f,l)),(r=e[5])&&n.push(new $(r,c,o,y,h,v,l)),(r=e[4])&&n.push(new $(r,s,o,y,c,v,l)),(r=e[3])&&n.push(new $(r,c,v,u,h,f,y)),(r=e[2])&&n.push(new $(r,s,v,u,c,f,y)),(r=e[1])&&n.push(new $(r,c,o,u,h,v,y)),(r=e[0])&&n.push(new $(r,s,o,u,c,v,y))}return this}function xn(t){var n=[],i=[],e;for(this._root&&n.push(new $(this._root,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1));e=n.pop();){var r=e.node;if(r.length){var s,o=e.x0,u=e.y0,h=e.z0,f=e.x1,l=e.y1,c=e.z1,v=(o+f)/2,y=(u+l)/2,_=(h+c)/2;(s=r[0])&&n.push(new $(s,o,u,h,v,y,_)),(s=r[1])&&n.push(new $(s,v,u,h,f,y,_)),(s=r[2])&&n.push(new $(s,o,y,h,v,l,_)),(s=r[3])&&n.push(new $(s,v,y,h,f,l,_)),(s=r[4])&&n.push(new $(s,o,u,_,v,y,c)),(s=r[5])&&n.push(new $(s,v,u,_,f,y,c)),(s=r[6])&&n.push(new $(s,o,y,_,v,l,c)),(s=r[7])&&n.push(new $(s,v,y,_,f,l,c))}i.push(e)}for(;e=i.pop();)t(e.node,e.x0,e.y0,e.z0,e.x1,e.y1,e.z1);return this}function yn(t){return t[0]}function pn(t){return arguments.length?(this._x=t,this):this._x}function gn(t){return t[1]}function wn(t){return arguments.length?(this._y=t,this):this._y}function dn(t){return t[2]}function Nn(t){return arguments.length?(this._z=t,this):this._z}function ut(t,n,i,e){var r=new K(n??yn,i??gn,e??dn,NaN,NaN,NaN,NaN,NaN,NaN);return t==null?r:r.addAll(t)}function K(t,n,i,e,r,s,o,u,h){this._x=t,this._y=n,this._z=i,this._x0=e,this._y0=r,this._z0=s,this._x1=o,this._y1=u,this._z1=h,this._root=void 0}function lt(t){for(var n={data:t.data},i=n;t=t.next;)i=i.next={data:t.data};return n}var q=ut.prototype=K.prototype;q.copy=function(){var t=new K(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),n=this._root,i,e;if(!n)return t;if(!n.length)return t._root=lt(n),t;for(i=[{source:n,target:t._root=new Array(8)}];n=i.pop();)for(var r=0;r<8;++r)(e=n.source[r])&&(e.length?i.push({source:e,target:n.target[r]=new Array(8)}):n.target[r]=lt(e));return t},q.add=nn,q.addAll=en,q.cover=rn,q.data=sn,q.extent=on,q.find=hn,q.findAllWithinRadius=fn,q.remove=un,q.removeAll=ln,q.root=cn,q.size=_n,q.visit=vn,q.visitAfter=xn,q.x=pn,q.y=wn,q.z=Nn;function X(t){return function(){return t}}function F(t){return(t()-.5)*1e-6}function Mn(t){return t.index}function ct(t,n){var i=t.get(n);if(!i)throw new Error("node not found: "+n);return i}function zn(t){var n=Mn,i=v,e,r=X(30),s,o,u,h,f,l,c=1;t==null&&(t=[]);function v(a){return 1/Math.min(h[a.source.index],h[a.target.index])}function y(a){for(var N=0,d=t.length;N<c;++N)for(var w=0,p,M,z,A=0,E=0,T=0,D,m;w<d;++w)p=t[w],M=p.source,z=p.target,A=z.x+z.vx-M.x-M.vx||F(l),u>1&&(E=z.y+z.vy-M.y-M.vy||F(l)),u>2&&(T=z.z+z.vz-M.z-M.vz||F(l)),D=Math.sqrt(A*A+E*E+T*T),D=(D-s[w])/D*a*e[w],A*=D,E*=D,T*=D,z.vx-=A*(m=f[w]),u>1&&(z.vy-=E*m),u>2&&(z.vz-=T*m),M.vx+=A*(m=1-m),u>1&&(M.vy+=E*m),u>2&&(M.vz+=T*m)}function _(){if(o){var a,N=o.length,d=t.length,w=new Map(o.map((M,z)=>[n(M,z,o),M])),p;for(a=0,h=new Array(N);a<d;++a)p=t[a],p.index=a,typeof p.source!="object"&&(p.source=ct(w,p.source)),typeof p.target!="object"&&(p.target=ct(w,p.target)),h[p.source.index]=(h[p.source.index]||0)+1,h[p.target.index]=(h[p.target.index]||0)+1;for(a=0,f=new Array(d);a<d;++a)p=t[a],f[a]=h[p.source.index]/(h[p.source.index]+h[p.target.index]);e=new Array(d),g(),s=new Array(d),x()}}function g(){if(o)for(var a=0,N=t.length;a<N;++a)e[a]=+i(t[a],a,t)}function x(){if(o)for(var a=0,N=t.length;a<N;++a)s[a]=+r(t[a],a,t)}return y.initialize=function(a,...N){o=a,l=N.find(d=>typeof d=="function")||Math.random,u=N.find(d=>[1,2,3].includes(d))||2,_()},y.links=function(a){return arguments.length?(t=a,_(),y):t},y.id=function(a){return arguments.length?(n=a,y):n},y.iterations=function(a){return arguments.length?(c=+a,y):c},y.strength=function(a){return arguments.length?(i=typeof a=="function"?a:X(+a),g(),y):i},y.distance=function(a){return arguments.length?(r=typeof a=="function"?a:X(+a),x(),y):r},y}var An={value:()=>{}};function _t(){for(var t=0,n=arguments.length,i={},e;t<n;++t){if(!(e=arguments[t]+"")||e in i||/[\\s.]/.test(e))throw new Error("illegal type: "+e);i[e]=[]}return new H(i)}function H(t){this._=t}function $n(t,n){return t.trim().split(/^|\\s+/).map(function(i){var e="",r=i.indexOf(".");if(r>=0&&(e=i.slice(r+1),i=i.slice(0,r)),i&&!n.hasOwnProperty(i))throw new Error("unknown type: "+i);return{type:i,name:e}})}H.prototype=_t.prototype={constructor:H,on:function(t,n){var i=this._,e=$n(t+"",i),r,s=-1,o=e.length;if(arguments.length<2){for(;++s<o;)if((r=(t=e[s]).type)&&(r=mn(i[r],t.name)))return r;return}if(n!=null&&typeof n!="function")throw new Error("invalid callback: "+n);for(;++s<o;)if(r=(t=e[s]).type)i[r]=vt(i[r],t.name,n);else if(n==null)for(r in i)i[r]=vt(i[r],t.name,null);return this},copy:function(){var t={},n=this._;for(var i in n)t[i]=n[i].slice();return new H(t)},call:function(t,n){if((r=arguments.length-2)>0)for(var i=new Array(r),e=0,r,s;e<r;++e)i[e]=arguments[e+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(s=this._[t],e=0,r=s.length;e<r;++e)s[e].value.apply(n,i)},apply:function(t,n,i){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var e=this._[t],r=0,s=e.length;r<s;++r)e[r].value.apply(n,i)}};function mn(t,n){for(var i=0,e=t.length,r;i<e;++i)if((r=t[i]).name===n)return r.value}function vt(t,n,i){for(var e=0,r=t.length;e<r;++e)if(t[e].name===n){t[e]=An,t=t.slice(0,e).concat(t.slice(e+1));break}return i!=null&&t.push({name:n,value:i}),t}var R=0,B=0,C=0,xt=1e3,Q,L,W=0,O=0,Z=0,Y=typeof performance=="object"&&performance.now?performance:Date,yt=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};function pt(){return O||(yt(qn),O=Y.now()+Z)}function qn(){O=0}function U(){this._call=this._time=this._next=null}U.prototype=gt.prototype={constructor:U,restart:function(t,n,i){if(typeof t!="function")throw new TypeError("callback is not a function");i=(i==null?pt():+i)+(n==null?0:+n),!this._next&&L!==this&&(L?L._next=this:Q=this,L=this),this._call=t,this._time=i,V()},stop:function(){this._call&&(this._call=null,this._time=1/0,V())}};function gt(t,n,i){var e=new U;return e.restart(t,n,i),e}function In(){pt(),++R;for(var t=Q,n;t;)(n=O-t._time)>=0&&t._call.call(void 0,n),t=t._next;--R}function wt(){O=(W=Y.now())+Z,R=B=0;try{In()}finally{R=0,kn(),O=0}}function bn(){var t=Y.now(),n=t-W;n>xt&&(Z-=n,W=t)}function kn(){for(var t,n=Q,i,e=1/0;n;)n._call?(e>n._time&&(e=n._time),t=n,n=n._next):(i=n._next,n._next=null,n=t?t._next=i:Q=i);L=t,V(e)}function V(t){if(!R){B&&(B=clearTimeout(B));var n=t-O;n>24?(t<1/0&&(B=setTimeout(wt,t-Y.now()-Z)),C&&(C=clearInterval(C))):(C||(W=Y.now(),C=setInterval(bn,xt)),R=1,yt(wt))}}const Dn=1664525,En=1013904223,dt=4294967296;function Tn(){let t=1;return()=>(t=(Dn*t+En)%dt)/dt}var Nt=3;function tt(t){return t.x}function Mt(t){return t.y}function jn(t){return t.z}var Pn=10,Fn=Math.PI*(3-Math.sqrt(5)),Sn=Math.PI*20/(9+Math.sqrt(221));function On(t,n){n=n||2;var i=Math.min(Nt,Math.max(1,Math.round(n))),e,r=1,s=.001,o=1-Math.pow(s,1/300),u=0,h=.6,f=new Map,l=gt(y),c=_t("tick","end"),v=Tn();t==null&&(t=[]);function y(){_(),c.call("tick",e),r<s&&(l.stop(),c.call("end",e))}function _(a){var N,d=t.length,w;a===void 0&&(a=1);for(var p=0;p<a;++p)for(r+=(u-r)*o,f.forEach(function(M){M(r)}),N=0;N<d;++N)w=t[N],w.fx==null?w.x+=w.vx*=h:(w.x=w.fx,w.vx=0),i>1&&(w.fy==null?w.y+=w.vy*=h:(w.y=w.fy,w.vy=0)),i>2&&(w.fz==null?w.z+=w.vz*=h:(w.z=w.fz,w.vz=0));return e}function g(){for(var a=0,N=t.length,d;a<N;++a){if(d=t[a],d.index=a,d.fx!=null&&(d.x=d.fx),d.fy!=null&&(d.y=d.fy),d.fz!=null&&(d.z=d.fz),isNaN(d.x)||i>1&&isNaN(d.y)||i>2&&isNaN(d.z)){var w=Pn*(i>2?Math.cbrt(.5+a):i>1?Math.sqrt(.5+a):a),p=a*Fn,M=a*Sn;i===1?d.x=w:i===2?(d.x=w*Math.cos(p),d.y=w*Math.sin(p)):(d.x=w*Math.sin(p)*Math.cos(M),d.y=w*Math.cos(p),d.z=w*Math.sin(p)*Math.sin(M))}(isNaN(d.vx)||i>1&&isNaN(d.vy)||i>2&&isNaN(d.vz))&&(d.vx=0,i>1&&(d.vy=0),i>2&&(d.vz=0))}}function x(a){return a.initialize&&a.initialize(t,v,i),a}return g(),e={tick:_,restart:function(){return l.restart(y),e},stop:function(){return l.stop(),e},numDimensions:function(a){return arguments.length?(i=Math.min(Nt,Math.max(1,Math.round(a))),f.forEach(x),e):i},nodes:function(a){return arguments.length?(t=a,g(),f.forEach(x),e):t},alpha:function(a){return arguments.length?(r=+a,e):r},alphaMin:function(a){return arguments.length?(s=+a,e):s},alphaDecay:function(a){return arguments.length?(o=+a,e):+o},alphaTarget:function(a){return arguments.length?(u=+a,e):u},velocityDecay:function(a){return arguments.length?(h=1-a,e):1-h},randomSource:function(a){return arguments.length?(v=a,f.forEach(x),e):v},force:function(a,N){return arguments.length>1?(N==null?f.delete(a):f.set(a,x(N)),e):f.get(a)},find:function(){var a=Array.prototype.slice.call(arguments),N=a.shift()||0,d=(i>1?a.shift():null)||0,w=(i>2?a.shift():null)||0,p=a.shift()||1/0,M=0,z=t.length,A,E,T,D,m,zt;for(p*=p,M=0;M<z;++M)m=t[M],A=N-m.x,E=d-(m.y||0),T=w-(m.z||0),D=A*A+E*E+T*T,D<p&&(zt=m,p=D);return zt},on:function(a,N){return arguments.length>1?(c.on(a,N),e):c.on(a)}}}function Rn(){var t,n,i,e,r,s=X(-30),o,u=1,h=1/0,f=.81;function l(_){var g,x=t.length,a=(n===1?rt(t,tt):n===2?ht(t,tt,Mt):n===3?ut(t,tt,Mt,jn):null).visitAfter(v);for(r=_,g=0;g<x;++g)i=t[g],a.visit(y)}function c(){if(t){var _,g=t.length,x;for(o=new Array(g),_=0;_<g;++_)x=t[_],o[x.index]=+s(x,_,t)}}function v(_){var g=0,x,a,N=0,d,w,p,M,z=_.length;if(z){for(d=w=p=M=0;M<z;++M)(x=_[M])&&(a=Math.abs(x.value))&&(g+=x.value,N+=a,d+=a*(x.x||0),w+=a*(x.y||0),p+=a*(x.z||0));g*=Math.sqrt(4/z),_.x=d/N,n>1&&(_.y=w/N),n>2&&(_.z=p/N)}else{x=_,x.x=x.data.x,n>1&&(x.y=x.data.y),n>2&&(x.z=x.data.z);do g+=o[x.data.index];while(x=x.next)}_.value=g}function y(_,g,x,a,N){if(!_.value)return!0;var d=[x,a,N][n-1],w=_.x-i.x,p=n>1?_.y-i.y:0,M=n>2?_.z-i.z:0,z=d-g,A=w*w+p*p+M*M;if(z*z/f<A)return A<h&&(w===0&&(w=F(e),A+=w*w),n>1&&p===0&&(p=F(e),A+=p*p),n>2&&M===0&&(M=F(e),A+=M*M),A<u&&(A=Math.sqrt(u*A)),i.vx+=w*_.value*r/A,n>1&&(i.vy+=p*_.value*r/A),n>2&&(i.vz+=M*_.value*r/A)),!0;if(_.length||A>=h)return;(_.data!==i||_.next)&&(w===0&&(w=F(e),A+=w*w),n>1&&p===0&&(p=F(e),A+=p*p),n>2&&M===0&&(M=F(e),A+=M*M),A<u&&(A=Math.sqrt(u*A)));do _.data!==i&&(z=o[_.data.index]*r/A,i.vx+=w*z,n>1&&(i.vy+=p*z),n>2&&(i.vz+=M*z));while(_=_.next)}return l.initialize=function(_,...g){t=_,e=g.find(x=>typeof x=="function")||Math.random,n=g.find(x=>[1,2,3].includes(x))||2,c()},l.strength=function(_){return arguments.length?(s=typeof _=="function"?_:X(+_),c(),l):s},l.distanceMin=function(_){return arguments.length?(u=_*_,l):Math.sqrt(u)},l.distanceMax=function(_){return arguments.length?(h=_*_,l):Math.sqrt(h)},l.theta=function(_){return arguments.length?(f=_*_,l):Math.sqrt(f)},l}let S=null,j=[],nt=0,it=!1;self.onmessage=t=>{const n=t.data;if(n.type==="init"){S&&S.stop(),it=!1,nt=0;const i=n.nodes.length,e=n.params,r=n.initialPositions??{},s=e.dimensions===2?2:3;j=n.nodes.map((h,f)=>{const l=r[h.id];if(l)return{id:h.id,index:f,x:l.x,y:l.y,z:s===2?0:l.z};const c=Math.random()*Math.PI*2,v=e.initialRadius*(.5+Math.random()*.5);if(s===2)return{id:h.id,index:f,x:v*Math.cos(c),y:v*Math.sin(c),z:0};const y=Math.acos(2*Math.random()-1);return{id:h.id,index:f,x:v*Math.sin(y)*Math.cos(c),y:v*Math.sin(y)*Math.sin(c),z:v*Math.cos(y)}});const o=n.links.map(h=>({source:h.source,target:h.target}));S=On(j,s).force("charge",Rn().strength(e.charge).distanceMax(e.distanceMax).theta(e.theta)).force("link",zn(o).id(h=>h.id).distance(e.linkDistance).strength(.2)).force("center",At()).alphaDecay(e.alphaDecay).velocityDecay(e.velocityDecay);const u=n.groups;if(u&&u.length===j.length&&e.clusterStrength>0){const h=e.clusterStrength;S.force("cluster",f=>{const l={},c={},v={},y={};for(let g=0;g<j.length;g++){const x=u[g];x<0||(l[x]=(l[x]??0)+j[g].x,c[x]=(c[x]??0)+j[g].y,v[x]=(v[x]??0)+(j[g].z||0),y[x]=(y[x]??0)+1)}const _=h*f;for(let g=0;g<j.length;g++){const x=u[g];if(x<0||!y[x])continue;const a=j[g];a.vx=(a.vx||0)+(l[x]/y[x]-a.x)*_,a.vy=(a.vy||0)+(c[x]/y[x]-a.y)*_,s===3&&(a.vz=(a.vz||0)+(v[x]/y[x]-a.z)*_)}})}S.on("tick",()=>{nt++;const h=S.alpha();if(nt%e.postEvery!==0&&h>e.settledThreshold)return;const f=new Float32Array(i*3);for(let l=0;l<i;l++)f[l*3]=j[l].x||0,f[l*3+1]=j[l].y||0,f[l*3+2]=s===2?0:j[l].z||0;self.postMessage({type:"positions",positions:f.buffer,alpha:h},[f.buffer]),!it&&h<e.settledThreshold&&(it=!0,self.postMessage({type:"settled"}))})}n.type==="stop"&&S&&(S.stop(),S=null)}})();\n';
208
261
  function createLayoutWorker() {
209
262
  const blob = new Blob([WORKER_SOURCE], { type: "application/javascript" });
210
263
  const url = URL.createObjectURL(blob);
@@ -1705,6 +1758,7 @@ function applyNodeHighlight(nodesMesh, nodes, selectedNodeId, highlightSet, them
1705
1758
  const nc = nodes.length;
1706
1759
  const tmpColor = new THREE.Color();
1707
1760
  const brightTmp = new THREE.Color();
1761
+ const bgColor = new THREE.Color(theme.backgroundColor);
1708
1762
  for (let i = 0; i < nc; i++) {
1709
1763
  const node = nodes[i];
1710
1764
  const baseColor = theme.nodeColor(node.type);
@@ -1712,13 +1766,17 @@ function applyNodeHighlight(nodesMesh, nodes, selectedNodeId, highlightSet, them
1712
1766
  if (!highlightSet) {
1713
1767
  tmpColor.set(baseColor);
1714
1768
  } else if (node.id === selectedNodeId) {
1715
- tmpColor.set(brightColor);
1716
- brightTmp.setRGB(1, 1, 1);
1717
- tmpColor.lerp(brightTmp, 0.65);
1718
- tmpColor.multiplyScalar(1.4);
1719
- tmpColor.r = Math.min(tmpColor.r, 2);
1720
- tmpColor.g = Math.min(tmpColor.g, 2);
1721
- tmpColor.b = Math.min(tmpColor.b, 2);
1769
+ if (theme.isLight) {
1770
+ tmpColor.set(brightColor);
1771
+ } else {
1772
+ tmpColor.set(brightColor);
1773
+ brightTmp.setRGB(1, 1, 1);
1774
+ tmpColor.lerp(brightTmp, 0.65);
1775
+ tmpColor.multiplyScalar(1.4);
1776
+ tmpColor.r = Math.min(tmpColor.r, 2);
1777
+ tmpColor.g = Math.min(tmpColor.g, 2);
1778
+ tmpColor.b = Math.min(tmpColor.b, 2);
1779
+ }
1722
1780
  } else if (highlightSet.has(node.id)) {
1723
1781
  const hop = highlightSet.get(node.id);
1724
1782
  if (hop === 1) {
@@ -1730,6 +1788,8 @@ function applyNodeHighlight(nodesMesh, nodes, selectedNodeId, highlightSet, them
1730
1788
  } else {
1731
1789
  tmpColor.set(baseColor).multiplyScalar(0.6);
1732
1790
  }
1791
+ } else if (theme.isLight) {
1792
+ tmpColor.set(baseColor).lerp(bgColor, 0.88);
1733
1793
  } else {
1734
1794
  tmpColor.set(baseColor).multiplyScalar(0.04);
1735
1795
  }
@@ -1747,6 +1807,7 @@ function applyEdgeHighlight(edgesMesh, links, edgeNodeIndices, edgeLinkIndices,
1747
1807
  const colorArr = colorAttr.array;
1748
1808
  const validCount = edgeNodeIndices.length;
1749
1809
  const tmpColor = new THREE.Color();
1810
+ const bgColor = new THREE.Color(theme.backgroundColor);
1750
1811
  for (let i = 0; i < validCount; i++) {
1751
1812
  const origIdx = edgeLinkIndices[i];
1752
1813
  const link = links[origIdx];
@@ -1758,13 +1819,19 @@ function applyEdgeHighlight(edgesMesh, links, edgeNodeIndices, edgeLinkIndices,
1758
1819
  const maxHopVal = Math.max(highlightSet.get(sId), highlightSet.get(tId));
1759
1820
  tmpColor.set(theme.linkColor(link == null ? void 0 : link.type));
1760
1821
  if (maxHopVal <= 1) {
1761
- tmpColor.multiplyScalar(1.8);
1762
- tmpColor.r = Math.min(tmpColor.r, 1);
1763
- tmpColor.g = Math.min(tmpColor.g, 1);
1764
- tmpColor.b = Math.min(tmpColor.b, 1);
1822
+ if (theme.isLight) {
1823
+ tmpColor.multiplyScalar(0.55);
1824
+ } else {
1825
+ tmpColor.multiplyScalar(1.8);
1826
+ tmpColor.r = Math.min(tmpColor.r, 1);
1827
+ tmpColor.g = Math.min(tmpColor.g, 1);
1828
+ tmpColor.b = Math.min(tmpColor.b, 1);
1829
+ }
1765
1830
  } else if (maxHopVal === 2) {
1766
- tmpColor.multiplyScalar(1.2);
1831
+ tmpColor.multiplyScalar(theme.isLight ? 0.8 : 1.2);
1767
1832
  }
1833
+ } else if (theme.isLight) {
1834
+ tmpColor.set(theme.linkColor(link == null ? void 0 : link.type)).lerp(bgColor, 0.85);
1768
1835
  } else {
1769
1836
  tmpColor.setRGB(0.01, 0.01, 0.02);
1770
1837
  }
@@ -1894,7 +1961,7 @@ function getOrCreateTexture(cache, nodeId, text, color) {
1894
1961
  }
1895
1962
  return entry;
1896
1963
  }
1897
- function updateLabels(state, nodes, positions, scales, camera, theme, showLabels, labelScale, labelThreshold, maxLabels, labelFormatter, highlightSet) {
1964
+ function updateLabels(state, nodes, positions, scales, camera, theme, showLabels, labelScale, labelThreshold, maxLabels, labelFormatter, highlightSet, hidden) {
1898
1965
  if (!positions || nodes.length === 0 || !showLabels) {
1899
1966
  for (const sp of state.sprites) sp.visible = false;
1900
1967
  return;
@@ -1908,6 +1975,7 @@ function updateLabels(state, nodes, positions, scales, camera, theme, showLabels
1908
1975
  const maxDistSq = maxDist * maxDist;
1909
1976
  const candidates = [];
1910
1977
  for (let i = 0; i < nc; i++) {
1978
+ if (hidden && hidden[i]) continue;
1911
1979
  if (highlightSet && !highlightSet.has(nodes[i].id)) continue;
1912
1980
  const dx = positions[i * 3] - camPos.x;
1913
1981
  const dy = positions[i * 3 + 1] - camPos.y;
@@ -1963,6 +2031,45 @@ const _right = new THREE.Vector3();
1963
2031
  const _q = new THREE.Quaternion();
1964
2032
  const _dir = new THREE.Vector3();
1965
2033
  const _worldUp = new THREE.Vector3(0, 1, 0);
2034
+ const PAN_SPEED = 0.02;
2035
+ const PAN_ZOOM_FACTOR = 0.02;
2036
+ function createPanUpdate(camera, controls, keys) {
2037
+ const _panRight = new THREE.Vector3();
2038
+ const _panUp = new THREE.Vector3();
2039
+ const _panOffset = new THREE.Vector3();
2040
+ return function update() {
2041
+ let dx = 0;
2042
+ let dy = 0;
2043
+ if (keys["ArrowLeft"] || keys["a"] || keys["A"]) dx -= 1;
2044
+ if (keys["ArrowRight"] || keys["d"] || keys["D"]) dx += 1;
2045
+ if (keys["ArrowUp"] || keys["w"] || keys["W"]) dy += 1;
2046
+ if (keys["ArrowDown"] || keys["s"] || keys["S"]) dy -= 1;
2047
+ const zoomIn = keys["z"] || keys["Z"] || keys["+"] || keys["="];
2048
+ const zoomOut = keys["x"] || keys["X"] || keys["-"] || keys["_"];
2049
+ if (!dx && !dy && !zoomIn && !zoomOut) return false;
2050
+ const target = controls.target;
2051
+ const dist = camera.position.distanceTo(target);
2052
+ if (dx || dy) {
2053
+ const step = Math.max(dist, 50) * PAN_SPEED;
2054
+ _panRight.setFromMatrixColumn(camera.matrix, 0);
2055
+ _panUp.setFromMatrixColumn(camera.matrix, 1);
2056
+ _panOffset.set(0, 0, 0).addScaledVector(_panRight, dx * step).addScaledVector(_panUp, dy * step);
2057
+ camera.position.add(_panOffset);
2058
+ target.add(_panOffset);
2059
+ }
2060
+ if (zoomIn || zoomOut) {
2061
+ const factor = zoomIn ? -PAN_ZOOM_FACTOR : PAN_ZOOM_FACTOR;
2062
+ _panOffset.copy(camera.position).sub(target);
2063
+ const newLen = Math.max(
2064
+ controls.minDistance,
2065
+ Math.min(controls.maxDistance, _panOffset.length() * (1 + factor))
2066
+ );
2067
+ _panOffset.setLength(newLen);
2068
+ camera.position.copy(target).add(_panOffset);
2069
+ }
2070
+ return true;
2071
+ };
2072
+ }
1966
2073
  function createOrbitUpdate(camera, controls, keys) {
1967
2074
  return function update() {
1968
2075
  let zoom = 0;
@@ -2061,7 +2168,14 @@ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpe
2061
2168
  container.addEventListener("keydown", onKeyDown2);
2062
2169
  container.addEventListener("keyup", onKeyUp);
2063
2170
  container.addEventListener("blur", onBlur);
2064
- const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys, state) : createOrbitUpdate(camera, controls, keys);
2171
+ let enabled = true;
2172
+ let currentMode = mode;
2173
+ const updaters = {
2174
+ fly: createFlyUpdate(camera, controls, keys, state),
2175
+ orbit: createOrbitUpdate(camera, controls, keys),
2176
+ pan: createPanUpdate(camera, controls, keys)
2177
+ };
2178
+ const updateFn = () => enabled ? updaters[currentMode]() : false;
2065
2179
  function cleanup() {
2066
2180
  container.removeEventListener("keydown", onKeyDown2);
2067
2181
  container.removeEventListener("keyup", onKeyUp);
@@ -2070,7 +2184,15 @@ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpe
2070
2184
  function setFlySpeed(speed) {
2071
2185
  state.flySpeed = speed;
2072
2186
  }
2073
- return { update: updateFn, cleanup, setFlySpeed };
2187
+ function setEnabled(on) {
2188
+ enabled = on;
2189
+ if (!on) for (const k of Object.keys(keys)) keys[k] = false;
2190
+ }
2191
+ function setMode(m2) {
2192
+ currentMode = m2;
2193
+ for (const k of Object.keys(keys)) keys[k] = false;
2194
+ }
2195
+ return { update: updateFn, cleanup, setFlySpeed, setEnabled, setMode };
2074
2196
  }
2075
2197
  function createScene(container, backgroundColor, style, rendererConfig) {
2076
2198
  const scene = new THREE.Scene();
@@ -2110,8 +2232,13 @@ function createScene(container, backgroundColor, style, rendererConfig) {
2110
2232
  const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
2111
2233
  const keyboard = setupKeyboardControls(camera, controls, container, cameraMode, style.flySpeed ?? 1);
2112
2234
  controls.enableZoom = false;
2235
+ const flags = {
2236
+ is2D: false,
2237
+ keyboardMode3D: cameraMode
2238
+ };
2113
2239
  const _wheelDir = new THREE.Vector3();
2114
2240
  const onWheel = (e) => {
2241
+ if (flags.is2D) return;
2115
2242
  e.preventDefault();
2116
2243
  let delta = -e.deltaY;
2117
2244
  if (e.deltaMode === 1) delta *= 40;
@@ -2135,9 +2262,41 @@ function createScene(container, backgroundColor, style, rendererConfig) {
2135
2262
  composer: null,
2136
2263
  bloomPass: null,
2137
2264
  keyboard,
2138
- scrollCleanup
2265
+ scrollCleanup,
2266
+ flags
2139
2267
  };
2140
2268
  }
2269
+ function applyCameraMode2D(state, is2D) {
2270
+ const { controls, camera, keyboard } = state;
2271
+ state.flags.is2D = is2D;
2272
+ controls.enableRotate = true;
2273
+ controls.enableZoom = is2D;
2274
+ controls.screenSpacePanning = is2D;
2275
+ keyboard.setEnabled(true);
2276
+ keyboard.setMode(is2D ? "pan" : state.flags.keyboardMode3D);
2277
+ if (is2D) {
2278
+ controls.mouseButtons = {
2279
+ LEFT: THREE.MOUSE.PAN,
2280
+ MIDDLE: THREE.MOUSE.DOLLY,
2281
+ RIGHT: THREE.MOUSE.ROTATE
2282
+ };
2283
+ controls.touches = { ONE: THREE.TOUCH.PAN, TWO: THREE.TOUCH.DOLLY_PAN };
2284
+ const t = controls.target;
2285
+ const dist = Math.max(camera.position.distanceTo(t), 50);
2286
+ t.z = 0;
2287
+ camera.up.set(0, 1, 0);
2288
+ camera.position.set(t.x, t.y, dist);
2289
+ camera.lookAt(t);
2290
+ } else {
2291
+ controls.mouseButtons = {
2292
+ LEFT: THREE.MOUSE.ROTATE,
2293
+ MIDDLE: THREE.MOUSE.DOLLY,
2294
+ RIGHT: THREE.MOUSE.PAN
2295
+ };
2296
+ controls.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN };
2297
+ }
2298
+ controls.update();
2299
+ }
2141
2300
  function initBloom(state, nodeCount, style) {
2142
2301
  if (state.composer) return;
2143
2302
  try {
@@ -2334,14 +2493,14 @@ function createNodeMesh(nodes, scales, theme) {
2334
2493
  mesh.computeBoundingSphere();
2335
2494
  return { mesh, material, scales };
2336
2495
  }
2337
- function updateNodePositions(mesh, positions, scales, nodeCount) {
2496
+ function updateNodePositions(mesh, positions, scales, nodeCount, hidden) {
2338
2497
  const pos = new THREE.Vector3();
2339
2498
  const scale = new THREE.Vector3();
2340
2499
  const quat = new THREE.Quaternion();
2341
2500
  const mat = new THREE.Matrix4();
2342
2501
  for (let i = 0; i < nodeCount; i++) {
2343
2502
  pos.set(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
2344
- const sc = scales[i];
2503
+ const sc = hidden && hidden[i] ? 1e-4 : scales[i];
2345
2504
  scale.set(sc, sc, sc);
2346
2505
  mat.compose(pos, quat, scale);
2347
2506
  mesh.setMatrixAt(i, mat);
@@ -2398,7 +2557,7 @@ function createEdgeMesh(links, edgeNodeIndices, edgeLinkIndices, nodeCount, edge
2398
2557
  transparent: true,
2399
2558
  opacity: adaptiveOpacity,
2400
2559
  depthWrite: false,
2401
- blending: THREE.AdditiveBlending
2560
+ blending: theme.additiveEdges ? THREE.AdditiveBlending : THREE.NormalBlending
2402
2561
  });
2403
2562
  const mesh = new THREE.LineSegments(geometry, material);
2404
2563
  return {
@@ -2410,10 +2569,19 @@ function createEdgeMesh(links, edgeNodeIndices, edgeLinkIndices, nodeCount, edge
2410
2569
  edgeLinkIndices
2411
2570
  };
2412
2571
  }
2413
- function updateEdgePositions(positionArray, nodePositions, edgeNodeIndices, geometry) {
2572
+ function updateEdgePositions(positionArray, nodePositions, edgeNodeIndices, geometry, hiddenEdges) {
2414
2573
  const count = edgeNodeIndices.length;
2415
2574
  for (let i = 0; i < count; i++) {
2416
2575
  const [si, ti] = edgeNodeIndices[i];
2576
+ if (hiddenEdges && hiddenEdges[i]) {
2577
+ positionArray[i * 6 + 0] = nodePositions[si * 3];
2578
+ positionArray[i * 6 + 1] = nodePositions[si * 3 + 1];
2579
+ positionArray[i * 6 + 2] = nodePositions[si * 3 + 2];
2580
+ positionArray[i * 6 + 3] = nodePositions[si * 3];
2581
+ positionArray[i * 6 + 4] = nodePositions[si * 3 + 1];
2582
+ positionArray[i * 6 + 5] = nodePositions[si * 3 + 2];
2583
+ continue;
2584
+ }
2417
2585
  positionArray[i * 6 + 0] = nodePositions[si * 3];
2418
2586
  positionArray[i * 6 + 1] = nodePositions[si * 3 + 1];
2419
2587
  positionArray[i * 6 + 2] = nodePositions[si * 3 + 2];
@@ -2476,7 +2644,7 @@ function zoomToFitPositions(camera, controls, positions, duration, padding) {
2476
2644
  );
2477
2645
  }
2478
2646
  const EDGE_HIT_THRESHOLD = 5;
2479
- function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, callbacks, container, getEdgeData) {
2647
+ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, callbacks, container, getEdgeData, options) {
2480
2648
  const raycaster = new THREE.Raycaster();
2481
2649
  const mouse = new THREE.Vector2();
2482
2650
  let mouseDownPos = null;
@@ -2488,11 +2656,12 @@ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, call
2488
2656
  const dragPlane = new THREE.Plane();
2489
2657
  const dragIntersect = new THREE.Vector3();
2490
2658
  function onPointerDown2(e) {
2659
+ var _a;
2491
2660
  mouseDownPos = { x: e.clientX, y: e.clientY };
2492
2661
  if (container && document.activeElement !== container) {
2493
2662
  container.focus({ preventScroll: true });
2494
2663
  }
2495
- if (callbacks.onNodeDrag) {
2664
+ if (callbacks.onNodeDrag && (((_a = options == null ? void 0 : options.getNodeDragEnabled) == null ? void 0 : _a.call(options)) ?? true)) {
2496
2665
  const nodesMesh = getNodesMesh();
2497
2666
  if (nodesMesh) {
2498
2667
  const rect = canvas.getBoundingClientRect();
@@ -2634,20 +2803,34 @@ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, call
2634
2803
  lastClickTime = now2;
2635
2804
  lastClickNodeId = node.id;
2636
2805
  singleClickTimer = setTimeout(() => {
2806
+ var _a2, _b;
2637
2807
  singleClickTimer = null;
2638
- const nx = node.x ?? 0;
2639
- const ny = node.y ?? 0;
2640
- const nz = node.z ?? 0;
2641
- const dist = Math.hypot(nx, ny, nz);
2642
- if (dist > 1) {
2643
- const ratio = 1 + 120 / dist;
2644
- animateCamera(
2645
- camera,
2646
- controls,
2647
- { x: nx * ratio, y: ny * ratio, z: nz * ratio },
2648
- { x: nx, y: ny, z: nz },
2649
- 1200
2650
- );
2808
+ const clickToFocus = ((_a2 = options == null ? void 0 : options.getClickToFocus) == null ? void 0 : _a2.call(options)) ?? true;
2809
+ if (clickToFocus) {
2810
+ const nx = node.x ?? 0;
2811
+ const ny = node.y ?? 0;
2812
+ const nz = node.z ?? 0;
2813
+ if ((_b = options == null ? void 0 : options.getIs2D) == null ? void 0 : _b.call(options)) {
2814
+ animateCamera(
2815
+ camera,
2816
+ controls,
2817
+ { x: nx, y: ny, z: camera.position.z },
2818
+ { x: nx, y: ny, z: 0 },
2819
+ 800
2820
+ );
2821
+ } else {
2822
+ const dist = Math.hypot(nx, ny, nz);
2823
+ if (dist > 1) {
2824
+ const ratio = 1 + 120 / dist;
2825
+ animateCamera(
2826
+ camera,
2827
+ controls,
2828
+ { x: nx * ratio, y: ny * ratio, z: nz * ratio },
2829
+ { x: nx, y: ny, z: nz },
2830
+ 1200
2831
+ );
2832
+ }
2833
+ }
2651
2834
  }
2652
2835
  callbacks.onNodeClick(node);
2653
2836
  }, 250);
@@ -2787,7 +2970,13 @@ function NetworkGraph3DInner(props, ref) {
2787
2970
  layout: layoutProp,
2788
2971
  renderer: rendererProp,
2789
2972
  labelFormatter,
2790
- nodeValueAccessor
2973
+ nodeValueAccessor,
2974
+ visibleNodeIds,
2975
+ linkVisibility,
2976
+ enableNodeDrag = true,
2977
+ clickToFocus = true,
2978
+ hoverHighlight = false,
2979
+ hoverHighlightHops = 1
2791
2980
  } = props;
2792
2981
  const containerRef = useRef(null);
2793
2982
  const resolvedStyle = useMemo(
@@ -2824,6 +3013,14 @@ function NetworkGraph3DInner(props, ref) {
2824
3013
  const selectedNodeIdRef = useRef(selectedNodeId);
2825
3014
  const labelFormatterRef = useRef(labelFormatter);
2826
3015
  const highlightSetRef = useRef(null);
3016
+ const clickToFocusRef = useRef(clickToFocus);
3017
+ const enableNodeDragRef = useRef(enableNodeDrag);
3018
+ const hoverHighlightRef = useRef(hoverHighlight);
3019
+ const hoverHighlightHopsRef = useRef(hoverHighlightHops);
3020
+ const adjacencyMapRef = useRef(/* @__PURE__ */ new Map());
3021
+ const is2DRef = useRef(false);
3022
+ const hiddenNodesRef = useRef(null);
3023
+ const hiddenEdgesRef = useRef(null);
2827
3024
  onNodeClickRef.current = onNodeClick;
2828
3025
  onNodeDoubleClickRef.current = onNodeDoubleClick;
2829
3026
  onNodeHoverRef.current = onNodeHover;
@@ -2838,6 +3035,15 @@ function NetworkGraph3DInner(props, ref) {
2838
3035
  themeRef.current = resolvedTheme;
2839
3036
  selectedNodeIdRef.current = selectedNodeId;
2840
3037
  labelFormatterRef.current = labelFormatter;
3038
+ clickToFocusRef.current = clickToFocus;
3039
+ enableNodeDragRef.current = enableNodeDrag;
3040
+ hoverHighlightRef.current = hoverHighlight;
3041
+ hoverHighlightHopsRef.current = hoverHighlightHops;
3042
+ const is2D = (layoutProp == null ? void 0 : layoutProp.dimensions) === 2;
3043
+ is2DRef.current = is2D;
3044
+ const layoutKey = JSON.stringify(layoutProp ?? null);
3045
+ const layoutRef = useRef(layoutProp);
3046
+ layoutRef.current = layoutProp;
2841
3047
  const mergedData = useMemo(() => {
2842
3048
  if (!appendedData) return data;
2843
3049
  const existingIds = new Set(data.nodes.map((n) => n.id));
@@ -2864,6 +3070,11 @@ function NetworkGraph3DInner(props, ref) {
2864
3070
  () => buildAdjacencyMapFromLinks(mergedData.links),
2865
3071
  [mergedData.links]
2866
3072
  );
3073
+ adjacencyMapRef.current = adjacencyMap;
3074
+ const visibleSet = useMemo(() => {
3075
+ if (visibleNodeIds == null) return null;
3076
+ return visibleNodeIds instanceof Set ? visibleNodeIds : new Set(visibleNodeIds);
3077
+ }, [visibleNodeIds]);
2867
3078
  const highlightSet = useMemo(() => {
2868
3079
  if (!selectedNodeId) return null;
2869
3080
  return computeHighlightSet(selectedNodeId, adjacencyMap, highlightHops);
@@ -2877,6 +3088,32 @@ function NetworkGraph3DInner(props, ref) {
2877
3088
  }
2878
3089
  return { min: isFinite(min) ? min : 1, max: isFinite(max) ? max : 1 };
2879
3090
  }, [mergedData.nodes, nodeValueAccessor]);
3091
+ const applyHoverHighlight = (node) => {
3092
+ if (!hoverHighlightRef.current) return;
3093
+ if (selectedNodeIdRef.current) return;
3094
+ const gObj = graphObjRef.current;
3095
+ if (!gObj) return;
3096
+ const d = dataRef.current;
3097
+ const set2 = node ? computeHighlightSet(
3098
+ node.id,
3099
+ adjacencyMapRef.current,
3100
+ hoverHighlightHopsRef.current
3101
+ ) : null;
3102
+ highlightSetRef.current = set2;
3103
+ applyNodeHighlight(gObj.nodesMesh, d.nodes, (node == null ? void 0 : node.id) ?? null, set2, themeRef.current);
3104
+ applyEdgeHighlight(
3105
+ gObj.edgesMesh,
3106
+ d.links,
3107
+ d.edgeNodeIndices,
3108
+ d.edgeLinkIndices,
3109
+ set2,
3110
+ styleRef.current.edgeOpacity,
3111
+ d.nodes.length,
3112
+ themeRef.current
3113
+ );
3114
+ };
3115
+ const applyHoverHighlightRef = useRef(applyHoverHighlight);
3116
+ applyHoverHighlightRef.current = applyHoverHighlight;
2880
3117
  useEffect(() => {
2881
3118
  const container = containerRef.current;
2882
3119
  if (!container) return;
@@ -2900,7 +3137,8 @@ function NetworkGraph3DInner(props, ref) {
2900
3137
  styleRef.current.labelThreshold,
2901
3138
  styleRef.current.maxLabels,
2902
3139
  labelFormatterRef.current,
2903
- highlightSetRef.current
3140
+ highlightSetRef.current,
3141
+ hiddenNodesRef.current
2904
3142
  );
2905
3143
  });
2906
3144
  const resizeObserver = setupResize(container, state);
@@ -2924,7 +3162,8 @@ function NetworkGraph3DInner(props, ref) {
2924
3162
  },
2925
3163
  onNodeHover: (node) => {
2926
3164
  var _a;
2927
- return (_a = onNodeHoverRef.current) == null ? void 0 : _a.call(onNodeHoverRef, node);
3165
+ (_a = onNodeHoverRef.current) == null ? void 0 : _a.call(onNodeHoverRef, node);
3166
+ applyHoverHighlightRef.current(node);
2928
3167
  },
2929
3168
  onContextMenu: (node, pos) => {
2930
3169
  var _a;
@@ -2940,6 +3179,7 @@ function NetworkGraph3DInner(props, ref) {
2940
3179
  },
2941
3180
  onNodeDrag: (node, pos) => {
2942
3181
  var _a;
3182
+ if (is2DRef.current) pos = { ...pos, z: 0 };
2943
3183
  (_a = onNodeDragRef.current) == null ? void 0 : _a.call(onNodeDragRef, node, pos);
2944
3184
  const d = dataRef.current;
2945
3185
  const idx = d.nodeIdToIndex.get(node.id);
@@ -2952,7 +3192,13 @@ function NetworkGraph3DInner(props, ref) {
2952
3192
  node.z = pos.z;
2953
3193
  const gObj = graphObjRef.current;
2954
3194
  if (gObj && d.scales) {
2955
- updateNodePositions(gObj.nodesMesh, d.positions, d.scales, d.nodes.length);
3195
+ updateNodePositions(
3196
+ gObj.nodesMesh,
3197
+ d.positions,
3198
+ d.scales,
3199
+ d.nodes.length,
3200
+ hiddenNodesRef.current
3201
+ );
2956
3202
  }
2957
3203
  }
2958
3204
  },
@@ -2970,6 +3216,11 @@ function NetworkGraph3DInner(props, ref) {
2970
3216
  edgeLinkIndices: d.edgeLinkIndices,
2971
3217
  positions: d.positions
2972
3218
  };
3219
+ },
3220
+ {
3221
+ getClickToFocus: () => clickToFocusRef.current,
3222
+ getIs2D: () => is2DRef.current,
3223
+ getNodeDragEnabled: () => enableNodeDragRef.current
2973
3224
  }
2974
3225
  );
2975
3226
  return () => {
@@ -3116,17 +3367,26 @@ function NetworkGraph3DInner(props, ref) {
3116
3367
  if (msg.type === "positions") {
3117
3368
  const positions = new Float32Array(msg.positions);
3118
3369
  dataRef.current.positions = positions;
3119
- updateNodePositions(nodesMesh, positions, scales, nc);
3370
+ const hn = hiddenNodesRef.current;
3371
+ updateNodePositions(
3372
+ nodesMesh,
3373
+ positions,
3374
+ scales,
3375
+ nc,
3376
+ hn && hn.length === nc ? hn : null
3377
+ );
3120
3378
  for (let i = 0; i < nc; i++) {
3121
3379
  nodes[i].x = positions[i * 3];
3122
3380
  nodes[i].y = positions[i * 3 + 1];
3123
3381
  nodes[i].z = positions[i * 3 + 2];
3124
3382
  }
3383
+ const he = hiddenEdgesRef.current;
3125
3384
  updateEdgePositions(
3126
3385
  edgeResult.positionArray,
3127
3386
  positions,
3128
3387
  edgeNodeIndices,
3129
- edgeResult.geometry
3388
+ edgeResult.geometry,
3389
+ he && he.length === edgeNodeIndices.length ? he : null
3130
3390
  );
3131
3391
  const selId = selectedNodeIdRef.current;
3132
3392
  if (selId && sceneState.selectionRing.visible) {
@@ -3146,7 +3406,20 @@ function NetworkGraph3DInner(props, ref) {
3146
3406
  (_b = onLayoutSettledRef.current) == null ? void 0 : _b.call(onLayoutSettledRef);
3147
3407
  }
3148
3408
  };
3149
- const layoutParams = resolveLayoutParams(nc, layoutProp);
3409
+ const layoutConfig = layoutRef.current;
3410
+ const layoutParams = resolveLayoutParams(nc, layoutConfig);
3411
+ let groups;
3412
+ if (layoutConfig == null ? void 0 : layoutConfig.clusterBy) {
3413
+ const keyOf = (n) => layoutConfig.clusterBy === "type" ? n.type : n.group;
3414
+ const keyToIdx = /* @__PURE__ */ new Map();
3415
+ groups = nodes.map((n) => {
3416
+ const k = keyOf(n);
3417
+ if (k == null) return -1;
3418
+ const ks = String(k);
3419
+ if (!keyToIdx.has(ks)) keyToIdx.set(ks, keyToIdx.size);
3420
+ return keyToIdx.get(ks);
3421
+ });
3422
+ }
3150
3423
  worker.postMessage({
3151
3424
  type: "init",
3152
3425
  nodes: nodes.map((n) => ({ id: n.id })),
@@ -3155,7 +3428,8 @@ function NetworkGraph3DInner(props, ref) {
3155
3428
  target: typeof l.target === "object" ? l.target.id : l.target
3156
3429
  })),
3157
3430
  params: layoutParams,
3158
- initialPositions: preservedPositionsRef.current
3431
+ initialPositions: preservedPositionsRef.current,
3432
+ groups
3159
3433
  });
3160
3434
  return () => {
3161
3435
  const d = dataRef.current;
@@ -3180,7 +3454,56 @@ function NetworkGraph3DInner(props, ref) {
3180
3454
  disposeObject(edgeResult.mesh);
3181
3455
  graphObjRef.current = null;
3182
3456
  };
3183
- }, [mergedData, valRange, nodeValueAccessor, layoutProp]);
3457
+ }, [mergedData, valRange, nodeValueAccessor, layoutKey]);
3458
+ useEffect(() => {
3459
+ const d = dataRef.current;
3460
+ const gObj = graphObjRef.current;
3461
+ if (!visibleSet && !linkVisibility) {
3462
+ hiddenNodesRef.current = null;
3463
+ hiddenEdgesRef.current = null;
3464
+ } else {
3465
+ const nc = d.nodes.length;
3466
+ const hn = new Uint8Array(nc);
3467
+ if (visibleSet) {
3468
+ for (let i = 0; i < nc; i++) {
3469
+ if (!visibleSet.has(d.nodes[i].id)) hn[i] = 1;
3470
+ }
3471
+ }
3472
+ const ec = d.edgeNodeIndices.length;
3473
+ const he = new Uint8Array(ec);
3474
+ for (let i = 0; i < ec; i++) {
3475
+ const [si, ti] = d.edgeNodeIndices[i];
3476
+ if (hn[si] || hn[ti]) {
3477
+ he[i] = 1;
3478
+ } else if (linkVisibility) {
3479
+ const link = d.links[d.edgeLinkIndices[i]];
3480
+ if (link && !linkVisibility(link)) he[i] = 1;
3481
+ }
3482
+ }
3483
+ hiddenNodesRef.current = visibleSet ? hn : null;
3484
+ hiddenEdgesRef.current = he;
3485
+ }
3486
+ if (gObj && d.positions && d.scales) {
3487
+ updateNodePositions(
3488
+ gObj.nodesMesh,
3489
+ d.positions,
3490
+ d.scales,
3491
+ d.nodes.length,
3492
+ hiddenNodesRef.current
3493
+ );
3494
+ updateEdgePositions(
3495
+ gObj.edgePositionArray,
3496
+ d.positions,
3497
+ d.edgeNodeIndices,
3498
+ gObj.edgeGeometry,
3499
+ hiddenEdgesRef.current
3500
+ );
3501
+ }
3502
+ }, [visibleSet, linkVisibility, mergedData]);
3503
+ useEffect(() => {
3504
+ const s = sceneRef.current;
3505
+ if (s) applyCameraMode2D(s, is2D);
3506
+ }, [is2D]);
3184
3507
  useEffect(() => {
3185
3508
  const gObj = graphObjRef.current;
3186
3509
  const sceneState = sceneRef.current;
@@ -3248,7 +3571,7 @@ function NetworkGraph3DInner(props, ref) {
3248
3571
  resolvedStyle.nodeMaxSize
3249
3572
  );
3250
3573
  dataRef.current.scales = newScales;
3251
- updateNodePositions(gObj.nodesMesh, positions, newScales, nc);
3574
+ updateNodePositions(gObj.nodesMesh, positions, newScales, nc, hiddenNodesRef.current);
3252
3575
  }, [resolvedStyle.nodeMinSize, resolvedStyle.nodeMaxSize, valRange]);
3253
3576
  useEffect(() => {
3254
3577
  const gObj = graphObjRef.current;
@@ -3337,6 +3660,17 @@ function NetworkGraph3DInner(props, ref) {
3337
3660
  const nx = d.positions[idx * 3];
3338
3661
  const ny = d.positions[idx * 3 + 1];
3339
3662
  const nz = d.positions[idx * 3 + 2];
3663
+ if (is2DRef.current) {
3664
+ const z2 = Math.max(120, Math.min(Math.abs(s.camera.position.z), 500));
3665
+ animateCamera(
3666
+ s.camera,
3667
+ s.controls,
3668
+ { x: nx, y: ny, z: z2 },
3669
+ { x: nx, y: ny, z: 0 },
3670
+ duration
3671
+ );
3672
+ return;
3673
+ }
3340
3674
  const dist = Math.hypot(nx, ny, nz);
3341
3675
  if (dist < 1) return;
3342
3676
  const ratio = 1 + 120 / dist;
@@ -3348,6 +3682,34 @@ function NetworkGraph3DInner(props, ref) {
3348
3682
  duration
3349
3683
  );
3350
3684
  },
3685
+ panTo(x2, y2, duration = 600) {
3686
+ const s = sceneRef.current;
3687
+ if (!s) return;
3688
+ const t = s.controls.target;
3689
+ if (is2DRef.current) {
3690
+ animateCamera(
3691
+ s.camera,
3692
+ s.controls,
3693
+ { x: x2, y: y2, z: s.camera.position.z },
3694
+ { x: x2, y: y2, z: 0 },
3695
+ duration
3696
+ );
3697
+ } else {
3698
+ const dx = x2 - t.x;
3699
+ const dy = y2 - t.y;
3700
+ animateCamera(
3701
+ s.camera,
3702
+ s.controls,
3703
+ {
3704
+ x: s.camera.position.x + dx,
3705
+ y: s.camera.position.y + dy,
3706
+ z: s.camera.position.z
3707
+ },
3708
+ { x: x2, y: y2, z: t.z },
3709
+ duration
3710
+ );
3711
+ }
3712
+ },
3351
3713
  appendData(newNodes, newLinks) {
3352
3714
  if (newNodes.length === 0 && newLinks.length === 0) return 0;
3353
3715
  const existingIds = new Set(dataRef.current.nodes.map((n) => n.id));
@@ -3376,6 +3738,32 @@ function NetworkGraph3DInner(props, ref) {
3376
3738
  s.renderer.render(s.scene, s.camera);
3377
3739
  return s.renderer.domElement.toDataURL("image/png");
3378
3740
  },
3741
+ getGraphSnapshot() {
3742
+ var _a;
3743
+ const gObj = graphObjRef.current;
3744
+ const d = dataRef.current;
3745
+ if (!gObj || !d.positions) return null;
3746
+ return {
3747
+ positions: d.positions,
3748
+ count: d.nodes.length,
3749
+ colors: ((_a = gObj.nodesMesh.instanceColor) == null ? void 0 : _a.array) ?? null,
3750
+ hidden: hiddenNodesRef.current,
3751
+ selectedIndex: selectedNodeIdRef.current ? d.nodeIdToIndex.get(selectedNodeIdRef.current) ?? -1 : -1
3752
+ };
3753
+ },
3754
+ getViewportRect() {
3755
+ const s = sceneRef.current;
3756
+ if (!s) return null;
3757
+ const cam = s.camera;
3758
+ const dist = Math.abs(cam.position.z);
3759
+ const halfH = Math.tan(cam.fov * Math.PI / 360) * dist;
3760
+ return {
3761
+ cx: cam.position.x,
3762
+ cy: cam.position.y,
3763
+ halfW: halfH * cam.aspect,
3764
+ halfH
3765
+ };
3766
+ },
3379
3767
  reheatLayout() {
3380
3768
  const gObj = graphObjRef.current;
3381
3769
  if (gObj == null ? void 0 : gObj.worker) {
@@ -3397,6 +3785,150 @@ function NetworkGraph3DInner(props, ref) {
3397
3785
  );
3398
3786
  }
3399
3787
  const NetworkGraph3D = forwardRef(NetworkGraph3DInner);
3788
+ function GraphMinimap({
3789
+ graphRef,
3790
+ width = 200,
3791
+ height = 140,
3792
+ backgroundColor,
3793
+ viewportColor = "#94a3b8",
3794
+ dotRadius = 1.5,
3795
+ fps = 15,
3796
+ padding = 0.08,
3797
+ className,
3798
+ style
3799
+ }) {
3800
+ const canvasRef = useRef(null);
3801
+ const fitRef = useRef(null);
3802
+ const draggingRef = useRef(false);
3803
+ useEffect(() => {
3804
+ const canvas = canvasRef.current;
3805
+ if (!canvas) return;
3806
+ const ctx = canvas.getContext("2d");
3807
+ if (!ctx) return;
3808
+ const dpr = Math.min(window.devicePixelRatio || 1, 2);
3809
+ canvas.width = width * dpr;
3810
+ canvas.height = height * dpr;
3811
+ let raf = 0;
3812
+ let last = 0;
3813
+ const interval2 = 1e3 / fps;
3814
+ const draw = (now2) => {
3815
+ var _a, _b;
3816
+ raf = requestAnimationFrame(draw);
3817
+ if (now2 - last < interval2) return;
3818
+ last = now2;
3819
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
3820
+ ctx.clearRect(0, 0, width, height);
3821
+ if (backgroundColor) {
3822
+ ctx.fillStyle = backgroundColor;
3823
+ ctx.fillRect(0, 0, width, height);
3824
+ }
3825
+ const snap = (_a = graphRef.current) == null ? void 0 : _a.getGraphSnapshot();
3826
+ if (!snap || snap.count === 0) {
3827
+ fitRef.current = null;
3828
+ return;
3829
+ }
3830
+ const { positions, count, colors, hidden, selectedIndex } = snap;
3831
+ let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
3832
+ for (let i = 0; i < count; i++) {
3833
+ if (hidden && hidden[i]) continue;
3834
+ const x2 = positions[i * 3];
3835
+ const y2 = positions[i * 3 + 1];
3836
+ if (x2 < minX) minX = x2;
3837
+ if (x2 > maxX) maxX = x2;
3838
+ if (y2 < minY) minY = y2;
3839
+ if (y2 > maxY) maxY = y2;
3840
+ }
3841
+ if (!isFinite(minX)) {
3842
+ fitRef.current = null;
3843
+ return;
3844
+ }
3845
+ const spanX = Math.max(maxX - minX, 1);
3846
+ const spanY = Math.max(maxY - minY, 1);
3847
+ const pad = Math.min(width, height) * padding;
3848
+ const scale = Math.min(
3849
+ (width - pad * 2) / spanX,
3850
+ (height - pad * 2) / spanY
3851
+ );
3852
+ const offsetX = width / 2 - (minX + maxX) / 2 * scale;
3853
+ const offsetY = height / 2 + (minY + maxY) / 2 * scale;
3854
+ fitRef.current = { scale, offsetX, offsetY };
3855
+ const r = dotRadius;
3856
+ for (let i = 0; i < count; i++) {
3857
+ if (hidden && hidden[i]) continue;
3858
+ const cx = positions[i * 3] * scale + offsetX;
3859
+ const cy = -positions[i * 3 + 1] * scale + offsetY;
3860
+ if (colors) {
3861
+ const cr = Math.min(255, Math.round(colors[i * 3] * 255));
3862
+ const cg = Math.min(255, Math.round(colors[i * 3 + 1] * 255));
3863
+ const cb = Math.min(255, Math.round(colors[i * 3 + 2] * 255));
3864
+ ctx.fillStyle = `rgb(${cr},${cg},${cb})`;
3865
+ } else {
3866
+ ctx.fillStyle = viewportColor;
3867
+ }
3868
+ const rad = i === selectedIndex ? r * 2 : r;
3869
+ ctx.beginPath();
3870
+ ctx.arc(cx, cy, rad, 0, Math.PI * 2);
3871
+ ctx.fill();
3872
+ }
3873
+ const vp = (_b = graphRef.current) == null ? void 0 : _b.getViewportRect();
3874
+ if (vp) {
3875
+ const x2 = (vp.cx - vp.halfW) * scale + offsetX;
3876
+ const y2 = -(vp.cy + vp.halfH) * scale + offsetY;
3877
+ const w = vp.halfW * 2 * scale;
3878
+ const h = vp.halfH * 2 * scale;
3879
+ ctx.strokeStyle = viewportColor;
3880
+ ctx.lineWidth = 1;
3881
+ ctx.strokeRect(x2, y2, w, h);
3882
+ ctx.fillStyle = viewportColor + "1a";
3883
+ ctx.fillRect(x2, y2, w, h);
3884
+ }
3885
+ };
3886
+ raf = requestAnimationFrame(draw);
3887
+ return () => cancelAnimationFrame(raf);
3888
+ }, [graphRef, width, height, backgroundColor, viewportColor, dotRadius, fps, padding]);
3889
+ const panToPointer = (e) => {
3890
+ var _a;
3891
+ const fit = fitRef.current;
3892
+ const canvas = canvasRef.current;
3893
+ if (!fit || !canvas) return;
3894
+ const rect = canvas.getBoundingClientRect();
3895
+ const px = e.clientX - rect.left;
3896
+ const py = e.clientY - rect.top;
3897
+ const wx = (px - fit.offsetX) / fit.scale;
3898
+ const wy = -(py - fit.offsetY) / fit.scale;
3899
+ (_a = graphRef.current) == null ? void 0 : _a.panTo(wx, wy, draggingRef.current ? 0 : 300);
3900
+ };
3901
+ return /* @__PURE__ */ jsx(
3902
+ "canvas",
3903
+ {
3904
+ ref: canvasRef,
3905
+ className,
3906
+ style: {
3907
+ width,
3908
+ height,
3909
+ cursor: "pointer",
3910
+ touchAction: "none",
3911
+ display: "block",
3912
+ ...style
3913
+ },
3914
+ onPointerDown: (e) => {
3915
+ draggingRef.current = true;
3916
+ e.currentTarget.setPointerCapture(e.pointerId);
3917
+ panToPointer(e);
3918
+ },
3919
+ onPointerMove: (e) => {
3920
+ if (draggingRef.current) panToPointer(e);
3921
+ },
3922
+ onPointerUp: (e) => {
3923
+ draggingRef.current = false;
3924
+ e.currentTarget.releasePointerCapture(e.pointerId);
3925
+ },
3926
+ onPointerCancel: () => {
3927
+ draggingRef.current = false;
3928
+ }
3929
+ }
3930
+ );
3931
+ }
3400
3932
  function forceCenter(x2, y2, z2) {
3401
3933
  var nodes, strength = 1;
3402
3934
  if (x2 == null) x2 = 0;
@@ -5465,6 +5997,7 @@ function CtrlBtn({ children, title, onClick }) {
5465
5997
  export {
5466
5998
  DEFAULT_LAYOUT,
5467
5999
  DEFAULT_STYLE,
6000
+ GraphMinimap,
5468
6001
  NetworkGraph3D,
5469
6002
  NodeDetailPanel,
5470
6003
  SubgraphView2D,
@@ -5475,6 +6008,7 @@ export {
5475
6008
  computeHighlightSet,
5476
6009
  minimal,
5477
6010
  neon,
6011
+ paper,
5478
6012
  resolveTheme,
5479
6013
  zoomToFitPositions
5480
6014
  };