@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 +51 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +51 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -102,6 +102,13 @@ export declare interface LayoutConfig {
|
|
|
102
102
|
velocityDecay?: number;
|
|
103
103
|
/** Convergence threshold — simulation stops when alpha drops below this (default: 0.005) */
|
|
104
104
|
settledThreshold?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Spread multiplier — scales charge strength and link distance to control
|
|
107
|
+
* how far apart nodes spread. 1.0 = default, 2.0 = twice as spread out.
|
|
108
|
+
* Automatically scaled by node count when set to "auto".
|
|
109
|
+
* (default: "auto")
|
|
110
|
+
*/
|
|
111
|
+
spreadFactor?: "auto" | number;
|
|
105
112
|
}
|
|
106
113
|
|
|
107
114
|
/** Layout settled callback */
|
|
@@ -192,6 +199,8 @@ export declare interface NetworkGraph3DRef {
|
|
|
192
199
|
getCamera(): THREE.PerspectiveCamera | null;
|
|
193
200
|
/** Capture a screenshot as a PNG data URL string (synchronous, matches original) */
|
|
194
201
|
captureScreenshot(): string | null;
|
|
202
|
+
/** Re-run force layout from current positions (useful after changing spreadFactor) */
|
|
203
|
+
reheatLayout(): void;
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
export declare function NodeDetailPanel(props: NodeDetailPanelProps): JSX_2.Element;
|
|
@@ -286,6 +295,11 @@ export declare interface StyleConfig {
|
|
|
286
295
|
maxLabels?: number;
|
|
287
296
|
/** Edge line width multiplier (default: 1.0). Note: WebGL limits linewidth to 1 on most platforms. */
|
|
288
297
|
edgeWidthScale?: number;
|
|
298
|
+
/**
|
|
299
|
+
* Fly camera thrust speed multiplier (default: 1.0).
|
|
300
|
+
* 0.5 = half speed, 2.0 = double speed.
|
|
301
|
+
*/
|
|
302
|
+
flySpeed?: number;
|
|
289
303
|
}
|
|
290
304
|
|
|
291
305
|
export declare interface SubgraphOptions {
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,8 @@ const DEFAULT_STYLE = {
|
|
|
16
16
|
labelThreshold: 0.8,
|
|
17
17
|
showLabels: true,
|
|
18
18
|
maxLabels: 150,
|
|
19
|
-
edgeWidthScale: 1
|
|
19
|
+
edgeWidthScale: 1,
|
|
20
|
+
flySpeed: 1
|
|
20
21
|
};
|
|
21
22
|
const DEFAULT_LAYOUT = {
|
|
22
23
|
type: "force-3d",
|
|
@@ -24,7 +25,8 @@ const DEFAULT_LAYOUT = {
|
|
|
24
25
|
linkDistance: "auto",
|
|
25
26
|
alphaDecay: "auto",
|
|
26
27
|
velocityDecay: 0.4,
|
|
27
|
-
settledThreshold: 5e-3
|
|
28
|
+
settledThreshold: 5e-3,
|
|
29
|
+
spreadFactor: "auto"
|
|
28
30
|
};
|
|
29
31
|
function hexToRgb(hex) {
|
|
30
32
|
const c2 = hex.replace("#", "");
|
|
@@ -170,17 +172,26 @@ function resolveTheme(theme) {
|
|
|
170
172
|
}
|
|
171
173
|
return { nodeColor, nodeColorBright, linkColor, backgroundColor };
|
|
172
174
|
}
|
|
175
|
+
function autoSpreadFactor(n) {
|
|
176
|
+
if (n <= 500) return 1;
|
|
177
|
+
if (n <= 2e3) return 1 + (n - 500) / 1500 * 0.3;
|
|
178
|
+
if (n <= 1e4) return 1.3 + (n - 2e3) / 8e3 * 0.5;
|
|
179
|
+
return Math.min(2.5, 1.8 + (n - 1e4) / 4e4 * 0.7);
|
|
180
|
+
}
|
|
173
181
|
function resolveLayoutParams(nodeCount, config) {
|
|
174
182
|
const n = nodeCount;
|
|
175
|
-
const
|
|
176
|
-
const
|
|
183
|
+
const spread = (config == null ? void 0 : config.spreadFactor) !== "auto" && (config == null ? void 0 : config.spreadFactor) != null ? config.spreadFactor : autoSpreadFactor(n);
|
|
184
|
+
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;
|
|
185
|
+
const charge = baseCharge * spread;
|
|
186
|
+
const distanceMax = (n > 5e4 ? 1500 : n > 1e4 ? 2e3 : 3e3) * spread;
|
|
177
187
|
const theta = n > 2e4 ? 1.5 : n > 5e3 ? 1.2 : 0.9;
|
|
178
|
-
const
|
|
188
|
+
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;
|
|
189
|
+
const linkDistance = baseLinkDistance * spread;
|
|
179
190
|
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;
|
|
180
191
|
const velocityDecay = (config == null ? void 0 : config.velocityDecay) ?? 0.4;
|
|
181
192
|
const settledThreshold = (config == null ? void 0 : config.settledThreshold) ?? 5e-3;
|
|
182
193
|
const postEvery = n > 5e4 ? 5 : n > 1e4 ? 3 : 2;
|
|
183
|
-
const initialRadius2 = 500 + Math.min(n, 1e4) * 0.1;
|
|
194
|
+
const initialRadius2 = (500 + Math.min(n, 1e4) * 0.1) * spread;
|
|
184
195
|
return {
|
|
185
196
|
charge,
|
|
186
197
|
distanceMax,
|
|
@@ -1957,6 +1968,7 @@ const _offset = new THREE.Vector3();
|
|
|
1957
1968
|
const _right = new THREE.Vector3();
|
|
1958
1969
|
const _q = new THREE.Quaternion();
|
|
1959
1970
|
const _dir = new THREE.Vector3();
|
|
1971
|
+
const _worldUp = new THREE.Vector3(0, 1, 0);
|
|
1960
1972
|
function clamp(v, min, max) {
|
|
1961
1973
|
return v < min ? min : v > max ? max : v;
|
|
1962
1974
|
}
|
|
@@ -2007,18 +2019,19 @@ function createOrbitUpdate(camera, controls, keys) {
|
|
|
2007
2019
|
return true;
|
|
2008
2020
|
};
|
|
2009
2021
|
}
|
|
2010
|
-
function createFlyUpdate(camera, controls, keys) {
|
|
2022
|
+
function createFlyUpdate(camera, controls, keys, state) {
|
|
2011
2023
|
const vel = { thrust: 0, yaw: 0, pitch: 0 };
|
|
2012
2024
|
return function update() {
|
|
2013
|
-
|
|
2014
|
-
if (keys["
|
|
2025
|
+
const speedMul = state.flySpeed;
|
|
2026
|
+
if (keys["z"] || keys["Z"]) vel.thrust += FLY_ACCEL * speedMul;
|
|
2027
|
+
if (keys["x"] || keys["X"]) vel.thrust -= FLY_ACCEL * speedMul;
|
|
2015
2028
|
if (keys["a"] || keys["A"] || keys["ArrowLeft"]) vel.yaw += FLY_TURN_RATE;
|
|
2016
2029
|
if (keys["d"] || keys["D"] || keys["ArrowRight"]) vel.yaw -= FLY_TURN_RATE;
|
|
2017
2030
|
if (keys["w"] || keys["W"] || keys["ArrowUp"]) vel.pitch += FLY_TURN_RATE;
|
|
2018
2031
|
if (keys["s"] || keys["S"] || keys["ArrowDown"]) vel.pitch -= FLY_TURN_RATE;
|
|
2019
2032
|
const lookDist = camera.position.distanceTo(controls.target);
|
|
2020
2033
|
const distScale = Math.max(0.3, lookDist * 3e-3);
|
|
2021
|
-
vel.thrust = clamp(vel.thrust, -FLY_MAX_THRUST * distScale, FLY_MAX_THRUST * distScale);
|
|
2034
|
+
vel.thrust = clamp(vel.thrust, -FLY_MAX_THRUST * distScale * speedMul, FLY_MAX_THRUST * distScale * speedMul);
|
|
2022
2035
|
vel.yaw = clamp(vel.yaw, -FLY_TURN_RATE * 2, FLY_TURN_RATE * 2);
|
|
2023
2036
|
vel.pitch = clamp(vel.pitch, -FLY_TURN_RATE * 2, FLY_TURN_RATE * 2);
|
|
2024
2037
|
vel.thrust *= FLY_FRICTION;
|
|
@@ -2030,13 +2043,17 @@ function createFlyUpdate(camera, controls, keys) {
|
|
|
2030
2043
|
const hasMotion = vel.thrust !== 0 || vel.yaw !== 0 || vel.pitch !== 0;
|
|
2031
2044
|
if (!hasMotion) return false;
|
|
2032
2045
|
if (vel.yaw !== 0) {
|
|
2033
|
-
|
|
2046
|
+
const upDot = camera.up.dot(_worldUp);
|
|
2047
|
+
const yawSign = upDot < 0 ? -1 : 1;
|
|
2048
|
+
_q.setFromAxisAngle(_worldUp, vel.yaw * yawSign);
|
|
2034
2049
|
camera.quaternion.premultiply(_q);
|
|
2050
|
+
camera.up.applyQuaternion(_q).normalize();
|
|
2035
2051
|
}
|
|
2036
2052
|
if (vel.pitch !== 0) {
|
|
2037
2053
|
_right.setFromMatrixColumn(camera.matrixWorld, 0).normalize();
|
|
2038
2054
|
_q.setFromAxisAngle(_right, vel.pitch);
|
|
2039
2055
|
camera.quaternion.premultiply(_q);
|
|
2056
|
+
camera.up.applyQuaternion(_q).normalize();
|
|
2040
2057
|
}
|
|
2041
2058
|
if (vel.thrust !== 0) {
|
|
2042
2059
|
camera.getWorldDirection(_dir);
|
|
@@ -2047,8 +2064,9 @@ function createFlyUpdate(camera, controls, keys) {
|
|
|
2047
2064
|
return true;
|
|
2048
2065
|
};
|
|
2049
2066
|
}
|
|
2050
|
-
function setupKeyboardControls(camera, controls, container, mode = "fly") {
|
|
2067
|
+
function setupKeyboardControls(camera, controls, container, mode = "fly", flySpeed = 1) {
|
|
2051
2068
|
const keys = {};
|
|
2069
|
+
const state = { flySpeed };
|
|
2052
2070
|
function onKeyDown2(e) {
|
|
2053
2071
|
var _a;
|
|
2054
2072
|
const tag = (_a = e.target) == null ? void 0 : _a.tagName;
|
|
@@ -2064,13 +2082,16 @@ function setupKeyboardControls(camera, controls, container, mode = "fly") {
|
|
|
2064
2082
|
container.addEventListener("keydown", onKeyDown2);
|
|
2065
2083
|
container.addEventListener("keyup", onKeyUp);
|
|
2066
2084
|
container.addEventListener("blur", onBlur);
|
|
2067
|
-
const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys) : createOrbitUpdate(camera, controls, keys);
|
|
2085
|
+
const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys, state) : createOrbitUpdate(camera, controls, keys);
|
|
2068
2086
|
function cleanup() {
|
|
2069
2087
|
container.removeEventListener("keydown", onKeyDown2);
|
|
2070
2088
|
container.removeEventListener("keyup", onKeyUp);
|
|
2071
2089
|
container.removeEventListener("blur", onBlur);
|
|
2072
2090
|
}
|
|
2073
|
-
|
|
2091
|
+
function setFlySpeed(speed) {
|
|
2092
|
+
state.flySpeed = speed;
|
|
2093
|
+
}
|
|
2094
|
+
return { update: updateFn, cleanup, setFlySpeed };
|
|
2074
2095
|
}
|
|
2075
2096
|
function createScene(container, backgroundColor, style, rendererConfig) {
|
|
2076
2097
|
const scene = new THREE.Scene();
|
|
@@ -2108,7 +2129,7 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2108
2129
|
const labels = createLabelSystem(style.maxLabels);
|
|
2109
2130
|
scene.add(labels.group);
|
|
2110
2131
|
const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
|
|
2111
|
-
const keyboard = setupKeyboardControls(camera, controls, container, cameraMode);
|
|
2132
|
+
const keyboard = setupKeyboardControls(camera, controls, container, cameraMode, style.flySpeed ?? 1);
|
|
2112
2133
|
return {
|
|
2113
2134
|
scene,
|
|
2114
2135
|
camera,
|
|
@@ -3264,6 +3285,11 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3264
3285
|
}, 30);
|
|
3265
3286
|
return () => clearInterval(id);
|
|
3266
3287
|
}, [resolvedStyle.autoOrbit]);
|
|
3288
|
+
useEffect(() => {
|
|
3289
|
+
const s = sceneRef.current;
|
|
3290
|
+
if (!s) return;
|
|
3291
|
+
s.keyboard.setFlySpeed(resolvedStyle.flySpeed);
|
|
3292
|
+
}, [resolvedStyle.flySpeed]);
|
|
3267
3293
|
useImperativeHandle(ref, () => ({
|
|
3268
3294
|
cameraPosition(pos, lookAt, duration = 1e3) {
|
|
3269
3295
|
const s = sceneRef.current;
|
|
@@ -3341,6 +3367,16 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3341
3367
|
if (!s) return null;
|
|
3342
3368
|
s.renderer.render(s.scene, s.camera);
|
|
3343
3369
|
return s.renderer.domElement.toDataURL("image/png");
|
|
3370
|
+
},
|
|
3371
|
+
reheatLayout() {
|
|
3372
|
+
const gObj = graphObjRef.current;
|
|
3373
|
+
if (gObj == null ? void 0 : gObj.worker) {
|
|
3374
|
+
gObj.worker.postMessage({ type: "stop" });
|
|
3375
|
+
gObj.worker.terminate();
|
|
3376
|
+
gObj.worker = null;
|
|
3377
|
+
}
|
|
3378
|
+
dataRef.current.settled = false;
|
|
3379
|
+
setAppendedData((prev) => prev ? { ...prev } : { nodes: [], links: [] });
|
|
3344
3380
|
}
|
|
3345
3381
|
}));
|
|
3346
3382
|
return /* @__PURE__ */ jsx(
|