svelteplot 0.9.1 → 0.9.2

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.
@@ -51,7 +51,10 @@
51
51
  tickSpacing?: number;
52
52
  /** text anchor for axis labels */
53
53
  textAnchor?: ConstantAccessor<CSS.Property.TextAnchor | 'auto', Datum>;
54
- removeDuplicateTicks: boolean;
54
+ /**
55
+ * you can set this to true to remove duplicate tick labels
56
+ */
57
+ removeDuplicateTicks?: boolean;
55
58
  }
56
59
 
57
60
  let markProps: AxisXMarkProps = $props();
@@ -241,7 +244,7 @@
241
244
  {#if showAxis}
242
245
  <BaseAxisX
243
246
  {anchor}
244
- {className}
247
+ class={className}
245
248
  {labelAnchor}
246
249
  options={{ ...options, ...plot.options.x }}
247
250
  {plot}
@@ -88,7 +88,10 @@ declare function $$render<Datum extends RawValue>(): {
88
88
  tickSpacing?: number;
89
89
  /** text anchor for axis labels */
90
90
  textAnchor?: ConstantAccessor<CSS.Property.TextAnchor | "auto", Datum>;
91
- removeDuplicateTicks: boolean;
91
+ /**
92
+ * you can set this to true to remove duplicate tick labels
93
+ */
94
+ removeDuplicateTicks?: boolean;
92
95
  };
93
96
  exports: {};
94
97
  bindings: "";
@@ -221,7 +221,7 @@
221
221
  {#if showAxis}
222
222
  <BaseAxisY
223
223
  {anchor}
224
- {className}
224
+ class={className}
225
225
  {lineAnchor}
226
226
  options={{
227
227
  ...options,
@@ -11,6 +11,11 @@
11
11
  x2?: ChannelAccessor<Datum>;
12
12
  y?: ChannelAccessor<Datum>;
13
13
  stack?: StackOptions;
14
+ /**
15
+ * Renders using Canvas instead of SVG.
16
+ */
17
+
18
+ canvas?: boolean;
14
19
  /**
15
20
  * Converts x into x1/x2 ranges based on the provided interval. Disables the
16
21
  * implicit stacking
@@ -25,6 +30,7 @@
25
30
  import type { DataRow } from '../types/index.js';
26
31
  import GroupMultiple from './helpers/GroupMultiple.svelte';
27
32
  import RectPath from './helpers/RectPath.svelte';
33
+ import RectCanvas from './helpers/RectCanvas.svelte';
28
34
  import type {
29
35
  BaseMarkProps,
30
36
  BaseRectMarkProps,
@@ -46,6 +52,7 @@
46
52
  data = [{} as Datum],
47
53
  class: className = null,
48
54
  stack,
55
+ canvas = false,
49
56
  ...options
50
57
  }: BarXMarkProps = $derived({ ...DEFAULTS, ...markProps });
51
58
 
@@ -55,8 +62,7 @@
55
62
  stackX(
56
63
  intervalX(
57
64
  // by default, sort by y channel (the ordinal labels)
58
- sort(recordizeX({ data, ...options })),
59
- { plot }
65
+ sort(recordizeX({ data, ...options }))
60
66
  ),
61
67
  stack
62
68
  )
@@ -68,25 +74,50 @@
68
74
  requiredScales={{ y: ['band'] }}
69
75
  channels={['x1', 'x2', 'y', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
70
76
  {...args}>
71
- {#snippet children({ mark, usedScales, scaledData })}
72
- <GroupMultiple class="bar-x" length={scaledData.length}>
73
- {#each scaledData as d, i (i)}
74
- {@const bw = plot.scales.y.fn.bandwidth()}
75
- {@const minx = Math.min(d.x1, d.x2)}
76
- {@const maxx = Math.max(d.x1, d.x2)}
77
- {#if d.valid}
78
- <RectPath
79
- {usedScales}
80
- class={className}
81
- {options}
82
- datum={d}
83
- x={minx}
84
- useInsetAsFallbackHorizontally={false}
85
- y={d.y - bw * 0.5}
86
- width={maxx - minx}
87
- height={bw} />
88
- {/if}
89
- {/each}
90
- </GroupMultiple>
77
+ {#snippet children({ usedScales, scaledData })}
78
+ {@const bw = plot.scales.y.fn.bandwidth()}
79
+ {@const barGroupClass = className ? `bar-x ${className}` : 'bar-x'}
80
+ {#if canvas}
81
+ {@const rectCanvasData = scaledData
82
+ .filter((d) => d.valid)
83
+ .map((d) => {
84
+ const minx = Math.min(d.x1, d.x2);
85
+ const maxx = Math.max(d.x1, d.x2);
86
+
87
+ return {
88
+ ...d,
89
+ x1: minx,
90
+ x2: maxx,
91
+ y1: d.y - bw * 0.5,
92
+ y2: d.y + bw * 0.5
93
+ };
94
+ })}
95
+ <GroupMultiple class={barGroupClass} length={scaledData.length}>
96
+ <RectCanvas
97
+ {options}
98
+ data={rectCanvasData}
99
+ {usedScales}
100
+ useInsetAsFallbackHorizontally={false} />
101
+ </GroupMultiple>
102
+ {:else}
103
+ <GroupMultiple class="bar-x" length={scaledData.length}>
104
+ {#each scaledData as d, i (i)}
105
+ {@const minx = Math.min(d.x1, d.x2)}
106
+ {@const maxx = Math.max(d.x1, d.x2)}
107
+ {#if d.valid}
108
+ <RectPath
109
+ {usedScales}
110
+ class={className}
111
+ {options}
112
+ datum={d}
113
+ x={minx}
114
+ useInsetAsFallbackHorizontally={false}
115
+ y={d.y - bw * 0.5}
116
+ width={maxx - minx}
117
+ height={bw} />
118
+ {/if}
119
+ {/each}
120
+ </GroupMultiple>
121
+ {/if}
91
122
  {/snippet}
92
123
  </Mark>
@@ -72,6 +72,10 @@ declare function $$render<Datum extends DataRow>(): {
72
72
  x2?: ChannelAccessor<Datum>;
73
73
  y?: ChannelAccessor<Datum>;
74
74
  stack?: StackOptions;
75
+ /**
76
+ * Renders using Canvas instead of SVG.
77
+ */
78
+ canvas?: boolean;
75
79
  /**
76
80
  * Converts x into x1/x2 ranges based on the provided interval. Disables the
77
81
  * implicit stacking
@@ -12,6 +12,10 @@
12
12
  y1?: ChannelAccessor<Datum>;
13
13
  y2?: ChannelAccessor<Datum>;
14
14
  stack?: StackOptions;
15
+ /**
16
+ * Renders using Canvas instead of SVG.
17
+ */
18
+ canvas?: boolean;
15
19
  /**
16
20
  * Converts y into y1/y2 ranges based on the provided interval. Disables the
17
21
  * implicit stacking
@@ -25,6 +29,7 @@
25
29
  import type { StackOptions } from '../transforms/stack.js';
26
30
  import GroupMultiple from './helpers/GroupMultiple.svelte';
27
31
  import RectPath from './helpers/RectPath.svelte';
32
+ import RectCanvas from './helpers/RectCanvas.svelte';
28
33
  import type {
29
34
  BaseMarkProps,
30
35
  BaseRectMarkProps,
@@ -48,6 +53,7 @@
48
53
  data = [{}],
49
54
  class: className = null,
50
55
  stack,
56
+ canvas = false,
51
57
  ...options
52
58
  }: BarYMarkProps = $derived({ ...DEFAULTS, ...markProps });
53
59
 
@@ -55,8 +61,7 @@
55
61
  stackY(
56
62
  intervalY(
57
63
  // by default, sort by x channel (the ordinal labels)
58
- sort(recordizeY({ data, ...options })),
59
- { plot }
64
+ sort(recordizeY({ data, ...options }))
60
65
  ),
61
66
  stack
62
67
  )
@@ -69,24 +74,49 @@
69
74
  channels={['x', 'y1', 'y2', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
70
75
  {...args}>
71
76
  {#snippet children({ scaledData, usedScales })}
72
- <GroupMultiple class="bar-y" length={scaledData.length}>
73
- {#each scaledData as d, i (i)}
74
- {@const bw = plot.scales.x.fn.bandwidth()}
75
- {@const miny = Math.min(d.y1, d.y2)}
76
- {@const maxy = Math.max(d.y1, d.y2)}
77
- {#if d.valid}
78
- <RectPath
79
- x={d.x - bw * 0.5}
80
- y={miny}
81
- options={args}
82
- class={className}
83
- width={bw}
84
- height={maxy - miny}
85
- datum={d}
86
- {usedScales}
87
- useInsetAsFallbackVertically={false} />
88
- {/if}
89
- {/each}
90
- </GroupMultiple>
77
+ {@const bw = plot.scales.x.fn.bandwidth()}
78
+ {@const barGroupClass = className ? `bar-y ${className}` : 'bar-y'}
79
+ {#if canvas}
80
+ {@const rectCanvasData = scaledData
81
+ .filter((d) => d.valid)
82
+ .map((d) => {
83
+ const miny = Math.min(d.y1, d.y2);
84
+ const maxy = Math.max(d.y1, d.y2);
85
+
86
+ return {
87
+ ...d,
88
+ x1: d.x - bw * 0.5,
89
+ x2: d.x + bw * 0.5,
90
+ y1: miny,
91
+ y2: maxy
92
+ };
93
+ })}
94
+ <GroupMultiple class={barGroupClass} length={scaledData.length}>
95
+ <RectCanvas
96
+ {options}
97
+ data={rectCanvasData}
98
+ {usedScales}
99
+ useInsetAsFallbackVertically={false} />
100
+ </GroupMultiple>
101
+ {:else}
102
+ <GroupMultiple class="bar-y" length={scaledData.length}>
103
+ {#each scaledData as d, i (i)}
104
+ {@const miny = Math.min(d.y1, d.y2)}
105
+ {@const maxy = Math.max(d.y1, d.y2)}
106
+ {#if d.valid}
107
+ <RectPath
108
+ x={d.x - bw * 0.5}
109
+ y={miny}
110
+ options={args}
111
+ class={className}
112
+ width={bw}
113
+ height={maxy - miny}
114
+ datum={d}
115
+ {usedScales}
116
+ useInsetAsFallbackVertically={false} />
117
+ {/if}
118
+ {/each}
119
+ </GroupMultiple>
120
+ {/if}
91
121
  {/snippet}
92
122
  </Mark>
@@ -71,6 +71,10 @@ declare function $$render<Datum extends DataRow>(): {
71
71
  y1?: ChannelAccessor<Datum>;
72
72
  y2?: ChannelAccessor<Datum>;
73
73
  stack?: StackOptions;
74
+ /**
75
+ * Renders using Canvas instead of SVG.
76
+ */
77
+ canvas?: boolean;
74
78
  /**
75
79
  * Converts y into y1/y2 ranges based on the provided interval. Disables the
76
80
  * implicit stacking
@@ -8,6 +8,10 @@
8
8
  data: Datum[];
9
9
  x?: ChannelAccessor<Datum>;
10
10
  y?: ChannelAccessor<Datum>;
11
+ /**
12
+ * Renders using Canvas instead of SVG.
13
+ */
14
+ canvas?: boolean;
11
15
  }
12
16
  import type {
13
17
  DataRecord,
@@ -22,6 +26,7 @@
22
26
 
23
27
  import { isValid } from '../helpers/index.js';
24
28
  import RectPath from './helpers/RectPath.svelte';
29
+ import RectCanvas from './helpers/RectCanvas.svelte';
25
30
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
26
31
  import { usePlot } from '../hooks/usePlot.svelte.js';
27
32
 
@@ -34,6 +39,7 @@
34
39
  const {
35
40
  data = [{} as Datum],
36
41
  class: className = '',
42
+ canvas = false,
37
43
  ...options
38
44
  }: CellMarkProps = $derived({
39
45
  ...DEFAULTS,
@@ -67,19 +73,36 @@
67
73
  {@const bwx = plot.scales.x.fn.bandwidth()}
68
74
  {@const bwy = plot.scales.y.fn.bandwidth()}
69
75
  <g class="cell {className || ''}" data-fill={usedScales.fillOpacity}>
70
- {#each scaledData as d, i (i)}
71
- {#if d.valid && (args.fill == null || isValid(resolveChannel('fill', d.datum, args)))}
72
- <RectPath
73
- datum={d}
74
- class={className}
75
- {usedScales}
76
- options={args}
77
- x={d.x - bwx * 0.5}
78
- y={d.y - bwy * 0.5}
79
- width={bwx}
80
- height={bwy} />
81
- {/if}
82
- {/each}
76
+ {#if canvas}
77
+ {@const rectCanvasData = scaledData
78
+ .filter(
79
+ (d) =>
80
+ d.valid &&
81
+ (args.fill == null || isValid(resolveChannel('fill', d.datum, args)))
82
+ )
83
+ .map((d) => ({
84
+ ...d,
85
+ x1: d.x - bwx * 0.5,
86
+ x2: d.x + bwx * 0.5,
87
+ y1: d.y - bwy * 0.5,
88
+ y2: d.y + bwy * 0.5
89
+ }))}
90
+ <RectCanvas options={args} data={rectCanvasData} {usedScales} />
91
+ {:else}
92
+ {#each scaledData as d, i (i)}
93
+ {#if d.valid && (args.fill == null || isValid(resolveChannel('fill', d.datum, args)))}
94
+ <RectPath
95
+ datum={d}
96
+ class={className}
97
+ {usedScales}
98
+ options={args}
99
+ x={d.x - bwx * 0.5}
100
+ y={d.y - bwy * 0.5}
101
+ width={bwx}
102
+ height={bwy} />
103
+ {/if}
104
+ {/each}
105
+ {/if}
83
106
  </g>
84
107
  {/snippet}
85
108
  </Mark>
@@ -67,6 +67,10 @@ declare function $$render<Datum extends DataRecord>(): {
67
67
  data: Datum[];
68
68
  x?: ChannelAccessor<Datum>;
69
69
  y?: ChannelAccessor<Datum>;
70
+ /**
71
+ * Renders using Canvas instead of SVG.
72
+ */
73
+ canvas?: boolean;
70
74
  };
71
75
  exports: {};
72
76
  bindings: "";
@@ -67,6 +67,7 @@ declare function $$render<Datum extends DataRow>(): {
67
67
  data: Record<string | symbol, import("../types/index.js").RawValue>[];
68
68
  x?: import("../types/index.js").ChannelAccessor<Record<string | symbol, import("../types/index.js").RawValue>>;
69
69
  y?: import("../types/index.js").ChannelAccessor<Record<string | symbol, import("../types/index.js").RawValue>>;
70
+ canvas?: boolean;
70
71
  }, "data" | "y"> & {
71
72
  data: Datum[];
72
73
  };
@@ -67,6 +67,7 @@ declare function $$render<Datum extends DataRow>(): {
67
67
  data: Record<string | symbol, import("../types/index.js").RawValue>[];
68
68
  x?: import("../types/index.js").ChannelAccessor<Record<string | symbol, import("../types/index.js").RawValue>>;
69
69
  y?: import("../types/index.js").ChannelAccessor<Record<string | symbol, import("../types/index.js").RawValue>>;
70
+ canvas?: boolean;
70
71
  }, "data" | "x"> & {
71
72
  data: Datum[];
72
73
  };
@@ -13,7 +13,12 @@
13
13
  y1?: ChannelAccessor<Datum>;
14
14
  y2?: ChannelAccessor<Datum>;
15
15
  interval?: number | string;
16
- className?: string;
16
+ class?: string;
17
+ /**
18
+ * Renders using Canvas instead of SVG.
19
+ */
20
+
21
+ canvas?: boolean;
17
22
  }
18
23
  import Mark from '../Mark.svelte';
19
24
  import { intervalX, intervalY } from '../index.js';
@@ -26,6 +31,7 @@
26
31
  } from '../types/index.js';
27
32
  import GroupMultiple from './helpers/GroupMultiple.svelte';
28
33
  import RectPath from './helpers/RectPath.svelte';
34
+ import RectCanvas from './helpers/RectCanvas.svelte';
29
35
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
30
36
  import { IS_SORTED } from '../transforms/sort';
31
37
  import { usePlot } from '../hooks/usePlot.svelte.js';
@@ -39,6 +45,7 @@
39
45
  const {
40
46
  data = [{} as Datum],
41
47
  class: className = '',
48
+ canvas = false,
42
49
  ...options
43
50
  }: RectMarkProps = $derived({
44
51
  ...DEFAULTS,
@@ -47,9 +54,7 @@
47
54
 
48
55
  const plot = usePlot();
49
56
 
50
- const args = $derived(
51
- intervalY(intervalX({ data, ...options }, { plot }), { plot }) as RectMarkProps
52
- );
57
+ const args = $derived(intervalY(intervalX({ data, ...options })) as RectMarkProps);
53
58
  </script>
54
59
 
55
60
  <Mark
@@ -59,32 +64,52 @@
59
64
  {...markProps}
60
65
  {...args}>
61
66
  {#snippet children({ usedScales, scaledData })}
62
- <GroupMultiple class={scaledData.length > 1 ? className : null} length={scaledData.length}>
63
- {#each scaledData as d, i (i)}
64
- {#if d.valid}
65
- {@const x1 = d.x1 == null ? plot.options.marginLeft + d.dx : d.x1}
66
- {@const x2 =
67
- d.x2 == null ? plot.options.marginLeft + plot.facetWidth + d.dx : d.x2}
68
- {@const y1 = d.y1 == null ? plot.options.marginTop + d.dy : d.y1}
69
- {@const y2 =
70
- d.y2 == null ? plot.options.marginTop + plot.facetHeight + d.dy : d.y2}
67
+ {#if canvas}
68
+ {@const rectCanvasData = scaledData.map((d) => {
69
+ const x1 = d.x1 == null ? plot.options.marginLeft + d.dx : d.x1;
70
+ const x2 = d.x2 == null ? plot.options.marginLeft + plot.facetWidth + d.dx : d.x2;
71
+ const y1 = d.y1 == null ? plot.options.marginTop + d.dy : d.y1;
72
+ const y2 = d.y2 == null ? plot.options.marginTop + plot.facetHeight + d.dy : d.y2;
73
+ const minx = Math.min(x1, x2);
74
+ const maxx = Math.max(x1, x2);
75
+ const miny = Math.min(y1, y2);
76
+ const maxy = Math.max(y1, y2);
77
+
78
+ return { ...d, x1: minx, x2: maxx, y1: miny, y2: maxy };
79
+ })}
80
+ <GroupMultiple class={className} length={scaledData.length}>
81
+ <RectCanvas options={args} data={rectCanvasData} {usedScales} />
82
+ </GroupMultiple>
83
+ {:else}
84
+ <GroupMultiple
85
+ class={scaledData.length > 1 ? className : null}
86
+ length={scaledData.length}>
87
+ {#each scaledData as d, i (i)}
88
+ {#if d.valid}
89
+ {@const x1 = d.x1 == null ? plot.options.marginLeft + d.dx : d.x1}
90
+ {@const x2 =
91
+ d.x2 == null ? plot.options.marginLeft + plot.facetWidth + d.dx : d.x2}
92
+ {@const y1 = d.y1 == null ? plot.options.marginTop + d.dy : d.y1}
93
+ {@const y2 =
94
+ d.y2 == null ? plot.options.marginTop + plot.facetHeight + d.dy : d.y2}
71
95
 
72
- {@const miny = Math.min(y1, y2)}
73
- {@const maxy = Math.max(y1, y2)}
74
- {@const minx = Math.min(x1, x2)}
75
- {@const maxx = Math.max(x1, x2)}
96
+ {@const miny = Math.min(y1, y2)}
97
+ {@const maxy = Math.max(y1, y2)}
98
+ {@const minx = Math.min(x1, x2)}
99
+ {@const maxx = Math.max(x1, x2)}
76
100
 
77
- <RectPath
78
- datum={d}
79
- class={scaledData.length === 1 ? className : null}
80
- x={minx}
81
- y={miny}
82
- width={maxx - minx}
83
- height={maxy - miny}
84
- options={args}
85
- {usedScales} />
86
- {/if}
87
- {/each}
88
- </GroupMultiple>
101
+ <RectPath
102
+ datum={d}
103
+ class={scaledData.length === 1 ? className : null}
104
+ x={minx}
105
+ y={miny}
106
+ width={maxx - minx}
107
+ height={maxy - miny}
108
+ options={args}
109
+ {usedScales} />
110
+ {/if}
111
+ {/each}
112
+ </GroupMultiple>
113
+ {/if}
89
114
  {/snippet}
90
115
  </Mark>
@@ -72,7 +72,11 @@ declare function $$render<Datum extends DataRecord>(): {
72
72
  y1?: ChannelAccessor<Datum>;
73
73
  y2?: ChannelAccessor<Datum>;
74
74
  interval?: number | string;
75
- className?: string;
75
+ class?: string;
76
+ /**
77
+ * Renders using Canvas instead of SVG.
78
+ */
79
+ canvas?: boolean;
76
80
  };
77
81
  exports: {};
78
82
  bindings: "";
@@ -33,7 +33,7 @@
33
33
 
34
34
  const plot = usePlot();
35
35
 
36
- const args = $derived(stackX(intervalY(recordizeX({ data, ...options }), { plot }), stack));
36
+ const args = $derived(stackX(intervalY(recordizeX({ data, ...options })), stack));
37
37
  </script>
38
38
 
39
39
  <Rect {...args}></Rect>
@@ -31,7 +31,7 @@
31
31
 
32
32
  const plot = usePlot();
33
33
 
34
- const args = $derived(stackY(intervalX(recordizeY({ data, ...options }), { plot }), stack));
34
+ const args = $derived(stackY(intervalX(recordizeY({ data, ...options })), stack));
35
35
  </script>
36
36
 
37
37
  <Rect {...args}></Rect>
@@ -64,8 +64,7 @@
64
64
  stackX(
65
65
  intervalX(
66
66
  // by default, sort by y channel (the ordinal labels)
67
- sort(recordizeX({ data, ...options })),
68
- { plot }
67
+ sort(recordizeX({ data, ...options }))
69
68
  ),
70
69
  stack
71
70
  )
@@ -61,8 +61,7 @@
61
61
  stackY(
62
62
  intervalY(
63
63
  // by default, sort by y channel (the ordinal labels)
64
- sort(recordizeY({ data, ...options })),
65
- { plot }
64
+ sort(recordizeY({ data, ...options }))
66
65
  ),
67
66
  stack
68
67
  )
@@ -42,7 +42,7 @@
42
42
  };
43
43
  text: boolean;
44
44
  plot: PlotState;
45
- class: string;
45
+ class: string | undefined;
46
46
  };
47
47
 
48
48
  let {
@@ -22,7 +22,7 @@ type BaseAxisXProps = {
22
22
  };
23
23
  text: boolean;
24
24
  plot: PlotState;
25
- class: string;
25
+ class: string | undefined;
26
26
  };
27
27
  declare const BaseAxisX: import("svelte").Component<BaseAxisXProps, {}, "">;
28
28
  type BaseAxisX = ReturnType<typeof BaseAxisX>;
@@ -36,7 +36,7 @@
36
36
  };
37
37
  plot: PlotState;
38
38
  text: boolean | null;
39
- class: string;
39
+ class: string | undefined;
40
40
  };
41
41
 
42
42
  let {
@@ -20,7 +20,7 @@ type BaseAxisYProps = {
20
20
  };
21
21
  plot: PlotState;
22
22
  text: boolean | null;
23
- class: string;
23
+ class: string | undefined;
24
24
  };
25
25
  declare const BaseAxisY: import("svelte").Component<BaseAxisYProps, {}, "">;
26
26
  type BaseAxisY = ReturnType<typeof BaseAxisY>;