svelteplot 0.2.0 → 0.2.2
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 +12 -1
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/resolve.d.ts +1 -1
- package/dist/helpers/resolve.js +6 -5
- package/dist/helpers/scales.d.ts +2 -2
- package/dist/helpers/scales.js +5 -4
- package/dist/helpers/typeChecks.js +14 -10
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -2
- package/dist/marks/BarX.svelte +11 -37
- package/dist/marks/BarY.svelte +27 -58
- package/dist/marks/BarY.svelte.d.ts +2 -8
- package/dist/marks/Cell.svelte +12 -36
- package/dist/marks/ColorLegend.svelte +6 -10
- package/dist/marks/Dot.svelte +2 -2
- package/dist/marks/Geo.svelte +50 -41
- package/dist/marks/Geo.svelte.d.ts +3 -1
- package/dist/marks/GridX.svelte +2 -2
- package/dist/marks/GridY.svelte +2 -2
- package/dist/marks/Line.svelte +98 -80
- package/dist/marks/Line.svelte.d.ts +5 -3
- package/dist/marks/Pointer.svelte +2 -1
- package/dist/marks/Rect.svelte +10 -24
- package/dist/marks/helpers/CanvasLayer.svelte +10 -16
- package/dist/marks/helpers/CanvasLayer.svelte.d.ts +2 -6
- package/dist/marks/helpers/DotCanvas.svelte +72 -159
- package/dist/marks/helpers/DotCanvas.svelte.d.ts +2 -4
- package/dist/marks/helpers/GeoCanvas.svelte +95 -145
- package/dist/marks/helpers/GeoCanvas.svelte.d.ts +3 -5
- package/dist/marks/helpers/LineCanvas.svelte +116 -0
- package/dist/marks/helpers/LineCanvas.svelte.d.ts +12 -0
- package/dist/marks/helpers/LinearGradientX.svelte +27 -0
- package/dist/marks/helpers/LinearGradientX.svelte.d.ts +11 -0
- package/dist/marks/helpers/LinearGradientY.svelte +27 -0
- package/dist/marks/helpers/LinearGradientY.svelte.d.ts +11 -0
- package/dist/marks/helpers/RectPath.svelte +129 -0
- package/dist/marks/helpers/RectPath.svelte.d.ts +27 -0
- package/dist/marks/helpers/canvas.d.ts +1 -0
- package/dist/marks/helpers/canvas.js +34 -0
- package/dist/transforms/recordize.d.ts +1 -0
- package/dist/transforms/recordize.js +16 -5
- package/dist/transforms/stack.js +10 -7
- package/dist/types.d.ts +12 -6
- package/package.json +19 -17
package/dist/Mark.svelte
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
ScaledDataRecord,
|
|
19
19
|
ScaleType
|
|
20
20
|
} from './types.js';
|
|
21
|
+
import { isEqual } from 'es-toolkit';
|
|
21
22
|
import { getUsedScales, projectXY, projectX, projectY } from './helpers/scales.js';
|
|
22
23
|
import { testFilter, isValid } from './helpers/index.js';
|
|
23
24
|
import { resolveChannel, resolveProp } from './helpers/resolve.js';
|
|
@@ -105,6 +106,13 @@
|
|
|
105
106
|
|
|
106
107
|
let added = false;
|
|
107
108
|
|
|
109
|
+
$effect(() => {
|
|
110
|
+
const prevOptions = untrack(() => mark.options);
|
|
111
|
+
if (!isEqual(prevOptions, optionsWithAutoFacet)) {
|
|
112
|
+
mark.options = optionsWithAutoFacet;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
108
116
|
$effect(() => {
|
|
109
117
|
if (added) return;
|
|
110
118
|
// without using untrack() here we end up with inexplicable
|
|
@@ -118,6 +126,7 @@
|
|
|
118
126
|
);
|
|
119
127
|
mark.data = untrack(() => data);
|
|
120
128
|
mark.options = untrack(() => optionsWithAutoFacet);
|
|
129
|
+
|
|
121
130
|
addMark(mark);
|
|
122
131
|
added = true;
|
|
123
132
|
});
|
|
@@ -225,6 +234,7 @@
|
|
|
225
234
|
usedScales.y,
|
|
226
235
|
suffix
|
|
227
236
|
);
|
|
237
|
+
|
|
228
238
|
out[`x${suffix}`] = x;
|
|
229
239
|
out[`y${suffix}`] = y;
|
|
230
240
|
out.valid =
|
|
@@ -243,7 +253,7 @@
|
|
|
243
253
|
ScaleName
|
|
244
254
|
][]) {
|
|
245
255
|
// check if the mark has defined an accessor for this channel
|
|
246
|
-
if (options?.[channel]
|
|
256
|
+
if (options?.[channel] != null && out[channel] === undefined) {
|
|
247
257
|
// resolve value
|
|
248
258
|
const value = row[channel];
|
|
249
259
|
|
|
@@ -256,6 +266,7 @@
|
|
|
256
266
|
: value;
|
|
257
267
|
|
|
258
268
|
out.valid = out.valid && isValid(value);
|
|
269
|
+
|
|
259
270
|
// apply dx/dy transform
|
|
260
271
|
out[channel] =
|
|
261
272
|
scale === 'x' && Number.isFinite(scaled) ? (scaled as number) + dx : scaled;
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -16,3 +16,4 @@ export declare const POSITION_CHANNELS: Set<ChannelName>;
|
|
|
16
16
|
export declare function parseInset(inset: number | string, width: number): number;
|
|
17
17
|
export declare function omit<T extends {}, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K>;
|
|
18
18
|
export declare function identity<T>(x: T): T;
|
|
19
|
+
export declare const GEOJSON_PREFER_STROKE: Set<string>;
|
package/dist/helpers/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import type { ScaleName, ChannelName, ScaledChannelName, ChannelAccessor, DataRo
|
|
|
3
3
|
type ChannelAlias = {
|
|
4
4
|
channel: ScaledChannelName;
|
|
5
5
|
};
|
|
6
|
-
export declare function resolveProp<T>(accessor: ConstantAccessor<T>, datum: DataRecord | null, _defaultValue?: T | null): T |
|
|
6
|
+
export declare function resolveProp<T>(accessor: ConstantAccessor<T>, datum: DataRecord | null, _defaultValue?: T | null): T | typeof _defaultValue;
|
|
7
7
|
type ChannelOptions = {
|
|
8
8
|
value: ChannelAccessor;
|
|
9
9
|
scale?: ScaleName | null;
|
package/dist/helpers/resolve.js
CHANGED
|
@@ -4,16 +4,17 @@ import isRawValue from './isRawValue.js';
|
|
|
4
4
|
import { isValid } from './isValid.js';
|
|
5
5
|
import { pick } from 'es-toolkit';
|
|
6
6
|
import { getBaseStylesObject } from './getBaseStyles.js';
|
|
7
|
+
import { RAW_VALUE } from '../transforms/recordize.js';
|
|
7
8
|
export function resolveProp(accessor, datum, _defaultValue = null) {
|
|
8
9
|
if (typeof accessor === 'function') {
|
|
9
|
-
// datum
|
|
10
|
+
// datum[RAW_VALUE] exists if an array of raw values was used as dataset and got
|
|
10
11
|
// "recordized" by the recordize transform. We want to hide this wrapping to the user
|
|
11
12
|
// so we're passing the original value to accessor functions instead of our wrapped record
|
|
12
13
|
return datum == null
|
|
13
14
|
? accessor()
|
|
14
|
-
: accessor(datum
|
|
15
|
+
: accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum);
|
|
15
16
|
}
|
|
16
|
-
else if (typeof accessor === 'string' && datum && datum[accessor] !== undefined) {
|
|
17
|
+
else if ((typeof accessor === 'string' || typeof accessor === 'symbol') && datum && datum[accessor] !== undefined) {
|
|
17
18
|
return datum[accessor];
|
|
18
19
|
}
|
|
19
20
|
return isRawValue(accessor) ? accessor : _defaultValue;
|
|
@@ -46,10 +47,10 @@ function resolve(datum, accessor, channel, scale) {
|
|
|
46
47
|
if (isDataRecord(datum)) {
|
|
47
48
|
// use accessor function
|
|
48
49
|
if (typeof accessor === 'function')
|
|
49
|
-
// datum
|
|
50
|
+
// datum[RAW_VALUE] exists if an array of raw values was used as dataset and got
|
|
50
51
|
// "recordized" by the recordize transform. We want to hide this wrapping to the user
|
|
51
52
|
// so we're passing the original value to accessor functions instead of our wrapped record
|
|
52
|
-
return accessor(datum
|
|
53
|
+
return accessor(datum[RAW_VALUE] != null ? datum[RAW_VALUE] : datum);
|
|
53
54
|
// use accessor string
|
|
54
55
|
if ((typeof accessor === 'string' || typeof accessor === 'symbol') && datum[accessor] !== undefined)
|
|
55
56
|
return datum[accessor];
|
package/dist/helpers/scales.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChannelAccessor, GenericMarkOptions, Mark, MarkType, PlotDefaults, PlotOptions, PlotScales, PlotState, RawValue, ScaleName, ScaleOptions, ScaleType, ScaledChannelName } from '../types.js';
|
|
1
|
+
import type { ChannelAccessor, GenericMarkOptions, Mark, MarkType, PlotDefaults, PlotOptions, PlotScales, PlotState, RawValue, ScaleName, ScaleOptions, ScaleType, ScaledChannelName, UsedScales } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* compute the plot scales
|
|
4
4
|
*/
|
|
@@ -35,7 +35,7 @@ export declare function inferScaleType(name: ScaleName, dataValues: RawValue[],
|
|
|
35
35
|
* scales, we need to check if the the scale is supposed to be used
|
|
36
36
|
* not. That's what this function is used for.
|
|
37
37
|
*/
|
|
38
|
-
export declare function getUsedScales(plot: PlotState, options: GenericMarkOptions, mark: Mark<GenericMarkOptions>):
|
|
38
|
+
export declare function getUsedScales(plot: PlotState, options: GenericMarkOptions, mark: Mark<GenericMarkOptions>): UsedScales;
|
|
39
39
|
export declare function looksLikeANumber(input: string | number): boolean;
|
|
40
40
|
export declare function projectXY(scales: PlotScales, x: RawValue, y: RawValue, useXScale?: boolean, useYScale?: boolean): [number, number];
|
|
41
41
|
export declare function projectX(channel: 'x' | 'x1' | 'x2', scales: PlotScales, value: RawValue): number;
|
package/dist/helpers/scales.js
CHANGED
|
@@ -113,7 +113,7 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
113
113
|
for (const datum of mark.data) {
|
|
114
114
|
const value = resolveProp(channelOptions.value, datum);
|
|
115
115
|
dataValues.add(value);
|
|
116
|
-
if (name === 'color' && scaleOptions.type === 'quantile') {
|
|
116
|
+
if (name === 'color' && scaleOptions.type === 'quantile' || scaleOptions.type === 'quantile-cont') {
|
|
117
117
|
allDataValues.push(value);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
@@ -146,6 +146,7 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
146
146
|
if (isOrdinal && sortOrdinalDomain) {
|
|
147
147
|
valueArr.sort(ascending);
|
|
148
148
|
}
|
|
149
|
+
const valueArray = type === 'quantile' || type === 'quantile-cont' ? allDataValues.toSorted() : valueArr;
|
|
149
150
|
const domain = scaleOptions.domain
|
|
150
151
|
? isOrdinal
|
|
151
152
|
? scaleOptions.domain
|
|
@@ -157,9 +158,9 @@ export function createScale(name, scaleOptions, marks, plotOptions, plotWidth, p
|
|
|
157
158
|
type === 'quantile' ||
|
|
158
159
|
type === 'quantile-cont'
|
|
159
160
|
? name === 'y'
|
|
160
|
-
?
|
|
161
|
-
:
|
|
162
|
-
: extent(scaleOptions.zero ? [0, ...
|
|
161
|
+
? valueArray.toReversed()
|
|
162
|
+
: valueArray
|
|
163
|
+
: extent(scaleOptions.zero ? [0, ...valueArray] : valueArray);
|
|
163
164
|
if (!scaleOptions.scale) {
|
|
164
165
|
throw new Error(`No scale function defined for ${name}`);
|
|
165
166
|
}
|
|
@@ -26,16 +26,20 @@ export function isSymbolOrNull(v) {
|
|
|
26
26
|
return v == null || ((typeof v === 'string' || typeof v === 'object') && isSymbol(v));
|
|
27
27
|
}
|
|
28
28
|
export function isColorOrNull(v) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
if (v == null)
|
|
30
|
+
return true;
|
|
31
|
+
if (typeof v === 'string') {
|
|
32
|
+
v = `${v}`.toLowerCase();
|
|
33
|
+
return (v === 'currentcolor' ||
|
|
34
|
+
CSS_VAR.test(v) ||
|
|
35
|
+
CSS_COLOR.test(v) ||
|
|
36
|
+
CSS_COLOR_MIX.test(v) ||
|
|
37
|
+
CSS_COLOR_CONTRAST.test(v) ||
|
|
38
|
+
CSS_RGBA.test(v) ||
|
|
39
|
+
CSS_URL.test(v) ||
|
|
40
|
+
color(v) !== null);
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
39
43
|
}
|
|
40
44
|
export function isOpacityOrNull(v) {
|
|
41
45
|
return v == null || (typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1);
|
package/dist/index.d.ts
CHANGED
|
@@ -58,10 +58,12 @@ export { normalizeX, normalizeY } from './transforms/normalize.js';
|
|
|
58
58
|
export { group, groupX, groupY, groupZ } from './transforms/group.js';
|
|
59
59
|
export { intervalX, intervalY } from './transforms/interval.js';
|
|
60
60
|
export { recordizeX, recordizeY } from './transforms/recordize.js';
|
|
61
|
-
export { renameChannels } from './transforms/rename.js';
|
|
61
|
+
export { renameChannels, replaceChannels } from './transforms/rename.js';
|
|
62
62
|
export { select, selectFirst, selectLast, selectMaxX, selectMaxY, selectMinX, selectMinY } from './transforms/select.js';
|
|
63
63
|
export { shiftX, shiftY } from './transforms/shift.js';
|
|
64
64
|
export { sort, shuffle, reverse } from './transforms/sort.js';
|
|
65
65
|
export { stackX, stackY } from './transforms/stack.js';
|
|
66
66
|
export { windowX, windowY } from './transforms/window.js';
|
|
67
67
|
export { formatMonth } from './helpers/formats.js';
|
|
68
|
+
export { default as LinearGradientX } from './marks/helpers/LinearGradientX.svelte';
|
|
69
|
+
export { default as LinearGradientY } from './marks/helpers/LinearGradientY.svelte';
|
package/dist/index.js
CHANGED
|
@@ -61,11 +61,13 @@ export { normalizeX, normalizeY } from './transforms/normalize.js';
|
|
|
61
61
|
export { group, groupX, groupY, groupZ } from './transforms/group.js';
|
|
62
62
|
export { intervalX, intervalY } from './transforms/interval.js';
|
|
63
63
|
export { recordizeX, recordizeY } from './transforms/recordize.js';
|
|
64
|
-
export { renameChannels } from './transforms/rename.js';
|
|
64
|
+
export { renameChannels, replaceChannels } from './transforms/rename.js';
|
|
65
65
|
export { select, selectFirst, selectLast, selectMaxX, selectMaxY, selectMinX, selectMinY } from './transforms/select.js';
|
|
66
66
|
export { shiftX, shiftY } from './transforms/shift.js';
|
|
67
67
|
export { sort, shuffle, reverse } from './transforms/sort.js';
|
|
68
68
|
export { stackX, stackY } from './transforms/stack.js';
|
|
69
69
|
export { windowX, windowY } from './transforms/window.js';
|
|
70
|
-
//
|
|
70
|
+
// helpers
|
|
71
71
|
export { formatMonth } from './helpers/formats.js';
|
|
72
|
+
export { default as LinearGradientX } from './marks/helpers/LinearGradientX.svelte';
|
|
73
|
+
export { default as LinearGradientY } from './marks/helpers/LinearGradientY.svelte';
|
package/dist/marks/BarX.svelte
CHANGED
|
@@ -6,13 +6,11 @@
|
|
|
6
6
|
import Mark from '../Mark.svelte';
|
|
7
7
|
import { getContext } from 'svelte';
|
|
8
8
|
import { stackX, recordizeX, intervalX, sort } from '../index.js';
|
|
9
|
-
import { resolveProp, resolveStyles } from '../helpers/resolve.js';
|
|
10
|
-
import { roundedRect } from '../helpers/roundedRect.js';
|
|
11
9
|
import type { PlotContext, BaseMarkProps, RectMarkProps, ChannelAccessor } from '../types.js';
|
|
12
10
|
import type { StackOptions } from '../transforms/stack.js';
|
|
13
11
|
import type { DataRow } from '../types.js';
|
|
14
|
-
import { addEventHandlers } from './helpers/events.js';
|
|
15
12
|
import GroupMultiple from './helpers/GroupMultiple.svelte';
|
|
13
|
+
import RectPath from './helpers/RectPath.svelte';
|
|
16
14
|
|
|
17
15
|
type BarXProps = BaseMarkProps & {
|
|
18
16
|
data: DataRow[];
|
|
@@ -21,14 +19,6 @@
|
|
|
21
19
|
x2?: ChannelAccessor;
|
|
22
20
|
y?: ChannelAccessor;
|
|
23
21
|
stack?: StackOptions;
|
|
24
|
-
borderRadius?:
|
|
25
|
-
| number
|
|
26
|
-
| {
|
|
27
|
-
topLeft?: number;
|
|
28
|
-
topRight?: number;
|
|
29
|
-
bottomRight?: number;
|
|
30
|
-
bottomLeft?: number;
|
|
31
|
-
};
|
|
32
22
|
} & RectMarkProps;
|
|
33
23
|
|
|
34
24
|
let { data = [{}], class: className = null, stack, ...options }: BarXProps = $props();
|
|
@@ -59,33 +49,17 @@
|
|
|
59
49
|
{@const bw = plot.scales.y.fn.bandwidth()}
|
|
60
50
|
{@const minx = Math.min(d.x1, d.x2)}
|
|
61
51
|
{@const maxx = Math.max(d.x1, d.x2)}
|
|
62
|
-
{@const insetLeft = resolveProp(args.insetLeft, d.datum, 0)}
|
|
63
|
-
{@const insetRight = resolveProp(args.insetRight, d.datum, 0)}
|
|
64
|
-
{@const insetTop = resolveProp(args.insetTop || args.inset, d.datum, 0)}
|
|
65
|
-
{@const insetBottom = resolveProp(args.insetBottom || args.inset, d.datum, 0)}
|
|
66
|
-
{@const dx = resolveProp(args.dx, d.datum, 0)}
|
|
67
|
-
{@const dy = resolveProp(args.dy, d.datum, 0)}
|
|
68
52
|
{#if d.valid}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{style}
|
|
80
|
-
transform="translate({[
|
|
81
|
-
minx + dx + insetLeft,
|
|
82
|
-
d.y + insetTop + dy - bw * 0.5
|
|
83
|
-
]})"
|
|
84
|
-
use:addEventHandlers={{
|
|
85
|
-
getPlotState,
|
|
86
|
-
options: args,
|
|
87
|
-
datum: d.datum
|
|
88
|
-
}} />
|
|
53
|
+
<RectPath
|
|
54
|
+
{usedScales}
|
|
55
|
+
class={className}
|
|
56
|
+
{options}
|
|
57
|
+
datum={d}
|
|
58
|
+
x={minx}
|
|
59
|
+
useInsetAsFallbackHorizontally={false}
|
|
60
|
+
y={d.y - bw * 0.5}
|
|
61
|
+
width={maxx - minx}
|
|
62
|
+
height={bw} />
|
|
89
63
|
{/if}
|
|
90
64
|
{/each}
|
|
91
65
|
</GroupMultiple>
|
package/dist/marks/BarY.svelte
CHANGED
|
@@ -6,40 +6,25 @@
|
|
|
6
6
|
import Mark from '../Mark.svelte';
|
|
7
7
|
import { getContext } from 'svelte';
|
|
8
8
|
import { intervalY, stackY, recordizeY, sort } from '../index.js';
|
|
9
|
-
import {
|
|
10
|
-
import { roundedRect } from '../helpers/roundedRect.js';
|
|
11
|
-
import {
|
|
12
|
-
type PlotContext,
|
|
13
|
-
type BaseMarkProps,
|
|
14
|
-
type ChannelAccessor,
|
|
15
|
-
type DataRow
|
|
16
|
-
} from '../types.js';
|
|
9
|
+
import type { PlotContext, BaseMarkProps, BaseRectMarkProps } from '../types.js';
|
|
17
10
|
import type { StackOptions } from '../transforms/stack.js';
|
|
18
|
-
import { maybeData } from '../helpers/index.js';
|
|
19
|
-
import { addEventHandlers } from './helpers/events.js';
|
|
20
11
|
import GroupMultiple from './helpers/GroupMultiple.svelte';
|
|
12
|
+
import RectPath from './helpers/RectPath.svelte';
|
|
21
13
|
|
|
22
|
-
type BarYProps = BaseMarkProps &
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
| {
|
|
37
|
-
topLeft?: number;
|
|
38
|
-
topRight?: number;
|
|
39
|
-
bottomRight?: number;
|
|
40
|
-
bottomLeft?: number;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
14
|
+
type BarYProps = BaseMarkProps &
|
|
15
|
+
BaseRectMarkProps & {
|
|
16
|
+
data: DataRow[];
|
|
17
|
+
x?: ChannelAccessor;
|
|
18
|
+
y?: ChannelAccessor;
|
|
19
|
+
y1?: ChannelAccessor;
|
|
20
|
+
y2?: ChannelAccessor;
|
|
21
|
+
stack?: StackOptions;
|
|
22
|
+
/**
|
|
23
|
+
* Converts y into y1/y2 ranges based on the provided interval. Disables the
|
|
24
|
+
* implicit stacking
|
|
25
|
+
*/
|
|
26
|
+
interval?: number | string;
|
|
27
|
+
};
|
|
43
28
|
|
|
44
29
|
let { data = [{}], class: className = null, stack, ...options }: BarYProps = $props();
|
|
45
30
|
|
|
@@ -63,39 +48,23 @@
|
|
|
63
48
|
requiredScales={{ x: ['band'] }}
|
|
64
49
|
channels={['x', 'y1', 'y2', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
|
|
65
50
|
{...args}>
|
|
66
|
-
{#snippet children({
|
|
51
|
+
{#snippet children({ scaledData, usedScales })}
|
|
67
52
|
<GroupMultiple class="bar-y" length={scaledData.length}>
|
|
68
53
|
{#each scaledData as d}
|
|
69
54
|
{@const bw = plot.scales.x.fn.bandwidth()}
|
|
70
55
|
{@const miny = Math.min(d.y1, d.y2)}
|
|
71
56
|
{@const maxy = Math.max(d.y1, d.y2)}
|
|
72
|
-
{@const insetLeft = resolveProp(args.insetLeft || args.inset, d.datum, 0)}
|
|
73
|
-
{@const insetRight = resolveProp(args.insetRight || args.inset, d.datum, 0)}
|
|
74
|
-
{@const insetTop = resolveProp(args.insetTop, d.datum, 0)}
|
|
75
|
-
{@const insetBottom = resolveProp(args.insetBottom, d.datum, 0)}
|
|
76
|
-
{@const dx = resolveProp(args.dx, d.datum, 0)}
|
|
77
|
-
{@const dy = resolveProp(args.dy, d.datum, 0)}
|
|
78
57
|
{#if d.valid}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
{style}
|
|
90
|
-
transform="translate({[
|
|
91
|
-
d.x + insetLeft + dx - bw * 0.5,
|
|
92
|
-
miny + dy + insetTop
|
|
93
|
-
]})"
|
|
94
|
-
use:addEventHandlers={{
|
|
95
|
-
getPlotState,
|
|
96
|
-
options: args,
|
|
97
|
-
datum: d.datum
|
|
98
|
-
}} />
|
|
58
|
+
<RectPath
|
|
59
|
+
x={d.x - bw * 0.5}
|
|
60
|
+
y={miny}
|
|
61
|
+
options={args}
|
|
62
|
+
class={className}
|
|
63
|
+
width={bw}
|
|
64
|
+
height={maxy - miny}
|
|
65
|
+
datum={d}
|
|
66
|
+
{usedScales}
|
|
67
|
+
useInsetAsFallbackVertically={false} />
|
|
99
68
|
{/if}
|
|
100
69
|
{/each}
|
|
101
70
|
</GroupMultiple>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { BaseMarkProps, BaseRectMarkProps } from '../types.js';
|
|
2
2
|
import type { StackOptions } from '../transforms/stack.js';
|
|
3
|
-
type BarYProps = BaseMarkProps & {
|
|
3
|
+
type BarYProps = BaseMarkProps & BaseRectMarkProps & {
|
|
4
4
|
data: DataRow[];
|
|
5
5
|
x?: ChannelAccessor;
|
|
6
6
|
y?: ChannelAccessor;
|
|
@@ -12,12 +12,6 @@ type BarYProps = BaseMarkProps & {
|
|
|
12
12
|
* implicit stacking
|
|
13
13
|
*/
|
|
14
14
|
interval?: number | string;
|
|
15
|
-
borderRadius?: number | {
|
|
16
|
-
topLeft?: number;
|
|
17
|
-
topRight?: number;
|
|
18
|
-
bottomRight?: number;
|
|
19
|
-
bottomLeft?: number;
|
|
20
|
-
};
|
|
21
15
|
};
|
|
22
16
|
/** For vertical column charts using a band scale as x axis */
|
|
23
17
|
declare const BarY: import("svelte").Component<BarYProps, {}, "">;
|
package/dist/marks/Cell.svelte
CHANGED
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
import Mark from '../Mark.svelte';
|
|
7
7
|
import { getContext } from 'svelte';
|
|
8
8
|
import { recordizeY, sort } from '../index.js';
|
|
9
|
-
import {
|
|
10
|
-
import { resolveChannel, resolveProp, resolveStyles } from '../helpers/resolve.js';
|
|
11
|
-
import { coalesce, maybeNumber } from '../helpers/index.js';
|
|
9
|
+
import { resolveChannel } from '../helpers/resolve.js';
|
|
12
10
|
import type {
|
|
13
11
|
PlotContext,
|
|
14
12
|
DataRecord,
|
|
@@ -17,7 +15,7 @@
|
|
|
17
15
|
ChannelAccessor
|
|
18
16
|
} from '../types.js';
|
|
19
17
|
import { isValid } from '../helpers/isValid.js';
|
|
20
|
-
import
|
|
18
|
+
import RectPath from './helpers/RectPath.svelte';
|
|
21
19
|
|
|
22
20
|
type CellProps = BaseMarkProps & {
|
|
23
21
|
data: DataRecord[];
|
|
@@ -59,43 +57,21 @@
|
|
|
59
57
|
requiredScales={{ x: ['band'], y: ['band'] }}
|
|
60
58
|
channels={['x', 'y', 'fill', 'stroke', 'opacity', 'fillOpacity', 'strokeOpacity']}
|
|
61
59
|
{...args}>
|
|
62
|
-
{#snippet children({
|
|
60
|
+
{#snippet children({ scaledData, usedScales })}
|
|
63
61
|
{@const bwx = plot.scales.x.fn.bandwidth()}
|
|
64
62
|
{@const bwy = plot.scales.y.fn.bandwidth()}
|
|
65
63
|
<g class="cell {className || ''}" data-fill={usedScales.fillOpacity}>
|
|
66
64
|
{#each scaledData as d}
|
|
67
|
-
{@const inset = resolveProp(args.inset, d.datum, 0)}
|
|
68
|
-
{@const insetLeft = resolveProp(args.insetLeft, d.datum)}
|
|
69
|
-
{@const insetRight = resolveProp(args.insetRight, d.datum)}
|
|
70
|
-
{@const insetTop = resolveProp(args.insetTop, d.datum)}
|
|
71
|
-
{@const insetBottom = resolveProp(args.insetBottom, d.datum)}
|
|
72
|
-
{@const dx = resolveProp(args.dx, d.datum, 0)}
|
|
73
|
-
{@const dy = resolveProp(args.dy, d.datum, 0)}
|
|
74
|
-
{@const insetL = maybeNumber(coalesce(insetLeft, inset, 0))}
|
|
75
|
-
{@const insetT = maybeNumber(coalesce(insetTop, inset, 0))}
|
|
76
|
-
{@const insetR = maybeNumber(coalesce(insetRight, inset, 0))}
|
|
77
|
-
{@const insetB = maybeNumber(coalesce(insetBottom, inset, 0))}
|
|
78
65
|
{#if d.valid && (args.fill == null || isValid(resolveChannel('fill', d.datum, args)))}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class={[styleClass]}
|
|
89
|
-
{style}
|
|
90
|
-
transform="translate({[
|
|
91
|
-
d.x + insetL + dx - bwx * 0.5,
|
|
92
|
-
d.y + insetT + dy - bwy * 0.5
|
|
93
|
-
]})"
|
|
94
|
-
use:addEventHandlers={{
|
|
95
|
-
getPlotState,
|
|
96
|
-
options: args,
|
|
97
|
-
datum: d.datum
|
|
98
|
-
}} />
|
|
66
|
+
<RectPath
|
|
67
|
+
datum={d}
|
|
68
|
+
class={className}
|
|
69
|
+
{usedScales}
|
|
70
|
+
options={args}
|
|
71
|
+
x={d.x - bwx * 0.5}
|
|
72
|
+
y={d.y - bwy * 0.5}
|
|
73
|
+
width={bwx}
|
|
74
|
+
height={bwy} />
|
|
99
75
|
{/if}
|
|
100
76
|
{/each}
|
|
101
77
|
</g>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { getContext } from 'svelte';
|
|
3
3
|
import { Plot, AxisX, Frame } from '../index.js';
|
|
4
4
|
import { symbol as d3Symbol, symbol } from 'd3-shape';
|
|
5
|
-
import { range as d3Range } from 'd3-array';
|
|
5
|
+
import { range as d3Range, extent } from 'd3-array';
|
|
6
6
|
import { maybeSymbol } from '../helpers/symbols.js';
|
|
7
7
|
|
|
8
8
|
import type { DefaultOptions, PlotContext } from '../types.js';
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
</div>
|
|
73
73
|
{/each}
|
|
74
74
|
{:else if scaleType === 'quantile' || scaleType === 'quantize' || scaleType === 'threshold'}
|
|
75
|
-
{@const domain = plot.scales.color.domain}
|
|
75
|
+
{@const domain = extent(plot.scales.color.fn.domain())}
|
|
76
76
|
{@const range = plot.scales.color.range}
|
|
77
77
|
{@const tickLabels =
|
|
78
78
|
scaleType === 'quantile'
|
|
@@ -85,7 +85,6 @@
|
|
|
85
85
|
domain[1],
|
|
86
86
|
(domain[1] - domain[0]) / range.length
|
|
87
87
|
).slice(1)}
|
|
88
|
-
|
|
89
88
|
<Plot
|
|
90
89
|
maxWidth="240px"
|
|
91
90
|
margins={1}
|
|
@@ -112,16 +111,13 @@
|
|
|
112
111
|
</linearGradient>
|
|
113
112
|
</defs>
|
|
114
113
|
<Frame dy={-5} stroke={null} fill="url(#gradient-{randId})" />
|
|
115
|
-
<AxisX tickSize={18} dy={-17} />
|
|
114
|
+
<AxisX tickSize={18} dy={-17} tickFormat={(d, i) => tickFormat(tickLabels[i])} />
|
|
116
115
|
</Plot>
|
|
117
116
|
{:else}
|
|
118
117
|
<!--- continuous -->
|
|
119
|
-
{@const domain = plot.scales.color.domain}
|
|
120
|
-
{@const ticks =
|
|
121
|
-
|
|
122
|
-
...(plot.scales.color?.fn?.ticks?.(Math.ceil(width / 5)) ?? []),
|
|
123
|
-
domain[1]
|
|
124
|
-
])}
|
|
118
|
+
{@const domain = extent(plot.scales.color.domain)}
|
|
119
|
+
{@const ticks = d3Range(domain[0], domain[1], (domain[1] - domain[0]) / 7).slice(1)}
|
|
120
|
+
|
|
125
121
|
<Plot
|
|
126
122
|
maxWidth="240px"
|
|
127
123
|
margins={1}
|
package/dist/marks/Dot.svelte
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
}: DotProps = $props();
|
|
54
54
|
|
|
55
55
|
const { getPlotState } = getContext<PlotContext>('svelteplot');
|
|
56
|
-
|
|
56
|
+
const plot = $derived(getPlotState());
|
|
57
57
|
|
|
58
58
|
function getSymbolPath(symbolType, size) {
|
|
59
59
|
return d3Symbol(maybeSymbol(symbolType), size)();
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
{#snippet children({ mark, usedScales, scaledData })}
|
|
97
97
|
<g class="dots {className || ''}">
|
|
98
98
|
{#if canvas}
|
|
99
|
-
<DotCanvas data={
|
|
99
|
+
<DotCanvas data={scaledData} {mark} />
|
|
100
100
|
{:else}
|
|
101
101
|
{#each scaledData as d}
|
|
102
102
|
{#if d.valid && isValid(d.r)}
|