svelteplot 0.8.1 → 0.9.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 (114) hide show
  1. package/README.md +1 -1
  2. package/dist/Mark.svelte +1 -1
  3. package/dist/Mark.svelte.d.ts +1 -0
  4. package/dist/constants.d.ts +2 -0
  5. package/dist/constants.js +2 -0
  6. package/dist/core/Plot.svelte +4 -4
  7. package/dist/helpers/projection.js +7 -2
  8. package/dist/hooks/usePlot.svelte.d.ts +51 -0
  9. package/dist/hooks/usePlot.svelte.js +90 -0
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +1 -0
  12. package/dist/marks/Area.svelte +3 -5
  13. package/dist/marks/Area.svelte.d.ts +1 -0
  14. package/dist/marks/AreaX.svelte.d.ts +1 -0
  15. package/dist/marks/Arrow.svelte +3 -5
  16. package/dist/marks/Arrow.svelte.d.ts +1 -0
  17. package/dist/marks/AxisX.svelte +2 -3
  18. package/dist/marks/AxisX.svelte.d.ts +1 -0
  19. package/dist/marks/AxisY.svelte +3 -4
  20. package/dist/marks/AxisY.svelte.d.ts +1 -0
  21. package/dist/marks/BarX.svelte +2 -4
  22. package/dist/marks/BarX.svelte.d.ts +1 -0
  23. package/dist/marks/BarY.svelte +2 -4
  24. package/dist/marks/BarY.svelte.d.ts +1 -0
  25. package/dist/marks/BollingerX.svelte.d.ts +1 -0
  26. package/dist/marks/BollingerY.svelte.d.ts +1 -0
  27. package/dist/marks/BoxX.svelte +4 -138
  28. package/dist/marks/BoxY.svelte +20 -137
  29. package/dist/marks/BoxY.svelte.d.ts +8 -3
  30. package/dist/marks/Brush.svelte +3 -3
  31. package/dist/marks/Brush.svelte.d.ts +1 -0
  32. package/dist/marks/Cell.svelte +2 -4
  33. package/dist/marks/Cell.svelte.d.ts +1 -0
  34. package/dist/marks/ColorLegend.svelte +2 -4
  35. package/dist/marks/CustomMark.svelte.d.ts +1 -0
  36. package/dist/marks/CustomMarkHTML.svelte +5 -10
  37. package/dist/marks/DifferenceY.svelte +3 -5
  38. package/dist/marks/DifferenceY.svelte.d.ts +1 -0
  39. package/dist/marks/Dot.svelte +4 -5
  40. package/dist/marks/Dot.svelte.d.ts +1 -0
  41. package/dist/marks/DotX.svelte.d.ts +1 -0
  42. package/dist/marks/DotY.svelte.d.ts +1 -0
  43. package/dist/marks/Frame.svelte +3 -9
  44. package/dist/marks/Frame.svelte.d.ts +1 -0
  45. package/dist/marks/Geo.svelte +5 -5
  46. package/dist/marks/Geo.svelte.d.ts +2 -0
  47. package/dist/marks/GridX.svelte +3 -10
  48. package/dist/marks/GridX.svelte.d.ts +1 -0
  49. package/dist/marks/GridY.svelte +3 -4
  50. package/dist/marks/GridY.svelte.d.ts +1 -0
  51. package/dist/marks/HTMLTooltip.svelte +5 -5
  52. package/dist/marks/Image.svelte.d.ts +1 -0
  53. package/dist/marks/Line.svelte +7 -6
  54. package/dist/marks/Line.svelte.d.ts +1 -0
  55. package/dist/marks/LineX.svelte.d.ts +1 -0
  56. package/dist/marks/LineY.svelte.d.ts +1 -0
  57. package/dist/marks/Link.svelte +2 -4
  58. package/dist/marks/Link.svelte.d.ts +1 -0
  59. package/dist/marks/Pointer.svelte +4 -4
  60. package/dist/marks/Rect.svelte +2 -4
  61. package/dist/marks/Rect.svelte.d.ts +1 -0
  62. package/dist/marks/RectX.svelte +4 -4
  63. package/dist/marks/RectY.svelte +4 -4
  64. package/dist/marks/RuleX.svelte +2 -4
  65. package/dist/marks/RuleX.svelte.d.ts +1 -0
  66. package/dist/marks/RuleY.svelte +2 -4
  67. package/dist/marks/RuleY.svelte.d.ts +1 -0
  68. package/dist/marks/Spike.svelte.d.ts +1 -0
  69. package/dist/marks/SymbolLegend.svelte +2 -4
  70. package/dist/marks/SymbolLegend.svelte.d.ts +17 -2
  71. package/dist/marks/Text.svelte.d.ts +1 -0
  72. package/dist/marks/TickX.svelte +2 -3
  73. package/dist/marks/TickX.svelte.d.ts +1 -0
  74. package/dist/marks/TickY.svelte +2 -3
  75. package/dist/marks/TickY.svelte.d.ts +1 -0
  76. package/dist/marks/Trail.svelte +161 -0
  77. package/dist/marks/Trail.svelte.d.ts +107 -0
  78. package/dist/marks/Vector.svelte +3 -4
  79. package/dist/marks/Vector.svelte.d.ts +1 -0
  80. package/dist/marks/WaffleX.svelte +2 -3
  81. package/dist/marks/WaffleX.svelte.d.ts +1 -0
  82. package/dist/marks/WaffleY.svelte +2 -4
  83. package/dist/marks/WaffleY.svelte.d.ts +1 -0
  84. package/dist/marks/helpers/AreaCanvas.svelte +2 -4
  85. package/dist/marks/helpers/Box.svelte +271 -0
  86. package/dist/marks/helpers/Box.svelte.d.ts +118 -0
  87. package/dist/marks/helpers/CanvasLayer.svelte +2 -4
  88. package/dist/marks/helpers/DotCanvas.svelte +3 -5
  89. package/dist/marks/helpers/GeoCanvas.svelte +2 -4
  90. package/dist/marks/helpers/LineCanvas.svelte +2 -4
  91. package/dist/marks/helpers/LinearGradientX.svelte +3 -4
  92. package/dist/marks/helpers/LinearGradientY.svelte +3 -4
  93. package/dist/marks/helpers/MarkerPath.svelte +4 -5
  94. package/dist/marks/helpers/MarkerPath.svelte.d.ts +1 -0
  95. package/dist/marks/helpers/MultilineText.svelte +4 -4
  96. package/dist/marks/helpers/RectPath.svelte +5 -6
  97. package/dist/marks/helpers/Regression.svelte +4 -8
  98. package/dist/marks/helpers/TrailCanvas.svelte +138 -0
  99. package/dist/marks/helpers/TrailCanvas.svelte.d.ts +40 -0
  100. package/dist/marks/helpers/events.d.ts +2 -2
  101. package/dist/marks/helpers/events.js +4 -4
  102. package/dist/marks/helpers/trail.d.ts +23 -0
  103. package/dist/marks/helpers/trail.js +372 -0
  104. package/dist/marks/index.d.ts +1 -0
  105. package/dist/marks/index.js +1 -0
  106. package/dist/transforms/bollinger.d.ts +1 -0
  107. package/dist/transforms/interval.d.ts +2 -0
  108. package/dist/transforms/select.d.ts +7 -0
  109. package/dist/transforms/sort.d.ts +4 -0
  110. package/dist/transforms/window.d.ts +2 -0
  111. package/dist/types/mark.d.ts +2 -1
  112. package/dist/types/plot.d.ts +6 -1
  113. package/dist/ui/Spiral.svelte +4 -0
  114. package/package.json +24 -23
@@ -0,0 +1,372 @@
1
+ import { TAU } from '../../constants.js';
2
+ import { maybeCurve } from '../../helpers/curves.js';
3
+ /**
4
+ * Draw a stroked capsule trail along successive points with varying widths.
5
+ * Adapted from Vega's trail mark implementation.
6
+ */
7
+ export function trailPath(samples, defined, context, options = {}) {
8
+ const { curve = 'linear', cap = 'round', tension = 0.5 } = options;
9
+ const samplesPerSegment = options.samplesPerSegment ?? estimateSamplesPerSegment(samples, defined);
10
+ const curveFactory = maybeCurve(curve, tension);
11
+ let drawSamples = samples;
12
+ let drawDefined = defined;
13
+ if (curve !== 'linear' || tension !== 0) {
14
+ const smoothedSamples = [];
15
+ const smoothedDefined = [];
16
+ const len = Math.min(samples.length, defined.length);
17
+ let i = 0;
18
+ while (i < len) {
19
+ if (!defined[i]) {
20
+ smoothedSamples.push(samples[i]);
21
+ smoothedDefined.push(false);
22
+ i += 1;
23
+ continue;
24
+ }
25
+ const segment = [];
26
+ while (i < len && defined[i]) {
27
+ segment.push(samples[i]);
28
+ i += 1;
29
+ }
30
+ const resampled = resampleCurve(segment, curveFactory, Math.max(1, samplesPerSegment));
31
+ smoothedSamples.push(...resampled);
32
+ smoothedDefined.push(...new Array(resampled.length).fill(true));
33
+ // preserve a gap between defined segments
34
+ if (i < len) {
35
+ smoothedSamples.push(samples[i]);
36
+ smoothedDefined.push(false);
37
+ }
38
+ }
39
+ drawSamples = smoothedSamples;
40
+ drawDefined = smoothedDefined;
41
+ }
42
+ const len = Math.min(drawSamples.length, drawDefined.length);
43
+ if (len === 0)
44
+ return;
45
+ // Butt caps: build joined polygon offsets using angle bisectors to avoid gaps.
46
+ if (cap === 'butt') {
47
+ const normalizeVec = (x, y) => {
48
+ const lenVec = Math.hypot(x, y);
49
+ return lenVec === 0 ? [0, 0] : [x / lenVec, y / lenVec];
50
+ };
51
+ let i = 0;
52
+ while (i < len) {
53
+ if (!drawDefined[i]) {
54
+ i += 1;
55
+ continue;
56
+ }
57
+ const runStart = i;
58
+ while (i < len && drawDefined[i])
59
+ i += 1;
60
+ const runEnd = i - 1;
61
+ const left = [];
62
+ const right = [];
63
+ for (let j = runStart; j <= runEnd; j += 1) {
64
+ const curr = drawSamples[j];
65
+ const r = curr.r;
66
+ const hasPrev = j > runStart;
67
+ const hasNext = j < runEnd;
68
+ const prev = hasPrev ? drawSamples[j - 1] : curr;
69
+ const next = hasNext ? drawSamples[j + 1] : curr;
70
+ const dirPrev = hasPrev
71
+ ? normalizeVec(curr.x - prev.x, curr.y - prev.y)
72
+ : normalizeVec(next.x - curr.x, next.y - curr.y);
73
+ const dirNext = hasNext ? normalizeVec(next.x - curr.x, next.y - curr.y) : dirPrev;
74
+ const normPrev = [-dirPrev[1], dirPrev[0]];
75
+ const normNext = [-dirNext[1], dirNext[0]];
76
+ let nx = normPrev[0] + normNext[0];
77
+ let ny = normPrev[1] + normNext[1];
78
+ const nLen = Math.hypot(nx, ny);
79
+ if (nLen < 1e-6) {
80
+ // Straight/180-deg turn: fall back to current normal.
81
+ nx = normPrev[0];
82
+ ny = normPrev[1];
83
+ }
84
+ else {
85
+ nx /= nLen;
86
+ ny /= nLen;
87
+ }
88
+ // Scale to preserve half-width along the miter direction.
89
+ const dot = nx * normPrev[0] + ny * normPrev[1];
90
+ const safeDot = Math.abs(dot) < 1e-6 ? 1 : dot;
91
+ const scale = r / safeDot;
92
+ const ox = nx * scale;
93
+ const oy = ny * scale;
94
+ left.push([curr.x + ox, curr.y + oy]);
95
+ right.push([curr.x - ox, curr.y - oy]);
96
+ }
97
+ if (left.length > 0) {
98
+ context.moveTo(left[0][0], left[0][1]);
99
+ for (let j = 1; j < left.length; j += 1) {
100
+ context.lineTo(left[j][0], left[j][1]);
101
+ }
102
+ for (let j = right.length - 1; j >= 0; j -= 1) {
103
+ context.lineTo(right[j][0], right[j][1]);
104
+ }
105
+ context.closePath();
106
+ }
107
+ }
108
+ return typeof context.toString === 'function' ? context.toString() : undefined;
109
+ }
110
+ // Round caps: original capsule behavior.
111
+ let ready = false;
112
+ let x1 = 0;
113
+ let y1 = 0;
114
+ let r1 = 0;
115
+ function point(x2, y2, r2, isStartOfRun, isEndOfRun) {
116
+ if (ready) {
117
+ let ux = y1 - y2;
118
+ let uy = x2 - x1;
119
+ if (ux || uy) {
120
+ // compute normal vector scaled by radius
121
+ const ud = Math.hypot(ux, uy);
122
+ const rx = (ux /= ud) * r1;
123
+ const ry = (uy /= ud) * r1;
124
+ const t = Math.atan2(uy, ux);
125
+ // keep rounded joins for interior segments even when using butt caps
126
+ const drawStartCap = !isStartOfRun || cap === 'round';
127
+ const drawEndCap = !isEndOfRun || cap === 'round';
128
+ context.moveTo(x1 - rx, y1 - ry);
129
+ context.lineTo(x2 - ux * r2, y2 - uy * r2);
130
+ if (drawEndCap) {
131
+ context.arc(x2, y2, r2, t - Math.PI, t);
132
+ }
133
+ else {
134
+ context.lineTo(x2 + ux * r2, y2 + uy * r2);
135
+ }
136
+ context.lineTo(x1 + rx, y1 + ry);
137
+ if (drawStartCap) {
138
+ context.arc(x1, y1, r1, t, t + Math.PI);
139
+ }
140
+ }
141
+ else {
142
+ if (cap === 'round' || (!isStartOfRun && !isEndOfRun)) {
143
+ context.arc(x2, y2, r2, 0, TAU);
144
+ }
145
+ }
146
+ context.closePath();
147
+ }
148
+ else {
149
+ ready = true;
150
+ }
151
+ x1 = x2;
152
+ y1 = y2;
153
+ r1 = r2;
154
+ }
155
+ let i = 0;
156
+ while (i < len) {
157
+ // Skip gaps
158
+ if (!drawDefined[i]) {
159
+ i += 1;
160
+ ready = false;
161
+ continue;
162
+ }
163
+ const runStart = i;
164
+ while (i < len && drawDefined[i])
165
+ i += 1;
166
+ const runEnd = i - 1;
167
+ // Prime the first point of the run
168
+ const first = drawSamples[runStart];
169
+ ready = false;
170
+ x1 = first.x;
171
+ y1 = first.y;
172
+ r1 = first.r;
173
+ ready = true;
174
+ for (let j = runStart + 1; j <= runEnd; j += 1) {
175
+ const { x: x2, y: y2, r } = drawSamples[j];
176
+ const isStart = j - 1 === runStart;
177
+ const isEnd = j === runEnd;
178
+ point(Number(x2), Number(y2), Number(r), isStart, isEnd);
179
+ }
180
+ ready = false;
181
+ }
182
+ return typeof context.toString === 'function' ? context.toString() : undefined;
183
+ }
184
+ function resampleCurve(points, curveFactory, samplesPerSegment) {
185
+ if (points.length === 0)
186
+ return [];
187
+ const commands = [];
188
+ let pendingRadius = points[0].r;
189
+ let currentRadius = points[0].r;
190
+ let currentPoint = null;
191
+ const ctx = {
192
+ beginPath() { },
193
+ closePath() { },
194
+ moveTo(x, y) {
195
+ currentPoint = [x, y];
196
+ currentRadius = pendingRadius;
197
+ commands.push({ type: 'move', to: [x, y], r: currentRadius });
198
+ },
199
+ lineTo(x, y) {
200
+ const from = currentPoint ?? [x, y];
201
+ commands.push({
202
+ type: 'line',
203
+ from: [from[0], from[1], currentRadius],
204
+ to: [x, y, pendingRadius]
205
+ });
206
+ currentPoint = [x, y];
207
+ currentRadius = pendingRadius;
208
+ },
209
+ bezierCurveTo(x1, y1, x2, y2, x, y) {
210
+ const from = currentPoint ?? [x, y];
211
+ commands.push({
212
+ type: 'cubic',
213
+ from: [from[0], from[1], currentRadius],
214
+ cp1: [x1, y1],
215
+ cp2: [x2, y2],
216
+ to: [x, y, pendingRadius]
217
+ });
218
+ currentPoint = [x, y];
219
+ currentRadius = pendingRadius;
220
+ },
221
+ quadraticCurveTo(x1, y1, x, y) {
222
+ const from = currentPoint ?? [x, y];
223
+ commands.push({
224
+ type: 'quad',
225
+ from: [from[0], from[1], currentRadius],
226
+ cp: [x1, y1],
227
+ to: [x, y, pendingRadius]
228
+ });
229
+ currentPoint = [x, y];
230
+ currentRadius = pendingRadius;
231
+ },
232
+ arc() { },
233
+ rect() { }
234
+ };
235
+ const curve = curveFactory(ctx);
236
+ curve.lineStart();
237
+ for (let idx = 0; idx < points.length; idx += 1) {
238
+ const pt = points[idx];
239
+ pendingRadius = pt.r;
240
+ curve.point(pt.x, pt.y);
241
+ }
242
+ curve.lineEnd();
243
+ const geom = flattenCommands(commands, samplesPerSegment);
244
+ if (geom.length === 0)
245
+ return geom;
246
+ // Re-map radii along the resampled path using the original cumulative
247
+ // length as the parameter to avoid curve-specific radius drift.
248
+ const origCum = [0];
249
+ for (let i = 1; i < points.length; i += 1) {
250
+ const dx = points[i].x - points[i - 1].x;
251
+ const dy = points[i].y - points[i - 1].y;
252
+ origCum.push(origCum[i - 1] + Math.hypot(dx, dy));
253
+ }
254
+ const origTotal = origCum[origCum.length - 1] || 1;
255
+ const resCum = [0];
256
+ for (let i = 1; i < geom.length; i += 1) {
257
+ const dx = geom[i].x - geom[i - 1].x;
258
+ const dy = geom[i].y - geom[i - 1].y;
259
+ resCum.push(resCum[i - 1] + Math.hypot(dx, dy));
260
+ }
261
+ const resTotal = resCum[resCum.length - 1] || 1;
262
+ const radiusAt = (target) => {
263
+ let idx = 1;
264
+ while (idx < origCum.length && origCum[idx] < target)
265
+ idx += 1;
266
+ if (idx === origCum.length)
267
+ return points[points.length - 1].r;
268
+ const t0 = origCum[idx - 1];
269
+ const t1 = origCum[idx];
270
+ const r0 = points[idx - 1].r;
271
+ const r1 = points[idx].r;
272
+ const t = t1 === t0 ? 0 : (target - t0) / (t1 - t0);
273
+ return lerp(r0, r1, t);
274
+ };
275
+ for (let i = 0; i < geom.length; i += 1) {
276
+ const frac = resCum[i] / resTotal;
277
+ geom[i].r = Number(radiusAt(frac * origTotal).toFixed(2));
278
+ }
279
+ return geom;
280
+ }
281
+ function flattenCommands(commands, samplesPerSegment, precision = 2) {
282
+ const result = [];
283
+ let last = null;
284
+ const round = (v) => {
285
+ const m = 10 ** precision;
286
+ return Math.round(v * m) / m;
287
+ };
288
+ const pushPoint = (x, y, r) => {
289
+ x = round(x);
290
+ y = round(y);
291
+ r = round(r);
292
+ if (!last || last[0] !== x || last[1] !== y || last[2] !== r) {
293
+ result.push({ x, y, r });
294
+ last = [x, y, r];
295
+ }
296
+ };
297
+ for (const cmd of commands) {
298
+ if (cmd.type === 'move') {
299
+ pushPoint(cmd.to[0], cmd.to[1], cmd.r);
300
+ continue;
301
+ }
302
+ if (cmd.type === 'line') {
303
+ const [x1, y1, r1] = cmd.from;
304
+ const [x2, y2, r2] = cmd.to;
305
+ for (let step = 1; step <= samplesPerSegment; step += 1) {
306
+ const t = step / samplesPerSegment;
307
+ pushPoint(lerp(x1, x2, t), lerp(y1, y2, t), lerp(r1, r2, t));
308
+ }
309
+ continue;
310
+ }
311
+ if (cmd.type === 'cubic') {
312
+ const [x0, y0, r0] = cmd.from;
313
+ const [x1, y1] = cmd.cp1;
314
+ const [x2, y2] = cmd.cp2;
315
+ const [x3, y3, r3] = cmd.to;
316
+ for (let step = 1; step <= samplesPerSegment; step += 1) {
317
+ const t = step / samplesPerSegment;
318
+ pushPoint(cubic(x0, x1, x2, x3, t), cubic(y0, y1, y2, y3, t), lerp(r0, r3, t));
319
+ }
320
+ continue;
321
+ }
322
+ if (cmd.type === 'quad') {
323
+ const [x0, y0, r0] = cmd.from;
324
+ const [cx, cy] = cmd.cp;
325
+ const [x1, y1, r1] = cmd.to;
326
+ for (let step = 1; step <= samplesPerSegment; step += 1) {
327
+ const t = step / samplesPerSegment;
328
+ pushPoint(quad(x0, cx, x1, t), quad(y0, cy, y1, t), lerp(r0, r1, t));
329
+ }
330
+ }
331
+ }
332
+ return result;
333
+ }
334
+ function cubic(p0, p1, p2, p3, t) {
335
+ const it = 1 - t;
336
+ return it * it * it * p0 + 3 * it * it * t * p1 + 3 * it * t * t * p2 + t * t * t * p3;
337
+ }
338
+ function quad(p0, p1, p2, t) {
339
+ const it = 1 - t;
340
+ return it * it * p0 + 2 * it * t * p1 + t * t * p2;
341
+ }
342
+ function lerp(a, b, t) {
343
+ return a + (b - a) * t;
344
+ }
345
+ function estimateSamplesPerSegment(samples, defined) {
346
+ const n = Math.min(samples.length, defined.length);
347
+ let distSum = 0;
348
+ let distCount = 0;
349
+ let rSum = 0;
350
+ let rCount = 0;
351
+ for (let i = 0; i < n; i++) {
352
+ if (defined[i]) {
353
+ rSum += samples[i].r;
354
+ rCount += 1;
355
+ }
356
+ if (i === 0 || !defined[i] || !defined[i - 1])
357
+ continue;
358
+ const dx = samples[i].x - samples[i - 1].x;
359
+ const dy = samples[i].y - samples[i - 1].y;
360
+ const d = Math.hypot(dx, dy);
361
+ if (isFinite(d) && d > 0) {
362
+ distSum += d;
363
+ distCount += 1;
364
+ }
365
+ }
366
+ const meanDist = distCount ? distSum / distCount : 0;
367
+ const meanRadius = rCount ? rSum / rCount : 0;
368
+ const base = meanRadius > 0 ? meanDist / meanRadius : meanDist;
369
+ // Keep within a reasonable range to avoid excessive subdivision.
370
+ return Math.max(1, Math.min(32, Math.round(base || 1)));
371
+ }
372
+ export default trailPath;
@@ -45,6 +45,7 @@ export { default as Spike } from './Spike.svelte';
45
45
  export { default as Text } from './Text.svelte';
46
46
  export { default as TickX } from './TickX.svelte';
47
47
  export { default as TickY } from './TickY.svelte';
48
+ export { default as Trail } from './Trail.svelte';
48
49
  export { default as Vector } from './Vector.svelte';
49
50
  export { default as WaffleX } from './WaffleX.svelte';
50
51
  export { default as WaffleY } from './WaffleY.svelte';
@@ -45,6 +45,7 @@ export { default as Spike } from './Spike.svelte';
45
45
  export { default as Text } from './Text.svelte';
46
46
  export { default as TickX } from './TickX.svelte';
47
47
  export { default as TickY } from './TickY.svelte';
48
+ export { default as Trail } from './Trail.svelte';
48
49
  export { default as Vector } from './Vector.svelte';
49
50
  export { default as WaffleX } from './WaffleX.svelte';
50
51
  export { default as WaffleY } from './WaffleY.svelte';
@@ -37,6 +37,7 @@ export declare function bollingerDim(dim: 'x' | 'y', { data, ...channels }: Tran
37
37
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
38
38
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
39
39
  clipPath?: string | undefined;
40
+ mask?: string | undefined;
40
41
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
41
42
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
42
43
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -27,6 +27,7 @@ export declare function intervalX<T>(args: TransformArg<T>, { plot }: {
27
27
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, T>;
28
28
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, T>;
29
29
  clipPath?: string | undefined;
30
+ mask?: string | undefined;
30
31
  imageFilter?: import("../types/index.js").ConstantAccessor<string, T>;
31
32
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, T>;
32
33
  paintOrder?: import("../types/index.js").ConstantAccessor<string, T>;
@@ -93,6 +94,7 @@ export declare function intervalY<T>(args: TransformArg<T>, { plot }: {
93
94
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, T>;
94
95
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, T>;
95
96
  clipPath?: string | undefined;
97
+ mask?: string | undefined;
96
98
  imageFilter?: import("../types/index.js").ConstantAccessor<string, T>;
97
99
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, T>;
98
100
  paintOrder?: import("../types/index.js").ConstantAccessor<string, T>;
@@ -31,6 +31,7 @@ export declare function select({ data, ...channels }: TransformArg<DataRecord>,
31
31
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
32
32
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
33
33
  clipPath?: string | undefined;
34
+ mask?: string | undefined;
34
35
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
35
36
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
36
37
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -98,6 +99,7 @@ export declare function selectFirst(args: TransformArg<DataRecord>): {
98
99
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
99
100
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
100
101
  clipPath?: string | undefined;
102
+ mask?: string | undefined;
101
103
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
102
104
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
103
105
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -165,6 +167,7 @@ export declare function selectLast(args: TransformArg<DataRecord>): {
165
167
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
166
168
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
167
169
  clipPath?: string | undefined;
170
+ mask?: string | undefined;
168
171
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
169
172
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
170
173
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -229,6 +232,7 @@ export declare function selectMinX(args: TransformArg<DataRecord>): {
229
232
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
230
233
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
231
234
  clipPath?: string | undefined;
235
+ mask?: string | undefined;
232
236
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
233
237
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
234
238
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -293,6 +297,7 @@ export declare function selectMaxX(args: TransformArg<DataRecord>): {
293
297
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
294
298
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
295
299
  clipPath?: string | undefined;
300
+ mask?: string | undefined;
296
301
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
297
302
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
298
303
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -357,6 +362,7 @@ export declare function selectMinY(args: TransformArg<DataRecord>): {
357
362
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
358
363
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
359
364
  clipPath?: string | undefined;
365
+ mask?: string | undefined;
360
366
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
361
367
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
362
368
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -421,6 +427,7 @@ export declare function selectMaxY(args: TransformArg<DataRecord>): {
421
427
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
422
428
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
423
429
  clipPath?: string | undefined;
430
+ mask?: string | undefined;
424
431
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
425
432
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
426
433
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -27,6 +27,7 @@ export declare function sort<T>({ data, ...channels }: TransformArg<T>, options?
27
27
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, T>;
28
28
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, T>;
29
29
  clipPath?: string | undefined;
30
+ mask?: string | undefined;
30
31
  imageFilter?: import("../types/index.js").ConstantAccessor<string, T>;
31
32
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, T>;
32
33
  paintOrder?: import("../types/index.js").ConstantAccessor<string, T>;
@@ -92,6 +93,7 @@ export declare function sort<T>({ data, ...channels }: TransformArg<T>, options?
92
93
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, T>;
93
94
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, T>;
94
95
  clipPath?: string | undefined;
96
+ mask?: string | undefined;
95
97
  imageFilter?: import("../types/index.js").ConstantAccessor<string, T>;
96
98
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, T>;
97
99
  paintOrder?: import("../types/index.js").ConstantAccessor<string, T>;
@@ -159,6 +161,7 @@ export declare function shuffle({ data, ...channels }: TransformArg<DataRow[]>,
159
161
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, DataRow[]>;
160
162
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, DataRow[]>;
161
163
  clipPath?: string | undefined;
164
+ mask?: string | undefined;
162
165
  imageFilter?: import("../types/index.js").ConstantAccessor<string, DataRow[]>;
163
166
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, DataRow[]>;
164
167
  paintOrder?: import("../types/index.js").ConstantAccessor<string, DataRow[]>;
@@ -224,6 +227,7 @@ export declare function reverse({ data, ...channels }: TransformArg<DataRow[]>):
224
227
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, DataRow[]>;
225
228
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, DataRow[]>;
226
229
  clipPath?: string | undefined;
230
+ mask?: string | undefined;
227
231
  imageFilter?: import("../types/index.js").ConstantAccessor<string, DataRow[]>;
228
232
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, DataRow[]>;
229
233
  paintOrder?: import("../types/index.js").ConstantAccessor<string, DataRow[]>;
@@ -33,6 +33,7 @@ export declare function windowX(args: TransformArg<DataRecord>, options: WindowO
33
33
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
34
34
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
35
35
  clipPath?: string | undefined;
36
+ mask?: string | undefined;
36
37
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
37
38
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
38
39
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -100,6 +101,7 @@ export declare function windowY(args: TransformArg<DataRecord>, options: WindowO
100
101
  strokeDashoffset?: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/index.js").RawValue>>;
101
102
  mixBlendMode?: import("../types/index.js").ConstantAccessor<import("csstype").Property.MixBlendMode, Record<string | symbol, import("../types/index.js").RawValue>>;
102
103
  clipPath?: string | undefined;
104
+ mask?: string | undefined;
103
105
  imageFilter?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
104
106
  shapeRendering?: import("../types/index.js").ConstantAccessor<import("csstype").Property.ShapeRendering, Record<string | symbol, import("../types/index.js").RawValue>>;
105
107
  paintOrder?: import("../types/index.js").ConstantAccessor<string, Record<string | symbol, import("../types/index.js").RawValue>>;
@@ -6,7 +6,7 @@ export type Mark<T> = {
6
6
  data: DataRecord<T>[];
7
7
  options: T;
8
8
  };
9
- export type MarkType = 'area' | 'arrow' | 'barX' | 'barY' | 'cell' | 'custom' | 'dot' | 'vector' | 'frame' | 'geo' | 'gridX' | 'gridY' | 'line' | 'rect' | 'regression' | 'ruleX' | 'ruleY' | 'swoopyArrow' | 'text' | 'tickX' | 'tickY' | 'waffleX' | 'waffleY';
9
+ export type MarkType = 'area' | 'arrow' | 'barX' | 'barY' | 'cell' | 'custom' | 'dot' | 'vector' | 'frame' | 'geo' | 'gridX' | 'gridY' | 'line' | 'rect' | 'regression' | 'ruleX' | 'ruleY' | 'swoopyArrow' | 'text' | 'tickX' | 'tickY' | 'trail' | 'waffleX' | 'waffleY';
10
10
  export type MarkStyleProps = 'strokeDasharray' | 'strokeLinejoin' | 'strokeLinecap' | 'opacity' | 'cursor' | 'pointerEvents' | 'blend' | 'fill' | 'fillOpacity' | 'fontFamily' | 'fontWeight' | 'fontVariant' | 'fontSize' | 'fontStyle' | 'letterSpacing' | 'wordSpacing' | 'stroke' | 'strokeWidth' | 'strokeOpacity' | 'x' | 'y' | 'clipPath' | 'mask' | 'filter' | 'angle' | 'radius' | 'symbol' | 'textAnchor' | 'textTransform' | 'textDecoration' | 'width';
11
11
  import type { MouseEventHandler } from 'svelte/elements';
12
12
  import type { ChannelAccessor, ConstantAccessor, DataRecord, RawValue } from './index.js';
@@ -44,6 +44,7 @@ export type BaseMarkProps<T> = Partial<{
44
44
  strokeDashoffset: ConstantAccessor<number, T>;
45
45
  mixBlendMode: ConstantAccessor<CSS.Property.MixBlendMode, T>;
46
46
  clipPath: string;
47
+ mask: string;
47
48
  imageFilter: ConstantAccessor<string, T>;
48
49
  shapeRendering: ConstantAccessor<CSS.Property.ShapeRendering, T>;
49
50
  paintOrder: ConstantAccessor<string, T>;
@@ -3,7 +3,7 @@ import type { ColorScheme } from './colorScheme.js';
3
3
  import type { GeoProjection } from 'd3-geo';
4
4
  import type { ChannelAccessor, ChannelName, ColorScaleOptions, DataRecord, LegendScaleOptions, PlotScales, RawValue, ScaleOptions, XScaleOptions, YScaleOptions } from './index.js';
5
5
  import type { Snippet } from 'svelte';
6
- import type { Area, AreaX, AreaY, Arrow, AxisX, AxisY, BarX, BarY, BoxX, BoxY, Brush, BrushX, BrushY, Cell, DifferenceY, Dot, Frame, Geo, Graticule, GridX, GridY, Image, Line, Link, Pointer, Rect, RectX, RectY, RuleX, RuleY, Sphere, Spike, Text, TickX, TickY, Vector } from '../marks/index.js';
6
+ import type { Area, AreaX, AreaY, Arrow, AxisX, AxisY, BarX, BarY, BoxX, BoxY, Brush, BrushX, BrushY, Cell, DifferenceY, Dot, Frame, Geo, Graticule, GridX, GridY, Image, Line, Link, Pointer, Rect, RectX, RectY, RuleX, RuleY, Sphere, Spike, Text, TickX, TickY, Trail, Vector } from '../marks/index.js';
7
7
  import type WaffleX from '../marks/WaffleX.svelte';
8
8
  import type WaffleY from '../marks/WaffleY.svelte';
9
9
  export type PlotState = {
@@ -26,6 +26,7 @@ export type PlotState = {
26
26
  */
27
27
  hasFilledDotMarks: boolean;
28
28
  css: ((d: string) => string) | null;
29
+ publicState: Readonly<PlotState>;
29
30
  };
30
31
  export type PlotContext = {
31
32
  /**
@@ -296,6 +297,10 @@ export type PlotDefaults = {
296
297
  * default props for tickY marks
297
298
  */
298
299
  tickY: Partial<Omit<ComponentProps<typeof TickY>, IgnoreDefaults>>;
300
+ /**
301
+ * default props for tickY marks
302
+ */
303
+ trail: Partial<Omit<ComponentProps<typeof Trail>, IgnoreDefaults>>;
299
304
  /**
300
305
  * default props for vector marks
301
306
  */
@@ -1,6 +1,10 @@
1
1
  <script>
2
+ import { usePlot } from '../hooks/usePlot.svelte';
3
+
2
4
  let { numTurns = 4, finalRadius = 10, duration = 2, ...restProps } = $props();
3
5
 
6
+ const plot = usePlot();
7
+
4
8
  const pathD = $derived.by(() => {
5
9
  const numPoints = 100;
6
10
  const k = finalRadius / (2 * Math.PI * numTurns);