layerchart 2.0.0-next.61 → 2.0.0-next.62
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/canvas.d.ts +2 -2
- package/dist/canvas.js +2 -2
- package/dist/components/Arc/Arc.base.svelte +49 -11
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-full-circle--360-degree-range--1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-full-circle--360-degree-range--2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-innerRadius-of-0--pie-slice--1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-innerRadius-of-0--pie-slice--2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-negative-domain-values-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-negative-domain-values-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-partial-arc--e-g---180-degrees--1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-partial-arc--e-g---180-degrees--2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-at-max-domain-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-at-max-domain-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-below-domain-min-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-below-domain-min-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-exceeding-domain-max-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-exceeding-domain-max-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-of-0-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-edge-cases-should-handle-value-of-0-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-events-should-handle-pointer-enter-events-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-events-should-handle-pointer-enter-events-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-events-should-handle-pointer-move-events-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-events-should-handle-pointer-move-events-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-events-should-handle-touch-move-events-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-events-should-handle-touch-move-events-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-custom-class-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-custom-class-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-fill-color-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-fill-color-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-fillOpacity-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-fillOpacity-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-offset-to-arc-position-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-offset-to-arc-position-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-opacity-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-opacity-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-stroke-color-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-stroke-color-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-strokeWidth-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-strokeWidth-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-zero-offset-by-default-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-apply-zero-offset-by-default-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-call-tooltip-hide-on-pointer-leave-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-call-tooltip-hide-on-pointer-leave-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-call-tooltip-show-on-pointer-enter-with-data-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-call-tooltip-show-on-pointer-enter-with-data-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-handle-custom-start-angle-in-range-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-handle-custom-start-angle-in-range-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-have-stroke--none--by-default-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-have-stroke--none--by-default-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-an-arc-path-with-value-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-an-arc-path-with-value-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-when-track-prop-is-provided-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-when-track-prop-is-provided-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-custom-class-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-custom-class-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackCornerRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackCornerRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackEndAngle-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackEndAngle-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackInnerRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackInnerRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackInnerRadius-and-trackOuterRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackInnerRadius-and-trackOuterRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackOuterRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackOuterRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackPadAngle-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackPadAngle-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackStartAngle-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackStartAngle-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackStartAngle-and-trackEndAngle-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-track-with-trackStartAngle-and-trackEndAngle-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-both-startAngle-and-endAngle-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-both-startAngle-and-endAngle-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-cornerRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-cornerRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-custom-domain-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-custom-domain-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-custom-domain-and-range-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-custom-domain-and-range-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-custom-range-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-custom-range-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-endAngle-in-radians-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-endAngle-in-radians-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-innerRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-innerRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-innerRadius-and-outerRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-innerRadius-and-outerRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-outerRadius-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-outerRadius-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-padAngle-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-padAngle-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-startAngle-in-radians-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-props-should-render-with-startAngle-in-radians-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-should-render-Arc-element-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-should-render-Arc-element-2.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-should-render-track-1.png +0 -0
- package/dist/components/Arc/__screenshots__/Arc.svelte.test.ts/Arc-should-render-track-2.png +0 -0
- package/dist/components/{ArcLabel.svelte.test.js → ArcLabel/ArcLabel.svelte.test.js} +3 -3
- package/dist/components/ArcLabel/__screenshots__/ArcLabel.svelte.test.ts/ArcLabel-renders-a-text-element-with-the-supplied-value-at-the-centroid-1.png +0 -0
- package/dist/components/ArcLabel/__screenshots__/ArcLabel.svelte.test.ts/ArcLabel-renders-a-text-element-with-the-supplied-value-at-the-centroid-2.png +0 -0
- package/dist/components/Blur/Blur.canvas.svelte +25 -0
- package/dist/components/Blur/Blur.canvas.svelte.d.ts +4 -0
- package/dist/components/Blur/Blur.html.svelte +11 -0
- package/dist/components/Blur/Blur.html.svelte.d.ts +4 -0
- package/dist/components/{Blur.svelte.d.ts → Blur/Blur.shared.svelte.d.ts} +3 -5
- package/dist/components/Blur/Blur.svelte +23 -0
- package/dist/components/Blur/Blur.svelte.d.ts +4 -0
- package/dist/components/Blur/Blur.svg.svelte +24 -0
- package/dist/components/Blur/Blur.svg.svelte.d.ts +4 -0
- package/dist/components/Chart/Chart.base.svelte +13 -7
- package/dist/components/Chart/ChartCore.svelte.test.d.ts +1 -0
- package/dist/components/{ChartCore.svelte.test.js → Chart/ChartCore.svelte.test.js} +1 -1
- package/dist/components/Link/Link.base.svelte +15 -9
- package/dist/components/Path/Path.canvas.svelte +5 -2
- package/dist/components/Path/Path.shared.svelte.d.ts +17 -4
- package/dist/components/Path/Path.shared.svelte.js +26 -8
- package/dist/components/Path/Path.svg.svelte +75 -60
- package/dist/components/RectClipPath/RectClipPath.base.svelte +25 -1
- package/dist/components/RectClipPath/RectClipPath.shared.svelte.d.ts +8 -0
- package/dist/components/Trail/Trail.base.svelte +10 -7
- package/dist/components/charts/__screenshots__/ArcChart.svelte.test.ts/ArcChart-uses-the-chart-value-accessor-for-explicit-per-series-tooltip-values-1.png +0 -0
- package/dist/components/charts/__screenshots__/ArcChart.svelte.test.ts/ArcChart-uses-the-chart-value-accessor-for-explicit-per-series-tooltip-values-2.png +0 -0
- package/dist/components/charts/__screenshots__/BarChart.svelte.test.ts/BarChart-legend-series-toggle-adjusts-group-scale-should-adjust-grouped-bar-widths-when-series-are-toggled-via-legend-1.png +0 -0
- package/dist/components/charts/__screenshots__/PieChart.svelte.test.ts/PieChart-uses-hovered-slice-identity-for-implicit-tooltip-series-1.png +0 -0
- package/dist/components/charts/__screenshots__/PieChart.svelte.test.ts/PieChart-uses-hovered-slice-identity-for-implicit-tooltip-series-2.png +0 -0
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +2 -2
- package/dist/html.d.ts +2 -2
- package/dist/html.js +2 -2
- package/dist/states/chart.svelte.d.ts +4 -2
- package/dist/states/chart.svelte.js +45 -18
- package/dist/states/chart.svelte.test.js +1 -1
- package/dist/states/series.svelte.js +9 -13
- package/dist/states/series.svelte.test.js +5 -1
- package/dist/svg.d.ts +2 -2
- package/dist/svg.js +2 -2
- package/package.json +1 -1
- package/dist/components/Blur.svelte +0 -49
- /package/dist/components/{ArcLabel.svelte.test.d.ts → ArcLabel/ArcLabel.svelte.test.d.ts} +0 -0
- /package/dist/components/{ChartCore.svelte.test.d.ts → Blur/Blur.shared.svelte.js} +0 -0
|
@@ -9,9 +9,12 @@
|
|
|
9
9
|
import { createKey } from '../../utils/key.svelte.js';
|
|
10
10
|
import { PathState, type PathProps } from './Path.shared.svelte.js';
|
|
11
11
|
|
|
12
|
-
let { ...rest }: PathProps = $props();
|
|
12
|
+
let { pathData, ...rest }: PathProps = $props();
|
|
13
13
|
|
|
14
|
-
const c = new PathState(
|
|
14
|
+
const c = new PathState(
|
|
15
|
+
() => pathData,
|
|
16
|
+
() => rest as PathProps
|
|
17
|
+
);
|
|
15
18
|
|
|
16
19
|
function render(
|
|
17
20
|
ctx: CanvasRenderingContext2D,
|
|
@@ -7,10 +7,15 @@ import type { ChartState } from '../../states/chart.svelte.js';
|
|
|
7
7
|
import type { draw as _drawTransition } from 'svelte/transition';
|
|
8
8
|
export type PathPropsWithoutHTML = {
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* The `d` attribute of the rendered `<path>`.
|
|
11
|
+
*
|
|
12
|
+
* Accepts either a value (resolved at call site) or a function that
|
|
13
|
+
* returns the current value. Passing a function lets the parent avoid
|
|
14
|
+
* re-rendering its own template on every change to the path data —
|
|
15
|
+
* useful when a parent like `Link` / `Spline` / `Area` updates the
|
|
16
|
+
* path on every animation tick across hundreds of instances.
|
|
12
17
|
*/
|
|
13
|
-
pathData?: string | undefined | null;
|
|
18
|
+
pathData?: string | undefined | null | (() => string | undefined | null);
|
|
14
19
|
/**
|
|
15
20
|
* Whether to animate the drawing of the path over time.
|
|
16
21
|
* Pass either `true` or an object with transition options to
|
|
@@ -66,5 +71,13 @@ export declare class PathState {
|
|
|
66
71
|
chartCtx: ChartState;
|
|
67
72
|
get tweenedPathData(): any;
|
|
68
73
|
drawKey: symbol;
|
|
69
|
-
|
|
74
|
+
/**
|
|
75
|
+
* @param getPathData Hot-path getter — reads only `pathData`. Kept separate from
|
|
76
|
+
* `getProps` so the `<path d=...>` updater (and the canvas
|
|
77
|
+
* `tweenedPathData` consumer) does not subscribe to every
|
|
78
|
+
* Path prop on every tick.
|
|
79
|
+
* @param getProps Full-props getter — used for one-time / cold-path config
|
|
80
|
+
* (motion, draw).
|
|
81
|
+
*/
|
|
82
|
+
constructor(getPathData: () => PathProps['pathData'], getProps?: () => PathProps);
|
|
70
83
|
}
|
|
@@ -2,11 +2,20 @@ import { interpolatePath } from 'd3-interpolate-path';
|
|
|
2
2
|
import { flattenPathData } from '../../utils/path.js';
|
|
3
3
|
import { createMotion, extractTweenConfig, } from '../../utils/motion.svelte.js';
|
|
4
4
|
import { getChartContext } from '../../contexts/chart.js';
|
|
5
|
+
/** Resolve `pathData` whether it was passed as a value or a getter function. */
|
|
6
|
+
function resolvePathData(v) {
|
|
7
|
+
return typeof v === 'function' ? v() : v;
|
|
8
|
+
}
|
|
5
9
|
/**
|
|
6
10
|
* Reactive state shared by every per-layer Path variant.
|
|
7
11
|
*/
|
|
8
12
|
export class PathState {
|
|
9
|
-
|
|
13
|
+
// Hot-path getter: reads only `pathData` (or invokes the function-getter form).
|
|
14
|
+
// Kept separate from the full-props getter so that the `<path d=...>` template
|
|
15
|
+
// updater does not subscribe to every Path prop on every read — critical for
|
|
16
|
+
// mark-heavy scenes (force-simulation graphs with hundreds of links updating
|
|
17
|
+
// per tick) where pre-fix each tween read re-evaluated all 15+ props.
|
|
18
|
+
#getPathData;
|
|
10
19
|
// Contexts
|
|
11
20
|
chartCtx = getChartContext();
|
|
12
21
|
// Path data tween source — the actual `d` attribute / canvas render input
|
|
@@ -16,8 +25,16 @@ export class PathState {
|
|
|
16
25
|
}
|
|
17
26
|
// Re-key trigger for draw transitions
|
|
18
27
|
drawKey = $state(Symbol());
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
/**
|
|
29
|
+
* @param getPathData Hot-path getter — reads only `pathData`. Kept separate from
|
|
30
|
+
* `getProps` so the `<path d=...>` updater (and the canvas
|
|
31
|
+
* `tweenedPathData` consumer) does not subscribe to every
|
|
32
|
+
* Path prop on every tick.
|
|
33
|
+
* @param getProps Full-props getter — used for one-time / cold-path config
|
|
34
|
+
* (motion, draw).
|
|
35
|
+
*/
|
|
36
|
+
constructor(getPathData, getProps = () => ({})) {
|
|
37
|
+
this.#getPathData = () => resolvePathData(getPathData());
|
|
21
38
|
const initial = getProps();
|
|
22
39
|
const extractedTween = extractTweenConfig(initial.motion);
|
|
23
40
|
const tweenedOptions = extractedTween
|
|
@@ -32,18 +49,19 @@ export class PathState {
|
|
|
32
49
|
// Fast initial render when not tweened
|
|
33
50
|
return '';
|
|
34
51
|
}
|
|
35
|
-
|
|
36
|
-
|
|
52
|
+
const resolved = resolvePathData(getPathData());
|
|
53
|
+
if (resolved) {
|
|
54
|
+
return flattenPathData(resolved, Math.min(this.chartCtx.yScale(0) ?? this.chartCtx.yRange[0], this.chartCtx.yRange[0]));
|
|
37
55
|
}
|
|
38
56
|
return '';
|
|
39
57
|
})();
|
|
40
|
-
this.#tweenedState = createMotion(defaultPathData,
|
|
58
|
+
this.#tweenedState = createMotion(defaultPathData, this.#getPathData, tweenedOptions);
|
|
41
59
|
// Re-trigger draw transition when path data changes
|
|
42
60
|
$effect(() => {
|
|
43
61
|
if (!getProps().draw)
|
|
44
62
|
return;
|
|
45
|
-
// Touch dependency
|
|
46
|
-
void
|
|
63
|
+
// Touch dependency (resolves getter form too)
|
|
64
|
+
void this.#getPathData();
|
|
47
65
|
this.drawKey = Symbol();
|
|
48
66
|
});
|
|
49
67
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
const uid = $props.id();
|
|
17
17
|
|
|
18
18
|
let {
|
|
19
|
-
pathRef
|
|
19
|
+
pathRef = $bindable(),
|
|
20
20
|
marker,
|
|
21
21
|
markerStart: markerStartProp,
|
|
22
22
|
markerMid: markerMidProp,
|
|
@@ -24,29 +24,35 @@
|
|
|
24
24
|
startContent,
|
|
25
25
|
endContent,
|
|
26
26
|
draw,
|
|
27
|
+
motion,
|
|
28
|
+
// Extracted out of `rest` so the `<path>` element's `{...rest}`
|
|
29
|
+
// spread doesn't re-evaluate on every frame in mark-heavy scenes
|
|
30
|
+
// (force-simulation graphs with hundreds of links updating per tick).
|
|
31
|
+
// - `pathData`: changes every frame
|
|
32
|
+
// - `class`: parents typically pass `cls(...)` which produces a new
|
|
33
|
+
// string reference per parent render
|
|
34
|
+
// - styling props: explicit on the <path> element below, no need to
|
|
35
|
+
// leak them through the spread
|
|
36
|
+
pathData: _pathData,
|
|
37
|
+
class: classProp,
|
|
38
|
+
fill: fillProp,
|
|
39
|
+
fillOpacity: fillOpacityProp,
|
|
40
|
+
stroke: strokeProp,
|
|
41
|
+
strokeOpacity: strokeOpacityProp,
|
|
42
|
+
strokeWidth: strokeWidthProp,
|
|
43
|
+
opacity: opacityProp,
|
|
27
44
|
...rest
|
|
28
45
|
}: PathProps = $props();
|
|
29
46
|
|
|
47
|
+
// Pass `pathData` as its own getter so the hot-path tween read only subscribes
|
|
48
|
+
// to `pathData` (which changes per tick on force sims) and not to every other
|
|
49
|
+
// Path prop. Pre-fix the per-tick `<path d=...>` updater re-read all 15+ props
|
|
50
|
+
// through `getProps()` on each force-sim tick × hundreds of paths.
|
|
30
51
|
const c = new PathState(
|
|
31
|
-
() =>
|
|
32
|
-
|
|
33
|
-
marker,
|
|
34
|
-
markerStart: markerStartProp,
|
|
35
|
-
markerMid: markerMidProp,
|
|
36
|
-
markerEnd: markerEndProp,
|
|
37
|
-
startContent,
|
|
38
|
-
endContent,
|
|
39
|
-
draw,
|
|
40
|
-
...rest,
|
|
41
|
-
}) as PathProps
|
|
52
|
+
() => _pathData,
|
|
53
|
+
() => ({ draw, motion }) as PathProps
|
|
42
54
|
);
|
|
43
55
|
|
|
44
|
-
let pathRef = $state<SVGPathElement>();
|
|
45
|
-
|
|
46
|
-
$effect.pre(() => {
|
|
47
|
-
pathRefProp = pathRef;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
56
|
const markerStart = $derived(markerStartProp ?? marker);
|
|
51
57
|
const markerMid = $derived(markerMidProp ?? marker);
|
|
52
58
|
const markerEnd = $derived(markerEndProp ?? marker);
|
|
@@ -56,7 +62,6 @@
|
|
|
56
62
|
const markerEndId = $derived(markerEnd ? createId('marker-end', uid) : '');
|
|
57
63
|
|
|
58
64
|
const drawTransition = $derived(draw ? _drawTransition : () => ({}));
|
|
59
|
-
|
|
60
65
|
let startPoint = $state<DOMPoint | undefined>();
|
|
61
66
|
|
|
62
67
|
const endPointDuration = $derived.by(() => {
|
|
@@ -70,60 +75,70 @@
|
|
|
70
75
|
return 800;
|
|
71
76
|
});
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
tick().then(() => {
|
|
78
|
+
// Only allocate the controlled motion container when `draw` is configured;
|
|
79
|
+
// otherwise the per-Path `MotionNone` × hundreds of paths was a measurable
|
|
80
|
+
// mount-time cost in mark-heavy scenes.
|
|
81
|
+
const endPoint = draw
|
|
82
|
+
? createControlledMotion<DOMPoint | undefined>(undefined, {
|
|
83
|
+
type: 'tween',
|
|
84
|
+
duration: () => endPointDuration,
|
|
85
|
+
easing: typeof draw === 'object' && draw.easing ? draw.easing : cubicInOut,
|
|
86
|
+
interpolate() {
|
|
87
|
+
return (t: number) => {
|
|
88
|
+
const totalLength = pathRef?.getTotalLength() ?? 0;
|
|
89
|
+
const point = pathRef?.getPointAtLength(totalLength * t);
|
|
90
|
+
return point;
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
: null;
|
|
95
|
+
|
|
96
|
+
// Only set up path-end tracking when startContent/endContent require it.
|
|
97
|
+
if (startContent || endContent) {
|
|
98
|
+
$effect(() => {
|
|
99
|
+
// Track path data changes
|
|
100
|
+
void c.tweenedPathData;
|
|
98
101
|
if (!pathRef) return;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
|
|
103
|
+
tick().then(() => {
|
|
104
|
+
if (!pathRef) return;
|
|
105
|
+
const totalLength = pathRef.getTotalLength();
|
|
106
|
+
if (!totalLength) return;
|
|
107
|
+
startPoint = pathRef.getPointAtLength(0);
|
|
108
|
+
if (endPoint) {
|
|
109
|
+
endPoint.target = pathRef.getPointAtLength(totalLength);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
103
112
|
});
|
|
104
|
-
}
|
|
113
|
+
}
|
|
105
114
|
</script>
|
|
106
115
|
|
|
107
116
|
{#key c.drawKey}
|
|
108
117
|
<path
|
|
109
118
|
{...rest as any}
|
|
110
119
|
d={c.tweenedPathData}
|
|
111
|
-
fill={
|
|
112
|
-
fill-opacity={
|
|
113
|
-
stroke={
|
|
114
|
-
stroke-opacity={
|
|
115
|
-
stroke-width={
|
|
116
|
-
opacity={
|
|
117
|
-
class={cls('lc-path',
|
|
120
|
+
fill={fillProp}
|
|
121
|
+
fill-opacity={fillOpacityProp}
|
|
122
|
+
stroke={strokeProp}
|
|
123
|
+
stroke-opacity={strokeOpacityProp}
|
|
124
|
+
stroke-width={strokeWidthProp}
|
|
125
|
+
opacity={opacityProp}
|
|
126
|
+
class={cls('lc-path', classProp as string | undefined)}
|
|
118
127
|
marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
|
|
119
128
|
marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
|
|
120
129
|
marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
|
|
121
130
|
in:drawTransition|global={typeof draw === 'object' ? draw : undefined}
|
|
122
131
|
bind:this={pathRef}
|
|
123
132
|
/>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
{#if markerStart}
|
|
134
|
+
<MarkerWrapper id={markerStartId} marker={markerStart} />
|
|
135
|
+
{/if}
|
|
136
|
+
{#if markerMid}
|
|
137
|
+
<MarkerWrapper id={markerMidId} marker={markerMid} />
|
|
138
|
+
{/if}
|
|
139
|
+
{#if markerEnd}
|
|
140
|
+
<MarkerWrapper id={markerEndId} marker={markerEnd} />
|
|
141
|
+
{/if}
|
|
127
142
|
|
|
128
143
|
{#if startContent && startPoint}
|
|
129
144
|
<Group x={startPoint.x} y={startPoint.y} class="lc-path-g-start">
|
|
@@ -137,7 +152,7 @@
|
|
|
137
152
|
</Group>
|
|
138
153
|
{/if}
|
|
139
154
|
|
|
140
|
-
{#if endContent && endPoint
|
|
155
|
+
{#if endContent && endPoint?.current}
|
|
141
156
|
<Group x={endPoint.current.x} y={endPoint.current.y} class="lc-path-g-end">
|
|
142
157
|
{@render endContent({
|
|
143
158
|
point: endPoint.current,
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
<script lang="ts">
|
|
13
13
|
import { createId } from '../../utils/createId.js';
|
|
14
|
+
import { createMotion, parseMotionProp } from '../../utils/motion.svelte.js';
|
|
14
15
|
|
|
15
16
|
const uid = $props.id();
|
|
16
17
|
|
|
@@ -19,14 +20,37 @@
|
|
|
19
20
|
id = createId('clipPath-', uid),
|
|
20
21
|
x = 0,
|
|
21
22
|
y = 0,
|
|
23
|
+
initialX,
|
|
24
|
+
initialY,
|
|
22
25
|
width,
|
|
23
26
|
height,
|
|
27
|
+
initialWidth,
|
|
28
|
+
initialHeight,
|
|
24
29
|
disabled = false,
|
|
25
30
|
invert = false,
|
|
31
|
+
motion,
|
|
26
32
|
children: childrenProp,
|
|
27
33
|
}: RectClipPathBaseProps = $props();
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
// When `motion` is undefined `createMotion` returns a passthrough that just
|
|
36
|
+
// reads the getter, so we can call it unconditionally and let the fast path
|
|
37
|
+
// handle the no-motion case.
|
|
38
|
+
const motionX = createMotion(initialX ?? x, () => x, motion && parseMotionProp(motion, 'x'));
|
|
39
|
+
const motionY = createMotion(initialY ?? y, () => y, motion && parseMotionProp(motion, 'y'));
|
|
40
|
+
const motionWidth = createMotion(
|
|
41
|
+
initialWidth ?? width,
|
|
42
|
+
() => width,
|
|
43
|
+
motion && parseMotionProp(motion, 'width')
|
|
44
|
+
);
|
|
45
|
+
const motionHeight = createMotion(
|
|
46
|
+
initialHeight ?? height,
|
|
47
|
+
() => height,
|
|
48
|
+
motion && parseMotionProp(motion, 'height')
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const path = $derived(
|
|
52
|
+
`M${motionX.current},${motionY.current} h${motionWidth.current} v${motionHeight.current} h${-motionWidth.current} Z`
|
|
53
|
+
);
|
|
30
54
|
</script>
|
|
31
55
|
|
|
32
56
|
<ClipPath {id} {disabled} {invert} {path}>
|
|
@@ -8,12 +8,20 @@ export type BaseRectClipPathPropsWithoutHTML = {
|
|
|
8
8
|
id?: string;
|
|
9
9
|
/** The x position of the clipPath. @default 0 */
|
|
10
10
|
x?: number;
|
|
11
|
+
/** The initial x position (used as the animation start when `motion` is set). @default x */
|
|
12
|
+
initialX?: number;
|
|
11
13
|
/** The y position of the clipPath. @default 0 */
|
|
12
14
|
y?: number;
|
|
15
|
+
/** The initial y position (used as the animation start when `motion` is set). @default y */
|
|
16
|
+
initialY?: number;
|
|
13
17
|
/** The width of the clipPath. @required */
|
|
14
18
|
width: number;
|
|
19
|
+
/** The initial width (used as the animation start when `motion` is set). @default width */
|
|
20
|
+
initialWidth?: number;
|
|
15
21
|
/** The height of the clipPath. @required */
|
|
16
22
|
height: number;
|
|
23
|
+
/** The initial height (used as the animation start when `motion` is set). @default height */
|
|
24
|
+
initialHeight?: number;
|
|
17
25
|
/** Whether to disable clipping (show all). @default false */
|
|
18
26
|
disabled?: boolean;
|
|
19
27
|
/** Invert the clip — content renders *outside* the rect. @default false */
|
|
@@ -122,12 +122,15 @@
|
|
|
122
122
|
return '';
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
// Only allocate the tween container when the user opts into a tween via
|
|
126
|
+
// `motion`; otherwise the template reads `trailPath` directly.
|
|
127
|
+
const tweenState =
|
|
128
|
+
extractTweenConfig(motion) != null
|
|
129
|
+
? createMotion(defaultPathData(), () => trailPath, {
|
|
130
|
+
type: 'tween',
|
|
131
|
+
interpolate: interpolatePath,
|
|
132
|
+
})
|
|
133
|
+
: null;
|
|
131
134
|
|
|
132
135
|
ctx.registerComponent({
|
|
133
136
|
name: 'Trail',
|
|
@@ -137,7 +140,7 @@
|
|
|
137
140
|
</script>
|
|
138
141
|
|
|
139
142
|
<Path
|
|
140
|
-
pathData={
|
|
143
|
+
pathData={tweenState ? tweenState.current : trailPath}
|
|
141
144
|
{fill}
|
|
142
145
|
{fillOpacity}
|
|
143
146
|
{opacity}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -18,8 +18,8 @@ export { default as Bar } from './Bar/Bar.svelte';
|
|
|
18
18
|
export * from './Bar/Bar.svelte';
|
|
19
19
|
export { default as Bars } from './Bars/Bars.svelte';
|
|
20
20
|
export * from './Bars/Bars.svelte';
|
|
21
|
-
export { default as Blur } from './Blur.svelte';
|
|
22
|
-
export * from './Blur.svelte';
|
|
21
|
+
export { default as Blur } from './Blur/Blur.svelte';
|
|
22
|
+
export * from './Blur/Blur.svelte';
|
|
23
23
|
export { default as BoxPlot } from './BoxPlot/BoxPlot.svelte';
|
|
24
24
|
export * from './BoxPlot/BoxPlot.svelte';
|
|
25
25
|
export { default as Bounds } from './Bounds.svelte';
|
package/dist/components/index.js
CHANGED
|
@@ -18,8 +18,8 @@ export { default as Bar } from './Bar/Bar.svelte';
|
|
|
18
18
|
export * from './Bar/Bar.svelte';
|
|
19
19
|
export { default as Bars } from './Bars/Bars.svelte';
|
|
20
20
|
export * from './Bars/Bars.svelte';
|
|
21
|
-
export { default as Blur } from './Blur.svelte';
|
|
22
|
-
export * from './Blur.svelte';
|
|
21
|
+
export { default as Blur } from './Blur/Blur.svelte';
|
|
22
|
+
export * from './Blur/Blur.svelte';
|
|
23
23
|
export { default as BoxPlot } from './BoxPlot/BoxPlot.svelte';
|
|
24
24
|
export * from './BoxPlot/BoxPlot.svelte';
|
|
25
25
|
export { default as Bounds } from './Bounds.svelte';
|
package/dist/html.d.ts
CHANGED
|
@@ -72,8 +72,8 @@ export { default as Calendar } from './components/Calendar/Calendar.html.svelte'
|
|
|
72
72
|
export type { CalendarProps, CalendarPropsWithoutHTML, CalendarCell, } from './components/Calendar/Calendar.shared.svelte.js';
|
|
73
73
|
export { default as Month } from './components/Month/Month.html.svelte';
|
|
74
74
|
export type { MonthProps, MonthPropsWithoutHTML, MonthCell, } from './components/Month/Month.shared.svelte.js';
|
|
75
|
-
export { default as Blur } from './components/Blur.svelte';
|
|
76
|
-
export * from './components/Blur.svelte';
|
|
75
|
+
export { default as Blur } from './components/Blur/Blur.svelte';
|
|
76
|
+
export * from './components/Blur/Blur.svelte';
|
|
77
77
|
export { default as Bounds } from './components/Bounds.svelte';
|
|
78
78
|
export * from './components/Bounds.svelte';
|
|
79
79
|
export { default as BrushContext } from './components/BrushContext.svelte';
|
package/dist/html.js
CHANGED
|
@@ -47,8 +47,8 @@ export { default as Month } from './components/Month/Month.html.svelte';
|
|
|
47
47
|
// helpers, context providers, or composite chart wrappers). Re-exported here
|
|
48
48
|
// so the per-layer sub-path has a complete API.
|
|
49
49
|
// Helpers / context providers
|
|
50
|
-
export { default as Blur } from './components/Blur.svelte';
|
|
51
|
-
export * from './components/Blur.svelte';
|
|
50
|
+
export { default as Blur } from './components/Blur/Blur.svelte';
|
|
51
|
+
export * from './components/Blur/Blur.svelte';
|
|
52
52
|
export { default as Bounds } from './components/Bounds.svelte';
|
|
53
53
|
export * from './components/Bounds.svelte';
|
|
54
54
|
export { default as BrushContext } from './components/BrushContext.svelte';
|
|
@@ -50,7 +50,6 @@ export interface RegisterComponentOptions<T extends Element = Element> {
|
|
|
50
50
|
}
|
|
51
51
|
export declare class ChartState<TData = any, XScale extends AnyScale = AnyScale, YScale extends AnyScale = AnyScale> {
|
|
52
52
|
#private;
|
|
53
|
-
private _propsGetter;
|
|
54
53
|
props: ChartPropsWithoutHTML<TData, XScale, YScale>;
|
|
55
54
|
geoState: GeoState;
|
|
56
55
|
transformState: TransformState;
|
|
@@ -90,7 +89,10 @@ export declare class ChartState<TData = any, XScale extends AnyScale = AnyScale,
|
|
|
90
89
|
private _xDomainIsDate;
|
|
91
90
|
private _yDomainIsDate;
|
|
92
91
|
meta: Record<string, any>;
|
|
93
|
-
constructor(
|
|
92
|
+
constructor(props: ChartPropsWithoutHTML<TData, XScale, YScale>, overrides?: {
|
|
93
|
+
brushXDomain?: () => BrushDomainType | undefined;
|
|
94
|
+
brushYDomain?: () => BrushDomainType | undefined;
|
|
95
|
+
});
|
|
94
96
|
containerWidth: number;
|
|
95
97
|
containerHeight: number;
|
|
96
98
|
data: import("d3-sankey").SankeyGraph<any, any> | readonly TData[] | import("d3-hierarchy").HierarchyNode<TData>;
|
|
@@ -17,11 +17,22 @@ const defaultPadding = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
|
17
17
|
const EMPTY_SERIES = [];
|
|
18
18
|
/** Svelte context key for tracking the nearest parent ComponentNode. */
|
|
19
19
|
const _ParentNodeContext = new Context('ComponentTreeParent');
|
|
20
|
+
/** Mark info is "empty" when none of the fields the chart uses for series /
|
|
21
|
+
* domain inference are populated. Pixel-mode primitives produce empty info
|
|
22
|
+
* since they have no string/function accessors and no own data. */
|
|
23
|
+
function isEmptyMarkInfo(info) {
|
|
24
|
+
return !info.x && !info.y && !info.data && !info.color && !info.seriesKey && !info.label;
|
|
25
|
+
}
|
|
20
26
|
export class ChartState {
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
props
|
|
27
|
+
// The `$props()` proxy from the host component. Reads on `this.props.X` go
|
|
28
|
+
// straight through to the underlying reactive prop — no spread / no derived
|
|
29
|
+
// wrapper needed.
|
|
30
|
+
props;
|
|
31
|
+
// Brush-domain overrides. The host component owns the brush state as local
|
|
32
|
+
// `$state` and supplies these getters so brush selections take precedence
|
|
33
|
+
// over `props.xDomain` / `props.yDomain` when reading the effective domain.
|
|
34
|
+
#brushXDomain;
|
|
35
|
+
#brushYDomain;
|
|
25
36
|
// State / contexts
|
|
26
37
|
geoState;
|
|
27
38
|
transformState = $state(null);
|
|
@@ -132,14 +143,26 @@ export class ChartState {
|
|
|
132
143
|
};
|
|
133
144
|
});
|
|
134
145
|
if (markInfo && !insideCompositeMark) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
// Probe once at construction: if mark info is initially empty
|
|
147
|
+
// (pixel-mode primitives where cx/cy/r are numbers), skip the
|
|
148
|
+
// tracking $effect entirely. This is the common case for
|
|
149
|
+
// mark-heavy scenes (force simulations, scatter plots with
|
|
150
|
+
// pixel coordinates) and avoids one effect frame per primitive.
|
|
151
|
+
//
|
|
152
|
+
// Trade-off: a primitive that starts in pixel mode and later
|
|
153
|
+
// flips to data mode (e.g. cx changes from number to string at
|
|
154
|
+
// runtime) won't register a mark. This is uncommon — modes are
|
|
155
|
+
// typically static — but if needed, use explicit `series` on the
|
|
156
|
+
// chart instead of relying on implicit mark-derived series.
|
|
157
|
+
const initial = untrack(markInfo);
|
|
158
|
+
if (!isEmptyMarkInfo(initial)) {
|
|
159
|
+
$effect(() => {
|
|
160
|
+
const info = markInfo();
|
|
161
|
+
if (isEmptyMarkInfo(info))
|
|
162
|
+
return;
|
|
163
|
+
return untrack(() => this.registerMark(info));
|
|
164
|
+
});
|
|
165
|
+
}
|
|
143
166
|
}
|
|
144
167
|
return node;
|
|
145
168
|
}
|
|
@@ -159,8 +182,10 @@ export class ChartState {
|
|
|
159
182
|
_yDomainIsDate = false;
|
|
160
183
|
// Meta data - reactive to props.meta changes
|
|
161
184
|
meta = $derived(this.props.meta ?? {});
|
|
162
|
-
constructor(
|
|
163
|
-
this.
|
|
185
|
+
constructor(props, overrides) {
|
|
186
|
+
this.props = props;
|
|
187
|
+
this.#brushXDomain = overrides?.brushXDomain ?? (() => undefined);
|
|
188
|
+
this.#brushYDomain = overrides?.brushYDomain ?? (() => undefined);
|
|
164
189
|
// Create GeoState instance — pass a dimensions getter so projection
|
|
165
190
|
// is available during SSR (where $effect doesn't run)
|
|
166
191
|
this.geoState = new GeoState(() => this.props.geo ?? {}, () => ({ width: this.width, height: this.height }));
|
|
@@ -272,7 +297,7 @@ export class ChartState {
|
|
|
272
297
|
}
|
|
273
298
|
});
|
|
274
299
|
// Set up domain motion if motion prop is configured
|
|
275
|
-
const motionProp =
|
|
300
|
+
const motionProp = props.motion;
|
|
276
301
|
if (motionProp) {
|
|
277
302
|
const resolved = parseMotionProp(motionProp);
|
|
278
303
|
this._xDomainMotion = createControlledMotion([], resolved);
|
|
@@ -373,7 +398,7 @@ export class ChartState {
|
|
|
373
398
|
if (this.props.bandPadding != null && this.valueAxis === 'y') {
|
|
374
399
|
return scaleBand().padding(this.props.bandPadding);
|
|
375
400
|
}
|
|
376
|
-
return autoScale(this.props.xDomain, this.flatData, this.x);
|
|
401
|
+
return autoScale(this.#brushXDomain() ?? this.props.xDomain, this.flatData, this.x);
|
|
377
402
|
});
|
|
378
403
|
_yScaleProp = $derived.by(() => {
|
|
379
404
|
if (this.props.yScale)
|
|
@@ -385,7 +410,7 @@ export class ChartState {
|
|
|
385
410
|
if (this.props.bandPadding != null && this.valueAxis === 'x') {
|
|
386
411
|
return scaleBand().padding(this.props.bandPadding);
|
|
387
412
|
}
|
|
388
|
-
return autoScale(this.props.yDomain, this.flatData, this.y);
|
|
413
|
+
return autoScale(this.#brushYDomain() ?? this.props.yDomain, this.flatData, this.y);
|
|
389
414
|
});
|
|
390
415
|
_zScaleProp = $derived.by(() => {
|
|
391
416
|
return this.props.zScale ?? autoScale(this.props.zDomain, this.flatData, this.props.z);
|
|
@@ -579,7 +604,9 @@ export class ChartState {
|
|
|
579
604
|
return undefined;
|
|
580
605
|
}
|
|
581
606
|
resolveDomain(axis) {
|
|
582
|
-
const domain = axis === 'x'
|
|
607
|
+
const domain = axis === 'x'
|
|
608
|
+
? (this.#brushXDomain() ?? this.props.xDomain)
|
|
609
|
+
: (this.#brushYDomain() ?? this.props.yDomain);
|
|
583
610
|
const interval = axis === 'x' ? this.props.xInterval : this.props.yInterval;
|
|
584
611
|
const explicitBaseline = axis === 'x' ? this.props.xBaseline : this.props.yBaseline;
|
|
585
612
|
// Use explicit baseline if provided (null means "no baseline"), otherwise auto-derive
|
|
@@ -9,19 +9,6 @@ export class SeriesState {
|
|
|
9
9
|
#series = $derived(this._getSeries());
|
|
10
10
|
#stackConfig = $derived(this._getStackConfig());
|
|
11
11
|
selectedKeys;
|
|
12
|
-
/**
|
|
13
|
-
* Reactively syncs selectedKeys when series `selected` props change.
|
|
14
|
-
* When any series explicitly sets `selected: false`, the remaining series
|
|
15
|
-
* (with `selected` undefined or true) are pre-selected.
|
|
16
|
-
*/
|
|
17
|
-
#_syncSelectedFromProps = $effect.root(() => {
|
|
18
|
-
$effect(() => {
|
|
19
|
-
const keys = SeriesState.#selectedKeysFromSeries(this.#series);
|
|
20
|
-
if (keys) {
|
|
21
|
-
this.selectedKeys.current = keys;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
12
|
/**
|
|
26
13
|
* The current highlight series key for the chart.
|
|
27
14
|
*/
|
|
@@ -32,6 +19,15 @@ export class SeriesState {
|
|
|
32
19
|
// Compute initial selectedKeys synchronously from series `selected` props
|
|
33
20
|
const initialKeys = SeriesState.#selectedKeysFromSeries(getSeries());
|
|
34
21
|
this.selectedKeys = new SelectionState({ initial: initialKeys ?? undefined });
|
|
22
|
+
// Reactively sync selectedKeys when series `selected` props change.
|
|
23
|
+
// When any series explicitly sets `selected: false`, the remaining series
|
|
24
|
+
// (with `selected` undefined or true) are pre-selected.
|
|
25
|
+
$effect(() => {
|
|
26
|
+
const keys = SeriesState.#selectedKeysFromSeries(this.#series);
|
|
27
|
+
if (keys) {
|
|
28
|
+
this.selectedKeys.current = keys;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
35
31
|
}
|
|
36
32
|
/**
|
|
37
33
|
* Extract selected keys from series definitions.
|