@simplex-viz/react 0.2.0 → 0.3.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/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://raw.githubusercontent.com/ghackenberg/simplex-viz/main/docs/assets/logo-react.png" width="640" alt="SimplexViz / react — @simplex-viz/react" />
2
+ <img src="https://raw.githubusercontent.com/ghackenberg/simplex-viz/main/docs/assets/logo-react.png" width="525" alt="SimplexViz / react — @simplex-viz/react" />
3
3
  </p>
4
4
 
5
5
  # @simplex-viz/react
@@ -356,6 +356,59 @@ export function FastGraph({
356
356
 
357
357
  > **Tip:** Memoize `visualResolver` (e.g., via `useMemo`) and keep `contentView` / `clusterView` instances stable outside render to avoid unnecessary crossfades. Changing `preset`, `visualResolver`, or switching view props intentionally triggers a smooth crossfade/morph transition.
358
358
 
359
+ ## Combining Presets & Pluggable Core Strategies
360
+
361
+ Every `@simplex-viz/core` strategy factory is re-exported from `@simplex-viz/react` (`createFixedLatticeMeshStrategy`, `createIncrementalAnchorClusteringStrategy`, `createThemeAdaptiveOklabColorStrategy`, `createPaletteColorStrategy`, `createWarmStartPbdLayoutStrategy`, `createLocalAdaptiveLayoutStrategy`, etc.). Memoize strategy instances with `useMemo` and pass them alongside any `preset`, `theme`, or custom JSX renderer:
362
+
363
+ ```tsx
364
+ import { useMemo, useState } from 'react';
365
+ import {
366
+ SimplexTopicGraph,
367
+ createFixedLatticeMeshStrategy,
368
+ createIncrementalAnchorClusteringStrategy,
369
+ createLocalAdaptiveLayoutStrategy,
370
+ createThemeAdaptiveOklabColorStrategy,
371
+ type DefaultTaggedItem,
372
+ } from '@simplex-viz/react';
373
+
374
+ export function StrategyShowcase({ items }: { items: readonly DefaultTaggedItem[] }) {
375
+ const [theme, setTheme] = useState<'dark' | 'light'>('light');
376
+
377
+ const meshStrategy = useMemo(
378
+ () => createFixedLatticeMeshStrategy<DefaultTaggedItem>({ cols: 3, rows: 3 }),
379
+ [],
380
+ );
381
+ const clusteringStrategy = useMemo(
382
+ () =>
383
+ createIncrementalAnchorClusteringStrategy<DefaultTaggedItem>({
384
+ sharedTagRule: 'planar-hitting-set',
385
+ anchorRule: 'explaining-away',
386
+ }),
387
+ [],
388
+ );
389
+ const colorStrategy = useMemo(
390
+ () => createThemeAdaptiveOklabColorStrategy<DefaultTaggedItem>(),
391
+ [],
392
+ );
393
+ const layoutStrategy = useMemo(
394
+ () => createLocalAdaptiveLayoutStrategy({ warmStart: true }),
395
+ [],
396
+ );
397
+
398
+ return (
399
+ <SimplexTopicGraph
400
+ items={items}
401
+ preset="badges"
402
+ theme={theme}
403
+ meshStrategy={meshStrategy}
404
+ clusteringStrategy={clusteringStrategy}
405
+ colorStrategy={colorStrategy}
406
+ layoutStrategy={layoutStrategy}
407
+ />
408
+ );
409
+ }
410
+ ```
411
+
359
412
  ## `<SimplexTopicGraph />` Props Reference
360
413
 
361
414
  ### Data, Typing & Metadata
@@ -373,6 +426,7 @@ export function FastGraph({
373
426
  | Prop | Default | Description |
374
427
  | --- | --- | --- |
375
428
  | `preset` | `'geometric'` | Built-in visual preset (`'geometric' \| 'glyphs' \| 'badges'`) used when custom views or `visualResolver` are omitted. |
429
+ | `theme` | `'dark'` | Color theme (`'dark' \| 'light'`) applied to built-in presets, tooltips, and theme-adaptive color strategies. |
376
430
  | `visualResolver` | Built-in preset resolver | Optional `VisualResolver` mapping items and clusters to custom descriptors and cache keys. |
377
431
  | `renderContentNode` | — | Declarative React JSX renderer `(item, ctx, state) => ReactNode` (works with or without `visualResolver`, auto-measured via `getBBox()`). |
378
432
  | `renderClusterNode` | — | Declarative React JSX renderer `(cluster, state) => ReactNode` (works with or without `visualResolver`, auto-measured via `getBBox()`). |
@@ -381,11 +435,15 @@ export function FastGraph({
381
435
  | `contentView` | Preset view | Portable `SvgNodeView<TContentVisual>` plugin (used when `renderContentNode` is omitted). |
382
436
  | `clusterView` | Preset view | Portable `SvgNodeView<TClusterVisual>` plugin (used when `renderClusterNode` is omitted). |
383
437
 
384
- ### Mesh, Solver & Visual Emphasis
438
+ ### Mesh, Solver, Strategies & Visual Emphasis
385
439
  | Prop | Default | Description |
386
440
  | --- | --- | --- |
387
441
  | `meshOptions` | — | `{ innerPadding, minSideLength, maxSideLength, maxClusters }`. |
388
442
  | `layoutOptions` | — | `{ clusterGapPx, itemGapPx, minContentScale, relaxationIterations, seed }`. |
443
+ | `meshStrategy` | `createAdaptiveHexMeshStrategy()` | Pluggable `SimplexMeshStrategy<TItem>` controlling 60° triangulation layout. |
444
+ | `clusteringStrategy` | `createJaccardAnnealingClusteringStrategy()` | Pluggable `SimplexClusteringStrategy<TItem, TTagMeta>` (`initialize` + `update`, `sharedTagRule`, `anchorRule`). |
445
+ | `colorStrategy` | `createOklabContrastColorStrategy()` | Pluggable `SimplexColorStrategy<TItem, TTagMeta>` (OKLab contrast, theme-adaptive, or custom palette). |
446
+ | `layoutStrategy` | `createPbdUniformLayoutStrategy()` | Pluggable `SimplexLayoutStrategy` (`pbd-uniform`, `pbd-warm-start`, `local-adaptive`, or custom). |
389
447
  | `sizeMultiplier` | `1.0` | Uniform node size multiplier (`0.35` – `3.0`). |
390
448
  | `showHulls` | `false` | Renders convex bounding hull wireframes over nodes. |
391
449
  | `pinnedIds` | — | `ReadonlySet<string> \| readonly string[]` of pinned item IDs. |
@@ -415,6 +473,7 @@ Returns `{ controllerRef, handle }`:
415
473
  - `handle.addItems(items)` — Appends items without resetting existing camera or springs.
416
474
  - `handle.removeItems(ids)` — Removes items by ID with smooth fade-out.
417
475
  - `handle.setItems(items)` — Replaces the active dataset.
476
+ - `handle.setMeshStrategy(strategy)` / `handle.setClusteringStrategy(strategy)` / `handle.setColorStrategy(strategy)` / `handle.setLayoutStrategy(strategy)` — Hot-swaps core pipeline strategies imperatively.
418
477
  - `handle.zoomBy(factor)` — Zooms relative to viewport center.
419
478
  - `handle.resetCamera()` — Resets zoom & pan smoothly to `(1, 0, 0)`.
420
479
  - `handle.getMetrics()` — Returns the latest `LayoutMetrics | null`.
@@ -1,5 +1,5 @@
1
- import type { ClusterDescriptor, ClusterHoverEvent, ClusterMetaConfig, ContentHoverEvent, ContentLayoutContext, DefaultTaggedItem, HitTarget, ItemIdentityConfig, LayoutMetrics, LayoutSolverOptions, MeshOptions, NodeRenderState, NormalizedPointerEvent, VisualResolver, WheelBehavior } from '@simplex-viz/core';
2
- import { SimplexSvgController, type DefaultClusterPresetVisual, type DefaultContentPresetVisual, type SimplexVisualPreset, type SvgNodeView } from '@simplex-viz/svg';
1
+ import type { ClusterDescriptor, ClusterHoverEvent, ClusterMetaConfig, ContentHoverEvent, ContentLayoutContext, DefaultTaggedItem, HitTarget, ItemIdentityConfig, LayoutMetrics, LayoutSolverOptions, MeshOptions, NodeRenderState, NormalizedPointerEvent, SimplexClusteringStrategy, SimplexColorStrategy, SimplexLayoutStrategy, SimplexMeshStrategy, VisualResolver, WheelBehavior } from '@simplex-viz/core';
2
+ import { SimplexSvgController, type DefaultClusterPresetVisual, type DefaultContentPresetVisual, type SimplexTheme, type SimplexVisualPreset, type SvgNodeView } from '@simplex-viz/svg';
3
3
  import { type CSSProperties, type MutableRefObject, type ReactNode } from 'react';
4
4
  /**
5
5
  * Union payload passed to a custom React `tooltip` formatter on `<SimplexTopicGraph />`.
@@ -21,6 +21,8 @@ export type SimplexTopicGraphProps<TItem = DefaultTaggedItem, TContentVisual = D
21
21
  readonly items: readonly TItem[];
22
22
  /** Built-in visual preset used when custom views / `visualResolver` are omitted. Default: `'geometric'`. */
23
23
  readonly preset?: SimplexVisualPreset;
24
+ /** Visual color theme (`'dark'` or `'light'`) for built-in presets and tooltips. Default: `'dark'`. */
25
+ readonly theme?: SimplexTheme;
24
26
  /** Optional label extractor for built-in presets and default hover tooltips. */
25
27
  readonly getLabel?: (item: TItem) => string;
26
28
  /**
@@ -44,6 +46,14 @@ export type SimplexTopicGraphProps<TItem = DefaultTaggedItem, TContentVisual = D
44
46
  readonly resolveTagMeta?: (normalizedTag: string) => TTagMeta | undefined;
45
47
  readonly meshOptions?: MeshOptions;
46
48
  readonly layoutOptions?: LayoutSolverOptions;
49
+ /** Optional custom mesh/triangulation strategy. */
50
+ readonly meshStrategy?: SimplexMeshStrategy<TItem>;
51
+ /** Optional custom topic clustering & vertex assignment strategy. */
52
+ readonly clusteringStrategy?: SimplexClusteringStrategy<TItem, TTagMeta>;
53
+ /** Optional custom cluster coloring & item color-mixing strategy. */
54
+ readonly colorStrategy?: SimplexColorStrategy<TItem, TTagMeta>;
55
+ /** Optional custom node positioning & scaling strategy. */
56
+ readonly layoutStrategy?: SimplexLayoutStrategy;
47
57
  readonly sizeMultiplier?: number;
48
58
  readonly showHulls?: boolean;
49
59
  readonly pinnedIds?: ReadonlySet<string> | readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"SimplexTopicGraph.d.ts","sourceRoot":"","sources":["../src/SimplexTopicGraph.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SimplexTopicGraph.d.ts","sourceRoot":"","sources":["../src/SimplexTopicGraph.tsx"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './ReactJsxSvgView';
2
2
  export * from './useSimplexGraphController';
3
3
  export * from './SimplexTopicGraph';
4
- export { BadgeClusterSvgView, ClusterAnchorSvgView, GeometricShapeSvgView, MultiSectorGlyphSvgView, SimplexSvgController, createSimplexSvg, type BadgeClusterVisual, type ClusterAnchorVisual, type DefaultClusterPresetVisual, type DefaultContentPresetVisual, type GeometricShapeVisual, type MultiSectorGlyphVisual, type SimplexVisualPreset, type SvgNodeView, } from '@simplex-viz/svg';
5
- export { solveSimplexSnapshot, computeConvexHull, rectToConvexPolygon, regularPolygon, starConvexHull, type CameraController, type CameraState, type ClusterDescriptor, type ClusterHoverEvent, type ContentHoverEvent, type ContentLayoutContext, type ConvexGeometry, type DefaultTaggedItem, type HitTarget, type LayoutMetrics, type LayoutSolverOptions, type MeshOptions, type NodeRenderState, type SimplexLayoutSnapshot, type SimplexSnapshotOptions, type VisualResolver, } from '@simplex-viz/core';
4
+ export { BadgeClusterSvgView, ClusterAnchorSvgView, GeometricShapeSvgView, MultiSectorGlyphSvgView, SimplexSvgController, createSimplexSvg, type BadgeClusterVisual, type ClusterAnchorVisual, type DefaultClusterPresetVisual, type DefaultContentPresetVisual, type GeometricShapeVisual, type MultiSectorGlyphVisual, type SimplexTheme, type SimplexVisualPreset, type SvgNodeView, } from '@simplex-viz/svg';
5
+ export { solveSimplexSnapshot, computeConvexHull, rectToConvexPolygon, regularPolygon, starConvexHull, createAdaptiveHexMeshStrategy, createFixedLatticeMeshStrategy, createJaccardAnnealingClusteringStrategy, createIncrementalAnchorClusteringStrategy, createOklabContrastColorStrategy, createThemeAdaptiveOklabColorStrategy, createPaletteColorStrategy, createPbdUniformLayoutStrategy, createWarmStartPbdLayoutStrategy, createLocalAdaptiveLayoutStrategy, type AssignedColor, type CameraController, type CameraState, type ClusterColorInput, type ClusterColorStrategyContext, type ClusterDescriptor, type ClusterHoverEvent, type ClusteringStrategyContext, type ClusteringStrategyOutput, type ComputedItemAnchor, type ComputedTopicCluster, type ContentHoverEvent, type ContentLayoutContext, type ConvexGeometry, type DefaultTaggedItem, type HitTarget, type ItemColorMixContext, type LayoutMetrics, type LayoutSolverOptions, type LayoutStrategyContext, type MeshOptions, type NodeRenderState, type PipelineUpdateReason, type PreviousNodeLayout, type SharedTagExpansionContext, type SharedTagExpansionFn, type SharedTagRule, type SharedTagRuleKind, type SimplexAnchorRule, type SimplexAnchorRuleKind, type SimplexClusteringStrategy, type SimplexColorStrategy, type SimplexColorTheme, type SimplexItemAnchorContext, type SimplexItemAnchorFn, type SimplexLayoutSnapshot, type SimplexLayoutStrategy, type SimplexMeshContext, type SimplexMeshStrategy, type SimplexSnapshotOptions, type VisualResolver, } from '@simplex-viz/core';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AAGpC,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AAGpC,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,6BAA6B,EAC7B,8BAA8B,EAC9B,wCAAwC,EACxC,yCAAyC,EACzC,gCAAgC,EAChC,qCAAqC,EACrC,0BAA0B,EAC1B,8BAA8B,EAC9B,gCAAgC,EAChC,iCAAiC,EACjC,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { rectToConvexPolygon } from '@simplex-viz/core';
2
- export { computeConvexHull, rectToConvexPolygon, regularPolygon, solveSimplexSnapshot, starConvexHull } from '@simplex-viz/core';
2
+ export { computeConvexHull, createAdaptiveHexMeshStrategy, createFixedLatticeMeshStrategy, createIncrementalAnchorClusteringStrategy, createJaccardAnnealingClusteringStrategy, createLocalAdaptiveLayoutStrategy, createOklabContrastColorStrategy, createPaletteColorStrategy, createPbdUniformLayoutStrategy, createThemeAdaptiveOklabColorStrategy, createWarmStartPbdLayoutStrategy, rectToConvexPolygon, regularPolygon, solveSimplexSnapshot, starConvexHull } from '@simplex-viz/core';
3
3
  import { SVG_NS, SimplexSvgController, createPresetVisualResolver, createPresetViews, extractDefaultItemLabel } from '@simplex-viz/svg';
4
4
  export { BadgeClusterSvgView, ClusterAnchorSvgView, GeometricShapeSvgView, MultiSectorGlyphSvgView, SimplexSvgController, createSimplexSvg } from '@simplex-viz/svg';
5
5
  import { createRoot } from 'react-dom/client';
@@ -138,6 +138,24 @@ function useSimplexGraphController() {
138
138
  const setItems = useCallback((items) => {
139
139
  controllerRef.current?.setItems(items);
140
140
  }, []);
141
+ const setMeshStrategy = useCallback((strategy) => {
142
+ controllerRef.current?.setMeshStrategy(strategy);
143
+ }, []);
144
+ const setClusteringStrategy = useCallback(
145
+ (strategy) => {
146
+ controllerRef.current?.setClusteringStrategy(strategy);
147
+ },
148
+ []
149
+ );
150
+ const setColorStrategy = useCallback(
151
+ (strategy) => {
152
+ controllerRef.current?.setColorStrategy(strategy);
153
+ },
154
+ []
155
+ );
156
+ const setLayoutStrategy = useCallback((strategy) => {
157
+ controllerRef.current?.setLayoutStrategy(strategy);
158
+ }, []);
141
159
  const resetCamera = useCallback(() => {
142
160
  controllerRef.current?.camera.reset();
143
161
  }, []);
@@ -146,8 +164,10 @@ function useSimplexGraphController() {
146
164
  if (!ctrl) return;
147
165
  const svg = ctrl.getSvgElement();
148
166
  const rect = svg.getBoundingClientRect();
167
+ const width = rect.width > 0 ? rect.width : svg.clientWidth || 960;
168
+ const height = rect.height > 0 ? rect.height : svg.clientHeight || 620;
149
169
  const cam = ctrl.camera;
150
- cam.zoomToCursor(rect.width / 2, rect.height / 2, factor);
170
+ cam.zoomToCursor(width / 2, height / 2, factor);
151
171
  }, []);
152
172
  const getMetrics = useCallback(() => {
153
173
  return controllerRef.current?.getMetrics() ?? null;
@@ -164,6 +184,10 @@ function useSimplexGraphController() {
164
184
  addItems,
165
185
  removeItems,
166
186
  setItems,
187
+ setMeshStrategy,
188
+ setClusteringStrategy,
189
+ setColorStrategy,
190
+ setLayoutStrategy,
167
191
  resetCamera,
168
192
  zoomBy,
169
193
  getMetrics,
@@ -190,9 +214,14 @@ function SimplexTopicGraph(props) {
190
214
  const jsxClusterViewRef = useRef(null);
191
215
  const latestPropsRef = useRef(props);
192
216
  latestPropsRef.current = props;
217
+ const syncedMeshStrategyRef = useRef(props.meshStrategy);
218
+ const syncedClusteringStrategyRef = useRef(props.clusteringStrategy);
219
+ const syncedColorStrategyRef = useRef(props.colorStrategy);
220
+ const syncedLayoutStrategyRef = useRef(props.layoutStrategy);
193
221
  const resolveEffectiveResolver = () => {
194
222
  const p = latestPropsRef.current;
195
223
  const preset = p.preset ?? "geometric";
224
+ const theme = p.theme ?? "dark";
196
225
  const presetResolver = createPresetVisualResolver(
197
226
  preset,
198
227
  (item) => {
@@ -213,7 +242,8 @@ function SimplexTopicGraph(props) {
213
242
  }
214
243
  }
215
244
  return "";
216
- }
245
+ },
246
+ theme
217
247
  );
218
248
  const base = p.visualResolver;
219
249
  const getKey = (visual) => {
@@ -319,6 +349,7 @@ function SimplexTopicGraph(props) {
319
349
  getLabel: p.getLabel,
320
350
  deriveClusterMeta: p.deriveClusterMeta,
321
351
  preset: p.preset,
352
+ theme: p.theme,
322
353
  visualResolver: effectiveResolver,
323
354
  contentView,
324
355
  clusterView,
@@ -329,6 +360,10 @@ function SimplexTopicGraph(props) {
329
360
  ...p.layoutOptions,
330
361
  sizeMultiplier: p.sizeMultiplier ?? p.layoutOptions?.sizeMultiplier ?? 1
331
362
  },
363
+ meshStrategy: p.meshStrategy,
364
+ clusteringStrategy: p.clusteringStrategy,
365
+ colorStrategy: p.colorStrategy,
366
+ layoutStrategy: p.layoutStrategy,
332
367
  showHulls: p.showHulls,
333
368
  focusOnClusterClick: false,
334
369
  interactions: {
@@ -403,12 +438,14 @@ function SimplexTopicGraph(props) {
403
438
  useEffect(() => {
404
439
  const ctrl = ctrlRef.current;
405
440
  if (!ctrl) return;
441
+ ctrl.setTheme(props.theme ?? "dark");
406
442
  const effectiveResolver = resolveEffectiveResolver();
407
443
  const { contentView, clusterView } = resolveActiveViews(effectiveResolver);
408
444
  ctrl.setViews({ contentView, clusterView });
409
445
  ctrl.setVisualResolver(effectiveResolver);
410
446
  }, [
411
447
  props.preset,
448
+ props.theme,
412
449
  props.visualResolver,
413
450
  props.contentView,
414
451
  props.clusterView,
@@ -425,6 +462,34 @@ function SimplexTopicGraph(props) {
425
462
  ctrlRef.current?.setShowHulls(props.showHulls);
426
463
  }
427
464
  }, [props.showHulls]);
465
+ useEffect(() => {
466
+ if (syncedMeshStrategyRef.current === props.meshStrategy) return;
467
+ syncedMeshStrategyRef.current = props.meshStrategy;
468
+ if (props.meshStrategy) {
469
+ ctrlRef.current?.setMeshStrategy(props.meshStrategy);
470
+ }
471
+ }, [props.meshStrategy]);
472
+ useEffect(() => {
473
+ if (syncedClusteringStrategyRef.current === props.clusteringStrategy) return;
474
+ syncedClusteringStrategyRef.current = props.clusteringStrategy;
475
+ if (props.clusteringStrategy) {
476
+ ctrlRef.current?.setClusteringStrategy(props.clusteringStrategy);
477
+ }
478
+ }, [props.clusteringStrategy]);
479
+ useEffect(() => {
480
+ if (syncedColorStrategyRef.current === props.colorStrategy) return;
481
+ syncedColorStrategyRef.current = props.colorStrategy;
482
+ if (props.colorStrategy) {
483
+ ctrlRef.current?.setColorStrategy(props.colorStrategy);
484
+ }
485
+ }, [props.colorStrategy]);
486
+ useEffect(() => {
487
+ if (syncedLayoutStrategyRef.current === props.layoutStrategy) return;
488
+ syncedLayoutStrategyRef.current = props.layoutStrategy;
489
+ if (props.layoutStrategy) {
490
+ ctrlRef.current?.setLayoutStrategy(props.layoutStrategy);
491
+ }
492
+ }, [props.layoutStrategy]);
428
493
  useEffect(() => {
429
494
  if (props.pinnedIds !== void 0) {
430
495
  ctrlRef.current?.setPinnedIds(props.pinnedIds);
@@ -458,16 +523,17 @@ function SimplexTopicGraph(props) {
458
523
  Math.max(8, Math.round(hoveredTarget.screenPosition.y + 14)),
459
524
  Math.max(8, containerH - 80)
460
525
  );
526
+ const isLight = props.theme === "light";
461
527
  const content = typeof props.tooltip === "function" ? props.tooltip(hoveredTarget) : hoveredTarget.kind === "content" ? /* @__PURE__ */ jsxs("div", { children: [
462
- /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, color: "#f8fafc" }, children: extractDefaultItemLabel(
528
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, color: isLight ? "#0f172a" : "#f8fafc" }, children: extractDefaultItemLabel(
463
529
  hoveredTarget.item,
464
530
  hoveredTarget.layoutContext.id,
465
531
  props.getLabel
466
532
  ) }),
467
- hoveredTarget.layoutContext.tags.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: 3, fontSize: 11, color: "#94a3b8" }, children: hoveredTarget.layoutContext.tags.map((t) => `#${t.tag}`).slice(0, 5).join(" \xB7 ") })
533
+ hoveredTarget.layoutContext.tags.length > 0 && /* @__PURE__ */ jsx("div", { style: { marginTop: 3, fontSize: 11, color: isLight ? "#475569" : "#94a3b8" }, children: hoveredTarget.layoutContext.tags.map((t) => `#${t.tag}`).slice(0, 5).join(" \xB7 ") })
468
534
  ] }) : /* @__PURE__ */ jsxs("div", { children: [
469
535
  /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, color: hoveredTarget.cluster.colorHex }, children: `${hoveredTarget.cluster.code} \xB7 ${hoveredTarget.cluster.defaultLabel}` }),
470
- /* @__PURE__ */ jsx("div", { style: { marginTop: 3, fontSize: 11, color: "#94a3b8" }, children: `${hoveredTarget.cluster.members.length} ${hoveredTarget.cluster.members.length === 1 ? "item" : "items"}` })
536
+ /* @__PURE__ */ jsx("div", { style: { marginTop: 3, fontSize: 11, color: isLight ? "#475569" : "#94a3b8" }, children: `${hoveredTarget.cluster.members.length} ${hoveredTarget.cluster.members.length === 1 ? "item" : "items"}` })
471
537
  ] });
472
538
  return /* @__PURE__ */ jsx(
473
539
  "div",
@@ -481,13 +547,13 @@ function SimplexTopicGraph(props) {
481
547
  maxWidth: 244,
482
548
  padding: "7px 10px",
483
549
  borderRadius: 8,
484
- background: "rgba(9, 13, 22, 0.94)",
485
- border: "1px solid rgba(51, 65, 85, 0.85)",
486
- color: "#f1f5f9",
550
+ background: isLight ? "rgba(255, 255, 255, 0.96)" : "rgba(9, 13, 22, 0.94)",
551
+ border: isLight ? "1px solid rgba(203, 213, 225, 0.95)" : "1px solid rgba(51, 65, 85, 0.85)",
552
+ color: isLight ? "#0f172a" : "#f1f5f9",
487
553
  fontSize: 12,
488
554
  lineHeight: 1.4,
489
555
  pointerEvents: "none",
490
- boxShadow: "0 10px 24px rgba(0, 0, 0, 0.45)"
556
+ boxShadow: isLight ? "0 10px 24px rgba(15, 23, 42, 0.12)" : "0 10px 24px rgba(0, 0, 0, 0.45)"
491
557
  },
492
558
  children: content
493
559
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ReactJsxSvgView.ts","../src/useSimplexGraphController.ts","../src/SimplexTopicGraph.tsx"],"names":["jsx","useRef"],"mappings":"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","file":"index.js","sourcesContent":["import {\n rectToConvexPolygon,\n type ClusterDescriptor,\n type ContentLayoutContext,\n type ConvexGeometry,\n type NodeRenderState,\n} from '@simplex-viz/core';\nimport { SVG_NS, type SvgNodeView } from '@simplex-viz/svg';\nimport type { ReactNode } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport { renderToStaticMarkup } from 'react-dom/server';\n\nexport interface ContentDomainRecord<TItem, TTagMeta, TClusterMeta> {\n readonly item: TItem;\n readonly ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>;\n}\n\n/**\n * Bridges a declarative React JSX render function into an `@simplex-viz/svg` `SvgNodeView`\n * with automatic offscreen `getBBox()` convex hull measurement and cached DOM updates.\n */\nexport class ReactJsxSvgView<TVisual, TDomain> implements SvgNodeView<TVisual> {\n private readonly renderFn: (\n domain: TDomain,\n state: NodeRenderState<TVisual>,\n ) => ReactNode;\n private readonly getKey: (visual: TVisual) => string;\n private readonly domainByKey: ReadonlyMap<string, TDomain>;\n private readonly rootsByGroup = new WeakMap<SVGGElement, Root>();\n private readonly activeRoots = new Set<Root>();\n private measureGroup: SVGGElement | null = null;\n\n constructor(params: {\n readonly renderFn: (domain: TDomain, state: NodeRenderState<TVisual>) => ReactNode;\n readonly getKey: (visual: TVisual) => string;\n readonly domainByKey: ReadonlyMap<string, TDomain>;\n }) {\n this.renderFn = params.renderFn;\n this.getKey = params.getKey;\n this.domainByKey = params.domainByKey;\n }\n\n measureConvexHull(visual: TVisual, measureSvg: SVGSVGElement): ConvexGeometry {\n const key = this.getKey(visual);\n const domain = this.domainByKey.get(key);\n if (!domain) {\n return rectToConvexPolygon(48, 28, 6);\n }\n\n const doc = measureSvg.ownerDocument;\n let bin = measureSvg.querySelector<SVGGElement>('g.sv-measure-bin');\n if (!bin) {\n bin = doc.createElementNS(SVG_NS, 'g');\n bin.setAttribute('class', 'sv-measure-bin');\n bin.setAttribute('visibility', 'hidden');\n bin.setAttribute('pointer-events', 'none');\n bin.setAttribute('transform', 'translate(-99999, -99999)');\n measureSvg.appendChild(bin);\n }\n\n if (!this.measureGroup || this.measureGroup.parentNode !== bin) {\n this.measureGroup = doc.createElementNS(SVG_NS, 'g');\n bin.appendChild(this.measureGroup);\n }\n\n const dummyState: NodeRenderState<TVisual> = {\n id: '__measure__',\n x: 0,\n y: 0,\n scale: 1,\n opacity: 1,\n visual,\n hull: { kind: 'circle', radius: 16 },\n cacheKey: key,\n interaction: {\n isHovered: false,\n isPinned: false,\n isDimmed: false,\n isHighlighted: false,\n },\n transition: null,\n };\n\n const jsx = this.renderFn(domain, dummyState);\n const markup = renderToStaticMarkup(jsx);\n // Parse JSX markup into SVG namespace inside the offscreen measurement group\n const wrapperSvg = doc.createElementNS(SVG_NS, 'svg');\n wrapperSvg.innerHTML = markup;\n while (this.measureGroup.firstChild) {\n this.measureGroup.removeChild(this.measureGroup.firstChild);\n }\n while (wrapperSvg.firstChild) {\n this.measureGroup.appendChild(wrapperSvg.firstChild);\n }\n\n let width = 0;\n let height = 0;\n try {\n if (typeof this.measureGroup.getBBox === 'function') {\n const bbox = this.measureGroup.getBBox();\n width = bbox.width;\n height = bbox.height;\n }\n } catch {\n // Headless DOM without layout engine\n }\n\n if (width <= 1 || height <= 1) {\n let maxHalfW = 0;\n let maxHalfH = 0;\n this.measureGroup.querySelectorAll('rect, circle, text').forEach((el) => {\n const tag = el.tagName.toLowerCase();\n if (tag === 'rect') {\n const w = parseFloat(el.getAttribute('width') ?? '0');\n const h = parseFloat(el.getAttribute('height') ?? '0');\n maxHalfW = Math.max(maxHalfW, w / 2);\n maxHalfH = Math.max(maxHalfH, h / 2);\n } else if (tag === 'circle') {\n const r = parseFloat(el.getAttribute('r') ?? '0');\n maxHalfW = Math.max(maxHalfW, r);\n maxHalfH = Math.max(maxHalfH, r);\n } else if (tag === 'text') {\n const len = (el.textContent ?? '').length;\n const fs = parseFloat(el.getAttribute('font-size') ?? '11');\n maxHalfW = Math.max(maxHalfW, (len * fs * 0.56) / 2);\n maxHalfH = Math.max(maxHalfH, fs * 0.75);\n }\n });\n width = Math.max(24, maxHalfW * 2);\n height = Math.max(20, maxHalfH * 2);\n }\n\n return rectToConvexPolygon(width + 4, height + 4, 6);\n }\n\n mountOrUpdate(\n groupEl: SVGGElement,\n visual: TVisual,\n state: NodeRenderState<TVisual>,\n ): void {\n const key = this.getKey(visual);\n const domain = this.domainByKey.get(key);\n if (!domain) return;\n\n let root = this.rootsByGroup.get(groupEl);\n if (!root) {\n while (groupEl.firstChild) groupEl.removeChild(groupEl.firstChild);\n root = createRoot(groupEl);\n this.rootsByGroup.set(groupEl, root);\n this.activeRoots.add(root);\n }\n\n root.render(this.renderFn(domain, state));\n }\n\n dispose(): void {\n const roots = [...this.activeRoots];\n this.activeRoots.clear();\n this.measureGroup = null;\n queueMicrotask(() => {\n for (const r of roots) {\n r.unmount();\n }\n });\n }\n}\n\nexport type ContentJsxRenderFn<TItem, TContentVisual, TTagMeta, TClusterMeta> = (\n item: TItem,\n ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TContentVisual>,\n) => ReactNode;\n\nexport type ClusterJsxRenderFn<TItem, TClusterVisual, TTagMeta, TClusterMeta> = (\n cluster: ClusterDescriptor<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TClusterVisual>,\n) => ReactNode;\n","import type {\n CameraController,\n ClusterDescriptor,\n DefaultTaggedItem,\n LayoutMetrics,\n} from '@simplex-viz/core';\nimport type { SimplexSvgController } from '@simplex-viz/svg';\nimport { useCallback, useRef } from 'react';\n\n/**\n * Imperative handle bound to `<SimplexTopicGraph controllerRef={...} />`.\n */\nexport interface SimplexGraphHandle<\n TItem = DefaultTaggedItem,\n TContentVisual = unknown,\n TClusterVisual = unknown,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n> {\n addItems(items: TItem | readonly TItem[]): void;\n removeItems(ids: string | readonly string[]): void;\n setItems(items: readonly TItem[]): void;\n resetCamera(): void;\n zoomBy(factor: number): void;\n getMetrics(): LayoutMetrics | null;\n getClusters(): readonly ClusterDescriptor<TItem, TTagMeta, TClusterMeta>[];\n getRawController(): SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null;\n}\n\n/**\n * React hook returning a stable `controllerRef` and imperative transaction helpers\n * (`addItems`, `removeItems`, `setItems`, camera controls, and live telemetry getters).\n */\nexport function useSimplexGraphController<\n TItem = DefaultTaggedItem,\n TContentVisual = unknown,\n TClusterVisual = unknown,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n>(): {\n readonly controllerRef: React.MutableRefObject<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>;\n readonly handle: SimplexGraphHandle<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >;\n} {\n const controllerRef = useRef<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>(null);\n\n const addItems = useCallback((items: TItem | readonly TItem[]) => {\n controllerRef.current?.addItems(items);\n }, []);\n\n const removeItems = useCallback((ids: string | readonly string[]) => {\n controllerRef.current?.removeItems(ids);\n }, []);\n\n const setItems = useCallback((items: readonly TItem[]) => {\n controllerRef.current?.setItems(items);\n }, []);\n\n const resetCamera = useCallback(() => {\n controllerRef.current?.camera.reset();\n }, []);\n\n const zoomBy = useCallback((factor: number) => {\n const ctrl = controllerRef.current;\n if (!ctrl) return;\n const svg = ctrl.getSvgElement();\n const rect = svg.getBoundingClientRect();\n const cam: CameraController = ctrl.camera;\n cam.zoomToCursor(rect.width / 2, rect.height / 2, factor);\n }, []);\n\n const getMetrics = useCallback(() => {\n return controllerRef.current?.getMetrics() ?? null;\n }, []);\n\n const getClusters = useCallback(() => {\n return controllerRef.current?.getClusters() ?? [];\n }, []);\n\n const getRawController = useCallback(() => {\n return controllerRef.current;\n }, []);\n\n return {\n controllerRef,\n handle: {\n addItems,\n removeItems,\n setItems,\n resetCamera,\n zoomBy,\n getMetrics,\n getClusters,\n getRawController,\n },\n };\n}\n","import type {\n ClusterDescriptor,\n ClusterHoverEvent,\n ClusterMetaConfig,\n ContentHoverEvent,\n ContentLayoutContext,\n DefaultTaggedItem,\n HitTarget,\n ItemIdentityConfig,\n LayoutMetrics,\n LayoutSolverOptions,\n MeshOptions,\n NodeRenderState,\n NormalizedPointerEvent,\n VisualResolver,\n WheelBehavior,\n} from '@simplex-viz/core';\nimport {\n SimplexSvgController,\n createPresetViews,\n createPresetVisualResolver,\n extractDefaultItemLabel,\n type DefaultClusterPresetVisual,\n type DefaultContentPresetVisual,\n type SimplexVisualPreset,\n type SvgNodeView,\n} from '@simplex-viz/svg';\nimport {\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport {\n ReactJsxSvgView,\n type ContentDomainRecord,\n} from './ReactJsxSvgView';\n\n/**\n * Union payload passed to a custom React `tooltip` formatter on `<SimplexTopicGraph />`.\n */\nexport type SimplexReactTooltipTarget<\n TItem = DefaultTaggedItem,\n TContentVisual = DefaultContentPresetVisual,\n TClusterVisual = DefaultClusterPresetVisual,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n> =\n | ({ readonly kind: 'content' } & ContentHoverEvent<\n TItem,\n TContentVisual,\n TTagMeta,\n TClusterMeta\n >)\n | ({ readonly kind: 'cluster' } & ClusterHoverEvent<\n TItem,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >);\n\n/**\n * Props for `<SimplexTopicGraph />`, preserving end-to-end generic inference across\n * `TItem`, `TContentVisual`, `TClusterVisual`, `TTagMeta`, and `TClusterMeta`.\n *\n * Works zero-config with `<SimplexTopicGraph items={items} />` via built-in presets,\n * or with keyless declarative JSX renderers (`renderContentNode` / `renderClusterNode`),\n * or with full `VisualResolver` + `SvgNodeView` customization.\n */\nexport type SimplexTopicGraphProps<\n TItem = DefaultTaggedItem,\n TContentVisual = DefaultContentPresetVisual,\n TClusterVisual = DefaultClusterPresetVisual,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n> = ItemIdentityConfig<TItem> &\n ClusterMetaConfig<TItem, TTagMeta, TClusterMeta> & {\n readonly items: readonly TItem[];\n /** Built-in visual preset used when custom views / `visualResolver` are omitted. Default: `'geometric'`. */\n readonly preset?: SimplexVisualPreset;\n /** Optional label extractor for built-in presets and default hover tooltips. */\n readonly getLabel?: (item: TItem) => string;\n /**\n * Optional `VisualResolver` mapping items and clusters to pure visual descriptors.\n * Optional in both zero-config preset mode and declarative JSX renderer mode.\n */\n readonly visualResolver?: VisualResolver<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >;\n /** Optional cache key override when using `renderContentNode` without `visualResolver`. */\n readonly getContentCacheKey?: (\n item: TItem,\n ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>,\n ) => string;\n /** Optional cache key override when using `renderClusterNode` without `visualResolver`. */\n readonly getClusterCacheKey?: (\n cluster: ClusterDescriptor<TItem, TTagMeta, TClusterMeta>,\n ) => string;\n /** Portable `@simplex-viz/svg` view plugin for content items. */\n readonly contentView?: SvgNodeView<TContentVisual>;\n /** Portable `@simplex-viz/svg` view plugin for topic clusters. */\n readonly clusterView?: SvgNodeView<TClusterVisual>;\n /** Optional declarative React JSX renderer for content items (auto-measured via `getBBox()`). */\n readonly renderContentNode?: (\n item: TItem,\n ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TContentVisual>,\n ) => ReactNode;\n /** Optional declarative React JSX renderer for topic clusters (auto-measured via `getBBox()`). */\n readonly renderClusterNode?: (\n cluster: ClusterDescriptor<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TClusterVisual>,\n ) => ReactNode;\n readonly normalizeTag?: (rawTag: string) => string;\n readonly resolveTagMeta?: (normalizedTag: string) => TTagMeta | undefined;\n readonly meshOptions?: MeshOptions;\n readonly layoutOptions?: LayoutSolverOptions;\n readonly sizeMultiplier?: number;\n readonly showHulls?: boolean;\n readonly pinnedIds?: ReadonlySet<string> | readonly string[];\n readonly highlightedIds?: ReadonlySet<string> | readonly string[];\n readonly focusedClusterUid?: string | null;\n /**\n * Enables built-in cluster focus toggle on click when `focusedClusterUid` and `onLeftClick`\n * are not controlled externally. Default: `true`.\n */\n readonly focusOnClusterClick?: boolean;\n /**\n * Enables a built-in floating hover tooltip, or accepts a custom `(target) => ReactNode` formatter.\n * Default: `false`.\n */\n readonly tooltip?:\n | boolean\n | ((\n target: SimplexReactTooltipTarget<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >,\n ) => ReactNode);\n readonly onContentHover?: (\n event: ContentHoverEvent<TItem, TContentVisual, TTagMeta, TClusterMeta> | null,\n ) => void;\n readonly onClusterHover?: (\n event: ClusterHoverEvent<TItem, TClusterVisual, TTagMeta, TClusterMeta> | null,\n ) => void;\n readonly onLeftClick?: (\n target: HitTarget<TItem, TContentVisual, TClusterVisual, TTagMeta, TClusterMeta>,\n rawEvent: NormalizedPointerEvent,\n ) => void;\n readonly onRightClick?: (\n target: HitTarget<TItem, TContentVisual, TClusterVisual, TTagMeta, TClusterMeta>,\n rawEvent: NormalizedPointerEvent,\n ) => boolean | void;\n readonly onWheel?: WheelBehavior;\n readonly onMetricsChange?: (metrics: LayoutMetrics) => void;\n readonly onClustersChange?: (\n clusters: readonly ClusterDescriptor<TItem, TTagMeta, TClusterMeta>[],\n ) => void;\n readonly onFpsUpdate?: (fps: number) => void;\n readonly controllerRef?: MutableRefObject<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>;\n readonly className?: string;\n readonly style?: CSSProperties;\n };\n\ninterface AutoKeyVisual {\n readonly __svAutoKey: string;\n}\n\nfunction isAutoKeyVisual(v: unknown): v is AutoKeyVisual {\n return (\n typeof v === 'object' &&\n v !== null &&\n '__svAutoKey' in v &&\n typeof (v as AutoKeyVisual).__svAutoKey === 'string'\n );\n}\n\n/**\n * Type-safe React visualization component wrapping `@simplex-viz/core` and `@simplex-viz/svg`.\n */\nexport function SimplexTopicGraph<\n TItem = DefaultTaggedItem,\n TContentVisual = DefaultContentPresetVisual,\n TClusterVisual = DefaultClusterPresetVisual,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n>(\n props: SimplexTopicGraphProps<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >,\n) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const ctrlRef = useRef<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>(null);\n\n const [hoveredTarget, setHoveredTarget] = useState<SimplexReactTooltipTarget<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>(null);\n\n const internalFocusedUidRef = useRef<string | null>(null);\n\n const contentDomainByKeyRef = useRef(\n new Map<string, ContentDomainRecord<TItem, TTagMeta, TClusterMeta>>(),\n );\n const clusterDomainByKeyRef = useRef(\n new Map<string, ClusterDescriptor<TItem, TTagMeta, TClusterMeta>>(),\n );\n const jsxContentViewRef = useRef<ReactJsxSvgView<\n TContentVisual,\n ContentDomainRecord<TItem, TTagMeta, TClusterMeta>\n > | null>(null);\n const jsxClusterViewRef = useRef<ReactJsxSvgView<\n TClusterVisual,\n ClusterDescriptor<TItem, TTagMeta, TClusterMeta>\n > | null>(null);\n\n const latestPropsRef = useRef(props);\n latestPropsRef.current = props;\n\n const resolveEffectiveResolver = (): VisualResolver<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > => {\n const p = latestPropsRef.current;\n const preset: SimplexVisualPreset = p.preset ?? 'geometric';\n const presetResolver = createPresetVisualResolver<TItem, TTagMeta, TClusterMeta>(\n preset,\n (item) => {\n const curGetLabel = latestPropsRef.current.getLabel;\n if (curGetLabel) return curGetLabel(item);\n if (typeof item === 'object' && item !== null) {\n if ('label' in item && typeof item.label === 'string' && item.label.length > 0) {\n return item.label;\n }\n if ('title' in item && typeof item.title === 'string' && item.title.length > 0) {\n return item.title;\n }\n if ('headline' in item && typeof item.headline === 'string' && item.headline.length > 0) {\n return item.headline;\n }\n if ('name' in item && typeof item.name === 'string' && item.name.length > 0) {\n return item.name;\n }\n }\n return '';\n },\n );\n const base = p.visualResolver;\n\n const getKey = (visual: TContentVisual | TClusterVisual): string => {\n if (isAutoKeyVisual(visual)) {\n return visual.__svAutoKey;\n }\n if (base) {\n return base.getVisualCacheKey(visual);\n }\n return presetResolver.getVisualCacheKey(\n visual as unknown as DefaultContentPresetVisual | DefaultClusterPresetVisual,\n );\n };\n\n return {\n resolveContentVisual: (item, ctx) => {\n const cur = latestPropsRef.current;\n let visual: TContentVisual;\n if (base) {\n visual = base.resolveContentVisual(item, ctx);\n } else if (cur.renderContentNode) {\n const autoKey = cur.getContentCacheKey\n ? cur.getContentCacheKey(item, ctx)\n : `${ctx.id}:${ctx.mixedColorHex}:${ctx.tags.map((t) => t.tag).join(',')}`;\n visual = { __svAutoKey: autoKey } as unknown as TContentVisual;\n } else {\n visual = presetResolver.resolveContentVisual(item, ctx) as unknown as TContentVisual;\n }\n const key = getKey(visual);\n contentDomainByKeyRef.current.set(key, { item, ctx });\n return visual;\n },\n resolveClusterVisual: (cluster) => {\n const cur = latestPropsRef.current;\n let visual: TClusterVisual;\n if (base) {\n visual = base.resolveClusterVisual(cluster);\n } else if (cur.renderClusterNode) {\n const autoKey = cur.getClusterCacheKey\n ? cur.getClusterCacheKey(cluster)\n : `${cluster.clusterUid}:${cluster.defaultLabel}:${cluster.members.length}:${cluster.colorHex}`;\n visual = { __svAutoKey: autoKey } as unknown as TClusterVisual;\n } else {\n visual = presetResolver.resolveClusterVisual(cluster) as unknown as TClusterVisual;\n }\n const key = getKey(visual);\n clusterDomainByKeyRef.current.set(key, cluster);\n return visual;\n },\n getVisualCacheKey: getKey,\n };\n };\n\n const resolveActiveViews = (\n activeResolver: VisualResolver<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >,\n ): {\n contentView: SvgNodeView<TContentVisual>;\n clusterView: SvgNodeView<TClusterVisual>;\n } => {\n const p = latestPropsRef.current;\n const presetViews = createPresetViews(p.preset ?? 'geometric');\n\n let contentView: SvgNodeView<TContentVisual>;\n if (p.renderContentNode) {\n const renderFn = p.renderContentNode;\n jsxContentViewRef.current?.dispose();\n const jsxView = new ReactJsxSvgView<\n TContentVisual,\n ContentDomainRecord<TItem, TTagMeta, TClusterMeta>\n >({\n renderFn: (domain, state) => renderFn(domain.item, domain.ctx, state),\n getKey: (v) => activeResolver.getVisualCacheKey(v),\n domainByKey: contentDomainByKeyRef.current,\n });\n jsxContentViewRef.current = jsxView;\n contentView = jsxView;\n } else if (p.contentView) {\n jsxContentViewRef.current?.dispose();\n jsxContentViewRef.current = null;\n contentView = p.contentView;\n } else {\n jsxContentViewRef.current?.dispose();\n jsxContentViewRef.current = null;\n contentView = presetViews.contentView as unknown as SvgNodeView<TContentVisual>;\n }\n\n let clusterView: SvgNodeView<TClusterVisual>;\n if (p.renderClusterNode) {\n const renderFn = p.renderClusterNode;\n jsxClusterViewRef.current?.dispose();\n const jsxView = new ReactJsxSvgView<\n TClusterVisual,\n ClusterDescriptor<TItem, TTagMeta, TClusterMeta>\n >({\n renderFn: (cluster, state) => renderFn(cluster, state),\n getKey: (v) => activeResolver.getVisualCacheKey(v),\n domainByKey: clusterDomainByKeyRef.current,\n });\n jsxClusterViewRef.current = jsxView;\n clusterView = jsxView;\n } else if (p.clusterView) {\n jsxClusterViewRef.current?.dispose();\n jsxClusterViewRef.current = null;\n clusterView = p.clusterView;\n } else {\n jsxClusterViewRef.current?.dispose();\n jsxClusterViewRef.current = null;\n clusterView = presetViews.clusterView as unknown as SvgNodeView<TClusterVisual>;\n }\n\n return { contentView, clusterView };\n };\n\n // Mount controller once on container\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const p = latestPropsRef.current;\n const effectiveResolver = resolveEffectiveResolver();\n const { contentView, clusterView } = resolveActiveViews(effectiveResolver);\n\n const ctrl = SimplexSvgController.createFromResolved(el, {\n items: p.items,\n getId: p.getId,\n getTags: p.getTags,\n getLabel: p.getLabel,\n deriveClusterMeta: p.deriveClusterMeta,\n preset: p.preset,\n visualResolver: effectiveResolver,\n contentView,\n clusterView,\n normalizeTag: p.normalizeTag,\n resolveTagMeta: p.resolveTagMeta,\n meshOptions: p.meshOptions,\n layoutOptions: {\n ...p.layoutOptions,\n sizeMultiplier: p.sizeMultiplier ?? p.layoutOptions?.sizeMultiplier ?? 1,\n },\n showHulls: p.showHulls,\n focusOnClusterClick: false,\n interactions: {\n onContentHover: (ev) => {\n latestPropsRef.current.onContentHover?.(ev);\n if (latestPropsRef.current.tooltip) {\n setHoveredTarget(ev ? { kind: 'content', ...ev } : null);\n }\n },\n onClusterHover: (ev) => {\n latestPropsRef.current.onClusterHover?.(ev);\n if (latestPropsRef.current.tooltip) {\n setHoveredTarget(ev ? { kind: 'cluster', ...ev } : null);\n }\n },\n onLeftClick: (target, raw) => {\n const cur = latestPropsRef.current;\n if (cur.onLeftClick) {\n cur.onLeftClick(target, raw);\n return;\n }\n if (cur.focusedClusterUid === undefined && (cur.focusOnClusterClick ?? true)) {\n if (target.kind === 'cluster') {\n const next =\n internalFocusedUidRef.current === target.cluster.clusterUid\n ? null\n : target.cluster.clusterUid;\n internalFocusedUidRef.current = next;\n ctrlRef.current?.setFocusedClusterUid(next);\n } else if (\n target.kind === 'background' &&\n internalFocusedUidRef.current !== null\n ) {\n internalFocusedUidRef.current = null;\n ctrlRef.current?.setFocusedClusterUid(null);\n }\n }\n },\n onRightClick: (t, raw) => latestPropsRef.current.onRightClick?.(t, raw),\n onWheel: (ev, cam) => {\n const policy = latestPropsRef.current.onWheel ?? 'zoom-to-cursor';\n if (policy === 'none') return;\n if (typeof policy === 'function') {\n policy(ev, cam);\n return;\n }\n if (policy === 'pan-vertical') {\n cam.panBy(-ev.deltaX, -ev.deltaY);\n return;\n }\n const factor = Math.exp(-ev.deltaY * 0.0014);\n cam.zoomToCursor(ev.screenX, ev.screenY, factor);\n },\n },\n onMetricsChange: (m) => latestPropsRef.current.onMetricsChange?.(m),\n onClustersChange: (c) => latestPropsRef.current.onClustersChange?.(c),\n onFpsUpdate: (fps) => latestPropsRef.current.onFpsUpdate?.(fps),\n });\n ctrlRef.current = ctrl;\n if (p.controllerRef) {\n p.controllerRef.current = ctrl;\n }\n\n return () => {\n ctrl.destroy();\n ctrlRef.current = null;\n if (latestPropsRef.current.controllerRef) {\n latestPropsRef.current.controllerRef.current = null;\n }\n jsxContentViewRef.current?.dispose();\n jsxClusterViewRef.current?.dispose();\n jsxContentViewRef.current = null;\n jsxClusterViewRef.current = null;\n };\n }, []);\n\n // Sync items\n useEffect(() => {\n ctrlRef.current?.setItems(props.items);\n }, [props.items]);\n\n // Sync views, presets & visual resolver (triggers smooth crossfade / morph!)\n useEffect(() => {\n const ctrl = ctrlRef.current;\n if (!ctrl) return;\n const effectiveResolver = resolveEffectiveResolver();\n const { contentView, clusterView } = resolveActiveViews(effectiveResolver);\n ctrl.setViews({ contentView, clusterView });\n ctrl.setVisualResolver(effectiveResolver);\n }, [\n props.preset,\n props.visualResolver,\n props.contentView,\n props.clusterView,\n props.renderContentNode,\n props.renderClusterNode,\n ]);\n\n // Sync sizeMultiplier\n useEffect(() => {\n if (props.sizeMultiplier !== undefined) {\n ctrlRef.current?.setSizeMultiplier(props.sizeMultiplier);\n }\n }, [props.sizeMultiplier]);\n\n // Sync showHulls\n useEffect(() => {\n if (props.showHulls !== undefined) {\n ctrlRef.current?.setShowHulls(props.showHulls);\n }\n }, [props.showHulls]);\n\n // Sync pinned / highlighted / focused cluster\n useEffect(() => {\n if (props.pinnedIds !== undefined) {\n ctrlRef.current?.setPinnedIds(props.pinnedIds);\n }\n }, [props.pinnedIds]);\n\n useEffect(() => {\n if (props.highlightedIds !== undefined) {\n ctrlRef.current?.setHighlightedIds(props.highlightedIds);\n }\n }, [props.highlightedIds]);\n\n useEffect(() => {\n if (props.focusedClusterUid !== undefined) {\n internalFocusedUidRef.current = props.focusedClusterUid;\n ctrlRef.current?.setFocusedClusterUid(props.focusedClusterUid);\n }\n }, [props.focusedClusterUid]);\n\n // Clear built-in tooltip if prop toggled off\n useEffect(() => {\n if (!props.tooltip) {\n setHoveredTarget(null);\n }\n }, [props.tooltip]);\n\n const renderBuiltInTooltip = () => {\n if (!props.tooltip || !hoveredTarget) return null;\n\n const containerW = containerRef.current?.clientWidth || 960;\n const containerH = containerRef.current?.clientHeight || 600;\n const left = Math.min(\n Math.max(8, Math.round(hoveredTarget.screenPosition.x + 14)),\n Math.max(8, containerW - 256),\n );\n const top = Math.min(\n Math.max(8, Math.round(hoveredTarget.screenPosition.y + 14)),\n Math.max(8, containerH - 80),\n );\n\n const content =\n typeof props.tooltip === 'function' ? (\n props.tooltip(hoveredTarget)\n ) : hoveredTarget.kind === 'content' ? (\n <div>\n <div style={{ fontWeight: 600, color: '#f8fafc' }}>\n {extractDefaultItemLabel(\n hoveredTarget.item,\n hoveredTarget.layoutContext.id,\n props.getLabel,\n )}\n </div>\n {hoveredTarget.layoutContext.tags.length > 0 && (\n <div style={{ marginTop: 3, fontSize: 11, color: '#94a3b8' }}>\n {hoveredTarget.layoutContext.tags\n .map((t) => `#${t.tag}`)\n .slice(0, 5)\n .join(' · ')}\n </div>\n )}\n </div>\n ) : (\n <div>\n <div style={{ fontWeight: 600, color: hoveredTarget.cluster.colorHex }}>\n {`${hoveredTarget.cluster.code} · ${hoveredTarget.cluster.defaultLabel}`}\n </div>\n <div style={{ marginTop: 3, fontSize: 11, color: '#94a3b8' }}>\n {`${hoveredTarget.cluster.members.length} ${\n hoveredTarget.cluster.members.length === 1 ? 'item' : 'items'\n }`}\n </div>\n </div>\n );\n\n return (\n <div\n role=\"tooltip\"\n style={{\n position: 'absolute',\n left,\n top,\n zIndex: 20,\n maxWidth: 244,\n padding: '7px 10px',\n borderRadius: 8,\n background: 'rgba(9, 13, 22, 0.94)',\n border: '1px solid rgba(51, 65, 85, 0.85)',\n color: '#f1f5f9',\n fontSize: 12,\n lineHeight: 1.4,\n pointerEvents: 'none',\n boxShadow: '0 10px 24px rgba(0, 0, 0, 0.45)',\n }}\n >\n {content}\n </div>\n );\n };\n\n return (\n <div\n ref={containerRef}\n className={props.className}\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n ...props.style,\n }}\n >\n {renderBuiltInTooltip()}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/ReactJsxSvgView.ts","../src/useSimplexGraphController.ts","../src/SimplexTopicGraph.tsx"],"names":["jsx","useRef"],"mappings":"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","file":"index.js","sourcesContent":["import {\n rectToConvexPolygon,\n type ClusterDescriptor,\n type ContentLayoutContext,\n type ConvexGeometry,\n type NodeRenderState,\n} from '@simplex-viz/core';\nimport { SVG_NS, type SvgNodeView } from '@simplex-viz/svg';\nimport type { ReactNode } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport { renderToStaticMarkup } from 'react-dom/server';\n\nexport interface ContentDomainRecord<TItem, TTagMeta, TClusterMeta> {\n readonly item: TItem;\n readonly ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>;\n}\n\n/**\n * Bridges a declarative React JSX render function into an `@simplex-viz/svg` `SvgNodeView`\n * with automatic offscreen `getBBox()` convex hull measurement and cached DOM updates.\n */\nexport class ReactJsxSvgView<TVisual, TDomain> implements SvgNodeView<TVisual> {\n private readonly renderFn: (\n domain: TDomain,\n state: NodeRenderState<TVisual>,\n ) => ReactNode;\n private readonly getKey: (visual: TVisual) => string;\n private readonly domainByKey: ReadonlyMap<string, TDomain>;\n private readonly rootsByGroup = new WeakMap<SVGGElement, Root>();\n private readonly activeRoots = new Set<Root>();\n private measureGroup: SVGGElement | null = null;\n\n constructor(params: {\n readonly renderFn: (domain: TDomain, state: NodeRenderState<TVisual>) => ReactNode;\n readonly getKey: (visual: TVisual) => string;\n readonly domainByKey: ReadonlyMap<string, TDomain>;\n }) {\n this.renderFn = params.renderFn;\n this.getKey = params.getKey;\n this.domainByKey = params.domainByKey;\n }\n\n measureConvexHull(visual: TVisual, measureSvg: SVGSVGElement): ConvexGeometry {\n const key = this.getKey(visual);\n const domain = this.domainByKey.get(key);\n if (!domain) {\n return rectToConvexPolygon(48, 28, 6);\n }\n\n const doc = measureSvg.ownerDocument;\n let bin = measureSvg.querySelector<SVGGElement>('g.sv-measure-bin');\n if (!bin) {\n bin = doc.createElementNS(SVG_NS, 'g');\n bin.setAttribute('class', 'sv-measure-bin');\n bin.setAttribute('visibility', 'hidden');\n bin.setAttribute('pointer-events', 'none');\n bin.setAttribute('transform', 'translate(-99999, -99999)');\n measureSvg.appendChild(bin);\n }\n\n if (!this.measureGroup || this.measureGroup.parentNode !== bin) {\n this.measureGroup = doc.createElementNS(SVG_NS, 'g');\n bin.appendChild(this.measureGroup);\n }\n\n const dummyState: NodeRenderState<TVisual> = {\n id: '__measure__',\n x: 0,\n y: 0,\n scale: 1,\n opacity: 1,\n visual,\n hull: { kind: 'circle', radius: 16 },\n cacheKey: key,\n interaction: {\n isHovered: false,\n isPinned: false,\n isDimmed: false,\n isHighlighted: false,\n },\n transition: null,\n };\n\n const jsx = this.renderFn(domain, dummyState);\n const markup = renderToStaticMarkup(jsx);\n // Parse JSX markup into SVG namespace inside the offscreen measurement group\n const wrapperSvg = doc.createElementNS(SVG_NS, 'svg');\n wrapperSvg.innerHTML = markup;\n while (this.measureGroup.firstChild) {\n this.measureGroup.removeChild(this.measureGroup.firstChild);\n }\n while (wrapperSvg.firstChild) {\n this.measureGroup.appendChild(wrapperSvg.firstChild);\n }\n\n let width = 0;\n let height = 0;\n try {\n if (typeof this.measureGroup.getBBox === 'function') {\n const bbox = this.measureGroup.getBBox();\n width = bbox.width;\n height = bbox.height;\n }\n } catch {\n // Headless DOM without layout engine\n }\n\n if (width <= 1 || height <= 1) {\n let maxHalfW = 0;\n let maxHalfH = 0;\n this.measureGroup.querySelectorAll('rect, circle, text').forEach((el) => {\n const tag = el.tagName.toLowerCase();\n if (tag === 'rect') {\n const w = parseFloat(el.getAttribute('width') ?? '0');\n const h = parseFloat(el.getAttribute('height') ?? '0');\n maxHalfW = Math.max(maxHalfW, w / 2);\n maxHalfH = Math.max(maxHalfH, h / 2);\n } else if (tag === 'circle') {\n const r = parseFloat(el.getAttribute('r') ?? '0');\n maxHalfW = Math.max(maxHalfW, r);\n maxHalfH = Math.max(maxHalfH, r);\n } else if (tag === 'text') {\n const len = (el.textContent ?? '').length;\n const fs = parseFloat(el.getAttribute('font-size') ?? '11');\n maxHalfW = Math.max(maxHalfW, (len * fs * 0.56) / 2);\n maxHalfH = Math.max(maxHalfH, fs * 0.75);\n }\n });\n width = Math.max(24, maxHalfW * 2);\n height = Math.max(20, maxHalfH * 2);\n }\n\n return rectToConvexPolygon(width + 4, height + 4, 6);\n }\n\n mountOrUpdate(\n groupEl: SVGGElement,\n visual: TVisual,\n state: NodeRenderState<TVisual>,\n ): void {\n const key = this.getKey(visual);\n const domain = this.domainByKey.get(key);\n if (!domain) return;\n\n let root = this.rootsByGroup.get(groupEl);\n if (!root) {\n while (groupEl.firstChild) groupEl.removeChild(groupEl.firstChild);\n root = createRoot(groupEl);\n this.rootsByGroup.set(groupEl, root);\n this.activeRoots.add(root);\n }\n\n root.render(this.renderFn(domain, state));\n }\n\n dispose(): void {\n const roots = [...this.activeRoots];\n this.activeRoots.clear();\n this.measureGroup = null;\n queueMicrotask(() => {\n for (const r of roots) {\n r.unmount();\n }\n });\n }\n}\n\nexport type ContentJsxRenderFn<TItem, TContentVisual, TTagMeta, TClusterMeta> = (\n item: TItem,\n ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TContentVisual>,\n) => ReactNode;\n\nexport type ClusterJsxRenderFn<TItem, TClusterVisual, TTagMeta, TClusterMeta> = (\n cluster: ClusterDescriptor<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TClusterVisual>,\n) => ReactNode;\n","import type {\n CameraController,\n ClusterDescriptor,\n DefaultTaggedItem,\n LayoutMetrics,\n SimplexClusteringStrategy,\n SimplexColorStrategy,\n SimplexLayoutStrategy,\n SimplexMeshStrategy,\n} from '@simplex-viz/core';\nimport type { SimplexSvgController } from '@simplex-viz/svg';\nimport { useCallback, useRef } from 'react';\n\n/**\n * Imperative handle bound to `<SimplexTopicGraph controllerRef={...} />`.\n */\nexport interface SimplexGraphHandle<\n TItem = DefaultTaggedItem,\n TContentVisual = unknown,\n TClusterVisual = unknown,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n> {\n addItems(items: TItem | readonly TItem[]): void;\n removeItems(ids: string | readonly string[]): void;\n setItems(items: readonly TItem[]): void;\n setMeshStrategy(strategy: SimplexMeshStrategy<TItem>): void;\n setClusteringStrategy(strategy: SimplexClusteringStrategy<TItem, TTagMeta>): void;\n setColorStrategy(strategy: SimplexColorStrategy<TItem, TTagMeta>): void;\n setLayoutStrategy(strategy: SimplexLayoutStrategy): void;\n resetCamera(): void;\n zoomBy(factor: number): void;\n getMetrics(): LayoutMetrics | null;\n getClusters(): readonly ClusterDescriptor<TItem, TTagMeta, TClusterMeta>[];\n getRawController(): SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null;\n}\n\n/**\n * React hook returning a stable `controllerRef` and imperative transaction helpers\n * (`addItems`, `removeItems`, `setItems`, strategy setters, camera controls, and live telemetry getters).\n */\nexport function useSimplexGraphController<\n TItem = DefaultTaggedItem,\n TContentVisual = unknown,\n TClusterVisual = unknown,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n>(): {\n readonly controllerRef: React.MutableRefObject<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>;\n readonly handle: SimplexGraphHandle<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >;\n} {\n const controllerRef = useRef<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>(null);\n\n const addItems = useCallback((items: TItem | readonly TItem[]) => {\n controllerRef.current?.addItems(items);\n }, []);\n\n const removeItems = useCallback((ids: string | readonly string[]) => {\n controllerRef.current?.removeItems(ids);\n }, []);\n\n const setItems = useCallback((items: readonly TItem[]) => {\n controllerRef.current?.setItems(items);\n }, []);\n\n const setMeshStrategy = useCallback((strategy: SimplexMeshStrategy<TItem>) => {\n controllerRef.current?.setMeshStrategy(strategy);\n }, []);\n\n const setClusteringStrategy = useCallback(\n (strategy: SimplexClusteringStrategy<TItem, TTagMeta>) => {\n controllerRef.current?.setClusteringStrategy(strategy);\n },\n [],\n );\n\n const setColorStrategy = useCallback(\n (strategy: SimplexColorStrategy<TItem, TTagMeta>) => {\n controllerRef.current?.setColorStrategy(strategy);\n },\n [],\n );\n\n const setLayoutStrategy = useCallback((strategy: SimplexLayoutStrategy) => {\n controllerRef.current?.setLayoutStrategy(strategy);\n }, []);\n\n const resetCamera = useCallback(() => {\n controllerRef.current?.camera.reset();\n }, []);\n\n const zoomBy = useCallback((factor: number) => {\n const ctrl = controllerRef.current;\n if (!ctrl) return;\n const svg = ctrl.getSvgElement();\n const rect = svg.getBoundingClientRect();\n const width = rect.width > 0 ? rect.width : svg.clientWidth || 960;\n const height = rect.height > 0 ? rect.height : svg.clientHeight || 620;\n const cam: CameraController = ctrl.camera;\n cam.zoomToCursor(width / 2, height / 2, factor);\n }, []);\n\n const getMetrics = useCallback(() => {\n return controllerRef.current?.getMetrics() ?? null;\n }, []);\n\n const getClusters = useCallback(() => {\n return controllerRef.current?.getClusters() ?? [];\n }, []);\n\n const getRawController = useCallback(() => {\n return controllerRef.current;\n }, []);\n\n return {\n controllerRef,\n handle: {\n addItems,\n removeItems,\n setItems,\n setMeshStrategy,\n setClusteringStrategy,\n setColorStrategy,\n setLayoutStrategy,\n resetCamera,\n zoomBy,\n getMetrics,\n getClusters,\n getRawController,\n },\n };\n}\n","import type {\n ClusterDescriptor,\n ClusterHoverEvent,\n ClusterMetaConfig,\n ContentHoverEvent,\n ContentLayoutContext,\n DefaultTaggedItem,\n HitTarget,\n ItemIdentityConfig,\n LayoutMetrics,\n LayoutSolverOptions,\n MeshOptions,\n NodeRenderState,\n NormalizedPointerEvent,\n SimplexClusteringStrategy,\n SimplexColorStrategy,\n SimplexLayoutStrategy,\n SimplexMeshStrategy,\n VisualResolver,\n WheelBehavior,\n} from '@simplex-viz/core';\nimport {\n SimplexSvgController,\n createPresetViews,\n createPresetVisualResolver,\n extractDefaultItemLabel,\n type DefaultClusterPresetVisual,\n type DefaultContentPresetVisual,\n type SimplexTheme,\n type SimplexVisualPreset,\n type SvgNodeView,\n} from '@simplex-viz/svg';\nimport {\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type MutableRefObject,\n type ReactNode,\n} from 'react';\nimport {\n ReactJsxSvgView,\n type ContentDomainRecord,\n} from './ReactJsxSvgView';\n\n/**\n * Union payload passed to a custom React `tooltip` formatter on `<SimplexTopicGraph />`.\n */\nexport type SimplexReactTooltipTarget<\n TItem = DefaultTaggedItem,\n TContentVisual = DefaultContentPresetVisual,\n TClusterVisual = DefaultClusterPresetVisual,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n> =\n | ({ readonly kind: 'content' } & ContentHoverEvent<\n TItem,\n TContentVisual,\n TTagMeta,\n TClusterMeta\n >)\n | ({ readonly kind: 'cluster' } & ClusterHoverEvent<\n TItem,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >);\n\n/**\n * Props for `<SimplexTopicGraph />`, preserving end-to-end generic inference across\n * `TItem`, `TContentVisual`, `TClusterVisual`, `TTagMeta`, and `TClusterMeta`.\n *\n * Works zero-config with `<SimplexTopicGraph items={items} />` via built-in presets,\n * or with keyless declarative JSX renderers (`renderContentNode` / `renderClusterNode`),\n * or with full `VisualResolver` + `SvgNodeView` customization.\n */\nexport type SimplexTopicGraphProps<\n TItem = DefaultTaggedItem,\n TContentVisual = DefaultContentPresetVisual,\n TClusterVisual = DefaultClusterPresetVisual,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n> = ItemIdentityConfig<TItem> &\n ClusterMetaConfig<TItem, TTagMeta, TClusterMeta> & {\n readonly items: readonly TItem[];\n /** Built-in visual preset used when custom views / `visualResolver` are omitted. Default: `'geometric'`. */\n readonly preset?: SimplexVisualPreset;\n /** Visual color theme (`'dark'` or `'light'`) for built-in presets and tooltips. Default: `'dark'`. */\n readonly theme?: SimplexTheme;\n /** Optional label extractor for built-in presets and default hover tooltips. */\n readonly getLabel?: (item: TItem) => string;\n /**\n * Optional `VisualResolver` mapping items and clusters to pure visual descriptors.\n * Optional in both zero-config preset mode and declarative JSX renderer mode.\n */\n readonly visualResolver?: VisualResolver<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >;\n /** Optional cache key override when using `renderContentNode` without `visualResolver`. */\n readonly getContentCacheKey?: (\n item: TItem,\n ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>,\n ) => string;\n /** Optional cache key override when using `renderClusterNode` without `visualResolver`. */\n readonly getClusterCacheKey?: (\n cluster: ClusterDescriptor<TItem, TTagMeta, TClusterMeta>,\n ) => string;\n /** Portable `@simplex-viz/svg` view plugin for content items. */\n readonly contentView?: SvgNodeView<TContentVisual>;\n /** Portable `@simplex-viz/svg` view plugin for topic clusters. */\n readonly clusterView?: SvgNodeView<TClusterVisual>;\n /** Optional declarative React JSX renderer for content items (auto-measured via `getBBox()`). */\n readonly renderContentNode?: (\n item: TItem,\n ctx: ContentLayoutContext<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TContentVisual>,\n ) => ReactNode;\n /** Optional declarative React JSX renderer for topic clusters (auto-measured via `getBBox()`). */\n readonly renderClusterNode?: (\n cluster: ClusterDescriptor<TItem, TTagMeta, TClusterMeta>,\n state: NodeRenderState<TClusterVisual>,\n ) => ReactNode;\n readonly normalizeTag?: (rawTag: string) => string;\n readonly resolveTagMeta?: (normalizedTag: string) => TTagMeta | undefined;\n readonly meshOptions?: MeshOptions;\n readonly layoutOptions?: LayoutSolverOptions;\n /** Optional custom mesh/triangulation strategy. */\n readonly meshStrategy?: SimplexMeshStrategy<TItem>;\n /** Optional custom topic clustering & vertex assignment strategy. */\n readonly clusteringStrategy?: SimplexClusteringStrategy<TItem, TTagMeta>;\n /** Optional custom cluster coloring & item color-mixing strategy. */\n readonly colorStrategy?: SimplexColorStrategy<TItem, TTagMeta>;\n /** Optional custom node positioning & scaling strategy. */\n readonly layoutStrategy?: SimplexLayoutStrategy;\n readonly sizeMultiplier?: number;\n readonly showHulls?: boolean;\n readonly pinnedIds?: ReadonlySet<string> | readonly string[];\n readonly highlightedIds?: ReadonlySet<string> | readonly string[];\n readonly focusedClusterUid?: string | null;\n /**\n * Enables built-in cluster focus toggle on click when `focusedClusterUid` and `onLeftClick`\n * are not controlled externally. Default: `true`.\n */\n readonly focusOnClusterClick?: boolean;\n /**\n * Enables a built-in floating hover tooltip, or accepts a custom `(target) => ReactNode` formatter.\n * Default: `false`.\n */\n readonly tooltip?:\n | boolean\n | ((\n target: SimplexReactTooltipTarget<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >,\n ) => ReactNode);\n readonly onContentHover?: (\n event: ContentHoverEvent<TItem, TContentVisual, TTagMeta, TClusterMeta> | null,\n ) => void;\n readonly onClusterHover?: (\n event: ClusterHoverEvent<TItem, TClusterVisual, TTagMeta, TClusterMeta> | null,\n ) => void;\n readonly onLeftClick?: (\n target: HitTarget<TItem, TContentVisual, TClusterVisual, TTagMeta, TClusterMeta>,\n rawEvent: NormalizedPointerEvent,\n ) => void;\n readonly onRightClick?: (\n target: HitTarget<TItem, TContentVisual, TClusterVisual, TTagMeta, TClusterMeta>,\n rawEvent: NormalizedPointerEvent,\n ) => boolean | void;\n readonly onWheel?: WheelBehavior;\n readonly onMetricsChange?: (metrics: LayoutMetrics) => void;\n readonly onClustersChange?: (\n clusters: readonly ClusterDescriptor<TItem, TTagMeta, TClusterMeta>[],\n ) => void;\n readonly onFpsUpdate?: (fps: number) => void;\n readonly controllerRef?: MutableRefObject<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>;\n readonly className?: string;\n readonly style?: CSSProperties;\n };\n\ninterface AutoKeyVisual {\n readonly __svAutoKey: string;\n}\n\nfunction isAutoKeyVisual(v: unknown): v is AutoKeyVisual {\n return (\n typeof v === 'object' &&\n v !== null &&\n '__svAutoKey' in v &&\n typeof (v as AutoKeyVisual).__svAutoKey === 'string'\n );\n}\n\n/**\n * Type-safe React visualization component wrapping `@simplex-viz/core` and `@simplex-viz/svg`.\n */\nexport function SimplexTopicGraph<\n TItem = DefaultTaggedItem,\n TContentVisual = DefaultContentPresetVisual,\n TClusterVisual = DefaultClusterPresetVisual,\n TTagMeta = undefined,\n TClusterMeta = undefined,\n>(\n props: SimplexTopicGraphProps<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >,\n) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const ctrlRef = useRef<SimplexSvgController<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>(null);\n\n const [hoveredTarget, setHoveredTarget] = useState<SimplexReactTooltipTarget<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > | null>(null);\n\n const internalFocusedUidRef = useRef<string | null>(null);\n\n const contentDomainByKeyRef = useRef(\n new Map<string, ContentDomainRecord<TItem, TTagMeta, TClusterMeta>>(),\n );\n const clusterDomainByKeyRef = useRef(\n new Map<string, ClusterDescriptor<TItem, TTagMeta, TClusterMeta>>(),\n );\n const jsxContentViewRef = useRef<ReactJsxSvgView<\n TContentVisual,\n ContentDomainRecord<TItem, TTagMeta, TClusterMeta>\n > | null>(null);\n const jsxClusterViewRef = useRef<ReactJsxSvgView<\n TClusterVisual,\n ClusterDescriptor<TItem, TTagMeta, TClusterMeta>\n > | null>(null);\n\n const latestPropsRef = useRef(props);\n latestPropsRef.current = props;\n\n const syncedMeshStrategyRef = useRef(props.meshStrategy);\n const syncedClusteringStrategyRef = useRef(props.clusteringStrategy);\n const syncedColorStrategyRef = useRef(props.colorStrategy);\n const syncedLayoutStrategyRef = useRef(props.layoutStrategy);\n\n const resolveEffectiveResolver = (): VisualResolver<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n > => {\n const p = latestPropsRef.current;\n const preset: SimplexVisualPreset = p.preset ?? 'geometric';\n const theme: SimplexTheme = p.theme ?? 'dark';\n const presetResolver = createPresetVisualResolver<TItem, TTagMeta, TClusterMeta>(\n preset,\n (item) => {\n const curGetLabel = latestPropsRef.current.getLabel;\n if (curGetLabel) return curGetLabel(item);\n if (typeof item === 'object' && item !== null) {\n if ('label' in item && typeof item.label === 'string' && item.label.length > 0) {\n return item.label;\n }\n if ('title' in item && typeof item.title === 'string' && item.title.length > 0) {\n return item.title;\n }\n if ('headline' in item && typeof item.headline === 'string' && item.headline.length > 0) {\n return item.headline;\n }\n if ('name' in item && typeof item.name === 'string' && item.name.length > 0) {\n return item.name;\n }\n }\n return '';\n },\n theme,\n );\n const base = p.visualResolver;\n\n const getKey = (visual: TContentVisual | TClusterVisual): string => {\n if (isAutoKeyVisual(visual)) {\n return visual.__svAutoKey;\n }\n if (base) {\n return base.getVisualCacheKey(visual);\n }\n return presetResolver.getVisualCacheKey(\n visual as unknown as DefaultContentPresetVisual | DefaultClusterPresetVisual,\n );\n };\n\n return {\n resolveContentVisual: (item, ctx) => {\n const cur = latestPropsRef.current;\n let visual: TContentVisual;\n if (base) {\n visual = base.resolveContentVisual(item, ctx);\n } else if (cur.renderContentNode) {\n const autoKey = cur.getContentCacheKey\n ? cur.getContentCacheKey(item, ctx)\n : `${ctx.id}:${ctx.mixedColorHex}:${ctx.tags.map((t) => t.tag).join(',')}`;\n visual = { __svAutoKey: autoKey } as unknown as TContentVisual;\n } else {\n visual = presetResolver.resolveContentVisual(item, ctx) as unknown as TContentVisual;\n }\n const key = getKey(visual);\n contentDomainByKeyRef.current.set(key, { item, ctx });\n return visual;\n },\n resolveClusterVisual: (cluster) => {\n const cur = latestPropsRef.current;\n let visual: TClusterVisual;\n if (base) {\n visual = base.resolveClusterVisual(cluster);\n } else if (cur.renderClusterNode) {\n const autoKey = cur.getClusterCacheKey\n ? cur.getClusterCacheKey(cluster)\n : `${cluster.clusterUid}:${cluster.defaultLabel}:${cluster.members.length}:${cluster.colorHex}`;\n visual = { __svAutoKey: autoKey } as unknown as TClusterVisual;\n } else {\n visual = presetResolver.resolveClusterVisual(cluster) as unknown as TClusterVisual;\n }\n const key = getKey(visual);\n clusterDomainByKeyRef.current.set(key, cluster);\n return visual;\n },\n getVisualCacheKey: getKey,\n };\n };\n\n const resolveActiveViews = (\n activeResolver: VisualResolver<\n TItem,\n TContentVisual,\n TClusterVisual,\n TTagMeta,\n TClusterMeta\n >,\n ): {\n contentView: SvgNodeView<TContentVisual>;\n clusterView: SvgNodeView<TClusterVisual>;\n } => {\n const p = latestPropsRef.current;\n const presetViews = createPresetViews(p.preset ?? 'geometric');\n\n let contentView: SvgNodeView<TContentVisual>;\n if (p.renderContentNode) {\n const renderFn = p.renderContentNode;\n jsxContentViewRef.current?.dispose();\n const jsxView = new ReactJsxSvgView<\n TContentVisual,\n ContentDomainRecord<TItem, TTagMeta, TClusterMeta>\n >({\n renderFn: (domain, state) => renderFn(domain.item, domain.ctx, state),\n getKey: (v) => activeResolver.getVisualCacheKey(v),\n domainByKey: contentDomainByKeyRef.current,\n });\n jsxContentViewRef.current = jsxView;\n contentView = jsxView;\n } else if (p.contentView) {\n jsxContentViewRef.current?.dispose();\n jsxContentViewRef.current = null;\n contentView = p.contentView;\n } else {\n jsxContentViewRef.current?.dispose();\n jsxContentViewRef.current = null;\n contentView = presetViews.contentView as unknown as SvgNodeView<TContentVisual>;\n }\n\n let clusterView: SvgNodeView<TClusterVisual>;\n if (p.renderClusterNode) {\n const renderFn = p.renderClusterNode;\n jsxClusterViewRef.current?.dispose();\n const jsxView = new ReactJsxSvgView<\n TClusterVisual,\n ClusterDescriptor<TItem, TTagMeta, TClusterMeta>\n >({\n renderFn: (cluster, state) => renderFn(cluster, state),\n getKey: (v) => activeResolver.getVisualCacheKey(v),\n domainByKey: clusterDomainByKeyRef.current,\n });\n jsxClusterViewRef.current = jsxView;\n clusterView = jsxView;\n } else if (p.clusterView) {\n jsxClusterViewRef.current?.dispose();\n jsxClusterViewRef.current = null;\n clusterView = p.clusterView;\n } else {\n jsxClusterViewRef.current?.dispose();\n jsxClusterViewRef.current = null;\n clusterView = presetViews.clusterView as unknown as SvgNodeView<TClusterVisual>;\n }\n\n return { contentView, clusterView };\n };\n\n // Mount controller once on container\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n\n const p = latestPropsRef.current;\n const effectiveResolver = resolveEffectiveResolver();\n const { contentView, clusterView } = resolveActiveViews(effectiveResolver);\n\n const ctrl = SimplexSvgController.createFromResolved(el, {\n items: p.items,\n getId: p.getId,\n getTags: p.getTags,\n getLabel: p.getLabel,\n deriveClusterMeta: p.deriveClusterMeta,\n preset: p.preset,\n theme: p.theme,\n visualResolver: effectiveResolver,\n contentView,\n clusterView,\n normalizeTag: p.normalizeTag,\n resolveTagMeta: p.resolveTagMeta,\n meshOptions: p.meshOptions,\n layoutOptions: {\n ...p.layoutOptions,\n sizeMultiplier: p.sizeMultiplier ?? p.layoutOptions?.sizeMultiplier ?? 1,\n },\n meshStrategy: p.meshStrategy,\n clusteringStrategy: p.clusteringStrategy,\n colorStrategy: p.colorStrategy,\n layoutStrategy: p.layoutStrategy,\n showHulls: p.showHulls,\n focusOnClusterClick: false,\n interactions: {\n onContentHover: (ev) => {\n latestPropsRef.current.onContentHover?.(ev);\n if (latestPropsRef.current.tooltip) {\n setHoveredTarget(ev ? { kind: 'content', ...ev } : null);\n }\n },\n onClusterHover: (ev) => {\n latestPropsRef.current.onClusterHover?.(ev);\n if (latestPropsRef.current.tooltip) {\n setHoveredTarget(ev ? { kind: 'cluster', ...ev } : null);\n }\n },\n onLeftClick: (target, raw) => {\n const cur = latestPropsRef.current;\n if (cur.onLeftClick) {\n cur.onLeftClick(target, raw);\n return;\n }\n if (cur.focusedClusterUid === undefined && (cur.focusOnClusterClick ?? true)) {\n if (target.kind === 'cluster') {\n const next =\n internalFocusedUidRef.current === target.cluster.clusterUid\n ? null\n : target.cluster.clusterUid;\n internalFocusedUidRef.current = next;\n ctrlRef.current?.setFocusedClusterUid(next);\n } else if (\n target.kind === 'background' &&\n internalFocusedUidRef.current !== null\n ) {\n internalFocusedUidRef.current = null;\n ctrlRef.current?.setFocusedClusterUid(null);\n }\n }\n },\n onRightClick: (t, raw) => latestPropsRef.current.onRightClick?.(t, raw),\n onWheel: (ev, cam) => {\n const policy = latestPropsRef.current.onWheel ?? 'zoom-to-cursor';\n if (policy === 'none') return;\n if (typeof policy === 'function') {\n policy(ev, cam);\n return;\n }\n if (policy === 'pan-vertical') {\n cam.panBy(-ev.deltaX, -ev.deltaY);\n return;\n }\n const factor = Math.exp(-ev.deltaY * 0.0014);\n cam.zoomToCursor(ev.screenX, ev.screenY, factor);\n },\n },\n onMetricsChange: (m) => latestPropsRef.current.onMetricsChange?.(m),\n onClustersChange: (c) => latestPropsRef.current.onClustersChange?.(c),\n onFpsUpdate: (fps) => latestPropsRef.current.onFpsUpdate?.(fps),\n });\n ctrlRef.current = ctrl;\n if (p.controllerRef) {\n p.controllerRef.current = ctrl;\n }\n\n return () => {\n ctrl.destroy();\n ctrlRef.current = null;\n if (latestPropsRef.current.controllerRef) {\n latestPropsRef.current.controllerRef.current = null;\n }\n jsxContentViewRef.current?.dispose();\n jsxClusterViewRef.current?.dispose();\n jsxContentViewRef.current = null;\n jsxClusterViewRef.current = null;\n };\n }, []);\n\n // Sync items\n useEffect(() => {\n ctrlRef.current?.setItems(props.items);\n }, [props.items]);\n\n // Sync views, presets, theme & visual resolver (triggers smooth crossfade / morph!)\n useEffect(() => {\n const ctrl = ctrlRef.current;\n if (!ctrl) return;\n ctrl.setTheme(props.theme ?? 'dark');\n const effectiveResolver = resolveEffectiveResolver();\n const { contentView, clusterView } = resolveActiveViews(effectiveResolver);\n ctrl.setViews({ contentView, clusterView });\n ctrl.setVisualResolver(effectiveResolver);\n }, [\n props.preset,\n props.theme,\n props.visualResolver,\n props.contentView,\n props.clusterView,\n props.renderContentNode,\n props.renderClusterNode,\n ]);\n\n // Sync sizeMultiplier\n useEffect(() => {\n if (props.sizeMultiplier !== undefined) {\n ctrlRef.current?.setSizeMultiplier(props.sizeMultiplier);\n }\n }, [props.sizeMultiplier]);\n\n // Sync showHulls\n useEffect(() => {\n if (props.showHulls !== undefined) {\n ctrlRef.current?.setShowHulls(props.showHulls);\n }\n }, [props.showHulls]);\n\n // Sync pluggable core algorithm strategies when props change after mount\n useEffect(() => {\n if (syncedMeshStrategyRef.current === props.meshStrategy) return;\n syncedMeshStrategyRef.current = props.meshStrategy;\n if (props.meshStrategy) {\n ctrlRef.current?.setMeshStrategy(props.meshStrategy);\n }\n }, [props.meshStrategy]);\n\n useEffect(() => {\n if (syncedClusteringStrategyRef.current === props.clusteringStrategy) return;\n syncedClusteringStrategyRef.current = props.clusteringStrategy;\n if (props.clusteringStrategy) {\n ctrlRef.current?.setClusteringStrategy(props.clusteringStrategy);\n }\n }, [props.clusteringStrategy]);\n\n useEffect(() => {\n if (syncedColorStrategyRef.current === props.colorStrategy) return;\n syncedColorStrategyRef.current = props.colorStrategy;\n if (props.colorStrategy) {\n ctrlRef.current?.setColorStrategy(props.colorStrategy);\n }\n }, [props.colorStrategy]);\n\n useEffect(() => {\n if (syncedLayoutStrategyRef.current === props.layoutStrategy) return;\n syncedLayoutStrategyRef.current = props.layoutStrategy;\n if (props.layoutStrategy) {\n ctrlRef.current?.setLayoutStrategy(props.layoutStrategy);\n }\n }, [props.layoutStrategy]);\n\n // Sync pinned / highlighted / focused cluster\n useEffect(() => {\n if (props.pinnedIds !== undefined) {\n ctrlRef.current?.setPinnedIds(props.pinnedIds);\n }\n }, [props.pinnedIds]);\n\n useEffect(() => {\n if (props.highlightedIds !== undefined) {\n ctrlRef.current?.setHighlightedIds(props.highlightedIds);\n }\n }, [props.highlightedIds]);\n\n useEffect(() => {\n if (props.focusedClusterUid !== undefined) {\n internalFocusedUidRef.current = props.focusedClusterUid;\n ctrlRef.current?.setFocusedClusterUid(props.focusedClusterUid);\n }\n }, [props.focusedClusterUid]);\n\n // Clear built-in tooltip if prop toggled off\n useEffect(() => {\n if (!props.tooltip) {\n setHoveredTarget(null);\n }\n }, [props.tooltip]);\n\n const renderBuiltInTooltip = () => {\n if (!props.tooltip || !hoveredTarget) return null;\n\n const containerW = containerRef.current?.clientWidth || 960;\n const containerH = containerRef.current?.clientHeight || 600;\n const left = Math.min(\n Math.max(8, Math.round(hoveredTarget.screenPosition.x + 14)),\n Math.max(8, containerW - 256),\n );\n const top = Math.min(\n Math.max(8, Math.round(hoveredTarget.screenPosition.y + 14)),\n Math.max(8, containerH - 80),\n );\n\n const isLight = props.theme === 'light';\n const content =\n typeof props.tooltip === 'function' ? (\n props.tooltip(hoveredTarget)\n ) : hoveredTarget.kind === 'content' ? (\n <div>\n <div style={{ fontWeight: 600, color: isLight ? '#0f172a' : '#f8fafc' }}>\n {extractDefaultItemLabel(\n hoveredTarget.item,\n hoveredTarget.layoutContext.id,\n props.getLabel,\n )}\n </div>\n {hoveredTarget.layoutContext.tags.length > 0 && (\n <div style={{ marginTop: 3, fontSize: 11, color: isLight ? '#475569' : '#94a3b8' }}>\n {hoveredTarget.layoutContext.tags\n .map((t) => `#${t.tag}`)\n .slice(0, 5)\n .join(' · ')}\n </div>\n )}\n </div>\n ) : (\n <div>\n <div style={{ fontWeight: 600, color: hoveredTarget.cluster.colorHex }}>\n {`${hoveredTarget.cluster.code} · ${hoveredTarget.cluster.defaultLabel}`}\n </div>\n <div style={{ marginTop: 3, fontSize: 11, color: isLight ? '#475569' : '#94a3b8' }}>\n {`${hoveredTarget.cluster.members.length} ${\n hoveredTarget.cluster.members.length === 1 ? 'item' : 'items'\n }`}\n </div>\n </div>\n );\n\n return (\n <div\n role=\"tooltip\"\n style={{\n position: 'absolute',\n left,\n top,\n zIndex: 20,\n maxWidth: 244,\n padding: '7px 10px',\n borderRadius: 8,\n background: isLight ? 'rgba(255, 255, 255, 0.96)' : 'rgba(9, 13, 22, 0.94)',\n border: isLight\n ? '1px solid rgba(203, 213, 225, 0.95)'\n : '1px solid rgba(51, 65, 85, 0.85)',\n color: isLight ? '#0f172a' : '#f1f5f9',\n fontSize: 12,\n lineHeight: 1.4,\n pointerEvents: 'none',\n boxShadow: isLight\n ? '0 10px 24px rgba(15, 23, 42, 0.12)'\n : '0 10px 24px rgba(0, 0, 0, 0.45)',\n }}\n >\n {content}\n </div>\n );\n };\n\n return (\n <div\n ref={containerRef}\n className={props.className}\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n ...props.style,\n }}\n >\n {renderBuiltInTooltip()}\n </div>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { ClusterDescriptor, DefaultTaggedItem, LayoutMetrics } from '@simplex-viz/core';
1
+ import type { ClusterDescriptor, DefaultTaggedItem, LayoutMetrics, SimplexClusteringStrategy, SimplexColorStrategy, SimplexLayoutStrategy, SimplexMeshStrategy } from '@simplex-viz/core';
2
2
  import type { SimplexSvgController } from '@simplex-viz/svg';
3
3
  /**
4
4
  * Imperative handle bound to `<SimplexTopicGraph controllerRef={...} />`.
@@ -7,6 +7,10 @@ export interface SimplexGraphHandle<TItem = DefaultTaggedItem, TContentVisual =
7
7
  addItems(items: TItem | readonly TItem[]): void;
8
8
  removeItems(ids: string | readonly string[]): void;
9
9
  setItems(items: readonly TItem[]): void;
10
+ setMeshStrategy(strategy: SimplexMeshStrategy<TItem>): void;
11
+ setClusteringStrategy(strategy: SimplexClusteringStrategy<TItem, TTagMeta>): void;
12
+ setColorStrategy(strategy: SimplexColorStrategy<TItem, TTagMeta>): void;
13
+ setLayoutStrategy(strategy: SimplexLayoutStrategy): void;
10
14
  resetCamera(): void;
11
15
  zoomBy(factor: number): void;
12
16
  getMetrics(): LayoutMetrics | null;
@@ -15,7 +19,7 @@ export interface SimplexGraphHandle<TItem = DefaultTaggedItem, TContentVisual =
15
19
  }
16
20
  /**
17
21
  * React hook returning a stable `controllerRef` and imperative transaction helpers
18
- * (`addItems`, `removeItems`, `setItems`, camera controls, and live telemetry getters).
22
+ * (`addItems`, `removeItems`, `setItems`, strategy setters, camera controls, and live telemetry getters).
19
23
  */
20
24
  export declare function useSimplexGraphController<TItem = DefaultTaggedItem, TContentVisual = unknown, TClusterVisual = unknown, TTagMeta = undefined, TClusterMeta = undefined>(): {
21
25
  readonly controllerRef: React.MutableRefObject<SimplexSvgController<TItem, TContentVisual, TClusterVisual, TTagMeta, TClusterMeta> | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"useSimplexGraphController.d.ts","sourceRoot":"","sources":["../src/useSimplexGraphController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D;;GAEG;AACH,MAAM,WAAW,kBAAkB,CACjC,KAAK,GAAG,iBAAiB,EACzB,cAAc,GAAG,OAAO,EACxB,cAAc,GAAG,OAAO,EACxB,QAAQ,GAAG,SAAS,EACpB,YAAY,GAAG,SAAS;IAExB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,EAAE,GAAG,IAAI,CAAC;IAChD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,SAAS,KAAK,EAAE,GAAG,IAAI,CAAC;IACxC,WAAW,IAAI,IAAI,CAAC;IACpB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,IAAI,aAAa,GAAG,IAAI,CAAC;IACnC,WAAW,IAAI,SAAS,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;IAC3E,gBAAgB,IAAI,oBAAoB,CACtC,KAAK,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,YAAY,CACb,GAAG,IAAI,CAAC;CACV;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,GAAG,iBAAiB,EACzB,cAAc,GAAG,OAAO,EACxB,cAAc,GAAG,OAAO,EACxB,QAAQ,GAAG,SAAS,EACpB,YAAY,GAAG,SAAS,KACrB;IACH,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,CACjE,KAAK,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,YAAY,CACb,GAAG,IAAI,CAAC,CAAC;IACV,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CACjC,KAAK,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,YAAY,CACb,CAAC;CACH,CA2DA"}
1
+ {"version":3,"file":"useSimplexGraphController.d.ts","sourceRoot":"","sources":["../src/useSimplexGraphController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D;;GAEG;AACH,MAAM,WAAW,kBAAkB,CACjC,KAAK,GAAG,iBAAiB,EACzB,cAAc,GAAG,OAAO,EACxB,cAAc,GAAG,OAAO,EACxB,QAAQ,GAAG,SAAS,EACpB,YAAY,GAAG,SAAS;IAExB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,KAAK,EAAE,GAAG,IAAI,CAAC;IAChD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,SAAS,KAAK,EAAE,GAAG,IAAI,CAAC;IACxC,eAAe,CAAC,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC;IAClF,gBAAgB,CAAC,QAAQ,EAAE,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC;IACxE,iBAAiB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACzD,WAAW,IAAI,IAAI,CAAC;IACpB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,IAAI,aAAa,GAAG,IAAI,CAAC;IACnC,WAAW,IAAI,SAAS,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;IAC3E,gBAAgB,IAAI,oBAAoB,CACtC,KAAK,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,YAAY,CACb,GAAG,IAAI,CAAC;CACV;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,GAAG,iBAAiB,EACzB,cAAc,GAAG,OAAO,EACxB,cAAc,GAAG,OAAO,EACxB,QAAQ,GAAG,SAAS,EACpB,YAAY,GAAG,SAAS,KACrB;IACH,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,CACjE,KAAK,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,YAAY,CACb,GAAG,IAAI,CAAC,CAAC;IACV,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CACjC,KAAK,EACL,cAAc,EACd,cAAc,EACd,QAAQ,EACR,YAAY,CACb,CAAC;CACH,CAuFA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplex-viz/react",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "End-to-end type-safe React bindings, declarative JSX node renderers, and hooks for @simplex-viz/core and @simplex-viz/svg.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  "LICENSE"
21
21
  ],
22
22
  "dependencies": {
23
- "@simplex-viz/core": "^0.2.0",
24
- "@simplex-viz/svg": "^0.2.0"
23
+ "@simplex-viz/core": "^0.3.0",
24
+ "@simplex-viz/svg": "^0.3.0"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "react": ">=18.0.0",