microboard-temp 0.13.15 → 0.13.17

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.
@@ -4675,6 +4675,11 @@ var conf = {
4675
4675
  DEFAULT_GAME_ITEM_DIMENSIONS: { width: 200, height: 200 },
4676
4676
  MAX_CARD_SIZE: 500,
4677
4677
  CONNECTOR_ITEM_OFFSET: 20,
4678
+ FG_SPRING_K: 3,
4679
+ FG_TARGET_GAP: 20,
4680
+ FG_REPULSION: 400000,
4681
+ FG_DAMPING: 0.8,
4682
+ FG_SLEEP_THRESHOLD: 0.5,
4678
4683
  GRAVITY_G: 80,
4679
4684
  GRAVITY_G_CENTER: 120,
4680
4685
  GRAVITY_DAMPING: 0.96,
@@ -54569,6 +54574,208 @@ class GravityEngine {
54569
54574
  }
54570
54575
  }
54571
54576
 
54577
+ // src/ForceGraph/ForceGraphEngine.ts
54578
+ class UnionFind {
54579
+ parent = new Map;
54580
+ find(id) {
54581
+ if (!this.parent.has(id))
54582
+ this.parent.set(id, id);
54583
+ const root3 = this.parent.get(id);
54584
+ if (root3 !== id) {
54585
+ const canonical = this.find(root3);
54586
+ this.parent.set(id, canonical);
54587
+ return canonical;
54588
+ }
54589
+ return root3;
54590
+ }
54591
+ union(a2, b) {
54592
+ const ra = this.find(a2);
54593
+ const rb = this.find(b);
54594
+ if (ra !== rb)
54595
+ this.parent.set(ra, rb);
54596
+ }
54597
+ sameComponent(a2, b) {
54598
+ return this.find(a2) === this.find(b);
54599
+ }
54600
+ }
54601
+ var EXCLUDED_TYPES = new Set(["Connector", "Comment"]);
54602
+
54603
+ class ForceGraphEngine {
54604
+ board;
54605
+ velocities = new Map;
54606
+ tickTimer = null;
54607
+ syncTimer = null;
54608
+ lastSyncedPositions = new Map;
54609
+ TICK_MS = 33;
54610
+ SYNC_MS = 300;
54611
+ SOFTENING_SQ = 100 * 100;
54612
+ MIN_MOVE_PX = 0.05;
54613
+ constructor(board) {
54614
+ this.board = board;
54615
+ }
54616
+ start() {
54617
+ if (this.tickTimer !== null)
54618
+ return;
54619
+ for (const item of this.getNodes()) {
54620
+ const pos = item.transformation.getTranslation();
54621
+ this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
54622
+ this.velocities.set(item.getId(), { vx: 0, vy: 0 });
54623
+ }
54624
+ this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
54625
+ this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
54626
+ }
54627
+ stop() {
54628
+ if (this.tickTimer !== null) {
54629
+ clearInterval(this.tickTimer);
54630
+ this.tickTimer = null;
54631
+ }
54632
+ if (this.syncTimer !== null) {
54633
+ clearInterval(this.syncTimer);
54634
+ this.syncTimer = null;
54635
+ }
54636
+ this.syncPositions();
54637
+ this.velocities.clear();
54638
+ this.lastSyncedPositions.clear();
54639
+ }
54640
+ getNodes() {
54641
+ return this.board.items.listAll().filter((item) => !EXCLUDED_TYPES.has(item.itemType) && !item.transformation.isLocked);
54642
+ }
54643
+ getConnectors() {
54644
+ return this.board.items.listAll().filter((item) => item.itemType === "Connector");
54645
+ }
54646
+ tick() {
54647
+ const dt = this.TICK_MS / 1000;
54648
+ const nodes = this.getNodes();
54649
+ if (nodes.length < 2)
54650
+ return;
54651
+ const snapMap = new Map;
54652
+ for (const item of nodes) {
54653
+ const pos = item.transformation.getTranslation();
54654
+ const mbr = item.getMbr();
54655
+ const w = Math.max(mbr.getWidth(), 1);
54656
+ const h2 = Math.max(mbr.getHeight(), 1);
54657
+ snapMap.set(item.getId(), {
54658
+ id: item.getId(),
54659
+ cx: pos.x + w * 0.5,
54660
+ cy: pos.y + h2 * 0.5,
54661
+ w,
54662
+ h: h2
54663
+ });
54664
+ }
54665
+ const snap = Array.from(snapMap.values());
54666
+ const uf = new UnionFind;
54667
+ for (const connector of this.getConnectors()) {
54668
+ const { startItem, endItem } = connector.getConnectedItems();
54669
+ if (startItem && endItem) {
54670
+ uf.union(startItem.getId(), endItem.getId());
54671
+ }
54672
+ }
54673
+ const ax = new Map;
54674
+ const ay = new Map;
54675
+ for (const s2 of snap) {
54676
+ ax.set(s2.id, 0);
54677
+ ay.set(s2.id, 0);
54678
+ }
54679
+ for (const connector of this.getConnectors()) {
54680
+ const { startItem, endItem } = connector.getConnectedItems();
54681
+ if (!startItem || !endItem)
54682
+ continue;
54683
+ const s1 = snapMap.get(startItem.getId());
54684
+ const s2 = snapMap.get(endItem.getId());
54685
+ if (!s1 || !s2)
54686
+ continue;
54687
+ const dx = s2.cx - s1.cx;
54688
+ const dy = s2.cy - s1.cy;
54689
+ const dist = Math.sqrt(dx * dx + dy * dy) + 0.001;
54690
+ const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + conf.FG_TARGET_GAP;
54691
+ const stretch = dist - targetDist;
54692
+ const forceMag = stretch * conf.FG_SPRING_K;
54693
+ const fx = dx / dist * forceMag;
54694
+ const fy = dy / dist * forceMag;
54695
+ ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
54696
+ ay.set(s1.id, (ay.get(s1.id) ?? 0) + fy);
54697
+ ax.set(s2.id, (ax.get(s2.id) ?? 0) - fx);
54698
+ ay.set(s2.id, (ay.get(s2.id) ?? 0) - fy);
54699
+ }
54700
+ for (let i = 0;i < snap.length; i++) {
54701
+ for (let j = i + 1;j < snap.length; j++) {
54702
+ const s1 = snap[i];
54703
+ const s2 = snap[j];
54704
+ if (!uf.sameComponent(s1.id, s2.id))
54705
+ continue;
54706
+ const dx = s2.cx - s1.cx;
54707
+ const dy = s2.cy - s1.cy;
54708
+ const distSq = dx * dx + dy * dy + this.SOFTENING_SQ;
54709
+ const repMag = conf.FG_REPULSION / distSq;
54710
+ const fx = dx * repMag;
54711
+ const fy = dy * repMag;
54712
+ ax.set(s1.id, (ax.get(s1.id) ?? 0) - fx);
54713
+ ay.set(s1.id, (ay.get(s1.id) ?? 0) - fy);
54714
+ ax.set(s2.id, (ax.get(s2.id) ?? 0) + fx);
54715
+ ay.set(s2.id, (ay.get(s2.id) ?? 0) + fy);
54716
+ }
54717
+ }
54718
+ let totalEnergy = 0;
54719
+ for (const item of nodes) {
54720
+ const id = item.getId();
54721
+ if (!this.velocities.has(id)) {
54722
+ this.velocities.set(id, { vx: 0, vy: 0 });
54723
+ }
54724
+ const vel = this.velocities.get(id);
54725
+ vel.vx = (vel.vx + (ax.get(id) ?? 0) * dt) * conf.FG_DAMPING;
54726
+ vel.vy = (vel.vy + (ay.get(id) ?? 0) * dt) * conf.FG_DAMPING;
54727
+ totalEnergy += vel.vx * vel.vx + vel.vy * vel.vy;
54728
+ const moveX = vel.vx * dt;
54729
+ const moveY = vel.vy * dt;
54730
+ if (Math.abs(moveX) >= this.MIN_MOVE_PX || Math.abs(moveY) >= this.MIN_MOVE_PX) {
54731
+ item.transformation.applyMatrixSilent({
54732
+ translateX: moveX,
54733
+ translateY: moveY,
54734
+ scaleX: 1,
54735
+ scaleY: 1,
54736
+ shearX: 0,
54737
+ shearY: 0
54738
+ });
54739
+ }
54740
+ }
54741
+ if (totalEnergy < conf.FG_SLEEP_THRESHOLD && this.tickTimer !== null) {
54742
+ clearInterval(this.tickTimer);
54743
+ this.tickTimer = null;
54744
+ this.syncPositions();
54745
+ }
54746
+ }
54747
+ syncPositions() {
54748
+ const nodes = this.getNodes();
54749
+ if (nodes.length === 0)
54750
+ return;
54751
+ const movedItems = nodes.map((item) => {
54752
+ const id = item.getId();
54753
+ const pos = item.transformation.getTranslation();
54754
+ const last = this.lastSyncedPositions.get(id);
54755
+ const dx = last ? pos.x - last.x : 0;
54756
+ const dy = last ? pos.y - last.y : 0;
54757
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
54758
+ return { id, dx, dy };
54759
+ }).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
54760
+ if (movedItems.length === 0)
54761
+ return;
54762
+ const operation = {
54763
+ class: "Transformation",
54764
+ method: "applyMatrix",
54765
+ items: movedItems.map(({ id, dx, dy }) => ({
54766
+ id,
54767
+ matrix: { translateX: dx, translateY: dy, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 }
54768
+ }))
54769
+ };
54770
+ this.board.events.emit(operation);
54771
+ }
54772
+ wake() {
54773
+ if (this.tickTimer === null && this.syncTimer !== null) {
54774
+ this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
54775
+ }
54776
+ }
54777
+ }
54778
+
54572
54779
  // src/Board.ts
54573
54780
  class Board {
54574
54781
  boardId;
@@ -55641,6 +55848,25 @@ class Board {
55641
55848
  isGravityEnabled() {
55642
55849
  return this.gravity !== null;
55643
55850
  }
55851
+ forceGraph = null;
55852
+ enableForceGraph() {
55853
+ if (this.forceGraph)
55854
+ return;
55855
+ this.forceGraph = new ForceGraphEngine(this);
55856
+ this.forceGraph.start();
55857
+ }
55858
+ disableForceGraph() {
55859
+ if (!this.forceGraph)
55860
+ return;
55861
+ this.forceGraph.stop();
55862
+ this.forceGraph = null;
55863
+ }
55864
+ isForceGraphEnabled() {
55865
+ return this.forceGraph !== null;
55866
+ }
55867
+ wakeForceGraph() {
55868
+ this.forceGraph?.wake();
55869
+ }
55644
55870
  }
55645
55871
  // src/Events/Merge.ts
55646
55872
  var import_slate36 = require("slate");
package/dist/cjs/index.js CHANGED
@@ -4675,6 +4675,11 @@ var conf = {
4675
4675
  DEFAULT_GAME_ITEM_DIMENSIONS: { width: 200, height: 200 },
4676
4676
  MAX_CARD_SIZE: 500,
4677
4677
  CONNECTOR_ITEM_OFFSET: 20,
4678
+ FG_SPRING_K: 3,
4679
+ FG_TARGET_GAP: 20,
4680
+ FG_REPULSION: 400000,
4681
+ FG_DAMPING: 0.8,
4682
+ FG_SLEEP_THRESHOLD: 0.5,
4678
4683
  GRAVITY_G: 80,
4679
4684
  GRAVITY_G_CENTER: 120,
4680
4685
  GRAVITY_DAMPING: 0.96,
@@ -54569,6 +54574,208 @@ class GravityEngine {
54569
54574
  }
54570
54575
  }
54571
54576
 
54577
+ // src/ForceGraph/ForceGraphEngine.ts
54578
+ class UnionFind {
54579
+ parent = new Map;
54580
+ find(id) {
54581
+ if (!this.parent.has(id))
54582
+ this.parent.set(id, id);
54583
+ const root3 = this.parent.get(id);
54584
+ if (root3 !== id) {
54585
+ const canonical = this.find(root3);
54586
+ this.parent.set(id, canonical);
54587
+ return canonical;
54588
+ }
54589
+ return root3;
54590
+ }
54591
+ union(a2, b) {
54592
+ const ra = this.find(a2);
54593
+ const rb = this.find(b);
54594
+ if (ra !== rb)
54595
+ this.parent.set(ra, rb);
54596
+ }
54597
+ sameComponent(a2, b) {
54598
+ return this.find(a2) === this.find(b);
54599
+ }
54600
+ }
54601
+ var EXCLUDED_TYPES = new Set(["Connector", "Comment"]);
54602
+
54603
+ class ForceGraphEngine {
54604
+ board;
54605
+ velocities = new Map;
54606
+ tickTimer = null;
54607
+ syncTimer = null;
54608
+ lastSyncedPositions = new Map;
54609
+ TICK_MS = 33;
54610
+ SYNC_MS = 300;
54611
+ SOFTENING_SQ = 100 * 100;
54612
+ MIN_MOVE_PX = 0.05;
54613
+ constructor(board) {
54614
+ this.board = board;
54615
+ }
54616
+ start() {
54617
+ if (this.tickTimer !== null)
54618
+ return;
54619
+ for (const item of this.getNodes()) {
54620
+ const pos = item.transformation.getTranslation();
54621
+ this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
54622
+ this.velocities.set(item.getId(), { vx: 0, vy: 0 });
54623
+ }
54624
+ this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
54625
+ this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
54626
+ }
54627
+ stop() {
54628
+ if (this.tickTimer !== null) {
54629
+ clearInterval(this.tickTimer);
54630
+ this.tickTimer = null;
54631
+ }
54632
+ if (this.syncTimer !== null) {
54633
+ clearInterval(this.syncTimer);
54634
+ this.syncTimer = null;
54635
+ }
54636
+ this.syncPositions();
54637
+ this.velocities.clear();
54638
+ this.lastSyncedPositions.clear();
54639
+ }
54640
+ getNodes() {
54641
+ return this.board.items.listAll().filter((item) => !EXCLUDED_TYPES.has(item.itemType) && !item.transformation.isLocked);
54642
+ }
54643
+ getConnectors() {
54644
+ return this.board.items.listAll().filter((item) => item.itemType === "Connector");
54645
+ }
54646
+ tick() {
54647
+ const dt = this.TICK_MS / 1000;
54648
+ const nodes = this.getNodes();
54649
+ if (nodes.length < 2)
54650
+ return;
54651
+ const snapMap = new Map;
54652
+ for (const item of nodes) {
54653
+ const pos = item.transformation.getTranslation();
54654
+ const mbr = item.getMbr();
54655
+ const w = Math.max(mbr.getWidth(), 1);
54656
+ const h2 = Math.max(mbr.getHeight(), 1);
54657
+ snapMap.set(item.getId(), {
54658
+ id: item.getId(),
54659
+ cx: pos.x + w * 0.5,
54660
+ cy: pos.y + h2 * 0.5,
54661
+ w,
54662
+ h: h2
54663
+ });
54664
+ }
54665
+ const snap = Array.from(snapMap.values());
54666
+ const uf = new UnionFind;
54667
+ for (const connector of this.getConnectors()) {
54668
+ const { startItem, endItem } = connector.getConnectedItems();
54669
+ if (startItem && endItem) {
54670
+ uf.union(startItem.getId(), endItem.getId());
54671
+ }
54672
+ }
54673
+ const ax = new Map;
54674
+ const ay = new Map;
54675
+ for (const s2 of snap) {
54676
+ ax.set(s2.id, 0);
54677
+ ay.set(s2.id, 0);
54678
+ }
54679
+ for (const connector of this.getConnectors()) {
54680
+ const { startItem, endItem } = connector.getConnectedItems();
54681
+ if (!startItem || !endItem)
54682
+ continue;
54683
+ const s1 = snapMap.get(startItem.getId());
54684
+ const s2 = snapMap.get(endItem.getId());
54685
+ if (!s1 || !s2)
54686
+ continue;
54687
+ const dx = s2.cx - s1.cx;
54688
+ const dy = s2.cy - s1.cy;
54689
+ const dist = Math.sqrt(dx * dx + dy * dy) + 0.001;
54690
+ const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + conf.FG_TARGET_GAP;
54691
+ const stretch = dist - targetDist;
54692
+ const forceMag = stretch * conf.FG_SPRING_K;
54693
+ const fx = dx / dist * forceMag;
54694
+ const fy = dy / dist * forceMag;
54695
+ ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
54696
+ ay.set(s1.id, (ay.get(s1.id) ?? 0) + fy);
54697
+ ax.set(s2.id, (ax.get(s2.id) ?? 0) - fx);
54698
+ ay.set(s2.id, (ay.get(s2.id) ?? 0) - fy);
54699
+ }
54700
+ for (let i = 0;i < snap.length; i++) {
54701
+ for (let j = i + 1;j < snap.length; j++) {
54702
+ const s1 = snap[i];
54703
+ const s2 = snap[j];
54704
+ if (!uf.sameComponent(s1.id, s2.id))
54705
+ continue;
54706
+ const dx = s2.cx - s1.cx;
54707
+ const dy = s2.cy - s1.cy;
54708
+ const distSq = dx * dx + dy * dy + this.SOFTENING_SQ;
54709
+ const repMag = conf.FG_REPULSION / distSq;
54710
+ const fx = dx * repMag;
54711
+ const fy = dy * repMag;
54712
+ ax.set(s1.id, (ax.get(s1.id) ?? 0) - fx);
54713
+ ay.set(s1.id, (ay.get(s1.id) ?? 0) - fy);
54714
+ ax.set(s2.id, (ax.get(s2.id) ?? 0) + fx);
54715
+ ay.set(s2.id, (ay.get(s2.id) ?? 0) + fy);
54716
+ }
54717
+ }
54718
+ let totalEnergy = 0;
54719
+ for (const item of nodes) {
54720
+ const id = item.getId();
54721
+ if (!this.velocities.has(id)) {
54722
+ this.velocities.set(id, { vx: 0, vy: 0 });
54723
+ }
54724
+ const vel = this.velocities.get(id);
54725
+ vel.vx = (vel.vx + (ax.get(id) ?? 0) * dt) * conf.FG_DAMPING;
54726
+ vel.vy = (vel.vy + (ay.get(id) ?? 0) * dt) * conf.FG_DAMPING;
54727
+ totalEnergy += vel.vx * vel.vx + vel.vy * vel.vy;
54728
+ const moveX = vel.vx * dt;
54729
+ const moveY = vel.vy * dt;
54730
+ if (Math.abs(moveX) >= this.MIN_MOVE_PX || Math.abs(moveY) >= this.MIN_MOVE_PX) {
54731
+ item.transformation.applyMatrixSilent({
54732
+ translateX: moveX,
54733
+ translateY: moveY,
54734
+ scaleX: 1,
54735
+ scaleY: 1,
54736
+ shearX: 0,
54737
+ shearY: 0
54738
+ });
54739
+ }
54740
+ }
54741
+ if (totalEnergy < conf.FG_SLEEP_THRESHOLD && this.tickTimer !== null) {
54742
+ clearInterval(this.tickTimer);
54743
+ this.tickTimer = null;
54744
+ this.syncPositions();
54745
+ }
54746
+ }
54747
+ syncPositions() {
54748
+ const nodes = this.getNodes();
54749
+ if (nodes.length === 0)
54750
+ return;
54751
+ const movedItems = nodes.map((item) => {
54752
+ const id = item.getId();
54753
+ const pos = item.transformation.getTranslation();
54754
+ const last = this.lastSyncedPositions.get(id);
54755
+ const dx = last ? pos.x - last.x : 0;
54756
+ const dy = last ? pos.y - last.y : 0;
54757
+ this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
54758
+ return { id, dx, dy };
54759
+ }).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
54760
+ if (movedItems.length === 0)
54761
+ return;
54762
+ const operation = {
54763
+ class: "Transformation",
54764
+ method: "applyMatrix",
54765
+ items: movedItems.map(({ id, dx, dy }) => ({
54766
+ id,
54767
+ matrix: { translateX: dx, translateY: dy, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 }
54768
+ }))
54769
+ };
54770
+ this.board.events.emit(operation);
54771
+ }
54772
+ wake() {
54773
+ if (this.tickTimer === null && this.syncTimer !== null) {
54774
+ this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
54775
+ }
54776
+ }
54777
+ }
54778
+
54572
54779
  // src/Board.ts
54573
54780
  class Board {
54574
54781
  boardId;
@@ -55641,6 +55848,25 @@ class Board {
55641
55848
  isGravityEnabled() {
55642
55849
  return this.gravity !== null;
55643
55850
  }
55851
+ forceGraph = null;
55852
+ enableForceGraph() {
55853
+ if (this.forceGraph)
55854
+ return;
55855
+ this.forceGraph = new ForceGraphEngine(this);
55856
+ this.forceGraph.start();
55857
+ }
55858
+ disableForceGraph() {
55859
+ if (!this.forceGraph)
55860
+ return;
55861
+ this.forceGraph.stop();
55862
+ this.forceGraph = null;
55863
+ }
55864
+ isForceGraphEnabled() {
55865
+ return this.forceGraph !== null;
55866
+ }
55867
+ wakeForceGraph() {
55868
+ this.forceGraph?.wake();
55869
+ }
55644
55870
  }
55645
55871
  // src/Events/Merge.ts
55646
55872
  var import_slate36 = require("slate");