svelteplot 0.10.3 → 0.11.0-pr-514.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/Mark.svelte +42 -25
- package/dist/Mark.svelte.d.ts +111 -32
- package/dist/Plot.svelte +21 -15
- package/dist/core/Facet.svelte +1 -1
- package/dist/core/FacetAxes.svelte +13 -8
- package/dist/core/FacetGrid.svelte +4 -4
- package/dist/core/Plot.svelte +70 -36
- package/dist/helpers/arrowPath.js +10 -5
- package/dist/helpers/autoScales.d.ts +3 -3
- package/dist/helpers/autoScales.js +28 -18
- package/dist/helpers/autoTicks.js +2 -0
- package/dist/helpers/callWithProps.d.ts +1 -2
- package/dist/helpers/colors.d.ts +4 -4
- package/dist/helpers/facets.d.ts +42 -1
- package/dist/helpers/facets.js +83 -1
- package/dist/helpers/index.js +1 -1
- package/dist/helpers/math.js +1 -1
- package/dist/helpers/mergeDeep.d.ts +1 -3
- package/dist/helpers/mergeDeep.js +15 -16
- package/dist/helpers/noise.js +1 -1
- package/dist/helpers/projection.d.ts +4 -3
- package/dist/helpers/projection.js +17 -5
- package/dist/helpers/reduce.d.ts +4 -4
- package/dist/helpers/reduce.js +6 -4
- package/dist/helpers/regressionLoess.js +2 -1
- package/dist/helpers/resolve.d.ts +6 -3
- package/dist/helpers/resolve.js +25 -16
- package/dist/helpers/roundedRect.js +1 -1
- package/dist/helpers/scales.d.ts +11 -10
- package/dist/helpers/scales.js +43 -13
- package/dist/helpers/time.d.ts +10 -3
- package/dist/helpers/time.js +2 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/plotDefaults.d.ts +3 -1
- package/dist/hooks/plotDefaults.js +33 -1
- package/dist/hooks/usePlot.svelte.d.ts +10 -25
- package/dist/hooks/usePlot.svelte.js +8 -7
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -3
- package/dist/marks/Area.svelte +24 -13
- package/dist/marks/Area.svelte.d.ts +118 -34
- package/dist/marks/AreaX.svelte +42 -8
- package/dist/marks/AreaX.svelte.d.ts +154 -71
- package/dist/marks/AreaY.svelte +42 -8
- package/dist/marks/AreaY.svelte.d.ts +154 -71
- package/dist/marks/Arrow.svelte +42 -23
- package/dist/marks/Arrow.svelte.d.ts +114 -35
- package/dist/marks/AxisX.svelte +43 -28
- package/dist/marks/AxisX.svelte.d.ts +125 -40
- package/dist/marks/AxisY.svelte +43 -26
- package/dist/marks/AxisY.svelte.d.ts +127 -40
- package/dist/marks/BarX.svelte +12 -10
- package/dist/marks/BarX.svelte.d.ts +104 -32
- package/dist/marks/BarY.svelte +11 -10
- package/dist/marks/BarY.svelte.d.ts +106 -34
- package/dist/marks/BollingerX.svelte +4 -7
- package/dist/marks/BollingerX.svelte.d.ts +105 -30
- package/dist/marks/BollingerY.svelte +3 -0
- package/dist/marks/BollingerY.svelte.d.ts +105 -30
- package/dist/marks/BoxX.svelte +3 -3
- package/dist/marks/BoxY.svelte +12 -9
- package/dist/marks/BoxY.svelte.d.ts +128 -53
- package/dist/marks/Brush.svelte +26 -21
- package/dist/marks/Brush.svelte.d.ts +119 -60
- package/dist/marks/Cell.svelte +13 -9
- package/dist/marks/Cell.svelte.d.ts +105 -30
- package/dist/marks/CellX.svelte +2 -1
- package/dist/marks/CellX.svelte.d.ts +105 -32
- package/dist/marks/CellY.svelte +2 -1
- package/dist/marks/CellY.svelte.d.ts +105 -32
- package/dist/marks/ColorLegend.svelte +24 -13
- package/dist/marks/ColorLegend.svelte.d.ts +1 -0
- package/dist/marks/CustomMark.svelte +16 -10
- package/dist/marks/CustomMark.svelte.d.ts +112 -31
- package/dist/marks/CustomMarkHTML.svelte +8 -2
- package/dist/marks/CustomMarkHTML.svelte.d.ts +8 -2
- package/dist/marks/DifferenceY.svelte +31 -20
- package/dist/marks/DifferenceY.svelte.d.ts +134 -55
- package/dist/marks/Dot.svelte +21 -11
- package/dist/marks/Dot.svelte.d.ts +117 -38
- package/dist/marks/DotX.svelte +2 -0
- package/dist/marks/DotX.svelte.d.ts +136 -62
- package/dist/marks/DotY.svelte +1 -0
- package/dist/marks/DotY.svelte.d.ts +135 -62
- package/dist/marks/Frame.svelte +47 -9
- package/dist/marks/Frame.svelte.d.ts +124 -41
- package/dist/marks/Geo.svelte +21 -12
- package/dist/marks/Geo.svelte.d.ts +105 -30
- package/dist/marks/Graticule.svelte +3 -0
- package/dist/marks/Graticule.svelte.d.ts +3 -0
- package/dist/marks/GridX.svelte +31 -16
- package/dist/marks/GridX.svelte.d.ts +108 -32
- package/dist/marks/GridY.svelte +30 -15
- package/dist/marks/GridY.svelte.d.ts +108 -32
- package/dist/marks/HTMLTooltip.svelte +37 -27
- package/dist/marks/HTMLTooltip.svelte.d.ts +7 -0
- package/dist/marks/Image.svelte +50 -25
- package/dist/marks/Image.svelte.d.ts +117 -35
- package/dist/marks/Line.svelte +67 -44
- package/dist/marks/Line.svelte.d.ts +119 -30
- package/dist/marks/LineX.svelte +2 -1
- package/dist/marks/LineX.svelte.d.ts +142 -69
- package/dist/marks/LineY.svelte +2 -1
- package/dist/marks/LineY.svelte.d.ts +142 -69
- package/dist/marks/Link.svelte +70 -46
- package/dist/marks/Link.svelte.d.ts +126 -41
- package/dist/marks/Pointer.svelte +46 -35
- package/dist/marks/Pointer.svelte.d.ts +7 -0
- package/dist/marks/Rect.svelte +13 -5
- package/dist/marks/Rect.svelte.d.ts +116 -35
- package/dist/marks/RectX.svelte +6 -3
- package/dist/marks/RectX.svelte.d.ts +158 -12
- package/dist/marks/RectY.svelte +6 -3
- package/dist/marks/RectY.svelte.d.ts +158 -12
- package/dist/marks/RegressionX.svelte +13 -6
- package/dist/marks/RegressionX.svelte.d.ts +8 -3
- package/dist/marks/RegressionY.svelte +13 -6
- package/dist/marks/RegressionY.svelte.d.ts +8 -3
- package/dist/marks/RuleX.svelte +18 -11
- package/dist/marks/RuleX.svelte.d.ts +112 -32
- package/dist/marks/RuleY.svelte +19 -12
- package/dist/marks/RuleY.svelte.d.ts +114 -34
- package/dist/marks/Spike.svelte +11 -5
- package/dist/marks/Spike.svelte.d.ts +146 -68
- package/dist/marks/Text.svelte +24 -7
- package/dist/marks/Text.svelte.d.ts +253 -75
- package/dist/marks/TickX.svelte +56 -48
- package/dist/marks/TickX.svelte.d.ts +114 -40
- package/dist/marks/TickY.svelte +59 -51
- package/dist/marks/TickY.svelte.d.ts +117 -43
- package/dist/marks/Trail.svelte +25 -13
- package/dist/marks/Trail.svelte.d.ts +116 -33
- package/dist/marks/Vector.svelte +20 -11
- package/dist/marks/Vector.svelte.d.ts +116 -35
- package/dist/marks/WaffleX.svelte +18 -16
- package/dist/marks/WaffleX.svelte.d.ts +131 -57
- package/dist/marks/WaffleY.svelte +16 -15
- package/dist/marks/WaffleY.svelte.d.ts +129 -56
- package/dist/marks/helpers/Anchor.svelte +17 -2
- package/dist/marks/helpers/Anchor.svelte.d.ts +16 -1
- package/dist/marks/helpers/AreaCanvas.svelte +8 -8
- package/dist/marks/helpers/BaseAxisX.svelte +38 -41
- package/dist/marks/helpers/BaseAxisX.svelte.d.ts +11 -17
- package/dist/marks/helpers/BaseAxisY.svelte +35 -35
- package/dist/marks/helpers/BaseAxisY.svelte.d.ts +12 -15
- package/dist/marks/helpers/Box.svelte +35 -28
- package/dist/marks/helpers/Box.svelte.d.ts +122 -50
- package/dist/marks/helpers/DotCanvas.svelte +11 -9
- package/dist/marks/helpers/GeoCanvas.svelte +7 -6
- package/dist/marks/helpers/LineCanvas.svelte +7 -7
- package/dist/marks/helpers/LinearGradientX.svelte +2 -2
- package/dist/marks/helpers/LinearGradientX.svelte.d.ts +1 -1
- package/dist/marks/helpers/LinearGradientY.svelte +2 -2
- package/dist/marks/helpers/LinearGradientY.svelte.d.ts +1 -1
- package/dist/marks/helpers/Marker.svelte +2 -2
- package/dist/marks/helpers/MarkerPath.svelte +15 -12
- package/dist/marks/helpers/MarkerPath.svelte.d.ts +105 -32
- package/dist/marks/helpers/MultilineText.svelte +24 -17
- package/dist/marks/helpers/MultilineText.svelte.d.ts +1 -1
- package/dist/marks/helpers/RectCanvas.svelte +31 -26
- package/dist/marks/helpers/RectPath.svelte +2 -2
- package/dist/marks/helpers/Regression.svelte +176 -86
- package/dist/marks/helpers/Regression.svelte.d.ts +20 -8
- package/dist/marks/helpers/RuleCanvas.svelte +9 -6
- package/dist/marks/helpers/TextCanvas.svelte +13 -9
- package/dist/marks/helpers/TextCanvas.svelte.d.ts +6 -6
- package/dist/marks/helpers/TickCanvas.svelte +6 -5
- package/dist/marks/helpers/TrailCanvas.svelte +16 -18
- package/dist/marks/helpers/TrailCanvas.svelte.d.ts +3 -5
- package/dist/marks/helpers/canvas.js +16 -9
- package/dist/marks/helpers/events.d.ts +2 -2
- package/dist/marks/helpers/events.js +14 -7
- package/dist/marks/helpers/trail.js +1 -1
- package/dist/marks/helpers/waffle.d.ts +3 -3
- package/dist/marks/helpers/waffle.js +7 -5
- package/dist/regression/polynomial.d.ts +1 -1
- package/dist/regression/polynomial.js +7 -7
- package/dist/regression/utils/determination.d.ts +1 -1
- package/dist/regression/utils/determination.js +1 -1
- package/dist/regression/utils/geometry.d.ts +1 -1
- package/dist/regression/utils/interpose.d.ts +1 -1
- package/dist/regression/utils/interpose.js +1 -1
- package/dist/regression/utils/points.d.ts +1 -1
- package/dist/transforms/bin.d.ts +3 -3
- package/dist/transforms/bin.js +29 -20
- package/dist/transforms/bollinger.d.ts +8 -0
- package/dist/transforms/bollinger.js +15 -4
- package/dist/transforms/centroid.d.ts +4 -0
- package/dist/transforms/centroid.js +4 -0
- package/dist/transforms/density.d.ts +4 -4
- package/dist/transforms/density.js +23 -16
- package/dist/transforms/dodge.d.ts +12 -1
- package/dist/transforms/dodge.js +15 -6
- package/dist/transforms/group.d.ts +141 -4
- package/dist/transforms/group.js +4 -1
- package/dist/transforms/interval.d.ts +204 -60
- package/dist/transforms/jitter.d.ts +421 -4
- package/dist/transforms/jitter.js +10 -1
- package/dist/transforms/map.d.ts +412 -4
- package/dist/transforms/map.js +5 -5
- package/dist/transforms/normalize.d.ts +276 -5
- package/dist/transforms/normalize.js +6 -4
- package/dist/transforms/recordize.d.ts +17 -5
- package/dist/transforms/recordize.js +13 -9
- package/dist/transforms/rename.d.ts +11 -4
- package/dist/transforms/rename.js +7 -2
- package/dist/transforms/select.d.ts +722 -210
- package/dist/transforms/select.js +13 -1
- package/dist/transforms/shift.d.ts +8 -0
- package/dist/transforms/shift.js +20 -6
- package/dist/transforms/sort.d.ts +13 -258
- package/dist/transforms/sort.js +13 -10
- package/dist/transforms/stack.d.ts +58 -9
- package/dist/transforms/stack.js +27 -11
- package/dist/transforms/window.d.ts +221 -66
- package/dist/transforms/window.js +8 -2
- package/dist/types/axes.d.ts +43 -0
- package/dist/types/axes.js +1 -0
- package/dist/types/channel.d.ts +30 -2
- package/dist/types/data.d.ts +14 -1
- package/dist/types/facet.d.ts +5 -0
- package/dist/types/index.d.ts +33 -8
- package/dist/types/index.js +11 -7
- package/dist/types/mark.d.ts +125 -36
- package/dist/types/plot.d.ts +118 -16
- package/dist/types/scale.d.ts +125 -8
- package/package.json +37 -32
- package/dist/helpers/autoTicks.d.ts +0 -12
package/dist/core/Plot.svelte
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
import { setContext } from 'svelte';
|
|
12
12
|
import { SvelteMap } from 'svelte/reactivity';
|
|
13
13
|
import { writable } from 'svelte/store';
|
|
14
|
+
import { scaleBand } from 'd3-scale';
|
|
14
15
|
|
|
15
16
|
import type {
|
|
16
17
|
PlotOptions,
|
|
18
|
+
ResolvedPlotOptions,
|
|
17
19
|
GenericMarkOptions,
|
|
18
20
|
Mark,
|
|
19
21
|
PlotScales,
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
import FacetGrid from './FacetGrid.svelte';
|
|
28
30
|
|
|
29
31
|
import mergeDeep from '../helpers/mergeDeep.js';
|
|
30
|
-
import { computeScales, projectXY } from '../helpers/scales.js';
|
|
32
|
+
import { computeScales, normalizeScaleFn, projectXY } from '../helpers/scales.js';
|
|
31
33
|
import { CHANNEL_SCALE, SCALES } from '../constants.js';
|
|
32
34
|
import { getPlotDefaults, setPlotDefaults } from '../hooks/plotDefaults.js';
|
|
33
35
|
import { maybeNumber } from '../helpers/index.js';
|
|
@@ -59,6 +61,11 @@
|
|
|
59
61
|
|
|
60
62
|
// default settings in the plot and marks can be overwritten by
|
|
61
63
|
// defining the svelteplot/defaults context outside of Plot
|
|
64
|
+
const asGridDefaults = (opts: PlotDefaults['grid'] | undefined) =>
|
|
65
|
+
opts === true ? { implicit: true } : opts == null ? {} : opts;
|
|
66
|
+
const isImplicit = (opts: { implicit?: boolean } | true | undefined) =>
|
|
67
|
+
opts === true ? true : (opts?.implicit ?? false);
|
|
68
|
+
|
|
62
69
|
const DEFAULTS: PlotDefaults = {
|
|
63
70
|
height: 350,
|
|
64
71
|
initialWidth: 500,
|
|
@@ -88,20 +95,20 @@
|
|
|
88
95
|
axisY: {
|
|
89
96
|
anchor: 'left',
|
|
90
97
|
implicit: true,
|
|
91
|
-
...USER_DEFAULTS.axis,
|
|
92
|
-
...USER_DEFAULTS.axisY
|
|
98
|
+
...(USER_DEFAULTS.axis as any),
|
|
99
|
+
...(USER_DEFAULTS.axisY as any)
|
|
93
100
|
},
|
|
94
101
|
gridX: {
|
|
95
102
|
implicit: false,
|
|
96
|
-
...USER_DEFAULTS.grid,
|
|
97
|
-
...USER_DEFAULTS.gridX
|
|
103
|
+
...asGridDefaults(USER_DEFAULTS.grid),
|
|
104
|
+
...asGridDefaults(USER_DEFAULTS.gridX)
|
|
98
105
|
},
|
|
99
106
|
gridY: {
|
|
100
107
|
implicit: false,
|
|
101
|
-
...USER_DEFAULTS.grid,
|
|
102
|
-
...USER_DEFAULTS.gridY
|
|
108
|
+
...asGridDefaults(USER_DEFAULTS.grid),
|
|
109
|
+
...asGridDefaults(USER_DEFAULTS.gridY)
|
|
103
110
|
}
|
|
104
|
-
};
|
|
111
|
+
} as PlotDefaults;
|
|
105
112
|
|
|
106
113
|
let {
|
|
107
114
|
header,
|
|
@@ -165,7 +172,7 @@
|
|
|
165
172
|
);
|
|
166
173
|
|
|
167
174
|
const explicitDomains = $derived(
|
|
168
|
-
new Set(SCALES.filter((scale) => !!initialOptions[scale]?.domain))
|
|
175
|
+
new Set(SCALES.filter((scale) => !!(initialOptions as any)[scale]?.domain))
|
|
169
176
|
);
|
|
170
177
|
|
|
171
178
|
// one-dimensional plots have different automatic margins and heights
|
|
@@ -178,7 +185,7 @@
|
|
|
178
185
|
explicitScales,
|
|
179
186
|
explicitDomains,
|
|
180
187
|
hasProjection: !!initialOptions.projection,
|
|
181
|
-
margin: initialOptions.margin,
|
|
188
|
+
margin: initialOptions.margin as number | 'auto' | undefined,
|
|
182
189
|
inset: initialOptions.inset
|
|
183
190
|
})
|
|
184
191
|
);
|
|
@@ -211,7 +218,7 @@
|
|
|
211
218
|
|
|
212
219
|
const defaultPointScaleHeight = $derived(
|
|
213
220
|
explicitScales.has('r') && plotOptions.r.range
|
|
214
|
-
? plotOptions.r.range[1] * 2
|
|
221
|
+
? (plotOptions.r.range[1] as number) * 2
|
|
215
222
|
: DEFAULTS.pointScaleHeight
|
|
216
223
|
);
|
|
217
224
|
|
|
@@ -227,8 +234,8 @@
|
|
|
227
234
|
? plotOptions.height(plotWidth)
|
|
228
235
|
: maybeNumber(plotOptions.height) === null || plotOptions.height === 'auto'
|
|
229
236
|
? Math.round(
|
|
230
|
-
preScales.projection && preScales.projection.aspectRatio
|
|
231
|
-
? ((plotWidth * preScales.projection.aspectRatio) / xFacetCount) *
|
|
237
|
+
preScales.projection && (preScales.projection as any).aspectRatio
|
|
238
|
+
? ((plotWidth * (preScales.projection as any).aspectRatio) / xFacetCount) *
|
|
232
239
|
yFacetCount +
|
|
233
240
|
plotOptions.marginTop +
|
|
234
241
|
plotOptions.marginBottom
|
|
@@ -254,7 +261,7 @@
|
|
|
254
261
|
: maybeNumber(plotOptions.height)
|
|
255
262
|
);
|
|
256
263
|
|
|
257
|
-
const plotHeight = $derived(height - plotOptions.marginTop - plotOptions.marginBottom);
|
|
264
|
+
const plotHeight = $derived((height ?? 0) - plotOptions.marginTop - plotOptions.marginBottom);
|
|
258
265
|
|
|
259
266
|
// TODO: check if there's still a reason to store and expose the plot body element
|
|
260
267
|
let plotBody: HTMLDivElement | null = $state(null);
|
|
@@ -274,11 +281,38 @@
|
|
|
274
281
|
const scales = computeScales(
|
|
275
282
|
plotOptions,
|
|
276
283
|
facetWidth || width,
|
|
277
|
-
facetHeight
|
|
284
|
+
facetHeight ?? height ?? 0,
|
|
278
285
|
hasFilledDotMarks,
|
|
279
286
|
marks,
|
|
280
287
|
DEFAULTS
|
|
281
288
|
);
|
|
289
|
+
// Fix fx/fy scale ranges: computeScales creates them with empty ranges
|
|
290
|
+
// because getScaleRange has no case for fx/fy. We set the correct range
|
|
291
|
+
// here using overall plotWidth/plotHeight, matching FacetGrid's layout.
|
|
292
|
+
if (scales.fx.domain.length > 0) {
|
|
293
|
+
const fxOpts = plotOptions.fx;
|
|
294
|
+
const fxPaddingInner = fxOpts?.paddingInner ?? fxOpts?.padding ?? 0.1;
|
|
295
|
+
const fxFn = scaleBand()
|
|
296
|
+
.domain(scales.fx.domain as string[])
|
|
297
|
+
.paddingOuter(0)
|
|
298
|
+
.paddingInner(scales.fx.domain.length > 1 ? fxPaddingInner : 0)
|
|
299
|
+
.rangeRound([0, plotWidth]) as any;
|
|
300
|
+
fxFn.ticks = () => scales.fx.domain;
|
|
301
|
+
scales.fx.fn = normalizeScaleFn(fxFn);
|
|
302
|
+
scales.fx.range = fxFn.range();
|
|
303
|
+
}
|
|
304
|
+
if (scales.fy.domain.length > 0) {
|
|
305
|
+
const fyOpts = plotOptions.fy;
|
|
306
|
+
const fyPaddingInner = fyOpts?.paddingInner ?? fyOpts?.padding ?? 0.1;
|
|
307
|
+
const fyFn = scaleBand()
|
|
308
|
+
.domain(scales.fy.domain as string[])
|
|
309
|
+
.paddingOuter(0)
|
|
310
|
+
.paddingInner(scales.fy.domain.length > 1 ? fyPaddingInner : 0)
|
|
311
|
+
.rangeRound([0, plotHeight]) as any;
|
|
312
|
+
fyFn.ticks = () => scales.fy.domain;
|
|
313
|
+
scales.fy.fn = normalizeScaleFn(fyFn);
|
|
314
|
+
scales.fy.range = fyFn.range();
|
|
315
|
+
}
|
|
282
316
|
const colorSymbolRedundant =
|
|
283
317
|
scales.color.uniqueScaleProps?.size === 1 &&
|
|
284
318
|
scales.symbol.uniqueScaleProps?.size === 1 &&
|
|
@@ -287,9 +321,9 @@
|
|
|
287
321
|
return {
|
|
288
322
|
options: plotOptions,
|
|
289
323
|
width,
|
|
290
|
-
height,
|
|
291
|
-
facetWidth,
|
|
292
|
-
facetHeight,
|
|
324
|
+
height: height ?? 0,
|
|
325
|
+
facetWidth: facetWidth ?? undefined,
|
|
326
|
+
facetHeight: facetHeight ?? undefined,
|
|
293
327
|
plotHeight,
|
|
294
328
|
plotWidth,
|
|
295
329
|
scales,
|
|
@@ -297,7 +331,7 @@
|
|
|
297
331
|
hasFilledDotMarks,
|
|
298
332
|
body: plotBody,
|
|
299
333
|
css
|
|
300
|
-
};
|
|
334
|
+
} as any;
|
|
301
335
|
}
|
|
302
336
|
|
|
303
337
|
setContext('svelteplot', {
|
|
@@ -357,11 +391,11 @@
|
|
|
357
391
|
const xDomainExtent =
|
|
358
392
|
x.type === 'band' || x.type === 'point'
|
|
359
393
|
? x.domain.length
|
|
360
|
-
: Math.abs(x.domain[1] - x.domain[0]);
|
|
394
|
+
: Math.abs((x.domain[1] as number) - (x.domain[0] as number));
|
|
361
395
|
const yDomainExtent =
|
|
362
396
|
y.type === 'band' || y.type === 'point'
|
|
363
397
|
? y.domain.length
|
|
364
|
-
: Math.abs(y.domain[1] - y.domain[0]);
|
|
398
|
+
: Math.abs((y.domain[1] as number) - (y.domain[0] as number));
|
|
365
399
|
return (
|
|
366
400
|
((plotWidth / xDomainExtent) * yDomainExtent) / aspectRatio + marginTop + marginBottom
|
|
367
401
|
);
|
|
@@ -370,13 +404,13 @@
|
|
|
370
404
|
function extendPlotOptions(
|
|
371
405
|
initialOpts: Partial<PlotOptions>,
|
|
372
406
|
opts: PlotOptionsParameters
|
|
373
|
-
):
|
|
407
|
+
): ResolvedPlotOptions {
|
|
374
408
|
return mergeDeep<PlotOptions>(
|
|
375
|
-
{}
|
|
376
|
-
{ sortOrdinalDomains: DEFAULTS.sortOrdinalDomains }
|
|
377
|
-
smartDefaultPlotOptions(opts),
|
|
378
|
-
initialOptions
|
|
379
|
-
);
|
|
409
|
+
{} as Partial<PlotOptions>,
|
|
410
|
+
{ sortOrdinalDomains: DEFAULTS.sortOrdinalDomains } as Partial<PlotOptions>,
|
|
411
|
+
smartDefaultPlotOptions(opts) as any,
|
|
412
|
+
initialOptions as any
|
|
413
|
+
) as ResolvedPlotOptions;
|
|
380
414
|
}
|
|
381
415
|
|
|
382
416
|
function maybeMargin(
|
|
@@ -419,7 +453,7 @@
|
|
|
419
453
|
explicitDomains,
|
|
420
454
|
hasProjection,
|
|
421
455
|
margin
|
|
422
|
-
}: PlotOptionsParameters):
|
|
456
|
+
}: PlotOptionsParameters): ResolvedPlotOptions {
|
|
423
457
|
const autoXAxis = explicitScales.has('x') || explicitDomains.has('x');
|
|
424
458
|
const autoYAxis = explicitScales.has('y') || explicitDomains.has('y');
|
|
425
459
|
const isOneDimensional = autoXAxis !== autoYAxis;
|
|
@@ -444,9 +478,9 @@
|
|
|
444
478
|
marginTop: maybeMargin(margin, 'top', DEFAULTS.margin, autoMargins),
|
|
445
479
|
marginBottom: maybeMargin(margin, 'bottom', DEFAULTS.margin, autoMargins),
|
|
446
480
|
inset: isOneDimensional ? 10 : DEFAULTS.inset,
|
|
447
|
-
grid: (DEFAULTS.gridX
|
|
481
|
+
grid: isImplicit(DEFAULTS.gridX) && isImplicit(DEFAULTS.gridY),
|
|
448
482
|
axes: (DEFAULTS.axisX?.implicit ?? false) && (DEFAULTS.axisY?.implicit ?? false),
|
|
449
|
-
frame: DEFAULTS.frame
|
|
483
|
+
frame: isImplicit(DEFAULTS.frame),
|
|
450
484
|
projection: null,
|
|
451
485
|
aspectRatio: null,
|
|
452
486
|
facet: {},
|
|
@@ -464,7 +498,7 @@
|
|
|
464
498
|
align: 0.5,
|
|
465
499
|
tickSpacing: DEFAULTS.axisX.tickSpacing ?? 80,
|
|
466
500
|
tickFormat: 'auto',
|
|
467
|
-
grid: DEFAULTS.gridX
|
|
501
|
+
grid: isImplicit(DEFAULTS.gridX)
|
|
468
502
|
},
|
|
469
503
|
y: {
|
|
470
504
|
type: 'auto',
|
|
@@ -479,7 +513,7 @@
|
|
|
479
513
|
align: 0.5,
|
|
480
514
|
tickSpacing: DEFAULTS.axisY.tickSpacing ?? 50,
|
|
481
515
|
tickFormat: 'auto',
|
|
482
|
-
grid: DEFAULTS.gridY
|
|
516
|
+
grid: isImplicit(DEFAULTS.gridY)
|
|
483
517
|
},
|
|
484
518
|
opacity: {
|
|
485
519
|
type: 'linear',
|
|
@@ -504,14 +538,14 @@
|
|
|
504
538
|
padding: 0,
|
|
505
539
|
align: 0
|
|
506
540
|
},
|
|
507
|
-
color: { type: 'auto', unknown: DEFAULTS.unknown },
|
|
541
|
+
color: { type: 'auto' as any, unknown: DEFAULTS.unknown },
|
|
508
542
|
length: { type: 'linear' },
|
|
509
543
|
symbol: { type: 'ordinal' },
|
|
510
544
|
fx: { type: 'band', axis: 'top' },
|
|
511
545
|
fy: { type: 'band', axis: 'right' },
|
|
512
546
|
locale: DEFAULTS.locale,
|
|
513
547
|
css: DEFAULTS.css
|
|
514
|
-
};
|
|
548
|
+
} as ResolvedPlotOptions;
|
|
515
549
|
}
|
|
516
550
|
|
|
517
551
|
const mapXY = $derived((x: RawValue, y: RawValue) => {
|
|
@@ -542,7 +576,7 @@
|
|
|
542
576
|
{#if children}
|
|
543
577
|
{@render children({
|
|
544
578
|
width,
|
|
545
|
-
height,
|
|
579
|
+
height: height ?? 0,
|
|
546
580
|
options: plotOptions,
|
|
547
581
|
scales: plotState.scales,
|
|
548
582
|
mapXY,
|
|
@@ -558,7 +592,7 @@
|
|
|
558
592
|
{#if overlay}<div class="plot-overlay">
|
|
559
593
|
{@render overlay?.({
|
|
560
594
|
width,
|
|
561
|
-
height,
|
|
595
|
+
height: height ?? 0,
|
|
562
596
|
options: plotOptions,
|
|
563
597
|
scales: plotState.scales,
|
|
564
598
|
mapXY,
|
|
@@ -53,16 +53,21 @@ export function arrowPath(x1, y1, x2, y2, insetStart, insetEnd, headAngle, headL
|
|
|
53
53
|
if (insetEnd) {
|
|
54
54
|
const [x, y] = circleCircleIntersect([cx, cy, r], [x2, y2, insetEnd], sign * Math.sign(insetEnd));
|
|
55
55
|
lineAngle += Math.atan2(y - cy, x - cx) - Math.atan2(y2 - cy, x2 - cx);
|
|
56
|
-
|
|
56
|
+
x2 = x;
|
|
57
|
+
y2 = y;
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
else {
|
|
60
61
|
// For inset straight arrows, offset along the straight line.
|
|
61
62
|
const dx = x2 - x1, dy = y2 - y1, d = Math.hypot(dx, dy);
|
|
62
|
-
if (insetStart)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
if (insetStart) {
|
|
64
|
+
x1 += (dx / d) * insetStart;
|
|
65
|
+
y1 += (dy / d) * insetStart;
|
|
66
|
+
}
|
|
67
|
+
if (insetEnd) {
|
|
68
|
+
x2 -= (dx / d) * insetEnd;
|
|
69
|
+
y2 -= (dy / d) * insetEnd;
|
|
70
|
+
}
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
73
|
// The angle of the arrow as it approaches the endpoint, and the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ColorScaleOptions, PlotDefaults, PlotOptions, RawValue, ScaleName, ScaleOptions, ScaleType } from '../types/index.js';
|
|
2
|
-
export declare function autoScale({ name, type, domain, scaleOptions, plotOptions, plotWidth, plotHeight, plotHasFilledDotMarks, plotDefaults }: {
|
|
2
|
+
export declare function autoScale({ name, type, domain, scaleOptions, plotOptions, plotWidth, plotHeight, plotHasFilledDotMarks, plotDefaults: _plotDefaults }: {
|
|
3
3
|
name: ScaleName;
|
|
4
4
|
type: ScaleType;
|
|
5
5
|
domain: RawValue[];
|
|
@@ -9,8 +9,8 @@ export declare function autoScale({ name, type, domain, scaleOptions, plotOption
|
|
|
9
9
|
plotHeight: number;
|
|
10
10
|
plotHasFilledDotMarks: boolean;
|
|
11
11
|
plotDefaults: PlotDefaults;
|
|
12
|
-
}):
|
|
13
|
-
export declare function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWidth, plotHeight, plotHasFilledDotMarks, plotDefaults }: {
|
|
12
|
+
}): any;
|
|
13
|
+
export declare function autoScaleColor({ type, domain, scaleOptions, plotOptions: _plotOptions, plotWidth: _plotWidth, plotHeight: _plotHeight, plotHasFilledDotMarks: _plotHasFilledDotMarks, plotDefaults }: {
|
|
14
14
|
name: ScaleName;
|
|
15
15
|
type: ScaleType;
|
|
16
16
|
domain: RawValue[];
|
|
@@ -41,7 +41,7 @@ const ThresholdScales = {
|
|
|
41
41
|
quantize: scaleQuantize,
|
|
42
42
|
quantile: scaleQuantile
|
|
43
43
|
};
|
|
44
|
-
export function autoScale({ name, type, domain, scaleOptions, plotOptions, plotWidth, plotHeight, plotHasFilledDotMarks, plotDefaults }) {
|
|
44
|
+
export function autoScale({ name, type, domain, scaleOptions, plotOptions, plotWidth, plotHeight, plotHasFilledDotMarks, plotDefaults: _plotDefaults }) {
|
|
45
45
|
let fn;
|
|
46
46
|
let range;
|
|
47
47
|
range =
|
|
@@ -55,7 +55,7 @@ export function autoScale({ name, type, domain, scaleOptions, plotOptions, plotW
|
|
|
55
55
|
const scaleProps = {
|
|
56
56
|
domain,
|
|
57
57
|
range,
|
|
58
|
-
...((type === 'linear' || type === 'log') && scaleOptions.nice
|
|
58
|
+
...((type === 'linear' || type === 'log' || type === 'time') && scaleOptions.nice
|
|
59
59
|
? {
|
|
60
60
|
nice: scaleOptions.nice ? niceTickCount : true
|
|
61
61
|
}
|
|
@@ -92,6 +92,8 @@ export function autoScale({ name, type, domain, scaleOptions, plotOptions, plotW
|
|
|
92
92
|
}
|
|
93
93
|
: {})
|
|
94
94
|
};
|
|
95
|
+
// The scale function is augmented with custom ticks() methods below,
|
|
96
|
+
// so we type it broadly to allow property assignments
|
|
95
97
|
fn = callWithProps(Scales[type], [], scaleProps);
|
|
96
98
|
if (type === 'band' || type === 'point') {
|
|
97
99
|
fn.ticks = () => domain;
|
|
@@ -102,13 +104,13 @@ export function autoScale({ name, type, domain, scaleOptions, plotOptions, plotW
|
|
|
102
104
|
else if (type === 'symlog') {
|
|
103
105
|
const maxabs = Math.max(Math.abs(domain[0]), Math.abs(domain[1]));
|
|
104
106
|
fn.ticks = (count) => {
|
|
105
|
-
const ticks = getLogTicks([scaleProps.constant + 1, maxabs], count / 2);
|
|
107
|
+
const ticks = getLogTicks([(scaleProps.constant ?? 1) + 1, maxabs], count / 2);
|
|
106
108
|
return [...ticks.map((t) => -t).reverse(), 0, ...ticks];
|
|
107
109
|
};
|
|
108
110
|
}
|
|
109
111
|
return fn;
|
|
110
112
|
}
|
|
111
|
-
export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWidth, plotHeight, plotHasFilledDotMarks, plotDefaults }) {
|
|
113
|
+
export function autoScaleColor({ type, domain, scaleOptions, plotOptions: _plotOptions, plotWidth: _plotWidth, plotHeight: _plotHeight, plotHasFilledDotMarks: _plotHasFilledDotMarks, plotDefaults }) {
|
|
112
114
|
let fn;
|
|
113
115
|
let range;
|
|
114
116
|
// special treatment for color scales
|
|
@@ -117,12 +119,14 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWi
|
|
|
117
119
|
// categorical
|
|
118
120
|
let scheme_ = scheme || plotDefaults.categoricalColorScheme;
|
|
119
121
|
if (isPlainObject(scheme_)) {
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
+
const schemeObj = scheme_;
|
|
123
|
+
const newScheme = Object.values(schemeObj);
|
|
124
|
+
const newDomain = Object.keys(schemeObj);
|
|
122
125
|
// for every value in domain that's not part of the scheme, map to unknown
|
|
123
126
|
for (const v of domain) {
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
const key = String(v);
|
|
128
|
+
if (schemeObj[key] == null) {
|
|
129
|
+
newDomain.push(key);
|
|
126
130
|
newScheme.push(unknown);
|
|
127
131
|
}
|
|
128
132
|
}
|
|
@@ -133,11 +137,13 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWi
|
|
|
133
137
|
range = Array.isArray(scheme_)
|
|
134
138
|
? scheme_
|
|
135
139
|
: isCategoricalScheme(scheme_)
|
|
136
|
-
? categoricalSchemes.get(scheme_)
|
|
140
|
+
? (categoricalSchemes.get(scheme_) ?? [])
|
|
137
141
|
: ordinalScheme(scheme_)(domain.length);
|
|
138
|
-
fn = scaleOrdinal()
|
|
142
|
+
fn = scaleOrdinal()
|
|
143
|
+
.domain(domain)
|
|
144
|
+
.range(range);
|
|
139
145
|
}
|
|
140
|
-
else if (
|
|
146
|
+
else if (ThresholdScales[type]) {
|
|
141
147
|
const scheme_ = scheme || plotDefaults.colorScheme;
|
|
142
148
|
range =
|
|
143
149
|
Array.isArray(scheme_) && (scaleOptions.n == null || scaleOptions.n === scheme_.length)
|
|
@@ -146,7 +152,7 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWi
|
|
|
146
152
|
? // interpolate n colors from custom colors
|
|
147
153
|
d3Range(n)
|
|
148
154
|
.map((i) => i / (n - 1))
|
|
149
|
-
.map(scaleLinear(scheme_.map((
|
|
155
|
+
.map(scaleLinear(scheme_.map((_c, i) => i / (scheme_.length - 1)), scheme_).interpolate(interpolateLab))
|
|
150
156
|
: interpolate
|
|
151
157
|
? d3Range(n).map((i) => interpolate(i / (n - 1)))
|
|
152
158
|
: isOrdinalScheme(scheme_)
|
|
@@ -157,11 +163,15 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWi
|
|
|
157
163
|
}
|
|
158
164
|
if (scaleOptions.reverse)
|
|
159
165
|
range = range.toReversed();
|
|
160
|
-
fn = ThresholdScales[type]()
|
|
166
|
+
fn = ThresholdScales[type]()
|
|
167
|
+
.domain(domain)
|
|
168
|
+
.range(range);
|
|
161
169
|
}
|
|
162
|
-
else if (
|
|
170
|
+
else if (SequentialScales[type] ||
|
|
171
|
+
DivergingScales[type]) {
|
|
163
172
|
// continuous color scale
|
|
164
|
-
const scale = SequentialScales[type] ||
|
|
173
|
+
const scale = (SequentialScales[type] ||
|
|
174
|
+
DivergingScales[type]);
|
|
165
175
|
const scheme_ = scheme || plotDefaults.colorScheme;
|
|
166
176
|
if (interpolate) {
|
|
167
177
|
// user-defined interpolation function [0, 1] -> color
|
|
@@ -172,14 +182,14 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWi
|
|
|
172
182
|
const step = 1 / (scheme_.length - 1);
|
|
173
183
|
fn = scale(domain, (type === 'linear' ? scaleLinear : scaleLog)(d3Range(0, 1 + step / 2, step), scheme_).interpolate(interpolateLab));
|
|
174
184
|
}
|
|
175
|
-
else if (
|
|
185
|
+
else if (DivergingScales[type] ||
|
|
176
186
|
(scaleOptions.type === 'auto' && isDivergingScheme(scheme_))) {
|
|
177
187
|
// diverging color scheme, explicit or auto-detected
|
|
178
188
|
const maxabs = Math.max(Math.abs(domain[0]), Math.abs(domain[1]));
|
|
179
189
|
const domain_ = pivot != null ? [domain[0], pivot, domain[1]] : [-maxabs, 0, maxabs];
|
|
180
190
|
fn = scale(domain_, quantitativeScheme(scheme_));
|
|
181
191
|
}
|
|
182
|
-
else if (
|
|
192
|
+
else if (SequentialScales[type] ||
|
|
183
193
|
(scaleOptions.type === 'auto' && isQuantitativeScheme(scheme_))) {
|
|
184
194
|
// sequential
|
|
185
195
|
fn = scale(domain, quantitativeScheme(scheme_));
|
|
@@ -191,7 +201,7 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions, plotWi
|
|
|
191
201
|
if (!fn) {
|
|
192
202
|
console.error('color problem', type);
|
|
193
203
|
// problem
|
|
194
|
-
fn = () => 'red';
|
|
204
|
+
fn = (() => 'red');
|
|
195
205
|
fn.range = () => ['red'];
|
|
196
206
|
}
|
|
197
207
|
return fn;
|
|
@@ -37,6 +37,8 @@ export function autoTicks(type, ticks, interval, domain, scaleFn, count) {
|
|
|
37
37
|
if (lo == null || hi == null)
|
|
38
38
|
return [];
|
|
39
39
|
const I = maybeInterval(interval);
|
|
40
|
+
if (!I)
|
|
41
|
+
return [];
|
|
40
42
|
return I.range(lo, I.offset(hi)).filter((d) => d >= lo && d <= hi);
|
|
41
43
|
}
|
|
42
44
|
return typeof scaleFn.ticks === 'function' ? scaleFn.ticks(count) : [];
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { RawValue } from '../types/index.js';
|
|
2
1
|
/**
|
|
3
2
|
* Helper function to call a D3 "function class" while also calling
|
|
4
3
|
* property setter functions on the result.
|
|
5
4
|
*/
|
|
6
|
-
export default function <T extends object>(d3func: (...args:
|
|
5
|
+
export default function <T extends object>(d3func: (...args: any[]) => T, args?: any[], props?: Record<string, any>): T;
|
package/dist/helpers/colors.d.ts
CHANGED
|
@@ -4,10 +4,10 @@ export declare const categoricalSchemes: Map<string, readonly string[]>;
|
|
|
4
4
|
export declare function isCategoricalScheme(scheme: string): boolean;
|
|
5
5
|
type SchemeGetter = (n: number) => readonly string[];
|
|
6
6
|
export declare function isOrdinalScheme(scheme: ColorScheme): boolean;
|
|
7
|
-
export declare function ordinalScheme(scheme: ColorScheme | string): SchemeGetter;
|
|
8
|
-
export declare function ordinalRange(scheme: ColorScheme | string, length: number): readonly string[];
|
|
9
|
-
export declare function maybeBooleanRange(domain: boolean[], scheme?: ColorScheme | string): unknown[] | undefined;
|
|
7
|
+
export declare function ordinalScheme(scheme: ColorScheme | (string & {})): SchemeGetter;
|
|
8
|
+
export declare function ordinalRange(scheme: ColorScheme | (string & {}), length: number): readonly string[];
|
|
9
|
+
export declare function maybeBooleanRange(domain: boolean[], scheme?: ColorScheme | (string & {})): unknown[] | undefined;
|
|
10
10
|
export declare function isQuantitativeScheme(scheme: string): boolean;
|
|
11
|
-
export declare function quantitativeScheme(scheme: ColorScheme | string): typeof interpolateBrBG | undefined;
|
|
11
|
+
export declare function quantitativeScheme(scheme: ColorScheme | (string & {})): typeof interpolateBrBG | undefined;
|
|
12
12
|
export declare function isDivergingScheme(scheme: string): boolean;
|
|
13
13
|
export {};
|
package/dist/helpers/facets.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GenericMarkOptions, Mark, RawValue } from '../types/index.js';
|
|
1
|
+
import type { GenericMarkOptions, Mark, PlotState, RawValue } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* This function tracks which facets are "empty", meaning that they don't contain
|
|
4
4
|
* any "facetted" data points. This can happen when fx and fy are combined and
|
|
@@ -10,3 +10,44 @@ import type { GenericMarkOptions, Mark, RawValue } from '../types/index.js';
|
|
|
10
10
|
* @returns
|
|
11
11
|
*/
|
|
12
12
|
export declare function getEmptyFacets(marks: Mark<GenericMarkOptions>[], fxValues: RawValue[], fyValues: RawValue[]): Map<RawValue, Map<RawValue, boolean>>;
|
|
13
|
+
/**
|
|
14
|
+
* Stable string key for a (fxValue, fyValue) pair, used as Map keys
|
|
15
|
+
* for the keyed tree map in Pointer/HTMLTooltip.
|
|
16
|
+
*/
|
|
17
|
+
export declare function facetKey(fxValue: RawValue | boolean, fyValue: RawValue | boolean): string;
|
|
18
|
+
/**
|
|
19
|
+
* Inverts a d3 band scale: given a pixel position, returns the domain value
|
|
20
|
+
* whose band contains that position, or undefined if outside all bands.
|
|
21
|
+
*
|
|
22
|
+
* d3.scaleBand has no .invert(), so we iterate the domain (O(n), n = facet count,
|
|
23
|
+
* typically <20).
|
|
24
|
+
*/
|
|
25
|
+
export declare function invertBand(scale: {
|
|
26
|
+
(value: string): number | undefined;
|
|
27
|
+
bandwidth(): number;
|
|
28
|
+
}, domain: readonly (string | RawValue)[], pixelPos: number): RawValue | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Walk up the DOM from `target` to find the nearest `g.facet` element.
|
|
31
|
+
* Returns the facet x/y indices from `data-facet-x` and `data-facet-y`
|
|
32
|
+
* attributes, or null if no facet element is found.
|
|
33
|
+
*/
|
|
34
|
+
export declare function findFacetFromDOM(target: Element | null): {
|
|
35
|
+
fxIndex: number;
|
|
36
|
+
fyIndex: number;
|
|
37
|
+
} | null;
|
|
38
|
+
/**
|
|
39
|
+
* Detect which facet the mouse event is in and compute the pixel offset.
|
|
40
|
+
*
|
|
41
|
+
* Strategy: try DOM walk first (fast, reliable when the event target is inside
|
|
42
|
+
* a facet `<g>`). Fall back to inverting the fx/fy band scales from the mouse
|
|
43
|
+
* position (works in jsdom where getBoundingClientRect returns zeros).
|
|
44
|
+
*
|
|
45
|
+
* Returns { fxValue, fyValue, offsetX, offsetY } where offset is the pixel
|
|
46
|
+
* translation of the facet from the plot body origin.
|
|
47
|
+
*/
|
|
48
|
+
export declare function detectFacet(evt: MouseEvent, plot: PlotState): {
|
|
49
|
+
fxValue: RawValue | boolean;
|
|
50
|
+
fyValue: RawValue | boolean;
|
|
51
|
+
offsetX: number;
|
|
52
|
+
offsetY: number;
|
|
53
|
+
};
|
package/dist/helpers/facets.js
CHANGED
|
@@ -46,4 +46,86 @@ export function getEmptyFacets(marks, fxValues, fyValues) {
|
|
|
46
46
|
}
|
|
47
47
|
return out;
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Stable string key for a (fxValue, fyValue) pair, used as Map keys
|
|
51
|
+
* for the keyed tree map in Pointer/HTMLTooltip.
|
|
52
|
+
*/
|
|
53
|
+
export function facetKey(fxValue, fyValue) {
|
|
54
|
+
return JSON.stringify([fxValue, fyValue]);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Inverts a d3 band scale: given a pixel position, returns the domain value
|
|
58
|
+
* whose band contains that position, or undefined if outside all bands.
|
|
59
|
+
*
|
|
60
|
+
* d3.scaleBand has no .invert(), so we iterate the domain (O(n), n = facet count,
|
|
61
|
+
* typically <20).
|
|
62
|
+
*/
|
|
63
|
+
export function invertBand(scale, domain, pixelPos) {
|
|
64
|
+
const bw = scale.bandwidth();
|
|
65
|
+
for (const value of domain) {
|
|
66
|
+
const start = scale(value);
|
|
67
|
+
if (start != null && pixelPos >= start && pixelPos < start + bw) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Walk up the DOM from `target` to find the nearest `g.facet` element.
|
|
75
|
+
* Returns the facet x/y indices from `data-facet-x` and `data-facet-y`
|
|
76
|
+
* attributes, or null if no facet element is found.
|
|
77
|
+
*/
|
|
78
|
+
export function findFacetFromDOM(target) {
|
|
79
|
+
let el = target;
|
|
80
|
+
while (el) {
|
|
81
|
+
if (el.classList?.contains('facet')) {
|
|
82
|
+
const fxIndex = parseInt(el.dataset?.facetX ?? '0', 10);
|
|
83
|
+
const fyIndex = parseInt(el.dataset?.facetY ?? '0', 10);
|
|
84
|
+
return { fxIndex, fyIndex };
|
|
85
|
+
}
|
|
86
|
+
el = el.parentElement;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Detect which facet the mouse event is in and compute the pixel offset.
|
|
92
|
+
*
|
|
93
|
+
* Strategy: try DOM walk first (fast, reliable when the event target is inside
|
|
94
|
+
* a facet `<g>`). Fall back to inverting the fx/fy band scales from the mouse
|
|
95
|
+
* position (works in jsdom where getBoundingClientRect returns zeros).
|
|
96
|
+
*
|
|
97
|
+
* Returns { fxValue, fyValue, offsetX, offsetY } where offset is the pixel
|
|
98
|
+
* translation of the facet from the plot body origin.
|
|
99
|
+
*/
|
|
100
|
+
export function detectFacet(evt, plot) {
|
|
101
|
+
const fxScale = plot.scales.fx;
|
|
102
|
+
const fyScale = plot.scales.fy;
|
|
103
|
+
const fxDomain = fxScale.domain;
|
|
104
|
+
const fyDomain = fyScale.domain;
|
|
105
|
+
const hasFx = fxDomain.length > 0;
|
|
106
|
+
const hasFy = fyDomain.length > 0;
|
|
107
|
+
// Try DOM walk
|
|
108
|
+
const facetInfo = findFacetFromDOM(evt.target);
|
|
109
|
+
if (facetInfo) {
|
|
110
|
+
const fxValue = hasFx ? fxDomain[facetInfo.fxIndex] : true;
|
|
111
|
+
const fyValue = hasFy ? fyDomain[facetInfo.fyIndex] : true;
|
|
112
|
+
return {
|
|
113
|
+
fxValue,
|
|
114
|
+
fyValue,
|
|
115
|
+
offsetX: hasFx ? (fxScale.fn(fxValue) ?? 0) : 0,
|
|
116
|
+
offsetY: hasFy ? (fyScale.fn(fyValue) ?? 0) : 0
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Fallback: invert mouse position against band scales
|
|
120
|
+
const bodyRect = plot.body.getBoundingClientRect();
|
|
121
|
+
const svgX = evt.clientX - bodyRect.left;
|
|
122
|
+
const svgY = evt.clientY - bodyRect.top;
|
|
123
|
+
const fxValue = hasFx ? (invertBand(fxScale.fn, fxDomain, svgX) ?? fxDomain[0]) : true;
|
|
124
|
+
const fyValue = hasFy ? (invertBand(fyScale.fn, fyDomain, svgY) ?? fyDomain[0]) : true;
|
|
125
|
+
return {
|
|
126
|
+
fxValue,
|
|
127
|
+
fyValue,
|
|
128
|
+
offsetX: hasFx ? (fxScale.fn(fxValue) ?? 0) : 0,
|
|
129
|
+
offsetY: hasFy ? (fyScale.fn(fyValue) ?? 0) : 0
|
|
130
|
+
};
|
|
131
|
+
}
|
package/dist/helpers/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export function coalesce(...args) {
|
|
|
12
12
|
return null; // Return null if all arguments are null or undefined
|
|
13
13
|
}
|
|
14
14
|
export function testFilter(datum, options) {
|
|
15
|
-
return options.filter == null || resolveProp(options.filter, datum);
|
|
15
|
+
return (options.filter == null || resolveProp(options.filter, datum));
|
|
16
16
|
}
|
|
17
17
|
export function randomId() {
|
|
18
18
|
return Math.ceil(1e9 + Math.random() * 1e9).toString(36);
|
package/dist/helpers/math.js
CHANGED
|
@@ -16,7 +16,7 @@ export function normdev(p) {
|
|
|
16
16
|
return -Infinity;
|
|
17
17
|
if (p == 1)
|
|
18
18
|
return Infinity;
|
|
19
|
-
const a0 = 3.
|
|
19
|
+
const a0 = 3.3871328727963665, a1 = 133.14166789178438, a2 = 1971.5909503065513, a3 = 13731.69376550946, a4 = 45921.95393154987, a5 = 67265.7709270087, a6 = 33430.57558358813, a7 = 2509.0809287301227, b1 = 42.31333070160091, b2 = 687.1870074920579, b3 = 5394.196021424751, b4 = 21213.794301586597, b5 = 39307.89580009271, b6 = 28729.085735721943, b7 = 5226.495278852854, c0 = 1.4234371107496835, c1 = 4.630337846156546, c2 = 5.769497221460691, c3 = 3.6478483247632045, c4 = 1.2704582524523684, c5 = 0.2417807251774506, c6 = 0.022723844989269184, c7 = 0.0007745450142783414, d1 = 2.053191626637759, d2 = 1.6763848301838038, d3 = 0.6897673349851, d4 = 0.14810397642748008, d5 = 0.015198666563616457, d6 = 0.0005475938084995345, d7 = 1.0507500716444169e-9, e0 = 6.657904643501103, e1 = 5.463784911164114, e2 = 1.7848265399172913, e3 = 0.29656057182850487, e4 = 0.026532189526576124, e5 = 0.0012426609473880784, e6 = 0.000027115555687434876, e7 = 2.0103343992922881e-7, f1 = 0.599832206555888, f2 = 0.1369298809227358, f3 = 0.014875361290850615, f4 = 0.0007868691311456133, f5 = 0.000018463183175100548, f6 = 1.421511758316446e-7, f7 = 2.0442631033899397e-15;
|
|
20
20
|
const q = p - 0.5;
|
|
21
21
|
let r, z;
|
|
22
22
|
// p close to 0.5
|