svelteplot 0.11.0 → 0.11.1
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 +31 -3
- package/dist/helpers/arrowPath.js +10 -5
- package/dist/helpers/autoScales.js +4 -2
- 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/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.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/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.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/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 +2 -2
- package/dist/types/plot.d.ts +1 -1
- package/dist/types/scale.d.ts +2 -2
- package/package.json +181 -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';
|
|
@@ -285,11 +286,38 @@
|
|
|
285
286
|
marks,
|
|
286
287
|
DEFAULTS
|
|
287
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
|
+
}
|
|
288
316
|
const colorSymbolRedundant =
|
|
289
317
|
scales.color.uniqueScaleProps?.size === 1 &&
|
|
290
318
|
scales.symbol.uniqueScaleProps?.size === 1 &&
|
|
291
|
-
[...scales.color.uniqueScaleProps?.values()][0] ===
|
|
292
|
-
[...scales.symbol.uniqueScaleProps?.values()][0];
|
|
319
|
+
[...(scales.color.uniqueScaleProps?.values() ?? [])][0] ===
|
|
320
|
+
[...(scales.symbol.uniqueScaleProps?.values() ?? [])][0];
|
|
293
321
|
return {
|
|
294
322
|
options: plotOptions,
|
|
295
323
|
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
|
}
|
|
@@ -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
|
}
|
|
@@ -9,7 +9,7 @@ export function roundedRect(x, y, width, height, borderRadius = {
|
|
|
9
9
|
}) {
|
|
10
10
|
const maxRadius = Math.min(width, height) / 2;
|
|
11
11
|
const [tl, tr, bl, br] = (typeof borderRadius === 'number'
|
|
12
|
-
?
|
|
12
|
+
? Array.from({ length: 4 }, () => borderRadius)
|
|
13
13
|
: [
|
|
14
14
|
borderRadius?.topLeft || 0,
|
|
15
15
|
borderRadius?.topRight || 0,
|
package/dist/helpers/scales.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ChannelAccessor, GenericMarkOptions, Mark, MarkType, PlotDefaults, PlotScaleFunction, ResolvedPlotOptions, PlotScales, PlotState, RawValue, ScaleName, ScaleOptions, ScaleType, ScaledChannelName, UsedScales } from '../types/index.js';
|
|
2
|
+
export declare function normalizeScaleFn(fn: any): PlotScaleFunction;
|
|
2
3
|
/**
|
|
3
4
|
* compute the plot scales
|
|
4
5
|
*/
|
package/dist/helpers/scales.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { extent, ascending } from 'd3-array';
|
|
2
2
|
import { isColorOrNull, isDate, isDateOrNull, isNumberOrNull, isNumberOrNullOrNaN, isStringOrNull } from './typeChecks.js';
|
|
3
3
|
import { CHANNEL_SCALE, ORIGINAL_NAME_KEYS, VALID_SCALE_TYPES } from '../constants.js';
|
|
4
|
-
import { isSymbolOrNull } from './typeChecks.js';
|
|
4
|
+
import { isSymbolOrNull, isTemporalScale } from './typeChecks.js';
|
|
5
5
|
import { resolveProp, toChannelOption } from './resolve.js';
|
|
6
6
|
import isDataRecord from './isDataRecord.js';
|
|
7
7
|
import { createProjection } from './projection.js';
|
|
8
8
|
import { maybeInterval } from './autoTicks.js';
|
|
9
9
|
import { IS_SORTED } from '../transforms/sort.js';
|
|
10
|
-
function normalizeScaleFn(fn) {
|
|
10
|
+
export function normalizeScaleFn(fn) {
|
|
11
11
|
const out = fn;
|
|
12
12
|
out.range ||= () => [];
|
|
13
13
|
out.invert ||= (value) => value;
|
|
@@ -165,7 +165,8 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
165
165
|
sortOrdinalDomain = false;
|
|
166
166
|
}
|
|
167
167
|
// construct domain from data values
|
|
168
|
-
|
|
168
|
+
// For facet scales (fx/fy), null is a valid grouping category (e.g. penguins with sex=null)
|
|
169
|
+
const valueArr = [...dataValues.values(), ...(scaleOptions.domain || [])].filter((d) => d != null || name === 'fx' || name === 'fy');
|
|
169
170
|
const type = !scaleOptions.type || scaleOptions.type === 'auto'
|
|
170
171
|
? inferScaleType(name, valueArr, markTypes, scaleOptions)
|
|
171
172
|
: scaleOptions.type;
|
|
@@ -177,7 +178,9 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
177
178
|
if (isOrdinal && sortOrdinalDomain) {
|
|
178
179
|
valueArr.sort(ascending);
|
|
179
180
|
}
|
|
180
|
-
const valueArray = type === 'quantile' || type === 'quantile-cont'
|
|
181
|
+
const valueArray = type === 'quantile' || type === 'quantile-cont'
|
|
182
|
+
? allDataValues.toSorted((a, b) => Number(a) - Number(b))
|
|
183
|
+
: valueArr;
|
|
181
184
|
let domain = scaleOptions.domain
|
|
182
185
|
? isOrdinal
|
|
183
186
|
? scaleOptions.domain
|
|
@@ -228,7 +231,7 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
228
231
|
skip,
|
|
229
232
|
manualActiveMarks,
|
|
230
233
|
uniqueScaleProps,
|
|
231
|
-
autoTitle: type
|
|
234
|
+
autoTitle: isTemporalScale(type)
|
|
232
235
|
? null
|
|
233
236
|
: propNames.size === 1
|
|
234
237
|
? `${[...propNames.values()][0]}${type === 'log' ? ' (log)' : ''}`
|
package/dist/helpers/time.js
CHANGED
|
@@ -139,7 +139,7 @@ const timeFormatIntervals = [
|
|
|
139
139
|
// from largest to smallest, used to determine the most specific standard time
|
|
140
140
|
// format for a given array of dates. This is a subset of the tick intervals
|
|
141
141
|
// listed above; we only need the breakpoints where the format changes.
|
|
142
|
-
const
|
|
142
|
+
const _formatIntervals = [
|
|
143
143
|
utcFormatIntervals[0],
|
|
144
144
|
timeFormatIntervals[0],
|
|
145
145
|
utcFormatIntervals[1],
|
|
@@ -8,3 +8,4 @@ export declare function isStringOrNull(v: RawValue | null | undefined): v is str
|
|
|
8
8
|
export declare function isSymbolOrNull(v: RawValue | null | undefined): v is ("square" | "circle" | "asterisk" | "cross" | "diamond" | "diamond2" | "hexagon" | "plus" | "square2" | "star" | "times" | "triangle" | "triangle2" | "wye") | import("d3-shape").SymbolType | null | undefined;
|
|
9
9
|
export declare function isColorOrNull(v: RawValue | null | undefined): boolean;
|
|
10
10
|
export declare function isOpacityOrNull(v: RawValue): boolean;
|
|
11
|
+
export declare function isTemporalScale(type: string): boolean;
|
|
@@ -14,7 +14,7 @@ declare function $$render<Datum extends DataRecord>(): {
|
|
|
14
14
|
fill: ChannelAccessor<Datum>;
|
|
15
15
|
fillOpacity: ConstantAccessor<number, Datum>;
|
|
16
16
|
fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
|
|
17
|
-
fontSize: ConstantAccessor<
|
|
17
|
+
fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
|
|
18
18
|
fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
|
|
19
19
|
fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
|
|
20
20
|
fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
|
|
@@ -14,7 +14,7 @@ declare function $$render<Datum extends DataRow>(): {
|
|
|
14
14
|
fill: ChannelAccessor<Datum>;
|
|
15
15
|
fillOpacity: ConstantAccessor<number, Datum>;
|
|
16
16
|
fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
|
|
17
|
-
fontSize: ConstantAccessor<
|
|
17
|
+
fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
|
|
18
18
|
fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
|
|
19
19
|
fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
|
|
20
20
|
fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
|
|
@@ -14,7 +14,7 @@ declare function $$render<Datum extends DataRow>(): {
|
|
|
14
14
|
fill: ChannelAccessor<Datum>;
|
|
15
15
|
fillOpacity: ConstantAccessor<number, Datum>;
|
|
16
16
|
fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
|
|
17
|
-
fontSize: ConstantAccessor<
|
|
17
|
+
fontSize: ConstantAccessor<import("csstype").Property.FontSize<number>, Datum>;
|
|
18
18
|
fontStyle: ConstantAccessor<import("csstype").Property.FontStyle, Datum>;
|
|
19
19
|
fontVariant: ConstantAccessor<import("csstype").Property.FontVariant, Datum>;
|
|
20
20
|
fontWeight: ConstantAccessor<import("csstype").Property.FontWeight, Datum>;
|
|
@@ -13,7 +13,7 @@ declare function $$render<Datum = DataRecord | GeoJSON.GeoJsonObject>(): {
|
|
|
13
13
|
fill: ChannelAccessor<Datum>;
|
|
14
14
|
fillOpacity: ConstantAccessor<number, Datum>;
|
|
15
15
|
fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
|
|
16
|
-
fontSize: ConstantAccessor<
|
|
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>;
|
package/dist/marks/AxisX.svelte
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type * as CSS from 'csstype';
|
|
19
19
|
import autoTimeFormat from '../helpers/autoTimeFormat.js';
|
|
20
20
|
import { autoTicks } from '../helpers/autoTicks.js';
|
|
21
|
+
import { isTemporalScale } from '../helpers/typeChecks.js';
|
|
21
22
|
import { resolveScaledStyles } from '../helpers/resolve.js';
|
|
22
23
|
import { getPlotDefaults } from '../hooks/plotDefaults.js';
|
|
23
24
|
import { extent } from 'd3-array';
|
|
@@ -161,10 +162,14 @@
|
|
|
161
162
|
? tickFmt
|
|
162
163
|
: plot.scales.x.type === 'band' || plot.scales.x.type === 'point'
|
|
163
164
|
? (d: RawValue) => String(d)
|
|
164
|
-
: plot.scales.x.type
|
|
165
|
-
? // time scale
|
|
165
|
+
: isTemporalScale(plot.scales.x.type)
|
|
166
|
+
? // time/utc scale
|
|
166
167
|
typeof tickFmt === 'object'
|
|
167
|
-
? (d: Date) =>
|
|
168
|
+
? (d: Date) =>
|
|
169
|
+
Intl.DateTimeFormat(plot.options.locale, {
|
|
170
|
+
...tickFmt,
|
|
171
|
+
...(plot.scales.x.type === 'utc' ? { timeZone: 'UTC' } : {})
|
|
172
|
+
}).format(d)
|
|
168
173
|
: autoTimeFormat(plot.scales.x, plot.plotWidth, plot.options.locale)
|
|
169
174
|
: // numeric scale
|
|
170
175
|
typeof tickFmt === 'object'
|
|
@@ -13,7 +13,7 @@ declare function $$render<Datum extends RawValue>(): {
|
|
|
13
13
|
fill: import("../types/channel.js").ChannelAccessor<Datum>;
|
|
14
14
|
fillOpacity: ConstantAccessor<number, Datum>;
|
|
15
15
|
fontFamily: ConstantAccessor<CSS.Property.FontFamily, Datum>;
|
|
16
|
-
fontSize: ConstantAccessor<number
|
|
16
|
+
fontSize: ConstantAccessor<CSS.Property.FontSize<number>, Datum>;
|
|
17
17
|
fontStyle: ConstantAccessor<CSS.Property.FontStyle, Datum>;
|
|
18
18
|
fontVariant: ConstantAccessor<CSS.Property.FontVariant, Datum>;
|
|
19
19
|
fontWeight: ConstantAccessor<CSS.Property.FontWeight, Datum>;
|
package/dist/marks/AxisY.svelte
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
} from '../types/index.js';
|
|
18
18
|
import autoTimeFormat from '../helpers/autoTimeFormat.js';
|
|
19
19
|
import { autoTicks } from '../helpers/autoTicks.js';
|
|
20
|
+
import { isTemporalScale } from '../helpers/typeChecks.js';
|
|
20
21
|
import { resolveScaledStyles } from '../helpers/resolve.js';
|
|
21
22
|
import { getPlotDefaults } from '../hooks/plotDefaults.js';
|
|
22
23
|
import { extent } from 'd3-array';
|
|
@@ -158,10 +159,14 @@
|
|
|
158
159
|
? tickFmt
|
|
159
160
|
: plot.scales.y.type === 'band' || plot.scales.y.type === 'point'
|
|
160
161
|
? (d: RawValue) => String(d)
|
|
161
|
-
: plot.scales.y.type
|
|
162
|
-
? // time scale
|
|
162
|
+
: isTemporalScale(plot.scales.y.type)
|
|
163
|
+
? // time/utc scale
|
|
163
164
|
typeof tickFmt === 'object'
|
|
164
|
-
? (d: Date) =>
|
|
165
|
+
? (d: Date) =>
|
|
166
|
+
Intl.DateTimeFormat(plot.options.locale, {
|
|
167
|
+
...tickFmt,
|
|
168
|
+
...(plot.scales.y.type === 'utc' ? { timeZone: 'UTC' } : {})
|
|
169
|
+
}).format(d)
|
|
165
170
|
: autoTimeFormat(plot.scales.y, plot.plotWidth, plot.options.locale)
|
|
166
171
|
: // numeric scale
|
|
167
172
|
typeof tickFmt === 'object'
|
|
@@ -12,7 +12,7 @@ declare function $$render<Datum extends RawValue>(): {
|
|
|
12
12
|
fill: import("../types/channel.js").ChannelAccessor<Datum>;
|
|
13
13
|
fillOpacity: ConstantAccessor<number, Datum>;
|
|
14
14
|
fontFamily: ConstantAccessor<import("csstype").Property.FontFamily, Datum>;
|
|
15
|
-
fontSize: ConstantAccessor<
|
|
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>;
|