svelteplot 0.13.0 → 0.14.0-pr-545.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/helpers/group.d.ts +1 -1
  2. package/dist/helpers/group.js +3 -3
  3. package/dist/marks/ColorLegend.svelte +5 -1
  4. package/dist/marks/Contour.svelte +21 -30
  5. package/dist/marks/Contour.svelte.d.ts +2 -0
  6. package/dist/marks/DelaunayLink.svelte +127 -0
  7. package/dist/marks/DelaunayLink.svelte.d.ts +175 -0
  8. package/dist/marks/DelaunayMesh.svelte +102 -0
  9. package/dist/marks/DelaunayMesh.svelte.d.ts +172 -0
  10. package/dist/marks/Density.svelte +552 -0
  11. package/dist/marks/Density.svelte.d.ts +108 -0
  12. package/dist/marks/Hull.svelte +103 -0
  13. package/dist/marks/Hull.svelte.d.ts +175 -0
  14. package/dist/marks/Voronoi.svelte +118 -0
  15. package/dist/marks/Voronoi.svelte.d.ts +172 -0
  16. package/dist/marks/VoronoiMesh.svelte +109 -0
  17. package/dist/marks/VoronoiMesh.svelte.d.ts +172 -0
  18. package/dist/marks/helpers/DensityCanvas.svelte +118 -0
  19. package/dist/marks/helpers/DensityCanvas.svelte.d.ts +18 -0
  20. package/dist/marks/helpers/GeoPathCanvas.svelte +130 -0
  21. package/dist/marks/helpers/GeoPathCanvas.svelte.d.ts +24 -0
  22. package/dist/marks/helpers/GeoPathGroup.svelte +104 -0
  23. package/dist/marks/helpers/GeoPathGroup.svelte.d.ts +37 -0
  24. package/dist/marks/helpers/PathGroup.svelte +100 -0
  25. package/dist/marks/helpers/PathGroup.svelte.d.ts +16 -0
  26. package/dist/marks/helpers/PathItems.svelte +112 -0
  27. package/dist/marks/helpers/PathItems.svelte.d.ts +16 -0
  28. package/dist/marks/index.d.ts +7 -1
  29. package/dist/marks/index.js +7 -1
  30. package/dist/types/mark.d.ts +1 -1
  31. package/dist/types/plot.d.ts +25 -1
  32. package/package.json +1 -1
@@ -0,0 +1,103 @@
1
+ <!-- @component
2
+ Renders the convex hull of data points. Supports grouping by z/fill/stroke
3
+ to draw separate hulls per group.
4
+ -->
5
+ <script lang="ts" generics="Datum = DataRecord">
6
+ interface HullMarkProps extends BaseMarkProps<Datum> {
7
+ /** the input data array */
8
+ data?: Datum[];
9
+ /** the horizontal position channel */
10
+ x?: ChannelAccessor<Datum>;
11
+ /** the vertical position channel */
12
+ y?: ChannelAccessor<Datum>;
13
+ /** the grouping channel; separate hulls per group */
14
+ z?: ChannelAccessor<Datum>;
15
+ /** Render using a canvas element instead of SVG paths. */
16
+ canvas?: boolean;
17
+ }
18
+
19
+ import { Delaunay } from 'd3-delaunay';
20
+ import type {
21
+ DataRecord,
22
+ BaseMarkProps,
23
+ ChannelAccessor,
24
+ MarkType,
25
+ ScaledDataRecord
26
+ } from '../types/index.js';
27
+ import { groupFacetsAndZ } from '../helpers/group.js';
28
+ import { recordizeXY } from '../transforms/recordize.js';
29
+ import Mark from '../Mark.svelte';
30
+ import PathGroup from './helpers/PathGroup.svelte';
31
+ import { usePlot } from '../hooks/usePlot.svelte.js';
32
+ import { getPlotDefaults } from '../hooks/plotDefaults.js';
33
+
34
+ const DEFAULTS = {
35
+ ...getPlotDefaults().hull
36
+ };
37
+
38
+ let markProps: HullMarkProps = $props();
39
+
40
+ const {
41
+ data = [] as Datum[],
42
+ class: className = 'hull',
43
+ canvas = false,
44
+ ...options
45
+ }: HullMarkProps = $derived({ ...DEFAULTS, ...markProps });
46
+
47
+ const args = $derived(
48
+ recordizeXY({
49
+ data: data as any[],
50
+ ...options
51
+ })
52
+ );
53
+
54
+ const plot = usePlot();
55
+
56
+ function computeHulls(scaledData: ScaledDataRecord[]) {
57
+ const scaledByDatum = new Map(scaledData.map((d) => [d.datum, d]));
58
+ const hulls: { path: string; datum: ScaledDataRecord }[] = [];
59
+
60
+ groupFacetsAndZ(
61
+ scaledData.map((d) => d.datum),
62
+ args,
63
+ (groupItems) => {
64
+ const groupScaled = groupItems
65
+ .map((d) => scaledByDatum.get(d))
66
+ .filter(
67
+ (d): d is ScaledDataRecord =>
68
+ d !== undefined &&
69
+ d.valid &&
70
+ Number.isFinite(d.x as number) &&
71
+ Number.isFinite(d.y as number)
72
+ );
73
+ if (groupScaled.length < 2) return;
74
+ const delaunay = Delaunay.from(
75
+ groupScaled,
76
+ (d) => d.x as number,
77
+ (d) => d.y as number
78
+ );
79
+ const path = delaunay.renderHull();
80
+ if (path) hulls.push({ path, datum: groupScaled[0] });
81
+ }
82
+ );
83
+
84
+ return hulls;
85
+ }
86
+ </script>
87
+
88
+ <Mark
89
+ type={'hull' as MarkType}
90
+ channels={['x', 'y', 'fill', 'opacity', 'stroke', 'fillOpacity', 'strokeOpacity']}
91
+ defaults={{ fill: 'none', stroke: 'currentColor' }}
92
+ {...args}>
93
+ {#snippet children({ scaledData, usedScales })}
94
+ <PathGroup
95
+ paths={computeHulls(scaledData)}
96
+ {args}
97
+ {className}
98
+ {usedScales}
99
+ {plot}
100
+ defaultStrokeWidth={1.5}
101
+ {canvas} />
102
+ {/snippet}
103
+ </Mark>
@@ -0,0 +1,175 @@
1
+ import type { DataRecord, ChannelAccessor } from '../types/index.js';
2
+ declare function $$render<Datum = DataRecord>(): {
3
+ props: Partial<{
4
+ filter: import("../types/index.js").ConstantAccessor<boolean, Datum>;
5
+ facet: "auto" | "include" | "exclude";
6
+ fx: ChannelAccessor<Datum>;
7
+ fy: ChannelAccessor<Datum>;
8
+ dx: import("../types/index.js").ConstantAccessor<number, Datum>;
9
+ dy: import("../types/index.js").ConstantAccessor<number, Datum>;
10
+ dodgeX: import("../transforms/dodge.js").DodgeXOptions;
11
+ dodgeY: import("../transforms/dodge.js").DodgeYOptions;
12
+ fill: ChannelAccessor<Datum>;
13
+ fillOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
14
+ fontFamily: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
+ fontSize: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
+ fontStyle: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
+ fontVariant: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
+ fontWeight: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
19
+ letterSpacing: import("../types/index.js").ConstantAccessor<import("csstype").Property.LetterSpacing<0 | (string & {})>, Datum>;
20
+ wordSpacing: import("../types/index.js").ConstantAccessor<import("csstype").Property.WordSpacing<0 | (string & {})>, Datum>;
21
+ textAnchor: import("../types/index.js").ConstantAccessor<import("csstype").Property.TextAnchor, Datum>;
22
+ textTransform: import("../types/index.js").ConstantAccessor<import("csstype").Property.TextTransform, Datum>;
23
+ textDecoration: import("../types/index.js").ConstantAccessor<import("csstype").Property.TextDecoration<0 | (string & {})>, Datum>;
24
+ sort: ((a: import("../types/data.js").RawValue, b: import("../types/data.js").RawValue) => number) | {
25
+ channel: string;
26
+ order?: "ascending" | "descending";
27
+ } | import("../types/index.js").ConstantAccessor<import("../types/data.js").RawValue, Datum>;
28
+ stroke: ChannelAccessor<Datum>;
29
+ strokeWidth: import("../types/index.js").ConstantAccessor<number, Datum>;
30
+ strokeOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
31
+ strokeLinejoin: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinejoin, Datum>;
32
+ strokeLinecap: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinecap, Datum>;
33
+ strokeMiterlimit: import("../types/index.js").ConstantAccessor<number, Datum>;
34
+ opacity: ChannelAccessor<Datum>;
35
+ strokeDasharray: import("../types/index.js").ConstantAccessor<string, Datum>;
36
+ strokeDashoffset: import("../types/index.js").ConstantAccessor<number, Datum>;
37
+ blend: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
38
+ mixBlendMode: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
39
+ clipPath: string;
40
+ mask: string;
41
+ imageFilter: import("../types/index.js").ConstantAccessor<string, Datum>;
42
+ shapeRendering: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Datum>;
43
+ paintOrder: import("../types/index.js").ConstantAccessor<string, Datum>;
44
+ onclick: (event: Event & {
45
+ currentTarget: SVGPathElement;
46
+ }, datum: Datum, index: number) => void;
47
+ ondblclick: (event: Event & {
48
+ currentTarget: SVGPathElement;
49
+ }, datum: Datum, index: number) => void;
50
+ onmouseup: (event: Event & {
51
+ currentTarget: SVGPathElement;
52
+ }, datum: Datum, index: number) => void;
53
+ onmousedown: (event: Event & {
54
+ currentTarget: SVGPathElement;
55
+ }, datum: Datum, index: number) => void;
56
+ onmouseenter: (event: Event & {
57
+ currentTarget: SVGPathElement;
58
+ }, datum: Datum, index: number) => void;
59
+ onmousemove: (event: Event & {
60
+ currentTarget: SVGPathElement;
61
+ }, datum: Datum, index: number) => void;
62
+ onmouseleave: (event: Event & {
63
+ currentTarget: SVGPathElement;
64
+ }, datum: Datum, index: number) => void;
65
+ onmouseout: (event: Event & {
66
+ currentTarget: SVGPathElement;
67
+ }, datum: Datum, index: number) => void;
68
+ onmouseover: (event: Event & {
69
+ currentTarget: SVGPathElement;
70
+ }, datum: Datum, index: number) => void;
71
+ onpointercancel: (event: Event & {
72
+ currentTarget: SVGPathElement;
73
+ }, datum: Datum, index: number) => void;
74
+ onpointerdown: (event: Event & {
75
+ currentTarget: SVGPathElement;
76
+ }, datum: Datum, index: number) => void;
77
+ onpointerup: (event: Event & {
78
+ currentTarget: SVGPathElement;
79
+ }, datum: Datum, index: number) => void;
80
+ onpointerenter: (event: Event & {
81
+ currentTarget: SVGPathElement;
82
+ }, datum: Datum, index: number) => void;
83
+ onpointerleave: (event: Event & {
84
+ currentTarget: SVGPathElement;
85
+ }, datum: Datum, index: number) => void;
86
+ onpointermove: (event: Event & {
87
+ currentTarget: SVGPathElement;
88
+ }, datum: Datum, index: number) => void;
89
+ onpointerover: (event: Event & {
90
+ currentTarget: SVGPathElement;
91
+ }, datum: Datum, index: number) => void;
92
+ onpointerout: (event: Event & {
93
+ currentTarget: SVGPathElement;
94
+ }, datum: Datum, index: number) => void;
95
+ ondrag: (event: Event & {
96
+ currentTarget: SVGPathElement;
97
+ }, datum: Datum, index: number) => void;
98
+ ondrop: (event: Event & {
99
+ currentTarget: SVGPathElement;
100
+ }, datum: Datum, index: number) => void;
101
+ ondragstart: (event: Event & {
102
+ currentTarget: SVGPathElement;
103
+ }, datum: Datum, index: number) => void;
104
+ ondragenter: (event: Event & {
105
+ currentTarget: SVGPathElement;
106
+ }, datum: Datum, index: number) => void;
107
+ ondragleave: (event: Event & {
108
+ currentTarget: SVGPathElement;
109
+ }, datum: Datum, index: number) => void;
110
+ ondragover: (event: Event & {
111
+ currentTarget: SVGPathElement;
112
+ }, datum: Datum, index: number) => void;
113
+ ondragend: (event: Event & {
114
+ currentTarget: SVGPathElement;
115
+ }, datum: Datum, index: number) => void;
116
+ ontouchstart: (event: Event & {
117
+ currentTarget: SVGPathElement;
118
+ }, datum: Datum, index: number) => void;
119
+ ontouchmove: (event: Event & {
120
+ currentTarget: SVGPathElement;
121
+ }, datum: Datum, index: number) => void;
122
+ ontouchend: (event: Event & {
123
+ currentTarget: SVGPathElement;
124
+ }, datum: Datum, index: number) => void;
125
+ ontouchcancel: (event: Event & {
126
+ currentTarget: SVGPathElement;
127
+ }, datum: Datum, index: number) => void;
128
+ oncontextmenu: (event: Event & {
129
+ currentTarget: SVGPathElement;
130
+ }, datum: Datum, index: number) => void;
131
+ onwheel: (event: Event & {
132
+ currentTarget: SVGPathElement;
133
+ }, datum: Datum, index: number) => void;
134
+ class: string;
135
+ style: string;
136
+ cursor: import("../types/index.js").ConstantAccessor<import("csstype").Property.Cursor, Datum>;
137
+ title: import("../types/index.js").ConstantAccessor<string, Datum>;
138
+ }> & {
139
+ /** the input data array */
140
+ data?: Datum[];
141
+ /** the horizontal position channel */
142
+ x?: ChannelAccessor<Datum>;
143
+ /** the vertical position channel */
144
+ y?: ChannelAccessor<Datum>;
145
+ /** the grouping channel; separate hulls per group */
146
+ z?: ChannelAccessor<Datum>;
147
+ /** Render using a canvas element instead of SVG paths. */
148
+ canvas?: boolean;
149
+ };
150
+ exports: {};
151
+ bindings: "";
152
+ slots: {};
153
+ events: {};
154
+ };
155
+ declare class __sveltets_Render<Datum = DataRecord> {
156
+ props(): ReturnType<typeof $$render<Datum>>['props'];
157
+ events(): ReturnType<typeof $$render<Datum>>['events'];
158
+ slots(): ReturnType<typeof $$render<Datum>>['slots'];
159
+ bindings(): "";
160
+ exports(): {};
161
+ }
162
+ interface $$IsomorphicComponent {
163
+ new <Datum = DataRecord>(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']>> & {
164
+ $$bindings?: ReturnType<__sveltets_Render<Datum>['bindings']>;
165
+ } & ReturnType<__sveltets_Render<Datum>['exports']>;
166
+ <Datum = DataRecord>(internal: unknown, props: ReturnType<__sveltets_Render<Datum>['props']> & {}): ReturnType<__sveltets_Render<Datum>['exports']>;
167
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
168
+ }
169
+ /**
170
+ * Renders the convex hull of data points. Supports grouping by z/fill/stroke
171
+ * to draw separate hulls per group.
172
+ */
173
+ declare const Hull: $$IsomorphicComponent;
174
+ type Hull<Datum = DataRecord> = InstanceType<typeof Hull<Datum>>;
175
+ export default Hull;
@@ -0,0 +1,118 @@
1
+ <!-- @component
2
+ Renders individual Voronoi cells, one per data point, allowing per-cell styling.
3
+ -->
4
+ <script lang="ts" generics="Datum = DataRecord">
5
+ interface VoronoiMarkProps extends BaseMarkProps<Datum>, LinkableMarkProps<Datum> {
6
+ /** the input data array */
7
+ data?: Datum[];
8
+ /** the horizontal position channel */
9
+ x?: ChannelAccessor<Datum>;
10
+ /** the vertical position channel */
11
+ y?: ChannelAccessor<Datum>;
12
+ /** the grouping channel; separate Voronoi diagrams per group */
13
+ z?: ChannelAccessor<Datum>;
14
+ /** Render using a canvas element instead of SVG paths. */
15
+ canvas?: boolean;
16
+ }
17
+
18
+ import { Delaunay } from 'd3-delaunay';
19
+ import type {
20
+ DataRecord,
21
+ BaseMarkProps,
22
+ ChannelAccessor,
23
+ LinkableMarkProps,
24
+ MarkType,
25
+ ScaledDataRecord
26
+ } from '../types/index.js';
27
+ import { groupFacetsAndZ } from '../helpers/group.js';
28
+ import { recordizeXY } from '../transforms/recordize.js';
29
+ import { sort } from '../index.js';
30
+ import Mark from '../Mark.svelte';
31
+ import PathItems from './helpers/PathItems.svelte';
32
+ import { usePlot } from '../hooks/usePlot.svelte.js';
33
+ import { getPlotDefaults } from '../hooks/plotDefaults.js';
34
+
35
+ const DEFAULTS = {
36
+ ...getPlotDefaults().voronoi
37
+ };
38
+
39
+ let markProps: VoronoiMarkProps = $props();
40
+
41
+ const {
42
+ data = [] as Datum[],
43
+ class: className = 'voronoi',
44
+ canvas = false,
45
+ ...options
46
+ }: VoronoiMarkProps = $derived({ ...DEFAULTS, ...markProps });
47
+
48
+ const args = $derived(
49
+ sort(
50
+ recordizeXY({
51
+ data: data as any[],
52
+ ...options
53
+ })
54
+ )
55
+ );
56
+
57
+ const plot = usePlot();
58
+
59
+ function computeVoronoi(scaledData: ScaledDataRecord[]) {
60
+ const x0 = plot.options.marginLeft;
61
+ const y0 = plot.options.marginTop;
62
+ const x1 = x0 + plot.facetWidth;
63
+ const y1 = y0 + plot.facetHeight;
64
+ if (!(x1 > x0) || !(y1 > y0)) return [];
65
+
66
+ const scaledByDatum = new Map(scaledData.map((d) => [d.datum, d]));
67
+ const results: { path: string; datum: ScaledDataRecord }[] = [];
68
+
69
+ groupFacetsAndZ(
70
+ scaledData.map((d) => d.datum),
71
+ args,
72
+ (groupItems) => {
73
+ const groupScaled = groupItems
74
+ .map((d) => scaledByDatum.get(d))
75
+ .filter(
76
+ (d): d is ScaledDataRecord =>
77
+ d !== undefined &&
78
+ d.valid &&
79
+ Number.isFinite(d.x as number) &&
80
+ Number.isFinite(d.y as number)
81
+ );
82
+ if (groupScaled.length < 2) return;
83
+
84
+ const delaunay = Delaunay.from(
85
+ groupScaled,
86
+ (d) => d.x as number,
87
+ (d) => d.y as number
88
+ );
89
+ const voronoi = delaunay.voronoi([x0, y0, x1, y1]);
90
+
91
+ groupScaled.forEach((d, cellIndex) => {
92
+ const path = voronoi.renderCell(cellIndex);
93
+ if (path) results.push({ path, datum: d });
94
+ });
95
+ },
96
+ false
97
+ );
98
+
99
+ return results;
100
+ }
101
+ </script>
102
+
103
+ <Mark
104
+ type={'voronoi' as MarkType}
105
+ channels={['x', 'y', 'fill', 'opacity', 'stroke', 'fillOpacity', 'strokeOpacity']}
106
+ defaults={{ fill: 'none', stroke: 'currentColor' }}
107
+ {...args}>
108
+ {#snippet children({ mark, usedScales, scaledData })}
109
+ <PathItems
110
+ paths={computeVoronoi(scaledData)}
111
+ {args}
112
+ {options}
113
+ {className}
114
+ {usedScales}
115
+ {plot}
116
+ {canvas} />
117
+ {/snippet}
118
+ </Mark>
@@ -0,0 +1,172 @@
1
+ import type { DataRecord, ChannelAccessor, LinkableMarkProps } from '../types/index.js';
2
+ declare function $$render<Datum = DataRecord>(): {
3
+ props: Partial<{
4
+ filter: import("../types/index.js").ConstantAccessor<boolean, Datum>;
5
+ facet: "auto" | "include" | "exclude";
6
+ fx: ChannelAccessor<Datum>;
7
+ fy: ChannelAccessor<Datum>;
8
+ dx: import("../types/index.js").ConstantAccessor<number, Datum>;
9
+ dy: import("../types/index.js").ConstantAccessor<number, Datum>;
10
+ dodgeX: import("../transforms/dodge.js").DodgeXOptions;
11
+ dodgeY: import("../transforms/dodge.js").DodgeYOptions;
12
+ fill: ChannelAccessor<Datum>;
13
+ fillOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
14
+ fontFamily: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
+ fontSize: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
+ fontStyle: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
+ fontVariant: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
+ fontWeight: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
19
+ letterSpacing: import("../types/index.js").ConstantAccessor<import("csstype").Property.LetterSpacing<0 | (string & {})>, Datum>;
20
+ wordSpacing: import("../types/index.js").ConstantAccessor<import("csstype").Property.WordSpacing<0 | (string & {})>, Datum>;
21
+ textAnchor: import("../types/index.js").ConstantAccessor<import("csstype").Property.TextAnchor, Datum>;
22
+ textTransform: import("../types/index.js").ConstantAccessor<import("csstype").Property.TextTransform, Datum>;
23
+ textDecoration: import("../types/index.js").ConstantAccessor<import("csstype").Property.TextDecoration<0 | (string & {})>, Datum>;
24
+ sort: ((a: import("../types/data.js").RawValue, b: import("../types/data.js").RawValue) => number) | {
25
+ channel: string;
26
+ order?: "ascending" | "descending";
27
+ } | import("../types/index.js").ConstantAccessor<import("../types/data.js").RawValue, Datum>;
28
+ stroke: ChannelAccessor<Datum>;
29
+ strokeWidth: import("../types/index.js").ConstantAccessor<number, Datum>;
30
+ strokeOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
31
+ strokeLinejoin: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinejoin, Datum>;
32
+ strokeLinecap: import("../types/index.js").ConstantAccessor<import("csstype").Property.StrokeLinecap, Datum>;
33
+ strokeMiterlimit: import("../types/index.js").ConstantAccessor<number, Datum>;
34
+ opacity: ChannelAccessor<Datum>;
35
+ strokeDasharray: import("../types/index.js").ConstantAccessor<string, Datum>;
36
+ strokeDashoffset: import("../types/index.js").ConstantAccessor<number, Datum>;
37
+ blend: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
38
+ mixBlendMode: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Datum>;
39
+ clipPath: string;
40
+ mask: string;
41
+ imageFilter: import("../types/index.js").ConstantAccessor<string, Datum>;
42
+ shapeRendering: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Datum>;
43
+ paintOrder: import("../types/index.js").ConstantAccessor<string, Datum>;
44
+ onclick: (event: Event & {
45
+ currentTarget: SVGPathElement;
46
+ }, datum: Datum, index: number) => void;
47
+ ondblclick: (event: Event & {
48
+ currentTarget: SVGPathElement;
49
+ }, datum: Datum, index: number) => void;
50
+ onmouseup: (event: Event & {
51
+ currentTarget: SVGPathElement;
52
+ }, datum: Datum, index: number) => void;
53
+ onmousedown: (event: Event & {
54
+ currentTarget: SVGPathElement;
55
+ }, datum: Datum, index: number) => void;
56
+ onmouseenter: (event: Event & {
57
+ currentTarget: SVGPathElement;
58
+ }, datum: Datum, index: number) => void;
59
+ onmousemove: (event: Event & {
60
+ currentTarget: SVGPathElement;
61
+ }, datum: Datum, index: number) => void;
62
+ onmouseleave: (event: Event & {
63
+ currentTarget: SVGPathElement;
64
+ }, datum: Datum, index: number) => void;
65
+ onmouseout: (event: Event & {
66
+ currentTarget: SVGPathElement;
67
+ }, datum: Datum, index: number) => void;
68
+ onmouseover: (event: Event & {
69
+ currentTarget: SVGPathElement;
70
+ }, datum: Datum, index: number) => void;
71
+ onpointercancel: (event: Event & {
72
+ currentTarget: SVGPathElement;
73
+ }, datum: Datum, index: number) => void;
74
+ onpointerdown: (event: Event & {
75
+ currentTarget: SVGPathElement;
76
+ }, datum: Datum, index: number) => void;
77
+ onpointerup: (event: Event & {
78
+ currentTarget: SVGPathElement;
79
+ }, datum: Datum, index: number) => void;
80
+ onpointerenter: (event: Event & {
81
+ currentTarget: SVGPathElement;
82
+ }, datum: Datum, index: number) => void;
83
+ onpointerleave: (event: Event & {
84
+ currentTarget: SVGPathElement;
85
+ }, datum: Datum, index: number) => void;
86
+ onpointermove: (event: Event & {
87
+ currentTarget: SVGPathElement;
88
+ }, datum: Datum, index: number) => void;
89
+ onpointerover: (event: Event & {
90
+ currentTarget: SVGPathElement;
91
+ }, datum: Datum, index: number) => void;
92
+ onpointerout: (event: Event & {
93
+ currentTarget: SVGPathElement;
94
+ }, datum: Datum, index: number) => void;
95
+ ondrag: (event: Event & {
96
+ currentTarget: SVGPathElement;
97
+ }, datum: Datum, index: number) => void;
98
+ ondrop: (event: Event & {
99
+ currentTarget: SVGPathElement;
100
+ }, datum: Datum, index: number) => void;
101
+ ondragstart: (event: Event & {
102
+ currentTarget: SVGPathElement;
103
+ }, datum: Datum, index: number) => void;
104
+ ondragenter: (event: Event & {
105
+ currentTarget: SVGPathElement;
106
+ }, datum: Datum, index: number) => void;
107
+ ondragleave: (event: Event & {
108
+ currentTarget: SVGPathElement;
109
+ }, datum: Datum, index: number) => void;
110
+ ondragover: (event: Event & {
111
+ currentTarget: SVGPathElement;
112
+ }, datum: Datum, index: number) => void;
113
+ ondragend: (event: Event & {
114
+ currentTarget: SVGPathElement;
115
+ }, datum: Datum, index: number) => void;
116
+ ontouchstart: (event: Event & {
117
+ currentTarget: SVGPathElement;
118
+ }, datum: Datum, index: number) => void;
119
+ ontouchmove: (event: Event & {
120
+ currentTarget: SVGPathElement;
121
+ }, datum: Datum, index: number) => void;
122
+ ontouchend: (event: Event & {
123
+ currentTarget: SVGPathElement;
124
+ }, datum: Datum, index: number) => void;
125
+ ontouchcancel: (event: Event & {
126
+ currentTarget: SVGPathElement;
127
+ }, datum: Datum, index: number) => void;
128
+ oncontextmenu: (event: Event & {
129
+ currentTarget: SVGPathElement;
130
+ }, datum: Datum, index: number) => void;
131
+ onwheel: (event: Event & {
132
+ currentTarget: SVGPathElement;
133
+ }, datum: Datum, index: number) => void;
134
+ class: string;
135
+ style: string;
136
+ cursor: import("../types/index.js").ConstantAccessor<import("csstype").Property.Cursor, Datum>;
137
+ title: import("../types/index.js").ConstantAccessor<string, Datum>;
138
+ }> & LinkableMarkProps<Datum> & {
139
+ /** the input data array */
140
+ data?: Datum[];
141
+ /** the horizontal position channel */
142
+ x?: ChannelAccessor<Datum>;
143
+ /** the vertical position channel */
144
+ y?: ChannelAccessor<Datum>;
145
+ /** the grouping channel; separate Voronoi diagrams per group */
146
+ z?: ChannelAccessor<Datum>;
147
+ /** Render using a canvas element instead of SVG paths. */
148
+ canvas?: boolean;
149
+ };
150
+ exports: {};
151
+ bindings: "";
152
+ slots: {};
153
+ events: {};
154
+ };
155
+ declare class __sveltets_Render<Datum = DataRecord> {
156
+ props(): ReturnType<typeof $$render<Datum>>['props'];
157
+ events(): ReturnType<typeof $$render<Datum>>['events'];
158
+ slots(): ReturnType<typeof $$render<Datum>>['slots'];
159
+ bindings(): "";
160
+ exports(): {};
161
+ }
162
+ interface $$IsomorphicComponent {
163
+ new <Datum = DataRecord>(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']>> & {
164
+ $$bindings?: ReturnType<__sveltets_Render<Datum>['bindings']>;
165
+ } & ReturnType<__sveltets_Render<Datum>['exports']>;
166
+ <Datum = DataRecord>(internal: unknown, props: ReturnType<__sveltets_Render<Datum>['props']> & {}): ReturnType<__sveltets_Render<Datum>['exports']>;
167
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
168
+ }
169
+ /** Renders individual Voronoi cells, one per data point, allowing per-cell styling. */
170
+ declare const Voronoi: $$IsomorphicComponent;
171
+ type Voronoi<Datum = DataRecord> = InstanceType<typeof Voronoi<Datum>>;
172
+ export default Voronoi;
@@ -0,0 +1,109 @@
1
+ <!-- @component
2
+ Renders the full Voronoi diagram as a single SVG path.
3
+ -->
4
+ <script lang="ts" generics="Datum = DataRecord">
5
+ interface VoronoiMeshMarkProps extends BaseMarkProps<Datum> {
6
+ /** the input data array */
7
+ data?: Datum[];
8
+ /** the horizontal position channel */
9
+ x?: ChannelAccessor<Datum>;
10
+ /** the vertical position channel */
11
+ y?: ChannelAccessor<Datum>;
12
+ /** the grouping channel; separate diagrams per group */
13
+ z?: ChannelAccessor<Datum>;
14
+ /** Render using a canvas element instead of SVG paths. */
15
+ canvas?: boolean;
16
+ }
17
+
18
+ import { Delaunay } from 'd3-delaunay';
19
+ import type {
20
+ DataRecord,
21
+ BaseMarkProps,
22
+ ChannelAccessor,
23
+ MarkType,
24
+ ScaledDataRecord
25
+ } from '../types/index.js';
26
+ import { groupFacetsAndZ } from '../helpers/group.js';
27
+ import { recordizeXY } from '../transforms/recordize.js';
28
+ import Mark from '../Mark.svelte';
29
+ import PathGroup from './helpers/PathGroup.svelte';
30
+ import { usePlot } from '../hooks/usePlot.svelte.js';
31
+ import { getPlotDefaults } from '../hooks/plotDefaults.js';
32
+
33
+ const DEFAULTS = {
34
+ ...getPlotDefaults().voronoiMesh
35
+ };
36
+
37
+ let markProps: VoronoiMeshMarkProps = $props();
38
+
39
+ const {
40
+ data = [] as Datum[],
41
+ class: className = 'voronoi-mesh',
42
+ canvas = false,
43
+ ...options
44
+ }: VoronoiMeshMarkProps = $derived({ ...DEFAULTS, ...markProps });
45
+
46
+ const args = $derived(
47
+ recordizeXY({
48
+ data: data as any[],
49
+ ...options
50
+ })
51
+ );
52
+
53
+ const plot = usePlot();
54
+
55
+ function computeMeshPaths(scaledData: ScaledDataRecord[]) {
56
+ const x0 = plot.options.marginLeft;
57
+ const y0 = plot.options.marginTop;
58
+ const x1 = x0 + plot.facetWidth;
59
+ const y1 = y0 + plot.facetHeight;
60
+ if (!(x1 > x0) || !(y1 > y0)) return [];
61
+
62
+ const scaledByDatum = new Map(scaledData.map((d) => [d.datum, d]));
63
+ const meshes: { path: string; datum: ScaledDataRecord }[] = [];
64
+
65
+ groupFacetsAndZ(
66
+ scaledData.map((d) => d.datum),
67
+ args,
68
+ (groupItems) => {
69
+ const groupScaled = groupItems
70
+ .map((d) => scaledByDatum.get(d))
71
+ .filter(
72
+ (d): d is ScaledDataRecord =>
73
+ d !== undefined &&
74
+ d.valid &&
75
+ Number.isFinite(d.x as number) &&
76
+ Number.isFinite(d.y as number)
77
+ );
78
+ if (groupScaled.length < 2) return;
79
+ const delaunay = Delaunay.from(
80
+ groupScaled,
81
+ (d) => d.x as number,
82
+ (d) => d.y as number
83
+ );
84
+ const voronoi = delaunay.voronoi([x0, y0, x1, y1]);
85
+ const path = voronoi.render();
86
+ if (path) meshes.push({ path, datum: groupScaled[0] });
87
+ },
88
+ false
89
+ );
90
+
91
+ return meshes;
92
+ }
93
+ </script>
94
+
95
+ <Mark
96
+ type={'voronoiMesh' as MarkType}
97
+ channels={['x', 'y', 'fill', 'stroke', 'strokeOpacity', 'fillOpacity', 'opacity']}
98
+ defaults={{ fill: 'none', stroke: 'currentColor' }}
99
+ {...args}>
100
+ {#snippet children({ scaledData, usedScales })}
101
+ <PathGroup
102
+ paths={computeMeshPaths(scaledData)}
103
+ {args}
104
+ {className}
105
+ {usedScales}
106
+ {plot}
107
+ {canvas} />
108
+ {/snippet}
109
+ </Mark>