microboard-temp 0.13.50 → 0.13.52

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,7 +3957,7 @@ 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,
@@ -60712,18 +60712,18 @@ class ForceGraphEngine {
60712
60712
  if (this.isNodeInActiveGraph(startNodeId))
60713
60713
  return;
60714
60714
  const nodeIds = this.bfsComponent(startNodeId);
60715
- const targetGap = this.calibrateTargetGap(nodeIds);
60716
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60717
- for (const id of nodeIds) {
60718
- if (!this.velocities.has(id)) {
60719
- this.velocities.set(id, { vx: 0, vy: 0 });
60720
- }
60721
- const item = this.board.items.getById(id);
60722
- if (item && !this.lastSyncedPositions.has(id)) {
60723
- const pos = item.transformation.getTranslation();
60724
- 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
+ }
60725
60722
  }
60726
60723
  }
60724
+ const targetGap = this.calibrateTargetGap(nodeIds);
60725
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60726
+ this.initNodes(nodeIds);
60727
60727
  this.ensureRunning();
60728
60728
  }
60729
60729
  disableForGraph(nodeId) {
@@ -60778,6 +60778,32 @@ class ForceGraphEngine {
60778
60778
  this.lastSyncedPositions.clear();
60779
60779
  this.activeComponents.clear();
60780
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
+ }
60781
60807
  ensureRunning() {
60782
60808
  if (this.tickTimer === null) {
60783
60809
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60842,6 +60868,7 @@ class ForceGraphEngine {
60842
60868
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60843
60869
  }
60844
60870
  tick() {
60871
+ this.refreshComponentTopology();
60845
60872
  const activeIds = this.getActiveNodeIds();
60846
60873
  const draggedIds = this.board.getDraggedItemIds();
60847
60874
  const allNodes = this.getNodes();
@@ -60881,10 +60908,10 @@ class ForceGraphEngine {
60881
60908
  const dx = s2.cx - s1.cx;
60882
60909
  const dy = s2.cy - s1.cy;
60883
60910
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60884
- const compId = this.findComponentId(s1.id);
60885
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60886
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60887
- 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;
60888
60915
  const fx = dx / dist * force;
60889
60916
  const fy = dy / dist * force;
60890
60917
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60900,8 +60927,12 @@ class ForceGraphEngine {
60900
60927
  continue;
60901
60928
  const dx = s2.cx - s1.cx;
60902
60929
  const dy = s2.cy - s1.cy;
60903
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60904
- 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 minDistSq = refDist * refDist / 100;
60934
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60935
+ const force = conf.FG_REPULSION * refDist / distSq;
60905
60936
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60906
60937
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60907
60938
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/cjs/index.js CHANGED
@@ -3957,7 +3957,7 @@ 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,
@@ -60712,18 +60712,18 @@ class ForceGraphEngine {
60712
60712
  if (this.isNodeInActiveGraph(startNodeId))
60713
60713
  return;
60714
60714
  const nodeIds = this.bfsComponent(startNodeId);
60715
- const targetGap = this.calibrateTargetGap(nodeIds);
60716
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60717
- for (const id of nodeIds) {
60718
- if (!this.velocities.has(id)) {
60719
- this.velocities.set(id, { vx: 0, vy: 0 });
60720
- }
60721
- const item = this.board.items.getById(id);
60722
- if (item && !this.lastSyncedPositions.has(id)) {
60723
- const pos = item.transformation.getTranslation();
60724
- 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
+ }
60725
60722
  }
60726
60723
  }
60724
+ const targetGap = this.calibrateTargetGap(nodeIds);
60725
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60726
+ this.initNodes(nodeIds);
60727
60727
  this.ensureRunning();
60728
60728
  }
60729
60729
  disableForGraph(nodeId) {
@@ -60778,6 +60778,32 @@ class ForceGraphEngine {
60778
60778
  this.lastSyncedPositions.clear();
60779
60779
  this.activeComponents.clear();
60780
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
+ }
60781
60807
  ensureRunning() {
60782
60808
  if (this.tickTimer === null) {
60783
60809
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60842,6 +60868,7 @@ class ForceGraphEngine {
60842
60868
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60843
60869
  }
60844
60870
  tick() {
60871
+ this.refreshComponentTopology();
60845
60872
  const activeIds = this.getActiveNodeIds();
60846
60873
  const draggedIds = this.board.getDraggedItemIds();
60847
60874
  const allNodes = this.getNodes();
@@ -60881,10 +60908,10 @@ class ForceGraphEngine {
60881
60908
  const dx = s2.cx - s1.cx;
60882
60909
  const dy = s2.cy - s1.cy;
60883
60910
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60884
- const compId = this.findComponentId(s1.id);
60885
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60886
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60887
- 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;
60888
60915
  const fx = dx / dist * force;
60889
60916
  const fy = dy / dist * force;
60890
60917
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60900,8 +60927,12 @@ class ForceGraphEngine {
60900
60927
  continue;
60901
60928
  const dx = s2.cx - s1.cx;
60902
60929
  const dy = s2.cy - s1.cy;
60903
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60904
- 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 minDistSq = refDist * refDist / 100;
60934
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60935
+ const force = conf.FG_REPULSION * refDist / distSq;
60905
60936
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60906
60937
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60907
60938
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/cjs/node.js CHANGED
@@ -3957,7 +3957,7 @@ 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,
@@ -63187,18 +63187,18 @@ class ForceGraphEngine {
63187
63187
  if (this.isNodeInActiveGraph(startNodeId))
63188
63188
  return;
63189
63189
  const nodeIds = this.bfsComponent(startNodeId);
63190
- const targetGap = this.calibrateTargetGap(nodeIds);
63191
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
63192
- for (const id of nodeIds) {
63193
- if (!this.velocities.has(id)) {
63194
- this.velocities.set(id, { vx: 0, vy: 0 });
63195
- }
63196
- const item = this.board.items.getById(id);
63197
- if (item && !this.lastSyncedPositions.has(id)) {
63198
- const pos = item.transformation.getTranslation();
63199
- 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
+ }
63200
63197
  }
63201
63198
  }
63199
+ const targetGap = this.calibrateTargetGap(nodeIds);
63200
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
63201
+ this.initNodes(nodeIds);
63202
63202
  this.ensureRunning();
63203
63203
  }
63204
63204
  disableForGraph(nodeId) {
@@ -63253,6 +63253,32 @@ class ForceGraphEngine {
63253
63253
  this.lastSyncedPositions.clear();
63254
63254
  this.activeComponents.clear();
63255
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
+ }
63256
63282
  ensureRunning() {
63257
63283
  if (this.tickTimer === null) {
63258
63284
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -63317,6 +63343,7 @@ class ForceGraphEngine {
63317
63343
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
63318
63344
  }
63319
63345
  tick() {
63346
+ this.refreshComponentTopology();
63320
63347
  const activeIds = this.getActiveNodeIds();
63321
63348
  const draggedIds = this.board.getDraggedItemIds();
63322
63349
  const allNodes = this.getNodes();
@@ -63356,10 +63383,10 @@ class ForceGraphEngine {
63356
63383
  const dx = s2.cx - s1.cx;
63357
63384
  const dy = s2.cy - s1.cy;
63358
63385
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
63359
- const compId = this.findComponentId(s1.id);
63360
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
63361
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
63362
- 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;
63363
63390
  const fx = dx / dist * force;
63364
63391
  const fy = dy / dist * force;
63365
63392
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -63375,8 +63402,12 @@ class ForceGraphEngine {
63375
63402
  continue;
63376
63403
  const dx = s2.cx - s1.cx;
63377
63404
  const dy = s2.cy - s1.cy;
63378
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
63379
- 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 minDistSq = refDist * refDist / 100;
63409
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
63410
+ const force = conf.FG_REPULSION * refDist / distSq;
63380
63411
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
63381
63412
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
63382
63413
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
@@ -3964,7 +3964,7 @@ 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,
@@ -60455,18 +60455,18 @@ class ForceGraphEngine {
60455
60455
  if (this.isNodeInActiveGraph(startNodeId))
60456
60456
  return;
60457
60457
  const nodeIds = this.bfsComponent(startNodeId);
60458
- const targetGap = this.calibrateTargetGap(nodeIds);
60459
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60460
- for (const id of nodeIds) {
60461
- if (!this.velocities.has(id)) {
60462
- this.velocities.set(id, { vx: 0, vy: 0 });
60463
- }
60464
- const item = this.board.items.getById(id);
60465
- if (item && !this.lastSyncedPositions.has(id)) {
60466
- const pos = item.transformation.getTranslation();
60467
- 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
+ }
60468
60465
  }
60469
60466
  }
60467
+ const targetGap = this.calibrateTargetGap(nodeIds);
60468
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60469
+ this.initNodes(nodeIds);
60470
60470
  this.ensureRunning();
60471
60471
  }
60472
60472
  disableForGraph(nodeId) {
@@ -60521,6 +60521,32 @@ class ForceGraphEngine {
60521
60521
  this.lastSyncedPositions.clear();
60522
60522
  this.activeComponents.clear();
60523
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
+ }
60524
60550
  ensureRunning() {
60525
60551
  if (this.tickTimer === null) {
60526
60552
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60585,6 +60611,7 @@ class ForceGraphEngine {
60585
60611
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60586
60612
  }
60587
60613
  tick() {
60614
+ this.refreshComponentTopology();
60588
60615
  const activeIds = this.getActiveNodeIds();
60589
60616
  const draggedIds = this.board.getDraggedItemIds();
60590
60617
  const allNodes = this.getNodes();
@@ -60624,10 +60651,10 @@ class ForceGraphEngine {
60624
60651
  const dx = s2.cx - s1.cx;
60625
60652
  const dy = s2.cy - s1.cy;
60626
60653
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60627
- const compId = this.findComponentId(s1.id);
60628
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60629
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60630
- 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;
60631
60658
  const fx = dx / dist * force;
60632
60659
  const fy = dy / dist * force;
60633
60660
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60643,8 +60670,12 @@ class ForceGraphEngine {
60643
60670
  continue;
60644
60671
  const dx = s2.cx - s1.cx;
60645
60672
  const dy = s2.cy - s1.cy;
60646
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60647
- 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 minDistSq = refDist * refDist / 100;
60677
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60678
+ const force = conf.FG_REPULSION * refDist / distSq;
60648
60679
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60649
60680
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60650
60681
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/esm/index.js CHANGED
@@ -3957,7 +3957,7 @@ 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,
@@ -60448,18 +60448,18 @@ class ForceGraphEngine {
60448
60448
  if (this.isNodeInActiveGraph(startNodeId))
60449
60449
  return;
60450
60450
  const nodeIds = this.bfsComponent(startNodeId);
60451
- const targetGap = this.calibrateTargetGap(nodeIds);
60452
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60453
- for (const id of nodeIds) {
60454
- if (!this.velocities.has(id)) {
60455
- this.velocities.set(id, { vx: 0, vy: 0 });
60456
- }
60457
- const item = this.board.items.getById(id);
60458
- if (item && !this.lastSyncedPositions.has(id)) {
60459
- const pos = item.transformation.getTranslation();
60460
- 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
+ }
60461
60458
  }
60462
60459
  }
60460
+ const targetGap = this.calibrateTargetGap(nodeIds);
60461
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
60462
+ this.initNodes(nodeIds);
60463
60463
  this.ensureRunning();
60464
60464
  }
60465
60465
  disableForGraph(nodeId) {
@@ -60514,6 +60514,32 @@ class ForceGraphEngine {
60514
60514
  this.lastSyncedPositions.clear();
60515
60515
  this.activeComponents.clear();
60516
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
+ }
60517
60543
  ensureRunning() {
60518
60544
  if (this.tickTimer === null) {
60519
60545
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -60578,6 +60604,7 @@ class ForceGraphEngine {
60578
60604
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
60579
60605
  }
60580
60606
  tick() {
60607
+ this.refreshComponentTopology();
60581
60608
  const activeIds = this.getActiveNodeIds();
60582
60609
  const draggedIds = this.board.getDraggedItemIds();
60583
60610
  const allNodes = this.getNodes();
@@ -60617,10 +60644,10 @@ class ForceGraphEngine {
60617
60644
  const dx = s2.cx - s1.cx;
60618
60645
  const dy = s2.cy - s1.cy;
60619
60646
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
60620
- const compId = this.findComponentId(s1.id);
60621
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
60622
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
60623
- 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;
60624
60651
  const fx = dx / dist * force;
60625
60652
  const fy = dy / dist * force;
60626
60653
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -60636,8 +60663,12 @@ class ForceGraphEngine {
60636
60663
  continue;
60637
60664
  const dx = s2.cx - s1.cx;
60638
60665
  const dy = s2.cy - s1.cy;
60639
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
60640
- 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 minDistSq = refDist * refDist / 100;
60670
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
60671
+ const force = conf.FG_REPULSION * refDist / distSq;
60641
60672
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
60642
60673
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
60643
60674
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
package/dist/esm/node.js CHANGED
@@ -3959,7 +3959,7 @@ 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,
@@ -62912,18 +62912,18 @@ class ForceGraphEngine {
62912
62912
  if (this.isNodeInActiveGraph(startNodeId))
62913
62913
  return;
62914
62914
  const nodeIds = this.bfsComponent(startNodeId);
62915
- const targetGap = this.calibrateTargetGap(nodeIds);
62916
- this.activeComponents.set(startNodeId, { nodeIds, targetGap });
62917
- for (const id of nodeIds) {
62918
- if (!this.velocities.has(id)) {
62919
- this.velocities.set(id, { vx: 0, vy: 0 });
62920
- }
62921
- const item = this.board.items.getById(id);
62922
- if (item && !this.lastSyncedPositions.has(id)) {
62923
- const pos = item.transformation.getTranslation();
62924
- 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
+ }
62925
62922
  }
62926
62923
  }
62924
+ const targetGap = this.calibrateTargetGap(nodeIds);
62925
+ this.activeComponents.set(startNodeId, { nodeIds, targetGap });
62926
+ this.initNodes(nodeIds);
62927
62927
  this.ensureRunning();
62928
62928
  }
62929
62929
  disableForGraph(nodeId) {
@@ -62978,6 +62978,32 @@ class ForceGraphEngine {
62978
62978
  this.lastSyncedPositions.clear();
62979
62979
  this.activeComponents.clear();
62980
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
+ }
62981
63007
  ensureRunning() {
62982
63008
  if (this.tickTimer === null) {
62983
63009
  this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
@@ -63042,6 +63068,7 @@ class ForceGraphEngine {
63042
63068
  return this.board.items.listAll().filter((item) => item.itemType === "Connector");
63043
63069
  }
63044
63070
  tick() {
63071
+ this.refreshComponentTopology();
63045
63072
  const activeIds = this.getActiveNodeIds();
63046
63073
  const draggedIds = this.board.getDraggedItemIds();
63047
63074
  const allNodes = this.getNodes();
@@ -63081,10 +63108,10 @@ class ForceGraphEngine {
63081
63108
  const dx = s2.cx - s1.cx;
63082
63109
  const dy = s2.cy - s1.cy;
63083
63110
  const dist = Math.sqrt(dx * dx + dy * dy) || 1;
63084
- const compId = this.findComponentId(s1.id);
63085
- const targetGap = compId ? this.activeComponents.get(compId)?.targetGap ?? conf.FG_TARGET_GAP : conf.FG_TARGET_GAP;
63086
- const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + targetGap;
63087
- 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;
63088
63115
  const fx = dx / dist * force;
63089
63116
  const fy = dy / dist * force;
63090
63117
  ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
@@ -63100,8 +63127,12 @@ class ForceGraphEngine {
63100
63127
  continue;
63101
63128
  const dx = s2.cx - s1.cx;
63102
63129
  const dy = s2.cy - s1.cy;
63103
- const distSq = Math.max(dx * dx + dy * dy, conf.FG_MIN_DIST_SQ);
63104
- 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 minDistSq = refDist * refDist / 100;
63134
+ const distSq = Math.max(dx * dx + dy * dy, minDistSq);
63135
+ const force = conf.FG_REPULSION * refDist / distSq;
63105
63136
  ax.set(s1.id, (ax.get(s1.id) ?? 0) - dx * force);
63106
63137
  ay.set(s1.id, (ay.get(s1.id) ?? 0) - dy * force);
63107
63138
  ax.set(s2.id, (ax.get(s2.id) ?? 0) + dx * force);
@@ -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`. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "microboard-temp",
3
- "version": "0.13.50",
3
+ "version": "0.13.52",
4
4
  "description": "A flexible interactive whiteboard library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",