@cocorof/graphier 1.1.1 → 1.2.0

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.cjs CHANGED
@@ -34,7 +34,8 @@ const DEFAULT_STYLE = {
34
34
  labelThreshold: 0.8,
35
35
  showLabels: true,
36
36
  maxLabels: 150,
37
- edgeWidthScale: 1
37
+ edgeWidthScale: 1,
38
+ flySpeed: 1
38
39
  };
39
40
  const DEFAULT_LAYOUT = {
40
41
  type: "force-3d",
@@ -42,7 +43,8 @@ const DEFAULT_LAYOUT = {
42
43
  linkDistance: "auto",
43
44
  alphaDecay: "auto",
44
45
  velocityDecay: 0.4,
45
- settledThreshold: 5e-3
46
+ settledThreshold: 5e-3,
47
+ spreadFactor: "auto"
46
48
  };
47
49
  function hexToRgb(hex) {
48
50
  const c2 = hex.replace("#", "");
@@ -188,17 +190,26 @@ function resolveTheme(theme) {
188
190
  }
189
191
  return { nodeColor, nodeColorBright, linkColor, backgroundColor };
190
192
  }
193
+ function autoSpreadFactor(n) {
194
+ if (n <= 500) return 1;
195
+ if (n <= 2e3) return 1 + (n - 500) / 1500 * 0.3;
196
+ if (n <= 1e4) return 1.3 + (n - 2e3) / 8e3 * 0.5;
197
+ return Math.min(2.5, 1.8 + (n - 1e4) / 4e4 * 0.7);
198
+ }
191
199
  function resolveLayoutParams(nodeCount, config) {
192
200
  const n = nodeCount;
193
- const charge = (config == null ? void 0 : config.charge) !== "auto" && (config == null ? void 0 : config.charge) != null ? config.charge : n > 5e4 ? -80 : n > 1e4 ? -120 : -200;
194
- const distanceMax = n > 5e4 ? 1500 : n > 1e4 ? 2e3 : 3e3;
201
+ const spread = (config == null ? void 0 : config.spreadFactor) !== "auto" && (config == null ? void 0 : config.spreadFactor) != null ? config.spreadFactor : autoSpreadFactor(n);
202
+ const baseCharge = (config == null ? void 0 : config.charge) !== "auto" && (config == null ? void 0 : config.charge) != null ? config.charge : n > 5e4 ? -80 : n > 1e4 ? -120 : -200;
203
+ const charge = baseCharge * spread;
204
+ const distanceMax = (n > 5e4 ? 1500 : n > 1e4 ? 2e3 : 3e3) * spread;
195
205
  const theta = n > 2e4 ? 1.5 : n > 5e3 ? 1.2 : 0.9;
196
- const linkDistance = (config == null ? void 0 : config.linkDistance) !== "auto" && (config == null ? void 0 : config.linkDistance) != null ? config.linkDistance : n > 5e4 ? 120 : n > 1e4 ? 180 : 250;
206
+ const baseLinkDistance = (config == null ? void 0 : config.linkDistance) !== "auto" && (config == null ? void 0 : config.linkDistance) != null ? config.linkDistance : n > 5e4 ? 120 : n > 1e4 ? 180 : 250;
207
+ const linkDistance = baseLinkDistance * spread;
197
208
  const alphaDecay = (config == null ? void 0 : config.alphaDecay) !== "auto" && (config == null ? void 0 : config.alphaDecay) != null ? config.alphaDecay : n > 5e4 ? 0.04 : n > 1e4 ? 0.03 : 0.02;
198
209
  const velocityDecay = (config == null ? void 0 : config.velocityDecay) ?? 0.4;
199
210
  const settledThreshold = (config == null ? void 0 : config.settledThreshold) ?? 5e-3;
200
211
  const postEvery = n > 5e4 ? 5 : n > 1e4 ? 3 : 2;
201
- const initialRadius2 = 500 + Math.min(n, 1e4) * 0.1;
212
+ const initialRadius2 = (500 + Math.min(n, 1e4) * 0.1) * spread;
202
213
  return {
203
214
  charge,
204
215
  distanceMax,
@@ -1975,6 +1986,7 @@ const _offset = new THREE__namespace.Vector3();
1975
1986
  const _right = new THREE__namespace.Vector3();
1976
1987
  const _q = new THREE__namespace.Quaternion();
1977
1988
  const _dir = new THREE__namespace.Vector3();
1989
+ const _worldUp = new THREE__namespace.Vector3(0, 1, 0);
1978
1990
  function clamp(v, min, max) {
1979
1991
  return v < min ? min : v > max ? max : v;
1980
1992
  }
@@ -2025,18 +2037,19 @@ function createOrbitUpdate(camera, controls, keys) {
2025
2037
  return true;
2026
2038
  };
2027
2039
  }
2028
- function createFlyUpdate(camera, controls, keys) {
2040
+ function createFlyUpdate(camera, controls, keys, state) {
2029
2041
  const vel = { thrust: 0, yaw: 0, pitch: 0 };
2030
2042
  return function update() {
2031
- if (keys["z"] || keys["Z"]) vel.thrust += FLY_ACCEL;
2032
- if (keys["x"] || keys["X"]) vel.thrust -= FLY_ACCEL;
2043
+ const speedMul = state.flySpeed;
2044
+ if (keys["z"] || keys["Z"]) vel.thrust += FLY_ACCEL * speedMul;
2045
+ if (keys["x"] || keys["X"]) vel.thrust -= FLY_ACCEL * speedMul;
2033
2046
  if (keys["a"] || keys["A"] || keys["ArrowLeft"]) vel.yaw += FLY_TURN_RATE;
2034
2047
  if (keys["d"] || keys["D"] || keys["ArrowRight"]) vel.yaw -= FLY_TURN_RATE;
2035
2048
  if (keys["w"] || keys["W"] || keys["ArrowUp"]) vel.pitch += FLY_TURN_RATE;
2036
2049
  if (keys["s"] || keys["S"] || keys["ArrowDown"]) vel.pitch -= FLY_TURN_RATE;
2037
2050
  const lookDist = camera.position.distanceTo(controls.target);
2038
2051
  const distScale = Math.max(0.3, lookDist * 3e-3);
2039
- vel.thrust = clamp(vel.thrust, -FLY_MAX_THRUST * distScale, FLY_MAX_THRUST * distScale);
2052
+ vel.thrust = clamp(vel.thrust, -FLY_MAX_THRUST * distScale * speedMul, FLY_MAX_THRUST * distScale * speedMul);
2040
2053
  vel.yaw = clamp(vel.yaw, -FLY_TURN_RATE * 2, FLY_TURN_RATE * 2);
2041
2054
  vel.pitch = clamp(vel.pitch, -FLY_TURN_RATE * 2, FLY_TURN_RATE * 2);
2042
2055
  vel.thrust *= FLY_FRICTION;
@@ -2048,13 +2061,17 @@ function createFlyUpdate(camera, controls, keys) {
2048
2061
  const hasMotion = vel.thrust !== 0 || vel.yaw !== 0 || vel.pitch !== 0;
2049
2062
  if (!hasMotion) return false;
2050
2063
  if (vel.yaw !== 0) {
2051
- _q.setFromAxisAngle(camera.up, vel.yaw);
2064
+ const upDot = camera.up.dot(_worldUp);
2065
+ const yawSign = upDot < 0 ? -1 : 1;
2066
+ _q.setFromAxisAngle(_worldUp, vel.yaw * yawSign);
2052
2067
  camera.quaternion.premultiply(_q);
2068
+ camera.up.applyQuaternion(_q).normalize();
2053
2069
  }
2054
2070
  if (vel.pitch !== 0) {
2055
2071
  _right.setFromMatrixColumn(camera.matrixWorld, 0).normalize();
2056
2072
  _q.setFromAxisAngle(_right, vel.pitch);
2057
2073
  camera.quaternion.premultiply(_q);
2074
+ camera.up.applyQuaternion(_q).normalize();
2058
2075
  }
2059
2076
  if (vel.thrust !== 0) {
2060
2077
  camera.getWorldDirection(_dir);
@@ -2065,8 +2082,9 @@ function createFlyUpdate(camera, controls, keys) {
2065
2082
  return true;
2066
2083
  };
2067
2084
  }
2068
- function setupKeyboardControls(camera, controls, container, mode = "fly") {
2085
+ function setupKeyboardControls(camera, controls, container, mode = "fly", flySpeed = 1) {
2069
2086
  const keys = {};
2087
+ const state = { flySpeed };
2070
2088
  function onKeyDown2(e) {
2071
2089
  var _a;
2072
2090
  const tag = (_a = e.target) == null ? void 0 : _a.tagName;
@@ -2082,13 +2100,16 @@ function setupKeyboardControls(camera, controls, container, mode = "fly") {
2082
2100
  container.addEventListener("keydown", onKeyDown2);
2083
2101
  container.addEventListener("keyup", onKeyUp);
2084
2102
  container.addEventListener("blur", onBlur);
2085
- const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys) : createOrbitUpdate(camera, controls, keys);
2103
+ const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys, state) : createOrbitUpdate(camera, controls, keys);
2086
2104
  function cleanup() {
2087
2105
  container.removeEventListener("keydown", onKeyDown2);
2088
2106
  container.removeEventListener("keyup", onKeyUp);
2089
2107
  container.removeEventListener("blur", onBlur);
2090
2108
  }
2091
- return { update: updateFn, cleanup };
2109
+ function setFlySpeed(speed) {
2110
+ state.flySpeed = speed;
2111
+ }
2112
+ return { update: updateFn, cleanup, setFlySpeed };
2092
2113
  }
2093
2114
  function createScene(container, backgroundColor, style, rendererConfig) {
2094
2115
  const scene = new THREE__namespace.Scene();
@@ -2126,7 +2147,7 @@ function createScene(container, backgroundColor, style, rendererConfig) {
2126
2147
  const labels = createLabelSystem(style.maxLabels);
2127
2148
  scene.add(labels.group);
2128
2149
  const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
2129
- const keyboard = setupKeyboardControls(camera, controls, container, cameraMode);
2150
+ const keyboard = setupKeyboardControls(camera, controls, container, cameraMode, style.flySpeed ?? 1);
2130
2151
  return {
2131
2152
  scene,
2132
2153
  camera,
@@ -3282,6 +3303,11 @@ function NetworkGraph3DInner(props, ref) {
3282
3303
  }, 30);
3283
3304
  return () => clearInterval(id);
3284
3305
  }, [resolvedStyle.autoOrbit]);
3306
+ react.useEffect(() => {
3307
+ const s = sceneRef.current;
3308
+ if (!s) return;
3309
+ s.keyboard.setFlySpeed(resolvedStyle.flySpeed);
3310
+ }, [resolvedStyle.flySpeed]);
3285
3311
  react.useImperativeHandle(ref, () => ({
3286
3312
  cameraPosition(pos, lookAt, duration = 1e3) {
3287
3313
  const s = sceneRef.current;
@@ -3359,6 +3385,16 @@ function NetworkGraph3DInner(props, ref) {
3359
3385
  if (!s) return null;
3360
3386
  s.renderer.render(s.scene, s.camera);
3361
3387
  return s.renderer.domElement.toDataURL("image/png");
3388
+ },
3389
+ reheatLayout() {
3390
+ const gObj = graphObjRef.current;
3391
+ if (gObj == null ? void 0 : gObj.worker) {
3392
+ gObj.worker.postMessage({ type: "stop" });
3393
+ gObj.worker.terminate();
3394
+ gObj.worker = null;
3395
+ }
3396
+ dataRef.current.settled = false;
3397
+ setAppendedData((prev) => prev ? { ...prev } : { nodes: [], links: [] });
3362
3398
  }
3363
3399
  }));
3364
3400
  return /* @__PURE__ */ jsxRuntime.jsx(