layerchart 2.0.0-next.15 → 2.0.0-next.17
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/Arc.svelte +2 -2
- package/dist/components/Blur.svelte +5 -3
- package/dist/components/Blur.svelte.d.ts +2 -5
- package/dist/components/Connector.svelte +2 -2
- package/dist/components/Connector.svelte.d.ts +1 -1
- package/dist/components/Ellipse.svelte +187 -0
- package/dist/components/Ellipse.svelte.d.ts +64 -0
- package/dist/components/ForceSimulation.svelte +122 -38
- package/dist/components/ForceSimulation.svelte.d.ts +58 -23
- package/dist/components/GeoPath.svelte +5 -4
- package/dist/components/GeoPoint.svelte +1 -2
- package/dist/components/GeoSpline.svelte +4 -4
- package/dist/components/GeoSpline.svelte.d.ts +1 -1
- package/dist/components/MonthPath.svelte +11 -8
- package/dist/components/MonthPath.svelte.d.ts +4 -3
- package/dist/components/Polygon.svelte +285 -0
- package/dist/components/Polygon.svelte.d.ts +115 -0
- package/dist/components/Spline.svelte +29 -17
- package/dist/components/Spline.svelte.d.ts +12 -4
- package/dist/components/Treemap.svelte +63 -26
- package/dist/components/Treemap.svelte.d.ts +11 -11
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +4 -0
- package/dist/components/layout/Layer.svelte +6 -4
- package/dist/components/layout/Layer.svelte.d.ts +6 -4
- package/dist/components/tooltip/TooltipList.svelte +1 -1
- package/dist/utils/canvas.js +15 -0
- package/dist/utils/path.d.ts +10 -0
- package/dist/utils/path.js +30 -0
- package/dist/utils/shape.d.ts +43 -0
- package/dist/utils/shape.js +59 -0
- package/dist/utils/treemap.d.ts +1 -1
- package/package.json +1 -1
|
@@ -401,13 +401,13 @@
|
|
|
401
401
|
<Spline
|
|
402
402
|
pathData={trackArc()}
|
|
403
403
|
stroke="none"
|
|
404
|
-
bind:
|
|
404
|
+
bind:pathRef={trackRef}
|
|
405
405
|
{...extractLayerProps(track, 'arc-track')}
|
|
406
406
|
/>
|
|
407
407
|
{/if}
|
|
408
408
|
|
|
409
409
|
<Spline
|
|
410
|
-
bind:
|
|
410
|
+
bind:pathRef={ref}
|
|
411
411
|
pathData={arc()}
|
|
412
412
|
transform="translate({xOffset}, {yOffset})"
|
|
413
413
|
{fill}
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The default children snippet which provides
|
|
17
|
-
* the id
|
|
17
|
+
* the id for the filter.
|
|
18
18
|
*/
|
|
19
|
-
children?: Snippet
|
|
19
|
+
children?: Snippet;
|
|
20
20
|
};
|
|
21
21
|
</script>
|
|
22
22
|
|
|
@@ -42,7 +42,9 @@
|
|
|
42
42
|
|
|
43
43
|
{#if children}
|
|
44
44
|
<g filter="url(#{id})" class={layerClass('blur-g')}>
|
|
45
|
-
{@render children(
|
|
45
|
+
{@render children()}
|
|
46
46
|
</g>
|
|
47
47
|
{/if}
|
|
48
|
+
{:else if children}
|
|
49
|
+
{@render children()}
|
|
48
50
|
{/if}
|
|
@@ -11,12 +11,9 @@ export type BlurProps = {
|
|
|
11
11
|
stdDeviation?: number;
|
|
12
12
|
/**
|
|
13
13
|
* The default children snippet which provides
|
|
14
|
-
* the id
|
|
14
|
+
* the id for the filter.
|
|
15
15
|
*/
|
|
16
|
-
children?: Snippet
|
|
17
|
-
id: string;
|
|
18
|
-
url: string;
|
|
19
|
-
}]>;
|
|
16
|
+
children?: Snippet;
|
|
20
17
|
};
|
|
21
18
|
import type { Snippet } from 'svelte';
|
|
22
19
|
declare const Blur: import("svelte").Component<BlurProps, {}, "">;
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
type = 'rounded',
|
|
83
83
|
radius = 20,
|
|
84
84
|
curve = curveLinear,
|
|
85
|
-
|
|
85
|
+
pathRef = $bindable(),
|
|
86
86
|
pathData: pathDataProp,
|
|
87
87
|
marker,
|
|
88
88
|
markerStart,
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
|
|
138
138
|
<Spline
|
|
139
139
|
pathData={motionPath.current}
|
|
140
|
-
bind:
|
|
140
|
+
bind:pathRef
|
|
141
141
|
marker-start={markerStartId ? `url(#${markerStartId})` : undefined}
|
|
142
142
|
marker-mid={markerMidId ? `url(#${markerMidId})` : undefined}
|
|
143
143
|
marker-end={markerEndId ? `url(#${markerEndId})` : undefined}
|
|
@@ -46,6 +46,6 @@ import { type CurveFactory } from 'd3-shape';
|
|
|
46
46
|
import { type ConnectorCoords, type ConnectorSweep, type ConnectorType } from '../utils/connectorUtils.js';
|
|
47
47
|
import { type SplineProps, type SplinePropsWithoutHTML } from './Spline.svelte';
|
|
48
48
|
import type { Without } from '../utils/types.js';
|
|
49
|
-
declare const Connector: import("svelte").Component<ConnectorProps, {}, "
|
|
49
|
+
declare const Connector: import("svelte").Component<ConnectorProps, {}, "pathRef">;
|
|
50
50
|
type Connector = ReturnType<typeof Connector>;
|
|
51
51
|
export default Connector;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { CommonStyleProps, Without } from '../utils/types.js';
|
|
3
|
+
|
|
4
|
+
export type EllipsePropsWithoutHTML = {
|
|
5
|
+
/**
|
|
6
|
+
* The center x position of the ellipse.
|
|
7
|
+
*
|
|
8
|
+
* @default 0
|
|
9
|
+
*/
|
|
10
|
+
cx?: number;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The initial center x position of the ellipse.
|
|
14
|
+
*
|
|
15
|
+
* @default cx
|
|
16
|
+
*/
|
|
17
|
+
initialCx?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The center y position of the ellipse.
|
|
21
|
+
*
|
|
22
|
+
* @default 0
|
|
23
|
+
*/
|
|
24
|
+
cy?: number;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The initial center y position of the ellipse.
|
|
28
|
+
*
|
|
29
|
+
* @default cy
|
|
30
|
+
*/
|
|
31
|
+
initialCy?: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The radius of the ellipse on the x-axis.
|
|
35
|
+
*
|
|
36
|
+
* @default 1
|
|
37
|
+
*/
|
|
38
|
+
rx?: number;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The initial radius of the ellipse on the x-axis.
|
|
42
|
+
*
|
|
43
|
+
* @default rx
|
|
44
|
+
*/
|
|
45
|
+
initialRx?: number;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The radius of the ellipse on the y-axis.
|
|
49
|
+
*
|
|
50
|
+
* @default 1
|
|
51
|
+
*/
|
|
52
|
+
ry?: number;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The initial radius of the ellipse on the y-axis.
|
|
56
|
+
*
|
|
57
|
+
* @default ry
|
|
58
|
+
*/
|
|
59
|
+
initialRy?: number;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A bindable reference to the `<ellipse>` element
|
|
63
|
+
*
|
|
64
|
+
* @bindable
|
|
65
|
+
*/
|
|
66
|
+
ref?: SVGEllipseElement;
|
|
67
|
+
|
|
68
|
+
motion?: MotionProp;
|
|
69
|
+
} & CommonStyleProps;
|
|
70
|
+
|
|
71
|
+
export type EllipseProps = EllipsePropsWithoutHTML &
|
|
72
|
+
Without<SVGAttributes<Element>, EllipsePropsWithoutHTML>;
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<script lang="ts">
|
|
76
|
+
import { cls } from '@layerstack/tailwind';
|
|
77
|
+
import { merge } from 'lodash-es';
|
|
78
|
+
|
|
79
|
+
import { getRenderContext } from './Chart.svelte';
|
|
80
|
+
import { createMotion, type MotionProp } from '../utils/motion.svelte.js';
|
|
81
|
+
import { registerCanvasComponent } from './layout/Canvas.svelte';
|
|
82
|
+
import { renderEllipse, type ComputedStylesOptions } from '../utils/canvas.js';
|
|
83
|
+
import type { SVGAttributes } from 'svelte/elements';
|
|
84
|
+
import { createKey } from '../utils/key.svelte.js';
|
|
85
|
+
import { layerClass } from '../utils/attributes.js';
|
|
86
|
+
|
|
87
|
+
let {
|
|
88
|
+
cx = 0,
|
|
89
|
+
initialCx: initialCxProp,
|
|
90
|
+
cy = 0,
|
|
91
|
+
initialCy: initialCyProp,
|
|
92
|
+
rx = 1,
|
|
93
|
+
initialRx: initialRxProp,
|
|
94
|
+
ry = 1,
|
|
95
|
+
initialRy: initialRyProp,
|
|
96
|
+
motion,
|
|
97
|
+
fill,
|
|
98
|
+
fillOpacity,
|
|
99
|
+
stroke,
|
|
100
|
+
strokeWidth,
|
|
101
|
+
opacity,
|
|
102
|
+
class: className,
|
|
103
|
+
ref: refProp = $bindable(),
|
|
104
|
+
...restProps
|
|
105
|
+
}: EllipseProps = $props();
|
|
106
|
+
|
|
107
|
+
let ref = $state<SVGEllipseElement>();
|
|
108
|
+
|
|
109
|
+
$effect.pre(() => {
|
|
110
|
+
refProp = ref;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const initialCx = initialCxProp ?? cx;
|
|
114
|
+
const initialCy = initialCyProp ?? cy;
|
|
115
|
+
const initialRx = initialRxProp ?? rx;
|
|
116
|
+
const initialRy = initialRyProp ?? ry;
|
|
117
|
+
|
|
118
|
+
const renderCtx = getRenderContext();
|
|
119
|
+
|
|
120
|
+
const motionCx = createMotion(initialCx, () => cx, motion);
|
|
121
|
+
const motionCy = createMotion(initialCy, () => cy, motion);
|
|
122
|
+
const motionRx = createMotion(initialRx, () => rx, motion);
|
|
123
|
+
const motionRy = createMotion(initialRy, () => ry, motion);
|
|
124
|
+
|
|
125
|
+
function render(
|
|
126
|
+
ctx: CanvasRenderingContext2D,
|
|
127
|
+
styleOverrides: ComputedStylesOptions | undefined
|
|
128
|
+
) {
|
|
129
|
+
renderEllipse(
|
|
130
|
+
ctx,
|
|
131
|
+
{ cx: motionCx.current, cy: motionCy.current, rx: motionRx.current, ry: motionRy.current },
|
|
132
|
+
styleOverrides
|
|
133
|
+
? merge({ styles: { strokeWidth } }, styleOverrides)
|
|
134
|
+
: {
|
|
135
|
+
styles: { fill, fillOpacity, stroke, strokeWidth, opacity },
|
|
136
|
+
classes: className,
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// TODO: Use objectId to work around Svelte 4 reactivity issue (even when memoizing gradients)
|
|
142
|
+
const fillKey = createKey(() => fill);
|
|
143
|
+
const strokeKey = createKey(() => stroke);
|
|
144
|
+
|
|
145
|
+
if (renderCtx === 'canvas') {
|
|
146
|
+
registerCanvasComponent({
|
|
147
|
+
name: 'Ellipse',
|
|
148
|
+
render,
|
|
149
|
+
events: {
|
|
150
|
+
click: restProps.onclick,
|
|
151
|
+
pointerdown: restProps.onpointerdown,
|
|
152
|
+
pointerenter: restProps.onpointerenter,
|
|
153
|
+
pointermove: restProps.onpointermove,
|
|
154
|
+
pointerleave: restProps.onpointerleave,
|
|
155
|
+
},
|
|
156
|
+
deps: () => [
|
|
157
|
+
motionCx.current,
|
|
158
|
+
motionCy.current,
|
|
159
|
+
motionRx.current,
|
|
160
|
+
motionRy.current,
|
|
161
|
+
fillKey.current,
|
|
162
|
+
fillOpacity,
|
|
163
|
+
strokeKey.current,
|
|
164
|
+
strokeWidth,
|
|
165
|
+
opacity,
|
|
166
|
+
className,
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
{#if renderCtx === 'svg'}
|
|
173
|
+
<ellipse
|
|
174
|
+
bind:this={ref}
|
|
175
|
+
cx={motionCx.current}
|
|
176
|
+
cy={motionCy.current}
|
|
177
|
+
rx={motionRx.current}
|
|
178
|
+
ry={motionRy.current}
|
|
179
|
+
{fill}
|
|
180
|
+
fill-opacity={fillOpacity}
|
|
181
|
+
{stroke}
|
|
182
|
+
stroke-width={strokeWidth}
|
|
183
|
+
{opacity}
|
|
184
|
+
class={cls(layerClass('ellipse'), fill == null && 'fill-surface-content', className)}
|
|
185
|
+
{...restProps}
|
|
186
|
+
/>
|
|
187
|
+
{/if}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CommonStyleProps, Without } from '../utils/types.js';
|
|
2
|
+
export type EllipsePropsWithoutHTML = {
|
|
3
|
+
/**
|
|
4
|
+
* The center x position of the ellipse.
|
|
5
|
+
*
|
|
6
|
+
* @default 0
|
|
7
|
+
*/
|
|
8
|
+
cx?: number;
|
|
9
|
+
/**
|
|
10
|
+
* The initial center x position of the ellipse.
|
|
11
|
+
*
|
|
12
|
+
* @default cx
|
|
13
|
+
*/
|
|
14
|
+
initialCx?: number;
|
|
15
|
+
/**
|
|
16
|
+
* The center y position of the ellipse.
|
|
17
|
+
*
|
|
18
|
+
* @default 0
|
|
19
|
+
*/
|
|
20
|
+
cy?: number;
|
|
21
|
+
/**
|
|
22
|
+
* The initial center y position of the ellipse.
|
|
23
|
+
*
|
|
24
|
+
* @default cy
|
|
25
|
+
*/
|
|
26
|
+
initialCy?: number;
|
|
27
|
+
/**
|
|
28
|
+
* The radius of the ellipse on the x-axis.
|
|
29
|
+
*
|
|
30
|
+
* @default 1
|
|
31
|
+
*/
|
|
32
|
+
rx?: number;
|
|
33
|
+
/**
|
|
34
|
+
* The initial radius of the ellipse on the x-axis.
|
|
35
|
+
*
|
|
36
|
+
* @default rx
|
|
37
|
+
*/
|
|
38
|
+
initialRx?: number;
|
|
39
|
+
/**
|
|
40
|
+
* The radius of the ellipse on the y-axis.
|
|
41
|
+
*
|
|
42
|
+
* @default 1
|
|
43
|
+
*/
|
|
44
|
+
ry?: number;
|
|
45
|
+
/**
|
|
46
|
+
* The initial radius of the ellipse on the y-axis.
|
|
47
|
+
*
|
|
48
|
+
* @default ry
|
|
49
|
+
*/
|
|
50
|
+
initialRy?: number;
|
|
51
|
+
/**
|
|
52
|
+
* A bindable reference to the `<ellipse>` element
|
|
53
|
+
*
|
|
54
|
+
* @bindable
|
|
55
|
+
*/
|
|
56
|
+
ref?: SVGEllipseElement;
|
|
57
|
+
motion?: MotionProp;
|
|
58
|
+
} & CommonStyleProps;
|
|
59
|
+
export type EllipseProps = EllipsePropsWithoutHTML & Without<SVGAttributes<Element>, EllipsePropsWithoutHTML>;
|
|
60
|
+
import { type MotionProp } from '../utils/motion.svelte.js';
|
|
61
|
+
import type { SVGAttributes } from 'svelte/elements';
|
|
62
|
+
declare const Ellipse: import("svelte").Component<EllipseProps, {}, "ref">;
|
|
63
|
+
type Ellipse = ReturnType<typeof Ellipse>;
|
|
64
|
+
export default Ellipse;
|
|
@@ -8,35 +8,97 @@
|
|
|
8
8
|
} from 'd3-force';
|
|
9
9
|
import type { Snippet } from 'svelte';
|
|
10
10
|
|
|
11
|
-
type Forces
|
|
11
|
+
export type Forces<
|
|
12
|
+
NodeDatum extends SimulationNodeDatum,
|
|
13
|
+
LinkDatum extends SimulationLinkDatum<NodeDatum> | undefined,
|
|
14
|
+
> = Record<string, Force<NodeDatum, LinkDatum>>;
|
|
12
15
|
|
|
13
16
|
export type Data<TNode = any, TLink = any> = {
|
|
14
17
|
nodes: TNode[];
|
|
15
18
|
links?: TLink[];
|
|
16
19
|
};
|
|
17
20
|
|
|
18
|
-
export type LinkPosition =
|
|
21
|
+
export type LinkPosition = {
|
|
19
22
|
x1: number;
|
|
20
23
|
y1: number;
|
|
21
24
|
x2: number;
|
|
22
25
|
y2: number;
|
|
23
|
-
}
|
|
26
|
+
};
|
|
24
27
|
|
|
25
|
-
type
|
|
26
|
-
|
|
27
|
-
LinkDatum
|
|
28
|
-
|
|
28
|
+
export type OnStartEvent<
|
|
29
|
+
NodeDatum extends SimulationNodeDatum,
|
|
30
|
+
LinkDatum extends SimulationLinkDatum<NodeDatum> | undefined,
|
|
31
|
+
> = {
|
|
32
|
+
alpha: number;
|
|
33
|
+
alphaTarget: number;
|
|
34
|
+
simulation: SimulationFor<NodeDatum, LinkDatum>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type OnTickEvent<
|
|
38
|
+
NodeDatum extends SimulationNodeDatum,
|
|
39
|
+
LinkDatum extends SimulationLinkDatum<NodeDatum> | undefined,
|
|
40
|
+
> = {
|
|
41
|
+
alpha: number;
|
|
42
|
+
alphaTarget: number;
|
|
43
|
+
nodes: NodeDatumFor<NodeDatum>[];
|
|
44
|
+
links: LinkDatumFor<NodeDatum, LinkDatum>[];
|
|
45
|
+
simulation: SimulationFor<NodeDatum, LinkDatum>;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type OnEndEvent<
|
|
49
|
+
NodeDatum extends SimulationNodeDatum,
|
|
50
|
+
LinkDatum extends SimulationLinkDatum<NodeDatum> | undefined,
|
|
51
|
+
> = {
|
|
52
|
+
alpha: number;
|
|
53
|
+
alphaTarget: number;
|
|
54
|
+
simulation: SimulationFor<NodeDatum, LinkDatum>;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Default initial alpha value of the simulation.
|
|
59
|
+
*/
|
|
60
|
+
export const DEFAULT_ALPHA: number = 1;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Default target alpha value for the simulation.
|
|
64
|
+
*/
|
|
65
|
+
export const DEFAULT_ALPHA_TARGET: number = 0;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Default alpha decay rate per tick.
|
|
69
|
+
*
|
|
70
|
+
* Formula: `1 - Math.pow(0.001, 1 / 300)`.
|
|
71
|
+
*/
|
|
72
|
+
export const DEFAULT_ALPHA_DECAY: number = 1 - Math.pow(0.001, 1 / 300);
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Default minimum alpha value at which simulation stops.
|
|
76
|
+
*/
|
|
77
|
+
export const DEFAULT_ALPHA_MIN: number = 0.01;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Default velocity decay factor applied to nodes each tick.
|
|
81
|
+
*/
|
|
82
|
+
export const DEFAULT_VELOCITY_DECAY: number = 0.4;
|
|
83
|
+
|
|
84
|
+
type NodeDatumFor<NodeDatum> = NodeDatum & SimulationNodeDatum;
|
|
85
|
+
|
|
86
|
+
type LinkDatumFor<NodeDatum, LinkDatum> = LinkDatum &
|
|
87
|
+
SimulationLinkDatum<NodeDatumFor<NodeDatum>>;
|
|
29
88
|
|
|
30
89
|
type SimulationFor<NodeDatum, LinkDatum> = Simulation<
|
|
31
90
|
NodeDatumFor<NodeDatum>,
|
|
32
91
|
LinkDatumFor<NodeDatum, LinkDatum>
|
|
33
92
|
>;
|
|
34
93
|
|
|
35
|
-
export type ForceSimulationProps<
|
|
94
|
+
export type ForceSimulationProps<
|
|
95
|
+
NodeDatum extends SimulationNodeDatum,
|
|
96
|
+
LinkDatum extends SimulationLinkDatum<NodeDatum> | undefined,
|
|
97
|
+
> = {
|
|
36
98
|
/**
|
|
37
99
|
* Force simulation parameters
|
|
38
100
|
*/
|
|
39
|
-
forces: Forces
|
|
101
|
+
forces: Forces<NodeDatum, LinkDatum>;
|
|
40
102
|
|
|
41
103
|
/**
|
|
42
104
|
* An object with arrays of nodes and links,
|
|
@@ -46,31 +108,31 @@
|
|
|
46
108
|
|
|
47
109
|
/**
|
|
48
110
|
* Current alpha value of the simulation
|
|
49
|
-
* @default
|
|
111
|
+
* @default DEFAULT_ALPHA
|
|
50
112
|
*/
|
|
51
113
|
alpha?: number;
|
|
52
114
|
|
|
53
115
|
/**
|
|
54
116
|
* Target alpha value for the simulation
|
|
55
|
-
* @default
|
|
117
|
+
* @default DEFAULT_ALPHA_TARGET
|
|
56
118
|
*/
|
|
57
119
|
alphaTarget?: number;
|
|
58
120
|
|
|
59
121
|
/**
|
|
60
122
|
* Alpha decay rate per tick
|
|
61
|
-
* @default
|
|
123
|
+
* @default DEFAULT_ALPHA_DECAY
|
|
62
124
|
*/
|
|
63
125
|
alphaDecay?: number;
|
|
64
126
|
|
|
65
127
|
/**
|
|
66
128
|
* Minimum alpha value at which simulation stops
|
|
67
|
-
* @default
|
|
129
|
+
* @default DEFAULT_ALPHA_MIN
|
|
68
130
|
*/
|
|
69
131
|
alphaMin?: number;
|
|
70
132
|
|
|
71
133
|
/**
|
|
72
134
|
* Velocity decay factor applied to nodes each tick
|
|
73
|
-
* @default
|
|
135
|
+
* @default DEFAULT_VELOCITY_DECAY
|
|
74
136
|
*/
|
|
75
137
|
velocityDecay?: number;
|
|
76
138
|
|
|
@@ -95,17 +157,17 @@
|
|
|
95
157
|
/**
|
|
96
158
|
* Callback function triggered when simulation starts
|
|
97
159
|
*/
|
|
98
|
-
onStart?: () => void;
|
|
160
|
+
onStart?: (e: OnStartEvent<NodeDatum, LinkDatum | undefined>) => void;
|
|
99
161
|
|
|
100
162
|
/**
|
|
101
163
|
* Callback function triggered on each simulation tick
|
|
102
164
|
*/
|
|
103
|
-
onTick?: (e:
|
|
165
|
+
onTick?: (e: OnTickEvent<NodeDatum, LinkDatum | undefined>) => void;
|
|
104
166
|
|
|
105
167
|
/**
|
|
106
168
|
* Callback function triggered when simulation ends
|
|
107
169
|
*/
|
|
108
|
-
onEnd?: () => void;
|
|
170
|
+
onEnd?: (e: OnEndEvent<NodeDatum, LinkDatum | undefined>) => void;
|
|
109
171
|
|
|
110
172
|
children?: Snippet<
|
|
111
173
|
[
|
|
@@ -120,23 +182,26 @@
|
|
|
120
182
|
};
|
|
121
183
|
</script>
|
|
122
184
|
|
|
123
|
-
<script
|
|
185
|
+
<script
|
|
186
|
+
lang="ts"
|
|
187
|
+
generics="NodeDatum extends SimulationNodeDatum,
|
|
188
|
+
LinkDatum extends SimulationLinkDatum<NodeDatum> | undefined,"
|
|
189
|
+
>
|
|
124
190
|
import { watch } from 'runed';
|
|
125
|
-
import type { Prettify } from '@layerstack/utils';
|
|
126
191
|
|
|
127
192
|
let {
|
|
128
193
|
forces,
|
|
129
194
|
data,
|
|
130
|
-
alpha = $bindable(
|
|
131
|
-
alphaTarget =
|
|
132
|
-
alphaDecay =
|
|
133
|
-
alphaMin =
|
|
134
|
-
velocityDecay =
|
|
195
|
+
alpha = $bindable(DEFAULT_ALPHA),
|
|
196
|
+
alphaTarget = DEFAULT_ALPHA_TARGET,
|
|
197
|
+
alphaDecay = DEFAULT_ALPHA_DECAY,
|
|
198
|
+
alphaMin = DEFAULT_ALPHA_MIN,
|
|
199
|
+
velocityDecay = DEFAULT_VELOCITY_DECAY,
|
|
135
200
|
stopped = false,
|
|
136
201
|
static: staticProp,
|
|
137
|
-
onStart: onStartProp
|
|
138
|
-
onTick: onTickProp
|
|
139
|
-
onEnd: onEndProp
|
|
202
|
+
onStart: onStartProp,
|
|
203
|
+
onTick: onTickProp,
|
|
204
|
+
onEnd: onEndProp,
|
|
140
205
|
children,
|
|
141
206
|
cloneNodes = false,
|
|
142
207
|
}: ForceSimulationProps<NodeDatum, LinkDatum> = $props();
|
|
@@ -159,7 +224,7 @@
|
|
|
159
224
|
|
|
160
225
|
// d3.Simulation does not provide a `.forces()` getter, so we need to
|
|
161
226
|
// keep track of previous forces ourselves, for diffing against `forces`.
|
|
162
|
-
let previousForces: Forces = {};
|
|
227
|
+
let previousForces: Forces<NodeDatum, LinkDatum> = {};
|
|
163
228
|
|
|
164
229
|
let paused: boolean = true;
|
|
165
230
|
|
|
@@ -220,12 +285,8 @@
|
|
|
220
285
|
// pass it to the internal d3 simulation object:
|
|
221
286
|
pushAlphaToSimulation(alpha);
|
|
222
287
|
|
|
223
|
-
//
|
|
224
|
-
|
|
225
|
-
// otherwise our simulation will never terminate:
|
|
226
|
-
if (simulation.alpha() >= simulation.alphaMin()) {
|
|
227
|
-
runOrResumeSimulation();
|
|
228
|
-
}
|
|
288
|
+
// Then we attempt to resume the simulation:
|
|
289
|
+
runOrResumeSimulation();
|
|
229
290
|
}
|
|
230
291
|
);
|
|
231
292
|
|
|
@@ -263,7 +324,7 @@
|
|
|
263
324
|
simulation.nodes(nodes);
|
|
264
325
|
}
|
|
265
326
|
|
|
266
|
-
function pushForcesToSimulation(forces: Forces) {
|
|
327
|
+
function pushForcesToSimulation(forces: Forces<NodeDatum, LinkDatum>) {
|
|
267
328
|
// Evict obsolete forces:
|
|
268
329
|
const names = Object.keys(previousForces);
|
|
269
330
|
for (const name of names) {
|
|
@@ -366,6 +427,13 @@
|
|
|
366
427
|
return;
|
|
367
428
|
}
|
|
368
429
|
|
|
430
|
+
if (simulation.alpha() < simulation.alphaMin()) {
|
|
431
|
+
// Only resume the simulation as long as `alpha`
|
|
432
|
+
// is above the cut-off threshold of `alphaMin`,
|
|
433
|
+
// otherwise our simulation will never terminate:
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
369
437
|
onStart();
|
|
370
438
|
simulation.restart();
|
|
371
439
|
|
|
@@ -393,7 +461,12 @@
|
|
|
393
461
|
}
|
|
394
462
|
|
|
395
463
|
paused = false;
|
|
396
|
-
|
|
464
|
+
|
|
465
|
+
onStartProp?.({
|
|
466
|
+
alpha,
|
|
467
|
+
alphaTarget,
|
|
468
|
+
simulation,
|
|
469
|
+
});
|
|
397
470
|
}
|
|
398
471
|
|
|
399
472
|
function onTick() {
|
|
@@ -401,7 +474,13 @@
|
|
|
401
474
|
pullAlphaFromSimulation();
|
|
402
475
|
updateLinkPositions();
|
|
403
476
|
|
|
404
|
-
onTickProp({
|
|
477
|
+
onTickProp?.({
|
|
478
|
+
alpha,
|
|
479
|
+
alphaTarget,
|
|
480
|
+
nodes: simulatedNodes,
|
|
481
|
+
links: simulatedLinks,
|
|
482
|
+
simulation,
|
|
483
|
+
});
|
|
405
484
|
}
|
|
406
485
|
|
|
407
486
|
function onEnd() {
|
|
@@ -411,7 +490,12 @@
|
|
|
411
490
|
}
|
|
412
491
|
|
|
413
492
|
paused = true;
|
|
414
|
-
|
|
493
|
+
|
|
494
|
+
onEndProp?.({
|
|
495
|
+
alpha,
|
|
496
|
+
alphaTarget,
|
|
497
|
+
simulation,
|
|
498
|
+
});
|
|
415
499
|
}
|
|
416
500
|
|
|
417
501
|
$effect(() => {
|