svelteplot 0.12.0 → 0.13.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.
@@ -0,0 +1,150 @@
1
+ import type { DataRow, ChannelAccessor } from '../types/index.js';
2
+ import { type InterpolateFunction } from '../helpers/rasterInterpolate.js';
3
+ declare function $$render<Datum extends DataRow>(): {
4
+ props: {
5
+ /**
6
+ * Input data. For **dense grid** mode supply a flat row-major array and
7
+ * set `width`/`height`. Omit (or set null) for **function-sampling**
8
+ * mode. For **scatter interpolation** supply an array of records with
9
+ * `x`/`y` channels.
10
+ */
11
+ data?: Datum[] | null;
12
+ /** x position channel (scatter mode) */
13
+ x?: ChannelAccessor<Datum>;
14
+ /** y position channel (scatter mode) */
15
+ y?: ChannelAccessor<Datum>;
16
+ /**
17
+ * Scalar field accessor, identity function for dense grid, or an
18
+ * `(x, y) => number` function for function-sampling mode.
19
+ */
20
+ value?: ChannelAccessor<Datum> | ((x: number, y: number) => number);
21
+ /**
22
+ * Contour threshold levels. Can be:
23
+ * - a **count** (number): approximately that many nicely-spaced levels
24
+ * - an explicit **array** of threshold values
25
+ * - a **function** `(values, min, max) => number[]`
26
+ * - a d3 **threshold scheme** object with `.floor()` / `.range()`
27
+ *
28
+ * Defaults to Sturges' formula applied to the value range.
29
+ */
30
+ thresholds?: number | number[] | ((values: number[], min: number, max: number) => number[]) | {
31
+ floor(x: number): number;
32
+ range(a: number, b: number): number[];
33
+ };
34
+ /**
35
+ * Step interval between contour levels (alternative to `thresholds`).
36
+ * Can be a number (constant step) or an interval object with `.floor()`
37
+ * / `.range()`.
38
+ */
39
+ interval?: number | {
40
+ floor(x: number): number;
41
+ range(a: number, b: number): number[];
42
+ };
43
+ /**
44
+ * Whether to apply linear interpolation when tracing contour edges
45
+ * (default `true`). Set to `false` for a blockier, faster appearance.
46
+ */
47
+ smooth?: boolean;
48
+ /** left bound of the domain in data coordinates */
49
+ x1?: number;
50
+ /** top bound of the domain in data coordinates */
51
+ y1?: number;
52
+ /** right bound of the domain in data coordinates */
53
+ x2?: number;
54
+ /** bottom bound of the domain in data coordinates */
55
+ y2?: number;
56
+ /**
57
+ * Explicit grid width; required for dense grid mode, overrides
58
+ * `pixelSize` in other modes.
59
+ */
60
+ width?: number;
61
+ /**
62
+ * Explicit grid height; required for dense grid mode, overrides
63
+ * `pixelSize` in other modes.
64
+ */
65
+ height?: number;
66
+ /** pixel size in screen pixels (default 2) */
67
+ pixelSize?: number;
68
+ /** Gaussian blur radius applied before contouring (default 0) */
69
+ blur?: number;
70
+ /**
71
+ * Spatial interpolation for scatter mode:
72
+ * `"none"` | `"nearest"` | `"barycentric"` | `"random-walk"` or a
73
+ * custom `(index, w, h, X, Y, V) => W` function.
74
+ * Defaults to `"nearest"` when data is provided.
75
+ */
76
+ interpolate?: "none" | "nearest" | "barycentric" | "random-walk" | InterpolateFunction;
77
+ /**
78
+ * Fill color for contour polygons. Use `"value"` to map each
79
+ * threshold level through the plot's color scale. Default `"none"`.
80
+ *
81
+ * **Shorthand**: if `value` is omitted and `fill` is a field name or
82
+ * accessor function (not a CSS color), it is automatically promoted to
83
+ * the `value` channel and `fill` is set to `"value"`.
84
+ */
85
+ fill?: string | ChannelAccessor<Datum>;
86
+ /**
87
+ * Stroke color for contour lines. Use `"value"` to map each
88
+ * threshold level through the plot's color scale. Default
89
+ * `"currentColor"`.
90
+ *
91
+ * **Shorthand**: if `value` is omitted and `stroke` is a field name or
92
+ * accessor function (not a CSS color), it is automatically promoted to
93
+ * the `value` channel and `stroke` is set to `"value"`.
94
+ */
95
+ stroke?: string | ChannelAccessor<Datum>;
96
+ strokeWidth?: number;
97
+ strokeOpacity?: number;
98
+ fillOpacity?: number;
99
+ opacity?: number;
100
+ strokeMiterlimit?: number;
101
+ clipPath?: string;
102
+ class?: string;
103
+ /** the horizontal facet channel */
104
+ fx?: ChannelAccessor<Datum>;
105
+ /** the vertical facet channel */
106
+ fy?: ChannelAccessor<Datum>;
107
+ };
108
+ exports: {};
109
+ bindings: "";
110
+ slots: {};
111
+ events: {};
112
+ };
113
+ declare class __sveltets_Render<Datum extends DataRow> {
114
+ props(): ReturnType<typeof $$render<Datum>>['props'];
115
+ events(): ReturnType<typeof $$render<Datum>>['events'];
116
+ slots(): ReturnType<typeof $$render<Datum>>['slots'];
117
+ bindings(): "";
118
+ exports(): {};
119
+ }
120
+ interface $$IsomorphicComponent {
121
+ new <Datum extends DataRow>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Datum>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Datum>['props']>, ReturnType<__sveltets_Render<Datum>['events']>, ReturnType<__sveltets_Render<Datum>['slots']>> & {
122
+ $$bindings?: ReturnType<__sveltets_Render<Datum>['bindings']>;
123
+ } & ReturnType<__sveltets_Render<Datum>['exports']>;
124
+ <Datum extends DataRow>(internal: unknown, props: ReturnType<__sveltets_Render<Datum>['props']> & {}): ReturnType<__sveltets_Render<Datum>['exports']>;
125
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
126
+ }
127
+ /**
128
+ * Renders contour lines (or filled contour bands) from a scalar field using
129
+ * the marching-squares algorithm.
130
+ *
131
+ * Supports the same three input modes as the `Raster` mark:
132
+ *
133
+ * **Dense grid mode** (`data` is a flat row-major array, `width`/`height` are
134
+ * set, no `x`/`y` channels): each datum is its own scalar value (unless `value`
135
+ * is specified).
136
+ *
137
+ * **Function sampling mode** (`data` is omitted/null, `value` is an
138
+ * `(x, y) => number` function): the function is evaluated on a pixel grid.
139
+ *
140
+ * **Scatter interpolation mode** (`data` is an array with `x`/`y` channels):
141
+ * each datum contributes a position and scalar value; the mark spatially
142
+ * interpolates over the grid before running marching squares.
143
+ *
144
+ * Styling: `fill` and `stroke` accept ordinary CSS color strings **or** the
145
+ * special keyword `"value"`, which maps each contour level's threshold through
146
+ * the plot's color scale. Defaults: `fill="none"`, `stroke="currentColor"`.
147
+ */
148
+ declare const Contour: $$IsomorphicComponent;
149
+ type Contour<Datum extends DataRow> = InstanceType<typeof Contour<Datum>>;
150
+ export default Contour;
@@ -22,7 +22,8 @@
22
22
  title?: ConstantAccessor<string, Datum>;
23
23
  /** the SVG preserveAspectRatio attribute for the image (e.g. "xMidYMid meet") */
24
24
  preserveAspectRatio?: string;
25
- // canvas?: boolean;
25
+ /** if true, renders using Canvas instead of SVG */
26
+ canvas?: boolean;
26
27
  /** CSS class name(s) to apply to individual image elements */
27
28
  imageClass?: ConstantAccessor<string, Datum>;
28
29
  }
@@ -39,6 +40,7 @@
39
40
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
40
41
  import { sort } from '../transforms/index.js';
41
42
  import Anchor from './helpers/Anchor.svelte';
43
+ import ImageCanvas from './helpers/ImageCanvas.svelte';
42
44
  import Mark from '../Mark.svelte';
43
45
 
44
46
  let markProps: ImageMarkProps = $props();
@@ -51,6 +53,7 @@
51
53
 
52
54
  const {
53
55
  data = [{} as Datum],
56
+ canvas = false,
54
57
  width,
55
58
  height,
56
59
  src,
@@ -71,31 +74,38 @@
71
74
  channels={['x', 'y', 'r', 'fill', 'opacity', 'stroke', 'fillOpacity', 'strokeOpacity']}
72
75
  {...args}
73
76
  type="image">
74
- {#snippet children({ scaledData })}
75
- {#each scaledData as record, i (i)}
76
- {#if record.valid}
77
- {@const w =
78
- record.r !== undefined
79
- ? record.r * 2
80
- : Number(resolveProp(width, record.datum, 20) ?? 20)}
81
- {@const h =
82
- record.r !== undefined
83
- ? record.r * 2
84
- : Number(resolveProp(height || width, record.datum, 20) ?? 20)}
85
- <Anchor {options} datum={record.datum}>
86
- <image
87
- class={resolveProp(imageClass, record.datum, null)}
88
- href={resolveProp(src, record.datum, '')}
89
- x={record.x! - w * 0.5}
90
- y={record.y! - h * 0.5}
91
- {preserveAspectRatio}
92
- clip-path={record.r !== undefined ? `circle(${record.r}px)` : null}
93
- width={w}
94
- height={h}
95
- >{#if title}<title>{resolveProp(title, record.datum, '')}</title
96
- >{/if}</image>
97
- </Anchor>
98
- {/if}
99
- {/each}
77
+ {#snippet children({ scaledData, usedScales })}
78
+ {#if canvas}
79
+ <ImageCanvas
80
+ data={scaledData}
81
+ options={{ ...options, src, width, height }}
82
+ {usedScales} />
83
+ {:else}
84
+ {#each scaledData as record, i (i)}
85
+ {#if record.valid}
86
+ {@const w =
87
+ record.r !== undefined
88
+ ? record.r * 2
89
+ : Number(resolveProp(width, record.datum, 20) ?? 20)}
90
+ {@const h =
91
+ record.r !== undefined
92
+ ? record.r * 2
93
+ : Number(resolveProp(height || width, record.datum, 20) ?? 20)}
94
+ <Anchor {options} datum={record.datum}>
95
+ <image
96
+ class={resolveProp(imageClass, record.datum, null)}
97
+ href={resolveProp(src, record.datum, '')}
98
+ x={record.x! - w * 0.5}
99
+ y={record.y! - h * 0.5}
100
+ {preserveAspectRatio}
101
+ clip-path={record.r !== undefined ? `circle(${record.r}px)` : null}
102
+ width={w}
103
+ height={h}
104
+ >{#if title}<title>{resolveProp(title, record.datum, '')}</title
105
+ >{/if}</image>
106
+ </Anchor>
107
+ {/if}
108
+ {/each}
109
+ {/if}
100
110
  {/snippet}
101
111
  </Mark>
@@ -154,6 +154,8 @@ declare function $$render<Datum extends DataRecord>(): {
154
154
  title?: ConstantAccessor<string, Datum>;
155
155
  /** the SVG preserveAspectRatio attribute for the image (e.g. "xMidYMid meet") */
156
156
  preserveAspectRatio?: string;
157
+ /** if true, renders using Canvas instead of SVG */
158
+ canvas?: boolean;
157
159
  /** CSS class name(s) to apply to individual image elements */
158
160
  imageClass?: ConstantAccessor<string, Datum>;
159
161
  };
@@ -45,6 +45,8 @@
45
45
  textStartOffset?: ConstantAccessor<string, Datum>;
46
46
  /** the stroke width for the text label rendered along the link */
47
47
  textStrokeWidth?: ConstantAccessor<number, Datum>;
48
+ /** if true, renders using Canvas instead of SVG */
49
+ canvas?: boolean;
48
50
  }
49
51
  import type {
50
52
  DataRecord,
@@ -65,6 +67,7 @@
65
67
  import { maybeCurve } from '../helpers/curves.js';
66
68
  import { geoPath } from 'd3-geo';
67
69
  import { pick } from 'es-toolkit';
70
+ import LinkCanvas from './helpers/LinkCanvas.svelte';
68
71
  import { sort } from '../transforms/sort.js';
69
72
  import { indexData } from '../transforms/recordize.js';
70
73
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
@@ -81,6 +84,7 @@
81
84
  tension = 0,
82
85
  bend,
83
86
  text,
87
+ canvas,
84
88
  class: className = '',
85
89
  ...options
86
90
  }: LinkMarkProps = $derived({
@@ -103,6 +107,13 @@
103
107
 
104
108
  const sphericalLine = $derived(plot.scales.projection && curve === 'auto');
105
109
 
110
+ const curveFactory = $derived(
111
+ maybeCurve(
112
+ curve === 'auto' ? 'linear' : curve,
113
+ bend === true ? 0.6 : bend === false ? 0 : (bend ?? tension ?? 0)
114
+ )
115
+ );
116
+
106
117
  const linePath: (d: ScaledDataRecord, reversed?: boolean) => string | null = $derived.by(() => {
107
118
  const fn: D3Line<[number, number]> = line<[number, number]>()
108
119
  .curve(
@@ -168,56 +179,63 @@
168
179
  channels={['x1', 'y1', 'x2', 'y2', 'opacity', 'stroke', 'strokeOpacity']}
169
180
  {...args}>
170
181
  {#snippet children({ mark, scaledData, usedScales })}
171
- <g class={['link', className]} data-use-x={usedScales.x ? 1 : 0}>
172
- {#each scaledData as d, i (i)}
173
- {#if d.valid || true}
174
- {@const [style, styleClass] = resolveStyles(
175
- plot,
176
- d,
177
- { strokeWidth: 1.6, ...args },
178
- 'stroke',
179
- usedScales
180
- )}
181
- {@const [textStyle, textStyleClass] = resolveStyles(
182
- plot,
183
- d,
184
- {
185
- textAnchor: 'middle',
186
- ...pick(args, ['fontSize', 'fontWeight', 'fontStyle']),
187
- fill: options.textFill || args.stroke,
188
- stroke: options.textStroke,
189
- strokeWidth: options.textStrokeWidth
190
- },
191
- 'fill',
192
- usedScales
193
- )}
182
+ {#if canvas}
183
+ <LinkCanvas data={scaledData} options={args} {usedScales} {curveFactory} />
184
+ {:else}
185
+ <g class={['link', className]} data-use-x={usedScales.x ? 1 : 0}>
186
+ {#each scaledData as d, i (i)}
187
+ {#if d.valid || true}
188
+ {@const [style, styleClass] = resolveStyles(
189
+ plot,
190
+ d,
191
+ { strokeWidth: 1.6, ...args },
192
+ 'stroke',
193
+ usedScales
194
+ )}
195
+ {@const [textStyle, textStyleClass] = resolveStyles(
196
+ plot,
197
+ d,
198
+ {
199
+ textAnchor: 'middle',
200
+ ...pick(args, ['fontSize', 'fontWeight', 'fontStyle']),
201
+ fill: options.textFill || args.stroke,
202
+ stroke: options.textStroke,
203
+ strokeWidth: options.textStrokeWidth
204
+ },
205
+ 'fill',
206
+ usedScales
207
+ )}
194
208
 
195
- <MarkerPath
196
- mark={{ ...mark, options: args }}
197
- transform=""
198
- scales={plot.scales}
199
- markerStart={options.markerStart as boolean | MarkerShape | undefined}
200
- markerEnd={options.markerEnd as boolean | MarkerShape | undefined}
201
- marker={options.marker as boolean | MarkerShape | undefined}
202
- markerScale={options.markerScale}
203
- class={styleClass ?? undefined}
204
- strokeWidth={options.strokeWidth as ConstantAccessor<number>}
205
- datum={d.datum as DataRecord}
206
- color={d.stroke ?? 'currentColor'}
207
- d={(sphericalLine ? sphericalLinePath(d) : linePath(d)) ?? ''}
208
- dInv={(sphericalLine ? sphericalLinePath(d, true) : linePath(d, true)) ??
209
- undefined}
210
- style={style ?? ''}
211
- text={text ? ((resolveProp(text, d.datum as Datum) as string) ?? '') : ''}
212
- startOffset={(resolveProp(
213
- options.textStartOffset,
214
- d.datum as Datum,
215
- '50%'
216
- ) as string) ?? '50%'}
217
- textStyle={textStyle ?? ''}
218
- {textStyleClass} />
219
- {/if}
220
- {/each}
221
- </g>
209
+ <MarkerPath
210
+ mark={{ ...mark, options: args }}
211
+ transform=""
212
+ scales={plot.scales}
213
+ markerStart={options.markerStart as boolean | MarkerShape | undefined}
214
+ markerEnd={options.markerEnd as boolean | MarkerShape | undefined}
215
+ marker={options.marker as boolean | MarkerShape | undefined}
216
+ markerScale={options.markerScale}
217
+ class={styleClass ?? undefined}
218
+ strokeWidth={options.strokeWidth as ConstantAccessor<number>}
219
+ datum={d.datum as DataRecord}
220
+ color={d.stroke ?? 'currentColor'}
221
+ d={(sphericalLine ? sphericalLinePath(d) : linePath(d)) ?? ''}
222
+ dInv={(sphericalLine
223
+ ? sphericalLinePath(d, true)
224
+ : linePath(d, true)) ?? undefined}
225
+ style={style ?? ''}
226
+ text={text
227
+ ? ((resolveProp(text, d.datum as Datum) as string) ?? '')
228
+ : ''}
229
+ startOffset={(resolveProp(
230
+ options.textStartOffset,
231
+ d.datum as Datum,
232
+ '50%'
233
+ ) as string) ?? '50%'}
234
+ textStyle={textStyle ?? ''}
235
+ {textStyleClass} />
236
+ {/if}
237
+ {/each}
238
+ </g>
239
+ {/if}
222
240
  {/snippet}
223
241
  </Mark>
@@ -180,6 +180,8 @@ declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
180
180
  textStartOffset?: ConstantAccessor<string, Datum>;
181
181
  /** the stroke width for the text label rendered along the link */
182
182
  textStrokeWidth?: ConstantAccessor<number, Datum>;
183
+ /** if true, renders using Canvas instead of SVG */
184
+ canvas?: boolean;
183
185
  };
184
186
  exports: {};
185
187
  bindings: "";
@@ -90,6 +90,11 @@
90
90
  } from '../helpers/rasterInterpolate.js';
91
91
  import { X, Y, RAW_VALUE } from '../transforms/recordize.js';
92
92
  import { scaleLinear } from 'd3-scale';
93
+ import { getPlotDefaults } from '../hooks/plotDefaults.js';
94
+
95
+ const DEFAULTS = {
96
+ ...getPlotDefaults().raster
97
+ };
93
98
 
94
99
  let markProps: RasterMarkProps = $props();
95
100
 
@@ -108,7 +113,7 @@
108
113
  interpolate,
109
114
  imageRendering = 'auto',
110
115
  ...options
111
- }: RasterMarkProps = $derived({ ...markProps });
116
+ }: RasterMarkProps = $derived({ ...DEFAULTS, ...markProps });
112
117
 
113
118
  const plot = usePlot();
114
119
 
@@ -3,10 +3,7 @@
3
3
  The vector mark lets you place shapes (like arrows) on your plot.
4
4
  -->
5
5
  <script lang="ts" module>
6
- type D3Path = ReturnType<typeof import('d3-path').path>;
7
- export type ShapeRenderer = {
8
- draw(context: D3Path, l: number, r: number): void;
9
- };
6
+ export type { ShapeRenderer } from '../helpers/vectorShapes.js';
10
7
  </script>
11
8
 
12
9
  <script lang="ts" generics="Datum = DataRecord | GeoJSON.GeoJsonObject">
@@ -45,25 +42,23 @@
45
42
  } from '../types/index.js';
46
43
 
47
44
  import { getContext, type Snippet } from 'svelte';
48
- import { pathRound as path } from 'd3-path';
49
45
 
50
46
  import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
51
47
  import { sort } from '../index.js';
52
48
  import Mark from '../Mark.svelte';
53
- //import DotCanvas from './helpers/DotCanvas.svelte';
49
+ import VectorCanvas from './helpers/VectorCanvas.svelte';
54
50
  import { isValid } from '../helpers/index.js';
55
51
  import { addEventHandlers } from './helpers/events.js';
56
52
  import { indexData } from '../transforms/recordize.js';
57
53
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
58
54
  import { usePlot } from '../hooks/usePlot.svelte.js';
59
55
 
60
- const defaultRadius = 3;
61
-
62
- // The size of the arrowhead is proportional to its length, but we still allow
63
- // the relative size of the head to be controlled via the mark's width option;
64
- // doubling the default radius will produce an arrowhead that is twice as big.
65
- // That said, we'll probably want a arrow with a fixed head size, too.
66
- const wingRatio = defaultRadius * 5;
56
+ import {
57
+ defaultRadius,
58
+ maybeShape,
59
+ shapePath,
60
+ type ShapeRenderer
61
+ } from '../helpers/vectorShapes.js';
67
62
 
68
63
  let markProps: VectorMarkProps = $props();
69
64
  const DEFAULTS = {
@@ -83,72 +78,6 @@
83
78
 
84
79
  const plot = usePlot();
85
80
 
86
- const shapeArrow: ShapeRenderer = {
87
- draw(context: D3Path, l: number, r: number) {
88
- const wing = (l * r) / wingRatio;
89
- context.moveTo(0, 0);
90
- context.lineTo(0, -l);
91
- context.moveTo(-wing, wing - l);
92
- context.lineTo(0, -l);
93
- context.lineTo(wing, wing - l);
94
- }
95
- };
96
-
97
- const shapeSpike: ShapeRenderer = {
98
- draw(context: D3Path, l: number, r: number) {
99
- context.moveTo(-r, 0);
100
- context.lineTo(0, -l);
101
- context.lineTo(r, 0);
102
- }
103
- };
104
-
105
- const shapeArrowFilled: ShapeRenderer = {
106
- draw(context: D3Path, l: number, r: number) {
107
- // const wing = (l * r) / wingRatio;
108
- const headLength = Math.max(3, l * 0.3);
109
- const headSpike = headLength * 0.2;
110
- const headWidth = Math.max(2, l * 0.3);
111
- const tailWidth = Math.max(2, l * 0.3) * 0.3;
112
-
113
- context.moveTo(0, 0);
114
-
115
- context.lineTo(tailWidth * 0.5, -l + headLength - headSpike);
116
- context.lineTo(headWidth * 0.5, -l + headLength);
117
- context.lineTo(0, -l);
118
- context.lineTo(-headWidth * 0.5, -l + headLength);
119
- context.lineTo(-tailWidth * 0.5, -l + headLength - headSpike);
120
-
121
- context.closePath();
122
- }
123
- };
124
-
125
- const shapes = new Map([
126
- ['arrow', shapeArrow],
127
- ['arrow-filled', shapeArrowFilled],
128
- ['spike', shapeSpike]
129
- ]);
130
-
131
- function isShapeObject(value: any): value is ShapeRenderer {
132
- return value && typeof value.draw === 'function';
133
- }
134
-
135
- function maybeShape(shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer) {
136
- if (isShapeObject(shape)) return shape;
137
- const value = shapes.get(`${shape}`.toLowerCase());
138
- if (value) return value;
139
- throw new Error(`invalid shape: ${shape}`);
140
- }
141
-
142
- function shapePath(
143
- shape: 'arrow' | 'spike' | 'arrow-filled' | ShapeRenderer,
144
- l: number,
145
- r: number
146
- ) {
147
- const context = path();
148
- maybeShape(shape).draw(context, l, r);
149
- return context.toString();
150
- }
151
-
152
81
  const args = $derived(
153
82
  sort({
154
83
  data: indexData(data as object[]) as unknown as Datum[],
@@ -177,8 +106,10 @@
177
106
  {#snippet children({ scaledData, usedScales })}
178
107
  <g class="vector" data-l={usedScales.length}>
179
108
  {#if canvas}
180
- <text x="30" y="30" style="color:red"
181
- >implement canvas rendering for vector mark</text>
109
+ <VectorCanvas
110
+ data={scaledData}
111
+ options={{ ...args, shape, anchor } as any}
112
+ {usedScales} />
182
113
  {:else}
183
114
  {#each scaledData as d, i (i)}
184
115
  {#if d.valid && isValid(d.r)}
@@ -1,9 +1,7 @@
1
- type D3Path = ReturnType<typeof import('d3-path').path>;
2
- export type ShapeRenderer = {
3
- draw(context: D3Path, l: number, r: number): void;
4
- };
1
+ export type { ShapeRenderer } from '../helpers/vectorShapes.js';
5
2
  import type { DataRecord, ChannelAccessor } from '../types/index.js';
6
3
  import { type Snippet } from 'svelte';
4
+ import { type ShapeRenderer } from '../helpers/vectorShapes.js';
7
5
  declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
8
6
  props: Partial<{
9
7
  filter: import("../types/index.js").ConstantAccessor<boolean, Datum>;