@tsparticles/preset-confetti-explosions 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,35 @@
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
- /* Preset 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.presets = global.__tsParticlesInternals.presets || {}, global.__tsParticlesInternals.presets.confettiExplosions = global.__tsParticlesInternals.presets.confettiExplosions || {})));
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", double = 2, doublePI = Math.PI * double, defaultFps = 60, 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, 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, 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
+ /* Preset v4.5.1 */
4
+ g.__tsParticlesInternals = g.__tsParticlesInternals || {};
5
+ g.__tsParticlesInternals.presets = g.__tsParticlesInternals.presets || {};
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 getLogger() {
31
+ return _logger;
32
+ }
19
33
 
20
34
  var MoveDirection;
21
35
  (function (MoveDirection) {
@@ -32,6 +46,17 @@
32
46
  MoveDirection["inside"] = "inside";
33
47
  })(MoveDirection || (MoveDirection = {}));
34
48
 
49
+ const generatedAttribute = "generated", fullPercent = "100%", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
50
+ x: 0,
51
+ y: 0,
52
+ z: 0,
53
+ }, defaultTransform = {
54
+ a: 1,
55
+ b: 0,
56
+ c: 0,
57
+ d: 1,
58
+ }, randomColorValue = "random", 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, 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;
59
+
35
60
  function getZ(source) {
36
61
  return "z" in source ? source.z : originPoint.z;
37
62
  }
@@ -147,6 +172,12 @@
147
172
  function isNumber(arg) {
148
173
  return typeof arg === "number";
149
174
  }
175
+ function isEnumValue(enumObject, arg) {
176
+ return Object.values(enumObject).some(enumValue => enumValue === arg);
177
+ }
178
+ function toEnumValue(enumObject, arg, defaultValue) {
179
+ return isEnumValue(enumObject, arg) ? arg : defaultValue;
180
+ }
150
181
  function isObject(arg) {
151
182
  return typeof arg === "object" && arg !== null;
152
183
  }
@@ -283,11 +314,61 @@
283
314
  };
284
315
  }
285
316
  function parseAlpha(input) {
286
- const defaultAlpha = 1;
287
317
  if (!input) {
288
318
  return defaultAlpha;
289
319
  }
290
- return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
320
+ return input.endsWith("%") ? Number.parseFloat(input) / percentDenominator : Number.parseFloat(input);
321
+ }
322
+
323
+ const ErrorCodes$2 = {
324
+ engineVersionMismatch: "TSP-1001",
325
+ particlePositionNotFound: "TSP-1002",
326
+ pluginRegisterAfterLoad: "TSP-1003",
327
+ offscreenCanvasUnsupported: "TSP-1101",
328
+ offscreenCanvasTransferFailed: "TSP-1102",
329
+ hdrEnableInvalid: "TSP-1201",
330
+ hdrModeInvalid: "TSP-1202",
331
+ hdrPeakNitsInvalid: "TSP-1203",
332
+ };
333
+
334
+ const messages = {
335
+ [ErrorCodes$2.engineVersionMismatch]: "The tsParticles version is different from the loaded plugins version. Engine version: {0}. Plugin version: {1}",
336
+ [ErrorCodes$2.particlePositionNotFound]: "a valid position cannot be found for particle",
337
+ [ErrorCodes$2.pluginRegisterAfterLoad]: "Register plugins can only be done before calling tsParticles.load()",
338
+ [ErrorCodes$2.offscreenCanvasUnsupported]: "OffscreenCanvas is required but not supported by this browser",
339
+ [ErrorCodes$2.offscreenCanvasTransferFailed]: "OffscreenCanvas transfer failed",
340
+ [ErrorCodes$2.hdrEnableInvalid]: 'Invalid HDR "enable" value: expected a boolean, got "{0}"',
341
+ [ErrorCodes$2.hdrModeInvalid]: 'Invalid HDR "mode" value: expected one of {0}, got "{1}"',
342
+ [ErrorCodes$2.hdrPeakNitsInvalid]: 'Invalid HDR "peakNits" value: expected a positive number, got "{0}"',
343
+ };
344
+
345
+ let registeredMessages;
346
+ const ensureRegisteredMessages = () => {
347
+ registeredMessages ??= new Map(Object.entries(messages));
348
+ return registeredMessages;
349
+ }, toStringValue$1 = (value) => String(value), format = (template, args) => {
350
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
351
+ const arg = args[Number(index)];
352
+ return arg === undefined ? match : toStringValue$1(arg);
353
+ });
354
+ };
355
+ function addErrorMessages(extraMessages) {
356
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
357
+ return;
358
+ }
359
+ const catalog = ensureRegisteredMessages();
360
+ for (const [code, message] of Object.entries(extraMessages)) {
361
+ if (message !== undefined) {
362
+ catalog.set(code, message);
363
+ }
364
+ }
365
+ }
366
+ function getErrorMessage(code, ...args) {
367
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
368
+ return `[tsParticles Error ${code}] https://particles.js.org/errors/#${code}`;
369
+ }
370
+ const template = ensureRegisteredMessages().get(code) ?? `Unknown error code ${code}`;
371
+ return format(template, args);
291
372
  }
292
373
 
293
374
  var OutModeDirection;
@@ -304,7 +385,6 @@
304
385
  PixelMode["percent"] = "percent";
305
386
  })(PixelMode || (PixelMode = {}));
306
387
 
307
- const minRadius = 0;
308
388
  function isForbiddenKey(key) {
309
389
  return key === "__proto__" || key === "constructor" || key === "prototype";
310
390
  }
@@ -500,22 +580,84 @@
500
580
  element.removeEventListener(event, handler, removeOptions);
501
581
  }
502
582
  }
503
- async function getItemsFromInitializer(container, map, initializers, force = false) {
504
- let res = map.get(container);
505
- if (!res || force) {
506
- res = await Promise.all([...initializers.values()].map(t => t(container)));
507
- map.set(container, res);
583
+ async function getItemsFromInitializer(container, initializers) {
584
+ return await Promise.all([...initializers.values()].map(t => t(container)));
585
+ }
586
+ async function getItemMapFromInitializer(container, initializers) {
587
+ const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
588
+ return new Map(entries);
589
+ }
590
+ async function getDataFromUrl(data) {
591
+ const url = itemFromSingleOrMultiple(data.url, data.index);
592
+ if (!url) {
593
+ return data.fallback;
508
594
  }
509
- return res;
595
+ try {
596
+ const response = await fetch(url);
597
+ if (response.ok) {
598
+ const current = (await response.json());
599
+ if (isSourceOptionsValue(current)) {
600
+ return current;
601
+ }
602
+ getLogger().error("invalid configuration data while retrieving config file");
603
+ }
604
+ else {
605
+ getLogger().error(`${response.status.toString()} while retrieving config file`);
606
+ }
607
+ }
608
+ catch (error) {
609
+ getLogger().error(`error while retrieving config file: ${error}`);
610
+ }
611
+ return data.fallback;
510
612
  }
511
- async function getItemMapFromInitializer(container, map, initializers, force = false) {
512
- let res = map.get(container);
513
- if (!res || force) {
514
- const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
515
- res = new Map(entries);
516
- map.set(container, res);
613
+ function isSourceOptionsValue(value) {
614
+ if (isArray(value)) {
615
+ return value.every((entry) => isObject(entry) && !isArray(entry));
517
616
  }
518
- return res;
617
+ return isObject(value) && !isArray(value);
618
+ }
619
+ function getCanvasFromContainer(domContainer) {
620
+ let canvasEl;
621
+ const documentSafe = safeDocument(), isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
622
+ if (isCanvas) {
623
+ canvasEl = domContainer;
624
+ canvasEl.dataset[generatedAttribute] ??= generatedFalse;
625
+ if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
626
+ canvasEl.style.width ||= fullPercent;
627
+ canvasEl.style.height ||= fullPercent;
628
+ canvasEl.style.pointerEvents = "none";
629
+ canvasEl.style.setProperty("pointer-events", "none");
630
+ }
631
+ }
632
+ else {
633
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
634
+ if (foundCanvas) {
635
+ canvasEl = foundCanvas;
636
+ canvasEl.dataset[generatedAttribute] = generatedFalse;
637
+ }
638
+ else {
639
+ canvasEl = documentSafe.createElement(canvasTag);
640
+ canvasEl.dataset[generatedAttribute] = generatedTrue;
641
+ domContainer.appendChild(canvasEl);
642
+ }
643
+ canvasEl.style.width ||= fullPercent;
644
+ canvasEl.style.height ||= fullPercent;
645
+ canvasEl.style.pointerEvents = "none";
646
+ canvasEl.style.setProperty("pointer-events", "none");
647
+ }
648
+ return canvasEl;
649
+ }
650
+ function getDomContainer(id, source) {
651
+ const documentSafe = safeDocument();
652
+ let domContainer = source ?? documentSafe.getElementById(id);
653
+ if (domContainer) {
654
+ return domContainer;
655
+ }
656
+ domContainer = documentSafe.createElement("canvas");
657
+ domContainer.id = id;
658
+ domContainer.dataset[generatedAttribute] = generatedTrue;
659
+ documentSafe.body.append(domContainer);
660
+ return domContainer;
519
661
  }
520
662
 
521
663
  class EventDispatcher {
@@ -525,12 +667,8 @@
525
667
  }
526
668
  addEventListener(type, listener) {
527
669
  this.removeEventListener(type, listener);
528
- let arr = this.#listeners.get(type);
529
- if (!arr) {
530
- arr = [];
531
- this.#listeners.set(type, arr);
532
- }
533
- arr.push(listener);
670
+ const arr = this.#listeners.get(type);
671
+ this.#listeners.set(type, arr ? [...arr, listener] : [listener]);
534
672
  }
535
673
  dispatchEvent(type, args) {
536
674
  const listeners = this.#listeners.get(type);
@@ -562,7 +700,7 @@
562
700
  this.#listeners.delete(type);
563
701
  }
564
702
  else {
565
- arr.splice(idx, deleteCount);
703
+ this.#listeners.set(type, [...arr.slice(minIndex, idx), ...arr.slice(idx + deleteCount)]);
566
704
  }
567
705
  }
568
706
  }
@@ -586,7 +724,6 @@
586
724
  class PluginManager {
587
725
  colorManagers = new Map();
588
726
  easingFunctions = new Map();
589
- effectDrawers = new Map();
590
727
  initializers = {
591
728
  effects: new Map(),
592
729
  shapes: new Map(),
@@ -595,8 +732,6 @@
595
732
  palettes = new Map();
596
733
  plugins = [];
597
734
  presets = new Map();
598
- shapeDrawers = new Map();
599
- updaters = new Map();
600
735
  #allLoadersSet = new Set();
601
736
  #configs = new Map();
602
737
  #engine;
@@ -614,57 +749,79 @@
614
749
  }
615
750
  return res;
616
751
  }
752
+ get initialized() {
753
+ return this.#initialized;
754
+ }
617
755
  addColorManager(name, manager) {
756
+ if (this.#initialized) {
757
+ return;
758
+ }
618
759
  this.colorManagers.set(name, manager);
619
760
  }
620
761
  addConfig(config) {
762
+ if (this.#initialized) {
763
+ return;
764
+ }
621
765
  const key = config.key ?? config.name ?? "default";
622
766
  this.#configs.set(key, config);
623
767
  this.#engine.dispatchEvent(EventType.configAdded, { data: { name: key, config } });
624
768
  }
625
769
  addEasing(name, easing) {
770
+ if (this.#initialized) {
771
+ return;
772
+ }
626
773
  if (this.easingFunctions.get(name)) {
627
774
  return;
628
775
  }
629
776
  this.easingFunctions.set(name, easing);
630
777
  }
631
778
  addEffect(effect, drawer) {
779
+ if (this.#initialized) {
780
+ return;
781
+ }
632
782
  this.initializers.effects.set(effect, drawer);
633
783
  }
634
784
  addPalette(name, palette) {
785
+ if (this.#initialized) {
786
+ return;
787
+ }
635
788
  this.palettes.set(name, palette);
636
789
  }
637
790
  addParticleUpdater(name, updaterInitializer) {
791
+ if (this.#initialized) {
792
+ return;
793
+ }
638
794
  this.initializers.updaters.set(name, updaterInitializer);
639
795
  }
640
796
  addPlugin(plugin) {
797
+ if (this.#initialized) {
798
+ return;
799
+ }
641
800
  if (this.getPlugin(plugin.id)) {
642
801
  return;
643
802
  }
644
803
  this.plugins.push(plugin);
645
804
  }
646
805
  addPreset(preset, options, override = false) {
806
+ if (this.#initialized) {
807
+ return;
808
+ }
647
809
  if (!(override || !this.getPreset(preset))) {
648
810
  return;
649
811
  }
650
812
  this.presets.set(preset, options);
651
813
  }
652
814
  addShape(shapes, drawer) {
815
+ if (this.#initialized) {
816
+ return;
817
+ }
653
818
  for (const shape of shapes) {
654
819
  this.initializers.shapes.set(shape, drawer);
655
820
  }
656
821
  }
657
- clearPlugins(container) {
658
- this.effectDrawers.delete(container);
659
- this.shapeDrawers.delete(container);
660
- this.updaters.delete(container);
661
- }
662
822
  getEasing(name) {
663
823
  return this.easingFunctions.get(name) ?? ((value) => value);
664
824
  }
665
- getEffectDrawers(container, force = false) {
666
- return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
667
- }
668
825
  getPalette(name) {
669
826
  return this.palettes.get(name);
670
827
  }
@@ -674,12 +831,6 @@
674
831
  getPreset(preset) {
675
832
  return this.presets.get(preset);
676
833
  }
677
- async getShapeDrawers(container, force = false) {
678
- return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
679
- }
680
- async getUpdaters(container, force = false) {
681
- return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
682
- }
683
834
  async init() {
684
835
  if (this.#initialized || this.#isRunningLoaders) {
685
836
  return;
@@ -698,16 +849,9 @@
698
849
  this.#initialized = true;
699
850
  }
700
851
  }
701
- loadParticlesOptions(container, options, ...sourceOptions) {
702
- const updaters = this.updaters.get(container);
703
- if (!updaters) {
704
- return;
705
- }
706
- updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
707
- }
708
852
  async register(...loaders) {
709
853
  if (this.#initialized) {
710
- throw new Error("Register plugins can only be done before calling tsParticles.load()");
854
+ throw new Error(getErrorMessage(ErrorCodes$2.pluginRegisterAfterLoad));
711
855
  }
712
856
  for (const loader of loaders) {
713
857
  if (this.#isRunningLoaders) {
@@ -719,88 +863,15 @@
719
863
  }
720
864
  }
721
865
  async #runLoader(loader, executed, allLoaders) {
722
- if (executed.has(loader))
866
+ if (executed.has(loader)) {
723
867
  return;
868
+ }
724
869
  executed.add(loader);
725
870
  allLoaders.add(loader);
726
871
  await loader(this.#engine);
727
872
  }
728
873
  }
729
874
 
730
- const errorPrefix = "tsParticles - Error";
731
- const wrap = (fn) => (...args) => {
732
- fn(...args);
733
- }, _logger = {
734
- debug: wrap(console.debug),
735
- error: (message, ...optionalParams) => {
736
- console.error(`${errorPrefix} - ${message}`, ...optionalParams);
737
- },
738
- info: wrap(console.info),
739
- log: wrap(console.log),
740
- trace: wrap(console.trace),
741
- verbose: wrap(console.log),
742
- warning: wrap(console.warn),
743
- };
744
- function getLogger() {
745
- return _logger;
746
- }
747
-
748
- const fullPercent = "100%";
749
- async function getDataFromUrl(data) {
750
- const url = itemFromSingleOrMultiple(data.url, data.index);
751
- if (!url) {
752
- return data.fallback;
753
- }
754
- const response = await fetch(url);
755
- if (response.ok) {
756
- return (await response.json());
757
- }
758
- getLogger().error(`${response.status.toString()} while retrieving config file`);
759
- return data.fallback;
760
- }
761
- const getCanvasFromContainer = (domContainer) => {
762
- const documentSafe = safeDocument();
763
- let canvasEl;
764
- const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
765
- if (isCanvas) {
766
- canvasEl = domContainer;
767
- canvasEl.dataset[generatedAttribute] ??= generatedFalse;
768
- if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
769
- canvasEl.style.width ||= fullPercent;
770
- canvasEl.style.height ||= fullPercent;
771
- canvasEl.style.pointerEvents = "none";
772
- canvasEl.style.setProperty("pointer-events", "none");
773
- }
774
- }
775
- else {
776
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
777
- if (foundCanvas) {
778
- canvasEl = foundCanvas;
779
- canvasEl.dataset[generatedAttribute] = generatedFalse;
780
- }
781
- else {
782
- canvasEl = documentSafe.createElement(canvasTag);
783
- canvasEl.dataset[generatedAttribute] = generatedTrue;
784
- domContainer.appendChild(canvasEl);
785
- }
786
- canvasEl.style.width ||= fullPercent;
787
- canvasEl.style.height ||= fullPercent;
788
- canvasEl.style.pointerEvents = "none";
789
- canvasEl.style.setProperty("pointer-events", "none");
790
- }
791
- return canvasEl;
792
- }, getDomContainer = (id, source) => {
793
- const documentSafe = safeDocument();
794
- let domContainer = source ?? documentSafe.getElementById(id);
795
- if (domContainer) {
796
- return domContainer;
797
- }
798
- domContainer = documentSafe.createElement("canvas");
799
- domContainer.id = id;
800
- domContainer.dataset[generatedAttribute] = generatedTrue;
801
- documentSafe.body.append(domContainer);
802
- return domContainer;
803
- };
804
875
  class Engine {
805
876
  pluginManager = new PluginManager(this);
806
877
  #domArray = [];
@@ -810,7 +881,7 @@
810
881
  return this.#domArray;
811
882
  }
812
883
  get version() {
813
- return "4.4.0";
884
+ return "4.5.1";
814
885
  }
815
886
  addEventListener(type, listener) {
816
887
  this.#eventDispatcher.addEventListener(type, listener);
@@ -819,7 +890,7 @@
819
890
  if (this.version === pluginVersion) {
820
891
  return;
821
892
  }
822
- throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
893
+ throw new Error(getErrorMessage(ErrorCodes$2.engineVersionMismatch, this.version, pluginVersion));
823
894
  }
824
895
  dispatchEvent(type, args) {
825
896
  this.#eventDispatcher.dispatchEvent(type, args);
@@ -1068,20 +1139,6 @@
1068
1139
  DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1069
1140
  })(DrawLayer || (DrawLayer = {}));
1070
1141
 
1071
- class OptionLoader {
1072
- load(data) {
1073
- if (isNull(data)) {
1074
- return;
1075
- }
1076
- this.doLoad(data);
1077
- }
1078
- }
1079
- function loadOptions(options, ...sourceOptionsArr) {
1080
- for (const sourceOptions of sourceOptionsArr) {
1081
- options.load(sourceOptions);
1082
- }
1083
- }
1084
-
1085
1142
  function loadProperty(obj, key, value) {
1086
1143
  if (value !== undefined) {
1087
1144
  obj[key] = value;
@@ -1113,6 +1170,20 @@
1113
1170
  }
1114
1171
  }
1115
1172
 
1173
+ class OptionLoader {
1174
+ load(data) {
1175
+ if (isNull(data)) {
1176
+ return;
1177
+ }
1178
+ this.doLoad(data);
1179
+ }
1180
+ }
1181
+ function loadOptions(options, ...sourceOptionsArr) {
1182
+ for (const sourceOptions of sourceOptionsArr) {
1183
+ options.load(sourceOptions);
1184
+ }
1185
+ }
1186
+
1116
1187
  class AnimationOptions extends OptionLoader {
1117
1188
  count = 0;
1118
1189
  decay = 0;
@@ -1263,15 +1334,14 @@
1263
1334
  peakNits = defaultPeakNits;
1264
1335
  doLoad(data) {
1265
1336
  if (data.enable !== undefined && !isBoolean(data.enable)) {
1266
- throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1337
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrEnableInvalid, String(data.enable)));
1267
1338
  }
1268
- if (data.mode !== undefined &&
1269
- (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1270
- throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1339
+ if (data.mode !== undefined && !isEnumValue(HdrMode, data.mode)) {
1340
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrModeInvalid, Object.values(HdrMode).join(", "), toStringValue(data.mode)));
1271
1341
  }
1272
1342
  if (data.peakNits !== undefined &&
1273
1343
  (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1274
- throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1344
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrPeakNitsInvalid, String(data.peakNits)));
1275
1345
  }
1276
1346
  loadProperty(this, "enable", data.enable);
1277
1347
  loadProperty(this, "mode", data.mode);
@@ -1649,12 +1719,10 @@
1649
1719
  plugin.loadParticlesOptions(this.#container, this, data);
1650
1720
  }
1651
1721
  }
1652
- const updaters = this.#pluginManager.updaters.get(this.#container);
1653
- if (updaters) {
1654
- for (const updater of updaters) {
1655
- if (updater.loadOptions) {
1656
- updater.loadOptions(this, data);
1657
- }
1722
+ const updaters = this.#container.particleUpdaters;
1723
+ for (const updater of updaters) {
1724
+ if (updater.loadOptions) {
1725
+ updater.loadOptions(this, data);
1658
1726
  }
1659
1727
  }
1660
1728
  }
@@ -1987,9 +2055,9 @@
1987
2055
  const grayscaleValue = Math.round(lNormalized * rgbMax);
1988
2056
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1989
2057
  }
1990
- const temp1 = lNormalized < half
2058
+ const temp2 = lNormalized < half
1991
2059
  ? lNormalized * (sNormalizedOffset + sNormalized)
1992
- : 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));
2060
+ : 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));
1993
2061
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1994
2062
  }
1995
2063
  function hslToRgbFloat(hsl) {
@@ -1998,9 +2066,9 @@
1998
2066
  const grayscaleValue = lNormalized * rgbMax;
1999
2067
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2000
2068
  }
2001
- const temp1 = lNormalized < half
2069
+ const temp2 = lNormalized < half
2002
2070
  ? lNormalized * (sNormalizedOffset + sNormalized)
2003
- : 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));
2071
+ : 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));
2004
2072
  return { r: red, g: green, b: blue };
2005
2073
  }
2006
2074
  function hslaToRgba(hsla) {
@@ -2214,7 +2282,7 @@
2214
2282
  }
2215
2283
 
2216
2284
  async function loadBlendPlugin(engine) {
2217
- engine.checkVersion("4.4.0");
2285
+ engine.checkVersion("4.5.1");
2218
2286
  await engine.pluginManager.register(e => {
2219
2287
  e.pluginManager.addPlugin(new BlendPlugin());
2220
2288
  });
@@ -2251,7 +2319,7 @@
2251
2319
  }
2252
2320
 
2253
2321
  async function loadCircleShape(engine) {
2254
- engine.checkVersion("4.4.0");
2322
+ engine.checkVersion("4.5.1");
2255
2323
  await engine.pluginManager.register(e => {
2256
2324
  e.pluginManager.addShape(["circle"], () => {
2257
2325
  return Promise.resolve(new CircleDrawer());
@@ -2266,7 +2334,7 @@
2266
2334
  RgbIndexes[RgbIndexes["b"] = 3] = "b";
2267
2335
  RgbIndexes[RgbIndexes["a"] = 4] = "a";
2268
2336
  })(RgbIndexes$1 || (RgbIndexes$1 = {}));
2269
- 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;
2337
+ 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;
2270
2338
  class HexColorManager {
2271
2339
  accepts(input) {
2272
2340
  return input.startsWith("#");
@@ -2299,7 +2367,7 @@
2299
2367
  }
2300
2368
 
2301
2369
  async function loadHexColorPlugin(engine) {
2302
- engine.checkVersion("4.4.0");
2370
+ engine.checkVersion("4.5.1");
2303
2371
  await engine.pluginManager.register(e => {
2304
2372
  e.pluginManager.addColorManager("hex", new HexColorManager());
2305
2373
  });
@@ -2339,7 +2407,7 @@
2339
2407
  if (!this.accepts(input)) {
2340
2408
  return;
2341
2409
  }
2342
- const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
2410
+ const result = hslRegex.exec(input), minLength = 4, radix = 10;
2343
2411
  return result
2344
2412
  ? hslaToRgba({
2345
2413
  a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
@@ -2352,12 +2420,20 @@
2352
2420
  }
2353
2421
 
2354
2422
  async function loadHslColorPlugin(engine) {
2355
- engine.checkVersion("4.4.0");
2423
+ engine.checkVersion("4.5.1");
2356
2424
  await engine.pluginManager.register(e => {
2357
2425
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2358
2426
  });
2359
2427
  }
2360
2428
 
2429
+ const ErrorCodes$1 = {
2430
+ baseMoverNotLoaded: "TSP-3203",
2431
+ };
2432
+
2433
+ const ErrorMessages$1 = {
2434
+ [ErrorCodes$1.baseMoverNotLoaded]: "tsParticles Base Mover is not loaded",
2435
+ };
2436
+
2361
2437
  class MovePlugin {
2362
2438
  id = "move";
2363
2439
  #pluginManager;
@@ -2376,20 +2452,20 @@
2376
2452
  }
2377
2453
 
2378
2454
  async function loadMovePlugin(engine) {
2379
- engine.checkVersion("4.4.0");
2455
+ engine.checkVersion("4.5.1");
2456
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
2457
+ addErrorMessages(ErrorMessages$1);
2458
+ }
2380
2459
  await engine.pluginManager.register(e => {
2381
2460
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2382
2461
  movePluginManager.initializers.pathGenerators ??= new Map();
2383
- movePluginManager.pathGenerators ??= new Map();
2384
2462
  movePluginManager.addPathGenerator = (name, generator) => {
2463
+ if (movePluginManager.initialized) {
2464
+ return;
2465
+ }
2385
2466
  movePluginManager.initializers.pathGenerators ??= new Map();
2386
2467
  movePluginManager.initializers.pathGenerators.set(name, generator);
2387
2468
  };
2388
- movePluginManager.getPathGenerators = async (container, force = false) => {
2389
- movePluginManager.initializers.pathGenerators ??= new Map();
2390
- movePluginManager.pathGenerators ??= new Map();
2391
- return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
2392
- };
2393
2469
  e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
2394
2470
  });
2395
2471
  }
@@ -2592,7 +2668,7 @@
2592
2668
  }
2593
2669
 
2594
2670
  async function loadOpacityUpdater(engine) {
2595
- engine.checkVersion("4.4.0");
2671
+ engine.checkVersion("4.5.1");
2596
2672
  await engine.pluginManager.register(e => {
2597
2673
  e.pluginManager.addParticleUpdater("opacity", container => {
2598
2674
  return Promise.resolve(new OpacityUpdater(container));
@@ -2601,70 +2677,60 @@
2601
2677
  }
2602
2678
 
2603
2679
  const boundsMin = 0;
2604
- function bounceHorizontal(data) {
2605
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2606
- (data.direction !== OutModeDirection.left && data.direction !== OutModeDirection.right)) {
2607
- return;
2608
- }
2609
- if (data.bounds.right < boundsMin && data.direction === OutModeDirection.left) {
2610
- data.particle.position.x = data.size + data.offset.x;
2611
- }
2612
- else if (data.bounds.left > data.canvasSize.width && data.direction === OutModeDirection.right) {
2613
- data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
2614
- }
2615
- const velocity = data.particle.velocity.x;
2616
- let bounced = false;
2617
- if (data.outOfCanvas &&
2618
- ((data.direction === OutModeDirection.right && velocity > minVelocity) ||
2619
- (data.direction === OutModeDirection.left && velocity < minVelocity))) {
2620
- const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
2621
- data.particle.velocity.x *= -newVelocity;
2622
- bounced = true;
2623
- }
2624
- if (!bounced) {
2625
- return;
2626
- }
2627
- const minPos = data.offset.x + data.size;
2628
- if (data.outOfCanvas && data.direction === OutModeDirection.right) {
2629
- data.particle.position.x = data.canvasSize.width - minPos;
2630
- }
2631
- else if (data.outOfCanvas && data.direction === OutModeDirection.left) {
2632
- data.particle.position.x = minPos;
2633
- }
2634
- if (data.outMode === OutMode.split) {
2635
- data.particle.destroy();
2636
- }
2637
- }
2638
- function bounceVertical(data) {
2639
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2640
- (data.direction !== OutModeDirection.bottom && data.direction !== OutModeDirection.top)) {
2680
+ const bounceAxisConfigs = {
2681
+ [OutModeDirection.left]: {
2682
+ axis: "x",
2683
+ canvas: "width",
2684
+ bounce: "horizontal",
2685
+ negativeEdge: "right",
2686
+ positiveEdge: "left",
2687
+ negative: true,
2688
+ },
2689
+ [OutModeDirection.right]: {
2690
+ axis: "x",
2691
+ canvas: "width",
2692
+ bounce: "horizontal",
2693
+ negativeEdge: "right",
2694
+ positiveEdge: "left",
2695
+ negative: false,
2696
+ },
2697
+ [OutModeDirection.top]: {
2698
+ axis: "y",
2699
+ canvas: "height",
2700
+ bounce: "vertical",
2701
+ negativeEdge: "bottom",
2702
+ positiveEdge: "top",
2703
+ negative: true,
2704
+ },
2705
+ [OutModeDirection.bottom]: {
2706
+ axis: "y",
2707
+ canvas: "height",
2708
+ bounce: "vertical",
2709
+ negativeEdge: "bottom",
2710
+ positiveEdge: "top",
2711
+ negative: false,
2712
+ },
2713
+ };
2714
+ function bounce(data) {
2715
+ if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) || !(data.direction in bounceAxisConfigs)) {
2641
2716
  return;
2642
2717
  }
2643
- if (data.bounds.bottom < boundsMin && data.direction === OutModeDirection.top) {
2644
- data.particle.position.y = data.size + data.offset.y;
2718
+ const config = bounceAxisConfigs[data.direction], bounds = data.bounds, canvasDim = data.canvasSize[config.canvas], position = data.particle.position, velocity = data.particle.velocity[config.axis];
2719
+ if (config.negative && bounds[config.negativeEdge] < boundsMin) {
2720
+ position[config.axis] = data.size + data.offset[config.axis];
2645
2721
  }
2646
- else if (data.bounds.top > data.canvasSize.height && data.direction === OutModeDirection.bottom) {
2647
- data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
2722
+ else if (!config.negative && bounds[config.positiveEdge] > canvasDim) {
2723
+ position[config.axis] = canvasDim - data.size - data.offset[config.axis];
2648
2724
  }
2649
- const velocity = data.particle.velocity.y;
2650
- let bounced = false;
2651
2725
  if (data.outOfCanvas &&
2652
- ((data.direction === OutModeDirection.bottom && velocity > minVelocity) ||
2653
- (data.direction === OutModeDirection.top && velocity < minVelocity))) {
2654
- const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
2655
- data.particle.velocity.y *= -newVelocity;
2656
- bounced = true;
2726
+ ((config.negative && velocity < minVelocity) || (!config.negative && velocity > minVelocity))) {
2727
+ data.particle.velocity[config.axis] *= -getRangeValue(data.particle.options.bounce[config.bounce].value);
2657
2728
  }
2658
- if (!bounced) {
2729
+ else {
2659
2730
  return;
2660
2731
  }
2661
- const minPos = data.offset.y + data.size;
2662
- if (data.outOfCanvas && data.direction === OutModeDirection.bottom) {
2663
- data.particle.position.y = data.canvasSize.height - minPos;
2664
- }
2665
- else if (data.outOfCanvas && data.direction === OutModeDirection.top) {
2666
- data.particle.position.y = minPos;
2667
- }
2732
+ const minPos = data.offset[config.axis] + data.size;
2733
+ position[config.axis] = config.negative ? minPos : canvasDim - minPos;
2668
2734
  if (data.outMode === OutMode.split) {
2669
2735
  data.particle.destroy();
2670
2736
  }
@@ -2680,26 +2746,19 @@
2680
2746
  OutMode.bounce,
2681
2747
  OutMode.split,
2682
2748
  ];
2683
- this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
2749
+ this.#particleBouncePlugins = container.plugins.filter(p => !!p.particleBounce);
2684
2750
  }
2685
2751
  update(particle, direction, delta, outMode) {
2686
2752
  if (!this.modes.includes(outMode)) {
2687
2753
  return;
2688
2754
  }
2689
- const container = this.#container;
2690
- let handled = false;
2691
2755
  for (const plugin of this.#particleBouncePlugins) {
2692
- handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
2693
- if (handled) {
2694
- break;
2756
+ if (plugin.particleBounce?.(particle, delta, direction)) {
2757
+ return;
2695
2758
  }
2696
2759
  }
2697
- if (handled) {
2698
- return;
2699
- }
2700
- const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2701
- bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2702
- bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2760
+ const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = this.#container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2761
+ bounce({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2703
2762
  }
2704
2763
  }
2705
2764
 
@@ -2788,108 +2847,109 @@
2788
2847
  return;
2789
2848
  }
2790
2849
  const container = this.#container;
2791
- switch (particle.outType) {
2792
- case ParticleOutType.inside: {
2793
- const { x: vx, y: vy } = particle.velocity;
2794
- updateVector.setTo(originPoint);
2795
- updateVector.length = particle.moveCenter.radius;
2796
- updateVector.angle = particle.velocity.angle + Math.PI;
2797
- updateVector.addTo(particle.moveCenter);
2798
- const { dx, dy } = getDistances(particle.position, updateVector);
2799
- if ((vx <= minVelocity && dx >= minDistance) ||
2800
- (vy <= minVelocity && dy >= minDistance) ||
2801
- (vx >= minVelocity && dx <= minDistance) ||
2802
- (vy >= minVelocity && dy <= minDistance)) {
2803
- return;
2804
- }
2805
- particle.position.x = Math.floor(randomInRangeValue({
2806
- min: 0,
2807
- max: container.canvas.size.width,
2808
- }));
2809
- particle.position.y = Math.floor(randomInRangeValue({
2810
- min: 0,
2811
- max: container.canvas.size.height,
2812
- }));
2813
- const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2814
- particle.direction = Math.atan2(-newDy, -newDx);
2815
- particle.velocity.angle = particle.direction;
2816
- particle.justWarped = true;
2817
- break;
2850
+ if (particle.outType === ParticleOutType.inside) {
2851
+ this.#applyOutModeInside(particle, container);
2852
+ }
2853
+ else {
2854
+ if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2855
+ return;
2818
2856
  }
2819
- default: {
2820
- if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2821
- return;
2822
- }
2823
- switch (particle.outType) {
2824
- case ParticleOutType.outside: {
2825
- particle.position.x =
2826
- Math.floor(randomInRangeValue({
2827
- min: -particle.moveCenter.radius,
2828
- max: particle.moveCenter.radius,
2829
- })) + particle.moveCenter.x;
2830
- particle.position.y =
2831
- Math.floor(randomInRangeValue({
2832
- min: -particle.moveCenter.radius,
2833
- max: particle.moveCenter.radius,
2834
- })) + particle.moveCenter.y;
2835
- const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2836
- if (particle.moveCenter.radius) {
2837
- particle.direction = Math.atan2(dy, dx);
2838
- particle.velocity.angle = particle.direction;
2839
- }
2840
- particle.justWarped = true;
2841
- break;
2842
- }
2843
- case ParticleOutType.normal: {
2844
- const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
2845
- bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
2846
- left: -particle.getRadius() - particle.offset.x,
2847
- right: canvasSize.width + particle.getRadius() + particle.offset.x,
2848
- top: -particle.getRadius() - particle.offset.y,
2849
- }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
2850
- if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2851
- particle.position.x = newPos.left;
2852
- particle.initialPosition.x = particle.position.x;
2853
- if (!warp) {
2854
- particle.position.y = getRandom() * canvasSize.height;
2855
- particle.initialPosition.y = particle.position.y;
2856
- }
2857
- particle.justWarped = true;
2858
- }
2859
- else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2860
- particle.position.x = newPos.right;
2861
- particle.initialPosition.x = particle.position.x;
2862
- if (!warp) {
2863
- particle.position.y = getRandom() * canvasSize.height;
2864
- particle.initialPosition.y = particle.position.y;
2865
- }
2866
- particle.justWarped = true;
2867
- }
2868
- if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2869
- if (!warp) {
2870
- particle.position.x = getRandom() * canvasSize.width;
2871
- particle.initialPosition.x = particle.position.x;
2872
- }
2873
- particle.position.y = newPos.top;
2874
- particle.initialPosition.y = particle.position.y;
2875
- particle.justWarped = true;
2876
- }
2877
- else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2878
- if (!warp) {
2879
- particle.position.x = getRandom() * canvasSize.width;
2880
- particle.initialPosition.x = particle.position.x;
2881
- }
2882
- particle.position.y = newPos.bottom;
2883
- particle.initialPosition.y = particle.position.y;
2884
- particle.justWarped = true;
2885
- }
2886
- break;
2887
- }
2888
- }
2889
- break;
2857
+ if (particle.outType === ParticleOutType.outside) {
2858
+ this.#applyParticleModeOutside(particle);
2859
+ }
2860
+ else {
2861
+ this.#applyOutModeNormal(particle, container, direction);
2890
2862
  }
2891
2863
  }
2892
2864
  }
2865
+ #applyOutModeInside(particle, container) {
2866
+ const { x: vx, y: vy } = particle.velocity;
2867
+ updateVector.setTo(originPoint);
2868
+ updateVector.length = particle.moveCenter.radius;
2869
+ updateVector.angle = particle.velocity.angle + Math.PI;
2870
+ updateVector.addTo(particle.moveCenter);
2871
+ const { dx, dy } = getDistances(particle.position, updateVector);
2872
+ if ((vx <= minVelocity && dx >= minDistance) ||
2873
+ (vy <= minVelocity && dy >= minDistance) ||
2874
+ (vx >= minVelocity && dx <= minDistance) ||
2875
+ (vy >= minVelocity && dy <= minDistance)) {
2876
+ return;
2877
+ }
2878
+ particle.position.x = Math.floor(randomInRangeValue({
2879
+ min: 0,
2880
+ max: container.canvas.size.width,
2881
+ }));
2882
+ particle.position.y = Math.floor(randomInRangeValue({
2883
+ min: 0,
2884
+ max: container.canvas.size.height,
2885
+ }));
2886
+ const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2887
+ particle.direction = Math.atan2(-newDy, -newDx);
2888
+ particle.velocity.angle = particle.direction;
2889
+ particle.justWarped = true;
2890
+ }
2891
+ #applyOutModeNormal(particle, container, direction) {
2892
+ const warp = particle.options.move.warp, canvasSize = container.canvas.size, sizeValue = particle.getRadius(), newPos = {
2893
+ bottom: canvasSize.height + sizeValue + particle.offset.y,
2894
+ left: -sizeValue - particle.offset.x,
2895
+ right: canvasSize.width + sizeValue + particle.offset.x,
2896
+ top: -sizeValue - particle.offset.y,
2897
+ }, nextBounds = calculateBounds(particle.position, sizeValue);
2898
+ if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2899
+ particle.position.x = newPos.left;
2900
+ particle.initialPosition.x = particle.position.x;
2901
+ if (!warp) {
2902
+ particle.position.y = getRandom() * canvasSize.height;
2903
+ particle.initialPosition.y = particle.position.y;
2904
+ }
2905
+ particle.justWarped = true;
2906
+ }
2907
+ else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2908
+ particle.position.x = newPos.right;
2909
+ particle.initialPosition.x = particle.position.x;
2910
+ if (!warp) {
2911
+ particle.position.y = getRandom() * canvasSize.height;
2912
+ particle.initialPosition.y = particle.position.y;
2913
+ }
2914
+ particle.justWarped = true;
2915
+ }
2916
+ if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2917
+ if (!warp) {
2918
+ particle.position.x = getRandom() * canvasSize.width;
2919
+ particle.initialPosition.x = particle.position.x;
2920
+ }
2921
+ particle.position.y = newPos.top;
2922
+ particle.initialPosition.y = particle.position.y;
2923
+ particle.justWarped = true;
2924
+ }
2925
+ else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2926
+ if (!warp) {
2927
+ particle.position.x = getRandom() * canvasSize.width;
2928
+ particle.initialPosition.x = particle.position.x;
2929
+ }
2930
+ particle.position.y = newPos.bottom;
2931
+ particle.initialPosition.y = particle.position.y;
2932
+ particle.justWarped = true;
2933
+ }
2934
+ }
2935
+ #applyParticleModeOutside(particle) {
2936
+ particle.position.x =
2937
+ Math.floor(randomInRangeValue({
2938
+ min: -particle.moveCenter.radius,
2939
+ max: particle.moveCenter.radius,
2940
+ })) + particle.moveCenter.x;
2941
+ particle.position.y =
2942
+ Math.floor(randomInRangeValue({
2943
+ min: -particle.moveCenter.radius,
2944
+ max: particle.moveCenter.radius,
2945
+ })) + particle.moveCenter.y;
2946
+ const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2947
+ if (particle.moveCenter.radius) {
2948
+ particle.direction = Math.atan2(dy, dx);
2949
+ particle.velocity.angle = particle.direction;
2950
+ }
2951
+ particle.justWarped = true;
2952
+ }
2893
2953
  }
2894
2954
 
2895
2955
  const checkOutMode = (outModes, outMode) => {
@@ -2937,7 +2997,7 @@
2937
2997
  }
2938
2998
 
2939
2999
  async function loadOutModesUpdater(engine) {
2940
- engine.checkVersion("4.4.0");
3000
+ engine.checkVersion("4.5.1");
2941
3001
  await engine.pluginManager.register(e => {
2942
3002
  e.pluginManager.addParticleUpdater("outModes", container => {
2943
3003
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2954,39 +3014,9 @@
2954
3014
  this.#pluginManager = pluginManager;
2955
3015
  }
2956
3016
  init(particle) {
2957
- 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;
2958
- if (fill) {
2959
- const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
2960
- particle.fillEnabled = fill.enable;
2961
- particle.fillOpacity = getRangeValue(fill.opacity);
2962
- particle.fillAnimation = fillColor.animation;
2963
- const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
2964
- if (fillHslColor) {
2965
- particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
2966
- }
2967
- }
2968
- else {
2969
- particle.fillEnabled = false;
2970
- particle.fillAnimation = undefined;
2971
- particle.fillColor = undefined;
2972
- particle.fillOpacity = defaultOpacity;
2973
- }
2974
- if (stroke) {
2975
- const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
2976
- particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
2977
- particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
2978
- particle.strokeAnimation = strokeColor.animation;
2979
- const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
2980
- if (strokeHslColor) {
2981
- particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
2982
- }
2983
- }
2984
- else {
2985
- particle.strokeAnimation = undefined;
2986
- particle.strokeColor = undefined;
2987
- particle.strokeOpacity = defaultOpacity;
2988
- particle.strokeWidth = 0;
2989
- }
3017
+ const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates);
3018
+ this.#initFill(paint, particle, container);
3019
+ this.#initStroke(paint, particle, container);
2990
3020
  }
2991
3021
  isEnabled(particle) {
2992
3022
  const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
@@ -3005,10 +3035,48 @@
3005
3035
  updateColor(particle.fillColor, delta, this.#container.hdr);
3006
3036
  updateColor(particle.strokeColor, delta, this.#container.hdr);
3007
3037
  }
3038
+ #initFill(paint, particle, container) {
3039
+ const fill = paint?.fill, color = paint?.color, paintColor = color ?? undefined;
3040
+ if (!fill) {
3041
+ particle.fillEnabled = false;
3042
+ particle.fillAnimation = undefined;
3043
+ particle.fillColor = undefined;
3044
+ particle.fillOpacity = defaultOpacity;
3045
+ return;
3046
+ }
3047
+ const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3048
+ particle.fillEnabled = fill.enable;
3049
+ particle.fillOpacity = getRangeValue(fill.opacity);
3050
+ particle.fillAnimation = fillColor.animation;
3051
+ const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3052
+ if (!fillHslColor) {
3053
+ return;
3054
+ }
3055
+ particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3056
+ }
3057
+ #initStroke(paint, particle, container) {
3058
+ const stroke = paint?.stroke, color = paint?.color, paintColor = color ?? undefined;
3059
+ if (!stroke) {
3060
+ particle.strokeAnimation = undefined;
3061
+ particle.strokeColor = undefined;
3062
+ particle.strokeOpacity = defaultOpacity;
3063
+ particle.strokeWidth = 0;
3064
+ return;
3065
+ }
3066
+ const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3067
+ particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3068
+ particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3069
+ particle.strokeAnimation = strokeColor.animation;
3070
+ const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3071
+ if (!strokeHslColor) {
3072
+ return;
3073
+ }
3074
+ particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3075
+ }
3008
3076
  }
3009
3077
 
3010
3078
  async function loadPaintUpdater(engine) {
3011
- engine.checkVersion("4.4.0");
3079
+ engine.checkVersion("4.5.1");
3012
3080
  await engine.pluginManager.register(e => {
3013
3081
  e.pluginManager.addParticleUpdater("paint", container => {
3014
3082
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3050,7 +3118,7 @@
3050
3118
  if (!this.accepts(input)) {
3051
3119
  return;
3052
3120
  }
3053
- const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
3121
+ const result = rgbRegex.exec(input), radix = 10, minLength = 4;
3054
3122
  return result
3055
3123
  ? {
3056
3124
  a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
@@ -3063,7 +3131,7 @@
3063
3131
  }
3064
3132
 
3065
3133
  async function loadRgbColorPlugin(engine) {
3066
- engine.checkVersion("4.4.0");
3134
+ engine.checkVersion("4.5.1");
3067
3135
  await engine.pluginManager.register(e => {
3068
3136
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3069
3137
  });
@@ -3148,7 +3216,7 @@
3148
3216
  }
3149
3217
 
3150
3218
  async function loadSizeUpdater(engine) {
3151
- engine.checkVersion("4.4.0");
3219
+ engine.checkVersion("4.5.1");
3152
3220
  await engine.pluginManager.register(e => {
3153
3221
  e.pluginManager.addParticleUpdater("size", container => {
3154
3222
  return Promise.resolve(new SizeUpdater(container));
@@ -3157,7 +3225,7 @@
3157
3225
  }
3158
3226
 
3159
3227
  async function loadBasic(engine) {
3160
- engine.checkVersion("4.4.0");
3228
+ engine.checkVersion("4.5.1");
3161
3229
  await engine.pluginManager.register(async (e) => {
3162
3230
  await Promise.all([
3163
3231
  loadBlendPlugin(e),
@@ -3296,6 +3364,8 @@
3296
3364
  autoPlay = true;
3297
3365
  direction;
3298
3366
  domId;
3367
+ draggable = false;
3368
+ draw = false;
3299
3369
  fill = true;
3300
3370
  life = new EmitterLife();
3301
3371
  name;
@@ -3319,6 +3389,8 @@
3319
3389
  }
3320
3390
  loadProperty(this, "direction", data.direction);
3321
3391
  loadProperty(this, "domId", data.domId);
3392
+ loadProperty(this, "draggable", data.draggable);
3393
+ loadProperty(this, "draw", data.draw);
3322
3394
  loadProperty(this, "fill", data.fill);
3323
3395
  this.life.load(data.life);
3324
3396
  loadProperty(this, "name", data.name);
@@ -3380,6 +3452,14 @@
3380
3452
  }
3381
3453
  }
3382
3454
 
3455
+ const ErrorCodes = {
3456
+ emittersPluginNotLoaded: "TSP-3101",
3457
+ };
3458
+
3459
+ const ErrorMessages = {
3460
+ [ErrorCodes.emittersPluginNotLoaded]: "tsParticles Emitters Plugin is not loaded",
3461
+ };
3462
+
3383
3463
  async function addEmittersShapesManager(e) {
3384
3464
  const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
3385
3465
  pluginManager.emitterShapeManager ??= new ShapeManager();
@@ -3410,7 +3490,10 @@
3410
3490
  })(EmitterClickMode || (EmitterClickMode = {}));
3411
3491
 
3412
3492
  async function loadEmittersPluginSimple(engine) {
3413
- engine.checkVersion("4.4.0");
3493
+ engine.checkVersion("4.5.1");
3494
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
3495
+ addErrorMessages(ErrorMessages);
3496
+ }
3414
3497
  await engine.pluginManager.register(async (e) => {
3415
3498
  const instancesManager = await getEmittersInstancesManager(e);
3416
3499
  await addEmittersShapesManager(e);
@@ -3464,7 +3547,7 @@
3464
3547
  }
3465
3548
 
3466
3549
  async function loadMotionPlugin(engine) {
3467
- engine.checkVersion("4.4.0");
3550
+ engine.checkVersion("4.5.1");
3468
3551
  await engine.pluginManager.register(e => {
3469
3552
  e.pluginManager.addPlugin(new MotionPlugin());
3470
3553
  });
@@ -3597,7 +3680,7 @@
3597
3680
  }
3598
3681
 
3599
3682
  async function loadRollUpdater(engine) {
3600
- engine.checkVersion("4.4.0");
3683
+ engine.checkVersion("4.5.1");
3601
3684
  await engine.pluginManager.register(e => {
3602
3685
  e.pluginManager.addParticleUpdater("roll", () => {
3603
3686
  return Promise.resolve(new RollUpdater(e.pluginManager));
@@ -3656,7 +3739,7 @@
3656
3739
  particle.pathRotation = rotateOptions.path;
3657
3740
  let rotateDirection = rotateOptions.direction;
3658
3741
  if (rotateDirection === RotateDirection.random) {
3659
- const index = Math.floor(getRandom() * double), minIndex = 0;
3742
+ const index = Math.floor(getRandom() * double);
3660
3743
  rotateDirection = index > minIndex ? RotateDirection.counterClockwise : RotateDirection.clockwise;
3661
3744
  }
3662
3745
  switch (rotateDirection) {
@@ -3703,7 +3786,7 @@
3703
3786
  }
3704
3787
 
3705
3788
  async function loadRotateUpdater(engine) {
3706
- engine.checkVersion("4.4.0");
3789
+ engine.checkVersion("4.5.1");
3707
3790
  await engine.pluginManager.register(e => {
3708
3791
  e.pluginManager.addParticleUpdater("rotate", container => {
3709
3792
  return Promise.resolve(new RotateUpdater(container));
@@ -3727,7 +3810,7 @@
3727
3810
  }
3728
3811
 
3729
3812
  async function loadSquareShape(engine) {
3730
- engine.checkVersion("4.4.0");
3813
+ engine.checkVersion("4.5.1");
3731
3814
  await engine.pluginManager.register(e => {
3732
3815
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
3733
3816
  });
@@ -3799,7 +3882,7 @@
3799
3882
  };
3800
3883
  let tiltDirection = tiltOptions.direction;
3801
3884
  if (tiltDirection === TiltDirection.random) {
3802
- const index = Math.floor(getRandom() * double), minIndex = 0;
3885
+ const index = Math.floor(getRandom() * double);
3803
3886
  tiltDirection = index > minIndex ? TiltDirection.counterClockwise : TiltDirection.clockwise;
3804
3887
  }
3805
3888
  switch (tiltDirection) {
@@ -3836,7 +3919,7 @@
3836
3919
  }
3837
3920
 
3838
3921
  async function loadTiltUpdater(engine) {
3839
- engine.checkVersion("4.4.0");
3922
+ engine.checkVersion("4.5.1");
3840
3923
  await engine.pluginManager.register(e => {
3841
3924
  e.pluginManager.addParticleUpdater("tilt", container => {
3842
3925
  return Promise.resolve(new TiltUpdater(container));
@@ -3938,7 +4021,7 @@
3938
4021
  }
3939
4022
 
3940
4023
  async function loadWobbleUpdater(engine) {
3941
- engine.checkVersion("4.4.0");
4024
+ engine.checkVersion("4.5.1");
3942
4025
  await engine.pluginManager.register(e => {
3943
4026
  e.pluginManager.addParticleUpdater("wobble", container => {
3944
4027
  return Promise.resolve(new WobbleUpdater(container));
@@ -4163,21 +4246,28 @@
4163
4246
  });
4164
4247
  }
4165
4248
  clear() {
4249
+ const visited = new Set();
4166
4250
  for (const plugin of this.#canvasClearPlugins) {
4251
+ visited.add(plugin);
4167
4252
  if (plugin.canvasClear?.() ?? false) {
4168
- return;
4253
+ return plugin;
4169
4254
  }
4170
4255
  }
4171
4256
  for (const layer of Object.values(DrawLayer)) {
4172
4257
  if (typeof layer === "number") {
4173
4258
  for (const plugin of this.#getLayerPlugins(layer)) {
4259
+ if (visited.has(plugin)) {
4260
+ continue;
4261
+ }
4262
+ visited.add(plugin);
4174
4263
  if (plugin.canvasClear?.() ?? false) {
4175
- return;
4264
+ return plugin;
4176
4265
  }
4177
4266
  }
4178
4267
  }
4179
4268
  }
4180
4269
  this.canvasClear();
4270
+ return undefined;
4181
4271
  }
4182
4272
  destroy() {
4183
4273
  this.stop();
@@ -4255,8 +4345,7 @@
4255
4345
  });
4256
4346
  }
4257
4347
  drawParticles(delta) {
4258
- const { particles, actualOptions } = this.#container;
4259
- this.clear();
4348
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
4260
4349
  particles.update(delta);
4261
4350
  this.draw(ctx => {
4262
4351
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -4278,7 +4367,9 @@
4278
4367
  }
4279
4368
  }
4280
4369
  for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
4281
- plugin.canvasPaint?.();
4370
+ if (plugin !== clearedPlugin) {
4371
+ plugin.canvasPaint?.();
4372
+ }
4282
4373
  }
4283
4374
  for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
4284
4375
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -4310,35 +4401,7 @@
4310
4401
  this.#layers[layer] = [];
4311
4402
  }
4312
4403
  }
4313
- for (const plugin of this.#container.plugins) {
4314
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4315
- this.#colorPlugins.push(plugin);
4316
- }
4317
- if (plugin.drawParticle) {
4318
- this.#drawParticlePlugins.push(plugin);
4319
- }
4320
- if (plugin.drawParticleSetup) {
4321
- this.#drawParticlesSetupPlugins.push(plugin);
4322
- }
4323
- if (plugin.drawParticleCleanup) {
4324
- this.#drawParticlesCleanupPlugins.push(plugin);
4325
- }
4326
- if (plugin.canvasClear) {
4327
- this.#canvasClearPlugins.push(plugin);
4328
- }
4329
- if (plugin.canvasPaint) {
4330
- this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
4331
- }
4332
- if (plugin.drawSettingsSetup) {
4333
- this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
4334
- }
4335
- if (plugin.draw) {
4336
- this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
4337
- }
4338
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4339
- this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
4340
- }
4341
- }
4404
+ this.#initPluginsArray();
4342
4405
  }
4343
4406
  initUpdaters() {
4344
4407
  this.#preDrawUpdaters = [];
@@ -4547,6 +4610,45 @@
4547
4610
  this.#reusablePluginColors[sColorIndex] = sColor;
4548
4611
  return this.#reusablePluginColors;
4549
4612
  }
4613
+ #initLayerPlugin(plugin) {
4614
+ const layerMap = [
4615
+ [DrawLayer.BackgroundMask, !!plugin.canvasPaint],
4616
+ [DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
4617
+ [DrawLayer.PluginContent, !!plugin.draw],
4618
+ [DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
4619
+ ];
4620
+ for (const [layer, active] of layerMap) {
4621
+ if (active) {
4622
+ this.#layers[layer].push(plugin);
4623
+ }
4624
+ }
4625
+ }
4626
+ #initPluginsArray() {
4627
+ for (const plugin of this.#container.plugins) {
4628
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4629
+ this.#colorPlugins.push(plugin);
4630
+ }
4631
+ if (plugin.drawParticle) {
4632
+ this.#drawParticlePlugins.push(plugin);
4633
+ }
4634
+ if (plugin.drawParticleSetup) {
4635
+ this.#drawParticlesSetupPlugins.push(plugin);
4636
+ }
4637
+ if (plugin.drawParticleCleanup) {
4638
+ this.#drawParticlesCleanupPlugins.push(plugin);
4639
+ }
4640
+ if (plugin.canvasClear) {
4641
+ this.#canvasClearPlugins.push(plugin);
4642
+ }
4643
+ this.#initLayerPlugin(plugin);
4644
+ }
4645
+ }
4646
+ #isSupportedElement(element) {
4647
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
4648
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
4649
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
4650
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
4651
+ }
4550
4652
  #resolveBackgroundElement() {
4551
4653
  const background = this.#container.actualOptions.background;
4552
4654
  this.#backgroundElement = null;
@@ -4556,9 +4658,7 @@
4556
4658
  if (typeof background.element === "string") {
4557
4659
  if (typeof document !== "undefined") {
4558
4660
  const node = document.querySelector(background.element);
4559
- if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4560
- (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4561
- (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4661
+ if (node && this.#isSupportedElement(node)) {
4562
4662
  this.#backgroundElement = node;
4563
4663
  }
4564
4664
  else if (node) {
@@ -4569,10 +4669,7 @@
4569
4669
  }
4570
4670
  }
4571
4671
  }
4572
- else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4573
- (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4574
- (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4575
- (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4672
+ else if (this.#isSupportedElement(background.element)) {
4576
4673
  this.#backgroundElement = background.element;
4577
4674
  }
4578
4675
  }
@@ -4590,7 +4687,7 @@
4590
4687
  return transferredCanvas;
4591
4688
  }
4592
4689
  if (typeof canvas.transferControlToOffscreen !== "function") {
4593
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4690
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasUnsupported));
4594
4691
  }
4595
4692
  try {
4596
4693
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -4598,10 +4695,16 @@
4598
4695
  return offscreenCanvas;
4599
4696
  }
4600
4697
  catch {
4601
- throw new TypeError("OffscreenCanvas transfer failed");
4698
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasTransferFailed));
4602
4699
  }
4603
4700
  }, isHtmlCanvasElement = (canvas) => {
4604
4701
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4702
+ }, getEffectiveColorSpace = (context) => {
4703
+ if (!context) {
4704
+ return undefined;
4705
+ }
4706
+ const colorInfo = context;
4707
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
4605
4708
  };
4606
4709
  function setStyle(canvas, style, important = false) {
4607
4710
  if (!style) {
@@ -4726,7 +4829,7 @@
4726
4829
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4727
4830
  if (color) {
4728
4831
  const hdrOptions = container.actualOptions.hdr;
4729
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4832
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard));
4730
4833
  }
4731
4834
  else {
4732
4835
  elementStyle.backgroundColor = "";
@@ -4846,11 +4949,11 @@
4846
4949
  const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4847
4950
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4848
4951
  safeMatchMedia("(dynamic-range: high)")?.matches;
4849
- container.hdr = canSupportHdr ?? false;
4850
- container.hdrMode = container.actualOptions.hdr.mode;
4952
+ container.hdrMode = toEnumValue(HdrMode, container.actualOptions.hdr.mode, HdrMode.standard);
4851
4953
  container.peakNits = container.actualOptions.hdr.peakNits;
4852
4954
  const renderCanvas = this.renderCanvas;
4853
4955
  if (!renderCanvas) {
4956
+ container.hdr = canSupportHdr ?? false;
4854
4957
  return;
4855
4958
  }
4856
4959
  this.render.setContextSettings({
@@ -4869,7 +4972,6 @@
4869
4972
  context = null;
4870
4973
  }
4871
4974
  if (canSupportHdr && !context) {
4872
- container.hdr = false;
4873
4975
  const sdrSettings = {
4874
4976
  alpha: true,
4875
4977
  desynchronized: true,
@@ -4885,11 +4987,16 @@
4885
4987
  }
4886
4988
  }
4887
4989
  this.render.setContext(context);
4990
+ if (context) {
4991
+ const effectiveColorSpace = getEffectiveColorSpace(context);
4992
+ if (effectiveColorSpace !== undefined) {
4993
+ container.hdr = effectiveColorSpace === "display-p3";
4994
+ }
4995
+ }
4888
4996
  }
4889
4997
  #initHdrListeners() {
4890
4998
  this.#removeHdrListeners();
4891
4999
  const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4892
- this.#recreateRenderCanvas();
4893
5000
  this.#initContext();
4894
5001
  this.initBackground();
4895
5002
  }, listeners = [];
@@ -4925,16 +5032,6 @@
4925
5032
  element.style.setProperty(key, value, "important");
4926
5033
  }
4927
5034
  }
4928
- #recreateRenderCanvas() {
4929
- const renderCanvas = this.renderCanvas;
4930
- if (!renderCanvas) {
4931
- return;
4932
- }
4933
- if (this.domElement) {
4934
- return;
4935
- }
4936
- this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4937
- }
4938
5035
  #removeHdrListeners() {
4939
5036
  if (!this.#hdrMediaListeners) {
4940
5037
  return;
@@ -5006,6 +5103,10 @@
5006
5103
  this.#manageListeners(true);
5007
5104
  }
5008
5105
  removeListeners() {
5106
+ if (this.#resizeTimeout !== undefined) {
5107
+ clearTimeout(this.#resizeTimeout);
5108
+ this.#resizeTimeout = undefined;
5109
+ }
5009
5110
  this.#manageListeners(false);
5010
5111
  }
5011
5112
  #handleVisibilityChange() {
@@ -5033,8 +5134,7 @@
5033
5134
  this.#resizeTimeout = undefined;
5034
5135
  }
5035
5136
  const handleResize = async () => {
5036
- const canvas = this.#container.canvas;
5037
- await canvas.windowResize();
5137
+ await this.#container.canvas.windowResize();
5038
5138
  };
5039
5139
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
5040
5140
  }
@@ -5062,8 +5162,8 @@
5062
5162
  }
5063
5163
  else if (!this.#resizeObserver && add && canvasEl) {
5064
5164
  this.#resizeObserver = new ResizeObserver((entries) => {
5065
- const entry = entries.find(e => e.target === canvasEl);
5066
- if (!entry) {
5165
+ const res = entries.some(e => e.target === canvasEl);
5166
+ if (!res) {
5067
5167
  return;
5068
5168
  }
5069
5169
  this.#handleWindowResize();
@@ -5327,10 +5427,10 @@
5327
5427
  return this.#modifiers.find(m => m.id === id);
5328
5428
  }
5329
5429
  getOpacity() {
5330
- 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;
5331
- this.#cachedOpacityData.fillOpacity = fillOpacity;
5430
+ 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;
5431
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
5332
5432
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5333
- this.#cachedOpacityData.strokeOpacity = strokeOpacity;
5433
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5334
5434
  return this.#cachedOpacityData;
5335
5435
  }
5336
5436
  getPosition() {
@@ -5577,7 +5677,7 @@
5577
5677
  #initPosition(position) {
5578
5678
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5579
5679
  if (!initialPosition) {
5580
- throw new Error("a valid position cannot be found for particle");
5680
+ throw new Error(getErrorMessage(ErrorCodes$2.particlePositionNotFound));
5581
5681
  }
5582
5682
  this.position = initialPosition;
5583
5683
  this.initialPosition = this.position.copy();
@@ -5626,6 +5726,12 @@
5626
5726
  this.#circlePoolIdx = 0;
5627
5727
  this.#rectanglePoolIdx = 0;
5628
5728
  }
5729
+ get cellSize() {
5730
+ return this.#cellSize;
5731
+ }
5732
+ set cellSize(value) {
5733
+ this.#pendingCellSize = value;
5734
+ }
5629
5735
  clear() {
5630
5736
  this.#cells.clear();
5631
5737
  const pendingCellSize = this.#pendingCellSize;
@@ -5649,40 +5755,46 @@
5649
5755
  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);
5650
5756
  for (let cx = minCellX; cx <= maxCellX; cx++) {
5651
5757
  for (let cy = minCellY; cy <= maxCellY; cy++) {
5652
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
5653
- if (!cellParticles) {
5654
- continue;
5655
- }
5656
- for (const p of cellParticles) {
5657
- if (check && !check(p)) {
5658
- continue;
5659
- }
5660
- if (range.contains(p.getPosition())) {
5661
- out.push(p);
5662
- }
5663
- }
5758
+ this.#queryCell(cx, cy, range, check, out);
5664
5759
  }
5665
5760
  }
5666
5761
  return out;
5667
5762
  }
5668
5763
  queryCircle(position, radius, check, out = []) {
5669
- const circle = this.#acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
5670
- this.#releaseShapes();
5671
- return result;
5764
+ const circle = this.#acquireCircle(position.x, position.y, radius);
5765
+ try {
5766
+ return this.query(circle, check, out);
5767
+ }
5768
+ finally {
5769
+ this.#circlePoolIdx--;
5770
+ }
5672
5771
  }
5673
5772
  queryRectangle(position, size, check, out = []) {
5674
- const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
5675
- this.#releaseShapes();
5676
- return result;
5677
- }
5678
- setCellSize(cellSize) {
5679
- this.#pendingCellSize = cellSize;
5773
+ const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height);
5774
+ try {
5775
+ return this.query(rect, check, out);
5776
+ }
5777
+ finally {
5778
+ this.#rectanglePoolIdx--;
5779
+ }
5680
5780
  }
5681
5781
  #acquireCircle(x, y, r) {
5682
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
5782
+ const idx = this.#circlePoolIdx++;
5783
+ let circle = this.#circlePool[idx];
5784
+ if (!circle) {
5785
+ circle = new Circle(x, y, r);
5786
+ this.#circlePool[idx] = circle;
5787
+ }
5788
+ return circle.reset(x, y, r);
5683
5789
  }
5684
5790
  #acquireRectangle(x, y, w, h) {
5685
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
5791
+ const idx = this.#rectanglePoolIdx++;
5792
+ let rectangle = this.#rectanglePool[idx];
5793
+ if (!rectangle) {
5794
+ rectangle = new Rectangle(x, y, w, h);
5795
+ this.#rectanglePool[idx] = rectangle;
5796
+ }
5797
+ return rectangle.reset(x, y, w, h);
5686
5798
  }
5687
5799
  #cellKeyFromCoords(x, y) {
5688
5800
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -5709,17 +5821,27 @@
5709
5821
  }
5710
5822
  return null;
5711
5823
  }
5712
- #releaseShapes() {
5713
- this.#circlePoolIdx = 0;
5714
- this.#rectanglePoolIdx = 0;
5824
+ #queryCell(cx, cy, range, check, out) {
5825
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
5826
+ if (!cellParticles) {
5827
+ return;
5828
+ }
5829
+ for (const p of cellParticles) {
5830
+ if (check && !check(p)) {
5831
+ continue;
5832
+ }
5833
+ if (range.contains(p.getPosition())) {
5834
+ out.push(p);
5835
+ }
5836
+ }
5715
5837
  }
5716
5838
  }
5717
5839
 
5718
5840
  class ParticlesManager {
5719
5841
  checkParticlePositionPlugins;
5720
- grid;
5721
5842
  #array;
5722
5843
  #container;
5844
+ #grid;
5723
5845
  #groupLimits;
5724
5846
  #limit;
5725
5847
  #nextId;
@@ -5743,7 +5865,7 @@
5743
5865
  this.#groupLimits = new Map();
5744
5866
  this.#particleBuckets = new Map();
5745
5867
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
5746
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5868
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
5747
5869
  this.checkParticlePositionPlugins = [];
5748
5870
  this.#particleResetPlugins = [];
5749
5871
  this.#particleUpdatePlugins = [];
@@ -5754,23 +5876,12 @@
5754
5876
  get count() {
5755
5877
  return this.#array.length;
5756
5878
  }
5879
+ get grid() {
5880
+ return this.#grid;
5881
+ }
5757
5882
  addParticle(position, overrideOptions, group, initializer) {
5758
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
5759
- if (limit > minLimit) {
5760
- switch (limitMode) {
5761
- case LimitMode.delete: {
5762
- const countToRemove = currentCount + countOffset - limit;
5763
- if (countToRemove > minCount) {
5764
- this.removeQuantity(countToRemove);
5765
- }
5766
- break;
5767
- }
5768
- case LimitMode.wait:
5769
- if (currentCount >= limit) {
5770
- return;
5771
- }
5772
- break;
5773
- }
5883
+ if (this.#checkAndApplyLimits(group, this.count)) {
5884
+ return;
5774
5885
  }
5775
5886
  try {
5776
5887
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -5834,7 +5945,7 @@
5834
5945
  return this.#array[index];
5835
5946
  }
5836
5947
  async init() {
5837
- const container = this.#container, options = container.actualOptions;
5948
+ const container = this.#container;
5838
5949
  this.checkParticlePositionPlugins = [];
5839
5950
  this.#updatePlugins = [];
5840
5951
  this.#particleUpdatePlugins = [];
@@ -5843,59 +5954,16 @@
5843
5954
  this.#postParticleUpdatePlugins = [];
5844
5955
  this.#particleBuckets.clear();
5845
5956
  this.#resetBuckets(container.zLayers);
5846
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5847
- for (const plugin of container.plugins) {
5848
- if (plugin.redrawInit) {
5849
- await plugin.redrawInit();
5850
- }
5851
- if (plugin.checkParticlePosition) {
5852
- this.checkParticlePositionPlugins.push(plugin);
5853
- }
5854
- if (plugin.update) {
5855
- this.#updatePlugins.push(plugin);
5856
- }
5857
- if (plugin.particleUpdate) {
5858
- this.#particleUpdatePlugins.push(plugin);
5859
- }
5860
- if (plugin.postUpdate) {
5861
- this.#postUpdatePlugins.push(plugin);
5862
- }
5863
- if (plugin.particleReset) {
5864
- this.#particleResetPlugins.push(plugin);
5865
- }
5866
- if (plugin.postParticleUpdate) {
5867
- this.#postParticleUpdatePlugins.push(plugin);
5868
- }
5869
- }
5870
- await this.#container.initDrawersAndUpdaters();
5871
- for (const drawer of this.#container.effectDrawers.values()) {
5872
- await drawer.init?.(container);
5873
- }
5874
- for (const drawer of this.#container.shapeDrawers.values()) {
5875
- await drawer.init?.(container);
5876
- }
5877
- let handled = false;
5878
- for (const plugin of container.plugins) {
5879
- handled = plugin.particlesInitialization?.() ?? handled;
5880
- if (handled) {
5881
- break;
5882
- }
5883
- }
5884
- if (!handled) {
5885
- const particlesOptions = options.particles, groups = particlesOptions.groups;
5886
- for (const group in groups) {
5887
- const groupOptions = groups[group];
5888
- if (!groupOptions) {
5889
- continue;
5890
- }
5891
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5892
- this.addParticle(undefined, groupOptions, group);
5893
- }
5894
- }
5895
- for (let i = this.count; i < particlesOptions.number.value; i++) {
5896
- this.addParticle();
5957
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5958
+ this.#applyLimits(container.actualOptions.particles);
5959
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5960
+ for (const group in groups) {
5961
+ const groupData = groups[group];
5962
+ if (groupData) {
5963
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
5897
5964
  }
5898
5965
  }
5966
+ await this.#initPlugins();
5899
5967
  }
5900
5968
  push(nb, position, overrideOptions, group) {
5901
5969
  for (let i = 0; i < nb; i++) {
@@ -5910,13 +5978,13 @@
5910
5978
  remove(particle, group, override) {
5911
5979
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
5912
5980
  }
5913
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
5981
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
5914
5982
  if (index < minIndex || index > this.count) {
5915
5983
  return;
5916
5984
  }
5917
5985
  let deleted = 0;
5918
5986
  for (let i = index; deleted < quantity && i < this.count; i++) {
5919
- if (this.#removeParticle(i, group, override)) {
5987
+ if (this.#removeParticle(i, group, override, matchGroup)) {
5920
5988
  i--;
5921
5989
  deleted++;
5922
5990
  }
@@ -5947,7 +6015,7 @@
5947
6015
  this.#resizeFactor = factor;
5948
6016
  }
5949
6017
  update(delta) {
5950
- this.grid.clear();
6018
+ this.#grid.clear();
5951
6019
  for (const plugin of this.#updatePlugins) {
5952
6020
  plugin.update?.(delta);
5953
6021
  }
@@ -5958,7 +6026,7 @@
5958
6026
  this.#updateParticlesPhase2(delta, particlesToDelete);
5959
6027
  if (particlesToDelete.size) {
5960
6028
  for (const particle of particlesToDelete) {
5961
- this.remove(particle);
6029
+ this.remove(particle, particle.group);
5962
6030
  }
5963
6031
  }
5964
6032
  this.#resizeFactor = undefined;
@@ -5969,12 +6037,7 @@
5969
6037
  #applyDensity(options, pluginsCount, group, groupOptions) {
5970
6038
  const numberOptions = options.number;
5971
6039
  if (!numberOptions.density.enable) {
5972
- if (group === undefined) {
5973
- this.#limit = numberOptions.limit.value;
5974
- }
5975
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
5976
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
5977
- }
6040
+ this.#applyLimits(options, group, groupOptions);
5978
6041
  return;
5979
6042
  }
5980
6043
  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);
@@ -5982,7 +6045,10 @@
5982
6045
  this.#limit = numberOptions.limit.value * densityFactor;
5983
6046
  }
5984
6047
  else {
5985
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
6048
+ this.#groupLimits.set(group, {
6049
+ limit: numberOptions.limit.value * densityFactor,
6050
+ mode: toEnumValue(LimitMode, numberOptions.limit.mode, LimitMode.delete),
6051
+ });
5986
6052
  }
5987
6053
  if (particlesCount < particlesNumber) {
5988
6054
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -5991,6 +6057,55 @@
5991
6057
  this.removeQuantity(particlesCount - particlesNumber, group);
5992
6058
  }
5993
6059
  }
6060
+ #applyLimits(options, group, groupOptions) {
6061
+ if (group === undefined) {
6062
+ this.#limit = options.number.limit.value;
6063
+ const groups = this.#container.actualOptions.particles.groups;
6064
+ for (const existingGroup of this.#groupLimits.keys()) {
6065
+ if (!(existingGroup in groups)) {
6066
+ this.#groupLimits.delete(existingGroup);
6067
+ }
6068
+ }
6069
+ }
6070
+ else {
6071
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
6072
+ if (limitValue > minLimit) {
6073
+ this.#groupLimits.set(group, {
6074
+ limit: limitValue,
6075
+ mode: toEnumValue(LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, LimitMode.delete),
6076
+ });
6077
+ }
6078
+ else {
6079
+ this.#groupLimits.delete(group);
6080
+ }
6081
+ }
6082
+ }
6083
+ #checkAndApplyLimits(group, currentCount) {
6084
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
6085
+ if (globalLimit > minLimit && globalMode === LimitMode.wait && currentCount >= globalLimit) {
6086
+ return true;
6087
+ }
6088
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
6089
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.wait) {
6090
+ const groupCount = this.filter(t => t.group === group).length;
6091
+ if (groupCount >= groupLimitEntry.limit) {
6092
+ return true;
6093
+ }
6094
+ }
6095
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.delete) {
6096
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
6097
+ if (groupCountToRemove > minCount) {
6098
+ this.removeQuantity(groupCountToRemove, group);
6099
+ }
6100
+ }
6101
+ if (globalLimit > minLimit && globalMode === LimitMode.delete) {
6102
+ const globalCountToRemove = this.count + countOffset - globalLimit;
6103
+ if (globalCountToRemove > minCount) {
6104
+ this.#removeAny(globalCountToRemove);
6105
+ }
6106
+ }
6107
+ return false;
6108
+ }
5994
6109
  #createBuckets(zLayers) {
5995
6110
  const bucketCount = Math.max(Math.floor(zLayers), one);
5996
6111
  return Array.from({ length: bucketCount }, () => []);
@@ -6013,6 +6128,70 @@
6013
6128
  }
6014
6129
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
6015
6130
  }
6131
+ async #initDrawersAndUpdaters() {
6132
+ const container = this.#container;
6133
+ await container.initDrawersAndUpdaters();
6134
+ for (const drawer of container.effectDrawers.values()) {
6135
+ await drawer.init?.(container);
6136
+ }
6137
+ for (const drawer of container.shapeDrawers.values()) {
6138
+ await drawer.init?.(container);
6139
+ }
6140
+ }
6141
+ async #initPlugins() {
6142
+ await this.#initPluginsArrays();
6143
+ await this.#initDrawersAndUpdaters();
6144
+ let handled = false;
6145
+ const container = this.#container;
6146
+ for (const plugin of container.plugins) {
6147
+ handled = plugin.particlesInitialization?.() ?? handled;
6148
+ if (handled) {
6149
+ break;
6150
+ }
6151
+ }
6152
+ if (handled) {
6153
+ return;
6154
+ }
6155
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
6156
+ for (const group in groups) {
6157
+ const groupOptions = groups[group];
6158
+ if (!groupOptions) {
6159
+ continue;
6160
+ }
6161
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
6162
+ this.addParticle(undefined, groupOptions, group);
6163
+ }
6164
+ }
6165
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
6166
+ this.addParticle();
6167
+ }
6168
+ }
6169
+ async #initPluginsArrays() {
6170
+ const container = this.#container;
6171
+ for (const plugin of container.plugins) {
6172
+ if (plugin.redrawInit) {
6173
+ await plugin.redrawInit();
6174
+ }
6175
+ if (plugin.checkParticlePosition) {
6176
+ this.checkParticlePositionPlugins.push(plugin);
6177
+ }
6178
+ if (plugin.update) {
6179
+ this.#updatePlugins.push(plugin);
6180
+ }
6181
+ if (plugin.particleUpdate) {
6182
+ this.#particleUpdatePlugins.push(plugin);
6183
+ }
6184
+ if (plugin.postUpdate) {
6185
+ this.#postUpdatePlugins.push(plugin);
6186
+ }
6187
+ if (plugin.particleReset) {
6188
+ this.#particleResetPlugins.push(plugin);
6189
+ }
6190
+ if (plugin.postParticleUpdate) {
6191
+ this.#postParticleUpdatePlugins.push(plugin);
6192
+ }
6193
+ }
6194
+ }
6016
6195
  #insertParticleIntoBucket(particle) {
6017
6196
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6018
6197
  if (!bucket) {
@@ -6021,12 +6200,15 @@
6021
6200
  bucket.push(particle);
6022
6201
  this.#particleBuckets.set(particle.id, bucketIndex);
6023
6202
  }
6024
- #removeParticle(index, group, override) {
6203
+ #removeAny(quantity) {
6204
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
6205
+ }
6206
+ #removeParticle(index, group, override, matchGroup = true) {
6025
6207
  const particle = this.#array[index];
6026
6208
  if (!particle) {
6027
6209
  return false;
6028
6210
  }
6029
- if (particle.group !== group) {
6211
+ if (matchGroup && particle.group !== group) {
6030
6212
  return false;
6031
6213
  }
6032
6214
  this.#array.splice(index, deleteCount);
@@ -6113,7 +6295,7 @@
6113
6295
  particlesToDelete.add(particle);
6114
6296
  continue;
6115
6297
  }
6116
- this.grid.insert(particle);
6298
+ this.#grid.insert(particle);
6117
6299
  }
6118
6300
  return particlesToDelete;
6119
6301
  }
@@ -6200,6 +6382,7 @@
6200
6382
  started;
6201
6383
  zLayers;
6202
6384
  #delay;
6385
+ #delayResolve;
6203
6386
  #delayTimeout;
6204
6387
  #delta = { value: 0, factor: 0 };
6205
6388
  #dispatchCallback;
@@ -6289,7 +6472,6 @@
6289
6472
  this.shapeDrawers = new Map();
6290
6473
  this.particleUpdaters = [];
6291
6474
  this.plugins.length = 0;
6292
- this.#pluginManager.clearPlugins(this);
6293
6475
  this.destroyed = true;
6294
6476
  this.#onDestroy(remove);
6295
6477
  this.dispatchEvent(EventType.containerDestroyed);
@@ -6342,31 +6524,14 @@
6342
6524
  await this.initDrawersAndUpdaters();
6343
6525
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
6344
6526
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
6345
- this.plugins.length = 0;
6346
- this.particleDestroyedPlugins.length = 0;
6347
- this.particleCreatedPlugins.length = 0;
6348
- this.particlePositionPlugins.length = 0;
6349
- for (const [plugin, containerPlugin] of allContainerPlugins) {
6350
- if (plugin.needsPlugin(this.actualOptions)) {
6351
- this.plugins.push(containerPlugin);
6352
- if (containerPlugin.particleCreated) {
6353
- this.particleCreatedPlugins.push(containerPlugin);
6354
- }
6355
- if (containerPlugin.particleDestroyed) {
6356
- this.particleDestroyedPlugins.push(containerPlugin);
6357
- }
6358
- if (containerPlugin.particlePosition) {
6359
- this.particlePositionPlugins.push(containerPlugin);
6360
- }
6361
- }
6362
- }
6527
+ this.#initPlugins(allContainerPlugins);
6363
6528
  this.retina.init();
6364
6529
  this.canvas.init();
6365
6530
  this.updateActualOptions();
6366
6531
  this.canvas.initBackground();
6367
6532
  this.canvas.resize();
6368
6533
  const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6369
- this.hdrMode = hdrOptions.mode;
6534
+ this.hdrMode = toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard);
6370
6535
  this.peakNits = hdrOptions.peakNits;
6371
6536
  this.zLayers = zLayers;
6372
6537
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
@@ -6387,9 +6552,9 @@
6387
6552
  }
6388
6553
  async initDrawersAndUpdaters() {
6389
6554
  const pluginManager = this.#pluginManager;
6390
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
6391
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
6392
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
6555
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
6556
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
6557
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
6393
6558
  }
6394
6559
  pause() {
6395
6560
  if (!guardCheck(this)) {
@@ -6456,7 +6621,10 @@
6456
6621
  await this.init();
6457
6622
  this.started = true;
6458
6623
  await new Promise(resolve => {
6624
+ this.#delayResolve = resolve;
6459
6625
  const start = async () => {
6626
+ this.#delayTimeout = undefined;
6627
+ this.#delayResolve = undefined;
6460
6628
  this.#eventListeners.addListeners();
6461
6629
  for (const plugin of this.plugins) {
6462
6630
  await plugin.start?.();
@@ -6472,9 +6640,11 @@
6472
6640
  if (!guardCheck(this) || !this.started) {
6473
6641
  return;
6474
6642
  }
6475
- if (this.#delayTimeout) {
6643
+ if (this.#delayTimeout !== undefined) {
6476
6644
  clearTimeout(this.#delayTimeout);
6477
6645
  this.#delayTimeout = undefined;
6646
+ this.#delayResolve?.();
6647
+ this.#delayResolve = undefined;
6478
6648
  }
6479
6649
  this.#firstStart = true;
6480
6650
  this.started = false;
@@ -6500,6 +6670,27 @@
6500
6670
  }
6501
6671
  return refresh;
6502
6672
  }
6673
+ #initPlugins(allContainerPlugins) {
6674
+ this.plugins.length = 0;
6675
+ this.particleDestroyedPlugins.length = 0;
6676
+ this.particleCreatedPlugins.length = 0;
6677
+ this.particlePositionPlugins.length = 0;
6678
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
6679
+ if (!plugin.needsPlugin(this.actualOptions)) {
6680
+ continue;
6681
+ }
6682
+ this.plugins.push(containerPlugin);
6683
+ if (containerPlugin.particleCreated) {
6684
+ this.particleCreatedPlugins.push(containerPlugin);
6685
+ }
6686
+ if (containerPlugin.particleDestroyed) {
6687
+ this.particleDestroyedPlugins.push(containerPlugin);
6688
+ }
6689
+ if (containerPlugin.particlePosition) {
6690
+ this.particlePositionPlugins.push(containerPlugin);
6691
+ }
6692
+ }
6693
+ }
6503
6694
  #nextFrame(timestamp) {
6504
6695
  try {
6505
6696
  if (!this.#smooth &&
@@ -6776,11 +6967,11 @@
6776
6967
  }
6777
6968
  }
6778
6969
  async #init() {
6779
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
6780
- if (!availablePathGenerators) {
6970
+ const pluginManager = this.#pluginManager;
6971
+ if (!pluginManager.initializers.pathGenerators) {
6781
6972
  return;
6782
6973
  }
6783
- this.availablePathGenerators = availablePathGenerators;
6974
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
6784
6975
  this.pathGenerators = new Map();
6785
6976
  for (const pathGenerator of this.pathGenerators.values()) {
6786
6977
  pathGenerator.init();
@@ -6801,6 +6992,11 @@
6801
6992
  this.#container = container;
6802
6993
  this.#instancesManager.initContainer(container);
6803
6994
  }
6995
+ draw(context, _delta) {
6996
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
6997
+ emitter.draw(context);
6998
+ }
6999
+ }
6804
7000
  async init() {
6805
7001
  const emittersOptions = this.#container.actualOptions.emitters;
6806
7002
  if (isArray(emittersOptions)) {
@@ -6871,14 +7067,21 @@
6871
7067
  this.#pluginManager = pluginManager;
6872
7068
  }
6873
7069
  async addEmitter(container, options, position) {
6874
- const emitterOptions = new Emitter();
6875
- emitterOptions.load(options);
6876
- const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
6877
- this.removeEmitter(container, emitter);
6878
- }, emitterOptions, position);
6879
- await emitter.init();
6880
- this.getArray(container).push(emitter);
6881
- return emitter;
7070
+ return this.addEmitters(container, [{ options, position }]).then(t => t[defaultIndex]);
7071
+ }
7072
+ async addEmitters(container, emitters) {
7073
+ const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), res = [];
7074
+ for (const { options, position } of emitters) {
7075
+ const emitterOptions = new Emitter();
7076
+ emitterOptions.load(options);
7077
+ const emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
7078
+ this.removeEmitter(container, emitter);
7079
+ }, emitterOptions, position);
7080
+ await emitter.init();
7081
+ this.getArray(container).push(emitter);
7082
+ res.push(emitter);
7083
+ }
7084
+ return res;
6882
7085
  }
6883
7086
  clear(container) {
6884
7087
  this.initContainer(container);
@@ -6905,6 +7108,7 @@
6905
7108
  : array.find(t => t.name === idxOrName);
6906
7109
  };
6907
7110
  container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
7111
+ container.addEmitters = async (emitters) => this.addEmitters(container, emitters);
6908
7112
  container.removeEmitter = (idxOrName) => {
6909
7113
  const emitter = container.getEmitter?.(idxOrName);
6910
7114
  if (emitter) {
@@ -6925,7 +7129,7 @@
6925
7129
  };
6926
7130
  }
6927
7131
  removeEmitter(container, emitter) {
6928
- const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
7132
+ const index = this.getArray(container).indexOf(emitter), deleteCount = 1;
6929
7133
  if (index >= minIndex) {
6930
7134
  this.getArray(container).splice(index, deleteCount);
6931
7135
  }
@@ -7035,6 +7239,7 @@
7035
7239
  #particlesOptions;
7036
7240
  #paused;
7037
7241
  #pluginManager;
7242
+ #positionOverride = false;
7038
7243
  #removeCallback;
7039
7244
  #resizeObserver;
7040
7245
  #shape;
@@ -7111,6 +7316,31 @@
7111
7316
  });
7112
7317
  this.play();
7113
7318
  }
7319
+ draw(context) {
7320
+ if (!this.options.draw || !this.#shape) {
7321
+ return;
7322
+ }
7323
+ const container = this.#container, fillEnabled = this.options.spawn.fill?.enable ?? true;
7324
+ context.save();
7325
+ context.beginPath();
7326
+ if (fillEnabled) {
7327
+ context.fillStyle = this.spawnFillColor
7328
+ ? getStyleFromHsl(this.spawnFillColor, container.hdr, this.spawnFillOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode)
7329
+ : getStyleFromRgb({ r: 0, g: 0, b: 0 }, container.hdr, defaultOpacity$1, container.peakNits, container.hdrMode);
7330
+ }
7331
+ if (this.spawnStrokeColor) {
7332
+ context.strokeStyle = getStyleFromHsl(this.spawnStrokeColor, container.hdr, this.spawnStrokeOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode);
7333
+ context.lineWidth = this.spawnStrokeWidth ?? defaultStrokeWidth;
7334
+ }
7335
+ this.#shape.draw?.(context);
7336
+ if (fillEnabled) {
7337
+ context.fill();
7338
+ }
7339
+ if (this.spawnStrokeColor) {
7340
+ context.stroke();
7341
+ }
7342
+ context.restore();
7343
+ }
7114
7344
  externalPause() {
7115
7345
  this.#paused = true;
7116
7346
  this.pause();
@@ -7148,11 +7378,14 @@
7148
7378
  }
7149
7379
  }
7150
7380
  resize() {
7151
- const initialPosition = this.#initialPosition, container = this.#container;
7152
- this.position =
7153
- initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
7154
- ? initialPosition
7155
- : this.#calcPosition();
7381
+ const container = this.#container;
7382
+ if (!this.#positionOverride) {
7383
+ const initialPosition = this.#initialPosition;
7384
+ this.position =
7385
+ initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
7386
+ ? initialPosition
7387
+ : this.#calcPosition();
7388
+ }
7156
7389
  this.#size = this.#calcSize();
7157
7390
  this.size =
7158
7391
  this.#size.mode === PixelMode.percent
@@ -7163,6 +7396,11 @@
7163
7396
  : { width: this.#size.width, height: this.#size.height };
7164
7397
  this.#shape?.resize(this.position, this.size);
7165
7398
  }
7399
+ setPosition(position) {
7400
+ this.#positionOverride = true;
7401
+ this.position = { ...position };
7402
+ this.#shape?.resize(this.position, this.size);
7403
+ }
7166
7404
  update(delta) {
7167
7405
  if (this.#paused) {
7168
7406
  return;
@@ -7188,8 +7426,10 @@
7188
7426
  this.#lifeCount--;
7189
7427
  }
7190
7428
  if (this.#lifeCount > minLifeCount || this.#immortal) {
7191
- this.position = this.#calcPosition();
7192
- this.#shape?.resize(this.position, this.size);
7429
+ if (!this.#positionOverride) {
7430
+ this.position = this.#calcPosition();
7431
+ this.#shape?.resize(this.position, this.size);
7432
+ }
7193
7433
  this.#spawnDelay = container.retina.reduceFactor
7194
7434
  ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
7195
7435
  container.retina.reduceFactor
@@ -7358,6 +7598,7 @@
7358
7598
  exports.loadConfettiExplosionsPreset = loadConfettiExplosionsPreset;
7359
7599
  exports.tsParticles = tsParticles;
7360
7600
 
7361
- }));
7601
+ })(g.__tsParticlesInternals.presets.confettiExplosions = g.__tsParticlesInternals.presets.confettiExplosions || {});
7602
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
7603
+
7362
7604
  Object.assign(globalThis.window || globalThis, { loadConfettiExplosionsPreset: (globalThis.__tsParticlesInternals.presets.confettiExplosions || {}).loadConfettiExplosionsPreset });
7363
- delete (globalThis.window || globalThis).tsparticlesInternalExports;