@modernrelay/orbit-react 0.15.0 → 0.17.0
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 +18 -2
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode, CSSProperties, RefAttributes, ReactElement } from 'react';
|
|
2
|
-
import { GraphSnapshotInput, Accessor, GraphNode, Scale, AcceptedEdge, LayoutKind,
|
|
2
|
+
import { GraphSnapshotInput, Accessor, GraphNode, Scale, AcceptedEdge, LayoutKind, SimulationInput, ThemeInput, MetricColumn, ScaleChannelInfo, GraphTheme, LabelConfig, AccessibilityConfig, NodeId, SubgraphSpec, FilterSpec, DimensionSpec, GroupSpec, GroupBySpec, ClusterSpec, ScaleLimits, WorkerFactoryOption, SearchResult, SearchUnavailableReason, CreateGraphInstanceOptions, SelectionState, DegradeEvent, GraphPerfSnapshot, ResolvedGroup, MetaEdge, JsonValue, ViewportState, GraphViewState, SetViewStateResult, PathOptions, PathResult, ExpandNodeResult, ResolvedCluster, BeginIngestOptions, IngestSession, TimelinePlayback, CrossfilterSession, MetricName, Revisions, GraphDiagnostic, GraphInstance, DimensionSummary, BrushState, EdgeId, InstanceStatus } from '@modernrelay/orbit-core';
|
|
3
3
|
import { EngineFactory, FitViewOptions } from '@modernrelay/orbit-core/engine';
|
|
4
4
|
export { G as GraphProvider, a as GraphProviderProps } from './GraphProvider-B8ITDXS0.js';
|
|
5
5
|
export { D as DEFAULT_CORNER_OFFSET, G as GraphCorner, a as GraphLabelsSurface, b as GraphOverlaySurface, u as useResolvedInstance } from './shared-n98tkXJe.js';
|
|
@@ -32,7 +32,9 @@ interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {
|
|
|
32
32
|
linkColor?: Accessor<AcceptedEdge<E>, string>;
|
|
33
33
|
linkWidth?: Accessor<AcceptedEdge<E>, number>;
|
|
34
34
|
layout?: LayoutKind;
|
|
35
|
-
|
|
35
|
+
/** Full config or a named preset ('calm' | 'spread' | 'tight' |
|
|
36
|
+
* 'lively'). Omitted = the 'calm' preset — the measured-good default. */
|
|
37
|
+
simulation?: SimulationInput;
|
|
36
38
|
/** theme tokens: full GraphTheme, Partial over a named base, or the
|
|
37
39
|
* v0.1 `{background}` shorthand. Diffed structurally (JSON). */
|
|
38
40
|
theme?: ThemeInput;
|
|
@@ -146,6 +148,20 @@ interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {
|
|
|
146
148
|
onSearchResultUnavailable?: (result: SearchResult, reason: SearchUnavailableReason) => void;
|
|
147
149
|
/** Captured at first render (instance construction option). Default true. */
|
|
148
150
|
fitViewOnFirstData?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Camera behavior while the FIRST force-layout settle runs (construction-
|
|
153
|
+
* only). 'follow' (default): the camera keeps the contracting graph framed
|
|
154
|
+
* with periodic animated refits and a final fit at quiescence; any user
|
|
155
|
+
* camera input cancels it. 'once': single fit at first quiescence.
|
|
156
|
+
* false: fit at first data only.
|
|
157
|
+
*/
|
|
158
|
+
fitViewOnSettle?: 'follow' | 'once' | false;
|
|
159
|
+
/**
|
|
160
|
+
* Upper bound on the zoom any internally issued fit lands at (construction-
|
|
161
|
+
* only). Small graphs otherwise fit until nodes balloon. Default 1.5;
|
|
162
|
+
* null disables the clamp.
|
|
163
|
+
*/
|
|
164
|
+
fitViewMaxZoom?: number | null;
|
|
149
165
|
/** service seam (instance construction option, D7): custom
|
|
150
166
|
* revision-aware services — most usefully an async `expansion` service
|
|
151
167
|
* backed by the host's own data source, so `expandNode`/the context menu's
|
package/dist/index.js
CHANGED
|
@@ -417,6 +417,8 @@ function GraphInner(props, ref) {
|
|
|
417
417
|
if (props.fitViewOnFirstData !== void 0) {
|
|
418
418
|
options.fitViewOnFirstData = props.fitViewOnFirstData;
|
|
419
419
|
}
|
|
420
|
+
if (props.fitViewOnSettle !== void 0) options.fitViewOnSettle = props.fitViewOnSettle;
|
|
421
|
+
if (props.fitViewMaxZoom !== void 0) options.fitViewMaxZoom = props.fitViewMaxZoom;
|
|
420
422
|
if (props.searchIndex !== void 0) options.searchIndex = props.searchIndex;
|
|
421
423
|
if (props.limits !== void 0) options.limits = props.limits;
|
|
422
424
|
if (props.execution !== void 0) options.execution = props.execution;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Lasso.tsx","../src/LabelLayer.tsx","../src/LiveRegion.tsx","../src/Graph.tsx"],"names":["useState","useRef","useEffect","jsx","useLayoutEffect","prevRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Lasso — the Shift+drag freeform selection overlay.\n *\n * A transparent div rendered above the engine canvas that captures pointer\n * events ONLY while Shift is held (or a lasso drag is already in progress);\n * otherwise `pointer-events: none` so it never intercepts canvas interaction.\n *\n * Gesture: pointerdown starts capture; pointermove appends polygon points\n * throttled to at most one per animation frame (leading edge + trailing\n * commit); an SVG path previews the polygon; pointerup with ≥3 points calls\n * `instance.selectWithinPolygon(polygon, { additive: metaKey })`. Abort paths\n * (pointercancel, Escape, unmount) always release capture and leave no state.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { CSSProperties, PointerEvent as ReactPointerEvent, ReactElement } from 'react';\nimport { useAmbientGraphInstance } from './GraphProvider';\n\ninterface DragState {\n pointerId: number;\n /** Committed polygon vertices (overlay-local screen coordinates). */\n points: [number, number][];\n /** Latest uncommitted pointer position (throttle window open). */\n pending: [number, number] | null;\n /** Scheduled animation frame id; null when no frame is pending. */\n frame: number | null;\n}\n\nconst OVERLAY_BASE: CSSProperties = {\n position: 'absolute',\n inset: 0,\n touchAction: 'none',\n userSelect: 'none',\n};\n\nconst OVERLAY_INACTIVE: CSSProperties = { ...OVERLAY_BASE, pointerEvents: 'none' };\nconst OVERLAY_ACTIVE: CSSProperties = {\n ...OVERLAY_BASE,\n pointerEvents: 'auto',\n cursor: 'crosshair',\n};\n\nconst SVG_STYLE: CSSProperties = {\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n overflow: 'visible',\n};\n\nfunction toPathData(points: readonly [number, number][]): string {\n let d = `M ${points[0]![0]} ${points[0]![1]}`;\n for (let i = 1; i < points.length; i++) d += ` L ${points[i]![0]} ${points[i]![1]}`;\n return points.length >= 3 ? `${d} Z` : d;\n}\n\n/** rAF when available; otherwise run synchronously (headless environments\n * throttling degrades to per-event appends, which is still correct). */\nfunction scheduleFrame(cb: () => void): number | null {\n if (typeof requestAnimationFrame === 'function') return requestAnimationFrame(cb);\n cb();\n return null;\n}\n\nfunction cancelFrame(id: number | null): void {\n if (id !== null && typeof cancelAnimationFrame === 'function') cancelAnimationFrame(id);\n}\n\n/** Guarded pointer capture: jsdom (and older engines) may not implement it. */\nfunction capturePointer(el: HTMLElement, pointerId: number): void {\n if (typeof el.setPointerCapture === 'function') {\n try {\n el.setPointerCapture(pointerId);\n } catch {\n /* capture unavailable for this pointer — the gesture still works */\n }\n }\n}\n\nfunction releasePointer(el: HTMLElement, pointerId: number): void {\n if (typeof el.releasePointerCapture === 'function') {\n try {\n el.releasePointerCapture(pointerId);\n } catch {\n /* no active capture — already released */\n }\n }\n}\n\n/** Internal to <Graph> (gated by its `enableLasso` prop); reads the ambient\n * instance so advanced hosts composing GraphProvider directly can reuse it. */\nexport function Lasso(): ReactElement {\n const instance = useAmbientGraphInstance('Lasso');\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const dragRef = useRef<DragState | null>(null);\n const [shiftHeld, setShiftHeld] = useState(false);\n /** Render mirror of the committed polygon; null = no drag in progress. */\n const [preview, setPreview] = useState<readonly [number, number][] | null>(null);\n\n /** Tear down the in-progress drag: cancel the pending frame, release\n * capture, clear all drag state. Safe to call when idle. */\n const releaseDrag = useCallback((): void => {\n const drag = dragRef.current;\n if (drag === null) return;\n dragRef.current = null;\n cancelFrame(drag.frame);\n const el = overlayRef.current;\n if (el !== null) releasePointer(el, drag.pointerId);\n setPreview(null);\n }, []);\n\n // Shift tracking + Escape abort. Window-level so the overlay activates\n // before it can receive any pointer event; blur releases a stuck Shift.\n useEffect(() => {\n const onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Shift') setShiftHeld(true);\n else if (e.key === 'Escape') releaseDrag();\n };\n const onKeyUp = (e: KeyboardEvent): void => {\n if (e.key === 'Shift') setShiftHeld(false);\n };\n const onBlur = (): void => setShiftHeld(false);\n window.addEventListener('keydown', onKeyDown);\n window.addEventListener('keyup', onKeyUp);\n window.addEventListener('blur', onBlur);\n return () => {\n window.removeEventListener('keydown', onKeyDown);\n window.removeEventListener('keyup', onKeyUp);\n window.removeEventListener('blur', onBlur);\n releaseDrag(); // unmount mid-drag leaves no capture and no frame\n };\n }, [releaseDrag]);\n\n const localPoint = (e: ReactPointerEvent<HTMLDivElement>): [number, number] => {\n const el = overlayRef.current;\n if (el === null) return [e.clientX, e.clientY];\n const rect = el.getBoundingClientRect();\n return [e.clientX - rect.left, e.clientY - rect.top];\n };\n\n const commitPending = (drag: DragState): void => {\n if (drag.pending === null) return;\n drag.points.push(drag.pending);\n drag.pending = null;\n setPreview([...drag.points]);\n };\n\n const onPointerDown = (e: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current !== null || e.button !== 0) return;\n // Lasso is a Shift gesture: the overlay only receives events while Shift\n // is held, but re-check for robustness (tests, synthetic dispatch).\n if (!e.shiftKey && !shiftHeld) return;\n const pointerId = e.pointerId ?? -1;\n const el = overlayRef.current;\n if (el !== null) capturePointer(el, pointerId);\n const p = localPoint(e);\n dragRef.current = { pointerId, points: [p], pending: null, frame: null };\n setPreview([p]);\n e.preventDefault();\n };\n\n const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (drag === null || (e.pointerId ?? -1) !== drag.pointerId) return;\n drag.pending = localPoint(e);\n if (drag.frame !== null) return; // throttle window open — coalesce\n // Leading edge: append immediately, then hold the window one frame at a\n // time while moves keep streaming in (trailing commit per frame).\n commitPending(drag);\n const tick = (): void => {\n drag.frame = null;\n if (dragRef.current !== drag) return; // drag ended while scheduled\n if (drag.pending !== null) {\n commitPending(drag);\n drag.frame = scheduleFrame(tick);\n }\n };\n drag.frame = scheduleFrame(tick);\n };\n\n const onPointerUp = (e: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (drag === null || (e.pointerId ?? -1) !== drag.pointerId) return;\n commitPending(drag); // the trailing point must land in the polygon\n const polygon = drag.points;\n const additive = e.metaKey;\n releaseDrag();\n if (polygon.length >= 3) instance.selectWithinPolygon(polygon, { additive });\n };\n\n const onPointerCancel = (e: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (drag === null || (e.pointerId ?? -1) !== drag.pointerId) return;\n releaseDrag();\n };\n\n const active = shiftHeld || preview !== null;\n return (\n <div\n ref={overlayRef}\n data-orbit-lasso=\"\"\n style={active ? OVERLAY_ACTIVE : OVERLAY_INACTIVE}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerCancel}\n >\n {preview !== null && preview.length > 0 ? (\n <svg data-orbit-lasso-preview=\"\" style={SVG_STYLE}>\n <path\n d={toPathData(preview)}\n fill=\"rgba(88, 134, 255, 0.12)\"\n stroke=\"rgba(88, 134, 255, 0.9)\"\n strokeWidth={1.5}\n strokeDasharray=\"4 3\"\n />\n </svg>\n ) : null}\n </div>\n );\n}\n","/**\n * LabelLayer — the DOM label lane.\n *\n * Two-channel rendering against the pinned overlay interface:\n * - `labels.subscribeCandidates` fires only when the candidate SET changes →\n * React state → one absolutely-positioned <div> per candidate. Label text\n * is rendered as a TEXT NODE only (never markup), so hostile strings in\n * node attrs appear literally.\n * - `labels.subscribePositions` fires on scheduler ticks with fresh x/y for\n * the SAME set → imperative `style.transform` writes through refs keyed by\n * id. No React re-render per tick (M0: the label lane is pure CPU O(k)).\n *\n * The layer is pointer-inert; built-in label divs opt back in as focusable\n * buttons and drive the same public selection mutators by click or Enter/Space\n * (replace normally, toggle with meta/shift). Custom renderers own their\n * content's focus semantics, avoiding a button-role wrapper around a native\n * interactive control. Node labels expose their context action through\n * right-click plus ContextMenu/Shift+F10.\n */\n\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport type {\n CSSProperties,\n KeyboardEvent as ReactKeyboardEvent,\n MouseEvent as ReactMouseEvent,\n ReactElement,\n ReactNode,\n} from 'react';\nimport type { GraphNode, LabelPlacement, NodeId } from '@modernrelay/orbit-core';\nimport { useAmbientGraphInstance } from './GraphProvider';\nimport { overlaySurface, overlayLayerStyle } from './components/shared';\n\nexport interface LabelLayerProps {\n /** Class hook applied to every label div. */\n labelClassName?: string | undefined;\n /** Escape hatch rendered INSIDE the positioned div instead of the text node. */\n renderNodeLabel?: ((ctx: { node: GraphNode<any>; text: string }) => ReactNode) | undefined;\n /** Class hook applied to CLUSTER label divs (in addition to\n * `labelClassName`), so the coarse layer can be styled apart. */\n clusterLabelClassName?: string | undefined;\n /** Escape hatch for cluster labels; `memberIds` are the ids a click\n * selects. */\n renderClusterLabel?:\n | ((ctx: { clusterKey: string; text: string; memberIds: readonly NodeId[] }) => ReactNode)\n | undefined;\n}\n\n/** Placements come from two id namespaces (node ids and cluster keys), so\n * element/position maps and React keys are keyed on `(kind, id)`. */\nfunction placementKey(p: LabelPlacement): string {\n return p.kind === 'cluster' ? `cluster\\u0000${p.id}` : `node\\u0000${p.id}`;\n}\n\nconst LAYER_STYLE: CSSProperties = { ...overlayLayerStyle, overflow: 'hidden' };\n\nconst LABEL_BASE_STYLE: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n pointerEvents: 'auto',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n userSelect: 'none',\n willChange: 'transform',\n};\n\nfunction transformOf(x: number, y: number): string {\n return `translate3d(${x}px, ${y}px, 0)`;\n}\n\n/** Internal to <Graph> (gated by `labels.enabled`); reads the ambient\n * instance so hosts composing GraphProvider directly can reuse it. */\nexport function LabelLayer(props: LabelLayerProps): ReactElement {\n const instance = useAmbientGraphInstance('LabelLayer');\n const labels = overlaySurface(instance).labels;\n\n const [candidates, setCandidates] = useState<readonly LabelPlacement[]>([]);\n /** Live label elements, keyed by `(kind, id)` (populated via ref callbacks). */\n const elementsRef = useRef(new Map<string, HTMLDivElement>());\n /** Freshest known screen position per candidate — written by BOTH channels\n * so a candidate re-render never snaps back to a stale x/y. */\n const positionsRef = useRef(new Map<string, readonly [number, number]>());\n const layerRef = useRef<HTMLDivElement | null>(null);\n\n // Candidate SET changes: throttled re-rank → React re-render of the content.\n useEffect(() => {\n if (labels === undefined) return undefined;\n return labels.subscribeCandidates((list) => {\n const positions = positionsRef.current;\n const keep = new Set<string>();\n for (const p of list) {\n const key = placementKey(p);\n keep.add(key);\n positions.set(key, [p.x, p.y]);\n }\n for (const key of [...positions.keys()]) {\n if (!keep.has(key)) positions.delete(key);\n }\n // The core REUSES the emitted array/placement objects across ticks\n // copy so React state gets a fresh identity (no Object.is bail-out).\n setCandidates(list.map((p) => ({ ...p })));\n });\n }, [labels]);\n\n // Scheduler position ticks: imperative transform writes, no re-render.\n useLayoutEffect(() => {\n if (labels === undefined) return undefined;\n return labels.subscribePositions((list) => {\n const elements = elementsRef.current;\n const positions = positionsRef.current;\n for (const p of list) {\n const key = placementKey(p);\n positions.set(key, [p.x, p.y]);\n const el = elements.get(key);\n if (el !== undefined) el.style.transform = transformOf(p.x, p.y);\n }\n });\n }, [labels]);\n\n // Click-selection semantics through the public mutators:\n // plain click replaces the node selection; meta/shift click toggles the id.\n const selectLabel = (id: NodeId, additive: boolean): void => {\n if (additive) {\n const cur = instance.store.getState().selection.nodeIds;\n instance.setSelection(cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id]);\n return;\n }\n instance.setSelection([id]);\n };\n\n const onLabelClick = (id: NodeId, e: ReactMouseEvent<HTMLDivElement>): void => {\n e.stopPropagation();\n selectLabel(id, e.metaKey || e.shiftKey);\n };\n\n // a cluster label resolves to its MEMBER node ids through the\n // core mutator — clusters never enter the group selection namespace.\n const onClusterLabelClick = (key: string, e: ReactMouseEvent<HTMLDivElement>): void => {\n e.stopPropagation();\n instance.selectCluster(key, { additive: e.metaKey || e.shiftKey });\n };\n\n const onLabelKeyDown = (\n p: LabelPlacement,\n e: ReactKeyboardEvent<HTMLDivElement>,\n ): void => {\n // Native button activation does not exist for a div with role=\"button\",\n // and keyboard-triggered `contextmenu` coordinates vary by browser. Give\n // node labels (including native controls supplied by a custom renderer)\n // an explicit ContextMenu / Shift+F10 path, anchored at the label's center\n // in the same container-relative coordinate system as a pointer-triggered\n // menu.\n if (\n p.kind !== 'cluster' &&\n (e.key === 'ContextMenu' || (e.key === 'F10' && e.shiftKey))\n ) {\n e.preventDefault();\n e.stopPropagation();\n const layerRect = layerRef.current?.getBoundingClientRect();\n if (layerRect === undefined) return;\n const labelRect = e.currentTarget.getBoundingClientRect();\n instance.requestNodeContextMenu(p.id, [\n labelRect.left + labelRect.width / 2 - layerRect.left,\n labelRect.top + labelRect.height / 2 - layerRect.top,\n ]);\n return;\n }\n // An escape-hatch renderer may supply its own focusable control. Its\n // Enter keydown can synthesize a click that already bubbles through the\n // label's click path, so handling the bubbled keydown here as well would\n // activate the label twice.\n if (e.target !== e.currentTarget) return;\n if (e.key !== 'Enter' && e.key !== ' ') return;\n e.preventDefault();\n e.stopPropagation();\n const additive = e.metaKey || e.shiftKey;\n if (p.kind === 'cluster') instance.selectCluster(p.id, { additive });\n else selectLabel(p.id, additive);\n };\n\n // Right-click routes into the SAME typed 'contextMenu' channel the canvas\n // gesture feeds. Label divs are pointerEvents:'auto' (click-to-focus), so\n // without this the gesture dies here and the browser's native menu opens\n // on exactly the nodes prominent enough to carry labels. Coordinates are\n // container-relative CSS px (the layer fills the container), matching the\n // payload contract the canvas path uses.\n const onLabelContextMenu = (id: NodeId, e: ReactMouseEvent<HTMLDivElement>): void => {\n e.preventDefault();\n e.stopPropagation();\n const rect = layerRef.current?.getBoundingClientRect();\n if (rect === undefined) return;\n instance.requestNodeContextMenu(id, [e.clientX - rect.left, e.clientY - rect.top]);\n };\n\n const clusterMembers = (key: string): readonly NodeId[] =>\n instance.getClusters().find((c) => c.key === key)?.memberIds ?? [];\n\n return (\n <div data-orbit-label-layer=\"\" ref={layerRef} style={LAYER_STYLE}>\n {candidates.map((p) => {\n const key = placementKey(p);\n const [x, y] = positionsRef.current.get(key) ?? [p.x, p.y];\n const isCluster = p.kind === 'cluster';\n const className = isCluster\n ? [props.labelClassName, props.clusterLabelClassName].filter(Boolean).join(' ') ||\n undefined\n : props.labelClassName;\n const hasCustomRenderer = isCluster\n ? props.renderClusterLabel !== undefined\n : props.renderNodeLabel !== undefined;\n return (\n <div\n key={key}\n {...(isCluster ? { 'data-orbit-cluster-label': p.id } : { 'data-orbit-label': p.id })}\n className={className}\n {...(!hasCustomRenderer\n ? {\n role: 'button',\n tabIndex: 0,\n 'aria-label': p.text,\n ...(!isCluster ? { 'aria-haspopup': 'menu' as const } : {}),\n }\n : {})}\n style={{ ...LABEL_BASE_STYLE, transform: transformOf(x, y) }}\n ref={(el) => {\n if (el === null) elementsRef.current.delete(key);\n else elementsRef.current.set(key, el);\n }}\n onClick={(e) => (isCluster ? onClusterLabelClick(p.id, e) : onLabelClick(p.id, e))}\n onKeyDown={(e) => onLabelKeyDown(p, e)}\n // Cluster labels keep the browser menu for now: their click\n // already selects members, and no cluster menu target exists.\n onContextMenu={isCluster ? undefined : (e) => onLabelContextMenu(p.id, e)}\n >\n {/* text-node-only rendering holds for both kinds: a hostile\n key or label appears literally, never as markup. */}\n {isCluster\n ? props.renderClusterLabel !== undefined\n ? props.renderClusterLabel({\n clusterKey: p.id,\n text: p.text,\n memberIds: clusterMembers(p.id),\n })\n : p.text\n : props.renderNodeLabel !== undefined\n ? props.renderNodeLabel({\n node: instance.getNode(p.id) ?? { id: p.id },\n text: p.text,\n })\n : p.text}\n </div>\n );\n })}\n </div>\n );\n}\n","/**\n * LiveRegion — screen-reader announcements.\n *\n * A visually-hidden `aria-live=\"polite\"` region adjacent to the canvas. It\n * subscribes to the STORE (never the frame clock, so simulation frames can\n * never announce) and speaks a coalesced summary — node/edge counts,\n * selection count, status — at most once every 800ms and only when the\n * summary STRING changes. Trailing-edge coalescing: a burst of store changes\n * lands as ONE announcement carrying the freshest state.\n *\n * Gated off entirely when `accessibility.announcements === false`.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { ReactElement } from 'react';\nimport type { GraphStoreState } from '@modernrelay/orbit-core';\nimport { useAmbientGraphInstance } from './GraphProvider';\nimport { visuallyHiddenStyle } from './components/shared';\n\nexport const ANNOUNCE_INTERVAL_MS = 800;\n\nexport interface LiveRegionProps {\n /** `accessibility.announcements`; false gates all announcements. Default true. */\n announcements?: boolean | undefined;\n}\n\nfunction summarize(s: GraphStoreState): string {\n const selected = s.selection.nodeIds.length + s.selection.edgeIds.length;\n return `Graph ${s.status}. ${s.nodeCount} nodes, ${s.edgeCount} edges. ${selected} selected.`;\n}\n\n/** Internal to <Graph>; reads the ambient instance so hosts composing\n * GraphProvider directly can reuse it. */\nexport function LiveRegion(props: LiveRegionProps): ReactElement {\n const instance = useAmbientGraphInstance('LiveRegion');\n const enabled = props.announcements !== false;\n const [message, setMessage] = useState('');\n /** Last ANNOUNCED summary; seeded at subscribe time so the initial state\n * (already conveyed by the container's aria-label) is never announced. */\n const lastAnnouncedRef = useRef<string | null>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!enabled) return undefined;\n const store = instance.store;\n lastAnnouncedRef.current = summarize(store.getState());\n\n const fire = (): void => {\n timerRef.current = null;\n const next = summarize(store.getState());\n if (next === lastAnnouncedRef.current) return;\n lastAnnouncedRef.current = next;\n setMessage(next);\n };\n\n const unsubscribe = store.subscribe(() => {\n if (timerRef.current !== null) return; // window open — coalesce\n if (summarize(store.getState()) === lastAnnouncedRef.current) return;\n timerRef.current = setTimeout(fire, ANNOUNCE_INTERVAL_MS);\n });\n\n return () => {\n unsubscribe();\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n }, [instance, enabled]);\n\n return (\n <div\n data-orbit-live-region=\"\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style={visuallyHiddenStyle}\n >\n {message}\n </div>\n );\n}\n","/**\n * <Graph> — the declarative React binding over a headless GraphInstance.\n *\n * Binding parity: one committed render that changes multiple declarative\n * props issues AT MOST ONE applyHostUpdate carrying exactly the changed keys,\n * so a multi-prop commit produces exactly one store revision and at most one\n * engine commit.\n */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { CSSProperties, ForwardedRef, ReactElement, ReactNode, RefAttributes } from 'react';\nimport {\n canonicalJson,\n canonicalScaleKey,\n createGraphInstance,\n sameGroupSpecArrays,\n} from '@modernrelay/orbit-core';\nimport type {\n Accessor,\n AcceptedEdge,\n AccessibilityConfig,\n BeginIngestOptions,\n ClusterSpec,\n CreateGraphInstanceOptions,\n CrossfilterSession,\n DimensionSpec,\n ExpandNodeResult,\n FilterExpr,\n FilterSpec,\n GraphDiagnostic,\n GraphHostUpdate,\n GraphInstance,\n GraphNode,\n GraphSnapshotInput,\n GraphTheme,\n GraphViewState,\n GroupBySpec,\n GroupSpec,\n IngestSession,\n JsonValue,\n LabelConfig,\n LayoutKind,\n MetaEdge,\n MetricColumn,\n PathOptions,\n PathResult,\n MetricName,\n NodeId,\n ResolvedCluster,\n ResolvedGroup,\n Revisions,\n Scale,\n ScaleChannelInfo,\n SearchResult,\n SearchUnavailableReason,\n SelectionState,\n ScaleLimits,\n WorkerFactoryOption,\n DegradeEvent,\n GraphPerfSnapshot,\n SetViewStateResult,\n SimulationConfig,\n SubgraphSpec,\n ThemeInput,\n TimelinePlayback,\n ViewportState,\n} from '@modernrelay/orbit-core';\nimport type { EngineFactory, FitViewOptions } from '@modernrelay/orbit-core/engine';\nimport { GraphProvider } from './GraphProvider';\nimport { setSearchResultUnavailableCallback, useScaleInfoSubscription } from './hooks';\nimport { Lasso } from './Lasso';\nimport { LabelLayer } from './LabelLayer';\nimport { LiveRegion } from './LiveRegion';\nimport { overlaySurface, visuallyHiddenStyle } from './components/shared';\n\n/** Snapshot handed to `renderLegend`: the active scale info per styling\n * channel (null when the channel is not scale-valued) plus the resolved\n * theme tokens. Recomputed on model/scope/render/theme store changes. */\nexport interface GraphLegendRenderInfo<N = Record<string, unknown>> {\n nodeColor: ScaleChannelInfo<N> | null;\n nodeSize: ScaleChannelInfo<N> | null;\n theme: GraphTheme;\n}\n\nexport interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {\n /** Engine factory; captured at first render — one factory per instance. */\n engine: EngineFactory;\n data?: GraphSnapshotInput<N, E>;\n /** Constant, accessor, or Scale descriptor. Scale-valued props compare\n * by canonical structural value — equal inline literals never reproject. */\n nodeColor?: Accessor<GraphNode<N>, string> | Scale<string, N>;\n nodeSize?: Accessor<GraphNode<N>, number> | Scale<number, N>;\n linkColor?: Accessor<AcceptedEdge<E>, string>;\n linkWidth?: Accessor<AcceptedEdge<E>, number>;\n layout?: LayoutKind;\n simulation?: SimulationConfig;\n /** theme tokens: full GraphTheme, Partial over a named base, or the\n * v0.1 `{background}` shorthand. Diffed structurally (JSON). */\n theme?: ThemeInput;\n /** async metric columns, joined once with revision-gated admission.\n * Diffed by array reference. */\n metrics?: readonly MetricColumn[];\n /** image sprites: synchronous string-ref accessor (URL/blob ref/cache\n * key — opaque to orbit). Diffed by reference. */\n nodeImage?: (node: GraphNode<N>) => string | null;\n /** instanced arrowheads (capability-gated; inert when unsupported). */\n edgeArrows?: boolean;\n /** runtime link-render toggle — a config-only commit. */\n showLinks?: boolean;\n /** emphasis-ring toggle (default true). False clears the ring once and\n * suppresses every driver (hover, focusNode, emphasizeNode). */\n emphasisRing?: boolean;\n /** legend escape hatch: rendered inside the provider in a positioned\n * wrapper (bottom-left) whenever provided; re-invoked when scale info or\n * theme changes. Return custom JSX, or compose <GraphLegend> from\n * '@modernrelay/orbit-react/components/Legend' for the built-in rendering. */\n renderLegend?: (info: GraphLegendRenderInfo<N>) => ReactNode;\n /** DOM label lane; forwarded through applyHostUpdate. `enabled: false`\n * also unmounts the <LabelLayer> overlay entirely. */\n labels?: LabelConfig<N>;\n /** accessibility runtime options; forwarded through applyHostUpdate\n * and mirrored onto the container ARIA surface / live region. */\n accessibility?: AccessibilityConfig<N>;\n /** Class hook applied to every DOM label div. */\n labelClassName?: string;\n /** Escape hatch: custom label content rendered INSIDE the positioned label\n * div, replacing the default text node. */\n renderNodeLabel?: (ctx: { node: GraphNode<N>; text: string }) => ReactNode;\n /** Class hook applied to cluster label divs, in addition to\n * `labelClassName`. */\n clusterLabelClassName?: string;\n /** Escape hatch: custom cluster-label content (replaces the default text\n * node; text-node-only rendering otherwise). `memberIds` are the ids a\n * click selects. */\n renderClusterLabel?: (ctx: {\n clusterKey: string;\n text: string;\n memberIds: readonly NodeId[];\n }) => ReactNode;\n /** Controlled selection of the NODE namespace; providing it once flips\n * ownership permanently. Edge/group namespaces stay instance-owned. */\n selection?: readonly NodeId[];\n /** hard scope: feed ONLY the resolved subset through the reconciler;\n * `null` restores the full accepted model. Diffed STRUCTURALLY (specs are\n * small), so a new-but-equal object is a no-op. UNCONTROLLED-ONLY in v0.5:\n * this prop and isolateSelection/resetIsolation write the same\n * instance-owned state — last writer wins, and omitting the prop leaves\n * the last written scope in place. */\n subgraph?: SubgraphSpec | null;\n /** soft filter: mask (hide/dim) with ZERO relayout; `null` clears.\n * Diffed by canonical structural compare — serializable exprs by JSON,\n * function predicates by reference — so a new-but-equal spec never\n * re-publishes (and the core no-ops canonical-equal specs regardless). */\n filter?: FilterSpec<N, E> | null;\n /** crossfilter dimensions (declarative; brushes live on the session\n * — reach it via useGraphCrossfilter or handle.getCrossfilterSession).\n * Forwarded on array-reference change; the core no-ops when every\n * DimensionSpec element is reference-equal. */\n crossfilter?: readonly DimensionSpec<N>[];\n /** manual groups; `null` clears. Diffed STRUCTURALLY (equal inline\n * literals never re-forward). Providing it once flips the groups slice to\n * CONTROLLED: handle ops then fire onGroupsChange with the next\n * array instead of writing — reflect it back here. Config error together\n * with `groupBy`. */\n groups?: readonly GroupSpec[] | null;\n /** derived grouping; `null` clears. Reference-diffed (the spec\n * carries a function accessor); the core additionally no-ops structurally\n * equal respecs. Membership under groupBy is derived and READ-ONLY\n * groupNodes/ungroup become config errors; setGroupCollapsed toggles the\n * instance-owned per-key collapsed residue. */\n groupBy?: GroupBySpec<N> | null;\n /** stage-4 non-collapsing clusters; `null` clears (D2).\n * Reference-diffed (the spec carries a function accessor). Clusters PRESERVE\n * every node and edge — they never collapse anything — so they coexist with\n * `groups`/`groupBy`. Their labels ride the overlay lane under\n * `labels.maxZoom` and select their member nodes on click. */\n clusters?: ClusterSpec<N> | null;\n /** PERSISTENT pins — independent of transient drag\n * pinning: the engine receives the UNION, so releasing a drag on a\n * persistently-pinned node leaves it pinned. Providing it once latches the\n * slice controlled: handle ops then fire onPinnedChange with the\n * next array instead of writing. `null` clears (D2). */\n pinnedNodeIds?: readonly NodeId[] | null;\n /** node attr fields the DEFAULT search service indexes (ids always).\n * Absent = id-only search — the service never guesses attr names.\n * CONSTRUCTION-ONLY (D7, spec host construction options): read once at\n * mount; changing it requires a keyed remount (a changed prop warns once\n * and is ignored). */\n searchIndex?: readonly string[];\n /** Degradation-ladder thresholds. CONSTRUCTION-ONLY: read\n * once at mount; a runtime change warns once and is ignored. */\n limits?: Partial<ScaleLimits>;\n /** Execution mode. CONSTRUCTION-ONLY: read once\n * at mount; a runtime change warns once and is ignored. Current worker\n * cargo: columnar acceptance off-thread. */\n execution?: 'auto' | 'main' | 'worker';\n /** Worker construction tri-option. CONSTRUCTION-ONLY. */\n workerFactory?: WorkerFactoryOption;\n /** result contract: the instance-wide DEFAULT for an activated\n * search result that cannot be focused ('not-loaded' | 'out-of-scope' |\n * 'filtered'). `<GraphSearch onResultUnavailable>` overrides it locally;\n * the host reacts explicitly (fetch/publish an overlay, reset isolation,\n * alter filters) — search never mutates scope/filters itself. */\n onSearchResultUnavailable?: (result: SearchResult, reason: SearchUnavailableReason) => void;\n /** Captured at first render (instance construction option). Default true. */\n fitViewOnFirstData?: boolean;\n /** service seam (instance construction option, D7): custom\n * revision-aware services — most usefully an async `expansion` service\n * backed by the host's own data source, so `expandNode`/the context menu's\n * Expand run against the network instead of the built-in local-adjacency\n * walk. CONSTRUCTION-ONLY: read once at mount; changing it requires a keyed\n * remount. */\n services?: CreateGraphInstanceOptions<N, E>['services'];\n /** Shift+drag freeform lasso selection overlay. Default true. */\n enableLasso?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Rendered inside the provider, above (after) the canvas container. */\n children?: ReactNode;\n onNodeClick?: (payload: { node: GraphNode<N>; metaKey?: boolean }) => void;\n onBackgroundClick?: () => void;\n onNodeHover?: (payload: { node: GraphNode<N> | null }) => void;\n onEdgeClick?: (payload: { edge: AcceptedEdge<E> }) => void;\n onEdgeHover?: (payload: { edge: AcceptedEdge<E> | null }) => void;\n onNodeDragStart?: (payload: { node: GraphNode<N> }) => void;\n onNodeDragEnd?: (payload: { node: GraphNode<N>; x: number; y: number }) => void;\n /** Fires with the full namespaced SelectionState. */\n onSelectionChange?: (payload: SelectionState) => void;\n /** ladder step engagement/disengagement (notification pattern). */\n onDegrade?: (event: DegradeEvent) => void;\n /** throttled telemetry sample — never per frame. */\n onPerfSample?: (snapshot: GraphPerfSnapshot) => void;\n /** Fires on a super-node hit with the resolved group payload, never a GraphNode. */\n onGroupClick?: (payload: { group: ResolvedGroup; metaKey?: boolean }) => void;\n /** Fires on a meta-edge hit with the MetaEdge record used by the count badge. */\n onMetaEdgeClick?: (payload: { metaEdge: MetaEdge }) => void;\n /** groups slice change callback: op results (uncontrolled), op\n * INTENTS (controlled — reflect the array back into `groups`), and groupBy\n * re-derivations (notification). Receives the resolved array. */\n onGroupsChange?: (groups: readonly ResolvedGroup[]) => void;\n /** durable source coordinate — forwarded verbatim; serialized into\n * view states and canonically compared on restore. Diffed by canonical\n * JSON, so a new-but-equal object never re-forwards. */\n dataRef?: JsonValue;\n /** aggregate restore intent (fires once per restore/history\n * transaction touching a controlled slice or serialized styling): reflect\n * every participating prop in ONE commit; matching values acknowledge. */\n onViewStateRestore?: (intent: {\n transactionId: string;\n source: 'setViewState' | 'undo' | 'redo';\n next: unknown;\n }) => void;\n /** fired INSTEAD of applying a state whose dataRef mismatches. */\n onViewStateMismatch?: (stored: JsonValue | undefined, current: JsonValue | undefined) => void;\n /** persistent-pin slice change: the applied set when\n * uncontrolled, the INTENT when controlled. */\n onPinnedChange?: (pinnedNodeIds: readonly NodeId[]) => void;\n onViewportChange?: (v: ViewportState) => void;\n onReady?: () => void;\n onError?: (payload: { error: Error }) => void;\n}\n\nexport interface GraphHandle<N = Record<string, unknown>, E = Record<string, unknown>> {\n /** `opts` is accepted for forward compatibility; core v0.1 ignores it. */\n fitView(opts?: FitViewOptions): void;\n zoomIn(): void;\n zoomOut(): void;\n /** `opts` is accepted for forward compatibility; core v0.1 ignores it. */\n setViewport(v: Partial<ViewportState>, opts?: { durationMs?: number }): void;\n focusNode(id: NodeId): void;\n /** ring-only emphasis, no camera move (null clears; unknown ids\n * no-op). The keyboard-navigation analog of hover. */\n emphasizeNode(id: NodeId | null): void;\n /** telemetry snapshot (never raw attrs or ids). */\n getPerfSnapshot(): GraphPerfSnapshot;\n /** Open the typed context menu for a node from host chrome (a list row, a\n * custom label) — the same 'contextMenu' event the canvas gesture emits.\n * `screen` is container-relative CSS px. */\n requestNodeContextMenu(id: NodeId, screen: readonly [number, number]): void;\n /** serialize the exploration state (see core docs). */\n getViewState(opts?: { includePositions?: false }): GraphViewState;\n /** atomic restore; typed results, never partial. */\n setViewState(\n raw: unknown,\n opts?: { ignoreMismatch?: boolean },\n ): Promise<SetViewStateResult>;\n /** picture export: 'png' via the engine screenshot; 'svg' via the\n * engine-free exporter (typed export-too-large past the bound;\n * raster-hybrid fallback available). */\n exportImage(format: 'png'): Promise<Blob>;\n exportImage(\n format: 'svg',\n opts?: { maxSvgElements?: number; fallback?: 'raster-hybrid' },\n ): Promise<string>;\n /** bounded object export; typed rejection past the limit. */\n exportData(\n scope?: 'visible' | 'accepted',\n opts?: { limit?: number },\n ): Promise<{ nodes: readonly GraphNode<N>[]; edges: readonly AcceptedEdge<E>[] }>;\n /** memory-bounded JSONL stream over one pinned revision. */\n exportDataStream(scope?: 'visible' | 'accepted'): AsyncGenerator<string, void, undefined>;\n /** bounded id → [x, y] map (one position readback). */\n exportLayout(opts?: { limit?: number }): Promise<ReadonlyMap<NodeId, readonly [number, number]>>;\n /** layout JSONL stream over one pinned readback. */\n exportLayoutStream(): AsyncGenerator<string, void, undefined>;\n setSelection(ids: readonly NodeId[]): void;\n clearSelection(): void;\n // --- persistent pins ---\n /** Hold nodes at their CURRENT position (independent of drag pinning). */\n pinNodes(ids: readonly NodeId[]): void;\n unpinNodes(ids: readonly NodeId[]): void;\n // --- paths ---\n /** Resolve + atomically emphasize a path; null = unreachable (a result).\n * Emphasis is session-local — released by clearPath, any selection\n * mutation, undo/redo, or a scene rebuild; never in history/view state. */\n findPath(sourceId: NodeId, targetId: NodeId, options?: PathOptions): Promise<PathResult | null>;\n clearPath(): void;\n // --- selection algebra ---\n /** Expand to the 1-hop neighborhood of `id` (or of the current selection). */\n selectNeighbors(id?: NodeId): void;\n selectAll(): void;\n invertSelection(): void;\n /** Resolve a SCREEN-coordinate polygon to node ids and replace (default) or\n * union (`additive`) the node selection; returns the resolved ids. */\n selectWithinPolygon(\n polygon: readonly [number, number][],\n opts?: { additive?: boolean },\n ): readonly NodeId[];\n // --- pin / hide slices ---\n /** Pin at `xy` (space coords) or at the node's current position. */\n pinNode(id: NodeId, xy?: readonly [number, number]): void;\n unpinNode(id: NodeId): void;\n clearPins(): void;\n hideNodes(ids: readonly NodeId[]): void;\n showAll(): void;\n // --- hard scope + expansion ---\n /** Hard-scope to the current node selection; no-op when empty. */\n isolateSelection(): void;\n /** Clear the hard scope — the full accepted model returns. */\n resetIsolation(): void;\n /** Ego-expand `id` through the configured ExpansionService. */\n expandNode(id: NodeId, opts?: { hops?: number }): Promise<ExpandNodeResult>;\n /** Abort `id`'s pending expansion and remove its committed expansion\n * overlays. */\n retractExpansion(id: NodeId): void;\n // --- group operations ---\n /** Add one group (same acyclic/singly-parented validation as the `groups` prop).\n * Controlled mode fires onGroupsChange with the next array instead. */\n groupNodes(spec: GroupSpec): void;\n /** Remove one group definition; its id prunes from selection.groupIds. */\n ungroup(groupId: string): void;\n /** Collapse/expand one group as a structural diff — the ONE op allowed on\n * groupBy-derived groups (toggles the per-key collapsed residue). */\n setGroupCollapsed(groupId: string, collapsed: boolean): void;\n // --- node folds: an EXISTING node stands for its own neighbourhood.\n // Distinct from `expandNode`/`retractExpansion`, which navigate the data\n // source; a fold is pure containment over what is already loaded. ---\n /** Hide `id`'s neighbourhood behind `id`, rerouting the members' outside\n * edges onto it. Members default to unclaimed neighbours (first fold wins). */\n foldNode(id: NodeId, opts?: { memberIds?: readonly NodeId[] }): void;\n /** Return `id`'s folded members to the scene. No-op when not folded. */\n unfoldNode(id: NodeId): void;\n /** The members `id` stands for, or null when it is not folded. */\n getFold(id: NodeId): { memberIds: readonly NodeId[] } | null;\n // --- stage-4 clusters ---\n /** Current clusters over the physical scene (keys, members, force center,\n * settled centroid). Empty when no `clusters` prop is active. */\n getClusters(): readonly ResolvedCluster[];\n /** Select a cluster's MEMBER node ids; `additive` unions. */\n selectCluster(key: string, opts?: { additive?: boolean }): void;\n // --- revisioned ingestion ---\n /** Begin a bounded, cancellable ingest session. */\n beginIngest(opts: BeginIngestOptions): IngestSession<N, E>;\n /** Atomically remove exactly one committed overlay; unknown ids are an\n * idempotent `{ removed: false }`. */\n removeOverlay(overlayId: string): { removed: boolean };\n // --- history ---\n /** Undo the most recent uncontrolled mutation entry (selection / hidden /\n * pins / scope / brushes). Returns false when there is nothing to undo. */\n undo(): boolean;\n /** Re-apply the most recently undone entry. False when nothing to redo. */\n redo(): boolean;\n // --- timeline playback ---\n /** Play a brush window across a numeric/temporal dimension's domain\n * (crossfilter mask fast path; one playing dimension at a time). */\n playTimeline(key: string, playback?: Partial<TimelinePlayback>): void;\n pauseTimeline(): void;\n // --- crossfilter ---\n /** The crossfilter session facade, or null until the `crossfilter` prop\n * has configured dimensions over an accepted base. */\n getCrossfilterSession(): CrossfilterSession | null;\n // --- styling reads ---\n /** legend surface: the active Scale on a styling channel plus its\n * resolved domain or categorical rows; null when not scale-valued. */\n getScaleInfo(channel: 'nodeColor' | 'nodeSize'): ScaleChannelInfo<N> | null;\n /** metric read for one node id (built-in degree family + admitted\n * columns); null for unknown ids or metrics and for null/non-finite values. */\n getMetricValue(metric: MetricName, id: NodeId): number | null;\n getRevisions(): Revisions;\n getDiagnostics(): readonly GraphDiagnostic[];\n instance: GraphInstance<N, E>;\n}\n\n/** Last-committed declarative props. Fields are `| undefined` (not optional)\n * so the diff record is assignable under exactOptionalPropertyTypes. */\ninterface CommittedProps<N, E> {\n data: GraphSnapshotInput<N, E> | undefined;\n nodeColor: Accessor<GraphNode<N>, string> | Scale<string, N> | undefined;\n /** Canonical structural key when the committed nodeColor is a Scale;\n * undefined for accessor/constant forms (those diff by reference). */\n nodeColorKey: string | undefined;\n nodeSize: Accessor<GraphNode<N>, number> | Scale<number, N> | undefined;\n nodeSizeKey: string | undefined;\n linkColor: Accessor<AcceptedEdge<E>, string> | undefined;\n linkWidth: Accessor<AcceptedEdge<E>, number> | undefined;\n layout: LayoutKind | undefined;\n simulation: SimulationConfig | undefined;\n /** JSON form of the last committed `theme` prop (small token set). */\n themeJson: string | undefined;\n metrics: readonly MetricColumn[] | undefined;\n nodeImage: ((node: GraphNode<N>) => string | null) | undefined;\n edgeArrows: boolean | undefined;\n showLinks: boolean | undefined;\n emphasisRing: boolean | undefined;\n selection: readonly NodeId[] | undefined;\n labels: LabelConfig<N> | undefined;\n accessibility: AccessibilityConfig<N> | undefined;\n /** JSON form of the last committed `subgraph` prop — specs are small, so\n * the diff is a structural string compare ('null' when scope cleared). */\n subgraphJson: string | undefined;\n /** Last committed `filter` prop + its canonical key: exprs compare\n * by JSON, function predicates by reference. */\n filter: FilterSpec<N, E> | null | undefined;\n filterKey: string | undefined;\n /** Last committed `crossfilter` prop, compared by array reference. */\n crossfilter: readonly DimensionSpec<N>[] | undefined;\n /** Last committed `groups` prop (structural diff via sameGroupSpecArrays;\n * — equal inline literals never re-forward). */\n groups: readonly GroupSpec[] | null | undefined;\n dataRef: JsonValue | undefined;\n /** Last committed `groupBy` prop (reference diff — function-bearing). */\n groupBy: GroupBySpec<N> | null | undefined;\n /** Last committed `clusters` prop (reference diff — function-bearing). */\n clusters: ClusterSpec<N> | null | undefined;\n /** Last committed `pinnedNodeIds` prop, compared by shallow element diff. */\n pinnedNodeIds: readonly NodeId[] | null | undefined;\n /** Last committed `searchIndex` prop (shallow element diff). */\n searchIndex: readonly string[] | undefined;\n}\n\n/**\n * Canonical key of a scale-valued styling channel: `canonicalScaleKey`\n * when the value is a Scale descriptor, undefined for constant/accessor forms\n * (which diff by reference). Equal inline scale literals therefore never\n * re-forward; a function `by` keys by reference identity inside the core.\n */\nfunction scaleKeyOf(value: unknown): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const kind = (value as { kind?: unknown }).kind;\n if (kind !== 'sequential' && kind !== 'categorical' && kind !== 'diverging') return undefined;\n return canonicalScaleKey(value as Scale<unknown>);\n}\n\n/** Diff one nodeColor/nodeSize channel: scale forms compare by canonical key,\n * everything else by reference (a scale↔accessor flip always differs). */\nfunction styleChannelChanged(\n prevValue: unknown,\n prevKey: string | undefined,\n nextValue: unknown,\n nextKey: string | undefined,\n): boolean {\n if (nextKey !== undefined || prevKey !== undefined) return nextKey !== prevKey;\n return prevValue !== nextValue;\n}\n\n/** Canonical key of one filter side: 'u' absent, 'fn' a function predicate\n * (paired with a reference compare), else the expr JSON. */\nfunction filterSideKey(side: FilterExpr | ((item: never) => boolean) | undefined): string {\n if (side === undefined) return 'u';\n if (typeof side === 'function') return 'fn';\n return JSON.stringify(side);\n}\n\nfunction filterKeyOf<N, E>(spec: FilterSpec<N, E> | null): string {\n if (spec === null) return 'null';\n return `${spec.mode ?? 'hide'}|${filterSideKey(spec.nodes)}|${filterSideKey(spec.edges)}`;\n}\n\n/** Canonical-equal check: keys match AND any function sides are the SAME\n * references (a changed predicate function must re-evaluate). */\nfunction sameFilterSpec<N, E>(\n prev: FilterSpec<N, E> | null | undefined,\n prevKey: string | undefined,\n next: FilterSpec<N, E> | null,\n nextKey: string,\n): boolean {\n if (prevKey === undefined || prevKey !== nextKey) return false;\n if (next === null) return prev === null;\n if (prev === null || prev === undefined) return false;\n if (typeof next.nodes === 'function' && next.nodes !== prev.nodes) return false;\n if (typeof next.edges === 'function' && next.edges !== prev.edges) return false;\n return true;\n}\n\ninterface CallbackHolder<N, E> {\n onNodeClick: ((payload: { node: GraphNode<N>; metaKey?: boolean }) => void) | undefined;\n onBackgroundClick: (() => void) | undefined;\n onNodeHover: ((payload: { node: GraphNode<N> | null }) => void) | undefined;\n onEdgeClick: ((payload: { edge: AcceptedEdge<E> }) => void) | undefined;\n onEdgeHover: ((payload: { edge: AcceptedEdge<E> | null }) => void) | undefined;\n onNodeDragStart: ((payload: { node: GraphNode<N> }) => void) | undefined;\n onNodeDragEnd: ((payload: { node: GraphNode<N>; x: number; y: number }) => void) | undefined;\n onSelectionChange: ((payload: SelectionState) => void) | undefined;\n onDegrade: ((event: DegradeEvent) => void) | undefined;\n onPerfSample: ((snapshot: GraphPerfSnapshot) => void) | undefined;\n onGroupClick: ((payload: { group: ResolvedGroup; metaKey?: boolean }) => void) | undefined;\n onMetaEdgeClick: ((payload: { metaEdge: MetaEdge }) => void) | undefined;\n onGroupsChange: ((groups: readonly ResolvedGroup[]) => void) | undefined;\n onViewStateRestore:\n | ((intent: {\n transactionId: string;\n source: 'setViewState' | 'undo' | 'redo';\n next: unknown;\n }) => void)\n | undefined;\n onViewStateMismatch:\n | ((stored: JsonValue | undefined, current: JsonValue | undefined) => void)\n | undefined;\n onPinnedChange: ((pinnedNodeIds: readonly NodeId[]) => void) | undefined;\n onViewportChange: ((v: ViewportState) => void) | undefined;\n onReady: (() => void) | undefined;\n onError: ((payload: { error: Error }) => void) | undefined;\n}\n\nfunction sameIdArrays(a: readonly NodeId[], b: readonly NodeId[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nconst CONTAINER_BASE_STYLE: CSSProperties = {\n position: 'relative',\n width: '100%',\n height: '100%',\n};\n\n// The canvas layer fills the outer div; children render after it in DOM order\n// so they naturally stack above the canvas.\nconst CANVAS_STYLE: CSSProperties = { position: 'absolute', inset: 0 };\n\n/** Positioned wrapper for the `renderLegend` slot: bottom-left, above\n * the canvas, interactive (category rows are clickable). */\nconst LEGEND_SLOT_STYLE: CSSProperties = {\n position: 'absolute',\n left: 12,\n bottom: 12,\n};\n\n/** `renderLegend` slot host: re-reads getScaleInfo on every store publication\n * that can move scale info (model/scope/render revisions) or theme change,\n * and re-invokes the host's render function with the fresh snapshot. */\nfunction LegendSlot<N, E>(props: {\n instance: GraphInstance<N, E>;\n renderLegend: (info: GraphLegendRenderInfo<N>) => ReactNode;\n}): ReactElement {\n const { instance } = props;\n const { version, theme } = useScaleInfoSubscription(instance);\n const info = useMemo<GraphLegendRenderInfo<N>>(\n () => ({\n nodeColor: instance.getScaleInfo('nodeColor'),\n nodeSize: instance.getScaleInfo('nodeSize'),\n theme,\n }),\n // `version` is the invalidation token: a new store revision can change\n // what getScaleInfo returns without changing any other dependency.\n [instance, theme, version],\n );\n return (\n <div data-orbit-legend-slot=\"\" style={LEGEND_SLOT_STYLE}>\n {props.renderLegend(info)}\n </div>\n );\n}\n\nfunction GraphInner<N, E>(\n props: GraphProps<N, E>,\n ref: ForwardedRef<GraphHandle<N, E>>,\n): ReactElement {\n // Lazy, once per mounted component. `engine`/`fitViewOnFirstData`/\n // `searchIndex` are construction options (D7); later changes to them are\n // intentionally ignored (searchIndex additionally warns once below).\n const [instance] = useState<GraphInstance<N, E>>(() => {\n const options: CreateGraphInstanceOptions<N, E> = { engine: props.engine };\n if (props.fitViewOnFirstData !== undefined) {\n options.fitViewOnFirstData = props.fitViewOnFirstData;\n }\n if (props.searchIndex !== undefined) options.searchIndex = props.searchIndex;\n if (props.limits !== undefined) options.limits = props.limits;\n if (props.execution !== undefined) options.execution = props.execution;\n if (props.workerFactory !== undefined) options.workerFactory = props.workerFactory;\n if (props.services !== undefined) options.services = props.services;\n return createGraphInstance<N, E>(options);\n });\n const searchIndexWarnedRef = useRef(false);\n const limitsWarnedRef = useRef(false);\n const initialLimitsRef = useRef(props.limits);\n if (props.limits !== initialLimitsRef.current && !limitsWarnedRef.current) {\n limitsWarnedRef.current = true;\n console.warn(\n 'orbit: `limits` is a construction-only prop — the runtime change is ignored; remount with a key to apply new thresholds.',\n );\n }\n const executionWarnedRef = useRef(false);\n const initialExecutionRef = useRef(props.execution);\n if (props.execution !== initialExecutionRef.current && !executionWarnedRef.current) {\n executionWarnedRef.current = true;\n console.warn(\n 'orbit: `execution` is a construction-only prop — the runtime change is ignored; remount with a key to switch lanes.',\n );\n }\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // --- latest-callback holder: event subscriptions read through this ref so\n // per-render callback identity churn never resubscribes ---\n const callbacksRef = useRef<CallbackHolder<N, E>>({\n onNodeClick: undefined,\n onBackgroundClick: undefined,\n onNodeHover: undefined,\n onEdgeClick: undefined,\n onEdgeHover: undefined,\n onNodeDragStart: undefined,\n onNodeDragEnd: undefined,\n onSelectionChange: undefined,\n onDegrade: undefined,\n onPerfSample: undefined,\n onGroupClick: undefined,\n onMetaEdgeClick: undefined,\n onGroupsChange: undefined,\n onViewStateRestore: undefined,\n onViewStateMismatch: undefined,\n onPinnedChange: undefined,\n onViewportChange: undefined,\n onReady: undefined,\n onError: undefined,\n });\n useLayoutEffect(() => {\n callbacksRef.current = {\n onNodeClick: props.onNodeClick,\n onBackgroundClick: props.onBackgroundClick,\n onNodeHover: props.onNodeHover,\n onEdgeClick: props.onEdgeClick,\n onEdgeHover: props.onEdgeHover,\n onNodeDragStart: props.onNodeDragStart,\n onNodeDragEnd: props.onNodeDragEnd,\n onSelectionChange: props.onSelectionChange,\n onDegrade: props.onDegrade,\n onPerfSample: props.onPerfSample,\n onGroupClick: props.onGroupClick,\n onMetaEdgeClick: props.onMetaEdgeClick,\n onGroupsChange: props.onGroupsChange,\n onViewStateRestore: props.onViewStateRestore,\n onViewStateMismatch: props.onViewStateMismatch,\n onPinnedChange: props.onPinnedChange,\n onViewportChange: props.onViewportChange,\n onReady: props.onReady,\n onError: props.onError,\n };\n });\n\n // --- event subscriptions: keyed on the instance only; identity churn of\n // the props is absorbed by callbacksRef. A LAYOUT effect so it commits\n // BEFORE the prop-diff layout effect of the NEXT render pass — and on the\n // first pass the subscriptions land in the same commit as the initial\n // host update's effects; events fired during that first applyHostUpdate\n // (e.g. a mount-time 'degrade' engagement) are re-emittable states\n // that the ladder re-evaluates, but ordering here still matters for any\n // strictly edge-triggered channel, so subscriptions must not lag a frame\n // behind the data. ---\n useLayoutEffect(() => {\n const offs = [\n instance.on('nodeClick', (p) => callbacksRef.current.onNodeClick?.(p)),\n instance.on('backgroundClick', () => callbacksRef.current.onBackgroundClick?.()),\n instance.on('nodeHover', (p) => callbacksRef.current.onNodeHover?.(p)),\n instance.on('edgeClick', (p) => callbacksRef.current.onEdgeClick?.(p)),\n instance.on('edgeHover', (p) => callbacksRef.current.onEdgeHover?.(p)),\n instance.on('nodeDragStart', (p) => callbacksRef.current.onNodeDragStart?.(p)),\n instance.on('nodeDragEnd', (p) => callbacksRef.current.onNodeDragEnd?.(p)),\n instance.on('selectionChange', (p) => callbacksRef.current.onSelectionChange?.(p)),\n instance.on('degrade', (p) => callbacksRef.current.onDegrade?.(p)),\n instance.on('perfSample', (p) => callbacksRef.current.onPerfSample?.(p)),\n instance.on('groupClick', (p) => callbacksRef.current.onGroupClick?.(p)),\n instance.on('metaEdgeClick', (p) => callbacksRef.current.onMetaEdgeClick?.(p)),\n instance.on('groupsChange', (p) => callbacksRef.current.onGroupsChange?.(p.groups)),\n instance.on('viewStateRestore', (p) => callbacksRef.current.onViewStateRestore?.(p)),\n instance.on('viewStateMismatch', (p) =>\n callbacksRef.current.onViewStateMismatch?.(p.stored, p.current),\n ),\n instance.on('pinnedChange', (p) => callbacksRef.current.onPinnedChange?.(p.pinnedNodeIds)),\n instance.on('viewportChange', (v) => callbacksRef.current.onViewportChange?.(v)),\n instance.on('ready', () => callbacksRef.current.onReady?.()),\n instance.on('error', (p) => callbacksRef.current.onError?.(p)),\n ];\n return () => {\n for (const off of offs) off();\n };\n }, [instance]);\n\n // --- prop → host update: diff against the previous committed render and\n // issue at most one applyHostUpdate with exactly the changed keys ---\n const prevRef = useRef<CommittedProps<N, E> | null>(null);\n useLayoutEffect(() => {\n const prev = prevRef.current;\n const update: GraphHostUpdate<N, E> = {};\n let dirty = false;\n\n if (props.data !== undefined && (prev === null || prev.data !== props.data)) {\n update.data = props.data;\n dirty = true;\n }\n // scale-aware channels: Scale descriptors diff by canonical\n // structural key (equal inline literals never re-forward); accessor and\n // constant forms keep the reference diff.\n const nodeColorKey = scaleKeyOf(props.nodeColor);\n if (\n props.nodeColor !== undefined &&\n (prev === null ||\n styleChannelChanged(prev.nodeColor, prev.nodeColorKey, props.nodeColor, nodeColorKey))\n ) {\n update.nodeColor = props.nodeColor;\n dirty = true;\n }\n const nodeSizeKey = scaleKeyOf(props.nodeSize);\n if (\n props.nodeSize !== undefined &&\n (prev === null ||\n styleChannelChanged(prev.nodeSize, prev.nodeSizeKey, props.nodeSize, nodeSizeKey))\n ) {\n update.nodeSize = props.nodeSize;\n dirty = true;\n }\n if (props.linkColor !== undefined && (prev === null || prev.linkColor !== props.linkColor)) {\n update.linkColor = props.linkColor;\n dirty = true;\n }\n if (props.linkWidth !== undefined && (prev === null || prev.linkWidth !== props.linkWidth)) {\n update.linkWidth = props.linkWidth;\n dirty = true;\n }\n if (props.layout !== undefined && (prev === null || prev.layout !== props.layout)) {\n update.layout = props.layout;\n dirty = true;\n }\n if (\n props.simulation !== undefined &&\n (prev === null || prev.simulation !== props.simulation)\n ) {\n update.simulation = props.simulation;\n dirty = true;\n }\n // theme: a small token set — diffed structurally (JSON), so a\n // new-but-equal inline object never re-publishes.\n let themeJson: string | undefined;\n if (props.theme !== undefined) {\n themeJson = JSON.stringify(props.theme);\n if (prev === null || prev.themeJson !== themeJson) {\n update.theme = props.theme;\n dirty = true;\n }\n }\n // metric columns: array-reference diff (columns are one-shot joins).\n if (props.metrics !== undefined && (prev === null || prev.metrics !== props.metrics)) {\n update.metrics = props.metrics;\n dirty = true;\n }\n // image refs: function-prop contract — reference diff.\n if (props.nodeImage !== undefined && (prev === null || prev.nodeImage !== props.nodeImage)) {\n update.nodeImage = props.nodeImage;\n dirty = true;\n } else if (props.nodeImage === undefined && prev !== null && prev.nodeImage !== undefined) {\n // Removing the prop forwards the explicit clear; the natural\n // React idiom must not silently freeze the last accessor's images.\n update.nodeImage = null;\n dirty = true;\n }\n // Display toggles use plain value diffing for config-only commits.\n if (props.edgeArrows !== undefined && (prev === null || prev.edgeArrows !== props.edgeArrows)) {\n update.edgeArrows = props.edgeArrows;\n dirty = true;\n }\n if (props.showLinks !== undefined && (prev === null || prev.showLinks !== props.showLinks)) {\n update.showLinks = props.showLinks;\n dirty = true;\n }\n if (\n props.emphasisRing !== undefined &&\n (prev === null || prev.emphasisRing !== props.emphasisRing)\n ) {\n update.emphasisRing = props.emphasisRing;\n dirty = true;\n } else if (\n props.emphasisRing === undefined &&\n prev !== null &&\n prev.emphasisRing !== undefined\n ) {\n // Removing the prop restores the documented default (true); the\n // natural React idiom must not leave the ring silently disabled.\n update.emphasisRing = true;\n dirty = true;\n }\n if (\n props.selection !== undefined &&\n (prev === null ||\n prev.selection === undefined ||\n !sameIdArrays(prev.selection, props.selection))\n ) {\n update.selection = props.selection;\n dirty = true;\n }\n if (props.labels !== undefined && (prev === null || prev.labels !== props.labels)) {\n update.labels = props.labels;\n dirty = true;\n }\n if (\n props.accessibility !== undefined &&\n (prev === null || prev.accessibility !== props.accessibility)\n ) {\n update.accessibility = props.accessibility;\n dirty = true;\n }\n // hard scope: structural (JSON) diff — a new-but-equal spec object\n // never re-publishes. An omitted prop is never forwarded (uncontrolled).\n let subgraphJson: string | undefined;\n if (props.subgraph !== undefined) {\n subgraphJson = JSON.stringify(props.subgraph);\n if (prev === null || prev.subgraphJson !== subgraphJson) {\n update.subgraph = props.subgraph;\n dirty = true;\n }\n }\n // soft filter: canonical structural diff (exprs by JSON, function\n // predicates by reference). An omitted prop is never forwarded.\n let filterKey: string | undefined;\n if (props.filter !== undefined) {\n filterKey = filterKeyOf(props.filter);\n if (\n prev === null ||\n !sameFilterSpec(prev.filter, prev.filterKey, props.filter, filterKey)\n ) {\n update.filter = props.filter;\n dirty = true;\n }\n }\n // crossfilter dimensions: forwarded on array-reference change; the\n // core no-ops when every DimensionSpec element is reference-equal.\n if (\n props.crossfilter !== undefined &&\n (prev === null || prev.crossfilter !== props.crossfilter)\n ) {\n update.crossfilter = props.crossfilter;\n dirty = true;\n }\n // groups: structural diff (equal inline literals never\n // re-forward). An omitted prop is never forwarded — but ONCE provided\n // the core latches the slice controlled.\n if (props.dataRef !== undefined) {\n const prevRef = prev === null ? undefined : prev.dataRef;\n if (prevRef === undefined || canonicalJson(props.dataRef) !== canonicalJson(prevRef)) {\n update.dataRef = props.dataRef;\n dirty = true;\n }\n }\n if (props.groups !== undefined) {\n const prevGroups = prev === null ? undefined : prev.groups;\n if (prevGroups === undefined || !sameGroupSpecArrays(prevGroups, props.groups)) {\n update.groups = props.groups;\n dirty = true;\n }\n }\n // groupBy: reference diff (the spec carries a function accessor);\n // the core additionally no-ops structurally equal respecs.\n if (props.groupBy !== undefined && (prev === null || prev.groupBy !== props.groupBy)) {\n update.groupBy = props.groupBy;\n dirty = true;\n }\n // clusters: reference diff (function-bearing spec); the core\n // re-derives membership only on a `by` identity change.\n if (props.clusters !== undefined && (prev === null || prev.clusters !== props.clusters)) {\n update.clusters = props.clusters;\n dirty = true;\n }\n // pinnedNodeIds: shallow element diff (a small id list); ONCE\n // provided the core latches the slice controlled.\n if (props.pinnedNodeIds !== undefined) {\n const prevPinned = prev === null ? undefined : prev.pinnedNodeIds;\n const changed =\n prevPinned === undefined ||\n prevPinned === null ||\n props.pinnedNodeIds === null ||\n !sameIdArrays(prevPinned, props.pinnedNodeIds);\n if (changed) {\n update.pinnedNodeIds = props.pinnedNodeIds;\n dirty = true;\n }\n }\n // searchIndex is construction-only and is read once above. A\n // changed prop cannot take effect without a keyed remount — warn once\n // (shallow element diff, so a new-but-equal inline literal is fine).\n if (\n prev !== null &&\n !sameIdArrays(prev.searchIndex ?? [], props.searchIndex ?? []) &&\n !searchIndexWarnedRef.current\n ) {\n searchIndexWarnedRef.current = true;\n console.warn(\n '[orbit] searchIndex is construction-only: the changed value was ignored — key-remount <Graph> to change it',\n );\n }\n\n prevRef.current = {\n data: props.data,\n nodeColor: props.nodeColor,\n nodeColorKey,\n nodeSize: props.nodeSize,\n nodeSizeKey,\n linkColor: props.linkColor,\n linkWidth: props.linkWidth,\n layout: props.layout,\n simulation: props.simulation,\n themeJson,\n metrics: props.metrics,\n nodeImage: props.nodeImage,\n edgeArrows: props.edgeArrows,\n showLinks: props.showLinks,\n emphasisRing: props.emphasisRing,\n selection: props.selection,\n labels: props.labels,\n accessibility: props.accessibility,\n subgraphJson,\n filter: props.filter,\n filterKey,\n crossfilter: props.crossfilter,\n groups: props.groups,\n dataRef: props.dataRef,\n groupBy: props.groupBy,\n clusters: props.clusters,\n pinnedNodeIds: props.pinnedNodeIds,\n searchIndex: props.searchIndex,\n };\n\n if (dirty) instance.applyHostUpdate(update);\n });\n\n // Register the instance-wide default unavailable-result\n // callback so <GraphSearch> (and bespoke activation UIs) resolve it without\n // <Graph> in their import graph. Identity churn is fine — registration is a\n // WeakMap write, never a re-render.\n useLayoutEffect(() => {\n setSearchResultUnavailableCallback(instance, props.onSearchResultUnavailable);\n });\n\n\n // --- attach/detach: StrictMode's simulated remount detaches (destroying\n // the first engine) and re-attaches (fresh engine + full state replay) ---\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return undefined;\n // Each StrictMode setup (and each real mount) owns exactly one attach\n // result. Its promise may settle after cleanup because engine mounting is\n // asynchronous; a discarded generation must never inspect the newer\n // instance state or call the latest component callbacks.\n let active = true;\n void instance.attach(container).catch((err: unknown) => {\n if (!active) return;\n // A fatal mount fault already reached onError via the 'error' event.\n if (instance.store.getState().status === 'error') return;\n const error = err instanceof Error ? err : new Error(String(err));\n callbacksRef.current.onError?.({ error });\n });\n return () => {\n active = false;\n instance.detach();\n };\n }, [instance]);\n\n // --- destroy on true unmount only. destroy is irreversible, so the\n // cleanup defers it one microtask; a StrictMode remount re-runs the setup\n // synchronously first and cancels it, leaving detach/attach replay to\n // restore the engine. A real unmount has no re-setup, so destroy fires. ---\n const destroyGateRef = useRef({ pendingDestroy: false });\n useEffect(() => {\n const gate = destroyGateRef.current;\n gate.pendingDestroy = false;\n return () => {\n gate.pendingDestroy = true;\n queueMicrotask(() => {\n if (gate.pendingDestroy) instance.destroy();\n });\n };\n }, [instance]);\n\n // --- reduced motion: the binding detects the media preference and\n // reports it via instance.setReducedMotion; accessibility.reducedMotion\n // overrides inside the core. Subscribed for live preference changes. ---\n useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return undefined;\n }\n const mq = window.matchMedia('(prefers-reduced-motion: reduce)');\n const surface = overlaySurface(instance);\n surface.setReducedMotion?.(mq.matches);\n const onChange = (e: MediaQueryListEvent): void => {\n surface.setReducedMotion?.(e.matches);\n };\n if (typeof mq.addEventListener === 'function') {\n mq.addEventListener('change', onChange);\n return () => {\n mq.removeEventListener('change', onChange);\n };\n }\n // Legacy MediaQueryList (Safari < 14).\n if (typeof mq.addListener === 'function') {\n mq.addListener(onChange);\n return () => {\n mq.removeListener(onChange);\n };\n }\n return undefined;\n }, [instance]);\n\n useImperativeHandle(\n ref,\n (): GraphHandle<N, E> => ({\n fitView: (_opts?: FitViewOptions) => {\n instance.fitView();\n },\n zoomIn: () => {\n instance.zoomIn();\n },\n zoomOut: () => {\n instance.zoomOut();\n },\n setViewport: (v: Partial<ViewportState>, _opts?: { durationMs?: number }) => {\n instance.setViewport(v);\n },\n requestNodeContextMenu: (id: NodeId, screen: readonly [number, number]) => {\n instance.requestNodeContextMenu(id, screen);\n },\n getViewState: (opts?: { includePositions?: false }): GraphViewState =>\n instance.getViewState(opts),\n setViewState: (\n raw: unknown,\n opts?: { ignoreMismatch?: boolean },\n ): Promise<SetViewStateResult> => instance.setViewState(raw, opts),\n exportImage: ((format: 'png' | 'svg', opts?: { maxSvgElements?: number; fallback?: 'raster-hybrid' }) =>\n format === 'png' ? instance.exportImage('png') : instance.exportImage('svg', opts)) as GraphHandle<N, E>['exportImage'],\n exportData: (scope?: 'visible' | 'accepted', opts?: { limit?: number }) =>\n instance.exportData(scope, opts),\n exportDataStream: (scope?: 'visible' | 'accepted') => instance.exportDataStream(scope),\n exportLayout: (opts?: { limit?: number }) => instance.exportLayout(opts),\n exportLayoutStream: () => instance.exportLayoutStream(),\n focusNode: (id: NodeId) => {\n instance.focusNode(id);\n },\n emphasizeNode: (id: NodeId | null) => {\n instance.emphasizeNode(id);\n },\n getPerfSnapshot: () => instance.getPerfSnapshot(),\n setSelection: (ids: readonly NodeId[]) => {\n instance.setSelection(ids);\n },\n findPath: (sourceId: NodeId, targetId: NodeId, options?: PathOptions) =>\n instance.findPath(sourceId, targetId, options),\n clearPath: () => {\n instance.clearPath();\n },\n clearSelection: () => {\n instance.clearSelection();\n },\n selectNeighbors: (id?: NodeId) => {\n instance.selectNeighbors(id);\n },\n selectAll: () => {\n instance.selectAll();\n },\n invertSelection: () => {\n instance.invertSelection();\n },\n selectWithinPolygon: (\n polygon: readonly [number, number][],\n opts?: { additive?: boolean },\n ): readonly NodeId[] => instance.selectWithinPolygon(polygon, opts),\n pinNode: (id: NodeId, xy?: readonly [number, number]) => {\n instance.pinNode(id, xy);\n },\n unpinNode: (id: NodeId) => {\n instance.unpinNode(id);\n },\n clearPins: () => {\n instance.clearPins();\n },\n hideNodes: (ids: readonly NodeId[]) => {\n instance.hideNodes(ids);\n },\n showAll: () => {\n instance.showAll();\n },\n isolateSelection: () => {\n instance.isolateSelection();\n },\n resetIsolation: () => {\n instance.resetIsolation();\n },\n expandNode: (id: NodeId, opts?: { hops?: number }): Promise<ExpandNodeResult> =>\n instance.expandNode(id, opts),\n retractExpansion: (id: NodeId) => {\n instance.retractExpansion(id);\n },\n pinNodes: (ids: readonly NodeId[]) => {\n instance.pinNodes(ids);\n },\n unpinNodes: (ids: readonly NodeId[]) => {\n instance.unpinNodes(ids);\n },\n groupNodes: (spec: GroupSpec) => {\n instance.groupNodes(spec);\n },\n ungroup: (groupId: string) => {\n instance.ungroup(groupId);\n },\n setGroupCollapsed: (groupId: string, collapsed: boolean) => {\n instance.setGroupCollapsed(groupId, collapsed);\n },\n foldNode: (id: NodeId, opts?: { memberIds?: readonly NodeId[] }) => {\n instance.foldNode(id, opts);\n },\n unfoldNode: (id: NodeId) => {\n instance.unfoldNode(id);\n },\n getFold: (id: NodeId): { memberIds: readonly NodeId[] } | null => instance.getFold(id),\n getClusters: (): readonly ResolvedCluster[] => instance.getClusters(),\n selectCluster: (key: string, opts?: { additive?: boolean }) => {\n instance.selectCluster(key, opts);\n },\n beginIngest: (opts: BeginIngestOptions): IngestSession<N, E> => instance.beginIngest(opts),\n removeOverlay: (overlayId: string): { removed: boolean } =>\n instance.removeOverlay(overlayId),\n undo: (): boolean => instance.undo(),\n redo: (): boolean => instance.redo(),\n playTimeline: (key: string, playback?: Partial<TimelinePlayback>) => {\n instance.playTimeline(key, playback);\n },\n pauseTimeline: () => {\n instance.pauseTimeline();\n },\n getCrossfilterSession: (): CrossfilterSession | null => instance.getCrossfilterSession(),\n getScaleInfo: (channel: 'nodeColor' | 'nodeSize'): ScaleChannelInfo<N> | null =>\n instance.getScaleInfo(channel),\n getMetricValue: (metric: MetricName, id: NodeId): number | null =>\n instance.getMetricValue(metric, id),\n getRevisions: () => instance.getRevisions(),\n getDiagnostics: () => instance.getDiagnostics(),\n instance,\n }),\n [instance],\n );\n\n // --- container ARIA surface ---\n const descriptionId = useId();\n const description = props.accessibility?.description;\n\n return (\n <div className={props.className} style={{ ...CONTAINER_BASE_STYLE, ...props.style }}>\n <GraphProvider instance={instance}>\n {/* Engine-owned canvas layer: must never contain React children. */}\n <div\n ref={containerRef}\n data-orbit-canvas=\"\"\n style={CANVAS_STYLE}\n role=\"application\"\n aria-label={props.accessibility?.label ?? 'Graph visualization'}\n aria-describedby={description !== undefined ? descriptionId : undefined}\n />\n {description !== undefined ? (\n <div id={descriptionId} style={visuallyHiddenStyle}>\n {description}\n </div>\n ) : null}\n {/* DOM label lane: candidates via React, positions imperative. */}\n {props.labels?.enabled !== false ? (\n <LabelLayer\n labelClassName={props.labelClassName}\n renderNodeLabel={props.renderNodeLabel}\n clusterLabelClassName={props.clusterLabelClassName}\n renderClusterLabel={props.renderClusterLabel}\n />\n ) : null}\n {/* Lasso overlay: above the canvas, pointer-inert unless Shift-drag. */}\n {props.enableLasso !== false ? <Lasso /> : null}\n {/* live region: store-driven, coalesced, visually hidden. */}\n <LiveRegion announcements={props.accessibility?.announcements} />\n {/* legend slot: positioned wrapper re-rendered on scale/theme\n changes; the host returns custom JSX (or composes <GraphLegend>). */}\n {props.renderLegend !== undefined ? (\n <LegendSlot instance={instance} renderLegend={props.renderLegend} />\n ) : null}\n {props.children}\n </GraphProvider>\n </div>\n );\n}\n\n/** forwardRef erases generics; restore them with a typed call signature. */\ntype GraphComponent = <N = Record<string, unknown>, E = Record<string, unknown>>(\n props: GraphProps<N, E> & RefAttributes<GraphHandle<N, E>>,\n) => ReactElement;\n\nexport const Graph = forwardRef(GraphInner) as GraphComponent;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/Lasso.tsx","../src/LabelLayer.tsx","../src/LiveRegion.tsx","../src/Graph.tsx"],"names":["useState","useRef","useEffect","jsx","useLayoutEffect","prevRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Lasso — the Shift+drag freeform selection overlay.\n *\n * A transparent div rendered above the engine canvas that captures pointer\n * events ONLY while Shift is held (or a lasso drag is already in progress);\n * otherwise `pointer-events: none` so it never intercepts canvas interaction.\n *\n * Gesture: pointerdown starts capture; pointermove appends polygon points\n * throttled to at most one per animation frame (leading edge + trailing\n * commit); an SVG path previews the polygon; pointerup with ≥3 points calls\n * `instance.selectWithinPolygon(polygon, { additive: metaKey })`. Abort paths\n * (pointercancel, Escape, unmount) always release capture and leave no state.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { CSSProperties, PointerEvent as ReactPointerEvent, ReactElement } from 'react';\nimport { useAmbientGraphInstance } from './GraphProvider';\n\ninterface DragState {\n pointerId: number;\n /** Committed polygon vertices (overlay-local screen coordinates). */\n points: [number, number][];\n /** Latest uncommitted pointer position (throttle window open). */\n pending: [number, number] | null;\n /** Scheduled animation frame id; null when no frame is pending. */\n frame: number | null;\n}\n\nconst OVERLAY_BASE: CSSProperties = {\n position: 'absolute',\n inset: 0,\n touchAction: 'none',\n userSelect: 'none',\n};\n\nconst OVERLAY_INACTIVE: CSSProperties = { ...OVERLAY_BASE, pointerEvents: 'none' };\nconst OVERLAY_ACTIVE: CSSProperties = {\n ...OVERLAY_BASE,\n pointerEvents: 'auto',\n cursor: 'crosshair',\n};\n\nconst SVG_STYLE: CSSProperties = {\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n overflow: 'visible',\n};\n\nfunction toPathData(points: readonly [number, number][]): string {\n let d = `M ${points[0]![0]} ${points[0]![1]}`;\n for (let i = 1; i < points.length; i++) d += ` L ${points[i]![0]} ${points[i]![1]}`;\n return points.length >= 3 ? `${d} Z` : d;\n}\n\n/** rAF when available; otherwise run synchronously (headless environments\n * throttling degrades to per-event appends, which is still correct). */\nfunction scheduleFrame(cb: () => void): number | null {\n if (typeof requestAnimationFrame === 'function') return requestAnimationFrame(cb);\n cb();\n return null;\n}\n\nfunction cancelFrame(id: number | null): void {\n if (id !== null && typeof cancelAnimationFrame === 'function') cancelAnimationFrame(id);\n}\n\n/** Guarded pointer capture: jsdom (and older engines) may not implement it. */\nfunction capturePointer(el: HTMLElement, pointerId: number): void {\n if (typeof el.setPointerCapture === 'function') {\n try {\n el.setPointerCapture(pointerId);\n } catch {\n /* capture unavailable for this pointer — the gesture still works */\n }\n }\n}\n\nfunction releasePointer(el: HTMLElement, pointerId: number): void {\n if (typeof el.releasePointerCapture === 'function') {\n try {\n el.releasePointerCapture(pointerId);\n } catch {\n /* no active capture — already released */\n }\n }\n}\n\n/** Internal to <Graph> (gated by its `enableLasso` prop); reads the ambient\n * instance so advanced hosts composing GraphProvider directly can reuse it. */\nexport function Lasso(): ReactElement {\n const instance = useAmbientGraphInstance('Lasso');\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const dragRef = useRef<DragState | null>(null);\n const [shiftHeld, setShiftHeld] = useState(false);\n /** Render mirror of the committed polygon; null = no drag in progress. */\n const [preview, setPreview] = useState<readonly [number, number][] | null>(null);\n\n /** Tear down the in-progress drag: cancel the pending frame, release\n * capture, clear all drag state. Safe to call when idle. */\n const releaseDrag = useCallback((): void => {\n const drag = dragRef.current;\n if (drag === null) return;\n dragRef.current = null;\n cancelFrame(drag.frame);\n const el = overlayRef.current;\n if (el !== null) releasePointer(el, drag.pointerId);\n setPreview(null);\n }, []);\n\n // Shift tracking + Escape abort. Window-level so the overlay activates\n // before it can receive any pointer event; blur releases a stuck Shift.\n useEffect(() => {\n const onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === 'Shift') setShiftHeld(true);\n else if (e.key === 'Escape') releaseDrag();\n };\n const onKeyUp = (e: KeyboardEvent): void => {\n if (e.key === 'Shift') setShiftHeld(false);\n };\n const onBlur = (): void => setShiftHeld(false);\n window.addEventListener('keydown', onKeyDown);\n window.addEventListener('keyup', onKeyUp);\n window.addEventListener('blur', onBlur);\n return () => {\n window.removeEventListener('keydown', onKeyDown);\n window.removeEventListener('keyup', onKeyUp);\n window.removeEventListener('blur', onBlur);\n releaseDrag(); // unmount mid-drag leaves no capture and no frame\n };\n }, [releaseDrag]);\n\n const localPoint = (e: ReactPointerEvent<HTMLDivElement>): [number, number] => {\n const el = overlayRef.current;\n if (el === null) return [e.clientX, e.clientY];\n const rect = el.getBoundingClientRect();\n return [e.clientX - rect.left, e.clientY - rect.top];\n };\n\n const commitPending = (drag: DragState): void => {\n if (drag.pending === null) return;\n drag.points.push(drag.pending);\n drag.pending = null;\n setPreview([...drag.points]);\n };\n\n const onPointerDown = (e: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current !== null || e.button !== 0) return;\n // Lasso is a Shift gesture: the overlay only receives events while Shift\n // is held, but re-check for robustness (tests, synthetic dispatch).\n if (!e.shiftKey && !shiftHeld) return;\n const pointerId = e.pointerId ?? -1;\n const el = overlayRef.current;\n if (el !== null) capturePointer(el, pointerId);\n const p = localPoint(e);\n dragRef.current = { pointerId, points: [p], pending: null, frame: null };\n setPreview([p]);\n e.preventDefault();\n };\n\n const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (drag === null || (e.pointerId ?? -1) !== drag.pointerId) return;\n drag.pending = localPoint(e);\n if (drag.frame !== null) return; // throttle window open — coalesce\n // Leading edge: append immediately, then hold the window one frame at a\n // time while moves keep streaming in (trailing commit per frame).\n commitPending(drag);\n const tick = (): void => {\n drag.frame = null;\n if (dragRef.current !== drag) return; // drag ended while scheduled\n if (drag.pending !== null) {\n commitPending(drag);\n drag.frame = scheduleFrame(tick);\n }\n };\n drag.frame = scheduleFrame(tick);\n };\n\n const onPointerUp = (e: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (drag === null || (e.pointerId ?? -1) !== drag.pointerId) return;\n commitPending(drag); // the trailing point must land in the polygon\n const polygon = drag.points;\n const additive = e.metaKey;\n releaseDrag();\n if (polygon.length >= 3) instance.selectWithinPolygon(polygon, { additive });\n };\n\n const onPointerCancel = (e: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (drag === null || (e.pointerId ?? -1) !== drag.pointerId) return;\n releaseDrag();\n };\n\n const active = shiftHeld || preview !== null;\n return (\n <div\n ref={overlayRef}\n data-orbit-lasso=\"\"\n style={active ? OVERLAY_ACTIVE : OVERLAY_INACTIVE}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerCancel}\n >\n {preview !== null && preview.length > 0 ? (\n <svg data-orbit-lasso-preview=\"\" style={SVG_STYLE}>\n <path\n d={toPathData(preview)}\n fill=\"rgba(88, 134, 255, 0.12)\"\n stroke=\"rgba(88, 134, 255, 0.9)\"\n strokeWidth={1.5}\n strokeDasharray=\"4 3\"\n />\n </svg>\n ) : null}\n </div>\n );\n}\n","/**\n * LabelLayer — the DOM label lane.\n *\n * Two-channel rendering against the pinned overlay interface:\n * - `labels.subscribeCandidates` fires only when the candidate SET changes →\n * React state → one absolutely-positioned <div> per candidate. Label text\n * is rendered as a TEXT NODE only (never markup), so hostile strings in\n * node attrs appear literally.\n * - `labels.subscribePositions` fires on scheduler ticks with fresh x/y for\n * the SAME set → imperative `style.transform` writes through refs keyed by\n * id. No React re-render per tick (M0: the label lane is pure CPU O(k)).\n *\n * The layer is pointer-inert; built-in label divs opt back in as focusable\n * buttons and drive the same public selection mutators by click or Enter/Space\n * (replace normally, toggle with meta/shift). Custom renderers own their\n * content's focus semantics, avoiding a button-role wrapper around a native\n * interactive control. Node labels expose their context action through\n * right-click plus ContextMenu/Shift+F10.\n */\n\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport type {\n CSSProperties,\n KeyboardEvent as ReactKeyboardEvent,\n MouseEvent as ReactMouseEvent,\n ReactElement,\n ReactNode,\n} from 'react';\nimport type { GraphNode, LabelPlacement, NodeId } from '@modernrelay/orbit-core';\nimport { useAmbientGraphInstance } from './GraphProvider';\nimport { overlaySurface, overlayLayerStyle } from './components/shared';\n\nexport interface LabelLayerProps {\n /** Class hook applied to every label div. */\n labelClassName?: string | undefined;\n /** Escape hatch rendered INSIDE the positioned div instead of the text node. */\n renderNodeLabel?: ((ctx: { node: GraphNode<any>; text: string }) => ReactNode) | undefined;\n /** Class hook applied to CLUSTER label divs (in addition to\n * `labelClassName`), so the coarse layer can be styled apart. */\n clusterLabelClassName?: string | undefined;\n /** Escape hatch for cluster labels; `memberIds` are the ids a click\n * selects. */\n renderClusterLabel?:\n | ((ctx: { clusterKey: string; text: string; memberIds: readonly NodeId[] }) => ReactNode)\n | undefined;\n}\n\n/** Placements come from two id namespaces (node ids and cluster keys), so\n * element/position maps and React keys are keyed on `(kind, id)`. */\nfunction placementKey(p: LabelPlacement): string {\n return p.kind === 'cluster' ? `cluster\\u0000${p.id}` : `node\\u0000${p.id}`;\n}\n\nconst LAYER_STYLE: CSSProperties = { ...overlayLayerStyle, overflow: 'hidden' };\n\nconst LABEL_BASE_STYLE: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n pointerEvents: 'auto',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n userSelect: 'none',\n willChange: 'transform',\n};\n\nfunction transformOf(x: number, y: number): string {\n return `translate3d(${x}px, ${y}px, 0)`;\n}\n\n/** Internal to <Graph> (gated by `labels.enabled`); reads the ambient\n * instance so hosts composing GraphProvider directly can reuse it. */\nexport function LabelLayer(props: LabelLayerProps): ReactElement {\n const instance = useAmbientGraphInstance('LabelLayer');\n const labels = overlaySurface(instance).labels;\n\n const [candidates, setCandidates] = useState<readonly LabelPlacement[]>([]);\n /** Live label elements, keyed by `(kind, id)` (populated via ref callbacks). */\n const elementsRef = useRef(new Map<string, HTMLDivElement>());\n /** Freshest known screen position per candidate — written by BOTH channels\n * so a candidate re-render never snaps back to a stale x/y. */\n const positionsRef = useRef(new Map<string, readonly [number, number]>());\n const layerRef = useRef<HTMLDivElement | null>(null);\n\n // Candidate SET changes: throttled re-rank → React re-render of the content.\n useEffect(() => {\n if (labels === undefined) return undefined;\n return labels.subscribeCandidates((list) => {\n const positions = positionsRef.current;\n const keep = new Set<string>();\n for (const p of list) {\n const key = placementKey(p);\n keep.add(key);\n positions.set(key, [p.x, p.y]);\n }\n for (const key of [...positions.keys()]) {\n if (!keep.has(key)) positions.delete(key);\n }\n // The core REUSES the emitted array/placement objects across ticks\n // copy so React state gets a fresh identity (no Object.is bail-out).\n setCandidates(list.map((p) => ({ ...p })));\n });\n }, [labels]);\n\n // Scheduler position ticks: imperative transform writes, no re-render.\n useLayoutEffect(() => {\n if (labels === undefined) return undefined;\n return labels.subscribePositions((list) => {\n const elements = elementsRef.current;\n const positions = positionsRef.current;\n for (const p of list) {\n const key = placementKey(p);\n positions.set(key, [p.x, p.y]);\n const el = elements.get(key);\n if (el !== undefined) el.style.transform = transformOf(p.x, p.y);\n }\n });\n }, [labels]);\n\n // Click-selection semantics through the public mutators:\n // plain click replaces the node selection; meta/shift click toggles the id.\n const selectLabel = (id: NodeId, additive: boolean): void => {\n if (additive) {\n const cur = instance.store.getState().selection.nodeIds;\n instance.setSelection(cur.includes(id) ? cur.filter((x) => x !== id) : [...cur, id]);\n return;\n }\n instance.setSelection([id]);\n };\n\n const onLabelClick = (id: NodeId, e: ReactMouseEvent<HTMLDivElement>): void => {\n e.stopPropagation();\n selectLabel(id, e.metaKey || e.shiftKey);\n };\n\n // a cluster label resolves to its MEMBER node ids through the\n // core mutator — clusters never enter the group selection namespace.\n const onClusterLabelClick = (key: string, e: ReactMouseEvent<HTMLDivElement>): void => {\n e.stopPropagation();\n instance.selectCluster(key, { additive: e.metaKey || e.shiftKey });\n };\n\n const onLabelKeyDown = (\n p: LabelPlacement,\n e: ReactKeyboardEvent<HTMLDivElement>,\n ): void => {\n // Native button activation does not exist for a div with role=\"button\",\n // and keyboard-triggered `contextmenu` coordinates vary by browser. Give\n // node labels (including native controls supplied by a custom renderer)\n // an explicit ContextMenu / Shift+F10 path, anchored at the label's center\n // in the same container-relative coordinate system as a pointer-triggered\n // menu.\n if (\n p.kind !== 'cluster' &&\n (e.key === 'ContextMenu' || (e.key === 'F10' && e.shiftKey))\n ) {\n e.preventDefault();\n e.stopPropagation();\n const layerRect = layerRef.current?.getBoundingClientRect();\n if (layerRect === undefined) return;\n const labelRect = e.currentTarget.getBoundingClientRect();\n instance.requestNodeContextMenu(p.id, [\n labelRect.left + labelRect.width / 2 - layerRect.left,\n labelRect.top + labelRect.height / 2 - layerRect.top,\n ]);\n return;\n }\n // An escape-hatch renderer may supply its own focusable control. Its\n // Enter keydown can synthesize a click that already bubbles through the\n // label's click path, so handling the bubbled keydown here as well would\n // activate the label twice.\n if (e.target !== e.currentTarget) return;\n if (e.key !== 'Enter' && e.key !== ' ') return;\n e.preventDefault();\n e.stopPropagation();\n const additive = e.metaKey || e.shiftKey;\n if (p.kind === 'cluster') instance.selectCluster(p.id, { additive });\n else selectLabel(p.id, additive);\n };\n\n // Right-click routes into the SAME typed 'contextMenu' channel the canvas\n // gesture feeds. Label divs are pointerEvents:'auto' (click-to-focus), so\n // without this the gesture dies here and the browser's native menu opens\n // on exactly the nodes prominent enough to carry labels. Coordinates are\n // container-relative CSS px (the layer fills the container), matching the\n // payload contract the canvas path uses.\n const onLabelContextMenu = (id: NodeId, e: ReactMouseEvent<HTMLDivElement>): void => {\n e.preventDefault();\n e.stopPropagation();\n const rect = layerRef.current?.getBoundingClientRect();\n if (rect === undefined) return;\n instance.requestNodeContextMenu(id, [e.clientX - rect.left, e.clientY - rect.top]);\n };\n\n const clusterMembers = (key: string): readonly NodeId[] =>\n instance.getClusters().find((c) => c.key === key)?.memberIds ?? [];\n\n return (\n <div data-orbit-label-layer=\"\" ref={layerRef} style={LAYER_STYLE}>\n {candidates.map((p) => {\n const key = placementKey(p);\n const [x, y] = positionsRef.current.get(key) ?? [p.x, p.y];\n const isCluster = p.kind === 'cluster';\n const className = isCluster\n ? [props.labelClassName, props.clusterLabelClassName].filter(Boolean).join(' ') ||\n undefined\n : props.labelClassName;\n const hasCustomRenderer = isCluster\n ? props.renderClusterLabel !== undefined\n : props.renderNodeLabel !== undefined;\n return (\n <div\n key={key}\n {...(isCluster ? { 'data-orbit-cluster-label': p.id } : { 'data-orbit-label': p.id })}\n className={className}\n {...(!hasCustomRenderer\n ? {\n role: 'button',\n tabIndex: 0,\n 'aria-label': p.text,\n ...(!isCluster ? { 'aria-haspopup': 'menu' as const } : {}),\n }\n : {})}\n style={{ ...LABEL_BASE_STYLE, transform: transformOf(x, y) }}\n ref={(el) => {\n if (el === null) elementsRef.current.delete(key);\n else elementsRef.current.set(key, el);\n }}\n onClick={(e) => (isCluster ? onClusterLabelClick(p.id, e) : onLabelClick(p.id, e))}\n onKeyDown={(e) => onLabelKeyDown(p, e)}\n // Cluster labels keep the browser menu for now: their click\n // already selects members, and no cluster menu target exists.\n onContextMenu={isCluster ? undefined : (e) => onLabelContextMenu(p.id, e)}\n >\n {/* text-node-only rendering holds for both kinds: a hostile\n key or label appears literally, never as markup. */}\n {isCluster\n ? props.renderClusterLabel !== undefined\n ? props.renderClusterLabel({\n clusterKey: p.id,\n text: p.text,\n memberIds: clusterMembers(p.id),\n })\n : p.text\n : props.renderNodeLabel !== undefined\n ? props.renderNodeLabel({\n node: instance.getNode(p.id) ?? { id: p.id },\n text: p.text,\n })\n : p.text}\n </div>\n );\n })}\n </div>\n );\n}\n","/**\n * LiveRegion — screen-reader announcements.\n *\n * A visually-hidden `aria-live=\"polite\"` region adjacent to the canvas. It\n * subscribes to the STORE (never the frame clock, so simulation frames can\n * never announce) and speaks a coalesced summary — node/edge counts,\n * selection count, status — at most once every 800ms and only when the\n * summary STRING changes. Trailing-edge coalescing: a burst of store changes\n * lands as ONE announcement carrying the freshest state.\n *\n * Gated off entirely when `accessibility.announcements === false`.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { ReactElement } from 'react';\nimport type { GraphStoreState } from '@modernrelay/orbit-core';\nimport { useAmbientGraphInstance } from './GraphProvider';\nimport { visuallyHiddenStyle } from './components/shared';\n\nexport const ANNOUNCE_INTERVAL_MS = 800;\n\nexport interface LiveRegionProps {\n /** `accessibility.announcements`; false gates all announcements. Default true. */\n announcements?: boolean | undefined;\n}\n\nfunction summarize(s: GraphStoreState): string {\n const selected = s.selection.nodeIds.length + s.selection.edgeIds.length;\n return `Graph ${s.status}. ${s.nodeCount} nodes, ${s.edgeCount} edges. ${selected} selected.`;\n}\n\n/** Internal to <Graph>; reads the ambient instance so hosts composing\n * GraphProvider directly can reuse it. */\nexport function LiveRegion(props: LiveRegionProps): ReactElement {\n const instance = useAmbientGraphInstance('LiveRegion');\n const enabled = props.announcements !== false;\n const [message, setMessage] = useState('');\n /** Last ANNOUNCED summary; seeded at subscribe time so the initial state\n * (already conveyed by the container's aria-label) is never announced. */\n const lastAnnouncedRef = useRef<string | null>(null);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!enabled) return undefined;\n const store = instance.store;\n lastAnnouncedRef.current = summarize(store.getState());\n\n const fire = (): void => {\n timerRef.current = null;\n const next = summarize(store.getState());\n if (next === lastAnnouncedRef.current) return;\n lastAnnouncedRef.current = next;\n setMessage(next);\n };\n\n const unsubscribe = store.subscribe(() => {\n if (timerRef.current !== null) return; // window open — coalesce\n if (summarize(store.getState()) === lastAnnouncedRef.current) return;\n timerRef.current = setTimeout(fire, ANNOUNCE_INTERVAL_MS);\n });\n\n return () => {\n unsubscribe();\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n }, [instance, enabled]);\n\n return (\n <div\n data-orbit-live-region=\"\"\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style={visuallyHiddenStyle}\n >\n {message}\n </div>\n );\n}\n","/**\n * <Graph> — the declarative React binding over a headless GraphInstance.\n *\n * Binding parity: one committed render that changes multiple declarative\n * props issues AT MOST ONE applyHostUpdate carrying exactly the changed keys,\n * so a multi-prop commit produces exactly one store revision and at most one\n * engine commit.\n */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { CSSProperties, ForwardedRef, ReactElement, ReactNode, RefAttributes } from 'react';\nimport {\n canonicalJson,\n canonicalScaleKey,\n createGraphInstance,\n sameGroupSpecArrays,\n} from '@modernrelay/orbit-core';\nimport type {\n Accessor,\n AcceptedEdge,\n AccessibilityConfig,\n BeginIngestOptions,\n ClusterSpec,\n CreateGraphInstanceOptions,\n CrossfilterSession,\n DimensionSpec,\n ExpandNodeResult,\n FilterExpr,\n FilterSpec,\n GraphDiagnostic,\n GraphHostUpdate,\n GraphInstance,\n GraphNode,\n GraphSnapshotInput,\n GraphTheme,\n GraphViewState,\n GroupBySpec,\n GroupSpec,\n IngestSession,\n JsonValue,\n LabelConfig,\n LayoutKind,\n MetaEdge,\n MetricColumn,\n PathOptions,\n PathResult,\n MetricName,\n NodeId,\n ResolvedCluster,\n ResolvedGroup,\n Revisions,\n Scale,\n ScaleChannelInfo,\n SearchResult,\n SearchUnavailableReason,\n SelectionState,\n ScaleLimits,\n WorkerFactoryOption,\n DegradeEvent,\n GraphPerfSnapshot,\n SetViewStateResult,\n SimulationInput,\n SubgraphSpec,\n ThemeInput,\n TimelinePlayback,\n ViewportState,\n} from '@modernrelay/orbit-core';\nimport type { EngineFactory, FitViewOptions } from '@modernrelay/orbit-core/engine';\nimport { GraphProvider } from './GraphProvider';\nimport { setSearchResultUnavailableCallback, useScaleInfoSubscription } from './hooks';\nimport { Lasso } from './Lasso';\nimport { LabelLayer } from './LabelLayer';\nimport { LiveRegion } from './LiveRegion';\nimport { overlaySurface, visuallyHiddenStyle } from './components/shared';\n\n/** Snapshot handed to `renderLegend`: the active scale info per styling\n * channel (null when the channel is not scale-valued) plus the resolved\n * theme tokens. Recomputed on model/scope/render/theme store changes. */\nexport interface GraphLegendRenderInfo<N = Record<string, unknown>> {\n nodeColor: ScaleChannelInfo<N> | null;\n nodeSize: ScaleChannelInfo<N> | null;\n theme: GraphTheme;\n}\n\nexport interface GraphProps<N = Record<string, unknown>, E = Record<string, unknown>> {\n /** Engine factory; captured at first render — one factory per instance. */\n engine: EngineFactory;\n data?: GraphSnapshotInput<N, E>;\n /** Constant, accessor, or Scale descriptor. Scale-valued props compare\n * by canonical structural value — equal inline literals never reproject. */\n nodeColor?: Accessor<GraphNode<N>, string> | Scale<string, N>;\n nodeSize?: Accessor<GraphNode<N>, number> | Scale<number, N>;\n linkColor?: Accessor<AcceptedEdge<E>, string>;\n linkWidth?: Accessor<AcceptedEdge<E>, number>;\n layout?: LayoutKind;\n /** Full config or a named preset ('calm' | 'spread' | 'tight' |\n * 'lively'). Omitted = the 'calm' preset — the measured-good default. */\n simulation?: SimulationInput;\n /** theme tokens: full GraphTheme, Partial over a named base, or the\n * v0.1 `{background}` shorthand. Diffed structurally (JSON). */\n theme?: ThemeInput;\n /** async metric columns, joined once with revision-gated admission.\n * Diffed by array reference. */\n metrics?: readonly MetricColumn[];\n /** image sprites: synchronous string-ref accessor (URL/blob ref/cache\n * key — opaque to orbit). Diffed by reference. */\n nodeImage?: (node: GraphNode<N>) => string | null;\n /** instanced arrowheads (capability-gated; inert when unsupported). */\n edgeArrows?: boolean;\n /** runtime link-render toggle — a config-only commit. */\n showLinks?: boolean;\n /** emphasis-ring toggle (default true). False clears the ring once and\n * suppresses every driver (hover, focusNode, emphasizeNode). */\n emphasisRing?: boolean;\n /** legend escape hatch: rendered inside the provider in a positioned\n * wrapper (bottom-left) whenever provided; re-invoked when scale info or\n * theme changes. Return custom JSX, or compose <GraphLegend> from\n * '@modernrelay/orbit-react/components/Legend' for the built-in rendering. */\n renderLegend?: (info: GraphLegendRenderInfo<N>) => ReactNode;\n /** DOM label lane; forwarded through applyHostUpdate. `enabled: false`\n * also unmounts the <LabelLayer> overlay entirely. */\n labels?: LabelConfig<N>;\n /** accessibility runtime options; forwarded through applyHostUpdate\n * and mirrored onto the container ARIA surface / live region. */\n accessibility?: AccessibilityConfig<N>;\n /** Class hook applied to every DOM label div. */\n labelClassName?: string;\n /** Escape hatch: custom label content rendered INSIDE the positioned label\n * div, replacing the default text node. */\n renderNodeLabel?: (ctx: { node: GraphNode<N>; text: string }) => ReactNode;\n /** Class hook applied to cluster label divs, in addition to\n * `labelClassName`. */\n clusterLabelClassName?: string;\n /** Escape hatch: custom cluster-label content (replaces the default text\n * node; text-node-only rendering otherwise). `memberIds` are the ids a\n * click selects. */\n renderClusterLabel?: (ctx: {\n clusterKey: string;\n text: string;\n memberIds: readonly NodeId[];\n }) => ReactNode;\n /** Controlled selection of the NODE namespace; providing it once flips\n * ownership permanently. Edge/group namespaces stay instance-owned. */\n selection?: readonly NodeId[];\n /** hard scope: feed ONLY the resolved subset through the reconciler;\n * `null` restores the full accepted model. Diffed STRUCTURALLY (specs are\n * small), so a new-but-equal object is a no-op. UNCONTROLLED-ONLY in v0.5:\n * this prop and isolateSelection/resetIsolation write the same\n * instance-owned state — last writer wins, and omitting the prop leaves\n * the last written scope in place. */\n subgraph?: SubgraphSpec | null;\n /** soft filter: mask (hide/dim) with ZERO relayout; `null` clears.\n * Diffed by canonical structural compare — serializable exprs by JSON,\n * function predicates by reference — so a new-but-equal spec never\n * re-publishes (and the core no-ops canonical-equal specs regardless). */\n filter?: FilterSpec<N, E> | null;\n /** crossfilter dimensions (declarative; brushes live on the session\n * — reach it via useGraphCrossfilter or handle.getCrossfilterSession).\n * Forwarded on array-reference change; the core no-ops when every\n * DimensionSpec element is reference-equal. */\n crossfilter?: readonly DimensionSpec<N>[];\n /** manual groups; `null` clears. Diffed STRUCTURALLY (equal inline\n * literals never re-forward). Providing it once flips the groups slice to\n * CONTROLLED: handle ops then fire onGroupsChange with the next\n * array instead of writing — reflect it back here. Config error together\n * with `groupBy`. */\n groups?: readonly GroupSpec[] | null;\n /** derived grouping; `null` clears. Reference-diffed (the spec\n * carries a function accessor); the core additionally no-ops structurally\n * equal respecs. Membership under groupBy is derived and READ-ONLY\n * groupNodes/ungroup become config errors; setGroupCollapsed toggles the\n * instance-owned per-key collapsed residue. */\n groupBy?: GroupBySpec<N> | null;\n /** stage-4 non-collapsing clusters; `null` clears (D2).\n * Reference-diffed (the spec carries a function accessor). Clusters PRESERVE\n * every node and edge — they never collapse anything — so they coexist with\n * `groups`/`groupBy`. Their labels ride the overlay lane under\n * `labels.maxZoom` and select their member nodes on click. */\n clusters?: ClusterSpec<N> | null;\n /** PERSISTENT pins — independent of transient drag\n * pinning: the engine receives the UNION, so releasing a drag on a\n * persistently-pinned node leaves it pinned. Providing it once latches the\n * slice controlled: handle ops then fire onPinnedChange with the\n * next array instead of writing. `null` clears (D2). */\n pinnedNodeIds?: readonly NodeId[] | null;\n /** node attr fields the DEFAULT search service indexes (ids always).\n * Absent = id-only search — the service never guesses attr names.\n * CONSTRUCTION-ONLY (D7, spec host construction options): read once at\n * mount; changing it requires a keyed remount (a changed prop warns once\n * and is ignored). */\n searchIndex?: readonly string[];\n /** Degradation-ladder thresholds. CONSTRUCTION-ONLY: read\n * once at mount; a runtime change warns once and is ignored. */\n limits?: Partial<ScaleLimits>;\n /** Execution mode. CONSTRUCTION-ONLY: read once\n * at mount; a runtime change warns once and is ignored. Current worker\n * cargo: columnar acceptance off-thread. */\n execution?: 'auto' | 'main' | 'worker';\n /** Worker construction tri-option. CONSTRUCTION-ONLY. */\n workerFactory?: WorkerFactoryOption;\n /** result contract: the instance-wide DEFAULT for an activated\n * search result that cannot be focused ('not-loaded' | 'out-of-scope' |\n * 'filtered'). `<GraphSearch onResultUnavailable>` overrides it locally;\n * the host reacts explicitly (fetch/publish an overlay, reset isolation,\n * alter filters) — search never mutates scope/filters itself. */\n onSearchResultUnavailable?: (result: SearchResult, reason: SearchUnavailableReason) => void;\n /** Captured at first render (instance construction option). Default true. */\n fitViewOnFirstData?: boolean;\n /**\n * Camera behavior while the FIRST force-layout settle runs (construction-\n * only). 'follow' (default): the camera keeps the contracting graph framed\n * with periodic animated refits and a final fit at quiescence; any user\n * camera input cancels it. 'once': single fit at first quiescence.\n * false: fit at first data only.\n */\n fitViewOnSettle?: 'follow' | 'once' | false;\n /**\n * Upper bound on the zoom any internally issued fit lands at (construction-\n * only). Small graphs otherwise fit until nodes balloon. Default 1.5;\n * null disables the clamp.\n */\n fitViewMaxZoom?: number | null;\n /** service seam (instance construction option, D7): custom\n * revision-aware services — most usefully an async `expansion` service\n * backed by the host's own data source, so `expandNode`/the context menu's\n * Expand run against the network instead of the built-in local-adjacency\n * walk. CONSTRUCTION-ONLY: read once at mount; changing it requires a keyed\n * remount. */\n services?: CreateGraphInstanceOptions<N, E>['services'];\n /** Shift+drag freeform lasso selection overlay. Default true. */\n enableLasso?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Rendered inside the provider, above (after) the canvas container. */\n children?: ReactNode;\n onNodeClick?: (payload: { node: GraphNode<N>; metaKey?: boolean }) => void;\n onBackgroundClick?: () => void;\n onNodeHover?: (payload: { node: GraphNode<N> | null }) => void;\n onEdgeClick?: (payload: { edge: AcceptedEdge<E> }) => void;\n onEdgeHover?: (payload: { edge: AcceptedEdge<E> | null }) => void;\n onNodeDragStart?: (payload: { node: GraphNode<N> }) => void;\n onNodeDragEnd?: (payload: { node: GraphNode<N>; x: number; y: number }) => void;\n /** Fires with the full namespaced SelectionState. */\n onSelectionChange?: (payload: SelectionState) => void;\n /** ladder step engagement/disengagement (notification pattern). */\n onDegrade?: (event: DegradeEvent) => void;\n /** throttled telemetry sample — never per frame. */\n onPerfSample?: (snapshot: GraphPerfSnapshot) => void;\n /** Fires on a super-node hit with the resolved group payload, never a GraphNode. */\n onGroupClick?: (payload: { group: ResolvedGroup; metaKey?: boolean }) => void;\n /** Fires on a meta-edge hit with the MetaEdge record used by the count badge. */\n onMetaEdgeClick?: (payload: { metaEdge: MetaEdge }) => void;\n /** groups slice change callback: op results (uncontrolled), op\n * INTENTS (controlled — reflect the array back into `groups`), and groupBy\n * re-derivations (notification). Receives the resolved array. */\n onGroupsChange?: (groups: readonly ResolvedGroup[]) => void;\n /** durable source coordinate — forwarded verbatim; serialized into\n * view states and canonically compared on restore. Diffed by canonical\n * JSON, so a new-but-equal object never re-forwards. */\n dataRef?: JsonValue;\n /** aggregate restore intent (fires once per restore/history\n * transaction touching a controlled slice or serialized styling): reflect\n * every participating prop in ONE commit; matching values acknowledge. */\n onViewStateRestore?: (intent: {\n transactionId: string;\n source: 'setViewState' | 'undo' | 'redo';\n next: unknown;\n }) => void;\n /** fired INSTEAD of applying a state whose dataRef mismatches. */\n onViewStateMismatch?: (stored: JsonValue | undefined, current: JsonValue | undefined) => void;\n /** persistent-pin slice change: the applied set when\n * uncontrolled, the INTENT when controlled. */\n onPinnedChange?: (pinnedNodeIds: readonly NodeId[]) => void;\n onViewportChange?: (v: ViewportState) => void;\n onReady?: () => void;\n onError?: (payload: { error: Error }) => void;\n}\n\nexport interface GraphHandle<N = Record<string, unknown>, E = Record<string, unknown>> {\n /** `opts` is accepted for forward compatibility; core v0.1 ignores it. */\n fitView(opts?: FitViewOptions): void;\n zoomIn(): void;\n zoomOut(): void;\n /** `opts` is accepted for forward compatibility; core v0.1 ignores it. */\n setViewport(v: Partial<ViewportState>, opts?: { durationMs?: number }): void;\n focusNode(id: NodeId): void;\n /** ring-only emphasis, no camera move (null clears; unknown ids\n * no-op). The keyboard-navigation analog of hover. */\n emphasizeNode(id: NodeId | null): void;\n /** telemetry snapshot (never raw attrs or ids). */\n getPerfSnapshot(): GraphPerfSnapshot;\n /** Open the typed context menu for a node from host chrome (a list row, a\n * custom label) — the same 'contextMenu' event the canvas gesture emits.\n * `screen` is container-relative CSS px. */\n requestNodeContextMenu(id: NodeId, screen: readonly [number, number]): void;\n /** serialize the exploration state (see core docs). */\n getViewState(opts?: { includePositions?: false }): GraphViewState;\n /** atomic restore; typed results, never partial. */\n setViewState(\n raw: unknown,\n opts?: { ignoreMismatch?: boolean },\n ): Promise<SetViewStateResult>;\n /** picture export: 'png' via the engine screenshot; 'svg' via the\n * engine-free exporter (typed export-too-large past the bound;\n * raster-hybrid fallback available). */\n exportImage(format: 'png'): Promise<Blob>;\n exportImage(\n format: 'svg',\n opts?: { maxSvgElements?: number; fallback?: 'raster-hybrid' },\n ): Promise<string>;\n /** bounded object export; typed rejection past the limit. */\n exportData(\n scope?: 'visible' | 'accepted',\n opts?: { limit?: number },\n ): Promise<{ nodes: readonly GraphNode<N>[]; edges: readonly AcceptedEdge<E>[] }>;\n /** memory-bounded JSONL stream over one pinned revision. */\n exportDataStream(scope?: 'visible' | 'accepted'): AsyncGenerator<string, void, undefined>;\n /** bounded id → [x, y] map (one position readback). */\n exportLayout(opts?: { limit?: number }): Promise<ReadonlyMap<NodeId, readonly [number, number]>>;\n /** layout JSONL stream over one pinned readback. */\n exportLayoutStream(): AsyncGenerator<string, void, undefined>;\n setSelection(ids: readonly NodeId[]): void;\n clearSelection(): void;\n // --- persistent pins ---\n /** Hold nodes at their CURRENT position (independent of drag pinning). */\n pinNodes(ids: readonly NodeId[]): void;\n unpinNodes(ids: readonly NodeId[]): void;\n // --- paths ---\n /** Resolve + atomically emphasize a path; null = unreachable (a result).\n * Emphasis is session-local — released by clearPath, any selection\n * mutation, undo/redo, or a scene rebuild; never in history/view state. */\n findPath(sourceId: NodeId, targetId: NodeId, options?: PathOptions): Promise<PathResult | null>;\n clearPath(): void;\n // --- selection algebra ---\n /** Expand to the 1-hop neighborhood of `id` (or of the current selection). */\n selectNeighbors(id?: NodeId): void;\n selectAll(): void;\n invertSelection(): void;\n /** Resolve a SCREEN-coordinate polygon to node ids and replace (default) or\n * union (`additive`) the node selection; returns the resolved ids. */\n selectWithinPolygon(\n polygon: readonly [number, number][],\n opts?: { additive?: boolean },\n ): readonly NodeId[];\n // --- pin / hide slices ---\n /** Pin at `xy` (space coords) or at the node's current position. */\n pinNode(id: NodeId, xy?: readonly [number, number]): void;\n unpinNode(id: NodeId): void;\n clearPins(): void;\n hideNodes(ids: readonly NodeId[]): void;\n showAll(): void;\n // --- hard scope + expansion ---\n /** Hard-scope to the current node selection; no-op when empty. */\n isolateSelection(): void;\n /** Clear the hard scope — the full accepted model returns. */\n resetIsolation(): void;\n /** Ego-expand `id` through the configured ExpansionService. */\n expandNode(id: NodeId, opts?: { hops?: number }): Promise<ExpandNodeResult>;\n /** Abort `id`'s pending expansion and remove its committed expansion\n * overlays. */\n retractExpansion(id: NodeId): void;\n // --- group operations ---\n /** Add one group (same acyclic/singly-parented validation as the `groups` prop).\n * Controlled mode fires onGroupsChange with the next array instead. */\n groupNodes(spec: GroupSpec): void;\n /** Remove one group definition; its id prunes from selection.groupIds. */\n ungroup(groupId: string): void;\n /** Collapse/expand one group as a structural diff — the ONE op allowed on\n * groupBy-derived groups (toggles the per-key collapsed residue). */\n setGroupCollapsed(groupId: string, collapsed: boolean): void;\n // --- node folds: an EXISTING node stands for its own neighbourhood.\n // Distinct from `expandNode`/`retractExpansion`, which navigate the data\n // source; a fold is pure containment over what is already loaded. ---\n /** Hide `id`'s neighbourhood behind `id`, rerouting the members' outside\n * edges onto it. Members default to unclaimed neighbours (first fold wins). */\n foldNode(id: NodeId, opts?: { memberIds?: readonly NodeId[] }): void;\n /** Return `id`'s folded members to the scene. No-op when not folded. */\n unfoldNode(id: NodeId): void;\n /** The members `id` stands for, or null when it is not folded. */\n getFold(id: NodeId): { memberIds: readonly NodeId[] } | null;\n // --- stage-4 clusters ---\n /** Current clusters over the physical scene (keys, members, force center,\n * settled centroid). Empty when no `clusters` prop is active. */\n getClusters(): readonly ResolvedCluster[];\n /** Select a cluster's MEMBER node ids; `additive` unions. */\n selectCluster(key: string, opts?: { additive?: boolean }): void;\n // --- revisioned ingestion ---\n /** Begin a bounded, cancellable ingest session. */\n beginIngest(opts: BeginIngestOptions): IngestSession<N, E>;\n /** Atomically remove exactly one committed overlay; unknown ids are an\n * idempotent `{ removed: false }`. */\n removeOverlay(overlayId: string): { removed: boolean };\n // --- history ---\n /** Undo the most recent uncontrolled mutation entry (selection / hidden /\n * pins / scope / brushes). Returns false when there is nothing to undo. */\n undo(): boolean;\n /** Re-apply the most recently undone entry. False when nothing to redo. */\n redo(): boolean;\n // --- timeline playback ---\n /** Play a brush window across a numeric/temporal dimension's domain\n * (crossfilter mask fast path; one playing dimension at a time). */\n playTimeline(key: string, playback?: Partial<TimelinePlayback>): void;\n pauseTimeline(): void;\n // --- crossfilter ---\n /** The crossfilter session facade, or null until the `crossfilter` prop\n * has configured dimensions over an accepted base. */\n getCrossfilterSession(): CrossfilterSession | null;\n // --- styling reads ---\n /** legend surface: the active Scale on a styling channel plus its\n * resolved domain or categorical rows; null when not scale-valued. */\n getScaleInfo(channel: 'nodeColor' | 'nodeSize'): ScaleChannelInfo<N> | null;\n /** metric read for one node id (built-in degree family + admitted\n * columns); null for unknown ids or metrics and for null/non-finite values. */\n getMetricValue(metric: MetricName, id: NodeId): number | null;\n getRevisions(): Revisions;\n getDiagnostics(): readonly GraphDiagnostic[];\n instance: GraphInstance<N, E>;\n}\n\n/** Last-committed declarative props. Fields are `| undefined` (not optional)\n * so the diff record is assignable under exactOptionalPropertyTypes. */\ninterface CommittedProps<N, E> {\n data: GraphSnapshotInput<N, E> | undefined;\n nodeColor: Accessor<GraphNode<N>, string> | Scale<string, N> | undefined;\n /** Canonical structural key when the committed nodeColor is a Scale;\n * undefined for accessor/constant forms (those diff by reference). */\n nodeColorKey: string | undefined;\n nodeSize: Accessor<GraphNode<N>, number> | Scale<number, N> | undefined;\n nodeSizeKey: string | undefined;\n linkColor: Accessor<AcceptedEdge<E>, string> | undefined;\n linkWidth: Accessor<AcceptedEdge<E>, number> | undefined;\n layout: LayoutKind | undefined;\n simulation: SimulationInput | undefined;\n /** JSON form of the last committed `theme` prop (small token set). */\n themeJson: string | undefined;\n metrics: readonly MetricColumn[] | undefined;\n nodeImage: ((node: GraphNode<N>) => string | null) | undefined;\n edgeArrows: boolean | undefined;\n showLinks: boolean | undefined;\n emphasisRing: boolean | undefined;\n selection: readonly NodeId[] | undefined;\n labels: LabelConfig<N> | undefined;\n accessibility: AccessibilityConfig<N> | undefined;\n /** JSON form of the last committed `subgraph` prop — specs are small, so\n * the diff is a structural string compare ('null' when scope cleared). */\n subgraphJson: string | undefined;\n /** Last committed `filter` prop + its canonical key: exprs compare\n * by JSON, function predicates by reference. */\n filter: FilterSpec<N, E> | null | undefined;\n filterKey: string | undefined;\n /** Last committed `crossfilter` prop, compared by array reference. */\n crossfilter: readonly DimensionSpec<N>[] | undefined;\n /** Last committed `groups` prop (structural diff via sameGroupSpecArrays;\n * — equal inline literals never re-forward). */\n groups: readonly GroupSpec[] | null | undefined;\n dataRef: JsonValue | undefined;\n /** Last committed `groupBy` prop (reference diff — function-bearing). */\n groupBy: GroupBySpec<N> | null | undefined;\n /** Last committed `clusters` prop (reference diff — function-bearing). */\n clusters: ClusterSpec<N> | null | undefined;\n /** Last committed `pinnedNodeIds` prop, compared by shallow element diff. */\n pinnedNodeIds: readonly NodeId[] | null | undefined;\n /** Last committed `searchIndex` prop (shallow element diff). */\n searchIndex: readonly string[] | undefined;\n}\n\n/**\n * Canonical key of a scale-valued styling channel: `canonicalScaleKey`\n * when the value is a Scale descriptor, undefined for constant/accessor forms\n * (which diff by reference). Equal inline scale literals therefore never\n * re-forward; a function `by` keys by reference identity inside the core.\n */\nfunction scaleKeyOf(value: unknown): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const kind = (value as { kind?: unknown }).kind;\n if (kind !== 'sequential' && kind !== 'categorical' && kind !== 'diverging') return undefined;\n return canonicalScaleKey(value as Scale<unknown>);\n}\n\n/** Diff one nodeColor/nodeSize channel: scale forms compare by canonical key,\n * everything else by reference (a scale↔accessor flip always differs). */\nfunction styleChannelChanged(\n prevValue: unknown,\n prevKey: string | undefined,\n nextValue: unknown,\n nextKey: string | undefined,\n): boolean {\n if (nextKey !== undefined || prevKey !== undefined) return nextKey !== prevKey;\n return prevValue !== nextValue;\n}\n\n/** Canonical key of one filter side: 'u' absent, 'fn' a function predicate\n * (paired with a reference compare), else the expr JSON. */\nfunction filterSideKey(side: FilterExpr | ((item: never) => boolean) | undefined): string {\n if (side === undefined) return 'u';\n if (typeof side === 'function') return 'fn';\n return JSON.stringify(side);\n}\n\nfunction filterKeyOf<N, E>(spec: FilterSpec<N, E> | null): string {\n if (spec === null) return 'null';\n return `${spec.mode ?? 'hide'}|${filterSideKey(spec.nodes)}|${filterSideKey(spec.edges)}`;\n}\n\n/** Canonical-equal check: keys match AND any function sides are the SAME\n * references (a changed predicate function must re-evaluate). */\nfunction sameFilterSpec<N, E>(\n prev: FilterSpec<N, E> | null | undefined,\n prevKey: string | undefined,\n next: FilterSpec<N, E> | null,\n nextKey: string,\n): boolean {\n if (prevKey === undefined || prevKey !== nextKey) return false;\n if (next === null) return prev === null;\n if (prev === null || prev === undefined) return false;\n if (typeof next.nodes === 'function' && next.nodes !== prev.nodes) return false;\n if (typeof next.edges === 'function' && next.edges !== prev.edges) return false;\n return true;\n}\n\ninterface CallbackHolder<N, E> {\n onNodeClick: ((payload: { node: GraphNode<N>; metaKey?: boolean }) => void) | undefined;\n onBackgroundClick: (() => void) | undefined;\n onNodeHover: ((payload: { node: GraphNode<N> | null }) => void) | undefined;\n onEdgeClick: ((payload: { edge: AcceptedEdge<E> }) => void) | undefined;\n onEdgeHover: ((payload: { edge: AcceptedEdge<E> | null }) => void) | undefined;\n onNodeDragStart: ((payload: { node: GraphNode<N> }) => void) | undefined;\n onNodeDragEnd: ((payload: { node: GraphNode<N>; x: number; y: number }) => void) | undefined;\n onSelectionChange: ((payload: SelectionState) => void) | undefined;\n onDegrade: ((event: DegradeEvent) => void) | undefined;\n onPerfSample: ((snapshot: GraphPerfSnapshot) => void) | undefined;\n onGroupClick: ((payload: { group: ResolvedGroup; metaKey?: boolean }) => void) | undefined;\n onMetaEdgeClick: ((payload: { metaEdge: MetaEdge }) => void) | undefined;\n onGroupsChange: ((groups: readonly ResolvedGroup[]) => void) | undefined;\n onViewStateRestore:\n | ((intent: {\n transactionId: string;\n source: 'setViewState' | 'undo' | 'redo';\n next: unknown;\n }) => void)\n | undefined;\n onViewStateMismatch:\n | ((stored: JsonValue | undefined, current: JsonValue | undefined) => void)\n | undefined;\n onPinnedChange: ((pinnedNodeIds: readonly NodeId[]) => void) | undefined;\n onViewportChange: ((v: ViewportState) => void) | undefined;\n onReady: (() => void) | undefined;\n onError: ((payload: { error: Error }) => void) | undefined;\n}\n\nfunction sameIdArrays(a: readonly NodeId[], b: readonly NodeId[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\n\nconst CONTAINER_BASE_STYLE: CSSProperties = {\n position: 'relative',\n width: '100%',\n height: '100%',\n};\n\n// The canvas layer fills the outer div; children render after it in DOM order\n// so they naturally stack above the canvas.\nconst CANVAS_STYLE: CSSProperties = { position: 'absolute', inset: 0 };\n\n/** Positioned wrapper for the `renderLegend` slot: bottom-left, above\n * the canvas, interactive (category rows are clickable). */\nconst LEGEND_SLOT_STYLE: CSSProperties = {\n position: 'absolute',\n left: 12,\n bottom: 12,\n};\n\n/** `renderLegend` slot host: re-reads getScaleInfo on every store publication\n * that can move scale info (model/scope/render revisions) or theme change,\n * and re-invokes the host's render function with the fresh snapshot. */\nfunction LegendSlot<N, E>(props: {\n instance: GraphInstance<N, E>;\n renderLegend: (info: GraphLegendRenderInfo<N>) => ReactNode;\n}): ReactElement {\n const { instance } = props;\n const { version, theme } = useScaleInfoSubscription(instance);\n const info = useMemo<GraphLegendRenderInfo<N>>(\n () => ({\n nodeColor: instance.getScaleInfo('nodeColor'),\n nodeSize: instance.getScaleInfo('nodeSize'),\n theme,\n }),\n // `version` is the invalidation token: a new store revision can change\n // what getScaleInfo returns without changing any other dependency.\n [instance, theme, version],\n );\n return (\n <div data-orbit-legend-slot=\"\" style={LEGEND_SLOT_STYLE}>\n {props.renderLegend(info)}\n </div>\n );\n}\n\nfunction GraphInner<N, E>(\n props: GraphProps<N, E>,\n ref: ForwardedRef<GraphHandle<N, E>>,\n): ReactElement {\n // Lazy, once per mounted component. `engine`/`fitViewOnFirstData`/\n // `searchIndex` are construction options (D7); later changes to them are\n // intentionally ignored (searchIndex additionally warns once below).\n const [instance] = useState<GraphInstance<N, E>>(() => {\n const options: CreateGraphInstanceOptions<N, E> = { engine: props.engine };\n if (props.fitViewOnFirstData !== undefined) {\n options.fitViewOnFirstData = props.fitViewOnFirstData;\n }\n if (props.fitViewOnSettle !== undefined) options.fitViewOnSettle = props.fitViewOnSettle;\n if (props.fitViewMaxZoom !== undefined) options.fitViewMaxZoom = props.fitViewMaxZoom;\n if (props.searchIndex !== undefined) options.searchIndex = props.searchIndex;\n if (props.limits !== undefined) options.limits = props.limits;\n if (props.execution !== undefined) options.execution = props.execution;\n if (props.workerFactory !== undefined) options.workerFactory = props.workerFactory;\n if (props.services !== undefined) options.services = props.services;\n return createGraphInstance<N, E>(options);\n });\n const searchIndexWarnedRef = useRef(false);\n const limitsWarnedRef = useRef(false);\n const initialLimitsRef = useRef(props.limits);\n if (props.limits !== initialLimitsRef.current && !limitsWarnedRef.current) {\n limitsWarnedRef.current = true;\n console.warn(\n 'orbit: `limits` is a construction-only prop — the runtime change is ignored; remount with a key to apply new thresholds.',\n );\n }\n const executionWarnedRef = useRef(false);\n const initialExecutionRef = useRef(props.execution);\n if (props.execution !== initialExecutionRef.current && !executionWarnedRef.current) {\n executionWarnedRef.current = true;\n console.warn(\n 'orbit: `execution` is a construction-only prop — the runtime change is ignored; remount with a key to switch lanes.',\n );\n }\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // --- latest-callback holder: event subscriptions read through this ref so\n // per-render callback identity churn never resubscribes ---\n const callbacksRef = useRef<CallbackHolder<N, E>>({\n onNodeClick: undefined,\n onBackgroundClick: undefined,\n onNodeHover: undefined,\n onEdgeClick: undefined,\n onEdgeHover: undefined,\n onNodeDragStart: undefined,\n onNodeDragEnd: undefined,\n onSelectionChange: undefined,\n onDegrade: undefined,\n onPerfSample: undefined,\n onGroupClick: undefined,\n onMetaEdgeClick: undefined,\n onGroupsChange: undefined,\n onViewStateRestore: undefined,\n onViewStateMismatch: undefined,\n onPinnedChange: undefined,\n onViewportChange: undefined,\n onReady: undefined,\n onError: undefined,\n });\n useLayoutEffect(() => {\n callbacksRef.current = {\n onNodeClick: props.onNodeClick,\n onBackgroundClick: props.onBackgroundClick,\n onNodeHover: props.onNodeHover,\n onEdgeClick: props.onEdgeClick,\n onEdgeHover: props.onEdgeHover,\n onNodeDragStart: props.onNodeDragStart,\n onNodeDragEnd: props.onNodeDragEnd,\n onSelectionChange: props.onSelectionChange,\n onDegrade: props.onDegrade,\n onPerfSample: props.onPerfSample,\n onGroupClick: props.onGroupClick,\n onMetaEdgeClick: props.onMetaEdgeClick,\n onGroupsChange: props.onGroupsChange,\n onViewStateRestore: props.onViewStateRestore,\n onViewStateMismatch: props.onViewStateMismatch,\n onPinnedChange: props.onPinnedChange,\n onViewportChange: props.onViewportChange,\n onReady: props.onReady,\n onError: props.onError,\n };\n });\n\n // --- event subscriptions: keyed on the instance only; identity churn of\n // the props is absorbed by callbacksRef. A LAYOUT effect so it commits\n // BEFORE the prop-diff layout effect of the NEXT render pass — and on the\n // first pass the subscriptions land in the same commit as the initial\n // host update's effects; events fired during that first applyHostUpdate\n // (e.g. a mount-time 'degrade' engagement) are re-emittable states\n // that the ladder re-evaluates, but ordering here still matters for any\n // strictly edge-triggered channel, so subscriptions must not lag a frame\n // behind the data. ---\n useLayoutEffect(() => {\n const offs = [\n instance.on('nodeClick', (p) => callbacksRef.current.onNodeClick?.(p)),\n instance.on('backgroundClick', () => callbacksRef.current.onBackgroundClick?.()),\n instance.on('nodeHover', (p) => callbacksRef.current.onNodeHover?.(p)),\n instance.on('edgeClick', (p) => callbacksRef.current.onEdgeClick?.(p)),\n instance.on('edgeHover', (p) => callbacksRef.current.onEdgeHover?.(p)),\n instance.on('nodeDragStart', (p) => callbacksRef.current.onNodeDragStart?.(p)),\n instance.on('nodeDragEnd', (p) => callbacksRef.current.onNodeDragEnd?.(p)),\n instance.on('selectionChange', (p) => callbacksRef.current.onSelectionChange?.(p)),\n instance.on('degrade', (p) => callbacksRef.current.onDegrade?.(p)),\n instance.on('perfSample', (p) => callbacksRef.current.onPerfSample?.(p)),\n instance.on('groupClick', (p) => callbacksRef.current.onGroupClick?.(p)),\n instance.on('metaEdgeClick', (p) => callbacksRef.current.onMetaEdgeClick?.(p)),\n instance.on('groupsChange', (p) => callbacksRef.current.onGroupsChange?.(p.groups)),\n instance.on('viewStateRestore', (p) => callbacksRef.current.onViewStateRestore?.(p)),\n instance.on('viewStateMismatch', (p) =>\n callbacksRef.current.onViewStateMismatch?.(p.stored, p.current),\n ),\n instance.on('pinnedChange', (p) => callbacksRef.current.onPinnedChange?.(p.pinnedNodeIds)),\n instance.on('viewportChange', (v) => callbacksRef.current.onViewportChange?.(v)),\n instance.on('ready', () => callbacksRef.current.onReady?.()),\n instance.on('error', (p) => callbacksRef.current.onError?.(p)),\n ];\n return () => {\n for (const off of offs) off();\n };\n }, [instance]);\n\n // --- prop → host update: diff against the previous committed render and\n // issue at most one applyHostUpdate with exactly the changed keys ---\n const prevRef = useRef<CommittedProps<N, E> | null>(null);\n useLayoutEffect(() => {\n const prev = prevRef.current;\n const update: GraphHostUpdate<N, E> = {};\n let dirty = false;\n\n if (props.data !== undefined && (prev === null || prev.data !== props.data)) {\n update.data = props.data;\n dirty = true;\n }\n // scale-aware channels: Scale descriptors diff by canonical\n // structural key (equal inline literals never re-forward); accessor and\n // constant forms keep the reference diff.\n const nodeColorKey = scaleKeyOf(props.nodeColor);\n if (\n props.nodeColor !== undefined &&\n (prev === null ||\n styleChannelChanged(prev.nodeColor, prev.nodeColorKey, props.nodeColor, nodeColorKey))\n ) {\n update.nodeColor = props.nodeColor;\n dirty = true;\n }\n const nodeSizeKey = scaleKeyOf(props.nodeSize);\n if (\n props.nodeSize !== undefined &&\n (prev === null ||\n styleChannelChanged(prev.nodeSize, prev.nodeSizeKey, props.nodeSize, nodeSizeKey))\n ) {\n update.nodeSize = props.nodeSize;\n dirty = true;\n }\n if (props.linkColor !== undefined && (prev === null || prev.linkColor !== props.linkColor)) {\n update.linkColor = props.linkColor;\n dirty = true;\n }\n if (props.linkWidth !== undefined && (prev === null || prev.linkWidth !== props.linkWidth)) {\n update.linkWidth = props.linkWidth;\n dirty = true;\n }\n if (props.layout !== undefined && (prev === null || prev.layout !== props.layout)) {\n update.layout = props.layout;\n dirty = true;\n }\n if (\n props.simulation !== undefined &&\n (prev === null || prev.simulation !== props.simulation)\n ) {\n update.simulation = props.simulation;\n dirty = true;\n }\n // theme: a small token set — diffed structurally (JSON), so a\n // new-but-equal inline object never re-publishes.\n let themeJson: string | undefined;\n if (props.theme !== undefined) {\n themeJson = JSON.stringify(props.theme);\n if (prev === null || prev.themeJson !== themeJson) {\n update.theme = props.theme;\n dirty = true;\n }\n }\n // metric columns: array-reference diff (columns are one-shot joins).\n if (props.metrics !== undefined && (prev === null || prev.metrics !== props.metrics)) {\n update.metrics = props.metrics;\n dirty = true;\n }\n // image refs: function-prop contract — reference diff.\n if (props.nodeImage !== undefined && (prev === null || prev.nodeImage !== props.nodeImage)) {\n update.nodeImage = props.nodeImage;\n dirty = true;\n } else if (props.nodeImage === undefined && prev !== null && prev.nodeImage !== undefined) {\n // Removing the prop forwards the explicit clear; the natural\n // React idiom must not silently freeze the last accessor's images.\n update.nodeImage = null;\n dirty = true;\n }\n // Display toggles use plain value diffing for config-only commits.\n if (props.edgeArrows !== undefined && (prev === null || prev.edgeArrows !== props.edgeArrows)) {\n update.edgeArrows = props.edgeArrows;\n dirty = true;\n }\n if (props.showLinks !== undefined && (prev === null || prev.showLinks !== props.showLinks)) {\n update.showLinks = props.showLinks;\n dirty = true;\n }\n if (\n props.emphasisRing !== undefined &&\n (prev === null || prev.emphasisRing !== props.emphasisRing)\n ) {\n update.emphasisRing = props.emphasisRing;\n dirty = true;\n } else if (\n props.emphasisRing === undefined &&\n prev !== null &&\n prev.emphasisRing !== undefined\n ) {\n // Removing the prop restores the documented default (true); the\n // natural React idiom must not leave the ring silently disabled.\n update.emphasisRing = true;\n dirty = true;\n }\n if (\n props.selection !== undefined &&\n (prev === null ||\n prev.selection === undefined ||\n !sameIdArrays(prev.selection, props.selection))\n ) {\n update.selection = props.selection;\n dirty = true;\n }\n if (props.labels !== undefined && (prev === null || prev.labels !== props.labels)) {\n update.labels = props.labels;\n dirty = true;\n }\n if (\n props.accessibility !== undefined &&\n (prev === null || prev.accessibility !== props.accessibility)\n ) {\n update.accessibility = props.accessibility;\n dirty = true;\n }\n // hard scope: structural (JSON) diff — a new-but-equal spec object\n // never re-publishes. An omitted prop is never forwarded (uncontrolled).\n let subgraphJson: string | undefined;\n if (props.subgraph !== undefined) {\n subgraphJson = JSON.stringify(props.subgraph);\n if (prev === null || prev.subgraphJson !== subgraphJson) {\n update.subgraph = props.subgraph;\n dirty = true;\n }\n }\n // soft filter: canonical structural diff (exprs by JSON, function\n // predicates by reference). An omitted prop is never forwarded.\n let filterKey: string | undefined;\n if (props.filter !== undefined) {\n filterKey = filterKeyOf(props.filter);\n if (\n prev === null ||\n !sameFilterSpec(prev.filter, prev.filterKey, props.filter, filterKey)\n ) {\n update.filter = props.filter;\n dirty = true;\n }\n }\n // crossfilter dimensions: forwarded on array-reference change; the\n // core no-ops when every DimensionSpec element is reference-equal.\n if (\n props.crossfilter !== undefined &&\n (prev === null || prev.crossfilter !== props.crossfilter)\n ) {\n update.crossfilter = props.crossfilter;\n dirty = true;\n }\n // groups: structural diff (equal inline literals never\n // re-forward). An omitted prop is never forwarded — but ONCE provided\n // the core latches the slice controlled.\n if (props.dataRef !== undefined) {\n const prevRef = prev === null ? undefined : prev.dataRef;\n if (prevRef === undefined || canonicalJson(props.dataRef) !== canonicalJson(prevRef)) {\n update.dataRef = props.dataRef;\n dirty = true;\n }\n }\n if (props.groups !== undefined) {\n const prevGroups = prev === null ? undefined : prev.groups;\n if (prevGroups === undefined || !sameGroupSpecArrays(prevGroups, props.groups)) {\n update.groups = props.groups;\n dirty = true;\n }\n }\n // groupBy: reference diff (the spec carries a function accessor);\n // the core additionally no-ops structurally equal respecs.\n if (props.groupBy !== undefined && (prev === null || prev.groupBy !== props.groupBy)) {\n update.groupBy = props.groupBy;\n dirty = true;\n }\n // clusters: reference diff (function-bearing spec); the core\n // re-derives membership only on a `by` identity change.\n if (props.clusters !== undefined && (prev === null || prev.clusters !== props.clusters)) {\n update.clusters = props.clusters;\n dirty = true;\n }\n // pinnedNodeIds: shallow element diff (a small id list); ONCE\n // provided the core latches the slice controlled.\n if (props.pinnedNodeIds !== undefined) {\n const prevPinned = prev === null ? undefined : prev.pinnedNodeIds;\n const changed =\n prevPinned === undefined ||\n prevPinned === null ||\n props.pinnedNodeIds === null ||\n !sameIdArrays(prevPinned, props.pinnedNodeIds);\n if (changed) {\n update.pinnedNodeIds = props.pinnedNodeIds;\n dirty = true;\n }\n }\n // searchIndex is construction-only and is read once above. A\n // changed prop cannot take effect without a keyed remount — warn once\n // (shallow element diff, so a new-but-equal inline literal is fine).\n if (\n prev !== null &&\n !sameIdArrays(prev.searchIndex ?? [], props.searchIndex ?? []) &&\n !searchIndexWarnedRef.current\n ) {\n searchIndexWarnedRef.current = true;\n console.warn(\n '[orbit] searchIndex is construction-only: the changed value was ignored — key-remount <Graph> to change it',\n );\n }\n\n prevRef.current = {\n data: props.data,\n nodeColor: props.nodeColor,\n nodeColorKey,\n nodeSize: props.nodeSize,\n nodeSizeKey,\n linkColor: props.linkColor,\n linkWidth: props.linkWidth,\n layout: props.layout,\n simulation: props.simulation,\n themeJson,\n metrics: props.metrics,\n nodeImage: props.nodeImage,\n edgeArrows: props.edgeArrows,\n showLinks: props.showLinks,\n emphasisRing: props.emphasisRing,\n selection: props.selection,\n labels: props.labels,\n accessibility: props.accessibility,\n subgraphJson,\n filter: props.filter,\n filterKey,\n crossfilter: props.crossfilter,\n groups: props.groups,\n dataRef: props.dataRef,\n groupBy: props.groupBy,\n clusters: props.clusters,\n pinnedNodeIds: props.pinnedNodeIds,\n searchIndex: props.searchIndex,\n };\n\n if (dirty) instance.applyHostUpdate(update);\n });\n\n // Register the instance-wide default unavailable-result\n // callback so <GraphSearch> (and bespoke activation UIs) resolve it without\n // <Graph> in their import graph. Identity churn is fine — registration is a\n // WeakMap write, never a re-render.\n useLayoutEffect(() => {\n setSearchResultUnavailableCallback(instance, props.onSearchResultUnavailable);\n });\n\n\n // --- attach/detach: StrictMode's simulated remount detaches (destroying\n // the first engine) and re-attaches (fresh engine + full state replay) ---\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return undefined;\n // Each StrictMode setup (and each real mount) owns exactly one attach\n // result. Its promise may settle after cleanup because engine mounting is\n // asynchronous; a discarded generation must never inspect the newer\n // instance state or call the latest component callbacks.\n let active = true;\n void instance.attach(container).catch((err: unknown) => {\n if (!active) return;\n // A fatal mount fault already reached onError via the 'error' event.\n if (instance.store.getState().status === 'error') return;\n const error = err instanceof Error ? err : new Error(String(err));\n callbacksRef.current.onError?.({ error });\n });\n return () => {\n active = false;\n instance.detach();\n };\n }, [instance]);\n\n // --- destroy on true unmount only. destroy is irreversible, so the\n // cleanup defers it one microtask; a StrictMode remount re-runs the setup\n // synchronously first and cancels it, leaving detach/attach replay to\n // restore the engine. A real unmount has no re-setup, so destroy fires. ---\n const destroyGateRef = useRef({ pendingDestroy: false });\n useEffect(() => {\n const gate = destroyGateRef.current;\n gate.pendingDestroy = false;\n return () => {\n gate.pendingDestroy = true;\n queueMicrotask(() => {\n if (gate.pendingDestroy) instance.destroy();\n });\n };\n }, [instance]);\n\n // --- reduced motion: the binding detects the media preference and\n // reports it via instance.setReducedMotion; accessibility.reducedMotion\n // overrides inside the core. Subscribed for live preference changes. ---\n useEffect(() => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return undefined;\n }\n const mq = window.matchMedia('(prefers-reduced-motion: reduce)');\n const surface = overlaySurface(instance);\n surface.setReducedMotion?.(mq.matches);\n const onChange = (e: MediaQueryListEvent): void => {\n surface.setReducedMotion?.(e.matches);\n };\n if (typeof mq.addEventListener === 'function') {\n mq.addEventListener('change', onChange);\n return () => {\n mq.removeEventListener('change', onChange);\n };\n }\n // Legacy MediaQueryList (Safari < 14).\n if (typeof mq.addListener === 'function') {\n mq.addListener(onChange);\n return () => {\n mq.removeListener(onChange);\n };\n }\n return undefined;\n }, [instance]);\n\n useImperativeHandle(\n ref,\n (): GraphHandle<N, E> => ({\n fitView: (_opts?: FitViewOptions) => {\n instance.fitView();\n },\n zoomIn: () => {\n instance.zoomIn();\n },\n zoomOut: () => {\n instance.zoomOut();\n },\n setViewport: (v: Partial<ViewportState>, _opts?: { durationMs?: number }) => {\n instance.setViewport(v);\n },\n requestNodeContextMenu: (id: NodeId, screen: readonly [number, number]) => {\n instance.requestNodeContextMenu(id, screen);\n },\n getViewState: (opts?: { includePositions?: false }): GraphViewState =>\n instance.getViewState(opts),\n setViewState: (\n raw: unknown,\n opts?: { ignoreMismatch?: boolean },\n ): Promise<SetViewStateResult> => instance.setViewState(raw, opts),\n exportImage: ((format: 'png' | 'svg', opts?: { maxSvgElements?: number; fallback?: 'raster-hybrid' }) =>\n format === 'png' ? instance.exportImage('png') : instance.exportImage('svg', opts)) as GraphHandle<N, E>['exportImage'],\n exportData: (scope?: 'visible' | 'accepted', opts?: { limit?: number }) =>\n instance.exportData(scope, opts),\n exportDataStream: (scope?: 'visible' | 'accepted') => instance.exportDataStream(scope),\n exportLayout: (opts?: { limit?: number }) => instance.exportLayout(opts),\n exportLayoutStream: () => instance.exportLayoutStream(),\n focusNode: (id: NodeId) => {\n instance.focusNode(id);\n },\n emphasizeNode: (id: NodeId | null) => {\n instance.emphasizeNode(id);\n },\n getPerfSnapshot: () => instance.getPerfSnapshot(),\n setSelection: (ids: readonly NodeId[]) => {\n instance.setSelection(ids);\n },\n findPath: (sourceId: NodeId, targetId: NodeId, options?: PathOptions) =>\n instance.findPath(sourceId, targetId, options),\n clearPath: () => {\n instance.clearPath();\n },\n clearSelection: () => {\n instance.clearSelection();\n },\n selectNeighbors: (id?: NodeId) => {\n instance.selectNeighbors(id);\n },\n selectAll: () => {\n instance.selectAll();\n },\n invertSelection: () => {\n instance.invertSelection();\n },\n selectWithinPolygon: (\n polygon: readonly [number, number][],\n opts?: { additive?: boolean },\n ): readonly NodeId[] => instance.selectWithinPolygon(polygon, opts),\n pinNode: (id: NodeId, xy?: readonly [number, number]) => {\n instance.pinNode(id, xy);\n },\n unpinNode: (id: NodeId) => {\n instance.unpinNode(id);\n },\n clearPins: () => {\n instance.clearPins();\n },\n hideNodes: (ids: readonly NodeId[]) => {\n instance.hideNodes(ids);\n },\n showAll: () => {\n instance.showAll();\n },\n isolateSelection: () => {\n instance.isolateSelection();\n },\n resetIsolation: () => {\n instance.resetIsolation();\n },\n expandNode: (id: NodeId, opts?: { hops?: number }): Promise<ExpandNodeResult> =>\n instance.expandNode(id, opts),\n retractExpansion: (id: NodeId) => {\n instance.retractExpansion(id);\n },\n pinNodes: (ids: readonly NodeId[]) => {\n instance.pinNodes(ids);\n },\n unpinNodes: (ids: readonly NodeId[]) => {\n instance.unpinNodes(ids);\n },\n groupNodes: (spec: GroupSpec) => {\n instance.groupNodes(spec);\n },\n ungroup: (groupId: string) => {\n instance.ungroup(groupId);\n },\n setGroupCollapsed: (groupId: string, collapsed: boolean) => {\n instance.setGroupCollapsed(groupId, collapsed);\n },\n foldNode: (id: NodeId, opts?: { memberIds?: readonly NodeId[] }) => {\n instance.foldNode(id, opts);\n },\n unfoldNode: (id: NodeId) => {\n instance.unfoldNode(id);\n },\n getFold: (id: NodeId): { memberIds: readonly NodeId[] } | null => instance.getFold(id),\n getClusters: (): readonly ResolvedCluster[] => instance.getClusters(),\n selectCluster: (key: string, opts?: { additive?: boolean }) => {\n instance.selectCluster(key, opts);\n },\n beginIngest: (opts: BeginIngestOptions): IngestSession<N, E> => instance.beginIngest(opts),\n removeOverlay: (overlayId: string): { removed: boolean } =>\n instance.removeOverlay(overlayId),\n undo: (): boolean => instance.undo(),\n redo: (): boolean => instance.redo(),\n playTimeline: (key: string, playback?: Partial<TimelinePlayback>) => {\n instance.playTimeline(key, playback);\n },\n pauseTimeline: () => {\n instance.pauseTimeline();\n },\n getCrossfilterSession: (): CrossfilterSession | null => instance.getCrossfilterSession(),\n getScaleInfo: (channel: 'nodeColor' | 'nodeSize'): ScaleChannelInfo<N> | null =>\n instance.getScaleInfo(channel),\n getMetricValue: (metric: MetricName, id: NodeId): number | null =>\n instance.getMetricValue(metric, id),\n getRevisions: () => instance.getRevisions(),\n getDiagnostics: () => instance.getDiagnostics(),\n instance,\n }),\n [instance],\n );\n\n // --- container ARIA surface ---\n const descriptionId = useId();\n const description = props.accessibility?.description;\n\n return (\n <div className={props.className} style={{ ...CONTAINER_BASE_STYLE, ...props.style }}>\n <GraphProvider instance={instance}>\n {/* Engine-owned canvas layer: must never contain React children. */}\n <div\n ref={containerRef}\n data-orbit-canvas=\"\"\n style={CANVAS_STYLE}\n role=\"application\"\n aria-label={props.accessibility?.label ?? 'Graph visualization'}\n aria-describedby={description !== undefined ? descriptionId : undefined}\n />\n {description !== undefined ? (\n <div id={descriptionId} style={visuallyHiddenStyle}>\n {description}\n </div>\n ) : null}\n {/* DOM label lane: candidates via React, positions imperative. */}\n {props.labels?.enabled !== false ? (\n <LabelLayer\n labelClassName={props.labelClassName}\n renderNodeLabel={props.renderNodeLabel}\n clusterLabelClassName={props.clusterLabelClassName}\n renderClusterLabel={props.renderClusterLabel}\n />\n ) : null}\n {/* Lasso overlay: above the canvas, pointer-inert unless Shift-drag. */}\n {props.enableLasso !== false ? <Lasso /> : null}\n {/* live region: store-driven, coalesced, visually hidden. */}\n <LiveRegion announcements={props.accessibility?.announcements} />\n {/* legend slot: positioned wrapper re-rendered on scale/theme\n changes; the host returns custom JSX (or composes <GraphLegend>). */}\n {props.renderLegend !== undefined ? (\n <LegendSlot instance={instance} renderLegend={props.renderLegend} />\n ) : null}\n {props.children}\n </GraphProvider>\n </div>\n );\n}\n\n/** forwardRef erases generics; restore them with a typed call signature. */\ntype GraphComponent = <N = Record<string, unknown>, E = Record<string, unknown>>(\n props: GraphProps<N, E> & RefAttributes<GraphHandle<N, E>>,\n) => ReactElement;\n\nexport const Graph = forwardRef(GraphInner) as GraphComponent;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modernrelay/orbit-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "React binding for Orbit: <Graph> plus tree-shakeable components (toolbar, search, minimap, tooltip, inspector, table, navigator, and more).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"access": "public"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@modernrelay/orbit-core": "0.
|
|
78
|
+
"@modernrelay/orbit-core": "0.17.0"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
81
|
"react": ">=18",
|