@andespindola/brainlink 0.1.0-beta.62 → 0.1.0-beta.63

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.
@@ -38,7 +38,7 @@ export const createClientHtml = () => `<!doctype html>
38
38
  <div class="toolbar" aria-label="Graph controls">
39
39
  <button id="zoomIn" type="button" title="Zoom in">+</button>
40
40
  <button id="zoomOut" type="button" title="Zoom out">-</button>
41
- <button id="fit" type="button" title="Fit visible nodes">◎</button>
41
+ <button id="fit" type="button" title="Focus central hub">◎</button>
42
42
  <button id="reset" type="button" title="Reset view">⌂</button>
43
43
  </div>
44
44
  </div>
@@ -571,13 +571,12 @@ const nodeBudgetForScale = (scale) => {
571
571
  }
572
572
 
573
573
  const layerWindowForScale = (scale) => {
574
- if (scale < 0.08) return { inner: 0.78, outer: 1 }
575
- if (scale < 0.14) return { inner: 0.62, outer: 0.9 }
576
- if (scale < 0.24) return { inner: 0.46, outer: 0.74 }
577
- if (scale < 0.36) return { inner: 0.3, outer: 0.58 }
578
- if (scale < layeredCoreScaleThreshold) return { inner: 0.16, outer: 0.42 }
579
- if (scale < 0.9) return { inner: 0.06, outer: 0.26 }
580
- return { inner: 0, outer: 0.14 }
574
+ const normalized = Math.max(0, Math.min(1, (scale - 0.06) / 0.94))
575
+ const outer = Math.max(0.14, 1 - normalized * 0.86)
576
+ const band = Math.max(0.14, 0.26 - normalized * 0.12)
577
+ const inner = Math.max(0, outer - band)
578
+
579
+ return { inner, outer }
581
580
  }
582
581
 
583
582
  const selectLayeredNodesForScale = (sourceNodes) => {
@@ -1143,6 +1142,27 @@ const fitView = (options = { useFiltered: true, macro: false, preferHubCenter: t
1143
1142
 
1144
1143
  const resetView = () => fitView({ useFiltered: false, macro: true, preferHubCenter: true })
1145
1144
 
1145
+ const focusPrimaryHub = () => {
1146
+ const hub = state.primaryHub
1147
+ if (!hub) {
1148
+ fitView({ useFiltered: true, macro: false, preferHubCenter: true })
1149
+ return
1150
+ }
1151
+
1152
+ const rect = canvas.getBoundingClientRect()
1153
+ const width = Math.max(rect.width, 320)
1154
+ const height = Math.max(rect.height, 320)
1155
+ const targetScale = clampScale(Math.max(0.78, state.transform.scale))
1156
+
1157
+ state.transform = {
1158
+ x: clampTransformCoordinate(width / 2 - hub.x * targetScale),
1159
+ y: clampTransformCoordinate(height / 2 - hub.y * targetScale),
1160
+ scale: targetScale
1161
+ }
1162
+ state.offscreenFrameCount = 0
1163
+ markRenderDirty()
1164
+ }
1165
+
1146
1166
  const createLayout = graph => {
1147
1167
  const nodeRows = Array.isArray(graph.nodes) ? graph.nodes : []
1148
1168
  const edgeRows = Array.isArray(graph.edges) ? graph.edges : []
@@ -2020,8 +2040,8 @@ const wheelZoomFactor = event => {
2020
2040
  return 1
2021
2041
  }
2022
2042
 
2023
- const baseStep = Math.max(0.06, Math.min(0.45, absoluteDelta / 480))
2024
- const adjustedStep = baseStep * (isModifierZoom ? 1.4 : 1)
2043
+ const baseStep = Math.max(0.03, Math.min(0.2, absoluteDelta / 680))
2044
+ const adjustedStep = baseStep * (isModifierZoom ? 1.24 : 1)
2025
2045
 
2026
2046
  return event.deltaY < 0 ? 1 + adjustedStep : 1 / (1 + adjustedStep)
2027
2047
  }
@@ -2068,15 +2088,15 @@ const bindEvents = () => {
2068
2088
  })
2069
2089
  elements.zoomIn.addEventListener('click', () => {
2070
2090
  const rect = canvas.getBoundingClientRect()
2071
- zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 1.3)
2091
+ zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 1.14)
2072
2092
  })
2073
2093
  elements.zoomOut.addEventListener('click', () => {
2074
2094
  const rect = canvas.getBoundingClientRect()
2075
- zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 0.77)
2095
+ zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 0.88)
2076
2096
  })
2077
2097
  if (elements.fit) {
2078
2098
  elements.fit.addEventListener('click', () => {
2079
- fitView({ useFiltered: true })
2099
+ focusPrimaryHub()
2080
2100
  })
2081
2101
  }
2082
2102
  elements.reset.addEventListener('click', () => {
@@ -2096,7 +2116,7 @@ const bindEvents = () => {
2096
2116
  const rect = canvas.getBoundingClientRect()
2097
2117
  const cursorX = event.clientX - rect.left
2098
2118
  const cursorY = event.clientY - rect.top
2099
- zoomAtPoint(cursorX, cursorY, 1.25)
2119
+ zoomAtPoint(cursorX, cursorY, 1.12)
2100
2120
  })
2101
2121
  canvas.addEventListener('pointerdown', event => {
2102
2122
  const point = worldPoint(event)
@@ -2170,14 +2190,14 @@ const bindEvents = () => {
2170
2190
  if (event.key === '+' || event.key === '=') {
2171
2191
  event.preventDefault()
2172
2192
  const rect = canvas.getBoundingClientRect()
2173
- zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 1.25)
2193
+ zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 1.12)
2174
2194
  return
2175
2195
  }
2176
2196
 
2177
2197
  if (event.key === '-' || event.key === '_') {
2178
2198
  event.preventDefault()
2179
2199
  const rect = canvas.getBoundingClientRect()
2180
- zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 0.8)
2200
+ zoomAtPoint(Math.max(rect.width, 320) / 2, Math.max(rect.height, 320) / 2, 0.89)
2181
2201
  return
2182
2202
  }
2183
2203
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.62",
3
+ "version": "0.1.0-beta.63",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",