@opendata-ai/openchart-svelte 8.0.0-rc.9 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) 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/ChartStory.svelte +2 -2
  5. package/dist/ChartStory.svelte.d.ts +2 -2
  6. package/dist/ChartStory.svelte.d.ts.map +1 -1
  7. package/dist/GeoMap.svelte +12 -12
  8. package/dist/GeoMap.svelte.d.ts +5 -5
  9. package/dist/GeoMap.svelte.d.ts.map +1 -1
  10. package/dist/Graph.svelte +135 -12
  11. package/dist/Graph.svelte.d.ts +56 -3
  12. package/dist/Graph.svelte.d.ts.map +1 -1
  13. package/dist/Visualization.svelte +2 -2
  14. package/dist/__tests__/Graph.test.js +50 -0
  15. package/dist/composables/useChart.svelte.d.ts +2 -0
  16. package/dist/composables/useChart.svelte.d.ts.map +1 -1
  17. package/dist/composables/useChart.svelte.js +1 -0
  18. package/dist/composables/useGraph.svelte.d.ts +72 -9
  19. package/dist/composables/useGraph.svelte.d.ts.map +1 -1
  20. package/dist/composables/useGraph.svelte.js +48 -8
  21. package/dist/index.d.ts +5 -5
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -2
  24. package/dist/styles.css +1 -1
  25. package/dist/styles.css.map +1 -1
  26. package/dist/types.d.ts +8 -6
  27. package/dist/types.d.ts.map +1 -1
  28. package/package.json +5 -6
  29. package/src/BarList.svelte +0 -95
  30. package/src/Chart.svelte +0 -196
  31. package/src/ChartStory.svelte +0 -116
  32. package/src/DataTable.svelte +0 -132
  33. package/src/GeoMap.svelte +0 -89
  34. package/src/Graph.svelte +0 -119
  35. package/src/Sankey.svelte +0 -94
  36. package/src/ThemeProvider.svelte +0 -27
  37. package/src/TileMap.svelte +0 -112
  38. package/src/Visualization.svelte +0 -54
  39. package/src/__tests__/Chart.test.ts +0 -134
  40. package/src/__tests__/ChartStory.test.ts +0 -64
  41. package/src/__tests__/ChartStoryHarness.svelte +0 -13
  42. package/src/__tests__/DataTable.test.ts +0 -126
  43. package/src/__tests__/Graph.test.ts +0 -130
  44. package/src/__tests__/ThemeContext.test.ts +0 -106
  45. package/src/__tests__/composables.test.ts +0 -101
  46. package/src/__tests__/useTableState.test.ts +0 -134
  47. package/src/composables/useChart.svelte.ts +0 -108
  48. package/src/composables/useDarkMode.svelte.ts +0 -51
  49. package/src/composables/useGraph.svelte.ts +0 -115
  50. package/src/composables/useTable.svelte.ts +0 -85
  51. package/src/composables/useTableState.svelte.ts +0 -78
  52. package/src/context.ts +0 -35
  53. package/src/index.ts +0 -100
  54. package/src/types.ts +0 -149
package/dist/Chart.svelte CHANGED
@@ -27,6 +27,7 @@ let {
27
27
  spec,
28
28
  theme,
29
29
  darkMode,
30
+ renderer,
30
31
  onmarkclick,
31
32
  onmarkhover,
32
33
  onmarkleave,
@@ -47,6 +48,7 @@ let {
47
48
  spec: ChartSpec | LayerSpec | GraphSpec;
48
49
  theme?: ThemeConfig;
49
50
  darkMode?: DarkMode;
51
+ renderer?: 'auto' | 'svg' | 'canvas';
50
52
  onmarkclick?: (event: MarkEvent) => void;
51
53
  onmarkhover?: (event: MarkEvent) => void;
52
54
  onmarkleave?: () => void;
@@ -109,6 +111,7 @@ let prevSpec = '';
109
111
  $effect(() => {
110
112
  const resolvedTheme = theme ?? ctxTheme?.();
111
113
  const resolvedDarkMode = darkMode ?? ctxDarkMode?.();
114
+ const resolvedRenderer = renderer;
112
115
  const resolvedEditable = editable;
113
116
  // Read spec without tracking - spec changes handled in Effect 2
114
117
  const currentSpec = untrack(() => spec);
@@ -125,6 +128,7 @@ $effect(() => {
125
128
  const options: MountOptions = {
126
129
  theme: resolvedTheme,
127
130
  darkMode: resolvedDarkMode,
131
+ renderer: resolvedRenderer,
128
132
  responsive: true,
129
133
  ...stableHandlers,
130
134
  ...(resolvedEditable != null ? { editable: resolvedEditable } : {}),
@@ -3,6 +3,7 @@ type $$ComponentProps = {
3
3
  spec: ChartSpec | LayerSpec | GraphSpec;
4
4
  theme?: ThemeConfig;
5
5
  darkMode?: DarkMode;
6
+ renderer?: 'auto' | 'svg' | 'canvas';
6
7
  onmarkclick?: (event: MarkEvent) => void;
7
8
  onmarkhover?: (event: MarkEvent) => void;
8
9
  onmarkleave?: () => void;
@@ -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,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"}
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,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IACrC,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;AAiKF,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"}
@@ -11,7 +11,7 @@
11
11
  Pass `step` to drive the story externally; omit for self-driving scroll.
12
12
  -->
13
13
  <script lang="ts">
14
- import type { ChartSpec, GraphSpec, LayerSpec, MapSpec } from '@opendata-ai/openchart-core';
14
+ import type { ChartSpec, GeoMapSpec, GraphSpec, LayerSpec } from '@opendata-ai/openchart-core';
15
15
  import type { MountOptions } from '@opendata-ai/openchart-vanilla';
16
16
  import {
17
17
  type ChartStoryInstance,
@@ -30,7 +30,7 @@ let {
30
30
  mountOptions,
31
31
  class: className,
32
32
  }: {
33
- spec: ChartSpec | LayerSpec | GraphSpec | MapSpec;
33
+ spec: ChartSpec | LayerSpec | GraphSpec | GeoMapSpec;
34
34
  steps: ChartStoryOptions['steps'];
35
35
  narrative: Snippet[];
36
36
  step?: number;
@@ -1,9 +1,9 @@
1
- import type { ChartSpec, GraphSpec, LayerSpec, MapSpec } from '@opendata-ai/openchart-core';
1
+ import type { ChartSpec, GeoMapSpec, GraphSpec, LayerSpec } from '@opendata-ai/openchart-core';
2
2
  import type { MountOptions } from '@opendata-ai/openchart-vanilla';
3
3
  import { type ChartStoryInstance, type ChartStoryOptions } from '@opendata-ai/openchart-vanilla/story';
4
4
  import { type Snippet } from 'svelte';
5
5
  type $$ComponentProps = {
6
- spec: ChartSpec | LayerSpec | GraphSpec | MapSpec;
6
+ spec: ChartSpec | LayerSpec | GraphSpec | GeoMapSpec;
7
7
  steps: ChartStoryOptions['steps'];
8
8
  narrative: Snippet[];
9
9
  step?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ChartStory.svelte.d.ts","sourceRoot":"","sources":["../src/ChartStory.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAEvB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAW,KAAK,OAAO,EAAW,MAAM,QAAQ,CAAC;AAEvD,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IAClD,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAsFF,QAAA,MAAM,UAAU;kBA1BM,MAAM,KAAG,IAAI;uBAIV,kBAAkB,GAAG,IAAI;MAsBM,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ChartStory.svelte.d.ts","sourceRoot":"","sources":["../src/ChartStory.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC/F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAEvB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAW,KAAK,OAAO,EAAW,MAAM,QAAQ,CAAC;AAEvD,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IACrD,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAsFF,QAAA,MAAM,UAAU;kBA1BM,MAAM,KAAG,IAAI;uBAIV,kBAAkB,GAAG,IAAI;MAsBM,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -3,15 +3,15 @@
3
3
 
4
4
  Mounts a map instance on render, updates when spec changes,
5
5
  and cleans up on unmount. All heavy lifting is done by the vanilla
6
- createMap() function.
6
+ createGeoMap() function.
7
7
  -->
8
8
  <script lang="ts">
9
- import type { DarkMode, MapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
9
+ import type { DarkMode, GeoMapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
10
10
  import {
11
- createMap,
12
- type MapInstance,
13
- type MapMarkEvent,
14
- type MapMountOptions,
11
+ createGeoMap,
12
+ type GeoMapInstance,
13
+ type GeoMapMarkEvent,
14
+ type GeoMapMountOptions,
15
15
  } from '@opendata-ai/openchart-vanilla';
16
16
  import { onMount, untrack } from 'svelte';
17
17
  import { getVizDarkMode, getVizTheme } from './context.js';
@@ -25,17 +25,17 @@ let {
25
25
  class: className,
26
26
  style,
27
27
  }: {
28
- spec: MapSpec;
28
+ spec: GeoMapSpec;
29
29
  theme?: ThemeConfig;
30
30
  darkMode?: DarkMode;
31
- onmarkclick?: (event: MapMarkEvent) => void;
32
- onmarkhover?: (event: MapMarkEvent | null) => void;
31
+ onmarkclick?: (event: GeoMapMarkEvent) => void;
32
+ onmarkhover?: (event: GeoMapMarkEvent | null) => void;
33
33
  class?: string;
34
34
  style?: string;
35
35
  } = $props();
36
36
 
37
37
  let containerEl: HTMLDivElement;
38
- let instance: MapInstance | null = null;
38
+ let instance: GeoMapInstance | null = null;
39
39
 
40
40
  const ctxTheme = getVizTheme();
41
41
  const ctxDarkMode = getVizDarkMode();
@@ -57,7 +57,7 @@ $effect(() => {
57
57
 
58
58
  instance?.destroy();
59
59
 
60
- const options: MapMountOptions = {
60
+ const options: GeoMapMountOptions = {
61
61
  theme: resolvedTheme,
62
62
  darkMode: resolvedDarkMode,
63
63
  onMarkClick: (feature) => untrack(() => onmarkclick)?.(feature),
@@ -65,7 +65,7 @@ $effect(() => {
65
65
  responsive: true,
66
66
  };
67
67
 
68
- instance = createMap(containerEl, currentSpec, options);
68
+ instance = createGeoMap(containerEl, currentSpec, options);
69
69
  prevSpec = JSON.stringify(currentSpec);
70
70
  });
71
71
 
@@ -1,11 +1,11 @@
1
- import type { DarkMode, MapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
2
- import { type MapMarkEvent } from '@opendata-ai/openchart-vanilla';
1
+ import type { DarkMode, GeoMapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
2
+ import { type GeoMapMarkEvent } from '@opendata-ai/openchart-vanilla';
3
3
  type $$ComponentProps = {
4
- spec: MapSpec;
4
+ spec: GeoMapSpec;
5
5
  theme?: ThemeConfig;
6
6
  darkMode?: DarkMode;
7
- onmarkclick?: (event: MapMarkEvent) => void;
8
- onmarkhover?: (event: MapMarkEvent | null) => void;
7
+ onmarkclick?: (event: GeoMapMarkEvent) => void;
8
+ onmarkhover?: (event: GeoMapMarkEvent | null) => void;
9
9
  class?: string;
10
10
  style?: string;
11
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;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"}
1
+ {"version":3,"file":"GeoMap.svelte.d.ts","sourceRoot":"","sources":["../src/GeoMap.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,gCAAgC,CAAC;AAIvC,KAAK,gBAAgB,GAAI;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,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;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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"}
@@ -8,8 +8,8 @@
8
8
  import type { DarkMode, ThemeConfig, VizSpec } from '@opendata-ai/openchart-core';
9
9
  import {
10
10
  isBarListSpec,
11
+ isGeoMapSpec,
11
12
  isGraphSpec,
12
- isMapSpec,
13
13
  isSankeySpec,
14
14
  isTableSpec,
15
15
  isTileMapSpec,
@@ -47,7 +47,7 @@ let {
47
47
  <TileMap {spec} {theme} {darkMode} class={className} {style} />
48
48
  {:else if isBarListSpec(spec)}
49
49
  <BarList {spec} {theme} {darkMode} class={className} {style} />
50
- {:else if isMapSpec(spec)}
50
+ {:else if isGeoMapSpec(spec)}
51
51
  <GeoMap {spec} {theme} {darkMode} class={className} {style} />
52
52
  {:else}
53
53
  <Chart {spec} {theme} {darkMode} class={className} {style} />
@@ -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
  });
@@ -26,6 +26,8 @@ export interface UseChartOptions {
26
26
  onDataPointClick?: MountOptions['onDataPointClick'];
27
27
  /** Enable responsive resizing. Defaults to true. */
28
28
  responsive?: boolean;
29
+ /** Rendering backend for point marks; see the vanilla `MountOptions.renderer`. */
30
+ renderer?: MountOptions['renderer'];
29
31
  }
30
32
  export interface UseChartReturn {
31
33
  /** Svelte action to attach to a container div. */
@@ -1 +1 @@
1
- {"version":3,"file":"useChart.svelte.d.ts","sourceRoot":"","sources":["../../src/composables/useChart.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EAAE,KAAK,aAAa,EAAe,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAGpG,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9B,yBAAyB;IACzB,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACpC,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAAC,CAAC;IACpD,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,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,EAC7C,OAAO,CAAC,EAAE,MAAM,eAAe,GAAG,SAAS,GAC1C,cAAc,CA8DhB"}
1
+ {"version":3,"file":"useChart.svelte.d.ts","sourceRoot":"","sources":["../../src/composables/useChart.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EAAE,KAAK,aAAa,EAAe,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAGpG,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9B,yBAAyB;IACzB,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACpC,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,YAAY,CAAC,kBAAkB,CAAC,CAAC;IACpD,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK;QAAE,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACvD,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,wDAAwD;IACxD,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,EAC7C,OAAO,CAAC,EAAE,MAAM,eAAe,GAAG,SAAS,GAC1C,cAAc,CA+DhB"}
@@ -30,6 +30,7 @@ export function useChart(spec, options) {
30
30
  darkMode: opts?.darkMode,
31
31
  onDataPointClick: opts?.onDataPointClick,
32
32
  responsive: opts?.responsive ?? true,
33
+ renderer: opts?.renderer,
33
34
  };
34
35
  // Read spec without tracking
35
36
  const currentSpec = untrack(() => spec());