@modernrelay/orbit-react 0.13.6 → 0.14.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.
Files changed (56) hide show
  1. package/dist/{chunk-DGFLU2SN.js → chunk-DTXFQLNP.js} +2 -2
  2. package/dist/chunk-DTXFQLNP.js.map +1 -0
  3. package/dist/{chunk-7XB47YST.js → chunk-NPOV5GA3.js} +2 -2
  4. package/dist/chunk-NPOV5GA3.js.map +1 -0
  5. package/dist/{chunk-QJ7JXQVK.js → chunk-ODOPSUI7.js} +4 -4
  6. package/dist/chunk-ODOPSUI7.js.map +1 -0
  7. package/dist/{chunk-JN7QCMFW.js → chunk-S36LHSNX.js} +2 -2
  8. package/dist/chunk-S36LHSNX.js.map +1 -0
  9. package/dist/components/ContextMenu.d.ts +4 -4
  10. package/dist/components/ContextMenu.js +2 -2
  11. package/dist/components/ContextMenu.js.map +1 -1
  12. package/dist/components/Histogram.d.ts +1 -1
  13. package/dist/components/Histogram.js +3 -3
  14. package/dist/components/Histogram.js.map +1 -1
  15. package/dist/components/Inspector.d.ts +20 -20
  16. package/dist/components/Inspector.js +1 -1
  17. package/dist/components/Inspector.js.map +1 -1
  18. package/dist/components/Legend.d.ts +9 -10
  19. package/dist/components/Legend.js +3 -3
  20. package/dist/components/Legend.js.map +1 -1
  21. package/dist/components/Minimap.d.ts +29 -29
  22. package/dist/components/Minimap.js +1 -1
  23. package/dist/components/Minimap.js.map +1 -1
  24. package/dist/components/Navigator.d.ts +24 -24
  25. package/dist/components/Navigator.js +3 -3
  26. package/dist/components/Navigator.js.map +1 -1
  27. package/dist/components/Search.d.ts +28 -28
  28. package/dist/components/Search.js +3 -3
  29. package/dist/components/Search.js.map +1 -1
  30. package/dist/components/SelectionActions.d.ts +3 -3
  31. package/dist/components/SelectionActions.js +1 -1
  32. package/dist/components/SelectionActions.js.map +1 -1
  33. package/dist/components/SimControls.d.ts +15 -16
  34. package/dist/components/SimControls.js +2 -2
  35. package/dist/components/SimControls.js.map +1 -1
  36. package/dist/components/Table.d.ts +4 -4
  37. package/dist/components/Table.js +1 -1
  38. package/dist/components/Table.js.map +1 -1
  39. package/dist/components/Timeline.d.ts +2 -2
  40. package/dist/components/Timeline.js +3 -3
  41. package/dist/components/Timeline.js.map +1 -1
  42. package/dist/components/Toolbar.d.ts +2 -2
  43. package/dist/components/Toolbar.js +1 -1
  44. package/dist/components/Toolbar.js.map +1 -1
  45. package/dist/components/Tooltip.d.ts +16 -16
  46. package/dist/components/Tooltip.js +1 -1
  47. package/dist/components/Tooltip.js.map +1 -1
  48. package/dist/index.d.ts +105 -106
  49. package/dist/index.js +8 -8
  50. package/dist/index.js.map +1 -1
  51. package/dist/{shared-Bj3Gk219.d.ts → shared-n98tkXJe.d.ts} +3 -3
  52. package/package.json +2 -2
  53. package/dist/chunk-7XB47YST.js.map +0 -1
  54. package/dist/chunk-DGFLU2SN.js.map +0 -1
  55. package/dist/chunk-JN7QCMFW.js.map +0 -1
  56. package/dist/chunk-QJ7JXQVK.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/GraphProvider.tsx","../src/components/shared.ts"],"names":["useContext"],"mappings":";;;;AAgBO,IAAM,oBAAA,GAAuB,cAAuC,IAAI,CAAA;AAMxE,SAAS,wBAAwB,QAAA,EAAoC;AAC1E,EAAA,MAAM,QAAA,GAAW,WAAW,oBAAoB,CAAA;AAChD,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,QAAQ,CAAA,2DAAA;AAAA,KAC1B;AAAA,EACF;AACA,EAAA,OAAO,QAAA;AACT;AAOO,SAAS,cAAc,KAAA,EAAyC;AACrE,EAAA,uBACE,GAAA,CAAC,qBAAqB,QAAA,EAArB,EAA8B,OAAO,KAAA,CAAM,QAAA,EACzC,gBAAM,QAAA,EACT,CAAA;AAEJ;ACxBO,SAAS,mBAAA,CACd,QAAA,EACA,aAAA,GAAgB,gBAAA,EACE;AAClB,EAAA,MAAM,OAAA,GAAUA,WAAW,oBAAoB,CAAA;AAC/C,EAAA,MAAM,WAAW,QAAA,IAAY,OAAA;AAC7B,EAAA,IAAI,QAAA,KAAa,IAAA,IAAQ,QAAA,KAAa,MAAA,EAAW;AAC/C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,gBAAgB,aAAa,CAAA,8HAAA;AAAA,KAE/B;AAAA,EACF;AACA,EAAA,OAAO,QAAA;AACT;AAWO,IAAM,qBAAA,GAAwB;AAO9B,SAAS,WAAA,CACd,MAAA,EACA,MAAA,GAAiB,qBAAA,EACF;AACf,EAAA,MAAM,CAAC,QAAA,EAAU,UAAU,CAAA,GAAI,MAAA,CAAO,MAAM,GAAG,CAAA;AAC/C,EAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,CAAC,QAAQ,GAAG,MAAA,EAAQ,CAAC,UAAU,GAAG,MAAA,EAAO;AAC1E;AAEA,IAAM,cAAA,GAAiB;AAAA,EACrB,GAAA,EAAK,QAAA;AAAA,EACL,MAAA,EAAQ,KAAA;AAAA,EACR,IAAA,EAAM,OAAA;AAAA,EACN,KAAA,EAAO;AACT,CAAA;AAaO,SAAS,UAAA,CAAW,MAAqB,QAAA,EAAyC;AACvF,EAAA,IAAI,QAAA,KAAa,QAAW,OAAO,IAAA;AACnC,EAAA,MAAM,GAAA,GAAqB,EAAE,GAAG,IAAA,EAAK;AACrC,EAAA,KAAA,MAAW,SAAS,CAAC,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA,EAAY;AAC/D,IAAA,IAAI,QAAA,CAAS,KAAK,CAAA,KAAM,MAAA,SAAkB,GAAA,CAAI,cAAA,CAAe,KAAK,CAAC,CAAA;AAAA,EACrE;AACA,EAAA,OAAO,EAAE,GAAG,GAAA,EAAK,GAAG,QAAA,EAAS;AAC/B;AAgCO,SAAS,eAAe,QAAA,EAAiD;AAC9E,EAAA,OAAO,QAAA;AACT;AAOO,IAAM,mBAAA,GAAqC;AAAA,EAChD,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,CAAA;AAAA,EACR,OAAA,EAAS,CAAA;AAAA,EACT,MAAA,EAAQ,EAAA;AAAA,EACR,QAAA,EAAU,QAAA;AAAA,EACV,IAAA,EAAM,eAAA;AAAA,EACN,UAAA,EAAY,QAAA;AAAA,EACZ,MAAA,EAAQ;AACV;AAIO,IAAM,iBAAA,GAAmC;AAAA,EAC9C,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO,CAAA;AAAA,EACP,aAAA,EAAe;AACjB","file":"chunk-7XB47YST.js","sourcesContent":["/**\n * GraphProvider — context plumbing for the React binding.\n *\n * `<Graph>` renders this internally around its children; advanced hosts can\n * use it directly to compose against an externally created GraphInstance.\n */\n\nimport { createContext, useContext } from 'react';\nimport type { ReactElement, ReactNode } from 'react';\nimport type { GraphInstance } from '@modernrelay/orbit-core';\n\n// GraphInstance is invariant in its attribute generics (applyHostUpdate is\n// contravariant, getNode covariant), so the context stores an `any`-erased\n// instance; typed surfaces (hooks, GraphHandle) re-narrow at the edges.\nexport type AnyGraphInstance = GraphInstance<any, any>;\n\nexport const GraphInstanceContext = createContext<AnyGraphInstance | null>(null);\n\n/**\n * Internal: resolve the ambient instance or throw a descriptive error naming\n * the calling hook. Must be called unconditionally (it is itself a hook).\n */\nexport function useAmbientGraphInstance(hookName: string): AnyGraphInstance {\n const instance = useContext(GraphInstanceContext);\n if (instance === null) {\n throw new Error(\n `orbit-react: ${hookName}() must be used within a <Graph> or <GraphProvider> subtree`,\n );\n }\n return instance;\n}\n\nexport interface GraphProviderProps {\n instance: AnyGraphInstance;\n children?: ReactNode;\n}\n\nexport function GraphProvider(props: GraphProviderProps): ReactElement {\n return (\n <GraphInstanceContext.Provider value={props.instance}>\n {props.children}\n </GraphInstanceContext.Provider>\n );\n}\n","/**\n * Shared component foundation (S7-T03): instance resolution + tiny styling\n * primitives every packaged component (`Toolbar`, `ContextMenu`,\n * `SelectionActions`, `Navigator`) and the built-in overlays use.\n */\n\nimport { useContext } from 'react';\nimport type { CSSProperties } from 'react';\nimport type { LabelPlacement } from '@modernrelay/orbit-core';\nimport { GraphInstanceContext } from '../GraphProvider';\nimport type { AnyGraphInstance } from '../GraphProvider';\n\n/**\n * Resolve the GraphInstance a component operates on: an explicit `instance`\n * prop wins, else the ambient <Graph>/<GraphProvider> context. Throws a\n * descriptive error naming the component when neither exists.\n *\n * Must be called unconditionally (it is itself a hook).\n */\nexport function useResolvedInstance(\n explicit?: AnyGraphInstance,\n componentName = 'This component',\n): AnyGraphInstance {\n const ambient = useContext(GraphInstanceContext);\n const resolved = explicit ?? ambient;\n if (resolved === null || resolved === undefined) {\n throw new Error(\n `orbit-react: ${componentName} requires a GraphInstance — render it inside a ` +\n '<Graph> or <GraphProvider> subtree, or pass an explicit `instance` prop.',\n );\n }\n return resolved;\n}\n\n// ---------------------------------------------------------------------------\n// Placement (§6 component chrome). Floating components are positioned by a\n// PROP, not by CSS the host has to reverse-engineer.\n// ---------------------------------------------------------------------------\n\n/** Corner a floating component anchors to inside the graph container. */\nexport type GraphCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\n/** Default distance from the two anchored edges, in CSS px. */\nexport const DEFAULT_CORNER_OFFSET = 12;\n\n/**\n * Absolute-position style for one corner. Only the TWO insets that corner\n * needs are emitted — never all four — so a caller-supplied inset in `style`\n * has nothing to fight with.\n */\nexport function cornerStyle(\n corner: GraphCorner,\n offset: number = DEFAULT_CORNER_OFFSET,\n): CSSProperties {\n const [vertical, horizontal] = corner.split('-') as ['top' | 'bottom', 'left' | 'right'];\n return { position: 'absolute', [vertical]: offset, [horizontal]: offset };\n}\n\nconst OPPOSITE_INSET = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n} as const;\n\n/**\n * Merge a component's default style UNDER a caller override, resolving inset\n * conflicts per AXIS: an inset the caller supplies drops the default's\n * opposite.\n *\n * Plain spreading layers them instead, which is a silent partial application —\n * `{ right: 8 }` over a default `left: 12` leaves BOTH live, `left` wins in\n * LTR, and the caller's value sits in the DOM doing nothing. Per-axis (rather\n * than dropping every inset) keeps the perpendicular anchor, so a lone\n * `{ top: 20 }` nudges vertically instead of jumping to the container edge.\n */\nexport function mergeStyle(base: CSSProperties, override?: CSSProperties): CSSProperties {\n if (override === undefined) return base;\n const out: CSSProperties = { ...base };\n for (const inset of ['top', 'bottom', 'left', 'right'] as const) {\n if (override[inset] !== undefined) delete out[OPPOSITE_INSET[inset]];\n }\n return { ...out, ...override };\n}\n\n// ---------------------------------------------------------------------------\n// Pinned core↔react overlay interface (S7). W1a lands these members on\n// GraphInstance; until the core type surface catches up, components reach\n// them through this structural view with optional access, which stays exactly\n// signature-compatible once the members are required on GraphInstance.\n// ---------------------------------------------------------------------------\n\n/** `instance.labels` — the §14 DOM label lane subscription surface. */\nexport interface GraphLabelsSurface {\n /** Fires ONLY when the candidate SET changes (throttled re-rank; React\n * re-renders label content). Replays current state on subscribe. */\n subscribeCandidates(cb: (list: readonly LabelPlacement[]) => void): () => void;\n /** Fires on scheduler ticks with fresh x/y for the SAME set (imperative\n * transform writes — never a React re-render). Replays on subscribe. */\n subscribePositions(cb: (list: readonly LabelPlacement[]) => void): () => void;\n}\n\n/** Instance members components rely on beyond the v0.3 GraphInstance type. */\nexport interface GraphOverlaySurface {\n labels?: GraphLabelsSurface;\n /** Binding-detected reduced-motion media preference (§15.1). */\n setReducedMotion?(v: boolean | undefined): void;\n pauseSimulation?(): void;\n resumeSimulation?(): void;\n isSimulationRunning?(): boolean;\n /** Delegates to the engine; resolves null when unsupported/not ready. */\n captureScreenshot?(): Promise<Blob | null>;\n}\n\n/** Structural view of the S7 overlay surface on a GraphInstance. */\nexport function overlaySurface(instance: AnyGraphInstance): GraphOverlaySurface {\n return instance as unknown as GraphOverlaySurface;\n}\n\n// ---------------------------------------------------------------------------\n// Styling primitives\n// ---------------------------------------------------------------------------\n\n/** Screen-reader-only content (the classic visually-hidden clip pattern). */\nexport const visuallyHiddenStyle: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\n/** A full-bleed overlay layer above the canvas that never eats pointevents\n * unless a child opts back in with `pointerEvents: 'auto'`. */\nexport const overlayLayerStyle: CSSProperties = {\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/_shared/brush.ts"],"names":[],"mappings":"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","file":"chunk-DGFLU2SN.js","sourcesContent":["/**\n * Shared range-brush interaction (S9): pointer-drag over a plot maps x → a\n * {min,max} window in the dimension's domain units. Any drag REPLACES the\n * brush; double-click clears; ArrowLeft/ArrowRight nudge the window by one\n * bin; Escape clears. The plot element itself is focusable. Used by the\n * packaged /components/Histogram and /components/Timeline entries.\n */\n\nimport { useCallback, useRef } from 'react';\nimport type { KeyboardEvent as ReactKeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';\nimport type { BrushState } from '@modernrelay/orbit-core';\n\nexport interface RangeDomain {\n min: number;\n max: number;\n}\n\nexport function clampValue(v: number, min: number, max: number): number {\n return v < min ? min : v > max ? max : v;\n}\n\n/** Map a pointer clientX over the plot rect to a domain value (clamped). */\nexport function xToDomainValue(\n clientX: number,\n rect: { left: number; width: number },\n domain: RangeDomain,\n): number {\n if (rect.width <= 0) return domain.min;\n const t = clampValue((clientX - rect.left) / rect.width, 0, 1);\n return domain.min + t * (domain.max - domain.min);\n}\n\n/** Range brush → left/width percentages inside the domain (null when the\n * brush is absent, categorical, or the domain is degenerate). */\nexport function brushRangePct(\n brush: BrushState,\n domain: RangeDomain | null,\n): { leftPct: number; widthPct: number } | null {\n if (brush === null || !('min' in brush) || domain === null) return null;\n const span = domain.max - domain.min;\n if (span <= 0) return null;\n const lo = clampValue(brush.min, domain.min, domain.max);\n const hi = clampValue(brush.max, domain.min, domain.max);\n if (hi < lo) return null;\n return { leftPct: ((lo - domain.min) / span) * 100, widthPct: ((hi - lo) / span) * 100 };\n}\n\n/**\n * Shift a {min,max} brush by ±one bin (domain span / binCount), clamped so\n * the window keeps its width. Returns the INPUT reference when there is\n * nothing to nudge (no range brush / degenerate domain) — callers skip the\n * write on reference equality.\n */\nexport function nudgeRangeBrush(\n brush: BrushState,\n domain: RangeDomain,\n binCount: number,\n direction: -1 | 1,\n): BrushState {\n if (brush === null || !('min' in brush)) return brush;\n const span = domain.max - domain.min;\n if (span <= 0 || binCount <= 0) return brush;\n const stepSize = span / binCount;\n const width = Math.min(brush.max - brush.min, span);\n const min = clampValue(brush.min + direction * stepSize, domain.min, domain.max - width);\n return { min, max: min + width };\n}\n\n/** Toggle one category exclusion; an empty exclusion list clears the brush. */\nexport function toggleCategoryExclusion(brush: BrushState, key: string): BrushState {\n const excluded = brush !== null && 'excluded' in brush ? brush.excluded : [];\n const next = excluded.includes(key) ? excluded.filter((k) => k !== key) : [...excluded, key];\n return next.length === 0 ? null : { excluded: next };\n}\n\nexport interface RangeBrushOptions {\n /** Numeric/temporal domain; null disables pointer/arrow interaction. */\n domain: RangeDomain | null;\n /** Bin count — one arrow nudge moves the window by span/binCount. */\n binCount: number;\n brush: BrushState;\n setBrush(brush: BrushState): void;\n}\n\nexport interface RangeBrushHandlers {\n onPointerDown(e: ReactPointerEvent<HTMLElement>): void;\n onPointerMove(e: ReactPointerEvent<HTMLElement>): void;\n onPointerUp(e: ReactPointerEvent<HTMLElement>): void;\n onPointerCancel(e: ReactPointerEvent<HTMLElement>): void;\n onDoubleClick(): void;\n onKeyDown(e: ReactKeyboardEvent<HTMLElement>): void;\n}\n\n/**\n * The drag/keyboard brush behavior over a plot element. Handler identities\n * are stable across renders (options are read through a ref), so spreading\n * them onto the plot never churns DOM listeners.\n */\nexport function useRangeBrush(options: RangeBrushOptions): RangeBrushHandlers {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const dragRef = useRef<{ pointerId: number; startValue: number } | null>(null);\n\n const onPointerDown = useCallback((e: ReactPointerEvent<HTMLElement>): void => {\n const { domain } = optionsRef.current;\n if (domain === null || e.button !== 0) return;\n const start = xToDomainValue(e.clientX, e.currentTarget.getBoundingClientRect(), domain);\n dragRef.current = { pointerId: e.pointerId, startValue: start };\n const el = e.currentTarget;\n if (typeof el.setPointerCapture === 'function') {\n try {\n el.setPointerCapture(e.pointerId);\n } catch {\n // jsdom / detached element: capture is an optimization only.\n }\n }\n }, []);\n\n const onPointerMove = useCallback((e: ReactPointerEvent<HTMLElement>): void => {\n const drag = dragRef.current;\n const { domain, setBrush } = optionsRef.current;\n if (drag === null || domain === null || e.pointerId !== drag.pointerId) return;\n const value = xToDomainValue(e.clientX, e.currentTarget.getBoundingClientRect(), domain);\n setBrush(\n value < drag.startValue\n ? { min: value, max: drag.startValue }\n : { min: drag.startValue, max: value },\n );\n }, []);\n\n const endDrag = useCallback((e: ReactPointerEvent<HTMLElement>): void => {\n if (dragRef.current === null || dragRef.current.pointerId !== e.pointerId) return;\n dragRef.current = null;\n const el = e.currentTarget;\n if (typeof el.releasePointerCapture === 'function') {\n try {\n el.releasePointerCapture(e.pointerId);\n } catch {\n // Capture may never have been established.\n }\n }\n }, []);\n\n const onDoubleClick = useCallback((): void => {\n optionsRef.current.setBrush(null);\n }, []);\n\n const onKeyDown = useCallback((e: ReactKeyboardEvent<HTMLElement>): void => {\n const { domain, binCount, brush, setBrush } = optionsRef.current;\n if (e.key === 'Escape') {\n if (brush !== null) setBrush(null);\n e.preventDefault();\n return;\n }\n if (domain === null || (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight')) return;\n const next = nudgeRangeBrush(brush, domain, binCount, e.key === 'ArrowLeft' ? -1 : 1);\n if (next !== brush) setBrush(next);\n e.preventDefault();\n }, []);\n\n return {\n onPointerDown,\n onPointerMove,\n onPointerUp: endDrag,\n onPointerCancel: endDrag,\n onDoubleClick,\n onKeyDown,\n };\n}\n\n/** aria-valuenow for a brush \"slider\": the window's center (or domain min). */\nexport function sliderValueNow(brush: BrushState, domain: RangeDomain | undefined): number {\n if (domain === undefined) return 0;\n if (brush !== null && 'min' in brush) return (brush.min + brush.max) / 2;\n return domain.min;\n}\n\n/** aria-valuetext: human-readable brush window (or 'no filter'). */\nexport function sliderValueText(brush: BrushState, domain: RangeDomain | undefined): string {\n if (domain === undefined || brush === null || !('min' in brush)) return 'no filter';\n return `filtering ${brush.min} to ${brush.max}`;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/_shared/crossfilter.ts"],"names":[],"mappings":"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","file":"chunk-JN7QCMFW.js","sourcesContent":["/**\n * Internal crossfilter subscription (S9): shared by the public\n * useGraphCrossfilter hook and the packaged /components/Histogram and\n * /components/Timeline entries.\n *\n * Subscribes to the SESSION (session.subscribe) and re-reads\n * summarize/getBrush on notify. The session resolves lazily — null until the\n * `crossfilter` prop has built dimensions over an accepted base — polled via\n * a store subscription (the store publishes when dimensions build). A\n * dimension rebuild swaps the underlying engine WITHOUT changing the session\n * facade identity (and clears the old engine's subscribers), so every store\n * publication re-attaches the session callback; snapshots are structurally\n * cached, making the extra notifications free.\n */\n\nimport { useCallback, useRef, useSyncExternalStore } from 'react';\nimport type { BrushState, DimensionSummary } from '@modernrelay/orbit-core';\nimport type { AnyGraphInstance } from '../../GraphProvider';\n\nexport interface CrossfilterSnapshot {\n /** Null until the dimension exists (no session yet / unknown key). */\n summary: DimensionSummary | null;\n brush: BrushState;\n}\n\nconst EMPTY_SNAPSHOT: CrossfilterSnapshot = { summary: null, brush: null };\n\n/** Structural brush equality (brushes are tiny). */\nexport function sameBrush(a: BrushState, b: BrushState): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if ('excluded' in a) {\n return (\n 'excluded' in b &&\n a.excluded.length === b.excluded.length &&\n a.excluded.every((k, i) => k === b.excluded[i])\n );\n }\n return !('excluded' in b) && a.min === b.min && a.max === b.max;\n}\n\nfunction sameSummary(a: DimensionSummary | null, b: DimensionSummary | null): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if (a.key !== b.key || a.kind !== b.kind || a.excludedRows !== b.excludedRows) return false;\n if (a.domain?.min !== b.domain?.min || a.domain?.max !== b.domain?.max) return false;\n if (a.bins.length !== b.bins.length || a.categories.length !== b.categories.length) {\n return false;\n }\n for (let i = 0; i < a.bins.length; i++) {\n const x = a.bins[i]!;\n const y = b.bins[i]!;\n if (x.x0 !== y.x0 || x.x1 !== y.x1 || x.total !== y.total || x.filtered !== y.filtered) {\n return false;\n }\n }\n for (let i = 0; i < a.categories.length; i++) {\n const x = a.categories[i]!;\n const y = b.categories[i]!;\n if (\n x.key !== y.key ||\n x.total !== y.total ||\n x.filtered !== y.filtered ||\n x.excluded !== y.excluded\n ) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Live {summary, brush} for one dimension key on an explicit instance.\n * Returns a referentially stable snapshot until the content actually changes.\n */\nexport function useCrossfilterDimension(\n instance: AnyGraphInstance,\n key: string,\n): CrossfilterSnapshot {\n const subscribe = useCallback(\n (onChange: () => void) => {\n let sessionUnsub: (() => void) | null = null;\n const attach = (): void => {\n sessionUnsub?.();\n sessionUnsub = null;\n const session = instance.getCrossfilterSession();\n if (session !== null) sessionUnsub = session.subscribe(onChange);\n };\n attach();\n const storeUnsub = instance.store.subscribe(() => {\n attach();\n onChange();\n });\n return () => {\n storeUnsub();\n sessionUnsub?.();\n sessionUnsub = null;\n };\n },\n [instance],\n );\n\n const cacheRef = useRef<{ key: string; value: CrossfilterSnapshot } | null>(null);\n const getSnapshot = useCallback((): CrossfilterSnapshot => {\n const session = instance.getCrossfilterSession();\n let next = EMPTY_SNAPSHOT;\n if (session !== null) {\n try {\n next = { summary: session.summarize(key), brush: session.getBrush(key) };\n } catch {\n // Unknown key / dimension mid-rebuild: absent, never a crash.\n next = EMPTY_SNAPSHOT;\n }\n }\n const cache = cacheRef.current;\n if (\n cache !== null &&\n cache.key === key &&\n sameSummary(cache.value.summary, next.summary) &&\n sameBrush(cache.value.brush, next.brush)\n ) {\n return cache.value;\n }\n cacheRef.current = { key, value: next };\n return next;\n }, [instance, key]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/** Stable setter routing through the session (no-op until it exists). */\nexport function useSessionSetBrush(\n instance: AnyGraphInstance,\n key: string,\n): (brush: BrushState) => void {\n return useCallback(\n (brush: BrushState): void => {\n const session = instance.getCrossfilterSession();\n if (session === null) return;\n // Rejections only occur on teardown races (destroyed instance).\n void session.setBrush(key, brush).catch(() => undefined);\n },\n [instance, key],\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks.ts"],"names":[],"mappings":"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","file":"chunk-QJ7JXQVK.js","sourcesContent":["/**\n * Public hooks — thin useSyncExternalStore selectors over the ambient\n * GraphInstance's vanilla zustand store. All throw a descriptive error when\n * used outside a <Graph>/<GraphProvider> subtree.\n */\n\nimport { useCallback, useRef, useSyncExternalStore } from 'react';\nimport type {\n BrushState,\n DimensionSummary,\n EdgeId,\n GraphDiagnostic,\n GraphInstance,\n GraphStoreState,\n GraphTheme,\n InstanceStatus,\n NodeId,\n SearchResult,\n SearchUnavailableReason,\n SelectionState,\n SubgraphSpec,\n ViewportState,\n} from '@modernrelay/orbit-core';\nimport { useAmbientGraphInstance } from './GraphProvider';\nimport type { AnyGraphInstance } from './GraphProvider';\nimport { useCrossfilterDimension, useSessionSetBrush } from './components/_shared/crossfilter';\n\ninterface SelectorCache<T> {\n hasValue: boolean;\n value: T;\n}\n\n/**\n * Subscribe to a projection of the store. The snapshot is memoized with\n * Object.is so selectors that recompute to the same value keep a stable\n * reference (required by useSyncExternalStore to avoid render loops).\n */\nfunction useStoreSelector<T>(instance: AnyGraphInstance, selector: (s: GraphStoreState) => T): T {\n const selectorRef = useRef(selector);\n selectorRef.current = selector;\n const cacheRef = useRef<SelectorCache<T>>({ hasValue: false, value: undefined as T });\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => instance.store.subscribe(onStoreChange),\n [instance],\n );\n const getSnapshot = useCallback(() => {\n const next = selectorRef.current(instance.store.getState());\n const cache = cacheRef.current;\n if (cache.hasValue && Object.is(cache.value, next)) return cache.value;\n cache.hasValue = true;\n cache.value = next;\n return next;\n }, [instance]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nconst selectSelection = (s: GraphStoreState): SelectionState => s.selection;\n// W1a (S7) adds `simulationRunning` to GraphStoreState; read it tolerantly so\n// the hook is correct both before and after the core field lands.\nconst selectSimulationRunning = (s: GraphStoreState): boolean =>\n (s as GraphStoreState & { simulationRunning?: boolean }).simulationRunning ?? false;\nconst selectHover = (s: GraphStoreState): NodeId | null => s.hover.nodeId;\nconst selectEdgeHover = (s: GraphStoreState): EdgeId | null => s.hover.edgeId;\nconst selectPins = (s: GraphStoreState): ReadonlyMap<NodeId, readonly [number, number]> => s.pins;\nconst selectViewport = (s: GraphStoreState): ViewportState | null => s.viewport;\nconst selectStatus = (s: GraphStoreState): InstanceStatus => s.status;\nconst selectDiagnostics = (s: GraphStoreState): readonly GraphDiagnostic[] => s.diagnostics;\nconst selectScope = (s: GraphStoreState): SubgraphSpec | null => s.scope;\nconst selectPendingExpansions = (s: GraphStoreState): ReadonlySet<NodeId> => s.pendingExpansions;\nconst selectOverlayIds = (s: GraphStoreState): readonly string[] => s.overlayIds;\nconst selectVisible = (s: GraphStoreState): { nodes: number; edges: number } => s.visible;\nconst selectTimeline = (s: GraphStoreState): { playingKey: string | null } => s.timeline;\nconst selectHistory = (s: GraphStoreState): { undoDepth: number; redoDepth: number } => s.history;\n// S10 (§8/§11): resolved theme tokens + the scale-info invalidation signal.\nconst selectTheme = (s: GraphStoreState): GraphTheme => s.theme;\nconst selectScaleVersion = (s: GraphStoreState): string =>\n `${s.revisions.model}:${s.revisions.scope}:${s.revisions.render}`;\n\nexport function useGraphInstance<\n N = Record<string, unknown>,\n E = Record<string, unknown>,\n>(): GraphInstance<N, E> {\n return useAmbientGraphInstance('useGraphInstance') as GraphInstance<N, E>;\n}\n\n/** The full namespaced SelectionState (§16.2); was `readonly NodeId[]` before\n * v0.3 — read `.nodeIds` for the node namespace. */\nexport function useGraphSelection(): SelectionState {\n return useStoreSelector(useAmbientGraphInstance('useGraphSelection'), selectSelection);\n}\n\nexport function useGraphHover(): NodeId | null {\n return useStoreSelector(useAmbientGraphInstance('useGraphHover'), selectHover);\n}\n\nexport function useGraphEdgeHover(): EdgeId | null {\n return useStoreSelector(useAmbientGraphInstance('useGraphEdgeHover'), selectEdgeHover);\n}\n\n/** The §16.3 pin slice: node id → pinned space position. */\nexport function useGraphPins(): ReadonlyMap<NodeId, readonly [number, number]> {\n return useStoreSelector(useAmbientGraphInstance('useGraphPins'), selectPins);\n}\n\nexport function useGraphViewport(): ViewportState | null {\n return useStoreSelector(useAmbientGraphInstance('useGraphViewport'), selectViewport);\n}\n\nexport function useGraphStatus(): InstanceStatus {\n return useStoreSelector(useAmbientGraphInstance('useGraphStatus'), selectStatus);\n}\n\nexport function useGraphDiagnostics(): readonly GraphDiagnostic[] {\n return useStoreSelector(useAmbientGraphInstance('useGraphDiagnostics'), selectDiagnostics);\n}\n\n/** Whether the engine force simulation is currently running (S7; drives the\n * toolbar pause/resume affordance). */\nexport function useGraphSimulationRunning(): boolean {\n return useStoreSelector(\n useAmbientGraphInstance('useGraphSimulationRunning'),\n selectSimulationRunning,\n );\n}\n\n/** The active §9.2 hard scope (`subgraph`); null while the full accepted\n * model is in view. Uncontrolled-only in v0.5: the `subgraph` prop and\n * isolateSelection()/resetIsolation() write this same instance-owned state. */\nexport function useGraphScope(): SubgraphSpec | null {\n return useStoreSelector(useAmbientGraphInstance('useGraphScope'), selectScope);\n}\n\n/** Node ids with an expansion in flight (§9.2 loading affordance — drive\n * spinners/ghost skeletons from this set). */\nexport function useGraphPendingExpansions(): ReadonlySet<NodeId> {\n return useStoreSelector(\n useAmbientGraphInstance('useGraphPendingExpansions'),\n selectPendingExpansions,\n );\n}\n\n/** Committed §7.5 overlay ids for the current dataset. */\nexport function useGraphOverlays(): readonly string[] {\n return useStoreSelector(useAmbientGraphInstance('useGraphOverlays'), selectOverlayIds);\n}\n\n/** §9.1 soft-mask visibility counts: scene entities with zero hide-failures\n * (equals the accepted counts when nothing masks). */\nexport function useGraphVisible(): { nodes: number; edges: number } {\n return useStoreSelector(useAmbientGraphInstance('useGraphVisible'), selectVisible);\n}\n\n/** §16.6 timeline playback state — at most one playing dimension key. */\nexport function useGraphTimeline(): { playingKey: string | null } {\n return useStoreSelector(useAmbientGraphInstance('useGraphTimeline'), selectTimeline);\n}\n\n/** §16.14 history kernel depths (S9 wiring; full walk semantics in S15). */\nexport function useGraphHistory(): { undoDepth: number; redoDepth: number } {\n return useStoreSelector(useAmbientGraphInstance('useGraphHistory'), selectHistory);\n}\n\n/** §8 resolved theme tokens (S10): the merged GraphTheme currently driving\n * engine config, projection fallbacks, and mask dim alpha (`store.theme`).\n * Style legend chrome, tooltips, and other host overlays from these tokens. */\nexport function useGraphTheme(): GraphTheme {\n return useStoreSelector(useAmbientGraphInstance('useGraphTheme'), selectTheme);\n}\n\n/**\n * INTERNAL (S10): subscription surface for `instance.getScaleInfo` readers\n * (<GraphLegend>, the `renderLegend` slot). `version` changes whenever a\n * store publication could change scale info (model/scope/render revisions);\n * `theme` is the stable-by-value theme reference. Consumers recompute\n * getScaleInfo in a memo keyed on both. Not re-exported from the package\n * root — subject to change without notice.\n */\nexport function useScaleInfoSubscription(instance: AnyGraphInstance): {\n version: string;\n theme: GraphTheme;\n} {\n const version = useStoreSelector(instance, selectScaleVersion);\n const theme = useStoreSelector(instance, selectTheme);\n return { version, theme };\n}\n\n// ---------------------------------------------------------------------------\n// §16.5 search (S11)\n// ---------------------------------------------------------------------------\n\nconst selectSearch = (\n s: GraphStoreState,\n): { query: string; results: readonly SearchResult[] } | null => s.search;\n\n/** The last completed §16.5 search (`store.search`): `{query, results}` after\n * a successful `instance.search`, null after `clearSearch()` / a dataset\n * swap. Drives `<GraphSearch>`'s result list and the §15.1 navigator's\n * search-results section. */\nexport function useGraphSearch(): { query: string; results: readonly SearchResult[] } | null {\n return useStoreSelector(useAmbientGraphInstance('useGraphSearch'), selectSearch);\n}\n\n/** §16.5 `onSearchResultUnavailable` callback type (spec §16.5 result\n * contract): fired when an activated result cannot be focused; `reason` is\n * 'not-loaded' | 'out-of-scope' | 'filtered'. The host reacts explicitly —\n * orbit never changes scope/filters behind the user's back. */\nexport type SearchResultUnavailableCallback = (\n result: SearchResult,\n reason: SearchUnavailableReason,\n) => void;\n\n/**\n * INTERNAL (S11): the `<Graph onSearchResultUnavailable>` → `<GraphSearch>`\n * default-callback channel. `<Graph>` registers its prop here per instance;\n * `<GraphSearch>` (and other activation surfaces) fall back to it when they\n * have no local `onResultUnavailable` prop. A WeakMap keyed by the instance —\n * not a React context — so packaged component entries can resolve it without\n * `<Graph>` in their import graph (treeshake sentinels stay clean) and\n * registration never re-renders subscribers. Not re-exported from the package\n * root — subject to change without notice.\n */\nconst searchUnavailableCallbacks = new WeakMap<AnyGraphInstance, SearchResultUnavailableCallback>();\n\n/** INTERNAL (S11): register/clear the instance's default unavailable-result\n * callback (undefined clears). See {@link searchUnavailableCallbacks}. */\nexport function setSearchResultUnavailableCallback(\n instance: AnyGraphInstance,\n cb: SearchResultUnavailableCallback | undefined,\n): void {\n if (cb === undefined) searchUnavailableCallbacks.delete(instance);\n else searchUnavailableCallbacks.set(instance, cb);\n}\n\n/** INTERNAL (S11): resolve the instance's default unavailable-result callback. */\nexport function getSearchResultUnavailableCallback(\n instance: AnyGraphInstance,\n): SearchResultUnavailableCallback | undefined {\n return searchUnavailableCallbacks.get(instance);\n}\n\n/** One §16.6 crossfilter dimension: live summary + brush + a setter. */\nexport interface GraphCrossfilterDimension {\n /** Null until the `crossfilter` prop builds the dimension over data. */\n summary: DimensionSummary | null;\n brush: BrushState;\n setBrush: (brush: BrushState) => void;\n}\n\n/**\n * Subscribe to one crossfilter dimension by key (§16.6). Re-reads\n * summarize/getBrush on session notify; resolves the session lazily (null\n * summary until the `crossfilter` prop builds dimensions over an accepted\n * base — the store publishes when they do).\n */\nexport function useGraphCrossfilter(key: string): GraphCrossfilterDimension {\n const instance = useAmbientGraphInstance('useGraphCrossfilter');\n const snapshot = useCrossfilterDimension(instance, key);\n const setBrush = useSessionSetBrush(instance, key);\n return { summary: snapshot.summary, brush: snapshot.brush, setBrush };\n}\n"]}