layerchart 0.79.4 → 0.81.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/components/Brush.svelte +42 -45
- package/dist/components/Brush.svelte.d.ts +15 -15
- package/dist/components/ChartClipPath.svelte +4 -0
- package/dist/components/ChartClipPath.svelte.d.ts +1 -0
- package/dist/components/CircleClipPath.svelte +4 -1
- package/dist/components/RectClipPath.svelte +4 -1
- package/dist/components/charts/AreaChart.svelte +54 -13
- package/dist/components/charts/BarChart.svelte +4 -1
- package/dist/components/charts/LineChart.svelte +52 -11
- package/dist/components/charts/PieChart.svelte +2 -0
- package/dist/components/charts/PieChart.svelte.d.ts +1 -0
- package/dist/components/charts/ScatterChart.svelte +48 -7
- package/dist/utils/types.d.ts +4 -0
- package/dist/utils/types.js +4 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { type ComponentProps } from 'svelte';
|
|
3
3
|
import type { SVGAttributes } from 'svelte/elements';
|
|
4
4
|
import { extent, min, max } from 'd3-array';
|
|
5
5
|
import { clamp } from '@layerstack/utils';
|
|
@@ -12,15 +12,11 @@
|
|
|
12
12
|
import Text from './Text.svelte';
|
|
13
13
|
|
|
14
14
|
import { localPoint } from '../utils/event.js';
|
|
15
|
+
import type { DomainType } from '../utils/scales.js';
|
|
16
|
+
import { asAny } from '../utils/types.js';
|
|
15
17
|
|
|
16
18
|
const { xScale, yScale, width, height, padding } = chartContext();
|
|
17
19
|
|
|
18
|
-
const dispatch = createEventDispatcher<{
|
|
19
|
-
change: { xDomain?: [any, any]; yDomain?: [any, any] };
|
|
20
|
-
brushStart: { xDomain?: [any, any]; yDomain?: [any, any] };
|
|
21
|
-
brushEnd: { xDomain?: [any, any]; yDomain?: [any, any] };
|
|
22
|
-
}>();
|
|
23
|
-
|
|
24
20
|
/** Axis to apply brushing */
|
|
25
21
|
export let axis: 'x' | 'y' | 'both' = 'x';
|
|
26
22
|
|
|
@@ -30,14 +26,8 @@
|
|
|
30
26
|
/** Only show range while actively brushing. Useful with `brushEnd` event */
|
|
31
27
|
export let resetOnEnd = false;
|
|
32
28
|
|
|
33
|
-
export let xDomain:
|
|
34
|
-
|
|
35
|
-
number,
|
|
36
|
-
];
|
|
37
|
-
export let yDomain: [number | Date | null, number | Date | null] = $yScale.domain() as [
|
|
38
|
-
number,
|
|
39
|
-
number,
|
|
40
|
-
];
|
|
29
|
+
export let xDomain: DomainType = $xScale.domain() as [number, number];
|
|
30
|
+
export let yDomain: DomainType = $yScale.domain() as [number, number];
|
|
41
31
|
|
|
42
32
|
export let labels: ComponentProps<Text> | boolean = false;
|
|
43
33
|
|
|
@@ -65,6 +55,10 @@
|
|
|
65
55
|
labels?: string;
|
|
66
56
|
} = {};
|
|
67
57
|
|
|
58
|
+
export let onChange: (e: { xDomain?: DomainType; yDomain?: DomainType }) => void = () => {};
|
|
59
|
+
export let onBrushStart: (e: { xDomain?: DomainType; yDomain?: DomainType }) => void = () => {};
|
|
60
|
+
export let onBrushEnd: (e: { xDomain?: DomainType; yDomain?: DomainType }) => void = () => {};
|
|
61
|
+
|
|
68
62
|
let frameEl: SVGRectElement;
|
|
69
63
|
|
|
70
64
|
function handler(
|
|
@@ -79,15 +73,15 @@
|
|
|
79
73
|
) {
|
|
80
74
|
return (e: PointerEvent) => {
|
|
81
75
|
const start = {
|
|
82
|
-
xDomain: [xDomain[0] ?? xDomainMin, xDomain[1] ?? xDomainMax] as [number, number],
|
|
83
|
-
yDomain: [yDomain[0] ?? yDomainMin, yDomain[1] ?? yDomainMax] as [number, number],
|
|
76
|
+
xDomain: [xDomain?.[0] ?? xDomainMin, xDomain?.[1] ?? xDomainMax] as [number, number],
|
|
77
|
+
yDomain: [yDomain?.[0] ?? yDomainMin, yDomain?.[1] ?? yDomainMax] as [number, number],
|
|
84
78
|
value: {
|
|
85
79
|
x: $xScale.invert?.((localPoint(frameEl, e)?.x ?? 0) - $padding.left),
|
|
86
80
|
y: $yScale.invert?.((localPoint(frameEl, e)?.y ?? 0) - $padding.top),
|
|
87
81
|
},
|
|
88
82
|
};
|
|
89
83
|
|
|
90
|
-
|
|
84
|
+
onBrushStart({ xDomain, yDomain });
|
|
91
85
|
|
|
92
86
|
const onPointerMove = (e: PointerEvent) => {
|
|
93
87
|
fn(start, {
|
|
@@ -99,17 +93,17 @@
|
|
|
99
93
|
// // Ignore?
|
|
100
94
|
// // TODO: What about when using `x` or `y` axis?
|
|
101
95
|
// } else {
|
|
102
|
-
|
|
96
|
+
onChange({ xDomain, yDomain });
|
|
103
97
|
// }
|
|
104
98
|
};
|
|
105
99
|
|
|
106
100
|
const onPointerUp = (e: PointerEvent) => {
|
|
107
101
|
if (e.target === frameEl) {
|
|
108
102
|
reset();
|
|
109
|
-
|
|
103
|
+
onChange({ xDomain, yDomain });
|
|
110
104
|
}
|
|
111
105
|
|
|
112
|
-
|
|
106
|
+
onBrushEnd({ xDomain, yDomain });
|
|
113
107
|
|
|
114
108
|
if (resetOnEnd) {
|
|
115
109
|
reset();
|
|
@@ -208,10 +202,10 @@
|
|
|
208
202
|
yDomain = [yDomainMin, yDomainMax];
|
|
209
203
|
}
|
|
210
204
|
|
|
211
|
-
$: top = $yScale(yDomain[1]);
|
|
212
|
-
$: bottom = $yScale(yDomain[0]);
|
|
213
|
-
$: left = $xScale(xDomain[0]);
|
|
214
|
-
$: right = $xScale(xDomain[1]);
|
|
205
|
+
$: top = $yScale(yDomain?.[1]);
|
|
206
|
+
$: bottom = $yScale(yDomain?.[0]);
|
|
207
|
+
$: left = $xScale(xDomain?.[0]);
|
|
208
|
+
$: right = $xScale(xDomain?.[1]);
|
|
215
209
|
|
|
216
210
|
$: rangeTop = axis === 'both' || axis === 'y' ? top : 0;
|
|
217
211
|
$: rangeLeft = axis === 'both' || axis === 'x' ? left : 0;
|
|
@@ -220,15 +214,10 @@
|
|
|
220
214
|
|
|
221
215
|
// Set reactively to handle cases where xDomain/yDomain are set externally (ex. `bind:xDomain`)
|
|
222
216
|
$: isActive =
|
|
223
|
-
xDomain[0]?.valueOf() !== originalXDomain[0]?.valueOf() ||
|
|
224
|
-
xDomain[1]?.valueOf() !== originalXDomain[1]?.valueOf() ||
|
|
225
|
-
yDomain[0]?.valueOf() !== originalYDomain[0]?.valueOf() ||
|
|
226
|
-
yDomain[1]?.valueOf() !== originalYDomain[1]?.valueOf();
|
|
227
|
-
|
|
228
|
-
/** TODO: Fix types and remove workaround (Svelte 5)*/
|
|
229
|
-
function any(value: any): any {
|
|
230
|
-
return value;
|
|
231
|
-
}
|
|
217
|
+
xDomain?.[0]?.valueOf() !== originalXDomain[0]?.valueOf() ||
|
|
218
|
+
xDomain?.[1]?.valueOf() !== originalXDomain[1]?.valueOf() ||
|
|
219
|
+
yDomain?.[0]?.valueOf() !== originalYDomain[0]?.valueOf() ||
|
|
220
|
+
yDomain?.[1]?.valueOf() !== originalYDomain[1]?.valueOf();
|
|
232
221
|
</script>
|
|
233
222
|
|
|
234
223
|
<g class={cls('Brush select-none', classes.root, $$props.class)}>
|
|
@@ -265,8 +254,10 @@
|
|
|
265
254
|
class="handle top"
|
|
266
255
|
on:pointerdown={adjustTop}
|
|
267
256
|
on:dblclick={() => {
|
|
268
|
-
yDomain
|
|
269
|
-
|
|
257
|
+
if (yDomain) {
|
|
258
|
+
yDomain[0] = yDomainMin;
|
|
259
|
+
onChange({ xDomain, yDomain });
|
|
260
|
+
}
|
|
270
261
|
}}
|
|
271
262
|
>
|
|
272
263
|
<slot name="handle" edge="top" {rangeWidth} {rangeHeight}>
|
|
@@ -285,7 +276,9 @@
|
|
|
285
276
|
class="handle bottom"
|
|
286
277
|
on:pointerdown={adjustBottom}
|
|
287
278
|
on:dblclick={() => {
|
|
288
|
-
yDomain
|
|
279
|
+
if (yDomain) {
|
|
280
|
+
yDomain[1] = yDomainMax;
|
|
281
|
+
}
|
|
289
282
|
}}
|
|
290
283
|
>
|
|
291
284
|
<slot name="handle" edge="bottom" {rangeWidth} {rangeHeight}>
|
|
@@ -306,8 +299,10 @@
|
|
|
306
299
|
class="handle left"
|
|
307
300
|
on:pointerdown={adjustLeft}
|
|
308
301
|
on:dblclick={() => {
|
|
309
|
-
xDomain
|
|
310
|
-
|
|
302
|
+
if (xDomain) {
|
|
303
|
+
xDomain[0] = xDomainMin;
|
|
304
|
+
onChange({ xDomain, yDomain });
|
|
305
|
+
}
|
|
311
306
|
}}
|
|
312
307
|
>
|
|
313
308
|
<slot name="handle" edge="left" {rangeWidth} {rangeHeight}>
|
|
@@ -326,8 +321,10 @@
|
|
|
326
321
|
class="handle right"
|
|
327
322
|
on:pointerdown={adjustRight}
|
|
328
323
|
on:dblclick={() => {
|
|
329
|
-
xDomain
|
|
330
|
-
|
|
324
|
+
if (xDomain) {
|
|
325
|
+
xDomain[1] = xDomainMax;
|
|
326
|
+
onChange({ xDomain, yDomain });
|
|
327
|
+
}
|
|
331
328
|
}}
|
|
332
329
|
>
|
|
333
330
|
<slot name="handle" edge="right" {rangeWidth} {rangeHeight}>
|
|
@@ -356,7 +353,7 @@
|
|
|
356
353
|
dx={-4}
|
|
357
354
|
textAnchor="end"
|
|
358
355
|
verticalAnchor="middle"
|
|
359
|
-
value={formatValue(
|
|
356
|
+
value={formatValue(asAny(xDomain?.[0]), format)}
|
|
360
357
|
{...typeof labels === 'object' ? labels : null}
|
|
361
358
|
class={labelClass}
|
|
362
359
|
/>
|
|
@@ -367,7 +364,7 @@
|
|
|
367
364
|
dx={4}
|
|
368
365
|
textAnchor="start"
|
|
369
366
|
verticalAnchor="middle"
|
|
370
|
-
value={formatValue(
|
|
367
|
+
value={formatValue(asAny(xDomain?.[1]), format)}
|
|
371
368
|
{...typeof labels === 'object' ? labels : null}
|
|
372
369
|
class={labelClass}
|
|
373
370
|
/>
|
|
@@ -380,7 +377,7 @@
|
|
|
380
377
|
dy={-4}
|
|
381
378
|
textAnchor="middle"
|
|
382
379
|
verticalAnchor="end"
|
|
383
|
-
value={formatValue(
|
|
380
|
+
value={formatValue(asAny(yDomain?.[1]), format)}
|
|
384
381
|
{...typeof labels === 'object' ? labels : null}
|
|
385
382
|
class={labelClass}
|
|
386
383
|
/>
|
|
@@ -391,7 +388,7 @@
|
|
|
391
388
|
dy={4}
|
|
392
389
|
textAnchor="middle"
|
|
393
390
|
verticalAnchor="start"
|
|
394
|
-
value={formatValue(
|
|
391
|
+
value={formatValue(asAny(yDomain?.[0]), format)}
|
|
395
392
|
{...typeof labels === 'object' ? labels : null}
|
|
396
393
|
class={labelClass}
|
|
397
394
|
/>
|
|
@@ -3,14 +3,15 @@ import { type ComponentProps } from 'svelte';
|
|
|
3
3
|
import type { SVGAttributes } from 'svelte/elements';
|
|
4
4
|
import { type FormatType } from '@layerstack/utils';
|
|
5
5
|
import Text from './Text.svelte';
|
|
6
|
+
import type { DomainType } from '../utils/scales.js';
|
|
6
7
|
declare const __propDef: {
|
|
7
8
|
props: {
|
|
8
9
|
[x: string]: any;
|
|
9
10
|
axis?: "x" | "y" | "both" | undefined;
|
|
10
11
|
handleSize?: number | undefined;
|
|
11
12
|
resetOnEnd?: boolean | undefined;
|
|
12
|
-
xDomain?:
|
|
13
|
-
yDomain?:
|
|
13
|
+
xDomain?: DomainType | undefined;
|
|
14
|
+
yDomain?: DomainType | undefined;
|
|
14
15
|
labels?: (ComponentProps<Text> | boolean) | undefined;
|
|
15
16
|
range?: SVGAttributes<SVGRectElement> | undefined;
|
|
16
17
|
handle?: SVGAttributes<SVGRectElement> | undefined;
|
|
@@ -22,21 +23,20 @@ declare const __propDef: {
|
|
|
22
23
|
handle?: string;
|
|
23
24
|
labels?: string;
|
|
24
25
|
} | undefined;
|
|
26
|
+
onChange?: ((e: {
|
|
27
|
+
xDomain?: DomainType;
|
|
28
|
+
yDomain?: DomainType;
|
|
29
|
+
}) => void) | undefined;
|
|
30
|
+
onBrushStart?: ((e: {
|
|
31
|
+
xDomain?: DomainType;
|
|
32
|
+
yDomain?: DomainType;
|
|
33
|
+
}) => void) | undefined;
|
|
34
|
+
onBrushEnd?: ((e: {
|
|
35
|
+
xDomain?: DomainType;
|
|
36
|
+
yDomain?: DomainType;
|
|
37
|
+
}) => void) | undefined;
|
|
25
38
|
};
|
|
26
39
|
events: {
|
|
27
|
-
change: CustomEvent<{
|
|
28
|
-
xDomain?: [any, any];
|
|
29
|
-
yDomain?: [any, any];
|
|
30
|
-
}>;
|
|
31
|
-
brushStart: CustomEvent<{
|
|
32
|
-
xDomain?: [any, any];
|
|
33
|
-
yDomain?: [any, any];
|
|
34
|
-
}>;
|
|
35
|
-
brushEnd: CustomEvent<{
|
|
36
|
-
xDomain?: [any, any];
|
|
37
|
-
yDomain?: [any, any];
|
|
38
|
-
}>;
|
|
39
|
-
} & {
|
|
40
40
|
[evt: string]: CustomEvent<any>;
|
|
41
41
|
};
|
|
42
42
|
slots: {
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
/** Include padding area (ex. axis) */
|
|
8
8
|
export let full = false;
|
|
9
|
+
|
|
10
|
+
/** Disable clipping (show all) */
|
|
11
|
+
export let disabled: boolean = false;
|
|
9
12
|
</script>
|
|
10
13
|
|
|
11
14
|
<RectClipPath
|
|
@@ -13,6 +16,7 @@
|
|
|
13
16
|
y={full && $padding.top ? -$padding.top : 0}
|
|
14
17
|
width={$width + (full ? ($padding?.left ?? 0) + ($padding?.right ?? 0) : 0)}
|
|
15
18
|
height={$height + (full ? ($padding?.top ?? 0) + ($padding?.bottom ?? 0) : 0)}
|
|
19
|
+
{disabled}
|
|
16
20
|
on:click
|
|
17
21
|
{...$$restProps}
|
|
18
22
|
>
|
|
@@ -14,9 +14,12 @@
|
|
|
14
14
|
export let r: number;
|
|
15
15
|
export let spring: boolean | Parameters<typeof springStore>[1] = undefined;
|
|
16
16
|
export let tweened: boolean | Parameters<typeof tweenedStore>[1] = undefined;
|
|
17
|
+
|
|
18
|
+
/** Disable clipping (show all) */
|
|
19
|
+
export let disabled: boolean = false;
|
|
17
20
|
</script>
|
|
18
21
|
|
|
19
|
-
<ClipPath {id} let:url>
|
|
22
|
+
<ClipPath {id} {disabled} let:url>
|
|
20
23
|
<Circle slot="clip" {cx} {cy} {r} {spring} {tweened} {...$$restProps} />
|
|
21
24
|
<slot {id} {url} />
|
|
22
25
|
</ClipPath>
|
|
@@ -14,9 +14,12 @@
|
|
|
14
14
|
export let height: number;
|
|
15
15
|
export let spring: ComponentProps<Rect>['spring'] = undefined;
|
|
16
16
|
export let tweened: ComponentProps<Rect>['tweened'] = undefined;
|
|
17
|
+
|
|
18
|
+
/** Disable clipping (show all) */
|
|
19
|
+
export let disabled: boolean = false;
|
|
17
20
|
</script>
|
|
18
21
|
|
|
19
|
-
<ClipPath {id} let:url>
|
|
22
|
+
<ClipPath {id} {disabled} let:url>
|
|
20
23
|
<Rect slot="clip" {x} {y} {width} {height} {spring} {tweened} {...$$restProps} />
|
|
21
24
|
<slot {id} {url} />
|
|
22
25
|
</ClipPath>
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
import Area from '../Area.svelte';
|
|
11
11
|
import Axis from '../Axis.svelte';
|
|
12
|
+
import Brush from '../Brush.svelte';
|
|
12
13
|
import Canvas from '../layout/Canvas.svelte';
|
|
13
14
|
import Chart from '../Chart.svelte';
|
|
15
|
+
import ChartClipPath from '../ChartClipPath.svelte';
|
|
14
16
|
import Grid from '../Grid.svelte';
|
|
15
17
|
import Highlight, { type HighlightPointData } from '../Highlight.svelte';
|
|
16
18
|
import Labels from '../Labels.svelte';
|
|
@@ -32,6 +34,7 @@
|
|
|
32
34
|
|
|
33
35
|
interface $$Props extends ComponentProps<Chart<TData>> {
|
|
34
36
|
axis?: typeof axis;
|
|
37
|
+
brush?: typeof brush;
|
|
35
38
|
grid?: typeof grid;
|
|
36
39
|
labels?: typeof labels;
|
|
37
40
|
legend?: typeof legend;
|
|
@@ -50,6 +53,9 @@
|
|
|
50
53
|
export let x: Accessor<TData> = undefined;
|
|
51
54
|
export let y: Accessor<TData> = undefined;
|
|
52
55
|
|
|
56
|
+
/** Set xDomain. Useful for external brush control */
|
|
57
|
+
export let xDomain: ComponentProps<typeof Brush>['xDomain'] = undefined;
|
|
58
|
+
|
|
53
59
|
/** Use radial instead of cartesian coordinates, mapping `x` to `angle` and `y`` to radial. Radial lines are positioned relative to the origin, use transform (ex. `<Group center>`) to change the origin */
|
|
54
60
|
export let radial = false;
|
|
55
61
|
|
|
@@ -69,11 +75,12 @@
|
|
|
69
75
|
$: stackSeries = seriesLayout.startsWith('stack');
|
|
70
76
|
|
|
71
77
|
export let axis: ComponentProps<Axis> | 'x' | 'y' | boolean = true;
|
|
78
|
+
export let brush: ({ mode: 'integrated' } & ComponentProps<Brush>) | false = false;
|
|
72
79
|
export let grid: ComponentProps<Grid> | boolean = true;
|
|
73
|
-
export let rule: ComponentProps<Rule> | boolean = true;
|
|
74
80
|
export let labels: ComponentProps<Labels> | boolean = false;
|
|
75
81
|
export let legend: ComponentProps<Legend> | boolean = false;
|
|
76
82
|
export let points: ComponentProps<Points> | boolean = false;
|
|
83
|
+
export let rule: ComponentProps<Rule> | boolean = true;
|
|
77
84
|
|
|
78
85
|
/** Event dispatched with current tooltip data */
|
|
79
86
|
export let onTooltipClick: (e: { data: any }) => void = () => {};
|
|
@@ -85,23 +92,25 @@
|
|
|
85
92
|
}) => void = () => {};
|
|
86
93
|
|
|
87
94
|
export let props: {
|
|
88
|
-
xAxis?: Partial<ComponentProps<Axis>>;
|
|
89
|
-
yAxis?: Partial<ComponentProps<Axis>>;
|
|
90
|
-
grid?: Partial<ComponentProps<Grid>>;
|
|
91
|
-
rule?: Partial<ComponentProps<Rule>>;
|
|
92
95
|
area?: Partial<ComponentProps<Area>>;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
points?: Partial<ComponentProps<Points>>;
|
|
96
|
+
brush?: Partial<ComponentProps<Brush>>;
|
|
97
|
+
grid?: Partial<ComponentProps<Grid>>;
|
|
96
98
|
highlight?: Partial<ComponentProps<Highlight>>;
|
|
97
99
|
labels?: Partial<ComponentProps<Labels>>;
|
|
100
|
+
legend?: Partial<ComponentProps<Legend>>;
|
|
101
|
+
line?: Partial<ComponentProps<Line>>;
|
|
102
|
+
points?: Partial<ComponentProps<Points>>;
|
|
103
|
+
rule?: Partial<ComponentProps<Rule>>;
|
|
98
104
|
tooltip?: {
|
|
105
|
+
context?: Partial<ComponentProps<Tooltip.Context>>;
|
|
99
106
|
root?: Partial<ComponentProps<Tooltip.Root>>;
|
|
100
107
|
header?: Partial<ComponentProps<Tooltip.Header>>;
|
|
101
108
|
list?: Partial<ComponentProps<Tooltip.List>>;
|
|
102
109
|
item?: Partial<ComponentProps<Tooltip.Item>>;
|
|
103
110
|
separator?: Partial<ComponentProps<Tooltip.Separator>>;
|
|
104
111
|
};
|
|
112
|
+
xAxis?: Partial<ComponentProps<Axis>>;
|
|
113
|
+
yAxis?: Partial<ComponentProps<Axis>>;
|
|
105
114
|
} = {};
|
|
106
115
|
|
|
107
116
|
export let renderContext: 'svg' | 'canvas' = 'svg';
|
|
@@ -250,6 +259,7 @@
|
|
|
250
259
|
<Chart
|
|
251
260
|
data={chartData}
|
|
252
261
|
{x}
|
|
262
|
+
{xDomain}
|
|
253
263
|
{xScale}
|
|
254
264
|
y={y ??
|
|
255
265
|
(stackSeries
|
|
@@ -260,7 +270,14 @@
|
|
|
260
270
|
{radial}
|
|
261
271
|
padding={radial ? undefined : defaultChartPadding(axis, legend)}
|
|
262
272
|
{...$$restProps}
|
|
263
|
-
tooltip={
|
|
273
|
+
tooltip={$$props.tooltip === false
|
|
274
|
+
? false
|
|
275
|
+
: {
|
|
276
|
+
mode: 'bisect-x',
|
|
277
|
+
onClick: onTooltipClick,
|
|
278
|
+
...props.tooltip?.context,
|
|
279
|
+
...$$props.tooltip,
|
|
280
|
+
}}
|
|
264
281
|
let:x
|
|
265
282
|
let:xScale
|
|
266
283
|
let:y
|
|
@@ -301,9 +318,11 @@
|
|
|
301
318
|
<slot name="belowMarks" {...slotProps} />
|
|
302
319
|
|
|
303
320
|
<slot name="marks" {...slotProps}>
|
|
304
|
-
{
|
|
305
|
-
|
|
306
|
-
|
|
321
|
+
<ChartClipPath disabled={!brush}>
|
|
322
|
+
{#each visibleSeries as s, i (s.key)}
|
|
323
|
+
<Area {...getAreaProps(s, i)} />
|
|
324
|
+
{/each}
|
|
325
|
+
</ChartClipPath>
|
|
307
326
|
</slot>
|
|
308
327
|
|
|
309
328
|
<slot name="aboveMarks" {...slotProps} />
|
|
@@ -354,7 +373,13 @@
|
|
|
354
373
|
<Highlight
|
|
355
374
|
data={seriesTooltipData}
|
|
356
375
|
y={stackSeries ? (d) => d.stackData[i][1] : (s.value ?? (s.data ? undefined : s.key))}
|
|
357
|
-
points={{
|
|
376
|
+
points={{
|
|
377
|
+
fill: s.color,
|
|
378
|
+
class: cls(
|
|
379
|
+
'transition-opacity',
|
|
380
|
+
highlightSeriesKey && highlightSeriesKey !== s.key && 'opacity-10'
|
|
381
|
+
),
|
|
382
|
+
}}
|
|
358
383
|
lines={i == 0}
|
|
359
384
|
onPointClick={(e) => onPointClick({ ...e, series: s })}
|
|
360
385
|
onPointEnter={() => (highlightSeriesKey = s.key)}
|
|
@@ -371,6 +396,22 @@
|
|
|
371
396
|
{/if}
|
|
372
397
|
</svelte:component>
|
|
373
398
|
|
|
399
|
+
{#if brush && brush.mode === 'integrated'}
|
|
400
|
+
<Svg>
|
|
401
|
+
{@const brushProps = { ...(typeof brush === 'object' ? brush : null), ...props.brush }}
|
|
402
|
+
<Brush
|
|
403
|
+
axis="x"
|
|
404
|
+
resetOnEnd
|
|
405
|
+
{xDomain}
|
|
406
|
+
{...brushProps}
|
|
407
|
+
onBrushEnd={(e) => {
|
|
408
|
+
xDomain = e.xDomain;
|
|
409
|
+
brushProps.onBrushEnd?.(e);
|
|
410
|
+
}}
|
|
411
|
+
/>
|
|
412
|
+
</Svg>
|
|
413
|
+
{/if}
|
|
414
|
+
|
|
374
415
|
<slot name="legend" {...slotProps}>
|
|
375
416
|
{#if legend}
|
|
376
417
|
<Legend
|
|
@@ -135,6 +135,7 @@
|
|
|
135
135
|
highlight?: Partial<ComponentProps<Highlight>>;
|
|
136
136
|
labels?: Partial<ComponentProps<Labels>>;
|
|
137
137
|
tooltip?: {
|
|
138
|
+
context?: Partial<ComponentProps<Tooltip.Context>>;
|
|
138
139
|
root?: Partial<ComponentProps<Tooltip.Root>>;
|
|
139
140
|
header?: Partial<ComponentProps<Tooltip.Header>>;
|
|
140
141
|
list?: Partial<ComponentProps<Tooltip.List>>;
|
|
@@ -300,7 +301,9 @@
|
|
|
300
301
|
cRange={['hsl(var(--color-primary))']}
|
|
301
302
|
padding={defaultChartPadding(axis, legend)}
|
|
302
303
|
{...$$restProps}
|
|
303
|
-
tooltip={
|
|
304
|
+
tooltip={$$props.tooltip === false
|
|
305
|
+
? false
|
|
306
|
+
: { mode: 'band', onClick: onTooltipClick, ...props.tooltip?.context, ...$$props.tooltip }}
|
|
304
307
|
let:x
|
|
305
308
|
let:xScale
|
|
306
309
|
let:y
|
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
import { selectionStore } from '@layerstack/svelte-stores';
|
|
7
7
|
|
|
8
8
|
import Axis from '../Axis.svelte';
|
|
9
|
+
import Brush from '../Brush.svelte';
|
|
9
10
|
import Canvas from '../layout/Canvas.svelte';
|
|
10
11
|
import Chart from '../Chart.svelte';
|
|
12
|
+
import ChartClipPath from '../ChartClipPath.svelte';
|
|
11
13
|
import Grid from '../Grid.svelte';
|
|
12
14
|
import Highlight, { type HighlightPointData } from '../Highlight.svelte';
|
|
13
15
|
import Labels from '../Labels.svelte';
|
|
@@ -29,6 +31,7 @@
|
|
|
29
31
|
|
|
30
32
|
interface $$Props extends ComponentProps<Chart<TData>> {
|
|
31
33
|
axis?: typeof axis;
|
|
34
|
+
brush?: typeof brush;
|
|
32
35
|
grid?: typeof grid;
|
|
33
36
|
labels?: typeof labels;
|
|
34
37
|
legend?: typeof legend;
|
|
@@ -46,6 +49,9 @@
|
|
|
46
49
|
export let x: Accessor<TData> = undefined;
|
|
47
50
|
export let y: Accessor<TData> = undefined;
|
|
48
51
|
|
|
52
|
+
/** Set xDomain. Useful for external brush control */
|
|
53
|
+
export let xDomain: ComponentProps<typeof Brush>['xDomain'] = undefined;
|
|
54
|
+
|
|
49
55
|
/** Use radial instead of cartesian coordinates, mapping `x` to `angle` and `y`` to radial. Radial lines are positioned relative to the origin, use transform (ex. `<Group center>`) to change the origin */
|
|
50
56
|
export let radial = false;
|
|
51
57
|
|
|
@@ -61,11 +67,12 @@
|
|
|
61
67
|
$: isDefaultSeries = series.length === 1 && series[0].key === 'default';
|
|
62
68
|
|
|
63
69
|
export let axis: ComponentProps<Axis> | 'x' | 'y' | boolean = true;
|
|
64
|
-
export let
|
|
70
|
+
export let brush: ({ mode: 'integrated' } & ComponentProps<Brush>) | false = false;
|
|
65
71
|
export let grid: ComponentProps<Grid> | boolean = true;
|
|
66
72
|
export let labels: ComponentProps<Labels> | boolean = false;
|
|
67
73
|
export let legend: ComponentProps<Legend> | boolean = false;
|
|
68
74
|
export let points: ComponentProps<Points> | boolean = false;
|
|
75
|
+
export let rule: ComponentProps<Rule> | boolean = true;
|
|
69
76
|
|
|
70
77
|
/** Event dispatched with current tooltip data */
|
|
71
78
|
export let onTooltipClick: (e: { data: any }) => void = () => {};
|
|
@@ -77,22 +84,24 @@
|
|
|
77
84
|
}) => void = () => {};
|
|
78
85
|
|
|
79
86
|
export let props: {
|
|
80
|
-
|
|
81
|
-
yAxis?: Partial<ComponentProps<Axis>>;
|
|
87
|
+
brush?: Partial<ComponentProps<Brush>>;
|
|
82
88
|
grid?: Partial<ComponentProps<Grid>>;
|
|
83
|
-
rule?: Partial<ComponentProps<Rule>>;
|
|
84
|
-
spline?: Partial<ComponentProps<Spline>>;
|
|
85
|
-
legend?: Partial<ComponentProps<Legend>>;
|
|
86
89
|
highlight?: Partial<ComponentProps<Highlight>>;
|
|
87
90
|
labels?: Partial<ComponentProps<Labels>>;
|
|
91
|
+
legend?: Partial<ComponentProps<Legend>>;
|
|
88
92
|
points?: Partial<ComponentProps<Points>>;
|
|
93
|
+
rule?: Partial<ComponentProps<Rule>>;
|
|
94
|
+
spline?: Partial<ComponentProps<Spline>>;
|
|
89
95
|
tooltip?: {
|
|
96
|
+
context?: Partial<ComponentProps<Tooltip.Context>>;
|
|
90
97
|
root?: Partial<ComponentProps<Tooltip.Root>>;
|
|
91
98
|
header?: Partial<ComponentProps<Tooltip.Header>>;
|
|
92
99
|
list?: Partial<ComponentProps<Tooltip.List>>;
|
|
93
100
|
item?: Partial<ComponentProps<Tooltip.Item>>;
|
|
94
101
|
separator?: Partial<ComponentProps<Tooltip.Separator>>;
|
|
95
102
|
};
|
|
103
|
+
xAxis?: Partial<ComponentProps<Axis>>;
|
|
104
|
+
yAxis?: Partial<ComponentProps<Axis>>;
|
|
96
105
|
} = {};
|
|
97
106
|
|
|
98
107
|
export let renderContext: 'svg' | 'canvas' = 'svg';
|
|
@@ -187,6 +196,7 @@
|
|
|
187
196
|
<Chart
|
|
188
197
|
data={chartData}
|
|
189
198
|
{x}
|
|
199
|
+
{xDomain}
|
|
190
200
|
{xScale}
|
|
191
201
|
y={y ?? series.map((s) => s.value ?? s.key)}
|
|
192
202
|
yBaseline={0}
|
|
@@ -194,7 +204,14 @@
|
|
|
194
204
|
{radial}
|
|
195
205
|
padding={radial ? undefined : defaultChartPadding(axis, legend)}
|
|
196
206
|
{...$$restProps}
|
|
197
|
-
tooltip={
|
|
207
|
+
tooltip={$$props.tooltip === false
|
|
208
|
+
? false
|
|
209
|
+
: {
|
|
210
|
+
mode: 'bisect-x',
|
|
211
|
+
onClick: onTooltipClick,
|
|
212
|
+
...props.tooltip?.context,
|
|
213
|
+
...$$props.tooltip,
|
|
214
|
+
}}
|
|
198
215
|
let:x
|
|
199
216
|
let:xScale
|
|
200
217
|
let:y
|
|
@@ -234,9 +251,11 @@
|
|
|
234
251
|
<slot name="belowMarks" {...slotProps} />
|
|
235
252
|
|
|
236
253
|
<slot name="marks" {...slotProps}>
|
|
237
|
-
{
|
|
238
|
-
|
|
239
|
-
|
|
254
|
+
<ChartClipPath disabled={!brush}>
|
|
255
|
+
{#each visibleSeries as s, i (s.key)}
|
|
256
|
+
<Spline {...getSplineProps(s, i)} />
|
|
257
|
+
{/each}
|
|
258
|
+
</ChartClipPath>
|
|
240
259
|
</slot>
|
|
241
260
|
|
|
242
261
|
<slot name="aboveMarks" {...slotProps} />
|
|
@@ -286,7 +305,13 @@
|
|
|
286
305
|
<Highlight
|
|
287
306
|
data={seriesTooltipData}
|
|
288
307
|
y={s.value ?? (s.data ? undefined : s.key)}
|
|
289
|
-
points={{
|
|
308
|
+
points={{
|
|
309
|
+
fill: s.color,
|
|
310
|
+
class: cls(
|
|
311
|
+
'transition-opacity',
|
|
312
|
+
highlightSeriesKey && highlightSeriesKey !== s.key && 'opacity-10'
|
|
313
|
+
),
|
|
314
|
+
}}
|
|
290
315
|
lines={i === 0}
|
|
291
316
|
onPointClick={(e) => onPointClick({ ...e, series: s })}
|
|
292
317
|
onPointEnter={() => (highlightSeriesKey = s.key)}
|
|
@@ -297,6 +322,22 @@
|
|
|
297
322
|
</slot>
|
|
298
323
|
</svelte:component>
|
|
299
324
|
|
|
325
|
+
{#if brush && brush.mode === 'integrated'}
|
|
326
|
+
<Svg>
|
|
327
|
+
{@const brushProps = { ...(typeof brush === 'object' ? brush : null), ...props.brush }}
|
|
328
|
+
<Brush
|
|
329
|
+
axis="x"
|
|
330
|
+
resetOnEnd
|
|
331
|
+
{xDomain}
|
|
332
|
+
{...brushProps}
|
|
333
|
+
onBrushEnd={(e) => {
|
|
334
|
+
xDomain = e.xDomain;
|
|
335
|
+
brushProps.onBrushEnd?.(e);
|
|
336
|
+
}}
|
|
337
|
+
/>
|
|
338
|
+
</Svg>
|
|
339
|
+
{/if}
|
|
340
|
+
|
|
300
341
|
<slot name="legend" {...slotProps}>
|
|
301
342
|
{#if legend}
|
|
302
343
|
<Legend
|
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
arc?: Partial<ComponentProps<Arc>>;
|
|
112
112
|
legend?: Partial<ComponentProps<Legend>>;
|
|
113
113
|
tooltip?: {
|
|
114
|
+
context?: Partial<ComponentProps<Tooltip.Context>>;
|
|
114
115
|
root?: Partial<ComponentProps<Tooltip.Root>>;
|
|
115
116
|
header?: Partial<ComponentProps<Tooltip.Header>>;
|
|
116
117
|
list?: Partial<ComponentProps<Tooltip.List>>;
|
|
@@ -170,6 +171,7 @@
|
|
|
170
171
|
]}
|
|
171
172
|
padding={{ bottom: legend === true ? 32 : 0 }}
|
|
172
173
|
{...$$restProps}
|
|
174
|
+
tooltip={props.tooltip?.context}
|
|
173
175
|
let:x
|
|
174
176
|
let:xScale
|
|
175
177
|
let:y
|
|
@@ -237,6 +237,7 @@ declare class __sveltets_Render<TData> {
|
|
|
237
237
|
arc?: Partial<ComponentProps<Arc>>;
|
|
238
238
|
legend?: Partial<ComponentProps<Legend>>;
|
|
239
239
|
tooltip?: {
|
|
240
|
+
context?: Partial<ComponentProps<Tooltip.Context>>;
|
|
240
241
|
root?: Partial<ComponentProps<Tooltip.Root>>;
|
|
241
242
|
header?: Partial<ComponentProps<Tooltip.Header>>;
|
|
242
243
|
list?: Partial<ComponentProps<Tooltip.List>>;
|
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
import { selectionStore } from '@layerstack/svelte-stores';
|
|
7
7
|
|
|
8
8
|
import Axis from '../Axis.svelte';
|
|
9
|
+
import Brush from '../Brush.svelte';
|
|
9
10
|
import Canvas from '../layout/Canvas.svelte';
|
|
10
11
|
import Chart from '../Chart.svelte';
|
|
12
|
+
import ChartClipPath from '../ChartClipPath.svelte';
|
|
11
13
|
import Grid from '../Grid.svelte';
|
|
12
14
|
import Highlight from '../Highlight.svelte';
|
|
13
15
|
import Labels from '../Labels.svelte';
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
|
|
27
29
|
interface $$Props extends ComponentProps<Chart<TData>> {
|
|
28
30
|
axis?: typeof axis;
|
|
31
|
+
brush?: typeof brush;
|
|
29
32
|
grid?: typeof grid;
|
|
30
33
|
labels?: typeof labels;
|
|
31
34
|
legend?: typeof legend;
|
|
@@ -40,6 +43,11 @@
|
|
|
40
43
|
export let x: Accessor<TData> = undefined;
|
|
41
44
|
export let y: Accessor<TData> = undefined;
|
|
42
45
|
|
|
46
|
+
/** Set xDomain. Useful for external brush control */
|
|
47
|
+
export let xDomain: ComponentProps<typeof Brush>['xDomain'] = undefined;
|
|
48
|
+
/** Set yDomain. Useful for external brush control */
|
|
49
|
+
export let yDomain: ComponentProps<typeof Brush>['yDomain'] = undefined;
|
|
50
|
+
|
|
43
51
|
export let series: {
|
|
44
52
|
key: string;
|
|
45
53
|
label?: string;
|
|
@@ -50,6 +58,7 @@
|
|
|
50
58
|
$: isDefaultSeries = series.length === 1 && series[0].key === 'default';
|
|
51
59
|
|
|
52
60
|
export let axis: ComponentProps<Axis> | 'x' | 'y' | boolean = true;
|
|
61
|
+
export let brush: ({ mode: 'integrated' } & ComponentProps<Brush>) | false = false;
|
|
53
62
|
export let grid: ComponentProps<Grid> | boolean = true;
|
|
54
63
|
export let labels: ComponentProps<Labels> | boolean = false;
|
|
55
64
|
export let legend: ComponentProps<Legend> | boolean = false;
|
|
@@ -59,21 +68,23 @@
|
|
|
59
68
|
export let onTooltipClick: (e: { data: any }) => void = () => {};
|
|
60
69
|
|
|
61
70
|
export let props: {
|
|
62
|
-
|
|
63
|
-
yAxis?: Partial<ComponentProps<Axis>>;
|
|
71
|
+
brush?: Partial<ComponentProps<Brush>>;
|
|
64
72
|
grid?: Partial<ComponentProps<Grid>>;
|
|
65
|
-
points?: Partial<ComponentProps<Points>>;
|
|
66
73
|
highlight?: Partial<ComponentProps<Highlight>>;
|
|
67
74
|
labels?: Partial<ComponentProps<Labels>>;
|
|
68
75
|
legend?: Partial<ComponentProps<Legend>>;
|
|
76
|
+
points?: Partial<ComponentProps<Points>>;
|
|
69
77
|
rule?: Partial<ComponentProps<Rule>>;
|
|
70
78
|
tooltip?: {
|
|
79
|
+
context?: Partial<ComponentProps<Tooltip.Context>>;
|
|
71
80
|
root?: Partial<ComponentProps<Tooltip.Root>>;
|
|
72
81
|
header?: Partial<ComponentProps<Tooltip.Header>>;
|
|
73
82
|
list?: Partial<ComponentProps<Tooltip.List>>;
|
|
74
83
|
item?: Partial<ComponentProps<Tooltip.Item>>;
|
|
75
84
|
separator?: Partial<ComponentProps<Tooltip.Separator>>;
|
|
76
85
|
};
|
|
86
|
+
xAxis?: Partial<ComponentProps<Axis>>;
|
|
87
|
+
yAxis?: Partial<ComponentProps<Axis>>;
|
|
77
88
|
} = {};
|
|
78
89
|
|
|
79
90
|
export let renderContext: 'svg' | 'canvas' = 'svg';
|
|
@@ -152,13 +163,22 @@
|
|
|
152
163
|
<Chart
|
|
153
164
|
data={chartData}
|
|
154
165
|
{x}
|
|
166
|
+
{xDomain}
|
|
155
167
|
{xScale}
|
|
156
168
|
{y}
|
|
169
|
+
{yDomain}
|
|
157
170
|
{yScale}
|
|
158
171
|
yNice
|
|
159
172
|
padding={defaultChartPadding(axis, legend)}
|
|
160
173
|
{...$$restProps}
|
|
161
|
-
tooltip={
|
|
174
|
+
tooltip={$$props.tooltip === false
|
|
175
|
+
? false
|
|
176
|
+
: {
|
|
177
|
+
mode: 'voronoi',
|
|
178
|
+
onClick: onTooltipClick,
|
|
179
|
+
...props.tooltip?.context,
|
|
180
|
+
...$$props.tooltip,
|
|
181
|
+
}}
|
|
162
182
|
let:x
|
|
163
183
|
let:xScale
|
|
164
184
|
let:y
|
|
@@ -203,9 +223,11 @@
|
|
|
203
223
|
<slot name="belowMarks" {...slotProps} />
|
|
204
224
|
|
|
205
225
|
<slot name="marks" {...slotProps}>
|
|
206
|
-
{
|
|
207
|
-
|
|
208
|
-
|
|
226
|
+
<ChartClipPath disabled={!brush}>
|
|
227
|
+
{#each visibleSeries as s, i (s.key)}
|
|
228
|
+
<Points {...getPointsProps(s, i)} />
|
|
229
|
+
{/each}
|
|
230
|
+
</ChartClipPath>
|
|
209
231
|
</slot>
|
|
210
232
|
|
|
211
233
|
<slot name="aboveMarks" {...slotProps} />
|
|
@@ -247,6 +269,25 @@
|
|
|
247
269
|
{/if}
|
|
248
270
|
</svelte:component>
|
|
249
271
|
|
|
272
|
+
<!-- TODO: Determine how to coordinate with `tooltip={{ mode: 'voronoi' }} -->
|
|
273
|
+
{#if brush && brush.mode === 'integrated'}
|
|
274
|
+
<Svg>
|
|
275
|
+
{@const brushProps = { ...(typeof brush === 'object' ? brush : null), ...props.brush }}
|
|
276
|
+
<Brush
|
|
277
|
+
axis="both"
|
|
278
|
+
resetOnEnd
|
|
279
|
+
{xDomain}
|
|
280
|
+
{yDomain}
|
|
281
|
+
{...brushProps}
|
|
282
|
+
onBrushEnd={(e) => {
|
|
283
|
+
xDomain = e.xDomain;
|
|
284
|
+
yDomain = e.yDomain;
|
|
285
|
+
brushProps.onBrushEnd?.(e);
|
|
286
|
+
}}
|
|
287
|
+
/>
|
|
288
|
+
</Svg>
|
|
289
|
+
{/if}
|
|
290
|
+
|
|
250
291
|
<slot name="legend" {...slotProps}>
|
|
251
292
|
{#if legend}
|
|
252
293
|
<Legend
|
package/dist/utils/types.d.ts
CHANGED
package/dist/utils/types.js
CHANGED