microboard-temp 0.13.49 → 0.13.51

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.
@@ -3957,10 +3957,11 @@ var init_Settings = __esm(() => {
3957
3957
  CONNECTOR_ITEM_OFFSET: 20,
3958
3958
  FG_SPRING_K: 0.2,
3959
3959
  FG_TARGET_GAP: 50,
3960
- FG_REPULSION: 100,
3960
+ FG_REPULSION: 0.06,
3961
3961
  FG_MIN_DIST_SQ: 100,
3962
3962
  FG_DAMPING: 0.6,
3963
3963
  FG_SLEEP_THRESHOLD: 0.5,
3964
+ FG_TICK_MS: 16,
3964
3965
  GRAVITY_G: 80,
3965
3966
  GRAVITY_G_CENTER: 120,
3966
3967
  GRAVITY_DAMPING: 0.96,
@@ -60683,7 +60684,9 @@ class ForceGraphEngine {
60683
60684
  lastSyncedPositions = new Map;
60684
60685
  activeComponents = new Map;
60685
60686
  isPhysicsEmit = false;
60686
- TICK_MS = 33;
60687
+ get TICK_MS() {
60688
+ return conf.FG_TICK_MS;
60689
+ }
60687
60690
  SYNC_MS = 300;
60688
60691
  MIN_MOVE_PX = 0.05;
60689
60692
  constructor(board) {
@@ -60709,18 +60712,18 @@ class ForceGraphEngine {
60709
60712
  if (this.isNodeInActiveGraph(startNodeId))
60710
60713
  return;
60711
60714
  const nodeIds = this.bfsComponent(startNodeId);
60712
- const targetGap = this.calibrateTargetGap(nodeIds);
60713
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60714
- for (const id of nodeIds) {
60715
- if (!this.velocities.has(id)) {
60716
- this.velocities.set(id, { vx: 0, vy: 0 });
60717
- }
60718
- const item = this.board.items.getById(id);
60719
- if (item && !this.lastSyncedPositions.has(id)) {
60720
- const pos = item.transformation.getTranslation();
60721
- this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60715
+ for (const [, comp] of this.activeComponents) {
60716
+ for (const id of nodeIds) {
60717
+ if (comp.nodeIds.has(id)) {
60718
+ this.initNodes(nodeIds, comp.nodeIds);
60719
+ this.ensureRunning();
60720
+ return;
60721
+ }
60722
60722
  }
60723
60723
  }
60724
+ const targetGap = this.calibrateTargetGap(nodeIds);
60725
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60726
+ this.initNodes(nodeIds);
60724
60727
  this.ensureRunning();
60725
60728
  }
60726
60729
  disableForGraph(nodeId) {
@@ -60775,6 +60778,32 @@ class ForceGraphEngine {
60775
60778
  this.lastSyncedPositions.clear();
60776
60779
  this.activeComponents.clear();
60777
60780
  }
60781
+ initNodes(nodeIds, target) {
60782
+ for (const id of nodeIds) {
60783
+ target?.add(id);
60784
+ if (!this.velocities.has(id)) {
60785
+ this.velocities.set(id, { vx: 0, vy: 0 });
60786
+ }
60787
+ const item = this.board.items.getById(id);
60788
+ if (item && !this.lastSyncedPositions.has(id)) {
60789
+ const pos = item.transformation.getTranslation();
60790
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60791
+ }
60792
+ }
60793
+ }
60794
+ refreshComponentTopology() {
60795
+ for (const [compId, comp] of this.activeComponents) {
60796
+ const current = this.bfsComponent(compId);
60797
+ const newIds = new Set;
60798
+ for (const id of current) {
60799
+ if (!comp.nodeIds.has(id))
60800
+ newIds.add(id);
60801
+ }
60802
+ if (newIds.size > 0) {
60803
+ this.initNodes(newIds, comp.nodeIds);
60804
+ }
60805
+ }
60806
+ }
60778
60807
  ensureRunning() {
60779
60808
  if (this.tickTimer === null) {
60780
60809
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60839,6 +60868,7 @@ class ForceGraphEngine {
60839
60868
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60840
60869
  }
60841
60870
  tick() {
60871
+ this.refreshComponentTopology();
60842
60872
  const activeIds = this.getActiveNodeIds();
60843
60873
  const draggedIds = this.board.getDraggedItemIds();
60844
60874
  const allNodes = this.getNodes();
@@ -60878,10 +60908,10 @@ class ForceGraphEngine {
60878
60908
  const dx = s2.cx - s1.cx;
60879
60909
  const dy = s2.cy - s1.cy;
60880
60910
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60881
- const compId = this.findComponentId(s1.id);
60882
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60883
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60884
- const force = (dist - targetDist) * conf.FG_SPRING_K;
60911
+ const maxDimA = Math.max(s1.w, s1.h);
60912
+ const maxDimB = Math.max(s2.w, s2.h);
60913
+ const targetDist = (maxDimA + maxDimB) * 0.5 + Math.max(maxDimA, maxDimB);
60914
+ const force = (dist - targetDist) / targetDist * conf.FG_SPRING_K;
60885
60915
  const fx = dx / dist * force;
60886
60916
  const fy = dy / dist * force;
60887
60917
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60897,8 +60927,13 @@ class ForceGraphEngine {
60897
60927
  continue;
60898
60928
  const dx = s2.cx - s1.cx;
60899
60929
  const dy = s2.cy - s1.cy;
60900
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60901
- const force = conf.FG_REPULSION / distSq;
60930
+ const refDimA = Math.max(s1.w, s1.h);
60931
+ const refDimB = Math.max(s2.w, s2.h);
60932
+ const refDist = (refDimA + refDimB) * 0.5 + Math.max(refDimA, refDimB);
60933
+ const refDistSq = refDist * refDist;
60934
+ const minDistSq = conf.FG_MIN_DIST_SQ * refDistSq / 1e4;
60935
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60936
+ const force = conf.FG_REPULSION * refDistSq / distSq;
60902
60937
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60903
60938
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60904
60939
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/cjs/index.js CHANGED
@@ -3957,10 +3957,11 @@ var init_Settings = __esm(() => {
3957
3957
  CONNECTOR_ITEM_OFFSET: 20,
3958
3958
  FG_SPRING_K: 0.2,
3959
3959
  FG_TARGET_GAP: 50,
3960
- FG_REPULSION: 100,
3960
+ FG_REPULSION: 0.06,
3961
3961
  FG_MIN_DIST_SQ: 100,
3962
3962
  FG_DAMPING: 0.6,
3963
3963
  FG_SLEEP_THRESHOLD: 0.5,
3964
+ FG_TICK_MS: 16,
3964
3965
  GRAVITY_G: 80,
3965
3966
  GRAVITY_G_CENTER: 120,
3966
3967
  GRAVITY_DAMPING: 0.96,
@@ -60683,7 +60684,9 @@ class ForceGraphEngine {
60683
60684
  lastSyncedPositions = new Map;
60684
60685
  activeComponents = new Map;
60685
60686
  isPhysicsEmit = false;
60686
- TICK_MS = 33;
60687
+ get TICK_MS() {
60688
+ return conf.FG_TICK_MS;
60689
+ }
60687
60690
  SYNC_MS = 300;
60688
60691
  MIN_MOVE_PX = 0.05;
60689
60692
  constructor(board) {
@@ -60709,18 +60712,18 @@ class ForceGraphEngine {
60709
60712
  if (this.isNodeInActiveGraph(startNodeId))
60710
60713
  return;
60711
60714
  const nodeIds = this.bfsComponent(startNodeId);
60712
- const targetGap = this.calibrateTargetGap(nodeIds);
60713
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60714
- for (const id of nodeIds) {
60715
- if (!this.velocities.has(id)) {
60716
- this.velocities.set(id, { vx: 0, vy: 0 });
60717
- }
60718
- const item = this.board.items.getById(id);
60719
- if (item && !this.lastSyncedPositions.has(id)) {
60720
- const pos = item.transformation.getTranslation();
60721
- this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60715
+ for (const [, comp] of this.activeComponents) {
60716
+ for (const id of nodeIds) {
60717
+ if (comp.nodeIds.has(id)) {
60718
+ this.initNodes(nodeIds, comp.nodeIds);
60719
+ this.ensureRunning();
60720
+ return;
60721
+ }
60722
60722
  }
60723
60723
  }
60724
+ const targetGap = this.calibrateTargetGap(nodeIds);
60725
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60726
+ this.initNodes(nodeIds);
60724
60727
  this.ensureRunning();
60725
60728
  }
60726
60729
  disableForGraph(nodeId) {
@@ -60775,6 +60778,32 @@ class ForceGraphEngine {
60775
60778
  this.lastSyncedPositions.clear();
60776
60779
  this.activeComponents.clear();
60777
60780
  }
60781
+ initNodes(nodeIds, target) {
60782
+ for (const id of nodeIds) {
60783
+ target?.add(id);
60784
+ if (!this.velocities.has(id)) {
60785
+ this.velocities.set(id, { vx: 0, vy: 0 });
60786
+ }
60787
+ const item = this.board.items.getById(id);
60788
+ if (item && !this.lastSyncedPositions.has(id)) {
60789
+ const pos = item.transformation.getTranslation();
60790
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60791
+ }
60792
+ }
60793
+ }
60794
+ refreshComponentTopology() {
60795
+ for (const [compId, comp] of this.activeComponents) {
60796
+ const current = this.bfsComponent(compId);
60797
+ const newIds = new Set;
60798
+ for (const id of current) {
60799
+ if (!comp.nodeIds.has(id))
60800
+ newIds.add(id);
60801
+ }
60802
+ if (newIds.size > 0) {
60803
+ this.initNodes(newIds, comp.nodeIds);
60804
+ }
60805
+ }
60806
+ }
60778
60807
  ensureRunning() {
60779
60808
  if (this.tickTimer === null) {
60780
60809
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60839,6 +60868,7 @@ class ForceGraphEngine {
60839
60868
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60840
60869
  }
60841
60870
  tick() {
60871
+ this.refreshComponentTopology();
60842
60872
  const activeIds = this.getActiveNodeIds();
60843
60873
  const draggedIds = this.board.getDraggedItemIds();
60844
60874
  const allNodes = this.getNodes();
@@ -60878,10 +60908,10 @@ class ForceGraphEngine {
60878
60908
  const dx = s2.cx - s1.cx;
60879
60909
  const dy = s2.cy - s1.cy;
60880
60910
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60881
- const compId = this.findComponentId(s1.id);
60882
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60883
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60884
- const force = (dist - targetDist) * conf.FG_SPRING_K;
60911
+ const maxDimA = Math.max(s1.w, s1.h);
60912
+ const maxDimB = Math.max(s2.w, s2.h);
60913
+ const targetDist = (maxDimA + maxDimB) * 0.5 + Math.max(maxDimA, maxDimB);
60914
+ const force = (dist - targetDist) / targetDist * conf.FG_SPRING_K;
60885
60915
  const fx = dx / dist * force;
60886
60916
  const fy = dy / dist * force;
60887
60917
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60897,8 +60927,13 @@ class ForceGraphEngine {
60897
60927
  continue;
60898
60928
  const dx = s2.cx - s1.cx;
60899
60929
  const dy = s2.cy - s1.cy;
60900
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60901
- const force = conf.FG_REPULSION / distSq;
60930
+ const refDimA = Math.max(s1.w, s1.h);
60931
+ const refDimB = Math.max(s2.w, s2.h);
60932
+ const refDist = (refDimA + refDimB) * 0.5 + Math.max(refDimA, refDimB);
60933
+ const refDistSq = refDist * refDist;
60934
+ const minDistSq = conf.FG_MIN_DIST_SQ * refDistSq / 1e4;
60935
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60936
+ const force = conf.FG_REPULSION * refDistSq / distSq;
60902
60937
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60903
60938
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60904
60939
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/cjs/node.js CHANGED
@@ -3957,10 +3957,11 @@ var init_Settings = __esm(() => {
3957
3957
  CONNECTOR_ITEM_OFFSET: 20,
3958
3958
  FG_SPRING_K: 0.2,
3959
3959
  FG_TARGET_GAP: 50,
3960
- FG_REPULSION: 100,
3960
+ FG_REPULSION: 0.06,
3961
3961
  FG_MIN_DIST_SQ: 100,
3962
3962
  FG_DAMPING: 0.6,
3963
3963
  FG_SLEEP_THRESHOLD: 0.5,
3964
+ FG_TICK_MS: 16,
3964
3965
  GRAVITY_G: 80,
3965
3966
  GRAVITY_G_CENTER: 120,
3966
3967
  GRAVITY_DAMPING: 0.96,
@@ -63158,7 +63159,9 @@ class ForceGraphEngine {
63158
63159
  lastSyncedPositions = new Map;
63159
63160
  activeComponents = new Map;
63160
63161
  isPhysicsEmit = false;
63161
- TICK_MS = 33;
63162
+ get TICK_MS() {
63163
+ return conf.FG_TICK_MS;
63164
+ }
63162
63165
  SYNC_MS = 300;
63163
63166
  MIN_MOVE_PX = 0.05;
63164
63167
  constructor(board) {
@@ -63184,18 +63187,18 @@ class ForceGraphEngine {
63184
63187
  if (this.isNodeInActiveGraph(startNodeId))
63185
63188
  return;
63186
63189
  const nodeIds = this.bfsComponent(startNodeId);
63187
- const targetGap = this.calibrateTargetGap(nodeIds);
63188
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
63189
- for (const id of nodeIds) {
63190
- if (!this.velocities.has(id)) {
63191
- this.velocities.set(id, { vx: 0, vy: 0 });
63192
- }
63193
- const item = this.board.items.getById(id);
63194
- if (item && !this.lastSyncedPositions.has(id)) {
63195
- const pos = item.transformation.getTranslation();
63196
- this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
63190
+ for (const [, comp] of this.activeComponents) {
63191
+ for (const id of nodeIds) {
63192
+ if (comp.nodeIds.has(id)) {
63193
+ this.initNodes(nodeIds, comp.nodeIds);
63194
+ this.ensureRunning();
63195
+ return;
63196
+ }
63197
63197
  }
63198
63198
  }
63199
+ const targetGap = this.calibrateTargetGap(nodeIds);
63200
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
63201
+ this.initNodes(nodeIds);
63199
63202
  this.ensureRunning();
63200
63203
  }
63201
63204
  disableForGraph(nodeId) {
@@ -63250,6 +63253,32 @@ class ForceGraphEngine {
63250
63253
  this.lastSyncedPositions.clear();
63251
63254
  this.activeComponents.clear();
63252
63255
  }
63256
+ initNodes(nodeIds, target) {
63257
+ for (const id of nodeIds) {
63258
+ target?.add(id);
63259
+ if (!this.velocities.has(id)) {
63260
+ this.velocities.set(id, { vx: 0, vy: 0 });
63261
+ }
63262
+ const item = this.board.items.getById(id);
63263
+ if (item && !this.lastSyncedPositions.has(id)) {
63264
+ const pos = item.transformation.getTranslation();
63265
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
63266
+ }
63267
+ }
63268
+ }
63269
+ refreshComponentTopology() {
63270
+ for (const [compId, comp] of this.activeComponents) {
63271
+ const current = this.bfsComponent(compId);
63272
+ const newIds = new Set;
63273
+ for (const id of current) {
63274
+ if (!comp.nodeIds.has(id))
63275
+ newIds.add(id);
63276
+ }
63277
+ if (newIds.size > 0) {
63278
+ this.initNodes(newIds, comp.nodeIds);
63279
+ }
63280
+ }
63281
+ }
63253
63282
  ensureRunning() {
63254
63283
  if (this.tickTimer === null) {
63255
63284
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -63314,6 +63343,7 @@ class ForceGraphEngine {
63314
63343
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
63315
63344
  }
63316
63345
  tick() {
63346
+ this.refreshComponentTopology();
63317
63347
  const activeIds = this.getActiveNodeIds();
63318
63348
  const draggedIds = this.board.getDraggedItemIds();
63319
63349
  const allNodes = this.getNodes();
@@ -63353,10 +63383,10 @@ class ForceGraphEngine {
63353
63383
  const dx = s2.cx - s1.cx;
63354
63384
  const dy = s2.cy - s1.cy;
63355
63385
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
63356
- const compId = this.findComponentId(s1.id);
63357
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
63358
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
63359
- const force = (dist - targetDist) * conf.FG_SPRING_K;
63386
+ const maxDimA = Math.max(s1.w, s1.h);
63387
+ const maxDimB = Math.max(s2.w, s2.h);
63388
+ const targetDist = (maxDimA + maxDimB) * 0.5 + Math.max(maxDimA, maxDimB);
63389
+ const force = (dist - targetDist) / targetDist * conf.FG_SPRING_K;
63360
63390
  const fx = dx / dist * force;
63361
63391
  const fy = dy / dist * force;
63362
63392
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -63372,8 +63402,13 @@ class ForceGraphEngine {
63372
63402
  continue;
63373
63403
  const dx = s2.cx - s1.cx;
63374
63404
  const dy = s2.cy - s1.cy;
63375
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
63376
- const force = conf.FG_REPULSION / distSq;
63405
+ const refDimA = Math.max(s1.w, s1.h);
63406
+ const refDimB = Math.max(s2.w, s2.h);
63407
+ const refDist = (refDimA + refDimB) * 0.5 + Math.max(refDimA, refDimB);
63408
+ const refDistSq = refDist * refDist;
63409
+ const minDistSq = conf.FG_MIN_DIST_SQ * refDistSq / 1e4;
63410
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
63411
+ const force = conf.FG_REPULSION * refDistSq / distSq;
63377
63412
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
63378
63413
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
63379
63414
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
@@ -3964,10 +3964,11 @@ var init_Settings = __esm(() => {
3964
3964
  CONNECTOR_ITEM_OFFSET: 20,
3965
3965
  FG_SPRING_K: 0.2,
3966
3966
  FG_TARGET_GAP: 50,
3967
- FG_REPULSION: 100,
3967
+ FG_REPULSION: 0.06,
3968
3968
  FG_MIN_DIST_SQ: 100,
3969
3969
  FG_DAMPING: 0.6,
3970
3970
  FG_SLEEP_THRESHOLD: 0.5,
3971
+ FG_TICK_MS: 16,
3971
3972
  GRAVITY_G: 80,
3972
3973
  GRAVITY_G_CENTER: 120,
3973
3974
  GRAVITY_DAMPING: 0.96,
@@ -60426,7 +60427,9 @@ class ForceGraphEngine {
60426
60427
  lastSyncedPositions = new Map;
60427
60428
  activeComponents = new Map;
60428
60429
  isPhysicsEmit = false;
60429
- TICK_MS = 33;
60430
+ get TICK_MS() {
60431
+ return conf.FG_TICK_MS;
60432
+ }
60430
60433
  SYNC_MS = 300;
60431
60434
  MIN_MOVE_PX = 0.05;
60432
60435
  constructor(board) {
@@ -60452,18 +60455,18 @@ class ForceGraphEngine {
60452
60455
  if (this.isNodeInActiveGraph(startNodeId))
60453
60456
  return;
60454
60457
  const nodeIds = this.bfsComponent(startNodeId);
60455
- const targetGap = this.calibrateTargetGap(nodeIds);
60456
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60457
- for (const id of nodeIds) {
60458
- if (!this.velocities.has(id)) {
60459
- this.velocities.set(id, { vx: 0, vy: 0 });
60460
- }
60461
- const item = this.board.items.getById(id);
60462
- if (item && !this.lastSyncedPositions.has(id)) {
60463
- const pos = item.transformation.getTranslation();
60464
- this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60458
+ for (const [, comp] of this.activeComponents) {
60459
+ for (const id of nodeIds) {
60460
+ if (comp.nodeIds.has(id)) {
60461
+ this.initNodes(nodeIds, comp.nodeIds);
60462
+ this.ensureRunning();
60463
+ return;
60464
+ }
60465
60465
  }
60466
60466
  }
60467
+ const targetGap = this.calibrateTargetGap(nodeIds);
60468
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60469
+ this.initNodes(nodeIds);
60467
60470
  this.ensureRunning();
60468
60471
  }
60469
60472
  disableForGraph(nodeId) {
@@ -60518,6 +60521,32 @@ class ForceGraphEngine {
60518
60521
  this.lastSyncedPositions.clear();
60519
60522
  this.activeComponents.clear();
60520
60523
  }
60524
+ initNodes(nodeIds, target) {
60525
+ for (const id of nodeIds) {
60526
+ target?.add(id);
60527
+ if (!this.velocities.has(id)) {
60528
+ this.velocities.set(id, { vx: 0, vy: 0 });
60529
+ }
60530
+ const item = this.board.items.getById(id);
60531
+ if (item && !this.lastSyncedPositions.has(id)) {
60532
+ const pos = item.transformation.getTranslation();
60533
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60534
+ }
60535
+ }
60536
+ }
60537
+ refreshComponentTopology() {
60538
+ for (const [compId, comp] of this.activeComponents) {
60539
+ const current = this.bfsComponent(compId);
60540
+ const newIds = new Set;
60541
+ for (const id of current) {
60542
+ if (!comp.nodeIds.has(id))
60543
+ newIds.add(id);
60544
+ }
60545
+ if (newIds.size > 0) {
60546
+ this.initNodes(newIds, comp.nodeIds);
60547
+ }
60548
+ }
60549
+ }
60521
60550
  ensureRunning() {
60522
60551
  if (this.tickTimer === null) {
60523
60552
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60582,6 +60611,7 @@ class ForceGraphEngine {
60582
60611
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60583
60612
  }
60584
60613
  tick() {
60614
+ this.refreshComponentTopology();
60585
60615
  const activeIds = this.getActiveNodeIds();
60586
60616
  const draggedIds = this.board.getDraggedItemIds();
60587
60617
  const allNodes = this.getNodes();
@@ -60621,10 +60651,10 @@ class ForceGraphEngine {
60621
60651
  const dx = s2.cx - s1.cx;
60622
60652
  const dy = s2.cy - s1.cy;
60623
60653
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60624
- const compId = this.findComponentId(s1.id);
60625
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60626
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60627
- const force = (dist - targetDist) * conf.FG_SPRING_K;
60654
+ const maxDimA = Math.max(s1.w, s1.h);
60655
+ const maxDimB = Math.max(s2.w, s2.h);
60656
+ const targetDist = (maxDimA + maxDimB) * 0.5 + Math.max(maxDimA, maxDimB);
60657
+ const force = (dist - targetDist) / targetDist * conf.FG_SPRING_K;
60628
60658
  const fx = dx / dist * force;
60629
60659
  const fy = dy / dist * force;
60630
60660
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60640,8 +60670,13 @@ class ForceGraphEngine {
60640
60670
  continue;
60641
60671
  const dx = s2.cx - s1.cx;
60642
60672
  const dy = s2.cy - s1.cy;
60643
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60644
- const force = conf.FG_REPULSION / distSq;
60673
+ const refDimA = Math.max(s1.w, s1.h);
60674
+ const refDimB = Math.max(s2.w, s2.h);
60675
+ const refDist = (refDimA + refDimB) * 0.5 + Math.max(refDimA, refDimB);
60676
+ const refDistSq = refDist * refDist;
60677
+ const minDistSq = conf.FG_MIN_DIST_SQ * refDistSq / 1e4;
60678
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60679
+ const force = conf.FG_REPULSION * refDistSq / distSq;
60645
60680
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60646
60681
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60647
60682
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/esm/index.js CHANGED
@@ -3957,10 +3957,11 @@ var init_Settings = __esm(() => {
3957
3957
  CONNECTOR_ITEM_OFFSET: 20,
3958
3958
  FG_SPRING_K: 0.2,
3959
3959
  FG_TARGET_GAP: 50,
3960
- FG_REPULSION: 100,
3960
+ FG_REPULSION: 0.06,
3961
3961
  FG_MIN_DIST_SQ: 100,
3962
3962
  FG_DAMPING: 0.6,
3963
3963
  FG_SLEEP_THRESHOLD: 0.5,
3964
+ FG_TICK_MS: 16,
3964
3965
  GRAVITY_G: 80,
3965
3966
  GRAVITY_G_CENTER: 120,
3966
3967
  GRAVITY_DAMPING: 0.96,
@@ -60419,7 +60420,9 @@ class ForceGraphEngine {
60419
60420
  lastSyncedPositions = new Map;
60420
60421
  activeComponents = new Map;
60421
60422
  isPhysicsEmit = false;
60422
- TICK_MS = 33;
60423
+ get TICK_MS() {
60424
+ return conf.FG_TICK_MS;
60425
+ }
60423
60426
  SYNC_MS = 300;
60424
60427
  MIN_MOVE_PX = 0.05;
60425
60428
  constructor(board) {
@@ -60445,18 +60448,18 @@ class ForceGraphEngine {
60445
60448
  if (this.isNodeInActiveGraph(startNodeId))
60446
60449
  return;
60447
60450
  const nodeIds = this.bfsComponent(startNodeId);
60448
- const targetGap = this.calibrateTargetGap(nodeIds);
60449
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60450
- for (const id of nodeIds) {
60451
- if (!this.velocities.has(id)) {
60452
- this.velocities.set(id, { vx: 0, vy: 0 });
60453
- }
60454
- const item = this.board.items.getById(id);
60455
- if (item && !this.lastSyncedPositions.has(id)) {
60456
- const pos = item.transformation.getTranslation();
60457
- this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60451
+ for (const [, comp] of this.activeComponents) {
60452
+ for (const id of nodeIds) {
60453
+ if (comp.nodeIds.has(id)) {
60454
+ this.initNodes(nodeIds, comp.nodeIds);
60455
+ this.ensureRunning();
60456
+ return;
60457
+ }
60458
60458
  }
60459
60459
  }
60460
+ const targetGap = this.calibrateTargetGap(nodeIds);
60461
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60462
+ this.initNodes(nodeIds);
60460
60463
  this.ensureRunning();
60461
60464
  }
60462
60465
  disableForGraph(nodeId) {
@@ -60511,6 +60514,32 @@ class ForceGraphEngine {
60511
60514
  this.lastSyncedPositions.clear();
60512
60515
  this.activeComponents.clear();
60513
60516
  }
60517
+ initNodes(nodeIds, target) {
60518
+ for (const id of nodeIds) {
60519
+ target?.add(id);
60520
+ if (!this.velocities.has(id)) {
60521
+ this.velocities.set(id, { vx: 0, vy: 0 });
60522
+ }
60523
+ const item = this.board.items.getById(id);
60524
+ if (item && !this.lastSyncedPositions.has(id)) {
60525
+ const pos = item.transformation.getTranslation();
60526
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
60527
+ }
60528
+ }
60529
+ }
60530
+ refreshComponentTopology() {
60531
+ for (const [compId, comp] of this.activeComponents) {
60532
+ const current = this.bfsComponent(compId);
60533
+ const newIds = new Set;
60534
+ for (const id of current) {
60535
+ if (!comp.nodeIds.has(id))
60536
+ newIds.add(id);
60537
+ }
60538
+ if (newIds.size > 0) {
60539
+ this.initNodes(newIds, comp.nodeIds);
60540
+ }
60541
+ }
60542
+ }
60514
60543
  ensureRunning() {
60515
60544
  if (this.tickTimer === null) {
60516
60545
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60575,6 +60604,7 @@ class ForceGraphEngine {
60575
60604
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60576
60605
  }
60577
60606
  tick() {
60607
+ this.refreshComponentTopology();
60578
60608
  const activeIds = this.getActiveNodeIds();
60579
60609
  const draggedIds = this.board.getDraggedItemIds();
60580
60610
  const allNodes = this.getNodes();
@@ -60614,10 +60644,10 @@ class ForceGraphEngine {
60614
60644
  const dx = s2.cx - s1.cx;
60615
60645
  const dy = s2.cy - s1.cy;
60616
60646
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60617
- const compId = this.findComponentId(s1.id);
60618
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60619
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60620
- const force = (dist - targetDist) * conf.FG_SPRING_K;
60647
+ const maxDimA = Math.max(s1.w, s1.h);
60648
+ const maxDimB = Math.max(s2.w, s2.h);
60649
+ const targetDist = (maxDimA + maxDimB) * 0.5 + Math.max(maxDimA, maxDimB);
60650
+ const force = (dist - targetDist) / targetDist * conf.FG_SPRING_K;
60621
60651
  const fx = dx / dist * force;
60622
60652
  const fy = dy / dist * force;
60623
60653
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60633,8 +60663,13 @@ class ForceGraphEngine {
60633
60663
  continue;
60634
60664
  const dx = s2.cx - s1.cx;
60635
60665
  const dy = s2.cy - s1.cy;
60636
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60637
- const force = conf.FG_REPULSION / distSq;
60666
+ const refDimA = Math.max(s1.w, s1.h);
60667
+ const refDimB = Math.max(s2.w, s2.h);
60668
+ const refDist = (refDimA + refDimB) * 0.5 + Math.max(refDimA, refDimB);
60669
+ const refDistSq = refDist * refDist;
60670
+ const minDistSq = conf.FG_MIN_DIST_SQ * refDistSq / 1e4;
60671
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60672
+ const force = conf.FG_REPULSION * refDistSq / distSq;
60638
60673
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60639
60674
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60640
60675
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/esm/node.js CHANGED
@@ -3959,10 +3959,11 @@ var init_Settings = __esm(() => {
3959
3959
  CONNECTOR_ITEM_OFFSET: 20,
3960
3960
  FG_SPRING_K: 0.2,
3961
3961
  FG_TARGET_GAP: 50,
3962
- FG_REPULSION: 100,
3962
+ FG_REPULSION: 0.06,
3963
3963
  FG_MIN_DIST_SQ: 100,
3964
3964
  FG_DAMPING: 0.6,
3965
3965
  FG_SLEEP_THRESHOLD: 0.5,
3966
+ FG_TICK_MS: 16,
3966
3967
  GRAVITY_G: 80,
3967
3968
  GRAVITY_G_CENTER: 120,
3968
3969
  GRAVITY_DAMPING: 0.96,
@@ -62883,7 +62884,9 @@ class ForceGraphEngine {
62883
62884
  lastSyncedPositions = new Map;
62884
62885
  activeComponents = new Map;
62885
62886
  isPhysicsEmit = false;
62886
- TICK_MS = 33;
62887
+ get TICK_MS() {
62888
+ return conf.FG_TICK_MS;
62889
+ }
62887
62890
  SYNC_MS = 300;
62888
62891
  MIN_MOVE_PX = 0.05;
62889
62892
  constructor(board) {
@@ -62909,18 +62912,18 @@ class ForceGraphEngine {
62909
62912
  if (this.isNodeInActiveGraph(startNodeId))
62910
62913
  return;
62911
62914
  const nodeIds = this.bfsComponent(startNodeId);
62912
- const targetGap = this.calibrateTargetGap(nodeIds);
62913
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
62914
- for (const id of nodeIds) {
62915
- if (!this.velocities.has(id)) {
62916
- this.velocities.set(id, { vx: 0, vy: 0 });
62917
- }
62918
- const item = this.board.items.getById(id);
62919
- if (item && !this.lastSyncedPositions.has(id)) {
62920
- const pos = item.transformation.getTranslation();
62921
- this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
62915
+ for (const [, comp] of this.activeComponents) {
62916
+ for (const id of nodeIds) {
62917
+ if (comp.nodeIds.has(id)) {
62918
+ this.initNodes(nodeIds, comp.nodeIds);
62919
+ this.ensureRunning();
62920
+ return;
62921
+ }
62922
62922
  }
62923
62923
  }
62924
+ const targetGap = this.calibrateTargetGap(nodeIds);
62925
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
62926
+ this.initNodes(nodeIds);
62924
62927
  this.ensureRunning();
62925
62928
  }
62926
62929
  disableForGraph(nodeId) {
@@ -62975,6 +62978,32 @@ class ForceGraphEngine {
62975
62978
  this.lastSyncedPositions.clear();
62976
62979
  this.activeComponents.clear();
62977
62980
  }
62981
+ initNodes(nodeIds, target) {
62982
+ for (const id of nodeIds) {
62983
+ target?.add(id);
62984
+ if (!this.velocities.has(id)) {
62985
+ this.velocities.set(id, { vx: 0, vy: 0 });
62986
+ }
62987
+ const item = this.board.items.getById(id);
62988
+ if (item && !this.lastSyncedPositions.has(id)) {
62989
+ const pos = item.transformation.getTranslation();
62990
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
62991
+ }
62992
+ }
62993
+ }
62994
+ refreshComponentTopology() {
62995
+ for (const [compId, comp] of this.activeComponents) {
62996
+ const current = this.bfsComponent(compId);
62997
+ const newIds = new Set;
62998
+ for (const id of current) {
62999
+ if (!comp.nodeIds.has(id))
63000
+ newIds.add(id);
63001
+ }
63002
+ if (newIds.size > 0) {
63003
+ this.initNodes(newIds, comp.nodeIds);
63004
+ }
63005
+ }
63006
+ }
62978
63007
  ensureRunning() {
62979
63008
  if (this.tickTimer === null) {
62980
63009
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -63039,6 +63068,7 @@ class ForceGraphEngine {
63039
63068
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
63040
63069
  }
63041
63070
  tick() {
63071
+ this.refreshComponentTopology();
63042
63072
  const activeIds = this.getActiveNodeIds();
63043
63073
  const draggedIds = this.board.getDraggedItemIds();
63044
63074
  const allNodes = this.getNodes();
@@ -63078,10 +63108,10 @@ class ForceGraphEngine {
63078
63108
  const dx = s2.cx - s1.cx;
63079
63109
  const dy = s2.cy - s1.cy;
63080
63110
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
63081
- const compId = this.findComponentId(s1.id);
63082
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
63083
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
63084
- const force = (dist - targetDist) * conf.FG_SPRING_K;
63111
+ const maxDimA = Math.max(s1.w, s1.h);
63112
+ const maxDimB = Math.max(s2.w, s2.h);
63113
+ const targetDist = (maxDimA + maxDimB) * 0.5 + Math.max(maxDimA, maxDimB);
63114
+ const force = (dist - targetDist) / targetDist * conf.FG_SPRING_K;
63085
63115
  const fx = dx / dist * force;
63086
63116
  const fy = dy / dist * force;
63087
63117
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -63097,8 +63127,13 @@ class ForceGraphEngine {
63097
63127
  continue;
63098
63128
  const dx = s2.cx - s1.cx;
63099
63129
  const dy = s2.cy - s1.cy;
63100
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
63101
- const force = conf.FG_REPULSION / distSq;
63130
+ const refDimA = Math.max(s1.w, s1.h);
63131
+ const refDimB = Math.max(s2.w, s2.h);
63132
+ const refDist = (refDimA + refDimB) * 0.5 + Math.max(refDimA, refDimB);
63133
+ const refDistSq = refDist * refDist;
63134
+ const minDistSq = conf.FG_MIN_DIST_SQ * refDistSq / 1e4;
63135
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
63136
+ const force = conf.FG_REPULSION * refDistSq / distSq;
63102
63137
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
63103
63138
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
63104
63139
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
@@ -11,7 +11,7 @@ export declare class ForceGraphEngine {
11
11
  /** Set to true while we are emitting a physics sync operation, so the
12
12
  * board-event subscription below doesn't double-update lastSyncedPositions. */
13
13
  private isPhysicsEmit;
14
- private readonly TICK_MS;
14
+ private get TICK_MS();
15
15
  private readonly SYNC_MS;
16
16
  private readonly MIN_MOVE_PX;
17
17
  constructor(board: Board);
@@ -46,6 +46,11 @@ export declare class ForceGraphEngine {
46
46
  wake(): void;
47
47
  /** Full stop — called when Board destroys the engine. */
48
48
  stop(): void;
49
+ /** Initialize velocities and sync baseline for a set of node ids.
50
+ * If `target` is provided, new ids are also added into that Set. */
51
+ private initNodes;
52
+ /** Re-BFS each active component to pick up nodes/connectors added after enableForGraph. */
53
+ private refreshComponentTopology;
49
54
  private ensureRunning;
50
55
  private stopTimers;
51
56
  /** Find the componentId (Map key) for the component containing `nodeId`. */
@@ -259,6 +259,7 @@ export declare const conf: {
259
259
  FG_MIN_DIST_SQ: number;
260
260
  FG_DAMPING: number;
261
261
  FG_SLEEP_THRESHOLD: number;
262
+ FG_TICK_MS: number;
262
263
  GRAVITY_G: number;
263
264
  GRAVITY_G_CENTER: number;
264
265
  GRAVITY_DAMPING: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "microboard-temp",
3
- "version": "0.13.49",
3
+ "version": "0.13.51",
4
4
  "description": "A flexible interactive whiteboard library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",