layerchart 0.93.2 → 0.93.4
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/Circle.svelte +3 -5
- package/dist/components/Highlight.svelte +1 -6
- package/dist/components/charts/AreaChart.svelte +43 -40
- package/dist/components/charts/LineChart.svelte +43 -40
- package/dist/components/charts/ScatterChart.svelte +22 -14
- package/dist/components/layout/Canvas.svelte +6 -1
- package/dist/utils/canvas.js +20 -3
- package/dist/utils/color.d.ts +7 -2
- package/dist/utils/color.js +9 -4
- package/package.json +1 -1
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { motionStore } from '../stores/motionStore.js';
|
|
9
9
|
import { getCanvasContext } from './layout/Canvas.svelte';
|
|
10
|
-
import {
|
|
11
|
-
import { renderPathData, type ComputedStylesOptions } from '../utils/canvas.js';
|
|
10
|
+
import { renderCircle, type ComputedStylesOptions } from '../utils/canvas.js';
|
|
12
11
|
|
|
13
12
|
export let cx: number = 0;
|
|
14
13
|
export let initialCx = cx;
|
|
@@ -53,10 +52,9 @@
|
|
|
53
52
|
ctx: CanvasRenderingContext2D,
|
|
54
53
|
styleOverrides: ComputedStylesOptions | undefined
|
|
55
54
|
) {
|
|
56
|
-
|
|
57
|
-
renderPathData(
|
|
55
|
+
renderCircle(
|
|
58
56
|
ctx,
|
|
59
|
-
|
|
57
|
+
{ cx: $tweened_cx, cy: $tweened_cy, r: $tweened_r },
|
|
60
58
|
styleOverrides
|
|
61
59
|
? merge({ styles: { strokeWidth } }, styleOverrides)
|
|
62
60
|
: {
|
|
@@ -368,13 +368,8 @@
|
|
|
368
368
|
<slot name="bar" {bar}>
|
|
369
369
|
<Bar
|
|
370
370
|
spring={motion}
|
|
371
|
-
x={typeof bar === 'object' ? bar.x : undefined}
|
|
372
|
-
y={typeof bar === 'object' ? bar.y : undefined}
|
|
373
|
-
insets={typeof bar === 'object' ? bar.insets : undefined}
|
|
374
|
-
stroke={typeof bar === 'object' ? bar.stroke : undefined}
|
|
375
|
-
strokeWidth={typeof bar === 'object' ? bar.strokeWidth : undefined}
|
|
376
|
-
radius={typeof bar === 'object' ? bar.radius : undefined}
|
|
377
371
|
bar={highlightData}
|
|
372
|
+
{...typeof bar === 'object' ? bar : null}
|
|
378
373
|
class={cls(
|
|
379
374
|
// @ts-expect-error
|
|
380
375
|
!bar.fill && 'fill-primary',
|
|
@@ -346,15 +346,15 @@
|
|
|
346
346
|
{/if}
|
|
347
347
|
</slot>
|
|
348
348
|
|
|
349
|
-
<
|
|
349
|
+
<ChartClipPath disabled={!brush}>
|
|
350
|
+
<slot name="belowMarks" {...slotProps} />
|
|
350
351
|
|
|
351
|
-
|
|
352
|
-
<ChartClipPath disabled={!brush}>
|
|
352
|
+
<slot name="marks" {...slotProps}>
|
|
353
353
|
{#each visibleSeries as s, i (s.key)}
|
|
354
354
|
<Area {...getAreaProps(s, i)} />
|
|
355
355
|
{/each}
|
|
356
|
-
</
|
|
357
|
-
</
|
|
356
|
+
</slot>
|
|
357
|
+
</ChartClipPath>
|
|
358
358
|
|
|
359
359
|
<slot name="aboveMarks" {...slotProps} />
|
|
360
360
|
|
|
@@ -390,43 +390,46 @@
|
|
|
390
390
|
{/if}
|
|
391
391
|
</slot>
|
|
392
392
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
393
|
+
<!-- Use `full` to allow labels on edge to not be cropped (bleed into padding) -->
|
|
394
|
+
<ChartClipPath disabled={!brush} full>
|
|
395
|
+
{#if points}
|
|
396
|
+
{#each visibleSeries as s, i (s.key)}
|
|
397
|
+
<Points {...getPointsProps(s, i)} />
|
|
398
|
+
{/each}
|
|
399
|
+
{/if}
|
|
398
400
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
401
|
+
<slot name="highlight" {...slotProps}>
|
|
402
|
+
{#each visibleSeries as s, i (s.key)}
|
|
403
|
+
{@const seriesTooltipData =
|
|
404
|
+
s.data && tooltip.data ? findRelatedData(s.data, tooltip.data, x) : null}
|
|
405
|
+
|
|
406
|
+
<Highlight
|
|
407
|
+
data={seriesTooltipData}
|
|
408
|
+
y={stackSeries ? (d) => d.stackData[i][1] : (s.value ?? (s.data ? undefined : s.key))}
|
|
409
|
+
points={{
|
|
410
|
+
fill: s.color,
|
|
411
|
+
class: cls(
|
|
412
|
+
'transition-opacity',
|
|
413
|
+
highlightSeriesKey && highlightSeriesKey !== s.key && 'opacity-10'
|
|
414
|
+
),
|
|
415
|
+
}}
|
|
416
|
+
lines={i == 0}
|
|
417
|
+
onpointclick={onpointclick
|
|
418
|
+
? (e, detail) => onpointclick(e, { ...detail, series: s })
|
|
419
|
+
: undefined}
|
|
420
|
+
onpointenter={() => (highlightSeriesKey = s.key)}
|
|
421
|
+
onpointleave={() => (highlightSeriesKey = null)}
|
|
422
|
+
{...props.highlight}
|
|
423
|
+
/>
|
|
424
|
+
{/each}
|
|
425
|
+
</slot>
|
|
424
426
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
427
|
+
{#if labels}
|
|
428
|
+
{#each visibleSeries as s, i (s.key)}
|
|
429
|
+
<Labels {...getLabelsProps(s, i)} />
|
|
430
|
+
{/each}
|
|
431
|
+
{/if}
|
|
432
|
+
</ChartClipPath>
|
|
430
433
|
</svelte:component>
|
|
431
434
|
|
|
432
435
|
<slot name="legend" {...slotProps}>
|
|
@@ -276,17 +276,17 @@
|
|
|
276
276
|
{/if}
|
|
277
277
|
</slot>
|
|
278
278
|
|
|
279
|
-
<
|
|
279
|
+
<ChartClipPath disabled={!brush}>
|
|
280
|
+
<slot name="belowMarks" {...slotProps} />
|
|
280
281
|
|
|
281
|
-
|
|
282
|
-
<ChartClipPath disabled={!brush}>
|
|
282
|
+
<slot name="marks" {...slotProps}>
|
|
283
283
|
{#each visibleSeries as s, i (s.key)}
|
|
284
284
|
<Spline {...getSplineProps(s, i)} />
|
|
285
285
|
{/each}
|
|
286
|
-
</
|
|
287
|
-
</slot>
|
|
286
|
+
</slot>
|
|
288
287
|
|
|
289
|
-
|
|
288
|
+
<slot name="aboveMarks" {...slotProps} />
|
|
289
|
+
</ChartClipPath>
|
|
290
290
|
|
|
291
291
|
<slot name="axis" {...slotProps}>
|
|
292
292
|
{#if axis}
|
|
@@ -314,42 +314,45 @@
|
|
|
314
314
|
{/if}
|
|
315
315
|
</slot>
|
|
316
316
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
317
|
+
<!-- Use `full` to allow labels on edge to not be cropped (bleed into padding) -->
|
|
318
|
+
<ChartClipPath disabled={!brush} full>
|
|
319
|
+
{#if points}
|
|
320
|
+
{#each visibleSeries as s, i (s.key)}
|
|
321
|
+
<Points {...getPointsProps(s, i)} />
|
|
322
|
+
{/each}
|
|
323
|
+
{/if}
|
|
322
324
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
{#if labels}
|
|
326
|
+
{#each visibleSeries as s, i (s.key)}
|
|
327
|
+
<Labels {...getLabelsProps(s, i)} />
|
|
328
|
+
{/each}
|
|
329
|
+
{/if}
|
|
328
330
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
331
|
+
<slot name="highlight" {...slotProps}>
|
|
332
|
+
{#each visibleSeries as s, i (s.key)}
|
|
333
|
+
{@const seriesTooltipData =
|
|
334
|
+
s.data && tooltip.data ? findRelatedData(s.data, tooltip.data, x) : null}
|
|
335
|
+
<Highlight
|
|
336
|
+
data={seriesTooltipData}
|
|
337
|
+
y={s.value ?? (s.data ? undefined : s.key)}
|
|
338
|
+
points={{
|
|
339
|
+
fill: s.color,
|
|
340
|
+
class: cls(
|
|
341
|
+
'transition-opacity',
|
|
342
|
+
highlightSeriesKey && highlightSeriesKey !== s.key && 'opacity-10'
|
|
343
|
+
),
|
|
344
|
+
}}
|
|
345
|
+
lines={i === 0}
|
|
346
|
+
onpointclick={onpointclick
|
|
347
|
+
? (e, detail) => onpointclick(e, { ...detail, series: s })
|
|
348
|
+
: undefined}
|
|
349
|
+
onpointenter={() => (highlightSeriesKey = s.key)}
|
|
350
|
+
onpointleave={() => (highlightSeriesKey = null)}
|
|
351
|
+
{...props.highlight}
|
|
352
|
+
/>
|
|
353
|
+
{/each}
|
|
354
|
+
</slot>
|
|
355
|
+
</ChartClipPath>
|
|
353
356
|
</svelte:component>
|
|
354
357
|
|
|
355
358
|
<slot name="legend" {...slotProps}>
|
|
@@ -242,17 +242,17 @@
|
|
|
242
242
|
{/if}
|
|
243
243
|
</slot>
|
|
244
244
|
|
|
245
|
-
<
|
|
245
|
+
<ChartClipPath disabled={!brush}>
|
|
246
|
+
<slot name="belowMarks" {...slotProps} />
|
|
246
247
|
|
|
247
|
-
|
|
248
|
-
<ChartClipPath disabled={!brush}>
|
|
248
|
+
<slot name="marks" {...slotProps}>
|
|
249
249
|
{#each visibleSeries as s, i (s.key)}
|
|
250
250
|
<Points {...getPointsProps(s, i)} />
|
|
251
251
|
{/each}
|
|
252
|
-
</
|
|
253
|
-
</slot>
|
|
252
|
+
</slot>
|
|
254
253
|
|
|
255
|
-
|
|
254
|
+
<slot name="aboveMarks" {...slotProps} />
|
|
255
|
+
</ChartClipPath>
|
|
256
256
|
|
|
257
257
|
<slot name="axis" {...slotProps}>
|
|
258
258
|
{#if axis}
|
|
@@ -280,15 +280,23 @@
|
|
|
280
280
|
{/if}
|
|
281
281
|
</slot>
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
<!-- Use `full` to allow labels on edge to not be cropped (bleed into padding) -->
|
|
284
|
+
<ChartClipPath disabled={!brush} full>
|
|
285
|
+
<slot name="highlight" {...slotProps}>
|
|
286
|
+
<Highlight
|
|
287
|
+
points={{ fill: activeSeries?.color }}
|
|
288
|
+
lines
|
|
289
|
+
axis="both"
|
|
290
|
+
{...props.highlight}
|
|
291
|
+
/>
|
|
292
|
+
</slot>
|
|
286
293
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
294
|
+
{#if labels}
|
|
295
|
+
{#each visibleSeries as s, i (s.key)}
|
|
296
|
+
<Labels {...getLabelsProps(s, i)} />
|
|
297
|
+
{/each}
|
|
298
|
+
{/if}
|
|
299
|
+
</ChartClipPath>
|
|
292
300
|
</svelte:component>
|
|
293
301
|
|
|
294
302
|
<slot name="legend" {...slotProps}>
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
<script lang="ts">
|
|
39
39
|
import { onMount } from 'svelte';
|
|
40
40
|
import { cls } from '@layerstack/tailwind';
|
|
41
|
+
import { Logger } from '@layerstack/utils';
|
|
41
42
|
|
|
42
43
|
import { chartContext } from '../ChartContext.svelte';
|
|
43
44
|
import { transformContext } from '../TransformContext.svelte';
|
|
@@ -85,6 +86,8 @@
|
|
|
85
86
|
/** Show hit canvas for debugging */
|
|
86
87
|
export let debug = false;
|
|
87
88
|
|
|
89
|
+
const logger = new Logger('Canvas');
|
|
90
|
+
|
|
88
91
|
let components = new Map<Symbol, ComponentRender>();
|
|
89
92
|
let pendingInvalidation = false;
|
|
90
93
|
let frameId: number | undefined;
|
|
@@ -106,7 +109,9 @@
|
|
|
106
109
|
const { x, y } = localPoint(e.target as HTMLCanvasElement, e) ?? { x: 0, y: 0 };
|
|
107
110
|
const color = getPixelColor(hitCanvasContext!, x, y);
|
|
108
111
|
const colorKey = getColorStr(color);
|
|
109
|
-
|
|
112
|
+
const component = componentByColor.get(colorKey);
|
|
113
|
+
logger.debug({ colorKey, component, componentByColor });
|
|
114
|
+
return component;
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
function onPointerMove(e: PointerEvent) {
|
package/dist/utils/canvas.js
CHANGED
|
@@ -76,8 +76,10 @@ function render(ctx, render, styleOptions = {}) {
|
|
|
76
76
|
}
|
|
77
77
|
paintOrder.forEach((attr) => {
|
|
78
78
|
if (attr === 'fill') {
|
|
79
|
-
const fill = styleOptions.styles?.fill
|
|
80
|
-
|
|
79
|
+
const fill = styleOptions.styles?.fill &&
|
|
80
|
+
(styleOptions.styles?.fill instanceof CanvasGradient ||
|
|
81
|
+
!styleOptions.styles?.fill?.includes('var'))
|
|
82
|
+
? styleOptions.styles.fill
|
|
81
83
|
: ['none', DEFAULT_FILL].includes(computedStyles?.fill)
|
|
82
84
|
? null
|
|
83
85
|
: computedStyles?.fill;
|
|
@@ -93,7 +95,9 @@ function render(ctx, render, styleOptions = {}) {
|
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
else if (attr === 'stroke') {
|
|
96
|
-
const stroke = styleOptions.styles?.stroke
|
|
98
|
+
const stroke = styleOptions.styles?.stroke &&
|
|
99
|
+
(styleOptions.styles?.stroke instanceof CanvasGradient ||
|
|
100
|
+
!styleOptions.styles?.stroke?.includes('var'))
|
|
97
101
|
? styleOptions.styles?.stroke
|
|
98
102
|
: computedStyles?.stroke === 'none'
|
|
99
103
|
? null
|
|
@@ -131,6 +135,19 @@ export function renderRect(ctx, coords, styleOptions = {}) {
|
|
|
131
135
|
stroke: (ctx) => ctx.strokeRect(coords.x, coords.y, coords.width, coords.height),
|
|
132
136
|
}, styleOptions);
|
|
133
137
|
}
|
|
138
|
+
export function renderCircle(ctx, coords, styleOptions = {}) {
|
|
139
|
+
ctx.beginPath();
|
|
140
|
+
ctx.arc(coords.cx, coords.cy, coords.r, 0, 2 * Math.PI);
|
|
141
|
+
render(ctx, {
|
|
142
|
+
fill: (ctx) => {
|
|
143
|
+
ctx.fill();
|
|
144
|
+
},
|
|
145
|
+
stroke: (ctx) => {
|
|
146
|
+
ctx.stroke();
|
|
147
|
+
},
|
|
148
|
+
}, styleOptions);
|
|
149
|
+
ctx.closePath();
|
|
150
|
+
}
|
|
134
151
|
/** Clear canvas accounting for Canvas `context.translate(...)` */
|
|
135
152
|
export function clearCanvasContext(ctx, options) {
|
|
136
153
|
// Clear with negative offset due to Canvas `context.translate(...)`
|
package/dist/utils/color.d.ts
CHANGED
|
@@ -3,13 +3,18 @@ export declare function rgbColorGenerator(step?: number): Generator<{
|
|
|
3
3
|
r: number;
|
|
4
4
|
g: number;
|
|
5
5
|
b: number;
|
|
6
|
+
a: number;
|
|
6
7
|
}, {
|
|
7
8
|
r: number;
|
|
8
9
|
g: number;
|
|
9
10
|
b: number;
|
|
11
|
+
a: number;
|
|
10
12
|
}, unknown>;
|
|
11
|
-
|
|
13
|
+
type RGBColor = {
|
|
12
14
|
r: number;
|
|
13
15
|
g: number;
|
|
14
16
|
b: number;
|
|
15
|
-
|
|
17
|
+
a?: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function getColorStr(color: RGBColor): string;
|
|
20
|
+
export {};
|
package/dist/utils/color.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/** Generator to create a new color on each call */
|
|
2
2
|
export function* rgbColorGenerator(step = 500) {
|
|
3
|
-
let nextColor =
|
|
3
|
+
let nextColor = 0;
|
|
4
4
|
while (nextColor < 16777216) {
|
|
5
5
|
const r = nextColor & 0xff;
|
|
6
6
|
const g = (nextColor & 0xff00) >> 8;
|
|
7
7
|
const b = (nextColor & 0xff0000) >> 16;
|
|
8
8
|
nextColor += step;
|
|
9
|
-
yield { r, g, b };
|
|
9
|
+
yield { r, g, b, a: 255 };
|
|
10
10
|
}
|
|
11
|
-
return { r: 0, g: 0, b: 0 };
|
|
11
|
+
return { r: 0, g: 0, b: 0, a: 255 };
|
|
12
12
|
}
|
|
13
13
|
export function getColorStr(color) {
|
|
14
|
-
|
|
14
|
+
if (color.a !== undefined) {
|
|
15
|
+
return `rgba(${color.r},${color.g},${color.b},${color.a})`;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return `rgb(${color.r},${color.g},${color.b})`;
|
|
19
|
+
}
|
|
15
20
|
}
|