@tsparticles/preset-snow 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.snow = global.__tsParticlesInternals.presets.snow || {})));
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, 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, 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
  }
@@ -270,11 +301,61 @@
270
301
  };
271
302
  }
272
303
  function parseAlpha(input) {
273
- const defaultAlpha = 1;
274
304
  if (!input) {
275
305
  return defaultAlpha;
276
306
  }
277
- return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
307
+ return input.endsWith("%") ? Number.parseFloat(input) / percentDenominator : Number.parseFloat(input);
308
+ }
309
+
310
+ const ErrorCodes$1 = {
311
+ engineVersionMismatch: "TSP-1001",
312
+ particlePositionNotFound: "TSP-1002",
313
+ pluginRegisterAfterLoad: "TSP-1003",
314
+ offscreenCanvasUnsupported: "TSP-1101",
315
+ offscreenCanvasTransferFailed: "TSP-1102",
316
+ hdrEnableInvalid: "TSP-1201",
317
+ hdrModeInvalid: "TSP-1202",
318
+ hdrPeakNitsInvalid: "TSP-1203",
319
+ };
320
+
321
+ const messages = {
322
+ [ErrorCodes$1.engineVersionMismatch]: "The tsParticles version is different from the loaded plugins version. Engine version: {0}. Plugin version: {1}",
323
+ [ErrorCodes$1.particlePositionNotFound]: "a valid position cannot be found for particle",
324
+ [ErrorCodes$1.pluginRegisterAfterLoad]: "Register plugins can only be done before calling tsParticles.load()",
325
+ [ErrorCodes$1.offscreenCanvasUnsupported]: "OffscreenCanvas is required but not supported by this browser",
326
+ [ErrorCodes$1.offscreenCanvasTransferFailed]: "OffscreenCanvas transfer failed",
327
+ [ErrorCodes$1.hdrEnableInvalid]: 'Invalid HDR "enable" value: expected a boolean, got "{0}"',
328
+ [ErrorCodes$1.hdrModeInvalid]: 'Invalid HDR "mode" value: expected one of {0}, got "{1}"',
329
+ [ErrorCodes$1.hdrPeakNitsInvalid]: 'Invalid HDR "peakNits" value: expected a positive number, got "{0}"',
330
+ };
331
+
332
+ let registeredMessages;
333
+ const ensureRegisteredMessages = () => {
334
+ registeredMessages ??= new Map(Object.entries(messages));
335
+ return registeredMessages;
336
+ }, toStringValue$1 = (value) => String(value), format = (template, args) => {
337
+ return template.replace(/\{(\d+)\}/g, (match, index) => {
338
+ const arg = args[Number(index)];
339
+ return arg === undefined ? match : toStringValue$1(arg);
340
+ });
341
+ };
342
+ function addErrorMessages(extraMessages) {
343
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
344
+ return;
345
+ }
346
+ const catalog = ensureRegisteredMessages();
347
+ for (const [code, message] of Object.entries(extraMessages)) {
348
+ if (message !== undefined) {
349
+ catalog.set(code, message);
350
+ }
351
+ }
352
+ }
353
+ function getErrorMessage(code, ...args) {
354
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "production") {
355
+ return `[tsParticles Error ${code}] https://particles.js.org/errors/#${code}`;
356
+ }
357
+ const template = ensureRegisteredMessages().get(code) ?? `Unknown error code ${code}`;
358
+ return format(template, args);
278
359
  }
279
360
 
280
361
  var OutModeDirection;
@@ -291,7 +372,6 @@
291
372
  PixelMode["percent"] = "percent";
292
373
  })(PixelMode || (PixelMode = {}));
293
374
 
294
- const minRadius = 0;
295
375
  function isForbiddenKey(key) {
296
376
  return key === "__proto__" || key === "constructor" || key === "prototype";
297
377
  }
@@ -487,22 +567,84 @@
487
567
  element.removeEventListener(event, handler, removeOptions);
488
568
  }
489
569
  }
490
- async function getItemsFromInitializer(container, map, initializers, force = false) {
491
- let res = map.get(container);
492
- if (!res || force) {
493
- res = await Promise.all([...initializers.values()].map(t => t(container)));
494
- map.set(container, res);
570
+ async function getItemsFromInitializer(container, initializers) {
571
+ return await Promise.all([...initializers.values()].map(t => t(container)));
572
+ }
573
+ async function getItemMapFromInitializer(container, initializers) {
574
+ const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
575
+ return new Map(entries);
576
+ }
577
+ async function getDataFromUrl(data) {
578
+ const url = itemFromSingleOrMultiple(data.url, data.index);
579
+ if (!url) {
580
+ return data.fallback;
495
581
  }
496
- return res;
582
+ try {
583
+ const response = await fetch(url);
584
+ if (response.ok) {
585
+ const current = (await response.json());
586
+ if (isSourceOptionsValue(current)) {
587
+ return current;
588
+ }
589
+ getLogger().error("invalid configuration data while retrieving config file");
590
+ }
591
+ else {
592
+ getLogger().error(`${response.status.toString()} while retrieving config file`);
593
+ }
594
+ }
595
+ catch (error) {
596
+ getLogger().error(`error while retrieving config file: ${error}`);
597
+ }
598
+ return data.fallback;
497
599
  }
498
- async function getItemMapFromInitializer(container, map, initializers, force = false) {
499
- let res = map.get(container);
500
- if (!res || force) {
501
- const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
502
- res = new Map(entries);
503
- map.set(container, res);
600
+ function isSourceOptionsValue(value) {
601
+ if (isArray(value)) {
602
+ return value.every((entry) => isObject(entry) && !isArray(entry));
504
603
  }
505
- return res;
604
+ return isObject(value) && !isArray(value);
605
+ }
606
+ function getCanvasFromContainer(domContainer) {
607
+ let canvasEl;
608
+ const documentSafe = safeDocument(), isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
609
+ if (isCanvas) {
610
+ canvasEl = domContainer;
611
+ canvasEl.dataset[generatedAttribute] ??= generatedFalse;
612
+ if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
613
+ canvasEl.style.width ||= fullPercent;
614
+ canvasEl.style.height ||= fullPercent;
615
+ canvasEl.style.pointerEvents = "none";
616
+ canvasEl.style.setProperty("pointer-events", "none");
617
+ }
618
+ }
619
+ else {
620
+ const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
621
+ if (foundCanvas) {
622
+ canvasEl = foundCanvas;
623
+ canvasEl.dataset[generatedAttribute] = generatedFalse;
624
+ }
625
+ else {
626
+ canvasEl = documentSafe.createElement(canvasTag);
627
+ canvasEl.dataset[generatedAttribute] = generatedTrue;
628
+ domContainer.appendChild(canvasEl);
629
+ }
630
+ canvasEl.style.width ||= fullPercent;
631
+ canvasEl.style.height ||= fullPercent;
632
+ canvasEl.style.pointerEvents = "none";
633
+ canvasEl.style.setProperty("pointer-events", "none");
634
+ }
635
+ return canvasEl;
636
+ }
637
+ function getDomContainer(id, source) {
638
+ const documentSafe = safeDocument();
639
+ let domContainer = source ?? documentSafe.getElementById(id);
640
+ if (domContainer) {
641
+ return domContainer;
642
+ }
643
+ domContainer = documentSafe.createElement("canvas");
644
+ domContainer.id = id;
645
+ domContainer.dataset[generatedAttribute] = generatedTrue;
646
+ documentSafe.body.append(domContainer);
647
+ return domContainer;
506
648
  }
507
649
 
508
650
  class EventDispatcher {
@@ -573,7 +715,6 @@
573
715
  class PluginManager {
574
716
  colorManagers = new Map();
575
717
  easingFunctions = new Map();
576
- effectDrawers = new Map();
577
718
  initializers = {
578
719
  effects: new Map(),
579
720
  shapes: new Map(),
@@ -582,8 +723,6 @@
582
723
  palettes = new Map();
583
724
  plugins = [];
584
725
  presets = new Map();
585
- shapeDrawers = new Map();
586
- updaters = new Map();
587
726
  #allLoadersSet = new Set();
588
727
  #configs = new Map();
589
728
  #engine;
@@ -601,57 +740,79 @@
601
740
  }
602
741
  return res;
603
742
  }
743
+ get initialized() {
744
+ return this.#initialized;
745
+ }
604
746
  addColorManager(name, manager) {
747
+ if (this.#initialized) {
748
+ return;
749
+ }
605
750
  this.colorManagers.set(name, manager);
606
751
  }
607
752
  addConfig(config) {
753
+ if (this.#initialized) {
754
+ return;
755
+ }
608
756
  const key = config.key ?? config.name ?? "default";
609
757
  this.#configs.set(key, config);
610
758
  this.#engine.dispatchEvent(EventType.configAdded, { data: { name: key, config } });
611
759
  }
612
760
  addEasing(name, easing) {
761
+ if (this.#initialized) {
762
+ return;
763
+ }
613
764
  if (this.easingFunctions.get(name)) {
614
765
  return;
615
766
  }
616
767
  this.easingFunctions.set(name, easing);
617
768
  }
618
769
  addEffect(effect, drawer) {
770
+ if (this.#initialized) {
771
+ return;
772
+ }
619
773
  this.initializers.effects.set(effect, drawer);
620
774
  }
621
775
  addPalette(name, palette) {
776
+ if (this.#initialized) {
777
+ return;
778
+ }
622
779
  this.palettes.set(name, palette);
623
780
  }
624
781
  addParticleUpdater(name, updaterInitializer) {
782
+ if (this.#initialized) {
783
+ return;
784
+ }
625
785
  this.initializers.updaters.set(name, updaterInitializer);
626
786
  }
627
787
  addPlugin(plugin) {
788
+ if (this.#initialized) {
789
+ return;
790
+ }
628
791
  if (this.getPlugin(plugin.id)) {
629
792
  return;
630
793
  }
631
794
  this.plugins.push(plugin);
632
795
  }
633
796
  addPreset(preset, options, override = false) {
797
+ if (this.#initialized) {
798
+ return;
799
+ }
634
800
  if (!(override || !this.getPreset(preset))) {
635
801
  return;
636
802
  }
637
803
  this.presets.set(preset, options);
638
804
  }
639
805
  addShape(shapes, drawer) {
806
+ if (this.#initialized) {
807
+ return;
808
+ }
640
809
  for (const shape of shapes) {
641
810
  this.initializers.shapes.set(shape, drawer);
642
811
  }
643
812
  }
644
- clearPlugins(container) {
645
- this.effectDrawers.delete(container);
646
- this.shapeDrawers.delete(container);
647
- this.updaters.delete(container);
648
- }
649
813
  getEasing(name) {
650
814
  return this.easingFunctions.get(name) ?? ((value) => value);
651
815
  }
652
- getEffectDrawers(container, force = false) {
653
- return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
654
- }
655
816
  getPalette(name) {
656
817
  return this.palettes.get(name);
657
818
  }
@@ -661,12 +822,6 @@
661
822
  getPreset(preset) {
662
823
  return this.presets.get(preset);
663
824
  }
664
- async getShapeDrawers(container, force = false) {
665
- return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
666
- }
667
- async getUpdaters(container, force = false) {
668
- return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
669
- }
670
825
  async init() {
671
826
  if (this.#initialized || this.#isRunningLoaders) {
672
827
  return;
@@ -685,16 +840,9 @@
685
840
  this.#initialized = true;
686
841
  }
687
842
  }
688
- loadParticlesOptions(container, options, ...sourceOptions) {
689
- const updaters = this.updaters.get(container);
690
- if (!updaters) {
691
- return;
692
- }
693
- updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
694
- }
695
843
  async register(...loaders) {
696
844
  if (this.#initialized) {
697
- throw new Error("Register plugins can only be done before calling tsParticles.load()");
845
+ throw new Error(getErrorMessage(ErrorCodes$1.pluginRegisterAfterLoad));
698
846
  }
699
847
  for (const loader of loaders) {
700
848
  if (this.#isRunningLoaders) {
@@ -706,88 +854,15 @@
706
854
  }
707
855
  }
708
856
  async #runLoader(loader, executed, allLoaders) {
709
- if (executed.has(loader))
857
+ if (executed.has(loader)) {
710
858
  return;
859
+ }
711
860
  executed.add(loader);
712
861
  allLoaders.add(loader);
713
862
  await loader(this.#engine);
714
863
  }
715
864
  }
716
865
 
717
- const errorPrefix = "tsParticles - Error";
718
- const wrap = (fn) => (...args) => {
719
- fn(...args);
720
- }, _logger = {
721
- debug: wrap(console.debug),
722
- error: (message, ...optionalParams) => {
723
- console.error(`${errorPrefix} - ${message}`, ...optionalParams);
724
- },
725
- info: wrap(console.info),
726
- log: wrap(console.log),
727
- trace: wrap(console.trace),
728
- verbose: wrap(console.log),
729
- warning: wrap(console.warn),
730
- };
731
- function getLogger() {
732
- return _logger;
733
- }
734
-
735
- const fullPercent = "100%";
736
- async function getDataFromUrl(data) {
737
- const url = itemFromSingleOrMultiple(data.url, data.index);
738
- if (!url) {
739
- return data.fallback;
740
- }
741
- const response = await fetch(url);
742
- if (response.ok) {
743
- return (await response.json());
744
- }
745
- getLogger().error(`${response.status.toString()} while retrieving config file`);
746
- return data.fallback;
747
- }
748
- const getCanvasFromContainer = (domContainer) => {
749
- const documentSafe = safeDocument();
750
- let canvasEl;
751
- const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
752
- if (isCanvas) {
753
- canvasEl = domContainer;
754
- canvasEl.dataset[generatedAttribute] ??= generatedFalse;
755
- if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
756
- canvasEl.style.width ||= fullPercent;
757
- canvasEl.style.height ||= fullPercent;
758
- canvasEl.style.pointerEvents = "none";
759
- canvasEl.style.setProperty("pointer-events", "none");
760
- }
761
- }
762
- else {
763
- const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
764
- if (foundCanvas) {
765
- canvasEl = foundCanvas;
766
- canvasEl.dataset[generatedAttribute] = generatedFalse;
767
- }
768
- else {
769
- canvasEl = documentSafe.createElement(canvasTag);
770
- canvasEl.dataset[generatedAttribute] = generatedTrue;
771
- domContainer.appendChild(canvasEl);
772
- }
773
- canvasEl.style.width ||= fullPercent;
774
- canvasEl.style.height ||= fullPercent;
775
- canvasEl.style.pointerEvents = "none";
776
- canvasEl.style.setProperty("pointer-events", "none");
777
- }
778
- return canvasEl;
779
- }, getDomContainer = (id, source) => {
780
- const documentSafe = safeDocument();
781
- let domContainer = source ?? documentSafe.getElementById(id);
782
- if (domContainer) {
783
- return domContainer;
784
- }
785
- domContainer = documentSafe.createElement("canvas");
786
- domContainer.id = id;
787
- domContainer.dataset[generatedAttribute] = generatedTrue;
788
- documentSafe.body.append(domContainer);
789
- return domContainer;
790
- };
791
866
  class Engine {
792
867
  pluginManager = new PluginManager(this);
793
868
  #domArray = [];
@@ -797,7 +872,7 @@
797
872
  return this.#domArray;
798
873
  }
799
874
  get version() {
800
- return "4.3.2";
875
+ return "4.5.0";
801
876
  }
802
877
  addEventListener(type, listener) {
803
878
  this.#eventDispatcher.addEventListener(type, listener);
@@ -806,7 +881,7 @@
806
881
  if (this.version === pluginVersion) {
807
882
  return;
808
883
  }
809
- throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
884
+ throw new Error(getErrorMessage(ErrorCodes$1.engineVersionMismatch, this.version, pluginVersion));
810
885
  }
811
886
  dispatchEvent(type, args) {
812
887
  this.#eventDispatcher.dispatchEvent(type, args);
@@ -878,6 +953,10 @@
878
953
  }
879
954
 
880
955
  function initEngine() {
956
+ const existing = globalThis.tsParticles;
957
+ if (existing?.pluginManager) {
958
+ return existing;
959
+ }
881
960
  return new Engine();
882
961
  }
883
962
 
@@ -975,6 +1054,15 @@
975
1054
  AnimationMode["random"] = "random";
976
1055
  })(AnimationMode || (AnimationMode = {}));
977
1056
 
1057
+ var HdrMode;
1058
+ (function (HdrMode) {
1059
+ HdrMode["standard"] = "standard";
1060
+ HdrMode["natural"] = "natural";
1061
+ HdrMode["vivid"] = "vivid";
1062
+ HdrMode["cinematic"] = "cinematic";
1063
+ HdrMode["dynamic"] = "dynamic";
1064
+ })(HdrMode || (HdrMode = {}));
1065
+
978
1066
  var LimitMode;
979
1067
  (function (LimitMode) {
980
1068
  LimitMode["delete"] = "delete";
@@ -1042,20 +1130,6 @@
1042
1130
  DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
1043
1131
  })(DrawLayer || (DrawLayer = {}));
1044
1132
 
1045
- class OptionLoader {
1046
- load(data) {
1047
- if (isNull(data)) {
1048
- return;
1049
- }
1050
- this.doLoad(data);
1051
- }
1052
- }
1053
- function loadOptions(options, ...sourceOptionsArr) {
1054
- for (const sourceOptions of sourceOptionsArr) {
1055
- options.load(sourceOptions);
1056
- }
1057
- }
1058
-
1059
1133
  function loadProperty(obj, key, value) {
1060
1134
  if (value !== undefined) {
1061
1135
  obj[key] = value;
@@ -1087,6 +1161,20 @@
1087
1161
  }
1088
1162
  }
1089
1163
 
1164
+ class OptionLoader {
1165
+ load(data) {
1166
+ if (isNull(data)) {
1167
+ return;
1168
+ }
1169
+ this.doLoad(data);
1170
+ }
1171
+ }
1172
+ function loadOptions(options, ...sourceOptionsArr) {
1173
+ for (const sourceOptions of sourceOptionsArr) {
1174
+ options.load(sourceOptions);
1175
+ }
1176
+ }
1177
+
1090
1178
  class AnimationOptions extends OptionLoader {
1091
1179
  count = 0;
1092
1180
  decay = 0;
@@ -1230,6 +1318,28 @@
1230
1318
  }
1231
1319
  }
1232
1320
 
1321
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1322
+ class HDROptions extends OptionLoader {
1323
+ enable = true;
1324
+ mode = HdrMode.standard;
1325
+ peakNits = defaultPeakNits;
1326
+ doLoad(data) {
1327
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1328
+ throw new Error(getErrorMessage(ErrorCodes$1.hdrEnableInvalid, String(data.enable)));
1329
+ }
1330
+ if (data.mode !== undefined && !isEnumValue(HdrMode, data.mode)) {
1331
+ throw new Error(getErrorMessage(ErrorCodes$1.hdrModeInvalid, Object.values(HdrMode).join(", "), toStringValue(data.mode)));
1332
+ }
1333
+ if (data.peakNits !== undefined &&
1334
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1335
+ throw new Error(getErrorMessage(ErrorCodes$1.hdrPeakNitsInvalid, String(data.peakNits)));
1336
+ }
1337
+ loadProperty(this, "enable", data.enable);
1338
+ loadProperty(this, "mode", data.mode);
1339
+ loadProperty(this, "peakNits", data.peakNits);
1340
+ }
1341
+ }
1342
+
1233
1343
  class ResizeEvent extends OptionLoader {
1234
1344
  delay = 0.5;
1235
1345
  enable = true;
@@ -1600,12 +1710,10 @@
1600
1710
  plugin.loadParticlesOptions(this.#container, this, data);
1601
1711
  }
1602
1712
  }
1603
- const updaters = this.#pluginManager.updaters.get(this.#container);
1604
- if (updaters) {
1605
- for (const updater of updaters) {
1606
- if (updater.loadOptions) {
1607
- updater.loadOptions(this, data);
1608
- }
1713
+ const updaters = this.#container.particleUpdaters;
1714
+ for (const updater of updaters) {
1715
+ if (updater.loadOptions) {
1716
+ updater.loadOptions(this, data);
1609
1717
  }
1610
1718
  }
1611
1719
  }
@@ -1673,7 +1781,7 @@
1673
1781
  duration = 0;
1674
1782
  fpsLimit = 120;
1675
1783
  fullScreen;
1676
- hdr = true;
1784
+ hdr;
1677
1785
  key;
1678
1786
  name;
1679
1787
  palette;
@@ -1693,6 +1801,7 @@
1693
1801
  this.#container = container;
1694
1802
  this.background = new Background();
1695
1803
  this.fullScreen = new FullScreen();
1804
+ this.hdr = new HDROptions();
1696
1805
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1697
1806
  this.resize = new ResizeEvent();
1698
1807
  }
@@ -1715,7 +1824,15 @@
1715
1824
  loadProperty(this, "detectRetina", data.detectRetina);
1716
1825
  loadRangeProperty(this, "duration", data.duration);
1717
1826
  loadProperty(this, "fpsLimit", data.fpsLimit);
1718
- loadProperty(this, "hdr", data.hdr);
1827
+ const hdrData = data.hdr;
1828
+ if (isBoolean(hdrData)) {
1829
+ this.hdr.enable = hdrData;
1830
+ this.hdr.mode = HdrMode.standard;
1831
+ this.hdr.peakNits = 400;
1832
+ }
1833
+ else {
1834
+ this.hdr.load(hdrData);
1835
+ }
1719
1836
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1720
1837
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1721
1838
  loadProperty(this, "zLayers", data.zLayers);
@@ -1758,7 +1875,7 @@
1758
1875
  }
1759
1876
  }
1760
1877
 
1761
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1878
+ 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;
1762
1879
  function getCachedStyle(key, generator) {
1763
1880
  let cached = styleCache.get(key);
1764
1881
  if (!cached) {
@@ -1770,6 +1887,42 @@
1770
1887
  }
1771
1888
  return cached;
1772
1889
  }
1890
+ function acesFilmic(x) {
1891
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1892
+ }
1893
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1894
+ switch (mode) {
1895
+ case HdrMode.vivid: {
1896
+ const avg = (r + g + b) / channelCount;
1897
+ return {
1898
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1899
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1900
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1901
+ };
1902
+ }
1903
+ case HdrMode.cinematic: {
1904
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1905
+ return {
1906
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1907
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1908
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1909
+ };
1910
+ }
1911
+ case HdrMode.dynamic: {
1912
+ 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;
1913
+ return {
1914
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1915
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1916
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1917
+ };
1918
+ }
1919
+ case HdrMode.standard:
1920
+ return { b, g, r };
1921
+ case HdrMode.natural:
1922
+ default:
1923
+ return { b, g, r };
1924
+ }
1925
+ }
1773
1926
  function stringToRgba(pluginManager, input) {
1774
1927
  if (!input) {
1775
1928
  return;
@@ -1893,9 +2046,9 @@
1893
2046
  const grayscaleValue = Math.round(lNormalized * rgbMax);
1894
2047
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1895
2048
  }
1896
- const temp1 = lNormalized < half
2049
+ const temp2 = lNormalized < half
1897
2050
  ? lNormalized * (sNormalizedOffset + sNormalized)
1898
- : 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));
2051
+ : 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));
1899
2052
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1900
2053
  }
1901
2054
  function hslToRgbFloat(hsl) {
@@ -1904,9 +2057,9 @@
1904
2057
  const grayscaleValue = lNormalized * rgbMax;
1905
2058
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1906
2059
  }
1907
- const temp1 = lNormalized < half
2060
+ const temp2 = lNormalized < half
1908
2061
  ? lNormalized * (sNormalizedOffset + sNormalized)
1909
- : 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));
2062
+ : 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));
1910
2063
  return { r: red, g: green, b: blue };
1911
2064
  }
1912
2065
  function hslaToRgba(hsla) {
@@ -1927,21 +2080,40 @@
1927
2080
  r: getRgbInRangeValue(),
1928
2081
  };
1929
2082
  }
1930
- function getStyleFromRgb(color, hdr, opacity) {
1931
- 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()}`;
1932
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2083
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2084
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2085
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2086
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2087
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
2088
+ }
2089
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
2090
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2091
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2092
+ }
2093
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2094
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2095
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2096
+ return { b: bNorm, g: gNorm, r: rNorm };
2097
+ }
2098
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2099
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
1933
2100
  }
1934
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1935
- const headroom = peakNits / sdrReferenceWhiteNits;
1936
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2101
+ function hdrToneMap(normalized, headroom, middleGray) {
2102
+ if (normalized <= middleGray) {
2103
+ return acesFilmic(normalized);
2104
+ }
2105
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2106
+ return acesFilmic(expanded);
1937
2107
  }
1938
2108
  function getSdrStyleFromRgb(color, opacity) {
1939
2109
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1940
2110
  }
1941
- function getStyleFromHsl(color, hdr, opacity) {
1942
- 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()}`;
2111
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2112
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2113
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2114
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1943
2115
  return getCachedStyle(key, () => hdr
1944
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2116
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1945
2117
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1946
2118
  }
1947
2119
  function getHslFromAnimation(animation) {
@@ -2004,7 +2176,7 @@
2004
2176
  colorValue.velocity = defaultVelocity;
2005
2177
  }
2006
2178
  }
2007
- function updateColorValue(data, decrease, delta, hdr) {
2179
+ function updateColorValue(data, decrease, delta, _hdr) {
2008
2180
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2009
2181
  if (!data.enable ||
2010
2182
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2017,7 +2189,7 @@
2017
2189
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2018
2190
  return;
2019
2191
  }
2020
- 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;
2192
+ 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;
2021
2193
  if (!decrease || data.status === AnimationStatus.increasing) {
2022
2194
  data.value += velocity;
2023
2195
  if (data.value > max) {
@@ -2049,9 +2221,9 @@
2049
2221
  return;
2050
2222
  }
2051
2223
  const { h, s, l } = color;
2052
- updateColorValue(h, false, delta, hdr);
2053
- updateColorValue(s, true, delta, hdr);
2054
- updateColorValue(l, true, delta, hdr);
2224
+ updateColorValue(h, false, delta);
2225
+ updateColorValue(s, true, delta);
2226
+ updateColorValue(l, true, delta);
2055
2227
  }
2056
2228
  function alterHsl(color, type, value) {
2057
2229
  return {
@@ -2101,7 +2273,7 @@
2101
2273
  }
2102
2274
 
2103
2275
  async function loadBlendPlugin(engine) {
2104
- engine.checkVersion("4.3.2");
2276
+ engine.checkVersion("4.5.0");
2105
2277
  await engine.pluginManager.register(e => {
2106
2278
  e.pluginManager.addPlugin(new BlendPlugin());
2107
2279
  });
@@ -2138,7 +2310,7 @@
2138
2310
  }
2139
2311
 
2140
2312
  async function loadCircleShape(engine) {
2141
- engine.checkVersion("4.3.2");
2313
+ engine.checkVersion("4.5.0");
2142
2314
  await engine.pluginManager.register(e => {
2143
2315
  e.pluginManager.addShape(["circle"], () => {
2144
2316
  return Promise.resolve(new CircleDrawer());
@@ -2153,7 +2325,7 @@
2153
2325
  RgbIndexes[RgbIndexes["b"] = 3] = "b";
2154
2326
  RgbIndexes[RgbIndexes["a"] = 4] = "a";
2155
2327
  })(RgbIndexes$1 || (RgbIndexes$1 = {}));
2156
- 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;
2328
+ 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;
2157
2329
  class HexColorManager {
2158
2330
  accepts(input) {
2159
2331
  return input.startsWith("#");
@@ -2186,7 +2358,7 @@
2186
2358
  }
2187
2359
 
2188
2360
  async function loadHexColorPlugin(engine) {
2189
- engine.checkVersion("4.3.2");
2361
+ engine.checkVersion("4.5.0");
2190
2362
  await engine.pluginManager.register(e => {
2191
2363
  e.pluginManager.addColorManager("hex", new HexColorManager());
2192
2364
  });
@@ -2226,7 +2398,7 @@
2226
2398
  if (!this.accepts(input)) {
2227
2399
  return;
2228
2400
  }
2229
- const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
2401
+ const result = hslRegex.exec(input), minLength = 4, radix = 10;
2230
2402
  return result
2231
2403
  ? hslaToRgba({
2232
2404
  a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
@@ -2239,12 +2411,20 @@
2239
2411
  }
2240
2412
 
2241
2413
  async function loadHslColorPlugin(engine) {
2242
- engine.checkVersion("4.3.2");
2414
+ engine.checkVersion("4.5.0");
2243
2415
  await engine.pluginManager.register(e => {
2244
2416
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2245
2417
  });
2246
2418
  }
2247
2419
 
2420
+ const ErrorCodes = {
2421
+ baseMoverNotLoaded: "TSP-3203",
2422
+ };
2423
+
2424
+ const ErrorMessages = {
2425
+ [ErrorCodes.baseMoverNotLoaded]: "tsParticles Base Mover is not loaded",
2426
+ };
2427
+
2248
2428
  class MovePlugin {
2249
2429
  id = "move";
2250
2430
  #pluginManager;
@@ -2263,20 +2443,20 @@
2263
2443
  }
2264
2444
 
2265
2445
  async function loadMovePlugin(engine) {
2266
- engine.checkVersion("4.3.2");
2446
+ engine.checkVersion("4.5.0");
2447
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
2448
+ addErrorMessages(ErrorMessages);
2449
+ }
2267
2450
  await engine.pluginManager.register(e => {
2268
2451
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2269
2452
  movePluginManager.initializers.pathGenerators ??= new Map();
2270
- movePluginManager.pathGenerators ??= new Map();
2271
2453
  movePluginManager.addPathGenerator = (name, generator) => {
2454
+ if (movePluginManager.initialized) {
2455
+ return;
2456
+ }
2272
2457
  movePluginManager.initializers.pathGenerators ??= new Map();
2273
2458
  movePluginManager.initializers.pathGenerators.set(name, generator);
2274
2459
  };
2275
- movePluginManager.getPathGenerators = async (container, force = false) => {
2276
- movePluginManager.initializers.pathGenerators ??= new Map();
2277
- movePluginManager.pathGenerators ??= new Map();
2278
- return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
2279
- };
2280
2460
  e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
2281
2461
  });
2282
2462
  }
@@ -2473,7 +2653,7 @@
2473
2653
  }
2474
2654
 
2475
2655
  async function loadOpacityUpdater(engine) {
2476
- engine.checkVersion("4.3.2");
2656
+ engine.checkVersion("4.5.0");
2477
2657
  await engine.pluginManager.register(e => {
2478
2658
  e.pluginManager.addParticleUpdater("opacity", container => {
2479
2659
  return Promise.resolve(new OpacityUpdater(container));
@@ -2482,70 +2662,60 @@
2482
2662
  }
2483
2663
 
2484
2664
  const boundsMin = 0;
2485
- function bounceHorizontal(data) {
2486
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2487
- (data.direction !== OutModeDirection.left && data.direction !== OutModeDirection.right)) {
2488
- return;
2489
- }
2490
- if (data.bounds.right < boundsMin && data.direction === OutModeDirection.left) {
2491
- data.particle.position.x = data.size + data.offset.x;
2492
- }
2493
- else if (data.bounds.left > data.canvasSize.width && data.direction === OutModeDirection.right) {
2494
- data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
2495
- }
2496
- const velocity = data.particle.velocity.x;
2497
- let bounced = false;
2498
- if (data.outOfCanvas &&
2499
- ((data.direction === OutModeDirection.right && velocity > minVelocity) ||
2500
- (data.direction === OutModeDirection.left && velocity < minVelocity))) {
2501
- const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
2502
- data.particle.velocity.x *= -newVelocity;
2503
- bounced = true;
2504
- }
2505
- if (!bounced) {
2506
- return;
2507
- }
2508
- const minPos = data.offset.x + data.size;
2509
- if (data.outOfCanvas && data.direction === OutModeDirection.right) {
2510
- data.particle.position.x = data.canvasSize.width - minPos;
2511
- }
2512
- else if (data.outOfCanvas && data.direction === OutModeDirection.left) {
2513
- data.particle.position.x = minPos;
2514
- }
2515
- if (data.outMode === OutMode.split) {
2516
- data.particle.destroy();
2517
- }
2518
- }
2519
- function bounceVertical(data) {
2520
- if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) ||
2521
- (data.direction !== OutModeDirection.bottom && data.direction !== OutModeDirection.top)) {
2665
+ const bounceAxisConfigs = {
2666
+ [OutModeDirection.left]: {
2667
+ axis: "x",
2668
+ canvas: "width",
2669
+ bounce: "horizontal",
2670
+ negativeEdge: "right",
2671
+ positiveEdge: "left",
2672
+ negative: true,
2673
+ },
2674
+ [OutModeDirection.right]: {
2675
+ axis: "x",
2676
+ canvas: "width",
2677
+ bounce: "horizontal",
2678
+ negativeEdge: "right",
2679
+ positiveEdge: "left",
2680
+ negative: false,
2681
+ },
2682
+ [OutModeDirection.top]: {
2683
+ axis: "y",
2684
+ canvas: "height",
2685
+ bounce: "vertical",
2686
+ negativeEdge: "bottom",
2687
+ positiveEdge: "top",
2688
+ negative: true,
2689
+ },
2690
+ [OutModeDirection.bottom]: {
2691
+ axis: "y",
2692
+ canvas: "height",
2693
+ bounce: "vertical",
2694
+ negativeEdge: "bottom",
2695
+ positiveEdge: "top",
2696
+ negative: false,
2697
+ },
2698
+ };
2699
+ function bounce(data) {
2700
+ if ((data.outMode !== OutMode.bounce && data.outMode !== OutMode.split) || !(data.direction in bounceAxisConfigs)) {
2522
2701
  return;
2523
2702
  }
2524
- if (data.bounds.bottom < boundsMin && data.direction === OutModeDirection.top) {
2525
- data.particle.position.y = data.size + data.offset.y;
2703
+ const config = bounceAxisConfigs[data.direction], bounds = data.bounds, canvasDim = data.canvasSize[config.canvas], position = data.particle.position, velocity = data.particle.velocity[config.axis];
2704
+ if (config.negative && bounds[config.negativeEdge] < boundsMin) {
2705
+ position[config.axis] = data.size + data.offset[config.axis];
2526
2706
  }
2527
- else if (data.bounds.top > data.canvasSize.height && data.direction === OutModeDirection.bottom) {
2528
- data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
2707
+ else if (!config.negative && bounds[config.positiveEdge] > canvasDim) {
2708
+ position[config.axis] = canvasDim - data.size - data.offset[config.axis];
2529
2709
  }
2530
- const velocity = data.particle.velocity.y;
2531
- let bounced = false;
2532
2710
  if (data.outOfCanvas &&
2533
- ((data.direction === OutModeDirection.bottom && velocity > minVelocity) ||
2534
- (data.direction === OutModeDirection.top && velocity < minVelocity))) {
2535
- const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
2536
- data.particle.velocity.y *= -newVelocity;
2537
- bounced = true;
2711
+ ((config.negative && velocity < minVelocity) || (!config.negative && velocity > minVelocity))) {
2712
+ data.particle.velocity[config.axis] *= -getRangeValue(data.particle.options.bounce[config.bounce].value);
2538
2713
  }
2539
- if (!bounced) {
2714
+ else {
2540
2715
  return;
2541
2716
  }
2542
- const minPos = data.offset.y + data.size;
2543
- if (data.outOfCanvas && data.direction === OutModeDirection.bottom) {
2544
- data.particle.position.y = data.canvasSize.height - minPos;
2545
- }
2546
- else if (data.outOfCanvas && data.direction === OutModeDirection.top) {
2547
- data.particle.position.y = minPos;
2548
- }
2717
+ const minPos = data.offset[config.axis] + data.size;
2718
+ position[config.axis] = config.negative ? minPos : canvasDim - minPos;
2549
2719
  if (data.outMode === OutMode.split) {
2550
2720
  data.particle.destroy();
2551
2721
  }
@@ -2561,26 +2731,19 @@
2561
2731
  OutMode.bounce,
2562
2732
  OutMode.split,
2563
2733
  ];
2564
- this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
2734
+ this.#particleBouncePlugins = container.plugins.filter(p => !!p.particleBounce);
2565
2735
  }
2566
2736
  update(particle, direction, delta, outMode) {
2567
2737
  if (!this.modes.includes(outMode)) {
2568
2738
  return;
2569
2739
  }
2570
- const container = this.#container;
2571
- let handled = false;
2572
2740
  for (const plugin of this.#particleBouncePlugins) {
2573
- handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
2574
- if (handled) {
2575
- break;
2741
+ if (plugin.particleBounce?.(particle, delta, direction)) {
2742
+ return;
2576
2743
  }
2577
2744
  }
2578
- if (handled) {
2579
- return;
2580
- }
2581
- const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2582
- bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2583
- bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2745
+ const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = this.#container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
2746
+ bounce({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
2584
2747
  }
2585
2748
  }
2586
2749
 
@@ -2669,107 +2832,108 @@
2669
2832
  return;
2670
2833
  }
2671
2834
  const container = this.#container;
2672
- switch (particle.outType) {
2673
- case ParticleOutType.inside: {
2674
- const { x: vx, y: vy } = particle.velocity;
2675
- updateVector.setTo(originPoint);
2676
- updateVector.length = particle.moveCenter.radius;
2677
- updateVector.angle = particle.velocity.angle + Math.PI;
2678
- updateVector.addTo(particle.moveCenter);
2679
- const { dx, dy } = getDistances(particle.position, updateVector);
2680
- if ((vx <= minVelocity && dx >= minDistance) ||
2681
- (vy <= minVelocity && dy >= minDistance) ||
2682
- (vx >= minVelocity && dx <= minDistance) ||
2683
- (vy >= minVelocity && dy <= minDistance)) {
2684
- return;
2685
- }
2686
- particle.position.x = Math.floor(randomInRangeValue({
2687
- min: 0,
2688
- max: container.canvas.size.width,
2689
- }));
2690
- particle.position.y = Math.floor(randomInRangeValue({
2691
- min: 0,
2692
- max: container.canvas.size.height,
2693
- }));
2694
- const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2695
- particle.direction = Math.atan2(-newDy, -newDx);
2696
- particle.velocity.angle = particle.direction;
2697
- particle.justWarped = true;
2698
- break;
2835
+ if (particle.outType === ParticleOutType.inside) {
2836
+ this.#applyOutModeInside(particle, container);
2837
+ }
2838
+ else {
2839
+ if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2840
+ return;
2699
2841
  }
2700
- default: {
2701
- if (particle.isInsideCanvasForOutMode(outMode, direction)) {
2702
- return;
2703
- }
2704
- switch (particle.outType) {
2705
- case ParticleOutType.outside: {
2706
- particle.position.x =
2707
- Math.floor(randomInRangeValue({
2708
- min: -particle.moveCenter.radius,
2709
- max: particle.moveCenter.radius,
2710
- })) + particle.moveCenter.x;
2711
- particle.position.y =
2712
- Math.floor(randomInRangeValue({
2713
- min: -particle.moveCenter.radius,
2714
- max: particle.moveCenter.radius,
2715
- })) + particle.moveCenter.y;
2716
- const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2717
- if (particle.moveCenter.radius) {
2718
- particle.direction = Math.atan2(dy, dx);
2719
- particle.velocity.angle = particle.direction;
2720
- }
2721
- particle.justWarped = true;
2722
- break;
2723
- }
2724
- case ParticleOutType.normal: {
2725
- const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
2726
- bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
2727
- left: -particle.getRadius() - particle.offset.x,
2728
- right: canvasSize.width + particle.getRadius() + particle.offset.x,
2729
- top: -particle.getRadius() - particle.offset.y,
2730
- }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
2731
- if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2732
- particle.position.x = newPos.left;
2733
- particle.initialPosition.x = particle.position.x;
2734
- if (!warp) {
2735
- particle.position.y = getRandom() * canvasSize.height;
2736
- particle.initialPosition.y = particle.position.y;
2737
- }
2738
- particle.justWarped = true;
2739
- }
2740
- else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2741
- particle.position.x = newPos.right;
2742
- particle.initialPosition.x = particle.position.x;
2743
- if (!warp) {
2744
- particle.position.y = getRandom() * canvasSize.height;
2745
- particle.initialPosition.y = particle.position.y;
2746
- }
2747
- particle.justWarped = true;
2748
- }
2749
- if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2750
- if (!warp) {
2751
- particle.position.x = getRandom() * canvasSize.width;
2752
- particle.initialPosition.x = particle.position.x;
2753
- }
2754
- particle.position.y = newPos.top;
2755
- particle.initialPosition.y = particle.position.y;
2756
- particle.justWarped = true;
2757
- }
2758
- else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2759
- if (!warp) {
2760
- particle.position.x = getRandom() * canvasSize.width;
2761
- particle.initialPosition.x = particle.position.x;
2762
- }
2763
- particle.position.y = newPos.bottom;
2764
- particle.initialPosition.y = particle.position.y;
2765
- particle.justWarped = true;
2766
- }
2767
- break;
2768
- }
2769
- }
2770
- break;
2842
+ if (particle.outType === ParticleOutType.outside) {
2843
+ this.#applyParticleModeOutside(particle);
2771
2844
  }
2845
+ else {
2846
+ this.#applyOutModeNormal(particle, container, direction);
2847
+ }
2848
+ }
2849
+ }
2850
+ #applyOutModeInside(particle, container) {
2851
+ const { x: vx, y: vy } = particle.velocity;
2852
+ updateVector.setTo(originPoint);
2853
+ updateVector.length = particle.moveCenter.radius;
2854
+ updateVector.angle = particle.velocity.angle + Math.PI;
2855
+ updateVector.addTo(particle.moveCenter);
2856
+ const { dx, dy } = getDistances(particle.position, updateVector);
2857
+ if ((vx <= minVelocity && dx >= minDistance) ||
2858
+ (vy <= minVelocity && dy >= minDistance) ||
2859
+ (vx >= minVelocity && dx <= minDistance) ||
2860
+ (vy >= minVelocity && dy <= minDistance)) {
2861
+ return;
2772
2862
  }
2863
+ particle.position.x = Math.floor(randomInRangeValue({
2864
+ min: 0,
2865
+ max: container.canvas.size.width,
2866
+ }));
2867
+ particle.position.y = Math.floor(randomInRangeValue({
2868
+ min: 0,
2869
+ max: container.canvas.size.height,
2870
+ }));
2871
+ const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
2872
+ particle.direction = Math.atan2(-newDy, -newDx);
2873
+ particle.velocity.angle = particle.direction;
2874
+ particle.justWarped = true;
2875
+ }
2876
+ #applyOutModeNormal(particle, container, direction) {
2877
+ const warp = particle.options.move.warp, canvasSize = container.canvas.size, sizeValue = particle.getRadius(), newPos = {
2878
+ bottom: canvasSize.height + sizeValue + particle.offset.y,
2879
+ left: -sizeValue - particle.offset.x,
2880
+ right: canvasSize.width + sizeValue + particle.offset.x,
2881
+ top: -sizeValue - particle.offset.y,
2882
+ }, nextBounds = calculateBounds(particle.position, sizeValue);
2883
+ if (direction === OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
2884
+ particle.position.x = newPos.left;
2885
+ particle.initialPosition.x = particle.position.x;
2886
+ if (!warp) {
2887
+ particle.position.y = getRandom() * canvasSize.height;
2888
+ particle.initialPosition.y = particle.position.y;
2889
+ }
2890
+ particle.justWarped = true;
2891
+ }
2892
+ else if (direction === OutModeDirection.left && nextBounds.right < -particle.offset.x) {
2893
+ particle.position.x = newPos.right;
2894
+ particle.initialPosition.x = particle.position.x;
2895
+ if (!warp) {
2896
+ particle.position.y = getRandom() * canvasSize.height;
2897
+ particle.initialPosition.y = particle.position.y;
2898
+ }
2899
+ particle.justWarped = true;
2900
+ }
2901
+ if (direction === OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
2902
+ if (!warp) {
2903
+ particle.position.x = getRandom() * canvasSize.width;
2904
+ particle.initialPosition.x = particle.position.x;
2905
+ }
2906
+ particle.position.y = newPos.top;
2907
+ particle.initialPosition.y = particle.position.y;
2908
+ particle.justWarped = true;
2909
+ }
2910
+ else if (direction === OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
2911
+ if (!warp) {
2912
+ particle.position.x = getRandom() * canvasSize.width;
2913
+ particle.initialPosition.x = particle.position.x;
2914
+ }
2915
+ particle.position.y = newPos.bottom;
2916
+ particle.initialPosition.y = particle.position.y;
2917
+ particle.justWarped = true;
2918
+ }
2919
+ }
2920
+ #applyParticleModeOutside(particle) {
2921
+ particle.position.x =
2922
+ Math.floor(randomInRangeValue({
2923
+ min: -particle.moveCenter.radius,
2924
+ max: particle.moveCenter.radius,
2925
+ })) + particle.moveCenter.x;
2926
+ particle.position.y =
2927
+ Math.floor(randomInRangeValue({
2928
+ min: -particle.moveCenter.radius,
2929
+ max: particle.moveCenter.radius,
2930
+ })) + particle.moveCenter.y;
2931
+ const { dx, dy } = getDistances(particle.position, particle.moveCenter);
2932
+ if (particle.moveCenter.radius) {
2933
+ particle.direction = Math.atan2(dy, dx);
2934
+ particle.velocity.angle = particle.direction;
2935
+ }
2936
+ particle.justWarped = true;
2773
2937
  }
2774
2938
  }
2775
2939
 
@@ -2818,7 +2982,7 @@
2818
2982
  }
2819
2983
 
2820
2984
  async function loadOutModesUpdater(engine) {
2821
- engine.checkVersion("4.3.2");
2985
+ engine.checkVersion("4.5.0");
2822
2986
  await engine.pluginManager.register(e => {
2823
2987
  e.pluginManager.addParticleUpdater("outModes", container => {
2824
2988
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2835,39 +2999,9 @@
2835
2999
  this.#pluginManager = pluginManager;
2836
3000
  }
2837
3001
  init(particle) {
2838
- 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;
2839
- if (fill) {
2840
- const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
2841
- particle.fillEnabled = fill.enable;
2842
- particle.fillOpacity = getRangeValue(fill.opacity);
2843
- particle.fillAnimation = fillColor.animation;
2844
- const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
2845
- if (fillHslColor) {
2846
- particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
2847
- }
2848
- }
2849
- else {
2850
- particle.fillEnabled = false;
2851
- particle.fillAnimation = undefined;
2852
- particle.fillColor = undefined;
2853
- particle.fillOpacity = defaultOpacity;
2854
- }
2855
- if (stroke) {
2856
- const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
2857
- particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
2858
- particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
2859
- particle.strokeAnimation = strokeColor.animation;
2860
- const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
2861
- if (strokeHslColor) {
2862
- particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
2863
- }
2864
- }
2865
- else {
2866
- particle.strokeAnimation = undefined;
2867
- particle.strokeColor = undefined;
2868
- particle.strokeOpacity = defaultOpacity;
2869
- particle.strokeWidth = 0;
2870
- }
3002
+ const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates);
3003
+ this.#initFill(paint, particle, container);
3004
+ this.#initStroke(paint, particle, container);
2871
3005
  }
2872
3006
  isEnabled(particle) {
2873
3007
  const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
@@ -2879,17 +3013,55 @@
2879
3013
  (strokeColor?.l.value !== undefined && strokeColor.l.enable));
2880
3014
  return !particle.destroyed && !particle.spawning && (fillEnabled || strokeEnabled);
2881
3015
  }
2882
- update(particle, delta) {
2883
- if (!this.isEnabled(particle)) {
3016
+ update(particle, delta) {
3017
+ if (!this.isEnabled(particle)) {
3018
+ return;
3019
+ }
3020
+ updateColor(particle.fillColor, delta, this.#container.hdr);
3021
+ updateColor(particle.strokeColor, delta, this.#container.hdr);
3022
+ }
3023
+ #initFill(paint, particle, container) {
3024
+ const fill = paint?.fill, color = paint?.color, paintColor = color ?? undefined;
3025
+ if (!fill) {
3026
+ particle.fillEnabled = false;
3027
+ particle.fillAnimation = undefined;
3028
+ particle.fillColor = undefined;
3029
+ particle.fillOpacity = defaultOpacity;
3030
+ return;
3031
+ }
3032
+ const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
3033
+ particle.fillEnabled = fill.enable;
3034
+ particle.fillOpacity = getRangeValue(fill.opacity);
3035
+ particle.fillAnimation = fillColor.animation;
3036
+ const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
3037
+ if (!fillHslColor) {
3038
+ return;
3039
+ }
3040
+ particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
3041
+ }
3042
+ #initStroke(paint, particle, container) {
3043
+ const stroke = paint?.stroke, color = paint?.color, paintColor = color ?? undefined;
3044
+ if (!stroke) {
3045
+ particle.strokeAnimation = undefined;
3046
+ particle.strokeColor = undefined;
3047
+ particle.strokeOpacity = defaultOpacity;
3048
+ particle.strokeWidth = 0;
2884
3049
  return;
2885
3050
  }
2886
- updateColor(particle.fillColor, delta, this.#container.hdr);
2887
- updateColor(particle.strokeColor, delta, this.#container.hdr);
3051
+ const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
3052
+ particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
3053
+ particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
3054
+ particle.strokeAnimation = strokeColor.animation;
3055
+ const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
3056
+ if (!strokeHslColor) {
3057
+ return;
3058
+ }
3059
+ particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
2888
3060
  }
2889
3061
  }
2890
3062
 
2891
3063
  async function loadPaintUpdater(engine) {
2892
- engine.checkVersion("4.3.2");
3064
+ engine.checkVersion("4.5.0");
2893
3065
  await engine.pluginManager.register(e => {
2894
3066
  e.pluginManager.addParticleUpdater("paint", container => {
2895
3067
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2931,7 +3103,7 @@
2931
3103
  if (!this.accepts(input)) {
2932
3104
  return;
2933
3105
  }
2934
- const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
3106
+ const result = rgbRegex.exec(input), radix = 10, minLength = 4;
2935
3107
  return result
2936
3108
  ? {
2937
3109
  a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
@@ -2944,7 +3116,7 @@
2944
3116
  }
2945
3117
 
2946
3118
  async function loadRgbColorPlugin(engine) {
2947
- engine.checkVersion("4.3.2");
3119
+ engine.checkVersion("4.5.0");
2948
3120
  await engine.pluginManager.register(e => {
2949
3121
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2950
3122
  });
@@ -3029,7 +3201,7 @@
3029
3201
  }
3030
3202
 
3031
3203
  async function loadSizeUpdater(engine) {
3032
- engine.checkVersion("4.3.2");
3204
+ engine.checkVersion("4.5.0");
3033
3205
  await engine.pluginManager.register(e => {
3034
3206
  e.pluginManager.addParticleUpdater("size", container => {
3035
3207
  return Promise.resolve(new SizeUpdater(container));
@@ -3038,7 +3210,7 @@
3038
3210
  }
3039
3211
 
3040
3212
  async function loadBasic(engine) {
3041
- engine.checkVersion("4.3.2");
3213
+ engine.checkVersion("4.5.0");
3042
3214
  await engine.pluginManager.register(async (e) => {
3043
3215
  await Promise.all([
3044
3216
  loadBlendPlugin(e),
@@ -3174,7 +3346,7 @@
3174
3346
  }
3175
3347
 
3176
3348
  async function loadWobbleUpdater(engine) {
3177
- engine.checkVersion("4.3.2");
3349
+ engine.checkVersion("4.5.0");
3178
3350
  await engine.pluginManager.register(e => {
3179
3351
  e.pluginManager.addParticleUpdater("wobble", container => {
3180
3352
  return Promise.resolve(new WobbleUpdater(container));
@@ -3286,21 +3458,28 @@
3286
3458
  });
3287
3459
  }
3288
3460
  clear() {
3461
+ const visited = new Set();
3289
3462
  for (const plugin of this.#canvasClearPlugins) {
3463
+ visited.add(plugin);
3290
3464
  if (plugin.canvasClear?.() ?? false) {
3291
- return;
3465
+ return plugin;
3292
3466
  }
3293
3467
  }
3294
3468
  for (const layer of Object.values(DrawLayer)) {
3295
3469
  if (typeof layer === "number") {
3296
3470
  for (const plugin of this.#getLayerPlugins(layer)) {
3471
+ if (visited.has(plugin)) {
3472
+ continue;
3473
+ }
3474
+ visited.add(plugin);
3297
3475
  if (plugin.canvasClear?.() ?? false) {
3298
- return;
3476
+ return plugin;
3299
3477
  }
3300
3478
  }
3301
3479
  }
3302
3480
  }
3303
3481
  this.canvasClear();
3482
+ return undefined;
3304
3483
  }
3305
3484
  destroy() {
3306
3485
  this.stop();
@@ -3341,7 +3520,11 @@
3341
3520
  if (!fColor && !sColor) {
3342
3521
  return;
3343
3522
  }
3344
- 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;
3523
+ 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
3524
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3525
+ : undefined, stroke = sColor
3526
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3527
+ : fill;
3345
3528
  transform.a = transform.b = transform.c = transform.d = undefined;
3346
3529
  colorStyles.fill = fill;
3347
3530
  colorStyles.stroke = stroke;
@@ -3374,8 +3557,7 @@
3374
3557
  });
3375
3558
  }
3376
3559
  drawParticles(delta) {
3377
- const { particles, actualOptions } = this.#container;
3378
- this.clear();
3560
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
3379
3561
  particles.update(delta);
3380
3562
  this.draw(ctx => {
3381
3563
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -3397,7 +3579,9 @@
3397
3579
  }
3398
3580
  }
3399
3581
  for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3400
- plugin.canvasPaint?.();
3582
+ if (plugin !== clearedPlugin) {
3583
+ plugin.canvasPaint?.();
3584
+ }
3401
3585
  }
3402
3586
  for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3403
3587
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -3429,35 +3613,7 @@
3429
3613
  this.#layers[layer] = [];
3430
3614
  }
3431
3615
  }
3432
- for (const plugin of this.#container.plugins) {
3433
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3434
- this.#colorPlugins.push(plugin);
3435
- }
3436
- if (plugin.drawParticle) {
3437
- this.#drawParticlePlugins.push(plugin);
3438
- }
3439
- if (plugin.drawParticleSetup) {
3440
- this.#drawParticlesSetupPlugins.push(plugin);
3441
- }
3442
- if (plugin.drawParticleCleanup) {
3443
- this.#drawParticlesCleanupPlugins.push(plugin);
3444
- }
3445
- if (plugin.canvasClear) {
3446
- this.#canvasClearPlugins.push(plugin);
3447
- }
3448
- if (plugin.canvasPaint) {
3449
- this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3450
- }
3451
- if (plugin.drawSettingsSetup) {
3452
- this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3453
- }
3454
- if (plugin.draw) {
3455
- this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3456
- }
3457
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3458
- this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3459
- }
3460
- }
3616
+ this.#initPluginsArray();
3461
3617
  }
3462
3618
  initUpdaters() {
3463
3619
  this.#preDrawUpdaters = [];
@@ -3666,6 +3822,45 @@
3666
3822
  this.#reusablePluginColors[sColorIndex] = sColor;
3667
3823
  return this.#reusablePluginColors;
3668
3824
  }
3825
+ #initLayerPlugin(plugin) {
3826
+ const layerMap = [
3827
+ [DrawLayer.BackgroundMask, !!plugin.canvasPaint],
3828
+ [DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
3829
+ [DrawLayer.PluginContent, !!plugin.draw],
3830
+ [DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
3831
+ ];
3832
+ for (const [layer, active] of layerMap) {
3833
+ if (active) {
3834
+ this.#layers[layer].push(plugin);
3835
+ }
3836
+ }
3837
+ }
3838
+ #initPluginsArray() {
3839
+ for (const plugin of this.#container.plugins) {
3840
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3841
+ this.#colorPlugins.push(plugin);
3842
+ }
3843
+ if (plugin.drawParticle) {
3844
+ this.#drawParticlePlugins.push(plugin);
3845
+ }
3846
+ if (plugin.drawParticleSetup) {
3847
+ this.#drawParticlesSetupPlugins.push(plugin);
3848
+ }
3849
+ if (plugin.drawParticleCleanup) {
3850
+ this.#drawParticlesCleanupPlugins.push(plugin);
3851
+ }
3852
+ if (plugin.canvasClear) {
3853
+ this.#canvasClearPlugins.push(plugin);
3854
+ }
3855
+ this.#initLayerPlugin(plugin);
3856
+ }
3857
+ }
3858
+ #isSupportedElement(element) {
3859
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
3860
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
3861
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
3862
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
3863
+ }
3669
3864
  #resolveBackgroundElement() {
3670
3865
  const background = this.#container.actualOptions.background;
3671
3866
  this.#backgroundElement = null;
@@ -3675,7 +3870,7 @@
3675
3870
  if (typeof background.element === "string") {
3676
3871
  if (typeof document !== "undefined") {
3677
3872
  const node = document.querySelector(background.element);
3678
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
3873
+ if (node && this.#isSupportedElement(node)) {
3679
3874
  this.#backgroundElement = node;
3680
3875
  }
3681
3876
  else if (node) {
@@ -3686,10 +3881,7 @@
3686
3881
  }
3687
3882
  }
3688
3883
  }
3689
- else if (background.element instanceof HTMLCanvasElement ||
3690
- background.element instanceof OffscreenCanvas ||
3691
- background.element instanceof HTMLVideoElement ||
3692
- background.element instanceof HTMLImageElement) {
3884
+ else if (this.#isSupportedElement(background.element)) {
3693
3885
  this.#backgroundElement = background.element;
3694
3886
  }
3695
3887
  }
@@ -3707,7 +3899,7 @@
3707
3899
  return transferredCanvas;
3708
3900
  }
3709
3901
  if (typeof canvas.transferControlToOffscreen !== "function") {
3710
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
3902
+ throw new TypeError(getErrorMessage(ErrorCodes$1.offscreenCanvasUnsupported));
3711
3903
  }
3712
3904
  try {
3713
3905
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -3715,10 +3907,16 @@
3715
3907
  return offscreenCanvas;
3716
3908
  }
3717
3909
  catch {
3718
- throw new TypeError("OffscreenCanvas transfer failed");
3910
+ throw new TypeError(getErrorMessage(ErrorCodes$1.offscreenCanvasTransferFailed));
3719
3911
  }
3720
3912
  }, isHtmlCanvasElement = (canvas) => {
3721
3913
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
3914
+ }, getEffectiveColorSpace = (context) => {
3915
+ if (!context) {
3916
+ return undefined;
3917
+ }
3918
+ const colorInfo = context;
3919
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
3722
3920
  };
3723
3921
  function setStyle(canvas, style, important = false) {
3724
3922
  if (!style) {
@@ -3757,6 +3955,7 @@
3757
3955
  zoom = defaultZoom;
3758
3956
  #container;
3759
3957
  #generated;
3958
+ #hdrMediaListeners;
3760
3959
  #mutationObserver;
3761
3960
  #originalStyle;
3762
3961
  #pluginManager;
@@ -3821,7 +4020,6 @@
3821
4020
  });
3822
4021
  this.resize();
3823
4022
  this.#initStyle();
3824
- this.initBackground();
3825
4023
  this.#safeMutationObserver(obs => {
3826
4024
  const element = this.domElement;
3827
4025
  if (!element || !(element instanceof Node)) {
@@ -3831,6 +4029,8 @@
3831
4029
  });
3832
4030
  this.initPlugins();
3833
4031
  this.#initContext();
4032
+ this.initBackground();
4033
+ this.#initHdrListeners();
3834
4034
  this.render.init();
3835
4035
  }
3836
4036
  initBackground() {
@@ -3840,7 +4040,8 @@
3840
4040
  }
3841
4041
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
3842
4042
  if (color) {
3843
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4043
+ const hdrOptions = container.actualOptions.hdr;
4044
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard));
3844
4045
  }
3845
4046
  else {
3846
4047
  elementStyle.backgroundColor = "";
@@ -3937,6 +4138,7 @@
3937
4138
  obs.disconnect();
3938
4139
  });
3939
4140
  this.#mutationObserver = undefined;
4141
+ this.#removeHdrListeners();
3940
4142
  this.render.stop();
3941
4143
  }
3942
4144
  async windowResize() {
@@ -3956,9 +4158,16 @@
3956
4158
  }
3957
4159
  }
3958
4160
  #initContext() {
3959
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4161
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
3960
4162
  safeMatchMedia("(color-gamut: p3)")?.matches &&
3961
4163
  safeMatchMedia("(dynamic-range: high)")?.matches;
4164
+ container.hdrMode = toEnumValue(HdrMode, container.actualOptions.hdr.mode, HdrMode.standard);
4165
+ container.peakNits = container.actualOptions.hdr.peakNits;
4166
+ const renderCanvas = this.renderCanvas;
4167
+ if (!renderCanvas) {
4168
+ container.hdr = canSupportHdr ?? false;
4169
+ return;
4170
+ }
3962
4171
  this.render.setContextSettings({
3963
4172
  alpha: true,
3964
4173
  desynchronized: true,
@@ -3967,11 +4176,51 @@
3967
4176
  ? { colorSpace: "display-p3", colorType: "float16" }
3968
4177
  : { colorSpace: "srgb" }),
3969
4178
  });
3970
- const renderCanvas = this.renderCanvas;
3971
- if (!renderCanvas) {
3972
- return;
4179
+ let context;
4180
+ try {
4181
+ context = renderCanvas.getContext("2d", this.render.settings);
4182
+ }
4183
+ catch {
4184
+ context = null;
4185
+ }
4186
+ if (canSupportHdr && !context) {
4187
+ const sdrSettings = {
4188
+ alpha: true,
4189
+ desynchronized: true,
4190
+ willReadFrequently: false,
4191
+ colorSpace: "srgb",
4192
+ };
4193
+ this.render.setContextSettings(sdrSettings);
4194
+ try {
4195
+ context = renderCanvas.getContext("2d", sdrSettings);
4196
+ }
4197
+ catch {
4198
+ context = null;
4199
+ }
4200
+ }
4201
+ this.render.setContext(context);
4202
+ if (context) {
4203
+ const effectiveColorSpace = getEffectiveColorSpace(context);
4204
+ if (effectiveColorSpace !== undefined) {
4205
+ container.hdr = effectiveColorSpace === "display-p3";
4206
+ }
3973
4207
  }
3974
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4208
+ }
4209
+ #initHdrListeners() {
4210
+ this.#removeHdrListeners();
4211
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4212
+ this.#initContext();
4213
+ this.initBackground();
4214
+ }, listeners = [];
4215
+ if (p3Query) {
4216
+ p3Query.addEventListener("change", handleChange);
4217
+ listeners.push({ handler: handleChange, mql: p3Query });
4218
+ }
4219
+ if (hdrQuery) {
4220
+ hdrQuery.addEventListener("change", handleChange);
4221
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4222
+ }
4223
+ this.#hdrMediaListeners = listeners;
3975
4224
  }
3976
4225
  #initStyle() {
3977
4226
  const element = this.domElement, options = this.#container.actualOptions;
@@ -3995,6 +4244,15 @@
3995
4244
  element.style.setProperty(key, value, "important");
3996
4245
  }
3997
4246
  }
4247
+ #removeHdrListeners() {
4248
+ if (!this.#hdrMediaListeners) {
4249
+ return;
4250
+ }
4251
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4252
+ mql.removeEventListener("change", handler);
4253
+ }
4254
+ this.#hdrMediaListeners = undefined;
4255
+ }
3998
4256
  #repairStyle() {
3999
4257
  const element = this.domElement;
4000
4258
  if (!element) {
@@ -4084,8 +4342,7 @@
4084
4342
  this.#resizeTimeout = undefined;
4085
4343
  }
4086
4344
  const handleResize = async () => {
4087
- const canvas = this.#container.canvas;
4088
- await canvas.windowResize();
4345
+ await this.#container.canvas.windowResize();
4089
4346
  };
4090
4347
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
4091
4348
  }
@@ -4113,8 +4370,8 @@
4113
4370
  }
4114
4371
  else if (!this.#resizeObserver && add && canvasEl) {
4115
4372
  this.#resizeObserver = new ResizeObserver((entries) => {
4116
- const entry = entries.find(e => e.target === canvasEl);
4117
- if (!entry) {
4373
+ const res = entries.some(e => e.target === canvasEl);
4374
+ if (!res) {
4118
4375
  return;
4119
4376
  }
4120
4377
  this.#handleWindowResize();
@@ -4378,10 +4635,10 @@
4378
4635
  return this.#modifiers.find(m => m.id === id);
4379
4636
  }
4380
4637
  getOpacity() {
4381
- 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;
4382
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4638
+ 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;
4639
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
4383
4640
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4384
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4641
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
4385
4642
  return this.#cachedOpacityData;
4386
4643
  }
4387
4644
  getPosition() {
@@ -4628,7 +4885,7 @@
4628
4885
  #initPosition(position) {
4629
4886
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4630
4887
  if (!initialPosition) {
4631
- throw new Error("a valid position cannot be found for particle");
4888
+ throw new Error(getErrorMessage(ErrorCodes$1.particlePositionNotFound));
4632
4889
  }
4633
4890
  this.position = initialPosition;
4634
4891
  this.initialPosition = this.position.copy();
@@ -4677,6 +4934,12 @@
4677
4934
  this.#circlePoolIdx = 0;
4678
4935
  this.#rectanglePoolIdx = 0;
4679
4936
  }
4937
+ get cellSize() {
4938
+ return this.#cellSize;
4939
+ }
4940
+ set cellSize(value) {
4941
+ this.#pendingCellSize = value;
4942
+ }
4680
4943
  clear() {
4681
4944
  this.#cells.clear();
4682
4945
  const pendingCellSize = this.#pendingCellSize;
@@ -4700,18 +4963,7 @@
4700
4963
  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);
4701
4964
  for (let cx = minCellX; cx <= maxCellX; cx++) {
4702
4965
  for (let cy = minCellY; cy <= maxCellY; cy++) {
4703
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
4704
- if (!cellParticles) {
4705
- continue;
4706
- }
4707
- for (const p of cellParticles) {
4708
- if (check && !check(p)) {
4709
- continue;
4710
- }
4711
- if (range.contains(p.getPosition())) {
4712
- out.push(p);
4713
- }
4714
- }
4966
+ this.#queryCell(cx, cy, range, check, out);
4715
4967
  }
4716
4968
  }
4717
4969
  return out;
@@ -4726,14 +4978,23 @@
4726
4978
  this.#releaseShapes();
4727
4979
  return result;
4728
4980
  }
4729
- setCellSize(cellSize) {
4730
- this.#pendingCellSize = cellSize;
4731
- }
4732
4981
  #acquireCircle(x, y, r) {
4733
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
4982
+ const idx = this.#circlePoolIdx++;
4983
+ let circle = this.#circlePool[idx];
4984
+ if (!circle) {
4985
+ circle = new Circle(x, y, r);
4986
+ this.#circlePool[idx] = circle;
4987
+ }
4988
+ return circle.reset(x, y, r);
4734
4989
  }
4735
4990
  #acquireRectangle(x, y, w, h) {
4736
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
4991
+ const idx = this.#rectanglePoolIdx++;
4992
+ let rectangle = this.#rectanglePool[idx];
4993
+ if (!rectangle) {
4994
+ rectangle = new Rectangle(x, y, w, h);
4995
+ this.#rectanglePool[idx] = rectangle;
4996
+ }
4997
+ return rectangle.reset(x, y, w, h);
4737
4998
  }
4738
4999
  #cellKeyFromCoords(x, y) {
4739
5000
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -4760,6 +5021,20 @@
4760
5021
  }
4761
5022
  return null;
4762
5023
  }
5024
+ #queryCell(cx, cy, range, check, out) {
5025
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
5026
+ if (!cellParticles) {
5027
+ return;
5028
+ }
5029
+ for (const p of cellParticles) {
5030
+ if (check && !check(p)) {
5031
+ continue;
5032
+ }
5033
+ if (range.contains(p.getPosition())) {
5034
+ out.push(p);
5035
+ }
5036
+ }
5037
+ }
4763
5038
  #releaseShapes() {
4764
5039
  this.#circlePoolIdx = 0;
4765
5040
  this.#rectanglePoolIdx = 0;
@@ -4768,9 +5043,9 @@
4768
5043
 
4769
5044
  class ParticlesManager {
4770
5045
  checkParticlePositionPlugins;
4771
- grid;
4772
5046
  #array;
4773
5047
  #container;
5048
+ #grid;
4774
5049
  #groupLimits;
4775
5050
  #limit;
4776
5051
  #nextId;
@@ -4794,7 +5069,7 @@
4794
5069
  this.#groupLimits = new Map();
4795
5070
  this.#particleBuckets = new Map();
4796
5071
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
4797
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5072
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
4798
5073
  this.checkParticlePositionPlugins = [];
4799
5074
  this.#particleResetPlugins = [];
4800
5075
  this.#particleUpdatePlugins = [];
@@ -4805,23 +5080,12 @@
4805
5080
  get count() {
4806
5081
  return this.#array.length;
4807
5082
  }
5083
+ get grid() {
5084
+ return this.#grid;
5085
+ }
4808
5086
  addParticle(position, overrideOptions, group, initializer) {
4809
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
4810
- if (limit > minLimit) {
4811
- switch (limitMode) {
4812
- case LimitMode.delete: {
4813
- const countToRemove = currentCount + countOffset - limit;
4814
- if (countToRemove > minCount) {
4815
- this.removeQuantity(countToRemove);
4816
- }
4817
- break;
4818
- }
4819
- case LimitMode.wait:
4820
- if (currentCount >= limit) {
4821
- return;
4822
- }
4823
- break;
4824
- }
5087
+ if (this.#checkAndApplyLimits(group, this.count)) {
5088
+ return;
4825
5089
  }
4826
5090
  try {
4827
5091
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -4885,7 +5149,7 @@
4885
5149
  return this.#array[index];
4886
5150
  }
4887
5151
  async init() {
4888
- const container = this.#container, options = container.actualOptions;
5152
+ const container = this.#container;
4889
5153
  this.checkParticlePositionPlugins = [];
4890
5154
  this.#updatePlugins = [];
4891
5155
  this.#particleUpdatePlugins = [];
@@ -4894,59 +5158,16 @@
4894
5158
  this.#postParticleUpdatePlugins = [];
4895
5159
  this.#particleBuckets.clear();
4896
5160
  this.#resetBuckets(container.zLayers);
4897
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
4898
- for (const plugin of container.plugins) {
4899
- if (plugin.redrawInit) {
4900
- await plugin.redrawInit();
4901
- }
4902
- if (plugin.checkParticlePosition) {
4903
- this.checkParticlePositionPlugins.push(plugin);
4904
- }
4905
- if (plugin.update) {
4906
- this.#updatePlugins.push(plugin);
4907
- }
4908
- if (plugin.particleUpdate) {
4909
- this.#particleUpdatePlugins.push(plugin);
4910
- }
4911
- if (plugin.postUpdate) {
4912
- this.#postUpdatePlugins.push(plugin);
4913
- }
4914
- if (plugin.particleReset) {
4915
- this.#particleResetPlugins.push(plugin);
4916
- }
4917
- if (plugin.postParticleUpdate) {
4918
- this.#postParticleUpdatePlugins.push(plugin);
4919
- }
4920
- }
4921
- await this.#container.initDrawersAndUpdaters();
4922
- for (const drawer of this.#container.effectDrawers.values()) {
4923
- await drawer.init?.(container);
4924
- }
4925
- for (const drawer of this.#container.shapeDrawers.values()) {
4926
- await drawer.init?.(container);
4927
- }
4928
- let handled = false;
4929
- for (const plugin of container.plugins) {
4930
- handled = plugin.particlesInitialization?.() ?? handled;
4931
- if (handled) {
4932
- break;
4933
- }
4934
- }
4935
- if (!handled) {
4936
- const particlesOptions = options.particles, groups = particlesOptions.groups;
4937
- for (const group in groups) {
4938
- const groupOptions = groups[group];
4939
- if (!groupOptions) {
4940
- continue;
4941
- }
4942
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
4943
- this.addParticle(undefined, groupOptions, group);
4944
- }
4945
- }
4946
- for (let i = this.count; i < particlesOptions.number.value; i++) {
4947
- this.addParticle();
5161
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5162
+ this.#applyLimits(container.actualOptions.particles);
5163
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5164
+ for (const group in groups) {
5165
+ const groupData = groups[group];
5166
+ if (groupData) {
5167
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
4948
5168
  }
4949
5169
  }
5170
+ await this.#initPlugins();
4950
5171
  }
4951
5172
  push(nb, position, overrideOptions, group) {
4952
5173
  for (let i = 0; i < nb; i++) {
@@ -4961,13 +5182,13 @@
4961
5182
  remove(particle, group, override) {
4962
5183
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
4963
5184
  }
4964
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
5185
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
4965
5186
  if (index < minIndex || index > this.count) {
4966
5187
  return;
4967
5188
  }
4968
5189
  let deleted = 0;
4969
5190
  for (let i = index; deleted < quantity && i < this.count; i++) {
4970
- if (this.#removeParticle(i, group, override)) {
5191
+ if (this.#removeParticle(i, group, override, matchGroup)) {
4971
5192
  i--;
4972
5193
  deleted++;
4973
5194
  }
@@ -4998,7 +5219,7 @@
4998
5219
  this.#resizeFactor = factor;
4999
5220
  }
5000
5221
  update(delta) {
5001
- this.grid.clear();
5222
+ this.#grid.clear();
5002
5223
  for (const plugin of this.#updatePlugins) {
5003
5224
  plugin.update?.(delta);
5004
5225
  }
@@ -5009,7 +5230,7 @@
5009
5230
  this.#updateParticlesPhase2(delta, particlesToDelete);
5010
5231
  if (particlesToDelete.size) {
5011
5232
  for (const particle of particlesToDelete) {
5012
- this.remove(particle);
5233
+ this.remove(particle, particle.group);
5013
5234
  }
5014
5235
  }
5015
5236
  this.#resizeFactor = undefined;
@@ -5020,12 +5241,7 @@
5020
5241
  #applyDensity(options, pluginsCount, group, groupOptions) {
5021
5242
  const numberOptions = options.number;
5022
5243
  if (!numberOptions.density.enable) {
5023
- if (group === undefined) {
5024
- this.#limit = numberOptions.limit.value;
5025
- }
5026
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
5027
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
5028
- }
5244
+ this.#applyLimits(options, group, groupOptions);
5029
5245
  return;
5030
5246
  }
5031
5247
  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);
@@ -5033,7 +5249,10 @@
5033
5249
  this.#limit = numberOptions.limit.value * densityFactor;
5034
5250
  }
5035
5251
  else {
5036
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
5252
+ this.#groupLimits.set(group, {
5253
+ limit: numberOptions.limit.value * densityFactor,
5254
+ mode: toEnumValue(LimitMode, numberOptions.limit.mode, LimitMode.delete),
5255
+ });
5037
5256
  }
5038
5257
  if (particlesCount < particlesNumber) {
5039
5258
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -5042,6 +5261,55 @@
5042
5261
  this.removeQuantity(particlesCount - particlesNumber, group);
5043
5262
  }
5044
5263
  }
5264
+ #applyLimits(options, group, groupOptions) {
5265
+ if (group === undefined) {
5266
+ this.#limit = options.number.limit.value;
5267
+ const groups = this.#container.actualOptions.particles.groups;
5268
+ for (const existingGroup of this.#groupLimits.keys()) {
5269
+ if (!(existingGroup in groups)) {
5270
+ this.#groupLimits.delete(existingGroup);
5271
+ }
5272
+ }
5273
+ }
5274
+ else {
5275
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
5276
+ if (limitValue > minLimit) {
5277
+ this.#groupLimits.set(group, {
5278
+ limit: limitValue,
5279
+ mode: toEnumValue(LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, LimitMode.delete),
5280
+ });
5281
+ }
5282
+ else {
5283
+ this.#groupLimits.delete(group);
5284
+ }
5285
+ }
5286
+ }
5287
+ #checkAndApplyLimits(group, currentCount) {
5288
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
5289
+ if (globalLimit > minLimit && globalMode === LimitMode.wait && currentCount >= globalLimit) {
5290
+ return true;
5291
+ }
5292
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
5293
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.wait) {
5294
+ const groupCount = this.filter(t => t.group === group).length;
5295
+ if (groupCount >= groupLimitEntry.limit) {
5296
+ return true;
5297
+ }
5298
+ }
5299
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.delete) {
5300
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
5301
+ if (groupCountToRemove > minCount) {
5302
+ this.removeQuantity(groupCountToRemove, group);
5303
+ }
5304
+ }
5305
+ if (globalLimit > minLimit && globalMode === LimitMode.delete) {
5306
+ const globalCountToRemove = this.count + countOffset - globalLimit;
5307
+ if (globalCountToRemove > minCount) {
5308
+ this.#removeAny(globalCountToRemove);
5309
+ }
5310
+ }
5311
+ return false;
5312
+ }
5045
5313
  #createBuckets(zLayers) {
5046
5314
  const bucketCount = Math.max(Math.floor(zLayers), one);
5047
5315
  return Array.from({ length: bucketCount }, () => []);
@@ -5064,6 +5332,70 @@
5064
5332
  }
5065
5333
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5066
5334
  }
5335
+ async #initDrawersAndUpdaters() {
5336
+ const container = this.#container;
5337
+ await container.initDrawersAndUpdaters();
5338
+ for (const drawer of container.effectDrawers.values()) {
5339
+ await drawer.init?.(container);
5340
+ }
5341
+ for (const drawer of container.shapeDrawers.values()) {
5342
+ await drawer.init?.(container);
5343
+ }
5344
+ }
5345
+ async #initPlugins() {
5346
+ await this.#initPluginsArrays();
5347
+ await this.#initDrawersAndUpdaters();
5348
+ let handled = false;
5349
+ const container = this.#container;
5350
+ for (const plugin of container.plugins) {
5351
+ handled = plugin.particlesInitialization?.() ?? handled;
5352
+ if (handled) {
5353
+ break;
5354
+ }
5355
+ }
5356
+ if (handled) {
5357
+ return;
5358
+ }
5359
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5360
+ for (const group in groups) {
5361
+ const groupOptions = groups[group];
5362
+ if (!groupOptions) {
5363
+ continue;
5364
+ }
5365
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5366
+ this.addParticle(undefined, groupOptions, group);
5367
+ }
5368
+ }
5369
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
5370
+ this.addParticle();
5371
+ }
5372
+ }
5373
+ async #initPluginsArrays() {
5374
+ const container = this.#container;
5375
+ for (const plugin of container.plugins) {
5376
+ if (plugin.redrawInit) {
5377
+ await plugin.redrawInit();
5378
+ }
5379
+ if (plugin.checkParticlePosition) {
5380
+ this.checkParticlePositionPlugins.push(plugin);
5381
+ }
5382
+ if (plugin.update) {
5383
+ this.#updatePlugins.push(plugin);
5384
+ }
5385
+ if (plugin.particleUpdate) {
5386
+ this.#particleUpdatePlugins.push(plugin);
5387
+ }
5388
+ if (plugin.postUpdate) {
5389
+ this.#postUpdatePlugins.push(plugin);
5390
+ }
5391
+ if (plugin.particleReset) {
5392
+ this.#particleResetPlugins.push(plugin);
5393
+ }
5394
+ if (plugin.postParticleUpdate) {
5395
+ this.#postParticleUpdatePlugins.push(plugin);
5396
+ }
5397
+ }
5398
+ }
5067
5399
  #insertParticleIntoBucket(particle) {
5068
5400
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
5069
5401
  if (!bucket) {
@@ -5072,12 +5404,15 @@
5072
5404
  bucket.push(particle);
5073
5405
  this.#particleBuckets.set(particle.id, bucketIndex);
5074
5406
  }
5075
- #removeParticle(index, group, override) {
5407
+ #removeAny(quantity) {
5408
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
5409
+ }
5410
+ #removeParticle(index, group, override, matchGroup = true) {
5076
5411
  const particle = this.#array[index];
5077
5412
  if (!particle) {
5078
5413
  return false;
5079
5414
  }
5080
- if (particle.group !== group) {
5415
+ if (matchGroup && particle.group !== group) {
5081
5416
  return false;
5082
5417
  }
5083
5418
  this.#array.splice(index, deleteCount);
@@ -5164,7 +5499,7 @@
5164
5499
  particlesToDelete.add(particle);
5165
5500
  continue;
5166
5501
  }
5167
- this.grid.insert(particle);
5502
+ this.#grid.insert(particle);
5168
5503
  }
5169
5504
  return particlesToDelete;
5170
5505
  }
@@ -5236,6 +5571,7 @@
5236
5571
  effectDrawers;
5237
5572
  fpsLimit;
5238
5573
  hdr;
5574
+ hdrMode;
5239
5575
  id;
5240
5576
  pageHidden;
5241
5577
  particleCreatedPlugins;
@@ -5243,6 +5579,7 @@
5243
5579
  particlePositionPlugins;
5244
5580
  particleUpdaters;
5245
5581
  particles;
5582
+ peakNits;
5246
5583
  plugins;
5247
5584
  retina;
5248
5585
  shapeDrawers;
@@ -5273,6 +5610,8 @@
5273
5610
  this.id = Symbol(id);
5274
5611
  this.fpsLimit = 120;
5275
5612
  this.hdr = false;
5613
+ this.hdrMode = HdrMode.standard;
5614
+ this.peakNits = 400;
5276
5615
  this.#smooth = false;
5277
5616
  this.#delay = 0;
5278
5617
  this.#duration = 0;
@@ -5336,7 +5675,6 @@
5336
5675
  this.shapeDrawers = new Map();
5337
5676
  this.particleUpdaters = [];
5338
5677
  this.plugins.length = 0;
5339
- this.#pluginManager.clearPlugins(this);
5340
5678
  this.destroyed = true;
5341
5679
  this.#onDestroy(remove);
5342
5680
  this.dispatchEvent(EventType.containerDestroyed);
@@ -5389,31 +5727,15 @@
5389
5727
  await this.initDrawersAndUpdaters();
5390
5728
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
5391
5729
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
5392
- this.plugins.length = 0;
5393
- this.particleDestroyedPlugins.length = 0;
5394
- this.particleCreatedPlugins.length = 0;
5395
- this.particlePositionPlugins.length = 0;
5396
- for (const [plugin, containerPlugin] of allContainerPlugins) {
5397
- if (plugin.needsPlugin(this.actualOptions)) {
5398
- this.plugins.push(containerPlugin);
5399
- if (containerPlugin.particleCreated) {
5400
- this.particleCreatedPlugins.push(containerPlugin);
5401
- }
5402
- if (containerPlugin.particleDestroyed) {
5403
- this.particleDestroyedPlugins.push(containerPlugin);
5404
- }
5405
- if (containerPlugin.particlePosition) {
5406
- this.particlePositionPlugins.push(containerPlugin);
5407
- }
5408
- }
5409
- }
5730
+ this.#initPlugins(allContainerPlugins);
5410
5731
  this.retina.init();
5411
5732
  this.canvas.init();
5412
5733
  this.updateActualOptions();
5413
5734
  this.canvas.initBackground();
5414
5735
  this.canvas.resize();
5415
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5416
- this.hdr = hdr;
5736
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
5737
+ this.hdrMode = toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard);
5738
+ this.peakNits = hdrOptions.peakNits;
5417
5739
  this.zLayers = zLayers;
5418
5740
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5419
5741
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -5433,9 +5755,9 @@
5433
5755
  }
5434
5756
  async initDrawersAndUpdaters() {
5435
5757
  const pluginManager = this.#pluginManager;
5436
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
5437
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
5438
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
5758
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
5759
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
5760
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
5439
5761
  }
5440
5762
  pause() {
5441
5763
  if (!guardCheck(this)) {
@@ -5546,6 +5868,27 @@
5546
5868
  }
5547
5869
  return refresh;
5548
5870
  }
5871
+ #initPlugins(allContainerPlugins) {
5872
+ this.plugins.length = 0;
5873
+ this.particleDestroyedPlugins.length = 0;
5874
+ this.particleCreatedPlugins.length = 0;
5875
+ this.particlePositionPlugins.length = 0;
5876
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
5877
+ if (!plugin.needsPlugin(this.actualOptions)) {
5878
+ continue;
5879
+ }
5880
+ this.plugins.push(containerPlugin);
5881
+ if (containerPlugin.particleCreated) {
5882
+ this.particleCreatedPlugins.push(containerPlugin);
5883
+ }
5884
+ if (containerPlugin.particleDestroyed) {
5885
+ this.particleDestroyedPlugins.push(containerPlugin);
5886
+ }
5887
+ if (containerPlugin.particlePosition) {
5888
+ this.particlePositionPlugins.push(containerPlugin);
5889
+ }
5890
+ }
5891
+ }
5549
5892
  #nextFrame(timestamp) {
5550
5893
  try {
5551
5894
  if (!this.#smooth &&
@@ -5822,11 +6165,11 @@
5822
6165
  }
5823
6166
  }
5824
6167
  async #init() {
5825
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
5826
- if (!availablePathGenerators) {
6168
+ const pluginManager = this.#pluginManager;
6169
+ if (!pluginManager.initializers.pathGenerators) {
5827
6170
  return;
5828
6171
  }
5829
- this.availablePathGenerators = availablePathGenerators;
6172
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
5830
6173
  this.pathGenerators = new Map();
5831
6174
  for (const pathGenerator of this.pathGenerators.values()) {
5832
6175
  pathGenerator.init();
@@ -5842,6 +6185,7 @@
5842
6185
  exports.loadSnowPreset = loadSnowPreset;
5843
6186
  exports.tsParticles = tsParticles;
5844
6187
 
5845
- }));
6188
+ })(g.__tsParticlesInternals.presets.snow = g.__tsParticlesInternals.presets.snow || {});
6189
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
6190
+
5846
6191
  Object.assign(globalThis.window || globalThis, { loadSnowPreset: (globalThis.__tsParticlesInternals.presets.snow || {}).loadSnowPreset });
5847
- delete (globalThis.window || globalThis).tsparticlesInternalExports;