layerchart 0.99.1 → 0.99.3

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.
@@ -17,23 +17,16 @@
17
17
  // https://svelte.dev/repl/09711e43a1264ba18945d7db7cab9335?version=3.38.2
18
18
  // https://codepen.io/simeydotme/pen/rrOEmO/
19
19
 
20
- import { onDestroy, tick } from 'svelte';
21
- import type { SVGAttributes } from 'svelte/elements';
20
+ import { tick, type ComponentProps } from 'svelte';
22
21
  import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
23
22
  import { arc as d3arc } from 'd3-shape';
24
23
  import { scaleLinear } from 'd3-scale';
25
- import { min, max } from 'd3-array';
26
- import { merge } from 'lodash-es';
27
24
 
28
- import { objectId } from '@layerstack/utils/object';
29
-
30
- import { getRenderContext } from './Chart.svelte';
31
25
  import { chartContext } from './ChartContext.svelte';
32
26
  import { motionStore } from '../stores/motionStore.js';
33
27
  import { degreesToRadians } from '../utils/math.js';
34
28
  import type { TooltipContextValue } from './tooltip/TooltipContext.svelte';
35
- import { getCanvasContext } from './layout/Canvas.svelte';
36
- import { renderPathData, type ComputedStylesOptions } from '../utils/canvas.js';
29
+ import Spline from './Spline.svelte';
37
30
 
38
31
  export let spring: boolean | Parameters<typeof springStore>[1] = undefined;
39
32
  export let tweened: boolean | Parameters<typeof tweenedStore>[1] = undefined;
@@ -85,13 +78,13 @@
85
78
 
86
79
  export let fill: string | undefined = undefined;
87
80
  export let fillOpacity: number | undefined = undefined;
88
- export let stroke: string | undefined = undefined;
81
+ export let stroke: string | undefined = 'none';
89
82
  export let strokeWidth: number | undefined = undefined;
90
83
 
91
84
  let className: string | undefined = undefined;
92
85
  export { className as class };
93
86
 
94
- export let track: boolean | SVGAttributes<SVGPathElement> = false;
87
+ export let track: boolean | Partial<ComponentProps<Spline>> = false;
95
88
 
96
89
  export let onclick: ((e: MouseEvent) => void) | undefined = undefined;
97
90
  export let onpointerenter: ((e: PointerEvent) => void) | undefined = undefined;
@@ -200,118 +193,50 @@
200
193
  */
201
194
  export let data: any = undefined;
202
195
 
203
- const renderContext = getRenderContext();
204
- const canvasContext = getCanvasContext();
205
-
206
- function render(
207
- ctx: CanvasRenderingContext2D,
208
- styleOverrides: ComputedStylesOptions | undefined
209
- ) {
210
- ctx.translate(xOffset, yOffset);
211
-
212
- // Track
213
- const trackProps = { ...(typeof track === 'object' ? track : null) };
214
- renderPathData(ctx, trackArc(), {
215
- styles: {
216
- fill: trackProps['fill'] ?? undefined,
217
- fillOpacity: trackProps['fill-opacity'] ?? undefined,
218
- stroke: trackProps['stroke'] ?? undefined,
219
- strokeWidth: trackProps['stroke-width'] ?? undefined,
220
- opacity: trackProps['opacity'] ?? undefined,
221
- },
222
- classes: trackProps.class ?? undefined,
223
- });
224
-
225
- // Arc
226
- renderPathData(
227
- ctx,
228
- arc(),
229
- styleOverrides
230
- ? merge({ styles: { strokeWidth } }, styleOverrides)
231
- : {
232
- styles: { fill, fillOpacity, stroke, strokeWidth },
233
- classes: className,
234
- }
235
- );
236
- }
237
-
238
- // TODO: Use objectId to work around Svelte 4 reactivity issue (even when memoizing gradients)
239
- $: fillKey = fill && typeof fill === 'object' ? objectId(fill) : fill;
240
- $: strokeKey = stroke && typeof stroke === 'object' ? objectId(stroke) : stroke;
241
-
242
- $: if (renderContext === 'canvas') {
243
- // Redraw when props change
244
- arc && trackArc && fillKey && fillOpacity && strokeKey && strokeWidth && className;
245
- canvasContext.invalidate();
246
- }
247
-
248
- // Hide `tooltip` reactivity
249
- function _onPointerEnter(e: PointerEvent) {
196
+ function onPointerEnter(e: PointerEvent) {
250
197
  onpointerenter?.(e);
251
198
  tooltip?.show(e, data);
252
199
  }
253
- function _onPointerMove(e: PointerEvent) {
200
+ function onPointerMove(e: PointerEvent) {
254
201
  onpointermove?.(e);
255
202
  tooltip?.show(e, data);
256
203
  }
257
- function _onPointerLeave(e: PointerEvent) {
204
+ function onPointerLeave(e: PointerEvent) {
258
205
  onpointerleave?.(e);
259
206
  tooltip?.hide();
260
207
  }
261
-
262
- let canvasUnregister: ReturnType<typeof canvasContext.register>;
263
- $: if (renderContext === 'canvas') {
264
- canvasUnregister = canvasContext.register({
265
- name: 'Arc',
266
- render,
267
- events: {
268
- click: onclick,
269
- pointerenter: _onPointerEnter,
270
- pointermove: _onPointerMove,
271
- pointerleave: _onPointerLeave,
272
- },
273
- });
274
- }
275
-
276
- onDestroy(() => {
277
- if (renderContext === 'canvas') {
278
- canvasUnregister();
279
- }
280
- });
281
208
  </script>
282
209
 
283
- {#if renderContext === 'svg'}
284
- {#if track}
285
- <path
286
- d={trackArc()}
287
- class="track"
288
- bind:this={trackArcEl}
289
- {...typeof track === 'object' ? track : null}
290
- />
291
- {/if}
292
-
293
- <!-- svelte-ignore a11y-no-static-element-interactions -->
294
- <path
295
- d={arc()}
296
- transform="translate({xOffset}, {yOffset})"
297
- {fill}
298
- fill-opacity={fillOpacity}
299
- {stroke}
300
- stroke-width={strokeWidth}
301
- class={className}
302
- {...$$restProps}
303
- on:click={onclick}
304
- on:pointerenter={onpointerenter}
305
- on:pointermove={_onPointerMove}
306
- on:pointerleave={_onPointerLeave}
307
- on:touchmove={(e) => {
308
- if (tooltip) {
309
- // Prevent touch to not interfer with pointer when using tooltip
310
- e.preventDefault();
311
- }
312
- }}
313
- on:touchmove
210
+ {#if track}
211
+ <Spline
212
+ pathData={trackArc()}
213
+ class="track"
214
+ stroke="none"
215
+ bind:pathEl={trackArcEl}
216
+ {...typeof track === 'object' ? track : null}
314
217
  />
315
218
  {/if}
316
219
 
220
+ <Spline
221
+ pathData={arc()}
222
+ transform="translate({xOffset}, {yOffset})"
223
+ {fill}
224
+ fill-opacity={fillOpacity}
225
+ {stroke}
226
+ stroke-width={strokeWidth}
227
+ class={className}
228
+ {...$$restProps}
229
+ {onclick}
230
+ onpointerenter={onPointerEnter}
231
+ onpointermove={onPointerMove}
232
+ onpointerleave={onPointerLeave}
233
+ ontouchmove={(e) => {
234
+ if (tooltip) {
235
+ // Prevent touch to not interfer with pointer when using tooltip
236
+ e.preventDefault();
237
+ }
238
+ }}
239
+ on:touchmove
240
+ />
241
+
317
242
  <slot value={$tweened_value} centroid={trackArcCentroid} {boundingBox} />
@@ -411,13 +411,15 @@
411
411
  showTooltip(e);
412
412
  }
413
413
  }}
414
- on:pointermove={triggerPointerEvents ? showTooltip : undefined}
415
- on:pointerleave={(e) => {
416
- isHoveringTooltip = false;
414
+ on:pointermove={(e) => {
417
415
  if (triggerPointerEvents) {
418
- hideTooltip();
416
+ showTooltip(e);
419
417
  }
420
418
  }}
419
+ on:pointerleave={(e) => {
420
+ isHoveringTooltip = false;
421
+ hideTooltip();
422
+ }}
421
423
  on:click={(e) => {
422
424
  if (triggerPointerEvents) {
423
425
  onclick(e, { data: $tooltip?.data });
@@ -80,10 +80,8 @@ function render(ctx, render, styleOptions = {}) {
80
80
  (styleOptions.styles?.fill instanceof CanvasGradient ||
81
81
  !styleOptions.styles?.fill?.includes('var'))
82
82
  ? styleOptions.styles.fill
83
- : ['none', DEFAULT_FILL].includes(computedStyles?.fill)
84
- ? null
85
- : computedStyles?.fill;
86
- if (fill) {
83
+ : computedStyles?.fill;
84
+ if (fill && !['none', DEFAULT_FILL].includes(fill)) {
87
85
  const currentGlobalAlpha = ctx.globalAlpha;
88
86
  const fillOpacity = Number(computedStyles?.fillOpacity);
89
87
  const opacity = Number(computedStyles?.opacity);
@@ -99,10 +97,8 @@ function render(ctx, render, styleOptions = {}) {
99
97
  (styleOptions.styles?.stroke instanceof CanvasGradient ||
100
98
  !styleOptions.styles?.stroke?.includes('var'))
101
99
  ? styleOptions.styles?.stroke
102
- : computedStyles?.stroke === 'none'
103
- ? null
104
- : computedStyles?.stroke;
105
- if (stroke) {
100
+ : computedStyles?.stroke;
101
+ if (stroke && !['none'].includes(stroke)) {
106
102
  ctx.lineWidth =
107
103
  typeof computedStyles?.strokeWidth === 'string'
108
104
  ? Number(computedStyles?.strokeWidth?.replace('px', ''))
@@ -18,8 +18,8 @@ export function radiansToDegrees(radians) {
18
18
  */
19
19
  export function polarToCartesian(angle, radius) {
20
20
  return {
21
- x: radius * Math.cos(angle),
22
- y: radius * Math.sin(angle),
21
+ x: Math.cos(angle) * radius,
22
+ y: Math.sin(angle) * radius,
23
23
  };
24
24
  }
25
25
  /**
@@ -27,7 +27,7 @@ export function polarToCartesian(angle, radius) {
27
27
  */
28
28
  export function cartesianToPolar(x, y) {
29
29
  let radians = Math.atan2(y, x);
30
- radians += Math.PI / 2;
30
+ radians += Math.PI / 2; // shift 90 degrees to align 0deg at 12 o'clock
31
31
  // Ensure the result is between 0 and 2π
32
32
  if (radians < 0) {
33
33
  radians += 2 * Math.PI;
package/package.json CHANGED
@@ -4,12 +4,12 @@
4
4
  "author": "Sean Lynch <techniq35@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": "techniq/layerchart",
7
- "version": "0.99.1",
7
+ "version": "0.99.3",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.27.12",
10
10
  "@mdi/js": "^7.4.47",
11
11
  "@rollup/plugin-dsv": "^3.0.5",
12
- "@sveltejs/adapter-cloudflare": "^5.0.2",
12
+ "@sveltejs/adapter-cloudflare": "^4.9.0",
13
13
  "@sveltejs/kit": "^2.17.1",
14
14
  "@sveltejs/package": "^2.3.10",
15
15
  "@sveltejs/vite-plugin-svelte": "^5.0.3",