@tsparticles/fireworks 4.3.2 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,58 @@
1
- (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* tsParticles v4.3.2 */
3
- (function (global, factory) {
4
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
6
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.bundles = global.__tsParticlesInternals.bundles || {}, global.__tsParticlesInternals.bundles.fireworks = global.__tsParticlesInternals.bundles.fireworks || {})));
7
- })(this, (function (exports) { 'use strict';
8
-
9
- const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
10
- x: 0,
11
- y: 0,
12
- z: 0,
13
- }, defaultTransform = {
14
- a: 1,
15
- b: 0,
16
- c: 0,
17
- d: 1,
18
- }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha$1 = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius$1 = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
1
+ (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
+ (function (g) {
3
+ /* tsParticles v4.5.0 */
4
+ g.__tsParticlesInternals = g.__tsParticlesInternals || {};
5
+ g.__tsParticlesInternals.bundles = g.__tsParticlesInternals.bundles || {};
6
+ (function (exports) {
7
+ 'use strict';
8
+
9
+ const errorPrefix = "tsParticles - Error", codedErrorPattern = /^\[tsParticles Error (TSP-\d+)\]\s*/, fullMatchIndex = 0, codeIndex = 1;
10
+ const wrap = (fn) => (...args) => {
11
+ fn(...args);
12
+ }, _logger = {
13
+ debug: wrap(console.debug),
14
+ error: (message, ...optionalParams) => {
15
+ if (typeof message === "string") {
16
+ const match = codedErrorPattern.exec(message);
17
+ if (match?.[codeIndex]) {
18
+ console.error(`tsParticles - ${match[codeIndex]} - ${message.slice(match[fullMatchIndex].length)}`, ...optionalParams);
19
+ return;
20
+ }
21
+ }
22
+ console.error(`${errorPrefix} - ${message}`, ...optionalParams);
23
+ },
24
+ info: wrap(console.info),
25
+ log: wrap(console.log),
26
+ trace: wrap(console.trace),
27
+ verbose: wrap(console.log),
28
+ warning: wrap(console.warn),
29
+ };
30
+ function setLogger(logger) {
31
+ if (logger.debug) {
32
+ _logger.debug = wrap(logger.debug);
33
+ }
34
+ if (logger.error) {
35
+ _logger.error = wrap(logger.error);
36
+ }
37
+ if (logger.info) {
38
+ _logger.info = wrap(logger.info);
39
+ }
40
+ if (logger.log) {
41
+ _logger.log = wrap(logger.log);
42
+ }
43
+ if (logger.trace) {
44
+ _logger.trace = wrap(logger.trace);
45
+ }
46
+ if (logger.verbose) {
47
+ _logger.verbose = wrap(logger.verbose);
48
+ }
49
+ if (logger.warning) {
50
+ _logger.warning = wrap(logger.warning);
51
+ }
52
+ }
53
+ function getLogger() {
54
+ return _logger;
55
+ }
19
56
 
20
57
  exports.MoveDirection = void 0;
21
58
  (function (MoveDirection) {
@@ -32,6 +69,17 @@
32
69
  MoveDirection["inside"] = "inside";
33
70
  })(exports.MoveDirection || (exports.MoveDirection = {}));
34
71
 
72
+ const generatedAttribute = "generated", fullPercent = "100%", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
73
+ x: 0,
74
+ y: 0,
75
+ z: 0,
76
+ }, defaultTransform = {
77
+ a: 1,
78
+ b: 0,
79
+ c: 0,
80
+ d: 1,
81
+ }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
82
+
35
83
  function getZ(source) {
36
84
  return "z" in source ? source.z : originPoint.z;
37
85
  }
@@ -150,6 +198,12 @@
150
198
  function isFunction(arg) {
151
199
  return typeof arg === "function";
152
200
  }
201
+ function isEnumValue(enumObject, arg) {
202
+ return Object.values(enumObject).some(enumValue => enumValue === arg);
203
+ }
204
+ function toEnumValue(enumObject, arg, defaultValue) {
205
+ return isEnumValue(enumObject, arg) ? arg : defaultValue;
206
+ }
153
207
  function isObject(arg) {
154
208
  return typeof arg === "object" && arg !== null;
155
209
  }
@@ -310,11 +364,61 @@
310
364
  };
311
365
  }
312
366
  function parseAlpha(input) {
313
- const defaultAlpha = 1;
314
367
  if (!input) {
315
368
  return defaultAlpha;
316
369
  }
317
- return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
370
+ return input.endsWith("%") ? Number.parseFloat(input) / percentDenominator : Number.parseFloat(input);
371
+ }
372
+
373
+ const ErrorCodes$2 = {
374
+ engineVersionMismatch: "TSP-1001",
375
+ particlePositionNotFound: "TSP-1002",
376
+ pluginRegisterAfterLoad: "TSP-1003",
377
+ offscreenCanvasUnsupported: "TSP-1101",
378
+ offscreenCanvasTransferFailed: "TSP-1102",
379
+ hdrEnableInvalid: "TSP-1201",
380
+ hdrModeInvalid: "TSP-1202",
381
+ hdrPeakNitsInvalid: "TSP-1203",
382
+ };
383
+
384
+ const messages = {
385
+ [ErrorCodes$2.engineVersionMismatch]: "The tsParticles version is different from the loaded plugins version. Engine version: {0}. Plugin version: {1}",
386
+ [ErrorCodes$2.particlePositionNotFound]: "a valid position cannot be found for particle",
387
+ [ErrorCodes$2.pluginRegisterAfterLoad]: "Register plugins can only be done before calling tsParticles.load()",
388
+ [ErrorCodes$2.offscreenCanvasUnsupported]: "OffscreenCanvas is required but not supported by this browser",
389
+ [ErrorCodes$2.offscreenCanvasTransferFailed]: "OffscreenCanvas transfer failed",
390
+ [ErrorCodes$2.hdrEnableInvalid]: 'Invalid HDR "enable" value: expected a boolean, got "{0}"',
391
+ [ErrorCodes$2.hdrModeInvalid]: 'Invalid HDR "mode" value: expected one of {0}, got "{1}"',
392
+ [ErrorCodes$2.hdrPeakNitsInvalid]: 'Invalid HDR "peakNits" value: expected a positive number, got "{0}"',
393
+ };
394
+
395
+ let registeredMessages;
396
+ const ensureRegisteredMessages = () => {
397
+ registeredMessages ??= new Map(Object.entries(messages));
398
+ return registeredMessages;
399
+ }, toStringValue$1 = (value) => String(value), format = (template, args) => {
400
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
401
+ const arg = args[Number(index)];
402
+ return arg === undefined ? match : toStringValue$1(arg);
403
+ });
404
+ };
405
+ function addErrorMessages(extraMessages) {
406
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
407
+ return;
408
+ }
409
+ const catalog = ensureRegisteredMessages();
410
+ for (const [code, message] of Object.entries(extraMessages)) {
411
+ if (message !== undefined) {
412
+ catalog.set(code, message);
413
+ }
414
+ }
415
+ }
416
+ function getErrorMessage(code, ...args) {
417
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
418
+ return `[tsParticles Error ${code}] https://particles.js.org/errors/#${code}`;
419
+ }
420
+ const template = ensureRegisteredMessages().get(code) ?? `Unknown error code ${code}`;
421
+ return format(template, args);
318
422
  }
319
423
 
320
424
  exports.OutModeDirection = void 0;
@@ -331,7 +435,6 @@
331
435
  PixelMode["percent"] = "percent";
332
436
  })(exports.PixelMode || (exports.PixelMode = {}));
333
437
 
334
- const minRadius = 0;
335
438
  function isForbiddenKey(key) {
336
439
  return key === "__proto__" || key === "constructor" || key === "prototype";
337
440
  }
@@ -547,22 +650,84 @@
547
650
  element.removeEventListener(event, handler, removeOptions);
548
651
  }
549
652
  }
550
- async function getItemsFromInitializer(container, map, initializers, force = false) {
551
- let res = map.get(container);
552
- if (!res || force) {
553
- res = await Promise.all([...initializers.values()].map(t => t(container)));
554
- map.set(container, res);
653
+ async function getItemsFromInitializer(container, initializers) {
654
+ return await Promise.all([...initializers.values()].map(t => t(container)));
655
+ }
656
+ async function getItemMapFromInitializer(container, initializers) {
657
+ const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
658
+ return new Map(entries);
659
+ }
660
+ async function getDataFromUrl(data) {
661
+ const url = itemFromSingleOrMultiple(data.url, data.index);
662
+ if (!url) {
663
+ return data.fallback;
555
664
  }
556
- return res;
665
+ try {
666
+ const response = await fetch(url);
667
+ if (response.ok) {
668
+ const current = (await response.json());
669
+ if (isSourceOptionsValue(current)) {
670
+ return current;
671
+ }
672
+ getLogger().error("invalid configuration data while retrieving config file");
673
+ }
674
+ else {
675
+ getLogger().error(`${response.status.toString()} while retrieving config file`);
676
+ }
677
+ }
678
+ catch (error) {
679
+ getLogger().error(`error while retrieving config file: ${error}`);
680
+ }
681
+ return data.fallback;
557
682
  }
558
- async function getItemMapFromInitializer(container, map, initializers, force = false) {
559
- let res = map.get(container);
560
- if (!res || force) {
561
- const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
562
- res = new Map(entries);
563
- map.set(container, res);
683
+ function isSourceOptionsValue(value) {
684
+ if (isArray(value)) {
685
+ return value.every((entry) => isObject(entry) && !isArray(entry));
564
686
  }
565
- return res;
687
+ return isObject(value) && !isArray(value);
688
+ }
689
+ function getCanvasFromContainer(domContainer) {
690
+ let canvasEl;
691
+ const documentSafe = safeDocument(), isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
692
+ if (isCanvas) {
693
+ canvasEl = domContainer;
694
+ canvasEl.dataset[generatedAttribute] ??= generatedFalse;
695
+ if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
696
+ canvasEl.style.width ||= fullPercent;
697
+ canvasEl.style.height ||= fullPercent;
698
+ canvasEl.style.pointerEvents = "none";
699
+ canvasEl.style.setProperty("pointer-events", "none");
700
+ }
701
+ }
702
+ else {
703
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
704
+ if (foundCanvas) {
705
+ canvasEl = foundCanvas;
706
+ canvasEl.dataset[generatedAttribute] = generatedFalse;
707
+ }
708
+ else {
709
+ canvasEl = documentSafe.createElement(canvasTag);
710
+ canvasEl.dataset[generatedAttribute] = generatedTrue;
711
+ domContainer.appendChild(canvasEl);
712
+ }
713
+ canvasEl.style.width ||= fullPercent;
714
+ canvasEl.style.height ||= fullPercent;
715
+ canvasEl.style.pointerEvents = "none";
716
+ canvasEl.style.setProperty("pointer-events", "none");
717
+ }
718
+ return canvasEl;
719
+ }
720
+ function getDomContainer(id, source) {
721
+ const documentSafe = safeDocument();
722
+ let domContainer = source ?? documentSafe.getElementById(id);
723
+ if (domContainer) {
724
+ return domContainer;
725
+ }
726
+ domContainer = documentSafe.createElement("canvas");
727
+ domContainer.id = id;
728
+ domContainer.dataset[generatedAttribute] = generatedTrue;
729
+ documentSafe.body.append(domContainer);
730
+ return domContainer;
566
731
  }
567
732
 
568
733
  class EventDispatcher {
@@ -633,7 +798,6 @@
633
798
  class PluginManager {
634
799
  colorManagers = new Map();
635
800
  easingFunctions = new Map();
636
- effectDrawers = new Map();
637
801
  initializers = {
638
802
  effects: new Map(),
639
803
  shapes: new Map(),
@@ -642,8 +806,6 @@
642
806
  palettes = new Map();
643
807
  plugins = [];
644
808
  presets = new Map();
645
- shapeDrawers = new Map();
646
- updaters = new Map();
647
809
  #allLoadersSet = new Set();
648
810
  #configs = new Map();
649
811
  #engine;
@@ -661,57 +823,79 @@
661
823
  }
662
824
  return res;
663
825
  }
826
+ get initialized() {
827
+ return this.#initialized;
828
+ }
664
829
  addColorManager(name, manager) {
830
+ if (this.#initialized) {
831
+ return;
832
+ }
665
833
  this.colorManagers.set(name, manager);
666
834
  }
667
835
  addConfig(config) {
836
+ if (this.#initialized) {
837
+ return;
838
+ }
668
839
  const key = config.key ?? config.name ?? "default";
669
840
  this.#configs.set(key, config);
670
841
  this.#engine.dispatchEvent(exports.EventType.configAdded, { data: { name: key, config } });
671
842
  }
672
843
  addEasing(name, easing) {
844
+ if (this.#initialized) {
845
+ return;
846
+ }
673
847
  if (this.easingFunctions.get(name)) {
674
848
  return;
675
849
  }
676
850
  this.easingFunctions.set(name, easing);
677
851
  }
678
852
  addEffect(effect, drawer) {
853
+ if (this.#initialized) {
854
+ return;
855
+ }
679
856
  this.initializers.effects.set(effect, drawer);
680
857
  }
681
858
  addPalette(name, palette) {
859
+ if (this.#initialized) {
860
+ return;
861
+ }
682
862
  this.palettes.set(name, palette);
683
863
  }
684
864
  addParticleUpdater(name, updaterInitializer) {
865
+ if (this.#initialized) {
866
+ return;
867
+ }
685
868
  this.initializers.updaters.set(name, updaterInitializer);
686
869
  }
687
870
  addPlugin(plugin) {
871
+ if (this.#initialized) {
872
+ return;
873
+ }
688
874
  if (this.getPlugin(plugin.id)) {
689
875
  return;
690
876
  }
691
877
  this.plugins.push(plugin);
692
878
  }
693
879
  addPreset(preset, options, override = false) {
880
+ if (this.#initialized) {
881
+ return;
882
+ }
694
883
  if (!(override || !this.getPreset(preset))) {
695
884
  return;
696
885
  }
697
886
  this.presets.set(preset, options);
698
887
  }
699
888
  addShape(shapes, drawer) {
889
+ if (this.#initialized) {
890
+ return;
891
+ }
700
892
  for (const shape of shapes) {
701
893
  this.initializers.shapes.set(shape, drawer);
702
894
  }
703
895
  }
704
- clearPlugins(container) {
705
- this.effectDrawers.delete(container);
706
- this.shapeDrawers.delete(container);
707
- this.updaters.delete(container);
708
- }
709
896
  getEasing(name) {
710
897
  return this.easingFunctions.get(name) ?? ((value) => value);
711
898
  }
712
- getEffectDrawers(container, force = false) {
713
- return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
714
- }
715
899
  getPalette(name) {
716
900
  return this.palettes.get(name);
717
901
  }
@@ -721,12 +905,6 @@
721
905
  getPreset(preset) {
722
906
  return this.presets.get(preset);
723
907
  }
724
- async getShapeDrawers(container, force = false) {
725
- return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
726
- }
727
- async getUpdaters(container, force = false) {
728
- return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
729
- }
730
908
  async init() {
731
909
  if (this.#initialized || this.#isRunningLoaders) {
732
910
  return;
@@ -745,16 +923,9 @@
745
923
  this.#initialized = true;
746
924
  }
747
925
  }
748
- loadParticlesOptions(container, options, ...sourceOptions) {
749
- const updaters = this.updaters.get(container);
750
- if (!updaters) {
751
- return;
752
- }
753
- updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
754
- }
755
926
  async register(...loaders) {
756
927
  if (this.#initialized) {
757
- throw new Error("Register plugins can only be done before calling tsParticles.load()");
928
+ throw new Error(getErrorMessage(ErrorCodes$2.pluginRegisterAfterLoad));
758
929
  }
759
930
  for (const loader of loaders) {
760
931
  if (this.#isRunningLoaders) {
@@ -766,111 +937,15 @@
766
937
  }
767
938
  }
768
939
  async #runLoader(loader, executed, allLoaders) {
769
- if (executed.has(loader))
940
+ if (executed.has(loader)) {
770
941
  return;
942
+ }
771
943
  executed.add(loader);
772
944
  allLoaders.add(loader);
773
945
  await loader(this.#engine);
774
946
  }
775
947
  }
776
948
 
777
- const errorPrefix = "tsParticles - Error";
778
- const wrap = (fn) => (...args) => {
779
- fn(...args);
780
- }, _logger = {
781
- debug: wrap(console.debug),
782
- error: (message, ...optionalParams) => {
783
- console.error(`${errorPrefix} - ${message}`, ...optionalParams);
784
- },
785
- info: wrap(console.info),
786
- log: wrap(console.log),
787
- trace: wrap(console.trace),
788
- verbose: wrap(console.log),
789
- warning: wrap(console.warn),
790
- };
791
- function setLogger(logger) {
792
- if (logger.debug) {
793
- _logger.debug = wrap(logger.debug);
794
- }
795
- if (logger.error) {
796
- _logger.error = wrap(logger.error);
797
- }
798
- if (logger.info) {
799
- _logger.info = wrap(logger.info);
800
- }
801
- if (logger.log) {
802
- _logger.log = wrap(logger.log);
803
- }
804
- if (logger.trace) {
805
- _logger.trace = wrap(logger.trace);
806
- }
807
- if (logger.verbose) {
808
- _logger.verbose = wrap(logger.verbose);
809
- }
810
- if (logger.warning) {
811
- _logger.warning = wrap(logger.warning);
812
- }
813
- }
814
- function getLogger() {
815
- return _logger;
816
- }
817
-
818
- const fullPercent = "100%";
819
- async function getDataFromUrl(data) {
820
- const url = itemFromSingleOrMultiple(data.url, data.index);
821
- if (!url) {
822
- return data.fallback;
823
- }
824
- const response = await fetch(url);
825
- if (response.ok) {
826
- return (await response.json());
827
- }
828
- getLogger().error(`${response.status.toString()} while retrieving config file`);
829
- return data.fallback;
830
- }
831
- const getCanvasFromContainer = (domContainer) => {
832
- const documentSafe = safeDocument();
833
- let canvasEl;
834
- const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
835
- if (isCanvas) {
836
- canvasEl = domContainer;
837
- canvasEl.dataset[generatedAttribute] ??= generatedFalse;
838
- if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
839
- canvasEl.style.width ||= fullPercent;
840
- canvasEl.style.height ||= fullPercent;
841
- canvasEl.style.pointerEvents = "none";
842
- canvasEl.style.setProperty("pointer-events", "none");
843
- }
844
- }
845
- else {
846
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
847
- if (foundCanvas) {
848
- canvasEl = foundCanvas;
849
- canvasEl.dataset[generatedAttribute] = generatedFalse;
850
- }
851
- else {
852
- canvasEl = documentSafe.createElement(canvasTag);
853
- canvasEl.dataset[generatedAttribute] = generatedTrue;
854
- domContainer.appendChild(canvasEl);
855
- }
856
- canvasEl.style.width ||= fullPercent;
857
- canvasEl.style.height ||= fullPercent;
858
- canvasEl.style.pointerEvents = "none";
859
- canvasEl.style.setProperty("pointer-events", "none");
860
- }
861
- return canvasEl;
862
- }, getDomContainer = (id, source) => {
863
- const documentSafe = safeDocument();
864
- let domContainer = source ?? documentSafe.getElementById(id);
865
- if (domContainer) {
866
- return domContainer;
867
- }
868
- domContainer = documentSafe.createElement("canvas");
869
- domContainer.id = id;
870
- domContainer.dataset[generatedAttribute] = generatedTrue;
871
- documentSafe.body.append(domContainer);
872
- return domContainer;
873
- };
874
949
  class Engine {
875
950
  pluginManager = new PluginManager(this);
876
951
  #domArray = [];
@@ -880,7 +955,7 @@
880
955
  return this.#domArray;
881
956
  }
882
957
  get version() {
883
- return "4.3.2";
958
+ return "4.5.0";
884
959
  }
885
960
  addEventListener(type, listener) {
886
961
  this.#eventDispatcher.addEventListener(type, listener);
@@ -889,7 +964,7 @@
889
964
  if (this.version === pluginVersion) {
890
965
  return;
891
966
  }
892
- throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
967
+ throw new Error(getErrorMessage(ErrorCodes$2.engineVersionMismatch, this.version, pluginVersion));
893
968
  }
894
969
  dispatchEvent(type, args) {
895
970
  this.#eventDispatcher.dispatchEvent(type, args);
@@ -961,6 +1036,10 @@
961
1036
  }
962
1037
 
963
1038
  function initEngine() {
1039
+ const existing = globalThis.tsParticles;
1040
+ if (existing?.pluginManager) {
1041
+ return existing;
1042
+ }
964
1043
  return new Engine();
965
1044
  }
966
1045
 
@@ -1058,6 +1137,15 @@
1058
1137
  AnimationMode["random"] = "random";
1059
1138
  })(exports.AnimationMode || (exports.AnimationMode = {}));
1060
1139
 
1140
+ exports.HdrMode = void 0;
1141
+ (function (HdrMode) {
1142
+ HdrMode["standard"] = "standard";
1143
+ HdrMode["natural"] = "natural";
1144
+ HdrMode["vivid"] = "vivid";
1145
+ HdrMode["cinematic"] = "cinematic";
1146
+ HdrMode["dynamic"] = "dynamic";
1147
+ })(exports.HdrMode || (exports.HdrMode = {}));
1148
+
1061
1149
  exports.LimitMode = void 0;
1062
1150
  (function (LimitMode) {
1063
1151
  LimitMode["delete"] = "delete";
@@ -1125,20 +1213,6 @@
1125
1213
  DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1126
1214
  })(exports.DrawLayer || (exports.DrawLayer = {}));
1127
1215
 
1128
- class OptionLoader {
1129
- load(data) {
1130
- if (isNull(data)) {
1131
- return;
1132
- }
1133
- this.doLoad(data);
1134
- }
1135
- }
1136
- function loadOptions(options, ...sourceOptionsArr) {
1137
- for (const sourceOptions of sourceOptionsArr) {
1138
- options.load(sourceOptions);
1139
- }
1140
- }
1141
-
1142
1216
  function loadProperty(obj, key, value) {
1143
1217
  if (value !== undefined) {
1144
1218
  obj[key] = value;
@@ -1167,7 +1241,7 @@
1167
1241
  if (keyStr === "__proto__" || keyStr === "constructor" || keyStr === "prototype") {
1168
1242
  return;
1169
1243
  }
1170
- const objRecord = obj, currentValue = Object.prototype.hasOwnProperty.call(objRecord, keyStr) ? objRecord[keyStr] : {};
1244
+ const objRecord = obj, currentValue = Object.hasOwn(objRecord, keyStr) ? objRecord[keyStr] : {};
1171
1245
  objRecord[keyStr] = deepExtend(currentValue, value);
1172
1246
  }
1173
1247
  }
@@ -1180,6 +1254,20 @@
1180
1254
  }
1181
1255
  }
1182
1256
 
1257
+ class OptionLoader {
1258
+ load(data) {
1259
+ if (isNull(data)) {
1260
+ return;
1261
+ }
1262
+ this.doLoad(data);
1263
+ }
1264
+ }
1265
+ function loadOptions(options, ...sourceOptionsArr) {
1266
+ for (const sourceOptions of sourceOptionsArr) {
1267
+ options.load(sourceOptions);
1268
+ }
1269
+ }
1270
+
1183
1271
  class AnimationOptions extends OptionLoader {
1184
1272
  count = 0;
1185
1273
  decay = 0;
@@ -1323,6 +1411,28 @@
1323
1411
  }
1324
1412
  }
1325
1413
 
1414
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1415
+ class HDROptions extends OptionLoader {
1416
+ enable = true;
1417
+ mode = exports.HdrMode.standard;
1418
+ peakNits = defaultPeakNits;
1419
+ doLoad(data) {
1420
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1421
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrEnableInvalid, String(data.enable)));
1422
+ }
1423
+ if (data.mode !== undefined && !isEnumValue(exports.HdrMode, data.mode)) {
1424
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrModeInvalid, Object.values(exports.HdrMode).join(", "), toStringValue(data.mode)));
1425
+ }
1426
+ if (data.peakNits !== undefined &&
1427
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1428
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrPeakNitsInvalid, String(data.peakNits)));
1429
+ }
1430
+ loadProperty(this, "enable", data.enable);
1431
+ loadProperty(this, "mode", data.mode);
1432
+ loadProperty(this, "peakNits", data.peakNits);
1433
+ }
1434
+ }
1435
+
1326
1436
  class ResizeEvent extends OptionLoader {
1327
1437
  delay = 0.5;
1328
1438
  enable = true;
@@ -1693,12 +1803,10 @@
1693
1803
  plugin.loadParticlesOptions(this.#container, this, data);
1694
1804
  }
1695
1805
  }
1696
- const updaters = this.#pluginManager.updaters.get(this.#container);
1697
- if (updaters) {
1698
- for (const updater of updaters) {
1699
- if (updater.loadOptions) {
1700
- updater.loadOptions(this, data);
1701
- }
1806
+ const updaters = this.#container.particleUpdaters;
1807
+ for (const updater of updaters) {
1808
+ if (updater.loadOptions) {
1809
+ updater.loadOptions(this, data);
1702
1810
  }
1703
1811
  }
1704
1812
  }
@@ -1766,7 +1874,7 @@
1766
1874
  duration = 0;
1767
1875
  fpsLimit = 120;
1768
1876
  fullScreen;
1769
- hdr = true;
1877
+ hdr;
1770
1878
  key;
1771
1879
  name;
1772
1880
  palette;
@@ -1786,6 +1894,7 @@
1786
1894
  this.#container = container;
1787
1895
  this.background = new Background();
1788
1896
  this.fullScreen = new FullScreen();
1897
+ this.hdr = new HDROptions();
1789
1898
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1790
1899
  this.resize = new ResizeEvent();
1791
1900
  }
@@ -1808,7 +1917,15 @@
1808
1917
  loadProperty(this, "detectRetina", data.detectRetina);
1809
1918
  loadRangeProperty(this, "duration", data.duration);
1810
1919
  loadProperty(this, "fpsLimit", data.fpsLimit);
1811
- loadProperty(this, "hdr", data.hdr);
1920
+ const hdrData = data.hdr;
1921
+ if (isBoolean(hdrData)) {
1922
+ this.hdr.enable = hdrData;
1923
+ this.hdr.mode = exports.HdrMode.standard;
1924
+ this.hdr.peakNits = 400;
1925
+ }
1926
+ else {
1927
+ this.hdr.load(hdrData);
1928
+ }
1812
1929
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1813
1930
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1814
1931
  loadProperty(this, "zLayers", data.zLayers);
@@ -1851,7 +1968,7 @@
1851
1968
  }
1852
1969
  }
1853
1970
 
1854
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1971
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, acesA = 2.51, acesB = 0.03, acesC = 2.43, acesD = 0.59, acesE = 0.14, saturationBoost = 1.15, lightnessBoost = 1.05, temperatureR = 1.05, temperatureB = 0.95, contrastFactor = 1.1, luminanceR = 0.2126, luminanceG = 0.7152, luminanceB = 0.0722, dynamicLuminanceFactor = 2, channelCount = 3, srgbThreshold = 0.04045, srgbDivisor = 12.92, srgbOffset = 0.055, srgbScale = 1.055, srgbExponent = 2.4, linearThreshold = 0.0031308, linearScale = 12.92;
1855
1972
  function getCachedStyle(key, generator) {
1856
1973
  let cached = styleCache.get(key);
1857
1974
  if (!cached) {
@@ -1863,6 +1980,48 @@
1863
1980
  }
1864
1981
  return cached;
1865
1982
  }
1983
+ function acesFilmic(x) {
1984
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1985
+ }
1986
+ function srgbToLinear(c) {
1987
+ return c <= srgbThreshold ? c / srgbDivisor : Math.pow((c + srgbOffset) / srgbScale, srgbExponent);
1988
+ }
1989
+ function linearToSrgb(c) {
1990
+ return c <= linearThreshold ? c * linearScale : srgbScale * Math.pow(c, one / srgbExponent) - srgbOffset;
1991
+ }
1992
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1993
+ switch (mode) {
1994
+ case exports.HdrMode.vivid: {
1995
+ const avg = (r + g + b) / channelCount;
1996
+ return {
1997
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1998
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1999
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
2000
+ };
2001
+ }
2002
+ case exports.HdrMode.cinematic: {
2003
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
2004
+ return {
2005
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
2006
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
2007
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
2008
+ };
2009
+ }
2010
+ case exports.HdrMode.dynamic: {
2011
+ const luminance = luminanceR * r + luminanceG * g + luminanceB * b, vividWeight = Math.min(one, luminance * dynamicLuminanceFactor), naturalWeight = one - vividWeight, avg = (r + g + b) / channelCount, vividR = clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, vividG = clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, vividB = clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost;
2012
+ return {
2013
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
2014
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
2015
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
2016
+ };
2017
+ }
2018
+ case exports.HdrMode.standard:
2019
+ return { b, g, r };
2020
+ case exports.HdrMode.natural:
2021
+ default:
2022
+ return { b, g, r };
2023
+ }
2024
+ }
1866
2025
  function stringToRgba(pluginManager, input) {
1867
2026
  if (!input) {
1868
2027
  return;
@@ -1989,9 +2148,9 @@
1989
2148
  const grayscaleValue = Math.round(lNormalized * rgbMax);
1990
2149
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1991
2150
  }
1992
- const temp1 = lNormalized < half
2151
+ const temp2 = lNormalized < half
1993
2152
  ? lNormalized * (sNormalizedOffset + sNormalized)
1994
- : 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));
2153
+ : 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));
1995
2154
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1996
2155
  }
1997
2156
  function hslToRgbFloat(hsl) {
@@ -2000,9 +2159,9 @@
2000
2159
  const grayscaleValue = lNormalized * rgbMax;
2001
2160
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
2002
2161
  }
2003
- const temp1 = lNormalized < half
2162
+ const temp2 = lNormalized < half
2004
2163
  ? lNormalized * (sNormalizedOffset + sNormalized)
2005
- : 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));
2164
+ : 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));
2006
2165
  return { r: red, g: green, b: blue };
2007
2166
  }
2008
2167
  function hslaToRgba(hsla) {
@@ -2030,30 +2189,65 @@
2030
2189
  r: getRgbInRangeValue(),
2031
2190
  };
2032
2191
  }
2033
- function getStyleFromRgb(color, hdr, opacity) {
2034
- const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2035
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2192
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2193
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2194
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
2195
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2196
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
2197
+ }
2198
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = exports.HdrMode.standard) {
2199
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2200
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2201
+ }
2202
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2203
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2204
+ if (mode !== exports.HdrMode.natural && mode !== exports.HdrMode.vivid && mode !== exports.HdrMode.cinematic && mode !== exports.HdrMode.dynamic) {
2205
+ return { b: bNorm, g: gNorm, r: rNorm };
2206
+ }
2207
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2208
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2036
2209
  }
2037
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
2038
- const headroom = peakNits / sdrReferenceWhiteNits;
2039
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2210
+ function hdrToneMap(normalized, headroom, middleGray) {
2211
+ if (normalized <= middleGray) {
2212
+ return acesFilmic(normalized);
2213
+ }
2214
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2215
+ return acesFilmic(expanded);
2040
2216
  }
2041
2217
  function getSdrStyleFromRgb(color, opacity) {
2042
2218
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
2043
2219
  }
2044
- function getStyleFromHsl(color, hdr, opacity) {
2045
- const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2220
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2221
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2222
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
2223
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
2046
2224
  return getCachedStyle(key, () => hdr
2047
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2225
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
2048
2226
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
2049
2227
  }
2050
- function colorMix(color1, color2, size1, size2) {
2228
+ function colorMix(color1, color2, size1, size2, hdr) {
2051
2229
  let rgb1 = color1, rgb2 = color2;
2052
2230
  if (!("r" in rgb1)) {
2053
- rgb1 = hslToRgb(color1);
2231
+ rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
2054
2232
  }
2055
2233
  if (!("r" in rgb2)) {
2056
- rgb2 = hslToRgb(color2);
2234
+ rgb2 = hdr ? hslToRgbFloat(color2) : hslToRgb(color2);
2235
+ }
2236
+ if (hdr) {
2237
+ const lin1 = {
2238
+ b: srgbToLinear(rgb1.b / rgbMax),
2239
+ g: srgbToLinear(rgb1.g / rgbMax),
2240
+ r: srgbToLinear(rgb1.r / rgbMax),
2241
+ }, lin2 = {
2242
+ b: srgbToLinear(rgb2.b / rgbMax),
2243
+ g: srgbToLinear(rgb2.g / rgbMax),
2244
+ r: srgbToLinear(rgb2.r / rgbMax),
2245
+ }, totalWeight = size1 + size2;
2246
+ return {
2247
+ b: linearToSrgb((lin1.b * size1 + lin2.b * size2) / totalWeight) * rgbMax,
2248
+ g: linearToSrgb((lin1.g * size1 + lin2.g * size2) / totalWeight) * rgbMax,
2249
+ r: linearToSrgb((lin1.r * size1 + lin2.r * size2) / totalWeight) * rgbMax,
2250
+ };
2057
2251
  }
2058
2252
  return {
2059
2253
  b: mix(rgb1.b, rgb2.b, size1, size2),
@@ -2061,14 +2255,14 @@
2061
2255
  r: mix(rgb1.r, rgb2.r, size1, size2),
2062
2256
  };
2063
2257
  }
2064
- function getLinkColor(p1, p2, linkColor) {
2258
+ function getLinkColor(p1, p2, linkColor, hdr) {
2065
2259
  if (linkColor === randomColorValue) {
2066
2260
  return getRandomRgbColor();
2067
2261
  }
2068
2262
  else if (linkColor === midColorValue) {
2069
2263
  const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
2070
2264
  if (sourceColor && destColor && p2) {
2071
- return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius());
2265
+ return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
2072
2266
  }
2073
2267
  else {
2074
2268
  const hslColor = sourceColor ?? destColor;
@@ -2164,7 +2358,7 @@
2164
2358
  colorValue.velocity = defaultVelocity;
2165
2359
  }
2166
2360
  }
2167
- function updateColorValue(data, decrease, delta, hdr) {
2361
+ function updateColorValue(data, decrease, delta, _hdr) {
2168
2362
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2169
2363
  if (!data.enable ||
2170
2364
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2177,7 +2371,7 @@
2177
2371
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2178
2372
  return;
2179
2373
  }
2180
- const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = ((data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor) * (hdr ? hdrAnimationScale : identity), decay = data.decay ?? identity, max = data.max, min = data.min;
2374
+ const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor, decay = data.decay ?? identity, max = data.max, min = data.min;
2181
2375
  if (!decrease || data.status === exports.AnimationStatus.increasing) {
2182
2376
  data.value += velocity;
2183
2377
  if (data.value > max) {
@@ -2209,9 +2403,9 @@
2209
2403
  return;
2210
2404
  }
2211
2405
  const { h, s, l } = color;
2212
- updateColorValue(h, false, delta, hdr);
2213
- updateColorValue(s, true, delta, hdr);
2214
- updateColorValue(l, true, delta, hdr);
2406
+ updateColorValue(h, false, delta);
2407
+ updateColorValue(s, true, delta);
2408
+ updateColorValue(l, true, delta);
2215
2409
  }
2216
2410
  function alterHsl(color, type, value) {
2217
2411
  return {
@@ -2554,7 +2748,7 @@
2554
2748
  }
2555
2749
 
2556
2750
  async function loadBlendPlugin(engine) {
2557
- engine.checkVersion("4.3.2");
2751
+ engine.checkVersion("4.5.0");
2558
2752
  await engine.pluginManager.register(e => {
2559
2753
  e.pluginManager.addPlugin(new BlendPlugin());
2560
2754
  });
@@ -2591,7 +2785,7 @@
2591
2785
  }
2592
2786
 
2593
2787
  async function loadCircleShape(engine) {
2594
- engine.checkVersion("4.3.2");
2788
+ engine.checkVersion("4.5.0");
2595
2789
  await engine.pluginManager.register(e => {
2596
2790
  e.pluginManager.addShape(["circle"], () => {
2597
2791
  return Promise.resolve(new CircleDrawer());
@@ -2606,7 +2800,7 @@
2606
2800
  RgbIndexes[RgbIndexes["b"] = 3] = "b";
2607
2801
  RgbIndexes[RgbIndexes["a"] = 4] = "a";
2608
2802
  })(RgbIndexes$1 || (RgbIndexes$1 = {}));
2609
- 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;
2803
+ 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;
2610
2804
  class HexColorManager {
2611
2805
  accepts(input) {
2612
2806
  return input.startsWith("#");
@@ -2639,7 +2833,7 @@
2639
2833
  }
2640
2834
 
2641
2835
  async function loadHexColorPlugin(engine) {
2642
- engine.checkVersion("4.3.2");
2836
+ engine.checkVersion("4.5.0");
2643
2837
  await engine.pluginManager.register(e => {
2644
2838
  e.pluginManager.addColorManager("hex", new HexColorManager());
2645
2839
  });
@@ -2679,7 +2873,7 @@
2679
2873
  if (!this.accepts(input)) {
2680
2874
  return;
2681
2875
  }
2682
- const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
2876
+ const result = hslRegex.exec(input), minLength = 4, radix = 10;
2683
2877
  return result
2684
2878
  ? hslaToRgba({
2685
2879
  a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
@@ -2692,12 +2886,20 @@
2692
2886
  }
2693
2887
 
2694
2888
  async function loadHslColorPlugin(engine) {
2695
- engine.checkVersion("4.3.2");
2889
+ engine.checkVersion("4.5.0");
2696
2890
  await engine.pluginManager.register(e => {
2697
2891
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2698
2892
  });
2699
2893
  }
2700
2894
 
2895
+ const ErrorCodes$1 = {
2896
+ baseMoverNotLoaded: "TSP-3203",
2897
+ };
2898
+
2899
+ const ErrorMessages$1 = {
2900
+ [ErrorCodes$1.baseMoverNotLoaded]: "tsParticles Base Mover is not loaded",
2901
+ };
2902
+
2701
2903
  class MovePlugin {
2702
2904
  id = "move";
2703
2905
  #pluginManager;
@@ -2716,20 +2918,20 @@
2716
2918
  }
2717
2919
 
2718
2920
  async function loadMovePlugin(engine) {
2719
- engine.checkVersion("4.3.2");
2921
+ engine.checkVersion("4.5.0");
2922
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
2923
+ addErrorMessages(ErrorMessages$1);
2924
+ }
2720
2925
  await engine.pluginManager.register(e => {
2721
2926
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2722
2927
  movePluginManager.initializers.pathGenerators ??= new Map();
2723
- movePluginManager.pathGenerators ??= new Map();
2724
2928
  movePluginManager.addPathGenerator = (name, generator) => {
2929
+ if (movePluginManager.initialized) {
2930
+ return;
2931
+ }
2725
2932
  movePluginManager.initializers.pathGenerators ??= new Map();
2726
2933
  movePluginManager.initializers.pathGenerators.set(name, generator);
2727
2934
  };
2728
- movePluginManager.getPathGenerators = async (container, force = false) => {
2729
- movePluginManager.initializers.pathGenerators ??= new Map();
2730
- movePluginManager.pathGenerators ??= new Map();
2731
- return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
2732
- };
2733
2935
  e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
2734
2936
  });
2735
2937
  }
@@ -2932,7 +3134,7 @@
2932
3134
  }
2933
3135
 
2934
3136
  async function loadOpacityUpdater(engine) {
2935
- engine.checkVersion("4.3.2");
3137
+ engine.checkVersion("4.5.0");
2936
3138
  await engine.pluginManager.register(e => {
2937
3139
  e.pluginManager.addParticleUpdater("opacity", container => {
2938
3140
  return Promise.resolve(new OpacityUpdater(container));
@@ -2941,70 +3143,60 @@
2941
3143
  }
2942
3144
 
2943
3145
  const boundsMin = 0;
2944
- function bounceHorizontal(data) {
2945
- if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
2946
- (data.direction !== exports.OutModeDirection.left && data.direction !== exports.OutModeDirection.right)) {
2947
- return;
2948
- }
2949
- if (data.bounds.right < boundsMin && data.direction === exports.OutModeDirection.left) {
2950
- data.particle.position.x = data.size + data.offset.x;
2951
- }
2952
- else if (data.bounds.left > data.canvasSize.width && data.direction === exports.OutModeDirection.right) {
2953
- data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
2954
- }
2955
- const velocity = data.particle.velocity.x;
2956
- let bounced = false;
2957
- if (data.outOfCanvas &&
2958
- ((data.direction === exports.OutModeDirection.right && velocity > minVelocity) ||
2959
- (data.direction === exports.OutModeDirection.left && velocity < minVelocity))) {
2960
- const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
2961
- data.particle.velocity.x *= -newVelocity;
2962
- bounced = true;
2963
- }
2964
- if (!bounced) {
2965
- return;
2966
- }
2967
- const minPos = data.offset.x + data.size;
2968
- if (data.outOfCanvas && data.direction === exports.OutModeDirection.right) {
2969
- data.particle.position.x = data.canvasSize.width - minPos;
2970
- }
2971
- else if (data.outOfCanvas && data.direction === exports.OutModeDirection.left) {
2972
- data.particle.position.x = minPos;
2973
- }
2974
- if (data.outMode === exports.OutMode.split) {
2975
- data.particle.destroy();
2976
- }
2977
- }
2978
- function bounceVertical(data) {
2979
- if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
2980
- (data.direction !== exports.OutModeDirection.bottom && data.direction !== exports.OutModeDirection.top)) {
3146
+ const bounceAxisConfigs = {
3147
+ [exports.OutModeDirection.left]: {
3148
+ axis: "x",
3149
+ canvas: "width",
3150
+ bounce: "horizontal",
3151
+ negativeEdge: "right",
3152
+ positiveEdge: "left",
3153
+ negative: true,
3154
+ },
3155
+ [exports.OutModeDirection.right]: {
3156
+ axis: "x",
3157
+ canvas: "width",
3158
+ bounce: "horizontal",
3159
+ negativeEdge: "right",
3160
+ positiveEdge: "left",
3161
+ negative: false,
3162
+ },
3163
+ [exports.OutModeDirection.top]: {
3164
+ axis: "y",
3165
+ canvas: "height",
3166
+ bounce: "vertical",
3167
+ negativeEdge: "bottom",
3168
+ positiveEdge: "top",
3169
+ negative: true,
3170
+ },
3171
+ [exports.OutModeDirection.bottom]: {
3172
+ axis: "y",
3173
+ canvas: "height",
3174
+ bounce: "vertical",
3175
+ negativeEdge: "bottom",
3176
+ positiveEdge: "top",
3177
+ negative: false,
3178
+ },
3179
+ };
3180
+ function bounce(data) {
3181
+ if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) || !(data.direction in bounceAxisConfigs)) {
2981
3182
  return;
2982
3183
  }
2983
- if (data.bounds.bottom < boundsMin && data.direction === exports.OutModeDirection.top) {
2984
- data.particle.position.y = data.size + data.offset.y;
3184
+ const config = bounceAxisConfigs[data.direction], bounds = data.bounds, canvasDim = data.canvasSize[config.canvas], position = data.particle.position, velocity = data.particle.velocity[config.axis];
3185
+ if (config.negative && bounds[config.negativeEdge] < boundsMin) {
3186
+ position[config.axis] = data.size + data.offset[config.axis];
2985
3187
  }
2986
- else if (data.bounds.top > data.canvasSize.height && data.direction === exports.OutModeDirection.bottom) {
2987
- data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
3188
+ else if (!config.negative && bounds[config.positiveEdge] > canvasDim) {
3189
+ position[config.axis] = canvasDim - data.size - data.offset[config.axis];
2988
3190
  }
2989
- const velocity = data.particle.velocity.y;
2990
- let bounced = false;
2991
3191
  if (data.outOfCanvas &&
2992
- ((data.direction === exports.OutModeDirection.bottom && velocity > minVelocity) ||
2993
- (data.direction === exports.OutModeDirection.top && velocity < minVelocity))) {
2994
- const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
2995
- data.particle.velocity.y *= -newVelocity;
2996
- bounced = true;
3192
+ ((config.negative && velocity < minVelocity) || (!config.negative && velocity > minVelocity))) {
3193
+ data.particle.velocity[config.axis] *= -getRangeValue(data.particle.options.bounce[config.bounce].value);
2997
3194
  }
2998
- if (!bounced) {
3195
+ else {
2999
3196
  return;
3000
3197
  }
3001
- const minPos = data.offset.y + data.size;
3002
- if (data.outOfCanvas && data.direction === exports.OutModeDirection.bottom) {
3003
- data.particle.position.y = data.canvasSize.height - minPos;
3004
- }
3005
- else if (data.outOfCanvas && data.direction === exports.OutModeDirection.top) {
3006
- data.particle.position.y = minPos;
3007
- }
3198
+ const minPos = data.offset[config.axis] + data.size;
3199
+ position[config.axis] = config.negative ? minPos : canvasDim - minPos;
3008
3200
  if (data.outMode === exports.OutMode.split) {
3009
3201
  data.particle.destroy();
3010
3202
  }
@@ -3020,26 +3212,19 @@
3020
3212
  exports.OutMode.bounce,
3021
3213
  exports.OutMode.split,
3022
3214
  ];
3023
- this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
3215
+ this.#particleBouncePlugins = container.plugins.filter(p => !!p.particleBounce);
3024
3216
  }
3025
3217
  update(particle, direction, delta, outMode) {
3026
3218
  if (!this.modes.includes(outMode)) {
3027
3219
  return;
3028
3220
  }
3029
- const container = this.#container;
3030
- let handled = false;
3031
3221
  for (const plugin of this.#particleBouncePlugins) {
3032
- handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
3033
- if (handled) {
3034
- break;
3222
+ if (plugin.particleBounce?.(particle, delta, direction)) {
3223
+ return;
3035
3224
  }
3036
3225
  }
3037
- if (handled) {
3038
- return;
3039
- }
3040
- const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
3041
- bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
3042
- bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
3226
+ const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = this.#container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
3227
+ bounce({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
3043
3228
  }
3044
3229
  }
3045
3230
 
@@ -3128,107 +3313,108 @@
3128
3313
  return;
3129
3314
  }
3130
3315
  const container = this.#container;
3131
- switch (particle.outType) {
3132
- case exports.ParticleOutType.inside: {
3133
- const { x: vx, y: vy } = particle.velocity;
3134
- updateVector.setTo(originPoint);
3135
- updateVector.length = particle.moveCenter.radius;
3136
- updateVector.angle = particle.velocity.angle + Math.PI;
3137
- updateVector.addTo(particle.moveCenter);
3138
- const { dx, dy } = getDistances(particle.position, updateVector);
3139
- if ((vx <= minVelocity && dx >= minDistance) ||
3140
- (vy <= minVelocity && dy >= minDistance) ||
3141
- (vx >= minVelocity && dx <= minDistance) ||
3142
- (vy >= minVelocity && dy <= minDistance)) {
3143
- return;
3144
- }
3145
- particle.position.x = Math.floor(randomInRangeValue({
3146
- min: 0,
3147
- max: container.canvas.size.width,
3148
- }));
3149
- particle.position.y = Math.floor(randomInRangeValue({
3150
- min: 0,
3151
- max: container.canvas.size.height,
3152
- }));
3153
- const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
3154
- particle.direction = Math.atan2(-newDy, -newDx);
3155
- particle.velocity.angle = particle.direction;
3156
- particle.justWarped = true;
3157
- break;
3316
+ if (particle.outType === exports.ParticleOutType.inside) {
3317
+ this.#applyOutModeInside(particle, container);
3318
+ }
3319
+ else {
3320
+ if (particle.isInsideCanvasForOutMode(outMode, direction)) {
3321
+ return;
3158
3322
  }
3159
- default: {
3160
- if (particle.isInsideCanvasForOutMode(outMode, direction)) {
3161
- return;
3162
- }
3163
- switch (particle.outType) {
3164
- case exports.ParticleOutType.outside: {
3165
- particle.position.x =
3166
- Math.floor(randomInRangeValue({
3167
- min: -particle.moveCenter.radius,
3168
- max: particle.moveCenter.radius,
3169
- })) + particle.moveCenter.x;
3170
- particle.position.y =
3171
- Math.floor(randomInRangeValue({
3172
- min: -particle.moveCenter.radius,
3173
- max: particle.moveCenter.radius,
3174
- })) + particle.moveCenter.y;
3175
- const { dx, dy } = getDistances(particle.position, particle.moveCenter);
3176
- if (particle.moveCenter.radius) {
3177
- particle.direction = Math.atan2(dy, dx);
3178
- particle.velocity.angle = particle.direction;
3179
- }
3180
- particle.justWarped = true;
3181
- break;
3182
- }
3183
- case exports.ParticleOutType.normal: {
3184
- const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
3185
- bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
3186
- left: -particle.getRadius() - particle.offset.x,
3187
- right: canvasSize.width + particle.getRadius() + particle.offset.x,
3188
- top: -particle.getRadius() - particle.offset.y,
3189
- }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
3190
- if (direction === exports.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
3191
- particle.position.x = newPos.left;
3192
- particle.initialPosition.x = particle.position.x;
3193
- if (!warp) {
3194
- particle.position.y = getRandom() * canvasSize.height;
3195
- particle.initialPosition.y = particle.position.y;
3196
- }
3197
- particle.justWarped = true;
3198
- }
3199
- else if (direction === exports.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
3200
- particle.position.x = newPos.right;
3201
- particle.initialPosition.x = particle.position.x;
3202
- if (!warp) {
3203
- particle.position.y = getRandom() * canvasSize.height;
3204
- particle.initialPosition.y = particle.position.y;
3205
- }
3206
- particle.justWarped = true;
3207
- }
3208
- if (direction === exports.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
3209
- if (!warp) {
3210
- particle.position.x = getRandom() * canvasSize.width;
3211
- particle.initialPosition.x = particle.position.x;
3212
- }
3213
- particle.position.y = newPos.top;
3214
- particle.initialPosition.y = particle.position.y;
3215
- particle.justWarped = true;
3216
- }
3217
- else if (direction === exports.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
3218
- if (!warp) {
3219
- particle.position.x = getRandom() * canvasSize.width;
3220
- particle.initialPosition.x = particle.position.x;
3221
- }
3222
- particle.position.y = newPos.bottom;
3223
- particle.initialPosition.y = particle.position.y;
3224
- particle.justWarped = true;
3225
- }
3226
- break;
3227
- }
3228
- }
3229
- break;
3323
+ if (particle.outType === exports.ParticleOutType.outside) {
3324
+ this.#applyParticleModeOutside(particle);
3230
3325
  }
3326
+ else {
3327
+ this.#applyOutModeNormal(particle, container, direction);
3328
+ }
3329
+ }
3330
+ }
3331
+ #applyOutModeInside(particle, container) {
3332
+ const { x: vx, y: vy } = particle.velocity;
3333
+ updateVector.setTo(originPoint);
3334
+ updateVector.length = particle.moveCenter.radius;
3335
+ updateVector.angle = particle.velocity.angle + Math.PI;
3336
+ updateVector.addTo(particle.moveCenter);
3337
+ const { dx, dy } = getDistances(particle.position, updateVector);
3338
+ if ((vx <= minVelocity && dx >= minDistance) ||
3339
+ (vy <= minVelocity && dy >= minDistance) ||
3340
+ (vx >= minVelocity && dx <= minDistance) ||
3341
+ (vy >= minVelocity && dy <= minDistance)) {
3342
+ return;
3231
3343
  }
3344
+ particle.position.x = Math.floor(randomInRangeValue({
3345
+ min: 0,
3346
+ max: container.canvas.size.width,
3347
+ }));
3348
+ particle.position.y = Math.floor(randomInRangeValue({
3349
+ min: 0,
3350
+ max: container.canvas.size.height,
3351
+ }));
3352
+ const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
3353
+ particle.direction = Math.atan2(-newDy, -newDx);
3354
+ particle.velocity.angle = particle.direction;
3355
+ particle.justWarped = true;
3356
+ }
3357
+ #applyOutModeNormal(particle, container, direction) {
3358
+ const warp = particle.options.move.warp, canvasSize = container.canvas.size, sizeValue = particle.getRadius(), newPos = {
3359
+ bottom: canvasSize.height + sizeValue + particle.offset.y,
3360
+ left: -sizeValue - particle.offset.x,
3361
+ right: canvasSize.width + sizeValue + particle.offset.x,
3362
+ top: -sizeValue - particle.offset.y,
3363
+ }, nextBounds = calculateBounds(particle.position, sizeValue);
3364
+ if (direction === exports.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
3365
+ particle.position.x = newPos.left;
3366
+ particle.initialPosition.x = particle.position.x;
3367
+ if (!warp) {
3368
+ particle.position.y = getRandom() * canvasSize.height;
3369
+ particle.initialPosition.y = particle.position.y;
3370
+ }
3371
+ particle.justWarped = true;
3372
+ }
3373
+ else if (direction === exports.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
3374
+ particle.position.x = newPos.right;
3375
+ particle.initialPosition.x = particle.position.x;
3376
+ if (!warp) {
3377
+ particle.position.y = getRandom() * canvasSize.height;
3378
+ particle.initialPosition.y = particle.position.y;
3379
+ }
3380
+ particle.justWarped = true;
3381
+ }
3382
+ if (direction === exports.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
3383
+ if (!warp) {
3384
+ particle.position.x = getRandom() * canvasSize.width;
3385
+ particle.initialPosition.x = particle.position.x;
3386
+ }
3387
+ particle.position.y = newPos.top;
3388
+ particle.initialPosition.y = particle.position.y;
3389
+ particle.justWarped = true;
3390
+ }
3391
+ else if (direction === exports.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
3392
+ if (!warp) {
3393
+ particle.position.x = getRandom() * canvasSize.width;
3394
+ particle.initialPosition.x = particle.position.x;
3395
+ }
3396
+ particle.position.y = newPos.bottom;
3397
+ particle.initialPosition.y = particle.position.y;
3398
+ particle.justWarped = true;
3399
+ }
3400
+ }
3401
+ #applyParticleModeOutside(particle) {
3402
+ particle.position.x =
3403
+ Math.floor(randomInRangeValue({
3404
+ min: -particle.moveCenter.radius,
3405
+ max: particle.moveCenter.radius,
3406
+ })) + particle.moveCenter.x;
3407
+ particle.position.y =
3408
+ Math.floor(randomInRangeValue({
3409
+ min: -particle.moveCenter.radius,
3410
+ max: particle.moveCenter.radius,
3411
+ })) + particle.moveCenter.y;
3412
+ const { dx, dy } = getDistances(particle.position, particle.moveCenter);
3413
+ if (particle.moveCenter.radius) {
3414
+ particle.direction = Math.atan2(dy, dx);
3415
+ particle.velocity.angle = particle.direction;
3416
+ }
3417
+ particle.justWarped = true;
3232
3418
  }
3233
3419
  }
3234
3420
 
@@ -3277,7 +3463,7 @@
3277
3463
  }
3278
3464
 
3279
3465
  async function loadOutModesUpdater(engine) {
3280
- engine.checkVersion("4.3.2");
3466
+ engine.checkVersion("4.5.0");
3281
3467
  await engine.pluginManager.register(e => {
3282
3468
  e.pluginManager.addParticleUpdater("outModes", container => {
3283
3469
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3294,39 +3480,9 @@
3294
3480
  this.#pluginManager = pluginManager;
3295
3481
  }
3296
3482
  init(particle) {
3297
- 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;
3298
- if (fill) {
3299
- const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3300
- particle.fillEnabled = fill.enable;
3301
- particle.fillOpacity = getRangeValue(fill.opacity);
3302
- particle.fillAnimation = fillColor.animation;
3303
- const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3304
- if (fillHslColor) {
3305
- particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3306
- }
3307
- }
3308
- else {
3309
- particle.fillEnabled = false;
3310
- particle.fillAnimation = undefined;
3311
- particle.fillColor = undefined;
3312
- particle.fillOpacity = defaultOpacity;
3313
- }
3314
- if (stroke) {
3315
- const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3316
- particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3317
- particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3318
- particle.strokeAnimation = strokeColor.animation;
3319
- const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3320
- if (strokeHslColor) {
3321
- particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3322
- }
3323
- }
3324
- else {
3325
- particle.strokeAnimation = undefined;
3326
- particle.strokeColor = undefined;
3327
- particle.strokeOpacity = defaultOpacity;
3328
- particle.strokeWidth = 0;
3329
- }
3483
+ const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates);
3484
+ this.#initFill(paint, particle, container);
3485
+ this.#initStroke(paint, particle, container);
3330
3486
  }
3331
3487
  isEnabled(particle) {
3332
3488
  const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
@@ -3345,10 +3501,48 @@
3345
3501
  updateColor(particle.fillColor, delta, this.#container.hdr);
3346
3502
  updateColor(particle.strokeColor, delta, this.#container.hdr);
3347
3503
  }
3504
+ #initFill(paint, particle, container) {
3505
+ const fill = paint?.fill, color = paint?.color, paintColor = color ?? undefined;
3506
+ if (!fill) {
3507
+ particle.fillEnabled = false;
3508
+ particle.fillAnimation = undefined;
3509
+ particle.fillColor = undefined;
3510
+ particle.fillOpacity = defaultOpacity;
3511
+ return;
3512
+ }
3513
+ const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3514
+ particle.fillEnabled = fill.enable;
3515
+ particle.fillOpacity = getRangeValue(fill.opacity);
3516
+ particle.fillAnimation = fillColor.animation;
3517
+ const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3518
+ if (!fillHslColor) {
3519
+ return;
3520
+ }
3521
+ particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3522
+ }
3523
+ #initStroke(paint, particle, container) {
3524
+ const stroke = paint?.stroke, color = paint?.color, paintColor = color ?? undefined;
3525
+ if (!stroke) {
3526
+ particle.strokeAnimation = undefined;
3527
+ particle.strokeColor = undefined;
3528
+ particle.strokeOpacity = defaultOpacity;
3529
+ particle.strokeWidth = 0;
3530
+ return;
3531
+ }
3532
+ const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3533
+ particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3534
+ particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3535
+ particle.strokeAnimation = strokeColor.animation;
3536
+ const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3537
+ if (!strokeHslColor) {
3538
+ return;
3539
+ }
3540
+ particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3541
+ }
3348
3542
  }
3349
3543
 
3350
3544
  async function loadPaintUpdater(engine) {
3351
- engine.checkVersion("4.3.2");
3545
+ engine.checkVersion("4.5.0");
3352
3546
  await engine.pluginManager.register(e => {
3353
3547
  e.pluginManager.addParticleUpdater("paint", container => {
3354
3548
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3390,7 +3584,7 @@
3390
3584
  if (!this.accepts(input)) {
3391
3585
  return;
3392
3586
  }
3393
- const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
3587
+ const result = rgbRegex.exec(input), radix = 10, minLength = 4;
3394
3588
  return result
3395
3589
  ? {
3396
3590
  a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
@@ -3403,7 +3597,7 @@
3403
3597
  }
3404
3598
 
3405
3599
  async function loadRgbColorPlugin(engine) {
3406
- engine.checkVersion("4.3.2");
3600
+ engine.checkVersion("4.5.0");
3407
3601
  await engine.pluginManager.register(e => {
3408
3602
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3409
3603
  });
@@ -3488,7 +3682,7 @@
3488
3682
  }
3489
3683
 
3490
3684
  async function loadSizeUpdater(engine) {
3491
- engine.checkVersion("4.3.2");
3685
+ engine.checkVersion("4.5.0");
3492
3686
  await engine.pluginManager.register(e => {
3493
3687
  e.pluginManager.addParticleUpdater("size", container => {
3494
3688
  return Promise.resolve(new SizeUpdater(container));
@@ -3497,7 +3691,7 @@
3497
3691
  }
3498
3692
 
3499
3693
  async function loadBasic(engine) {
3500
- engine.checkVersion("4.3.2");
3694
+ engine.checkVersion("4.5.0");
3501
3695
  await engine.pluginManager.register(async (e) => {
3502
3696
  await Promise.all([
3503
3697
  loadBlendPlugin(e),
@@ -3828,7 +4022,7 @@
3828
4022
  }
3829
4023
 
3830
4024
  async function loadDestroyUpdater(engine) {
3831
- engine.checkVersion("4.3.2");
4025
+ engine.checkVersion("4.5.0");
3832
4026
  await engine.pluginManager.register(e => {
3833
4027
  e.pluginManager.addParticleUpdater("destroy", container => {
3834
4028
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -3928,6 +4122,8 @@
3928
4122
  autoPlay = true;
3929
4123
  direction;
3930
4124
  domId;
4125
+ draggable = false;
4126
+ draw = true;
3931
4127
  fill = true;
3932
4128
  life = new EmitterLife();
3933
4129
  name;
@@ -3951,6 +4147,8 @@
3951
4147
  }
3952
4148
  loadProperty(this, "direction", data.direction);
3953
4149
  loadProperty(this, "domId", data.domId);
4150
+ loadProperty(this, "draggable", data.draggable);
4151
+ loadProperty(this, "draw", data.draw);
3954
4152
  loadProperty(this, "fill", data.fill);
3955
4153
  this.life.load(data.life);
3956
4154
  loadProperty(this, "name", data.name);
@@ -4012,6 +4210,14 @@
4012
4210
  }
4013
4211
  }
4014
4212
 
4213
+ const ErrorCodes = {
4214
+ emittersPluginNotLoaded: "TSP-3101",
4215
+ };
4216
+
4217
+ const ErrorMessages = {
4218
+ [ErrorCodes.emittersPluginNotLoaded]: "tsParticles Emitters Plugin is not loaded",
4219
+ };
4220
+
4015
4221
  async function addEmittersShapesManager(e) {
4016
4222
  const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
4017
4223
  pluginManager.emitterShapeManager ??= new ShapeManager();
@@ -4047,6 +4253,8 @@
4047
4253
  this.fill = fill;
4048
4254
  this.options = options;
4049
4255
  }
4256
+ draw(_context) {
4257
+ }
4050
4258
  resize(position, size) {
4051
4259
  this.position = position;
4052
4260
  this.size = size;
@@ -4059,7 +4267,10 @@
4059
4267
  })(EmitterClickMode || (EmitterClickMode = {}));
4060
4268
 
4061
4269
  async function loadEmittersPluginSimple(engine) {
4062
- engine.checkVersion("4.3.2");
4270
+ engine.checkVersion("4.5.0");
4271
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
4272
+ addErrorMessages(ErrorMessages);
4273
+ }
4063
4274
  await engine.pluginManager.register(async (e) => {
4064
4275
  const instancesManager = await getEmittersInstancesManager(e);
4065
4276
  await addEmittersShapesManager(e);
@@ -4067,9 +4278,63 @@
4067
4278
  });
4068
4279
  }
4069
4280
 
4281
+ class EmittersPluginInstance {
4282
+ #container;
4283
+ #instancesManager;
4284
+ constructor(instancesManager, container) {
4285
+ this.#instancesManager = instancesManager;
4286
+ this.#container = container;
4287
+ this.#instancesManager.initContainer(container);
4288
+ }
4289
+ draw(context, _delta) {
4290
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4291
+ emitter.draw(context);
4292
+ }
4293
+ }
4294
+ async init() {
4295
+ const emittersOptions = this.#container.actualOptions.emitters;
4296
+ if (isArray(emittersOptions)) {
4297
+ for (const emitterOptions of emittersOptions) {
4298
+ await this.#instancesManager.addEmitter(this.#container, emitterOptions);
4299
+ }
4300
+ }
4301
+ else {
4302
+ await this.#instancesManager.addEmitter(this.#container, emittersOptions);
4303
+ }
4304
+ }
4305
+ pause() {
4306
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4307
+ emitter.pause();
4308
+ }
4309
+ }
4310
+ play() {
4311
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4312
+ emitter.play();
4313
+ }
4314
+ }
4315
+ resize() {
4316
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
4317
+ emitter.resize();
4318
+ }
4319
+ }
4320
+ stop() {
4321
+ this.#instancesManager.clear(this.#container);
4322
+ }
4323
+ update(delta) {
4324
+ this.#instancesManager.getArray(this.#container).forEach(emitter => {
4325
+ emitter.update(delta);
4326
+ });
4327
+ }
4328
+ }
4329
+
4330
+ var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
4331
+ __proto__: null,
4332
+ EmittersPluginInstance: EmittersPluginInstance
4333
+ });
4334
+
4070
4335
  function ensureEmittersPluginLoaded(e) {
4071
4336
  if (!e.pluginManager.addEmitterShapeGenerator) {
4072
- throw new Error("tsParticles Emitters Plugin is not loaded");
4337
+ throw new Error(getErrorMessage(ErrorCodes.emittersPluginNotLoaded));
4073
4338
  }
4074
4339
  }
4075
4340
 
@@ -4085,12 +4350,16 @@
4085
4350
  return position + offset * (getRandom() - half);
4086
4351
  }
4087
4352
  function getRandomSize(sides) {
4088
- return Math.floor(getRandom() * sides);
4353
+ return toEnumValue(Sides, Math.floor(getRandom() * sides), Sides.BottomLeft);
4089
4354
  }
4090
4355
  class EmittersSquareShape extends EmitterShapeBase {
4091
4356
  constructor(position, size, fill, options) {
4092
4357
  super(position, size, fill, options);
4093
4358
  }
4359
+ draw(context) {
4360
+ const position = this.position, size = this.size, halfW = size.width * half, halfH = size.height * half;
4361
+ context.rect(position.x - halfW, position.y - halfH, size.width, size.height);
4362
+ }
4094
4363
  async init() {
4095
4364
  }
4096
4365
  randomPosition() {
@@ -4147,7 +4416,7 @@
4147
4416
  }
4148
4417
 
4149
4418
  async function loadEmittersShapeSquare(engine) {
4150
- engine.checkVersion("4.3.2");
4419
+ engine.checkVersion("4.5.0");
4151
4420
  await engine.pluginManager.register((e) => {
4152
4421
  ensureEmittersPluginLoaded(e);
4153
4422
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -4291,7 +4560,7 @@
4291
4560
  }
4292
4561
 
4293
4562
  async function loadLifeUpdater(engine) {
4294
- engine.checkVersion("4.3.2");
4563
+ engine.checkVersion("4.5.0");
4295
4564
  await engine.pluginManager.register(e => {
4296
4565
  e.pluginManager.addParticleUpdater("life", container => {
4297
4566
  return Promise.resolve(new LifeUpdater(container));
@@ -4317,7 +4586,7 @@
4317
4586
  }
4318
4587
 
4319
4588
  async function loadLineShape(engine) {
4320
- engine.checkVersion("4.3.2");
4589
+ engine.checkVersion("4.5.0");
4321
4590
  await engine.pluginManager.register(e => {
4322
4591
  e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
4323
4592
  });
@@ -4374,7 +4643,7 @@
4374
4643
  particle.pathRotation = rotateOptions.path;
4375
4644
  let rotateDirection = rotateOptions.direction;
4376
4645
  if (rotateDirection === exports.RotateDirection.random) {
4377
- const index = Math.floor(getRandom() * double), minIndex = 0;
4646
+ const index = Math.floor(getRandom() * double);
4378
4647
  rotateDirection = index > minIndex ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
4379
4648
  }
4380
4649
  switch (rotateDirection) {
@@ -4421,7 +4690,7 @@
4421
4690
  }
4422
4691
 
4423
4692
  async function loadRotateUpdater(engine) {
4424
- engine.checkVersion("4.3.2");
4693
+ engine.checkVersion("4.5.0");
4425
4694
  await engine.pluginManager.register(e => {
4426
4695
  e.pluginManager.addParticleUpdater("rotate", container => {
4427
4696
  return Promise.resolve(new RotateUpdater(container));
@@ -4737,7 +5006,7 @@
4737
5006
  }
4738
5007
 
4739
5008
  async function loadSoundsPlugin(engine) {
4740
- engine.checkVersion("4.3.2");
5009
+ engine.checkVersion("4.5.0");
4741
5010
  await engine.pluginManager.register(e => {
4742
5011
  e.pluginManager.addPlugin(new SoundsPlugin(e));
4743
5012
  });
@@ -4745,7 +5014,7 @@
4745
5014
 
4746
5015
  let initPromise = null;
4747
5016
  async function doInitPlugins(engine) {
4748
- engine.checkVersion("4.3.2");
5017
+ engine.checkVersion("4.5.0");
4749
5018
  await engine.pluginManager.register(async (e) => {
4750
5019
  const loadEmittersForFireworks = async (e) => {
4751
5020
  await loadEmittersPluginSimple(e);
@@ -4792,7 +5061,7 @@
4792
5061
  fireworks.init = async () => {
4793
5062
  await initPlugins(tsParticles);
4794
5063
  };
4795
- fireworks.version = "4.3.2";
5064
+ fireworks.version = "4.5.0";
4796
5065
  globalThis.fireworks = fireworks;
4797
5066
 
4798
5067
  const globalObject = globalThis;
@@ -4862,21 +5131,28 @@
4862
5131
  });
4863
5132
  }
4864
5133
  clear() {
5134
+ const visited = new Set();
4865
5135
  for (const plugin of this.#canvasClearPlugins) {
5136
+ visited.add(plugin);
4866
5137
  if (plugin.canvasClear?.() ?? false) {
4867
- return;
5138
+ return plugin;
4868
5139
  }
4869
5140
  }
4870
5141
  for (const layer of Object.values(exports.DrawLayer)) {
4871
5142
  if (typeof layer === "number") {
4872
5143
  for (const plugin of this.#getLayerPlugins(layer)) {
5144
+ if (visited.has(plugin)) {
5145
+ continue;
5146
+ }
5147
+ visited.add(plugin);
4873
5148
  if (plugin.canvasClear?.() ?? false) {
4874
- return;
5149
+ return plugin;
4875
5150
  }
4876
5151
  }
4877
5152
  }
4878
5153
  }
4879
5154
  this.canvasClear();
5155
+ return undefined;
4880
5156
  }
4881
5157
  destroy() {
4882
5158
  this.stop();
@@ -4917,7 +5193,11 @@
4917
5193
  if (!fColor && !sColor) {
4918
5194
  return;
4919
5195
  }
4920
- const container = this.#container, zIndexOptions = particle.options.zIndex, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, { fillOpacity, opacity, strokeOpacity } = particle.getOpacity(), transform = this.#reusableTransform, colorStyles = this.#reusableColorStyles, fill = fColor ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity) : undefined, stroke = sColor ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity) : fill;
5196
+ const container = this.#container, zIndexOptions = particle.options.zIndex, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, { fillOpacity, opacity, strokeOpacity } = particle.getOpacity(), transform = this.#reusableTransform, colorStyles = this.#reusableColorStyles, fill = fColor
5197
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
5198
+ : undefined, stroke = sColor
5199
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
5200
+ : fill;
4921
5201
  transform.a = transform.b = transform.c = transform.d = undefined;
4922
5202
  colorStyles.fill = fill;
4923
5203
  colorStyles.stroke = stroke;
@@ -4950,8 +5230,7 @@
4950
5230
  });
4951
5231
  }
4952
5232
  drawParticles(delta) {
4953
- const { particles, actualOptions } = this.#container;
4954
- this.clear();
5233
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
4955
5234
  particles.update(delta);
4956
5235
  this.draw(ctx => {
4957
5236
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -4973,7 +5252,9 @@
4973
5252
  }
4974
5253
  }
4975
5254
  for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
4976
- plugin.canvasPaint?.();
5255
+ if (plugin !== clearedPlugin) {
5256
+ plugin.canvasPaint?.();
5257
+ }
4977
5258
  }
4978
5259
  for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
4979
5260
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -5005,35 +5286,7 @@
5005
5286
  this.#layers[layer] = [];
5006
5287
  }
5007
5288
  }
5008
- for (const plugin of this.#container.plugins) {
5009
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
5010
- this.#colorPlugins.push(plugin);
5011
- }
5012
- if (plugin.drawParticle) {
5013
- this.#drawParticlePlugins.push(plugin);
5014
- }
5015
- if (plugin.drawParticleSetup) {
5016
- this.#drawParticlesSetupPlugins.push(plugin);
5017
- }
5018
- if (plugin.drawParticleCleanup) {
5019
- this.#drawParticlesCleanupPlugins.push(plugin);
5020
- }
5021
- if (plugin.canvasClear) {
5022
- this.#canvasClearPlugins.push(plugin);
5023
- }
5024
- if (plugin.canvasPaint) {
5025
- this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
5026
- }
5027
- if (plugin.drawSettingsSetup) {
5028
- this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
5029
- }
5030
- if (plugin.draw) {
5031
- this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
5032
- }
5033
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
5034
- this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
5035
- }
5036
- }
5289
+ this.#initPluginsArray();
5037
5290
  }
5038
5291
  initUpdaters() {
5039
5292
  this.#preDrawUpdaters = [];
@@ -5242,6 +5495,45 @@
5242
5495
  this.#reusablePluginColors[sColorIndex] = sColor;
5243
5496
  return this.#reusablePluginColors;
5244
5497
  }
5498
+ #initLayerPlugin(plugin) {
5499
+ const layerMap = [
5500
+ [exports.DrawLayer.BackgroundMask, !!plugin.canvasPaint],
5501
+ [exports.DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
5502
+ [exports.DrawLayer.PluginContent, !!plugin.draw],
5503
+ [exports.DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
5504
+ ];
5505
+ for (const [layer, active] of layerMap) {
5506
+ if (active) {
5507
+ this.#layers[layer].push(plugin);
5508
+ }
5509
+ }
5510
+ }
5511
+ #initPluginsArray() {
5512
+ for (const plugin of this.#container.plugins) {
5513
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
5514
+ this.#colorPlugins.push(plugin);
5515
+ }
5516
+ if (plugin.drawParticle) {
5517
+ this.#drawParticlePlugins.push(plugin);
5518
+ }
5519
+ if (plugin.drawParticleSetup) {
5520
+ this.#drawParticlesSetupPlugins.push(plugin);
5521
+ }
5522
+ if (plugin.drawParticleCleanup) {
5523
+ this.#drawParticlesCleanupPlugins.push(plugin);
5524
+ }
5525
+ if (plugin.canvasClear) {
5526
+ this.#canvasClearPlugins.push(plugin);
5527
+ }
5528
+ this.#initLayerPlugin(plugin);
5529
+ }
5530
+ }
5531
+ #isSupportedElement(element) {
5532
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
5533
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
5534
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
5535
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
5536
+ }
5245
5537
  #resolveBackgroundElement() {
5246
5538
  const background = this.#container.actualOptions.background;
5247
5539
  this.#backgroundElement = null;
@@ -5251,7 +5543,7 @@
5251
5543
  if (typeof background.element === "string") {
5252
5544
  if (typeof document !== "undefined") {
5253
5545
  const node = document.querySelector(background.element);
5254
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
5546
+ if (node && this.#isSupportedElement(node)) {
5255
5547
  this.#backgroundElement = node;
5256
5548
  }
5257
5549
  else if (node) {
@@ -5262,10 +5554,7 @@
5262
5554
  }
5263
5555
  }
5264
5556
  }
5265
- else if (background.element instanceof HTMLCanvasElement ||
5266
- background.element instanceof OffscreenCanvas ||
5267
- background.element instanceof HTMLVideoElement ||
5268
- background.element instanceof HTMLImageElement) {
5557
+ else if (this.#isSupportedElement(background.element)) {
5269
5558
  this.#backgroundElement = background.element;
5270
5559
  }
5271
5560
  }
@@ -5283,7 +5572,7 @@
5283
5572
  return transferredCanvas;
5284
5573
  }
5285
5574
  if (typeof canvas.transferControlToOffscreen !== "function") {
5286
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
5575
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasUnsupported));
5287
5576
  }
5288
5577
  try {
5289
5578
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -5291,10 +5580,16 @@
5291
5580
  return offscreenCanvas;
5292
5581
  }
5293
5582
  catch {
5294
- throw new TypeError("OffscreenCanvas transfer failed");
5583
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasTransferFailed));
5295
5584
  }
5296
5585
  }, isHtmlCanvasElement = (canvas) => {
5297
5586
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
5587
+ }, getEffectiveColorSpace = (context) => {
5588
+ if (!context) {
5589
+ return undefined;
5590
+ }
5591
+ const colorInfo = context;
5592
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
5298
5593
  };
5299
5594
  function setStyle(canvas, style, important = false) {
5300
5595
  if (!style) {
@@ -5333,6 +5628,7 @@
5333
5628
  zoom = defaultZoom;
5334
5629
  #container;
5335
5630
  #generated;
5631
+ #hdrMediaListeners;
5336
5632
  #mutationObserver;
5337
5633
  #originalStyle;
5338
5634
  #pluginManager;
@@ -5397,7 +5693,6 @@
5397
5693
  });
5398
5694
  this.resize();
5399
5695
  this.#initStyle();
5400
- this.initBackground();
5401
5696
  this.#safeMutationObserver(obs => {
5402
5697
  const element = this.domElement;
5403
5698
  if (!element || !(element instanceof Node)) {
@@ -5407,6 +5702,8 @@
5407
5702
  });
5408
5703
  this.initPlugins();
5409
5704
  this.#initContext();
5705
+ this.initBackground();
5706
+ this.#initHdrListeners();
5410
5707
  this.render.init();
5411
5708
  }
5412
5709
  initBackground() {
@@ -5416,7 +5713,8 @@
5416
5713
  }
5417
5714
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
5418
5715
  if (color) {
5419
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
5716
+ const hdrOptions = container.actualOptions.hdr;
5717
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(exports.HdrMode, hdrOptions.mode, exports.HdrMode.standard));
5420
5718
  }
5421
5719
  else {
5422
5720
  elementStyle.backgroundColor = "";
@@ -5513,6 +5811,7 @@
5513
5811
  obs.disconnect();
5514
5812
  });
5515
5813
  this.#mutationObserver = undefined;
5814
+ this.#removeHdrListeners();
5516
5815
  this.render.stop();
5517
5816
  }
5518
5817
  async windowResize() {
@@ -5532,9 +5831,16 @@
5532
5831
  }
5533
5832
  }
5534
5833
  #initContext() {
5535
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
5834
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
5536
5835
  safeMatchMedia("(color-gamut: p3)")?.matches &&
5537
5836
  safeMatchMedia("(dynamic-range: high)")?.matches;
5837
+ container.hdrMode = toEnumValue(exports.HdrMode, container.actualOptions.hdr.mode, exports.HdrMode.standard);
5838
+ container.peakNits = container.actualOptions.hdr.peakNits;
5839
+ const renderCanvas = this.renderCanvas;
5840
+ if (!renderCanvas) {
5841
+ container.hdr = canSupportHdr ?? false;
5842
+ return;
5843
+ }
5538
5844
  this.render.setContextSettings({
5539
5845
  alpha: true,
5540
5846
  desynchronized: true,
@@ -5543,11 +5849,51 @@
5543
5849
  ? { colorSpace: "display-p3", colorType: "float16" }
5544
5850
  : { colorSpace: "srgb" }),
5545
5851
  });
5546
- const renderCanvas = this.renderCanvas;
5547
- if (!renderCanvas) {
5548
- return;
5852
+ let context;
5853
+ try {
5854
+ context = renderCanvas.getContext("2d", this.render.settings);
5855
+ }
5856
+ catch {
5857
+ context = null;
5858
+ }
5859
+ if (canSupportHdr && !context) {
5860
+ const sdrSettings = {
5861
+ alpha: true,
5862
+ desynchronized: true,
5863
+ willReadFrequently: false,
5864
+ colorSpace: "srgb",
5865
+ };
5866
+ this.render.setContextSettings(sdrSettings);
5867
+ try {
5868
+ context = renderCanvas.getContext("2d", sdrSettings);
5869
+ }
5870
+ catch {
5871
+ context = null;
5872
+ }
5873
+ }
5874
+ this.render.setContext(context);
5875
+ if (context) {
5876
+ const effectiveColorSpace = getEffectiveColorSpace(context);
5877
+ if (effectiveColorSpace !== undefined) {
5878
+ container.hdr = effectiveColorSpace === "display-p3";
5879
+ }
5880
+ }
5881
+ }
5882
+ #initHdrListeners() {
5883
+ this.#removeHdrListeners();
5884
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
5885
+ this.#initContext();
5886
+ this.initBackground();
5887
+ }, listeners = [];
5888
+ if (p3Query) {
5889
+ p3Query.addEventListener("change", handleChange);
5890
+ listeners.push({ handler: handleChange, mql: p3Query });
5891
+ }
5892
+ if (hdrQuery) {
5893
+ hdrQuery.addEventListener("change", handleChange);
5894
+ listeners.push({ handler: handleChange, mql: hdrQuery });
5549
5895
  }
5550
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
5896
+ this.#hdrMediaListeners = listeners;
5551
5897
  }
5552
5898
  #initStyle() {
5553
5899
  const element = this.domElement, options = this.#container.actualOptions;
@@ -5571,6 +5917,15 @@
5571
5917
  element.style.setProperty(key, value, "important");
5572
5918
  }
5573
5919
  }
5920
+ #removeHdrListeners() {
5921
+ if (!this.#hdrMediaListeners) {
5922
+ return;
5923
+ }
5924
+ for (const { handler, mql } of this.#hdrMediaListeners) {
5925
+ mql.removeEventListener("change", handler);
5926
+ }
5927
+ this.#hdrMediaListeners = undefined;
5928
+ }
5574
5929
  #repairStyle() {
5575
5930
  const element = this.domElement;
5576
5931
  if (!element) {
@@ -5660,8 +6015,7 @@
5660
6015
  this.#resizeTimeout = undefined;
5661
6016
  }
5662
6017
  const handleResize = async () => {
5663
- const canvas = this.#container.canvas;
5664
- await canvas.windowResize();
6018
+ await this.#container.canvas.windowResize();
5665
6019
  };
5666
6020
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
5667
6021
  }
@@ -5689,8 +6043,8 @@
5689
6043
  }
5690
6044
  else if (!this.#resizeObserver && add && canvasEl) {
5691
6045
  this.#resizeObserver = new ResizeObserver((entries) => {
5692
- const entry = entries.find(e => e.target === canvasEl);
5693
- if (!entry) {
6046
+ const res = entries.some(e => e.target === canvasEl);
6047
+ if (!res) {
5694
6048
  return;
5695
6049
  }
5696
6050
  this.#handleWindowResize();
@@ -5954,10 +6308,10 @@
5954
6308
  return this.#modifiers.find(m => m.id === id);
5955
6309
  }
5956
6310
  getOpacity() {
5957
- 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;
5958
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
6311
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity;
6312
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
5959
6313
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5960
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
6314
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5961
6315
  return this.#cachedOpacityData;
5962
6316
  }
5963
6317
  getPosition() {
@@ -6204,7 +6558,7 @@
6204
6558
  #initPosition(position) {
6205
6559
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
6206
6560
  if (!initialPosition) {
6207
- throw new Error("a valid position cannot be found for particle");
6561
+ throw new Error(getErrorMessage(ErrorCodes$2.particlePositionNotFound));
6208
6562
  }
6209
6563
  this.position = initialPosition;
6210
6564
  this.initialPosition = this.position.copy();
@@ -6253,6 +6607,12 @@
6253
6607
  this.#circlePoolIdx = 0;
6254
6608
  this.#rectanglePoolIdx = 0;
6255
6609
  }
6610
+ get cellSize() {
6611
+ return this.#cellSize;
6612
+ }
6613
+ set cellSize(value) {
6614
+ this.#pendingCellSize = value;
6615
+ }
6256
6616
  clear() {
6257
6617
  this.#cells.clear();
6258
6618
  const pendingCellSize = this.#pendingCellSize;
@@ -6276,18 +6636,7 @@
6276
6636
  const minCellX = Math.floor(bounds.minX / this.#cellSize), maxCellX = Math.floor(bounds.maxX / this.#cellSize), minCellY = Math.floor(bounds.minY / this.#cellSize), maxCellY = Math.floor(bounds.maxY / this.#cellSize);
6277
6637
  for (let cx = minCellX; cx <= maxCellX; cx++) {
6278
6638
  for (let cy = minCellY; cy <= maxCellY; cy++) {
6279
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
6280
- if (!cellParticles) {
6281
- continue;
6282
- }
6283
- for (const p of cellParticles) {
6284
- if (check && !check(p)) {
6285
- continue;
6286
- }
6287
- if (range.contains(p.getPosition())) {
6288
- out.push(p);
6289
- }
6290
- }
6639
+ this.#queryCell(cx, cy, range, check, out);
6291
6640
  }
6292
6641
  }
6293
6642
  return out;
@@ -6302,14 +6651,23 @@
6302
6651
  this.#releaseShapes();
6303
6652
  return result;
6304
6653
  }
6305
- setCellSize(cellSize) {
6306
- this.#pendingCellSize = cellSize;
6307
- }
6308
6654
  #acquireCircle(x, y, r) {
6309
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
6655
+ const idx = this.#circlePoolIdx++;
6656
+ let circle = this.#circlePool[idx];
6657
+ if (!circle) {
6658
+ circle = new Circle(x, y, r);
6659
+ this.#circlePool[idx] = circle;
6660
+ }
6661
+ return circle.reset(x, y, r);
6310
6662
  }
6311
6663
  #acquireRectangle(x, y, w, h) {
6312
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
6664
+ const idx = this.#rectanglePoolIdx++;
6665
+ let rectangle = this.#rectanglePool[idx];
6666
+ if (!rectangle) {
6667
+ rectangle = new Rectangle(x, y, w, h);
6668
+ this.#rectanglePool[idx] = rectangle;
6669
+ }
6670
+ return rectangle.reset(x, y, w, h);
6313
6671
  }
6314
6672
  #cellKeyFromCoords(x, y) {
6315
6673
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -6336,6 +6694,20 @@
6336
6694
  }
6337
6695
  return null;
6338
6696
  }
6697
+ #queryCell(cx, cy, range, check, out) {
6698
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
6699
+ if (!cellParticles) {
6700
+ return;
6701
+ }
6702
+ for (const p of cellParticles) {
6703
+ if (check && !check(p)) {
6704
+ continue;
6705
+ }
6706
+ if (range.contains(p.getPosition())) {
6707
+ out.push(p);
6708
+ }
6709
+ }
6710
+ }
6339
6711
  #releaseShapes() {
6340
6712
  this.#circlePoolIdx = 0;
6341
6713
  this.#rectanglePoolIdx = 0;
@@ -6344,9 +6716,9 @@
6344
6716
 
6345
6717
  class ParticlesManager {
6346
6718
  checkParticlePositionPlugins;
6347
- grid;
6348
6719
  #array;
6349
6720
  #container;
6721
+ #grid;
6350
6722
  #groupLimits;
6351
6723
  #limit;
6352
6724
  #nextId;
@@ -6370,7 +6742,7 @@
6370
6742
  this.#groupLimits = new Map();
6371
6743
  this.#particleBuckets = new Map();
6372
6744
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
6373
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
6745
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
6374
6746
  this.checkParticlePositionPlugins = [];
6375
6747
  this.#particleResetPlugins = [];
6376
6748
  this.#particleUpdatePlugins = [];
@@ -6381,23 +6753,12 @@
6381
6753
  get count() {
6382
6754
  return this.#array.length;
6383
6755
  }
6756
+ get grid() {
6757
+ return this.#grid;
6758
+ }
6384
6759
  addParticle(position, overrideOptions, group, initializer) {
6385
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
6386
- if (limit > minLimit) {
6387
- switch (limitMode) {
6388
- case exports.LimitMode.delete: {
6389
- const countToRemove = currentCount + countOffset - limit;
6390
- if (countToRemove > minCount) {
6391
- this.removeQuantity(countToRemove);
6392
- }
6393
- break;
6394
- }
6395
- case exports.LimitMode.wait:
6396
- if (currentCount >= limit) {
6397
- return;
6398
- }
6399
- break;
6400
- }
6760
+ if (this.#checkAndApplyLimits(group, this.count)) {
6761
+ return;
6401
6762
  }
6402
6763
  try {
6403
6764
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -6461,7 +6822,7 @@
6461
6822
  return this.#array[index];
6462
6823
  }
6463
6824
  async init() {
6464
- const container = this.#container, options = container.actualOptions;
6825
+ const container = this.#container;
6465
6826
  this.checkParticlePositionPlugins = [];
6466
6827
  this.#updatePlugins = [];
6467
6828
  this.#particleUpdatePlugins = [];
@@ -6470,59 +6831,16 @@
6470
6831
  this.#postParticleUpdatePlugins = [];
6471
6832
  this.#particleBuckets.clear();
6472
6833
  this.#resetBuckets(container.zLayers);
6473
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
6474
- for (const plugin of container.plugins) {
6475
- if (plugin.redrawInit) {
6476
- await plugin.redrawInit();
6477
- }
6478
- if (plugin.checkParticlePosition) {
6479
- this.checkParticlePositionPlugins.push(plugin);
6480
- }
6481
- if (plugin.update) {
6482
- this.#updatePlugins.push(plugin);
6483
- }
6484
- if (plugin.particleUpdate) {
6485
- this.#particleUpdatePlugins.push(plugin);
6486
- }
6487
- if (plugin.postUpdate) {
6488
- this.#postUpdatePlugins.push(plugin);
6489
- }
6490
- if (plugin.particleReset) {
6491
- this.#particleResetPlugins.push(plugin);
6492
- }
6493
- if (plugin.postParticleUpdate) {
6494
- this.#postParticleUpdatePlugins.push(plugin);
6495
- }
6496
- }
6497
- await this.#container.initDrawersAndUpdaters();
6498
- for (const drawer of this.#container.effectDrawers.values()) {
6499
- await drawer.init?.(container);
6500
- }
6501
- for (const drawer of this.#container.shapeDrawers.values()) {
6502
- await drawer.init?.(container);
6503
- }
6504
- let handled = false;
6505
- for (const plugin of container.plugins) {
6506
- handled = plugin.particlesInitialization?.() ?? handled;
6507
- if (handled) {
6508
- break;
6509
- }
6510
- }
6511
- if (!handled) {
6512
- const particlesOptions = options.particles, groups = particlesOptions.groups;
6513
- for (const group in groups) {
6514
- const groupOptions = groups[group];
6515
- if (!groupOptions) {
6516
- continue;
6517
- }
6518
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
6519
- this.addParticle(undefined, groupOptions, group);
6520
- }
6521
- }
6522
- for (let i = this.count; i < particlesOptions.number.value; i++) {
6523
- this.addParticle();
6834
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
6835
+ this.#applyLimits(container.actualOptions.particles);
6836
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
6837
+ for (const group in groups) {
6838
+ const groupData = groups[group];
6839
+ if (groupData) {
6840
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
6524
6841
  }
6525
6842
  }
6843
+ await this.#initPlugins();
6526
6844
  }
6527
6845
  push(nb, position, overrideOptions, group) {
6528
6846
  for (let i = 0; i < nb; i++) {
@@ -6537,13 +6855,13 @@
6537
6855
  remove(particle, group, override) {
6538
6856
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
6539
6857
  }
6540
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
6858
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
6541
6859
  if (index < minIndex || index > this.count) {
6542
6860
  return;
6543
6861
  }
6544
6862
  let deleted = 0;
6545
6863
  for (let i = index; deleted < quantity && i < this.count; i++) {
6546
- if (this.#removeParticle(i, group, override)) {
6864
+ if (this.#removeParticle(i, group, override, matchGroup)) {
6547
6865
  i--;
6548
6866
  deleted++;
6549
6867
  }
@@ -6574,7 +6892,7 @@
6574
6892
  this.#resizeFactor = factor;
6575
6893
  }
6576
6894
  update(delta) {
6577
- this.grid.clear();
6895
+ this.#grid.clear();
6578
6896
  for (const plugin of this.#updatePlugins) {
6579
6897
  plugin.update?.(delta);
6580
6898
  }
@@ -6585,7 +6903,7 @@
6585
6903
  this.#updateParticlesPhase2(delta, particlesToDelete);
6586
6904
  if (particlesToDelete.size) {
6587
6905
  for (const particle of particlesToDelete) {
6588
- this.remove(particle);
6906
+ this.remove(particle, particle.group);
6589
6907
  }
6590
6908
  }
6591
6909
  this.#resizeFactor = undefined;
@@ -6596,12 +6914,7 @@
6596
6914
  #applyDensity(options, pluginsCount, group, groupOptions) {
6597
6915
  const numberOptions = options.number;
6598
6916
  if (!numberOptions.density.enable) {
6599
- if (group === undefined) {
6600
- this.#limit = numberOptions.limit.value;
6601
- }
6602
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
6603
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
6604
- }
6917
+ this.#applyLimits(options, group, groupOptions);
6605
6918
  return;
6606
6919
  }
6607
6920
  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);
@@ -6609,7 +6922,10 @@
6609
6922
  this.#limit = numberOptions.limit.value * densityFactor;
6610
6923
  }
6611
6924
  else {
6612
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
6925
+ this.#groupLimits.set(group, {
6926
+ limit: numberOptions.limit.value * densityFactor,
6927
+ mode: toEnumValue(exports.LimitMode, numberOptions.limit.mode, exports.LimitMode.delete),
6928
+ });
6613
6929
  }
6614
6930
  if (particlesCount < particlesNumber) {
6615
6931
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -6618,6 +6934,55 @@
6618
6934
  this.removeQuantity(particlesCount - particlesNumber, group);
6619
6935
  }
6620
6936
  }
6937
+ #applyLimits(options, group, groupOptions) {
6938
+ if (group === undefined) {
6939
+ this.#limit = options.number.limit.value;
6940
+ const groups = this.#container.actualOptions.particles.groups;
6941
+ for (const existingGroup of this.#groupLimits.keys()) {
6942
+ if (!(existingGroup in groups)) {
6943
+ this.#groupLimits.delete(existingGroup);
6944
+ }
6945
+ }
6946
+ }
6947
+ else {
6948
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
6949
+ if (limitValue > minLimit) {
6950
+ this.#groupLimits.set(group, {
6951
+ limit: limitValue,
6952
+ mode: toEnumValue(exports.LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, exports.LimitMode.delete),
6953
+ });
6954
+ }
6955
+ else {
6956
+ this.#groupLimits.delete(group);
6957
+ }
6958
+ }
6959
+ }
6960
+ #checkAndApplyLimits(group, currentCount) {
6961
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
6962
+ if (globalLimit > minLimit && globalMode === exports.LimitMode.wait && currentCount >= globalLimit) {
6963
+ return true;
6964
+ }
6965
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
6966
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === exports.LimitMode.wait) {
6967
+ const groupCount = this.filter(t => t.group === group).length;
6968
+ if (groupCount >= groupLimitEntry.limit) {
6969
+ return true;
6970
+ }
6971
+ }
6972
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === exports.LimitMode.delete) {
6973
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
6974
+ if (groupCountToRemove > minCount) {
6975
+ this.removeQuantity(groupCountToRemove, group);
6976
+ }
6977
+ }
6978
+ if (globalLimit > minLimit && globalMode === exports.LimitMode.delete) {
6979
+ const globalCountToRemove = this.count + countOffset - globalLimit;
6980
+ if (globalCountToRemove > minCount) {
6981
+ this.#removeAny(globalCountToRemove);
6982
+ }
6983
+ }
6984
+ return false;
6985
+ }
6621
6986
  #createBuckets(zLayers) {
6622
6987
  const bucketCount = Math.max(Math.floor(zLayers), one);
6623
6988
  return Array.from({ length: bucketCount }, () => []);
@@ -6640,6 +7005,70 @@
6640
7005
  }
6641
7006
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
6642
7007
  }
7008
+ async #initDrawersAndUpdaters() {
7009
+ const container = this.#container;
7010
+ await container.initDrawersAndUpdaters();
7011
+ for (const drawer of container.effectDrawers.values()) {
7012
+ await drawer.init?.(container);
7013
+ }
7014
+ for (const drawer of container.shapeDrawers.values()) {
7015
+ await drawer.init?.(container);
7016
+ }
7017
+ }
7018
+ async #initPlugins() {
7019
+ await this.#initPluginsArrays();
7020
+ await this.#initDrawersAndUpdaters();
7021
+ let handled = false;
7022
+ const container = this.#container;
7023
+ for (const plugin of container.plugins) {
7024
+ handled = plugin.particlesInitialization?.() ?? handled;
7025
+ if (handled) {
7026
+ break;
7027
+ }
7028
+ }
7029
+ if (handled) {
7030
+ return;
7031
+ }
7032
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
7033
+ for (const group in groups) {
7034
+ const groupOptions = groups[group];
7035
+ if (!groupOptions) {
7036
+ continue;
7037
+ }
7038
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
7039
+ this.addParticle(undefined, groupOptions, group);
7040
+ }
7041
+ }
7042
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
7043
+ this.addParticle();
7044
+ }
7045
+ }
7046
+ async #initPluginsArrays() {
7047
+ const container = this.#container;
7048
+ for (const plugin of container.plugins) {
7049
+ if (plugin.redrawInit) {
7050
+ await plugin.redrawInit();
7051
+ }
7052
+ if (plugin.checkParticlePosition) {
7053
+ this.checkParticlePositionPlugins.push(plugin);
7054
+ }
7055
+ if (plugin.update) {
7056
+ this.#updatePlugins.push(plugin);
7057
+ }
7058
+ if (plugin.particleUpdate) {
7059
+ this.#particleUpdatePlugins.push(plugin);
7060
+ }
7061
+ if (plugin.postUpdate) {
7062
+ this.#postUpdatePlugins.push(plugin);
7063
+ }
7064
+ if (plugin.particleReset) {
7065
+ this.#particleResetPlugins.push(plugin);
7066
+ }
7067
+ if (plugin.postParticleUpdate) {
7068
+ this.#postParticleUpdatePlugins.push(plugin);
7069
+ }
7070
+ }
7071
+ }
6643
7072
  #insertParticleIntoBucket(particle) {
6644
7073
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
6645
7074
  if (!bucket) {
@@ -6648,12 +7077,15 @@
6648
7077
  bucket.push(particle);
6649
7078
  this.#particleBuckets.set(particle.id, bucketIndex);
6650
7079
  }
6651
- #removeParticle(index, group, override) {
7080
+ #removeAny(quantity) {
7081
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
7082
+ }
7083
+ #removeParticle(index, group, override, matchGroup = true) {
6652
7084
  const particle = this.#array[index];
6653
7085
  if (!particle) {
6654
7086
  return false;
6655
7087
  }
6656
- if (particle.group !== group) {
7088
+ if (matchGroup && particle.group !== group) {
6657
7089
  return false;
6658
7090
  }
6659
7091
  this.#array.splice(index, deleteCount);
@@ -6740,7 +7172,7 @@
6740
7172
  particlesToDelete.add(particle);
6741
7173
  continue;
6742
7174
  }
6743
- this.grid.insert(particle);
7175
+ this.#grid.insert(particle);
6744
7176
  }
6745
7177
  return particlesToDelete;
6746
7178
  }
@@ -6812,6 +7244,7 @@
6812
7244
  effectDrawers;
6813
7245
  fpsLimit;
6814
7246
  hdr;
7247
+ hdrMode;
6815
7248
  id;
6816
7249
  pageHidden;
6817
7250
  particleCreatedPlugins;
@@ -6819,6 +7252,7 @@
6819
7252
  particlePositionPlugins;
6820
7253
  particleUpdaters;
6821
7254
  particles;
7255
+ peakNits;
6822
7256
  plugins;
6823
7257
  retina;
6824
7258
  shapeDrawers;
@@ -6849,6 +7283,8 @@
6849
7283
  this.id = Symbol(id);
6850
7284
  this.fpsLimit = 120;
6851
7285
  this.hdr = false;
7286
+ this.hdrMode = exports.HdrMode.standard;
7287
+ this.peakNits = 400;
6852
7288
  this.#smooth = false;
6853
7289
  this.#delay = 0;
6854
7290
  this.#duration = 0;
@@ -6912,7 +7348,6 @@
6912
7348
  this.shapeDrawers = new Map();
6913
7349
  this.particleUpdaters = [];
6914
7350
  this.plugins.length = 0;
6915
- this.#pluginManager.clearPlugins(this);
6916
7351
  this.destroyed = true;
6917
7352
  this.#onDestroy(remove);
6918
7353
  this.dispatchEvent(exports.EventType.containerDestroyed);
@@ -6965,31 +7400,15 @@
6965
7400
  await this.initDrawersAndUpdaters();
6966
7401
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
6967
7402
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
6968
- this.plugins.length = 0;
6969
- this.particleDestroyedPlugins.length = 0;
6970
- this.particleCreatedPlugins.length = 0;
6971
- this.particlePositionPlugins.length = 0;
6972
- for (const [plugin, containerPlugin] of allContainerPlugins) {
6973
- if (plugin.needsPlugin(this.actualOptions)) {
6974
- this.plugins.push(containerPlugin);
6975
- if (containerPlugin.particleCreated) {
6976
- this.particleCreatedPlugins.push(containerPlugin);
6977
- }
6978
- if (containerPlugin.particleDestroyed) {
6979
- this.particleDestroyedPlugins.push(containerPlugin);
6980
- }
6981
- if (containerPlugin.particlePosition) {
6982
- this.particlePositionPlugins.push(containerPlugin);
6983
- }
6984
- }
6985
- }
7403
+ this.#initPlugins(allContainerPlugins);
6986
7404
  this.retina.init();
6987
7405
  this.canvas.init();
6988
7406
  this.updateActualOptions();
6989
7407
  this.canvas.initBackground();
6990
7408
  this.canvas.resize();
6991
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
6992
- this.hdr = hdr;
7409
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
7410
+ this.hdrMode = toEnumValue(exports.HdrMode, hdrOptions.mode, exports.HdrMode.standard);
7411
+ this.peakNits = hdrOptions.peakNits;
6993
7412
  this.zLayers = zLayers;
6994
7413
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
6995
7414
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -7009,9 +7428,9 @@
7009
7428
  }
7010
7429
  async initDrawersAndUpdaters() {
7011
7430
  const pluginManager = this.#pluginManager;
7012
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
7013
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
7014
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
7431
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
7432
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
7433
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
7015
7434
  }
7016
7435
  pause() {
7017
7436
  if (!guardCheck(this)) {
@@ -7122,6 +7541,27 @@
7122
7541
  }
7123
7542
  return refresh;
7124
7543
  }
7544
+ #initPlugins(allContainerPlugins) {
7545
+ this.plugins.length = 0;
7546
+ this.particleDestroyedPlugins.length = 0;
7547
+ this.particleCreatedPlugins.length = 0;
7548
+ this.particlePositionPlugins.length = 0;
7549
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
7550
+ if (!plugin.needsPlugin(this.actualOptions)) {
7551
+ continue;
7552
+ }
7553
+ this.plugins.push(containerPlugin);
7554
+ if (containerPlugin.particleCreated) {
7555
+ this.particleCreatedPlugins.push(containerPlugin);
7556
+ }
7557
+ if (containerPlugin.particleDestroyed) {
7558
+ this.particleDestroyedPlugins.push(containerPlugin);
7559
+ }
7560
+ if (containerPlugin.particlePosition) {
7561
+ this.particlePositionPlugins.push(containerPlugin);
7562
+ }
7563
+ }
7564
+ }
7125
7565
  #nextFrame(timestamp) {
7126
7566
  try {
7127
7567
  if (!this.#smooth &&
@@ -7428,11 +7868,11 @@
7428
7868
  }
7429
7869
  }
7430
7870
  async #init() {
7431
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
7432
- if (!availablePathGenerators) {
7871
+ const pluginManager = this.#pluginManager;
7872
+ if (!pluginManager.initializers.pathGenerators) {
7433
7873
  return;
7434
7874
  }
7435
- this.availablePathGenerators = availablePathGenerators;
7875
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
7436
7876
  this.pathGenerators = new Map();
7437
7877
  for (const pathGenerator of this.pathGenerators.values()) {
7438
7878
  pathGenerator.init();
@@ -7445,55 +7885,6 @@
7445
7885
  MovePluginInstance: MovePluginInstance
7446
7886
  });
7447
7887
 
7448
- class EmittersPluginInstance {
7449
- #container;
7450
- #instancesManager;
7451
- constructor(instancesManager, container) {
7452
- this.#instancesManager = instancesManager;
7453
- this.#container = container;
7454
- this.#instancesManager.initContainer(container);
7455
- }
7456
- async init() {
7457
- const emittersOptions = this.#container.actualOptions.emitters;
7458
- if (isArray(emittersOptions)) {
7459
- for (const emitterOptions of emittersOptions) {
7460
- await this.#instancesManager.addEmitter(this.#container, emitterOptions);
7461
- }
7462
- }
7463
- else {
7464
- await this.#instancesManager.addEmitter(this.#container, emittersOptions);
7465
- }
7466
- }
7467
- pause() {
7468
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
7469
- emitter.pause();
7470
- }
7471
- }
7472
- play() {
7473
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
7474
- emitter.play();
7475
- }
7476
- }
7477
- resize() {
7478
- for (const emitter of this.#instancesManager.getArray(this.#container)) {
7479
- emitter.resize();
7480
- }
7481
- }
7482
- stop() {
7483
- this.#instancesManager.clear(this.#container);
7484
- }
7485
- update(delta) {
7486
- this.#instancesManager.getArray(this.#container).forEach(emitter => {
7487
- emitter.update(delta);
7488
- });
7489
- }
7490
- }
7491
-
7492
- var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
7493
- __proto__: null,
7494
- EmittersPluginInstance: EmittersPluginInstance
7495
- });
7496
-
7497
7888
  const shapeGenerators = new Map();
7498
7889
  class ShapeManager {
7499
7890
  addShapeGenerator(name, generator) {
@@ -7523,14 +7914,21 @@
7523
7914
  this.#pluginManager = pluginManager;
7524
7915
  }
7525
7916
  async addEmitter(container, options, position) {
7526
- const emitterOptions = new Emitter();
7527
- emitterOptions.load(options);
7528
- const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
7529
- this.removeEmitter(container, emitter);
7530
- }, emitterOptions, position);
7531
- await emitter.init();
7532
- this.getArray(container).push(emitter);
7533
- return emitter;
7917
+ return this.addEmitters(container, [{ options, position }]).then(t => t[defaultIndex]);
7918
+ }
7919
+ async addEmitters(container, emitters) {
7920
+ const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), res = [];
7921
+ for (const { options, position } of emitters) {
7922
+ const emitterOptions = new Emitter();
7923
+ emitterOptions.load(options);
7924
+ const emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
7925
+ this.removeEmitter(container, emitter);
7926
+ }, emitterOptions, position);
7927
+ await emitter.init();
7928
+ this.getArray(container).push(emitter);
7929
+ res.push(emitter);
7930
+ }
7931
+ return res;
7534
7932
  }
7535
7933
  clear(container) {
7536
7934
  this.initContainer(container);
@@ -7557,6 +7955,7 @@
7557
7955
  : array.find(t => t.name === idxOrName);
7558
7956
  };
7559
7957
  container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
7958
+ container.addEmitters = async (emitters) => this.addEmitters(container, emitters);
7560
7959
  container.removeEmitter = (idxOrName) => {
7561
7960
  const emitter = container.getEmitter?.(idxOrName);
7562
7961
  if (emitter) {
@@ -7577,7 +7976,7 @@
7577
7976
  };
7578
7977
  }
7579
7978
  removeEmitter(container, emitter) {
7580
- const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
7979
+ const index = this.getArray(container).indexOf(emitter), deleteCount = 1;
7581
7980
  if (index >= minIndex) {
7582
7981
  this.getArray(container).splice(index, deleteCount);
7583
7982
  }
@@ -8082,6 +8481,7 @@
8082
8481
  #particlesOptions;
8083
8482
  #paused;
8084
8483
  #pluginManager;
8484
+ #positionOverride = false;
8085
8485
  #removeCallback;
8086
8486
  #resizeObserver;
8087
8487
  #shape;
@@ -8158,6 +8558,31 @@
8158
8558
  });
8159
8559
  this.play();
8160
8560
  }
8561
+ draw(context) {
8562
+ if (!this.options.draw || !this.#shape) {
8563
+ return;
8564
+ }
8565
+ const container = this.#container, fillEnabled = this.options.spawn.fill?.enable ?? true;
8566
+ context.save();
8567
+ context.beginPath();
8568
+ if (fillEnabled) {
8569
+ context.fillStyle = this.spawnFillColor
8570
+ ? getStyleFromHsl(this.spawnFillColor, container.hdr, this.spawnFillOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode)
8571
+ : getStyleFromRgb({ r: 0, g: 0, b: 0 }, container.hdr, defaultOpacity$1, container.peakNits, container.hdrMode);
8572
+ }
8573
+ if (this.spawnStrokeColor) {
8574
+ context.strokeStyle = getStyleFromHsl(this.spawnStrokeColor, container.hdr, this.spawnStrokeOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode);
8575
+ context.lineWidth = this.spawnStrokeWidth ?? defaultStrokeWidth;
8576
+ }
8577
+ this.#shape.draw?.(context);
8578
+ if (fillEnabled) {
8579
+ context.fill();
8580
+ }
8581
+ if (this.spawnStrokeColor) {
8582
+ context.stroke();
8583
+ }
8584
+ context.restore();
8585
+ }
8161
8586
  externalPause() {
8162
8587
  this.#paused = true;
8163
8588
  this.pause();
@@ -8195,11 +8620,14 @@
8195
8620
  }
8196
8621
  }
8197
8622
  resize() {
8198
- const initialPosition = this.#initialPosition, container = this.#container;
8199
- this.position =
8200
- initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
8201
- ? initialPosition
8202
- : this.#calcPosition();
8623
+ const container = this.#container;
8624
+ if (!this.#positionOverride) {
8625
+ const initialPosition = this.#initialPosition;
8626
+ this.position =
8627
+ initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
8628
+ ? initialPosition
8629
+ : this.#calcPosition();
8630
+ }
8203
8631
  this.#size = this.#calcSize();
8204
8632
  this.size =
8205
8633
  this.#size.mode === exports.PixelMode.percent
@@ -8210,6 +8638,11 @@
8210
8638
  : { width: this.#size.width, height: this.#size.height };
8211
8639
  this.#shape?.resize(this.position, this.size);
8212
8640
  }
8641
+ setPosition(position) {
8642
+ this.#positionOverride = true;
8643
+ this.position = { ...position };
8644
+ this.#shape?.resize(this.position, this.size);
8645
+ }
8213
8646
  update(delta) {
8214
8647
  if (this.#paused) {
8215
8648
  return;
@@ -8409,8 +8842,10 @@
8409
8842
  exports.BaseRange = BaseRange;
8410
8843
  exports.Circle = Circle;
8411
8844
  exports.ColorAnimation = ColorAnimation;
8845
+ exports.ErrorCodes = ErrorCodes$2;
8412
8846
  exports.Fill = Fill;
8413
8847
  exports.FullScreen = FullScreen;
8848
+ exports.HDROptions = HDROptions;
8414
8849
  exports.HslAnimation = HslAnimation;
8415
8850
  exports.Move = Move;
8416
8851
  exports.MoveAngle = MoveAngle;
@@ -8439,6 +8874,7 @@
8439
8874
  exports.Vector = Vector;
8440
8875
  exports.Vector3d = Vector3d;
8441
8876
  exports.ZIndex = ZIndex;
8877
+ exports.addErrorMessages = addErrorMessages;
8442
8878
  exports.alterHsl = alterHsl;
8443
8879
  exports.animate = animate;
8444
8880
  exports.areBoundsInside = areBoundsInside;
@@ -8461,7 +8897,7 @@
8461
8897
  exports.countOffset = countOffset;
8462
8898
  exports.decayOffset = decayOffset;
8463
8899
  exports.deepExtend = deepExtend;
8464
- exports.defaultAlpha = defaultAlpha$1;
8900
+ exports.defaultAlpha = defaultAlpha;
8465
8901
  exports.defaultAngle = defaultAngle;
8466
8902
  exports.defaultCompositeValue = defaultCompositeValue;
8467
8903
  exports.defaultDensityFactor = defaultDensityFactor;
@@ -8486,12 +8922,17 @@
8486
8922
  exports.empty = empty;
8487
8923
  exports.executeOnSingleOrMultiple = executeOnSingleOrMultiple;
8488
8924
  exports.fireworks = fireworks;
8925
+ exports.fullPercent = fullPercent;
8489
8926
  exports.generatedAttribute = generatedAttribute;
8490
8927
  exports.generatedFalse = generatedFalse;
8491
8928
  exports.generatedTrue = generatedTrue;
8929
+ exports.getCanvasFromContainer = getCanvasFromContainer;
8930
+ exports.getDataFromUrl = getDataFromUrl;
8492
8931
  exports.getDistance = getDistance;
8493
8932
  exports.getDistanceSq = getDistanceSq;
8494
8933
  exports.getDistances = getDistances;
8934
+ exports.getDomContainer = getDomContainer;
8935
+ exports.getErrorMessage = getErrorMessage;
8495
8936
  exports.getFullScreenStyle = getFullScreenStyle;
8496
8937
  exports.getHslAnimationFromHsl = getHslAnimationFromHsl;
8497
8938
  exports.getHslFromAnimation = getHslFromAnimation;
@@ -8523,6 +8964,7 @@
8523
8964
  exports.inverseFactorNumerator = inverseFactorNumerator;
8524
8965
  exports.isArray = isArray;
8525
8966
  exports.isBoolean = isBoolean;
8967
+ exports.isEnumValue = isEnumValue;
8526
8968
  exports.isFunction = isFunction;
8527
8969
  exports.isInArray = isInArray;
8528
8970
  exports.isNull = isNull;
@@ -8555,7 +8997,7 @@
8555
8997
  exports.minFpsLimit = minFpsLimit;
8556
8998
  exports.minIndex = minIndex;
8557
8999
  exports.minLimit = minLimit;
8558
- exports.minRadius = minRadius$1;
9000
+ exports.minRadius = minRadius;
8559
9001
  exports.minStrokeWidth = minStrokeWidth;
8560
9002
  exports.minVelocity = minVelocity;
8561
9003
  exports.minZ = minZ;
@@ -8593,6 +9035,7 @@
8593
9035
  exports.stringToAlpha = stringToAlpha;
8594
9036
  exports.stringToRgb = stringToRgb;
8595
9037
  exports.threeQuarter = threeQuarter;
9038
+ exports.toEnumValue = toEnumValue;
8596
9039
  exports.triple = triple;
8597
9040
  exports.tryCountIncrement = tryCountIncrement;
8598
9041
  exports.tsParticles = tsParticles;
@@ -8601,6 +9044,7 @@
8601
9044
  exports.visibilityChangeEvent = visibilityChangeEvent;
8602
9045
  exports.zIndexFactorOffset = zIndexFactorOffset;
8603
9046
 
8604
- }));
9047
+ })(g.__tsParticlesInternals.bundles.fireworks = g.__tsParticlesInternals.bundles.fireworks || {});
9048
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
9049
+
8605
9050
  Object.assign(globalThis.window || globalThis, { fireworks: (globalThis.__tsParticlesInternals.bundles.fireworks || {}).fireworks });
8606
- delete (globalThis.window || globalThis).tsparticlesInternalExports;