layerchart 0.40.2 → 0.41.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.
@@ -113,7 +113,7 @@ onMount(() => {
113
113
  let:data
114
114
  let:flatData
115
115
  >
116
- <!-- Apply fitGeojson using TransformContext instead of GeoContext if `applyTransform` is used -->
116
+ <!-- Apply `fitGeojson` using TransformContext instead of GeoContext if `applyTransform` is used -->
117
117
  {@const initialTransform =
118
118
  geo?.applyTransform && geo?.fitGeojson && geo?.projection
119
119
  ? geoFitObjectTransform(geo.projection(), [width, height], geo.fitGeojson)
@@ -20,6 +20,8 @@ export let lines = false;
20
20
  export let area = false;
21
21
  /** Show bar and pass props to Rect */
22
22
  export let bar = false;
23
+ /** Set to false to disable spring transitions */
24
+ export let motion = true;
23
25
  // TODO: Fix circle points being backwards for stack (see AreaStack)
24
26
  let _points = [];
25
27
  let _lines = [];
@@ -167,7 +169,7 @@ $: if (highlightData) {
167
169
  {#if area}
168
170
  <slot name="area" area={_area}>
169
171
  <Rect
170
- spring
172
+ spring={motion}
171
173
  {..._area}
172
174
  {...typeof area === 'object' ? area : null}
173
175
  class={cls(
@@ -182,7 +184,7 @@ $: if (highlightData) {
182
184
  {#if bar}
183
185
  <slot name="bar" {bar}>
184
186
  <Bar
185
- spring
187
+ spring={motion}
186
188
  x={typeof bar === 'object' ? bar.x : null}
187
189
  y={typeof bar === 'object' ? bar.y : null}
188
190
  inset={typeof bar === 'object' ? bar.inset : null}
@@ -200,7 +202,7 @@ $: if (highlightData) {
200
202
  <slot name="lines" lines={_lines}>
201
203
  {#each _lines as line}
202
204
  <Line
203
- spring
205
+ spring={motion}
204
206
  x1={line.x1}
205
207
  y1={line.y1}
206
208
  x2={line.x2}
@@ -221,7 +223,7 @@ $: if (highlightData) {
221
223
  <!-- TODO: Improve color with stacked data -->
222
224
  {@const fill = $config.r ? $rGet(highlightData) : null}
223
225
  <Circle
224
- spring
226
+ spring={motion}
225
227
  cx={point.x}
226
228
  cy={point.y}
227
229
  r={4}
@@ -61,6 +61,7 @@ declare const __propDef: {
61
61
  [prop: string]: import("svelte/motion").TweenedOptions<unknown> | undefined;
62
62
  } | undefined;
63
63
  }> | undefined;
64
+ /** Set to false to disable spring transitions */ motion?: boolean | undefined;
64
65
  };
65
66
  events: {
66
67
  click: MouseEvent;
@@ -1,9 +1,8 @@
1
1
  <script>import { getContext } from 'svelte';
2
- import { spring } from 'svelte/motion';
3
2
  import { fade } from 'svelte/transition';
4
- import { writable } from 'svelte/store';
5
3
  import { cls } from 'svelte-ux';
6
4
  import { tooltipContext } from './TooltipContext.svelte';
5
+ import { motionStore } from '../stores/motionStore.js';
7
6
  /** `x` position of tooltip. By default uses the pointer/mouse, can also snap to data or an explicit fixed position. */
8
7
  export let x = 'pointer';
9
8
  /** `y` position of tooltip. By default uses the pointer/mouse, can also snap to data or an explicit fixed position. */
@@ -14,16 +13,17 @@ export let xOffset = typeof x === 'number' || typeof y === 'number' ? 0 : 10;
14
13
  export let yOffset = typeof x === 'number' || typeof y === 'number' ? 0 : 10;
15
14
  export let anchor = 'top-left';
16
15
  export let contained = 'container'; // TODO: Support 'window' using getBoundingClientRect()
17
- export let animate = true;
18
16
  export let variant = 'default';
17
+ /** Set to `false` to disable spring transitions */
18
+ export let motion = true;
19
19
  export let header = undefined;
20
20
  export let classes = {};
21
21
  const { padding, xGet, yGet, containerWidth, containerHeight } = getContext('LayerCake');
22
22
  const tooltip = tooltipContext();
23
23
  let tooltipWidth = 0;
24
24
  let tooltipHeight = 0;
25
- const xPos = animate ? spring($tooltip.x) : writable($tooltip.x);
26
- const yPos = animate ? spring($tooltip.y) : writable($tooltip.y);
25
+ const xPos = motionStore($tooltip.x, { spring: motion });
26
+ const yPos = motionStore($tooltip.y, { spring: motion });
27
27
  function alignValue(value, align, addlOffset, tooltipSize) {
28
28
  const alignOffset = align === 'center' ? tooltipSize / 2 : align === 'end' ? tooltipSize : 0;
29
29
  return value + (align === 'end' ? -addlOffset : addlOffset) - alignOffset;
@@ -8,8 +8,8 @@ declare const __propDef: {
8
8
  yOffset?: number | undefined;
9
9
  anchor?: ("center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right") | undefined;
10
10
  contained?: false | "container" | undefined;
11
- animate?: boolean | undefined;
12
11
  variant?: "default" | "none" | "invert" | undefined;
12
+ motion?: boolean | undefined;
13
13
  header?: ((data: any) => any) | undefined;
14
14
  classes?: {
15
15
  root?: string | undefined;
@@ -26,7 +26,7 @@ import Voronoi from './Voronoi.svelte';
26
26
  import { localPoint } from '../utils/event.js';
27
27
  import { isScaleBand, scaleInvert } from '../utils/scales.js';
28
28
  import { quadtreeRects } from '../utils/quadtree.js';
29
- const { flatData, x, xScale, xGet, xRange, y, yScale, yGet, yRange, width, height, padding } = getContext('LayerCake');
29
+ const { flatData, x, xScale, xGet, xRange, y, yScale, yGet, yRange, width, height, containerWidth, containerHeight, padding, } = getContext('LayerCake');
30
30
  /*
31
31
  TODO: Defaults to consider (if possible to detect scale type, which might not be possible)
32
32
  - scaleTime / scaleLinear: bisect
@@ -124,8 +124,22 @@ function showTooltip(e, tooltipData) {
124
124
  // TODO: When using bisect-x/y/band, values should be sorted. Tyipcally are for `x`, but not `y` (and band depends on if x or y scale)
125
125
  if (tooltipData == null) {
126
126
  switch (mode) {
127
- case 'quadtree': {
128
- tooltipData = quadtree.find(localX, localY, radius);
127
+ case 'bisect-x': {
128
+ // `x` value at pointer coordinate
129
+ const xValueAtPoint = scaleInvert($xScale, localX - $padding.left);
130
+ const index = bisectX($flatData, xValueAtPoint, 1);
131
+ const previousValue = $flatData[index - 1];
132
+ const currentValue = $flatData[index];
133
+ tooltipData = findData(previousValue, currentValue, xValueAtPoint, $x);
134
+ break;
135
+ }
136
+ case 'bisect-y': {
137
+ // `y` value at pointer coordinate
138
+ const yValueAtPoint = scaleInvert($yScale, localY - $padding.top);
139
+ const index = bisectY($flatData, yValueAtPoint, 1);
140
+ const previousValue = $flatData[index - 1];
141
+ const currentValue = $flatData[index];
142
+ tooltipData = findData(previousValue, currentValue, yValueAtPoint, $y);
129
143
  break;
130
144
  }
131
145
  case 'bisect-band': {
@@ -153,22 +167,8 @@ function showTooltip(e, tooltipData) {
153
167
  }
154
168
  break;
155
169
  }
156
- case 'bisect-x': {
157
- // `x` value at pointer coordinate
158
- const xValueAtPoint = scaleInvert($xScale, localX - $padding.left);
159
- const index = bisectX($flatData, xValueAtPoint, 1);
160
- const previousValue = $flatData[index - 1];
161
- const currentValue = $flatData[index];
162
- tooltipData = findData(previousValue, currentValue, xValueAtPoint, $x);
163
- break;
164
- }
165
- case 'bisect-y': {
166
- // `y` value at pointer coordinate
167
- const yValueAtPoint = scaleInvert($yScale, localY - $padding.top);
168
- const index = bisectY($flatData, yValueAtPoint, 1);
169
- const previousValue = $flatData[index - 1];
170
- const currentValue = $flatData[index];
171
- tooltipData = findData(previousValue, currentValue, yValueAtPoint, $y);
170
+ case 'quadtree': {
171
+ tooltipData = quadtree.find(localX, localY, radius);
172
172
  break;
173
173
  }
174
174
  }
@@ -273,86 +273,85 @@ $: if (mode === 'bounds' || mode === 'band') {
273
273
  })
274
274
  .sort(sortFunc('x'));
275
275
  }
276
+ $: triggerPointEvents = ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode);
276
277
  </script>
277
278
 
278
- {#if ['bisect-x', 'bisect-y', 'bisect-band', 'quadtree'].includes(mode)}
279
- <div
280
- style:width="{$width}px"
281
- style:height="{$height}px"
282
- style:top="{$padding.top}px"
283
- style:left="{$padding.left}px"
284
- class={cls(
285
- 'tooltip-trigger absolute touch-none',
286
- debug && 'bg-danger/10 outline outline-danger'
287
- )}
288
- on:pointerenter={showTooltip}
289
- on:pointermove={showTooltip}
290
- on:pointerleave={hideTooltip}
291
- on:click={(e) => {
279
+ <div
280
+ style:width="{$width}px"
281
+ style:height="{$height}px"
282
+ style:top="{$padding.top}px"
283
+ style:left="{$padding.left}px"
284
+ class={cls(
285
+ 'tooltip-trigger absolute touch-none',
286
+ debug && triggerPointEvents && 'bg-danger/10 outline outline-danger'
287
+ )}
288
+ on:pointerenter={triggerPointEvents ? showTooltip : undefined}
289
+ on:pointermove={triggerPointEvents ? showTooltip : undefined}
290
+ on:pointerleave={triggerPointEvents ? hideTooltip : undefined}
291
+ on:click={(e) => {
292
+ if (triggerPointEvents) {
292
293
  onClick({ data: $tooltip?.data });
293
- }}
294
+ }
295
+ }}
296
+ >
297
+ <!-- Rendering slot within tooltip-trigger allows pointer events to bubble up (ex. Brush) -->
298
+ <div
299
+ class="absolute"
300
+ style:width="{$containerWidth}px"
301
+ style:height="{$containerHeight}px"
302
+ style:top="{-$padding.top}px"
303
+ style:left="{-$padding.left}px"
294
304
  >
295
- <!-- Rendering slot within tooltip-trigger allows pointer events to bubble up (ex. Brush) -->
296
- <div
297
- class="absolute w-full h-full"
298
- style:top="-{$padding.top}px"
299
- style:left="-{$padding.left}px"
300
- >
301
- <slot tooltip={$tooltip} />
302
- </div>
303
- </div>
304
- {:else if mode === 'voronoi'}
305
- <slot tooltip={$tooltip} />
306
- <Svg>
307
- <Voronoi
308
- on:pointerenter={(e) => showTooltip(e.detail.event, e.detail.data)}
309
- on:pointermove={(e) => showTooltip(e.detail.event, e.detail.data)}
310
- on:pointerleave={hideTooltip}
311
- on:click={(e) => {
312
- onClick({ data: e.detail.data });
313
- }}
314
- classes={{ path: cls(debug && 'fill-danger/10 stroke-danger') }}
315
- />
316
- </Svg>
317
- {:else if mode === 'bounds' || mode === 'band'}
318
- <slot tooltip={$tooltip} />
319
- <Svg>
320
- <g class="tooltip-rects">
321
- {#each rects as rect}
322
- <rect
323
- x={rect.x}
324
- y={rect.y}
325
- width={rect.width}
326
- height={rect.height}
327
- class={cls(debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent')}
328
- on:pointerenter={(e) => showTooltip(e, rect.data)}
329
- on:pointermove={(e) => showTooltip(e, rect.data)}
305
+ <slot tooltip={$tooltip} />
306
+
307
+ {#if mode === 'voronoi'}
308
+ <Svg>
309
+ <Voronoi
310
+ on:pointerenter={(e) => showTooltip(e.detail.event, e.detail.data)}
311
+ on:pointermove={(e) => showTooltip(e.detail.event, e.detail.data)}
330
312
  on:pointerleave={hideTooltip}
331
313
  on:click={(e) => {
332
- onClick({ data: rect.data });
314
+ onClick({ data: e.detail.data });
333
315
  }}
316
+ classes={{ path: cls(debug && 'fill-danger/10 stroke-danger') }}
334
317
  />
335
- {/each}
336
- </g>
337
- </Svg>
338
- {:else}
339
- <slot tooltip={$tooltip} />
340
- {/if}
341
-
342
- {#if mode === 'quadtree' && debug}
343
- <Svg pointerEvents={false}>
344
- <ChartClipPath>
345
- <g class="tooltip-quadtree">
346
- {#each quadtreeRects(quadtree, false) as rect}
347
- <rect
348
- x={rect.x}
349
- y={rect.y}
350
- width={rect.width}
351
- height={rect.height}
352
- class={cls(debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent')}
353
- />
354
- {/each}
355
- </g>
356
- </ChartClipPath>
357
- </Svg>
358
- {/if}
318
+ </Svg>
319
+ {:else if mode === 'bounds' || mode === 'band'}
320
+ <Svg>
321
+ <g class="tooltip-rects">
322
+ {#each rects as rect}
323
+ <rect
324
+ x={rect.x}
325
+ y={rect.y}
326
+ width={rect.width}
327
+ height={rect.height}
328
+ class={cls(debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent')}
329
+ on:pointerenter={(e) => showTooltip(e, rect.data)}
330
+ on:pointermove={(e) => showTooltip(e, rect.data)}
331
+ on:pointerleave={hideTooltip}
332
+ on:click={(e) => {
333
+ onClick({ data: rect.data });
334
+ }}
335
+ />
336
+ {/each}
337
+ </g>
338
+ </Svg>
339
+ {:else if mode === 'quadtree' && debug}
340
+ <Svg pointerEvents={false}>
341
+ <ChartClipPath>
342
+ <g class="tooltip-quadtree">
343
+ {#each quadtreeRects(quadtree, false) as rect}
344
+ <rect
345
+ x={rect.x}
346
+ y={rect.y}
347
+ width={rect.width}
348
+ height={rect.height}
349
+ class={cls(debug ? 'fill-danger/10 stroke-danger' : 'fill-transparent')}
350
+ />
351
+ {/each}
352
+ </g>
353
+ </ChartClipPath>
354
+ </Svg>
355
+ {/if}
356
+ </div>
357
+ </div>
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.40.2",
7
+ "version": "0.41.0",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.5",
10
10
  "@mdi/js": "^7.4.47",