@andespindola/brainlink 0.1.0-beta.71 → 0.1.0-beta.73

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.
@@ -8,6 +8,9 @@ const renderEdgeBudget = 2400
8
8
  const clusterActivationNodeThreshold = 600
9
9
  const clusterZoomThreshold = 0.18
10
10
  const macroGalaxyZoomThreshold = 0.012
11
+ const macroGalaxyEnterHysteresis = 0.86
12
+ const macroGalaxyExitHysteresis = 1.24
13
+ const galaxyDiscoveryEnabled = false
11
14
  const massiveAutoFitMacroScale = 0.006
12
15
  const defaultMacroScale = 0.006
13
16
  const clusterCellPixelSize = 64
@@ -25,6 +28,9 @@ const meshEdgeMaxBudget = 1400
25
28
  const layeredCoreScaleThreshold = 0.55
26
29
  const dragNeighborhoodMaxAffected = 180
27
30
  const dragSettleRounds = 3
31
+ const wheelZoomExponent = 0.0018
32
+ const wheelZoomExponentCap = 0.09
33
+ const wheelZoomModifierBoost = 1.22
28
34
  const state = {
29
35
  graph: { nodes: [], edges: [] },
30
36
  nodes: [],
@@ -65,7 +71,8 @@ const state = {
65
71
  filterReady: false,
66
72
  lastHoverHitAt: 0,
67
73
  lastManualZoomAt: 0,
68
- lastZoomFocus: { x: 0, y: 0, at: 0 }
74
+ lastZoomFocus: { x: 0, y: 0, at: 0 },
75
+ macroViewActive: false
69
76
  }
70
77
 
71
78
  const byId = id => document.getElementById(id)
@@ -662,6 +669,33 @@ const viewportCenterWorldPoint = () => {
662
669
  }
663
670
  }
664
671
 
672
+ const visibilityScaleBucket = (scale) => {
673
+ const safeScale = Math.max(zoomRange.min, scale)
674
+ if (safeScale < 0.01) return Math.round(safeScale * 300_000)
675
+ if (safeScale < 0.05) return Math.round(safeScale * 120_000)
676
+ if (safeScale < 0.2) return Math.round(safeScale * 40_000)
677
+ return Math.round(safeScale * 8_000)
678
+ }
679
+
680
+ const shouldRenderMacroGalaxyView = () => {
681
+ if (!galaxyDiscoveryEnabled) {
682
+ state.macroViewActive = false
683
+ return false
684
+ }
685
+ if (state.visibleNodes.length <= 1) {
686
+ state.macroViewActive = false
687
+ return false
688
+ }
689
+
690
+ const enterThreshold = macroGalaxyZoomThreshold * macroGalaxyEnterHysteresis
691
+ const exitThreshold = macroGalaxyZoomThreshold * macroGalaxyExitHysteresis
692
+ const shouldRender = state.macroViewActive
693
+ ? state.transform.scale <= exitThreshold
694
+ : state.transform.scale <= enterThreshold
695
+ state.macroViewActive = shouldRender
696
+ return shouldRender
697
+ }
698
+
665
699
  const mergeUniqueNodes = (leftNodes, rightNodes, limit) => {
666
700
  const merged = []
667
701
  const ids = new Set()
@@ -1733,7 +1767,7 @@ const computeRenderVisibility = () => {
1733
1767
  Math.round(viewport.maxX * 10) + ':' +
1734
1768
  Math.round(viewport.minY * 10) + ':' +
1735
1769
  Math.round(viewport.maxY * 10) + ':' +
1736
- Math.round(state.transform.scale * 1000)
1770
+ visibilityScaleBucket(state.transform.scale)
1737
1771
 
1738
1772
  if (!state.renderVisibilityDirty && viewportKey === state.lastViewportKey) {
1739
1773
  return
@@ -1741,8 +1775,7 @@ const computeRenderVisibility = () => {
1741
1775
  state.lastViewportKey = viewportKey
1742
1776
  state.renderVisibilityDirty = false
1743
1777
 
1744
- const shouldRenderMacroGalaxy =
1745
- state.transform.scale <= macroGalaxyZoomThreshold && state.visibleNodes.length > 1
1778
+ const shouldRenderMacroGalaxy = shouldRenderMacroGalaxyView()
1746
1779
 
1747
1780
  if (shouldRenderMacroGalaxy) {
1748
1781
  const viewportNodes = viewportNodesFromSpatialIndex(viewport)
@@ -1790,15 +1823,8 @@ const computeRenderVisibility = () => {
1790
1823
  carryOverNodes,
1791
1824
  Math.max(sampleLimit * 7, carryOverLimit)
1792
1825
  )
1793
- const layeredNodes = selectLayeredNodesForScale(sourceWithCarry, sampleLimit)
1794
- const bridgeLimit = Math.max(24, Math.min(180, Math.floor(sampleLimit * 0.26)))
1795
- const bridgedNodes = mergeUniqueNodes(
1796
- layeredNodes,
1797
- selectAccessBridgeNodes(sourceWithCarry, bridgeLimit),
1798
- Math.min(renderNodeBudget, sampleLimit + bridgeLimit)
1799
- )
1800
1826
  const sampledRaw = selectStableSampleNodes(
1801
- bridgedNodes,
1827
+ sourceWithCarry,
1802
1828
  Math.min(sampleLimit, renderNodeBudget)
1803
1829
  )
1804
1830
  const continuityBudget = Math.max(24, Math.min(sampleLimit - 8, Math.floor(sampleLimit * 0.42)))
@@ -2193,16 +2219,18 @@ const zoomAtPoint = (screenX, screenY, factor, source = 'generic') => {
2193
2219
  const wheelZoomFactor = event => {
2194
2220
  const isModifierZoom = event.metaKey || event.ctrlKey
2195
2221
  const deltaModeFactor = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 120 : 1
2196
- const absoluteDelta = Math.min(Math.abs(event.deltaY * deltaModeFactor), 1600)
2222
+ const normalizedDelta = event.deltaY * deltaModeFactor
2197
2223
 
2198
- if (absoluteDelta <= 0.0001) {
2224
+ if (!Number.isFinite(normalizedDelta) || Math.abs(normalizedDelta) <= 0.0001) {
2199
2225
  return 1
2200
2226
  }
2201
2227
 
2202
- const baseStep = Math.max(0.012, Math.min(0.11, absoluteDelta / 980))
2203
- const adjustedStep = baseStep * (isModifierZoom ? 1.24 : 1)
2204
-
2205
- return event.deltaY < 0 ? 1 + adjustedStep : 1 / (1 + adjustedStep)
2228
+ const sensitivity = wheelZoomExponent * (isModifierZoom ? wheelZoomModifierBoost : 1)
2229
+ const exponent = Math.max(
2230
+ -wheelZoomExponentCap,
2231
+ Math.min(wheelZoomExponentCap, -normalizedDelta * sensitivity)
2232
+ )
2233
+ return Math.exp(exponent)
2206
2234
  }
2207
2235
 
2208
2236
  const handleWheelZoom = event => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.71",
3
+ "version": "0.1.0-beta.73",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",