@opendata-ai/openchart-svelte 8.0.0-rc.9 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Chart.svelte +4 -0
- package/dist/Chart.svelte.d.ts +1 -0
- package/dist/Chart.svelte.d.ts.map +1 -1
- package/dist/ChartStory.svelte +2 -2
- package/dist/ChartStory.svelte.d.ts +2 -2
- package/dist/ChartStory.svelte.d.ts.map +1 -1
- package/dist/GeoMap.svelte +12 -12
- package/dist/GeoMap.svelte.d.ts +5 -5
- package/dist/GeoMap.svelte.d.ts.map +1 -1
- package/dist/Graph.svelte +135 -12
- package/dist/Graph.svelte.d.ts +56 -3
- package/dist/Graph.svelte.d.ts.map +1 -1
- package/dist/Visualization.svelte +2 -2
- package/dist/__tests__/Graph.test.js +50 -0
- package/dist/composables/useChart.svelte.d.ts +2 -0
- package/dist/composables/useChart.svelte.d.ts.map +1 -1
- package/dist/composables/useChart.svelte.js +1 -0
- package/dist/composables/useGraph.svelte.d.ts +66 -9
- package/dist/composables/useGraph.svelte.d.ts.map +1 -1
- package/dist/composables/useGraph.svelte.js +48 -8
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/dist/types.d.ts +8 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -6
- package/src/BarList.svelte +0 -95
- package/src/Chart.svelte +0 -196
- package/src/ChartStory.svelte +0 -116
- package/src/DataTable.svelte +0 -132
- package/src/GeoMap.svelte +0 -89
- package/src/Graph.svelte +0 -119
- package/src/Sankey.svelte +0 -94
- package/src/ThemeProvider.svelte +0 -27
- package/src/TileMap.svelte +0 -112
- package/src/Visualization.svelte +0 -54
- package/src/__tests__/Chart.test.ts +0 -134
- package/src/__tests__/ChartStory.test.ts +0 -64
- package/src/__tests__/ChartStoryHarness.svelte +0 -13
- package/src/__tests__/DataTable.test.ts +0 -126
- package/src/__tests__/Graph.test.ts +0 -130
- package/src/__tests__/ThemeContext.test.ts +0 -106
- package/src/__tests__/composables.test.ts +0 -101
- package/src/__tests__/useTableState.test.ts +0 -134
- package/src/composables/useChart.svelte.ts +0 -108
- package/src/composables/useDarkMode.svelte.ts +0 -51
- package/src/composables/useGraph.svelte.ts +0 -115
- package/src/composables/useTable.svelte.ts +0 -85
- package/src/composables/useTableState.svelte.ts +0 -78
- package/src/context.ts +0 -35
- package/src/index.ts +0 -100
- 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 } : {}),
|
package/dist/Chart.svelte.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/ChartStory.svelte
CHANGED
|
@@ -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
|
|
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 |
|
|
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
|
|
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 |
|
|
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,
|
|
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"}
|
package/dist/GeoMap.svelte
CHANGED
|
@@ -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
|
-
|
|
6
|
+
createGeoMap() function.
|
|
7
7
|
-->
|
|
8
8
|
<script lang="ts">
|
|
9
|
-
import type { DarkMode,
|
|
9
|
+
import type { DarkMode, GeoMapSpec, ThemeConfig } from '@opendata-ai/openchart-core';
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
type
|
|
13
|
-
type
|
|
14
|
-
type
|
|
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:
|
|
28
|
+
spec: GeoMapSpec;
|
|
29
29
|
theme?: ThemeConfig;
|
|
30
30
|
darkMode?: DarkMode;
|
|
31
|
-
onmarkclick?: (event:
|
|
32
|
-
onmarkhover?: (event:
|
|
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:
|
|
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:
|
|
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 =
|
|
68
|
+
instance = createGeoMap(containerEl, currentSpec, options);
|
|
69
69
|
prevSpec = JSON.stringify(currentSpec);
|
|
70
70
|
});
|
|
71
71
|
|
package/dist/GeoMap.svelte.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { DarkMode,
|
|
2
|
-
import { type
|
|
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:
|
|
4
|
+
spec: GeoMapSpec;
|
|
5
5
|
theme?: ThemeConfig;
|
|
6
6
|
darkMode?: DarkMode;
|
|
7
|
-
onmarkclick?: (event:
|
|
8
|
-
onmarkhover?: (event:
|
|
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,
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
99
|
-
instance?.
|
|
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
|
|
103
|
-
|
|
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
|
|
107
|
-
instance?.
|
|
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
|
package/dist/Graph.svelte.d.ts
CHANGED
|
@@ -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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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;
|
|
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
|
|
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;
|
|
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());
|