@visuallyjs/browser-ui-svelte 1.2.5 → 1.2.7

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.
@@ -1,45 +1,71 @@
1
1
  <script lang="ts">
2
+ import { AreaChart, type BrowserElement, type AreaChartOptions } from "@visuallyjs/browser-ui";
3
+ import type { AreaChartComponentProps } from "./charts/definitions";
4
+ import { useVisuallyJsModel } from "./surface-store";
2
5
 
3
- import { onMount } from "svelte";
6
+ const { options, className = "", data, url, dataSourceFilter }: AreaChartComponentProps = $props();
4
7
 
5
- import {AreaChart, type AreaChartOptions, type BrowserElement} from "@visuallyjs/browser-ui"
6
- import {type AreaChartComponentProps} from "./charts/definitions";
7
- import {useVisuallyJsModel} from "./surface-store";
8
+ let container: BrowserElement;
9
+ let chart: AreaChart | undefined = $state();
8
10
 
9
- let container:BrowserElement;
10
-
11
- let {options, className = "", data, url, dataSourceFilter }:AreaChartComponentProps = $props();
12
-
13
- let chart:AreaChart;
11
+ export function getChart() {
12
+ return chart;
13
+ }
14
14
 
15
+ // A single, unified effect to manage the chart's entire lifecycle.
16
+ // This effect re-runs when props that require recreation, like `options`, change.
15
17
  $effect(() => {
16
- if (chart) {
17
- if (dataSourceFilter != null) {
18
- chart.setDataSourceFilter(dataSourceFilter)
19
- }
20
- }
21
- })
22
-
23
- function init(opts:AreaChartOptions) {
24
- chart = new AreaChart(container, opts)
25
- if (url != null) {
26
- chart.load({url});
27
- } else if (data != null) {
28
- chart.load({data});
29
- }
30
- }
18
+ if (!container) return;
19
+
20
+ let chartInstance: AreaChart;
21
+ const chartOpts: AreaChartOptions = { ...options, dataSourceFilter };
22
+ let isDestroyed = false;
31
23
 
32
- onMount(async () => {
33
- const opts:AreaChartOptions = Object.assign({dataSourceFilter}, options)
24
+ // Initialize the chart. This can be async if we need to fetch a model.
34
25
  if (url == null && data == null) {
35
26
  useVisuallyJsModel().then(m => {
36
- opts.dataSource = m
37
- init(opts)
38
- })
27
+ if (!isDestroyed) { // Ensure component hasn't been destroyed in the meantime
28
+ chartOpts.dataSource = m;
29
+ chartInstance = new AreaChart(container, chartOpts);
30
+ chart = chartInstance;
31
+ }
32
+ });
39
33
  } else {
40
- init(opts)
34
+ // Synchronous initialization with `data` or `url` props.
35
+ chartInstance = new AreaChart(container, chartOpts);
36
+ chart = chartInstance;
41
37
  }
42
- })
38
+
39
+ // This nested effect runs ONLY when the `data` prop changes.
40
+ // It loads the new data into the existing chart without recreating it.
41
+ $effect(() => {
42
+ if (chartInstance && data != null) {
43
+ chartInstance.load({ data });
44
+ }
45
+ });
46
+
47
+ // This nested effect handles updates to the `url` prop.
48
+ $effect(() => {
49
+ if (chartInstance && url != null) {
50
+ chartInstance.load({ url });
51
+ }
52
+ });
53
+
54
+ // This nested effect handles updates to the filter.
55
+ $effect(() => {
56
+ if (chartInstance && dataSourceFilter != null) {
57
+ chartInstance.setDataSourceFilter(dataSourceFilter);
58
+ }
59
+ });
60
+
61
+ // The cleanup function for the main effect. It runs when the component
62
+ // is unmounted or when `options` change, ensuring the old chart is destroyed.
63
+ return () => {
64
+ isDestroyed = true;
65
+ chartInstance?.destroy();
66
+ chart = undefined;
67
+ };
68
+ });
43
69
 
44
70
  </script>
45
71
 
@@ -1,48 +1,71 @@
1
1
  <script lang="ts">
2
+ import { BarChart, type BrowserElement, type BarChartOptions } from "@visuallyjs/browser-ui";
3
+ import type { BarChartComponentProps } from "./charts/definitions";
4
+ import { useVisuallyJsModel } from "./surface-store";
2
5
 
3
- import { onMount } from "svelte";
6
+ const { options, className = "", data, url, dataSourceFilter }: BarChartComponentProps = $props();
4
7
 
5
- import {type BarChartOptions, BarChart, type BrowserElement} from "@visuallyjs/browser-ui"
6
- import {type BarChartComponentProps} from "./charts/definitions";
7
- import {useVisuallyJsModel} from "./surface-store";
8
+ let container: BrowserElement;
9
+ let chart: BarChart | undefined = $state();
8
10
 
9
- let container:BrowserElement;
10
-
11
- let {options, className = "", data, url, dataSourceFilter }:BarChartComponentProps = $props();
12
-
13
- let chart:BarChart;
14
-
15
- export function getChart() {
16
- return chart;
11
+ export function getChart() {
12
+ return chart;
17
13
  }
18
14
 
15
+ // A single, unified effect to manage the chart's entire lifecycle.
16
+ // This effect re-runs when props that require recreation, like `options`, change.
19
17
  $effect(() => {
20
- if (chart && dataSourceFilter != null) {
21
- chart.setDataSourceFilter(dataSourceFilter)
22
- }
18
+ if (!container) return;
23
19
 
24
- })
20
+ let chartInstance: BarChart;
21
+ const chartOpts: BarChartOptions = { ...options, dataSourceFilter };
22
+ let isDestroyed = false;
25
23
 
26
- function init(opts:BarChartOptions) {
27
- chart = new BarChart(container, opts)
28
- if (url != null) {
29
- chart.load({url});
30
- } else if (data != null) {
31
- chart.load({data});
32
- }
33
- }
34
-
35
- onMount(async () => {
36
- const opts:BarChartOptions = Object.assign({dataSourceFilter}, options)
24
+ // Initialize the chart. This can be async if we need to fetch a model.
37
25
  if (url == null && data == null) {
38
26
  useVisuallyJsModel().then(m => {
39
- opts.dataSource = m
40
- init(opts)
41
- })
27
+ if (!isDestroyed) { // Ensure component hasn't been destroyed in the meantime
28
+ chartOpts.dataSource = m;
29
+ chartInstance = new BarChart(container, chartOpts);
30
+ chart = chartInstance;
31
+ }
32
+ });
42
33
  } else {
43
- init(opts)
34
+ // Synchronous initialization with `data` or `url` props.
35
+ chartInstance = new BarChart(container, chartOpts);
36
+ chart = chartInstance;
44
37
  }
45
- })
38
+
39
+ // This nested effect runs ONLY when the `data` prop changes.
40
+ // It loads the new data into the existing chart without recreating it.
41
+ $effect(() => {
42
+ if (chartInstance && data != null) {
43
+ chartInstance.load({ data });
44
+ }
45
+ });
46
+
47
+ // This nested effect handles updates to the `url` prop.
48
+ $effect(() => {
49
+ if (chartInstance && url != null) {
50
+ chartInstance.load({ url });
51
+ }
52
+ });
53
+
54
+ // This nested effect handles updates to the filter.
55
+ $effect(() => {
56
+ if (chartInstance && dataSourceFilter != null) {
57
+ chartInstance.setDataSourceFilter(dataSourceFilter);
58
+ }
59
+ });
60
+
61
+ // The cleanup function for the main effect. It runs when the component
62
+ // is unmounted or when `options` change, ensuring the old chart is destroyed.
63
+ return () => {
64
+ isDestroyed = true;
65
+ chartInstance?.destroy();
66
+ chart = undefined;
67
+ };
68
+ });
46
69
 
47
70
  </script>
48
71
 
@@ -1,49 +1,71 @@
1
1
  <script lang="ts">
2
+ import { BubbleChart, type BrowserElement, type BubbleChartOptions } from "@visuallyjs/browser-ui";
3
+ import type { BubbleChartComponentProps } from "./charts/definitions";
4
+ import { useVisuallyJsModel } from "./surface-store";
2
5
 
3
- import { onMount } from "svelte";
6
+ const { options, className = "", data, url, dataSourceFilter }: BubbleChartComponentProps = $props();
4
7
 
5
- import {type BubbleChartOptions, type BrowserElement, BubbleChart} from "@visuallyjs/browser-ui"
6
- import {type BubbleChartComponentProps} from "./charts/definitions";
7
- import {useVisuallyJsModel} from "./surface-store";
8
+ let container: BrowserElement;
9
+ let chart: BubbleChart | undefined = $state();
8
10
 
9
- let container:BrowserElement;
10
-
11
- // BubbleChartOptions
12
- let {options, className = "", data, url, dataSourceFilter }:BubbleChartComponentProps = $props();
13
-
14
- let chart:BubbleChart;
15
-
16
- export function getChart() {
17
- return chart;
11
+ export function getChart() {
12
+ return chart;
18
13
  }
19
14
 
15
+ // A single, unified effect to manage the chart's entire lifecycle.
16
+ // This effect re-runs when props that require recreation, like `options`, change.
20
17
  $effect(() => {
21
- if (chart && dataSourceFilter != null) {
22
- chart.setDataSourceFilter(dataSourceFilter)
23
- }
24
- })
25
-
26
- function init(opts:BubbleChartOptions) {
27
- chart = new BubbleChart(container, opts)
28
- if (url != null) {
29
- chart.load({url});
30
- } else if (data != null) {
31
- chart.load({data});
32
- }
33
- }
18
+ if (!container) return;
19
+
20
+ let chartInstance: BubbleChart;
21
+ const chartOpts: BubbleChartOptions = { ...options, dataSourceFilter };
22
+ let isDestroyed = false;
34
23
 
35
- onMount(async () => {
36
- const opts:BubbleChartOptions = Object.assign({dataSourceFilter}, options)
24
+ // Initialize the chart. This can be async if we need to fetch a model.
37
25
  if (url == null && data == null) {
38
26
  useVisuallyJsModel().then(m => {
39
- opts.dataSource = m
40
- init(opts)
41
- })
27
+ if (!isDestroyed) { // Ensure component hasn't been destroyed in the meantime
28
+ chartOpts.dataSource = m;
29
+ chartInstance = new BubbleChart(container, chartOpts);
30
+ chart = chartInstance;
31
+ }
32
+ });
42
33
  } else {
43
- init(opts)
34
+ // Synchronous initialization with `data` or `url` props.
35
+ chartInstance = new BubbleChart(container, chartOpts);
36
+ chart = chartInstance;
44
37
  }
45
- })
46
38
 
39
+ // This nested effect runs ONLY when the `data` prop changes.
40
+ // It loads the new data into the existing chart without recreating it.
41
+ $effect(() => {
42
+ if (chartInstance && data != null) {
43
+ chartInstance.load({ data });
44
+ }
45
+ });
46
+
47
+ // This nested effect handles updates to the `url` prop.
48
+ $effect(() => {
49
+ if (chartInstance && url != null) {
50
+ chartInstance.load({ url });
51
+ }
52
+ });
53
+
54
+ // This nested effect handles updates to the filter.
55
+ $effect(() => {
56
+ if (chartInstance && dataSourceFilter != null) {
57
+ chartInstance.setDataSourceFilter(dataSourceFilter);
58
+ }
59
+ });
60
+
61
+ // The cleanup function for the main effect. It runs when the component
62
+ // is unmounted or when `options` change, ensuring the old chart is destroyed.
63
+ return () => {
64
+ isDestroyed = true;
65
+ chartInstance?.destroy();
66
+ chart = undefined;
67
+ };
68
+ });
47
69
 
48
70
  </script>
49
71
 
@@ -1,49 +1,71 @@
1
1
  <script lang="ts">
2
+ import { ColumnChart, type BrowserElement, type ColumnChartOptions } from "@visuallyjs/browser-ui";
3
+ import type { ColumnChartComponentProps } from "./charts/definitions";
4
+ import { useVisuallyJsModel } from "./surface-store";
2
5
 
3
- import { onMount } from "svelte";
6
+ const { options, className = "", data, url, dataSourceFilter }: ColumnChartComponentProps = $props();
4
7
 
5
- import {type BrowserElement, type ColumnChartOptions, ColumnChart} from "@visuallyjs/browser-ui"
6
- import {type ColumnChartComponentProps} from "./charts/definitions";
7
- import {useVisuallyJsModel} from "./surface-store";
8
+ let container: BrowserElement;
9
+ let chart: ColumnChart | undefined = $state();
8
10
 
9
- let container:BrowserElement;
10
-
11
- // ColumnChartOptions
12
- let {options, className = "", data, url, dataSourceFilter }:ColumnChartComponentProps = $props();
13
-
14
- let chart:ColumnChart;
15
-
16
- export function getChart() {
17
- return chart;
11
+ export function getChart() {
12
+ return chart;
18
13
  }
19
14
 
15
+ // A single, unified effect to manage the chart's entire lifecycle.
16
+ // This effect re-runs when props that require recreation, like `options`, change.
20
17
  $effect(() => {
21
- if (chart && dataSourceFilter != null) {
22
- chart.setDataSourceFilter(dataSourceFilter)
23
- }
24
- })
25
-
26
- function init(opts:ColumnChartOptions) {
27
- chart = new ColumnChart(container, opts)
28
- if (url != null) {
29
- chart.load({url});
30
- } else if (data != null) {
31
- chart.load({data});
32
- }
33
- }
18
+ if (!container) return;
19
+
20
+ let chartInstance: ColumnChart;
21
+ const chartOpts: ColumnChartOptions = { ...options, dataSourceFilter };
22
+ let isDestroyed = false;
34
23
 
35
- onMount(async () => {
36
- const opts:ColumnChartOptions = Object.assign({dataSourceFilter}, options)
24
+ // Initialize the chart. This can be async if we need to fetch a model.
37
25
  if (url == null && data == null) {
38
26
  useVisuallyJsModel().then(m => {
39
- opts.dataSource = m
40
- init(opts)
41
- })
27
+ if (!isDestroyed) { // Ensure component hasn't been destroyed in the meantime
28
+ chartOpts.dataSource = m;
29
+ chartInstance = new ColumnChart(container, chartOpts);
30
+ chart = chartInstance;
31
+ }
32
+ });
42
33
  } else {
43
- init(opts)
34
+ // Synchronous initialization with `data` or `url` props.
35
+ chartInstance = new ColumnChart(container, chartOpts);
36
+ chart = chartInstance;
44
37
  }
45
- })
46
38
 
39
+ // This nested effect runs ONLY when the `data` prop changes.
40
+ // It loads the new data into the existing chart without recreating it.
41
+ $effect(() => {
42
+ if (chartInstance && data != null) {
43
+ chartInstance.load({ data });
44
+ }
45
+ });
46
+
47
+ // This nested effect handles updates to the `url` prop.
48
+ $effect(() => {
49
+ if (chartInstance && url != null) {
50
+ chartInstance.load({ url });
51
+ }
52
+ });
53
+
54
+ // This nested effect handles updates to the filter.
55
+ $effect(() => {
56
+ if (chartInstance && dataSourceFilter != null) {
57
+ chartInstance.setDataSourceFilter(dataSourceFilter);
58
+ }
59
+ });
60
+
61
+ // The cleanup function for the main effect. It runs when the component
62
+ // is unmounted or when `options` change, ensuring the old chart is destroyed.
63
+ return () => {
64
+ isDestroyed = true;
65
+ chartInstance?.destroy();
66
+ chart = undefined;
67
+ };
68
+ });
47
69
 
48
70
  </script>
49
71
 
@@ -0,0 +1,69 @@
1
+ <script lang="ts">
2
+ import {
3
+ type EdgePropertyMappings,
4
+ type EdgeMapping,
5
+ type PropertyMapping,
6
+ Inspector, INSPECTOR_CONTEXT_EDGE_PROPERTY_MAPPINGS,
7
+ log
8
+ } from "@visuallyjs/browser-ui"
9
+ import {onMount} from "svelte"
10
+ import {type EdgePropertyMappingsInspectorProps} from "./definitions";
11
+ import {getInspectorContext} from "./inspector-store";
12
+ import EdgeTypePickerComponent from "./EdgeTypePickerComponent.svelte";
13
+
14
+ let inspector: Inspector
15
+ let mappings:EdgePropertyMappings = $state([])
16
+
17
+ let {
18
+ getPropertyName,
19
+ showName = true,
20
+ cssClass = "vjs-inspector-section",
21
+ mappings: propsMappings
22
+ }: EdgePropertyMappingsInspectorProps = $props()
23
+
24
+ const resolveMappings = (): EdgePropertyMappings => {
25
+ if (propsMappings) {
26
+ return propsMappings
27
+ } else if (inspector) {
28
+ const m = inspector.getFromContext<EdgePropertyMappings>(INSPECTOR_CONTEXT_EDGE_PROPERTY_MAPPINGS)
29
+ return m || inspector.$ui.$getEdgePropertyMappings()
30
+ } else {
31
+ return []
32
+ }
33
+ }
34
+
35
+ onMount(async () => {
36
+ const ic = getInspectorContext(true)
37
+ if (ic == null) {
38
+ log(`WARN: EdgePropertyMappingsInspector cannot find an inspector context; cannot mount.`)
39
+ } else {
40
+ ic.listen(i => {
41
+ inspector = i
42
+ mappings = resolveMappings()
43
+ })
44
+ }
45
+ })
46
+
47
+ function toList(pm: PropertyMapping<EdgeMapping>): Array<string> {
48
+ const p = pm.property
49
+ return Array.isArray(p) ? p : [p]
50
+ }
51
+
52
+ function getPropertyKey(pm: PropertyMapping<EdgeMapping>) {
53
+ return toList(pm).join(" ")
54
+ }
55
+
56
+ function getName(pm: PropertyMapping<EdgeMapping>) {
57
+ return getPropertyName ? getPropertyName(pm) : pm.name || getPropertyKey(pm)
58
+ }
59
+
60
+ </script>
61
+
62
+ {#each mappings as pm (getPropertyKey(pm))}
63
+ <div class={cssClass}>
64
+ {#if showName !== false}
65
+ <div>{getName(pm)}</div>
66
+ {/if}
67
+ <EdgeTypePickerComponent propertyName={getPropertyKey(pm)}/>
68
+ </div>
69
+ {/each}
@@ -24,18 +24,19 @@
24
24
 
25
25
  const ic = getInspectorContext(true)
26
26
  if (ic == null) {
27
- log(`WARN: color picker cannot find an inspector context; cannot mount.`)
27
+ log(`WARN: edge type picker cannot find an inspector context; cannot mount.`)
28
28
  } else {
29
29
  ic.listen(i => {
30
30
  inspector = i
31
31
  const edgeMappings = resolveMappings()
32
- edgeTypePicker = new EdgeTypePicker(inspector.$ui, container, edgeMappings, inspector.getValue(propertyName), (v) => {
33
- inspector.setValue(propertyName, v, null)
32
+ edgeTypePicker = new EdgeTypePicker(inspector.$ui, container, edgeMappings, inspector.getValue(propertyName), (property, value) => {
33
+ inspector.setValue(property, value, null)
34
34
  })
35
35
 
36
36
  edgeTypePicker.render(propertyName, inspector._currentCommonData)
37
37
 
38
38
  inspector.onChange(() => {
39
+ edgeTypePicker.reset()
39
40
  edgeTypePicker.select(propertyName, inspector.getValue(propertyName))
40
41
  })
41
42
  })
@@ -1,47 +1,71 @@
1
1
  <script lang="ts">
2
+ import { LineChart, type BrowserElement, type LineChartOptions } from "@visuallyjs/browser-ui";
3
+ import type { LineChartComponentProps } from "./charts/definitions";
4
+ import { useVisuallyJsModel } from "./surface-store";
2
5
 
3
- import { onMount } from "svelte";
6
+ const { options, className = "", data, url, dataSourceFilter }: LineChartComponentProps = $props();
4
7
 
5
- import {LineChart, type BrowserElement, type LineChartOptions} from "@visuallyjs/browser-ui"
6
- import {type LineChartComponentProps} from "./charts/definitions";
7
- import {useVisuallyJsModel} from "./surface-store";
8
+ let container: BrowserElement;
9
+ let chart: LineChart | undefined = $state();
8
10
 
9
- let container:BrowserElement;
10
-
11
- let {options, className = "", data, url, dataSourceFilter }:LineChartComponentProps = $props();
12
-
13
- let chart:LineChart;
14
-
15
- export function getChart() {
16
- return chart;
11
+ export function getChart() {
12
+ return chart;
17
13
  }
18
14
 
15
+ // A single, unified effect to manage the chart's entire lifecycle.
16
+ // This effect re-runs when props that require recreation, like `options`, change.
19
17
  $effect(() => {
20
- if (chart && dataSourceFilter != null) {
21
- chart.setDataSourceFilter(dataSourceFilter)
22
- }
23
- })
24
-
25
- function init(opts:LineChartOptions) {
26
- chart = new LineChart(container, opts)
27
- if (url != null) {
28
- chart.load({url});
29
- } else if (data != null) {
30
- chart.load({data});
31
- }
32
- }
18
+ if (!container) return;
33
19
 
34
- onMount(async () => {
35
- const opts:LineChartOptions = Object.assign({dataSourceFilter}, options)
20
+ let chartInstance: LineChart;
21
+ const chartOpts: LineChartOptions = { ...options, dataSourceFilter };
22
+ let isDestroyed = false;
23
+
24
+ // Initialize the chart. This can be async if we need to fetch a model.
36
25
  if (url == null && data == null) {
37
26
  useVisuallyJsModel().then(m => {
38
- opts.dataSource = m
39
- init(opts)
40
- })
27
+ if (!isDestroyed) { // Ensure component hasn't been destroyed in the meantime
28
+ chartOpts.dataSource = m;
29
+ chartInstance = new LineChart(container, chartOpts);
30
+ chart = chartInstance;
31
+ }
32
+ });
41
33
  } else {
42
- init(opts)
34
+ // Synchronous initialization with `data` or `url` props.
35
+ chartInstance = new LineChart(container, chartOpts);
36
+ chart = chartInstance;
43
37
  }
44
- })
38
+
39
+ // This nested effect runs ONLY when the `data` prop changes.
40
+ // It loads the new data into the existing chart without recreating it.
41
+ $effect(() => {
42
+ if (chartInstance && data != null) {
43
+ chartInstance.load({ data });
44
+ }
45
+ });
46
+
47
+ // This nested effect handles updates to the `url` prop.
48
+ $effect(() => {
49
+ if (chartInstance && url != null) {
50
+ chartInstance.load({ url });
51
+ }
52
+ });
53
+
54
+ // This nested effect handles updates to the filter.
55
+ $effect(() => {
56
+ if (chartInstance && dataSourceFilter != null) {
57
+ chartInstance.setDataSourceFilter(dataSourceFilter);
58
+ }
59
+ });
60
+
61
+ // The cleanup function for the main effect. It runs when the component
62
+ // is unmounted or when `options` change, ensuring the old chart is destroyed.
63
+ return () => {
64
+ isDestroyed = true;
65
+ chartInstance?.destroy();
66
+ chart = undefined;
67
+ };
68
+ });
45
69
 
46
70
  </script>
47
71
 
@@ -54,10 +54,7 @@
54
54
  ignoreDropOnNode,
55
55
  allowRotation,
56
56
  rotationSpeed,
57
- autoEdgeConnect,
58
- autoEdgeConnectActiveClass,
59
- autoEdgeConnectMode,
60
- autoEdgeLineStyle
57
+ autoEdgeConnect
61
58
  })
62
59
  }
63
60