svelteplot 0.12.0 → 0.14.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/core/Plot.svelte +3 -6
- package/dist/helpers/group.d.ts +1 -1
- package/dist/helpers/group.js +3 -3
- package/dist/helpers/scales.js +8 -0
- package/dist/helpers/vectorShapes.d.ts +13 -0
- package/dist/helpers/vectorShapes.js +57 -0
- package/dist/marks/Arrow.svelte +70 -59
- package/dist/marks/Arrow.svelte.d.ts +2 -0
- package/dist/marks/ColorLegend.svelte +7 -3
- package/dist/marks/Contour.svelte +684 -0
- package/dist/marks/Contour.svelte.d.ts +152 -0
- package/dist/marks/DelaunayLink.svelte +127 -0
- package/dist/marks/DelaunayLink.svelte.d.ts +175 -0
- package/dist/marks/DelaunayMesh.svelte +102 -0
- package/dist/marks/DelaunayMesh.svelte.d.ts +172 -0
- package/dist/marks/Density.svelte +461 -0
- package/dist/marks/Density.svelte.d.ts +87 -0
- package/dist/marks/Hull.svelte +103 -0
- package/dist/marks/Hull.svelte.d.ts +175 -0
- package/dist/marks/Image.svelte +37 -27
- package/dist/marks/Image.svelte.d.ts +2 -0
- package/dist/marks/Link.svelte +68 -50
- package/dist/marks/Link.svelte.d.ts +2 -0
- package/dist/marks/Raster.svelte +6 -1
- package/dist/marks/Vector.svelte +12 -81
- package/dist/marks/Vector.svelte.d.ts +2 -4
- package/dist/marks/Voronoi.svelte +118 -0
- package/dist/marks/Voronoi.svelte.d.ts +172 -0
- package/dist/marks/VoronoiMesh.svelte +109 -0
- package/dist/marks/VoronoiMesh.svelte.d.ts +172 -0
- package/dist/marks/helpers/ArrowCanvas.svelte +132 -0
- package/dist/marks/helpers/ArrowCanvas.svelte.d.ts +39 -0
- package/dist/marks/helpers/BaseAxisX.svelte +5 -7
- package/dist/marks/helpers/DensityCanvas.svelte +118 -0
- package/dist/marks/helpers/DensityCanvas.svelte.d.ts +18 -0
- package/dist/marks/helpers/GeoPathCanvas.svelte +125 -0
- package/dist/marks/helpers/GeoPathCanvas.svelte.d.ts +24 -0
- package/dist/marks/helpers/GeoPathGroup.svelte +103 -0
- package/dist/marks/helpers/GeoPathGroup.svelte.d.ts +37 -0
- package/dist/marks/helpers/ImageCanvas.svelte +126 -0
- package/dist/marks/helpers/ImageCanvas.svelte.d.ts +34 -0
- package/dist/marks/helpers/LinkCanvas.svelte +103 -0
- package/dist/marks/helpers/LinkCanvas.svelte.d.ts +32 -0
- package/dist/marks/helpers/PathGroup.svelte +100 -0
- package/dist/marks/helpers/PathGroup.svelte.d.ts +16 -0
- package/dist/marks/helpers/PathItems.svelte +112 -0
- package/dist/marks/helpers/PathItems.svelte.d.ts +16 -0
- package/dist/marks/helpers/VectorCanvas.svelte +127 -0
- package/dist/marks/helpers/VectorCanvas.svelte.d.ts +36 -0
- package/dist/marks/index.d.ts +7 -0
- package/dist/marks/index.js +7 -0
- package/dist/types/mark.d.ts +1 -1
- package/dist/types/plot.d.ts +33 -1
- package/package.json +185 -181
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { DataRecord, ChannelAccessor } from '../types/index.js';
|
|
2
|
+
declare function $$render<Datum extends DataRecord>(): {
|
|
3
|
+
props: {
|
|
4
|
+
/** Input data — an array of records with x/y positions. */
|
|
5
|
+
data?: Datum[] | null;
|
|
6
|
+
/** x position channel (data space). */
|
|
7
|
+
x?: ChannelAccessor<Datum>;
|
|
8
|
+
/** y position channel (data space). */
|
|
9
|
+
y?: ChannelAccessor<Datum>;
|
|
10
|
+
/** Optional weight channel; defaults to 1 for each point. */
|
|
11
|
+
weight?: ChannelAccessor<Datum>;
|
|
12
|
+
/**
|
|
13
|
+
* Gaussian kernel bandwidth in screen pixels (default 20).
|
|
14
|
+
* Larger values produce smoother, more blurred density estimates.
|
|
15
|
+
*/
|
|
16
|
+
bandwidth?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Density threshold levels. Can be:
|
|
19
|
+
* - a **count** (number): that many evenly-spaced levels from 0 to the
|
|
20
|
+
* maximum density (default 20)
|
|
21
|
+
* - an explicit **array** of threshold values in k-scaled density units
|
|
22
|
+
* (where k = 100; values from 0 to roughly 100× the peak density)
|
|
23
|
+
*/
|
|
24
|
+
thresholds?: number | number[];
|
|
25
|
+
/**
|
|
26
|
+
* Fill color for density bands. Use `"density"` to map each band's
|
|
27
|
+
* estimated density through the plot's color scale. Default `"none"`.
|
|
28
|
+
*/
|
|
29
|
+
fill?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Stroke color for density isolines. Use `"density"` to map each
|
|
32
|
+
* isoline's estimated density through the plot's color scale.
|
|
33
|
+
* Default `"currentColor"` when fill is `"none"`, otherwise `"none"`.
|
|
34
|
+
*/
|
|
35
|
+
stroke?: string;
|
|
36
|
+
strokeWidth?: number;
|
|
37
|
+
strokeOpacity?: number;
|
|
38
|
+
fillOpacity?: number;
|
|
39
|
+
opacity?: number;
|
|
40
|
+
strokeMiterlimit?: number;
|
|
41
|
+
clipPath?: string;
|
|
42
|
+
class?: string;
|
|
43
|
+
/** Render using a canvas element instead of SVG paths. */
|
|
44
|
+
canvas?: boolean;
|
|
45
|
+
/** the horizontal facet channel */
|
|
46
|
+
fx?: ChannelAccessor<Datum>;
|
|
47
|
+
/** the vertical facet channel */
|
|
48
|
+
fy?: ChannelAccessor<Datum>;
|
|
49
|
+
};
|
|
50
|
+
exports: {};
|
|
51
|
+
bindings: "";
|
|
52
|
+
slots: {};
|
|
53
|
+
events: {};
|
|
54
|
+
};
|
|
55
|
+
declare class __sveltets_Render<Datum extends DataRecord> {
|
|
56
|
+
props(): ReturnType<typeof $$render<Datum>>['props'];
|
|
57
|
+
events(): ReturnType<typeof $$render<Datum>>['events'];
|
|
58
|
+
slots(): ReturnType<typeof $$render<Datum>>['slots'];
|
|
59
|
+
bindings(): "";
|
|
60
|
+
exports(): {};
|
|
61
|
+
}
|
|
62
|
+
interface $$IsomorphicComponent {
|
|
63
|
+
new <Datum extends 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']>> & {
|
|
64
|
+
$$bindings?: ReturnType<__sveltets_Render<Datum>['bindings']>;
|
|
65
|
+
} & ReturnType<__sveltets_Render<Datum>['exports']>;
|
|
66
|
+
<Datum extends DataRecord>(internal: unknown, props: ReturnType<__sveltets_Render<Datum>['props']> & {}): ReturnType<__sveltets_Render<Datum>['exports']>;
|
|
67
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Renders two-dimensional kernel density estimation as filled or stroked
|
|
71
|
+
* contour paths.
|
|
72
|
+
*
|
|
73
|
+
* Data points with `x` and `y` channels are projected into pixel space and
|
|
74
|
+
* passed to d3's `contourDensity` estimator, which uses a Gaussian kernel to
|
|
75
|
+
* produce a density grid. Iso-density contour bands are then drawn using the
|
|
76
|
+
* marching-squares algorithm.
|
|
77
|
+
*
|
|
78
|
+
* Styling: `fill` and `stroke` accept ordinary CSS color strings **or** the
|
|
79
|
+
* special keyword `"density"`, which maps each contour level's estimated
|
|
80
|
+
* density through the plot's color scale. Defaults: `fill="none"`,
|
|
81
|
+
* `stroke="currentColor"`.
|
|
82
|
+
*
|
|
83
|
+
* Supports faceting via `fx`/`fy`.
|
|
84
|
+
*/
|
|
85
|
+
declare const Density: $$IsomorphicComponent;
|
|
86
|
+
type Density<Datum extends DataRecord> = InstanceType<typeof Density<Datum>>;
|
|
87
|
+
export default Density;
|
|
@@ -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;
|
package/dist/marks/Image.svelte
CHANGED
|
@@ -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
|
-
|
|
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
|
-
{#
|
|
76
|
-
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
};
|
package/dist/marks/Link.svelte
CHANGED
|
@@ -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
|
-
|
|
172
|
-
{
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
{
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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: "";
|
package/dist/marks/Raster.svelte
CHANGED
|
@@ -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
|
|