@andespindola/brainlink 0.1.0-beta.66 → 0.1.0-beta.67

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.
@@ -64,7 +64,8 @@ const state = {
64
64
  filterWorker: null,
65
65
  filterReady: false,
66
66
  lastHoverHitAt: 0,
67
- lastManualZoomAt: 0
67
+ lastManualZoomAt: 0,
68
+ lastZoomFocus: { x: 0, y: 0, at: 0 }
68
69
  }
69
70
 
70
71
  const byId = id => document.getElementById(id)
@@ -653,17 +654,11 @@ const selectLayeredNodesForScale = (sourceNodes, targetCount) => {
653
654
  return merged.length > 0 ? merged : sourceNodes
654
655
  }
655
656
 
656
- const cursorWorldPoint = () => {
657
- if (!state.cursor.inCanvas) {
658
- return null
659
- }
660
-
661
- const rect = canvas.getBoundingClientRect()
662
- const screenX = state.cursor.x - rect.left
663
- const screenY = state.cursor.y - rect.top
657
+ const viewportCenterWorldPoint = () => {
658
+ const viewport = worldViewportBounds()
664
659
  return {
665
- x: (screenX - state.transform.x) / state.transform.scale,
666
- y: (screenY - state.transform.y) / state.transform.scale
660
+ x: (viewport.minX + viewport.maxX) / 2,
661
+ y: (viewport.minY + viewport.maxY) / 2
667
662
  }
668
663
  }
669
664
 
@@ -694,8 +689,12 @@ const selectAccessBridgeNodes = (sourceNodes, limit) => {
694
689
  return []
695
690
  }
696
691
 
697
- const cursor = cursorWorldPoint()
698
- const anchor = cursor ?? state.primaryHub ?? state.macroCenter ?? { x: 0, y: 0 }
692
+ const now = performance.now()
693
+ const recentZoomFocus =
694
+ now - state.lastZoomFocus.at <= 1200
695
+ ? { x: state.lastZoomFocus.x, y: state.lastZoomFocus.y }
696
+ : null
697
+ const anchor = recentZoomFocus ?? viewportCenterWorldPoint()
699
698
  return [...sourceNodes]
700
699
  .sort((left, right) => {
701
700
  const leftDistance = Math.hypot(left.x - anchor.x, left.y - anchor.y)
@@ -1239,9 +1238,17 @@ const focusPrimaryHub = () => {
1239
1238
  markRenderDirty()
1240
1239
  }
1241
1240
 
1241
+ const layoutDensityScaleForNodeCount = (nodeCount) => {
1242
+ if (nodeCount > 50000) return 0.56
1243
+ if (nodeCount > 20000) return 0.64
1244
+ if (nodeCount > 6000) return 0.76
1245
+ return 1
1246
+ }
1247
+
1242
1248
  const createLayout = graph => {
1243
1249
  const nodeRows = Array.isArray(graph.nodes) ? graph.nodes : []
1244
1250
  const edgeRows = Array.isArray(graph.edges) ? graph.edges : []
1251
+ const densityScale = layoutDensityScaleForNodeCount(nodeRows.length)
1245
1252
  const nodes = nodeRows.map(node => {
1246
1253
  if (Array.isArray(node)) {
1247
1254
  const [id, title, x, y, group, segment] = node
@@ -1252,8 +1259,8 @@ const createLayout = graph => {
1252
1259
  tags: [],
1253
1260
  group: typeof group === 'string' ? group : 'root',
1254
1261
  segment: typeof segment === 'string' ? segment : 'root',
1255
- x: Number.isFinite(x) ? x : 0,
1256
- y: Number.isFinite(y) ? y : 0,
1262
+ x: Number.isFinite(x) ? x * densityScale : 0,
1263
+ y: Number.isFinite(y) ? y * densityScale : 0,
1257
1264
  vx: 0,
1258
1265
  vy: 0
1259
1266
  }
@@ -1263,8 +1270,8 @@ const createLayout = graph => {
1263
1270
  ...node,
1264
1271
  path: typeof node.path === 'string' ? node.path : '',
1265
1272
  tags: Array.isArray(node.tags) ? node.tags : [],
1266
- x: Number.isFinite(node.x) ? node.x : 0,
1267
- y: Number.isFinite(node.y) ? node.y : 0,
1273
+ x: Number.isFinite(node.x) ? node.x * densityScale : 0,
1274
+ y: Number.isFinite(node.y) ? node.y * densityScale : 0,
1268
1275
  vx: Number.isFinite(node.vx) ? node.vx : 0,
1269
1276
  vy: Number.isFinite(node.vy) ? node.vy : 0
1270
1277
  }
@@ -2106,6 +2113,11 @@ const zoomAtPoint = (screenX, screenY, factor, source = 'generic') => {
2106
2113
  }
2107
2114
  const worldX = (screenX - state.transform.x) / state.transform.scale
2108
2115
  const worldY = (screenY - state.transform.y) / state.transform.scale
2116
+ state.lastZoomFocus = {
2117
+ x: worldX,
2118
+ y: worldY,
2119
+ at: performance.now()
2120
+ }
2109
2121
  state.transform.scale = clampScale(nextScale)
2110
2122
  state.transform.x = clampTransformCoordinate(screenX - worldX * nextScale)
2111
2123
  state.transform.y = clampTransformCoordinate(screenY - worldY * nextScale)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.66",
3
+ "version": "0.1.0-beta.67",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",