svelteplot 0.11.0 → 0.11.1-pr-520.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 (94) hide show
  1. package/dist/Mark.svelte +6 -1
  2. package/dist/Mark.svelte.d.ts +1 -1
  3. package/dist/constants.js +2 -0
  4. package/dist/core/Plot.svelte +32 -3
  5. package/dist/helpers/arrowPath.js +10 -5
  6. package/dist/helpers/autoScales.js +7 -3
  7. package/dist/helpers/autoTicks.js +4 -4
  8. package/dist/helpers/autoTimeFormat.js +22 -12
  9. package/dist/helpers/colors.d.ts +4 -4
  10. package/dist/helpers/facets.d.ts +42 -1
  11. package/dist/helpers/facets.js +83 -0
  12. package/dist/helpers/math.js +1 -1
  13. package/dist/helpers/noise.js +1 -1
  14. package/dist/helpers/rasterInterpolate.d.ts +26 -0
  15. package/dist/helpers/rasterInterpolate.js +220 -0
  16. package/dist/helpers/roundedRect.js +1 -1
  17. package/dist/helpers/scales.d.ts +1 -0
  18. package/dist/helpers/scales.js +8 -5
  19. package/dist/helpers/time.js +1 -1
  20. package/dist/helpers/typeChecks.d.ts +1 -0
  21. package/dist/helpers/typeChecks.js +3 -0
  22. package/dist/marks/Area.svelte.d.ts +1 -1
  23. package/dist/marks/AreaX.svelte.d.ts +1 -1
  24. package/dist/marks/AreaY.svelte.d.ts +1 -1
  25. package/dist/marks/Arrow.svelte.d.ts +1 -1
  26. package/dist/marks/AxisX.svelte +8 -3
  27. package/dist/marks/AxisX.svelte.d.ts +1 -1
  28. package/dist/marks/AxisY.svelte +8 -3
  29. package/dist/marks/AxisY.svelte.d.ts +1 -1
  30. package/dist/marks/BarX.svelte.d.ts +1 -1
  31. package/dist/marks/BarY.svelte.d.ts +1 -1
  32. package/dist/marks/BollingerX.svelte.d.ts +1 -1
  33. package/dist/marks/BollingerY.svelte.d.ts +1 -1
  34. package/dist/marks/BoxY.svelte.d.ts +1 -1
  35. package/dist/marks/Brush.svelte.d.ts +1 -1
  36. package/dist/marks/Cell.svelte.d.ts +1 -1
  37. package/dist/marks/CellX.svelte.d.ts +1 -1
  38. package/dist/marks/CellY.svelte.d.ts +1 -1
  39. package/dist/marks/CustomMark.svelte.d.ts +1 -1
  40. package/dist/marks/DifferenceY.svelte.d.ts +1 -1
  41. package/dist/marks/Dot.svelte.d.ts +1 -1
  42. package/dist/marks/DotX.svelte.d.ts +1 -1
  43. package/dist/marks/DotY.svelte.d.ts +1 -1
  44. package/dist/marks/Frame.svelte.d.ts +1 -1
  45. package/dist/marks/Geo.svelte.d.ts +1 -1
  46. package/dist/marks/GridX.svelte.d.ts +1 -1
  47. package/dist/marks/GridY.svelte.d.ts +1 -1
  48. package/dist/marks/HTMLTooltip.svelte +28 -25
  49. package/dist/marks/Image.svelte.d.ts +1 -1
  50. package/dist/marks/Line.svelte +52 -15
  51. package/dist/marks/Line.svelte.d.ts +1 -1
  52. package/dist/marks/LineX.svelte.d.ts +1 -1
  53. package/dist/marks/LineY.svelte.d.ts +1 -1
  54. package/dist/marks/Link.svelte.d.ts +1 -1
  55. package/dist/marks/Pointer.svelte +31 -29
  56. package/dist/marks/Raster.svelte +414 -0
  57. package/dist/marks/Raster.svelte.d.ts +94 -0
  58. package/dist/marks/Rect.svelte.d.ts +1 -1
  59. package/dist/marks/RectX.svelte.d.ts +1 -1
  60. package/dist/marks/RectY.svelte.d.ts +1 -1
  61. package/dist/marks/RuleX.svelte.d.ts +1 -1
  62. package/dist/marks/RuleY.svelte.d.ts +1 -1
  63. package/dist/marks/Spike.svelte.d.ts +1 -1
  64. package/dist/marks/Text.svelte +7 -5
  65. package/dist/marks/Text.svelte.d.ts +2 -2
  66. package/dist/marks/TickX.svelte.d.ts +1 -1
  67. package/dist/marks/TickY.svelte.d.ts +1 -1
  68. package/dist/marks/Trail.svelte.d.ts +1 -1
  69. package/dist/marks/Vector.svelte.d.ts +1 -1
  70. package/dist/marks/WaffleX.svelte.d.ts +1 -1
  71. package/dist/marks/WaffleY.svelte.d.ts +1 -1
  72. package/dist/marks/helpers/Box.svelte.d.ts +1 -1
  73. package/dist/marks/helpers/MarkerPath.svelte.d.ts +1 -1
  74. package/dist/marks/helpers/Regression.svelte +2 -1
  75. package/dist/marks/helpers/trail.js +1 -1
  76. package/dist/marks/helpers/waffle.js +1 -1
  77. package/dist/marks/index.d.ts +1 -0
  78. package/dist/marks/index.js +1 -0
  79. package/dist/regression/polynomial.js +2 -2
  80. package/dist/transforms/bollinger.js +6 -3
  81. package/dist/transforms/density.js +3 -3
  82. package/dist/transforms/group.d.ts +1 -1
  83. package/dist/transforms/interval.d.ts +2 -2
  84. package/dist/transforms/jitter.d.ts +3 -3
  85. package/dist/transforms/map.d.ts +3 -3
  86. package/dist/transforms/map.js +2 -2
  87. package/dist/transforms/normalize.d.ts +2 -2
  88. package/dist/transforms/normalize.js +1 -1
  89. package/dist/transforms/select.d.ts +7 -7
  90. package/dist/transforms/window.d.ts +2 -2
  91. package/dist/types/mark.d.ts +3 -3
  92. package/dist/types/plot.d.ts +8 -1
  93. package/dist/types/scale.d.ts +2 -2
  94. package/package.json +183 -179
@@ -0,0 +1,414 @@
1
+ <!-- @component
2
+ Renders a raster image in one of three modes:
3
+
4
+ **Dense grid mode** (`data` is an array, `width` and `height` are set, no
5
+ `x`/`y` channels): the data is treated as a row-major grid of fill values.
6
+ `fill` defaults to the identity function (each datum is its own value).
7
+
8
+ **Function sampling mode** (`data` is omitted/null, `fill` and/or
9
+ `fillOpacity` are `(x, y) => value` functions): the mark evaluates the
10
+ function on a pixel grid, converting pixel coords to data coords via scale
11
+ inversion, then maps results through the color scale.
12
+
13
+ **Scatter interpolation mode** (`data` is an array with `x`/`y` channels):
14
+ each datum contributes a position and fill value; the mark spatially
15
+ interpolates over the grid using the chosen `interpolate` method.
16
+ -->
17
+ <script lang="ts" generics="Datum extends DataRow">
18
+ interface RasterMarkProps {
19
+ /**
20
+ * Input data. For **dense grid** mode supply a flat row-major array and
21
+ * set `width`/`height`. Omit (or set null) for **function-sampling**
22
+ * mode. For **scatter interpolation** supply an array of records with
23
+ * `x`/`y` channels.
24
+ */
25
+ data?: Datum[] | null;
26
+ /** x position channel (scatter interpolation mode) */
27
+ x?: ChannelAccessor<Datum>;
28
+ /** y position channel (scatter interpolation mode) */
29
+ y?: ChannelAccessor<Datum>;
30
+ /**
31
+ * fill color channel, identity function for dense grid, or an
32
+ * `(x, y) => value` function for function-sampling mode
33
+ */
34
+ fill?: ChannelAccessor<Datum> | ((x: number, y: number) => any);
35
+ /**
36
+ * fill opacity channel or an `(x, y) => number` function for
37
+ * function-sampling mode
38
+ */
39
+ fillOpacity?: ChannelAccessor<Datum> | ((x: number, y: number) => number);
40
+ /** left bound of the raster in data coordinates */
41
+ x1?: number;
42
+ /** top bound of the raster in data coordinates */
43
+ y1?: number;
44
+ /** right bound of the raster in data coordinates */
45
+ x2?: number;
46
+ /** bottom bound of the raster in data coordinates */
47
+ y2?: number;
48
+ /**
49
+ * explicit pixel-grid width; required for dense grid mode, also used
50
+ * to set the canvas resolution in other modes (overrides `pixelSize`)
51
+ */
52
+ width?: number;
53
+ /**
54
+ * explicit pixel-grid height; required for dense grid mode, also used
55
+ * to set the canvas resolution in other modes (overrides `pixelSize`)
56
+ */
57
+ height?: number;
58
+ /** pixel size in screen pixels (default 1); ignored when `width`/`height` are set */
59
+ pixelSize?: number;
60
+ /** Gaussian blur radius in grid pixels (default 0) */
61
+ blur?: number;
62
+ /**
63
+ * spatial interpolation for scatter mode:
64
+ * `"none"` | `"nearest"` | `"barycentric"` | `"random-walk"` or a
65
+ * custom `(index, w, h, X, Y, V) => W` function
66
+ */
67
+ interpolate?: 'none' | 'nearest' | 'barycentric' | 'random-walk' | InterpolateFunction;
68
+ /** CSS image-rendering property (default `"auto"`) */
69
+ imageRendering?: string;
70
+ }
71
+
72
+ import type {
73
+ DataRow,
74
+ DataRecord,
75
+ ChannelAccessor,
76
+ ScaledDataRecord,
77
+ MarkType
78
+ } from '../types/index.js';
79
+ import { blurImage, extent } from 'd3-array';
80
+ import { rgb } from 'd3-color';
81
+ import Mark from '../Mark.svelte';
82
+ import { usePlot } from '../hooks/usePlot.svelte.js';
83
+ import {
84
+ interpolateNone,
85
+ interpolateNearest,
86
+ interpolatorBarycentric,
87
+ interpolatorRandomWalk,
88
+ type InterpolateFunction
89
+ } from '../helpers/rasterInterpolate.js';
90
+ import { X, Y, RAW_VALUE } from '../transforms/recordize.js';
91
+ import { scaleLinear } from 'd3-scale';
92
+
93
+ let markProps: RasterMarkProps = $props();
94
+
95
+ const {
96
+ data,
97
+ fill,
98
+ fillOpacity,
99
+ x1: x1Prop,
100
+ y1: y1Prop,
101
+ x2: x2Prop,
102
+ y2: y2Prop,
103
+ width: widthProp,
104
+ height: heightProp,
105
+ pixelSize = 1,
106
+ blur = 0,
107
+ interpolate,
108
+ imageRendering = 'auto',
109
+ ...options
110
+ }: RasterMarkProps = $derived({ ...markProps });
111
+
112
+ const plot = usePlot();
113
+
114
+ /** No data: fill/fillOpacity are (x,y) functions */
115
+ const isSamplerMode = $derived(data == null);
116
+
117
+ /**
118
+ * Dense grid: data is a flat array, width+height are given, no x/y
119
+ * channels. Each datum is its own fill value (unless fill is specified).
120
+ */
121
+ const isDenseGridMode = $derived(
122
+ data != null &&
123
+ widthProp != null &&
124
+ heightProp != null &&
125
+ (options as any).x == null &&
126
+ (options as any).y == null
127
+ );
128
+
129
+ $inspect({ isSamplerMode, isDenseGridMode });
130
+
131
+ const interpolateFn = $derived(resolveInterpolate(interpolate));
132
+
133
+ function resolveInterpolate(interp: RasterMarkProps['interpolate']): InterpolateFunction {
134
+ if (typeof interp === 'function') return interp;
135
+ if (interp == null) return interpolateNone;
136
+ switch (String(interp).toLowerCase()) {
137
+ case 'none':
138
+ return interpolateNone;
139
+ case 'nearest':
140
+ return interpolateNearest;
141
+ case 'barycentric':
142
+ return interpolatorBarycentric();
143
+ case 'random-walk':
144
+ return interpolatorRandomWalk();
145
+ }
146
+ throw new Error(`invalid interpolate: ${interp}`);
147
+ }
148
+
149
+ /** Pixel-space bounds of the raster image. */
150
+ function getBounds() {
151
+ return { bx1: 0, by1: 0, bx2: plot.facetWidth ?? 100, by2: plot.facetHeight ?? 100 };
152
+ }
153
+
154
+ /** Build the off-screen canvas and return it together with its bounds. */
155
+ function computeCanvas(scaledData: ScaledDataRecord[]): {
156
+ canvas: HTMLCanvasElement;
157
+ bx1: number;
158
+ by1: number;
159
+ dx: number;
160
+ dy: number;
161
+ } | null {
162
+ if (typeof document === 'undefined') return null;
163
+
164
+ const { bx1, by1, bx2, by2 } = getBounds();
165
+ const dx = bx2 - bx1;
166
+ const dy = by2 - by1;
167
+ // Canvas pixel dimensions
168
+ const w = widthProp ?? Math.round(Math.abs(dx) / pixelSize);
169
+ const h = heightProp ?? Math.round(Math.abs(dy) / pixelSize);
170
+ if (w <= 0 || h <= 0) return null;
171
+ const n = w * h;
172
+
173
+ // --- Populate fill value array F (and optional opacity array FO) ---
174
+ let F: any[] | null = null;
175
+ let FO: number[] | null = null;
176
+
177
+ if (isDenseGridMode) {
178
+ // Build the value array in data order, then flip rows so that
179
+ // data row 0 (y=0) renders at the bottom of the canvas, matching
180
+ // the standard y-up chart convention.
181
+ let Fraw: any[];
182
+ if (typeof fill === 'function') {
183
+ Fraw = (data as any[]).map(fill as (d: any) => any);
184
+ } else if (fill != null && typeof fill !== 'string') {
185
+ Fraw = (data as any[]).map((d) =>
186
+ typeof fill === 'string' ? d[fill] : (fill as (d: any) => any)(d)
187
+ );
188
+ } else {
189
+ Fraw = data as any[];
190
+ }
191
+ // Flip vertically: canvas row 0 (top) = data row h-1 (highest y).
192
+ F = new Array(n);
193
+ for (let row = 0; row < h; ++row) {
194
+ const srcRow = h - 1 - row;
195
+ for (let col = 0; col < w; ++col) {
196
+ F[row * w + col] = Fraw[srcRow * w + col];
197
+ }
198
+ }
199
+ } else if (isSamplerMode) {
200
+ // Evaluate f(x,y) for every grid pixel
201
+ const xScale = scaleLinear().range([x1Prop, x2Prop]).domain([0, w]);
202
+ const yScale = scaleLinear().range([y1Prop, y2Prop]).domain([0, h]);
203
+ const kx = dx / w;
204
+ const ky = dy / h;
205
+ if (typeof fill === 'function') {
206
+ F = new Array(n);
207
+ let i = 0;
208
+ for (let yi = 0.5; yi < h; ++yi) {
209
+ for (let xi = 0.5; xi < w; ++xi, ++i) {
210
+ const xData = xScale(bx1 + xi * kx);
211
+ const yData = yScale(by1 + yi * ky);
212
+ // console.log({ xData, yData, xi, w, yi, h });
213
+ F[i] = (fill as (x: any, y: any) => any)(xData, yData);
214
+ }
215
+ }
216
+ console.log({ F });
217
+ }
218
+ if (typeof fillOpacity === 'function') {
219
+ FO = new Array(n);
220
+ let i = 0;
221
+ for (let yi = 0.5; yi < h; ++yi) {
222
+ for (let xi = 0.5; xi < w; ++xi, ++i) {
223
+ const xData = xScale(bx1 + xi * kx);
224
+ const yData = yScale(by1 + yi * ky);
225
+ FO[i] = (fillOpacity as (x: any, y: any) => number)(xData, yData);
226
+ }
227
+ }
228
+ }
229
+ } else if (scaledData.length > 0) {
230
+ // Scatter interpolation: map data points onto grid
231
+ const validData = scaledData.filter((d) => d.valid && d.x != null && d.y != null);
232
+
233
+ if (validData.length > 0) {
234
+ const kx = w / dx;
235
+ const ky = h / dy;
236
+ const index = validData.map((_, i) => i);
237
+ const IX = new Float64Array(validData.map((d) => ((d.x as number) - bx1) * kx));
238
+ const IY = new Float64Array(validData.map((d) => ((d.y as number) - by1) * ky));
239
+ // Use raw pre-color-scale fill values so we can interpolate
240
+ // numerically, then apply the color scale after interpolation.
241
+ const rawFill = validData.map((d) => d.resolved?.fill);
242
+ if (rawFill.some((v) => v != null)) {
243
+ F = Array.from(interpolateFn(index, w, h, IX, IY, rawFill));
244
+ }
245
+ if (fillOpacity !== undefined) {
246
+ const rawFO = validData.map((d) => d.resolved?.fillOpacity);
247
+ if (rawFO.some((v) => v != null)) {
248
+ FO = Array.from(interpolateFn(index, w, h, IX, IY, rawFO)) as number[];
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ // --- Rasterize: map value array to RGBA pixel data ---
255
+ const canvas = document.createElement('canvas');
256
+ canvas.width = w;
257
+ canvas.height = h;
258
+ const ctx = canvas.getContext('2d')!;
259
+ const imageData = ctx.createImageData(w, h);
260
+ const imgData = imageData.data;
261
+
262
+ // For sampler mode the fill function values are not registered with the
263
+ // Plot's mark data (to avoid reactive cycles), so the color scale may
264
+ // not have a domain set. In that case we compute the F extent here and
265
+ // rescale through the plot color scale using a normalised [0,1] input.
266
+ let colorFn: (v: any) => any = plot.scales.color?.fn ?? ((x: any) => x);
267
+ if (isSamplerMode && F && plot.scales.color?.fn) {
268
+ const [fMin, fMax] = extent(F.filter((v) => v != null) as number[]);
269
+ const colorDomain = plot.scales.color.fn.domain?.() ?? [];
270
+ const domainIsEmpty =
271
+ colorDomain.length === 0 || colorDomain[0] === colorDomain[colorDomain.length - 1];
272
+ if (domainIsEmpty && fMin != null && fMax != null && fMin !== fMax) {
273
+ // Remap raw F values into the color scale's current domain range
274
+ const [dMin, dMax] =
275
+ colorDomain.length >= 2
276
+ ? [colorDomain[0] as number, colorDomain[colorDomain.length - 1] as number]
277
+ : [0, 1];
278
+ const span = fMax - fMin;
279
+ colorFn = (v: any) =>
280
+ plot.scales.color!.fn(dMin + ((v - fMin) / span) * (dMax - dMin));
281
+ }
282
+ }
283
+
284
+ const defColor = typeof fill === 'string' ? rgb(fill) : null;
285
+ const defR = defColor?.r ?? 0;
286
+ const defG = defColor?.g ?? 0;
287
+ const defB = defColor?.b ?? 0;
288
+ const defA = typeof fillOpacity === 'number' ? fillOpacity * 255 : F ? 255 : 0;
289
+
290
+ for (let i = 0; i < n; ++i) {
291
+ const j = i << 2;
292
+ let r = defR,
293
+ g = defG,
294
+ b = defB,
295
+ a = defA;
296
+
297
+ if (F) {
298
+ const colorVal = colorFn(F[i]);
299
+ if (colorVal == null) {
300
+ imgData[j + 3] = 0;
301
+ continue;
302
+ }
303
+ const c = rgb(String(colorVal));
304
+ if (c) ({ r, g, b } = c);
305
+ a = 255;
306
+ }
307
+
308
+ if (FO != null) a = (FO[i] ?? 0) * 255;
309
+
310
+ imgData[j + 0] = r;
311
+ imgData[j + 1] = g;
312
+ imgData[j + 2] = b;
313
+ imgData[j + 3] = a;
314
+ }
315
+
316
+ if (blur > 0) blurImage(imageData, blur);
317
+ ctx.putImageData(imageData, 0, 0);
318
+
319
+ return { canvas, bx1, by1, dx, dy };
320
+ }
321
+
322
+ /**
323
+ * Resolves the fill value for a single datum in dense grid mode.
324
+ * The datum may be a raw primitive or a record; `fill` may be a
325
+ * field name, accessor, or omitted (identity).
326
+ */
327
+ function resolveFillValue(datum: any): any {
328
+ if (fill == null) return datum; // identity: datum IS the value
329
+ if (typeof fill === 'string') return datum[fill];
330
+ if (typeof fill === 'function') return (fill as (d: any) => any)(datum);
331
+ return datum;
332
+ }
333
+
334
+ /**
335
+ * For dense grid mode, fold the flat array into records keyed by Symbols
336
+ * (like recordizeXY). Symbol keys survive `{ ...d, [INDEX]: i }` spreading
337
+ * in Mark.svelte, so scale domains are computed from the actual values.
338
+ * The grid column/row indices become x/y channels so the x and y scale
339
+ * domains are also registered (0..width-1 and 0..height-1).
340
+ */
341
+ const denseMarkData = $derived(
342
+ isDenseGridMode
343
+ ? (data as any[]).map((d, i) => ({
344
+ [X]: i % widthProp!,
345
+ [Y]: Math.floor(i / widthProp!),
346
+ [RAW_VALUE]: resolveFillValue(d)
347
+ }))
348
+ : null
349
+ );
350
+
351
+ /**
352
+ * For sampler mode, pass two corner records so the Plot can register the
353
+ * x/y scale domains from x1/y1/x2/y2. We intentionally do NOT pre-evaluate
354
+ * the fill function here — doing so inside a $derived creates a reactive
355
+ * cycle because the resulting array (new reference each evaluation) feeds
356
+ * back through Mark → plot.scales → scaledData → effect → mark.data.
357
+ * The color scale domain is handled directly inside computeCanvas instead.
358
+ */
359
+ const samplerMarkData = $derived.by(() => {
360
+ if (!isSamplerMode) return null;
361
+ const x1 = x1Prop,
362
+ x2 = x2Prop,
363
+ y1 = y1Prop,
364
+ y2 = y2Prop;
365
+ if (x1 == null || x2 == null || y1 == null || y2 == null) return null;
366
+ return [
367
+ { [X]: x1, [Y]: y1 },
368
+ { [X]: x2, [Y]: y2 }
369
+ ] as unknown as DataRecord[];
370
+ });
371
+
372
+ const markChannels = $derived(
373
+ isDenseGridMode
374
+ ? (['x', 'y', 'fill'] as const)
375
+ : isSamplerMode
376
+ ? (['x', 'y'] as const)
377
+ : (['x', 'y', 'fill', 'fillOpacity'] as const)
378
+ );
379
+
380
+ const markFill = $derived(
381
+ isDenseGridMode ? (RAW_VALUE as any) : !isSamplerMode ? (fill as any) : undefined
382
+ );
383
+
384
+ const markX = $derived(isDenseGridMode || isSamplerMode ? (X as any) : undefined);
385
+ const markY = $derived(isDenseGridMode || isSamplerMode ? (Y as any) : undefined);
386
+ </script>
387
+
388
+ <Mark
389
+ type={'raster' as MarkType}
390
+ data={isDenseGridMode
391
+ ? (denseMarkData as DataRecord[])
392
+ : isSamplerMode
393
+ ? ((samplerMarkData ?? []) as DataRecord[])
394
+ : ((data ?? []) as DataRecord[])}
395
+ channels={markChannels as any}
396
+ x={markX}
397
+ y={markY}
398
+ fill={markFill}
399
+ fillOpacity={!isSamplerMode && !isDenseGridMode ? (fillOpacity as any) : undefined}
400
+ {...options}>
401
+ {#snippet children({ scaledData })}
402
+ {@const result = computeCanvas(scaledData)}
403
+ {#if result}
404
+ <image
405
+ transform="translate({plot.options.marginLeft},{plot.options
406
+ .marginTop}) scale({Math.sign(result.dx)},{Math.sign(result.dy)})"
407
+ width={Math.abs(result.dx)}
408
+ height={Math.abs(result.dy)}
409
+ preserveAspectRatio="none"
410
+ image-rendering={imageRendering}
411
+ href={result.canvas.toDataURL()} />
412
+ {/if}
413
+ {/snippet}
414
+ </Mark>
@@ -0,0 +1,94 @@
1
+ import type { DataRow, ChannelAccessor } from '../types/index.js';
2
+ import { type InterpolateFunction } from '../helpers/rasterInterpolate.js';
3
+ declare function $$render<Datum extends DataRow>(): {
4
+ props: {
5
+ /**
6
+ * Input data. For **dense grid** mode supply a flat row-major array and
7
+ * set `width`/`height`. Omit (or set null) for **function-sampling**
8
+ * mode. For **scatter interpolation** supply an array of records with
9
+ * `x`/`y` channels.
10
+ */
11
+ data?: Datum[] | null;
12
+ /** x position channel (scatter interpolation mode) */
13
+ x?: ChannelAccessor<Datum>;
14
+ /** y position channel (scatter interpolation mode) */
15
+ y?: ChannelAccessor<Datum>;
16
+ /**
17
+ * fill color channel, identity function for dense grid, or an
18
+ * `(x, y) => value` function for function-sampling mode
19
+ */
20
+ fill?: ChannelAccessor<Datum> | ((x: number, y: number) => any);
21
+ /**
22
+ * fill opacity channel or an `(x, y) => number` function for
23
+ * function-sampling mode
24
+ */
25
+ fillOpacity?: ChannelAccessor<Datum> | ((x: number, y: number) => number);
26
+ /** left bound of the raster in data coordinates */
27
+ x1?: number;
28
+ /** top bound of the raster in data coordinates */
29
+ y1?: number;
30
+ /** right bound of the raster in data coordinates */
31
+ x2?: number;
32
+ /** bottom bound of the raster in data coordinates */
33
+ y2?: number;
34
+ /**
35
+ * explicit pixel-grid width; required for dense grid mode, also used
36
+ * to set the canvas resolution in other modes (overrides `pixelSize`)
37
+ */
38
+ width?: number;
39
+ /**
40
+ * explicit pixel-grid height; required for dense grid mode, also used
41
+ * to set the canvas resolution in other modes (overrides `pixelSize`)
42
+ */
43
+ height?: number;
44
+ /** pixel size in screen pixels (default 1); ignored when `width`/`height` are set */
45
+ pixelSize?: number;
46
+ /** Gaussian blur radius in grid pixels (default 0) */
47
+ blur?: number;
48
+ /**
49
+ * spatial interpolation for scatter mode:
50
+ * `"none"` | `"nearest"` | `"barycentric"` | `"random-walk"` or a
51
+ * custom `(index, w, h, X, Y, V) => W` function
52
+ */
53
+ interpolate?: "none" | "nearest" | "barycentric" | "random-walk" | InterpolateFunction;
54
+ /** CSS image-rendering property (default `"auto"`) */
55
+ imageRendering?: string;
56
+ };
57
+ exports: {};
58
+ bindings: "";
59
+ slots: {};
60
+ events: {};
61
+ };
62
+ declare class __sveltets_Render<Datum extends DataRow> {
63
+ props(): ReturnType<typeof $$render<Datum>>['props'];
64
+ events(): ReturnType<typeof $$render<Datum>>['events'];
65
+ slots(): ReturnType<typeof $$render<Datum>>['slots'];
66
+ bindings(): "";
67
+ exports(): {};
68
+ }
69
+ interface $$IsomorphicComponent {
70
+ new <Datum extends DataRow>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Datum>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Datum>['props']>, ReturnType<__sveltets_Render<Datum>['events']>, ReturnType<__sveltets_Render<Datum>['slots']>> & {
71
+ $$bindings?: ReturnType<__sveltets_Render<Datum>['bindings']>;
72
+ } & ReturnType<__sveltets_Render<Datum>['exports']>;
73
+ <Datum extends DataRow>(internal: unknown, props: ReturnType<__sveltets_Render<Datum>['props']> & {}): ReturnType<__sveltets_Render<Datum>['exports']>;
74
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
75
+ }
76
+ /**
77
+ * Renders a raster image in one of three modes:
78
+ *
79
+ * **Dense grid mode** (`data` is an array, `width` and `height` are set, no
80
+ * `x`/`y` channels): the data is treated as a row-major grid of fill values.
81
+ * `fill` defaults to the identity function (each datum is its own value).
82
+ *
83
+ * **Function sampling mode** (`data` is omitted/null, `fill` and/or
84
+ * `fillOpacity` are `(x, y) => value` functions): the mark evaluates the
85
+ * function on a pixel grid, converting pixel coords to data coords via scale
86
+ * inversion, then maps results through the color scale.
87
+ *
88
+ * **Scatter interpolation mode** (`data` is an array with `x`/`y` channels):
89
+ * each datum contributes a position and fill value; the mark spatially
90
+ * interpolates over the grid using the chosen `interpolate` method.
91
+ */
92
+ declare const Raster: $$IsomorphicComponent;
93
+ type Raster<Datum extends DataRow> = InstanceType<typeof Raster<Datum>>;
94
+ export default Raster;
@@ -12,7 +12,7 @@ declare function $$render<Datum extends DataRecord>(): {
12
12
  fill: ChannelAccessor<Datum>;
13
13
  fillOpacity: import("../types/index.js").ConstantAccessor<number, Datum>;
14
14
  fontFamily: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
- fontSize: import("../types/index.js").ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
15
+ fontSize: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
16
  fontStyle: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
17
  fontVariant: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
18
  fontWeight: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
@@ -13,7 +13,7 @@ declare function $$render<Datum extends DataRow>(): {
13
13
  fill: import("../types/channel.js").ChannelAccessor<Record<string | symbol, import("../types/data.js").RawValue>>;
14
14
  fillOpacity: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/data.js").RawValue>>;
15
15
  fontFamily: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, Record<string | symbol, import("../types/data.js").RawValue>>;
16
- fontSize: import("../types/index.js").ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Record<string | symbol, import("../types/data.js").RawValue>>;
16
+ fontSize: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, Record<string | symbol, import("../types/data.js").RawValue>>;
17
17
  fontStyle: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, Record<string | symbol, import("../types/data.js").RawValue>>;
18
18
  fontVariant: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, Record<string | symbol, import("../types/data.js").RawValue>>;
19
19
  fontWeight: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, Record<string | symbol, import("../types/data.js").RawValue>>;
@@ -13,7 +13,7 @@ declare function $$render<Datum extends DataRow>(): {
13
13
  fill: import("../types/channel.js").ChannelAccessor<Record<string | symbol, import("../types/data.js").RawValue>>;
14
14
  fillOpacity: import("../types/index.js").ConstantAccessor<number, Record<string | symbol, import("../types/data.js").RawValue>>;
15
15
  fontFamily: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, Record<string | symbol, import("../types/data.js").RawValue>>;
16
- fontSize: import("../types/index.js").ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Record<string | symbol, import("../types/data.js").RawValue>>;
16
+ fontSize: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, Record<string | symbol, import("../types/data.js").RawValue>>;
17
17
  fontStyle: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, Record<string | symbol, import("../types/data.js").RawValue>>;
18
18
  fontVariant: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, Record<string | symbol, import("../types/data.js").RawValue>>;
19
19
  fontWeight: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, Record<string | symbol, import("../types/data.js").RawValue>>;
@@ -12,7 +12,7 @@ declare function $$render<Datum = DataRecord | RawValue>(): {
12
12
  fill: ChannelAccessor<Datum>;
13
13
  fillOpacity: ConstantAccessor<number, Datum>;
14
14
  fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
15
+ fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
16
  fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
17
  fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
18
  fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
@@ -12,7 +12,7 @@ declare function $$render<Datum = DataRecord>(): {
12
12
  fill: ChannelAccessor<Datum>;
13
13
  fillOpacity: ConstantAccessor<number, Datum>;
14
14
  fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
15
+ fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
16
  fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
17
  fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
18
  fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
@@ -12,7 +12,7 @@ declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
12
12
  fill: ChannelAccessor<unknown>;
13
13
  fillOpacity: import("../types/index.js").ConstantAccessor<number, unknown>;
14
14
  fontFamily: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, unknown>;
15
- fontSize: import("../types/index.js").ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", unknown>;
15
+ fontSize: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, unknown>;
16
16
  fontStyle: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, unknown>;
17
17
  fontVariant: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, unknown>;
18
18
  fontWeight: import("../types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, unknown>;
@@ -109,7 +109,7 @@
109
109
 
110
110
  import MultilineText from './helpers/MultilineText.svelte';
111
111
  import TextCanvas from './helpers/TextCanvas.svelte';
112
- import { indexData } from '../transforms/recordize.js';
112
+ import { indexData, recordize } from '../transforms/recordize.js';
113
113
  import { getPlotDefaults } from '../hooks/plotDefaults.js';
114
114
 
115
115
  const DEFAULTS = {
@@ -137,10 +137,12 @@
137
137
  } = $derived(mergedProps);
138
138
 
139
139
  const args = $derived(
140
- sort({
141
- data: indexData(data as object[]) as any,
142
- ...options
143
- })
140
+ sort(
141
+ recordize({
142
+ data,
143
+ ...options
144
+ })
145
+ )
144
146
  ) as TextMarkProps;
145
147
  </script>
146
148
 
@@ -14,7 +14,7 @@ declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
14
14
  fill: ChannelAccessor<Datum>;
15
15
  fillOpacity: ConstantAccessor<number, Datum>;
16
16
  fontFamily: ConstantAccessor<CSS.Property.FontFamily, Datum>;
17
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
17
+ fontSize: ConstantAccessor<CSS.Property.FontSize<number>, Datum>;
18
18
  fontStyle: ConstantAccessor<CSS.Property.FontStyle, Datum>;
19
19
  fontVariant: ConstantAccessor<CSS.Property.FontVariant, Datum>;
20
20
  fontWeight: ConstantAccessor<CSS.Property.FontWeight, Datum>;
@@ -212,7 +212,7 @@ declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
212
212
  fill: ChannelAccessor<Datum>;
213
213
  fillOpacity: ConstantAccessor<number, Datum>;
214
214
  fontFamily: ConstantAccessor<CSS.Property.FontFamily, Datum>;
215
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
215
+ fontSize: ConstantAccessor<CSS.Property.FontSize<number>, Datum>;
216
216
  fontStyle: ConstantAccessor<CSS.Property.FontStyle, Datum>;
217
217
  fontVariant: ConstantAccessor<CSS.Property.FontVariant, Datum>;
218
218
  fontWeight: ConstantAccessor<CSS.Property.FontWeight, Datum>;
@@ -12,7 +12,7 @@ declare function $$render<Datum = DataRecord | RawValue>(): {
12
12
  fill: ChannelAccessor<Datum>;
13
13
  fillOpacity: ConstantAccessor<number, Datum>;
14
14
  fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
15
+ fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
16
  fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
17
  fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
18
  fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
@@ -12,7 +12,7 @@ declare function $$render<Datum = DataRecord | RawValue>(): {
12
12
  fill: ChannelAccessor<Datum>;
13
13
  fillOpacity: ConstantAccessor<number, Datum>;
14
14
  fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
15
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
15
+ fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
16
16
  fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
17
17
  fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
18
18
  fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
@@ -13,7 +13,7 @@ declare function $$render<Datum extends DataRecord>(): {
13
13
  fill: ChannelAccessor<Datum>;
14
14
  fillOpacity: ConstantAccessor<number, Datum>;
15
15
  fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
16
- fontSize: ConstantAccessor<number | "-moz-initial" | "inherit" | "initial" | "revert" | "revert-layer" | "unset" | "math" | (string & {}) | "large" | "medium" | "small" | "x-large" | "x-small" | "xx-large" | "xx-small" | "xxx-large" | "larger" | "smaller", Datum>;
16
+ fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
17
17
  fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
18
18
  fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
19
19
  fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;