layerchart 0.21.1 → 0.22.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/Arc.svelte +8 -5
- package/dist/components/Arc.svelte.d.ts +1 -0
- package/dist/components/Circle.svelte +13 -7
- package/dist/components/Circle.svelte.d.ts +3 -0
- package/dist/components/CircleClipPath.svelte +1 -1
- package/dist/components/CircleClipPath.svelte.d.ts +2 -1
- package/dist/components/Group.svelte +9 -5
- package/dist/components/Group.svelte.d.ts +2 -0
- package/dist/components/Highlight.svelte +209 -0
- package/dist/components/Labels.svelte +7 -7
- package/dist/components/Line.svelte +16 -9
- package/dist/components/Line.svelte.d.ts +4 -0
- package/dist/components/LinearGradient.svelte +9 -2
- package/dist/components/LinearGradient.svelte.d.ts +7 -3
- package/dist/components/Link.svelte +4 -3
- package/dist/components/Link.svelte.d.ts +1 -1
- package/dist/components/Points.svelte +52 -2
- package/dist/components/Rect.svelte +16 -9
- package/dist/components/RectClipPath.svelte +1 -1
- package/dist/components/RectClipPath.svelte.d.ts +2 -1
- package/dist/components/index.d.ts +1 -3
- package/dist/components/index.js +1 -3
- package/dist/stores/motionStore.js +6 -2
- package/package.json +3 -3
- package/dist/components/ConnectedPoints.svelte +0 -75
- package/dist/components/ConnectedPoints.svelte.d.ts +0 -18
- package/dist/components/HighlightLine.svelte +0 -140
- package/dist/components/HighlightLine.svelte.d.ts +0 -21
- package/dist/components/HighlightRect.svelte +0 -72
- package/dist/components/HighlightRect.svelte.d.ts +0 -18
- package/dist/components/Points.svelte.d.ts +0 -23
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// https://github.com/mnsht/gradient-path
|
|
13
13
|
// https://svelte.dev/repl/09711e43a1264ba18945d7db7cab9335?version=3.38.2
|
|
14
14
|
// https://codepen.io/simeydotme/pen/rrOEmO/
|
|
15
|
-
import { getContext } from 'svelte';
|
|
15
|
+
import { getContext, tick } from 'svelte';
|
|
16
16
|
import { arc as d3arc } from 'd3-shape';
|
|
17
17
|
import { scaleLinear } from 'd3-scale';
|
|
18
18
|
import { min, max } from 'd3-array';
|
|
@@ -21,8 +21,11 @@ import { degreesToRadians } from '../utils/math';
|
|
|
21
21
|
export let spring = undefined;
|
|
22
22
|
export let tweened = undefined;
|
|
23
23
|
export let value = 0;
|
|
24
|
-
let
|
|
25
|
-
|
|
24
|
+
export let initialValue = value;
|
|
25
|
+
let tweened_value = motionStore(initialValue, { spring, tweened });
|
|
26
|
+
$: tick().then(() => {
|
|
27
|
+
tweened_value.set(value);
|
|
28
|
+
});
|
|
26
29
|
export let domain = [0, 100];
|
|
27
30
|
/**
|
|
28
31
|
* Range [min,max] in degrees. See also startAngle/endAngle
|
|
@@ -127,7 +130,7 @@ $: boundingBox = trackArc && trackArcEl ? trackArcEl.getBBox() : {};
|
|
|
127
130
|
$: labelArcCenterOffset = {
|
|
128
131
|
x: outerRadius - boundingBox.width / 2,
|
|
129
132
|
// x: 0,
|
|
130
|
-
y: (outerRadius - boundingBox.height / 2) * -1
|
|
133
|
+
y: (outerRadius - boundingBox.height / 2) * -1,
|
|
131
134
|
};
|
|
132
135
|
// $: console.log(labelArcCenterOffset)
|
|
133
136
|
$: labelArcBottomOffset = {
|
|
@@ -135,7 +138,7 @@ $: labelArcBottomOffset = {
|
|
|
135
138
|
x: outerRadius - boundingBox.width / 2,
|
|
136
139
|
// x: 0,
|
|
137
140
|
// y: (outerRadius - boundingBox.height) * -1
|
|
138
|
-
y: (outerRadius - boundingBox.height) * -1
|
|
141
|
+
y: (outerRadius - boundingBox.height) * -1,
|
|
139
142
|
};
|
|
140
143
|
// $: console.log(labelArcBottomOffset)
|
|
141
144
|
/**
|
|
@@ -7,6 +7,7 @@ declare const __propDef: {
|
|
|
7
7
|
spring?: boolean | Parameters<typeof springStore>[1];
|
|
8
8
|
tweened?: boolean | Parameters<typeof tweenedStore>[1];
|
|
9
9
|
value?: number | undefined;
|
|
10
|
+
initialValue?: number | undefined;
|
|
10
11
|
domain?: number[] | undefined;
|
|
11
12
|
range?: number[] | undefined;
|
|
12
13
|
startAngle?: number | undefined;
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { tick } from 'svelte';
|
|
2
|
+
import { motionStore } from '../stores/motionStore';
|
|
2
3
|
export let cx = 0;
|
|
4
|
+
export let initialCx = cx;
|
|
3
5
|
export let cy = 0;
|
|
6
|
+
export let initialCy = cy;
|
|
4
7
|
export let r;
|
|
8
|
+
export let initialR = r;
|
|
5
9
|
export let spring = undefined;
|
|
6
10
|
export let tweened = undefined;
|
|
7
|
-
let tweened_cx = motionStore(
|
|
8
|
-
let tweened_cy = motionStore(
|
|
9
|
-
let tweened_r = motionStore(
|
|
10
|
-
$:
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
let tweened_cx = motionStore(initialCx, { spring, tweened });
|
|
12
|
+
let tweened_cy = motionStore(initialCy, { spring, tweened });
|
|
13
|
+
let tweened_r = motionStore(initialR, { spring, tweened });
|
|
14
|
+
$: tick().then(() => {
|
|
15
|
+
tweened_cx.set(cx);
|
|
16
|
+
tweened_cy.set(cy);
|
|
17
|
+
tweened_r.set(r);
|
|
18
|
+
});
|
|
13
19
|
</script>
|
|
14
20
|
|
|
15
21
|
<circle
|
|
@@ -4,8 +4,11 @@ declare const __propDef: {
|
|
|
4
4
|
props: {
|
|
5
5
|
[x: string]: any;
|
|
6
6
|
cx?: number | undefined;
|
|
7
|
+
initialCx?: number | undefined;
|
|
7
8
|
cy?: number | undefined;
|
|
9
|
+
initialCy?: number | undefined;
|
|
8
10
|
r: number;
|
|
11
|
+
initialR?: number | undefined;
|
|
9
12
|
spring?: boolean | Parameters<typeof springStore>[1];
|
|
10
13
|
tweened?: boolean | Parameters<typeof tweenedStore>[1];
|
|
11
14
|
};
|
|
@@ -2,7 +2,8 @@ import { SvelteComponentTyped } from "svelte";
|
|
|
2
2
|
import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
|
|
5
|
+
[x: string]: any;
|
|
6
|
+
id?: string | undefined;
|
|
6
7
|
cx?: number | undefined;
|
|
7
8
|
cy?: number | undefined;
|
|
8
9
|
r: number;
|
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
<script>import { getContext } from 'svelte';
|
|
1
|
+
<script>import { getContext, tick } from 'svelte';
|
|
2
2
|
import { motionStore } from '../stores/motionStore';
|
|
3
3
|
const { width, height } = getContext('LayerCake');
|
|
4
4
|
/**
|
|
5
5
|
* Translate x
|
|
6
6
|
*/
|
|
7
7
|
export let x = undefined;
|
|
8
|
+
export let initialX = x;
|
|
8
9
|
/**
|
|
9
10
|
* Translate x
|
|
10
11
|
*/
|
|
11
12
|
export let y = undefined;
|
|
13
|
+
export let initialY = y;
|
|
12
14
|
/**
|
|
13
15
|
* Center within chart
|
|
14
16
|
*/
|
|
15
17
|
export let center = false;
|
|
16
18
|
export let spring = undefined;
|
|
17
19
|
export let tweened = undefined;
|
|
18
|
-
let tweened_x = motionStore(
|
|
19
|
-
let tweened_y = motionStore(
|
|
20
|
-
$:
|
|
21
|
-
|
|
20
|
+
let tweened_x = motionStore(initialX, { spring, tweened });
|
|
21
|
+
let tweened_y = motionStore(initialY, { spring, tweened });
|
|
22
|
+
$: tick().then(() => {
|
|
23
|
+
tweened_x.set(x);
|
|
24
|
+
tweened_y.set(y);
|
|
25
|
+
});
|
|
22
26
|
let transform = undefined;
|
|
23
27
|
$: if (x != null || y != null) {
|
|
24
28
|
transform = `translate(${$tweened_x ?? 0}, ${$tweened_y ?? 0})`;
|
|
@@ -4,7 +4,9 @@ declare const __propDef: {
|
|
|
4
4
|
props: {
|
|
5
5
|
[x: string]: any;
|
|
6
6
|
x?: number | undefined;
|
|
7
|
+
initialX?: number | undefined;
|
|
7
8
|
y?: number | undefined;
|
|
9
|
+
initialY?: number | undefined;
|
|
8
10
|
center?: boolean | undefined;
|
|
9
11
|
spring?: boolean | Parameters<typeof springStore>[1];
|
|
10
12
|
tweened?: boolean | Parameters<typeof tweenedStore>[1];
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { max, min } from 'd3-array';
|
|
3
|
+
import { cls, notNull } from 'svelte-ux';
|
|
4
|
+
import { isScaleBand } from '../utils/scales';
|
|
5
|
+
import Circle from './Circle.svelte';
|
|
6
|
+
import Line from './Line.svelte';
|
|
7
|
+
import Rect from './Rect.svelte';
|
|
8
|
+
import { tooltipContext } from './TooltipContext.svelte';
|
|
9
|
+
const { flatData, x, xDomain, xScale, xRange, xGet, y, yDomain, yScale, yRange, yGet, rGet, config, } = getContext('LayerCake');
|
|
10
|
+
const tooltip = tooltipContext();
|
|
11
|
+
export let axis = undefined;
|
|
12
|
+
/** Show points and pass props to Circles */
|
|
13
|
+
export let points = false;
|
|
14
|
+
/** Show lines and pass props to Lines */
|
|
15
|
+
export let lines = false;
|
|
16
|
+
/** Show area and pass props to Rect */
|
|
17
|
+
export let area = false;
|
|
18
|
+
// TODO: Fix circle points being backwards for stack (see AreaStack)
|
|
19
|
+
let _points = [];
|
|
20
|
+
let _lines = [];
|
|
21
|
+
let _area = {
|
|
22
|
+
x: 0,
|
|
23
|
+
y: 0,
|
|
24
|
+
width: 0,
|
|
25
|
+
height: 0,
|
|
26
|
+
};
|
|
27
|
+
$: if ($tooltip.data) {
|
|
28
|
+
let xCoord = $xGet($tooltip.data);
|
|
29
|
+
let xOffset = isScaleBand($xScale) ? $xScale.bandwidth() / 2 : 0;
|
|
30
|
+
let yCoord = $yGet($tooltip.data);
|
|
31
|
+
let yOffset = isScaleBand($yScale) ? $yScale.bandwidth() / 2 : 0;
|
|
32
|
+
// Reset lines
|
|
33
|
+
_lines = [];
|
|
34
|
+
const defaultAxis = isScaleBand($yScale) ? 'y' : 'x';
|
|
35
|
+
if (axis == null) {
|
|
36
|
+
axis = defaultAxis;
|
|
37
|
+
}
|
|
38
|
+
if (axis === 'x' || axis === 'both') {
|
|
39
|
+
// x lines
|
|
40
|
+
if (Array.isArray(xCoord)) {
|
|
41
|
+
// `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
|
|
42
|
+
_lines = [
|
|
43
|
+
..._lines,
|
|
44
|
+
...xCoord.filter(notNull).map((xItem, i) => ({
|
|
45
|
+
x1: xItem + xOffset,
|
|
46
|
+
y1: 0,
|
|
47
|
+
x2: xItem + xOffset,
|
|
48
|
+
y2: max($yRange),
|
|
49
|
+
})),
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
_lines = [
|
|
54
|
+
..._lines,
|
|
55
|
+
{
|
|
56
|
+
x1: xCoord + xOffset,
|
|
57
|
+
y1: 0,
|
|
58
|
+
x2: xCoord + xOffset,
|
|
59
|
+
y2: max($yRange),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
// x area
|
|
64
|
+
if (Array.isArray(xCoord)) {
|
|
65
|
+
// `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
|
|
66
|
+
_area.width = max(xCoord) - min(xCoord); // Use first/last values for width
|
|
67
|
+
}
|
|
68
|
+
else if (isScaleBand($xScale)) {
|
|
69
|
+
_area.width = $xScale.step();
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Find width to next data point
|
|
73
|
+
const index = $flatData.findIndex((d) => Number($x(d)) === Number($x($tooltip.data)));
|
|
74
|
+
const isLastPoint = index + 1 === $flatData.length;
|
|
75
|
+
const nextDataPoint = isLastPoint ? max($xDomain) : $x($flatData[index + 1]);
|
|
76
|
+
_area.width = ($xScale(nextDataPoint) ?? 0) - (xCoord ?? 0);
|
|
77
|
+
}
|
|
78
|
+
// If array, use left-most value for top left of rect
|
|
79
|
+
_area.x =
|
|
80
|
+
(Array.isArray(xCoord) ? min(xCoord) : xCoord) -
|
|
81
|
+
(isScaleBand($xScale) ? ($xScale.padding() * $xScale.step()) / 2 : 0);
|
|
82
|
+
if (axis === 'x') {
|
|
83
|
+
_area.height = max($yRange);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (axis === 'y' || axis === 'both') {
|
|
87
|
+
// y lines
|
|
88
|
+
if (Array.isArray(yCoord)) {
|
|
89
|
+
// `y` accessor with multiple properties (ex. `y={['start', 'end']})`)
|
|
90
|
+
_lines = [
|
|
91
|
+
..._lines,
|
|
92
|
+
...yCoord.filter(notNull).map((yItem, i) => ({
|
|
93
|
+
x1: 0,
|
|
94
|
+
y1: yItem + yOffset,
|
|
95
|
+
x2: max($xRange),
|
|
96
|
+
y2: yItem + yOffset,
|
|
97
|
+
})),
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
_lines = [
|
|
102
|
+
..._lines,
|
|
103
|
+
{
|
|
104
|
+
x1: 0,
|
|
105
|
+
y1: yCoord + yOffset,
|
|
106
|
+
x2: max($xRange),
|
|
107
|
+
y2: yCoord + yOffset,
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
// y area
|
|
112
|
+
if (Array.isArray(yCoord)) {
|
|
113
|
+
// `y` accessor with multiple properties (ex. `y={['start', 'end']})`)
|
|
114
|
+
_area.height = max(yCoord) - min(yCoord); // Use first/last values for width
|
|
115
|
+
}
|
|
116
|
+
else if (isScaleBand($yScale)) {
|
|
117
|
+
_area.height = $yScale.step();
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// Find width to next data point
|
|
121
|
+
const index = $flatData.findIndex((d) => Number($x(d)) === Number($x($tooltip.data)));
|
|
122
|
+
const isLastPoint = index + 1 === $flatData.length;
|
|
123
|
+
const nextDataPoint = isLastPoint ? max($yDomain) : $x($flatData[index + 1]);
|
|
124
|
+
_area.height = ($yScale(nextDataPoint) ?? 0) - (yCoord ?? 0);
|
|
125
|
+
}
|
|
126
|
+
// If array, use left-most value for top left of rect
|
|
127
|
+
_area.y =
|
|
128
|
+
(Array.isArray(yCoord) ? min(yCoord) : yCoord) -
|
|
129
|
+
(isScaleBand($yScale) ? ($yScale.padding() * $yScale.step()) / 2 : 0);
|
|
130
|
+
if (axis === 'y') {
|
|
131
|
+
_area.width = max($xRange);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// points
|
|
135
|
+
if (Array.isArray(xCoord)) {
|
|
136
|
+
// `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
|
|
137
|
+
_points = xCoord.filter(notNull).map((xItem, i) => ({
|
|
138
|
+
x: xItem + xOffset,
|
|
139
|
+
y: $yGet($tooltip.data) + yOffset,
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
else if (Array.isArray($tooltip.data)) {
|
|
143
|
+
// Stack series
|
|
144
|
+
_points = $tooltip.data.map((yValue, i) => ({
|
|
145
|
+
x: xCoord + xOffset,
|
|
146
|
+
y: $yScale(yValue) + yOffset,
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
_points = [
|
|
151
|
+
{
|
|
152
|
+
x: xCoord + xOffset,
|
|
153
|
+
y: $yGet($tooltip.data) + yOffset,
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
</script>
|
|
159
|
+
|
|
160
|
+
{#if $tooltip.data}
|
|
161
|
+
{#if area}
|
|
162
|
+
<slot name="area" area={_area}>
|
|
163
|
+
<Rect
|
|
164
|
+
spring
|
|
165
|
+
{..._area}
|
|
166
|
+
fill="rgba(0,0,0,.1)"
|
|
167
|
+
on:click
|
|
168
|
+
{...typeof area === 'object' ? area : null}
|
|
169
|
+
/>
|
|
170
|
+
</slot>
|
|
171
|
+
{/if}
|
|
172
|
+
|
|
173
|
+
{#if lines}
|
|
174
|
+
<slot name="lines" lines={_lines}>
|
|
175
|
+
{#each _lines as line}
|
|
176
|
+
<Line
|
|
177
|
+
spring
|
|
178
|
+
x1={line.x1}
|
|
179
|
+
y1={line.y1}
|
|
180
|
+
x2={line.x2}
|
|
181
|
+
y2={line.y2}
|
|
182
|
+
class="stroke-black/50 stroke-2 [stroke-dasharray:2,2] pointer-events-none"
|
|
183
|
+
{...typeof lines === 'object' ? lines : null}
|
|
184
|
+
/>
|
|
185
|
+
{/each}
|
|
186
|
+
</slot>
|
|
187
|
+
{/if}
|
|
188
|
+
|
|
189
|
+
{#if points}
|
|
190
|
+
<slot name="points" points={_points}>
|
|
191
|
+
{#each _points as point}
|
|
192
|
+
<!-- TODO: Improve color with stacked data -->
|
|
193
|
+
{@const fill = $config.r ? $rGet($tooltip.data) : null}
|
|
194
|
+
<Circle
|
|
195
|
+
spring
|
|
196
|
+
cx={point.x}
|
|
197
|
+
cy={point.y}
|
|
198
|
+
r={4}
|
|
199
|
+
{fill}
|
|
200
|
+
class={cls(
|
|
201
|
+
'stroke-[6] stroke-white [paint-order:stroke] drop-shadow',
|
|
202
|
+
!fill && 'fill-accent-500'
|
|
203
|
+
)}
|
|
204
|
+
{...typeof points === 'object' ? points : null}
|
|
205
|
+
/>
|
|
206
|
+
{/each}
|
|
207
|
+
</slot>
|
|
208
|
+
{/if}
|
|
209
|
+
{/if}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* - [ ] Support multiple values (threshold, stacks, etc)
|
|
5
5
|
*/
|
|
6
6
|
import { getContext } from 'svelte';
|
|
7
|
-
import Text from './Text.svelte';
|
|
8
7
|
import { format as formatValue } from 'svelte-ux';
|
|
9
8
|
import { formatNumberAsStyle } from 'svelte-ux/utils/number';
|
|
10
9
|
import { greatestAbs } from 'svelte-ux/utils/array';
|
|
10
|
+
import Text from './Text.svelte';
|
|
11
11
|
import { isScaleBand } from '../utils/scales';
|
|
12
12
|
import { createDimensionGetter } from '../utils/rect';
|
|
13
13
|
const { flatData, yScale, x, y, custom } = getContext('LayerCake');
|
|
@@ -27,8 +27,8 @@ $: getDimensions = createDimensionGetter(getContext('LayerCake'), {
|
|
|
27
27
|
// padding,
|
|
28
28
|
groupPadding: {
|
|
29
29
|
inner: groupPaddingInner,
|
|
30
|
-
outer: groupPaddingOuter
|
|
31
|
-
}
|
|
30
|
+
outer: groupPaddingOuter,
|
|
31
|
+
},
|
|
32
32
|
});
|
|
33
33
|
$: getValue = (item) => (isScaleBand($yScale) ? $x(item) : $y(item));
|
|
34
34
|
$: getLabelValue = (item) => {
|
|
@@ -62,7 +62,7 @@ $: getTextProps = (item) => {
|
|
|
62
62
|
y: dimensions?.y + (dimensions?.height ?? 0) / 2,
|
|
63
63
|
textAnchor: 'end',
|
|
64
64
|
verticalAnchor: 'middle',
|
|
65
|
-
capHeight: '.6rem'
|
|
65
|
+
capHeight: '.6rem',
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
@@ -72,7 +72,7 @@ $: getTextProps = (item) => {
|
|
|
72
72
|
y: dimensions?.y + (dimensions?.height ?? 0) / 2,
|
|
73
73
|
textAnchor: 'start',
|
|
74
74
|
verticalAnchor: 'middle',
|
|
75
|
-
capHeight: '.6rem'
|
|
75
|
+
capHeight: '.6rem',
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -85,7 +85,7 @@ $: getTextProps = (item) => {
|
|
|
85
85
|
y: dimensions?.y + dimensions?.height,
|
|
86
86
|
dy: '0.5em',
|
|
87
87
|
textAnchor: 'middle',
|
|
88
|
-
verticalAnchor: 'middle'
|
|
88
|
+
verticalAnchor: 'middle',
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
else {
|
|
@@ -95,7 +95,7 @@ $: getTextProps = (item) => {
|
|
|
95
95
|
y: dimensions?.y,
|
|
96
96
|
dy: '-0.6em',
|
|
97
97
|
textAnchor: 'middle',
|
|
98
|
-
verticalAnchor: 'middle'
|
|
98
|
+
verticalAnchor: 'middle',
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { tick } from 'svelte';
|
|
2
|
+
import { motionStore } from '../stores/motionStore';
|
|
2
3
|
export let x1;
|
|
4
|
+
export let initialX1 = x1;
|
|
3
5
|
export let y1;
|
|
6
|
+
export let initialY1 = x1;
|
|
4
7
|
export let x2;
|
|
8
|
+
export let initialX2 = x2;
|
|
5
9
|
export let y2;
|
|
10
|
+
export let initialY2 = y2;
|
|
6
11
|
export let spring = undefined;
|
|
7
12
|
export let tweened = undefined;
|
|
8
|
-
let tweened_x1 = motionStore(
|
|
9
|
-
let tweened_y1 = motionStore(
|
|
10
|
-
let tweened_x2 = motionStore(
|
|
11
|
-
let tweened_y2 = motionStore(
|
|
12
|
-
$:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
let tweened_x1 = motionStore(initialX1, { spring, tweened });
|
|
14
|
+
let tweened_y1 = motionStore(initialY1, { spring, tweened });
|
|
15
|
+
let tweened_x2 = motionStore(initialX2, { spring, tweened });
|
|
16
|
+
let tweened_y2 = motionStore(initialY2, { spring, tweened });
|
|
17
|
+
$: tick().then(() => {
|
|
18
|
+
tweened_x1.set(x1);
|
|
19
|
+
tweened_y1.set(y1);
|
|
20
|
+
tweened_x2.set(x2);
|
|
21
|
+
tweened_y2.set(y2);
|
|
22
|
+
});
|
|
16
23
|
</script>
|
|
17
24
|
|
|
18
25
|
<line
|
|
@@ -4,9 +4,13 @@ declare const __propDef: {
|
|
|
4
4
|
props: {
|
|
5
5
|
[x: string]: any;
|
|
6
6
|
x1: number;
|
|
7
|
+
initialX1?: number | undefined;
|
|
7
8
|
y1: number;
|
|
9
|
+
initialY1?: number | undefined;
|
|
8
10
|
x2: number;
|
|
11
|
+
initialX2?: number | undefined;
|
|
9
12
|
y2: number;
|
|
13
|
+
initialY2?: number | undefined;
|
|
10
14
|
spring?: boolean | Parameters<typeof springStore>[1];
|
|
11
15
|
tweened?: boolean | Parameters<typeof tweenedStore>[1];
|
|
12
16
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
<script>
|
|
1
|
+
<script>import { uniqueId } from 'svelte-ux';
|
|
2
|
+
/** Unique id for linearGradient */
|
|
3
|
+
export let id = uniqueId('linearGradient-');
|
|
2
4
|
export let from;
|
|
3
5
|
export let via = undefined; // TODO: Currently --tw-gradient-via is not the color but the full stops
|
|
4
6
|
export let to;
|
|
@@ -8,6 +10,8 @@ export let y1 = '0%';
|
|
|
8
10
|
export let x2 = vertical ? '0%' : '100%';
|
|
9
11
|
export let y2 = vertical ? '100%' : '0%';
|
|
10
12
|
export let rotate = undefined;
|
|
13
|
+
/** Define the coordinate system for attributes (i.e. gradientUnits) */
|
|
14
|
+
export let units = 'objectBoundingBox';
|
|
11
15
|
</script>
|
|
12
16
|
|
|
13
17
|
<defs>
|
|
@@ -18,9 +22,10 @@ export let rotate = undefined;
|
|
|
18
22
|
{x2}
|
|
19
23
|
{y2}
|
|
20
24
|
gradientTransform={rotate ? `rotate(${rotate})` : ''}
|
|
25
|
+
gradientUnits={units}
|
|
21
26
|
{...$$restProps}
|
|
22
27
|
>
|
|
23
|
-
<slot>
|
|
28
|
+
<slot name="stops">
|
|
24
29
|
{#if from}
|
|
25
30
|
<stop offset="0%" stop-color={from === true ? 'var(--tw-gradient-from)' : from} />
|
|
26
31
|
{/if}
|
|
@@ -36,3 +41,5 @@ export let rotate = undefined;
|
|
|
36
41
|
</slot>
|
|
37
42
|
</linearGradient>
|
|
38
43
|
</defs>
|
|
44
|
+
|
|
45
|
+
<slot {id} />
|
|
@@ -2,9 +2,9 @@ import { SvelteComponentTyped } from "svelte";
|
|
|
2
2
|
declare const __propDef: {
|
|
3
3
|
props: {
|
|
4
4
|
[x: string]: any;
|
|
5
|
-
id
|
|
5
|
+
id?: string | undefined;
|
|
6
6
|
from: string | boolean;
|
|
7
|
-
via?: string | undefined;
|
|
7
|
+
via?: string | boolean | undefined;
|
|
8
8
|
to: string | boolean;
|
|
9
9
|
vertical?: boolean | undefined;
|
|
10
10
|
x1?: string | undefined;
|
|
@@ -12,12 +12,16 @@ declare const __propDef: {
|
|
|
12
12
|
x2?: string | undefined;
|
|
13
13
|
y2?: string | undefined;
|
|
14
14
|
rotate?: number | undefined;
|
|
15
|
+
units?: "objectBoundingBox" | "userSpaceOnUse" | undefined;
|
|
15
16
|
};
|
|
16
17
|
events: {
|
|
17
18
|
[evt: string]: CustomEvent<any>;
|
|
18
19
|
};
|
|
19
20
|
slots: {
|
|
20
|
-
|
|
21
|
+
stops: {};
|
|
22
|
+
default: {
|
|
23
|
+
id: string;
|
|
24
|
+
};
|
|
21
25
|
};
|
|
22
26
|
};
|
|
23
27
|
export type LinearGradientProps = typeof __propDef.props;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script>import { link as d3Link, curveBumpX, curveBumpY } from 'd3-shape';
|
|
2
2
|
import { interpolatePath } from 'd3-interpolate-path';
|
|
3
3
|
import { motionStore } from '../stores/motionStore';
|
|
4
|
-
//
|
|
4
|
+
// Override what is used from context
|
|
5
5
|
export let data = undefined; // TODO: Update Type
|
|
6
|
-
export let orientation = 'horizontal';
|
|
7
6
|
/**
|
|
8
7
|
* Update source and target accessors to be compatible with d3-sankey. see: https://github.com/d3/d3-sankey#sankeyLinkHorizontal
|
|
9
8
|
*/
|
|
10
9
|
export let sankey = false;
|
|
11
10
|
export let source = sankey ? (d) => [d.source.x1, d.y0] : (d) => d.source;
|
|
12
11
|
export let target = sankey ? (d) => [d.target.x0, d.y1] : (d) => d.target;
|
|
12
|
+
/** Convenient property to swap x/y accessor logic */
|
|
13
|
+
export let orientation = sankey ? 'horizontal' : 'vertical';
|
|
13
14
|
export let x = sankey ? (d) => d[0] : (d) => (orientation === 'horizontal' ? d.y : d.x);
|
|
14
15
|
export let y = sankey ? (d) => d[1] : (d) => (orientation === 'horizontal' ? d.x : d.y);
|
|
15
16
|
export let curve = orientation === 'horizontal' ? curveBumpX : curveBumpY;
|
|
@@ -17,7 +18,7 @@ export let tweened = undefined;
|
|
|
17
18
|
$: tweenedOptions = tweened ? { interpolate: interpolatePath, ...tweened } : false;
|
|
18
19
|
$: tweened_d = motionStore('', { tweened: tweenedOptions });
|
|
19
20
|
$: {
|
|
20
|
-
orientation; // subscribe to orientation changes to link
|
|
21
|
+
orientation; // subscribe to orientation changes to update link
|
|
21
22
|
const link = d3Link(curve).source(source).target(target).x(x).y(y);
|
|
22
23
|
const d = link(data);
|
|
23
24
|
tweened_d.set(d);
|
|
@@ -4,10 +4,10 @@ declare const __propDef: {
|
|
|
4
4
|
props: {
|
|
5
5
|
[x: string]: any;
|
|
6
6
|
data?: any;
|
|
7
|
-
orientation?: "horizontal" | "vertical" | undefined;
|
|
8
7
|
sankey?: boolean | undefined;
|
|
9
8
|
source?: ((d: any) => any) | undefined;
|
|
10
9
|
target?: ((d: any) => any) | undefined;
|
|
10
|
+
orientation?: "horizontal" | "vertical" | undefined;
|
|
11
11
|
x?: ((d: any) => any) | undefined;
|
|
12
12
|
y?: ((d: any) => any) | undefined;
|
|
13
13
|
curve?: import("d3-shape").CurveFactory | undefined;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { extent } from 'd3-array';
|
|
3
|
+
import { notNull } from 'svelte-ux';
|
|
2
4
|
import Circle from './Circle.svelte';
|
|
5
|
+
import Link from './Link.svelte';
|
|
3
6
|
import { isScaleBand } from '../utils/scales';
|
|
4
|
-
import { notNull } from 'svelte-ux';
|
|
5
7
|
const context = getContext('LayerCake');
|
|
6
8
|
const { data, xGet, y, yGet, xScale, yScale, rGet, config } = context;
|
|
7
9
|
export let r = 5;
|
|
8
10
|
export let offsetX = undefined;
|
|
9
11
|
export let offsetY = undefined;
|
|
12
|
+
/** Enable showing links between related points (array x/y accessors) */
|
|
13
|
+
export let links = false;
|
|
10
14
|
function getOffset(value, offset, scale) {
|
|
11
15
|
if (typeof offset === 'function') {
|
|
12
16
|
return offset(value, context);
|
|
@@ -64,11 +68,57 @@ $: points = $data.flatMap((d) => {
|
|
|
64
68
|
};
|
|
65
69
|
}
|
|
66
70
|
});
|
|
71
|
+
$: _links = $data.flatMap((d) => {
|
|
72
|
+
if (Array.isArray($config.x)) {
|
|
73
|
+
/*
|
|
74
|
+
x={["prop1" ,"prop2"]}
|
|
75
|
+
y="prop3"
|
|
76
|
+
*/
|
|
77
|
+
const [xMin, xMax] = extent($xGet(d));
|
|
78
|
+
const y = $yGet(d) + getOffset($yGet(d), offsetY, $yScale);
|
|
79
|
+
return {
|
|
80
|
+
source: {
|
|
81
|
+
x: xMin + getOffset(xMin, offsetX, $xScale),
|
|
82
|
+
y,
|
|
83
|
+
},
|
|
84
|
+
target: {
|
|
85
|
+
x: xMax + getOffset(xMax, offsetX, $xScale),
|
|
86
|
+
y: y,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
else if (Array.isArray($config.y)) {
|
|
91
|
+
/*
|
|
92
|
+
x="prop1"
|
|
93
|
+
y={["prop2" ,"prop3"]}
|
|
94
|
+
*/
|
|
95
|
+
const x = $xGet(d) + getOffset($xGet(d), offsetX, $xScale);
|
|
96
|
+
const [yMin, yMax] = extent($yGet(d));
|
|
97
|
+
return {
|
|
98
|
+
source: {
|
|
99
|
+
x: x,
|
|
100
|
+
y: yMin + getOffset(yMin, offsetY, $yScale),
|
|
101
|
+
},
|
|
102
|
+
target: {
|
|
103
|
+
x: x,
|
|
104
|
+
y: yMax + getOffset(yMax, offsetY, $yScale),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
});
|
|
67
109
|
</script>
|
|
68
110
|
|
|
69
111
|
<slot {points}>
|
|
112
|
+
{#if links}
|
|
113
|
+
<g class="link-group">
|
|
114
|
+
{#each _links as link}
|
|
115
|
+
<Link data={link} stroke="black" {...typeof links === 'object' ? links : null} />
|
|
116
|
+
{/each}
|
|
117
|
+
</g>
|
|
118
|
+
{/if}
|
|
119
|
+
|
|
70
120
|
<g class="point-group">
|
|
71
|
-
{#each points as point
|
|
121
|
+
{#each points as point}
|
|
72
122
|
<Circle
|
|
73
123
|
cx={point.x}
|
|
74
124
|
cy={point.y}
|
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { tick } from 'svelte';
|
|
2
|
+
import { motionStore, resolveOptions, } from '../stores/motionStore';
|
|
2
3
|
export let x = 0;
|
|
4
|
+
export let initialX = x;
|
|
3
5
|
export let y = 0;
|
|
6
|
+
export let initialY = y;
|
|
4
7
|
export let width;
|
|
8
|
+
export let initialWidth = width;
|
|
5
9
|
export let height;
|
|
10
|
+
export let initialHeight = height;
|
|
6
11
|
export let spring = undefined;
|
|
7
12
|
export let tweened = undefined;
|
|
8
|
-
let tweened_x = motionStore(
|
|
9
|
-
let tweened_y = motionStore(
|
|
10
|
-
let tweened_width = motionStore(
|
|
11
|
-
let tweened_height = motionStore(
|
|
12
|
-
$:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
let tweened_x = motionStore(initialX, resolveOptions('x', { spring, tweened }));
|
|
14
|
+
let tweened_y = motionStore(initialY, resolveOptions('y', { spring, tweened }));
|
|
15
|
+
let tweened_width = motionStore(initialWidth, resolveOptions('width', { spring, tweened }));
|
|
16
|
+
let tweened_height = motionStore(initialHeight, resolveOptions('height', { spring, tweened }));
|
|
17
|
+
$: tick().then(() => {
|
|
18
|
+
tweened_x.set(x);
|
|
19
|
+
tweened_y.set(y);
|
|
20
|
+
tweened_width.set(width);
|
|
21
|
+
tweened_height.set(height);
|
|
22
|
+
});
|
|
16
23
|
</script>
|
|
17
24
|
|
|
18
25
|
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
|
@@ -2,7 +2,8 @@ import { SvelteComponentTyped } from "svelte";
|
|
|
2
2
|
import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
|
|
5
|
+
[x: string]: any;
|
|
6
|
+
id?: string | undefined;
|
|
6
7
|
x?: number | undefined;
|
|
7
8
|
y?: number | undefined;
|
|
8
9
|
width: number;
|
|
@@ -11,7 +11,6 @@ export { default as Circle } from './Circle.svelte';
|
|
|
11
11
|
export { default as CircleClipPath } from './CircleClipPath.svelte';
|
|
12
12
|
export { default as ClipPath } from './ClipPath.svelte';
|
|
13
13
|
export { default as ColorRamp } from './ColorRamp.svelte';
|
|
14
|
-
export { default as ConnectedPoints } from './ConnectedPoints.svelte';
|
|
15
14
|
export { default as Frame } from './Frame.svelte';
|
|
16
15
|
export { default as GeoContext } from './GeoContext.svelte';
|
|
17
16
|
export { default as GeoPath } from './GeoPath.svelte';
|
|
@@ -19,8 +18,7 @@ export { default as GeoPoint } from './GeoPoint.svelte';
|
|
|
19
18
|
export { default as GeoTile } from './GeoTile.svelte';
|
|
20
19
|
export { default as Graticule } from './Graticule.svelte';
|
|
21
20
|
export { default as Group } from './Group.svelte';
|
|
22
|
-
export { default as
|
|
23
|
-
export { default as HighlightRect } from './HighlightRect.svelte';
|
|
21
|
+
export { default as Highlight } from './Highlight.svelte';
|
|
24
22
|
export { default as Labels } from './Labels.svelte';
|
|
25
23
|
export { default as Legend } from './Legend.svelte';
|
|
26
24
|
export { default as Line } from './Line.svelte';
|
package/dist/components/index.js
CHANGED
|
@@ -11,7 +11,6 @@ export { default as Circle } from './Circle.svelte';
|
|
|
11
11
|
export { default as CircleClipPath } from './CircleClipPath.svelte';
|
|
12
12
|
export { default as ClipPath } from './ClipPath.svelte';
|
|
13
13
|
export { default as ColorRamp } from './ColorRamp.svelte';
|
|
14
|
-
export { default as ConnectedPoints } from './ConnectedPoints.svelte';
|
|
15
14
|
export { default as Frame } from './Frame.svelte';
|
|
16
15
|
export { default as GeoContext } from './GeoContext.svelte';
|
|
17
16
|
export { default as GeoPath } from './GeoPath.svelte';
|
|
@@ -19,8 +18,7 @@ export { default as GeoPoint } from './GeoPoint.svelte';
|
|
|
19
18
|
export { default as GeoTile } from './GeoTile.svelte';
|
|
20
19
|
export { default as Graticule } from './Graticule.svelte';
|
|
21
20
|
export { default as Group } from './Group.svelte';
|
|
22
|
-
export { default as
|
|
23
|
-
export { default as HighlightRect } from './HighlightRect.svelte';
|
|
21
|
+
export { default as Highlight } from './Highlight.svelte';
|
|
24
22
|
export { default as Labels } from './Labels.svelte';
|
|
25
23
|
export { default as Legend } from './Legend.svelte';
|
|
26
24
|
export { default as Line } from './Line.svelte';
|
|
@@ -23,11 +23,15 @@ export function resolveOptions(prop, options) {
|
|
|
23
23
|
? options.spring
|
|
24
24
|
: prop in options.spring
|
|
25
25
|
? options.spring[prop]
|
|
26
|
-
: options.spring,
|
|
26
|
+
: Object.keys(options.spring).some((key) => ['precision', 'damping', 'stiffness'].includes(key))
|
|
27
|
+
? options.tweened
|
|
28
|
+
: false,
|
|
27
29
|
tweened: typeof options.tweened === 'boolean' || options.tweened == null
|
|
28
30
|
? options.tweened
|
|
29
31
|
: prop in options.tweened
|
|
30
32
|
? options.tweened[prop]
|
|
31
|
-
: options.tweened,
|
|
33
|
+
: Object.keys(options.tweened).some((key) => ['delay', 'duration', 'easing'].includes(key))
|
|
34
|
+
? options.tweened
|
|
35
|
+
: false,
|
|
32
36
|
};
|
|
33
37
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Sean Lynch <techniq35@gmail.com>",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": "techniq/layerchart",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.22.0",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"dev": "vite dev",
|
|
9
9
|
"build": "vite build",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"marked": "^5.1.2",
|
|
48
48
|
"mdsvex": "^0.11.0",
|
|
49
49
|
"prettier": "^3.0.0",
|
|
50
|
-
"prettier-plugin-svelte": "^3.0.
|
|
50
|
+
"prettier-plugin-svelte": "^3.0.3",
|
|
51
51
|
"prism-themes": "^1.9.0",
|
|
52
52
|
"rehype-slug": "^5.1.0",
|
|
53
53
|
"svelte-check": "^3.4.6",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"lodash-es": "^4.17.21",
|
|
86
86
|
"shapefile": "^0.6.6",
|
|
87
87
|
"svelte": "^3.59.1",
|
|
88
|
-
"svelte-ux": "^0.47.
|
|
88
|
+
"svelte-ux": "^0.47.3",
|
|
89
89
|
"topojson-client": "^3.1.0"
|
|
90
90
|
},
|
|
91
91
|
"main": "./dist/index.js",
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
<script>/*
|
|
2
|
-
TODO:
|
|
3
|
-
- [ ] Consider becoming LinkLine using d3-path buider https://github.com/d3/d3-path
|
|
4
|
-
- https://github.com/airbnb/visx/blob/master/packages/visx-shape/src/shapes/link/line/LinkHorizontalLine.tsx
|
|
5
|
-
*/
|
|
6
|
-
import { getContext } from 'svelte';
|
|
7
|
-
import { extent } from 'd3-array';
|
|
8
|
-
import Line from './Line.svelte';
|
|
9
|
-
import { isScaleBand } from '../utils/scales';
|
|
10
|
-
const context = getContext('LayerCake');
|
|
11
|
-
const { data, xGet, yGet, xScale, yScale, config } = context;
|
|
12
|
-
export let offsetX = undefined;
|
|
13
|
-
export let offsetY = undefined;
|
|
14
|
-
function getOffset(value, offset, scale) {
|
|
15
|
-
if (typeof offset === 'function') {
|
|
16
|
-
return offset(value, context);
|
|
17
|
-
}
|
|
18
|
-
else if (offset != null) {
|
|
19
|
-
return offset;
|
|
20
|
-
}
|
|
21
|
-
else if (isScaleBand(scale)) {
|
|
22
|
-
return scale.bandwidth() / 2;
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
return 0;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
$: points = $data.flatMap((d) => {
|
|
29
|
-
if (Array.isArray($config.x)) {
|
|
30
|
-
/*
|
|
31
|
-
x={["prop1" ,"prop2"]}
|
|
32
|
-
y="prop3"
|
|
33
|
-
*/
|
|
34
|
-
const [xMin, xMax] = extent($xGet(d));
|
|
35
|
-
return {
|
|
36
|
-
x1: xMin + getOffset(xMin, offsetX, $xScale),
|
|
37
|
-
y1: $yGet(d) + getOffset($yGet(d), offsetY, $yScale),
|
|
38
|
-
x2: xMax + getOffset(xMax, offsetX, $xScale),
|
|
39
|
-
y2: $yGet(d) + getOffset($yGet(d), offsetY, $yScale)
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
else if (Array.isArray($config.y)) {
|
|
43
|
-
/*
|
|
44
|
-
x="prop1"
|
|
45
|
-
y={["prop2" ,"prop3"]}
|
|
46
|
-
*/
|
|
47
|
-
const [yMin, yMax] = extent($yGet(d));
|
|
48
|
-
return {
|
|
49
|
-
x1: $xGet(d) + getOffset($xGet(d), offsetX, $xScale),
|
|
50
|
-
y1: yMin + getOffset(yMin, offsetY, $yScale),
|
|
51
|
-
x2: $xGet(d) + getOffset($xGet(d), offsetX, $xScale),
|
|
52
|
-
y2: yMax + getOffset(yMax, offsetY, $yScale)
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
/*
|
|
57
|
-
x="prop1"
|
|
58
|
-
y="prop2"
|
|
59
|
-
*/
|
|
60
|
-
// Not really supported (nothing to connect...)
|
|
61
|
-
return {
|
|
62
|
-
x1: $xGet(d) + getOffset($xGet(d), offsetX, $xScale),
|
|
63
|
-
y1: $yGet(d) + getOffset($yGet(d), offsetY, $yScale),
|
|
64
|
-
x2: $xGet(d) + getOffset($xGet(d), offsetX, $xScale),
|
|
65
|
-
y2: $yGet(d) + getOffset($yGet(d), offsetY, $yScale)
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
</script>
|
|
70
|
-
|
|
71
|
-
<g class="connected-points">
|
|
72
|
-
{#each points as p}
|
|
73
|
-
<Line x1={p.x1} y1={p.y1} x2={p.x2} y2={p.y2} {...$$restProps} />
|
|
74
|
-
{/each}
|
|
75
|
-
</g>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
declare const __propDef: {
|
|
3
|
-
props: {
|
|
4
|
-
[x: string]: any;
|
|
5
|
-
offsetX?: (number | ((value: number, context: any) => number)) | undefined;
|
|
6
|
-
offsetY?: (number | ((value: number, context: any) => number)) | undefined;
|
|
7
|
-
};
|
|
8
|
-
events: {
|
|
9
|
-
[evt: string]: CustomEvent<any>;
|
|
10
|
-
};
|
|
11
|
-
slots: {};
|
|
12
|
-
};
|
|
13
|
-
export type ConnectedPointsProps = typeof __propDef.props;
|
|
14
|
-
export type ConnectedPointsEvents = typeof __propDef.events;
|
|
15
|
-
export type ConnectedPointsSlots = typeof __propDef.slots;
|
|
16
|
-
export default class ConnectedPoints extends SvelteComponentTyped<ConnectedPointsProps, ConnectedPointsEvents, ConnectedPointsSlots> {
|
|
17
|
-
}
|
|
18
|
-
export {};
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
<script>import { getContext } from 'svelte';
|
|
2
|
-
import { max } from 'd3-array';
|
|
3
|
-
import { notNull } from 'svelte-ux';
|
|
4
|
-
import { isScaleBand } from '../utils/scales';
|
|
5
|
-
import Circle from './Circle.svelte';
|
|
6
|
-
import Line from './Line.svelte';
|
|
7
|
-
import { tooltipContext } from './TooltipContext.svelte';
|
|
8
|
-
const { xScale, xRange, xGet, yScale, yRange, yGet, rGet, y, config } = getContext('LayerCake');
|
|
9
|
-
const tooltip = tooltipContext();
|
|
10
|
-
export let color = undefined;
|
|
11
|
-
export let axis = 'x';
|
|
12
|
-
// TODO: Fix circle points being backwards for stack (see AreaStack)
|
|
13
|
-
function getColor(item, index = -1) {
|
|
14
|
-
if (color) {
|
|
15
|
-
if (typeof color === 'function') {
|
|
16
|
-
return color({ value: $y(item), item, index });
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
return color;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
else if ($config.r) {
|
|
23
|
-
return $rGet(item);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
return 'var(--color-accent-500)';
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
let lines = [];
|
|
30
|
-
let points = [];
|
|
31
|
-
$: if ($tooltip.data) {
|
|
32
|
-
let x = $xGet($tooltip.data);
|
|
33
|
-
let xOffset = isScaleBand($xScale) ? $xScale.bandwidth() / 2 : 0;
|
|
34
|
-
let y = $yGet($tooltip.data);
|
|
35
|
-
let yOffset = isScaleBand($yScale) ? $yScale.bandwidth() / 2 : 0;
|
|
36
|
-
// Reset lines
|
|
37
|
-
lines = [];
|
|
38
|
-
if (axis === 'x' || axis === 'both') {
|
|
39
|
-
if (Array.isArray(x)) {
|
|
40
|
-
// `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
|
|
41
|
-
lines = [
|
|
42
|
-
...lines,
|
|
43
|
-
...x.filter(notNull).map((xItem, i) => ({
|
|
44
|
-
x1: xItem + xOffset,
|
|
45
|
-
y1: 0,
|
|
46
|
-
x2: xItem + xOffset,
|
|
47
|
-
y2: max($yRange)
|
|
48
|
-
}))
|
|
49
|
-
];
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
lines = [
|
|
53
|
-
...lines,
|
|
54
|
-
{
|
|
55
|
-
x1: x + xOffset,
|
|
56
|
-
y1: 0,
|
|
57
|
-
x2: x + xOffset,
|
|
58
|
-
y2: max($yRange)
|
|
59
|
-
}
|
|
60
|
-
];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (axis === 'y' || axis === 'both') {
|
|
64
|
-
if (Array.isArray(y)) {
|
|
65
|
-
// `y` accessor with multiple properties (ex. `y={['start', 'end']})`)
|
|
66
|
-
lines = [
|
|
67
|
-
...lines,
|
|
68
|
-
...y.filter(notNull).map((yItem, i) => ({
|
|
69
|
-
x1: 0,
|
|
70
|
-
y1: yItem + yOffset,
|
|
71
|
-
x2: max($xRange),
|
|
72
|
-
y2: yItem + yOffset
|
|
73
|
-
}))
|
|
74
|
-
];
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
lines = [
|
|
78
|
-
...lines,
|
|
79
|
-
{
|
|
80
|
-
x1: 0,
|
|
81
|
-
y1: y + yOffset,
|
|
82
|
-
x2: max($xRange),
|
|
83
|
-
y2: y + yOffset
|
|
84
|
-
}
|
|
85
|
-
];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
if (Array.isArray(x)) {
|
|
89
|
-
// `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
|
|
90
|
-
points = x.filter(notNull).map((xItem, i) => ({
|
|
91
|
-
x: xItem + xOffset,
|
|
92
|
-
y: $yGet($tooltip.data) + yOffset,
|
|
93
|
-
color: getColor($tooltip.data) // TODO: improve
|
|
94
|
-
}));
|
|
95
|
-
}
|
|
96
|
-
else if (Array.isArray($tooltip.data)) {
|
|
97
|
-
// Stack series
|
|
98
|
-
points = $tooltip.data.map((yValue, i) => ({
|
|
99
|
-
x: x + xOffset,
|
|
100
|
-
y: $yScale(yValue) + yOffset,
|
|
101
|
-
color: getColor($tooltip.data) // TODO: improve
|
|
102
|
-
}));
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
points = [
|
|
106
|
-
{
|
|
107
|
-
x: x + xOffset,
|
|
108
|
-
y: $yGet($tooltip.data) + yOffset,
|
|
109
|
-
// color: $rGet($tooltip.data) //getColor($tooltip.data)
|
|
110
|
-
color: getColor($tooltip.data)
|
|
111
|
-
}
|
|
112
|
-
];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
</script>
|
|
116
|
-
|
|
117
|
-
{#if $tooltip.data}
|
|
118
|
-
{#each lines as line}
|
|
119
|
-
<Line
|
|
120
|
-
spring
|
|
121
|
-
x1={line.x1}
|
|
122
|
-
y1={line.y1}
|
|
123
|
-
x2={line.x2}
|
|
124
|
-
y2={line.y2}
|
|
125
|
-
class="stroke-black/50 stroke-2 [stroke-dasharray:2,2] pointer-events-none"
|
|
126
|
-
/>
|
|
127
|
-
{/each}
|
|
128
|
-
|
|
129
|
-
{#each points as point}
|
|
130
|
-
<Circle
|
|
131
|
-
spring
|
|
132
|
-
cx={point.x}
|
|
133
|
-
cy={point.y}
|
|
134
|
-
r={7}
|
|
135
|
-
class="fill-white/90 stroke-2"
|
|
136
|
-
stroke={point.color}
|
|
137
|
-
/>
|
|
138
|
-
<Circle spring cx={point.x} cy={point.y} r={3} fill={point.color} />
|
|
139
|
-
{/each}
|
|
140
|
-
{/if}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
declare const __propDef: {
|
|
3
|
-
props: {
|
|
4
|
-
color?: string | ((obj: {
|
|
5
|
-
value: any;
|
|
6
|
-
item: any;
|
|
7
|
-
index: number;
|
|
8
|
-
}) => string) | undefined;
|
|
9
|
-
axis?: "x" | "y" | "none" | "both" | undefined;
|
|
10
|
-
};
|
|
11
|
-
events: {
|
|
12
|
-
[evt: string]: CustomEvent<any>;
|
|
13
|
-
};
|
|
14
|
-
slots: {};
|
|
15
|
-
};
|
|
16
|
-
export type HighlightLineProps = typeof __propDef.props;
|
|
17
|
-
export type HighlightLineEvents = typeof __propDef.events;
|
|
18
|
-
export type HighlightLineSlots = typeof __propDef.slots;
|
|
19
|
-
export default class HighlightLine extends SvelteComponentTyped<HighlightLineProps, HighlightLineEvents, HighlightLineSlots> {
|
|
20
|
-
}
|
|
21
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
<script>import { getContext } from 'svelte';
|
|
2
|
-
import { max, min } from 'd3-array';
|
|
3
|
-
import { isScaleBand } from '../utils/scales';
|
|
4
|
-
import Rect from './Rect.svelte';
|
|
5
|
-
import { tooltipContext } from './TooltipContext.svelte';
|
|
6
|
-
import { firstValue } from '../utils/rect';
|
|
7
|
-
const { flatData, x, xScale, xDomain, xRange, xGet, yScale, yDomain, yRange, yGet } = getContext('LayerCake');
|
|
8
|
-
const tooltip = tooltipContext();
|
|
9
|
-
export let axis = isScaleBand($yScale) ? 'y' : 'x';
|
|
10
|
-
let dimensions = {
|
|
11
|
-
x: 0,
|
|
12
|
-
y: 0,
|
|
13
|
-
width: 0,
|
|
14
|
-
height: 0
|
|
15
|
-
};
|
|
16
|
-
$: {
|
|
17
|
-
if ($tooltip.data) {
|
|
18
|
-
let xCoord = firstValue($xGet($tooltip.data));
|
|
19
|
-
let yCoord = firstValue($yGet($tooltip.data));
|
|
20
|
-
if (axis === 'x' || axis === 'both') {
|
|
21
|
-
if (isScaleBand($xScale)) {
|
|
22
|
-
dimensions.width = $xScale.step();
|
|
23
|
-
}
|
|
24
|
-
else if (Array.isArray(xCoord)) {
|
|
25
|
-
// `x` accessor with multiple properties (ex. `x={['start', 'end']})`)
|
|
26
|
-
// Use first/last values for width
|
|
27
|
-
dimensions.width = max(xCoord) - min(xCoord);
|
|
28
|
-
xCoord = min(xCoord); // Use left-most value for top left of rect
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
// Find width to next data point
|
|
32
|
-
const index = $flatData.findIndex((d) => Number($x(d)) === Number($x($tooltip.data)));
|
|
33
|
-
const isLastPoint = index + 1 === $flatData.length;
|
|
34
|
-
const nextDataPoint = isLastPoint ? max($xDomain) : $x($flatData[index + 1]);
|
|
35
|
-
dimensions.width = ($xScale(nextDataPoint) ?? 0) - (xCoord ?? 0);
|
|
36
|
-
}
|
|
37
|
-
dimensions.x =
|
|
38
|
-
xCoord - (isScaleBand($xScale) ? ($xScale.padding() * $xScale.step()) / 2 : 0);
|
|
39
|
-
if (axis === 'x') {
|
|
40
|
-
dimensions.height = max($yRange);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (axis === 'y' || axis === 'both') {
|
|
44
|
-
if (isScaleBand($yScale)) {
|
|
45
|
-
dimensions.height = $yScale.step();
|
|
46
|
-
}
|
|
47
|
-
else if (Array.isArray(xCoord)) {
|
|
48
|
-
// `y` accessor with multiple properties (ex. `y={['start', 'end']})`)
|
|
49
|
-
// Use first/last values for width
|
|
50
|
-
dimensions.height = max(yCoord) - min(yCoord);
|
|
51
|
-
yCoord = min(yCoord); // Use left-most value for top left of rect
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
// Find width to next data point
|
|
55
|
-
const index = $flatData.findIndex((d) => Number($x(d)) === Number($x($tooltip.data)));
|
|
56
|
-
const isLastPoint = index + 1 === $flatData.length;
|
|
57
|
-
const nextDataPoint = isLastPoint ? max($yDomain) : $x($flatData[index + 1]);
|
|
58
|
-
dimensions.height = ($yScale(nextDataPoint) ?? 0) - (yCoord ?? 0);
|
|
59
|
-
}
|
|
60
|
-
dimensions.y =
|
|
61
|
-
yCoord - (isScaleBand($yScale) ? ($yScale.padding() * $yScale.step()) / 2 : 0);
|
|
62
|
-
if (axis === 'y') {
|
|
63
|
-
dimensions.width = max($xRange);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
</script>
|
|
69
|
-
|
|
70
|
-
{#if $tooltip.data}
|
|
71
|
-
<Rect spring {...dimensions} fill="rgba(0,0,0,.1)" on:click />
|
|
72
|
-
{/if}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
declare const __propDef: {
|
|
3
|
-
props: {
|
|
4
|
-
axis?: "x" | "y" | "both" | undefined;
|
|
5
|
-
};
|
|
6
|
-
events: {
|
|
7
|
-
click: MouseEvent;
|
|
8
|
-
} & {
|
|
9
|
-
[evt: string]: CustomEvent<any>;
|
|
10
|
-
};
|
|
11
|
-
slots: {};
|
|
12
|
-
};
|
|
13
|
-
export type HighlightRectProps = typeof __propDef.props;
|
|
14
|
-
export type HighlightRectEvents = typeof __propDef.events;
|
|
15
|
-
export type HighlightRectSlots = typeof __propDef.slots;
|
|
16
|
-
export default class HighlightRect extends SvelteComponentTyped<HighlightRectProps, HighlightRectEvents, HighlightRectSlots> {
|
|
17
|
-
}
|
|
18
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
declare const __propDef: {
|
|
3
|
-
props: {
|
|
4
|
-
[x: string]: any;
|
|
5
|
-
r?: number | undefined;
|
|
6
|
-
offsetX?: (number | ((value: number, context: any) => number)) | undefined;
|
|
7
|
-
offsetY?: (number | ((value: number, context: any) => number)) | undefined;
|
|
8
|
-
};
|
|
9
|
-
events: {
|
|
10
|
-
[evt: string]: CustomEvent<any>;
|
|
11
|
-
};
|
|
12
|
-
slots: {
|
|
13
|
-
default: {
|
|
14
|
-
points: any;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
export type PointsProps = typeof __propDef.props;
|
|
19
|
-
export type PointsEvents = typeof __propDef.events;
|
|
20
|
-
export type PointsSlots = typeof __propDef.slots;
|
|
21
|
-
export default class Points extends SvelteComponentTyped<PointsProps, PointsEvents, PointsSlots> {
|
|
22
|
-
}
|
|
23
|
-
export {};
|