@tsparticles/engine 4.0.5 → 4.1.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 (102) hide show
  1. package/browser/Core/CanvasManager.js +72 -72
  2. package/browser/Core/Container.js +85 -85
  3. package/browser/Core/Engine.js +11 -11
  4. package/browser/Core/Particle.js +142 -63
  5. package/browser/Core/ParticlesManager.js +138 -138
  6. package/browser/Core/RenderManager.js +110 -110
  7. package/browser/Core/Retina.js +3 -4
  8. package/browser/Core/Utils/EventListeners.js +31 -31
  9. package/browser/Core/Utils/PluginManager.js +26 -26
  10. package/browser/Core/Utils/SpatialHashGrid.js +36 -36
  11. package/browser/Core/Utils/Vectors.js +3 -3
  12. package/browser/Options/Classes/Options.js +13 -13
  13. package/browser/Options/Classes/Particles/ParticlesOptions.js +11 -19
  14. package/browser/Utils/EventDispatcher.js +10 -10
  15. package/browser/exports.js +0 -4
  16. package/cjs/Core/CanvasManager.js +72 -72
  17. package/cjs/Core/Container.js +85 -85
  18. package/cjs/Core/Engine.js +11 -11
  19. package/cjs/Core/Particle.js +142 -63
  20. package/cjs/Core/ParticlesManager.js +138 -138
  21. package/cjs/Core/RenderManager.js +110 -110
  22. package/cjs/Core/Retina.js +3 -4
  23. package/cjs/Core/Utils/EventListeners.js +31 -31
  24. package/cjs/Core/Utils/PluginManager.js +26 -26
  25. package/cjs/Core/Utils/SpatialHashGrid.js +36 -36
  26. package/cjs/Core/Utils/Vectors.js +3 -3
  27. package/cjs/Options/Classes/Options.js +13 -13
  28. package/cjs/Options/Classes/Particles/ParticlesOptions.js +11 -19
  29. package/cjs/Utils/EventDispatcher.js +10 -10
  30. package/cjs/exports.js +0 -4
  31. package/esm/Core/CanvasManager.js +72 -72
  32. package/esm/Core/Container.js +85 -85
  33. package/esm/Core/Engine.js +11 -11
  34. package/esm/Core/Particle.js +142 -63
  35. package/esm/Core/ParticlesManager.js +138 -138
  36. package/esm/Core/RenderManager.js +110 -110
  37. package/esm/Core/Retina.js +3 -4
  38. package/esm/Core/Utils/EventListeners.js +31 -31
  39. package/esm/Core/Utils/PluginManager.js +26 -26
  40. package/esm/Core/Utils/SpatialHashGrid.js +36 -36
  41. package/esm/Core/Utils/Vectors.js +3 -3
  42. package/esm/Options/Classes/Options.js +13 -13
  43. package/esm/Options/Classes/Particles/ParticlesOptions.js +11 -19
  44. package/esm/Utils/EventDispatcher.js +10 -10
  45. package/esm/exports.js +0 -4
  46. package/package.json +1 -1
  47. package/report.html +1 -1
  48. package/tsparticles.engine.js +690 -697
  49. package/tsparticles.engine.min.js +1 -1
  50. package/types/Core/CanvasManager.d.ts +1 -16
  51. package/types/Core/Container.d.ts +1 -18
  52. package/types/Core/Engine.d.ts +1 -3
  53. package/types/Core/Interfaces/IEffectDrawer.d.ts +2 -0
  54. package/types/Core/Interfaces/IParticleCanvasBounds.d.ts +16 -0
  55. package/types/Core/Interfaces/IParticleUpdater.d.ts +1 -0
  56. package/types/Core/Interfaces/IShapeDrawer.d.ts +2 -0
  57. package/types/Core/Particle.d.ts +5 -13
  58. package/types/Core/ParticlesManager.d.ts +1 -28
  59. package/types/Core/RenderManager.d.ts +1 -23
  60. package/types/Core/Retina.d.ts +1 -1
  61. package/types/Core/Utils/EventListeners.d.ts +1 -8
  62. package/types/Core/Utils/PluginManager.d.ts +1 -8
  63. package/types/Core/Utils/SpatialHashGrid.d.ts +1 -12
  64. package/types/Core/Utils/Vectors.d.ts +1 -1
  65. package/types/Options/Classes/Options.d.ts +1 -4
  66. package/types/Options/Classes/Particles/ParticlesOptions.d.ts +1 -7
  67. package/types/Options/Interfaces/Particles/IParticlesOptions.d.ts +0 -4
  68. package/types/Utils/EventDispatcher.d.ts +1 -1
  69. package/types/export-types.d.ts +1 -4
  70. package/types/exports.d.ts +0 -4
  71. package/browser/Options/Classes/Particles/Opacity/Opacity.js +0 -21
  72. package/browser/Options/Classes/Particles/Opacity/OpacityAnimation.js +0 -20
  73. package/browser/Options/Classes/Particles/Size/Size.js +0 -21
  74. package/browser/Options/Classes/Particles/Size/SizeAnimation.js +0 -20
  75. package/browser/Options/Interfaces/Particles/Size/ISizeAnimation.js +0 -1
  76. package/cjs/Options/Classes/Particles/Opacity/Opacity.js +0 -21
  77. package/cjs/Options/Classes/Particles/Opacity/OpacityAnimation.js +0 -20
  78. package/cjs/Options/Classes/Particles/Size/Size.js +0 -21
  79. package/cjs/Options/Classes/Particles/Size/SizeAnimation.js +0 -20
  80. package/cjs/Options/Interfaces/Particles/Opacity/IOpacity.js +0 -1
  81. package/cjs/Options/Interfaces/Particles/Opacity/IOpacityAnimation.js +0 -1
  82. package/cjs/Options/Interfaces/Particles/Size/ISize.js +0 -1
  83. package/cjs/Options/Interfaces/Particles/Size/ISizeAnimation.js +0 -1
  84. package/esm/Options/Classes/Particles/Opacity/Opacity.js +0 -21
  85. package/esm/Options/Classes/Particles/Opacity/OpacityAnimation.js +0 -20
  86. package/esm/Options/Classes/Particles/Size/Size.js +0 -21
  87. package/esm/Options/Classes/Particles/Size/SizeAnimation.js +0 -20
  88. package/esm/Options/Interfaces/Particles/Opacity/IOpacity.js +0 -1
  89. package/esm/Options/Interfaces/Particles/Opacity/IOpacityAnimation.js +0 -1
  90. package/esm/Options/Interfaces/Particles/Size/ISize.js +0 -1
  91. package/esm/Options/Interfaces/Particles/Size/ISizeAnimation.js +0 -1
  92. package/types/Options/Classes/Particles/Opacity/Opacity.d.ts +0 -10
  93. package/types/Options/Classes/Particles/Opacity/OpacityAnimation.d.ts +0 -10
  94. package/types/Options/Classes/Particles/Size/Size.d.ts +0 -10
  95. package/types/Options/Classes/Particles/Size/SizeAnimation.d.ts +0 -10
  96. package/types/Options/Interfaces/Particles/Opacity/IOpacity.d.ts +0 -5
  97. package/types/Options/Interfaces/Particles/Opacity/IOpacityAnimation.d.ts +0 -5
  98. package/types/Options/Interfaces/Particles/Size/ISize.d.ts +0 -5
  99. package/types/Options/Interfaces/Particles/Size/ISizeAnimation.d.ts +0 -5
  100. /package/browser/{Options/Interfaces/Particles/Opacity/IOpacity.js → Core/Interfaces/IParticleCanvasBounds.js} +0 -0
  101. /package/{browser/Options/Interfaces/Particles/Opacity/IOpacityAnimation.js → cjs/Core/Interfaces/IParticleCanvasBounds.js} +0 -0
  102. /package/{browser/Options/Interfaces/Particles/Size/ISize.js → esm/Core/Interfaces/IParticleCanvasBounds.js} +0 -0
@@ -1,41 +1,41 @@
1
1
  import { Circle, Rectangle } from "./Ranges.js";
2
2
  export class SpatialHashGrid {
3
- _cellSize;
4
- _cells = new Map();
5
- _circlePool = [];
6
- _circlePoolIdx;
7
- _pendingCellSize;
8
- _rectanglePool = [];
9
- _rectanglePoolIdx;
3
+ #cellSize;
4
+ #cells = new Map();
5
+ #circlePool = [];
6
+ #circlePoolIdx;
7
+ #pendingCellSize;
8
+ #rectanglePool = [];
9
+ #rectanglePoolIdx;
10
10
  constructor(cellSize) {
11
- this._cellSize = cellSize;
12
- this._circlePoolIdx = 0;
13
- this._rectanglePoolIdx = 0;
11
+ this.#cellSize = cellSize;
12
+ this.#circlePoolIdx = 0;
13
+ this.#rectanglePoolIdx = 0;
14
14
  }
15
15
  clear() {
16
- this._cells.clear();
17
- const pendingCellSize = this._pendingCellSize;
16
+ this.#cells.clear();
17
+ const pendingCellSize = this.#pendingCellSize;
18
18
  if (pendingCellSize) {
19
- this._cellSize = pendingCellSize;
19
+ this.#cellSize = pendingCellSize;
20
20
  }
21
- this._pendingCellSize = undefined;
21
+ this.#pendingCellSize = undefined;
22
22
  }
23
23
  insert(particle) {
24
- const { x, y } = particle.getPosition(), key = this._cellKeyFromCoords(x, y);
25
- if (!this._cells.has(key)) {
26
- this._cells.set(key, []);
24
+ const { x, y } = particle.getPosition(), key = this.#cellKeyFromCoords(x, y);
25
+ if (!this.#cells.has(key)) {
26
+ this.#cells.set(key, []);
27
27
  }
28
- this._cells.get(key)?.push(particle);
28
+ this.#cells.get(key)?.push(particle);
29
29
  }
30
30
  query(range, check, out = []) {
31
- const bounds = this._getRangeBounds(range);
31
+ const bounds = this.#getRangeBounds(range);
32
32
  if (!bounds) {
33
33
  return out;
34
34
  }
35
- const minCellX = Math.floor(bounds.minX / this._cellSize), maxCellX = Math.floor(bounds.maxX / this._cellSize), minCellY = Math.floor(bounds.minY / this._cellSize), maxCellY = Math.floor(bounds.maxY / this._cellSize);
35
+ const minCellX = Math.floor(bounds.minX / this.#cellSize), maxCellX = Math.floor(bounds.maxX / this.#cellSize), minCellY = Math.floor(bounds.minY / this.#cellSize), maxCellY = Math.floor(bounds.maxY / this.#cellSize);
36
36
  for (let cx = minCellX; cx <= maxCellX; cx++) {
37
37
  for (let cy = minCellY; cy <= maxCellY; cy++) {
38
- const key = `${cx}_${cy}`, cellParticles = this._cells.get(key);
38
+ const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
39
39
  if (!cellParticles) {
40
40
  continue;
41
41
  }
@@ -52,29 +52,29 @@ export class SpatialHashGrid {
52
52
  return out;
53
53
  }
54
54
  queryCircle(position, radius, check, out = []) {
55
- const circle = this._acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
56
- this._releaseShapes();
55
+ const circle = this.#acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
56
+ this.#releaseShapes();
57
57
  return result;
58
58
  }
59
59
  queryRectangle(position, size, check, out = []) {
60
- const rect = this._acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
61
- this._releaseShapes();
60
+ const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
61
+ this.#releaseShapes();
62
62
  return result;
63
63
  }
64
64
  setCellSize(cellSize) {
65
- this._pendingCellSize = cellSize;
65
+ this.#pendingCellSize = cellSize;
66
66
  }
67
- _acquireCircle(x, y, r) {
68
- return (this._circlePool[this._circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
67
+ #acquireCircle(x, y, r) {
68
+ return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
69
69
  }
70
- _acquireRectangle(x, y, w, h) {
71
- return (this._rectanglePool[this._rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
70
+ #acquireRectangle(x, y, w, h) {
71
+ return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
72
72
  }
73
- _cellKeyFromCoords(x, y) {
74
- const cellX = Math.floor(x / this._cellSize), cellY = Math.floor(y / this._cellSize);
73
+ #cellKeyFromCoords(x, y) {
74
+ const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
75
75
  return `${cellX}_${cellY}`;
76
76
  }
77
- _getRangeBounds(range) {
77
+ #getRangeBounds(range) {
78
78
  if (range instanceof Circle) {
79
79
  const r = range.radius, { x, y } = range.position;
80
80
  return {
@@ -95,8 +95,8 @@ export class SpatialHashGrid {
95
95
  }
96
96
  return null;
97
97
  }
98
- _releaseShapes() {
99
- this._circlePoolIdx = 0;
100
- this._rectanglePoolIdx = 0;
98
+ #releaseShapes() {
99
+ this.#circlePoolIdx = 0;
100
+ this.#rectanglePoolIdx = 0;
101
101
  }
102
102
  }
@@ -18,13 +18,13 @@ export class Vector3d {
18
18
  return Math.atan2(this.y, this.x);
19
19
  }
20
20
  set angle(angle) {
21
- this._updateFromAngle(angle, this.length);
21
+ this.#updateFromAngle(angle, this.length);
22
22
  }
23
23
  get length() {
24
24
  return Math.sqrt(this.getLengthSq());
25
25
  }
26
26
  set length(length) {
27
- this._updateFromAngle(this.angle, length);
27
+ this.#updateFromAngle(this.angle, length);
28
28
  }
29
29
  static clone(source) {
30
30
  return Vector3d.create(source.x, source.y, getZ(source));
@@ -87,7 +87,7 @@ export class Vector3d {
87
87
  this.y -= v.y;
88
88
  this.z -= getZ(v);
89
89
  }
90
- _updateFromAngle(angle, length) {
90
+ #updateFromAngle(angle, length) {
91
91
  this.x = Math.cos(angle) * length;
92
92
  this.y = Math.sin(angle) * length;
93
93
  }
@@ -27,11 +27,11 @@ export class Options {
27
27
  smooth;
28
28
  style;
29
29
  zLayers;
30
- _container;
31
- _pluginManager;
30
+ #container;
31
+ #pluginManager;
32
32
  constructor(pluginManager, container) {
33
- this._pluginManager = pluginManager;
34
- this._container = container;
33
+ this.#pluginManager = pluginManager;
34
+ this.#container = container;
35
35
  this.autoPlay = true;
36
36
  this.background = new Background();
37
37
  this.clear = true;
@@ -42,7 +42,7 @@ export class Options {
42
42
  this.duration = 0;
43
43
  this.fpsLimit = 120;
44
44
  this.hdr = true;
45
- this.particles = loadParticlesOptions(this._pluginManager, this._container);
45
+ this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
46
46
  this.pauseOnBlur = true;
47
47
  this.pauseOnOutsideViewport = true;
48
48
  this.resize = new ResizeEvent();
@@ -57,12 +57,12 @@ export class Options {
57
57
  if (data.preset !== undefined) {
58
58
  this.preset = data.preset;
59
59
  executeOnSingleOrMultiple(this.preset, preset => {
60
- this._importPreset(preset);
60
+ this.#importPreset(preset);
61
61
  });
62
62
  }
63
63
  if (data.palette !== undefined) {
64
64
  this.palette = data.palette;
65
- this._importPalette(this.palette);
65
+ this.#importPalette(this.palette);
66
66
  }
67
67
  if (data.autoPlay !== undefined) {
68
68
  this.autoPlay = data.autoPlay;
@@ -116,12 +116,12 @@ export class Options {
116
116
  if (data.smooth !== undefined) {
117
117
  this.smooth = data.smooth;
118
118
  }
119
- this._pluginManager.plugins.forEach(plugin => {
120
- plugin.loadOptions(this._container, this, data);
119
+ this.#pluginManager.plugins.forEach(plugin => {
120
+ plugin.loadOptions(this.#container, this, data);
121
121
  });
122
122
  }
123
- _importPalette = palette => {
124
- const paletteData = this._pluginManager.getPalette(palette);
123
+ #importPalette = palette => {
124
+ const paletteData = this.#pluginManager.getPalette(palette);
125
125
  if (!paletteData) {
126
126
  return;
127
127
  }
@@ -138,7 +138,7 @@ export class Options {
138
138
  },
139
139
  });
140
140
  };
141
- _importPreset = preset => {
142
- this.load(this._pluginManager.getPreset(preset));
141
+ #importPreset = preset => {
142
+ this.load(this.#pluginManager.getPreset(preset));
143
143
  };
144
144
  }
@@ -4,12 +4,10 @@ import { AnimatableColor } from "../AnimatableColor.js";
4
4
  import { Effect } from "./Effect/Effect.js";
5
5
  import { Fill } from "./Fill.js";
6
6
  import { Move } from "./Move/Move.js";
7
- import { Opacity } from "./Opacity/Opacity.js";
8
7
  import { Paint } from "./Paint.js";
9
8
  import { ParticlesBounce } from "./Bounce/ParticlesBounce.js";
10
9
  import { ParticlesNumber } from "./Number/ParticlesNumber.js";
11
10
  import { Shape } from "./Shape/Shape.js";
12
- import { Size } from "./Size/Size.js";
13
11
  import { ZIndex } from "./ZIndex/ZIndex.js";
14
12
  export class ParticlesOptions {
15
13
  bounce;
@@ -17,24 +15,21 @@ export class ParticlesOptions {
17
15
  groups;
18
16
  move;
19
17
  number;
20
- opacity;
21
18
  paint;
22
19
  palette;
23
20
  reduceDuplicates;
24
21
  shape;
25
- size;
26
22
  zIndex;
27
- _container;
28
- _pluginManager;
23
+ #container;
24
+ #pluginManager;
29
25
  constructor(pluginManager, container) {
30
- this._pluginManager = pluginManager;
31
- this._container = container;
26
+ this.#pluginManager = pluginManager;
27
+ this.#container = container;
32
28
  this.bounce = new ParticlesBounce();
33
29
  this.effect = new Effect();
34
30
  this.groups = {};
35
31
  this.move = new Move();
36
32
  this.number = new ParticlesNumber();
37
- this.opacity = new Opacity();
38
33
  this.paint = new Paint();
39
34
  this.paint.color = new AnimatableColor();
40
35
  this.paint.color.value = "#fff";
@@ -42,7 +37,6 @@ export class ParticlesOptions {
42
37
  this.paint.fill.enable = true;
43
38
  this.reduceDuplicates = false;
44
39
  this.shape = new Shape();
45
- this.size = new Size();
46
40
  this.zIndex = new ZIndex();
47
41
  }
48
42
  load(data) {
@@ -51,7 +45,7 @@ export class ParticlesOptions {
51
45
  }
52
46
  if (data.palette) {
53
47
  this.palette = data.palette;
54
- this._importPalette(this.palette);
48
+ this.#importPalette(this.palette);
55
49
  }
56
50
  if (data.groups !== undefined) {
57
51
  for (const group of Object.keys(data.groups)) {
@@ -71,7 +65,6 @@ export class ParticlesOptions {
71
65
  this.effect.load(data.effect);
72
66
  this.move.load(data.move);
73
67
  this.number.load(data.number);
74
- this.opacity.load(data.opacity);
75
68
  const paintToLoad = data.paint;
76
69
  if (paintToLoad) {
77
70
  if (isArray(paintToLoad)) {
@@ -90,15 +83,14 @@ export class ParticlesOptions {
90
83
  }
91
84
  }
92
85
  this.shape.load(data.shape);
93
- this.size.load(data.size);
94
86
  this.zIndex.load(data.zIndex);
95
- if (this._container) {
96
- for (const plugin of this._pluginManager.plugins) {
87
+ if (this.#container) {
88
+ for (const plugin of this.#pluginManager.plugins) {
97
89
  if (plugin.loadParticlesOptions) {
98
- plugin.loadParticlesOptions(this._container, this, data);
90
+ plugin.loadParticlesOptions(this.#container, this, data);
99
91
  }
100
92
  }
101
- const updaters = this._pluginManager.updaters.get(this._container);
93
+ const updaters = this.#pluginManager.updaters.get(this.#container);
102
94
  if (updaters) {
103
95
  for (const updater of updaters) {
104
96
  if (updater.loadOptions) {
@@ -108,8 +100,8 @@ export class ParticlesOptions {
108
100
  }
109
101
  }
110
102
  }
111
- _importPalette = (palette) => {
112
- const paletteData = this._pluginManager.getPalette(palette);
103
+ #importPalette = (palette) => {
104
+ const paletteData = this.#pluginManager.getPalette(palette);
113
105
  if (!paletteData) {
114
106
  return;
115
107
  }
@@ -1,37 +1,37 @@
1
1
  import { deleteCount, minIndex } from "../Core/Utils/Constants.js";
2
2
  export class EventDispatcher {
3
- _listeners;
3
+ #listeners;
4
4
  constructor() {
5
- this._listeners = new Map();
5
+ this.#listeners = new Map();
6
6
  }
7
7
  addEventListener(type, listener) {
8
8
  this.removeEventListener(type, listener);
9
- let arr = this._listeners.get(type);
9
+ let arr = this.#listeners.get(type);
10
10
  if (!arr) {
11
11
  arr = [];
12
- this._listeners.set(type, arr);
12
+ this.#listeners.set(type, arr);
13
13
  }
14
14
  arr.push(listener);
15
15
  }
16
16
  dispatchEvent(type, args) {
17
- const listeners = this._listeners.get(type);
17
+ const listeners = this.#listeners.get(type);
18
18
  listeners?.forEach(handler => {
19
19
  handler(args);
20
20
  });
21
21
  }
22
22
  hasEventListener(type) {
23
- return !!this._listeners.get(type);
23
+ return !!this.#listeners.get(type);
24
24
  }
25
25
  removeAllEventListeners(type) {
26
26
  if (!type) {
27
- this._listeners = new Map();
27
+ this.#listeners = new Map();
28
28
  }
29
29
  else {
30
- this._listeners.delete(type);
30
+ this.#listeners.delete(type);
31
31
  }
32
32
  }
33
33
  removeEventListener(type, listener) {
34
- const arr = this._listeners.get(type);
34
+ const arr = this.#listeners.get(type);
35
35
  if (!arr) {
36
36
  return;
37
37
  }
@@ -40,7 +40,7 @@ export class EventDispatcher {
40
40
  return;
41
41
  }
42
42
  if (length === deleteCount) {
43
- this._listeners.delete(type);
43
+ this.#listeners.delete(type);
44
44
  }
45
45
  else {
46
46
  arr.splice(idx, deleteCount);
package/esm/exports.js CHANGED
@@ -40,11 +40,7 @@ export * from "./Options/Classes/Particles/Move/Spin.js";
40
40
  export * from "./Options/Classes/Particles/Number/ParticlesNumber.js";
41
41
  export * from "./Options/Classes/Particles/Number/ParticlesNumberLimit.js";
42
42
  export * from "./Options/Classes/Particles/Number/ParticlesDensity.js";
43
- export * from "./Options/Classes/Particles/Opacity/Opacity.js";
44
- export * from "./Options/Classes/Particles/Opacity/OpacityAnimation.js";
45
43
  export * from "./Options/Classes/Particles/Shape/Shape.js";
46
- export * from "./Options/Classes/Particles/Size/Size.js";
47
- export * from "./Options/Classes/Particles/Size/SizeAnimation.js";
48
44
  export * from "./Options/Classes/Particles/ZIndex/ZIndex.js";
49
45
  export * from "./Options/Classes/ResizeEvent.js";
50
46
  export * from "./Options/Classes/ValueWithRandom.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/engine",
3
- "version": "4.0.5",
3
+ "version": "4.1.0",
4
4
  "description": "Easily create highly customizable particle, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.",
5
5
  "homepage": "https://particles.js.org",
6
6
  "scripts": {