@tsparticles/preset-confetti-explosions 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,35 @@
1
- (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.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.presets = global.__tsParticlesInternals.presets || {}, global.__tsParticlesInternals.presets.confettiExplosions = global.__tsParticlesInternals.presets.confettiExplosions || {})));
7
- })(this, (function (exports) { 'use strict';
8
-
9
- const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
10
- x: 0,
11
- y: 0,
12
- z: 0,
13
- }, defaultTransform = {
14
- a: 1,
15
- b: 0,
16
- c: 0,
17
- d: 1,
18
- }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
1
+ (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
+ (function (g) {
3
+ /* Preset v4.5.0 */
4
+ g.__tsParticlesInternals = g.__tsParticlesInternals || {};
5
+ g.__tsParticlesInternals.presets = g.__tsParticlesInternals.presets || {};
6
+ (function (exports) {
7
+ 'use strict';
8
+
9
+ const errorPrefix = "tsParticles - Error", codedErrorPattern = /^\[tsParticles Error (TSP-\d+)\]\s*/, fullMatchIndex = 0, codeIndex = 1;
10
+ const wrap = (fn) => (...args) => {
11
+ fn(...args);
12
+ }, _logger = {
13
+ debug: wrap(console.debug),
14
+ error: (message, ...optionalParams) => {
15
+ if (typeof message === "string") {
16
+ const match = codedErrorPattern.exec(message);
17
+ if (match?.[codeIndex]) {
18
+ console.error(`tsParticles - ${match[codeIndex]} - ${message.slice(match[fullMatchIndex].length)}`, ...optionalParams);
19
+ return;
20
+ }
21
+ }
22
+ console.error(`${errorPrefix} - ${message}`, ...optionalParams);
23
+ },
24
+ info: wrap(console.info),
25
+ log: wrap(console.log),
26
+ trace: wrap(console.trace),
27
+ verbose: wrap(console.log),
28
+ warning: wrap(console.warn),
29
+ };
30
+ function getLogger() {
31
+ return _logger;
32
+ }
19
33
 
20
34
  var MoveDirection;
21
35
  (function (MoveDirection) {
@@ -32,6 +46,17 @@
32
46
  MoveDirection["inside"] = "inside";
33
47
  })(MoveDirection || (MoveDirection = {}));
34
48
 
49
+ const generatedAttribute = "generated", fullPercent = "100%", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
50
+ x: 0,
51
+ y: 0,
52
+ z: 0,
53
+ }, defaultTransform = {
54
+ a: 1,
55
+ b: 0,
56
+ c: 0,
57
+ d: 1,
58
+ }, randomColorValue = "random", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;
59
+
35
60
  function getZ(source) {
36
61
  return "z" in source ? source.z : originPoint.z;
37
62
  }
@@ -147,6 +172,12 @@
147
172
  function isNumber(arg) {
148
173
  return typeof arg === "number";
149
174
  }
175
+ function isEnumValue(enumObject, arg) {
176
+ return Object.values(enumObject).some(enumValue => enumValue === arg);
177
+ }
178
+ function toEnumValue(enumObject, arg, defaultValue) {
179
+ return isEnumValue(enumObject, arg) ? arg : defaultValue;
180
+ }
150
181
  function isObject(arg) {
151
182
  return typeof arg === "object" && arg !== null;
152
183
  }
@@ -283,11 +314,61 @@
283
314
  };
284
315
  }
285
316
  function parseAlpha(input) {
286
- const defaultAlpha = 1;
287
317
  if (!input) {
288
318
  return defaultAlpha;
289
319
  }
290
- return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
320
+ return input.endsWith("%") ? Number.parseFloat(input) / percentDenominator : Number.parseFloat(input);
321
+ }
322
+
323
+ const ErrorCodes$2 = {
324
+ engineVersionMismatch: "TSP-1001",
325
+ particlePositionNotFound: "TSP-1002",
326
+ pluginRegisterAfterLoad: "TSP-1003",
327
+ offscreenCanvasUnsupported: "TSP-1101",
328
+ offscreenCanvasTransferFailed: "TSP-1102",
329
+ hdrEnableInvalid: "TSP-1201",
330
+ hdrModeInvalid: "TSP-1202",
331
+ hdrPeakNitsInvalid: "TSP-1203",
332
+ };
333
+
334
+ const messages = {
335
+ [ErrorCodes$2.engineVersionMismatch]: "The tsParticles version is different from the loaded plugins version. Engine version: {0}. Plugin version: {1}",
336
+ [ErrorCodes$2.particlePositionNotFound]: "a valid position cannot be found for particle",
337
+ [ErrorCodes$2.pluginRegisterAfterLoad]: "Register plugins can only be done before calling tsParticles.load()",
338
+ [ErrorCodes$2.offscreenCanvasUnsupported]: "OffscreenCanvas is required but not supported by this browser",
339
+ [ErrorCodes$2.offscreenCanvasTransferFailed]: "OffscreenCanvas transfer failed",
340
+ [ErrorCodes$2.hdrEnableInvalid]: 'Invalid HDR "enable" value: expected a boolean, got "{0}"',
341
+ [ErrorCodes$2.hdrModeInvalid]: 'Invalid HDR "mode" value: expected one of {0}, got "{1}"',
342
+ [ErrorCodes$2.hdrPeakNitsInvalid]: 'Invalid HDR "peakNits" value: expected a positive number, got "{0}"',
343
+ };
344
+
345
+ let registeredMessages;
346
+ const ensureRegisteredMessages = () => {
347
+ registeredMessages ??= new Map(Object.entries(messages));
348
+ return registeredMessages;
349
+ }, toStringValue$1 = (value) => String(value), format = (template, args) => {
350
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
351
+ const arg = args[Number(index)];
352
+ return arg === undefined ? match : toStringValue$1(arg);
353
+ });
354
+ };
355
+ function addErrorMessages(extraMessages) {
356
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
357
+ return;
358
+ }
359
+ const catalog = ensureRegisteredMessages();
360
+ for (const [code, message] of Object.entries(extraMessages)) {
361
+ if (message !== undefined) {
362
+ catalog.set(code, message);
363
+ }
364
+ }
365
+ }
366
+ function getErrorMessage(code, ...args) {
367
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
368
+ return `[tsParticles Error ${code}] https://particles.js.org/errors/#${code}`;
369
+ }
370
+ const template = ensureRegisteredMessages().get(code) ?? `Unknown error code ${code}`;
371
+ return format(template, args);
291
372
  }
292
373
 
293
374
  var OutModeDirection;
@@ -304,7 +385,6 @@
304
385
  PixelMode["percent"] = "percent";
305
386
  })(PixelMode || (PixelMode = {}));
306
387
 
307
- const minRadius = 0;
308
388
  function isForbiddenKey(key) {
309
389
  return key === "__proto__" || key === "constructor" || key === "prototype";
310
390
  }
@@ -500,22 +580,84 @@
500
580
  element.removeEventListener(event, handler, removeOptions);
501
581
  }
502
582
  }
503
- async function getItemsFromInitializer(container, map, initializers, force = false) {
504
- let res = map.get(container);
505
- if (!res || force) {
506
- res = await Promise.all([...initializers.values()].map(t => t(container)));
507
- map.set(container, res);
583
+ async function getItemsFromInitializer(container, initializers) {
584
+ return await Promise.all([...initializers.values()].map(t => t(container)));
585
+ }
586
+ async function getItemMapFromInitializer(container, initializers) {
587
+ const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
588
+ return new Map(entries);
589
+ }
590
+ async function getDataFromUrl(data) {
591
+ const url = itemFromSingleOrMultiple(data.url, data.index);
592
+ if (!url) {
593
+ return data.fallback;
508
594
  }
509
- return res;
595
+ try {
596
+ const response = await fetch(url);
597
+ if (response.ok) {
598
+ const current = (await response.json());
599
+ if (isSourceOptionsValue(current)) {
600
+ return current;
601
+ }
602
+ getLogger().error("invalid configuration data while retrieving config file");
603
+ }
604
+ else {
605
+ getLogger().error(`${response.status.toString()} while retrieving config file`);
606
+ }
607
+ }
608
+ catch (error) {
609
+ getLogger().error(`error while retrieving config file: ${error}`);
610
+ }
611
+ return data.fallback;
510
612
  }
511
- async function getItemMapFromInitializer(container, map, initializers, force = false) {
512
- let res = map.get(container);
513
- if (!res || force) {
514
- const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
515
- res = new Map(entries);
516
- map.set(container, res);
613
+ function isSourceOptionsValue(value) {
614
+ if (isArray(value)) {
615
+ return value.every((entry) => isObject(entry) && !isArray(entry));
517
616
  }
518
- return res;
617
+ return isObject(value) && !isArray(value);
618
+ }
619
+ function getCanvasFromContainer(domContainer) {
620
+ let canvasEl;
621
+ const documentSafe = safeDocument(), isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
622
+ if (isCanvas) {
623
+ canvasEl = domContainer;
624
+ canvasEl.dataset[generatedAttribute] ??= generatedFalse;
625
+ if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
626
+ canvasEl.style.width ||= fullPercent;
627
+ canvasEl.style.height ||= fullPercent;
628
+ canvasEl.style.pointerEvents = "none";
629
+ canvasEl.style.setProperty("pointer-events", "none");
630
+ }
631
+ }
632
+ else {
633
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
634
+ if (foundCanvas) {
635
+ canvasEl = foundCanvas;
636
+ canvasEl.dataset[generatedAttribute] = generatedFalse;
637
+ }
638
+ else {
639
+ canvasEl = documentSafe.createElement(canvasTag);
640
+ canvasEl.dataset[generatedAttribute] = generatedTrue;
641
+ domContainer.appendChild(canvasEl);
642
+ }
643
+ canvasEl.style.width ||= fullPercent;
644
+ canvasEl.style.height ||= fullPercent;
645
+ canvasEl.style.pointerEvents = "none";
646
+ canvasEl.style.setProperty("pointer-events", "none");
647
+ }
648
+ return canvasEl;
649
+ }
650
+ function getDomContainer(id, source) {
651
+ const documentSafe = safeDocument();
652
+ let domContainer = source ?? documentSafe.getElementById(id);
653
+ if (domContainer) {
654
+ return domContainer;
655
+ }
656
+ domContainer = documentSafe.createElement("canvas");
657
+ domContainer.id = id;
658
+ domContainer.dataset[generatedAttribute] = generatedTrue;
659
+ documentSafe.body.append(domContainer);
660
+ return domContainer;
519
661
  }
520
662
 
521
663
  class EventDispatcher {
@@ -586,7 +728,6 @@
586
728
  class PluginManager {
587
729
  colorManagers = new Map();
588
730
  easingFunctions = new Map();
589
- effectDrawers = new Map();
590
731
  initializers = {
591
732
  effects: new Map(),
592
733
  shapes: new Map(),
@@ -595,8 +736,6 @@
595
736
  palettes = new Map();
596
737
  plugins = [];
597
738
  presets = new Map();
598
- shapeDrawers = new Map();
599
- updaters = new Map();
600
739
  #allLoadersSet = new Set();
601
740
  #configs = new Map();
602
741
  #engine;
@@ -614,57 +753,79 @@
614
753
  }
615
754
  return res;
616
755
  }
756
+ get initialized() {
757
+ return this.#initialized;
758
+ }
617
759
  addColorManager(name, manager) {
760
+ if (this.#initialized) {
761
+ return;
762
+ }
618
763
  this.colorManagers.set(name, manager);
619
764
  }
620
765
  addConfig(config) {
766
+ if (this.#initialized) {
767
+ return;
768
+ }
621
769
  const key = config.key ?? config.name ?? "default";
622
770
  this.#configs.set(key, config);
623
771
  this.#engine.dispatchEvent(EventType.configAdded, { data: { name: key, config } });
624
772
  }
625
773
  addEasing(name, easing) {
774
+ if (this.#initialized) {
775
+ return;
776
+ }
626
777
  if (this.easingFunctions.get(name)) {
627
778
  return;
628
779
  }
629
780
  this.easingFunctions.set(name, easing);
630
781
  }
631
782
  addEffect(effect, drawer) {
783
+ if (this.#initialized) {
784
+ return;
785
+ }
632
786
  this.initializers.effects.set(effect, drawer);
633
787
  }
634
788
  addPalette(name, palette) {
789
+ if (this.#initialized) {
790
+ return;
791
+ }
635
792
  this.palettes.set(name, palette);
636
793
  }
637
794
  addParticleUpdater(name, updaterInitializer) {
795
+ if (this.#initialized) {
796
+ return;
797
+ }
638
798
  this.initializers.updaters.set(name, updaterInitializer);
639
799
  }
640
800
  addPlugin(plugin) {
801
+ if (this.#initialized) {
802
+ return;
803
+ }
641
804
  if (this.getPlugin(plugin.id)) {
642
805
  return;
643
806
  }
644
807
  this.plugins.push(plugin);
645
808
  }
646
809
  addPreset(preset, options, override = false) {
810
+ if (this.#initialized) {
811
+ return;
812
+ }
647
813
  if (!(override || !this.getPreset(preset))) {
648
814
  return;
649
815
  }
650
816
  this.presets.set(preset, options);
651
817
  }
652
818
  addShape(shapes, drawer) {
819
+ if (this.#initialized) {
820
+ return;
821
+ }
653
822
  for (const shape of shapes) {
654
823
  this.initializers.shapes.set(shape, drawer);
655
824
  }
656
825
  }
657
- clearPlugins(container) {
658
- this.effectDrawers.delete(container);
659
- this.shapeDrawers.delete(container);
660
- this.updaters.delete(container);
661
- }
662
826
  getEasing(name) {
663
827
  return this.easingFunctions.get(name) ?? ((value) => value);
664
828
  }
665
- getEffectDrawers(container, force = false) {
666
- return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
667
- }
668
829
  getPalette(name) {
669
830
  return this.palettes.get(name);
670
831
  }
@@ -674,12 +835,6 @@
674
835
  getPreset(preset) {
675
836
  return this.presets.get(preset);
676
837
  }
677
- async getShapeDrawers(container, force = false) {
678
- return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
679
- }
680
- async getUpdaters(container, force = false) {
681
- return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
682
- }
683
838
  async init() {
684
839
  if (this.#initialized || this.#isRunningLoaders) {
685
840
  return;
@@ -698,16 +853,9 @@
698
853
  this.#initialized = true;
699
854
  }
700
855
  }
701
- loadParticlesOptions(container, options, ...sourceOptions) {
702
- const updaters = this.updaters.get(container);
703
- if (!updaters) {
704
- return;
705
- }
706
- updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
707
- }
708
856
  async register(...loaders) {
709
857
  if (this.#initialized) {
710
- throw new Error("Register plugins can only be done before calling tsParticles.load()");
858
+ throw new Error(getErrorMessage(ErrorCodes$2.pluginRegisterAfterLoad));
711
859
  }
712
860
  for (const loader of loaders) {
713
861
  if (this.#isRunningLoaders) {
@@ -719,88 +867,15 @@
719
867
  }
720
868
  }
721
869
  async #runLoader(loader, executed, allLoaders) {
722
- if (executed.has(loader))
870
+ if (executed.has(loader)) {
723
871
  return;
872
+ }
724
873
  executed.add(loader);
725
874
  allLoaders.add(loader);
726
875
  await loader(this.#engine);
727
876
  }
728
877
  }
729
878
 
730
- const errorPrefix = "tsParticles - Error";
731
- const wrap = (fn) => (...args) => {
732
- fn(...args);
733
- }, _logger = {
734
- debug: wrap(console.debug),
735
- error: (message, ...optionalParams) => {
736
- console.error(`${errorPrefix} - ${message}`, ...optionalParams);
737
- },
738
- info: wrap(console.info),
739
- log: wrap(console.log),
740
- trace: wrap(console.trace),
741
- verbose: wrap(console.log),
742
- warning: wrap(console.warn),
743
- };
744
- function getLogger() {
745
- return _logger;
746
- }
747
-
748
- const fullPercent = "100%";
749
- async function getDataFromUrl(data) {
750
- const url = itemFromSingleOrMultiple(data.url, data.index);
751
- if (!url) {
752
- return data.fallback;
753
- }
754
- const response = await fetch(url);
755
- if (response.ok) {
756
- return (await response.json());
757
- }
758
- getLogger().error(`${response.status.toString()} while retrieving config file`);
759
- return data.fallback;
760
- }
761
- const getCanvasFromContainer = (domContainer) => {
762
- const documentSafe = safeDocument();
763
- let canvasEl;
764
- const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
765
- if (isCanvas) {
766
- canvasEl = domContainer;
767
- canvasEl.dataset[generatedAttribute] ??= generatedFalse;
768
- if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
769
- canvasEl.style.width ||= fullPercent;
770
- canvasEl.style.height ||= fullPercent;
771
- canvasEl.style.pointerEvents = "none";
772
- canvasEl.style.setProperty("pointer-events", "none");
773
- }
774
- }
775
- else {
776
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
777
- if (foundCanvas) {
778
- canvasEl = foundCanvas;
779
- canvasEl.dataset[generatedAttribute] = generatedFalse;
780
- }
781
- else {
782
- canvasEl = documentSafe.createElement(canvasTag);
783
- canvasEl.dataset[generatedAttribute] = generatedTrue;
784
- domContainer.appendChild(canvasEl);
785
- }
786
- canvasEl.style.width ||= fullPercent;
787
- canvasEl.style.height ||= fullPercent;
788
- canvasEl.style.pointerEvents = "none";
789
- canvasEl.style.setProperty("pointer-events", "none");
790
- }
791
- return canvasEl;
792
- }, getDomContainer = (id, source) => {
793
- const documentSafe = safeDocument();
794
- let domContainer = source ?? documentSafe.getElementById(id);
795
- if (domContainer) {
796
- return domContainer;
797
- }
798
- domContainer = documentSafe.createElement("canvas");
799
- domContainer.id = id;
800
- domContainer.dataset[generatedAttribute] = generatedTrue;
801
- documentSafe.body.append(domContainer);
802
- return domContainer;
803
- };
804
879
  class Engine {
805
880
  pluginManager = new PluginManager(this);
806
881
  #domArray = [];
@@ -810,7 +885,7 @@
810
885
  return this.#domArray;
811
886
  }
812
887
  get version() {
813
- return "4.3.2";
888
+ return "4.5.0";
814
889
  }
815
890
  addEventListener(type, listener) {
816
891
  this.#eventDispatcher.addEventListener(type, listener);
@@ -819,7 +894,7 @@
819
894
  if (this.version === pluginVersion) {
820
895
  return;
821
896
  }
822
- throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
897
+ throw new Error(getErrorMessage(ErrorCodes$2.engineVersionMismatch, this.version, pluginVersion));
823
898
  }
824
899
  dispatchEvent(type, args) {
825
900
  this.#eventDispatcher.dispatchEvent(type, args);
@@ -891,6 +966,10 @@
891
966
  }
892
967
 
893
968
  function initEngine() {
969
+ const existing = globalThis.tsParticles;
970
+ if (existing?.pluginManager) {
971
+ return existing;
972
+ }
894
973
  return new Engine();
895
974
  }
896
975
 
@@ -988,6 +1067,15 @@
988
1067
  AnimationMode["random"] = "random";
989
1068
  })(AnimationMode || (AnimationMode = {}));
990
1069
 
1070
+ var HdrMode;
1071
+ (function (HdrMode) {
1072
+ HdrMode["standard"] = "standard";
1073
+ HdrMode["natural"] = "natural";
1074
+ HdrMode["vivid"] = "vivid";
1075
+ HdrMode["cinematic"] = "cinematic";
1076
+ HdrMode["dynamic"] = "dynamic";
1077
+ })(HdrMode || (HdrMode = {}));
1078
+
991
1079
  var LimitMode;
992
1080
  (function (LimitMode) {
993
1081
  LimitMode["delete"] = "delete";
@@ -1055,20 +1143,6 @@
1055
1143
  DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1056
1144
  })(DrawLayer || (DrawLayer = {}));
1057
1145
 
1058
- class OptionLoader {
1059
- load(data) {
1060
- if (isNull(data)) {
1061
- return;
1062
- }
1063
- this.doLoad(data);
1064
- }
1065
- }
1066
- function loadOptions(options, ...sourceOptionsArr) {
1067
- for (const sourceOptions of sourceOptionsArr) {
1068
- options.load(sourceOptions);
1069
- }
1070
- }
1071
-
1072
1146
  function loadProperty(obj, key, value) {
1073
1147
  if (value !== undefined) {
1074
1148
  obj[key] = value;
@@ -1100,6 +1174,20 @@
1100
1174
  }
1101
1175
  }
1102
1176
 
1177
+ class OptionLoader {
1178
+ load(data) {
1179
+ if (isNull(data)) {
1180
+ return;
1181
+ }
1182
+ this.doLoad(data);
1183
+ }
1184
+ }
1185
+ function loadOptions(options, ...sourceOptionsArr) {
1186
+ for (const sourceOptions of sourceOptionsArr) {
1187
+ options.load(sourceOptions);
1188
+ }
1189
+ }
1190
+
1103
1191
  class AnimationOptions extends OptionLoader {
1104
1192
  count = 0;
1105
1193
  decay = 0;
@@ -1243,6 +1331,28 @@
1243
1331
  }
1244
1332
  }
1245
1333
 
1334
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1335
+ class HDROptions extends OptionLoader {
1336
+ enable = true;
1337
+ mode = HdrMode.standard;
1338
+ peakNits = defaultPeakNits;
1339
+ doLoad(data) {
1340
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1341
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrEnableInvalid, String(data.enable)));
1342
+ }
1343
+ if (data.mode !== undefined && !isEnumValue(HdrMode, data.mode)) {
1344
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrModeInvalid, Object.values(HdrMode).join(", "), toStringValue(data.mode)));
1345
+ }
1346
+ if (data.peakNits !== undefined &&
1347
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1348
+ throw new Error(getErrorMessage(ErrorCodes$2.hdrPeakNitsInvalid, String(data.peakNits)));
1349
+ }
1350
+ loadProperty(this, "enable", data.enable);
1351
+ loadProperty(this, "mode", data.mode);
1352
+ loadProperty(this, "peakNits", data.peakNits);
1353
+ }
1354
+ }
1355
+
1246
1356
  class ResizeEvent extends OptionLoader {
1247
1357
  delay = 0.5;
1248
1358
  enable = true;
@@ -1613,12 +1723,10 @@
1613
1723
  plugin.loadParticlesOptions(this.#container, this, data);
1614
1724
  }
1615
1725
  }
1616
- const updaters = this.#pluginManager.updaters.get(this.#container);
1617
- if (updaters) {
1618
- for (const updater of updaters) {
1619
- if (updater.loadOptions) {
1620
- updater.loadOptions(this, data);
1621
- }
1726
+ const updaters = this.#container.particleUpdaters;
1727
+ for (const updater of updaters) {
1728
+ if (updater.loadOptions) {
1729
+ updater.loadOptions(this, data);
1622
1730
  }
1623
1731
  }
1624
1732
  }
@@ -1686,7 +1794,7 @@
1686
1794
  duration = 0;
1687
1795
  fpsLimit = 120;
1688
1796
  fullScreen;
1689
- hdr = true;
1797
+ hdr;
1690
1798
  key;
1691
1799
  name;
1692
1800
  palette;
@@ -1706,6 +1814,7 @@
1706
1814
  this.#container = container;
1707
1815
  this.background = new Background();
1708
1816
  this.fullScreen = new FullScreen();
1817
+ this.hdr = new HDROptions();
1709
1818
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1710
1819
  this.resize = new ResizeEvent();
1711
1820
  }
@@ -1728,7 +1837,15 @@
1728
1837
  loadProperty(this, "detectRetina", data.detectRetina);
1729
1838
  loadRangeProperty(this, "duration", data.duration);
1730
1839
  loadProperty(this, "fpsLimit", data.fpsLimit);
1731
- loadProperty(this, "hdr", data.hdr);
1840
+ const hdrData = data.hdr;
1841
+ if (isBoolean(hdrData)) {
1842
+ this.hdr.enable = hdrData;
1843
+ this.hdr.mode = HdrMode.standard;
1844
+ this.hdr.peakNits = 400;
1845
+ }
1846
+ else {
1847
+ this.hdr.load(hdrData);
1848
+ }
1732
1849
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1733
1850
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1734
1851
  loadProperty(this, "zLayers", data.zLayers);
@@ -1771,7 +1888,7 @@
1771
1888
  }
1772
1889
  }
1773
1890
 
1774
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1891
+ 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;
1775
1892
  function getCachedStyle(key, generator) {
1776
1893
  let cached = styleCache.get(key);
1777
1894
  if (!cached) {
@@ -1783,6 +1900,42 @@
1783
1900
  }
1784
1901
  return cached;
1785
1902
  }
1903
+ function acesFilmic(x) {
1904
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1905
+ }
1906
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1907
+ switch (mode) {
1908
+ case HdrMode.vivid: {
1909
+ const avg = (r + g + b) / channelCount;
1910
+ return {
1911
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1912
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1913
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1914
+ };
1915
+ }
1916
+ case HdrMode.cinematic: {
1917
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1918
+ return {
1919
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1920
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1921
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1922
+ };
1923
+ }
1924
+ case HdrMode.dynamic: {
1925
+ 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;
1926
+ return {
1927
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1928
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1929
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1930
+ };
1931
+ }
1932
+ case HdrMode.standard:
1933
+ return { b, g, r };
1934
+ case HdrMode.natural:
1935
+ default:
1936
+ return { b, g, r };
1937
+ }
1938
+ }
1786
1939
  function stringToRgba(pluginManager, input) {
1787
1940
  if (!input) {
1788
1941
  return;
@@ -1906,9 +2059,9 @@
1906
2059
  const grayscaleValue = Math.round(lNormalized * rgbMax);
1907
2060
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1908
2061
  }
1909
- const temp1 = lNormalized < half
2062
+ const temp2 = lNormalized < half
1910
2063
  ? lNormalized * (sNormalizedOffset + sNormalized)
1911
- : 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));
2064
+ : 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));
1912
2065
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1913
2066
  }
1914
2067
  function hslToRgbFloat(hsl) {
@@ -1917,9 +2070,9 @@
1917
2070
  const grayscaleValue = lNormalized * rgbMax;
1918
2071
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1919
2072
  }
1920
- const temp1 = lNormalized < half
2073
+ const temp2 = lNormalized < half
1921
2074
  ? lNormalized * (sNormalizedOffset + sNormalized)
1922
- : 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));
2075
+ : 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));
1923
2076
  return { r: red, g: green, b: blue };
1924
2077
  }
1925
2078
  function hslaToRgba(hsla) {
@@ -1940,21 +2093,40 @@
1940
2093
  r: getRgbInRangeValue(),
1941
2094
  };
1942
2095
  }
1943
- function getStyleFromRgb(color, hdr, opacity) {
1944
- 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()}`;
1945
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2096
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2097
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2098
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2099
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2100
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
2101
+ }
2102
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
2103
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2104
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
1946
2105
  }
1947
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1948
- const headroom = peakNits / sdrReferenceWhiteNits;
1949
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2106
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2107
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2108
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2109
+ return { b: bNorm, g: gNorm, r: rNorm };
2110
+ }
2111
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2112
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2113
+ }
2114
+ function hdrToneMap(normalized, headroom, middleGray) {
2115
+ if (normalized <= middleGray) {
2116
+ return acesFilmic(normalized);
2117
+ }
2118
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2119
+ return acesFilmic(expanded);
1950
2120
  }
1951
2121
  function getSdrStyleFromRgb(color, opacity) {
1952
2122
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1953
2123
  }
1954
- function getStyleFromHsl(color, hdr, opacity) {
1955
- 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()}`;
2124
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2125
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2126
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2127
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1956
2128
  return getCachedStyle(key, () => hdr
1957
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2129
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1958
2130
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1959
2131
  }
1960
2132
  function getHslFromAnimation(animation) {
@@ -2017,7 +2189,7 @@
2017
2189
  colorValue.velocity = defaultVelocity;
2018
2190
  }
2019
2191
  }
2020
- function updateColorValue(data, decrease, delta, hdr) {
2192
+ function updateColorValue(data, decrease, delta, _hdr) {
2021
2193
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2022
2194
  if (!data.enable ||
2023
2195
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2030,7 +2202,7 @@
2030
2202
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2031
2203
  return;
2032
2204
  }
2033
- 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;
2205
+ 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;
2034
2206
  if (!decrease || data.status === AnimationStatus.increasing) {
2035
2207
  data.value += velocity;
2036
2208
  if (data.value > max) {
@@ -2062,9 +2234,9 @@
2062
2234
  return;
2063
2235
  }
2064
2236
  const { h, s, l } = color;
2065
- updateColorValue(h, false, delta, hdr);
2066
- updateColorValue(s, true, delta, hdr);
2067
- updateColorValue(l, true, delta, hdr);
2237
+ updateColorValue(h, false, delta);
2238
+ updateColorValue(s, true, delta);
2239
+ updateColorValue(l, true, delta);
2068
2240
  }
2069
2241
  function alterHsl(color, type, value) {
2070
2242
  return {
@@ -2114,7 +2286,7 @@
2114
2286
  }
2115
2287
 
2116
2288
  async function loadBlendPlugin(engine) {
2117
- engine.checkVersion("4.3.2");
2289
+ engine.checkVersion("4.5.0");
2118
2290
  await engine.pluginManager.register(e => {
2119
2291
  e.pluginManager.addPlugin(new BlendPlugin());
2120
2292
  });
@@ -2151,7 +2323,7 @@
2151
2323
  }
2152
2324
 
2153
2325
  async function loadCircleShape(engine) {
2154
- engine.checkVersion("4.3.2");
2326
+ engine.checkVersion("4.5.0");
2155
2327
  await engine.pluginManager.register(e => {
2156
2328
  e.pluginManager.addShape(["circle"], () => {
2157
2329
  return Promise.resolve(new CircleDrawer());
@@ -2166,7 +2338,7 @@
2166
2338
  RgbIndexes[RgbIndexes["b"] = 3] = "b";
2167
2339
  RgbIndexes[RgbIndexes["a"] = 4] = "a";
2168
2340
  })(RgbIndexes$1 || (RgbIndexes$1 = {}));
2169
- 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;
2341
+ 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;
2170
2342
  class HexColorManager {
2171
2343
  accepts(input) {
2172
2344
  return input.startsWith("#");
@@ -2199,7 +2371,7 @@
2199
2371
  }
2200
2372
 
2201
2373
  async function loadHexColorPlugin(engine) {
2202
- engine.checkVersion("4.3.2");
2374
+ engine.checkVersion("4.5.0");
2203
2375
  await engine.pluginManager.register(e => {
2204
2376
  e.pluginManager.addColorManager("hex", new HexColorManager());
2205
2377
  });
@@ -2239,7 +2411,7 @@
2239
2411
  if (!this.accepts(input)) {
2240
2412
  return;
2241
2413
  }
2242
- const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
2414
+ const result = hslRegex.exec(input), minLength = 4, radix = 10;
2243
2415
  return result
2244
2416
  ? hslaToRgba({
2245
2417
  a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
@@ -2252,12 +2424,20 @@
2252
2424
  }
2253
2425
 
2254
2426
  async function loadHslColorPlugin(engine) {
2255
- engine.checkVersion("4.3.2");
2427
+ engine.checkVersion("4.5.0");
2256
2428
  await engine.pluginManager.register(e => {
2257
2429
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2258
2430
  });
2259
2431
  }
2260
2432
 
2433
+ const ErrorCodes$1 = {
2434
+ baseMoverNotLoaded: "TSP-3203",
2435
+ };
2436
+
2437
+ const ErrorMessages$1 = {
2438
+ [ErrorCodes$1.baseMoverNotLoaded]: "tsParticles Base Mover is not loaded",
2439
+ };
2440
+
2261
2441
  class MovePlugin {
2262
2442
  id = "move";
2263
2443
  #pluginManager;
@@ -2276,20 +2456,20 @@
2276
2456
  }
2277
2457
 
2278
2458
  async function loadMovePlugin(engine) {
2279
- engine.checkVersion("4.3.2");
2459
+ engine.checkVersion("4.5.0");
2460
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
2461
+ addErrorMessages(ErrorMessages$1);
2462
+ }
2280
2463
  await engine.pluginManager.register(e => {
2281
2464
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2282
2465
  movePluginManager.initializers.pathGenerators ??= new Map();
2283
- movePluginManager.pathGenerators ??= new Map();
2284
2466
  movePluginManager.addPathGenerator = (name, generator) => {
2467
+ if (movePluginManager.initialized) {
2468
+ return;
2469
+ }
2285
2470
  movePluginManager.initializers.pathGenerators ??= new Map();
2286
2471
  movePluginManager.initializers.pathGenerators.set(name, generator);
2287
2472
  };
2288
- movePluginManager.getPathGenerators = async (container, force = false) => {
2289
- movePluginManager.initializers.pathGenerators ??= new Map();
2290
- movePluginManager.pathGenerators ??= new Map();
2291
- return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
2292
- };
2293
2473
  e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
2294
2474
  });
2295
2475
  }
@@ -2492,7 +2672,7 @@
2492
2672
  }
2493
2673
 
2494
2674
  async function loadOpacityUpdater(engine) {
2495
- engine.checkVersion("4.3.2");
2675
+ engine.checkVersion("4.5.0");
2496
2676
  await engine.pluginManager.register(e => {
2497
2677
  e.pluginManager.addParticleUpdater("opacity", container => {
2498
2678
  return Promise.resolve(new OpacityUpdater(container));
@@ -2501,70 +2681,60 @@
2501
2681
  }
2502
2682
 
2503
2683
  const boundsMin = 0;
2504
- function bounceHorizontal(data) {
2505
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2506
- (data.direction !== OutModeDirection.left && data.direction !== OutModeDirection.right)) {
2507
- return;
2508
- }
2509
- if (data.bounds.right < boundsMin && data.direction === OutModeDirection.left) {
2510
- data.particle.position.x = data.size + data.offset.x;
2511
- }
2512
- else if (data.bounds.left > data.canvasSize.width && data.direction === OutModeDirection.right) {
2513
- data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
2514
- }
2515
- const velocity = data.particle.velocity.x;
2516
- let bounced = false;
2517
- if (data.outOfCanvas &&
2518
- ((data.direction === OutModeDirection.right && velocity > minVelocity) ||
2519
- (data.direction === OutModeDirection.left && velocity < minVelocity))) {
2520
- const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
2521
- data.particle.velocity.x *= -newVelocity;
2522
- bounced = true;
2523
- }
2524
- if (!bounced) {
2525
- return;
2526
- }
2527
- const minPos = data.offset.x + data.size;
2528
- if (data.outOfCanvas && data.direction === OutModeDirection.right) {
2529
- data.particle.position.x = data.canvasSize.width - minPos;
2530
- }
2531
- else if (data.outOfCanvas && data.direction === OutModeDirection.left) {
2532
- data.particle.position.x = minPos;
2533
- }
2534
- if (data.outMode === OutMode.split) {
2535
- data.particle.destroy();
2536
- }
2537
- }
2538
- function bounceVertical(data) {
2539
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2540
- (data.direction !== OutModeDirection.bottom && data.direction !== OutModeDirection.top)) {
2684
+ const bounceAxisConfigs = {
2685
+ [OutModeDirection.left]: {
2686
+ axis: "x",
2687
+ canvas: "width",
2688
+ bounce: "horizontal",
2689
+ negativeEdge: "right",
2690
+ positiveEdge: "left",
2691
+ negative: true,
2692
+ },
2693
+ [OutModeDirection.right]: {
2694
+ axis: "x",
2695
+ canvas: "width",
2696
+ bounce: "horizontal",
2697
+ negativeEdge: "right",
2698
+ positiveEdge: "left",
2699
+ negative: false,
2700
+ },
2701
+ [OutModeDirection.top]: {
2702
+ axis: "y",
2703
+ canvas: "height",
2704
+ bounce: "vertical",
2705
+ negativeEdge: "bottom",
2706
+ positiveEdge: "top",
2707
+ negative: true,
2708
+ },
2709
+ [OutModeDirection.bottom]: {
2710
+ axis: "y",
2711
+ canvas: "height",
2712
+ bounce: "vertical",
2713
+ negativeEdge: "bottom",
2714
+ positiveEdge: "top",
2715
+ negative: false,
2716
+ },
2717
+ };
2718
+ function bounce(data) {
2719
+ if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) || !(data.direction in bounceAxisConfigs)) {
2541
2720
  return;
2542
2721
  }
2543
- if (data.bounds.bottom < boundsMin && data.direction === OutModeDirection.top) {
2544
- data.particle.position.y = data.size + data.offset.y;
2722
+ const config = bounceAxisConfigs[data.direction], bounds = data.bounds, canvasDim = data.canvasSize[config.canvas], position = data.particle.position, velocity = data.particle.velocity[config.axis];
2723
+ if (config.negative && bounds[config.negativeEdge] < boundsMin) {
2724
+ position[config.axis] = data.size + data.offset[config.axis];
2545
2725
  }
2546
- else if (data.bounds.top > data.canvasSize.height && data.direction === OutModeDirection.bottom) {
2547
- data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
2726
+ else if (!config.negative && bounds[config.positiveEdge] > canvasDim) {
2727
+ position[config.axis] = canvasDim - data.size - data.offset[config.axis];
2548
2728
  }
2549
- const velocity = data.particle.velocity.y;
2550
- let bounced = false;
2551
2729
  if (data.outOfCanvas &&
2552
- ((data.direction === OutModeDirection.bottom && velocity > minVelocity) ||
2553
- (data.direction === OutModeDirection.top && velocity < minVelocity))) {
2554
- const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
2555
- data.particle.velocity.y *= -newVelocity;
2556
- bounced = true;
2730
+ ((config.negative && velocity < minVelocity) || (!config.negative && velocity > minVelocity))) {
2731
+ data.particle.velocity[config.axis] *= -getRangeValue(data.particle.options.bounce[config.bounce].value);
2557
2732
  }
2558
- if (!bounced) {
2733
+ else {
2559
2734
  return;
2560
2735
  }
2561
- const minPos = data.offset.y + data.size;
2562
- if (data.outOfCanvas && data.direction === OutModeDirection.bottom) {
2563
- data.particle.position.y = data.canvasSize.height - minPos;
2564
- }
2565
- else if (data.outOfCanvas && data.direction === OutModeDirection.top) {
2566
- data.particle.position.y = minPos;
2567
- }
2736
+ const minPos = data.offset[config.axis] + data.size;
2737
+ position[config.axis] = config.negative ? minPos : canvasDim - minPos;
2568
2738
  if (data.outMode === OutMode.split) {
2569
2739
  data.particle.destroy();
2570
2740
  }
@@ -2580,26 +2750,19 @@
2580
2750
  OutMode.bounce,
2581
2751
  OutMode.split,
2582
2752
  ];
2583
- this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
2753
+ this.#particleBouncePlugins = container.plugins.filter(p => !!p.particleBounce);
2584
2754
  }
2585
2755
  update(particle, direction, delta, outMode) {
2586
2756
  if (!this.modes.includes(outMode)) {
2587
2757
  return;
2588
2758
  }
2589
- const container = this.#container;
2590
- let handled = false;
2591
2759
  for (const plugin of this.#particleBouncePlugins) {
2592
- handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
2593
- if (handled) {
2594
- break;
2760
+ if (plugin.particleBounce?.(particle, delta, direction)) {
2761
+ return;
2595
2762
  }
2596
2763
  }
2597
- if (handled) {
2598
- return;
2599
- }
2600
- const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2601
- bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2602
- bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2764
+ const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = this.#container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2765
+ bounce({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2603
2766
  }
2604
2767
  }
2605
2768
 
@@ -2688,108 +2851,109 @@
2688
2851
  return;
2689
2852
  }
2690
2853
  const container = this.#container;
2691
- switch (particle.outType) {
2692
- case ParticleOutType.inside: {
2693
- const { x: vx, y: vy } = particle.velocity;
2694
- updateVector.setTo(originPoint);
2695
- updateVector.length = particle.moveCenter.radius;
2696
- updateVector.angle = particle.velocity.angle + Math.PI;
2697
- updateVector.addTo(particle.moveCenter);
2698
- const { dx, dy } = getDistances(particle.position, updateVector);
2699
- if ((vx <= minVelocity && dx >= minDistance) ||
2700
- (vy <= minVelocity && dy >= minDistance) ||
2701
- (vx >= minVelocity && dx <= minDistance) ||
2702
- (vy >= minVelocity && dy <= minDistance)) {
2703
- return;
2704
- }
2705
- particle.position.x = Math.floor(randomInRangeValue({
2706
- min: 0,
2707
- max: container.canvas.size.width,
2708
- }));
2709
- particle.position.y = Math.floor(randomInRangeValue({
2710
- min: 0,
2711
- max: container.canvas.size.height,
2712
- }));
2713
- const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2714
- particle.direction = Math.atan2(-newDy, -newDx);
2715
- particle.velocity.angle = particle.direction;
2716
- particle.justWarped = true;
2717
- break;
2854
+ if (particle.outType === ParticleOutType.inside) {
2855
+ this.#applyOutModeInside(particle, container);
2856
+ }
2857
+ else {
2858
+ if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2859
+ return;
2718
2860
  }
2719
- default: {
2720
- if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2721
- return;
2722
- }
2723
- switch (particle.outType) {
2724
- case ParticleOutType.outside: {
2725
- particle.position.x =
2726
- Math.floor(randomInRangeValue({
2727
- min: -particle.moveCenter.radius,
2728
- max: particle.moveCenter.radius,
2729
- })) + particle.moveCenter.x;
2730
- particle.position.y =
2731
- Math.floor(randomInRangeValue({
2732
- min: -particle.moveCenter.radius,
2733
- max: particle.moveCenter.radius,
2734
- })) + particle.moveCenter.y;
2735
- const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2736
- if (particle.moveCenter.radius) {
2737
- particle.direction = Math.atan2(dy, dx);
2738
- particle.velocity.angle = particle.direction;
2739
- }
2740
- particle.justWarped = true;
2741
- break;
2742
- }
2743
- case ParticleOutType.normal: {
2744
- const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
2745
- bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
2746
- left: -particle.getRadius() - particle.offset.x,
2747
- right: canvasSize.width + particle.getRadius() + particle.offset.x,
2748
- top: -particle.getRadius() - particle.offset.y,
2749
- }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
2750
- if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2751
- particle.position.x = newPos.left;
2752
- particle.initialPosition.x = particle.position.x;
2753
- if (!warp) {
2754
- particle.position.y = getRandom() * canvasSize.height;
2755
- particle.initialPosition.y = particle.position.y;
2756
- }
2757
- particle.justWarped = true;
2758
- }
2759
- else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2760
- particle.position.x = newPos.right;
2761
- particle.initialPosition.x = particle.position.x;
2762
- if (!warp) {
2763
- particle.position.y = getRandom() * canvasSize.height;
2764
- particle.initialPosition.y = particle.position.y;
2765
- }
2766
- particle.justWarped = true;
2767
- }
2768
- if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2769
- if (!warp) {
2770
- particle.position.x = getRandom() * canvasSize.width;
2771
- particle.initialPosition.x = particle.position.x;
2772
- }
2773
- particle.position.y = newPos.top;
2774
- particle.initialPosition.y = particle.position.y;
2775
- particle.justWarped = true;
2776
- }
2777
- else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2778
- if (!warp) {
2779
- particle.position.x = getRandom() * canvasSize.width;
2780
- particle.initialPosition.x = particle.position.x;
2781
- }
2782
- particle.position.y = newPos.bottom;
2783
- particle.initialPosition.y = particle.position.y;
2784
- particle.justWarped = true;
2785
- }
2786
- break;
2787
- }
2788
- }
2789
- break;
2861
+ if (particle.outType === ParticleOutType.outside) {
2862
+ this.#applyParticleModeOutside(particle);
2863
+ }
2864
+ else {
2865
+ this.#applyOutModeNormal(particle, container, direction);
2790
2866
  }
2791
2867
  }
2792
2868
  }
2869
+ #applyOutModeInside(particle, container) {
2870
+ const { x: vx, y: vy } = particle.velocity;
2871
+ updateVector.setTo(originPoint);
2872
+ updateVector.length = particle.moveCenter.radius;
2873
+ updateVector.angle = particle.velocity.angle + Math.PI;
2874
+ updateVector.addTo(particle.moveCenter);
2875
+ const { dx, dy } = getDistances(particle.position, updateVector);
2876
+ if ((vx <= minVelocity && dx >= minDistance) ||
2877
+ (vy <= minVelocity && dy >= minDistance) ||
2878
+ (vx >= minVelocity && dx <= minDistance) ||
2879
+ (vy >= minVelocity && dy <= minDistance)) {
2880
+ return;
2881
+ }
2882
+ particle.position.x = Math.floor(randomInRangeValue({
2883
+ min: 0,
2884
+ max: container.canvas.size.width,
2885
+ }));
2886
+ particle.position.y = Math.floor(randomInRangeValue({
2887
+ min: 0,
2888
+ max: container.canvas.size.height,
2889
+ }));
2890
+ const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2891
+ particle.direction = Math.atan2(-newDy, -newDx);
2892
+ particle.velocity.angle = particle.direction;
2893
+ particle.justWarped = true;
2894
+ }
2895
+ #applyOutModeNormal(particle, container, direction) {
2896
+ const warp = particle.options.move.warp, canvasSize = container.canvas.size, sizeValue = particle.getRadius(), newPos = {
2897
+ bottom: canvasSize.height + sizeValue + particle.offset.y,
2898
+ left: -sizeValue - particle.offset.x,
2899
+ right: canvasSize.width + sizeValue + particle.offset.x,
2900
+ top: -sizeValue - particle.offset.y,
2901
+ }, nextBounds = calculateBounds(particle.position, sizeValue);
2902
+ if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2903
+ particle.position.x = newPos.left;
2904
+ particle.initialPosition.x = particle.position.x;
2905
+ if (!warp) {
2906
+ particle.position.y = getRandom() * canvasSize.height;
2907
+ particle.initialPosition.y = particle.position.y;
2908
+ }
2909
+ particle.justWarped = true;
2910
+ }
2911
+ else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2912
+ particle.position.x = newPos.right;
2913
+ particle.initialPosition.x = particle.position.x;
2914
+ if (!warp) {
2915
+ particle.position.y = getRandom() * canvasSize.height;
2916
+ particle.initialPosition.y = particle.position.y;
2917
+ }
2918
+ particle.justWarped = true;
2919
+ }
2920
+ if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2921
+ if (!warp) {
2922
+ particle.position.x = getRandom() * canvasSize.width;
2923
+ particle.initialPosition.x = particle.position.x;
2924
+ }
2925
+ particle.position.y = newPos.top;
2926
+ particle.initialPosition.y = particle.position.y;
2927
+ particle.justWarped = true;
2928
+ }
2929
+ else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2930
+ if (!warp) {
2931
+ particle.position.x = getRandom() * canvasSize.width;
2932
+ particle.initialPosition.x = particle.position.x;
2933
+ }
2934
+ particle.position.y = newPos.bottom;
2935
+ particle.initialPosition.y = particle.position.y;
2936
+ particle.justWarped = true;
2937
+ }
2938
+ }
2939
+ #applyParticleModeOutside(particle) {
2940
+ particle.position.x =
2941
+ Math.floor(randomInRangeValue({
2942
+ min: -particle.moveCenter.radius,
2943
+ max: particle.moveCenter.radius,
2944
+ })) + particle.moveCenter.x;
2945
+ particle.position.y =
2946
+ Math.floor(randomInRangeValue({
2947
+ min: -particle.moveCenter.radius,
2948
+ max: particle.moveCenter.radius,
2949
+ })) + particle.moveCenter.y;
2950
+ const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2951
+ if (particle.moveCenter.radius) {
2952
+ particle.direction = Math.atan2(dy, dx);
2953
+ particle.velocity.angle = particle.direction;
2954
+ }
2955
+ particle.justWarped = true;
2956
+ }
2793
2957
  }
2794
2958
 
2795
2959
  const checkOutMode = (outModes, outMode) => {
@@ -2837,7 +3001,7 @@
2837
3001
  }
2838
3002
 
2839
3003
  async function loadOutModesUpdater(engine) {
2840
- engine.checkVersion("4.3.2");
3004
+ engine.checkVersion("4.5.0");
2841
3005
  await engine.pluginManager.register(e => {
2842
3006
  e.pluginManager.addParticleUpdater("outModes", container => {
2843
3007
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2854,39 +3018,9 @@
2854
3018
  this.#pluginManager = pluginManager;
2855
3019
  }
2856
3020
  init(particle) {
2857
- 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;
2858
- if (fill) {
2859
- const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
2860
- particle.fillEnabled = fill.enable;
2861
- particle.fillOpacity = getRangeValue(fill.opacity);
2862
- particle.fillAnimation = fillColor.animation;
2863
- const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
2864
- if (fillHslColor) {
2865
- particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
2866
- }
2867
- }
2868
- else {
2869
- particle.fillEnabled = false;
2870
- particle.fillAnimation = undefined;
2871
- particle.fillColor = undefined;
2872
- particle.fillOpacity = defaultOpacity;
2873
- }
2874
- if (stroke) {
2875
- const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
2876
- particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
2877
- particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
2878
- particle.strokeAnimation = strokeColor.animation;
2879
- const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
2880
- if (strokeHslColor) {
2881
- particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
2882
- }
2883
- }
2884
- else {
2885
- particle.strokeAnimation = undefined;
2886
- particle.strokeColor = undefined;
2887
- particle.strokeOpacity = defaultOpacity;
2888
- particle.strokeWidth = 0;
2889
- }
3021
+ const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates);
3022
+ this.#initFill(paint, particle, container);
3023
+ this.#initStroke(paint, particle, container);
2890
3024
  }
2891
3025
  isEnabled(particle) {
2892
3026
  const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
@@ -2905,10 +3039,48 @@
2905
3039
  updateColor(particle.fillColor, delta, this.#container.hdr);
2906
3040
  updateColor(particle.strokeColor, delta, this.#container.hdr);
2907
3041
  }
3042
+ #initFill(paint, particle, container) {
3043
+ const fill = paint?.fill, color = paint?.color, paintColor = color ?? undefined;
3044
+ if (!fill) {
3045
+ particle.fillEnabled = false;
3046
+ particle.fillAnimation = undefined;
3047
+ particle.fillColor = undefined;
3048
+ particle.fillOpacity = defaultOpacity;
3049
+ return;
3050
+ }
3051
+ const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3052
+ particle.fillEnabled = fill.enable;
3053
+ particle.fillOpacity = getRangeValue(fill.opacity);
3054
+ particle.fillAnimation = fillColor.animation;
3055
+ const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3056
+ if (!fillHslColor) {
3057
+ return;
3058
+ }
3059
+ particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3060
+ }
3061
+ #initStroke(paint, particle, container) {
3062
+ const stroke = paint?.stroke, color = paint?.color, paintColor = color ?? undefined;
3063
+ if (!stroke) {
3064
+ particle.strokeAnimation = undefined;
3065
+ particle.strokeColor = undefined;
3066
+ particle.strokeOpacity = defaultOpacity;
3067
+ particle.strokeWidth = 0;
3068
+ return;
3069
+ }
3070
+ const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3071
+ particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3072
+ particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3073
+ particle.strokeAnimation = strokeColor.animation;
3074
+ const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3075
+ if (!strokeHslColor) {
3076
+ return;
3077
+ }
3078
+ particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
3079
+ }
2908
3080
  }
2909
3081
 
2910
3082
  async function loadPaintUpdater(engine) {
2911
- engine.checkVersion("4.3.2");
3083
+ engine.checkVersion("4.5.0");
2912
3084
  await engine.pluginManager.register(e => {
2913
3085
  e.pluginManager.addParticleUpdater("paint", container => {
2914
3086
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2950,7 +3122,7 @@
2950
3122
  if (!this.accepts(input)) {
2951
3123
  return;
2952
3124
  }
2953
- const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
3125
+ const result = rgbRegex.exec(input), radix = 10, minLength = 4;
2954
3126
  return result
2955
3127
  ? {
2956
3128
  a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
@@ -2963,7 +3135,7 @@
2963
3135
  }
2964
3136
 
2965
3137
  async function loadRgbColorPlugin(engine) {
2966
- engine.checkVersion("4.3.2");
3138
+ engine.checkVersion("4.5.0");
2967
3139
  await engine.pluginManager.register(e => {
2968
3140
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2969
3141
  });
@@ -3048,7 +3220,7 @@
3048
3220
  }
3049
3221
 
3050
3222
  async function loadSizeUpdater(engine) {
3051
- engine.checkVersion("4.3.2");
3223
+ engine.checkVersion("4.5.0");
3052
3224
  await engine.pluginManager.register(e => {
3053
3225
  e.pluginManager.addParticleUpdater("size", container => {
3054
3226
  return Promise.resolve(new SizeUpdater(container));
@@ -3057,7 +3229,7 @@
3057
3229
  }
3058
3230
 
3059
3231
  async function loadBasic(engine) {
3060
- engine.checkVersion("4.3.2");
3232
+ engine.checkVersion("4.5.0");
3061
3233
  await engine.pluginManager.register(async (e) => {
3062
3234
  await Promise.all([
3063
3235
  loadBlendPlugin(e),
@@ -3196,6 +3368,8 @@
3196
3368
  autoPlay = true;
3197
3369
  direction;
3198
3370
  domId;
3371
+ draggable = false;
3372
+ draw = true;
3199
3373
  fill = true;
3200
3374
  life = new EmitterLife();
3201
3375
  name;
@@ -3219,6 +3393,8 @@
3219
3393
  }
3220
3394
  loadProperty(this, "direction", data.direction);
3221
3395
  loadProperty(this, "domId", data.domId);
3396
+ loadProperty(this, "draggable", data.draggable);
3397
+ loadProperty(this, "draw", data.draw);
3222
3398
  loadProperty(this, "fill", data.fill);
3223
3399
  this.life.load(data.life);
3224
3400
  loadProperty(this, "name", data.name);
@@ -3280,6 +3456,14 @@
3280
3456
  }
3281
3457
  }
3282
3458
 
3459
+ const ErrorCodes = {
3460
+ emittersPluginNotLoaded: "TSP-3101",
3461
+ };
3462
+
3463
+ const ErrorMessages = {
3464
+ [ErrorCodes.emittersPluginNotLoaded]: "tsParticles Emitters Plugin is not loaded",
3465
+ };
3466
+
3283
3467
  async function addEmittersShapesManager(e) {
3284
3468
  const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
3285
3469
  pluginManager.emitterShapeManager ??= new ShapeManager();
@@ -3310,7 +3494,10 @@
3310
3494
  })(EmitterClickMode || (EmitterClickMode = {}));
3311
3495
 
3312
3496
  async function loadEmittersPluginSimple(engine) {
3313
- engine.checkVersion("4.3.2");
3497
+ engine.checkVersion("4.5.0");
3498
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
3499
+ addErrorMessages(ErrorMessages);
3500
+ }
3314
3501
  await engine.pluginManager.register(async (e) => {
3315
3502
  const instancesManager = await getEmittersInstancesManager(e);
3316
3503
  await addEmittersShapesManager(e);
@@ -3364,7 +3551,7 @@
3364
3551
  }
3365
3552
 
3366
3553
  async function loadMotionPlugin(engine) {
3367
- engine.checkVersion("4.3.2");
3554
+ engine.checkVersion("4.5.0");
3368
3555
  await engine.pluginManager.register(e => {
3369
3556
  e.pluginManager.addPlugin(new MotionPlugin());
3370
3557
  });
@@ -3497,7 +3684,7 @@
3497
3684
  }
3498
3685
 
3499
3686
  async function loadRollUpdater(engine) {
3500
- engine.checkVersion("4.3.2");
3687
+ engine.checkVersion("4.5.0");
3501
3688
  await engine.pluginManager.register(e => {
3502
3689
  e.pluginManager.addParticleUpdater("roll", () => {
3503
3690
  return Promise.resolve(new RollUpdater(e.pluginManager));
@@ -3556,7 +3743,7 @@
3556
3743
  particle.pathRotation = rotateOptions.path;
3557
3744
  let rotateDirection = rotateOptions.direction;
3558
3745
  if (rotateDirection === RotateDirection.random) {
3559
- const index = Math.floor(getRandom() * double), minIndex = 0;
3746
+ const index = Math.floor(getRandom() * double);
3560
3747
  rotateDirection = index > minIndex ? RotateDirection.counterClockwise : RotateDirection.clockwise;
3561
3748
  }
3562
3749
  switch (rotateDirection) {
@@ -3603,7 +3790,7 @@
3603
3790
  }
3604
3791
 
3605
3792
  async function loadRotateUpdater(engine) {
3606
- engine.checkVersion("4.3.2");
3793
+ engine.checkVersion("4.5.0");
3607
3794
  await engine.pluginManager.register(e => {
3608
3795
  e.pluginManager.addParticleUpdater("rotate", container => {
3609
3796
  return Promise.resolve(new RotateUpdater(container));
@@ -3627,7 +3814,7 @@
3627
3814
  }
3628
3815
 
3629
3816
  async function loadSquareShape(engine) {
3630
- engine.checkVersion("4.3.2");
3817
+ engine.checkVersion("4.5.0");
3631
3818
  await engine.pluginManager.register(e => {
3632
3819
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
3633
3820
  });
@@ -3699,7 +3886,7 @@
3699
3886
  };
3700
3887
  let tiltDirection = tiltOptions.direction;
3701
3888
  if (tiltDirection === TiltDirection.random) {
3702
- const index = Math.floor(getRandom() * double), minIndex = 0;
3889
+ const index = Math.floor(getRandom() * double);
3703
3890
  tiltDirection = index > minIndex ? TiltDirection.counterClockwise : TiltDirection.clockwise;
3704
3891
  }
3705
3892
  switch (tiltDirection) {
@@ -3736,7 +3923,7 @@
3736
3923
  }
3737
3924
 
3738
3925
  async function loadTiltUpdater(engine) {
3739
- engine.checkVersion("4.3.2");
3926
+ engine.checkVersion("4.5.0");
3740
3927
  await engine.pluginManager.register(e => {
3741
3928
  e.pluginManager.addParticleUpdater("tilt", container => {
3742
3929
  return Promise.resolve(new TiltUpdater(container));
@@ -3838,7 +4025,7 @@
3838
4025
  }
3839
4026
 
3840
4027
  async function loadWobbleUpdater(engine) {
3841
- engine.checkVersion("4.3.2");
4028
+ engine.checkVersion("4.5.0");
3842
4029
  await engine.pluginManager.register(e => {
3843
4030
  e.pluginManager.addParticleUpdater("wobble", container => {
3844
4031
  return Promise.resolve(new WobbleUpdater(container));
@@ -4063,21 +4250,28 @@
4063
4250
  });
4064
4251
  }
4065
4252
  clear() {
4253
+ const visited = new Set();
4066
4254
  for (const plugin of this.#canvasClearPlugins) {
4255
+ visited.add(plugin);
4067
4256
  if (plugin.canvasClear?.() ?? false) {
4068
- return;
4257
+ return plugin;
4069
4258
  }
4070
4259
  }
4071
4260
  for (const layer of Object.values(DrawLayer)) {
4072
4261
  if (typeof layer === "number") {
4073
4262
  for (const plugin of this.#getLayerPlugins(layer)) {
4263
+ if (visited.has(plugin)) {
4264
+ continue;
4265
+ }
4266
+ visited.add(plugin);
4074
4267
  if (plugin.canvasClear?.() ?? false) {
4075
- return;
4268
+ return plugin;
4076
4269
  }
4077
4270
  }
4078
4271
  }
4079
4272
  }
4080
4273
  this.canvasClear();
4274
+ return undefined;
4081
4275
  }
4082
4276
  destroy() {
4083
4277
  this.stop();
@@ -4118,7 +4312,11 @@
4118
4312
  if (!fColor && !sColor) {
4119
4313
  return;
4120
4314
  }
4121
- 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;
4315
+ 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
4316
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
4317
+ : undefined, stroke = sColor
4318
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
4319
+ : fill;
4122
4320
  transform.a = transform.b = transform.c = transform.d = undefined;
4123
4321
  colorStyles.fill = fill;
4124
4322
  colorStyles.stroke = stroke;
@@ -4151,8 +4349,7 @@
4151
4349
  });
4152
4350
  }
4153
4351
  drawParticles(delta) {
4154
- const { particles, actualOptions } = this.#container;
4155
- this.clear();
4352
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
4156
4353
  particles.update(delta);
4157
4354
  this.draw(ctx => {
4158
4355
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -4174,7 +4371,9 @@
4174
4371
  }
4175
4372
  }
4176
4373
  for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
4177
- plugin.canvasPaint?.();
4374
+ if (plugin !== clearedPlugin) {
4375
+ plugin.canvasPaint?.();
4376
+ }
4178
4377
  }
4179
4378
  for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
4180
4379
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -4206,35 +4405,7 @@
4206
4405
  this.#layers[layer] = [];
4207
4406
  }
4208
4407
  }
4209
- for (const plugin of this.#container.plugins) {
4210
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4211
- this.#colorPlugins.push(plugin);
4212
- }
4213
- if (plugin.drawParticle) {
4214
- this.#drawParticlePlugins.push(plugin);
4215
- }
4216
- if (plugin.drawParticleSetup) {
4217
- this.#drawParticlesSetupPlugins.push(plugin);
4218
- }
4219
- if (plugin.drawParticleCleanup) {
4220
- this.#drawParticlesCleanupPlugins.push(plugin);
4221
- }
4222
- if (plugin.canvasClear) {
4223
- this.#canvasClearPlugins.push(plugin);
4224
- }
4225
- if (plugin.canvasPaint) {
4226
- this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
4227
- }
4228
- if (plugin.drawSettingsSetup) {
4229
- this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
4230
- }
4231
- if (plugin.draw) {
4232
- this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
4233
- }
4234
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
4235
- this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
4236
- }
4237
- }
4408
+ this.#initPluginsArray();
4238
4409
  }
4239
4410
  initUpdaters() {
4240
4411
  this.#preDrawUpdaters = [];
@@ -4443,6 +4614,45 @@
4443
4614
  this.#reusablePluginColors[sColorIndex] = sColor;
4444
4615
  return this.#reusablePluginColors;
4445
4616
  }
4617
+ #initLayerPlugin(plugin) {
4618
+ const layerMap = [
4619
+ [DrawLayer.BackgroundMask, !!plugin.canvasPaint],
4620
+ [DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
4621
+ [DrawLayer.PluginContent, !!plugin.draw],
4622
+ [DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
4623
+ ];
4624
+ for (const [layer, active] of layerMap) {
4625
+ if (active) {
4626
+ this.#layers[layer].push(plugin);
4627
+ }
4628
+ }
4629
+ }
4630
+ #initPluginsArray() {
4631
+ for (const plugin of this.#container.plugins) {
4632
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
4633
+ this.#colorPlugins.push(plugin);
4634
+ }
4635
+ if (plugin.drawParticle) {
4636
+ this.#drawParticlePlugins.push(plugin);
4637
+ }
4638
+ if (plugin.drawParticleSetup) {
4639
+ this.#drawParticlesSetupPlugins.push(plugin);
4640
+ }
4641
+ if (plugin.drawParticleCleanup) {
4642
+ this.#drawParticlesCleanupPlugins.push(plugin);
4643
+ }
4644
+ if (plugin.canvasClear) {
4645
+ this.#canvasClearPlugins.push(plugin);
4646
+ }
4647
+ this.#initLayerPlugin(plugin);
4648
+ }
4649
+ }
4650
+ #isSupportedElement(element) {
4651
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
4652
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
4653
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
4654
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
4655
+ }
4446
4656
  #resolveBackgroundElement() {
4447
4657
  const background = this.#container.actualOptions.background;
4448
4658
  this.#backgroundElement = null;
@@ -4452,7 +4662,7 @@
4452
4662
  if (typeof background.element === "string") {
4453
4663
  if (typeof document !== "undefined") {
4454
4664
  const node = document.querySelector(background.element);
4455
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4665
+ if (node && this.#isSupportedElement(node)) {
4456
4666
  this.#backgroundElement = node;
4457
4667
  }
4458
4668
  else if (node) {
@@ -4463,10 +4673,7 @@
4463
4673
  }
4464
4674
  }
4465
4675
  }
4466
- else if (background.element instanceof HTMLCanvasElement ||
4467
- background.element instanceof OffscreenCanvas ||
4468
- background.element instanceof HTMLVideoElement ||
4469
- background.element instanceof HTMLImageElement) {
4676
+ else if (this.#isSupportedElement(background.element)) {
4470
4677
  this.#backgroundElement = background.element;
4471
4678
  }
4472
4679
  }
@@ -4484,7 +4691,7 @@
4484
4691
  return transferredCanvas;
4485
4692
  }
4486
4693
  if (typeof canvas.transferControlToOffscreen !== "function") {
4487
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
4694
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasUnsupported));
4488
4695
  }
4489
4696
  try {
4490
4697
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -4492,10 +4699,16 @@
4492
4699
  return offscreenCanvas;
4493
4700
  }
4494
4701
  catch {
4495
- throw new TypeError("OffscreenCanvas transfer failed");
4702
+ throw new TypeError(getErrorMessage(ErrorCodes$2.offscreenCanvasTransferFailed));
4496
4703
  }
4497
4704
  }, isHtmlCanvasElement = (canvas) => {
4498
4705
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
4706
+ }, getEffectiveColorSpace = (context) => {
4707
+ if (!context) {
4708
+ return undefined;
4709
+ }
4710
+ const colorInfo = context;
4711
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
4499
4712
  };
4500
4713
  function setStyle(canvas, style, important = false) {
4501
4714
  if (!style) {
@@ -4534,6 +4747,7 @@
4534
4747
  zoom = defaultZoom;
4535
4748
  #container;
4536
4749
  #generated;
4750
+ #hdrMediaListeners;
4537
4751
  #mutationObserver;
4538
4752
  #originalStyle;
4539
4753
  #pluginManager;
@@ -4598,7 +4812,6 @@
4598
4812
  });
4599
4813
  this.resize();
4600
4814
  this.#initStyle();
4601
- this.initBackground();
4602
4815
  this.#safeMutationObserver(obs => {
4603
4816
  const element = this.domElement;
4604
4817
  if (!element || !(element instanceof Node)) {
@@ -4608,6 +4821,8 @@
4608
4821
  });
4609
4822
  this.initPlugins();
4610
4823
  this.#initContext();
4824
+ this.initBackground();
4825
+ this.#initHdrListeners();
4611
4826
  this.render.init();
4612
4827
  }
4613
4828
  initBackground() {
@@ -4617,7 +4832,8 @@
4617
4832
  }
4618
4833
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4619
4834
  if (color) {
4620
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4835
+ const hdrOptions = container.actualOptions.hdr;
4836
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard));
4621
4837
  }
4622
4838
  else {
4623
4839
  elementStyle.backgroundColor = "";
@@ -4714,6 +4930,7 @@
4714
4930
  obs.disconnect();
4715
4931
  });
4716
4932
  this.#mutationObserver = undefined;
4933
+ this.#removeHdrListeners();
4717
4934
  this.render.stop();
4718
4935
  }
4719
4936
  async windowResize() {
@@ -4733,9 +4950,16 @@
4733
4950
  }
4734
4951
  }
4735
4952
  #initContext() {
4736
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4953
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4737
4954
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4738
4955
  safeMatchMedia("(dynamic-range: high)")?.matches;
4956
+ container.hdrMode = toEnumValue(HdrMode, container.actualOptions.hdr.mode, HdrMode.standard);
4957
+ container.peakNits = container.actualOptions.hdr.peakNits;
4958
+ const renderCanvas = this.renderCanvas;
4959
+ if (!renderCanvas) {
4960
+ container.hdr = canSupportHdr ?? false;
4961
+ return;
4962
+ }
4739
4963
  this.render.setContextSettings({
4740
4964
  alpha: true,
4741
4965
  desynchronized: true,
@@ -4744,11 +4968,51 @@
4744
4968
  ? { colorSpace: "display-p3", colorType: "float16" }
4745
4969
  : { colorSpace: "srgb" }),
4746
4970
  });
4747
- const renderCanvas = this.renderCanvas;
4748
- if (!renderCanvas) {
4749
- return;
4971
+ let context;
4972
+ try {
4973
+ context = renderCanvas.getContext("2d", this.render.settings);
4974
+ }
4975
+ catch {
4976
+ context = null;
4977
+ }
4978
+ if (canSupportHdr && !context) {
4979
+ const sdrSettings = {
4980
+ alpha: true,
4981
+ desynchronized: true,
4982
+ willReadFrequently: false,
4983
+ colorSpace: "srgb",
4984
+ };
4985
+ this.render.setContextSettings(sdrSettings);
4986
+ try {
4987
+ context = renderCanvas.getContext("2d", sdrSettings);
4988
+ }
4989
+ catch {
4990
+ context = null;
4991
+ }
4992
+ }
4993
+ this.render.setContext(context);
4994
+ if (context) {
4995
+ const effectiveColorSpace = getEffectiveColorSpace(context);
4996
+ if (effectiveColorSpace !== undefined) {
4997
+ container.hdr = effectiveColorSpace === "display-p3";
4998
+ }
4750
4999
  }
4751
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
5000
+ }
5001
+ #initHdrListeners() {
5002
+ this.#removeHdrListeners();
5003
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
5004
+ this.#initContext();
5005
+ this.initBackground();
5006
+ }, listeners = [];
5007
+ if (p3Query) {
5008
+ p3Query.addEventListener("change", handleChange);
5009
+ listeners.push({ handler: handleChange, mql: p3Query });
5010
+ }
5011
+ if (hdrQuery) {
5012
+ hdrQuery.addEventListener("change", handleChange);
5013
+ listeners.push({ handler: handleChange, mql: hdrQuery });
5014
+ }
5015
+ this.#hdrMediaListeners = listeners;
4752
5016
  }
4753
5017
  #initStyle() {
4754
5018
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4772,6 +5036,15 @@
4772
5036
  element.style.setProperty(key, value, "important");
4773
5037
  }
4774
5038
  }
5039
+ #removeHdrListeners() {
5040
+ if (!this.#hdrMediaListeners) {
5041
+ return;
5042
+ }
5043
+ for (const { handler, mql } of this.#hdrMediaListeners) {
5044
+ mql.removeEventListener("change", handler);
5045
+ }
5046
+ this.#hdrMediaListeners = undefined;
5047
+ }
4775
5048
  #repairStyle() {
4776
5049
  const element = this.domElement;
4777
5050
  if (!element) {
@@ -4861,8 +5134,7 @@
4861
5134
  this.#resizeTimeout = undefined;
4862
5135
  }
4863
5136
  const handleResize = async () => {
4864
- const canvas = this.#container.canvas;
4865
- await canvas.windowResize();
5137
+ await this.#container.canvas.windowResize();
4866
5138
  };
4867
5139
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
4868
5140
  }
@@ -4890,8 +5162,8 @@
4890
5162
  }
4891
5163
  else if (!this.#resizeObserver && add && canvasEl) {
4892
5164
  this.#resizeObserver = new ResizeObserver((entries) => {
4893
- const entry = entries.find(e => e.target === canvasEl);
4894
- if (!entry) {
5165
+ const res = entries.some(e => e.target === canvasEl);
5166
+ if (!res) {
4895
5167
  return;
4896
5168
  }
4897
5169
  this.#handleWindowResize();
@@ -5155,10 +5427,10 @@
5155
5427
  return this.#modifiers.find(m => m.id === id);
5156
5428
  }
5157
5429
  getOpacity() {
5158
- 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;
5159
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5430
+ const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$1), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity;
5431
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
5160
5432
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5161
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5433
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
5162
5434
  return this.#cachedOpacityData;
5163
5435
  }
5164
5436
  getPosition() {
@@ -5405,7 +5677,7 @@
5405
5677
  #initPosition(position) {
5406
5678
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
5407
5679
  if (!initialPosition) {
5408
- throw new Error("a valid position cannot be found for particle");
5680
+ throw new Error(getErrorMessage(ErrorCodes$2.particlePositionNotFound));
5409
5681
  }
5410
5682
  this.position = initialPosition;
5411
5683
  this.initialPosition = this.position.copy();
@@ -5454,6 +5726,12 @@
5454
5726
  this.#circlePoolIdx = 0;
5455
5727
  this.#rectanglePoolIdx = 0;
5456
5728
  }
5729
+ get cellSize() {
5730
+ return this.#cellSize;
5731
+ }
5732
+ set cellSize(value) {
5733
+ this.#pendingCellSize = value;
5734
+ }
5457
5735
  clear() {
5458
5736
  this.#cells.clear();
5459
5737
  const pendingCellSize = this.#pendingCellSize;
@@ -5477,18 +5755,7 @@
5477
5755
  const minCellX = Math.floor(bounds.minX / this.#cellSize), maxCellX = Math.floor(bounds.maxX / this.#cellSize), minCellY = Math.floor(bounds.minY / this.#cellSize), maxCellY = Math.floor(bounds.maxY / this.#cellSize);
5478
5756
  for (let cx = minCellX; cx <= maxCellX; cx++) {
5479
5757
  for (let cy = minCellY; cy <= maxCellY; cy++) {
5480
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
5481
- if (!cellParticles) {
5482
- continue;
5483
- }
5484
- for (const p of cellParticles) {
5485
- if (check && !check(p)) {
5486
- continue;
5487
- }
5488
- if (range.contains(p.getPosition())) {
5489
- out.push(p);
5490
- }
5491
- }
5758
+ this.#queryCell(cx, cy, range, check, out);
5492
5759
  }
5493
5760
  }
5494
5761
  return out;
@@ -5503,14 +5770,23 @@
5503
5770
  this.#releaseShapes();
5504
5771
  return result;
5505
5772
  }
5506
- setCellSize(cellSize) {
5507
- this.#pendingCellSize = cellSize;
5508
- }
5509
5773
  #acquireCircle(x, y, r) {
5510
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
5774
+ const idx = this.#circlePoolIdx++;
5775
+ let circle = this.#circlePool[idx];
5776
+ if (!circle) {
5777
+ circle = new Circle(x, y, r);
5778
+ this.#circlePool[idx] = circle;
5779
+ }
5780
+ return circle.reset(x, y, r);
5511
5781
  }
5512
5782
  #acquireRectangle(x, y, w, h) {
5513
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
5783
+ const idx = this.#rectanglePoolIdx++;
5784
+ let rectangle = this.#rectanglePool[idx];
5785
+ if (!rectangle) {
5786
+ rectangle = new Rectangle(x, y, w, h);
5787
+ this.#rectanglePool[idx] = rectangle;
5788
+ }
5789
+ return rectangle.reset(x, y, w, h);
5514
5790
  }
5515
5791
  #cellKeyFromCoords(x, y) {
5516
5792
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -5537,6 +5813,20 @@
5537
5813
  }
5538
5814
  return null;
5539
5815
  }
5816
+ #queryCell(cx, cy, range, check, out) {
5817
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
5818
+ if (!cellParticles) {
5819
+ return;
5820
+ }
5821
+ for (const p of cellParticles) {
5822
+ if (check && !check(p)) {
5823
+ continue;
5824
+ }
5825
+ if (range.contains(p.getPosition())) {
5826
+ out.push(p);
5827
+ }
5828
+ }
5829
+ }
5540
5830
  #releaseShapes() {
5541
5831
  this.#circlePoolIdx = 0;
5542
5832
  this.#rectanglePoolIdx = 0;
@@ -5545,9 +5835,9 @@
5545
5835
 
5546
5836
  class ParticlesManager {
5547
5837
  checkParticlePositionPlugins;
5548
- grid;
5549
5838
  #array;
5550
5839
  #container;
5840
+ #grid;
5551
5841
  #groupLimits;
5552
5842
  #limit;
5553
5843
  #nextId;
@@ -5571,7 +5861,7 @@
5571
5861
  this.#groupLimits = new Map();
5572
5862
  this.#particleBuckets = new Map();
5573
5863
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
5574
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5864
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
5575
5865
  this.checkParticlePositionPlugins = [];
5576
5866
  this.#particleResetPlugins = [];
5577
5867
  this.#particleUpdatePlugins = [];
@@ -5582,23 +5872,12 @@
5582
5872
  get count() {
5583
5873
  return this.#array.length;
5584
5874
  }
5875
+ get grid() {
5876
+ return this.#grid;
5877
+ }
5585
5878
  addParticle(position, overrideOptions, group, initializer) {
5586
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
5587
- if (limit > minLimit) {
5588
- switch (limitMode) {
5589
- case LimitMode.delete: {
5590
- const countToRemove = currentCount + countOffset - limit;
5591
- if (countToRemove > minCount) {
5592
- this.removeQuantity(countToRemove);
5593
- }
5594
- break;
5595
- }
5596
- case LimitMode.wait:
5597
- if (currentCount >= limit) {
5598
- return;
5599
- }
5600
- break;
5601
- }
5879
+ if (this.#checkAndApplyLimits(group, this.count)) {
5880
+ return;
5602
5881
  }
5603
5882
  try {
5604
5883
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -5662,7 +5941,7 @@
5662
5941
  return this.#array[index];
5663
5942
  }
5664
5943
  async init() {
5665
- const container = this.#container, options = container.actualOptions;
5944
+ const container = this.#container;
5666
5945
  this.checkParticlePositionPlugins = [];
5667
5946
  this.#updatePlugins = [];
5668
5947
  this.#particleUpdatePlugins = [];
@@ -5671,59 +5950,16 @@
5671
5950
  this.#postParticleUpdatePlugins = [];
5672
5951
  this.#particleBuckets.clear();
5673
5952
  this.#resetBuckets(container.zLayers);
5674
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5675
- for (const plugin of container.plugins) {
5676
- if (plugin.redrawInit) {
5677
- await plugin.redrawInit();
5678
- }
5679
- if (plugin.checkParticlePosition) {
5680
- this.checkParticlePositionPlugins.push(plugin);
5681
- }
5682
- if (plugin.update) {
5683
- this.#updatePlugins.push(plugin);
5684
- }
5685
- if (plugin.particleUpdate) {
5686
- this.#particleUpdatePlugins.push(plugin);
5687
- }
5688
- if (plugin.postUpdate) {
5689
- this.#postUpdatePlugins.push(plugin);
5690
- }
5691
- if (plugin.particleReset) {
5692
- this.#particleResetPlugins.push(plugin);
5693
- }
5694
- if (plugin.postParticleUpdate) {
5695
- this.#postParticleUpdatePlugins.push(plugin);
5696
- }
5697
- }
5698
- await this.#container.initDrawersAndUpdaters();
5699
- for (const drawer of this.#container.effectDrawers.values()) {
5700
- await drawer.init?.(container);
5701
- }
5702
- for (const drawer of this.#container.shapeDrawers.values()) {
5703
- await drawer.init?.(container);
5704
- }
5705
- let handled = false;
5706
- for (const plugin of container.plugins) {
5707
- handled = plugin.particlesInitialization?.() ?? handled;
5708
- if (handled) {
5709
- break;
5710
- }
5711
- }
5712
- if (!handled) {
5713
- const particlesOptions = options.particles, groups = particlesOptions.groups;
5714
- for (const group in groups) {
5715
- const groupOptions = groups[group];
5716
- if (!groupOptions) {
5717
- continue;
5718
- }
5719
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5720
- this.addParticle(undefined, groupOptions, group);
5721
- }
5722
- }
5723
- for (let i = this.count; i < particlesOptions.number.value; i++) {
5724
- this.addParticle();
5953
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5954
+ this.#applyLimits(container.actualOptions.particles);
5955
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5956
+ for (const group in groups) {
5957
+ const groupData = groups[group];
5958
+ if (groupData) {
5959
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
5725
5960
  }
5726
5961
  }
5962
+ await this.#initPlugins();
5727
5963
  }
5728
5964
  push(nb, position, overrideOptions, group) {
5729
5965
  for (let i = 0; i < nb; i++) {
@@ -5738,13 +5974,13 @@
5738
5974
  remove(particle, group, override) {
5739
5975
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
5740
5976
  }
5741
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
5977
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
5742
5978
  if (index < minIndex || index > this.count) {
5743
5979
  return;
5744
5980
  }
5745
5981
  let deleted = 0;
5746
5982
  for (let i = index; deleted < quantity && i < this.count; i++) {
5747
- if (this.#removeParticle(i, group, override)) {
5983
+ if (this.#removeParticle(i, group, override, matchGroup)) {
5748
5984
  i--;
5749
5985
  deleted++;
5750
5986
  }
@@ -5775,7 +6011,7 @@
5775
6011
  this.#resizeFactor = factor;
5776
6012
  }
5777
6013
  update(delta) {
5778
- this.grid.clear();
6014
+ this.#grid.clear();
5779
6015
  for (const plugin of this.#updatePlugins) {
5780
6016
  plugin.update?.(delta);
5781
6017
  }
@@ -5786,7 +6022,7 @@
5786
6022
  this.#updateParticlesPhase2(delta, particlesToDelete);
5787
6023
  if (particlesToDelete.size) {
5788
6024
  for (const particle of particlesToDelete) {
5789
- this.remove(particle);
6025
+ this.remove(particle, particle.group);
5790
6026
  }
5791
6027
  }
5792
6028
  this.#resizeFactor = undefined;
@@ -5797,12 +6033,7 @@
5797
6033
  #applyDensity(options, pluginsCount, group, groupOptions) {
5798
6034
  const numberOptions = options.number;
5799
6035
  if (!numberOptions.density.enable) {
5800
- if (group === undefined) {
5801
- this.#limit = numberOptions.limit.value;
5802
- }
5803
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
5804
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
5805
- }
6036
+ this.#applyLimits(options, group, groupOptions);
5806
6037
  return;
5807
6038
  }
5808
6039
  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);
@@ -5810,7 +6041,10 @@
5810
6041
  this.#limit = numberOptions.limit.value * densityFactor;
5811
6042
  }
5812
6043
  else {
5813
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
6044
+ this.#groupLimits.set(group, {
6045
+ limit: numberOptions.limit.value * densityFactor,
6046
+ mode: toEnumValue(LimitMode, numberOptions.limit.mode, LimitMode.delete),
6047
+ });
5814
6048
  }
5815
6049
  if (particlesCount < particlesNumber) {
5816
6050
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -5819,6 +6053,55 @@
5819
6053
  this.removeQuantity(particlesCount - particlesNumber, group);
5820
6054
  }
5821
6055
  }
6056
+ #applyLimits(options, group, groupOptions) {
6057
+ if (group === undefined) {
6058
+ this.#limit = options.number.limit.value;
6059
+ const groups = this.#container.actualOptions.particles.groups;
6060
+ for (const existingGroup of this.#groupLimits.keys()) {
6061
+ if (!(existingGroup in groups)) {
6062
+ this.#groupLimits.delete(existingGroup);
6063
+ }
6064
+ }
6065
+ }
6066
+ else {
6067
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
6068
+ if (limitValue > minLimit) {
6069
+ this.#groupLimits.set(group, {
6070
+ limit: limitValue,
6071
+ mode: toEnumValue(LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, LimitMode.delete),
6072
+ });
6073
+ }
6074
+ else {
6075
+ this.#groupLimits.delete(group);
6076
+ }
6077
+ }
6078
+ }
6079
+ #checkAndApplyLimits(group, currentCount) {
6080
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
6081
+ if (globalLimit > minLimit && globalMode === LimitMode.wait && currentCount >= globalLimit) {
6082
+ return true;
6083
+ }
6084
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
6085
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.wait) {
6086
+ const groupCount = this.filter(t => t.group === group).length;
6087
+ if (groupCount >= groupLimitEntry.limit) {
6088
+ return true;
6089
+ }
6090
+ }
6091
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.delete) {
6092
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
6093
+ if (groupCountToRemove > minCount) {
6094
+ this.removeQuantity(groupCountToRemove, group);
6095
+ }
6096
+ }
6097
+ if (globalLimit > minLimit && globalMode === LimitMode.delete) {
6098
+ const globalCountToRemove = this.count + countOffset - globalLimit;
6099
+ if (globalCountToRemove > minCount) {
6100
+ this.#removeAny(globalCountToRemove);
6101
+ }
6102
+ }
6103
+ return false;
6104
+ }
5822
6105
  #createBuckets(zLayers) {
5823
6106
  const bucketCount = Math.max(Math.floor(zLayers), one);
5824
6107
  return Array.from({ length: bucketCount }, () => []);
@@ -5841,6 +6124,70 @@
5841
6124
  }
5842
6125
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5843
6126
  }
6127
+ async #initDrawersAndUpdaters() {
6128
+ const container = this.#container;
6129
+ await container.initDrawersAndUpdaters();
6130
+ for (const drawer of container.effectDrawers.values()) {
6131
+ await drawer.init?.(container);
6132
+ }
6133
+ for (const drawer of container.shapeDrawers.values()) {
6134
+ await drawer.init?.(container);
6135
+ }
6136
+ }
6137
+ async #initPlugins() {
6138
+ await this.#initPluginsArrays();
6139
+ await this.#initDrawersAndUpdaters();
6140
+ let handled = false;
6141
+ const container = this.#container;
6142
+ for (const plugin of container.plugins) {
6143
+ handled = plugin.particlesInitialization?.() ?? handled;
6144
+ if (handled) {
6145
+ break;
6146
+ }
6147
+ }
6148
+ if (handled) {
6149
+ return;
6150
+ }
6151
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
6152
+ for (const group in groups) {
6153
+ const groupOptions = groups[group];
6154
+ if (!groupOptions) {
6155
+ continue;
6156
+ }
6157
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
6158
+ this.addParticle(undefined, groupOptions, group);
6159
+ }
6160
+ }
6161
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
6162
+ this.addParticle();
6163
+ }
6164
+ }
6165
+ async #initPluginsArrays() {
6166
+ const container = this.#container;
6167
+ for (const plugin of container.plugins) {
6168
+ if (plugin.redrawInit) {
6169
+ await plugin.redrawInit();
6170
+ }
6171
+ if (plugin.checkParticlePosition) {
6172
+ this.checkParticlePositionPlugins.push(plugin);
6173
+ }
6174
+ if (plugin.update) {
6175
+ this.#updatePlugins.push(plugin);
6176
+ }
6177
+ if (plugin.particleUpdate) {
6178
+ this.#particleUpdatePlugins.push(plugin);
6179
+ }
6180
+ if (plugin.postUpdate) {
6181
+ this.#postUpdatePlugins.push(plugin);
6182
+ }
6183
+ if (plugin.particleReset) {
6184
+ this.#particleResetPlugins.push(plugin);
6185
+ }
6186
+ if (plugin.postParticleUpdate) {
6187
+ this.#postParticleUpdatePlugins.push(plugin);
6188
+ }
6189
+ }
6190
+ }
5844
6191
  #insertParticleIntoBucket(particle) {
5845
6192
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
5846
6193
  if (!bucket) {
@@ -5849,12 +6196,15 @@
5849
6196
  bucket.push(particle);
5850
6197
  this.#particleBuckets.set(particle.id, bucketIndex);
5851
6198
  }
5852
- #removeParticle(index, group, override) {
6199
+ #removeAny(quantity) {
6200
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
6201
+ }
6202
+ #removeParticle(index, group, override, matchGroup = true) {
5853
6203
  const particle = this.#array[index];
5854
6204
  if (!particle) {
5855
6205
  return false;
5856
6206
  }
5857
- if (particle.group !== group) {
6207
+ if (matchGroup && particle.group !== group) {
5858
6208
  return false;
5859
6209
  }
5860
6210
  this.#array.splice(index, deleteCount);
@@ -5941,7 +6291,7 @@
5941
6291
  particlesToDelete.add(particle);
5942
6292
  continue;
5943
6293
  }
5944
- this.grid.insert(particle);
6294
+ this.#grid.insert(particle);
5945
6295
  }
5946
6296
  return particlesToDelete;
5947
6297
  }
@@ -6013,6 +6363,7 @@
6013
6363
  effectDrawers;
6014
6364
  fpsLimit;
6015
6365
  hdr;
6366
+ hdrMode;
6016
6367
  id;
6017
6368
  pageHidden;
6018
6369
  particleCreatedPlugins;
@@ -6020,6 +6371,7 @@
6020
6371
  particlePositionPlugins;
6021
6372
  particleUpdaters;
6022
6373
  particles;
6374
+ peakNits;
6023
6375
  plugins;
6024
6376
  retina;
6025
6377
  shapeDrawers;
@@ -6050,6 +6402,8 @@
6050
6402
  this.id = Symbol(id);
6051
6403
  this.fpsLimit = 120;
6052
6404
  this.hdr = false;
6405
+ this.hdrMode = HdrMode.standard;
6406
+ this.peakNits = 400;
6053
6407
  this.#smooth = false;
6054
6408
  this.#delay = 0;
6055
6409
  this.#duration = 0;
@@ -6113,7 +6467,6 @@
6113
6467
  this.shapeDrawers = new Map();
6114
6468
  this.particleUpdaters = [];
6115
6469
  this.plugins.length = 0;
6116
- this.#pluginManager.clearPlugins(this);
6117
6470
  this.destroyed = true;
6118
6471
  this.#onDestroy(remove);
6119
6472
  this.dispatchEvent(EventType.containerDestroyed);
@@ -6166,31 +6519,15 @@
6166
6519
  await this.initDrawersAndUpdaters();
6167
6520
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
6168
6521
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
6169
- this.plugins.length = 0;
6170
- this.particleDestroyedPlugins.length = 0;
6171
- this.particleCreatedPlugins.length = 0;
6172
- this.particlePositionPlugins.length = 0;
6173
- for (const [plugin, containerPlugin] of allContainerPlugins) {
6174
- if (plugin.needsPlugin(this.actualOptions)) {
6175
- this.plugins.push(containerPlugin);
6176
- if (containerPlugin.particleCreated) {
6177
- this.particleCreatedPlugins.push(containerPlugin);
6178
- }
6179
- if (containerPlugin.particleDestroyed) {
6180
- this.particleDestroyedPlugins.push(containerPlugin);
6181
- }
6182
- if (containerPlugin.particlePosition) {
6183
- this.particlePositionPlugins.push(containerPlugin);
6184
- }
6185
- }
6186
- }
6522
+ this.#initPlugins(allContainerPlugins);
6187
6523
  this.retina.init();
6188
6524
  this.canvas.init();
6189
6525
  this.updateActualOptions();
6190
6526
  this.canvas.initBackground();
6191
6527
  this.canvas.resize();
6192
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
6193
- this.hdr = hdr;
6528
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6529
+ this.hdrMode = toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard);
6530
+ this.peakNits = hdrOptions.peakNits;
6194
6531
  this.zLayers = zLayers;
6195
6532
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
6196
6533
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6210,9 +6547,9 @@
6210
6547
  }
6211
6548
  async initDrawersAndUpdaters() {
6212
6549
  const pluginManager = this.#pluginManager;
6213
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
6214
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
6215
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
6550
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
6551
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
6552
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
6216
6553
  }
6217
6554
  pause() {
6218
6555
  if (!guardCheck(this)) {
@@ -6323,6 +6660,27 @@
6323
6660
  }
6324
6661
  return refresh;
6325
6662
  }
6663
+ #initPlugins(allContainerPlugins) {
6664
+ this.plugins.length = 0;
6665
+ this.particleDestroyedPlugins.length = 0;
6666
+ this.particleCreatedPlugins.length = 0;
6667
+ this.particlePositionPlugins.length = 0;
6668
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
6669
+ if (!plugin.needsPlugin(this.actualOptions)) {
6670
+ continue;
6671
+ }
6672
+ this.plugins.push(containerPlugin);
6673
+ if (containerPlugin.particleCreated) {
6674
+ this.particleCreatedPlugins.push(containerPlugin);
6675
+ }
6676
+ if (containerPlugin.particleDestroyed) {
6677
+ this.particleDestroyedPlugins.push(containerPlugin);
6678
+ }
6679
+ if (containerPlugin.particlePosition) {
6680
+ this.particlePositionPlugins.push(containerPlugin);
6681
+ }
6682
+ }
6683
+ }
6326
6684
  #nextFrame(timestamp) {
6327
6685
  try {
6328
6686
  if (!this.#smooth &&
@@ -6599,11 +6957,11 @@
6599
6957
  }
6600
6958
  }
6601
6959
  async #init() {
6602
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
6603
- if (!availablePathGenerators) {
6960
+ const pluginManager = this.#pluginManager;
6961
+ if (!pluginManager.initializers.pathGenerators) {
6604
6962
  return;
6605
6963
  }
6606
- this.availablePathGenerators = availablePathGenerators;
6964
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
6607
6965
  this.pathGenerators = new Map();
6608
6966
  for (const pathGenerator of this.pathGenerators.values()) {
6609
6967
  pathGenerator.init();
@@ -6624,6 +6982,11 @@
6624
6982
  this.#container = container;
6625
6983
  this.#instancesManager.initContainer(container);
6626
6984
  }
6985
+ draw(context, _delta) {
6986
+ for (const emitter of this.#instancesManager.getArray(this.#container)) {
6987
+ emitter.draw(context);
6988
+ }
6989
+ }
6627
6990
  async init() {
6628
6991
  const emittersOptions = this.#container.actualOptions.emitters;
6629
6992
  if (isArray(emittersOptions)) {
@@ -6694,14 +7057,21 @@
6694
7057
  this.#pluginManager = pluginManager;
6695
7058
  }
6696
7059
  async addEmitter(container, options, position) {
6697
- const emitterOptions = new Emitter();
6698
- emitterOptions.load(options);
6699
- const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
6700
- this.removeEmitter(container, emitter);
6701
- }, emitterOptions, position);
6702
- await emitter.init();
6703
- this.getArray(container).push(emitter);
6704
- return emitter;
7060
+ return this.addEmitters(container, [{ options, position }]).then(t => t[defaultIndex]);
7061
+ }
7062
+ async addEmitters(container, emitters) {
7063
+ const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), res = [];
7064
+ for (const { options, position } of emitters) {
7065
+ const emitterOptions = new Emitter();
7066
+ emitterOptions.load(options);
7067
+ const emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
7068
+ this.removeEmitter(container, emitter);
7069
+ }, emitterOptions, position);
7070
+ await emitter.init();
7071
+ this.getArray(container).push(emitter);
7072
+ res.push(emitter);
7073
+ }
7074
+ return res;
6705
7075
  }
6706
7076
  clear(container) {
6707
7077
  this.initContainer(container);
@@ -6728,6 +7098,7 @@
6728
7098
  : array.find(t => t.name === idxOrName);
6729
7099
  };
6730
7100
  container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
7101
+ container.addEmitters = async (emitters) => this.addEmitters(container, emitters);
6731
7102
  container.removeEmitter = (idxOrName) => {
6732
7103
  const emitter = container.getEmitter?.(idxOrName);
6733
7104
  if (emitter) {
@@ -6748,7 +7119,7 @@
6748
7119
  };
6749
7120
  }
6750
7121
  removeEmitter(container, emitter) {
6751
- const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
7122
+ const index = this.getArray(container).indexOf(emitter), deleteCount = 1;
6752
7123
  if (index >= minIndex) {
6753
7124
  this.getArray(container).splice(index, deleteCount);
6754
7125
  }
@@ -6858,6 +7229,7 @@
6858
7229
  #particlesOptions;
6859
7230
  #paused;
6860
7231
  #pluginManager;
7232
+ #positionOverride = false;
6861
7233
  #removeCallback;
6862
7234
  #resizeObserver;
6863
7235
  #shape;
@@ -6934,6 +7306,31 @@
6934
7306
  });
6935
7307
  this.play();
6936
7308
  }
7309
+ draw(context) {
7310
+ if (!this.options.draw || !this.#shape) {
7311
+ return;
7312
+ }
7313
+ const container = this.#container, fillEnabled = this.options.spawn.fill?.enable ?? true;
7314
+ context.save();
7315
+ context.beginPath();
7316
+ if (fillEnabled) {
7317
+ context.fillStyle = this.spawnFillColor
7318
+ ? getStyleFromHsl(this.spawnFillColor, container.hdr, this.spawnFillOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode)
7319
+ : getStyleFromRgb({ r: 0, g: 0, b: 0 }, container.hdr, defaultOpacity$1, container.peakNits, container.hdrMode);
7320
+ }
7321
+ if (this.spawnStrokeColor) {
7322
+ context.strokeStyle = getStyleFromHsl(this.spawnStrokeColor, container.hdr, this.spawnStrokeOpacity ?? defaultOpacity$1, container.peakNits, container.hdrMode);
7323
+ context.lineWidth = this.spawnStrokeWidth ?? defaultStrokeWidth;
7324
+ }
7325
+ this.#shape.draw?.(context);
7326
+ if (fillEnabled) {
7327
+ context.fill();
7328
+ }
7329
+ if (this.spawnStrokeColor) {
7330
+ context.stroke();
7331
+ }
7332
+ context.restore();
7333
+ }
6937
7334
  externalPause() {
6938
7335
  this.#paused = true;
6939
7336
  this.pause();
@@ -6971,11 +7368,14 @@
6971
7368
  }
6972
7369
  }
6973
7370
  resize() {
6974
- const initialPosition = this.#initialPosition, container = this.#container;
6975
- this.position =
6976
- initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
6977
- ? initialPosition
6978
- : this.#calcPosition();
7371
+ const container = this.#container;
7372
+ if (!this.#positionOverride) {
7373
+ const initialPosition = this.#initialPosition;
7374
+ this.position =
7375
+ initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
7376
+ ? initialPosition
7377
+ : this.#calcPosition();
7378
+ }
6979
7379
  this.#size = this.#calcSize();
6980
7380
  this.size =
6981
7381
  this.#size.mode === PixelMode.percent
@@ -6986,6 +7386,11 @@
6986
7386
  : { width: this.#size.width, height: this.#size.height };
6987
7387
  this.#shape?.resize(this.position, this.size);
6988
7388
  }
7389
+ setPosition(position) {
7390
+ this.#positionOverride = true;
7391
+ this.position = { ...position };
7392
+ this.#shape?.resize(this.position, this.size);
7393
+ }
6989
7394
  update(delta) {
6990
7395
  if (this.#paused) {
6991
7396
  return;
@@ -7181,6 +7586,7 @@
7181
7586
  exports.loadConfettiExplosionsPreset = loadConfettiExplosionsPreset;
7182
7587
  exports.tsParticles = tsParticles;
7183
7588
 
7184
- }));
7589
+ })(g.__tsParticlesInternals.presets.confettiExplosions = g.__tsParticlesInternals.presets.confettiExplosions || {});
7590
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
7591
+
7185
7592
  Object.assign(globalThis.window || globalThis, { loadConfettiExplosionsPreset: (globalThis.__tsParticlesInternals.presets.confettiExplosions || {}).loadConfettiExplosionsPreset });
7186
- delete (globalThis.window || globalThis).tsparticlesInternalExports;