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.
- package/dist/core/Plot.svelte +3 -6
- 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 +3 -3
- package/dist/marks/Contour.svelte +693 -0
- package/dist/marks/Contour.svelte.d.ts +150 -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/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/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/VectorCanvas.svelte +127 -0
- package/dist/marks/helpers/VectorCanvas.svelte.d.ts +36 -0
- package/dist/marks/index.d.ts +1 -0
- package/dist/marks/index.js +1 -0
- package/dist/types/plot.d.ts +9 -1
- package/package.json +185 -181
package/dist/core/Plot.svelte
CHANGED
|
@@ -210,11 +210,8 @@
|
|
|
210
210
|
(fixedWidth || width) - plotOptions.marginLeft - plotOptions.marginRight
|
|
211
211
|
);
|
|
212
212
|
|
|
213
|
-
// Width used for
|
|
214
|
-
// Excludes reactive auto-margins to prevent a feedback loop
|
|
215
|
-
// height → plotHeight → y-tick density → y-label widths → autoMarginLeft → plotWidth → height
|
|
216
|
-
// Using explicit user-specified margins (0 when set to 'auto') keeps height stable
|
|
217
|
-
// while still updating when the container width or user-specified margins change.
|
|
213
|
+
// Width used for geo-projection aspect-ratio height computation only.
|
|
214
|
+
// Excludes reactive auto-margins to prevent a feedback loop in projection mode.
|
|
218
215
|
const plotWidthForAspectRatio = $derived(
|
|
219
216
|
(fixedWidth || width) -
|
|
220
217
|
maybeMargin(
|
|
@@ -267,7 +264,7 @@
|
|
|
267
264
|
preScales.x,
|
|
268
265
|
preScales.y,
|
|
269
266
|
plotOptions.aspectRatio,
|
|
270
|
-
|
|
267
|
+
plotWidth,
|
|
271
268
|
plotOptions.marginTop,
|
|
272
269
|
plotOptions.marginBottom
|
|
273
270
|
)
|
package/dist/helpers/scales.js
CHANGED
|
@@ -151,6 +151,14 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
151
151
|
!mark.options[ORIGINAL_NAME_KEYS[name]].startsWith('__')) {
|
|
152
152
|
propNames.add(mark.options[ORIGINAL_NAME_KEYS[name]]);
|
|
153
153
|
}
|
|
154
|
+
// marks that use a Symbol as fill accessor (e.g. Contour) pass the
|
|
155
|
+
// original field name via ORIGINAL_NAME_KEYS.fill so the color scale
|
|
156
|
+
// can still derive an autoTitle
|
|
157
|
+
if (name === 'color' &&
|
|
158
|
+
mark.options[ORIGINAL_NAME_KEYS.fill] &&
|
|
159
|
+
!mark.options[ORIGINAL_NAME_KEYS.fill].startsWith('__')) {
|
|
160
|
+
propNames.add(mark.options[ORIGINAL_NAME_KEYS.fill]);
|
|
161
|
+
}
|
|
154
162
|
}
|
|
155
163
|
else {
|
|
156
164
|
// also skip marks without data to prevent exceptions
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { pathRound as path } from 'd3-path';
|
|
2
|
+
type D3Path = ReturnType<typeof path>;
|
|
3
|
+
export type ShapeRenderer = {
|
|
4
|
+
draw(context: D3Path, l: number, r: number): void;
|
|
5
|
+
};
|
|
6
|
+
declare const defaultRadius = 3;
|
|
7
|
+
export declare const shapeArrow: ShapeRenderer;
|
|
8
|
+
export declare const shapeSpike: ShapeRenderer;
|
|
9
|
+
export declare const shapeArrowFilled: ShapeRenderer;
|
|
10
|
+
export declare function isShapeObject(value: unknown): value is ShapeRenderer;
|
|
11
|
+
export declare function maybeShape(shape: string | ShapeRenderer): ShapeRenderer;
|
|
12
|
+
export declare function shapePath(shape: string | ShapeRenderer, l: number, r: number): string;
|
|
13
|
+
export { defaultRadius };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { pathRound as path } from 'd3-path';
|
|
2
|
+
const defaultRadius = 3;
|
|
3
|
+
const wingRatio = defaultRadius * 5;
|
|
4
|
+
export const shapeArrow = {
|
|
5
|
+
draw(context, l, r) {
|
|
6
|
+
const wing = (l * r) / wingRatio;
|
|
7
|
+
context.moveTo(0, 0);
|
|
8
|
+
context.lineTo(0, -l);
|
|
9
|
+
context.moveTo(-wing, wing - l);
|
|
10
|
+
context.lineTo(0, -l);
|
|
11
|
+
context.lineTo(wing, wing - l);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const shapeSpike = {
|
|
15
|
+
draw(context, l, r) {
|
|
16
|
+
context.moveTo(-r, 0);
|
|
17
|
+
context.lineTo(0, -l);
|
|
18
|
+
context.lineTo(r, 0);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
export const shapeArrowFilled = {
|
|
22
|
+
draw(context, l, r) {
|
|
23
|
+
const headLength = Math.max(3, l * 0.3);
|
|
24
|
+
const headSpike = headLength * 0.2;
|
|
25
|
+
const headWidth = Math.max(2, l * 0.3);
|
|
26
|
+
const tailWidth = Math.max(2, l * 0.3) * 0.3;
|
|
27
|
+
context.moveTo(0, 0);
|
|
28
|
+
context.lineTo(tailWidth * 0.5, -l + headLength - headSpike);
|
|
29
|
+
context.lineTo(headWidth * 0.5, -l + headLength);
|
|
30
|
+
context.lineTo(0, -l);
|
|
31
|
+
context.lineTo(-headWidth * 0.5, -l + headLength);
|
|
32
|
+
context.lineTo(-tailWidth * 0.5, -l + headLength - headSpike);
|
|
33
|
+
context.closePath();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const shapes = new Map([
|
|
37
|
+
['arrow', shapeArrow],
|
|
38
|
+
['arrow-filled', shapeArrowFilled],
|
|
39
|
+
['spike', shapeSpike]
|
|
40
|
+
]);
|
|
41
|
+
export function isShapeObject(value) {
|
|
42
|
+
return value != null && typeof value.draw === 'function';
|
|
43
|
+
}
|
|
44
|
+
export function maybeShape(shape) {
|
|
45
|
+
if (isShapeObject(shape))
|
|
46
|
+
return shape;
|
|
47
|
+
const value = shapes.get(`${shape}`.toLowerCase());
|
|
48
|
+
if (value)
|
|
49
|
+
return value;
|
|
50
|
+
throw new Error(`invalid shape: ${shape}`);
|
|
51
|
+
}
|
|
52
|
+
export function shapePath(shape, l, r) {
|
|
53
|
+
const context = path();
|
|
54
|
+
maybeShape(shape).draw(context, l, r);
|
|
55
|
+
return context.toString();
|
|
56
|
+
}
|
|
57
|
+
export { defaultRadius };
|
package/dist/marks/Arrow.svelte
CHANGED
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
inset?: ConstantAccessor<number, Datum>;
|
|
44
44
|
/** controls the sweep direction of the arrow arc; 1 or -1 */
|
|
45
45
|
sweep?: SweepOption;
|
|
46
|
+
/** if true, renders using Canvas instead of SVG */
|
|
47
|
+
canvas?: boolean;
|
|
46
48
|
}
|
|
47
49
|
import type {
|
|
48
50
|
DataRecord,
|
|
@@ -62,6 +64,7 @@
|
|
|
62
64
|
} from '../helpers/arrowPath.js';
|
|
63
65
|
import { replaceChannels } from '../transforms/rename.js';
|
|
64
66
|
import { addEventHandlers } from './helpers/events.js';
|
|
67
|
+
import ArrowCanvas from './helpers/ArrowCanvas.svelte';
|
|
65
68
|
import GroupMultiple from './helpers/GroupMultiple.svelte';
|
|
66
69
|
import { sort } from '../transforms/sort.js';
|
|
67
70
|
import { indexData } from '../transforms/recordize.js';
|
|
@@ -79,6 +82,7 @@
|
|
|
79
82
|
|
|
80
83
|
const {
|
|
81
84
|
data = [{} as Datum],
|
|
85
|
+
canvas = false,
|
|
82
86
|
class: className = '',
|
|
83
87
|
...options
|
|
84
88
|
}: ArrowMarkProps = $derived({
|
|
@@ -106,66 +110,73 @@
|
|
|
106
110
|
{#snippet children({ usedScales, scaledData })}
|
|
107
111
|
{@const sweep = maybeSweep(args.sweep) as SweepFunc}
|
|
108
112
|
<GroupMultiple class="arrow" length={scaledData.length}>
|
|
109
|
-
{#
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
args.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
strokeWidth: strokeWidth ?? 1.6
|
|
147
|
-
},
|
|
148
|
-
'stroke',
|
|
149
|
-
usedScales
|
|
150
|
-
)}
|
|
151
|
-
<g
|
|
152
|
-
class={[className]}
|
|
153
|
-
{@attach addEventHandlers({
|
|
113
|
+
{#if canvas}
|
|
114
|
+
<ArrowCanvas data={scaledData} options={args as any} {usedScales} />
|
|
115
|
+
{:else}
|
|
116
|
+
{#each scaledData as d, i (i)}
|
|
117
|
+
{#if d.valid}
|
|
118
|
+
{@const datum = d.datum as unknown as Datum}
|
|
119
|
+
{@const inset = resolveProp(args.inset, datum, 0)}
|
|
120
|
+
{@const insetStart = resolveProp(args.insetStart, datum)}
|
|
121
|
+
{@const insetEnd = resolveProp(args.insetEnd, datum)}
|
|
122
|
+
{@const headAngle = (resolveProp(args.headAngle, datum, 60) ??
|
|
123
|
+
60) as number}
|
|
124
|
+
{@const headLength = (resolveProp(args.headLength, datum, 8) ??
|
|
125
|
+
8) as number}
|
|
126
|
+
{@const bendVal =
|
|
127
|
+
args.bend === true
|
|
128
|
+
? 22.5
|
|
129
|
+
: (resolveProp(
|
|
130
|
+
args.bend as ConstantAccessor<number, Datum>,
|
|
131
|
+
datum,
|
|
132
|
+
0
|
|
133
|
+
) ?? 0)}
|
|
134
|
+
{@const strokeWidth = (resolveProp(args.strokeWidth, datum, 1) ??
|
|
135
|
+
1) as number}
|
|
136
|
+
{@const arrPath = arrowPath(
|
|
137
|
+
d.x1 ?? 0,
|
|
138
|
+
d.y1 ?? 0,
|
|
139
|
+
d.x2 ?? 0,
|
|
140
|
+
d.y2 ?? 0,
|
|
141
|
+
maybeNumber(coalesce(insetStart, inset)) ?? 0,
|
|
142
|
+
maybeNumber(coalesce(insetEnd, inset)) ?? 0,
|
|
143
|
+
headAngle,
|
|
144
|
+
headLength,
|
|
145
|
+
bendVal,
|
|
146
|
+
strokeWidth,
|
|
147
|
+
sweep
|
|
148
|
+
)}
|
|
149
|
+
{@const [style, styleClass] = resolveStyles(
|
|
154
150
|
plot,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
151
|
+
d,
|
|
152
|
+
{
|
|
153
|
+
strokeLinecap: 'round',
|
|
154
|
+
strokeLinejoin: 'round',
|
|
155
|
+
...args,
|
|
156
|
+
strokeWidth: strokeWidth ?? 1.6
|
|
157
|
+
},
|
|
158
|
+
'stroke',
|
|
159
|
+
usedScales
|
|
160
|
+
)}
|
|
161
|
+
<g
|
|
162
|
+
class={[className]}
|
|
163
|
+
{@attach addEventHandlers({
|
|
164
|
+
plot,
|
|
165
|
+
options: options as any,
|
|
166
|
+
datum: d?.datum
|
|
167
|
+
})}>
|
|
168
|
+
{#if options.onmouseenter || options.onclick}
|
|
169
|
+
<!-- add invisible path in bg for easier mouse access -->
|
|
170
|
+
<path
|
|
171
|
+
d={arrPath}
|
|
172
|
+
style="fill:none;stroke-width: {(strokeWidth || 1) +
|
|
173
|
+
10}; stroke: red; stroke-opacity:0" />
|
|
174
|
+
{/if}
|
|
175
|
+
<path class={[styleClass]} d={arrPath} {style} />
|
|
176
|
+
</g>
|
|
177
|
+
{/if}
|
|
178
|
+
{/each}
|
|
179
|
+
{/if}
|
|
169
180
|
</GroupMultiple>
|
|
170
181
|
{/snippet}
|
|
171
182
|
</Mark>
|
|
@@ -177,6 +177,8 @@ declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
|
|
|
177
177
|
inset?: ConstantAccessor<number, Datum>;
|
|
178
178
|
/** controls the sweep direction of the arrow arc; 1 or -1 */
|
|
179
179
|
sweep?: SweepOption;
|
|
180
|
+
/** if true, renders using Canvas instead of SVG */
|
|
181
|
+
canvas?: boolean;
|
|
180
182
|
};
|
|
181
183
|
exports: {};
|
|
182
184
|
bindings: "";
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
const DEFAULTS = getPlotDefaults();
|
|
21
21
|
|
|
22
|
-
const legendTitle = $derived(plot.options.color.label);
|
|
22
|
+
const legendTitle = $derived(plot.options.color.label ?? plot.scales.color?.autoTitle);
|
|
23
23
|
const scaleType = $derived(plot.scales.color.type);
|
|
24
24
|
const tickFormat = $derived(
|
|
25
25
|
typeof plot.options.color?.tickFormat === 'function'
|
|
@@ -158,12 +158,12 @@
|
|
|
158
158
|
<style>
|
|
159
159
|
.color-legend {
|
|
160
160
|
text-align: left;
|
|
161
|
-
font-size:
|
|
161
|
+
font-size: 11px;
|
|
162
162
|
display: inline-block;
|
|
163
163
|
margin-right: 2em;
|
|
164
164
|
}
|
|
165
165
|
.title {
|
|
166
|
-
|
|
166
|
+
opacity: 0.8;
|
|
167
167
|
}
|
|
168
168
|
.item {
|
|
169
169
|
margin: 0 1em 0.5ex 0;
|