layerchart 0.41.5 → 0.42.0

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.
Files changed (68) hide show
  1. package/dist/components/Arc.svelte.d.ts +8 -8
  2. package/dist/components/Area.svelte.d.ts +5 -15
  3. package/dist/components/AreaStack.svelte.d.ts +2 -2
  4. package/dist/components/Axis.svelte.d.ts +8 -8
  5. package/dist/components/Bar.svelte.d.ts +9 -9
  6. package/dist/components/Bars.svelte.d.ts +8 -8
  7. package/dist/components/Blur.svelte.d.ts +2 -2
  8. package/dist/components/Bounds.svelte.d.ts +2 -2
  9. package/dist/components/Brush.svelte.d.ts +16 -16
  10. package/dist/components/Calendar.svelte.d.ts +3 -5
  11. package/dist/components/Chart.svelte +1 -1
  12. package/dist/components/Chart.svelte.d.ts +7 -7
  13. package/dist/components/ChartClipPath.svelte.d.ts +1 -1
  14. package/dist/components/Circle.svelte.d.ts +6 -6
  15. package/dist/components/CircleClipPath.svelte.d.ts +3 -3
  16. package/dist/components/ClipPath.svelte.d.ts +2 -2
  17. package/dist/components/ColorRamp.svelte.d.ts +3 -3
  18. package/dist/components/ForceSimulation.svelte +180 -24
  19. package/dist/components/ForceSimulation.svelte.d.ts +18 -7
  20. package/dist/components/Frame.svelte.d.ts +1 -1
  21. package/dist/components/GeoCircle.svelte.d.ts +5 -4
  22. package/dist/components/GeoContext.svelte.d.ts +2 -2
  23. package/dist/components/GeoPath.svelte.d.ts +4 -4
  24. package/dist/components/GeoPoint.svelte.d.ts +2 -2
  25. package/dist/components/GeoSpline.svelte.d.ts +1 -1
  26. package/dist/components/GeoTile.svelte.d.ts +4 -4
  27. package/dist/components/Graticule.svelte.d.ts +1 -1
  28. package/dist/components/Group.svelte.d.ts +2 -2
  29. package/dist/components/Highlight.svelte.d.ts +22 -72
  30. package/dist/components/HitCanvas.svelte.d.ts +2 -2
  31. package/dist/components/Hull.svelte.d.ts +4 -4
  32. package/dist/components/Labels.svelte.d.ts +5 -5
  33. package/dist/components/Legend.svelte.d.ts +12 -12
  34. package/dist/components/Line.svelte.d.ts +4 -4
  35. package/dist/components/LinearGradient.svelte.d.ts +8 -8
  36. package/dist/components/Link.svelte.d.ts +7 -7
  37. package/dist/components/MotionPath.svelte.d.ts +5 -5
  38. package/dist/components/Partition.svelte.d.ts +1 -1
  39. package/dist/components/Pie.svelte.d.ts +5 -5
  40. package/dist/components/Points.svelte.d.ts +5 -14
  41. package/dist/components/RadialGradient.svelte.d.ts +10 -10
  42. package/dist/components/Rect.svelte.d.ts +6 -6
  43. package/dist/components/RectClipPath.svelte.d.ts +5 -5
  44. package/dist/components/Rule.svelte.d.ts +2 -2
  45. package/dist/components/Sankey.svelte.d.ts +6 -6
  46. package/dist/components/Spline.svelte.d.ts +2 -2
  47. package/dist/components/Text.svelte.d.ts +12 -12
  48. package/dist/components/Threshold.svelte.d.ts +7 -3
  49. package/dist/components/TileImage.svelte.d.ts +2 -2
  50. package/dist/components/Tooltip.svelte.d.ts +13 -13
  51. package/dist/components/TooltipContext.svelte.d.ts +7 -7
  52. package/dist/components/TooltipItem.svelte.d.ts +5 -5
  53. package/dist/components/TransformContext.svelte.d.ts +24 -24
  54. package/dist/components/TransformControls.svelte.d.ts +3 -3
  55. package/dist/components/Tree.svelte.d.ts +2 -2
  56. package/dist/components/Treemap.svelte.d.ts +6 -6
  57. package/dist/components/Voronoi.svelte.d.ts +7 -7
  58. package/dist/components/layout/Canvas.svelte.d.ts +3 -3
  59. package/dist/docs/Code.svelte.d.ts +7 -7
  60. package/dist/docs/CurveMenuField.svelte.d.ts +1 -1
  61. package/dist/docs/Json.svelte.d.ts +1 -1
  62. package/dist/docs/PathDataMenuField.svelte.d.ts +3 -3
  63. package/dist/docs/Preview.svelte.d.ts +3 -3
  64. package/dist/docs/TilesetField.svelte.d.ts +2 -2
  65. package/dist/stores/motionStore.d.ts +0 -1
  66. package/dist/utils/rect.d.ts +0 -1
  67. package/dist/utils/scales.d.ts +0 -1
  68. package/package.json +13 -13
@@ -6,18 +6,18 @@ declare const __propDef: {
6
6
  [x: string]: any;
7
7
  spring?: boolean | Parameters<typeof springStore>[1];
8
8
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
9
- value?: number | undefined;
10
- initialValue?: number | undefined;
11
- domain?: number[] | undefined;
12
- range?: number[] | undefined;
9
+ value?: number;
10
+ initialValue?: number;
11
+ domain?: number[];
12
+ range?: number[];
13
13
  startAngle?: number | undefined;
14
14
  endAngle?: number | undefined;
15
15
  innerRadius?: number | undefined;
16
16
  outerRadius?: number | undefined;
17
- cornerRadius?: number | undefined;
18
- padAngle?: number | undefined;
19
- track?: boolean | SVGAttributes<SVGPathElement> | undefined;
20
- offset?: number | undefined;
17
+ cornerRadius?: number;
18
+ padAngle?: number;
19
+ track?: boolean | SVGAttributes<SVGPathElement>;
20
+ offset?: number;
21
21
  };
22
22
  events: {
23
23
  click: MouseEvent;
@@ -1,32 +1,22 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import { type ComponentProps } from 'svelte';
2
3
  import type { tweened as tweenedStore } from 'svelte/motion';
3
- import { type Area } from 'd3-shape';
4
4
  import type { CurveFactory } from 'd3-shape';
5
+ import Spline from './Spline.svelte';
5
6
  declare const __propDef: {
6
7
  props: {
7
8
  [x: string]: any;
8
9
  data?: any;
9
10
  pathData?: string | undefined | null;
10
- radial?: boolean | undefined;
11
+ radial?: boolean;
11
12
  x?: any;
12
13
  y0?: any;
13
14
  y1?: any;
14
15
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
15
16
  clipPath?: string | undefined;
16
17
  curve?: CurveFactory | undefined;
17
- defined?: Parameters<Area<any>['defined']>[0] | undefined;
18
- line?: boolean | Partial<{
19
- [x: string]: any;
20
- data?: any;
21
- pathData?: string | null | undefined;
22
- radial?: boolean | undefined;
23
- x?: any;
24
- y?: any;
25
- tweened?: boolean | import("svelte/motion").TweenedOptions<unknown> | undefined;
26
- draw?: boolean | import("svelte/transition").DrawParams | undefined;
27
- curve?: CurveFactory | import("d3-shape").CurveFactoryLineOnly | undefined;
28
- defined?: ((d: any, index: number, data: any[]) => boolean) | undefined;
29
- }> | undefined;
18
+ defined?: Parameters<Area<any>["defined"]>[0] | undefined;
19
+ line?: boolean | Partial<ComponentProps<Spline>>;
30
20
  };
31
21
  events: {
32
22
  click: MouseEvent;
@@ -6,8 +6,8 @@ import Spline from './Spline.svelte';
6
6
  declare const __propDef: {
7
7
  props: {
8
8
  curve?: CurveFactory | undefined;
9
- defined?: ComponentProps<Spline>['defined'] | undefined;
10
- opacity?: number | undefined;
9
+ defined?: ComponentProps<Spline>["defined"] | undefined;
10
+ opacity?: number;
11
11
  line?: boolean | any;
12
12
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
13
13
  };
@@ -7,20 +7,20 @@ import { type FormatType, type TransitionParams } from 'svelte-ux';
7
7
  import Text from './Text.svelte';
8
8
  declare const __propDef: {
9
9
  props: {
10
- /** Location of axis */ placement: 'top' | 'bottom' | 'left' | 'right' | 'angle' | 'radius';
11
- /** Axis label */ label?: string | undefined;
12
- /** Location of axis label */ labelPlacement?: "start" | "end" | "middle" | undefined;
10
+ /** Location of axis */ placement: "top" | "bottom" | "left" | "right" | "angle" | "radius";
11
+ /** Axis label */ label?: string;
12
+ /** Location of axis label */ labelPlacement?: "start" | "middle" | "end";
13
13
  /** Props applied label Text */ labelProps?: Partial<ComponentProps<Text>> | undefined;
14
- /** Draw a rule line. Use Rule component for greater rendering order control */ rule?: boolean | SVGAttributes<SVGLineElement> | undefined;
15
- /** Draw a grid lines */ grid?: boolean | SVGAttributes<SVGLineElement> | undefined;
14
+ /** Draw a rule line. Use Rule component for greater rendering order control */ rule?: boolean | SVGAttributes<SVGLineElement>;
15
+ /** Draw a grid lines */ grid?: boolean | SVGAttributes<SVGLineElement>;
16
16
  /** Control the number of ticks*/ ticks?: number | any[] | Function | undefined;
17
- /** Length of the tick line */ tickLength?: number | undefined;
17
+ /** Length of the tick line */ tickLength?: number;
18
18
  /** Format tick labels */ format?: FormatType | undefined;
19
19
  /** Props to apply to each tick label */ tickLabelProps?: Partial<ComponentProps<Text>> | undefined;
20
20
  spring?: boolean | Parameters<typeof springStore>[1];
21
21
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
22
- transitionIn?: typeof fade | (() => void) | undefined;
23
- transitionInParams?: TransitionParams | undefined;
22
+ transitionIn?: typeof fade | (() => void);
23
+ transitionInParams?: TransitionParams;
24
24
  scale?: any;
25
25
  };
26
26
  events: {
@@ -8,16 +8,16 @@ declare const __propDef: {
8
8
  x?: any;
9
9
  y?: any;
10
10
  fill?: string | undefined;
11
- stroke?: string | undefined;
12
- strokeWidth?: number | undefined;
13
- radius?: number | undefined;
14
- rounded?: "top" | "bottom" | "left" | "right" | "all" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | undefined;
15
- inset?: number | undefined;
11
+ stroke?: string;
12
+ strokeWidth?: number;
13
+ radius?: number;
14
+ rounded?: "all" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
15
+ inset?: number;
16
16
  groupBy?: string | undefined;
17
- groupPaddingInner?: number | undefined;
18
- groupPaddingOuter?: number | undefined;
19
- spring?: ComponentProps<Rect>['spring'];
20
- tweened?: ComponentProps<Rect>['tweened'];
17
+ groupPaddingInner?: number;
18
+ groupPaddingOuter?: number;
19
+ spring?: ComponentProps<Rect>["spring"];
20
+ tweened?: ComponentProps<Rect>["tweened"];
21
21
  };
22
22
  events: {
23
23
  click: MouseEvent;
@@ -6,15 +6,15 @@ declare const __propDef: {
6
6
  [x: string]: any;
7
7
  x?: any;
8
8
  y?: any;
9
- stroke?: string | undefined;
10
- strokeWidth?: number | undefined;
11
- radius?: number | undefined;
12
- inset?: number | undefined;
13
- spring?: ComponentProps<Rect>['spring'];
14
- tweened?: ComponentProps<Rect>['tweened'];
9
+ stroke?: string;
10
+ strokeWidth?: number;
11
+ radius?: number;
12
+ inset?: number;
13
+ spring?: ComponentProps<Rect>["spring"];
14
+ tweened?: ComponentProps<Rect>["tweened"];
15
15
  groupBy?: string | undefined;
16
- groupPaddingInner?: number | undefined;
17
- groupPaddingOuter?: number | undefined;
16
+ groupPaddingInner?: number;
17
+ groupPaddingOuter?: number;
18
18
  };
19
19
  events: {
20
20
  [evt: string]: CustomEvent<any>;
@@ -1,8 +1,8 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
- id?: string | undefined;
5
- stdDeviation?: number | undefined;
4
+ id?: string;
5
+ stdDeviation?: number;
6
6
  };
7
7
  events: {
8
8
  [evt: string]: CustomEvent<any>;
@@ -30,8 +30,8 @@ declare const __propDef: {
30
30
  x1: number;
31
31
  y1: number;
32
32
  });
33
- spring?: boolean | Parameters<typeof motionScale>[1]['spring'];
34
- tweened?: boolean | Parameters<typeof motionScale>[1]['tweened'];
33
+ spring?: boolean | Parameters<typeof motionScale>[1]["spring"];
34
+ tweened?: boolean | Parameters<typeof motionScale>[1]["tweened"];
35
35
  };
36
36
  events: {
37
37
  [evt: string]: CustomEvent<any>;
@@ -3,32 +3,32 @@ import type { SVGAttributes } from 'svelte/elements';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  [x: string]: any;
6
- axis?: "x" | "y" | "both" | undefined;
7
- handleSize?: number | undefined;
8
- resetOnEnd?: boolean | undefined;
9
- xDomain?: [number | null, number | null] | undefined;
10
- yDomain?: [number | null, number | null] | undefined;
6
+ axis?: "x" | "y" | "both";
7
+ handleSize?: number;
8
+ resetOnEnd?: boolean;
9
+ xDomain?: [number | null, number | null];
10
+ yDomain?: [number | null, number | null];
11
11
  range?: SVGAttributes<SVGRectElement> | undefined;
12
12
  handle?: SVGAttributes<SVGRectElement> | undefined;
13
13
  classes?: {
14
- root?: string | undefined;
15
- frame?: string | undefined;
16
- range?: string | undefined;
17
- handle?: string | undefined;
18
- } | undefined;
14
+ root?: string;
15
+ frame?: string;
16
+ range?: string;
17
+ handle?: string;
18
+ };
19
19
  };
20
20
  events: {
21
21
  change: CustomEvent<{
22
- xDomain?: [any, any] | undefined;
23
- yDomain?: [any, any] | undefined;
22
+ xDomain?: [any, any];
23
+ yDomain?: [any, any];
24
24
  }>;
25
25
  brushStart: CustomEvent<{
26
- xDomain?: [any, any] | undefined;
27
- yDomain?: [any, any] | undefined;
26
+ xDomain?: [any, any];
27
+ yDomain?: [any, any];
28
28
  }>;
29
29
  brushEnd: CustomEvent<{
30
- xDomain?: [any, any] | undefined;
31
- yDomain?: [any, any] | undefined;
30
+ xDomain?: [any, any];
31
+ yDomain?: [any, any];
32
32
  }>;
33
33
  } & {
34
34
  [evt: string]: CustomEvent<any>;
@@ -1,16 +1,14 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
+ import { type ComponentProps } from 'svelte';
2
3
  import type { TooltipContextValue } from './TooltipContext.svelte';
4
+ import MonthPath from './MonthPath.svelte';
3
5
  declare const __propDef: {
4
6
  props: {
5
7
  [x: string]: any;
6
8
  start: Date;
7
9
  end: Date;
8
10
  cellSize?: number | [number, number] | undefined;
9
- monthPath?: boolean | Partial<{
10
- [x: string]: any;
11
- date: Date;
12
- cellSize: number | [number, number];
13
- }> | undefined;
11
+ monthPath?: boolean | Partial<ComponentProps<MonthPath>>;
14
12
  tooltip?: TooltipContextValue | undefined;
15
13
  };
16
14
  events: {
@@ -115,7 +115,7 @@ onMount(() => {
115
115
  >
116
116
  <!-- Apply `fitGeojson` using TransformContext instead of GeoContext if `applyTransform` is used -->
117
117
  {@const initialTransform =
118
- geo?.applyTransform && geo?.fitGeojson && geo?.projection
118
+ geo?.applyTransform?.includes('translate') && geo?.fitGeojson && geo?.projection
119
119
  ? geoFitObjectTransform(geo.projection(), [width, height], geo.fitGeojson)
120
120
  : undefined}
121
121
 
@@ -14,16 +14,16 @@ import TransformContext from './TransformContext.svelte';
14
14
  declare const __propDef: {
15
15
  props: {
16
16
  [x: string]: any;
17
- data?: any[] | undefined;
17
+ data?: any[];
18
18
  x?: (string | number | ((d: any) => number)) | (string | number | ((d: any) => number))[] | undefined;
19
19
  y?: (string | number | ((d: any) => number)) | (string | number | ((d: any) => number))[] | undefined;
20
20
  yScale?: Function | undefined;
21
- xBaseline?: number | null | undefined;
22
- yBaseline?: number | null | undefined;
21
+ xBaseline?: number | null;
22
+ yBaseline?: number | null;
23
23
  geo?: Partial<ComponentProps<GeoContext>> | undefined;
24
24
  tooltip?: Partial<ComponentProps<TooltipContext>> | boolean | undefined;
25
25
  transform?: Partial<ComponentProps<TransformContext>> | undefined;
26
- transformContext?: TransformContext | undefined;
26
+ transformContext?: TransformContext;
27
27
  };
28
28
  events: {
29
29
  transform: CustomEvent<{
@@ -49,7 +49,7 @@ declare const __propDef: {
49
49
  projection: import("d3-geo").GeoProjection | import("d3-geo").GeoIdentityTransform;
50
50
  transform: {
51
51
  scale: number;
52
- setScale: (value: number, options?: import("../stores/motionStore").MotionOptions | undefined) => void;
52
+ setScale: (value: number, options?: import("../stores/motionStore").MotionOptions) => void;
53
53
  translate: {
54
54
  x: number;
55
55
  y: number;
@@ -57,14 +57,14 @@ declare const __propDef: {
57
57
  setTranslate: (point: {
58
58
  x: number;
59
59
  y: number;
60
- }, options?: import("../stores/motionStore").MotionOptions | undefined) => void;
60
+ }, options?: import("../stores/motionStore").MotionOptions) => void;
61
61
  zoomTo: (center: {
62
62
  x: number;
63
63
  y: number;
64
64
  }, rect?: {
65
65
  width: number;
66
66
  height: number;
67
- } | undefined) => void;
67
+ }) => void;
68
68
  reset: () => void;
69
69
  };
70
70
  tooltip: {
@@ -2,7 +2,7 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  [x: string]: any;
5
- full?: boolean | undefined;
5
+ full?: boolean;
6
6
  };
7
7
  events: {
8
8
  click: CustomEvent<any>;
@@ -3,12 +3,12 @@ import type { spring as springStore, tweened as tweenedStore } from 'svelte/moti
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  [x: string]: any;
6
- cx?: number | undefined;
7
- initialCx?: number | undefined;
8
- cy?: number | undefined;
9
- initialCy?: number | undefined;
10
- r?: number | undefined;
11
- initialR?: number | undefined;
6
+ cx?: number;
7
+ initialCx?: number;
8
+ cy?: number;
9
+ initialCy?: number;
10
+ r?: number;
11
+ initialR?: number;
12
12
  spring?: boolean | Parameters<typeof springStore>[1];
13
13
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
14
14
  };
@@ -3,9 +3,9 @@ import type { spring as springStore, tweened as tweenedStore } from 'svelte/moti
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  [x: string]: any;
6
- id?: string | undefined;
7
- cx?: number | undefined;
8
- cy?: number | undefined;
6
+ id?: string;
7
+ cx?: number;
8
+ cy?: number;
9
9
  r: number;
10
10
  spring?: boolean | Parameters<typeof springStore>[1];
11
11
  tweened?: boolean | Parameters<typeof tweenedStore>[1];
@@ -2,9 +2,9 @@ import { SvelteComponentTyped } from "svelte";
2
2
  declare const __propDef: {
3
3
  props: {
4
4
  [x: string]: any;
5
- id?: string | undefined;
5
+ id?: string;
6
6
  useId?: string | undefined;
7
- disabled?: boolean | undefined;
7
+ disabled?: boolean;
8
8
  };
9
9
  events: {
10
10
  click: MouseEvent;
@@ -3,9 +3,9 @@ declare const __propDef: {
3
3
  props: {
4
4
  [x: string]: any;
5
5
  interpolator: (t: number) => string;
6
- steps?: number | undefined;
7
- height?: string | number | undefined;
8
- width?: string | number | undefined;
6
+ steps?: number;
7
+ height?: string | number;
8
+ width?: string | number;
9
9
  };
10
10
  events: {
11
11
  [evt: string]: CustomEvent<any>;
@@ -1,49 +1,205 @@
1
- <script>import { getContext } from 'svelte';
1
+ <script>import { createEventDispatcher, getContext } from 'svelte';
2
2
  import { forceSimulation } from 'd3-force';
3
3
  const { data } = getContext('LayerCake');
4
+ const dispatch = createEventDispatcher();
4
5
  export let forces;
5
6
  export let alpha = 1;
6
7
  export let alphaTarget = 0;
7
8
  export let alphaDecay = 1 - Math.pow(0.001, 1 / 300);
8
9
  export let alphaMin = 0.001;
9
10
  export let velocityDecay = 0.4;
10
- /** Clone data since simulation mutates original */
11
- export let cloneData = false;
11
+ export let alphaResponse = undefined;
12
+ export let stopped = false;
12
13
  let _static = false;
13
14
  /** If true, will only update nodes after simulation has completed */
14
15
  export { _static as static };
15
- let simulation = forceSimulation(cloneData ? structuredClone($data) : $data);
16
+ /** Clone data since simulation mutates original */
17
+ export const cloneData = false;
18
+ // MARK: Private Props
19
+ let nodes = [];
20
+ const simulation = forceSimulation().stop();
21
+ // d3.Simulation does not provide a `.forces()` getter, so we need to
22
+ // keep track of previous forces ourselves, for diffing against `forces`.
23
+ let previousForces = {};
24
+ let paused = true;
25
+ // MARK: Reactivity Effects
26
+ $: {
27
+ // Any time the `stopped` prop gets toggled we
28
+ // update the running state of the simulation:
29
+ if (stopped) {
30
+ pauseDynamicSimulation();
31
+ }
32
+ else {
33
+ runOrResumeSimulation();
34
+ }
35
+ }
36
+ $: {
37
+ // Any time the `static` prop gets toggled we
38
+ // either attach or detach our internal event listeners:
39
+ if (_static) {
40
+ simulation.on('tick', null).on('end', null);
41
+ }
42
+ else {
43
+ simulation.on('tick', onTick).on('end', onEnd);
44
+ }
45
+ runOrResumeSimulation();
46
+ }
47
+ $: {
48
+ // Any time the `$data` store gets changed we
49
+ // pass them to the internal d3 simulation object:
50
+ pushNodesToSimulation($data);
51
+ runOrResumeSimulation();
52
+ }
16
53
  $: {
54
+ // Any time the `forces` prop gets changed we
55
+ // pass them to the internal d3 simulation object:
56
+ pushForcesToSimulation(forces);
57
+ runOrResumeSimulation();
58
+ }
59
+ $: {
60
+ // Any time the `alpha` prop gets changed we
61
+ // pass it to the internal d3 simulation object:
62
+ pushAlphaToSimulation(alpha);
63
+ // Only resume the simulation as long as `alpha`
64
+ // is above the cut-off threshold of `alphaMin`,
65
+ // otherwise our simulation will never terminate:
66
+ if (simulation.alpha() >= simulation.alphaMin()) {
67
+ runOrResumeSimulation();
68
+ }
69
+ }
70
+ $: {
71
+ // Any time any of the the alpha props get changed we
72
+ // pass them all to the internal d3 simulation object
73
+ // (they are cheap, so passing them as a batch is fine!):
74
+ // We read `simulation.alpha()` instead of `alpha` here, so
75
+ // Svelte does not trigger this block on any change to `alpha`:
76
+ let alphaValue = simulation.alpha();
77
+ if (alphaTarget > alphaValue && alphaValue < alphaMin) {
78
+ // Lift `alpha` from below `alphaMin` in order to give the simulation
79
+ // a chance to get revived if an `alphaTarget > alpha` is provided:
80
+ alphaValue = alphaMin;
81
+ }
17
82
  simulation
18
- .alpha(alpha)
83
+ .alpha(alphaValue)
19
84
  .alphaTarget(alphaTarget)
20
85
  .alphaMin(alphaMin)
21
86
  .alphaDecay(alphaDecay)
22
- .velocityDecay(velocityDecay)
23
- .restart();
24
- if (_static) {
25
- // TODO: Not sure why it needs to be recreated when static
26
- simulation = forceSimulation(cloneData ? structuredClone($data) : $data);
27
- simulation.stop();
28
- Object.entries(forces).forEach(([name, force]) => {
87
+ .velocityDecay(velocityDecay);
88
+ runOrResumeSimulation();
89
+ }
90
+ // MARK: Push State
91
+ function pushAlphaToSimulation(alpha) {
92
+ simulation.alpha(alpha);
93
+ }
94
+ function pushNodesToSimulation(nodes) {
95
+ simulation.nodes(cloneData ? structuredClone(nodes) : nodes);
96
+ }
97
+ function pushForcesToSimulation(forces) {
98
+ // Evict obsolete forces:
99
+ Object.keys(previousForces).forEach((name) => {
100
+ if (!(name in forces)) {
101
+ simulation.force(name, null);
102
+ }
103
+ });
104
+ // Add new or overwrite existing forces:
105
+ Object.entries(forces).forEach(([name, force]) => {
106
+ if (!(name in previousForces) || force !== previousForces[name]) {
29
107
  simulation.force(name, force);
30
- });
31
- for (let i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
32
- simulation.tick();
33
108
  }
34
- nodes = simulation.nodes();
109
+ });
110
+ previousForces = forces;
111
+ }
112
+ // MARK: Pull State
113
+ function pullNodesFromSimulation() {
114
+ nodes = simulation.nodes();
115
+ }
116
+ function pullAlphaFromSimulation() {
117
+ alpha = simulation.alpha();
118
+ }
119
+ // MARK: Resume / Pause
120
+ function runOrResumeSimulation() {
121
+ if (_static) {
122
+ runStaticSimulationToCompletion();
35
123
  }
36
124
  else {
37
- // When variables change, set forces and restart the simulation
38
- Object.entries(forces).forEach(([name, force]) => {
39
- simulation.force(name, force);
40
- });
125
+ resumeDynamicSimulation();
41
126
  }
42
127
  }
43
- let nodes = [];
44
- simulation.on('tick', () => {
45
- nodes = simulation.nodes();
46
- });
128
+ function runStaticSimulationToCompletion() {
129
+ if (stopped) {
130
+ // If a simulation is marked as stopped, then it should not get started.
131
+ return;
132
+ }
133
+ if (!_static) {
134
+ // Only static simulations are run to completion.
135
+ return;
136
+ }
137
+ if (!paused) {
138
+ // Pause any possibly still running dynamic simulation:
139
+ pauseDynamicSimulation();
140
+ }
141
+ const ticks = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay()));
142
+ pushAlphaToSimulation(1.0);
143
+ onStart();
144
+ for (let i = 0; i < ticks; ++i) {
145
+ simulation.tick();
146
+ }
147
+ pullNodesFromSimulation();
148
+ pullAlphaFromSimulation();
149
+ onEnd();
150
+ }
151
+ function resumeDynamicSimulation() {
152
+ if (!paused) {
153
+ // No need to restart an already running simulation.
154
+ return;
155
+ }
156
+ if (stopped) {
157
+ // If a simulation is marked as stopped, then it should not get resumed.
158
+ return;
159
+ }
160
+ if (_static) {
161
+ // Only dynamic simulations can be resumed.
162
+ return;
163
+ }
164
+ onStart();
165
+ simulation.restart();
166
+ // No need to call `onEnd();` for dynamic simulations
167
+ // as the simulation itself takes care of firing `on:end`,
168
+ // which then gets calls `onEnd();` for us.
169
+ }
170
+ function pauseDynamicSimulation() {
171
+ if (paused) {
172
+ // No need to pause an already paused simulation.
173
+ return;
174
+ }
175
+ simulation.stop();
176
+ onEnd();
177
+ }
178
+ // MARK: Event Listeners
179
+ function onStart() {
180
+ if (!paused) {
181
+ // Avoid double-emissions of `start` event due to race conditions.
182
+ return;
183
+ }
184
+ paused = false;
185
+ dispatch('start');
186
+ }
187
+ function onTick() {
188
+ pullNodesFromSimulation();
189
+ pullAlphaFromSimulation();
190
+ dispatch('tick', {
191
+ alpha,
192
+ alphaTarget,
193
+ });
194
+ }
195
+ function onEnd() {
196
+ if (paused) {
197
+ // Avoid double-emissions of `end` event due to race conditions.
198
+ return;
199
+ }
200
+ paused = true;
201
+ dispatch('end');
202
+ }
47
203
  </script>
48
204
 
49
205
  <slot {nodes} {simulation} />
@@ -3,15 +3,25 @@ import { type Force } from 'd3-force';
3
3
  declare const __propDef: {
4
4
  props: {
5
5
  forces: Record<string, Force<any, any>>;
6
- alpha?: number | undefined;
7
- alphaTarget?: number | undefined;
8
- alphaDecay?: number | undefined;
9
- alphaMin?: number | undefined;
10
- velocityDecay?: number | undefined;
11
- /** Clone data since simulation mutates original */ cloneData?: boolean | undefined;
12
- /** If true, will only update nodes after simulation has completed */ static?: boolean | undefined;
6
+ alpha?: number;
7
+ alphaTarget?: number;
8
+ alphaDecay?: number;
9
+ alphaMin?: number;
10
+ velocityDecay?: number;
11
+ alphaResponse?: ((alpha: number, alphaTarget: number) => number) | undefined;
12
+ stopped?: boolean;
13
+ /** If true, will only update nodes after simulation has completed */ static?: boolean;
14
+ /** Clone data since simulation mutates original */ cloneData?: boolean;
13
15
  };
14
16
  events: {
17
+ start: CustomEvent<null>;
18
+ tick: CustomEvent<{
19
+ alpha: number;
20
+ alphaTarget: number;
21
+ }>;
22
+ change: CustomEvent<null>;
23
+ end: CustomEvent<null>;
24
+ } & {
15
25
  [evt: string]: CustomEvent<any>;
16
26
  };
17
27
  slots: {
@@ -25,5 +35,6 @@ export type ForceSimulationProps = typeof __propDef.props;
25
35
  export type ForceSimulationEvents = typeof __propDef.events;
26
36
  export type ForceSimulationSlots = typeof __propDef.slots;
27
37
  export default class ForceSimulation extends SvelteComponentTyped<ForceSimulationProps, ForceSimulationEvents, ForceSimulationSlots> {
38
+ get cloneData(): NonNullable<boolean | undefined>;
28
39
  }
29
40
  export {};