@andespindola/brainlink 0.1.0-beta.83 → 0.1.0-beta.84
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.
- package/README.md +1 -0
- package/dist/application/frontend/client-js.js +19 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -600,6 +600,7 @@ The graph UI shows:
|
|
|
600
600
|
- graph rendering safeguards (batched canvas drawing across graph sizes, edge draw caps, lower redraw rate, zoom-aware interaction)
|
|
601
601
|
- WebGL node and edge acceleration when supported, falling back to Canvas 2D without changing graph behavior
|
|
602
602
|
- compact macro-to-micro density progression so reset keeps the graph mass oriented and zoom-in separates local neighborhoods progressively
|
|
603
|
+
- graph camera treats hub-centered navigation as structural only when the hub is dominant; diffuse stress graphs reset and zoom around the full graph mass
|
|
603
604
|
- massive-graph LOD progression: very low zoom uses spatial overview sampling plus hub-neighborhood edge previews to preserve whole-vault shape and orientation, then progressively raises the focused node budget as zoom increases so dense local areas keep nearby notes and links visible
|
|
604
605
|
|
|
605
606
|
The server indexes before starting by default. Use `--no-index` to skip that step:
|
|
@@ -537,6 +537,17 @@ const nearestHubNeighborDistance = (hub, nodes) => {
|
|
|
537
537
|
return minimum
|
|
538
538
|
}
|
|
539
539
|
|
|
540
|
+
const isDominantHub = (hub, nodeCount = state.visibleNodes.length) => {
|
|
541
|
+
if (!hub || nodeCount <= 0) {
|
|
542
|
+
return false
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const degree = state.nodeDegrees.get(hub.id) ?? 0
|
|
546
|
+
const minimumDegree = Math.max(18, Math.sqrt(nodeCount) * 1.8)
|
|
547
|
+
const degreeRatio = degree / Math.max(nodeCount, 1)
|
|
548
|
+
return degree >= minimumDegree || degreeRatio >= 0.035
|
|
549
|
+
}
|
|
550
|
+
|
|
540
551
|
const recomputeVisibility = () => {
|
|
541
552
|
const nodes = filteredNodes()
|
|
542
553
|
const ids = new Set(nodes.map(node => node.id))
|
|
@@ -556,10 +567,11 @@ const recomputeVisibility = () => {
|
|
|
556
567
|
state.primaryHub = primaryHub
|
|
557
568
|
state.hubNeighborDistance = nearestHubNeighborDistance(primaryHub, nodes)
|
|
558
569
|
const bounds = graphBounds(nodes)
|
|
570
|
+
const macroHub = isDominantHub(primaryHub, nodes.length) ? primaryHub : null
|
|
559
571
|
state.macroCenter = bounds
|
|
560
572
|
? {
|
|
561
|
-
x:
|
|
562
|
-
y:
|
|
573
|
+
x: macroHub ? macroHub.x : (bounds.minX + bounds.maxX) / 2,
|
|
574
|
+
y: macroHub ? macroHub.y : (bounds.minY + bounds.maxY) / 2
|
|
563
575
|
}
|
|
564
576
|
: { x: 0, y: 0 }
|
|
565
577
|
state.macroRepresentative = resolveMacroRepresentative(nodes)
|
|
@@ -1675,7 +1687,9 @@ const zoomCapByHubDistance = (distance) => {
|
|
|
1675
1687
|
|
|
1676
1688
|
const currentZoomMax = () => {
|
|
1677
1689
|
const nodeCount = state.visibleNodes.length > 0 ? state.visibleNodes.length : state.nodes.length
|
|
1678
|
-
const hubDistanceCap =
|
|
1690
|
+
const hubDistanceCap = isDominantHub(state.primaryHub, nodeCount)
|
|
1691
|
+
? zoomCapByHubDistance(state.hubNeighborDistance)
|
|
1692
|
+
: zoomRange.max
|
|
1679
1693
|
const minimumUsefulCap = nodeCount > massiveGraphNodeThreshold ? 1.9 : nodeCount > largeGraphNodeThreshold ? 1.35 : 0.8
|
|
1680
1694
|
const capped = Math.min(zoomCapByNodeCount(nodeCount), Math.max(minimumUsefulCap, hubDistanceCap))
|
|
1681
1695
|
return Math.max(zoomRange.min * 2, capped)
|
|
@@ -1776,7 +1790,7 @@ const fitView = (options = { useFiltered: true, macro: false, preferHubCenter: t
|
|
|
1776
1790
|
? clampScale(Math.min(baselineScale, massiveAutoFitMacroScale))
|
|
1777
1791
|
: baselineScale
|
|
1778
1792
|
const hubCenter =
|
|
1779
|
-
options.preferHubCenter && state.primaryHub && nodes.some((node) => node.id === state.primaryHub.id)
|
|
1793
|
+
options.preferHubCenter && isDominantHub(state.primaryHub, nodes.length) && nodes.some((node) => node.id === state.primaryHub.id)
|
|
1780
1794
|
? state.primaryHub
|
|
1781
1795
|
: null
|
|
1782
1796
|
const centerX = hubCenter ? hubCenter.x : (bounds.minX + bounds.maxX) / 2
|
|
@@ -2735,27 +2749,8 @@ const selectNodeById = id => {
|
|
|
2735
2749
|
}
|
|
2736
2750
|
|
|
2737
2751
|
const zoomAtPoint = (screenX, screenY, factor, source = 'generic') => {
|
|
2738
|
-
const resolveZoomFactor = () => {
|
|
2739
|
-
if (state.nodes.length <= massiveGraphNodeThreshold) {
|
|
2740
|
-
return factor
|
|
2741
|
-
}
|
|
2742
|
-
|
|
2743
|
-
const scale = state.transform.scale
|
|
2744
|
-
if (factor > 1) {
|
|
2745
|
-
if (scale < 0.006) return Math.max(factor, 1.48)
|
|
2746
|
-
if (scale < 0.02) return Math.max(factor, 1.34)
|
|
2747
|
-
if (scale < 0.08) return Math.max(factor, 1.22)
|
|
2748
|
-
return factor
|
|
2749
|
-
}
|
|
2750
|
-
|
|
2751
|
-
if (scale < 0.006) return Math.min(factor, 0.68)
|
|
2752
|
-
if (scale < 0.02) return Math.min(factor, 0.78)
|
|
2753
|
-
if (scale < 0.08) return Math.min(factor, 0.86)
|
|
2754
|
-
return factor
|
|
2755
|
-
}
|
|
2756
|
-
|
|
2757
2752
|
state.lastManualZoomAt = performance.now()
|
|
2758
|
-
const effectiveFactor =
|
|
2753
|
+
const effectiveFactor = factor
|
|
2759
2754
|
const nextScale = clampScale(state.transform.scale * effectiveFactor)
|
|
2760
2755
|
if (nextScale === state.transform.scale) {
|
|
2761
2756
|
return
|
package/package.json
CHANGED