@fortemi/graph 2026.9.3 → 2026.9.5

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/dist/index.d.ts CHANGED
@@ -415,6 +415,6 @@ interface GraphRenderHandle {
415
415
  */
416
416
  declare function renderCommunityGraph(container: HTMLElement, graph: CommunityGraph, options?: GraphRenderOptions): GraphRenderHandle;
417
417
 
418
- declare const VERSION = "2026.9.3";
418
+ declare const VERSION = "2026.9.5";
419
419
 
420
420
  export { type BakeRenderGraphOptions, COMMUNITY_COLORS, CommunityGraph, type CommunityPalette, type ExpandOptions, type FitOptions, GRAPH_SNAPSHOT_VERSION, GREYSCALE_COMMUNITY_RAMP, GraphBounds, type GraphControlContract, type GraphControlFilters, type GraphFilter, GraphLayoutAlgorithm, type GraphLegendEntry, GraphNode, type GraphRenderFilters, type GraphRenderHandle, type GraphRenderOptions, type GraphRenderUpdate, type GraphSnapshot, type LayoutOptions, type LoadRenderSnapshotOptions, type MapCommunityGraphOptions, type NodeRadiusOptions, type NodeRadiusResolver, type PositionMap, PositionedGraph, PositionedGraphNode, type RenderGraph, type RenderLink, type RenderNode, type SerializeSnapshotOptions, UNASSIGNED_COMMUNITY_COLOR, VERSION, ViewportTransform, applyControlFilters, bakeRenderGraph, buildAdjacency, colorForCommunity, communityLegend, communityRanks, computeDegrees, computeGraphBounds, deserializeGraphSnapshot, expandNeighborhood, filterCommunityGraph, fitGraphToViewport, hasBakedPositions, isRenderGraph, layoutCommunityGraph, loadRenderSnapshot, mapCommunityGraph, neighborhoodSubgraph, neighborsOf, nodeRadius, renderCommunityGraph, serializeGraphSnapshot, stringifyGraphSnapshot, stringifyRenderGraph, subgraphForNodes };
package/dist/index.js CHANGED
@@ -898,7 +898,7 @@ function getComputedPosition(elm) {
898
898
  }
899
899
 
900
900
  // src/index.ts
901
- var VERSION = "2026.9.3";
901
+ var VERSION = "2026.9.5";
902
902
 
903
903
  export { COMMUNITY_COLORS, GRAPH_SNAPSHOT_VERSION, GREYSCALE_COMMUNITY_RAMP, UNASSIGNED_COMMUNITY_COLOR, VERSION, applyControlFilters, bakeRenderGraph, buildAdjacency, colorForCommunity, communityLegend, communityRanks, computeDegrees, computeGraphBounds, deserializeGraphSnapshot, expandNeighborhood, filterCommunityGraph, fitGraphToViewport, hasBakedPositions, isRenderGraph, layoutCommunityGraph, loadRenderSnapshot, mapCommunityGraph, neighborhoodSubgraph, neighborsOf, nodeRadius, renderCommunityGraph, serializeGraphSnapshot, stringifyGraphSnapshot, stringifyRenderGraph, subgraphForNodes };
904
904
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/degree.ts","../src/color.ts","../src/filter.ts","../src/rng.ts","../src/layout.ts","../src/bounds.ts","../src/neighborhood.ts","../src/serialize.ts","../src/render-prep.ts","../src/contract.ts","../src/render-dom.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { CommunityGraph } from './types.js'\n\n/** Count the (undirected) degree of every node, including isolated nodes (0). */\nexport function computeDegrees(graph: CommunityGraph): Map<string, number> {\n const degree = new Map<string, number>()\n for (const node of graph.nodes) degree.set(node.id, 0)\n for (const edge of graph.edges) {\n degree.set(edge.source, (degree.get(edge.source) ?? 0) + 1)\n degree.set(edge.target, (degree.get(edge.target) ?? 0) + 1)\n }\n return degree\n}\n\nexport interface NodeRadiusOptions {\n /** Radius of a degree-0 node. */\n base?: number\n /** Pixels added per unit of degree. */\n perDegree?: number\n /** Hard floor on the radius. */\n min?: number\n /** Hard ceiling on the radius. */\n max?: number\n}\n\n/**\n * Map a node degree to a render radius. Defaults match the values historically\n * used by the React `GraphView`: `clamp(5 + degree * 1.5, 5, 16)`.\n */\nexport function nodeRadius(degree: number, options: NodeRadiusOptions = {}): number {\n const base = options.base ?? 5\n const perDegree = options.perDegree ?? 1.5\n const min = options.min ?? 5\n const max = options.max ?? 16\n return Math.max(min, Math.min(max, base + degree * perDegree))\n}\n","/** Default qualitative palette for community coloring (8 hues). */\nexport const COMMUNITY_COLORS = [\n '#2f6fbb',\n '#d97706',\n '#218838',\n '#7c3aed',\n '#c2410c',\n '#0f766e',\n '#be185d',\n '#4b5563',\n] as const\n\n/** Color used for nodes that are not assigned to any community. */\nexport const UNASSIGNED_COMMUNITY_COLOR = '#64748b'\n\n/**\n * Deterministically assign a color to a community id by hashing the id into the\n * palette. The same id always maps to the same color across runs and hosts.\n * Pass a custom `palette` to theme the output. Matches the historical\n * `GraphView` color assignment.\n */\nexport function colorForCommunity(\n communityId: string | undefined,\n palette: readonly string[] = COMMUNITY_COLORS,\n unassignedColor: string = UNASSIGNED_COMMUNITY_COLOR,\n): string {\n if (!communityId) return unassignedColor\n if (palette.length === 0) return unassignedColor\n let hash = 0\n for (const char of communityId) hash = (hash * 31 + char.charCodeAt(0)) | 0\n return palette[Math.abs(hash) % palette.length]\n}\n","import type { CommunityGraph, GraphNode } from './types.js'\n\nexport interface GraphFilter {\n /** Keep only nodes belonging to these communities (by community id). */\n communityIds?: string[]\n /** Keep only edges whose `kind` is in this set. */\n edgeKinds?: string[]\n /** Explicit allow-list of node ids. Useful for privacy / visibility filtering. */\n nodeIds?: string[]\n /**\n * Arbitrary per-node predicate evaluated against the (allow-listed) nodes.\n * Returning `false` removes the node and any edge touching it. Hosts whose\n * nodes carry extra metadata (privacy class, type, etc.) can filter on it here.\n */\n nodePredicate?: (node: GraphNode) => boolean\n}\n\n/**\n * Produce a new {@link CommunityGraph} containing only the nodes, edges, and\n * community memberships permitted by `filter`. Pure — the input is not mutated.\n *\n * Filtering precedence:\n * 1. `communityIds` (if non-empty) restricts the candidate node set to members\n * of those communities; otherwise `nodeIds` (if given) is the candidate set,\n * else all nodes.\n * 2. `nodePredicate` further narrows the candidate set.\n * 3. Edges survive only when both endpoints survive and `edgeKinds` permits.\n * 4. Empty communities are dropped.\n */\nexport function filterCommunityGraph(\n graph: CommunityGraph | null | undefined,\n filter?: GraphFilter,\n): CommunityGraph {\n if (!graph) return { nodes: [], edges: [], communities: [] }\n\n const nodeIds = new Set(filter?.nodeIds ?? graph.nodes.map((node) => node.id))\n if (filter?.communityIds?.length) {\n const allowedCommunities = new Set(filter.communityIds)\n nodeIds.clear()\n for (const community of graph.communities) {\n if (allowedCommunities.has(community.id)) {\n for (const nodeId of community.nodes) nodeIds.add(nodeId)\n }\n }\n }\n\n const predicate = filter?.nodePredicate\n if (predicate) {\n for (const node of graph.nodes) {\n if (nodeIds.has(node.id) && !predicate(node)) nodeIds.delete(node.id)\n }\n }\n\n const edgeKinds = filter?.edgeKinds ? new Set(filter.edgeKinds) : null\n const nodes = graph.nodes.filter((node) => nodeIds.has(node.id))\n const edges = graph.edges.filter((edge) => (\n nodeIds.has(edge.source)\n && nodeIds.has(edge.target)\n && (!edgeKinds || edgeKinds.has(edge.kind ?? ''))\n ))\n const communities = graph.communities\n .map((community) => ({ ...community, nodes: community.nodes.filter((nodeId) => nodeIds.has(nodeId)) }))\n .filter((community) => community.nodes.length > 0)\n return { nodes, edges, communities }\n}\n","// Tiny deterministic PRNG (mulberry32). Used by the force layout to seed\n// initial jitter so that identical (seed, graph, options) always yields\n// identical coordinates — no Math.random, no time, no platform variance.\n\n/**\n * Create a deterministic pseudo-random generator from a 32-bit integer seed.\n * Returns a function producing floats in [0, 1). Identical seeds yield\n * identical sequences across platforms.\n */\nexport function mulberry32(seed: number): () => number {\n // Coerce to a non-zero unsigned 32-bit integer so seed 0 still advances.\n let a = (seed >>> 0) || 0x9e3779b9\n return function next(): number {\n a |= 0\n a = (a + 0x6d2b79f5) | 0\n let t = Math.imul(a ^ (a >>> 15), 1 | a)\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n","import { computeDegrees, nodeRadius as defaultNodeRadius, type NodeRadiusOptions } from './degree.js'\nimport { mulberry32 } from './rng.js'\nimport type {\n CommunityGraph,\n GraphLayoutAlgorithm,\n GraphNode,\n PositionedCommunity,\n PositionedGraph,\n PositionedGraphNode,\n} from './types.js'\n\n/**\n * How to derive each node's render radius. Either a fixed pixel value, a set of\n * {@link NodeRadiusOptions} fed to the default degree→radius mapping, or a full\n * resolver `(degree, node) => number`.\n */\nexport type NodeRadiusResolver =\n | number\n | NodeRadiusOptions\n | ((degree: number, node: GraphNode) => number)\n\nexport interface LayoutOptions {\n /** Layout algorithm. `force` runs deterministic settlement; the others are closed-form. */\n algorithm?: GraphLayoutAlgorithm\n width?: number\n height?: number\n /** Seed for the deterministic PRNG used by `force` initial jitter. Identical seed ⇒ identical output. */\n seed?: number\n /** Number of settlement iterations for the `force` algorithm. */\n ticks?: number\n /** Per-node render radius (default: degree-derived, clamped 5..16). */\n nodeRadius?: NodeRadiusResolver\n /** Target edge length in px for the spring force (`force` only). */\n linkDistance?: number\n /** Spring stiffness 0..1 (`force` only). */\n linkStrength?: number\n /** Repulsion magnitude; negative pushes nodes apart (`force` only). */\n chargeStrength?: number\n /** Extra spacing beyond `r_i + r_j` when resolving collisions (`force` only). */\n collisionPadding?: number\n /** Pull toward the node's community centroid, 0..1 (`force` only). */\n communityStrength?: number\n /** Keep every node center at least this many px from each canvas edge. */\n boundsPadding?: number\n /**\n * Positions to hold FIXED during settlement (drag pins, issue #245). Pinned\n * nodes stay put while the rest of the graph re-settles around them, giving an\n * incremental re-layout when a node is moved. Keyed by node id.\n */\n pinned?: PositionMap\n /**\n * Warm-start seed positions. Nodes present here begin the settlement from\n * these coordinates instead of the closed-form ring, so a re-layout resumes\n * from the current arrangement (smooth reshape) rather than re-seeding. Keyed\n * by node id. `pinned` overrides this for pinned nodes.\n */\n initialPositions?: PositionMap\n}\n\n/** A node-id → position lookup, accepted as either a Map or a plain record. */\nexport type PositionMap =\n | Map<string, { x: number; y: number }>\n | Record<string, { x: number; y: number }>\n\nfunction readPosition(\n map: PositionMap | undefined,\n id: string,\n): { x: number; y: number } | undefined {\n if (!map) return undefined\n if (map instanceof Map) return map.get(id)\n return Object.prototype.hasOwnProperty.call(map, id) ? map[id] : undefined\n}\n\nconst DEFAULTS = {\n width: 760,\n height: 460,\n seed: 1,\n ticks: 300,\n linkDistance: 60,\n linkStrength: 0.08,\n chargeStrength: -240,\n collisionPadding: 2,\n communityStrength: 0.05,\n boundsPadding: 24,\n} as const\n\n/** Mild global pull toward the canvas center so disconnected nodes don't drift. */\nconst GRAVITY = 0.02\n\nfunction resolveRadius(\n resolver: NodeRadiusResolver | undefined,\n degree: number,\n node: GraphNode,\n): number {\n if (resolver === undefined) return defaultNodeRadius(degree)\n if (typeof resolver === 'number') return resolver\n if (typeof resolver === 'function') return resolver(degree, node)\n return defaultNodeRadius(degree, resolver)\n}\n\n/** Clamp `value` into `[lo, hi]`, collapsing to the midpoint if the range inverts. */\nfunction clampToRange(value: number, lo: number, hi: number): number {\n if (lo > hi) return (lo + hi) / 2\n return Math.max(lo, Math.min(hi, value))\n}\n\n/**\n * Deterministically position the nodes of a {@link CommunityGraph} in 2D space.\n *\n * For the default `force` algorithm this runs a fixed-iteration, seeded force\n * settlement (spring link attraction, charge repulsion, collision spacing,\n * community cohesion, centering, and bounds clamping). It is fully synchronous\n * and headless — no animation frames — so the same `(graph, options)` always\n * yields identical coordinates, safe for snapshot rendering and SSR. The\n * `radial`, `community`, and `manual` algorithms remain closed-form.\n *\n * Every node is annotated with its render radius `r`, degree, and resolved\n * community; the result also carries community centroids over the final layout.\n */\nexport function layoutCommunityGraph(\n graph: CommunityGraph,\n options: LayoutOptions = {},\n): PositionedGraph {\n const algorithm = options.algorithm ?? 'force'\n const width = options.width ?? DEFAULTS.width\n const height = options.height ?? DEFAULTS.height\n const boundsPadding = options.boundsPadding ?? DEFAULTS.boundsPadding\n\n const degree = computeDegrees(graph)\n\n const communityByNode = new Map<string, string>()\n for (const community of graph.communities) {\n for (const nodeId of community.nodes) {\n if (!communityByNode.has(nodeId)) communityByNode.set(nodeId, community.id)\n }\n }\n\n const centerX = width / 2\n const centerY = height / 2\n const radius = Math.max(40, Math.min(width, height) * 0.38)\n const n = graph.nodes.length\n\n // Per-node render radius (stable, used by force spacing and by consumers).\n const r = graph.nodes.map((node) =>\n resolveRadius(options.nodeRadius, degree.get(node.id) ?? 0, node),\n )\n\n // Index from node id → array position (edges reference nodes by id).\n const indexOf = new Map<string, number>()\n graph.nodes.forEach((node, i) => indexOf.set(node.id, i))\n\n // Community ring anchors — used both as closed-form positions and as the\n // initial seed for force settlement, keeping clusters legible.\n const communityIndexById = new Map<string, number>()\n graph.communities.forEach((community, i) => communityIndexById.set(community.id, i))\n\n const x = new Float64Array(n)\n const y = new Float64Array(n)\n\n // --- Initial / closed-form positions ---------------------------------------\n graph.nodes.forEach((node, index) => {\n const angle = (Math.PI * 2 * index) / Math.max(1, n)\n const communityId = communityByNode.get(node.id)\n const communityIndex = communityId !== undefined ? communityIndexById.get(communityId) ?? -1 : -1\n const communityAngle =\n (Math.PI * 2 * Math.max(0, communityIndex)) / Math.max(1, graph.communities.length)\n const useCommunityOrbit = algorithm === 'community' || algorithm === 'force'\n const communityRadius = algorithm === 'community' ? radius * 0.55 : radius\n const localRadius =\n algorithm === 'force'\n ? radius * (0.7 + ((degree.get(node.id) ?? 0) % 4) * 0.08)\n : radius\n\n if (useCommunityOrbit && communityIndex >= 0) {\n x[index] = centerX + Math.cos(communityAngle) * communityRadius + Math.cos(angle) * 46\n y[index] = centerY + Math.sin(communityAngle) * communityRadius + Math.sin(angle) * 46\n } else {\n x[index] = centerX + Math.cos(angle) * localRadius\n y[index] =\n centerY + Math.sin(angle) * (algorithm === 'radial' ? radius : localRadius * 0.72)\n }\n })\n\n // Warm-start seed then pin overrides (issue #245). Warm start lets a re-layout\n // resume from the current arrangement; pinned coordinates win outright.\n const pinnedIndex = new Map<number, { x: number; y: number }>()\n // Nodes with a real seed (warm start or pin) already have distinct positions,\n // so they are exempt from the separation jitter below.\n const seededIndex = new Set<number>()\n graph.nodes.forEach((node, index) => {\n const seed = readPosition(options.initialPositions, node.id)\n if (seed) {\n x[index] = seed.x\n y[index] = seed.y\n seededIndex.add(index)\n }\n const pin = readPosition(options.pinned, node.id)\n if (pin) {\n x[index] = pin.x\n y[index] = pin.y\n pinnedIndex.set(index, pin)\n seededIndex.add(index)\n }\n })\n const holdPinned = () => {\n for (const [index, pos] of pinnedIndex) {\n x[index] = pos.x\n y[index] = pos.y\n }\n }\n\n // --- Force settlement (force algorithm only) -------------------------------\n if (algorithm === 'force' && n > 1) {\n const ticks = Math.max(0, Math.floor(options.ticks ?? DEFAULTS.ticks))\n const seed = options.seed ?? DEFAULTS.seed\n const linkDistance = options.linkDistance ?? DEFAULTS.linkDistance\n const linkStrength = options.linkStrength ?? DEFAULTS.linkStrength\n const chargeStrength = options.chargeStrength ?? DEFAULTS.chargeStrength\n const collisionPadding = options.collisionPadding ?? DEFAULTS.collisionPadding\n const communityStrength = options.communityStrength ?? DEFAULTS.communityStrength\n\n const rng = mulberry32(seed)\n // Deterministic jitter so no two seeded nodes coincide (avoids div-by-zero).\n // Pinned nodes are left exactly where they were placed. When nothing is\n // pinned the branch never fires, so unpinned output is bit-for-bit identical.\n for (let i = 0; i < n; i++) {\n if (seededIndex.has(i)) continue\n x[i] += (rng() - 0.5) * 8\n y[i] += (rng() - 0.5) * 8\n }\n\n // Pre-resolve edge endpoints to array indices once.\n const links: Array<{ a: number; b: number; weight: number }> = []\n for (const edge of graph.edges) {\n const a = indexOf.get(edge.source)\n const b = indexOf.get(edge.target)\n if (a === undefined || b === undefined || a === b) continue\n links.push({ a, b, weight: edge.weight > 0 ? edge.weight : 1 })\n }\n\n // Community membership as array indices, for centroid cohesion.\n const communityOf = graph.nodes.map((node) => communityByNode.get(node.id))\n const communityIds = graph.communities.map((c) => c.id)\n\n const dispX = new Float64Array(n)\n const dispY = new Float64Array(n)\n const chargeCutoff = linkDistance * 6\n const cooling = ticks > 0 ? Math.pow(0.001, 1 / ticks) : 1\n let alpha = 1\n\n for (let t = 0; t < ticks; t++) {\n dispX.fill(0)\n dispY.fill(0)\n\n // Spring link attraction toward linkDistance.\n for (const link of links) {\n let dx = x[link.b] - x[link.a]\n let dy = y[link.b] - y[link.a]\n const dist = Math.max(0.01, Math.hypot(dx, dy))\n const force = ((dist - linkDistance) / dist) * linkStrength * link.weight\n dx *= force\n dy *= force\n dispX[link.a] += dx\n dispY[link.a] += dy\n dispX[link.b] -= dx\n dispY[link.b] -= dy\n }\n\n // Pairwise charge repulsion (with a distance cutoff for dense graphs).\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n const dx = x[i] - x[j]\n const dy = y[i] - y[j]\n const dist = Math.max(0.01, Math.hypot(dx, dy))\n if (dist > chargeCutoff) continue\n // chargeStrength is negative ⇒ repulsion magnitude is positive.\n const mag = -chargeStrength / dist\n const ux = (dx / dist) * mag\n const uy = (dy / dist) * mag\n dispX[i] += ux\n dispY[i] += uy\n dispX[j] -= ux\n dispY[j] -= uy\n }\n }\n\n // Community cohesion (toward centroid) + global centering gravity.\n if (communityStrength > 0 && communityIds.length > 0) {\n const cx = new Float64Array(communityIds.length)\n const cy = new Float64Array(communityIds.length)\n const cn = new Int32Array(communityIds.length)\n const idxById = new Map<string, number>()\n communityIds.forEach((id, i) => idxById.set(id, i))\n for (let i = 0; i < n; i++) {\n const cid = communityOf[i]\n if (cid === undefined) continue\n const ci = idxById.get(cid)\n if (ci === undefined) continue\n cx[ci] += x[i]\n cy[ci] += y[i]\n cn[ci] += 1\n }\n for (let i = 0; i < n; i++) {\n const cid = communityOf[i]\n if (cid === undefined) continue\n const ci = idxById.get(cid)\n if (ci === undefined || cn[ci] === 0) continue\n dispX[i] += (cx[ci] / cn[ci] - x[i]) * communityStrength\n dispY[i] += (cy[ci] / cn[ci] - y[i]) * communityStrength\n }\n }\n for (let i = 0; i < n; i++) {\n dispX[i] += (centerX - x[i]) * GRAVITY\n dispY[i] += (centerY - y[i]) * GRAVITY\n }\n\n // Apply soft forces, cooled by alpha.\n for (let i = 0; i < n; i++) {\n x[i] += dispX[i] * alpha\n y[i] += dispY[i] * alpha\n }\n\n // Hard collision resolution (full strength) so nodes don't overlap.\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n const dx = x[i] - x[j]\n const dy = y[i] - y[j]\n const dist = Math.max(0.01, Math.hypot(dx, dy))\n const minDist = r[i] + r[j] + collisionPadding\n if (dist >= minDist) continue\n const push = (minDist - dist) / 2\n const ux = (dx / dist) * push\n const uy = (dy / dist) * push\n x[i] += ux\n y[i] += uy\n x[j] -= ux\n y[j] -= uy\n }\n }\n\n // Clamp inside the padded canvas every tick.\n for (let i = 0; i < n; i++) {\n x[i] = clampToRange(x[i], boundsPadding + r[i], width - boundsPadding - r[i])\n y[i] = clampToRange(y[i], boundsPadding + r[i], height - boundsPadding - r[i])\n }\n\n // Re-assert pinned positions last so pins hold exactly and neighbors\n // settle around them.\n holdPinned()\n\n alpha *= cooling\n }\n } else {\n // Closed-form algorithms: still honor the bounds clamp, then hold pins.\n for (let i = 0; i < n; i++) {\n x[i] = clampToRange(x[i], boundsPadding + r[i], width - boundsPadding - r[i])\n y[i] = clampToRange(y[i], boundsPadding + r[i], height - boundsPadding - r[i])\n }\n holdPinned()\n }\n\n // --- Build the result ------------------------------------------------------\n const nodes = graph.nodes.map((node, index): PositionedGraphNode => ({\n ...node,\n x: x[index],\n y: y[index],\n r: r[index],\n degree: degree.get(node.id) ?? 0,\n communityId: communityByNode.get(node.id),\n }))\n\n const nodeIndex = new Map(nodes.map((node) => [node.id, node]))\n\n const communities: PositionedCommunity[] = graph.communities.map((community) => {\n let sx = 0\n let sy = 0\n let size = 0\n for (const nodeId of community.nodes) {\n const positioned = nodeIndex.get(nodeId)\n if (!positioned) continue\n sx += positioned.x\n sy += positioned.y\n size += 1\n }\n return size > 0\n ? { id: community.id, x: sx / size, y: sy / size, size }\n : { id: community.id, x: centerX, y: centerY, size: 0 }\n })\n\n return { nodes, edges: graph.edges, nodeIndex, communities }\n}\n","import type { GraphBounds, PositionedGraphNode, ViewportTransform } from './types.js'\n\nconst EMPTY_BOUNDS: GraphBounds = {\n minX: 0,\n minY: 0,\n maxX: 0,\n maxY: 0,\n width: 0,\n height: 0,\n centerX: 0,\n centerY: 0,\n}\n\n/**\n * Compute the axis-aligned bounding box around a set of positioned nodes.\n * Returns an all-zero box for an empty input.\n */\nexport function computeGraphBounds(\n nodes: ReadonlyArray<Pick<PositionedGraphNode, 'x' | 'y'>>,\n): GraphBounds {\n if (nodes.length === 0) return { ...EMPTY_BOUNDS }\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const node of nodes) {\n if (node.x < minX) minX = node.x\n if (node.y < minY) minY = node.y\n if (node.x > maxX) maxX = node.x\n if (node.y > maxY) maxY = node.y\n }\n return {\n minX,\n minY,\n maxX,\n maxY,\n width: maxX - minX,\n height: maxY - minY,\n centerX: (minX + maxX) / 2,\n centerY: (minY + maxY) / 2,\n }\n}\n\nexport interface FitOptions {\n /** Uniform padding (in viewport units) to leave around the graph. */\n padding?: number\n /** Clamp the computed scale to this minimum. */\n minScale?: number\n /** Clamp the computed scale to this maximum. */\n maxScale?: number\n}\n\n/**\n * Compute a {@link ViewportTransform} (uniform scale + translation) that fits\n * `bounds` centered within a `viewport` of the given width/height. Apply the\n * result as `translate(offsetX, offsetY) scale(scale)` in SVG/canvas space.\n */\nexport function fitGraphToViewport(\n bounds: GraphBounds,\n viewport: { width: number; height: number },\n options: FitOptions = {},\n): ViewportTransform {\n const padding = options.padding ?? 0\n const minScale = options.minScale ?? 0\n const maxScale = options.maxScale ?? Infinity\n\n const availableWidth = Math.max(0, viewport.width - padding * 2)\n const availableHeight = Math.max(0, viewport.height - padding * 2)\n\n let scale = 1\n if (bounds.width > 0 || bounds.height > 0) {\n const scaleX = bounds.width > 0 ? availableWidth / bounds.width : Infinity\n const scaleY = bounds.height > 0 ? availableHeight / bounds.height : Infinity\n scale = Math.min(scaleX, scaleY)\n }\n if (!Number.isFinite(scale) || scale <= 0) scale = 1\n scale = Math.max(minScale, Math.min(maxScale, scale))\n\n const offsetX = viewport.width / 2 - bounds.centerX * scale\n const offsetY = viewport.height / 2 - bounds.centerY * scale\n return { scale, offsetX, offsetY }\n}\n","import { filterCommunityGraph } from './filter.js'\nimport type { CommunityGraph } from './types.js'\n\n/** Build an undirected adjacency map from a graph's edges. */\nexport function buildAdjacency(graph: CommunityGraph): Map<string, Set<string>> {\n const adjacency = new Map<string, Set<string>>()\n const ensure = (id: string) => {\n let set = adjacency.get(id)\n if (!set) {\n set = new Set<string>()\n adjacency.set(id, set)\n }\n return set\n }\n for (const node of graph.nodes) ensure(node.id)\n for (const edge of graph.edges) {\n ensure(edge.source).add(edge.target)\n ensure(edge.target).add(edge.source)\n }\n return adjacency\n}\n\n/** Return the set of node ids directly adjacent to `nodeId` (excludes itself). */\nexport function neighborsOf(graph: CommunityGraph, nodeId: string): Set<string> {\n return new Set(buildAdjacency(graph).get(nodeId) ?? [])\n}\n\nexport interface ExpandOptions {\n /** How many edge-hops to traverse from the seeds. Default 1. */\n depth?: number\n /** Include the seed ids in the result. Default true. */\n includeSeeds?: boolean\n}\n\n/**\n * Breadth-first expansion of one or more seed nodes out to `depth` hops.\n * Returns the set of reached node ids (seeds included by default).\n */\nexport function expandNeighborhood(\n graph: CommunityGraph,\n seeds: Iterable<string>,\n options: ExpandOptions = {},\n): Set<string> {\n const depth = options.depth ?? 1\n const includeSeeds = options.includeSeeds ?? true\n const adjacency = buildAdjacency(graph)\n\n const seen = new Set<string>()\n let frontier = new Set<string>()\n for (const seed of seeds) {\n if (adjacency.has(seed) || depth === 0) {\n seen.add(seed)\n frontier.add(seed)\n }\n }\n\n for (let hop = 0; hop < depth; hop++) {\n const next = new Set<string>()\n for (const id of frontier) {\n for (const neighbor of adjacency.get(id) ?? []) {\n if (!seen.has(neighbor)) {\n seen.add(neighbor)\n next.add(neighbor)\n }\n }\n }\n if (next.size === 0) break\n frontier = next\n }\n\n if (!includeSeeds) {\n for (const seed of seeds) seen.delete(seed)\n }\n return seen\n}\n\n/**\n * Extract the induced subgraph over `nodeIds` — a {@link CommunityGraph}\n * containing only those nodes, the edges between them, and the trimmed\n * community memberships. Thin wrapper over {@link filterCommunityGraph}.\n */\nexport function subgraphForNodes(graph: CommunityGraph, nodeIds: Iterable<string>): CommunityGraph {\n return filterCommunityGraph(graph, { nodeIds: Array.from(nodeIds) })\n}\n\n/**\n * Convenience: the induced subgraph of a seed node plus its `depth`-hop\n * neighborhood. Useful for \"expand selection\" interactions.\n */\nexport function neighborhoodSubgraph(\n graph: CommunityGraph,\n seeds: Iterable<string>,\n options: ExpandOptions = {},\n): CommunityGraph {\n return subgraphForNodes(graph, expandNeighborhood(graph, seeds, options))\n}\n","import type { CommunityGraph, GraphLayoutAlgorithm } from './types.js'\n\n/** Current on-disk version for {@link GraphSnapshot}. */\nexport const GRAPH_SNAPSHOT_VERSION = 1\n\n/**\n * A self-contained, serializable representation of a community graph plus the\n * layout intent used to render it. Designed to be written to a static JSON file\n * and consumed by a JS-only host (e.g. a documentation site) without recomputing\n * the graph.\n */\nexport interface GraphSnapshot {\n version: number\n graph: CommunityGraph\n layout?: {\n algorithm: GraphLayoutAlgorithm\n width: number\n height: number\n }\n generatedAt?: string\n}\n\nexport interface SerializeSnapshotOptions {\n layout?: GraphSnapshot['layout']\n /** ISO timestamp to stamp into the snapshot. Omit for reproducible output. */\n generatedAt?: string\n}\n\nfunction sortedGraph(graph: CommunityGraph): CommunityGraph {\n return {\n nodes: [...graph.nodes].sort((a, b) => a.id.localeCompare(b.id)),\n edges: [...graph.edges].sort((a, b) => (\n a.source.localeCompare(b.source)\n || a.target.localeCompare(b.target)\n || (a.kind ?? '').localeCompare(b.kind ?? '')\n )),\n communities: [...graph.communities]\n .map((community) => ({ ...community, nodes: [...community.nodes].sort() }))\n .sort((a, b) => a.id.localeCompare(b.id)),\n }\n}\n\n/**\n * Build a deterministic {@link GraphSnapshot} from a graph. Nodes, edges, and\n * community members are sorted so that equal graphs serialize identically\n * (stable diffs, content-addressable caching).\n */\nexport function serializeGraphSnapshot(\n graph: CommunityGraph,\n options: SerializeSnapshotOptions = {},\n): GraphSnapshot {\n const snapshot: GraphSnapshot = {\n version: GRAPH_SNAPSHOT_VERSION,\n graph: sortedGraph(graph),\n }\n if (options.layout) snapshot.layout = options.layout\n if (options.generatedAt) snapshot.generatedAt = options.generatedAt\n return snapshot\n}\n\n/** Stable JSON string for a graph snapshot. */\nexport function stringifyGraphSnapshot(\n graph: CommunityGraph,\n options: SerializeSnapshotOptions = {},\n): string {\n return JSON.stringify(serializeGraphSnapshot(graph, options))\n}\n\n/**\n * Validate and unwrap a {@link GraphSnapshot} (or its JSON string) back into a\n * {@link CommunityGraph}. Throws on shape/version mismatch.\n */\nexport function deserializeGraphSnapshot(input: GraphSnapshot | string): CommunityGraph {\n const snapshot: unknown = typeof input === 'string' ? JSON.parse(input) : input\n if (!snapshot || typeof snapshot !== 'object') {\n throw new Error('invalid graph snapshot: not an object')\n }\n const candidate = snapshot as Partial<GraphSnapshot>\n if (candidate.version !== GRAPH_SNAPSHOT_VERSION) {\n throw new Error(`unsupported graph snapshot version: ${String(candidate.version)}`)\n }\n const graph = candidate.graph\n if (\n !graph\n || !Array.isArray(graph.nodes)\n || !Array.isArray(graph.edges)\n || !Array.isArray(graph.communities)\n ) {\n throw new Error('invalid graph snapshot: missing graph nodes/edges/communities')\n }\n return graph\n}\n","// Render-prep + snapshot warm-start helpers (issue #264).\n//\n// Consumers (JS-only SVG #259, React GraphView, the interactive 2D/3D tiers)\n// all need the same two things a live `GraphController` build does not give\n// them directly:\n//\n// 1. a CommunityGraph → render-ready mapping (labels, degree-derived size,\n// per-community tone, and baked positions when available), and\n// 2. an instant \"snapshot-first\" load of a precomputed graph with baked x/y,\n// falling back to a live build when no snapshot exists.\n//\n// Both are generic and framework-agnostic, so they live here in @fortemi/graph\n// and every renderer shares them — the runtime loader and the build-time writer\n// map through the same `mapCommunityGraph` so on-disk snapshots and live builds\n// render identically.\n\nimport type { CommunityGraph } from './types.js'\nimport { computeDegrees, nodeRadius, type NodeRadiusOptions } from './degree.js'\nimport { colorForCommunity, UNASSIGNED_COMMUNITY_COLOR } from './color.js'\nimport { layoutCommunityGraph } from './layout.js'\nimport type { LayoutOptions } from './layout.js'\n\n/**\n * Greyscale community ramp — warm-grey, darkest first, meant to sit on a light\n * (\"cream\") background. Index 0 (darkest) is the largest community. Strictly\n * greyscale so community tone reads as density, not category.\n */\nexport const GREYSCALE_COMMUNITY_RAMP = [\n '#2B2824',\n '#43403A',\n '#585149',\n '#6E665A',\n '#837A6B',\n '#968C7C',\n] as const\n\n/** A render-ready node: identity + label + degree-derived size + tone + optional baked position. */\nexport interface RenderNode {\n id: string\n label: string\n /** Degree-derived render size. */\n size: number\n /** Community tone (see {@link CommunityPalette}). */\n color: string\n /** Community rank: 0 = largest community, ascending; -1 when unassigned. */\n communityRank: number\n /** Baked layout coordinate (present only when positions were supplied). */\n x?: number\n y?: number\n}\n\n/** A render-ready link (edge) referencing nodes by id. */\nexport interface RenderLink {\n source: string\n target: string\n weight: number\n kind?: string\n}\n\n/** A render-ready graph: the shape every renderer tier consumes. */\nexport interface RenderGraph {\n nodes: RenderNode[]\n links: RenderLink[]\n /** Number of communities in the source graph. */\n clusters: number\n}\n\n/**\n * Community coloring strategy for {@link mapCommunityGraph}:\n * - `'community'` (default): hash the community id into the qualitative palette\n * (matches the historical `GraphView` coloring).\n * - `'greyscale'`: {@link GREYSCALE_COMMUNITY_RAMP} indexed by community rank\n * (largest cluster = darkest).\n * - a custom array: indexed by community rank.\n */\nexport type CommunityPalette = 'community' | 'greyscale' | readonly string[]\n\nexport interface MapCommunityGraphOptions {\n /** Resolve a human label for a node id. Defaults to the id itself. */\n labelFor?: (id: string) => string\n /** Baked layout positions to stamp onto nodes (warm start). */\n positions?: Map<string, { x: number; y: number }> | Record<string, { x: number; y: number }>\n /** Community coloring strategy. Default `'community'`. */\n palette?: CommunityPalette\n /** Node-radius tuning passed to {@link nodeRadius} (default sizer). */\n radius?: NodeRadiusOptions\n /** Override the degree → size mapping entirely. */\n sizeFor?: (degree: number, id: string) => number\n}\n\nfunction positionGetter(\n positions: MapCommunityGraphOptions['positions'],\n): (id: string) => { x: number; y: number } | undefined {\n if (!positions) return () => undefined\n if (positions instanceof Map) return (id) => positions.get(id)\n return (id) => (Object.prototype.hasOwnProperty.call(positions, id) ? positions[id] : undefined)\n}\n\n/**\n * Rank communities by member count, largest first. Returns a map from community\n * id to its rank (0 = largest). Ties break on community id for determinism.\n */\nexport function communityRanks(graph: CommunityGraph): Map<string, number> {\n const rank = new Map<string, number>()\n ;[...graph.communities]\n .sort((a, b) => b.nodes.length - a.nodes.length || a.id.localeCompare(b.id))\n .forEach((community, index) => rank.set(community.id, index))\n return rank\n}\n\nfunction colorForRank(\n communityId: string | undefined,\n rank: number,\n palette: CommunityPalette,\n): string {\n if (palette === 'community') return colorForCommunity(communityId)\n const ramp = palette === 'greyscale' ? GREYSCALE_COMMUNITY_RAMP : palette\n if (ramp.length === 0) return UNASSIGNED_COMMUNITY_COLOR\n if (rank < 0) return ramp[ramp.length - 1] // unassigned → lightest\n return ramp[rank % ramp.length]\n}\n\n/**\n * Map a {@link CommunityGraph} to a render-ready {@link RenderGraph}: labels,\n * degree-derived node size, per-community tone (largest cluster = darkest for\n * ramped palettes), and baked positions when supplied. Pure and deterministic —\n * shared by the runtime loader and the build-time snapshot writer so both render\n * identically.\n */\nexport function mapCommunityGraph(\n graph: CommunityGraph,\n options: MapCommunityGraphOptions = {},\n): RenderGraph {\n const palette = options.palette ?? 'community'\n const labelFor = options.labelFor ?? ((id: string) => id)\n const getPos = positionGetter(options.positions)\n const sizeFor =\n options.sizeFor ?? ((degree: number) => nodeRadius(degree, options.radius))\n\n const degrees = computeDegrees(graph)\n const rankByComm = communityRanks(graph)\n const commOfNode = new Map<string, string>()\n for (const community of graph.communities) {\n for (const id of community.nodes) commOfNode.set(id, community.id)\n }\n\n const nodes: RenderNode[] = graph.nodes.map((node) => {\n const communityId = commOfNode.get(node.id)\n const rank = communityId != null ? rankByComm.get(communityId) ?? -1 : -1\n const degree = degrees.get(node.id) ?? 0\n const pos = getPos(node.id)\n const rendered: RenderNode = {\n id: node.id,\n label: labelFor(node.id),\n size: sizeFor(degree, node.id),\n color: colorForRank(communityId, rank, palette),\n communityRank: rank,\n }\n if (pos) {\n rendered.x = pos.x\n rendered.y = pos.y\n }\n return rendered\n })\n\n const links: RenderLink[] = graph.edges.map((edge) => {\n const link: RenderLink = { source: edge.source, target: edge.target, weight: edge.weight }\n if (edge.kind !== undefined) link.kind = edge.kind\n return link\n })\n\n return { nodes, links, clusters: graph.communities.length }\n}\n\nexport interface BakeRenderGraphOptions extends MapCommunityGraphOptions {\n /** Layout options for the one-shot build-time layout pass. */\n layout?: LayoutOptions\n}\n\n/**\n * Build-time snapshot writer: run the layout once and emit a {@link RenderGraph}\n * with baked x/y so hosts can warm-start (skip the layout pass) at runtime.\n * Companion to `serializeGraphSnapshot` — this bakes render-ready positions\n * rather than storing the raw graph + layout intent. Any `positions` passed in\n * options are ignored in favor of the freshly computed layout.\n */\nexport function bakeRenderGraph(\n graph: CommunityGraph,\n options: BakeRenderGraphOptions = {},\n): RenderGraph {\n const positioned = layoutCommunityGraph(graph, options.layout)\n const positions = new Map<string, { x: number; y: number }>()\n for (const node of positioned.nodes) positions.set(node.id, { x: node.x, y: node.y })\n // Re-map with the freshly computed positions; any `positions` passed in are ignored.\n const mapOptions: MapCommunityGraphOptions = { positions }\n if (options.labelFor) mapOptions.labelFor = options.labelFor\n if (options.palette) mapOptions.palette = options.palette\n if (options.radius) mapOptions.radius = options.radius\n if (options.sizeFor) mapOptions.sizeFor = options.sizeFor\n return mapCommunityGraph(graph, mapOptions)\n}\n\n/** Deterministic JSON for a render graph (stable key order for cache-friendly diffs). */\nexport function stringifyRenderGraph(graph: RenderGraph): string {\n const nodes = [...graph.nodes].sort((a, b) => a.id.localeCompare(b.id))\n const links = [...graph.links].sort(\n (a, b) =>\n a.source.localeCompare(b.source)\n || a.target.localeCompare(b.target)\n || (a.kind ?? '').localeCompare(b.kind ?? ''),\n )\n return JSON.stringify({ nodes, links, clusters: graph.clusters })\n}\n\n/** Structural guard for a {@link RenderGraph} loaded from an untrusted source. */\nexport function isRenderGraph(value: unknown): value is RenderGraph {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Partial<RenderGraph>\n return (\n Array.isArray(candidate.nodes)\n && candidate.nodes.length > 0\n && Array.isArray(candidate.links)\n && candidate.nodes.every(\n (n) => n && typeof n.id === 'string' && typeof n.size === 'number' && typeof n.color === 'string',\n )\n )\n}\n\n/** Whether every node in a render graph carries a baked position. */\nexport function hasBakedPositions(graph: RenderGraph): boolean {\n return graph.nodes.every((n) => typeof n.x === 'number' && typeof n.y === 'number')\n}\n\nexport interface LoadRenderSnapshotOptions {\n /** `fetch` implementation to use when `source` is a URL. Defaults to `globalThis.fetch`. */\n fetchImpl?: typeof fetch\n /** Require baked x/y on every node; a snapshot without positions resolves to `null`. Default `true`. */\n requirePositions?: boolean\n}\n\n/**\n * Snapshot-first loader (issue #264). Load a precomputed, render-ready graph\n * carrying baked positions — instant, no live `GraphController` build and no\n * layout pass. Accepts a URL to fetch, an already-parsed {@link RenderGraph}, or\n * a thunk. Returns `null` (never throws) when the snapshot is absent, malformed,\n * or lacks baked positions, so callers fall back to a live build + `mapCommunityGraph`.\n */\nexport async function loadRenderSnapshot(\n source: string | RenderGraph | (() => Promise<RenderGraph | null> | RenderGraph | null),\n options: LoadRenderSnapshotOptions = {},\n): Promise<RenderGraph | null> {\n const requirePositions = options.requirePositions ?? true\n try {\n let data: unknown\n if (typeof source === 'string') {\n const fetchImpl = options.fetchImpl ?? (globalThis.fetch as typeof fetch | undefined)\n if (!fetchImpl) return null\n const res = await fetchImpl(source)\n if (!res.ok) return null\n data = await res.json()\n } else if (typeof source === 'function') {\n data = await source()\n } else {\n data = source\n }\n if (!isRenderGraph(data)) return null\n if (requirePositions && !hasBakedPositions(data)) return null\n return data\n } catch {\n return null\n }\n}\n","// Shared renderer control contract (#260).\n//\n// Every community-graph renderer tier — the JS-only SVG renderer (#259), the\n// React `GraphView`, and the heavier interactive tiers (Sigma 2D #263, 3D #262)\n// — honors this control/options surface so consumers can swap tiers without\n// rewiring. Renderer-specific option types extend `GraphControlContract`; the\n// shared filter semantics (community / edge-kind / node allow-list / min-degree)\n// live in `applyControlFilters` so every tier filters identically.\n\nimport { colorForCommunity } from './color.js'\nimport { computeDegrees } from './degree.js'\nimport { filterCommunityGraph } from './filter.js'\nimport type { CommunityGraph, GraphLayoutAlgorithm } from './types.js'\n\n/** Node/edge visibility filter shared by every renderer tier. */\nexport interface GraphControlFilters {\n /** Keep only nodes in these communities. */\n communityIds?: string[]\n /** Keep only edges whose `kind` is in this set. */\n edgeKinds?: string[]\n /** Explicit node allow-list. */\n nodeIds?: string[]\n /** Hide nodes with fewer than this many connections (degree) in the visible set. */\n minDegree?: number\n}\n\n/**\n * The control surface common to all renderer tiers. A consumer coded against\n * this contract can move a graph between the JS-only renderer, React\n * `GraphView`, and future tiers by passing the same options object.\n */\nexport interface GraphControlContract {\n /** Layout algorithm. Default `force`. */\n algorithm?: GraphLayoutAlgorithm\n /** Visibility filter. */\n filters?: GraphControlFilters\n /** Selected node id (controlled). */\n selectedNodeId?: string | null\n /** Selection callback (click / keyboard). */\n onSelectNode?: (nodeId: string) => void\n /** Navigation callback (double-click / Enter on a selected node). */\n onNavigate?: (nodeId: string) => void\n /** Human label for a node (popup / a11y). Default: the node id. */\n labelFor?: (nodeId: string) => string\n /** Community palette override. */\n colors?: readonly string[]\n /** Logical viewport size. */\n width?: number\n height?: number\n}\n\n/** One community-legend row: community id, its color, and member count. */\nexport interface GraphLegendEntry {\n communityId: string\n color: string\n count: number\n}\n\n/**\n * Apply the shared {@link GraphControlFilters} to `graph`. Composes the engine's\n * community / edge-kind / node-allow-list filter with a `minDegree` pass\n * (degree computed over the already-filtered set). Pure — input is not mutated.\n */\nexport function applyControlFilters(\n graph: CommunityGraph | null | undefined,\n filters?: GraphControlFilters,\n): CommunityGraph {\n const base = filterCommunityGraph(graph, filters)\n const minDegree = filters?.minDegree ?? 0\n if (minDegree <= 0) return base\n const degree = computeDegrees(base)\n const keep = base.nodes.filter((n) => (degree.get(n.id) ?? 0) >= minDegree).map((n) => n.id)\n if (keep.length === base.nodes.length) return base\n return filterCommunityGraph(base, { nodeIds: keep })\n}\n\n/**\n * Build community-legend rows for a graph — the shared data that any tier can\n * render as a legend and use to drive the `communityIds` show/hide filter.\n * Sorted by member count (largest first). Colors match `colorForCommunity`.\n */\nexport function communityLegend(\n graph: CommunityGraph | null | undefined,\n colors?: readonly string[],\n): GraphLegendEntry[] {\n if (!graph) return []\n return graph.communities\n .map((c) => ({\n communityId: c.id,\n color: colorForCommunity(c.id, colors),\n count: c.nodes.length,\n }))\n .sort((a, b) => b.count - a.count || a.communityId.localeCompare(b.communityId))\n}\n","// Framework-agnostic DOM/SVG renderer for a CommunityGraph (#259).\n//\n// A batteries-included, dependency-free renderer that turns a CommunityGraph\n// into an interactive SVG view, reusing the engine (layoutCommunityGraph,\n// colorForCommunity, applyControlFilters, buildAdjacency) so it stays visually\n// identical to @fortemi/react's `GraphView`. No React, no sigma/graphology.\n//\n// Deterministic + headless-safe: layout is synchronous and seeded, and the DOM\n// is built without animation frames, so it renders identically in a browser,\n// jsdom, or an SSR-style document and can back static snapshots.\n\nimport { colorForCommunity } from './color.js'\nimport { applyControlFilters, type GraphControlContract, type GraphControlFilters } from './contract.js'\nimport { layoutCommunityGraph, type LayoutOptions } from './layout.js'\nimport { computeGraphBounds, fitGraphToViewport } from './bounds.js'\nimport { buildAdjacency } from './neighborhood.js'\nimport type { CommunityGraph, GraphLayoutAlgorithm, PositionedGraph } from './types.js'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** Filter shape accepted by the renderer — the shared control-filter contract. */\nexport type GraphRenderFilters = GraphControlFilters\n\n/**\n * Options for {@link renderCommunityGraph}. Extends the shared\n * {@link GraphControlContract} (algorithm, filters, selection, navigation,\n * labels, colors, size — honored by every renderer tier) with renderer-specific\n * knobs. The React `GraphView` honors the same contract, so the tiers are\n * drop-in swappable.\n */\nexport interface GraphRenderOptions extends GraphControlContract {\n /** Extra layout tuning forwarded to `layoutCommunityGraph`. */\n layoutOptions?: Omit<LayoutOptions, 'algorithm' | 'width' | 'height'>\n /** Canvas background. Default `#fafafa`. */\n background?: string\n /** Enable zoom/pan/hover interactions. Default `true`. */\n interactive?: boolean\n /** Zoom clamp. Default 0.4 / 3. */\n minScale?: number\n maxScale?: number\n}\n\n/** Mutable subset applied via {@link GraphRenderHandle.update}. */\nexport type GraphRenderUpdate = Partial<\n Pick<GraphRenderOptions, 'filters' | 'algorithm' | 'selectedNodeId' | 'labelFor'>\n> & { graph?: CommunityGraph }\n\n/** Live handle returned by {@link renderCommunityGraph}. */\nexport interface GraphRenderHandle {\n /** Apply new graph/filters/algorithm/selection without recreating the view. */\n update(next: GraphRenderUpdate): void\n /** Select and center a node (search/focus). Pass `null` to clear selection. */\n focus(nodeId: string | null): void\n /** Remove the view, its popup, and all listeners from the container. */\n destroy(): void\n /** The mounted `<svg>` element. */\n readonly element: SVGSVGElement\n}\n\nfunction el<K extends keyof SVGElementTagNameMap>(\n tag: K,\n attrs: Record<string, string | number>,\n): SVGElementTagNameMap[K] {\n const node = document.createElementNS(SVG_NS, tag)\n for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, String(v))\n return node\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, v))\n}\n\n/**\n * Render `graph` into `container` as an interactive SVG community graph.\n * Returns a {@link GraphRenderHandle}; call `destroy()` to tear it down.\n */\nexport function renderCommunityGraph(\n container: HTMLElement,\n graph: CommunityGraph,\n options: GraphRenderOptions = {},\n): GraphRenderHandle {\n const width = options.width ?? 760\n const height = options.height ?? 460\n const background = options.background ?? '#fafafa'\n const interactive = options.interactive ?? true\n const minScale = options.minScale ?? 0.4\n const maxScale = options.maxScale ?? 3\n\n // ── mutable state ─────────────────────────────────────────────────────────\n let currentGraph = graph\n let filters = options.filters\n let algorithm: GraphLayoutAlgorithm = options.algorithm ?? 'force'\n let selectedNodeId = options.selectedNodeId ?? null\n let labelFor = options.labelFor ?? ((id: string) => id)\n\n let visible: CommunityGraph = applyControlFilters(currentGraph, filters)\n let positioned: PositionedGraph = layoutCommunityGraph(visible, {\n algorithm,\n width,\n height,\n ...options.layoutOptions,\n })\n let adjacency = buildAdjacency(visible)\n\n const transform = { scale: 1, offsetX: 0, offsetY: 0 }\n\n // ── DOM scaffold ──────────────────────────────────────────────────────────\n if (getComputedPosition(container) === 'static') container.style.position = 'relative'\n\n const svg = el('svg', {\n role: 'img',\n 'aria-label': 'Community graph',\n viewBox: `0 0 ${width} ${height}`,\n width: '100%',\n })\n svg.style.display = 'block'\n svg.style.background = background\n svg.style.touchAction = 'none'\n ;(svg.style as CSSStyleDeclaration).aspectRatio = `${width} / ${height}`\n\n const viewport = el('g', {}) // pan/zoom transform group\n const edgesLayer = el('g', {})\n const nodesLayer = el('g', {})\n viewport.appendChild(edgesLayer)\n viewport.appendChild(nodesLayer)\n svg.appendChild(viewport)\n container.appendChild(svg)\n\n const popup = document.createElement('div')\n popup.setAttribute('data-fortemi-graph-popup', '')\n Object.assign(popup.style, {\n position: 'absolute',\n display: 'none',\n pointerEvents: 'none',\n padding: '2px 6px',\n font: '12px system-ui, sans-serif',\n background: '#111',\n color: '#fff',\n borderRadius: '4px',\n transform: 'translate(-50%, -130%)',\n whiteSpace: 'nowrap',\n zIndex: '2',\n } satisfies Partial<CSSStyleDeclaration>)\n container.appendChild(popup)\n\n // node id → its <circle> element, for restyle on select/hover.\n const circles = new Map<string, SVGCircleElement>()\n const lines: Array<{ line: SVGLineElement; source: string; target: string }> = []\n\n function applyTransform(): void {\n viewport.setAttribute(\n 'transform',\n `translate(${transform.offsetX} ${transform.offsetY}) scale(${transform.scale})`,\n )\n }\n\n function fitToViewport(): void {\n const bounds = computeGraphBounds(positioned.nodes)\n const fit = fitGraphToViewport(bounds, { width, height }, {\n padding: 24,\n minScale,\n maxScale,\n })\n transform.scale = fit.scale\n transform.offsetX = fit.offsetX\n transform.offsetY = fit.offsetY\n applyTransform()\n }\n\n function styleNode(id: string): void {\n const circle = circles.get(id)\n if (!circle) return\n const node = positioned.nodeIndex.get(id)\n if (!node) return\n const selected = id === selectedNodeId\n circle.setAttribute('r', String(selected ? node.r + 3 : node.r))\n circle.setAttribute('stroke', selected ? '#111' : '#fff')\n circle.setAttribute('stroke-width', selected ? '3' : '1.5')\n }\n\n function showPopup(id: string): void {\n const node = positioned.nodeIndex.get(id)\n if (!node) {\n popup.style.display = 'none'\n return\n }\n // node (user units) → screen: apply viewport transform, then SVG scale to px.\n const px = transform.offsetX + node.x * transform.scale\n const py = transform.offsetY + node.y * transform.scale\n const rect = svg.getBoundingClientRect?.()\n const scaleToPx = rect && rect.width ? rect.width / width : 1\n popup.textContent = labelFor(id)\n popup.style.left = `${px * scaleToPx}px`\n popup.style.top = `${py * scaleToPx}px`\n popup.style.display = 'block'\n }\n\n function setSelected(id: string | null, emit: boolean): void {\n const prev = selectedNodeId\n selectedNodeId = id\n if (prev && prev !== id) styleNode(prev)\n if (id) {\n styleNode(id)\n showPopup(id)\n if (emit) options.onSelectNode?.(id)\n } else {\n popup.style.display = 'none'\n }\n }\n\n function setHover(id: string | null): void {\n if (!interactive) return\n if (!id) {\n for (const [, c] of circles) c.style.opacity = '1'\n for (const { line } of lines) line.style.opacity = '0.55'\n return\n }\n const keep = new Set<string>(adjacency.get(id) ?? [])\n keep.add(id)\n for (const [nid, c] of circles) c.style.opacity = keep.has(nid) ? '1' : '0.15'\n for (const { line, source, target } of lines) {\n line.style.opacity = source === id || target === id ? '0.9' : '0.06'\n }\n }\n\n // ── (re)build the DOM for the current positioned graph ─────────────────────\n function build(): void {\n edgesLayer.replaceChildren()\n nodesLayer.replaceChildren()\n circles.clear()\n lines.length = 0\n\n for (const edge of positioned.edges) {\n const s = positioned.nodeIndex.get(edge.source)\n const t = positioned.nodeIndex.get(edge.target)\n if (!s || !t) continue\n const line = el('line', {\n x1: s.x,\n y1: s.y,\n x2: t.x,\n y2: t.y,\n stroke: '#9aa0a6',\n 'stroke-width': clamp(edge.weight, 1, 5),\n opacity: 0.55,\n })\n edgesLayer.appendChild(line)\n lines.push({ line, source: edge.source, target: edge.target })\n }\n\n for (const node of positioned.nodes) {\n const circle = el('circle', {\n cx: node.x,\n cy: node.y,\n r: node.r,\n fill: colorForCommunity(node.communityId, options.colors),\n stroke: '#fff',\n 'stroke-width': 1.5,\n tabindex: 0,\n role: 'button',\n 'data-node-id': node.id,\n 'aria-label': `Graph node ${labelFor(node.id)}`,\n })\n circle.style.cursor = 'pointer'\n circle.style.outline = 'none'\n const title = el('title', {})\n title.textContent = labelFor(node.id)\n circle.appendChild(title)\n\n if (interactive) {\n circle.addEventListener('click', (e) => {\n e.stopPropagation()\n setSelected(node.id, true)\n })\n circle.addEventListener('dblclick', (e) => {\n e.stopPropagation()\n options.onNavigate?.(node.id)\n })\n circle.addEventListener('mouseenter', () => setHover(node.id))\n circle.addEventListener('mouseleave', () => setHover(null))\n circle.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n if (selectedNodeId === node.id) options.onNavigate?.(node.id)\n else setSelected(node.id, true)\n }\n })\n }\n nodesLayer.appendChild(circle)\n circles.set(node.id, circle)\n }\n\n if (selectedNodeId && circles.has(selectedNodeId)) {\n styleNode(selectedNodeId)\n showPopup(selectedNodeId)\n } else {\n selectedNodeId = null\n popup.style.display = 'none'\n }\n }\n\n function relayout(): void {\n visible = applyControlFilters(currentGraph, filters)\n positioned = layoutCommunityGraph(visible, {\n algorithm,\n width,\n height,\n ...options.layoutOptions,\n })\n adjacency = buildAdjacency(visible)\n build()\n fitToViewport()\n }\n\n // ── interactions on the canvas (zoom + pan + deselect) ─────────────────────\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault()\n const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1\n transform.scale = clamp(transform.scale * factor, minScale, maxScale)\n applyTransform()\n if (selectedNodeId) showPopup(selectedNodeId)\n }\n let panning: { x: number; y: number } | null = null\n const onDown = (e: MouseEvent): void => {\n if (e.target === svg || e.target === viewport) {\n panning = { x: e.clientX, y: e.clientY }\n setSelected(null, true)\n }\n }\n const onMove = (e: MouseEvent): void => {\n if (!panning) return\n transform.offsetX += e.clientX - panning.x\n transform.offsetY += e.clientY - panning.y\n panning = { x: e.clientX, y: e.clientY }\n applyTransform()\n }\n const onUp = (): void => {\n panning = null\n }\n\n if (interactive) {\n svg.addEventListener('wheel', onWheel, { passive: false })\n svg.addEventListener('mousedown', onDown)\n svg.addEventListener('mousemove', onMove)\n svg.addEventListener('mouseup', onUp)\n svg.addEventListener('mouseleave', onUp)\n }\n\n // ── initial paint ──────────────────────────────────────────────────────────\n build()\n fitToViewport()\n\n return {\n element: svg,\n update(next: GraphRenderUpdate): void {\n let needsRelayout = false\n if (next.graph && next.graph !== currentGraph) {\n currentGraph = next.graph\n needsRelayout = true\n }\n if ('filters' in next) {\n filters = next.filters\n needsRelayout = true\n }\n if (next.algorithm && next.algorithm !== algorithm) {\n algorithm = next.algorithm\n needsRelayout = true\n }\n if (next.labelFor) labelFor = next.labelFor\n if (needsRelayout) relayout()\n if ('selectedNodeId' in next) setSelected(next.selectedNodeId ?? null, false)\n },\n focus(nodeId: string | null): void {\n if (!nodeId) {\n setSelected(null, false)\n return\n }\n const node = positioned.nodeIndex.get(nodeId)\n if (!node) return\n // Center the node in the viewport at the current scale.\n transform.offsetX = width / 2 - node.x * transform.scale\n transform.offsetY = height / 2 - node.y * transform.scale\n applyTransform()\n setSelected(nodeId, false)\n },\n destroy(): void {\n if (interactive) {\n svg.removeEventListener('wheel', onWheel)\n svg.removeEventListener('mousedown', onDown)\n svg.removeEventListener('mousemove', onMove)\n svg.removeEventListener('mouseup', onUp)\n svg.removeEventListener('mouseleave', onUp)\n }\n svg.remove()\n popup.remove()\n circles.clear()\n lines.length = 0\n },\n }\n}\n\nfunction getComputedPosition(elm: HTMLElement): string {\n const inline = elm.style.position\n if (inline) return inline\n const view = elm.ownerDocument?.defaultView\n if (view?.getComputedStyle) return view.getComputedStyle(elm).position || 'static'\n return 'static'\n}\n","// @fortemi/graph — framework-agnostic graph presentation/projection helpers\n// without the database-backed graph-source controller.\n//\n// This root entry intentionally has no runtime dependency on @fortemi/core, so\n// JS-only hosts can import graph helpers without pulling the PGlite module\n// graph. Database-backed graph-source orchestration lives at\n// @fortemi/graph/controller.\n//\n// Pure projection helpers (layout, filtering, coloring, sizing, bounds,\n// neighborhood, snapshot) give React and JS-only hosts the shared logic to\n// render their own SVG/canvas views.\n//\n// Community *detection* intentionally lives in @fortemi/core (the base layer);\n// this package only renders/projects graphs it is given and orchestrates which\n// source to load.\n\nexport const VERSION = '2026.9.3'\n\nexport type {\n GraphNode,\n GraphEdge,\n GraphCommunity,\n CommunityGraph,\n GraphLayoutAlgorithm,\n PositionedGraphNode,\n PositionedCommunity,\n PositionedGraph,\n GraphBounds,\n ViewportTransform,\n} from './types.js'\n\nexport { computeDegrees, nodeRadius } from './degree.js'\nexport type { NodeRadiusOptions } from './degree.js'\n\nexport { COMMUNITY_COLORS, UNASSIGNED_COMMUNITY_COLOR, colorForCommunity } from './color.js'\n\nexport { filterCommunityGraph } from './filter.js'\nexport type { GraphFilter } from './filter.js'\n\nexport { layoutCommunityGraph } from './layout.js'\nexport type { LayoutOptions, NodeRadiusResolver, PositionMap } from './layout.js'\n\nexport { computeGraphBounds, fitGraphToViewport } from './bounds.js'\nexport type { FitOptions } from './bounds.js'\n\nexport {\n buildAdjacency,\n neighborsOf,\n expandNeighborhood,\n subgraphForNodes,\n neighborhoodSubgraph,\n} from './neighborhood.js'\nexport type { ExpandOptions } from './neighborhood.js'\n\nexport {\n GRAPH_SNAPSHOT_VERSION,\n serializeGraphSnapshot,\n stringifyGraphSnapshot,\n deserializeGraphSnapshot,\n} from './serialize.js'\nexport type { GraphSnapshot, SerializeSnapshotOptions } from './serialize.js'\n\nexport {\n GREYSCALE_COMMUNITY_RAMP,\n communityRanks,\n mapCommunityGraph,\n bakeRenderGraph,\n stringifyRenderGraph,\n isRenderGraph,\n hasBakedPositions,\n loadRenderSnapshot,\n} from './render-prep.js'\nexport type {\n RenderNode,\n RenderLink,\n RenderGraph,\n CommunityPalette,\n MapCommunityGraphOptions,\n BakeRenderGraphOptions,\n LoadRenderSnapshotOptions,\n} from './render-prep.js'\n\nexport { applyControlFilters, communityLegend } from './contract.js'\nexport type {\n GraphControlContract,\n GraphControlFilters,\n GraphLegendEntry,\n} from './contract.js'\n\nexport { renderCommunityGraph } from './render-dom.js'\nexport type {\n GraphRenderOptions,\n GraphRenderFilters,\n GraphRenderUpdate,\n GraphRenderHandle,\n} from './render-dom.js'\n\nexport type {\n GraphControllerDb,\n GraphSourceMode,\n GraphLayoutState,\n GraphTransitionState,\n GraphControllerStatus,\n GraphSourceRef,\n GraphControllerState,\n GraphControllerOptions,\n GraphControllerListener,\n} from './controller.js'\n"]}
1
+ {"version":3,"sources":["../src/degree.ts","../src/color.ts","../src/filter.ts","../src/rng.ts","../src/layout.ts","../src/bounds.ts","../src/neighborhood.ts","../src/serialize.ts","../src/render-prep.ts","../src/contract.ts","../src/render-dom.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { CommunityGraph } from './types.js'\n\n/** Count the (undirected) degree of every node, including isolated nodes (0). */\nexport function computeDegrees(graph: CommunityGraph): Map<string, number> {\n const degree = new Map<string, number>()\n for (const node of graph.nodes) degree.set(node.id, 0)\n for (const edge of graph.edges) {\n degree.set(edge.source, (degree.get(edge.source) ?? 0) + 1)\n degree.set(edge.target, (degree.get(edge.target) ?? 0) + 1)\n }\n return degree\n}\n\nexport interface NodeRadiusOptions {\n /** Radius of a degree-0 node. */\n base?: number\n /** Pixels added per unit of degree. */\n perDegree?: number\n /** Hard floor on the radius. */\n min?: number\n /** Hard ceiling on the radius. */\n max?: number\n}\n\n/**\n * Map a node degree to a render radius. Defaults match the values historically\n * used by the React `GraphView`: `clamp(5 + degree * 1.5, 5, 16)`.\n */\nexport function nodeRadius(degree: number, options: NodeRadiusOptions = {}): number {\n const base = options.base ?? 5\n const perDegree = options.perDegree ?? 1.5\n const min = options.min ?? 5\n const max = options.max ?? 16\n return Math.max(min, Math.min(max, base + degree * perDegree))\n}\n","/** Default qualitative palette for community coloring (8 hues). */\nexport const COMMUNITY_COLORS = [\n '#2f6fbb',\n '#d97706',\n '#218838',\n '#7c3aed',\n '#c2410c',\n '#0f766e',\n '#be185d',\n '#4b5563',\n] as const\n\n/** Color used for nodes that are not assigned to any community. */\nexport const UNASSIGNED_COMMUNITY_COLOR = '#64748b'\n\n/**\n * Deterministically assign a color to a community id by hashing the id into the\n * palette. The same id always maps to the same color across runs and hosts.\n * Pass a custom `palette` to theme the output. Matches the historical\n * `GraphView` color assignment.\n */\nexport function colorForCommunity(\n communityId: string | undefined,\n palette: readonly string[] = COMMUNITY_COLORS,\n unassignedColor: string = UNASSIGNED_COMMUNITY_COLOR,\n): string {\n if (!communityId) return unassignedColor\n if (palette.length === 0) return unassignedColor\n let hash = 0\n for (const char of communityId) hash = (hash * 31 + char.charCodeAt(0)) | 0\n return palette[Math.abs(hash) % palette.length]\n}\n","import type { CommunityGraph, GraphNode } from './types.js'\n\nexport interface GraphFilter {\n /** Keep only nodes belonging to these communities (by community id). */\n communityIds?: string[]\n /** Keep only edges whose `kind` is in this set. */\n edgeKinds?: string[]\n /** Explicit allow-list of node ids. Useful for privacy / visibility filtering. */\n nodeIds?: string[]\n /**\n * Arbitrary per-node predicate evaluated against the (allow-listed) nodes.\n * Returning `false` removes the node and any edge touching it. Hosts whose\n * nodes carry extra metadata (privacy class, type, etc.) can filter on it here.\n */\n nodePredicate?: (node: GraphNode) => boolean\n}\n\n/**\n * Produce a new {@link CommunityGraph} containing only the nodes, edges, and\n * community memberships permitted by `filter`. Pure — the input is not mutated.\n *\n * Filtering precedence:\n * 1. `communityIds` (if non-empty) restricts the candidate node set to members\n * of those communities; otherwise `nodeIds` (if given) is the candidate set,\n * else all nodes.\n * 2. `nodePredicate` further narrows the candidate set.\n * 3. Edges survive only when both endpoints survive and `edgeKinds` permits.\n * 4. Empty communities are dropped.\n */\nexport function filterCommunityGraph(\n graph: CommunityGraph | null | undefined,\n filter?: GraphFilter,\n): CommunityGraph {\n if (!graph) return { nodes: [], edges: [], communities: [] }\n\n const nodeIds = new Set(filter?.nodeIds ?? graph.nodes.map((node) => node.id))\n if (filter?.communityIds?.length) {\n const allowedCommunities = new Set(filter.communityIds)\n nodeIds.clear()\n for (const community of graph.communities) {\n if (allowedCommunities.has(community.id)) {\n for (const nodeId of community.nodes) nodeIds.add(nodeId)\n }\n }\n }\n\n const predicate = filter?.nodePredicate\n if (predicate) {\n for (const node of graph.nodes) {\n if (nodeIds.has(node.id) && !predicate(node)) nodeIds.delete(node.id)\n }\n }\n\n const edgeKinds = filter?.edgeKinds ? new Set(filter.edgeKinds) : null\n const nodes = graph.nodes.filter((node) => nodeIds.has(node.id))\n const edges = graph.edges.filter((edge) => (\n nodeIds.has(edge.source)\n && nodeIds.has(edge.target)\n && (!edgeKinds || edgeKinds.has(edge.kind ?? ''))\n ))\n const communities = graph.communities\n .map((community) => ({ ...community, nodes: community.nodes.filter((nodeId) => nodeIds.has(nodeId)) }))\n .filter((community) => community.nodes.length > 0)\n return { nodes, edges, communities }\n}\n","// Tiny deterministic PRNG (mulberry32). Used by the force layout to seed\n// initial jitter so that identical (seed, graph, options) always yields\n// identical coordinates — no Math.random, no time, no platform variance.\n\n/**\n * Create a deterministic pseudo-random generator from a 32-bit integer seed.\n * Returns a function producing floats in [0, 1). Identical seeds yield\n * identical sequences across platforms.\n */\nexport function mulberry32(seed: number): () => number {\n // Coerce to a non-zero unsigned 32-bit integer so seed 0 still advances.\n let a = (seed >>> 0) || 0x9e3779b9\n return function next(): number {\n a |= 0\n a = (a + 0x6d2b79f5) | 0\n let t = Math.imul(a ^ (a >>> 15), 1 | a)\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n","import { computeDegrees, nodeRadius as defaultNodeRadius, type NodeRadiusOptions } from './degree.js'\nimport { mulberry32 } from './rng.js'\nimport type {\n CommunityGraph,\n GraphLayoutAlgorithm,\n GraphNode,\n PositionedCommunity,\n PositionedGraph,\n PositionedGraphNode,\n} from './types.js'\n\n/**\n * How to derive each node's render radius. Either a fixed pixel value, a set of\n * {@link NodeRadiusOptions} fed to the default degree→radius mapping, or a full\n * resolver `(degree, node) => number`.\n */\nexport type NodeRadiusResolver =\n | number\n | NodeRadiusOptions\n | ((degree: number, node: GraphNode) => number)\n\nexport interface LayoutOptions {\n /** Layout algorithm. `force` runs deterministic settlement; the others are closed-form. */\n algorithm?: GraphLayoutAlgorithm\n width?: number\n height?: number\n /** Seed for the deterministic PRNG used by `force` initial jitter. Identical seed ⇒ identical output. */\n seed?: number\n /** Number of settlement iterations for the `force` algorithm. */\n ticks?: number\n /** Per-node render radius (default: degree-derived, clamped 5..16). */\n nodeRadius?: NodeRadiusResolver\n /** Target edge length in px for the spring force (`force` only). */\n linkDistance?: number\n /** Spring stiffness 0..1 (`force` only). */\n linkStrength?: number\n /** Repulsion magnitude; negative pushes nodes apart (`force` only). */\n chargeStrength?: number\n /** Extra spacing beyond `r_i + r_j` when resolving collisions (`force` only). */\n collisionPadding?: number\n /** Pull toward the node's community centroid, 0..1 (`force` only). */\n communityStrength?: number\n /** Keep every node center at least this many px from each canvas edge. */\n boundsPadding?: number\n /**\n * Positions to hold FIXED during settlement (drag pins, issue #245). Pinned\n * nodes stay put while the rest of the graph re-settles around them, giving an\n * incremental re-layout when a node is moved. Keyed by node id.\n */\n pinned?: PositionMap\n /**\n * Warm-start seed positions. Nodes present here begin the settlement from\n * these coordinates instead of the closed-form ring, so a re-layout resumes\n * from the current arrangement (smooth reshape) rather than re-seeding. Keyed\n * by node id. `pinned` overrides this for pinned nodes.\n */\n initialPositions?: PositionMap\n}\n\n/** A node-id → position lookup, accepted as either a Map or a plain record. */\nexport type PositionMap =\n | Map<string, { x: number; y: number }>\n | Record<string, { x: number; y: number }>\n\nfunction readPosition(\n map: PositionMap | undefined,\n id: string,\n): { x: number; y: number } | undefined {\n if (!map) return undefined\n if (map instanceof Map) return map.get(id)\n return Object.prototype.hasOwnProperty.call(map, id) ? map[id] : undefined\n}\n\nconst DEFAULTS = {\n width: 760,\n height: 460,\n seed: 1,\n ticks: 300,\n linkDistance: 60,\n linkStrength: 0.08,\n chargeStrength: -240,\n collisionPadding: 2,\n communityStrength: 0.05,\n boundsPadding: 24,\n} as const\n\n/** Mild global pull toward the canvas center so disconnected nodes don't drift. */\nconst GRAVITY = 0.02\n\nfunction resolveRadius(\n resolver: NodeRadiusResolver | undefined,\n degree: number,\n node: GraphNode,\n): number {\n if (resolver === undefined) return defaultNodeRadius(degree)\n if (typeof resolver === 'number') return resolver\n if (typeof resolver === 'function') return resolver(degree, node)\n return defaultNodeRadius(degree, resolver)\n}\n\n/** Clamp `value` into `[lo, hi]`, collapsing to the midpoint if the range inverts. */\nfunction clampToRange(value: number, lo: number, hi: number): number {\n if (lo > hi) return (lo + hi) / 2\n return Math.max(lo, Math.min(hi, value))\n}\n\n/**\n * Deterministically position the nodes of a {@link CommunityGraph} in 2D space.\n *\n * For the default `force` algorithm this runs a fixed-iteration, seeded force\n * settlement (spring link attraction, charge repulsion, collision spacing,\n * community cohesion, centering, and bounds clamping). It is fully synchronous\n * and headless — no animation frames — so the same `(graph, options)` always\n * yields identical coordinates, safe for snapshot rendering and SSR. The\n * `radial`, `community`, and `manual` algorithms remain closed-form.\n *\n * Every node is annotated with its render radius `r`, degree, and resolved\n * community; the result also carries community centroids over the final layout.\n */\nexport function layoutCommunityGraph(\n graph: CommunityGraph,\n options: LayoutOptions = {},\n): PositionedGraph {\n const algorithm = options.algorithm ?? 'force'\n const width = options.width ?? DEFAULTS.width\n const height = options.height ?? DEFAULTS.height\n const boundsPadding = options.boundsPadding ?? DEFAULTS.boundsPadding\n\n const degree = computeDegrees(graph)\n\n const communityByNode = new Map<string, string>()\n for (const community of graph.communities) {\n for (const nodeId of community.nodes) {\n if (!communityByNode.has(nodeId)) communityByNode.set(nodeId, community.id)\n }\n }\n\n const centerX = width / 2\n const centerY = height / 2\n const radius = Math.max(40, Math.min(width, height) * 0.38)\n const n = graph.nodes.length\n\n // Per-node render radius (stable, used by force spacing and by consumers).\n const r = graph.nodes.map((node) =>\n resolveRadius(options.nodeRadius, degree.get(node.id) ?? 0, node),\n )\n\n // Index from node id → array position (edges reference nodes by id).\n const indexOf = new Map<string, number>()\n graph.nodes.forEach((node, i) => indexOf.set(node.id, i))\n\n // Community ring anchors — used both as closed-form positions and as the\n // initial seed for force settlement, keeping clusters legible.\n const communityIndexById = new Map<string, number>()\n graph.communities.forEach((community, i) => communityIndexById.set(community.id, i))\n\n const x = new Float64Array(n)\n const y = new Float64Array(n)\n\n // --- Initial / closed-form positions ---------------------------------------\n graph.nodes.forEach((node, index) => {\n const angle = (Math.PI * 2 * index) / Math.max(1, n)\n const communityId = communityByNode.get(node.id)\n const communityIndex = communityId !== undefined ? communityIndexById.get(communityId) ?? -1 : -1\n const communityAngle =\n (Math.PI * 2 * Math.max(0, communityIndex)) / Math.max(1, graph.communities.length)\n const useCommunityOrbit = algorithm === 'community' || algorithm === 'force'\n const communityRadius = algorithm === 'community' ? radius * 0.55 : radius\n const localRadius =\n algorithm === 'force'\n ? radius * (0.7 + ((degree.get(node.id) ?? 0) % 4) * 0.08)\n : radius\n\n if (useCommunityOrbit && communityIndex >= 0) {\n x[index] = centerX + Math.cos(communityAngle) * communityRadius + Math.cos(angle) * 46\n y[index] = centerY + Math.sin(communityAngle) * communityRadius + Math.sin(angle) * 46\n } else {\n x[index] = centerX + Math.cos(angle) * localRadius\n y[index] =\n centerY + Math.sin(angle) * (algorithm === 'radial' ? radius : localRadius * 0.72)\n }\n })\n\n // Warm-start seed then pin overrides (issue #245). Warm start lets a re-layout\n // resume from the current arrangement; pinned coordinates win outright.\n const pinnedIndex = new Map<number, { x: number; y: number }>()\n // Nodes with a real seed (warm start or pin) already have distinct positions,\n // so they are exempt from the separation jitter below.\n const seededIndex = new Set<number>()\n graph.nodes.forEach((node, index) => {\n const seed = readPosition(options.initialPositions, node.id)\n if (seed) {\n x[index] = seed.x\n y[index] = seed.y\n seededIndex.add(index)\n }\n const pin = readPosition(options.pinned, node.id)\n if (pin) {\n x[index] = pin.x\n y[index] = pin.y\n pinnedIndex.set(index, pin)\n seededIndex.add(index)\n }\n })\n const holdPinned = () => {\n for (const [index, pos] of pinnedIndex) {\n x[index] = pos.x\n y[index] = pos.y\n }\n }\n\n // --- Force settlement (force algorithm only) -------------------------------\n if (algorithm === 'force' && n > 1) {\n const ticks = Math.max(0, Math.floor(options.ticks ?? DEFAULTS.ticks))\n const seed = options.seed ?? DEFAULTS.seed\n const linkDistance = options.linkDistance ?? DEFAULTS.linkDistance\n const linkStrength = options.linkStrength ?? DEFAULTS.linkStrength\n const chargeStrength = options.chargeStrength ?? DEFAULTS.chargeStrength\n const collisionPadding = options.collisionPadding ?? DEFAULTS.collisionPadding\n const communityStrength = options.communityStrength ?? DEFAULTS.communityStrength\n\n const rng = mulberry32(seed)\n // Deterministic jitter so no two seeded nodes coincide (avoids div-by-zero).\n // Pinned nodes are left exactly where they were placed. When nothing is\n // pinned the branch never fires, so unpinned output is bit-for-bit identical.\n for (let i = 0; i < n; i++) {\n if (seededIndex.has(i)) continue\n x[i] += (rng() - 0.5) * 8\n y[i] += (rng() - 0.5) * 8\n }\n\n // Pre-resolve edge endpoints to array indices once.\n const links: Array<{ a: number; b: number; weight: number }> = []\n for (const edge of graph.edges) {\n const a = indexOf.get(edge.source)\n const b = indexOf.get(edge.target)\n if (a === undefined || b === undefined || a === b) continue\n links.push({ a, b, weight: edge.weight > 0 ? edge.weight : 1 })\n }\n\n // Community membership as array indices, for centroid cohesion.\n const communityOf = graph.nodes.map((node) => communityByNode.get(node.id))\n const communityIds = graph.communities.map((c) => c.id)\n\n const dispX = new Float64Array(n)\n const dispY = new Float64Array(n)\n const chargeCutoff = linkDistance * 6\n const cooling = ticks > 0 ? Math.pow(0.001, 1 / ticks) : 1\n let alpha = 1\n\n for (let t = 0; t < ticks; t++) {\n dispX.fill(0)\n dispY.fill(0)\n\n // Spring link attraction toward linkDistance.\n for (const link of links) {\n let dx = x[link.b] - x[link.a]\n let dy = y[link.b] - y[link.a]\n const dist = Math.max(0.01, Math.hypot(dx, dy))\n const force = ((dist - linkDistance) / dist) * linkStrength * link.weight\n dx *= force\n dy *= force\n dispX[link.a] += dx\n dispY[link.a] += dy\n dispX[link.b] -= dx\n dispY[link.b] -= dy\n }\n\n // Pairwise charge repulsion (with a distance cutoff for dense graphs).\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n const dx = x[i] - x[j]\n const dy = y[i] - y[j]\n const dist = Math.max(0.01, Math.hypot(dx, dy))\n if (dist > chargeCutoff) continue\n // chargeStrength is negative ⇒ repulsion magnitude is positive.\n const mag = -chargeStrength / dist\n const ux = (dx / dist) * mag\n const uy = (dy / dist) * mag\n dispX[i] += ux\n dispY[i] += uy\n dispX[j] -= ux\n dispY[j] -= uy\n }\n }\n\n // Community cohesion (toward centroid) + global centering gravity.\n if (communityStrength > 0 && communityIds.length > 0) {\n const cx = new Float64Array(communityIds.length)\n const cy = new Float64Array(communityIds.length)\n const cn = new Int32Array(communityIds.length)\n const idxById = new Map<string, number>()\n communityIds.forEach((id, i) => idxById.set(id, i))\n for (let i = 0; i < n; i++) {\n const cid = communityOf[i]\n if (cid === undefined) continue\n const ci = idxById.get(cid)\n if (ci === undefined) continue\n cx[ci] += x[i]\n cy[ci] += y[i]\n cn[ci] += 1\n }\n for (let i = 0; i < n; i++) {\n const cid = communityOf[i]\n if (cid === undefined) continue\n const ci = idxById.get(cid)\n if (ci === undefined || cn[ci] === 0) continue\n dispX[i] += (cx[ci] / cn[ci] - x[i]) * communityStrength\n dispY[i] += (cy[ci] / cn[ci] - y[i]) * communityStrength\n }\n }\n for (let i = 0; i < n; i++) {\n dispX[i] += (centerX - x[i]) * GRAVITY\n dispY[i] += (centerY - y[i]) * GRAVITY\n }\n\n // Apply soft forces, cooled by alpha.\n for (let i = 0; i < n; i++) {\n x[i] += dispX[i] * alpha\n y[i] += dispY[i] * alpha\n }\n\n // Hard collision resolution (full strength) so nodes don't overlap.\n for (let i = 0; i < n; i++) {\n for (let j = i + 1; j < n; j++) {\n const dx = x[i] - x[j]\n const dy = y[i] - y[j]\n const dist = Math.max(0.01, Math.hypot(dx, dy))\n const minDist = r[i] + r[j] + collisionPadding\n if (dist >= minDist) continue\n const push = (minDist - dist) / 2\n const ux = (dx / dist) * push\n const uy = (dy / dist) * push\n x[i] += ux\n y[i] += uy\n x[j] -= ux\n y[j] -= uy\n }\n }\n\n // Clamp inside the padded canvas every tick.\n for (let i = 0; i < n; i++) {\n x[i] = clampToRange(x[i], boundsPadding + r[i], width - boundsPadding - r[i])\n y[i] = clampToRange(y[i], boundsPadding + r[i], height - boundsPadding - r[i])\n }\n\n // Re-assert pinned positions last so pins hold exactly and neighbors\n // settle around them.\n holdPinned()\n\n alpha *= cooling\n }\n } else {\n // Closed-form algorithms: still honor the bounds clamp, then hold pins.\n for (let i = 0; i < n; i++) {\n x[i] = clampToRange(x[i], boundsPadding + r[i], width - boundsPadding - r[i])\n y[i] = clampToRange(y[i], boundsPadding + r[i], height - boundsPadding - r[i])\n }\n holdPinned()\n }\n\n // --- Build the result ------------------------------------------------------\n const nodes = graph.nodes.map((node, index): PositionedGraphNode => ({\n ...node,\n x: x[index],\n y: y[index],\n r: r[index],\n degree: degree.get(node.id) ?? 0,\n communityId: communityByNode.get(node.id),\n }))\n\n const nodeIndex = new Map(nodes.map((node) => [node.id, node]))\n\n const communities: PositionedCommunity[] = graph.communities.map((community) => {\n let sx = 0\n let sy = 0\n let size = 0\n for (const nodeId of community.nodes) {\n const positioned = nodeIndex.get(nodeId)\n if (!positioned) continue\n sx += positioned.x\n sy += positioned.y\n size += 1\n }\n return size > 0\n ? { id: community.id, x: sx / size, y: sy / size, size }\n : { id: community.id, x: centerX, y: centerY, size: 0 }\n })\n\n return { nodes, edges: graph.edges, nodeIndex, communities }\n}\n","import type { GraphBounds, PositionedGraphNode, ViewportTransform } from './types.js'\n\nconst EMPTY_BOUNDS: GraphBounds = {\n minX: 0,\n minY: 0,\n maxX: 0,\n maxY: 0,\n width: 0,\n height: 0,\n centerX: 0,\n centerY: 0,\n}\n\n/**\n * Compute the axis-aligned bounding box around a set of positioned nodes.\n * Returns an all-zero box for an empty input.\n */\nexport function computeGraphBounds(\n nodes: ReadonlyArray<Pick<PositionedGraphNode, 'x' | 'y'>>,\n): GraphBounds {\n if (nodes.length === 0) return { ...EMPTY_BOUNDS }\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const node of nodes) {\n if (node.x < minX) minX = node.x\n if (node.y < minY) minY = node.y\n if (node.x > maxX) maxX = node.x\n if (node.y > maxY) maxY = node.y\n }\n return {\n minX,\n minY,\n maxX,\n maxY,\n width: maxX - minX,\n height: maxY - minY,\n centerX: (minX + maxX) / 2,\n centerY: (minY + maxY) / 2,\n }\n}\n\nexport interface FitOptions {\n /** Uniform padding (in viewport units) to leave around the graph. */\n padding?: number\n /** Clamp the computed scale to this minimum. */\n minScale?: number\n /** Clamp the computed scale to this maximum. */\n maxScale?: number\n}\n\n/**\n * Compute a {@link ViewportTransform} (uniform scale + translation) that fits\n * `bounds` centered within a `viewport` of the given width/height. Apply the\n * result as `translate(offsetX, offsetY) scale(scale)` in SVG/canvas space.\n */\nexport function fitGraphToViewport(\n bounds: GraphBounds,\n viewport: { width: number; height: number },\n options: FitOptions = {},\n): ViewportTransform {\n const padding = options.padding ?? 0\n const minScale = options.minScale ?? 0\n const maxScale = options.maxScale ?? Infinity\n\n const availableWidth = Math.max(0, viewport.width - padding * 2)\n const availableHeight = Math.max(0, viewport.height - padding * 2)\n\n let scale = 1\n if (bounds.width > 0 || bounds.height > 0) {\n const scaleX = bounds.width > 0 ? availableWidth / bounds.width : Infinity\n const scaleY = bounds.height > 0 ? availableHeight / bounds.height : Infinity\n scale = Math.min(scaleX, scaleY)\n }\n if (!Number.isFinite(scale) || scale <= 0) scale = 1\n scale = Math.max(minScale, Math.min(maxScale, scale))\n\n const offsetX = viewport.width / 2 - bounds.centerX * scale\n const offsetY = viewport.height / 2 - bounds.centerY * scale\n return { scale, offsetX, offsetY }\n}\n","import { filterCommunityGraph } from './filter.js'\nimport type { CommunityGraph } from './types.js'\n\n/** Build an undirected adjacency map from a graph's edges. */\nexport function buildAdjacency(graph: CommunityGraph): Map<string, Set<string>> {\n const adjacency = new Map<string, Set<string>>()\n const ensure = (id: string) => {\n let set = adjacency.get(id)\n if (!set) {\n set = new Set<string>()\n adjacency.set(id, set)\n }\n return set\n }\n for (const node of graph.nodes) ensure(node.id)\n for (const edge of graph.edges) {\n ensure(edge.source).add(edge.target)\n ensure(edge.target).add(edge.source)\n }\n return adjacency\n}\n\n/** Return the set of node ids directly adjacent to `nodeId` (excludes itself). */\nexport function neighborsOf(graph: CommunityGraph, nodeId: string): Set<string> {\n return new Set(buildAdjacency(graph).get(nodeId) ?? [])\n}\n\nexport interface ExpandOptions {\n /** How many edge-hops to traverse from the seeds. Default 1. */\n depth?: number\n /** Include the seed ids in the result. Default true. */\n includeSeeds?: boolean\n}\n\n/**\n * Breadth-first expansion of one or more seed nodes out to `depth` hops.\n * Returns the set of reached node ids (seeds included by default).\n */\nexport function expandNeighborhood(\n graph: CommunityGraph,\n seeds: Iterable<string>,\n options: ExpandOptions = {},\n): Set<string> {\n const depth = options.depth ?? 1\n const includeSeeds = options.includeSeeds ?? true\n const adjacency = buildAdjacency(graph)\n\n const seen = new Set<string>()\n let frontier = new Set<string>()\n for (const seed of seeds) {\n if (adjacency.has(seed) || depth === 0) {\n seen.add(seed)\n frontier.add(seed)\n }\n }\n\n for (let hop = 0; hop < depth; hop++) {\n const next = new Set<string>()\n for (const id of frontier) {\n for (const neighbor of adjacency.get(id) ?? []) {\n if (!seen.has(neighbor)) {\n seen.add(neighbor)\n next.add(neighbor)\n }\n }\n }\n if (next.size === 0) break\n frontier = next\n }\n\n if (!includeSeeds) {\n for (const seed of seeds) seen.delete(seed)\n }\n return seen\n}\n\n/**\n * Extract the induced subgraph over `nodeIds` — a {@link CommunityGraph}\n * containing only those nodes, the edges between them, and the trimmed\n * community memberships. Thin wrapper over {@link filterCommunityGraph}.\n */\nexport function subgraphForNodes(graph: CommunityGraph, nodeIds: Iterable<string>): CommunityGraph {\n return filterCommunityGraph(graph, { nodeIds: Array.from(nodeIds) })\n}\n\n/**\n * Convenience: the induced subgraph of a seed node plus its `depth`-hop\n * neighborhood. Useful for \"expand selection\" interactions.\n */\nexport function neighborhoodSubgraph(\n graph: CommunityGraph,\n seeds: Iterable<string>,\n options: ExpandOptions = {},\n): CommunityGraph {\n return subgraphForNodes(graph, expandNeighborhood(graph, seeds, options))\n}\n","import type { CommunityGraph, GraphLayoutAlgorithm } from './types.js'\n\n/** Current on-disk version for {@link GraphSnapshot}. */\nexport const GRAPH_SNAPSHOT_VERSION = 1\n\n/**\n * A self-contained, serializable representation of a community graph plus the\n * layout intent used to render it. Designed to be written to a static JSON file\n * and consumed by a JS-only host (e.g. a documentation site) without recomputing\n * the graph.\n */\nexport interface GraphSnapshot {\n version: number\n graph: CommunityGraph\n layout?: {\n algorithm: GraphLayoutAlgorithm\n width: number\n height: number\n }\n generatedAt?: string\n}\n\nexport interface SerializeSnapshotOptions {\n layout?: GraphSnapshot['layout']\n /** ISO timestamp to stamp into the snapshot. Omit for reproducible output. */\n generatedAt?: string\n}\n\nfunction sortedGraph(graph: CommunityGraph): CommunityGraph {\n return {\n nodes: [...graph.nodes].sort((a, b) => a.id.localeCompare(b.id)),\n edges: [...graph.edges].sort((a, b) => (\n a.source.localeCompare(b.source)\n || a.target.localeCompare(b.target)\n || (a.kind ?? '').localeCompare(b.kind ?? '')\n )),\n communities: [...graph.communities]\n .map((community) => ({ ...community, nodes: [...community.nodes].sort() }))\n .sort((a, b) => a.id.localeCompare(b.id)),\n }\n}\n\n/**\n * Build a deterministic {@link GraphSnapshot} from a graph. Nodes, edges, and\n * community members are sorted so that equal graphs serialize identically\n * (stable diffs, content-addressable caching).\n */\nexport function serializeGraphSnapshot(\n graph: CommunityGraph,\n options: SerializeSnapshotOptions = {},\n): GraphSnapshot {\n const snapshot: GraphSnapshot = {\n version: GRAPH_SNAPSHOT_VERSION,\n graph: sortedGraph(graph),\n }\n if (options.layout) snapshot.layout = options.layout\n if (options.generatedAt) snapshot.generatedAt = options.generatedAt\n return snapshot\n}\n\n/** Stable JSON string for a graph snapshot. */\nexport function stringifyGraphSnapshot(\n graph: CommunityGraph,\n options: SerializeSnapshotOptions = {},\n): string {\n return JSON.stringify(serializeGraphSnapshot(graph, options))\n}\n\n/**\n * Validate and unwrap a {@link GraphSnapshot} (or its JSON string) back into a\n * {@link CommunityGraph}. Throws on shape/version mismatch.\n */\nexport function deserializeGraphSnapshot(input: GraphSnapshot | string): CommunityGraph {\n const snapshot: unknown = typeof input === 'string' ? JSON.parse(input) : input\n if (!snapshot || typeof snapshot !== 'object') {\n throw new Error('invalid graph snapshot: not an object')\n }\n const candidate = snapshot as Partial<GraphSnapshot>\n if (candidate.version !== GRAPH_SNAPSHOT_VERSION) {\n throw new Error(`unsupported graph snapshot version: ${String(candidate.version)}`)\n }\n const graph = candidate.graph\n if (\n !graph\n || !Array.isArray(graph.nodes)\n || !Array.isArray(graph.edges)\n || !Array.isArray(graph.communities)\n ) {\n throw new Error('invalid graph snapshot: missing graph nodes/edges/communities')\n }\n return graph\n}\n","// Render-prep + snapshot warm-start helpers (issue #264).\n//\n// Consumers (JS-only SVG #259, React GraphView, the interactive 2D/3D tiers)\n// all need the same two things a live `GraphController` build does not give\n// them directly:\n//\n// 1. a CommunityGraph → render-ready mapping (labels, degree-derived size,\n// per-community tone, and baked positions when available), and\n// 2. an instant \"snapshot-first\" load of a precomputed graph with baked x/y,\n// falling back to a live build when no snapshot exists.\n//\n// Both are generic and framework-agnostic, so they live here in @fortemi/graph\n// and every renderer shares them — the runtime loader and the build-time writer\n// map through the same `mapCommunityGraph` so on-disk snapshots and live builds\n// render identically.\n\nimport type { CommunityGraph } from './types.js'\nimport { computeDegrees, nodeRadius, type NodeRadiusOptions } from './degree.js'\nimport { colorForCommunity, UNASSIGNED_COMMUNITY_COLOR } from './color.js'\nimport { layoutCommunityGraph } from './layout.js'\nimport type { LayoutOptions } from './layout.js'\n\n/**\n * Greyscale community ramp — warm-grey, darkest first, meant to sit on a light\n * (\"cream\") background. Index 0 (darkest) is the largest community. Strictly\n * greyscale so community tone reads as density, not category.\n */\nexport const GREYSCALE_COMMUNITY_RAMP = [\n '#2B2824',\n '#43403A',\n '#585149',\n '#6E665A',\n '#837A6B',\n '#968C7C',\n] as const\n\n/** A render-ready node: identity + label + degree-derived size + tone + optional baked position. */\nexport interface RenderNode {\n id: string\n label: string\n /** Degree-derived render size. */\n size: number\n /** Community tone (see {@link CommunityPalette}). */\n color: string\n /** Community rank: 0 = largest community, ascending; -1 when unassigned. */\n communityRank: number\n /** Baked layout coordinate (present only when positions were supplied). */\n x?: number\n y?: number\n}\n\n/** A render-ready link (edge) referencing nodes by id. */\nexport interface RenderLink {\n source: string\n target: string\n weight: number\n kind?: string\n}\n\n/** A render-ready graph: the shape every renderer tier consumes. */\nexport interface RenderGraph {\n nodes: RenderNode[]\n links: RenderLink[]\n /** Number of communities in the source graph. */\n clusters: number\n}\n\n/**\n * Community coloring strategy for {@link mapCommunityGraph}:\n * - `'community'` (default): hash the community id into the qualitative palette\n * (matches the historical `GraphView` coloring).\n * - `'greyscale'`: {@link GREYSCALE_COMMUNITY_RAMP} indexed by community rank\n * (largest cluster = darkest).\n * - a custom array: indexed by community rank.\n */\nexport type CommunityPalette = 'community' | 'greyscale' | readonly string[]\n\nexport interface MapCommunityGraphOptions {\n /** Resolve a human label for a node id. Defaults to the id itself. */\n labelFor?: (id: string) => string\n /** Baked layout positions to stamp onto nodes (warm start). */\n positions?: Map<string, { x: number; y: number }> | Record<string, { x: number; y: number }>\n /** Community coloring strategy. Default `'community'`. */\n palette?: CommunityPalette\n /** Node-radius tuning passed to {@link nodeRadius} (default sizer). */\n radius?: NodeRadiusOptions\n /** Override the degree → size mapping entirely. */\n sizeFor?: (degree: number, id: string) => number\n}\n\nfunction positionGetter(\n positions: MapCommunityGraphOptions['positions'],\n): (id: string) => { x: number; y: number } | undefined {\n if (!positions) return () => undefined\n if (positions instanceof Map) return (id) => positions.get(id)\n return (id) => (Object.prototype.hasOwnProperty.call(positions, id) ? positions[id] : undefined)\n}\n\n/**\n * Rank communities by member count, largest first. Returns a map from community\n * id to its rank (0 = largest). Ties break on community id for determinism.\n */\nexport function communityRanks(graph: CommunityGraph): Map<string, number> {\n const rank = new Map<string, number>()\n ;[...graph.communities]\n .sort((a, b) => b.nodes.length - a.nodes.length || a.id.localeCompare(b.id))\n .forEach((community, index) => rank.set(community.id, index))\n return rank\n}\n\nfunction colorForRank(\n communityId: string | undefined,\n rank: number,\n palette: CommunityPalette,\n): string {\n if (palette === 'community') return colorForCommunity(communityId)\n const ramp = palette === 'greyscale' ? GREYSCALE_COMMUNITY_RAMP : palette\n if (ramp.length === 0) return UNASSIGNED_COMMUNITY_COLOR\n if (rank < 0) return ramp[ramp.length - 1] // unassigned → lightest\n return ramp[rank % ramp.length]\n}\n\n/**\n * Map a {@link CommunityGraph} to a render-ready {@link RenderGraph}: labels,\n * degree-derived node size, per-community tone (largest cluster = darkest for\n * ramped palettes), and baked positions when supplied. Pure and deterministic —\n * shared by the runtime loader and the build-time snapshot writer so both render\n * identically.\n */\nexport function mapCommunityGraph(\n graph: CommunityGraph,\n options: MapCommunityGraphOptions = {},\n): RenderGraph {\n const palette = options.palette ?? 'community'\n const labelFor = options.labelFor ?? ((id: string) => id)\n const getPos = positionGetter(options.positions)\n const sizeFor =\n options.sizeFor ?? ((degree: number) => nodeRadius(degree, options.radius))\n\n const degrees = computeDegrees(graph)\n const rankByComm = communityRanks(graph)\n const commOfNode = new Map<string, string>()\n for (const community of graph.communities) {\n for (const id of community.nodes) commOfNode.set(id, community.id)\n }\n\n const nodes: RenderNode[] = graph.nodes.map((node) => {\n const communityId = commOfNode.get(node.id)\n const rank = communityId != null ? rankByComm.get(communityId) ?? -1 : -1\n const degree = degrees.get(node.id) ?? 0\n const pos = getPos(node.id)\n const rendered: RenderNode = {\n id: node.id,\n label: labelFor(node.id),\n size: sizeFor(degree, node.id),\n color: colorForRank(communityId, rank, palette),\n communityRank: rank,\n }\n if (pos) {\n rendered.x = pos.x\n rendered.y = pos.y\n }\n return rendered\n })\n\n const links: RenderLink[] = graph.edges.map((edge) => {\n const link: RenderLink = { source: edge.source, target: edge.target, weight: edge.weight }\n if (edge.kind !== undefined) link.kind = edge.kind\n return link\n })\n\n return { nodes, links, clusters: graph.communities.length }\n}\n\nexport interface BakeRenderGraphOptions extends MapCommunityGraphOptions {\n /** Layout options for the one-shot build-time layout pass. */\n layout?: LayoutOptions\n}\n\n/**\n * Build-time snapshot writer: run the layout once and emit a {@link RenderGraph}\n * with baked x/y so hosts can warm-start (skip the layout pass) at runtime.\n * Companion to `serializeGraphSnapshot` — this bakes render-ready positions\n * rather than storing the raw graph + layout intent. Any `positions` passed in\n * options are ignored in favor of the freshly computed layout.\n */\nexport function bakeRenderGraph(\n graph: CommunityGraph,\n options: BakeRenderGraphOptions = {},\n): RenderGraph {\n const positioned = layoutCommunityGraph(graph, options.layout)\n const positions = new Map<string, { x: number; y: number }>()\n for (const node of positioned.nodes) positions.set(node.id, { x: node.x, y: node.y })\n // Re-map with the freshly computed positions; any `positions` passed in are ignored.\n const mapOptions: MapCommunityGraphOptions = { positions }\n if (options.labelFor) mapOptions.labelFor = options.labelFor\n if (options.palette) mapOptions.palette = options.palette\n if (options.radius) mapOptions.radius = options.radius\n if (options.sizeFor) mapOptions.sizeFor = options.sizeFor\n return mapCommunityGraph(graph, mapOptions)\n}\n\n/** Deterministic JSON for a render graph (stable key order for cache-friendly diffs). */\nexport function stringifyRenderGraph(graph: RenderGraph): string {\n const nodes = [...graph.nodes].sort((a, b) => a.id.localeCompare(b.id))\n const links = [...graph.links].sort(\n (a, b) =>\n a.source.localeCompare(b.source)\n || a.target.localeCompare(b.target)\n || (a.kind ?? '').localeCompare(b.kind ?? ''),\n )\n return JSON.stringify({ nodes, links, clusters: graph.clusters })\n}\n\n/** Structural guard for a {@link RenderGraph} loaded from an untrusted source. */\nexport function isRenderGraph(value: unknown): value is RenderGraph {\n if (!value || typeof value !== 'object') return false\n const candidate = value as Partial<RenderGraph>\n return (\n Array.isArray(candidate.nodes)\n && candidate.nodes.length > 0\n && Array.isArray(candidate.links)\n && candidate.nodes.every(\n (n) => n && typeof n.id === 'string' && typeof n.size === 'number' && typeof n.color === 'string',\n )\n )\n}\n\n/** Whether every node in a render graph carries a baked position. */\nexport function hasBakedPositions(graph: RenderGraph): boolean {\n return graph.nodes.every((n) => typeof n.x === 'number' && typeof n.y === 'number')\n}\n\nexport interface LoadRenderSnapshotOptions {\n /** `fetch` implementation to use when `source` is a URL. Defaults to `globalThis.fetch`. */\n fetchImpl?: typeof fetch\n /** Require baked x/y on every node; a snapshot without positions resolves to `null`. Default `true`. */\n requirePositions?: boolean\n}\n\n/**\n * Snapshot-first loader (issue #264). Load a precomputed, render-ready graph\n * carrying baked positions — instant, no live `GraphController` build and no\n * layout pass. Accepts a URL to fetch, an already-parsed {@link RenderGraph}, or\n * a thunk. Returns `null` (never throws) when the snapshot is absent, malformed,\n * or lacks baked positions, so callers fall back to a live build + `mapCommunityGraph`.\n */\nexport async function loadRenderSnapshot(\n source: string | RenderGraph | (() => Promise<RenderGraph | null> | RenderGraph | null),\n options: LoadRenderSnapshotOptions = {},\n): Promise<RenderGraph | null> {\n const requirePositions = options.requirePositions ?? true\n try {\n let data: unknown\n if (typeof source === 'string') {\n const fetchImpl = options.fetchImpl ?? (globalThis.fetch as typeof fetch | undefined)\n if (!fetchImpl) return null\n const res = await fetchImpl(source)\n if (!res.ok) return null\n data = await res.json()\n } else if (typeof source === 'function') {\n data = await source()\n } else {\n data = source\n }\n if (!isRenderGraph(data)) return null\n if (requirePositions && !hasBakedPositions(data)) return null\n return data\n } catch {\n return null\n }\n}\n","// Shared renderer control contract (#260).\n//\n// Every community-graph renderer tier — the JS-only SVG renderer (#259), the\n// React `GraphView`, and the heavier interactive tiers (Sigma 2D #263, 3D #262)\n// — honors this control/options surface so consumers can swap tiers without\n// rewiring. Renderer-specific option types extend `GraphControlContract`; the\n// shared filter semantics (community / edge-kind / node allow-list / min-degree)\n// live in `applyControlFilters` so every tier filters identically.\n\nimport { colorForCommunity } from './color.js'\nimport { computeDegrees } from './degree.js'\nimport { filterCommunityGraph } from './filter.js'\nimport type { CommunityGraph, GraphLayoutAlgorithm } from './types.js'\n\n/** Node/edge visibility filter shared by every renderer tier. */\nexport interface GraphControlFilters {\n /** Keep only nodes in these communities. */\n communityIds?: string[]\n /** Keep only edges whose `kind` is in this set. */\n edgeKinds?: string[]\n /** Explicit node allow-list. */\n nodeIds?: string[]\n /** Hide nodes with fewer than this many connections (degree) in the visible set. */\n minDegree?: number\n}\n\n/**\n * The control surface common to all renderer tiers. A consumer coded against\n * this contract can move a graph between the JS-only renderer, React\n * `GraphView`, and future tiers by passing the same options object.\n */\nexport interface GraphControlContract {\n /** Layout algorithm. Default `force`. */\n algorithm?: GraphLayoutAlgorithm\n /** Visibility filter. */\n filters?: GraphControlFilters\n /** Selected node id (controlled). */\n selectedNodeId?: string | null\n /** Selection callback (click / keyboard). */\n onSelectNode?: (nodeId: string) => void\n /** Navigation callback (double-click / Enter on a selected node). */\n onNavigate?: (nodeId: string) => void\n /** Human label for a node (popup / a11y). Default: the node id. */\n labelFor?: (nodeId: string) => string\n /** Community palette override. */\n colors?: readonly string[]\n /** Logical viewport size. */\n width?: number\n height?: number\n}\n\n/** One community-legend row: community id, its color, and member count. */\nexport interface GraphLegendEntry {\n communityId: string\n color: string\n count: number\n}\n\n/**\n * Apply the shared {@link GraphControlFilters} to `graph`. Composes the engine's\n * community / edge-kind / node-allow-list filter with a `minDegree` pass\n * (degree computed over the already-filtered set). Pure — input is not mutated.\n */\nexport function applyControlFilters(\n graph: CommunityGraph | null | undefined,\n filters?: GraphControlFilters,\n): CommunityGraph {\n const base = filterCommunityGraph(graph, filters)\n const minDegree = filters?.minDegree ?? 0\n if (minDegree <= 0) return base\n const degree = computeDegrees(base)\n const keep = base.nodes.filter((n) => (degree.get(n.id) ?? 0) >= minDegree).map((n) => n.id)\n if (keep.length === base.nodes.length) return base\n return filterCommunityGraph(base, { nodeIds: keep })\n}\n\n/**\n * Build community-legend rows for a graph — the shared data that any tier can\n * render as a legend and use to drive the `communityIds` show/hide filter.\n * Sorted by member count (largest first). Colors match `colorForCommunity`.\n */\nexport function communityLegend(\n graph: CommunityGraph | null | undefined,\n colors?: readonly string[],\n): GraphLegendEntry[] {\n if (!graph) return []\n return graph.communities\n .map((c) => ({\n communityId: c.id,\n color: colorForCommunity(c.id, colors),\n count: c.nodes.length,\n }))\n .sort((a, b) => b.count - a.count || a.communityId.localeCompare(b.communityId))\n}\n","// Framework-agnostic DOM/SVG renderer for a CommunityGraph (#259).\n//\n// A batteries-included, dependency-free renderer that turns a CommunityGraph\n// into an interactive SVG view, reusing the engine (layoutCommunityGraph,\n// colorForCommunity, applyControlFilters, buildAdjacency) so it stays visually\n// identical to @fortemi/react's `GraphView`. No React, no sigma/graphology.\n//\n// Deterministic + headless-safe: layout is synchronous and seeded, and the DOM\n// is built without animation frames, so it renders identically in a browser,\n// jsdom, or an SSR-style document and can back static snapshots.\n\nimport { colorForCommunity } from './color.js'\nimport { applyControlFilters, type GraphControlContract, type GraphControlFilters } from './contract.js'\nimport { layoutCommunityGraph, type LayoutOptions } from './layout.js'\nimport { computeGraphBounds, fitGraphToViewport } from './bounds.js'\nimport { buildAdjacency } from './neighborhood.js'\nimport type { CommunityGraph, GraphLayoutAlgorithm, PositionedGraph } from './types.js'\n\nconst SVG_NS = 'http://www.w3.org/2000/svg'\n\n/** Filter shape accepted by the renderer — the shared control-filter contract. */\nexport type GraphRenderFilters = GraphControlFilters\n\n/**\n * Options for {@link renderCommunityGraph}. Extends the shared\n * {@link GraphControlContract} (algorithm, filters, selection, navigation,\n * labels, colors, size — honored by every renderer tier) with renderer-specific\n * knobs. The React `GraphView` honors the same contract, so the tiers are\n * drop-in swappable.\n */\nexport interface GraphRenderOptions extends GraphControlContract {\n /** Extra layout tuning forwarded to `layoutCommunityGraph`. */\n layoutOptions?: Omit<LayoutOptions, 'algorithm' | 'width' | 'height'>\n /** Canvas background. Default `#fafafa`. */\n background?: string\n /** Enable zoom/pan/hover interactions. Default `true`. */\n interactive?: boolean\n /** Zoom clamp. Default 0.4 / 3. */\n minScale?: number\n maxScale?: number\n}\n\n/** Mutable subset applied via {@link GraphRenderHandle.update}. */\nexport type GraphRenderUpdate = Partial<\n Pick<GraphRenderOptions, 'filters' | 'algorithm' | 'selectedNodeId' | 'labelFor'>\n> & { graph?: CommunityGraph }\n\n/** Live handle returned by {@link renderCommunityGraph}. */\nexport interface GraphRenderHandle {\n /** Apply new graph/filters/algorithm/selection without recreating the view. */\n update(next: GraphRenderUpdate): void\n /** Select and center a node (search/focus). Pass `null` to clear selection. */\n focus(nodeId: string | null): void\n /** Remove the view, its popup, and all listeners from the container. */\n destroy(): void\n /** The mounted `<svg>` element. */\n readonly element: SVGSVGElement\n}\n\nfunction el<K extends keyof SVGElementTagNameMap>(\n tag: K,\n attrs: Record<string, string | number>,\n): SVGElementTagNameMap[K] {\n const node = document.createElementNS(SVG_NS, tag)\n for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, String(v))\n return node\n}\n\nfunction clamp(v: number, lo: number, hi: number): number {\n return Math.max(lo, Math.min(hi, v))\n}\n\n/**\n * Render `graph` into `container` as an interactive SVG community graph.\n * Returns a {@link GraphRenderHandle}; call `destroy()` to tear it down.\n */\nexport function renderCommunityGraph(\n container: HTMLElement,\n graph: CommunityGraph,\n options: GraphRenderOptions = {},\n): GraphRenderHandle {\n const width = options.width ?? 760\n const height = options.height ?? 460\n const background = options.background ?? '#fafafa'\n const interactive = options.interactive ?? true\n const minScale = options.minScale ?? 0.4\n const maxScale = options.maxScale ?? 3\n\n // ── mutable state ─────────────────────────────────────────────────────────\n let currentGraph = graph\n let filters = options.filters\n let algorithm: GraphLayoutAlgorithm = options.algorithm ?? 'force'\n let selectedNodeId = options.selectedNodeId ?? null\n let labelFor = options.labelFor ?? ((id: string) => id)\n\n let visible: CommunityGraph = applyControlFilters(currentGraph, filters)\n let positioned: PositionedGraph = layoutCommunityGraph(visible, {\n algorithm,\n width,\n height,\n ...options.layoutOptions,\n })\n let adjacency = buildAdjacency(visible)\n\n const transform = { scale: 1, offsetX: 0, offsetY: 0 }\n\n // ── DOM scaffold ──────────────────────────────────────────────────────────\n if (getComputedPosition(container) === 'static') container.style.position = 'relative'\n\n const svg = el('svg', {\n role: 'img',\n 'aria-label': 'Community graph',\n viewBox: `0 0 ${width} ${height}`,\n width: '100%',\n })\n svg.style.display = 'block'\n svg.style.background = background\n svg.style.touchAction = 'none'\n ;(svg.style as CSSStyleDeclaration).aspectRatio = `${width} / ${height}`\n\n const viewport = el('g', {}) // pan/zoom transform group\n const edgesLayer = el('g', {})\n const nodesLayer = el('g', {})\n viewport.appendChild(edgesLayer)\n viewport.appendChild(nodesLayer)\n svg.appendChild(viewport)\n container.appendChild(svg)\n\n const popup = document.createElement('div')\n popup.setAttribute('data-fortemi-graph-popup', '')\n Object.assign(popup.style, {\n position: 'absolute',\n display: 'none',\n pointerEvents: 'none',\n padding: '2px 6px',\n font: '12px system-ui, sans-serif',\n background: '#111',\n color: '#fff',\n borderRadius: '4px',\n transform: 'translate(-50%, -130%)',\n whiteSpace: 'nowrap',\n zIndex: '2',\n } satisfies Partial<CSSStyleDeclaration>)\n container.appendChild(popup)\n\n // node id → its <circle> element, for restyle on select/hover.\n const circles = new Map<string, SVGCircleElement>()\n const lines: Array<{ line: SVGLineElement; source: string; target: string }> = []\n\n function applyTransform(): void {\n viewport.setAttribute(\n 'transform',\n `translate(${transform.offsetX} ${transform.offsetY}) scale(${transform.scale})`,\n )\n }\n\n function fitToViewport(): void {\n const bounds = computeGraphBounds(positioned.nodes)\n const fit = fitGraphToViewport(bounds, { width, height }, {\n padding: 24,\n minScale,\n maxScale,\n })\n transform.scale = fit.scale\n transform.offsetX = fit.offsetX\n transform.offsetY = fit.offsetY\n applyTransform()\n }\n\n function styleNode(id: string): void {\n const circle = circles.get(id)\n if (!circle) return\n const node = positioned.nodeIndex.get(id)\n if (!node) return\n const selected = id === selectedNodeId\n circle.setAttribute('r', String(selected ? node.r + 3 : node.r))\n circle.setAttribute('stroke', selected ? '#111' : '#fff')\n circle.setAttribute('stroke-width', selected ? '3' : '1.5')\n }\n\n function showPopup(id: string): void {\n const node = positioned.nodeIndex.get(id)\n if (!node) {\n popup.style.display = 'none'\n return\n }\n // node (user units) → screen: apply viewport transform, then SVG scale to px.\n const px = transform.offsetX + node.x * transform.scale\n const py = transform.offsetY + node.y * transform.scale\n const rect = svg.getBoundingClientRect?.()\n const scaleToPx = rect && rect.width ? rect.width / width : 1\n popup.textContent = labelFor(id)\n popup.style.left = `${px * scaleToPx}px`\n popup.style.top = `${py * scaleToPx}px`\n popup.style.display = 'block'\n }\n\n function setSelected(id: string | null, emit: boolean): void {\n const prev = selectedNodeId\n selectedNodeId = id\n if (prev && prev !== id) styleNode(prev)\n if (id) {\n styleNode(id)\n showPopup(id)\n if (emit) options.onSelectNode?.(id)\n } else {\n popup.style.display = 'none'\n }\n }\n\n function setHover(id: string | null): void {\n if (!interactive) return\n if (!id) {\n for (const [, c] of circles) c.style.opacity = '1'\n for (const { line } of lines) line.style.opacity = '0.55'\n return\n }\n const keep = new Set<string>(adjacency.get(id) ?? [])\n keep.add(id)\n for (const [nid, c] of circles) c.style.opacity = keep.has(nid) ? '1' : '0.15'\n for (const { line, source, target } of lines) {\n line.style.opacity = source === id || target === id ? '0.9' : '0.06'\n }\n }\n\n // ── (re)build the DOM for the current positioned graph ─────────────────────\n function build(): void {\n edgesLayer.replaceChildren()\n nodesLayer.replaceChildren()\n circles.clear()\n lines.length = 0\n\n for (const edge of positioned.edges) {\n const s = positioned.nodeIndex.get(edge.source)\n const t = positioned.nodeIndex.get(edge.target)\n if (!s || !t) continue\n const line = el('line', {\n x1: s.x,\n y1: s.y,\n x2: t.x,\n y2: t.y,\n stroke: '#9aa0a6',\n 'stroke-width': clamp(edge.weight, 1, 5),\n opacity: 0.55,\n })\n edgesLayer.appendChild(line)\n lines.push({ line, source: edge.source, target: edge.target })\n }\n\n for (const node of positioned.nodes) {\n const circle = el('circle', {\n cx: node.x,\n cy: node.y,\n r: node.r,\n fill: colorForCommunity(node.communityId, options.colors),\n stroke: '#fff',\n 'stroke-width': 1.5,\n tabindex: 0,\n role: 'button',\n 'data-node-id': node.id,\n 'aria-label': `Graph node ${labelFor(node.id)}`,\n })\n circle.style.cursor = 'pointer'\n circle.style.outline = 'none'\n const title = el('title', {})\n title.textContent = labelFor(node.id)\n circle.appendChild(title)\n\n if (interactive) {\n circle.addEventListener('click', (e) => {\n e.stopPropagation()\n setSelected(node.id, true)\n })\n circle.addEventListener('dblclick', (e) => {\n e.stopPropagation()\n options.onNavigate?.(node.id)\n })\n circle.addEventListener('mouseenter', () => setHover(node.id))\n circle.addEventListener('mouseleave', () => setHover(null))\n circle.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n if (selectedNodeId === node.id) options.onNavigate?.(node.id)\n else setSelected(node.id, true)\n }\n })\n }\n nodesLayer.appendChild(circle)\n circles.set(node.id, circle)\n }\n\n if (selectedNodeId && circles.has(selectedNodeId)) {\n styleNode(selectedNodeId)\n showPopup(selectedNodeId)\n } else {\n selectedNodeId = null\n popup.style.display = 'none'\n }\n }\n\n function relayout(): void {\n visible = applyControlFilters(currentGraph, filters)\n positioned = layoutCommunityGraph(visible, {\n algorithm,\n width,\n height,\n ...options.layoutOptions,\n })\n adjacency = buildAdjacency(visible)\n build()\n fitToViewport()\n }\n\n // ── interactions on the canvas (zoom + pan + deselect) ─────────────────────\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault()\n const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1\n transform.scale = clamp(transform.scale * factor, minScale, maxScale)\n applyTransform()\n if (selectedNodeId) showPopup(selectedNodeId)\n }\n let panning: { x: number; y: number } | null = null\n const onDown = (e: MouseEvent): void => {\n if (e.target === svg || e.target === viewport) {\n panning = { x: e.clientX, y: e.clientY }\n setSelected(null, true)\n }\n }\n const onMove = (e: MouseEvent): void => {\n if (!panning) return\n transform.offsetX += e.clientX - panning.x\n transform.offsetY += e.clientY - panning.y\n panning = { x: e.clientX, y: e.clientY }\n applyTransform()\n }\n const onUp = (): void => {\n panning = null\n }\n\n if (interactive) {\n svg.addEventListener('wheel', onWheel, { passive: false })\n svg.addEventListener('mousedown', onDown)\n svg.addEventListener('mousemove', onMove)\n svg.addEventListener('mouseup', onUp)\n svg.addEventListener('mouseleave', onUp)\n }\n\n // ── initial paint ──────────────────────────────────────────────────────────\n build()\n fitToViewport()\n\n return {\n element: svg,\n update(next: GraphRenderUpdate): void {\n let needsRelayout = false\n if (next.graph && next.graph !== currentGraph) {\n currentGraph = next.graph\n needsRelayout = true\n }\n if ('filters' in next) {\n filters = next.filters\n needsRelayout = true\n }\n if (next.algorithm && next.algorithm !== algorithm) {\n algorithm = next.algorithm\n needsRelayout = true\n }\n if (next.labelFor) labelFor = next.labelFor\n if (needsRelayout) relayout()\n if ('selectedNodeId' in next) setSelected(next.selectedNodeId ?? null, false)\n },\n focus(nodeId: string | null): void {\n if (!nodeId) {\n setSelected(null, false)\n return\n }\n const node = positioned.nodeIndex.get(nodeId)\n if (!node) return\n // Center the node in the viewport at the current scale.\n transform.offsetX = width / 2 - node.x * transform.scale\n transform.offsetY = height / 2 - node.y * transform.scale\n applyTransform()\n setSelected(nodeId, false)\n },\n destroy(): void {\n if (interactive) {\n svg.removeEventListener('wheel', onWheel)\n svg.removeEventListener('mousedown', onDown)\n svg.removeEventListener('mousemove', onMove)\n svg.removeEventListener('mouseup', onUp)\n svg.removeEventListener('mouseleave', onUp)\n }\n svg.remove()\n popup.remove()\n circles.clear()\n lines.length = 0\n },\n }\n}\n\nfunction getComputedPosition(elm: HTMLElement): string {\n const inline = elm.style.position\n if (inline) return inline\n const view = elm.ownerDocument?.defaultView\n if (view?.getComputedStyle) return view.getComputedStyle(elm).position || 'static'\n return 'static'\n}\n","// @fortemi/graph — framework-agnostic graph presentation/projection helpers\n// without the database-backed graph-source controller.\n//\n// This root entry intentionally has no runtime dependency on @fortemi/core, so\n// JS-only hosts can import graph helpers without pulling the PGlite module\n// graph. Database-backed graph-source orchestration lives at\n// @fortemi/graph/controller.\n//\n// Pure projection helpers (layout, filtering, coloring, sizing, bounds,\n// neighborhood, snapshot) give React and JS-only hosts the shared logic to\n// render their own SVG/canvas views.\n//\n// Community *detection* intentionally lives in @fortemi/core (the base layer);\n// this package only renders/projects graphs it is given and orchestrates which\n// source to load.\n\nexport const VERSION = '2026.9.5'\n\nexport type {\n GraphNode,\n GraphEdge,\n GraphCommunity,\n CommunityGraph,\n GraphLayoutAlgorithm,\n PositionedGraphNode,\n PositionedCommunity,\n PositionedGraph,\n GraphBounds,\n ViewportTransform,\n} from './types.js'\n\nexport { computeDegrees, nodeRadius } from './degree.js'\nexport type { NodeRadiusOptions } from './degree.js'\n\nexport { COMMUNITY_COLORS, UNASSIGNED_COMMUNITY_COLOR, colorForCommunity } from './color.js'\n\nexport { filterCommunityGraph } from './filter.js'\nexport type { GraphFilter } from './filter.js'\n\nexport { layoutCommunityGraph } from './layout.js'\nexport type { LayoutOptions, NodeRadiusResolver, PositionMap } from './layout.js'\n\nexport { computeGraphBounds, fitGraphToViewport } from './bounds.js'\nexport type { FitOptions } from './bounds.js'\n\nexport {\n buildAdjacency,\n neighborsOf,\n expandNeighborhood,\n subgraphForNodes,\n neighborhoodSubgraph,\n} from './neighborhood.js'\nexport type { ExpandOptions } from './neighborhood.js'\n\nexport {\n GRAPH_SNAPSHOT_VERSION,\n serializeGraphSnapshot,\n stringifyGraphSnapshot,\n deserializeGraphSnapshot,\n} from './serialize.js'\nexport type { GraphSnapshot, SerializeSnapshotOptions } from './serialize.js'\n\nexport {\n GREYSCALE_COMMUNITY_RAMP,\n communityRanks,\n mapCommunityGraph,\n bakeRenderGraph,\n stringifyRenderGraph,\n isRenderGraph,\n hasBakedPositions,\n loadRenderSnapshot,\n} from './render-prep.js'\nexport type {\n RenderNode,\n RenderLink,\n RenderGraph,\n CommunityPalette,\n MapCommunityGraphOptions,\n BakeRenderGraphOptions,\n LoadRenderSnapshotOptions,\n} from './render-prep.js'\n\nexport { applyControlFilters, communityLegend } from './contract.js'\nexport type {\n GraphControlContract,\n GraphControlFilters,\n GraphLegendEntry,\n} from './contract.js'\n\nexport { renderCommunityGraph } from './render-dom.js'\nexport type {\n GraphRenderOptions,\n GraphRenderFilters,\n GraphRenderUpdate,\n GraphRenderHandle,\n} from './render-dom.js'\n\nexport type {\n GraphControllerDb,\n GraphSourceMode,\n GraphLayoutState,\n GraphTransitionState,\n GraphControllerStatus,\n GraphSourceRef,\n GraphControllerState,\n GraphControllerOptions,\n GraphControllerListener,\n} from './controller.js'\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fortemi/graph",
3
- "version": "2026.9.3",
3
+ "version": "2026.9.5",
4
4
  "description": "Framework-agnostic graph tooling for fortemi: pure TypeScript helpers for community-graph layout, filtering, color assignment, degree sizing, bounds/fit, neighborhood expansion, and static snapshot serialization, plus an optional controller subpath for database-backed graph-source selection. No React; consumed by @fortemi/react and JS-only hosts.",
5
5
  "keywords": [
6
6
  "fortemi",
@@ -48,7 +48,7 @@
48
48
  "LICENSE"
49
49
  ],
50
50
  "dependencies": {
51
- "@fortemi/core": "2026.9.3"
51
+ "@fortemi/core": "2026.9.5"
52
52
  },
53
53
  "devDependencies": {
54
54
  "tsup": "^8.3.5",