@tsparticles/fireworks 4.4.0 → 4.5.1

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,21 +1,58 @@
1
- (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* tsParticles v4.4.0 */
3
- (function (global, factory) {
4
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
6
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.bundles = global.__tsParticlesInternals.bundles || {}, global.__tsParticlesInternals.bundles.fireworks = global.__tsParticlesInternals.bundles.fireworks || {})));
7
- })(this, (function (exports) { 'use strict';
8
-
9
- const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
10
- x: 0,
11
- y: 0,
12
- z: 0,
13
- }, defaultTransform = {
14
- a: 1,
15
- b: 0,
16
- c: 0,
17
- d: 1,
18
- }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha$1 = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius$1 = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
1
+ (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
+ (function (g) {
3
+ /* tsParticles v4.5.1 */
4
+ g.__tsParticlesInternals = g.__tsParticlesInternals || {};
5
+ g.__tsParticlesInternals.bundles = g.__tsParticlesInternals.bundles || {};
6
+ (function (exports) {
7
+ 'use strict';
8
+
9
+ const errorPrefix = "tsParticles - Error", codedErrorPattern = /^\[tsParticles Error (TSP-\d+)\]\s*/, fullMatchIndex = 0, codeIndex = 1;
10
+ const wrap = (fn) => (...args) => {
11
+ fn(...args);
12
+ }, _logger = {
13
+ debug: wrap(console.debug),
14
+ error: (message, ...optionalParams) => {
15
+ if (typeof message === "string") {
16
+ const match = codedErrorPattern.exec(message);
17
+ if (match?.[codeIndex]) {
18
+ console.error(`tsParticles - ${match[codeIndex]} - ${message.slice(match[fullMatchIndex].length)}`, ...optionalParams);
19
+ return;
20
+ }
21
+ }
22
+ console.error(`${errorPrefix} - ${message}`, ...optionalParams);
23
+ },
24
+ info: wrap(console.info),
25
+ log: wrap(console.log),
26
+ trace: wrap(console.trace),
27
+ verbose: wrap(console.log),
28
+ warning: wrap(console.warn),
29
+ };
30
+ function setLogger(logger) {
31
+ if (logger.debug) {
32
+ _logger.debug = wrap(logger.debug);
33
+ }
34
+ if (logger.error) {
35
+ _logger.error = wrap(logger.error);
36
+ }
37
+ if (logger.info) {
38
+ _logger.info = wrap(logger.info);
39
+ }
40
+ if (logger.log) {
41
+ _logger.log = wrap(logger.log);
42
+ }
43
+ if (logger.trace) {
44
+ _logger.trace = wrap(logger.trace);
45
+ }
46
+ if (logger.verbose) {
47
+ _logger.verbose = wrap(logger.verbose);
48
+ }
49
+ if (logger.warning) {
50
+ _logger.warning = wrap(logger.warning);
51
+ }
52
+ }
53
+ function getLogger() {
54
+ return _logger;
55
+ }
19
56
 
20
57
  exports.MoveDirection = void 0;
21
58
  (function (MoveDirection) {
@@ -32,6 +69,17 @@
32
69
  MoveDirection["inside"] = "inside";
33
70
  })(exports.MoveDirection || (exports.MoveDirection = {}));
34
71
 
72
+ const generatedAttribute = "generated", fullPercent = "100%", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
73
+ x: 0,
74
+ y: 0,
75
+ z: 0,
76
+ }, defaultTransform = {
77
+ a: 1,
78
+ b: 0,
79
+ c: 0,
80
+ d: 1,
81
+ }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
82
+
35
83
  function getZ(source) {
36
84
  return "z" in source ? source.z : originPoint.z;
37
85
  }
@@ -150,6 +198,12 @@
150
198
  function isFunction(arg) {
151
199
  return typeof arg === "function";
152
200
  }
201
+ function isEnumValue(enumObject, arg) {
202
+ return Object.values(enumObject).some(enumValue => enumValue === arg);
203
+ }
204
+ function toEnumValue(enumObject, arg, defaultValue) {
205
+ return isEnumValue(enumObject, arg) ? arg : defaultValue;
206
+ }
153
207
  function isObject(arg) {
154
208
  return typeof arg === "object" && arg !== null;
155
209
  }
@@ -310,11 +364,61 @@
310
364
  };
311
365
  }
312
366
  function parseAlpha(input) {
313
- const defaultAlpha = 1;
314
367
  if (!input) {
315
368
  return defaultAlpha;
316
369
  }
317
- return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
370
+ return input.endsWith("%") ? Number.parseFloat(input) / percentDenominator : Number.parseFloat(input);
371
+ }
372
+
373
+ const ErrorCodes$2 = {
374
+ engineVersionMismatch: "TSP-1001",
375
+ particlePositionNotFound: "TSP-1002",
376
+ pluginRegisterAfterLoad: "TSP-1003",
377
+ offscreenCanvasUnsupported: "TSP-1101",
378
+ offscreenCanvasTransferFailed: "TSP-1102",
379
+ hdrEnableInvalid: "TSP-1201",
380
+ hdrModeInvalid: "TSP-1202",
381
+ hdrPeakNitsInvalid: "TSP-1203",
382
+ };
383
+
384
+ const messages = {
385
+ [ErrorCodes$2.engineVersionMismatch]: "The tsParticles version is different from the loaded plugins version. Engine version: {0}. Plugin version: {1}",
386
+ [ErrorCodes$2.particlePositionNotFound]: "a valid position cannot be found for particle",
387
+ [ErrorCodes$2.pluginRegisterAfterLoad]: "Register plugins can only be done before calling tsParticles.load()",
388
+ [ErrorCodes$2.offscreenCanvasUnsupported]: "OffscreenCanvas is required but not supported by this browser",
389
+ [ErrorCodes$2.offscreenCanvasTransferFailed]: "OffscreenCanvas transfer failed",
390
+ [ErrorCodes$2.hdrEnableInvalid]: 'Invalid HDR "enable" value: expected a boolean, got "{0}"',
391
+ [ErrorCodes$2.hdrModeInvalid]: 'Invalid HDR "mode" value: expected one of {0}, got "{1}"',
392
+ [ErrorCodes$2.hdrPeakNitsInvalid]: 'Invalid HDR "peakNits" value: expected a positive number, got "{0}"',
393
+ };
394
+
395
+ let registeredMessages;
396
+ const ensureRegisteredMessages = () => {
397
+ registeredMessages ??= new Map(Object.entries(messages));
398
+ return registeredMessages;
399
+ }, toStringValue$1 = (value) => String(value), format = (template, args) => {
400
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
401
+ const arg = args[Number(index)];
402
+ return arg === undefined ? match : toStringValue$1(arg);
403
+ });
404
+ };
405
+ function addErrorMessages(extraMessages) {
406
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
407
+ return;
408
+ }
409
+ const catalog = ensureRegisteredMessages();
410
+ for (const [code, message] of Object.entries(extraMessages)) {
411
+ if (message !== undefined) {
412
+ catalog.set(code, message);
413
+ }
414
+ }
415
+ }
416
+ function getErrorMessage(code, ...args) {
417
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
418
+ return `[tsParticles Error ${code}] https://particles.js.org/errors/#${code}`;
419
+ }
420
+ const template = ensureRegisteredMessages().get(code) ?? `Unknown error code ${code}`;
421
+ return format(template, args);
318
422
  }
319
423
 
320
424
  exports.OutModeDirection = void 0;
@@ -331,7 +435,6 @@
331
435
  PixelMode["percent"] = "percent";
332
436
  })(exports.PixelMode || (exports.PixelMode = {}));
333
437
 
334
- const minRadius = 0;
335
438
  function isForbiddenKey(key) {
336
439
  return key === "__proto__" || key === "constructor" || key === "prototype";
337
440
  }
@@ -547,22 +650,84 @@
547
650
  element.removeEventListener(event, handler, removeOptions);
548
651
  }
549
652
  }
550
- async function getItemsFromInitializer(container, map, initializers, force = false) {
551
- let res = map.get(container);
552
- if (!res || force) {
553
- res = await Promise.all([...initializers.values()].map(t => t(container)));
554
- map.set(container, res);
653
+ async function getItemsFromInitializer(container, initializers) {
654
+ return await Promise.all([...initializers.values()].map(t => t(container)));
655
+ }
656
+ async function getItemMapFromInitializer(container, initializers) {
657
+ const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
658
+ return new Map(entries);
659
+ }
660
+ async function getDataFromUrl(data) {
661
+ const url = itemFromSingleOrMultiple(data.url, data.index);
662
+ if (!url) {
663
+ return data.fallback;
555
664
  }
556
- return res;
665
+ try {
666
+ const response = await fetch(url);
667
+ if (response.ok) {
668
+ const current = (await response.json());
669
+ if (isSourceOptionsValue(current)) {
670
+ return current;
671
+ }
672
+ getLogger().error("invalid configuration data while retrieving config file");
673
+ }
674
+ else {
675
+ getLogger().error(`${response.status.toString()} while retrieving config file`);
676
+ }
677
+ }
678
+ catch (error) {
679
+ getLogger().error(`error while retrieving config file: ${error}`);
680
+ }
681
+ return data.fallback;
557
682
  }
558
- async function getItemMapFromInitializer(container, map, initializers, force = false) {
559
- let res = map.get(container);
560
- if (!res || force) {
561
- const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
562
- res = new Map(entries);
563
- map.set(container, res);
683
+ function isSourceOptionsValue(value) {
684
+ if (isArray(value)) {
685
+ return value.every((entry) => isObject(entry) && !isArray(entry));
564
686
  }
565
- return res;
687
+ return isObject(value) && !isArray(value);
688
+ }
689
+ function getCanvasFromContainer(domContainer) {
690
+ let canvasEl;
691
+ const documentSafe = safeDocument(), isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
692
+ if (isCanvas) {
693
+ canvasEl = domContainer;
694
+ canvasEl.dataset[generatedAttribute] ??= generatedFalse;
695
+ if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
696
+ canvasEl.style.width ||= fullPercent;
697
+ canvasEl.style.height ||= fullPercent;
698
+ canvasEl.style.pointerEvents = "none";
699
+ canvasEl.style.setProperty("pointer-events", "none");
700
+ }
701
+ }
702
+ else {
703
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
704
+ if (foundCanvas) {
705
+ canvasEl = foundCanvas;
706
+ canvasEl.dataset[generatedAttribute] = generatedFalse;
707
+ }
708
+ else {
709
+ canvasEl = documentSafe.createElement(canvasTag);
710
+ canvasEl.dataset[generatedAttribute] = generatedTrue;
711
+ domContainer.appendChild(canvasEl);
712
+ }
713
+ canvasEl.style.width ||= fullPercent;
714
+ canvasEl.style.height ||= fullPercent;
715
+ canvasEl.style.pointerEvents = "none";
716
+ canvasEl.style.setProperty("pointer-events", "none");
717
+ }
718
+ return canvasEl;
719
+ }
720
+ function getDomContainer(id, source) {
721
+ const documentSafe = safeDocument();
722
+ let domContainer = source ?? documentSafe.getElementById(id);
723
+ if (domContainer) {
724
+ return domContainer;
725
+ }
726
+ domContainer = documentSafe.createElement("canvas");
727
+ domContainer.id = id;
728
+ domContainer.dataset[generatedAttribute] = generatedTrue;
729
+ documentSafe.body.append(domContainer);
730
+ return domContainer;
566
731
  }
567
732
 
568
733
  class EventDispatcher {
@@ -572,12 +737,8 @@
572
737
  }
573
738
  addEventListener(type, listener) {
574
739
  this.removeEventListener(type, listener);
575
- let arr = this.#listeners.get(type);
576
- if (!arr) {
577
- arr = [];
578
- this.#listeners.set(type, arr);
579
- }
580
- arr.push(listener);
740
+ const arr = this.#listeners.get(type);
741
+ this.#listeners.set(type, arr ? [...arr, listener] : [listener]);
581
742
  }
582
743
  dispatchEvent(type, args) {
583
744
  const listeners = this.#listeners.get(type);
@@ -609,7 +770,7 @@
609
770
  this.#listeners.delete(type);
610
771
  }
611
772
  else {
612
- arr.splice(idx, deleteCount);
773
+ this.#listeners.set(type, [...arr.slice(minIndex, idx), ...arr.slice(idx + deleteCount)]);
613
774
  }
614
775
  }
615
776
  }
@@ -633,7 +794,6 @@
633
794
  class PluginManager {
634
795
  colorManagers = new Map();
635
796
  easingFunctions = new Map();
636
- effectDrawers = new Map();
637
797
  initializers = {
638
798
  effects: new Map(),
639
799
  shapes: new Map(),
@@ -642,8 +802,6 @@
642
802
  palettes = new Map();
643
803
  plugins = [];
644
804
  presets = new Map();
645
- shapeDrawers = new Map();
646
- updaters = new Map();
647
805
  #allLoadersSet = new Set();
648
806
  #configs = new Map();
649
807
  #engine;
@@ -661,57 +819,79 @@
661
819
  }
662
820
  return res;
663
821
  }
822
+ get initialized() {
823
+ return this.#initialized;
824
+ }
664
825
  addColorManager(name, manager) {
826
+ if (this.#initialized) {
827
+ return;
828
+ }
665
829
  this.colorManagers.set(name, manager);
666
830
  }
667
831
  addConfig(config) {
832
+ if (this.#initialized) {
833
+ return;
834
+ }
668
835
  const key = config.key ?? config.name ?? "default";
669
836
  this.#configs.set(key, config);
670
837
  this.#engine.dispatchEvent(exports.EventType.configAdded, { data: { name: key, config } });
671
838
  }
672
839
  addEasing(name, easing) {
840
+ if (this.#initialized) {
841
+ return;
842
+ }
673
843
  if (this.easingFunctions.get(name)) {
674
844
  return;
675
845
  }
676
846
  this.easingFunctions.set(name, easing);
677
847
  }
678
848
  addEffect(effect, drawer) {
849
+ if (this.#initialized) {
850
+ return;
851
+ }
679
852
  this.initializers.effects.set(effect, drawer);
680
853
  }
681
854
  addPalette(name, palette) {
855
+ if (this.#initialized) {
856
+ return;
857
+ }
682
858
  this.palettes.set(name, palette);
683
859
  }
684
860
  addParticleUpdater(name, updaterInitializer) {
861
+ if (this.#initialized) {
862
+ return;
863
+ }
685
864
  this.initializers.updaters.set(name, updaterInitializer);
686
865
  }
687
866
  addPlugin(plugin) {
867
+ if (this.#initialized) {
868
+ return;
869
+ }
688
870
  if (this.getPlugin(plugin.id)) {
689
871
  return;
690
872
  }
691
873
  this.plugins.push(plugin);
692
874
  }
693
875
  addPreset(preset, options, override = false) {
876
+ if (this.#initialized) {
877
+ return;
878
+ }
694
879
  if (!(override || !this.getPreset(preset))) {
695
880
  return;
696
881
  }
697
882
  this.presets.set(preset, options);
698
883
  }
699
884
  addShape(shapes, drawer) {
885
+ if (this.#initialized) {
886
+ return;
887
+ }
700
888
  for (const shape of shapes) {
701
889
  this.initializers.shapes.set(shape, drawer);
702
890
  }
703
891
  }
704
- clearPlugins(container) {
705
- this.effectDrawers.delete(container);
706
- this.shapeDrawers.delete(container);
707
- this.updaters.delete(container);
708
- }
709
892
  getEasing(name) {
710
893
  return this.easingFunctions.get(name) ?? ((value) => value);
711
894
  }
712
- getEffectDrawers(container, force = false) {
713
- return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
714
- }
715
895
  getPalette(name) {
716
896
  return this.palettes.get(name);
717
897
  }
@@ -721,12 +901,6 @@
721
901
  getPreset(preset) {
722
902
  return this.presets.get(preset);
723
903
  }
724
- async getShapeDrawers(container, force = false) {
725
- return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
726
- }
727
- async getUpdaters(container, force = false) {
728
- return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
729
- }
730
904
  async init() {
731
905
  if (this.#initialized || this.#isRunningLoaders) {
732
906
  return;
@@ -745,16 +919,9 @@
745
919
  this.#initialized = true;
746
920
  }
747
921
  }
748
- loadParticlesOptions(container, options, ...sourceOptions) {
749
- const updaters = this.updaters.get(container);
750
- if (!updaters) {
751
- return;
752
- }
753
- updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
754
- }
755
922
  async register(...loaders) {
756
923
  if (this.#initialized) {
757
- throw new Error("Register plugins can only be done before calling tsParticles.load()");
924
+ throw new Error(getErrorMessage(ErrorCodes$2.pluginRegisterAfterLoad));
758
925
  }
759
926
  for (const loader of loaders) {
760
927
  if (this.#isRunningLoaders) {
@@ -766,111 +933,15 @@
766
933
  }
767
934
  }
768
935
  async #runLoader(loader, executed, allLoaders) {
769
- if (executed.has(loader))
936
+ if (executed.has(loader)) {
770
937
  return;
938
+ }
771
939
  executed.add(loader);
772
940
  allLoaders.add(loader);
773
941
  await loader(this.#engine);
774
942
  }
775
943
  }
776
944
 
777
- const errorPrefix = "tsParticles - Error";
778
- const wrap = (fn) => (...args) => {
779
- fn(...args);
780
- }, _logger = {
781
- debug: wrap(console.debug),
782
- error: (message, ...optionalParams) => {
783
- console.error(`${errorPrefix} - ${message}`, ...optionalParams);
784
- },
785
- info: wrap(console.info),
786
- log: wrap(console.log),
787
- trace: wrap(console.trace),
788
- verbose: wrap(console.log),
789
- warning: wrap(console.warn),
790
- };
791
- function setLogger(logger) {
792
- if (logger.debug) {
793
- _logger.debug = wrap(logger.debug);
794
- }
795
- if (logger.error) {
796
- _logger.error = wrap(logger.error);
797
- }
798
- if (logger.info) {
799
- _logger.info = wrap(logger.info);
800
- }
801
- if (logger.log) {
802
- _logger.log = wrap(logger.log);
803
- }
804
- if (logger.trace) {
805
- _logger.trace = wrap(logger.trace);
806
- }
807
- if (logger.verbose) {
808
- _logger.verbose = wrap(logger.verbose);
809
- }
810
- if (logger.warning) {
811
- _logger.warning = wrap(logger.warning);
812
- }
813
- }
814
- function getLogger() {
815
- return _logger;
816
- }
817
-
818
- const fullPercent = "100%";
819
- async function getDataFromUrl(data) {
820
- const url = itemFromSingleOrMultiple(data.url, data.index);
821
- if (!url) {
822
- return data.fallback;
823
- }
824
- const response = await fetch(url);
825
- if (response.ok) {
826
- return (await response.json());
827
- }
828
- getLogger().error(`${response.status.toString()} while retrieving config file`);
829
- return data.fallback;
830
- }
831
- const getCanvasFromContainer = (domContainer) => {
832
- const documentSafe = safeDocument();
833
- let canvasEl;
834
- const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
835
- if (isCanvas) {
836
- canvasEl = domContainer;
837
- canvasEl.dataset[generatedAttribute] ??= generatedFalse;
838
- if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
839
- canvasEl.style.width ||= fullPercent;
840
- canvasEl.style.height ||= fullPercent;
841
- canvasEl.style.pointerEvents = "none";
842
- canvasEl.style.setProperty("pointer-events", "none");
843
- }
844
- }
845
- else {
846
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
847
- if (foundCanvas) {
848
- canvasEl = foundCanvas;
849
- canvasEl.dataset[generatedAttribute] = generatedFalse;
850
- }
851
- else {
852
- canvasEl = documentSafe.createElement(canvasTag);
853
- canvasEl.dataset[generatedAttribute] = generatedTrue;
854
- domContainer.appendChild(canvasEl);
855
- }
856
- canvasEl.style.width ||= fullPercent;
857
- canvasEl.style.height ||= fullPercent;
858
- canvasEl.style.pointerEvents = "none";
859
- canvasEl.style.setProperty("pointer-events", "none");
860
- }
861
- return canvasEl;
862
- }, getDomContainer = (id, source) => {
863
- const documentSafe = safeDocument();
864
- let domContainer = source ?? documentSafe.getElementById(id);
865
- if (domContainer) {
866
- return domContainer;
867
- }
868
- domContainer = documentSafe.createElement("canvas");
869
- domContainer.id = id;
870
- domContainer.dataset[generatedAttribute] = generatedTrue;
871
- documentSafe.body.append(domContainer);
872
- return domContainer;
873
- };
874
945
  class Engine {
875
946
  pluginManager = new PluginManager(this);
876
947
  #domArray = [];
@@ -880,7 +951,7 @@
880
951
  return this.#domArray;
881
952
  }
882
953
  get version() {
883
- return "4.4.0";
954
+ return "4.5.1";
884
955
  }
885
956
  addEventListener(type, listener) {
886
957
  this.#eventDispatcher.addEventListener(type, listener);
@@ -889,7 +960,7 @@
889
960
  if (this.version === pluginVersion) {
890
961
  return;
891
962
  }
892
- throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
963
+ throw new Error(getErrorMessage(ErrorCodes$2.engineVersionMismatch, this.version, pluginVersion));
893
964
  }
894
965
  dispatchEvent(type, args) {
895
966
  this.#eventDispatcher.dispatchEvent(type, args);
@@ -1138,20 +1209,6 @@
1138
1209
  DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1139
1210
  })(exports.DrawLayer || (exports.DrawLayer = {}));
1140
1211
 
1141
- class OptionLoader {
1142
- load(data) {
1143
- if (isNull(data)) {
1144
- return;
1145
- }
1146
- this.doLoad(data);
1147
- }
1148
- }
1149
- function loadOptions(options, ...sourceOptionsArr) {
1150
- for (const sourceOptions of sourceOptionsArr) {
1151
- options.load(sourceOptions);
1152
- }
1153
- }
1154
-
1155
1212
  function loadProperty(obj, key, value) {
1156
1213
  if (value !== undefined) {
1157
1214
  obj[key] = value;
@@ -1180,7 +1237,7 @@
1180
1237
  if (keyStr === "__proto__" || keyStr === "constructor" || keyStr === "prototype") {
1181
1238
  return;
1182
1239
  }
1183
- const objRecord = obj, currentValue = Object.prototype.hasOwnProperty.call(objRecord, keyStr) ? objRecord[keyStr] : {};
1240
+ const objRecord = obj, currentValue = Object.hasOwn(objRecord, keyStr) ? objRecord[keyStr] : {};
1184
1241
  objRecord[keyStr] = deepExtend(currentValue, value);
1185
1242
  }
1186
1243
  }
@@ -1193,6 +1250,20 @@
1193
1250
  }
1194
1251
  }
1195
1252
 
1253
+ class OptionLoader {
1254
+ load(data) {
1255
+ if (isNull(data)) {
1256
+ return;
1257
+ }
1258
+ this.doLoad(data);
1259
+ }
1260
+ }
1261
+ function loadOptions(options, ...sourceOptionsArr) {
1262
+ for (const sourceOptions of sourceOptionsArr) {
1263
+ options.load(sourceOptions);
1264
+ }
1265
+ }
1266
+
1196
1267
  class AnimationOptions extends OptionLoader {
1197
1268
  count = 0;
1198
1269
  decay = 0;
@@ -1343,15 +1414,14 @@
1343
1414
  peakNits = defaultPeakNits;
1344
1415
  doLoad(data) {
1345
1416
  if (data.enable !== undefined && !isBoolean(data.enable)) {
1346
- throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1417
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrEnableInvalid, String(data.enable)));
1347
1418
  }
1348
- if (data.mode !== undefined &&
1349
- (typeof data.mode !== "string" || !Object.values(exports.HdrMode).includes(data.mode))) {
1350
- throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(exports.HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1419
+ if (data.mode !== undefined && !isEnumValue(exports.HdrMode, data.mode)) {
1420
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrModeInvalid, Object.values(exports.HdrMode).join(", "), toStringValue(data.mode)));
1351
1421
  }
1352
1422
  if (data.peakNits !== undefined &&
1353
1423
  (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1354
- throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1424
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrPeakNitsInvalid, String(data.peakNits)));
1355
1425
  }
1356
1426
  loadProperty(this, "enable", data.enable);
1357
1427
  loadProperty(this, "mode", data.mode);
@@ -1729,12 +1799,10 @@
1729
1799
  plugin.loadParticlesOptions(this.#container, this, data);
1730
1800
  }
1731
1801
  }
1732
- const updaters = this.#pluginManager.updaters.get(this.#container);
1733
- if (updaters) {
1734
- for (const updater of updaters) {
1735
- if (updater.loadOptions) {
1736
- updater.loadOptions(this, data);
1737
- }
1802
+ const updaters = this.#container.particleUpdaters;
1803
+ for (const updater of updaters) {
1804
+ if (updater.loadOptions) {
1805
+ updater.loadOptions(this, data);
1738
1806
  }
1739
1807
  }
1740
1808
  }
@@ -2076,9 +2144,9 @@
2076
2144
  const grayscaleValue = Math.round(lNormalized * rgbMax);
2077
2145
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2078
2146
  }
2079
- const temp1 = lNormalized < half
2147
+ const temp2 = lNormalized < half
2080
2148
  ? lNormalized * (sNormalizedOffset + sNormalized)
2081
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
2149
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp1 = double * lNormalized - temp2, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized - phaseThird));
2082
2150
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
2083
2151
  }
2084
2152
  function hslToRgbFloat(hsl) {
@@ -2087,9 +2155,9 @@
2087
2155
  const grayscaleValue = lNormalized * rgbMax;
2088
2156
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2089
2157
  }
2090
- const temp1 = lNormalized < half
2158
+ const temp2 = lNormalized < half
2091
2159
  ? lNormalized * (sNormalizedOffset + sNormalized)
2092
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
2160
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp1 = double * lNormalized - temp2, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp1, temp2, hNormalized - phaseThird));
2093
2161
  return { r: red, g: green, b: blue };
2094
2162
  }
2095
2163
  function hslaToRgba(hsla) {
@@ -2676,7 +2744,7 @@
2676
2744
  }
2677
2745
 
2678
2746
  async function loadBlendPlugin(engine) {
2679
- engine.checkVersion("4.4.0");
2747
+ engine.checkVersion("4.5.1");
2680
2748
  await engine.pluginManager.register(e => {
2681
2749
  e.pluginManager.addPlugin(new BlendPlugin());
2682
2750
  });
@@ -2713,7 +2781,7 @@
2713
2781
  }
2714
2782
 
2715
2783
  async function loadCircleShape(engine) {
2716
- engine.checkVersion("4.4.0");
2784
+ engine.checkVersion("4.5.1");
2717
2785
  await engine.pluginManager.register(e => {
2718
2786
  e.pluginManager.addShape(["circle"], () => {
2719
2787
  return Promise.resolve(new CircleDrawer());
@@ -2728,7 +2796,7 @@
2728
2796
  RgbIndexes[RgbIndexes["b"] = 3] = "b";
2729
2797
  RgbIndexes[RgbIndexes["a"] = 4] = "a";
2730
2798
  })(RgbIndexes$1 || (RgbIndexes$1 = {}));
2731
- const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, hexRadix = 16, defaultAlpha = 1, alphaFactor = 0xff;
2799
+ const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, hexRadix = 16, alphaFactor = 0xff;
2732
2800
  class HexColorManager {
2733
2801
  accepts(input) {
2734
2802
  return input.startsWith("#");
@@ -2761,7 +2829,7 @@
2761
2829
  }
2762
2830
 
2763
2831
  async function loadHexColorPlugin(engine) {
2764
- engine.checkVersion("4.4.0");
2832
+ engine.checkVersion("4.5.1");
2765
2833
  await engine.pluginManager.register(e => {
2766
2834
  e.pluginManager.addColorManager("hex", new HexColorManager());
2767
2835
  });
@@ -2801,7 +2869,7 @@
2801
2869
  if (!this.accepts(input)) {
2802
2870
  return;
2803
2871
  }
2804
- const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
2872
+ const result = hslRegex.exec(input), minLength = 4, radix = 10;
2805
2873
  return result
2806
2874
  ? hslaToRgba({
2807
2875
  a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
@@ -2814,12 +2882,20 @@
2814
2882
  }
2815
2883
 
2816
2884
  async function loadHslColorPlugin(engine) {
2817
- engine.checkVersion("4.4.0");
2885
+ engine.checkVersion("4.5.1");
2818
2886
  await engine.pluginManager.register(e => {
2819
2887
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2820
2888
  });
2821
2889
  }
2822
2890
 
2891
+ const ErrorCodes$1 = {
2892
+ baseMoverNotLoaded: "TSP-3203",
2893
+ };
2894
+
2895
+ const ErrorMessages$1 = {
2896
+ [ErrorCodes$1.baseMoverNotLoaded]: "tsParticles Base Mover is not loaded",
2897
+ };
2898
+
2823
2899
  class MovePlugin {
2824
2900
  id = "move";
2825
2901
  #pluginManager;
@@ -2838,20 +2914,20 @@
2838
2914
  }
2839
2915
 
2840
2916
  async function loadMovePlugin(engine) {
2841
- engine.checkVersion("4.4.0");
2917
+ engine.checkVersion("4.5.1");
2918
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
2919
+ addErrorMessages(ErrorMessages$1);
2920
+ }
2842
2921
  await engine.pluginManager.register(e => {
2843
2922
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2844
2923
  movePluginManager.initializers.pathGenerators ??= new Map();
2845
- movePluginManager.pathGenerators ??= new Map();
2846
2924
  movePluginManager.addPathGenerator = (name, generator) => {
2925
+ if (movePluginManager.initialized) {
2926
+ return;
2927
+ }
2847
2928
  movePluginManager.initializers.pathGenerators ??= new Map();
2848
2929
  movePluginManager.initializers.pathGenerators.set(name, generator);
2849
2930
  };
2850
- movePluginManager.getPathGenerators = async (container, force = false) => {
2851
- movePluginManager.initializers.pathGenerators ??= new Map();
2852
- movePluginManager.pathGenerators ??= new Map();
2853
- return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
2854
- };
2855
2931
  e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
2856
2932
  });
2857
2933
  }
@@ -3054,7 +3130,7 @@
3054
3130
  }
3055
3131
 
3056
3132
  async function loadOpacityUpdater(engine) {
3057
- engine.checkVersion("4.4.0");
3133
+ engine.checkVersion("4.5.1");
3058
3134
  await engine.pluginManager.register(e => {
3059
3135
  e.pluginManager.addParticleUpdater("opacity", container => {
3060
3136
  return Promise.resolve(new OpacityUpdater(container));
@@ -3063,70 +3139,60 @@
3063
3139
  }
3064
3140
 
3065
3141
  const boundsMin = 0;
3066
- function bounceHorizontal(data) {
3067
- if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
3068
- (data.direction !== exports.OutModeDirection.left && data.direction !== exports.OutModeDirection.right)) {
3069
- return;
3070
- }
3071
- if (data.bounds.right < boundsMin && data.direction === exports.OutModeDirection.left) {
3072
- data.particle.position.x = data.size + data.offset.x;
3073
- }
3074
- else if (data.bounds.left > data.canvasSize.width && data.direction === exports.OutModeDirection.right) {
3075
- data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
3076
- }
3077
- const velocity = data.particle.velocity.x;
3078
- let bounced = false;
3079
- if (data.outOfCanvas &&
3080
- ((data.direction === exports.OutModeDirection.right && velocity > minVelocity) ||
3081
- (data.direction === exports.OutModeDirection.left && velocity < minVelocity))) {
3082
- const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
3083
- data.particle.velocity.x *= -newVelocity;
3084
- bounced = true;
3085
- }
3086
- if (!bounced) {
3087
- return;
3088
- }
3089
- const minPos = data.offset.x + data.size;
3090
- if (data.outOfCanvas && data.direction === exports.OutModeDirection.right) {
3091
- data.particle.position.x = data.canvasSize.width - minPos;
3092
- }
3093
- else if (data.outOfCanvas && data.direction === exports.OutModeDirection.left) {
3094
- data.particle.position.x = minPos;
3095
- }
3096
- if (data.outMode === exports.OutMode.split) {
3097
- data.particle.destroy();
3098
- }
3099
- }
3100
- function bounceVertical(data) {
3101
- if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
3102
- (data.direction !== exports.OutModeDirection.bottom && data.direction !== exports.OutModeDirection.top)) {
3142
+ const bounceAxisConfigs = {
3143
+ [exports.OutModeDirection.left]: {
3144
+ axis: "x",
3145
+ canvas: "width",
3146
+ bounce: "horizontal",
3147
+ negativeEdge: "right",
3148
+ positiveEdge: "left",
3149
+ negative: true,
3150
+ },
3151
+ [exports.OutModeDirection.right]: {
3152
+ axis: "x",
3153
+ canvas: "width",
3154
+ bounce: "horizontal",
3155
+ negativeEdge: "right",
3156
+ positiveEdge: "left",
3157
+ negative: false,
3158
+ },
3159
+ [exports.OutModeDirection.top]: {
3160
+ axis: "y",
3161
+ canvas: "height",
3162
+ bounce: "vertical",
3163
+ negativeEdge: "bottom",
3164
+ positiveEdge: "top",
3165
+ negative: true,
3166
+ },
3167
+ [exports.OutModeDirection.bottom]: {
3168
+ axis: "y",
3169
+ canvas: "height",
3170
+ bounce: "vertical",
3171
+ negativeEdge: "bottom",
3172
+ positiveEdge: "top",
3173
+ negative: false,
3174
+ },
3175
+ };
3176
+ function bounce(data) {
3177
+ if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) || !(data.direction in bounceAxisConfigs)) {
3103
3178
  return;
3104
3179
  }
3105
- if (data.bounds.bottom < boundsMin && data.direction === exports.OutModeDirection.top) {
3106
- data.particle.position.y = data.size + data.offset.y;
3180
+ const config = bounceAxisConfigs[data.direction], bounds = data.bounds, canvasDim = data.canvasSize[config.canvas], position = data.particle.position, velocity = data.particle.velocity[config.axis];
3181
+ if (config.negative && bounds[config.negativeEdge] < boundsMin) {
3182
+ position[config.axis] = data.size + data.offset[config.axis];
3107
3183
  }
3108
- else if (data.bounds.top > data.canvasSize.height && data.direction === exports.OutModeDirection.bottom) {
3109
- data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
3184
+ else if (!config.negative && bounds[config.positiveEdge] > canvasDim) {
3185
+ position[config.axis] = canvasDim - data.size - data.offset[config.axis];
3110
3186
  }
3111
- const velocity = data.particle.velocity.y;
3112
- let bounced = false;
3113
3187
  if (data.outOfCanvas &&
3114
- ((data.direction === exports.OutModeDirection.bottom && velocity > minVelocity) ||
3115
- (data.direction === exports.OutModeDirection.top && velocity < minVelocity))) {
3116
- const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
3117
- data.particle.velocity.y *= -newVelocity;
3118
- bounced = true;
3188
+ ((config.negative && velocity < minVelocity) || (!config.negative && velocity > minVelocity))) {
3189
+ data.particle.velocity[config.axis] *= -getRangeValue(data.particle.options.bounce[config.bounce].value);
3119
3190
  }
3120
- if (!bounced) {
3191
+ else {
3121
3192
  return;
3122
3193
  }
3123
- const minPos = data.offset.y + data.size;
3124
- if (data.outOfCanvas && data.direction === exports.OutModeDirection.bottom) {
3125
- data.particle.position.y = data.canvasSize.height - minPos;
3126
- }
3127
- else if (data.outOfCanvas && data.direction === exports.OutModeDirection.top) {
3128
- data.particle.position.y = minPos;
3129
- }
3194
+ const minPos = data.offset[config.axis] + data.size;
3195
+ position[config.axis] = config.negative ? minPos : canvasDim - minPos;
3130
3196
  if (data.outMode === exports.OutMode.split) {
3131
3197
  data.particle.destroy();
3132
3198
  }
@@ -3142,26 +3208,19 @@
3142
3208
  exports.OutMode.bounce,
3143
3209
  exports.OutMode.split,
3144
3210
  ];
3145
- this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
3211
+ this.#particleBouncePlugins = container.plugins.filter(p => !!p.particleBounce);
3146
3212
  }
3147
3213
  update(particle, direction, delta, outMode) {
3148
3214
  if (!this.modes.includes(outMode)) {
3149
3215
  return;
3150
3216
  }
3151
- const container = this.#container;
3152
- let handled = false;
3153
3217
  for (const plugin of this.#particleBouncePlugins) {
3154
- handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
3155
- if (handled) {
3156
- break;
3218
+ if (plugin.particleBounce?.(particle, delta, direction)) {
3219
+ return;
3157
3220
  }
3158
3221
  }
3159
- if (handled) {
3160
- return;
3161
- }
3162
- const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
3163
- bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
3164
- bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
3222
+ const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = this.#container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
3223
+ bounce({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
3165
3224
  }
3166
3225
  }
3167
3226
 
@@ -3250,108 +3309,109 @@
3250
3309
  return;
3251
3310
  }
3252
3311
  const container = this.#container;
3253
- switch (particle.outType) {
3254
- case exports.ParticleOutType.inside: {
3255
- const { x: vx, y: vy } = particle.velocity;
3256
- updateVector.setTo(originPoint);
3257
- updateVector.length = particle.moveCenter.radius;
3258
- updateVector.angle = particle.velocity.angle + Math.PI;
3259
- updateVector.addTo(particle.moveCenter);
3260
- const { dx, dy } = getDistances(particle.position, updateVector);
3261
- if ((vx <= minVelocity && dx >= minDistance) ||
3262
- (vy <= minVelocity && dy >= minDistance) ||
3263
- (vx >= minVelocity && dx <= minDistance) ||
3264
- (vy >= minVelocity && dy <= minDistance)) {
3265
- return;
3266
- }
3267
- particle.position.x = Math.floor(randomInRangeValue({
3268
- min: 0,
3269
- max: container.canvas.size.width,
3270
- }));
3271
- particle.position.y = Math.floor(randomInRangeValue({
3272
- min: 0,
3273
- max: container.canvas.size.height,
3274
- }));
3275
- const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
3276
- particle.direction = Math.atan2(-newDy, -newDx);
3277
- particle.velocity.angle = particle.direction;
3278
- particle.justWarped = true;
3279
- break;
3312
+ if (particle.outType === exports.ParticleOutType.inside) {
3313
+ this.#applyOutModeInside(particle, container);
3314
+ }
3315
+ else {
3316
+ if (particle.isInsideCanvasForOutMode(outMode, direction)) {
3317
+ return;
3280
3318
  }
3281
- default: {
3282
- if (particle.isInsideCanvasForOutMode(outMode, direction)) {
3283
- return;
3284
- }
3285
- switch (particle.outType) {
3286
- case exports.ParticleOutType.outside: {
3287
- particle.position.x =
3288
- Math.floor(randomInRangeValue({
3289
- min: -particle.moveCenter.radius,
3290
- max: particle.moveCenter.radius,
3291
- })) + particle.moveCenter.x;
3292
- particle.position.y =
3293
- Math.floor(randomInRangeValue({
3294
- min: -particle.moveCenter.radius,
3295
- max: particle.moveCenter.radius,
3296
- })) + particle.moveCenter.y;
3297
- const { dx, dy } = getDistances(particle.position, particle.moveCenter);
3298
- if (particle.moveCenter.radius) {
3299
- particle.direction = Math.atan2(dy, dx);
3300
- particle.velocity.angle = particle.direction;
3301
- }
3302
- particle.justWarped = true;
3303
- break;
3304
- }
3305
- case exports.ParticleOutType.normal: {
3306
- const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
3307
- bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
3308
- left: -particle.getRadius() - particle.offset.x,
3309
- right: canvasSize.width + particle.getRadius() + particle.offset.x,
3310
- top: -particle.getRadius() - particle.offset.y,
3311
- }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
3312
- if (direction === exports.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
3313
- particle.position.x = newPos.left;
3314
- particle.initialPosition.x = particle.position.x;
3315
- if (!warp) {
3316
- particle.position.y = getRandom() * canvasSize.height;
3317
- particle.initialPosition.y = particle.position.y;
3318
- }
3319
- particle.justWarped = true;
3320
- }
3321
- else if (direction === exports.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
3322
- particle.position.x = newPos.right;
3323
- particle.initialPosition.x = particle.position.x;
3324
- if (!warp) {
3325
- particle.position.y = getRandom() * canvasSize.height;
3326
- particle.initialPosition.y = particle.position.y;
3327
- }
3328
- particle.justWarped = true;
3329
- }
3330
- if (direction === exports.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
3331
- if (!warp) {
3332
- particle.position.x = getRandom() * canvasSize.width;
3333
- particle.initialPosition.x = particle.position.x;
3334
- }
3335
- particle.position.y = newPos.top;
3336
- particle.initialPosition.y = particle.position.y;
3337
- particle.justWarped = true;
3338
- }
3339
- else if (direction === exports.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
3340
- if (!warp) {
3341
- particle.position.x = getRandom() * canvasSize.width;
3342
- particle.initialPosition.x = particle.position.x;
3343
- }
3344
- particle.position.y = newPos.bottom;
3345
- particle.initialPosition.y = particle.position.y;
3346
- particle.justWarped = true;
3347
- }
3348
- break;
3349
- }
3350
- }
3351
- break;
3319
+ if (particle.outType === exports.ParticleOutType.outside) {
3320
+ this.#applyParticleModeOutside(particle);
3321
+ }
3322
+ else {
3323
+ this.#applyOutModeNormal(particle, container, direction);
3352
3324
  }
3353
3325
  }
3354
3326
  }
3327
+ #applyOutModeInside(particle, container) {
3328
+ const { x: vx, y: vy } = particle.velocity;
3329
+ updateVector.setTo(originPoint);
3330
+ updateVector.length = particle.moveCenter.radius;
3331
+ updateVector.angle = particle.velocity.angle + Math.PI;
3332
+ updateVector.addTo(particle.moveCenter);
3333
+ const { dx, dy } = getDistances(particle.position, updateVector);
3334
+ if ((vx <= minVelocity && dx >= minDistance) ||
3335
+ (vy <= minVelocity && dy >= minDistance) ||
3336
+ (vx >= minVelocity && dx <= minDistance) ||
3337
+ (vy >= minVelocity && dy <= minDistance)) {
3338
+ return;
3339
+ }
3340
+ particle.position.x = Math.floor(randomInRangeValue({
3341
+ min: 0,
3342
+ max: container.canvas.size.width,
3343
+ }));
3344
+ particle.position.y = Math.floor(randomInRangeValue({
3345
+ min: 0,
3346
+ max: container.canvas.size.height,
3347
+ }));
3348
+ const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
3349
+ particle.direction = Math.atan2(-newDy, -newDx);
3350
+ particle.velocity.angle = particle.direction;
3351
+ particle.justWarped = true;
3352
+ }
3353
+ #applyOutModeNormal(particle, container, direction) {
3354
+ const warp = particle.options.move.warp, canvasSize = container.canvas.size, sizeValue = particle.getRadius(), newPos = {
3355
+ bottom: canvasSize.height + sizeValue + particle.offset.y,
3356
+ left: -sizeValue - particle.offset.x,
3357
+ right: canvasSize.width + sizeValue + particle.offset.x,
3358
+ top: -sizeValue - particle.offset.y,
3359
+ }, nextBounds = calculateBounds(particle.position, sizeValue);
3360
+ if (direction === exports.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
3361
+ particle.position.x = newPos.left;
3362
+ particle.initialPosition.x = particle.position.x;
3363
+ if (!warp) {
3364
+ particle.position.y = getRandom() * canvasSize.height;
3365
+ particle.initialPosition.y = particle.position.y;
3366
+ }
3367
+ particle.justWarped = true;
3368
+ }
3369
+ else if (direction === exports.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
3370
+ particle.position.x = newPos.right;
3371
+ particle.initialPosition.x = particle.position.x;
3372
+ if (!warp) {
3373
+ particle.position.y = getRandom() * canvasSize.height;
3374
+ particle.initialPosition.y = particle.position.y;
3375
+ }
3376
+ particle.justWarped = true;
3377
+ }
3378
+ if (direction === exports.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
3379
+ if (!warp) {
3380
+ particle.position.x = getRandom() * canvasSize.width;
3381
+ particle.initialPosition.x = particle.position.x;
3382
+ }
3383
+ particle.position.y = newPos.top;
3384
+ particle.initialPosition.y = particle.position.y;
3385
+ particle.justWarped = true;
3386
+ }
3387
+ else if (direction === exports.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
3388
+ if (!warp) {
3389
+ particle.position.x = getRandom() * canvasSize.width;
3390
+ particle.initialPosition.x = particle.position.x;
3391
+ }
3392
+ particle.position.y = newPos.bottom;
3393
+ particle.initialPosition.y = particle.position.y;
3394
+ particle.justWarped = true;
3395
+ }
3396
+ }
3397
+ #applyParticleModeOutside(particle) {
3398
+ particle.position.x =
3399
+ Math.floor(randomInRangeValue({
3400
+ min: -particle.moveCenter.radius,
3401
+ max: particle.moveCenter.radius,
3402
+ })) + particle.moveCenter.x;
3403
+ particle.position.y =
3404
+ Math.floor(randomInRangeValue({
3405
+ min: -particle.moveCenter.radius,
3406
+ max: particle.moveCenter.radius,
3407
+ })) + particle.moveCenter.y;
3408
+ const { dx, dy } = getDistances(particle.position, particle.moveCenter);
3409
+ if (particle.moveCenter.radius) {
3410
+ particle.direction = Math.atan2(dy, dx);
3411
+ particle.velocity.angle = particle.direction;
3412
+ }
3413
+ particle.justWarped = true;
3414
+ }
3355
3415
  }
3356
3416
 
3357
3417
  const checkOutMode = (outModes, outMode) => {
@@ -3399,7 +3459,7 @@
3399
3459
  }
3400
3460
 
3401
3461
  async function loadOutModesUpdater(engine) {
3402
- engine.checkVersion("4.4.0");
3462
+ engine.checkVersion("4.5.1");
3403
3463
  await engine.pluginManager.register(e => {
3404
3464
  e.pluginManager.addParticleUpdater("outModes", container => {
3405
3465
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3416,39 +3476,9 @@
3416
3476
  this.#pluginManager = pluginManager;
3417
3477
  }
3418
3478
  init(particle) {
3419
- const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates), color = paint?.color, paintColor = color ?? undefined, fill = paint?.fill, stroke = paint?.stroke;
3420
- if (fill) {
3421
- const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3422
- particle.fillEnabled = fill.enable;
3423
- particle.fillOpacity = getRangeValue(fill.opacity);
3424
- particle.fillAnimation = fillColor.animation;
3425
- const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3426
- if (fillHslColor) {
3427
- particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3428
- }
3429
- }
3430
- else {
3431
- particle.fillEnabled = false;
3432
- particle.fillAnimation = undefined;
3433
- particle.fillColor = undefined;
3434
- particle.fillOpacity = defaultOpacity;
3435
- }
3436
- if (stroke) {
3437
- const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3438
- particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3439
- particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3440
- particle.strokeAnimation = strokeColor.animation;
3441
- const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3442
- if (strokeHslColor) {
3443
- particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3444
- }
3445
- }
3446
- else {
3447
- particle.strokeAnimation = undefined;
3448
- particle.strokeColor = undefined;
3449
- particle.strokeOpacity = defaultOpacity;
3450
- particle.strokeWidth = 0;
3451
- }
3479
+ const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates);
3480
+ this.#initFill(paint, particle, container);
3481
+ this.#initStroke(paint, particle, container);
3452
3482
  }
3453
3483
  isEnabled(particle) {
3454
3484
  const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
@@ -3467,10 +3497,48 @@
3467
3497
  updateColor(particle.fillColor, delta, this.#container.hdr);
3468
3498
  updateColor(particle.strokeColor, delta, this.#container.hdr);
3469
3499
  }
3500
+ #initFill(paint, particle, container) {
3501
+ const fill = paint?.fill, color = paint?.color, paintColor = color ?? undefined;
3502
+ if (!fill) {
3503
+ particle.fillEnabled = false;
3504
+ particle.fillAnimation = undefined;
3505
+ particle.fillColor = undefined;
3506
+ particle.fillOpacity = defaultOpacity;
3507
+ return;
3508
+ }
3509
+ const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3510
+ particle.fillEnabled = fill.enable;
3511
+ particle.fillOpacity = getRangeValue(fill.opacity);
3512
+ particle.fillAnimation = fillColor.animation;
3513
+ const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3514
+ if (!fillHslColor) {
3515
+ return;
3516
+ }
3517
+ particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3518
+ }
3519
+ #initStroke(paint, particle, container) {
3520
+ const stroke = paint?.stroke, color = paint?.color, paintColor = color ?? undefined;
3521
+ if (!stroke) {
3522
+ particle.strokeAnimation = undefined;
3523
+ particle.strokeColor = undefined;
3524
+ particle.strokeOpacity = defaultOpacity;
3525
+ particle.strokeWidth = 0;
3526
+ return;
3527
+ }
3528
+ const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3529
+ particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3530
+ particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3531
+ particle.strokeAnimation = strokeColor.animation;
3532
+ const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3533
+ if (!strokeHslColor) {
3534
+ return;
3535
+ }
3536
+ particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3537
+ }
3470
3538
  }
3471
3539
 
3472
3540
  async function loadPaintUpdater(engine) {
3473
- engine.checkVersion("4.4.0");
3541
+ engine.checkVersion("4.5.1");
3474
3542
  await engine.pluginManager.register(e => {
3475
3543
  e.pluginManager.addParticleUpdater("paint", container => {
3476
3544
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3512,7 +3580,7 @@
3512
3580
  if (!this.accepts(input)) {
3513
3581
  return;
3514
3582
  }
3515
- const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
3583
+ const result = rgbRegex.exec(input), radix = 10, minLength = 4;
3516
3584
  return result
3517
3585
  ? {
3518
3586
  a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
@@ -3525,7 +3593,7 @@
3525
3593
  }
3526
3594
 
3527
3595
  async function loadRgbColorPlugin(engine) {
3528
- engine.checkVersion("4.4.0");
3596
+ engine.checkVersion("4.5.1");
3529
3597
  await engine.pluginManager.register(e => {
3530
3598
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3531
3599
  });
@@ -3610,7 +3678,7 @@
3610
3678
  }
3611
3679
 
3612
3680
  async function loadSizeUpdater(engine) {
3613
- engine.checkVersion("4.4.0");
3681
+ engine.checkVersion("4.5.1");
3614
3682
  await engine.pluginManager.register(e => {
3615
3683
  e.pluginManager.addParticleUpdater("size", container => {
3616
3684
  return Promise.resolve(new SizeUpdater(container));
@@ -3619,7 +3687,7 @@
3619
3687
  }
3620
3688
 
3621
3689
  async function loadBasic(engine) {
3622
- engine.checkVersion("4.4.0");
3690
+ engine.checkVersion("4.5.1");
3623
3691
  await engine.pluginManager.register(async (e) => {
3624
3692
  await Promise.all([
3625
3693
  loadBlendPlugin(e),
@@ -3950,7 +4018,7 @@
3950
4018
  }
3951
4019
 
3952
4020
  async function loadDestroyUpdater(engine) {
3953
- engine.checkVersion("4.4.0");
4021
+ engine.checkVersion("4.5.1");
3954
4022
  await engine.pluginManager.register(e => {
3955
4023
  e.pluginManager.addParticleUpdater("destroy", container => {
3956
4024
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -4050,6 +4118,8 @@
4050
4118
  autoPlay = true;
4051
4119
  direction;
4052
4120
  domId;
4121
+ draggable = false;
4122
+ draw = false;
4053
4123
  fill = true;
4054
4124
  life = new EmitterLife();
4055
4125
  name;
@@ -4073,6 +4143,8 @@
4073
4143
  }
4074
4144
  loadProperty(this, "direction", data.direction);
4075
4145
  loadProperty(this, "domId", data.domId);
4146
+ loadProperty(this, "draggable", data.draggable);
4147
+ loadProperty(this, "draw", data.draw);
4076
4148
  loadProperty(this, "fill", data.fill);
4077
4149
  this.life.load(data.life);
4078
4150
  loadProperty(this, "name", data.name);
@@ -4134,6 +4206,14 @@
4134
4206
  }
4135
4207
  }
4136
4208
 
4209
+ const ErrorCodes = {
4210
+ emittersPluginNotLoaded: "TSP-3101",
4211
+ };
4212
+
4213
+ const ErrorMessages = {
4214
+ [ErrorCodes.emittersPluginNotLoaded]: "tsParticles Emitters Plugin is not loaded",
4215
+ };
4216
+
4137
4217
  async function addEmittersShapesManager(e) {
4138
4218
  const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
4139
4219
  pluginManager.emitterShapeManager ??= new ShapeManager();
@@ -4169,6 +4249,8 @@
4169
4249
  this.fill = fill;
4170
4250
  this.options = options;
4171
4251
  }
4252
+ draw(_context) {
4253
+ }
4172
4254
  resize(position, size) {
4173
4255
  this.position = position;
4174
4256
  this.size = size;
@@ -4181,7 +4263,10 @@
4181
4263
  })(EmitterClickMode || (EmitterClickMode = {}));
4182
4264
 
4183
4265
  async function loadEmittersPluginSimple(engine) {
4184
- engine.checkVersion("4.4.0");
4266
+ engine.checkVersion("4.5.1");
4267
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
4268
+ addErrorMessages(ErrorMessages);
4269
+ }
4185
4270
  await engine.pluginManager.register(async (e) => {
4186
4271
  const instancesManager = await getEmittersInstancesManager(e);
4187
4272
  await addEmittersShapesManager(e);
@@ -4189,9 +4274,63 @@
4189
4274
  });
4190
4275
  }
4191
4276
 
4277
+ class EmittersPluginInstance {
4278
+ #container;
4279
+ #instancesManager;
4280
+ constructor(instancesManager, container) {
4281
+ this.#instancesManager = instancesManager;
4282
+ this.#container = container;
4283
+ this.#instancesManager.initContainer(container);
4284
+ }
4285
+ draw(context, _delta) {
4286
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4287
+ emitter.draw(context);
4288
+ }
4289
+ }
4290
+ async init() {
4291
+ const emittersOptions = this.#container.actualOptions.emitters;
4292
+ if (isArray(emittersOptions)) {
4293
+ for (const emitterOptions of emittersOptions) {
4294
+ await this.#instancesManager.addEmitter(this.#container, emitterOptions);
4295
+ }
4296
+ }
4297
+ else {
4298
+ await this.#instancesManager.addEmitter(this.#container, emittersOptions);
4299
+ }
4300
+ }
4301
+ pause() {
4302
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4303
+ emitter.pause();
4304
+ }
4305
+ }
4306
+ play() {
4307
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4308
+ emitter.play();
4309
+ }
4310
+ }
4311
+ resize() {
4312
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4313
+ emitter.resize();
4314
+ }
4315
+ }
4316
+ stop() {
4317
+ this.#instancesManager.clear(this.#container);
4318
+ }
4319
+ update(delta) {
4320
+ this.#instancesManager.getArray(this.#container).forEach(emitter => {
4321
+ emitter.update(delta);
4322
+ });
4323
+ }
4324
+ }
4325
+
4326
+ var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
4327
+ __proto__: null,
4328
+ EmittersPluginInstance: EmittersPluginInstance
4329
+ });
4330
+
4192
4331
  function ensureEmittersPluginLoaded(e) {
4193
4332
  if (!e.pluginManager.addEmitterShapeGenerator) {
4194
- throw new Error("tsParticles Emitters Plugin is not loaded");
4333
+ throw new Error(getErrorMessage(ErrorCodes.emittersPluginNotLoaded));
4195
4334
  }
4196
4335
  }
4197
4336
 
@@ -4207,12 +4346,16 @@
4207
4346
  return position + offset * (getRandom() - half);
4208
4347
  }
4209
4348
  function getRandomSize(sides) {
4210
- return Math.floor(getRandom() * sides);
4349
+ return toEnumValue(Sides, Math.floor(getRandom() * sides), Sides.BottomLeft);
4211
4350
  }
4212
4351
  class EmittersSquareShape extends EmitterShapeBase {
4213
4352
  constructor(position, size, fill, options) {
4214
4353
  super(position, size, fill, options);
4215
4354
  }
4355
+ draw(context) {
4356
+ const position = this.position, size = this.size, halfW = size.width * half, halfH = size.height * half;
4357
+ context.rect(position.x - halfW, position.y - halfH, size.width, size.height);
4358
+ }
4216
4359
  async init() {
4217
4360
  }
4218
4361
  randomPosition() {
@@ -4269,7 +4412,7 @@
4269
4412
  }
4270
4413
 
4271
4414
  async function loadEmittersShapeSquare(engine) {
4272
- engine.checkVersion("4.4.0");
4415
+ engine.checkVersion("4.5.1");
4273
4416
  await engine.pluginManager.register((e) => {
4274
4417
  ensureEmittersPluginLoaded(e);
4275
4418
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -4351,7 +4494,7 @@
4351
4494
  particle.destroy();
4352
4495
  return;
4353
4496
  }
4354
- const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.width);
4497
+ const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.height);
4355
4498
  particle.position.x = randomInRangeValue(widthRange);
4356
4499
  particle.position.y = randomInRangeValue(heightRange);
4357
4500
  particle.spawning = true;
@@ -4413,7 +4556,7 @@
4413
4556
  }
4414
4557
 
4415
4558
  async function loadLifeUpdater(engine) {
4416
- engine.checkVersion("4.4.0");
4559
+ engine.checkVersion("4.5.1");
4417
4560
  await engine.pluginManager.register(e => {
4418
4561
  e.pluginManager.addParticleUpdater("life", container => {
4419
4562
  return Promise.resolve(new LifeUpdater(container));
@@ -4439,7 +4582,7 @@
4439
4582
  }
4440
4583
 
4441
4584
  async function loadLineShape(engine) {
4442
- engine.checkVersion("4.4.0");
4585
+ engine.checkVersion("4.5.1");
4443
4586
  await engine.pluginManager.register(e => {
4444
4587
  e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
4445
4588
  });
@@ -4496,7 +4639,7 @@
4496
4639
  particle.pathRotation = rotateOptions.path;
4497
4640
  let rotateDirection = rotateOptions.direction;
4498
4641
  if (rotateDirection === exports.RotateDirection.random) {
4499
- const index = Math.floor(getRandom() * double), minIndex = 0;
4642
+ const index = Math.floor(getRandom() * double);
4500
4643
  rotateDirection = index > minIndex ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
4501
4644
  }
4502
4645
  switch (rotateDirection) {
@@ -4543,7 +4686,7 @@
4543
4686
  }
4544
4687
 
4545
4688
  async function loadRotateUpdater(engine) {
4546
- engine.checkVersion("4.4.0");
4689
+ engine.checkVersion("4.5.1");
4547
4690
  await engine.pluginManager.register(e => {
4548
4691
  e.pluginManager.addParticleUpdater("rotate", container => {
4549
4692
  return Promise.resolve(new RotateUpdater(container));
@@ -4859,7 +5002,7 @@
4859
5002
  }
4860
5003
 
4861
5004
  async function loadSoundsPlugin(engine) {
4862
- engine.checkVersion("4.4.0");
5005
+ engine.checkVersion("4.5.1");
4863
5006
  await engine.pluginManager.register(e => {
4864
5007
  e.pluginManager.addPlugin(new SoundsPlugin(e));
4865
5008
  });
@@ -4867,7 +5010,7 @@
4867
5010
 
4868
5011
  let initPromise = null;
4869
5012
  async function doInitPlugins(engine) {
4870
- engine.checkVersion("4.4.0");
5013
+ engine.checkVersion("4.5.1");
4871
5014
  await engine.pluginManager.register(async (e) => {
4872
5015
  const loadEmittersForFireworks = async (e) => {
4873
5016
  await loadEmittersPluginSimple(e);
@@ -4914,7 +5057,7 @@
4914
5057
  fireworks.init = async () => {
4915
5058
  await initPlugins(tsParticles);
4916
5059
  };
4917
- fireworks.version = "4.4.0";
5060
+ fireworks.version = "4.5.1";
4918
5061
  globalThis.fireworks = fireworks;
4919
5062
 
4920
5063
  const globalObject = globalThis;
@@ -4984,21 +5127,28 @@
4984
5127
  });
4985
5128
  }
4986
5129
  clear() {
5130
+ const visited = new Set();
4987
5131
  for (const plugin of this.#canvasClearPlugins) {
5132
+ visited.add(plugin);
4988
5133
  if (plugin.canvasClear?.() ?? false) {
4989
- return;
5134
+ return plugin;
4990
5135
  }
4991
5136
  }
4992
5137
  for (const layer of Object.values(exports.DrawLayer)) {
4993
5138
  if (typeof layer === "number") {
4994
5139
  for (const plugin of this.#getLayerPlugins(layer)) {
5140
+ if (visited.has(plugin)) {
5141
+ continue;
5142
+ }
5143
+ visited.add(plugin);
4995
5144
  if (plugin.canvasClear?.() ?? false) {
4996
- return;
5145
+ return plugin;
4997
5146
  }
4998
5147
  }
4999
5148
  }
5000
5149
  }
5001
5150
  this.canvasClear();
5151
+ return undefined;
5002
5152
  }
5003
5153
  destroy() {
5004
5154
  this.stop();
@@ -5076,8 +5226,7 @@
5076
5226
  });
5077
5227
  }
5078
5228
  drawParticles(delta) {
5079
- const { particles, actualOptions } = this.#container;
5080
- this.clear();
5229
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
5081
5230
  particles.update(delta);
5082
5231
  this.draw(ctx => {
5083
5232
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -5099,7 +5248,9 @@
5099
5248
  }
5100
5249
  }
5101
5250
  for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
5102
- plugin.canvasPaint?.();
5251
+ if (plugin !== clearedPlugin) {
5252
+ plugin.canvasPaint?.();
5253
+ }
5103
5254
  }
5104
5255
  for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
5105
5256
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -5131,35 +5282,7 @@
5131
5282
  this.#layers[layer] = [];
5132
5283
  }
5133
5284
  }
5134
- for (const plugin of this.#container.plugins) {
5135
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
5136
- this.#colorPlugins.push(plugin);
5137
- }
5138
- if (plugin.drawParticle) {
5139
- this.#drawParticlePlugins.push(plugin);
5140
- }
5141
- if (plugin.drawParticleSetup) {
5142
- this.#drawParticlesSetupPlugins.push(plugin);
5143
- }
5144
- if (plugin.drawParticleCleanup) {
5145
- this.#drawParticlesCleanupPlugins.push(plugin);
5146
- }
5147
- if (plugin.canvasClear) {
5148
- this.#canvasClearPlugins.push(plugin);
5149
- }
5150
- if (plugin.canvasPaint) {
5151
- this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
5152
- }
5153
- if (plugin.drawSettingsSetup) {
5154
- this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
5155
- }
5156
- if (plugin.draw) {
5157
- this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
5158
- }
5159
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
5160
- this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
5161
- }
5162
- }
5285
+ this.#initPluginsArray();
5163
5286
  }
5164
5287
  initUpdaters() {
5165
5288
  this.#preDrawUpdaters = [];
@@ -5368,6 +5491,45 @@
5368
5491
  this.#reusablePluginColors[sColorIndex] = sColor;
5369
5492
  return this.#reusablePluginColors;
5370
5493
  }
5494
+ #initLayerPlugin(plugin) {
5495
+ const layerMap = [
5496
+ [exports.DrawLayer.BackgroundMask, !!plugin.canvasPaint],
5497
+ [exports.DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
5498
+ [exports.DrawLayer.PluginContent, !!plugin.draw],
5499
+ [exports.DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
5500
+ ];
5501
+ for (const [layer, active] of layerMap) {
5502
+ if (active) {
5503
+ this.#layers[layer].push(plugin);
5504
+ }
5505
+ }
5506
+ }
5507
+ #initPluginsArray() {
5508
+ for (const plugin of this.#container.plugins) {
5509
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
5510
+ this.#colorPlugins.push(plugin);
5511
+ }
5512
+ if (plugin.drawParticle) {
5513
+ this.#drawParticlePlugins.push(plugin);
5514
+ }
5515
+ if (plugin.drawParticleSetup) {
5516
+ this.#drawParticlesSetupPlugins.push(plugin);
5517
+ }
5518
+ if (plugin.drawParticleCleanup) {
5519
+ this.#drawParticlesCleanupPlugins.push(plugin);
5520
+ }
5521
+ if (plugin.canvasClear) {
5522
+ this.#canvasClearPlugins.push(plugin);
5523
+ }
5524
+ this.#initLayerPlugin(plugin);
5525
+ }
5526
+ }
5527
+ #isSupportedElement(element) {
5528
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
5529
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
5530
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
5531
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
5532
+ }
5371
5533
  #resolveBackgroundElement() {
5372
5534
  const background = this.#container.actualOptions.background;
5373
5535
  this.#backgroundElement = null;
@@ -5377,9 +5539,7 @@
5377
5539
  if (typeof background.element === "string") {
5378
5540
  if (typeof document !== "undefined") {
5379
5541
  const node = document.querySelector(background.element);
5380
- if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
5381
- (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
5382
- (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
5542
+ if (node && this.#isSupportedElement(node)) {
5383
5543
  this.#backgroundElement = node;
5384
5544
  }
5385
5545
  else if (node) {
@@ -5390,10 +5550,7 @@
5390
5550
  }
5391
5551
  }
5392
5552
  }
5393
- else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
5394
- (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
5395
- (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
5396
- (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
5553
+ else if (this.#isSupportedElement(background.element)) {
5397
5554
  this.#backgroundElement = background.element;
5398
5555
  }
5399
5556
  }
@@ -5411,7 +5568,7 @@
5411
5568
  return transferredCanvas;
5412
5569
  }
5413
5570
  if (typeof canvas.transferControlToOffscreen !== "function") {
5414
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
5571
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasUnsupported));
5415
5572
  }
5416
5573
  try {
5417
5574
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -5419,10 +5576,16 @@
5419
5576
  return offscreenCanvas;
5420
5577
  }
5421
5578
  catch {
5422
- throw new TypeError("OffscreenCanvas transfer failed");
5579
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasTransferFailed));
5423
5580
  }
5424
5581
  }, isHtmlCanvasElement = (canvas) => {
5425
5582
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
5583
+ }, getEffectiveColorSpace = (context) => {
5584
+ if (!context) {
5585
+ return undefined;
5586
+ }
5587
+ const colorInfo = context;
5588
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
5426
5589
  };
5427
5590
  function setStyle(canvas, style, important = false) {
5428
5591
  if (!style) {
@@ -5547,7 +5710,7 @@
5547
5710
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
5548
5711
  if (color) {
5549
5712
  const hdrOptions = container.actualOptions.hdr;
5550
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
5713
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(exports.HdrMode, hdrOptions.mode, exports.HdrMode.standard));
5551
5714
  }
5552
5715
  else {
5553
5716
  elementStyle.backgroundColor = "";
@@ -5667,11 +5830,11 @@
5667
5830
  const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
5668
5831
  safeMatchMedia("(color-gamut: p3)")?.matches &&
5669
5832
  safeMatchMedia("(dynamic-range: high)")?.matches;
5670
- container.hdr = canSupportHdr ?? false;
5671
- container.hdrMode = container.actualOptions.hdr.mode;
5833
+ container.hdrMode = toEnumValue(exports.HdrMode, container.actualOptions.hdr.mode, exports.HdrMode.standard);
5672
5834
  container.peakNits = container.actualOptions.hdr.peakNits;
5673
5835
  const renderCanvas = this.renderCanvas;
5674
5836
  if (!renderCanvas) {
5837
+ container.hdr = canSupportHdr ?? false;
5675
5838
  return;
5676
5839
  }
5677
5840
  this.render.setContextSettings({
@@ -5690,7 +5853,6 @@
5690
5853
  context = null;
5691
5854
  }
5692
5855
  if (canSupportHdr && !context) {
5693
- container.hdr = false;
5694
5856
  const sdrSettings = {
5695
5857
  alpha: true,
5696
5858
  desynchronized: true,
@@ -5706,11 +5868,16 @@
5706
5868
  }
5707
5869
  }
5708
5870
  this.render.setContext(context);
5871
+ if (context) {
5872
+ const effectiveColorSpace = getEffectiveColorSpace(context);
5873
+ if (effectiveColorSpace !== undefined) {
5874
+ container.hdr = effectiveColorSpace === "display-p3";
5875
+ }
5876
+ }
5709
5877
  }
5710
5878
  #initHdrListeners() {
5711
5879
  this.#removeHdrListeners();
5712
5880
  const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
5713
- this.#recreateRenderCanvas();
5714
5881
  this.#initContext();
5715
5882
  this.initBackground();
5716
5883
  }, listeners = [];
@@ -5746,16 +5913,6 @@
5746
5913
  element.style.setProperty(key, value, "important");
5747
5914
  }
5748
5915
  }
5749
- #recreateRenderCanvas() {
5750
- const renderCanvas = this.renderCanvas;
5751
- if (!renderCanvas) {
5752
- return;
5753
- }
5754
- if (this.domElement) {
5755
- return;
5756
- }
5757
- this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
5758
- }
5759
5916
  #removeHdrListeners() {
5760
5917
  if (!this.#hdrMediaListeners) {
5761
5918
  return;
@@ -5827,6 +5984,10 @@
5827
5984
  this.#manageListeners(true);
5828
5985
  }
5829
5986
  removeListeners() {
5987
+ if (this.#resizeTimeout !== undefined) {
5988
+ clearTimeout(this.#resizeTimeout);
5989
+ this.#resizeTimeout = undefined;
5990
+ }
5830
5991
  this.#manageListeners(false);
5831
5992
  }
5832
5993
  #handleVisibilityChange() {
@@ -5854,8 +6015,7 @@
5854
6015
  this.#resizeTimeout = undefined;
5855
6016
  }
5856
6017
  const handleResize = async () => {
5857
- const canvas = this.#container.canvas;
5858
- await canvas.windowResize();
6018
+ await this.#container.canvas.windowResize();
5859
6019
  };
5860
6020
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
5861
6021
  }
@@ -5883,8 +6043,8 @@
5883
6043
  }
5884
6044
  else if (!this.#resizeObserver && add && canvasEl) {
5885
6045
  this.#resizeObserver = new ResizeObserver((entries) => {
5886
- const entry = entries.find(e => e.target === canvasEl);
5887
- if (!entry) {
6046
+ const res = entries.some(e => e.target === canvasEl);
6047
+ if (!res) {
5888
6048
  return;
5889
6049
  }
5890
6050
  this.#handleWindowResize();
@@ -6148,10 +6308,10 @@
6148
6308
  return this.#modifiers.find(m => m.id === id);
6149
6309
  }
6150
6310
  getOpacity() {
6151
- const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$1, strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
6152
- this.#cachedOpacityData.fillOpacity = fillOpacity;
6311
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity;
6312
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
6153
6313
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
6154
- this.#cachedOpacityData.strokeOpacity = strokeOpacity;
6314
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
6155
6315
  return this.#cachedOpacityData;
6156
6316
  }
6157
6317
  getPosition() {
@@ -6398,7 +6558,7 @@
6398
6558
  #initPosition(position) {
6399
6559
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
6400
6560
  if (!initialPosition) {
6401
- throw new Error("a valid position cannot be found for particle");
6561
+ throw new Error(getErrorMessage(ErrorCodes$2.particlePositionNotFound));
6402
6562
  }
6403
6563
  this.position = initialPosition;
6404
6564
  this.initialPosition = this.position.copy();
@@ -6447,6 +6607,12 @@
6447
6607
  this.#circlePoolIdx = 0;
6448
6608
  this.#rectanglePoolIdx = 0;
6449
6609
  }
6610
+ get cellSize() {
6611
+ return this.#cellSize;
6612
+ }
6613
+ set cellSize(value) {
6614
+ this.#pendingCellSize = value;
6615
+ }
6450
6616
  clear() {
6451
6617
  this.#cells.clear();
6452
6618
  const pendingCellSize = this.#pendingCellSize;
@@ -6470,40 +6636,46 @@
6470
6636
  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);
6471
6637
  for (let cx = minCellX; cx <= maxCellX; cx++) {
6472
6638
  for (let cy = minCellY; cy <= maxCellY; cy++) {
6473
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
6474
- if (!cellParticles) {
6475
- continue;
6476
- }
6477
- for (const p of cellParticles) {
6478
- if (check && !check(p)) {
6479
- continue;
6480
- }
6481
- if (range.contains(p.getPosition())) {
6482
- out.push(p);
6483
- }
6484
- }
6639
+ this.#queryCell(cx, cy, range, check, out);
6485
6640
  }
6486
6641
  }
6487
6642
  return out;
6488
6643
  }
6489
6644
  queryCircle(position, radius, check, out = []) {
6490
- const circle = this.#acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
6491
- this.#releaseShapes();
6492
- return result;
6645
+ const circle = this.#acquireCircle(position.x, position.y, radius);
6646
+ try {
6647
+ return this.query(circle, check, out);
6648
+ }
6649
+ finally {
6650
+ this.#circlePoolIdx--;
6651
+ }
6493
6652
  }
6494
6653
  queryRectangle(position, size, check, out = []) {
6495
- const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
6496
- this.#releaseShapes();
6497
- return result;
6498
- }
6499
- setCellSize(cellSize) {
6500
- this.#pendingCellSize = cellSize;
6654
+ const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height);
6655
+ try {
6656
+ return this.query(rect, check, out);
6657
+ }
6658
+ finally {
6659
+ this.#rectanglePoolIdx--;
6660
+ }
6501
6661
  }
6502
6662
  #acquireCircle(x, y, r) {
6503
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
6663
+ const idx = this.#circlePoolIdx++;
6664
+ let circle = this.#circlePool[idx];
6665
+ if (!circle) {
6666
+ circle = new Circle(x, y, r);
6667
+ this.#circlePool[idx] = circle;
6668
+ }
6669
+ return circle.reset(x, y, r);
6504
6670
  }
6505
6671
  #acquireRectangle(x, y, w, h) {
6506
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
6672
+ const idx = this.#rectanglePoolIdx++;
6673
+ let rectangle = this.#rectanglePool[idx];
6674
+ if (!rectangle) {
6675
+ rectangle = new Rectangle(x, y, w, h);
6676
+ this.#rectanglePool[idx] = rectangle;
6677
+ }
6678
+ return rectangle.reset(x, y, w, h);
6507
6679
  }
6508
6680
  #cellKeyFromCoords(x, y) {
6509
6681
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -6530,17 +6702,27 @@
6530
6702
  }
6531
6703
  return null;
6532
6704
  }
6533
- #releaseShapes() {
6534
- this.#circlePoolIdx = 0;
6535
- this.#rectanglePoolIdx = 0;
6705
+ #queryCell(cx, cy, range, check, out) {
6706
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
6707
+ if (!cellParticles) {
6708
+ return;
6709
+ }
6710
+ for (const p of cellParticles) {
6711
+ if (check && !check(p)) {
6712
+ continue;
6713
+ }
6714
+ if (range.contains(p.getPosition())) {
6715
+ out.push(p);
6716
+ }
6717
+ }
6536
6718
  }
6537
6719
  }
6538
6720
 
6539
6721
  class ParticlesManager {
6540
6722
  checkParticlePositionPlugins;
6541
- grid;
6542
6723
  #array;
6543
6724
  #container;
6725
+ #grid;
6544
6726
  #groupLimits;
6545
6727
  #limit;
6546
6728
  #nextId;
@@ -6564,7 +6746,7 @@
6564
6746
  this.#groupLimits = new Map();
6565
6747
  this.#particleBuckets = new Map();
6566
6748
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
6567
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
6749
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
6568
6750
  this.checkParticlePositionPlugins = [];
6569
6751
  this.#particleResetPlugins = [];
6570
6752
  this.#particleUpdatePlugins = [];
@@ -6575,23 +6757,12 @@
6575
6757
  get count() {
6576
6758
  return this.#array.length;
6577
6759
  }
6760
+ get grid() {
6761
+ return this.#grid;
6762
+ }
6578
6763
  addParticle(position, overrideOptions, group, initializer) {
6579
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
6580
- if (limit > minLimit) {
6581
- switch (limitMode) {
6582
- case exports.LimitMode.delete: {
6583
- const countToRemove = currentCount + countOffset - limit;
6584
- if (countToRemove > minCount) {
6585
- this.removeQuantity(countToRemove);
6586
- }
6587
- break;
6588
- }
6589
- case exports.LimitMode.wait:
6590
- if (currentCount >= limit) {
6591
- return;
6592
- }
6593
- break;
6594
- }
6764
+ if (this.#checkAndApplyLimits(group, this.count)) {
6765
+ return;
6595
6766
  }
6596
6767
  try {
6597
6768
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -6655,7 +6826,7 @@
6655
6826
  return this.#array[index];
6656
6827
  }
6657
6828
  async init() {
6658
- const container = this.#container, options = container.actualOptions;
6829
+ const container = this.#container;
6659
6830
  this.checkParticlePositionPlugins = [];
6660
6831
  this.#updatePlugins = [];
6661
6832
  this.#particleUpdatePlugins = [];
@@ -6664,59 +6835,16 @@
6664
6835
  this.#postParticleUpdatePlugins = [];
6665
6836
  this.#particleBuckets.clear();
6666
6837
  this.#resetBuckets(container.zLayers);
6667
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
6668
- for (const plugin of container.plugins) {
6669
- if (plugin.redrawInit) {
6670
- await plugin.redrawInit();
6671
- }
6672
- if (plugin.checkParticlePosition) {
6673
- this.checkParticlePositionPlugins.push(plugin);
6674
- }
6675
- if (plugin.update) {
6676
- this.#updatePlugins.push(plugin);
6677
- }
6678
- if (plugin.particleUpdate) {
6679
- this.#particleUpdatePlugins.push(plugin);
6680
- }
6681
- if (plugin.postUpdate) {
6682
- this.#postUpdatePlugins.push(plugin);
6683
- }
6684
- if (plugin.particleReset) {
6685
- this.#particleResetPlugins.push(plugin);
6686
- }
6687
- if (plugin.postParticleUpdate) {
6688
- this.#postParticleUpdatePlugins.push(plugin);
6689
- }
6690
- }
6691
- await this.#container.initDrawersAndUpdaters();
6692
- for (const drawer of this.#container.effectDrawers.values()) {
6693
- await drawer.init?.(container);
6694
- }
6695
- for (const drawer of this.#container.shapeDrawers.values()) {
6696
- await drawer.init?.(container);
6697
- }
6698
- let handled = false;
6699
- for (const plugin of container.plugins) {
6700
- handled = plugin.particlesInitialization?.() ?? handled;
6701
- if (handled) {
6702
- break;
6703
- }
6704
- }
6705
- if (!handled) {
6706
- const particlesOptions = options.particles, groups = particlesOptions.groups;
6707
- for (const group in groups) {
6708
- const groupOptions = groups[group];
6709
- if (!groupOptions) {
6710
- continue;
6711
- }
6712
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
6713
- this.addParticle(undefined, groupOptions, group);
6714
- }
6715
- }
6716
- for (let i = this.count; i < particlesOptions.number.value; i++) {
6717
- this.addParticle();
6838
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
6839
+ this.#applyLimits(container.actualOptions.particles);
6840
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
6841
+ for (const group in groups) {
6842
+ const groupData = groups[group];
6843
+ if (groupData) {
6844
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
6718
6845
  }
6719
6846
  }
6847
+ await this.#initPlugins();
6720
6848
  }
6721
6849
  push(nb, position, overrideOptions, group) {
6722
6850
  for (let i = 0; i < nb; i++) {
@@ -6731,13 +6859,13 @@
6731
6859
  remove(particle, group, override) {
6732
6860
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
6733
6861
  }
6734
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
6862
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
6735
6863
  if (index < minIndex || index > this.count) {
6736
6864
  return;
6737
6865
  }
6738
6866
  let deleted = 0;
6739
6867
  for (let i = index; deleted < quantity && i < this.count; i++) {
6740
- if (this.#removeParticle(i, group, override)) {
6868
+ if (this.#removeParticle(i, group, override, matchGroup)) {
6741
6869
  i--;
6742
6870
  deleted++;
6743
6871
  }
@@ -6768,7 +6896,7 @@
6768
6896
  this.#resizeFactor = factor;
6769
6897
  }
6770
6898
  update(delta) {
6771
- this.grid.clear();
6899
+ this.#grid.clear();
6772
6900
  for (const plugin of this.#updatePlugins) {
6773
6901
  plugin.update?.(delta);
6774
6902
  }
@@ -6779,7 +6907,7 @@
6779
6907
  this.#updateParticlesPhase2(delta, particlesToDelete);
6780
6908
  if (particlesToDelete.size) {
6781
6909
  for (const particle of particlesToDelete) {
6782
- this.remove(particle);
6910
+ this.remove(particle, particle.group);
6783
6911
  }
6784
6912
  }
6785
6913
  this.#resizeFactor = undefined;
@@ -6790,12 +6918,7 @@
6790
6918
  #applyDensity(options, pluginsCount, group, groupOptions) {
6791
6919
  const numberOptions = options.number;
6792
6920
  if (!numberOptions.density.enable) {
6793
- if (group === undefined) {
6794
- this.#limit = numberOptions.limit.value;
6795
- }
6796
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
6797
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
6798
- }
6921
+ this.#applyLimits(options, group, groupOptions);
6799
6922
  return;
6800
6923
  }
6801
6924
  const densityFactor = this.#initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + pluginsCount, particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
@@ -6803,7 +6926,10 @@
6803
6926
  this.#limit = numberOptions.limit.value * densityFactor;
6804
6927
  }
6805
6928
  else {
6806
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
6929
+ this.#groupLimits.set(group, {
6930
+ limit: numberOptions.limit.value * densityFactor,
6931
+ mode: toEnumValue(exports.LimitMode, numberOptions.limit.mode, exports.LimitMode.delete),
6932
+ });
6807
6933
  }
6808
6934
  if (particlesCount < particlesNumber) {
6809
6935
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -6812,6 +6938,55 @@
6812
6938
  this.removeQuantity(particlesCount - particlesNumber, group);
6813
6939
  }
6814
6940
  }
6941
+ #applyLimits(options, group, groupOptions) {
6942
+ if (group === undefined) {
6943
+ this.#limit = options.number.limit.value;
6944
+ const groups = this.#container.actualOptions.particles.groups;
6945
+ for (const existingGroup of this.#groupLimits.keys()) {
6946
+ if (!(existingGroup in groups)) {
6947
+ this.#groupLimits.delete(existingGroup);
6948
+ }
6949
+ }
6950
+ }
6951
+ else {
6952
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
6953
+ if (limitValue > minLimit) {
6954
+ this.#groupLimits.set(group, {
6955
+ limit: limitValue,
6956
+ mode: toEnumValue(exports.LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, exports.LimitMode.delete),
6957
+ });
6958
+ }
6959
+ else {
6960
+ this.#groupLimits.delete(group);
6961
+ }
6962
+ }
6963
+ }
6964
+ #checkAndApplyLimits(group, currentCount) {
6965
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
6966
+ if (globalLimit > minLimit && globalMode === exports.LimitMode.wait && currentCount >= globalLimit) {
6967
+ return true;
6968
+ }
6969
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
6970
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === exports.LimitMode.wait) {
6971
+ const groupCount = this.filter(t => t.group === group).length;
6972
+ if (groupCount >= groupLimitEntry.limit) {
6973
+ return true;
6974
+ }
6975
+ }
6976
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === exports.LimitMode.delete) {
6977
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
6978
+ if (groupCountToRemove > minCount) {
6979
+ this.removeQuantity(groupCountToRemove, group);
6980
+ }
6981
+ }
6982
+ if (globalLimit > minLimit && globalMode === exports.LimitMode.delete) {
6983
+ const globalCountToRemove = this.count + countOffset - globalLimit;
6984
+ if (globalCountToRemove > minCount) {
6985
+ this.#removeAny(globalCountToRemove);
6986
+ }
6987
+ }
6988
+ return false;
6989
+ }
6815
6990
  #createBuckets(zLayers) {
6816
6991
  const bucketCount = Math.max(Math.floor(zLayers), one);
6817
6992
  return Array.from({ length: bucketCount }, () => []);
@@ -6834,6 +7009,70 @@
6834
7009
  }
6835
7010
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
6836
7011
  }
7012
+ async #initDrawersAndUpdaters() {
7013
+ const container = this.#container;
7014
+ await container.initDrawersAndUpdaters();
7015
+ for (const drawer of container.effectDrawers.values()) {
7016
+ await drawer.init?.(container);
7017
+ }
7018
+ for (const drawer of container.shapeDrawers.values()) {
7019
+ await drawer.init?.(container);
7020
+ }
7021
+ }
7022
+ async #initPlugins() {
7023
+ await this.#initPluginsArrays();
7024
+ await this.#initDrawersAndUpdaters();
7025
+ let handled = false;
7026
+ const container = this.#container;
7027
+ for (const plugin of container.plugins) {
7028
+ handled = plugin.particlesInitialization?.() ?? handled;
7029
+ if (handled) {
7030
+ break;
7031
+ }
7032
+ }
7033
+ if (handled) {
7034
+ return;
7035
+ }
7036
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
7037
+ for (const group in groups) {
7038
+ const groupOptions = groups[group];
7039
+ if (!groupOptions) {
7040
+ continue;
7041
+ }
7042
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
7043
+ this.addParticle(undefined, groupOptions, group);
7044
+ }
7045
+ }
7046
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
7047
+ this.addParticle();
7048
+ }
7049
+ }
7050
+ async #initPluginsArrays() {
7051
+ const container = this.#container;
7052
+ for (const plugin of container.plugins) {
7053
+ if (plugin.redrawInit) {
7054
+ await plugin.redrawInit();
7055
+ }
7056
+ if (plugin.checkParticlePosition) {
7057
+ this.checkParticlePositionPlugins.push(plugin);
7058
+ }
7059
+ if (plugin.update) {
7060
+ this.#updatePlugins.push(plugin);
7061
+ }
7062
+ if (plugin.particleUpdate) {
7063
+ this.#particleUpdatePlugins.push(plugin);
7064
+ }
7065
+ if (plugin.postUpdate) {
7066
+ this.#postUpdatePlugins.push(plugin);
7067
+ }
7068
+ if (plugin.particleReset) {
7069
+ this.#particleResetPlugins.push(plugin);
7070
+ }
7071
+ if (plugin.postParticleUpdate) {
7072
+ this.#postParticleUpdatePlugins.push(plugin);
7073
+ }
7074
+ }
7075
+ }
6837
7076
  #insertParticleIntoBucket(particle) {
6838
7077
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6839
7078
  if (!bucket) {
@@ -6842,12 +7081,15 @@
6842
7081
  bucket.push(particle);
6843
7082
  this.#particleBuckets.set(particle.id, bucketIndex);
6844
7083
  }
6845
- #removeParticle(index, group, override) {
7084
+ #removeAny(quantity) {
7085
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
7086
+ }
7087
+ #removeParticle(index, group, override, matchGroup = true) {
6846
7088
  const particle = this.#array[index];
6847
7089
  if (!particle) {
6848
7090
  return false;
6849
7091
  }
6850
- if (particle.group !== group) {
7092
+ if (matchGroup && particle.group !== group) {
6851
7093
  return false;
6852
7094
  }
6853
7095
  this.#array.splice(index, deleteCount);
@@ -6934,7 +7176,7 @@
6934
7176
  particlesToDelete.add(particle);
6935
7177
  continue;
6936
7178
  }
6937
- this.grid.insert(particle);
7179
+ this.#grid.insert(particle);
6938
7180
  }
6939
7181
  return particlesToDelete;
6940
7182
  }
@@ -7021,6 +7263,7 @@
7021
7263
  started;
7022
7264
  zLayers;
7023
7265
  #delay;
7266
+ #delayResolve;
7024
7267
  #delayTimeout;
7025
7268
  #delta = { value: 0, factor: 0 };
7026
7269
  #dispatchCallback;
@@ -7110,7 +7353,6 @@
7110
7353
  this.shapeDrawers = new Map();
7111
7354
  this.particleUpdaters = [];
7112
7355
  this.plugins.length = 0;
7113
- this.#pluginManager.clearPlugins(this);
7114
7356
  this.destroyed = true;
7115
7357
  this.#onDestroy(remove);
7116
7358
  this.dispatchEvent(exports.EventType.containerDestroyed);
@@ -7163,31 +7405,14 @@
7163
7405
  await this.initDrawersAndUpdaters();
7164
7406
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
7165
7407
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
7166
- this.plugins.length = 0;
7167
- this.particleDestroyedPlugins.length = 0;
7168
- this.particleCreatedPlugins.length = 0;
7169
- this.particlePositionPlugins.length = 0;
7170
- for (const [plugin, containerPlugin] of allContainerPlugins) {
7171
- if (plugin.needsPlugin(this.actualOptions)) {
7172
- this.plugins.push(containerPlugin);
7173
- if (containerPlugin.particleCreated) {
7174
- this.particleCreatedPlugins.push(containerPlugin);
7175
- }
7176
- if (containerPlugin.particleDestroyed) {
7177
- this.particleDestroyedPlugins.push(containerPlugin);
7178
- }
7179
- if (containerPlugin.particlePosition) {
7180
- this.particlePositionPlugins.push(containerPlugin);
7181
- }
7182
- }
7183
- }
7408
+ this.#initPlugins(allContainerPlugins);
7184
7409
  this.retina.init();
7185
7410
  this.canvas.init();
7186
7411
  this.updateActualOptions();
7187
7412
  this.canvas.initBackground();
7188
7413
  this.canvas.resize();
7189
7414
  const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
7190
- this.hdrMode = hdrOptions.mode;
7415
+ this.hdrMode = toEnumValue(exports.HdrMode, hdrOptions.mode, exports.HdrMode.standard);
7191
7416
  this.peakNits = hdrOptions.peakNits;
7192
7417
  this.zLayers = zLayers;
7193
7418
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
@@ -7208,9 +7433,9 @@
7208
7433
  }
7209
7434
  async initDrawersAndUpdaters() {
7210
7435
  const pluginManager = this.#pluginManager;
7211
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
7212
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
7213
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
7436
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
7437
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
7438
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
7214
7439
  }
7215
7440
  pause() {
7216
7441
  if (!guardCheck(this)) {
@@ -7277,7 +7502,10 @@
7277
7502
  await this.init();
7278
7503
  this.started = true;
7279
7504
  await new Promise(resolve => {
7505
+ this.#delayResolve = resolve;
7280
7506
  const start = async () => {
7507
+ this.#delayTimeout = undefined;
7508
+ this.#delayResolve = undefined;
7281
7509
  this.#eventListeners.addListeners();
7282
7510
  for (const plugin of this.plugins) {
7283
7511
  await plugin.start?.();
@@ -7293,9 +7521,11 @@
7293
7521
  if (!guardCheck(this) || !this.started) {
7294
7522
  return;
7295
7523
  }
7296
- if (this.#delayTimeout) {
7524
+ if (this.#delayTimeout !== undefined) {
7297
7525
  clearTimeout(this.#delayTimeout);
7298
7526
  this.#delayTimeout = undefined;
7527
+ this.#delayResolve?.();
7528
+ this.#delayResolve = undefined;
7299
7529
  }
7300
7530
  this.#firstStart = true;
7301
7531
  this.started = false;
@@ -7321,6 +7551,27 @@
7321
7551
  }
7322
7552
  return refresh;
7323
7553
  }
7554
+ #initPlugins(allContainerPlugins) {
7555
+ this.plugins.length = 0;
7556
+ this.particleDestroyedPlugins.length = 0;
7557
+ this.particleCreatedPlugins.length = 0;
7558
+ this.particlePositionPlugins.length = 0;
7559
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
7560
+ if (!plugin.needsPlugin(this.actualOptions)) {
7561
+ continue;
7562
+ }
7563
+ this.plugins.push(containerPlugin);
7564
+ if (containerPlugin.particleCreated) {
7565
+ this.particleCreatedPlugins.push(containerPlugin);
7566
+ }
7567
+ if (containerPlugin.particleDestroyed) {
7568
+ this.particleDestroyedPlugins.push(containerPlugin);
7569
+ }
7570
+ if (containerPlugin.particlePosition) {
7571
+ this.particlePositionPlugins.push(containerPlugin);
7572
+ }
7573
+ }
7574
+ }
7324
7575
  #nextFrame(timestamp) {
7325
7576
  try {
7326
7577
  if (!this.#smooth &&
@@ -7627,11 +7878,11 @@
7627
7878
  }
7628
7879
  }
7629
7880
  async #init() {
7630
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
7631
- if (!availablePathGenerators) {
7881
+ const pluginManager = this.#pluginManager;
7882
+ if (!pluginManager.initializers.pathGenerators) {
7632
7883
  return;
7633
7884
  }
7634
- this.availablePathGenerators = availablePathGenerators;
7885
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
7635
7886
  this.pathGenerators = new Map();
7636
7887
  for (const pathGenerator of this.pathGenerators.values()) {
7637
7888
  pathGenerator.init();
@@ -7644,55 +7895,6 @@
7644
7895
  MovePluginInstance: MovePluginInstance
7645
7896
  });
7646
7897
 
7647
- class EmittersPluginInstance {
7648
- #container;
7649
- #instancesManager;
7650
- constructor(instancesManager, container) {
7651
- this.#instancesManager = instancesManager;
7652
- this.#container = container;
7653
- this.#instancesManager.initContainer(container);
7654
- }
7655
- async init() {
7656
- const emittersOptions = this.#container.actualOptions.emitters;
7657
- if (isArray(emittersOptions)) {
7658
- for (const emitterOptions of emittersOptions) {
7659
- await this.#instancesManager.addEmitter(this.#container, emitterOptions);
7660
- }
7661
- }
7662
- else {
7663
- await this.#instancesManager.addEmitter(this.#container, emittersOptions);
7664
- }
7665
- }
7666
- pause() {
7667
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
7668
- emitter.pause();
7669
- }
7670
- }
7671
- play() {
7672
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
7673
- emitter.play();
7674
- }
7675
- }
7676
- resize() {
7677
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
7678
- emitter.resize();
7679
- }
7680
- }
7681
- stop() {
7682
- this.#instancesManager.clear(this.#container);
7683
- }
7684
- update(delta) {
7685
- this.#instancesManager.getArray(this.#container).forEach(emitter => {
7686
- emitter.update(delta);
7687
- });
7688
- }
7689
- }
7690
-
7691
- var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
7692
- __proto__: null,
7693
- EmittersPluginInstance: EmittersPluginInstance
7694
- });
7695
-
7696
7898
  const shapeGenerators = new Map();
7697
7899
  class ShapeManager {
7698
7900
  addShapeGenerator(name, generator) {
@@ -7722,14 +7924,21 @@
7722
7924
  this.#pluginManager = pluginManager;
7723
7925
  }
7724
7926
  async addEmitter(container, options, position) {
7725
- const emitterOptions = new Emitter();
7726
- emitterOptions.load(options);
7727
- const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
7728
- this.removeEmitter(container, emitter);
7729
- }, emitterOptions, position);
7730
- await emitter.init();
7731
- this.getArray(container).push(emitter);
7732
- return emitter;
7927
+ return this.addEmitters(container, [{ options, position }]).then(t => t[defaultIndex]);
7928
+ }
7929
+ async addEmitters(container, emitters) {
7930
+ const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), res = [];
7931
+ for (const { options, position } of emitters) {
7932
+ const emitterOptions = new Emitter();
7933
+ emitterOptions.load(options);
7934
+ const emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
7935
+ this.removeEmitter(container, emitter);
7936
+ }, emitterOptions, position);
7937
+ await emitter.init();
7938
+ this.getArray(container).push(emitter);
7939
+ res.push(emitter);
7940
+ }
7941
+ return res;
7733
7942
  }
7734
7943
  clear(container) {
7735
7944
  this.initContainer(container);
@@ -7756,6 +7965,7 @@
7756
7965
  : array.find(t => t.name === idxOrName);
7757
7966
  };
7758
7967
  container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
7968
+ container.addEmitters = async (emitters) => this.addEmitters(container, emitters);
7759
7969
  container.removeEmitter = (idxOrName) => {
7760
7970
  const emitter = container.getEmitter?.(idxOrName);
7761
7971
  if (emitter) {
@@ -7776,7 +7986,7 @@
7776
7986
  };
7777
7987
  }
7778
7988
  removeEmitter(container, emitter) {
7779
- const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
7989
+ const index = this.getArray(container).indexOf(emitter), deleteCount = 1;
7780
7990
  if (index >= minIndex) {
7781
7991
  this.getArray(container).splice(index, deleteCount);
7782
7992
  }
@@ -8281,6 +8491,7 @@
8281
8491
  #particlesOptions;
8282
8492
  #paused;
8283
8493
  #pluginManager;
8494
+ #positionOverride = false;
8284
8495
  #removeCallback;
8285
8496
  #resizeObserver;
8286
8497
  #shape;
@@ -8357,6 +8568,31 @@
8357
8568
  });
8358
8569
  this.play();
8359
8570
  }
8571
+ draw(context) {
8572
+ if (!this.options.draw || !this.#shape) {
8573
+ return;
8574
+ }
8575
+ const container = this.#container, fillEnabled = this.options.spawn.fill?.enable ?? true;
8576
+ context.save();
8577
+ context.beginPath();
8578
+ if (fillEnabled) {
8579
+ context.fillStyle = this.spawnFillColor
8580
+ ? getStyleFromHsl(this.spawnFillColor, container.hdr, this.spawnFillOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode)
8581
+ : getStyleFromRgb({ r: 0, g: 0, b: 0 }, container.hdr, defaultOpacity$1, container.peakNits, container.hdrMode);
8582
+ }
8583
+ if (this.spawnStrokeColor) {
8584
+ context.strokeStyle = getStyleFromHsl(this.spawnStrokeColor, container.hdr, this.spawnStrokeOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode);
8585
+ context.lineWidth = this.spawnStrokeWidth ?? defaultStrokeWidth;
8586
+ }
8587
+ this.#shape.draw?.(context);
8588
+ if (fillEnabled) {
8589
+ context.fill();
8590
+ }
8591
+ if (this.spawnStrokeColor) {
8592
+ context.stroke();
8593
+ }
8594
+ context.restore();
8595
+ }
8360
8596
  externalPause() {
8361
8597
  this.#paused = true;
8362
8598
  this.pause();
@@ -8394,11 +8630,14 @@
8394
8630
  }
8395
8631
  }
8396
8632
  resize() {
8397
- const initialPosition = this.#initialPosition, container = this.#container;
8398
- this.position =
8399
- initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
8400
- ? initialPosition
8401
- : this.#calcPosition();
8633
+ const container = this.#container;
8634
+ if (!this.#positionOverride) {
8635
+ const initialPosition = this.#initialPosition;
8636
+ this.position =
8637
+ initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
8638
+ ? initialPosition
8639
+ : this.#calcPosition();
8640
+ }
8402
8641
  this.#size = this.#calcSize();
8403
8642
  this.size =
8404
8643
  this.#size.mode === exports.PixelMode.percent
@@ -8409,6 +8648,11 @@
8409
8648
  : { width: this.#size.width, height: this.#size.height };
8410
8649
  this.#shape?.resize(this.position, this.size);
8411
8650
  }
8651
+ setPosition(position) {
8652
+ this.#positionOverride = true;
8653
+ this.position = { ...position };
8654
+ this.#shape?.resize(this.position, this.size);
8655
+ }
8412
8656
  update(delta) {
8413
8657
  if (this.#paused) {
8414
8658
  return;
@@ -8434,8 +8678,10 @@
8434
8678
  this.#lifeCount--;
8435
8679
  }
8436
8680
  if (this.#lifeCount > minLifeCount || this.#immortal) {
8437
- this.position = this.#calcPosition();
8438
- this.#shape?.resize(this.position, this.size);
8681
+ if (!this.#positionOverride) {
8682
+ this.position = this.#calcPosition();
8683
+ this.#shape?.resize(this.position, this.size);
8684
+ }
8439
8685
  this.#spawnDelay = container.retina.reduceFactor
8440
8686
  ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
8441
8687
  container.retina.reduceFactor
@@ -8608,6 +8854,7 @@
8608
8854
  exports.BaseRange = BaseRange;
8609
8855
  exports.Circle = Circle;
8610
8856
  exports.ColorAnimation = ColorAnimation;
8857
+ exports.ErrorCodes = ErrorCodes$2;
8611
8858
  exports.Fill = Fill;
8612
8859
  exports.FullScreen = FullScreen;
8613
8860
  exports.HDROptions = HDROptions;
@@ -8639,6 +8886,7 @@
8639
8886
  exports.Vector = Vector;
8640
8887
  exports.Vector3d = Vector3d;
8641
8888
  exports.ZIndex = ZIndex;
8889
+ exports.addErrorMessages = addErrorMessages;
8642
8890
  exports.alterHsl = alterHsl;
8643
8891
  exports.animate = animate;
8644
8892
  exports.areBoundsInside = areBoundsInside;
@@ -8661,7 +8909,7 @@
8661
8909
  exports.countOffset = countOffset;
8662
8910
  exports.decayOffset = decayOffset;
8663
8911
  exports.deepExtend = deepExtend;
8664
- exports.defaultAlpha = defaultAlpha$1;
8912
+ exports.defaultAlpha = defaultAlpha;
8665
8913
  exports.defaultAngle = defaultAngle;
8666
8914
  exports.defaultCompositeValue = defaultCompositeValue;
8667
8915
  exports.defaultDensityFactor = defaultDensityFactor;
@@ -8686,12 +8934,17 @@
8686
8934
  exports.empty = empty;
8687
8935
  exports.executeOnSingleOrMultiple = executeOnSingleOrMultiple;
8688
8936
  exports.fireworks = fireworks;
8937
+ exports.fullPercent = fullPercent;
8689
8938
  exports.generatedAttribute = generatedAttribute;
8690
8939
  exports.generatedFalse = generatedFalse;
8691
8940
  exports.generatedTrue = generatedTrue;
8941
+ exports.getCanvasFromContainer = getCanvasFromContainer;
8942
+ exports.getDataFromUrl = getDataFromUrl;
8692
8943
  exports.getDistance = getDistance;
8693
8944
  exports.getDistanceSq = getDistanceSq;
8694
8945
  exports.getDistances = getDistances;
8946
+ exports.getDomContainer = getDomContainer;
8947
+ exports.getErrorMessage = getErrorMessage;
8695
8948
  exports.getFullScreenStyle = getFullScreenStyle;
8696
8949
  exports.getHslAnimationFromHsl = getHslAnimationFromHsl;
8697
8950
  exports.getHslFromAnimation = getHslFromAnimation;
@@ -8723,6 +8976,7 @@
8723
8976
  exports.inverseFactorNumerator = inverseFactorNumerator;
8724
8977
  exports.isArray = isArray;
8725
8978
  exports.isBoolean = isBoolean;
8979
+ exports.isEnumValue = isEnumValue;
8726
8980
  exports.isFunction = isFunction;
8727
8981
  exports.isInArray = isInArray;
8728
8982
  exports.isNull = isNull;
@@ -8755,7 +9009,7 @@
8755
9009
  exports.minFpsLimit = minFpsLimit;
8756
9010
  exports.minIndex = minIndex;
8757
9011
  exports.minLimit = minLimit;
8758
- exports.minRadius = minRadius$1;
9012
+ exports.minRadius = minRadius;
8759
9013
  exports.minStrokeWidth = minStrokeWidth;
8760
9014
  exports.minVelocity = minVelocity;
8761
9015
  exports.minZ = minZ;
@@ -8793,6 +9047,7 @@
8793
9047
  exports.stringToAlpha = stringToAlpha;
8794
9048
  exports.stringToRgb = stringToRgb;
8795
9049
  exports.threeQuarter = threeQuarter;
9050
+ exports.toEnumValue = toEnumValue;
8796
9051
  exports.triple = triple;
8797
9052
  exports.tryCountIncrement = tryCountIncrement;
8798
9053
  exports.tsParticles = tsParticles;
@@ -8801,6 +9056,7 @@
8801
9056
  exports.visibilityChangeEvent = visibilityChangeEvent;
8802
9057
  exports.zIndexFactorOffset = zIndexFactorOffset;
8803
9058
 
8804
- }));
9059
+ })(g.__tsParticlesInternals.bundles.fireworks = g.__tsParticlesInternals.bundles.fireworks || {});
9060
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
9061
+
8805
9062
  Object.assign(globalThis.window || globalThis, { fireworks: (globalThis.__tsParticlesInternals.bundles.fireworks || {}).fireworks });
8806
- delete (globalThis.window || globalThis).tsparticlesInternalExports;