layerchart 0.21.0 → 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.
Files changed (32) hide show
  1. package/dist/components/Arc.svelte +8 -5
  2. package/dist/components/Arc.svelte.d.ts +1 -0
  3. package/dist/components/Circle.svelte +13 -7
  4. package/dist/components/Circle.svelte.d.ts +3 -0
  5. package/dist/components/CircleClipPath.svelte +1 -1
  6. package/dist/components/CircleClipPath.svelte.d.ts +2 -1
  7. package/dist/components/Group.svelte +9 -5
  8. package/dist/components/Group.svelte.d.ts +2 -0
  9. package/dist/components/Highlight.svelte +209 -0
  10. package/dist/components/Labels.svelte +7 -7
  11. package/dist/components/Line.svelte +16 -9
  12. package/dist/components/Line.svelte.d.ts +4 -0
  13. package/dist/components/LinearGradient.svelte +9 -2
  14. package/dist/components/LinearGradient.svelte.d.ts +7 -3
  15. package/dist/components/Link.svelte +4 -3
  16. package/dist/components/Link.svelte.d.ts +1 -1
  17. package/dist/components/Points.svelte +52 -2
  18. package/dist/components/Rect.svelte +16 -9
  19. package/dist/components/RectClipPath.svelte +1 -1
  20. package/dist/components/RectClipPath.svelte.d.ts +2 -1
  21. package/dist/components/TooltipContext.svelte +9 -10
  22. package/dist/components/index.d.ts +1 -3
  23. package/dist/components/index.js +1 -3
  24. package/dist/stores/motionStore.js +6 -2
  25. package/package.json +3 -3
  26. package/dist/components/ConnectedPoints.svelte +0 -75
  27. package/dist/components/ConnectedPoints.svelte.d.ts +0 -18
  28. package/dist/components/HighlightLine.svelte +0 -140
  29. package/dist/components/HighlightLine.svelte.d.ts +0 -21
  30. package/dist/components/HighlightRect.svelte +0 -72
  31. package/dist/components/HighlightRect.svelte.d.ts +0 -18
  32. 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 tweened_value = motionStore(value, { spring, tweened });
25
- $: tweened_value.set(value);
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 { motionStore } from '../stores/motionStore';
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(cx, { spring, tweened });
8
- let tweened_cy = motionStore(cy, { spring, tweened });
9
- let tweened_r = motionStore(r, { spring, tweened });
10
- $: tweened_cx.set(cx);
11
- $: tweened_cy.set(cy);
12
- $: tweened_r.set(r);
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
  };
@@ -11,6 +11,6 @@ export let tweened = undefined;
11
11
  </script>
12
12
 
13
13
  <ClipPath {id}>
14
- <Circle slot="clip" {cx} {cy} {r} {spring} {tweened} />
14
+ <Circle slot="clip" {cx} {cy} {r} {spring} {tweened} {...$$restProps} />
15
15
  <slot {id} />
16
16
  </ClipPath>
@@ -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
- /** Unique id for clipPath */ id?: string | undefined;
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(x, { spring, tweened });
19
- let tweened_y = motionStore(y, { spring, tweened });
20
- $: tweened_x.set(x);
21
- $: tweened_y.set(y);
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 { motionStore } from '../stores/motionStore';
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(x1, { spring, tweened });
9
- let tweened_y1 = motionStore(y1, { spring, tweened });
10
- let tweened_x2 = motionStore(x2, { spring, tweened });
11
- let tweened_y2 = motionStore(y2, { spring, tweened });
12
- $: tweened_x1.set(x1);
13
- $: tweened_y1.set(y1);
14
- $: tweened_x2.set(x2);
15
- $: tweened_y2.set(y2);
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>export let id;
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: string;
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
- default: {};
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
- // Properties to override what is used from context
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 is update
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, index}
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 { motionStore, resolveOptions } from '../stores/motionStore';
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(x, resolveOptions('x', { spring, tweened }));
9
- let tweened_y = motionStore(y, resolveOptions('y', { spring, tweened }));
10
- let tweened_width = motionStore(width, resolveOptions('width', { spring, tweened }));
11
- let tweened_height = motionStore(height, resolveOptions('height', { spring, tweened }));
12
- $: tweened_x.set(x);
13
- $: tweened_y.set(y);
14
- $: tweened_width.set(width);
15
- $: tweened_height.set(height);
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 -->
@@ -12,6 +12,6 @@ export let tweened = undefined;
12
12
  </script>
13
13
 
14
14
  <ClipPath {id}>
15
- <Rect slot="clip" {x} {y} {width} {height} {spring} {tweened} />
15
+ <Rect slot="clip" {x} {y} {width} {height} {spring} {tweened} {...$$restProps} />
16
16
  <slot {id} />
17
17
  </ClipPath>
@@ -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
- /** Unique id for clipPath */ id?: string | undefined;
5
+ [x: string]: any;
6
+ id?: string | undefined;
6
7
  x?: number | undefined;
7
8
  y?: number | undefined;
8
9
  width: number;
@@ -5,7 +5,7 @@ const defaultContext = writable({
5
5
  left: 0,
6
6
  data: null,
7
7
  show: () => { },
8
- hide: () => { }
8
+ hide: () => { },
9
9
  });
10
10
  export function tooltipContext() {
11
11
  return getContext(tooltipContextKey) ?? defaultContext;
@@ -27,7 +27,6 @@ import { localPoint } from '../utils/event';
27
27
  import { isScaleBand, scaleInvert } from '../utils/scales';
28
28
  import { quadtreeRects } from '../utils/quadtree';
29
29
  import { createPropertySortFunc, createSortFunc } from 'svelte-ux/utils/sort';
30
- import { firstValue } from '../utils/rect';
31
30
  const dispatch = createEventDispatcher();
32
31
  const { flatData, x, xScale, xGet, xRange, y, yScale, yGet, yRange, width, height, padding } = getContext('LayerCake');
33
32
  /*
@@ -171,7 +170,7 @@ function showTooltip(event, tooltipData) {
171
170
  ...$tooltip,
172
171
  left: snapToDataX ? $xGet(tooltipData) + $padding.left : localX,
173
172
  top: snapToDataY ? $yGet(tooltipData) + $padding.top : localY,
174
- data: tooltipData
173
+ data: tooltipData,
175
174
  };
176
175
  }
177
176
  else {
@@ -204,7 +203,7 @@ $: if (mode === 'quadtree') {
204
203
  quadtree = d3Quadtree()
205
204
  .extent([
206
205
  [0, 0],
207
- [$width, $height]
206
+ [$width, $height],
208
207
  ])
209
208
  .x((d) => {
210
209
  const value = $xGet(d);
@@ -238,10 +237,10 @@ let rects = [];
238
237
  $: if (mode === 'bounds' || mode === 'band') {
239
238
  rects = $flatData
240
239
  .map((d) => {
241
- const xValue = firstValue($xGet(d));
242
- const yValue = firstValue($yGet(d));
243
- const x = Array.isArray(xValue) ? min(xValue) : xValue;
244
- const y = Array.isArray(yValue) ? max(yValue) : yValue;
240
+ const xValue = $xGet(d);
241
+ const yValue = $yGet(d);
242
+ const x = Array.isArray(xValue) ? xValue[0] : xValue;
243
+ const y = Array.isArray(yValue) ? yValue[0] : yValue;
245
244
  const xOffset = isScaleBand($xScale) ? ($xScale.padding() * $xScale.step()) / 2 : 0;
246
245
  const yOffset = isScaleBand($yScale) ? ($yScale.padding() * $yScale.step()) / 2 : 0;
247
246
  const fullWidth = max($xRange) - min($xRange);
@@ -253,7 +252,7 @@ $: if (mode === 'bounds' || mode === 'band') {
253
252
  y: isScaleBand($yScale) ? y - yOffset : min($yRange),
254
253
  width: isScaleBand($xScale) ? $xScale.step() : fullWidth,
255
254
  height: isScaleBand($yScale) ? $yScale.step() : fullHeight,
256
- data: d
255
+ data: d,
257
256
  };
258
257
  }
259
258
  else if (mode === 'bounds') {
@@ -271,7 +270,7 @@ $: if (mode === 'bounds' || mode === 'band') {
271
270
  : isScaleBand($yScale)
272
271
  ? $yScale.step()
273
272
  : max($yRange) - y,
274
- data: d
273
+ data: d,
275
274
  };
276
275
  }
277
276
  })
@@ -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 HighlightLine } from './HighlightLine.svelte';
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';
@@ -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 HighlightLine } from './HighlightLine.svelte';
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.21.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.1",
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.1",
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 {};