layerchart 0.30.2 → 0.31.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.
@@ -5,7 +5,7 @@ import { interpolatePath } from 'd3-interpolate-path';
5
5
  import { cls } from 'svelte-ux';
6
6
  import { motionStore } from '../stores/motionStore';
7
7
  import Spline from './Spline.svelte';
8
- const { data: contextData, xGet, yGet, yRange } = getContext('LayerCake');
8
+ const { data: contextData, xScale, yScale, xGet, yGet, yRange } = getContext('LayerCake');
9
9
  /** Override data instead of using context */
10
10
  export let data = undefined;
11
11
  /** Pass `<path d={...} />` explicitly instead of calculating from data / context */
@@ -30,13 +30,13 @@ $: tweened_d = motionStore('', { tweened: tweenedOptions });
30
30
  $: {
31
31
  const path = radial
32
32
  ? areaRadial()
33
- .angle(x ?? $xGet)
34
- .innerRadius(y0 ?? max($yRange))
35
- .outerRadius(y1 ?? $yGet)
33
+ .angle((d) => (x ? $xScale(x(d)) : $xGet(d)))
34
+ .innerRadius((d) => (y0 ? $yScale(y0(d)) : max($yRange)))
35
+ .outerRadius((d) => (y1 ? $yScale(y1(d)) : $yGet(d)))
36
36
  : d3Area()
37
- .x(x ?? $xGet)
38
- .y0(y0 ?? max($yRange))
39
- .y1(y1 ?? $yGet);
37
+ .x((d) => (x ? $xScale(x(d)) : $xGet(d)))
38
+ .y0((d) => (y0 ? $yScale(y0(d)) : max($yRange)))
39
+ .y1((d) => (y1 ? $yScale(y1(d)) : $yGet(d)));
40
40
  if (curve)
41
41
  path.curve(curve);
42
42
  if (defined)
@@ -47,7 +47,7 @@ $: {
47
47
  </script>
48
48
 
49
49
  {#if line}
50
- <Spline {data} {curve} {defined} {tweened} {...typeof line === 'object' ? line : null} />
50
+ <Spline {data} y={y1} {curve} {defined} {tweened} {...typeof line === 'object' ? line : null} />
51
51
  {/if}
52
52
 
53
53
  <path
@@ -1,7 +1,7 @@
1
1
  <script>import { getContext } from 'svelte';
2
2
  import Area from './Area.svelte';
3
3
  import Spline from './Spline.svelte';
4
- const { data, yScale, rGet } = getContext('LayerCake');
4
+ const { data, rGet } = getContext('LayerCake');
5
5
  export let curve = undefined;
6
6
  export let defined = undefined;
7
7
  export let opacity = 0.3;
@@ -16,7 +16,7 @@ $: lineData = [...$data].reverse();
16
16
  {#each lineData as seriesData}
17
17
  <Spline
18
18
  data={seriesData}
19
- y={(d) => $yScale(d[1])}
19
+ y={(d) => d[1]}
20
20
  stroke={$rGet(seriesData)}
21
21
  {curve}
22
22
  {defined}
@@ -27,17 +27,19 @@ $: lineData = [...$data].reverse();
27
27
  </g>
28
28
  {/if}
29
29
 
30
- <g class="area-group">
31
- {#each $data as seriesData}
32
- <Area
33
- data={seriesData}
34
- y0={(d) => $yScale(d[0])}
35
- y1={(d) => $yScale(d[1])}
36
- fill={$rGet(seriesData)}
37
- {curve}
38
- {defined}
39
- {opacity}
40
- {tweened}
41
- />
42
- {/each}
43
- </g>
30
+ <slot data={$data}>
31
+ <g class="area-group">
32
+ {#each $data as seriesData}
33
+ <Area
34
+ data={seriesData}
35
+ y0={(d) => d[0]}
36
+ y1={(d) => d[1]}
37
+ fill={$rGet(seriesData)}
38
+ {curve}
39
+ {defined}
40
+ {opacity}
41
+ {tweened}
42
+ />
43
+ {/each}
44
+ </g>
45
+ </slot>
@@ -14,7 +14,11 @@ declare const __propDef: {
14
14
  events: {
15
15
  [evt: string]: CustomEvent<any>;
16
16
  };
17
- slots: {};
17
+ slots: {
18
+ default: {
19
+ data: any;
20
+ };
21
+ };
18
22
  };
19
23
  export type AreaStackProps = typeof __propDef.props;
20
24
  export type AreaStackEvents = typeof __propDef.events;
@@ -23,7 +23,7 @@ $: tick().then(() => {
23
23
  cx={$tweened_cx}
24
24
  cy={$tweened_cy}
25
25
  r={$tweened_r}
26
- class={cls($$props.fill === undefined && 'fill-surface-content')}
26
+ class={cls($$props.fill == null && 'fill-surface-content')}
27
27
  {...$$restProps}
28
28
  on:click
29
29
  on:mousemove
@@ -29,7 +29,7 @@ $: tick().then(() => {
29
29
  y={$tweened_y}
30
30
  width={$tweened_width}
31
31
  height={$tweened_height}
32
- class={cls($$props.fill === undefined && 'fill-surface-content')}
32
+ class={cls($$props.fill == null && 'fill-surface-content')}
33
33
  {...$$restProps}
34
34
  on:click
35
35
  on:mouseover
@@ -9,7 +9,7 @@ import { interpolatePath } from 'd3-interpolate-path';
9
9
  import { cls } from 'svelte-ux';
10
10
  import { motionStore } from '../stores/motionStore';
11
11
  import Group from './Group.svelte';
12
- const { data: contextData, xGet, yGet } = getContext('LayerCake');
12
+ const { data: contextData, xScale, yScale, xGet, yGet } = getContext('LayerCake');
13
13
  /** Override data instead of using context */
14
14
  export let data = undefined;
15
15
  /** Pass `<path d={...} />` explicitly instead of calculating from data / context */
@@ -41,11 +41,11 @@ $: tweened_d = motionStore('', { tweened: tweenedOptions });
41
41
  $: {
42
42
  const path = radial
43
43
  ? lineRadial()
44
- .angle(x ?? $xGet)
45
- .radius(y ?? $yGet)
44
+ .angle((d) => (x ? $xScale(x(d)) : $xGet(d)))
45
+ .radius((d) => (y ? $yScale(y(d)) : $yGet(d)))
46
46
  : d3Line()
47
- .x(x ?? $xGet)
48
- .y(y ?? $yGet);
47
+ .x((d) => (x ? $xScale(x(d)) : $xGet(d)))
48
+ .y((d) => (y ? $yScale(y(d)) : $yGet(d)));
49
49
  if (curve)
50
50
  path.curve(curve);
51
51
  if (defined)
@@ -18,11 +18,11 @@ function setTooltipContext(tooltip) {
18
18
  <script>import { raise } from 'layercake';
19
19
  import { writable } from 'svelte/store';
20
20
  import { bisector, max, min } from 'd3-array';
21
- import { Delaunay } from 'd3-delaunay';
22
21
  import { quadtree as d3Quadtree } from 'd3-quadtree';
23
- import { sortFunc } from 'svelte-ux';
22
+ import { cls, sortFunc } from 'svelte-ux';
24
23
  import { Svg, Html } from './Chart.svelte';
25
24
  import ChartClipPath from './ChartClipPath.svelte';
25
+ import Voronoi from './Voronoi.svelte';
26
26
  import { localPoint } from '../utils/event';
27
27
  import { isScaleBand, scaleInvert } from '../utils/scales';
28
28
  import { quadtreeRects } from '../utils/quadtree';
@@ -187,20 +187,6 @@ function hideTooltip() {
187
187
  $tooltip = { ...$tooltip, data: null };
188
188
  });
189
189
  }
190
- let points;
191
- let voronoi;
192
- $: if (mode === 'voronoi') {
193
- points = $flatData.map((d) => {
194
- const xValue = $xGet(d);
195
- const yValue = $yGet(d);
196
- const x = Array.isArray(xValue) ? min(xValue) : xValue;
197
- const y = Array.isArray(yValue) ? min(yValue) : yValue;
198
- const point = [x, y];
199
- point.data = d;
200
- return point;
201
- });
202
- voronoi = Delaunay.from(points).voronoi([0, 0, Math.max($width, 0), Math.max($height, 0)]); // width and/or height can sometimes be negative (when loading data remotely and updately)
203
- }
204
190
  let quadtree;
205
191
  $: if (mode === 'quadtree') {
206
192
  quadtree = d3Quadtree()
@@ -287,10 +273,9 @@ $: if (mode === 'bounds' || mode === 'band') {
287
273
  {#if ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode)}
288
274
  <Html>
289
275
  <div
290
- class="tooltip-trigger absolute"
291
276
  style:width="{$width}px"
292
277
  style:height="{$height}px"
293
- style:background={debug ? 'rgba(255 0 0 / .1)' : undefined}
278
+ class={cls('tooltip-trigger absolute', debug && 'bg-danger/10 outline outline-danger')}
294
279
  on:touchstart={showTooltip}
295
280
  on:touchmove={showTooltip}
296
281
  on:mousemove={showTooltip}
@@ -302,21 +287,14 @@ $: if (mode === 'bounds' || mode === 'band') {
302
287
  </Html>
303
288
  {:else if mode === 'voronoi'}
304
289
  <Svg>
305
- {#each points as point, i}
306
- <g class="tooltip-voronoi">
307
- <path
308
- d={voronoi.renderCell(i)}
309
- style:fill={debug ? 'red' : 'transparent'}
310
- style:fill-opacity={debug ? 0.1 : 0}
311
- style:stroke={debug ? 'red' : 'transparent'}
312
- on:mousemove={(e) => showTooltip(e, point.data)}
313
- on:mouseleave={hideTooltip}
314
- on:click={(e) => {
315
- onClick({ data: point.data });
316
- }}
317
- />
318
- </g>
319
- {/each}
290
+ <Voronoi
291
+ on:mousemove={(e) => showTooltip(e.detail.event, e.detail.point.data)}
292
+ on:mouseleave={hideTooltip}
293
+ on:click={(e) => {
294
+ onClick({ data: e.detail.point.data });
295
+ }}
296
+ classes={{ path: cls(debug && 'fill-danger/10 stroke-danger') }}
297
+ />
320
298
  </Svg>
321
299
  {:else if mode === 'bounds' || mode === 'band'}
322
300
  <Svg>
@@ -327,9 +305,7 @@ $: if (mode === 'bounds' || mode === 'band') {
327
305
  y={rect.y}
328
306
  width={rect.width}
329
307
  height={rect.height}
330
- style:fill={debug ? 'red' : 'transparent'}
331
- style:fill-opacity={debug ? 0.1 : 0}
332
- style:stroke={debug ? 'red' : 'transparent'}
308
+ class={cls(debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent')}
333
309
  on:mousemove={(e) => showTooltip(e, rect.data)}
334
310
  on:mouseleave={hideTooltip}
335
311
  on:click={(e) => {
@@ -351,9 +327,7 @@ $: if (mode === 'bounds' || mode === 'band') {
351
327
  y={rect.y}
352
328
  width={rect.width}
353
329
  height={rect.height}
354
- style:fill={debug ? 'red' : 'transparent'}
355
- style:fill-opacity={debug ? 0.1 : 0}
356
- stroke="red"
330
+ class={cls(debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent')}
357
331
  />
358
332
  {/each}
359
333
  </g>
@@ -0,0 +1,33 @@
1
+ <script>import { createEventDispatcher, getContext } from 'svelte';
2
+ import { draw as _drawTransition } from 'svelte/transition';
3
+ import { Delaunay } from 'd3-delaunay';
4
+ import { min } from 'd3-array';
5
+ import { cls } from 'svelte-ux';
6
+ const { flatData, xGet, yGet, width, height } = getContext('LayerCake');
7
+ /** Override data instead of using context */
8
+ export let data = undefined;
9
+ export let classes = {};
10
+ const dispatch = createEventDispatcher();
11
+ $: points = (data ?? $flatData).map((d) => {
12
+ const xValue = $xGet(d);
13
+ const yValue = $yGet(d);
14
+ const x = Array.isArray(xValue) ? min(xValue) : xValue;
15
+ const y = Array.isArray(yValue) ? min(yValue) : yValue;
16
+ const point = [x, y];
17
+ point.data = d;
18
+ return point;
19
+ });
20
+ $: voronoi = Delaunay.from(points).voronoi([0, 0, Math.max($width, 0), Math.max($height, 0)]); // width and/or height can sometimes be negative (when loading data remotely and updately)
21
+ </script>
22
+
23
+ <g {...$$restProps} class={cls(classes.root, $$props.class)}>
24
+ {#each points as point, i}
25
+ <path
26
+ d={voronoi.renderCell(i)}
27
+ class={cls('fill-transparent', classes.path)}
28
+ on:mousemove={(e) => dispatch('mousemove', { point, event: e })}
29
+ on:mouseleave
30
+ on:click={(e) => dispatch('click', { point })}
31
+ />
32
+ {/each}
33
+ </g>
@@ -0,0 +1,34 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ [x: string]: any;
5
+ data?: any;
6
+ classes?: {
7
+ root?: string | undefined;
8
+ path?: string | undefined;
9
+ } | undefined;
10
+ };
11
+ events: {
12
+ mouseleave: MouseEvent;
13
+ click: CustomEvent<{
14
+ point: {
15
+ data: any;
16
+ };
17
+ }>;
18
+ mousemove: CustomEvent<{
19
+ point: {
20
+ data: any;
21
+ };
22
+ event: MouseEvent;
23
+ }>;
24
+ } & {
25
+ [evt: string]: CustomEvent<any>;
26
+ };
27
+ slots: {};
28
+ };
29
+ export type VoronoiProps = typeof __propDef.props;
30
+ export type VoronoiEvents = typeof __propDef.events;
31
+ export type VoronoiSlots = typeof __propDef.slots;
32
+ export default class Voronoi extends SvelteComponentTyped<VoronoiProps, VoronoiEvents, VoronoiSlots> {
33
+ }
34
+ export {};
@@ -47,4 +47,5 @@ export { default as TooltipItem } from './TooltipItem.svelte';
47
47
  export { default as TooltipSeparator } from './TooltipSeparator.svelte';
48
48
  export { default as Tree } from './Tree.svelte';
49
49
  export { default as Treemap } from './Treemap.svelte';
50
+ export { default as Voronoi } from './Voronoi.svelte';
50
51
  export { default as Zoom } from './Zoom.svelte';
@@ -47,4 +47,5 @@ export { default as TooltipItem } from './TooltipItem.svelte';
47
47
  export { default as TooltipSeparator } from './TooltipSeparator.svelte';
48
48
  export { default as Tree } from './Tree.svelte';
49
49
  export { default as Treemap } from './Treemap.svelte';
50
+ export { default as Voronoi } from './Voronoi.svelte';
50
51
  export { default as Zoom } from './Zoom.svelte';
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "author": "Sean Lynch <techniq35@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": "techniq/layerchart",
7
- "version": "0.30.2",
7
+ "version": "0.31.0",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.1",
10
10
  "@mdi/js": "^7.4.47",