layerchart 2.0.0-next.14 → 2.0.0-next.15

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.
@@ -1,26 +1,48 @@
1
1
  <script lang="ts" module>
2
- import { forceSimulation, type Force, type Simulation, type SimulationNodeDatum } from 'd3-force';
2
+ import {
3
+ forceSimulation,
4
+ type Force,
5
+ type Simulation,
6
+ type SimulationLinkDatum,
7
+ type SimulationNodeDatum,
8
+ } from 'd3-force';
3
9
  import type { Snippet } from 'svelte';
4
10
 
5
11
  type Forces = Record<string, Force<any, any>>;
6
12
 
7
- export type LinkPosition = {
13
+ export type Data<TNode = any, TLink = any> = {
14
+ nodes: TNode[];
15
+ links?: TLink[];
16
+ };
17
+
18
+ export type LinkPosition = Prettify<{
8
19
  x1: number;
9
20
  y1: number;
10
21
  x2: number;
11
22
  y2: number;
12
- };
23
+ }>;
24
+
25
+ type NodeDatumFor<NodeDatum> = Prettify<NodeDatum & SimulationNodeDatum>;
26
+ type LinkDatumFor<NodeDatum, LinkDatum> = Prettify<
27
+ LinkDatum & SimulationLinkDatum<NodeDatumFor<NodeDatum>>
28
+ >;
13
29
 
14
- export type ForceSimulationProps = {
30
+ type SimulationFor<NodeDatum, LinkDatum> = Simulation<
31
+ NodeDatumFor<NodeDatum>,
32
+ LinkDatumFor<NodeDatum, LinkDatum>
33
+ >;
34
+
35
+ export type ForceSimulationProps<NodeDatum, LinkDatum> = {
15
36
  /**
16
37
  * Force simulation parameters
17
38
  */
18
39
  forces: Forces;
19
40
 
20
41
  /**
21
- * An array of links to be used for position calculation.
42
+ * An object with arrays of nodes and links,
43
+ * to be used for position calculation.
22
44
  */
23
- links?: any[];
45
+ data: Data<NodeDatum, LinkDatum>;
24
46
 
25
47
  /**
26
48
  * Current alpha value of the simulation
@@ -88,22 +110,23 @@
88
110
  children?: Snippet<
89
111
  [
90
112
  {
91
- nodes: any[];
92
- simulation: Simulation<SimulationNodeDatum, undefined>;
113
+ nodes: NodeDatumFor<NodeDatum>[];
114
+ links: LinkDatumFor<NodeDatum, LinkDatum>[];
93
115
  linkPositions: LinkPosition[];
116
+ simulation: SimulationFor<NodeDatum, LinkDatum>;
94
117
  },
95
118
  ]
96
119
  >;
97
120
  };
98
121
  </script>
99
122
 
100
- <script lang="ts">
101
- import { getChartContext } from './Chart.svelte';
123
+ <script lang="ts" generics="NodeDatum, LinkDatum = undefined">
102
124
  import { watch } from 'runed';
125
+ import type { Prettify } from '@layerstack/utils';
103
126
 
104
127
  let {
105
128
  forces,
106
- links = [],
129
+ data,
107
130
  alpha = $bindable(1),
108
131
  alphaTarget = 0,
109
132
  alphaDecay = 1 - Math.pow(0.001, 1 / 300),
@@ -116,18 +139,23 @@
116
139
  onEnd: onEndProp = () => {},
117
140
  children,
118
141
  cloneNodes = false,
119
- }: ForceSimulationProps = $props();
120
-
121
- const ctx = getChartContext();
142
+ }: ForceSimulationProps<NodeDatum, LinkDatum> = $props();
122
143
 
123
144
  // MARK: Public Props
124
145
 
125
146
  // MARK: Private Props
126
147
 
127
- let nodes: SimulationNodeDatum[] = $state([]);
128
148
  let linkPositions: LinkPosition[] = $state([]);
149
+ let simulatedNodes: NodeDatumFor<NodeDatum>[] = $state([]);
150
+ let simulatedLinks: LinkDatumFor<NodeDatum, LinkDatum>[] = $derived(
151
+ (data.links ?? []) as LinkDatumFor<NodeDatum, LinkDatum>[]
152
+ );
129
153
 
130
- const simulation = forceSimulation().stop();
154
+ // This casting is unfortunately necessary, due to unfortunate
155
+ // overloading choices made, over at `@typed/d3-force`:
156
+ const simulation: SimulationFor<NodeDatum, LinkDatum> = (
157
+ forceSimulation() as SimulationFor<NodeDatum, LinkDatum>
158
+ ).stop();
131
159
 
132
160
  // d3.Simulation does not provide a `.forces()` getter, so we need to
133
161
  // keep track of previous forces ourselves, for diffing against `forces`.
@@ -166,11 +194,11 @@
166
194
  );
167
195
 
168
196
  watch.pre(
169
- () => ctx.data,
197
+ () => data,
170
198
  () => {
171
- // Any time the `data` store gets changed we
172
- // pass them to the internal d3 simulation object:
173
- pushNodesToSimulation(ctx.data as any[]);
199
+ // Any time the `nodes` prop, or the `data` store gets changed
200
+ // we pass them to the internal d3 simulation object:
201
+ pushNodesToSimulation(data.nodes);
174
202
  runOrResumeSimulation();
175
203
  }
176
204
  );
@@ -259,7 +287,7 @@
259
287
  // Keeping the link positions in sync with the simulation
260
288
  // so we don't need to recalculate _all_ link positions on each tick
261
289
  // which bogs down the simulation
262
- linkPositions = links.map((link: any) => ({
290
+ linkPositions = simulatedLinks.map((link: any) => ({
263
291
  x1: link.source.x ?? 0,
264
292
  y1: link.source.y ?? 0,
265
293
  x2: link.target.x ?? 0,
@@ -270,7 +298,8 @@
270
298
  // MARK: Pull State
271
299
 
272
300
  function pullNodesFromSimulation() {
273
- nodes = cloneNodes ? structuredClone(simulation.nodes()) : simulation.nodes();
301
+ const simulationNodes = simulation.nodes();
302
+ simulatedNodes = cloneNodes ? structuredClone(simulationNodes) : simulationNodes;
274
303
  }
275
304
 
276
305
  function pullAlphaFromSimulation() {
@@ -393,4 +422,9 @@
393
422
  });
394
423
  </script>
395
424
 
396
- {@render children?.({ nodes: nodes, simulation, linkPositions })}
425
+ {@render children?.({
426
+ nodes: simulatedNodes,
427
+ links: simulatedLinks,
428
+ simulation,
429
+ linkPositions,
430
+ })}
@@ -1,21 +1,29 @@
1
- import { type Force, type Simulation, type SimulationNodeDatum } from 'd3-force';
1
+ import { type Force, type Simulation, type SimulationLinkDatum, type SimulationNodeDatum } from 'd3-force';
2
2
  import type { Snippet } from 'svelte';
3
3
  type Forces = Record<string, Force<any, any>>;
4
- export type LinkPosition = {
4
+ export type Data<TNode = any, TLink = any> = {
5
+ nodes: TNode[];
6
+ links?: TLink[];
7
+ };
8
+ export type LinkPosition = Prettify<{
5
9
  x1: number;
6
10
  y1: number;
7
11
  x2: number;
8
12
  y2: number;
9
- };
10
- export type ForceSimulationProps = {
13
+ }>;
14
+ type NodeDatumFor<NodeDatum> = Prettify<NodeDatum & SimulationNodeDatum>;
15
+ type LinkDatumFor<NodeDatum, LinkDatum> = Prettify<LinkDatum & SimulationLinkDatum<NodeDatumFor<NodeDatum>>>;
16
+ type SimulationFor<NodeDatum, LinkDatum> = Simulation<NodeDatumFor<NodeDatum>, LinkDatumFor<NodeDatum, LinkDatum>>;
17
+ export type ForceSimulationProps<NodeDatum, LinkDatum> = {
11
18
  /**
12
19
  * Force simulation parameters
13
20
  */
14
21
  forces: Forces;
15
22
  /**
16
- * An array of links to be used for position calculation.
23
+ * An object with arrays of nodes and links,
24
+ * to be used for position calculation.
17
25
  */
18
- links?: any[];
26
+ data: Data<NodeDatum, LinkDatum>;
19
27
  /**
20
28
  * Current alpha value of the simulation
21
29
  * @default 1
@@ -73,12 +81,28 @@ export type ForceSimulationProps = {
73
81
  onEnd?: () => void;
74
82
  children?: Snippet<[
75
83
  {
76
- nodes: any[];
77
- simulation: Simulation<SimulationNodeDatum, undefined>;
84
+ nodes: NodeDatumFor<NodeDatum>[];
85
+ links: LinkDatumFor<NodeDatum, LinkDatum>[];
78
86
  linkPositions: LinkPosition[];
87
+ simulation: SimulationFor<NodeDatum, LinkDatum>;
79
88
  }
80
89
  ]>;
81
90
  };
82
- declare const ForceSimulation: import("svelte").Component<ForceSimulationProps, {}, "alpha">;
83
- type ForceSimulation = ReturnType<typeof ForceSimulation>;
91
+ import type { Prettify } from '@layerstack/utils';
92
+ declare class __sveltets_Render<NodeDatum, LinkDatum = undefined> {
93
+ props(): ForceSimulationProps<NodeDatum, LinkDatum>;
94
+ events(): {};
95
+ slots(): {};
96
+ bindings(): "alpha";
97
+ exports(): {};
98
+ }
99
+ interface $$IsomorphicComponent {
100
+ new <NodeDatum, LinkDatum = undefined>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['props']>, ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['events']>, ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['slots']>> & {
101
+ $$bindings?: ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['bindings']>;
102
+ } & ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['exports']>;
103
+ <NodeDatum, LinkDatum = undefined>(internal: unknown, props: ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['props']> & {}): ReturnType<__sveltets_Render<NodeDatum, LinkDatum>['exports']>;
104
+ z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
105
+ }
106
+ declare const ForceSimulation: $$IsomorphicComponent;
107
+ type ForceSimulation<NodeDatum, LinkDatum = undefined> = InstanceType<typeof ForceSimulation<NodeDatum, LinkDatum>>;
84
108
  export default ForceSimulation;
@@ -75,3 +75,17 @@ export declare function getSpiral({ angle, radius, count, width, height, }: {
75
75
  x: number;
76
76
  y: number;
77
77
  }[];
78
+ interface SineWaveOptions {
79
+ numPoints: number;
80
+ frequency?: number;
81
+ amplitude?: number;
82
+ noiseLevel?: number;
83
+ phase?: number;
84
+ xMin?: number;
85
+ xMax?: number;
86
+ }
87
+ export declare function generateSineWave(options: SineWaveOptions): {
88
+ x: number;
89
+ y: number;
90
+ }[];
91
+ export {};
@@ -124,3 +124,21 @@ export function getSpiral({ angle, radius, count, width, height, }) {
124
124
  };
125
125
  });
126
126
  }
127
+ export function generateSineWave(options) {
128
+ const { numPoints, frequency = 1, amplitude = 1, noiseLevel = 0, phase = 0, xMin = 0, xMax = 2 * Math.PI, } = options;
129
+ if (numPoints <= 0) {
130
+ throw new Error('Number of points must be greater than 0');
131
+ }
132
+ const points = [];
133
+ const xStep = (xMax - xMin) / (numPoints - 1);
134
+ for (let i = 0; i < numPoints; i++) {
135
+ const x = xMin + i * xStep;
136
+ // Generate base sine wave
137
+ const sineValue = amplitude * Math.sin(frequency * x + phase);
138
+ // Add random noise if specified
139
+ const noise = noiseLevel > 0 ? (Math.random() - 0.5) * 2 * noiseLevel : 0;
140
+ const y = sineValue + noise;
141
+ points.push({ x, y });
142
+ }
143
+ return points;
144
+ }
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": "2.0.0-next.14",
7
+ "version": "2.0.0-next.15",
8
8
  "devDependencies": {
9
9
  "@changesets/cli": "^2.29.4",
10
10
  "@iconify-json/lucide": "^1.2.44",