@opendata-ai/openchart-svelte 8.0.0-rc.2 → 8.0.0-rc.20

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 (42) hide show
  1. package/dist/Chart.svelte +4 -0
  2. package/dist/Chart.svelte.d.ts +1 -0
  3. package/dist/Chart.svelte.d.ts.map +1 -1
  4. package/dist/GeoMap.svelte +8 -10
  5. package/dist/GeoMap.svelte.d.ts +3 -7
  6. package/dist/GeoMap.svelte.d.ts.map +1 -1
  7. package/dist/Graph.svelte +135 -12
  8. package/dist/Graph.svelte.d.ts +56 -3
  9. package/dist/Graph.svelte.d.ts.map +1 -1
  10. package/dist/__tests__/Graph.test.js +50 -0
  11. package/dist/composables/useGraph.svelte.d.ts +66 -9
  12. package/dist/composables/useGraph.svelte.d.ts.map +1 -1
  13. package/dist/composables/useGraph.svelte.js +48 -8
  14. package/dist/styles.css +1 -1
  15. package/dist/styles.css.map +1 -1
  16. package/package.json +5 -6
  17. package/src/BarList.svelte +0 -95
  18. package/src/Chart.svelte +0 -192
  19. package/src/ChartStory.svelte +0 -116
  20. package/src/DataTable.svelte +0 -132
  21. package/src/GeoMap.svelte +0 -91
  22. package/src/Graph.svelte +0 -119
  23. package/src/Sankey.svelte +0 -94
  24. package/src/ThemeProvider.svelte +0 -27
  25. package/src/TileMap.svelte +0 -112
  26. package/src/Visualization.svelte +0 -54
  27. package/src/__tests__/Chart.test.ts +0 -134
  28. package/src/__tests__/ChartStory.test.ts +0 -64
  29. package/src/__tests__/ChartStoryHarness.svelte +0 -13
  30. package/src/__tests__/DataTable.test.ts +0 -126
  31. package/src/__tests__/Graph.test.ts +0 -130
  32. package/src/__tests__/ThemeContext.test.ts +0 -106
  33. package/src/__tests__/composables.test.ts +0 -101
  34. package/src/__tests__/useTableState.test.ts +0 -134
  35. package/src/composables/useChart.svelte.ts +0 -108
  36. package/src/composables/useDarkMode.svelte.ts +0 -51
  37. package/src/composables/useGraph.svelte.ts +0 -115
  38. package/src/composables/useTable.svelte.ts +0 -85
  39. package/src/composables/useTableState.svelte.ts +0 -78
  40. package/src/context.ts +0 -35
  41. package/src/index.ts +0 -100
  42. package/src/types.ts +0 -149
package/dist/Chart.svelte CHANGED
@@ -38,6 +38,7 @@ let {
38
38
  ondeselect,
39
39
  ontextedit,
40
40
  ondatapointclick,
41
+ editable,
41
42
  selectedElement: selectedElementProp,
42
43
  highlight,
43
44
  class: className,
@@ -57,6 +58,7 @@ let {
57
58
  ondeselect?: (element: ElementRef) => void;
58
59
  ontextedit?: (element: ElementRef, oldText: string, newText: string) => void;
59
60
  ondatapointclick?: (data: Record<string, unknown>) => void;
61
+ editable?: boolean;
60
62
  selectedElement?: ElementRef;
61
63
  highlight?: string[] | null;
62
64
  class?: string;
@@ -107,6 +109,7 @@ let prevSpec = '';
107
109
  $effect(() => {
108
110
  const resolvedTheme = theme ?? ctxTheme?.();
109
111
  const resolvedDarkMode = darkMode ?? ctxDarkMode?.();
112
+ const resolvedEditable = editable;
110
113
  // Read spec without tracking - spec changes handled in Effect 2
111
114
  const currentSpec = untrack(() => spec);
112
115
 
@@ -124,6 +127,7 @@ $effect(() => {
124
127
  darkMode: resolvedDarkMode,
125
128
  responsive: true,
126
129
  ...stableHandlers,
130
+ ...(resolvedEditable != null ? { editable: resolvedEditable } : {}),
127
131
  ...(hasAnnotationEdit ? { onAnnotationEdit: stableOnAnnotationEdit } : {}),
128
132
  ...(hasEdit ? { onEdit: stableOnEdit } : {}),
129
133
  ...(hasSelect ? { onSelect: stableOnSelect } : {}),
@@ -14,6 +14,7 @@ type $$ComponentProps = {
14
14
  ondeselect?: (element: ElementRef) => void;
15
15
  ontextedit?: (element: ElementRef, oldText: string, newText: string) => void;
16
16
  ondatapointclick?: (data: Record<string, unknown>) => void;
17
+ editable?: boolean;
17
18
  selectedElement?: ElementRef;
18
19
  highlight?: string[] | null;
19
20
  class?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Chart.svelte.d.ts","sourceRoot":"","sources":["../src/Chart.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,cAAc,EACd,WAAW,EACZ,MAAM,6BAA6B,CAAC;AAKpC,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACxE,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC3D,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA2JF,QAAA,MAAM,KAAK;8BAlBqB,UAAU,GAAG,IAAI;kBAI3B,UAAU,KAAG,IAAI;oBAIjB,IAAI;MAUyB,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Chart.svelte.d.ts","sourceRoot":"","sources":["../src/Chart.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,cAAc,EACd,WAAW,EACZ,MAAM,6BAA6B,CAAC;AAKpC,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5D,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACxE,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA8JF,QAAA,MAAM,KAAK;8BAlBqB,UAAU,GAAG,IAAI;kBAI3B,UAAU,KAAG,IAAI;oBAIjB,IAAI;MAUyB,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -7,14 +7,12 @@
7
7
  -->
8
8
  <script lang="ts">
9
9
  import type { DarkMode, MapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
10
-
11
- type MapFeatureEvent = {
12
- id: string | number;
13
- name?: string;
14
- data: Record<string, unknown> | null;
15
- };
16
-
17
- import { createMap, type MapInstance, type MapMountOptions } from '@opendata-ai/openchart-vanilla';
10
+ import {
11
+ createMap,
12
+ type MapInstance,
13
+ type MapMarkEvent,
14
+ type MapMountOptions,
15
+ } from '@opendata-ai/openchart-vanilla';
18
16
  import { onMount, untrack } from 'svelte';
19
17
  import { getVizDarkMode, getVizTheme } from './context.js';
20
18
 
@@ -30,8 +28,8 @@ let {
30
28
  spec: MapSpec;
31
29
  theme?: ThemeConfig;
32
30
  darkMode?: DarkMode;
33
- onmarkclick?: (event: MapFeatureEvent) => void;
34
- onmarkhover?: (event: MapFeatureEvent | null) => void;
31
+ onmarkclick?: (event: MapMarkEvent) => void;
32
+ onmarkhover?: (event: MapMarkEvent | null) => void;
35
33
  class?: string;
36
34
  style?: string;
37
35
  } = $props();
@@ -1,15 +1,11 @@
1
1
  import type { DarkMode, MapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
2
- type MapFeatureEvent = {
3
- id: string | number;
4
- name?: string;
5
- data: Record<string, unknown> | null;
6
- };
2
+ import { type MapMarkEvent } from '@opendata-ai/openchart-vanilla';
7
3
  type $$ComponentProps = {
8
4
  spec: MapSpec;
9
5
  theme?: ThemeConfig;
10
6
  darkMode?: DarkMode;
11
- onmarkclick?: (event: MapFeatureEvent) => void;
12
- onmarkhover?: (event: MapFeatureEvent | null) => void;
7
+ onmarkclick?: (event: MapMarkEvent) => void;
8
+ onmarkhover?: (event: MapMarkEvent | null) => void;
13
9
  class?: string;
14
10
  style?: string;
15
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GeoMap.svelte.d.ts","sourceRoot":"","sources":["../src/GeoMap.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAOlF,KAAK,eAAe,GAAG;IACrB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACtC,CAAC;AACD,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAwEF,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"GeoMap.svelte.d.ts","sourceRoot":"","sources":["../src/GeoMap.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAClF,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,gCAAgC,CAAC;AAIvC,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAsEF,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
package/dist/Graph.svelte CHANGED
@@ -6,44 +6,95 @@
6
6
  createGraph() function.
7
7
 
8
8
  Exposes imperative methods via component exports for programmatic
9
- control (search, zoom, select).
9
+ control (search, zoom, select, fly, highlight).
10
10
  -->
11
11
  <script lang="ts">
12
12
  import type { DarkMode, GraphSpec, ThemeConfig } from '@opendata-ai/openchart-core';
13
13
  import {
14
+ type CameraFlightOptions,
14
15
  createGraph,
16
+ type GraphHighlightTarget,
15
17
  type GraphInstance,
18
+ type GraphLegendData,
16
19
  type GraphMountOptions,
20
+ type GraphTooltipFormatter,
17
21
  } from '@opendata-ai/openchart-vanilla';
18
22
  import { onMount, untrack } from 'svelte';
19
23
  import { getVizDarkMode, getVizTheme } from './context.js';
20
24
 
25
+ /** Tooltip prop: `false` off, `true` default, or an object with a formatter. */
26
+ type GraphTooltipProp = boolean | { formatter?: GraphTooltipFormatter };
27
+ /** Legend prop: `false` off, `true` default, or an object toggling interactivity/counts. */
28
+ type GraphLegendProp = boolean | { interactive?: boolean; counts?: boolean };
29
+
21
30
  let {
22
31
  spec,
23
32
  theme,
24
33
  darkMode,
34
+ tooltip,
35
+ legend,
36
+ fitOnLoad,
25
37
  onnodeclick,
26
38
  onnodedoubleclick,
39
+ onnodehover,
40
+ onedgehover,
27
41
  onselectionchange,
42
+ onlegendhover,
43
+ onlegendtoggle,
44
+ onhighlightchange,
45
+ oncamerachange,
28
46
  class: className,
29
47
  style,
30
48
  }: {
31
49
  spec: GraphSpec;
32
50
  theme?: ThemeConfig;
33
51
  darkMode?: DarkMode;
52
+ tooltip?: GraphTooltipProp;
53
+ legend?: GraphLegendProp;
54
+ fitOnLoad?: boolean;
34
55
  onnodeclick?: (node: Record<string, unknown>) => void;
35
56
  onnodedoubleclick?: (node: Record<string, unknown>) => void;
57
+ onnodehover?: (node: Record<string, unknown> | null) => void;
58
+ onedgehover?: (edge: Record<string, unknown> | null) => void;
36
59
  onselectionchange?: (nodeIds: string[]) => void;
60
+ onlegendhover?: (entry: { field: string; value: string } | null) => void;
61
+ onlegendtoggle?: (activeValues: string[]) => void;
62
+ onhighlightchange?: (nodeIds: string[] | null) => void;
63
+ oncamerachange?: (camera: { x: number; y: number; k: number }) => void;
37
64
  class?: string;
38
65
  style?: string;
39
66
  } = $props();
40
67
 
41
68
  let containerEl: HTMLDivElement;
42
69
  let instance: GraphInstance | null = null;
70
+ // First mount plays the entrance; theme/darkMode-only recreations suppress it.
71
+ let mountedOnce = false;
43
72
 
44
73
  const ctxTheme = getVizTheme();
45
74
  const ctxDarkMode = getVizDarkMode();
46
75
 
76
+ // Only the on/off decision gates recreation; the formatter (a function) rides
77
+ // the trampoline below so swapping it never remounts the graph.
78
+ const tooltipOn = $derived(tooltip !== false);
79
+ // Serialize the structural legend shape so a { interactive, counts } change
80
+ // recreates, but reference identity churn doesn't.
81
+ const legendKey = $derived(
82
+ legend === false
83
+ ? 'false'
84
+ : legend === true || legend === undefined
85
+ ? 'true'
86
+ : JSON.stringify({ interactive: legend.interactive, counts: legend.counts }),
87
+ );
88
+
89
+ // Stable tooltip formatter wrapper: always reads the LATEST formatter off the
90
+ // (untracked) prop, so a formatter can be added or swapped per-render without
91
+ // recreation and without going stale.
92
+ const stableTooltipFormatter: GraphTooltipFormatter = (item, defaults) => {
93
+ const t = untrack(() => tooltip);
94
+ const fn = t && typeof t === 'object' ? t.formatter : undefined;
95
+ return fn ? fn(item, defaults) : defaults;
96
+ };
97
+
47
98
  onMount(() => {
48
99
  return () => {
49
100
  instance?.destroy();
@@ -53,25 +104,49 @@ onMount(() => {
53
104
 
54
105
  let prevSpec = '';
55
106
 
56
- // Effect 1: Mount/recreate graph on theme/darkMode changes.
107
+ // Effect 1: Mount/recreate graph on theme/darkMode/structural option changes.
57
108
  $effect(() => {
58
109
  const resolvedTheme = theme ?? ctxTheme?.();
59
110
  const resolvedDarkMode = darkMode ?? ctxDarkMode?.();
111
+ // Read the structural tooltip/legend keys + fitOnLoad so a change to any of
112
+ // them recreates the graph; the tooltip formatter is deliberately NOT tracked
113
+ // (it rides the trampoline). Referencing `legendKey` here registers the
114
+ // reactive dependency — the actual `legend` object is read untracked below.
115
+ const on = tooltipOn;
116
+ void legendKey;
117
+ const fit = fitOnLoad;
60
118
  const currentSpec = untrack(() => spec);
61
119
 
62
120
  instance?.destroy();
63
121
 
122
+ const tooltipOption: GraphMountOptions['tooltip'] = on
123
+ ? { formatter: stableTooltipFormatter }
124
+ : false;
125
+
64
126
  const options: GraphMountOptions = {
65
127
  theme: resolvedTheme,
66
128
  darkMode: resolvedDarkMode,
67
- onNodeClick: (node: Record<string, unknown>) => untrack(() => onnodeclick)?.(node),
68
- onNodeDoubleClick: (node: Record<string, unknown>) => untrack(() => onnodedoubleclick)?.(node),
69
- onSelectionChange: (nodeIds: string[]) => untrack(() => onselectionchange)?.(nodeIds),
129
+ tooltip: tooltipOption,
130
+ legend: untrack(() => legend),
131
+ fitOnLoad: fit,
132
+ onNodeClick: (node) => untrack(() => onnodeclick)?.(node),
133
+ onNodeDoubleClick: (node) => untrack(() => onnodedoubleclick)?.(node),
134
+ onNodeHover: (node) => untrack(() => onnodehover)?.(node),
135
+ onEdgeHover: (edge) => untrack(() => onedgehover)?.(edge),
136
+ onSelectionChange: (nodeIds) => untrack(() => onselectionchange)?.(nodeIds),
137
+ onLegendHover: (entry) => untrack(() => onlegendhover)?.(entry),
138
+ onLegendToggle: (activeValues) => untrack(() => onlegendtoggle)?.(activeValues),
139
+ onHighlightChange: (nodeIds) => untrack(() => onhighlightchange)?.(nodeIds),
140
+ onCameraChange: (camera) => untrack(() => oncamerachange)?.(camera),
70
141
  responsive: true,
142
+ // untrack so reading the flag doesn't add a dependency; the value is set
143
+ // after the first mount and reset only on component teardown.
144
+ suppressEntrance: untrack(() => mountedOnce),
71
145
  };
72
146
 
73
147
  instance = createGraph(containerEl, currentSpec, options);
74
148
  prevSpec = JSON.stringify(currentSpec);
149
+ mountedOnce = true;
75
150
  });
76
151
 
77
152
  // Effect 2: Update graph when spec changes (no destroy/recreate).
@@ -86,7 +161,8 @@ $effect(() => {
86
161
  }
87
162
  });
88
163
 
89
- // Imperative methods exposed via component exports
164
+ // Imperative methods exposed via component exports. Each forwards opts to the
165
+ // underlying instance so consumers get the full vanilla API surface.
90
166
  export function search(query: string): void {
91
167
  instance?.search(query);
92
168
  }
@@ -95,21 +171,68 @@ export function clearSearch(): void {
95
171
  instance?.clearSearch();
96
172
  }
97
173
 
98
- export function zoomToFit(): void {
99
- instance?.zoomToFit();
174
+ export function getSearchMatches(): string[] {
175
+ return instance?.getSearchMatches() ?? [];
176
+ }
177
+
178
+ export function zoomToFit(opts?: CameraFlightOptions & { padding?: number }): void {
179
+ instance?.zoomToFit(opts);
180
+ }
181
+
182
+ export function zoomToNode(nodeId: string, opts?: CameraFlightOptions & { scale?: number }): void {
183
+ instance?.zoomToNode(nodeId, opts);
100
184
  }
101
185
 
102
- export function zoomToNode(nodeId: string): void {
103
- instance?.zoomToNode(nodeId);
186
+ export function flyTo(
187
+ target: { x: number; y: number; k?: number },
188
+ opts?: CameraFlightOptions,
189
+ ): void {
190
+ instance?.flyTo(target, opts);
104
191
  }
105
192
 
106
- export function selectNode(nodeId: string): void {
107
- instance?.selectNode(nodeId);
193
+ export function centerAt(x: number, y: number, opts?: CameraFlightOptions): void {
194
+ instance?.centerAt(x, y, opts);
195
+ }
196
+
197
+ export function getCamera(): { x: number; y: number; k: number } {
198
+ return instance?.getCamera() ?? { x: 0, y: 0, k: 1 };
199
+ }
200
+
201
+ export function selectNode(nodeId: string, opts?: { fly?: boolean } & CameraFlightOptions): void {
202
+ instance?.selectNode(nodeId, opts);
108
203
  }
109
204
 
110
205
  export function getSelectedNodes(): string[] {
111
206
  return instance?.getSelectedNodes() ?? [];
112
207
  }
208
+
209
+ export function highlight(target: GraphHighlightTarget, opts?: { dimOpacity?: number }): void {
210
+ instance?.highlight(target, opts);
211
+ }
212
+
213
+ export function clearHighlight(): void {
214
+ instance?.clearHighlight();
215
+ }
216
+
217
+ export function getHighlight(): string[] | null {
218
+ return instance?.getHighlight() ?? null;
219
+ }
220
+
221
+ export function getLegend(): GraphLegendData | null {
222
+ return instance?.getLegend() ?? null;
223
+ }
224
+
225
+ export function setActiveCategories(values: string[]): void {
226
+ instance?.setActiveCategories(values);
227
+ }
228
+
229
+ export function getActiveCategories(): string[] {
230
+ return instance?.getActiveCategories() ?? [];
231
+ }
232
+
233
+ export function updateVisuals(nextSpec: GraphSpec): void {
234
+ instance?.updateVisuals(nextSpec);
235
+ }
113
236
  </script>
114
237
 
115
238
  <div
@@ -1,21 +1,74 @@
1
1
  import type { DarkMode, GraphSpec, ThemeConfig } from '@opendata-ai/openchart-core';
2
+ import { type CameraFlightOptions, type GraphHighlightTarget, type GraphLegendData, type GraphTooltipFormatter } from '@opendata-ai/openchart-vanilla';
3
+ /** Tooltip prop: `false` off, `true` default, or an object with a formatter. */
4
+ type GraphTooltipProp = boolean | {
5
+ formatter?: GraphTooltipFormatter;
6
+ };
7
+ /** Legend prop: `false` off, `true` default, or an object toggling interactivity/counts. */
8
+ type GraphLegendProp = boolean | {
9
+ interactive?: boolean;
10
+ counts?: boolean;
11
+ };
2
12
  type $$ComponentProps = {
3
13
  spec: GraphSpec;
4
14
  theme?: ThemeConfig;
5
15
  darkMode?: DarkMode;
16
+ tooltip?: GraphTooltipProp;
17
+ legend?: GraphLegendProp;
18
+ fitOnLoad?: boolean;
6
19
  onnodeclick?: (node: Record<string, unknown>) => void;
7
20
  onnodedoubleclick?: (node: Record<string, unknown>) => void;
21
+ onnodehover?: (node: Record<string, unknown> | null) => void;
22
+ onedgehover?: (edge: Record<string, unknown> | null) => void;
8
23
  onselectionchange?: (nodeIds: string[]) => void;
24
+ onlegendhover?: (entry: {
25
+ field: string;
26
+ value: string;
27
+ } | null) => void;
28
+ onlegendtoggle?: (activeValues: string[]) => void;
29
+ onhighlightchange?: (nodeIds: string[] | null) => void;
30
+ oncamerachange?: (camera: {
31
+ x: number;
32
+ y: number;
33
+ k: number;
34
+ }) => void;
9
35
  class?: string;
10
36
  style?: string;
11
37
  };
12
38
  declare const Graph: import("svelte").Component<$$ComponentProps, {
13
39
  search: (query: string) => void;
14
40
  clearSearch: () => void;
15
- zoomToFit: () => void;
16
- zoomToNode: (nodeId: string) => void;
17
- selectNode: (nodeId: string) => void;
41
+ getSearchMatches: () => string[];
42
+ zoomToFit: (opts?: CameraFlightOptions & {
43
+ padding?: number;
44
+ }) => void;
45
+ zoomToNode: (nodeId: string, opts?: CameraFlightOptions & {
46
+ scale?: number;
47
+ }) => void;
48
+ flyTo: (target: {
49
+ x: number;
50
+ y: number;
51
+ k?: number;
52
+ }, opts?: CameraFlightOptions) => void;
53
+ centerAt: (x: number, y: number, opts?: CameraFlightOptions) => void;
54
+ getCamera: () => {
55
+ x: number;
56
+ y: number;
57
+ k: number;
58
+ };
59
+ selectNode: (nodeId: string, opts?: {
60
+ fly?: boolean;
61
+ } & CameraFlightOptions) => void;
18
62
  getSelectedNodes: () => string[];
63
+ highlight: (target: GraphHighlightTarget, opts?: {
64
+ dimOpacity?: number;
65
+ }) => void;
66
+ clearHighlight: () => void;
67
+ getHighlight: () => string[] | null;
68
+ getLegend: () => GraphLegendData | null;
69
+ setActiveCategories: (values: string[]) => void;
70
+ getActiveCategories: () => string[];
71
+ updateVisuals: (nextSpec: GraphSpec) => void;
19
72
  }, "">;
20
73
  type Graph = ReturnType<typeof Graph>;
21
74
  export default Graph;
@@ -1 +1 @@
1
- {"version":3,"file":"Graph.svelte.d.ts","sourceRoot":"","sources":["../src/Graph.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AASnF,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5D,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAiGF,QAAA,MAAM,KAAK;oBA9Ba,MAAM,KAAG,IAAI;uBAIZ,IAAI;qBAIN,IAAI;yBAIE,MAAM,KAAG,IAAI;yBAIb,MAAM,KAAG,IAAI;4BAIZ,MAAM,EAAE;MAUa,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Graph.svelte.d.ts","sourceRoot":"","sources":["../src/Graph.svelte.ts"],"names":[],"mappings":"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"}
@@ -101,4 +101,54 @@ describe('<Graph />', () => {
101
101
  const canvas = container.querySelector('canvas');
102
102
  expect(canvas).not.toBeNull();
103
103
  });
104
+ it('exposes the full imperative API and forwards calls without throwing', async () => {
105
+ const result = await renderGraph({ spec: basicSpec });
106
+ // Svelte 5 exposes component exports on the returned component instance.
107
+ const api = result.component;
108
+ for (const name of [
109
+ 'search',
110
+ 'clearSearch',
111
+ 'getSearchMatches',
112
+ 'zoomToFit',
113
+ 'zoomToNode',
114
+ 'flyTo',
115
+ 'centerAt',
116
+ 'getCamera',
117
+ 'selectNode',
118
+ 'getSelectedNodes',
119
+ 'highlight',
120
+ 'clearHighlight',
121
+ 'getHighlight',
122
+ 'getLegend',
123
+ 'updateVisuals',
124
+ ]) {
125
+ expect(typeof api[name]).toBe('function');
126
+ }
127
+ // Readback methods return sensible defaults from the live instance.
128
+ expect(api.getSelectedNodes()).toEqual([]);
129
+ expect(api.getSearchMatches()).toEqual([]);
130
+ expect(api.getHighlight()).toBeNull();
131
+ const cam = api.getCamera();
132
+ expect(cam.k).toBeGreaterThan(0);
133
+ // Opt-forwarding methods don't throw.
134
+ expect(() => api.zoomToFit({ duration: 0 })).not.toThrow();
135
+ expect(() => api.zoomToNode('a', { scale: 2 })).not.toThrow();
136
+ expect(() => api.flyTo({ x: 0, y: 0, k: 1 }, { duration: 0 })).not.toThrow();
137
+ expect(() => api.centerAt(0, 0, { duration: 0 })).not.toThrow();
138
+ expect(() => api.highlight({ nodeIds: ['a'] })).not.toThrow();
139
+ expect(() => api.clearHighlight()).not.toThrow();
140
+ });
141
+ it('renders with new option props (tooltip formatter, legend object, events)', async () => {
142
+ const { container } = await renderGraph({
143
+ spec: basicSpec,
144
+ tooltip: { formatter: () => 'custom' },
145
+ legend: { interactive: false, counts: false },
146
+ fitOnLoad: true,
147
+ onlegendhover: () => { },
148
+ onhighlightchange: () => { },
149
+ oncamerachange: () => { },
150
+ });
151
+ const canvas = container.querySelector('canvas');
152
+ expect(canvas).not.toBeNull();
153
+ });
104
154
  });
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * useGraph: composable for imperative graph control.
3
3
  *
4
- * Returns a Svelte action and exposes graph methods (search, zoom, select)
5
- * for programmatic control of the graph instance.
4
+ * Returns a Svelte action and exposes graph methods (search, zoom, select, fly,
5
+ * highlight) for programmatic control of the graph instance. The full vanilla
6
+ * GraphInstance API is threaded through.
6
7
  *
7
8
  * Usage:
8
9
  * ```svelte
@@ -16,18 +17,42 @@
16
17
  * .svelte components.
17
18
  */
18
19
  import type { GraphSpec } from '@opendata-ai/openchart-core';
19
- import { type GraphMountOptions } from '@opendata-ai/openchart-vanilla';
20
+ import { type CameraFlightOptions, type GraphHighlightTarget, type GraphLegendData, type GraphMountOptions } from '@opendata-ai/openchart-vanilla';
21
+ /** Camera transform components (graph-space). */
22
+ export type GraphCamera = {
23
+ x: number;
24
+ y: number;
25
+ k: number;
26
+ };
20
27
  export interface UseGraphOptions {
21
28
  /** Theme overrides. */
22
29
  theme?: GraphMountOptions['theme'];
23
30
  /** Dark mode setting. */
24
31
  darkMode?: GraphMountOptions['darkMode'];
32
+ /** Built-in tooltip; pass an object for a custom formatter. Defaults to true. */
33
+ tooltip?: GraphMountOptions['tooltip'];
34
+ /** Built-in legend. Defaults to true. Pass `false` if you render your own. */
35
+ legend?: GraphMountOptions['legend'];
36
+ /** Fit the graph to the viewport on the first tick. Default true. */
37
+ fitOnLoad?: GraphMountOptions['fitOnLoad'];
25
38
  /** Node click handler. */
26
39
  onNodeClick?: GraphMountOptions['onNodeClick'];
27
40
  /** Node double-click handler. */
28
41
  onNodeDoubleClick?: GraphMountOptions['onNodeDoubleClick'];
42
+ /** Node hover handler. */
43
+ onNodeHover?: GraphMountOptions['onNodeHover'];
44
+ /** Edge hover handler. */
45
+ onEdgeHover?: GraphMountOptions['onEdgeHover'];
29
46
  /** Selection change handler. */
30
47
  onSelectionChange?: GraphMountOptions['onSelectionChange'];
48
+ /** Legend hover handler. */
49
+ onLegendHover?: GraphMountOptions['onLegendHover'];
50
+ /** Legend toggle handler. */
51
+ onLegendToggle?: GraphMountOptions['onLegendToggle'];
52
+ /** Highlight change handler. */
53
+ onHighlightChange?: GraphMountOptions['onHighlightChange'];
54
+ /** Camera change handler. */
55
+ onCameraChange?: GraphMountOptions['onCameraChange'];
31
56
  /** Enable responsive resizing. Defaults to true. */
32
57
  responsive?: boolean;
33
58
  }
@@ -40,14 +65,46 @@ export interface UseGraphReturn {
40
65
  search: (query: string) => void;
41
66
  /** Clear the current search. */
42
67
  clearSearch: () => void;
43
- /** Zoom to fit all nodes in view. */
44
- zoomToFit: () => void;
45
- /** Zoom and center on a specific node. */
46
- zoomToNode: (nodeId: string) => void;
47
- /** Select a node by id. */
48
- selectNode: (nodeId: string) => void;
68
+ /** Node ids currently matching the active search query. */
69
+ getSearchMatches: () => string[];
70
+ /** Zoom to fit all nodes in view. Animated by default; `{ duration: 0 }` snaps. */
71
+ zoomToFit: (opts?: CameraFlightOptions & {
72
+ padding?: number;
73
+ }) => void;
74
+ /** Fly to a node and zoom in (default scale 2). */
75
+ zoomToNode: (nodeId: string, opts?: CameraFlightOptions & {
76
+ scale?: number;
77
+ }) => void;
78
+ /** Fly the camera to a graph-space target. */
79
+ flyTo: (target: {
80
+ x: number;
81
+ y: number;
82
+ k?: number;
83
+ }, opts?: CameraFlightOptions) => void;
84
+ /** Center the camera on a graph-space point (keeps current zoom). */
85
+ centerAt: (x: number, y: number, opts?: CameraFlightOptions) => void;
86
+ /** Current camera transform. */
87
+ getCamera: () => GraphCamera;
88
+ /** Select a node by id; `{ fly: true }` also flies to it. */
89
+ selectNode: (nodeId: string, opts?: {
90
+ fly?: boolean;
91
+ } & CameraFlightOptions) => void;
49
92
  /** Get the currently selected node ids. */
50
93
  getSelectedNodes: () => string[];
94
+ /** Emphasize a set of nodes; eased via the focus model. */
95
+ highlight: (target: GraphHighlightTarget, opts?: {
96
+ dimOpacity?: number;
97
+ }) => void;
98
+ /** Clear any programmatic highlight (and legend toggles). */
99
+ clearHighlight: () => void;
100
+ /** The currently highlighted node ids, or null when nothing is highlighted. */
101
+ getHighlight: () => string[] | null;
102
+ /** Headless snapshot of the legend. */
103
+ getLegend: () => GraphLegendData | null;
104
+ /** Set the active category filter declaratively (replaces legend toggle state). */
105
+ setActiveCategories: (values: string[]) => void;
106
+ /** Current active category values (empty = all active, no filter). */
107
+ getActiveCategories: () => string[];
51
108
  }
52
109
  export declare function useGraph(spec: () => GraphSpec, options?: () => UseGraphOptions | undefined): UseGraphReturn;
53
110
  //# sourceMappingURL=useGraph.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useGraph.svelte.d.ts","sourceRoot":"","sources":["../../src/composables/useGraph.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,gCAAgC,CAAC;AAExC,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,KAAK,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACnC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACzC,0BAA0B;IAC1B,WAAW,CAAC,EAAE,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAC/C,iCAAiC;IACjC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IAC3D,gCAAgC;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IAC3D,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK;QAAE,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACvD,gDAAgD;IAChD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,gCAAgC;IAChC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,qCAAqC;IACrC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,0CAA0C;IAC1C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,2BAA2B;IAC3B,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,2CAA2C;IAC3C,gBAAgB,EAAE,MAAM,MAAM,EAAE,CAAC;CAClC;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,SAAS,EACrB,OAAO,CAAC,EAAE,MAAM,eAAe,GAAG,SAAS,GAC1C,cAAc,CAsDhB"}
1
+ {"version":3,"file":"useGraph.svelte.d.ts","sourceRoot":"","sources":["../../src/composables/useGraph.svelte.ts"],"names":[],"mappings":"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"}