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.
- package/dist/Mark.svelte +6 -1
- package/dist/Mark.svelte.d.ts +1 -1
- package/dist/constants.js +2 -0
- package/dist/core/Plot.svelte +32 -3
- package/dist/helpers/arrowPath.js +10 -5
- package/dist/helpers/autoScales.js +7 -3
- package/dist/helpers/autoTicks.js +4 -4
- package/dist/helpers/autoTimeFormat.js +22 -12
- package/dist/helpers/colors.d.ts +4 -4
- package/dist/helpers/facets.d.ts +42 -1
- package/dist/helpers/facets.js +83 -0
- package/dist/helpers/math.js +1 -1
- package/dist/helpers/noise.js +1 -1
- package/dist/helpers/rasterInterpolate.d.ts +26 -0
- package/dist/helpers/rasterInterpolate.js +220 -0
- package/dist/helpers/roundedRect.js +1 -1
- package/dist/helpers/scales.d.ts +1 -0
- package/dist/helpers/scales.js +8 -5
- package/dist/helpers/time.js +1 -1
- package/dist/helpers/typeChecks.d.ts +1 -0
- package/dist/helpers/typeChecks.js +3 -0
- package/dist/marks/Area.svelte.d.ts +1 -1
- package/dist/marks/AreaX.svelte.d.ts +1 -1
- package/dist/marks/AreaY.svelte.d.ts +1 -1
- package/dist/marks/Arrow.svelte.d.ts +1 -1
- package/dist/marks/AxisX.svelte +8 -3
- package/dist/marks/AxisX.svelte.d.ts +1 -1
- package/dist/marks/AxisY.svelte +8 -3
- package/dist/marks/AxisY.svelte.d.ts +1 -1
- package/dist/marks/BarX.svelte.d.ts +1 -1
- package/dist/marks/BarY.svelte.d.ts +1 -1
- package/dist/marks/BollingerX.svelte.d.ts +1 -1
- package/dist/marks/BollingerY.svelte.d.ts +1 -1
- package/dist/marks/BoxY.svelte.d.ts +1 -1
- package/dist/marks/Brush.svelte.d.ts +1 -1
- package/dist/marks/Cell.svelte.d.ts +1 -1
- package/dist/marks/CellX.svelte.d.ts +1 -1
- package/dist/marks/CellY.svelte.d.ts +1 -1
- package/dist/marks/CustomMark.svelte.d.ts +1 -1
- package/dist/marks/DifferenceY.svelte.d.ts +1 -1
- package/dist/marks/Dot.svelte.d.ts +1 -1
- package/dist/marks/DotX.svelte.d.ts +1 -1
- package/dist/marks/DotY.svelte.d.ts +1 -1
- package/dist/marks/Frame.svelte.d.ts +1 -1
- package/dist/marks/Geo.svelte.d.ts +1 -1
- package/dist/marks/GridX.svelte.d.ts +1 -1
- package/dist/marks/GridY.svelte.d.ts +1 -1
- package/dist/marks/HTMLTooltip.svelte +28 -25
- package/dist/marks/Image.svelte.d.ts +1 -1
- package/dist/marks/Line.svelte +52 -15
- package/dist/marks/Line.svelte.d.ts +1 -1
- package/dist/marks/LineX.svelte.d.ts +1 -1
- package/dist/marks/LineY.svelte.d.ts +1 -1
- package/dist/marks/Link.svelte.d.ts +1 -1
- package/dist/marks/Pointer.svelte +31 -29
- package/dist/marks/Raster.svelte +414 -0
- package/dist/marks/Raster.svelte.d.ts +94 -0
- package/dist/marks/Rect.svelte.d.ts +1 -1
- package/dist/marks/RectX.svelte.d.ts +1 -1
- package/dist/marks/RectY.svelte.d.ts +1 -1
- package/dist/marks/RuleX.svelte.d.ts +1 -1
- package/dist/marks/RuleY.svelte.d.ts +1 -1
- package/dist/marks/Spike.svelte.d.ts +1 -1
- package/dist/marks/Text.svelte +7 -5
- package/dist/marks/Text.svelte.d.ts +2 -2
- package/dist/marks/TickX.svelte.d.ts +1 -1
- package/dist/marks/TickY.svelte.d.ts +1 -1
- package/dist/marks/Trail.svelte.d.ts +1 -1
- package/dist/marks/Vector.svelte.d.ts +1 -1
- package/dist/marks/WaffleX.svelte.d.ts +1 -1
- package/dist/marks/WaffleY.svelte.d.ts +1 -1
- package/dist/marks/helpers/Box.svelte.d.ts +1 -1
- package/dist/marks/helpers/MarkerPath.svelte.d.ts +1 -1
- package/dist/marks/helpers/Regression.svelte +2 -1
- package/dist/marks/helpers/trail.js +1 -1
- package/dist/marks/helpers/waffle.js +1 -1
- package/dist/marks/index.d.ts +1 -0
- package/dist/marks/index.js +1 -0
- package/dist/regression/polynomial.js +2 -2
- package/dist/transforms/bollinger.js +6 -3
- package/dist/transforms/density.js +3 -3
- package/dist/transforms/group.d.ts +1 -1
- package/dist/transforms/interval.d.ts +2 -2
- package/dist/transforms/jitter.d.ts +3 -3
- package/dist/transforms/map.d.ts +3 -3
- package/dist/transforms/map.js +2 -2
- package/dist/transforms/normalize.d.ts +2 -2
- package/dist/transforms/normalize.js +1 -1
- package/dist/transforms/select.d.ts +7 -7
- package/dist/transforms/window.d.ts +2 -2
- package/dist/types/mark.d.ts +3 -3
- package/dist/types/plot.d.ts +8 -1
- package/dist/types/scale.d.ts +2 -2
- package/package.json +183 -179
package/dist/Mark.svelte
CHANGED
|
@@ -297,7 +297,12 @@
|
|
|
297
297
|
: plot.scales[scale].fn(value)
|
|
298
298
|
: value;
|
|
299
299
|
|
|
300
|
-
out.valid =
|
|
300
|
+
out.valid =
|
|
301
|
+
out.valid &&
|
|
302
|
+
(scale === 'color' ||
|
|
303
|
+
scale === 'fx' ||
|
|
304
|
+
scale === 'fy' ||
|
|
305
|
+
isValid(value));
|
|
301
306
|
|
|
302
307
|
// apply dx/dy transform
|
|
303
308
|
(out as any)[channel] =
|
package/dist/Mark.svelte.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ declare function $$render<Datum extends DataRecord>(): {
|
|
|
14
14
|
fill: ChannelAccessor<Datum>;
|
|
15
15
|
fillOpacity: import("./types/index.js").ConstantAccessor<number, Datum>;
|
|
16
16
|
fontFamily: import("./types/index.js").ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
|
|
17
|
-
fontSize: import("./types/index.js").ConstantAccessor<
|
|
17
|
+
fontSize: import("./types/index.js").ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
|
|
18
18
|
fontStyle: import("./types/index.js").ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
|
|
19
19
|
fontVariant: import("./types/index.js").ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
|
|
20
20
|
fontWeight: import("./types/index.js").ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
|
package/dist/constants.js
CHANGED
|
@@ -68,6 +68,7 @@ export const VALID_SCALE_TYPES = {
|
|
|
68
68
|
'log',
|
|
69
69
|
'symlog',
|
|
70
70
|
'time',
|
|
71
|
+
'utc',
|
|
71
72
|
'ordinal',
|
|
72
73
|
'band',
|
|
73
74
|
'point',
|
|
@@ -80,6 +81,7 @@ export const VALID_SCALE_TYPES = {
|
|
|
80
81
|
'log',
|
|
81
82
|
'symlog',
|
|
82
83
|
'time',
|
|
84
|
+
'utc',
|
|
83
85
|
'ordinal',
|
|
84
86
|
'band',
|
|
85
87
|
'point',
|
package/dist/core/Plot.svelte
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
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,
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
import FacetGrid from './FacetGrid.svelte';
|
|
29
30
|
|
|
30
31
|
import mergeDeep from '../helpers/mergeDeep.js';
|
|
31
|
-
import { computeScales, projectXY } from '../helpers/scales.js';
|
|
32
|
+
import { computeScales, normalizeScaleFn, projectXY } from '../helpers/scales.js';
|
|
32
33
|
import { CHANNEL_SCALE, SCALES } from '../constants.js';
|
|
33
34
|
import { getPlotDefaults, setPlotDefaults } from '../hooks/plotDefaults.js';
|
|
34
35
|
import { maybeNumber } from '../helpers/index.js';
|
|
@@ -73,6 +74,7 @@
|
|
|
73
74
|
colorScheme: 'turbo',
|
|
74
75
|
unknown: '#cccccc99',
|
|
75
76
|
sortOrdinalDomains: true,
|
|
77
|
+
divergingColorScheme: 'RdBu',
|
|
76
78
|
categoricalColorScheme: 'observable10',
|
|
77
79
|
pointScaleHeight: 20,
|
|
78
80
|
bandScaleHeight: 30,
|
|
@@ -285,11 +287,38 @@
|
|
|
285
287
|
marks,
|
|
286
288
|
DEFAULTS
|
|
287
289
|
);
|
|
290
|
+
// Fix fx/fy scale ranges: computeScales creates them with empty ranges
|
|
291
|
+
// because getScaleRange has no case for fx/fy. We set the correct range
|
|
292
|
+
// here using overall plotWidth/plotHeight, matching FacetGrid's layout.
|
|
293
|
+
if (scales.fx.domain.length > 0) {
|
|
294
|
+
const fxOpts = plotOptions.fx;
|
|
295
|
+
const fxPaddingInner = fxOpts?.paddingInner ?? fxOpts?.padding ?? 0.1;
|
|
296
|
+
const fxFn = scaleBand()
|
|
297
|
+
.domain(scales.fx.domain as string[])
|
|
298
|
+
.paddingOuter(0)
|
|
299
|
+
.paddingInner(scales.fx.domain.length > 1 ? fxPaddingInner : 0)
|
|
300
|
+
.rangeRound([0, plotWidth]) as any;
|
|
301
|
+
fxFn.ticks = () => scales.fx.domain;
|
|
302
|
+
scales.fx.fn = normalizeScaleFn(fxFn);
|
|
303
|
+
scales.fx.range = fxFn.range();
|
|
304
|
+
}
|
|
305
|
+
if (scales.fy.domain.length > 0) {
|
|
306
|
+
const fyOpts = plotOptions.fy;
|
|
307
|
+
const fyPaddingInner = fyOpts?.paddingInner ?? fyOpts?.padding ?? 0.1;
|
|
308
|
+
const fyFn = scaleBand()
|
|
309
|
+
.domain(scales.fy.domain as string[])
|
|
310
|
+
.paddingOuter(0)
|
|
311
|
+
.paddingInner(scales.fy.domain.length > 1 ? fyPaddingInner : 0)
|
|
312
|
+
.rangeRound([0, plotHeight]) as any;
|
|
313
|
+
fyFn.ticks = () => scales.fy.domain;
|
|
314
|
+
scales.fy.fn = normalizeScaleFn(fyFn);
|
|
315
|
+
scales.fy.range = fyFn.range();
|
|
316
|
+
}
|
|
288
317
|
const colorSymbolRedundant =
|
|
289
318
|
scales.color.uniqueScaleProps?.size === 1 &&
|
|
290
319
|
scales.symbol.uniqueScaleProps?.size === 1 &&
|
|
291
|
-
[...scales.color.uniqueScaleProps?.values()][0] ===
|
|
292
|
-
[...scales.symbol.uniqueScaleProps?.values()][0];
|
|
320
|
+
[...(scales.color.uniqueScaleProps?.values() ?? [])][0] ===
|
|
321
|
+
[...(scales.symbol.uniqueScaleProps?.values() ?? [])][0];
|
|
293
322
|
return {
|
|
294
323
|
options: plotOptions,
|
|
295
324
|
width,
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import { scaleBand, scaleDiverging, scaleDivergingLog, scaleDivergingPow, scaleDivergingSqrt, scaleDivergingSymlog, scaleLinear, scaleLog, scaleOrdinal, scalePoint, scalePow, scaleQuantile, scaleQuantize, scaleSequential, scaleSequentialLog, scaleSequentialPow, scaleSequentialQuantile, scaleSequentialSqrt, scaleSequentialSymlog, scaleSqrt, scaleSymlog, scaleThreshold, scaleTime } from 'd3-scale';
|
|
1
|
+
import { scaleBand, scaleDiverging, scaleDivergingLog, scaleDivergingPow, scaleDivergingSqrt, scaleDivergingSymlog, scaleLinear, scaleLog, scaleOrdinal, scalePoint, scalePow, scaleQuantile, scaleQuantize, scaleSequential, scaleSequentialLog, scaleSequentialPow, scaleSequentialQuantile, scaleSequentialSqrt, scaleSequentialSymlog, scaleSqrt, scaleSymlog, scaleThreshold, scaleTime, scaleUtc } from 'd3-scale';
|
|
2
2
|
import { range as d3Range } from 'd3-array';
|
|
3
3
|
import { categoricalSchemes, isCategoricalScheme, isDivergingScheme, isOrdinalScheme, isQuantitativeScheme, ordinalScheme, quantitativeScheme } from './colors.js';
|
|
4
4
|
import callWithProps from './callWithProps.js';
|
|
@@ -6,11 +6,13 @@ import { interpolateLab, interpolateRound } from 'd3-interpolate';
|
|
|
6
6
|
import { coalesce, maybeNumber } from './index.js';
|
|
7
7
|
import { getLogTicks } from './getLogTicks.js';
|
|
8
8
|
import { isPlainObject } from 'es-toolkit';
|
|
9
|
+
import { isTemporalScale } from './typeChecks.js';
|
|
9
10
|
const Scales = {
|
|
10
11
|
point: scalePoint,
|
|
11
12
|
band: scaleBand,
|
|
12
13
|
linear: scaleLinear,
|
|
13
14
|
time: scaleTime,
|
|
15
|
+
utc: scaleUtc,
|
|
14
16
|
sqrt: scaleSqrt,
|
|
15
17
|
pow: scalePow,
|
|
16
18
|
log: scaleLog,
|
|
@@ -55,7 +57,7 @@ export function autoScale({ name, type, domain, scaleOptions, plotOptions, plotW
|
|
|
55
57
|
const scaleProps = {
|
|
56
58
|
domain,
|
|
57
59
|
range,
|
|
58
|
-
...((type === 'linear' || type === 'log' || type
|
|
60
|
+
...((type === 'linear' || type === 'log' || isTemporalScale(type)) && scaleOptions.nice
|
|
59
61
|
? {
|
|
60
62
|
nice: scaleOptions.nice ? niceTickCount : true
|
|
61
63
|
}
|
|
@@ -169,10 +171,12 @@ export function autoScaleColor({ type, domain, scaleOptions, plotOptions: _plotO
|
|
|
169
171
|
}
|
|
170
172
|
else if (SequentialScales[type] ||
|
|
171
173
|
DivergingScales[type]) {
|
|
174
|
+
const isDivergingType = DivergingScales.hasOwnProperty(type);
|
|
172
175
|
// continuous color scale
|
|
173
176
|
const scale = (SequentialScales[type] ||
|
|
174
177
|
DivergingScales[type]);
|
|
175
|
-
const scheme_ = scheme ||
|
|
178
|
+
const scheme_ = scheme ||
|
|
179
|
+
(isDivergingType ? plotDefaults.divergingColorScheme : plotDefaults.colorScheme);
|
|
176
180
|
if (interpolate) {
|
|
177
181
|
// user-defined interpolation function [0, 1] -> color
|
|
178
182
|
fn = scale(domain, interpolate);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { maybeTimeInterval } from './time.js';
|
|
1
|
+
import { maybeTimeInterval, maybeUtcInterval } from './time.js';
|
|
2
2
|
import { extent, range as rangei } from 'd3-array';
|
|
3
|
-
export function maybeInterval(interval) {
|
|
3
|
+
export function maybeInterval(interval, scaleType) {
|
|
4
4
|
if (interval == null)
|
|
5
5
|
return;
|
|
6
6
|
if (typeof interval === 'number') {
|
|
@@ -22,7 +22,7 @@ export function maybeInterval(interval) {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
if (typeof interval === 'string')
|
|
25
|
-
return maybeTimeInterval(interval);
|
|
25
|
+
return scaleType === 'utc' ? maybeUtcInterval(interval) : maybeTimeInterval(interval);
|
|
26
26
|
if (typeof interval.floor !== 'function')
|
|
27
27
|
throw new Error('invalid interval; missing floor method');
|
|
28
28
|
if (typeof interval.offset !== 'function')
|
|
@@ -36,7 +36,7 @@ export function autoTicks(type, ticks, interval, domain, scaleFn, count) {
|
|
|
36
36
|
const [lo, hi] = extent(domain);
|
|
37
37
|
if (lo == null || hi == null)
|
|
38
38
|
return [];
|
|
39
|
-
const I = maybeInterval(interval);
|
|
39
|
+
const I = maybeInterval(interval, type);
|
|
40
40
|
if (!I)
|
|
41
41
|
return [];
|
|
42
42
|
return I.range(lo, I.offset(hi)).filter((d) => d >= lo && d <= hi);
|
|
@@ -5,33 +5,43 @@ const DATE_TIME = {
|
|
|
5
5
|
month: 'short',
|
|
6
6
|
day: 'numeric'
|
|
7
7
|
};
|
|
8
|
-
const autoFormatDateTime = (locale) => {
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
const autoFormatDateTime = (locale, utc) => {
|
|
9
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
10
|
+
...DATE_TIME,
|
|
11
|
+
...(utc ? { timeZone: 'UTC' } : {})
|
|
12
|
+
});
|
|
13
|
+
return (date) => formatter.format(date).replace(', ', '\n');
|
|
11
14
|
};
|
|
12
15
|
const DAY_MONTH = {
|
|
13
16
|
month: 'short',
|
|
14
17
|
day: 'numeric'
|
|
15
18
|
};
|
|
16
|
-
const autoFormatDayMonth = (locale) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
+
const autoFormatDayMonth = (locale, utc) => {
|
|
20
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
21
|
+
...DAY_MONTH,
|
|
22
|
+
...(utc ? { timeZone: 'UTC' } : {})
|
|
23
|
+
});
|
|
24
|
+
return (date) => formatter.format(date).replace(' ', '\n');
|
|
19
25
|
};
|
|
20
26
|
const MONTH_YEAR = {
|
|
21
27
|
month: 'short',
|
|
22
28
|
year: 'numeric'
|
|
23
29
|
};
|
|
24
|
-
const autoFormatMonthYear = (locale) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
30
|
+
const autoFormatMonthYear = (locale, utc) => {
|
|
31
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
32
|
+
...MONTH_YEAR,
|
|
33
|
+
...(utc ? { timeZone: 'UTC' } : {})
|
|
34
|
+
});
|
|
35
|
+
return (date) => formatter.format(date).replace(' ', '\n');
|
|
27
36
|
};
|
|
28
37
|
export default function autoTimeFormat(x, plotWidth, plotLocale) {
|
|
38
|
+
const utc = x.type === 'utc';
|
|
29
39
|
const daysPer100Px = ((toNumber(x.domain[1]) - toNumber(x.domain[0])) / plotWidth / 864e5) * 100;
|
|
30
40
|
const format = daysPer100Px < 1
|
|
31
|
-
? autoFormatDateTime(plotLocale)
|
|
41
|
+
? autoFormatDateTime(plotLocale, utc)
|
|
32
42
|
: daysPer100Px < 30
|
|
33
|
-
? autoFormatDayMonth(plotLocale)
|
|
34
|
-
: autoFormatMonthYear(plotLocale);
|
|
43
|
+
? autoFormatDayMonth(plotLocale, utc)
|
|
44
|
+
: autoFormatMonthYear(plotLocale, utc);
|
|
35
45
|
return (date) => format(date).split('\n');
|
|
36
46
|
}
|
|
37
47
|
function toNumber(d) {
|
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,3 +46,86 @@ export function getEmptyFacets(marks, fxValues, fyValues) {
|
|
|
46
46
|
}
|
|
47
47
|
return out;
|
|
48
48
|
}
|
|
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/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
|
package/dist/helpers/noise.js
CHANGED
|
@@ -9,7 +9,7 @@ const scaled_cosine = (i) => 0.5 * (1.0 - Math.cos(i * Math.PI));
|
|
|
9
9
|
let perlin; // will be initialized lazily by noise() or noiseSeed()
|
|
10
10
|
export function noise(x, y = 0, z = 0) {
|
|
11
11
|
if (perlin == null) {
|
|
12
|
-
perlin =
|
|
12
|
+
perlin = Array.from({ length: PERLIN_SIZE + 1 });
|
|
13
13
|
for (let i = 0; i < PERLIN_SIZE + 1; i++) {
|
|
14
14
|
perlin[i] = Math.random();
|
|
15
15
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type InterpolateFunction = (index: number[], width: number, height: number, X: Float64Array, Y: Float64Array, V: ArrayLike<any>) => ArrayLike<any>;
|
|
2
|
+
/**
|
|
3
|
+
* Simple forward mapping: each sample is binned to its nearest pixel.
|
|
4
|
+
* If multiple samples map to the same pixel, the last one wins.
|
|
5
|
+
*/
|
|
6
|
+
export declare function interpolateNone(index: number[], width: number, height: number, X: Float64Array, Y: Float64Array, V: ArrayLike<any>): any[];
|
|
7
|
+
/**
|
|
8
|
+
* Nearest-neighbor interpolation using Delaunay triangulation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function interpolateNearest(index: number[], width: number, height: number, X: Float64Array, Y: Float64Array, V: ArrayLike<any>): any;
|
|
11
|
+
/**
|
|
12
|
+
* Barycentric interpolation: fills the interior of each Delaunay triangle with
|
|
13
|
+
* barycentric-weighted values, then extrapolates exterior pixels to the hull.
|
|
14
|
+
*/
|
|
15
|
+
export declare function interpolatorBarycentric({ random }?: {
|
|
16
|
+
random?: (() => number) | undefined;
|
|
17
|
+
}): InterpolateFunction;
|
|
18
|
+
/**
|
|
19
|
+
* Walk-on-spheres algorithm for smooth interpolation.
|
|
20
|
+
* https://observablehq.com/@observablehq/walk-on-spheres-precision
|
|
21
|
+
*/
|
|
22
|
+
export declare function interpolatorRandomWalk({ random, minDistance, maxSteps }?: {
|
|
23
|
+
random?: (() => number) | undefined;
|
|
24
|
+
minDistance?: number | undefined;
|
|
25
|
+
maxSteps?: number | undefined;
|
|
26
|
+
}): InterpolateFunction;
|