@tsparticles/preset-ambient 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.ambient = global.__tsParticlesInternals.presets.ambient || {})));
7
- })(this, (function (exports) { 'use strict';
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
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;
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));
1933
2088
  }
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()})`;
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);
2100
+ }
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,108 +2832,109 @@
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);
2844
+ }
2845
+ else {
2846
+ this.#applyOutModeNormal(particle, container, direction);
2771
2847
  }
2772
2848
  }
2773
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;
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;
2937
+ }
2774
2938
  }
2775
2939
 
2776
2940
  const checkOutMode = (outModes, outMode) => {
@@ -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),
@@ -3232,21 +3404,28 @@
3232
3404
  });
3233
3405
  }
3234
3406
  clear() {
3407
+ const visited = new Set();
3235
3408
  for (const plugin of this.#canvasClearPlugins) {
3409
+ visited.add(plugin);
3236
3410
  if (plugin.canvasClear?.() ?? false) {
3237
- return;
3411
+ return plugin;
3238
3412
  }
3239
3413
  }
3240
3414
  for (const layer of Object.values(DrawLayer)) {
3241
3415
  if (typeof layer === "number") {
3242
3416
  for (const plugin of this.#getLayerPlugins(layer)) {
3417
+ if (visited.has(plugin)) {
3418
+ continue;
3419
+ }
3420
+ visited.add(plugin);
3243
3421
  if (plugin.canvasClear?.() ?? false) {
3244
- return;
3422
+ return plugin;
3245
3423
  }
3246
3424
  }
3247
3425
  }
3248
3426
  }
3249
3427
  this.canvasClear();
3428
+ return undefined;
3250
3429
  }
3251
3430
  destroy() {
3252
3431
  this.stop();
@@ -3287,7 +3466,11 @@
3287
3466
  if (!fColor && !sColor) {
3288
3467
  return;
3289
3468
  }
3290
- 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;
3469
+ 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
3470
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3471
+ : undefined, stroke = sColor
3472
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3473
+ : fill;
3291
3474
  transform.a = transform.b = transform.c = transform.d = undefined;
3292
3475
  colorStyles.fill = fill;
3293
3476
  colorStyles.stroke = stroke;
@@ -3320,8 +3503,7 @@
3320
3503
  });
3321
3504
  }
3322
3505
  drawParticles(delta) {
3323
- const { particles, actualOptions } = this.#container;
3324
- this.clear();
3506
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
3325
3507
  particles.update(delta);
3326
3508
  this.draw(ctx => {
3327
3509
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -3343,7 +3525,9 @@
3343
3525
  }
3344
3526
  }
3345
3527
  for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3346
- plugin.canvasPaint?.();
3528
+ if (plugin !== clearedPlugin) {
3529
+ plugin.canvasPaint?.();
3530
+ }
3347
3531
  }
3348
3532
  for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3349
3533
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -3375,35 +3559,7 @@
3375
3559
  this.#layers[layer] = [];
3376
3560
  }
3377
3561
  }
3378
- for (const plugin of this.#container.plugins) {
3379
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3380
- this.#colorPlugins.push(plugin);
3381
- }
3382
- if (plugin.drawParticle) {
3383
- this.#drawParticlePlugins.push(plugin);
3384
- }
3385
- if (plugin.drawParticleSetup) {
3386
- this.#drawParticlesSetupPlugins.push(plugin);
3387
- }
3388
- if (plugin.drawParticleCleanup) {
3389
- this.#drawParticlesCleanupPlugins.push(plugin);
3390
- }
3391
- if (plugin.canvasClear) {
3392
- this.#canvasClearPlugins.push(plugin);
3393
- }
3394
- if (plugin.canvasPaint) {
3395
- this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3396
- }
3397
- if (plugin.drawSettingsSetup) {
3398
- this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3399
- }
3400
- if (plugin.draw) {
3401
- this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3402
- }
3403
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3404
- this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3405
- }
3406
- }
3562
+ this.#initPluginsArray();
3407
3563
  }
3408
3564
  initUpdaters() {
3409
3565
  this.#preDrawUpdaters = [];
@@ -3612,6 +3768,45 @@
3612
3768
  this.#reusablePluginColors[sColorIndex] = sColor;
3613
3769
  return this.#reusablePluginColors;
3614
3770
  }
3771
+ #initLayerPlugin(plugin) {
3772
+ const layerMap = [
3773
+ [DrawLayer.BackgroundMask, !!plugin.canvasPaint],
3774
+ [DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
3775
+ [DrawLayer.PluginContent, !!plugin.draw],
3776
+ [DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
3777
+ ];
3778
+ for (const [layer, active] of layerMap) {
3779
+ if (active) {
3780
+ this.#layers[layer].push(plugin);
3781
+ }
3782
+ }
3783
+ }
3784
+ #initPluginsArray() {
3785
+ for (const plugin of this.#container.plugins) {
3786
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3787
+ this.#colorPlugins.push(plugin);
3788
+ }
3789
+ if (plugin.drawParticle) {
3790
+ this.#drawParticlePlugins.push(plugin);
3791
+ }
3792
+ if (plugin.drawParticleSetup) {
3793
+ this.#drawParticlesSetupPlugins.push(plugin);
3794
+ }
3795
+ if (plugin.drawParticleCleanup) {
3796
+ this.#drawParticlesCleanupPlugins.push(plugin);
3797
+ }
3798
+ if (plugin.canvasClear) {
3799
+ this.#canvasClearPlugins.push(plugin);
3800
+ }
3801
+ this.#initLayerPlugin(plugin);
3802
+ }
3803
+ }
3804
+ #isSupportedElement(element) {
3805
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
3806
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
3807
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
3808
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
3809
+ }
3615
3810
  #resolveBackgroundElement() {
3616
3811
  const background = this.#container.actualOptions.background;
3617
3812
  this.#backgroundElement = null;
@@ -3621,7 +3816,7 @@
3621
3816
  if (typeof background.element === "string") {
3622
3817
  if (typeof document !== "undefined") {
3623
3818
  const node = document.querySelector(background.element);
3624
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
3819
+ if (node && this.#isSupportedElement(node)) {
3625
3820
  this.#backgroundElement = node;
3626
3821
  }
3627
3822
  else if (node) {
@@ -3632,10 +3827,7 @@
3632
3827
  }
3633
3828
  }
3634
3829
  }
3635
- else if (background.element instanceof HTMLCanvasElement ||
3636
- background.element instanceof OffscreenCanvas ||
3637
- background.element instanceof HTMLVideoElement ||
3638
- background.element instanceof HTMLImageElement) {
3830
+ else if (this.#isSupportedElement(background.element)) {
3639
3831
  this.#backgroundElement = background.element;
3640
3832
  }
3641
3833
  }
@@ -3653,7 +3845,7 @@
3653
3845
  return transferredCanvas;
3654
3846
  }
3655
3847
  if (typeof canvas.transferControlToOffscreen !== "function") {
3656
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
3848
+ throw new TypeError(getErrorMessage(ErrorCodes$1.offscreenCanvasUnsupported));
3657
3849
  }
3658
3850
  try {
3659
3851
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -3661,10 +3853,16 @@
3661
3853
  return offscreenCanvas;
3662
3854
  }
3663
3855
  catch {
3664
- throw new TypeError("OffscreenCanvas transfer failed");
3856
+ throw new TypeError(getErrorMessage(ErrorCodes$1.offscreenCanvasTransferFailed));
3665
3857
  }
3666
3858
  }, isHtmlCanvasElement = (canvas) => {
3667
3859
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
3860
+ }, getEffectiveColorSpace = (context) => {
3861
+ if (!context) {
3862
+ return undefined;
3863
+ }
3864
+ const colorInfo = context;
3865
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
3668
3866
  };
3669
3867
  function setStyle(canvas, style, important = false) {
3670
3868
  if (!style) {
@@ -3703,6 +3901,7 @@
3703
3901
  zoom = defaultZoom;
3704
3902
  #container;
3705
3903
  #generated;
3904
+ #hdrMediaListeners;
3706
3905
  #mutationObserver;
3707
3906
  #originalStyle;
3708
3907
  #pluginManager;
@@ -3767,7 +3966,6 @@
3767
3966
  });
3768
3967
  this.resize();
3769
3968
  this.#initStyle();
3770
- this.initBackground();
3771
3969
  this.#safeMutationObserver(obs => {
3772
3970
  const element = this.domElement;
3773
3971
  if (!element || !(element instanceof Node)) {
@@ -3777,6 +3975,8 @@
3777
3975
  });
3778
3976
  this.initPlugins();
3779
3977
  this.#initContext();
3978
+ this.initBackground();
3979
+ this.#initHdrListeners();
3780
3980
  this.render.init();
3781
3981
  }
3782
3982
  initBackground() {
@@ -3786,7 +3986,8 @@
3786
3986
  }
3787
3987
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
3788
3988
  if (color) {
3789
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
3989
+ const hdrOptions = container.actualOptions.hdr;
3990
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard));
3790
3991
  }
3791
3992
  else {
3792
3993
  elementStyle.backgroundColor = "";
@@ -3883,6 +4084,7 @@
3883
4084
  obs.disconnect();
3884
4085
  });
3885
4086
  this.#mutationObserver = undefined;
4087
+ this.#removeHdrListeners();
3886
4088
  this.render.stop();
3887
4089
  }
3888
4090
  async windowResize() {
@@ -3902,9 +4104,16 @@
3902
4104
  }
3903
4105
  }
3904
4106
  #initContext() {
3905
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4107
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
3906
4108
  safeMatchMedia("(color-gamut: p3)")?.matches &&
3907
4109
  safeMatchMedia("(dynamic-range: high)")?.matches;
4110
+ container.hdrMode = toEnumValue(HdrMode, container.actualOptions.hdr.mode, HdrMode.standard);
4111
+ container.peakNits = container.actualOptions.hdr.peakNits;
4112
+ const renderCanvas = this.renderCanvas;
4113
+ if (!renderCanvas) {
4114
+ container.hdr = canSupportHdr ?? false;
4115
+ return;
4116
+ }
3908
4117
  this.render.setContextSettings({
3909
4118
  alpha: true,
3910
4119
  desynchronized: true,
@@ -3913,11 +4122,51 @@
3913
4122
  ? { colorSpace: "display-p3", colorType: "float16" }
3914
4123
  : { colorSpace: "srgb" }),
3915
4124
  });
3916
- const renderCanvas = this.renderCanvas;
3917
- if (!renderCanvas) {
3918
- return;
4125
+ let context;
4126
+ try {
4127
+ context = renderCanvas.getContext("2d", this.render.settings);
4128
+ }
4129
+ catch {
4130
+ context = null;
4131
+ }
4132
+ if (canSupportHdr && !context) {
4133
+ const sdrSettings = {
4134
+ alpha: true,
4135
+ desynchronized: true,
4136
+ willReadFrequently: false,
4137
+ colorSpace: "srgb",
4138
+ };
4139
+ this.render.setContextSettings(sdrSettings);
4140
+ try {
4141
+ context = renderCanvas.getContext("2d", sdrSettings);
4142
+ }
4143
+ catch {
4144
+ context = null;
4145
+ }
4146
+ }
4147
+ this.render.setContext(context);
4148
+ if (context) {
4149
+ const effectiveColorSpace = getEffectiveColorSpace(context);
4150
+ if (effectiveColorSpace !== undefined) {
4151
+ container.hdr = effectiveColorSpace === "display-p3";
4152
+ }
3919
4153
  }
3920
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4154
+ }
4155
+ #initHdrListeners() {
4156
+ this.#removeHdrListeners();
4157
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4158
+ this.#initContext();
4159
+ this.initBackground();
4160
+ }, listeners = [];
4161
+ if (p3Query) {
4162
+ p3Query.addEventListener("change", handleChange);
4163
+ listeners.push({ handler: handleChange, mql: p3Query });
4164
+ }
4165
+ if (hdrQuery) {
4166
+ hdrQuery.addEventListener("change", handleChange);
4167
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4168
+ }
4169
+ this.#hdrMediaListeners = listeners;
3921
4170
  }
3922
4171
  #initStyle() {
3923
4172
  const element = this.domElement, options = this.#container.actualOptions;
@@ -3941,6 +4190,15 @@
3941
4190
  element.style.setProperty(key, value, "important");
3942
4191
  }
3943
4192
  }
4193
+ #removeHdrListeners() {
4194
+ if (!this.#hdrMediaListeners) {
4195
+ return;
4196
+ }
4197
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4198
+ mql.removeEventListener("change", handler);
4199
+ }
4200
+ this.#hdrMediaListeners = undefined;
4201
+ }
3944
4202
  #repairStyle() {
3945
4203
  const element = this.domElement;
3946
4204
  if (!element) {
@@ -4030,8 +4288,7 @@
4030
4288
  this.#resizeTimeout = undefined;
4031
4289
  }
4032
4290
  const handleResize = async () => {
4033
- const canvas = this.#container.canvas;
4034
- await canvas.windowResize();
4291
+ await this.#container.canvas.windowResize();
4035
4292
  };
4036
4293
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
4037
4294
  }
@@ -4059,8 +4316,8 @@
4059
4316
  }
4060
4317
  else if (!this.#resizeObserver && add && canvasEl) {
4061
4318
  this.#resizeObserver = new ResizeObserver((entries) => {
4062
- const entry = entries.find(e => e.target === canvasEl);
4063
- if (!entry) {
4319
+ const res = entries.some(e => e.target === canvasEl);
4320
+ if (!res) {
4064
4321
  return;
4065
4322
  }
4066
4323
  this.#handleWindowResize();
@@ -4324,10 +4581,10 @@
4324
4581
  return this.#modifiers.find(m => m.id === id);
4325
4582
  }
4326
4583
  getOpacity() {
4327
- 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;
4328
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4584
+ 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;
4585
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
4329
4586
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4330
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4587
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
4331
4588
  return this.#cachedOpacityData;
4332
4589
  }
4333
4590
  getPosition() {
@@ -4574,7 +4831,7 @@
4574
4831
  #initPosition(position) {
4575
4832
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4576
4833
  if (!initialPosition) {
4577
- throw new Error("a valid position cannot be found for particle");
4834
+ throw new Error(getErrorMessage(ErrorCodes$1.particlePositionNotFound));
4578
4835
  }
4579
4836
  this.position = initialPosition;
4580
4837
  this.initialPosition = this.position.copy();
@@ -4623,6 +4880,12 @@
4623
4880
  this.#circlePoolIdx = 0;
4624
4881
  this.#rectanglePoolIdx = 0;
4625
4882
  }
4883
+ get cellSize() {
4884
+ return this.#cellSize;
4885
+ }
4886
+ set cellSize(value) {
4887
+ this.#pendingCellSize = value;
4888
+ }
4626
4889
  clear() {
4627
4890
  this.#cells.clear();
4628
4891
  const pendingCellSize = this.#pendingCellSize;
@@ -4646,18 +4909,7 @@
4646
4909
  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);
4647
4910
  for (let cx = minCellX; cx <= maxCellX; cx++) {
4648
4911
  for (let cy = minCellY; cy <= maxCellY; cy++) {
4649
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
4650
- if (!cellParticles) {
4651
- continue;
4652
- }
4653
- for (const p of cellParticles) {
4654
- if (check && !check(p)) {
4655
- continue;
4656
- }
4657
- if (range.contains(p.getPosition())) {
4658
- out.push(p);
4659
- }
4660
- }
4912
+ this.#queryCell(cx, cy, range, check, out);
4661
4913
  }
4662
4914
  }
4663
4915
  return out;
@@ -4672,14 +4924,23 @@
4672
4924
  this.#releaseShapes();
4673
4925
  return result;
4674
4926
  }
4675
- setCellSize(cellSize) {
4676
- this.#pendingCellSize = cellSize;
4677
- }
4678
4927
  #acquireCircle(x, y, r) {
4679
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
4928
+ const idx = this.#circlePoolIdx++;
4929
+ let circle = this.#circlePool[idx];
4930
+ if (!circle) {
4931
+ circle = new Circle(x, y, r);
4932
+ this.#circlePool[idx] = circle;
4933
+ }
4934
+ return circle.reset(x, y, r);
4680
4935
  }
4681
4936
  #acquireRectangle(x, y, w, h) {
4682
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
4937
+ const idx = this.#rectanglePoolIdx++;
4938
+ let rectangle = this.#rectanglePool[idx];
4939
+ if (!rectangle) {
4940
+ rectangle = new Rectangle(x, y, w, h);
4941
+ this.#rectanglePool[idx] = rectangle;
4942
+ }
4943
+ return rectangle.reset(x, y, w, h);
4683
4944
  }
4684
4945
  #cellKeyFromCoords(x, y) {
4685
4946
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -4706,6 +4967,20 @@
4706
4967
  }
4707
4968
  return null;
4708
4969
  }
4970
+ #queryCell(cx, cy, range, check, out) {
4971
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
4972
+ if (!cellParticles) {
4973
+ return;
4974
+ }
4975
+ for (const p of cellParticles) {
4976
+ if (check && !check(p)) {
4977
+ continue;
4978
+ }
4979
+ if (range.contains(p.getPosition())) {
4980
+ out.push(p);
4981
+ }
4982
+ }
4983
+ }
4709
4984
  #releaseShapes() {
4710
4985
  this.#circlePoolIdx = 0;
4711
4986
  this.#rectanglePoolIdx = 0;
@@ -4714,9 +4989,9 @@
4714
4989
 
4715
4990
  class ParticlesManager {
4716
4991
  checkParticlePositionPlugins;
4717
- grid;
4718
4992
  #array;
4719
4993
  #container;
4994
+ #grid;
4720
4995
  #groupLimits;
4721
4996
  #limit;
4722
4997
  #nextId;
@@ -4740,7 +5015,7 @@
4740
5015
  this.#groupLimits = new Map();
4741
5016
  this.#particleBuckets = new Map();
4742
5017
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
4743
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5018
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
4744
5019
  this.checkParticlePositionPlugins = [];
4745
5020
  this.#particleResetPlugins = [];
4746
5021
  this.#particleUpdatePlugins = [];
@@ -4751,23 +5026,12 @@
4751
5026
  get count() {
4752
5027
  return this.#array.length;
4753
5028
  }
5029
+ get grid() {
5030
+ return this.#grid;
5031
+ }
4754
5032
  addParticle(position, overrideOptions, group, initializer) {
4755
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
4756
- if (limit > minLimit) {
4757
- switch (limitMode) {
4758
- case LimitMode.delete: {
4759
- const countToRemove = currentCount + countOffset - limit;
4760
- if (countToRemove > minCount) {
4761
- this.removeQuantity(countToRemove);
4762
- }
4763
- break;
4764
- }
4765
- case LimitMode.wait:
4766
- if (currentCount >= limit) {
4767
- return;
4768
- }
4769
- break;
4770
- }
5033
+ if (this.#checkAndApplyLimits(group, this.count)) {
5034
+ return;
4771
5035
  }
4772
5036
  try {
4773
5037
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -4831,7 +5095,7 @@
4831
5095
  return this.#array[index];
4832
5096
  }
4833
5097
  async init() {
4834
- const container = this.#container, options = container.actualOptions;
5098
+ const container = this.#container;
4835
5099
  this.checkParticlePositionPlugins = [];
4836
5100
  this.#updatePlugins = [];
4837
5101
  this.#particleUpdatePlugins = [];
@@ -4840,59 +5104,16 @@
4840
5104
  this.#postParticleUpdatePlugins = [];
4841
5105
  this.#particleBuckets.clear();
4842
5106
  this.#resetBuckets(container.zLayers);
4843
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
4844
- for (const plugin of container.plugins) {
4845
- if (plugin.redrawInit) {
4846
- await plugin.redrawInit();
4847
- }
4848
- if (plugin.checkParticlePosition) {
4849
- this.checkParticlePositionPlugins.push(plugin);
4850
- }
4851
- if (plugin.update) {
4852
- this.#updatePlugins.push(plugin);
4853
- }
4854
- if (plugin.particleUpdate) {
4855
- this.#particleUpdatePlugins.push(plugin);
4856
- }
4857
- if (plugin.postUpdate) {
4858
- this.#postUpdatePlugins.push(plugin);
4859
- }
4860
- if (plugin.particleReset) {
4861
- this.#particleResetPlugins.push(plugin);
4862
- }
4863
- if (plugin.postParticleUpdate) {
4864
- this.#postParticleUpdatePlugins.push(plugin);
4865
- }
4866
- }
4867
- await this.#container.initDrawersAndUpdaters();
4868
- for (const drawer of this.#container.effectDrawers.values()) {
4869
- await drawer.init?.(container);
4870
- }
4871
- for (const drawer of this.#container.shapeDrawers.values()) {
4872
- await drawer.init?.(container);
4873
- }
4874
- let handled = false;
4875
- for (const plugin of container.plugins) {
4876
- handled = plugin.particlesInitialization?.() ?? handled;
4877
- if (handled) {
4878
- break;
4879
- }
4880
- }
4881
- if (!handled) {
4882
- const particlesOptions = options.particles, groups = particlesOptions.groups;
4883
- for (const group in groups) {
4884
- const groupOptions = groups[group];
4885
- if (!groupOptions) {
4886
- continue;
4887
- }
4888
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
4889
- this.addParticle(undefined, groupOptions, group);
4890
- }
4891
- }
4892
- for (let i = this.count; i < particlesOptions.number.value; i++) {
4893
- this.addParticle();
5107
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5108
+ this.#applyLimits(container.actualOptions.particles);
5109
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5110
+ for (const group in groups) {
5111
+ const groupData = groups[group];
5112
+ if (groupData) {
5113
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
4894
5114
  }
4895
5115
  }
5116
+ await this.#initPlugins();
4896
5117
  }
4897
5118
  push(nb, position, overrideOptions, group) {
4898
5119
  for (let i = 0; i < nb; i++) {
@@ -4907,13 +5128,13 @@
4907
5128
  remove(particle, group, override) {
4908
5129
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
4909
5130
  }
4910
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
5131
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
4911
5132
  if (index < minIndex || index > this.count) {
4912
5133
  return;
4913
5134
  }
4914
5135
  let deleted = 0;
4915
5136
  for (let i = index; deleted < quantity && i < this.count; i++) {
4916
- if (this.#removeParticle(i, group, override)) {
5137
+ if (this.#removeParticle(i, group, override, matchGroup)) {
4917
5138
  i--;
4918
5139
  deleted++;
4919
5140
  }
@@ -4944,7 +5165,7 @@
4944
5165
  this.#resizeFactor = factor;
4945
5166
  }
4946
5167
  update(delta) {
4947
- this.grid.clear();
5168
+ this.#grid.clear();
4948
5169
  for (const plugin of this.#updatePlugins) {
4949
5170
  plugin.update?.(delta);
4950
5171
  }
@@ -4955,7 +5176,7 @@
4955
5176
  this.#updateParticlesPhase2(delta, particlesToDelete);
4956
5177
  if (particlesToDelete.size) {
4957
5178
  for (const particle of particlesToDelete) {
4958
- this.remove(particle);
5179
+ this.remove(particle, particle.group);
4959
5180
  }
4960
5181
  }
4961
5182
  this.#resizeFactor = undefined;
@@ -4966,12 +5187,7 @@
4966
5187
  #applyDensity(options, pluginsCount, group, groupOptions) {
4967
5188
  const numberOptions = options.number;
4968
5189
  if (!numberOptions.density.enable) {
4969
- if (group === undefined) {
4970
- this.#limit = numberOptions.limit.value;
4971
- }
4972
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
4973
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
4974
- }
5190
+ this.#applyLimits(options, group, groupOptions);
4975
5191
  return;
4976
5192
  }
4977
5193
  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);
@@ -4979,7 +5195,10 @@
4979
5195
  this.#limit = numberOptions.limit.value * densityFactor;
4980
5196
  }
4981
5197
  else {
4982
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
5198
+ this.#groupLimits.set(group, {
5199
+ limit: numberOptions.limit.value * densityFactor,
5200
+ mode: toEnumValue(LimitMode, numberOptions.limit.mode, LimitMode.delete),
5201
+ });
4983
5202
  }
4984
5203
  if (particlesCount < particlesNumber) {
4985
5204
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -4988,6 +5207,55 @@
4988
5207
  this.removeQuantity(particlesCount - particlesNumber, group);
4989
5208
  }
4990
5209
  }
5210
+ #applyLimits(options, group, groupOptions) {
5211
+ if (group === undefined) {
5212
+ this.#limit = options.number.limit.value;
5213
+ const groups = this.#container.actualOptions.particles.groups;
5214
+ for (const existingGroup of this.#groupLimits.keys()) {
5215
+ if (!(existingGroup in groups)) {
5216
+ this.#groupLimits.delete(existingGroup);
5217
+ }
5218
+ }
5219
+ }
5220
+ else {
5221
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
5222
+ if (limitValue > minLimit) {
5223
+ this.#groupLimits.set(group, {
5224
+ limit: limitValue,
5225
+ mode: toEnumValue(LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, LimitMode.delete),
5226
+ });
5227
+ }
5228
+ else {
5229
+ this.#groupLimits.delete(group);
5230
+ }
5231
+ }
5232
+ }
5233
+ #checkAndApplyLimits(group, currentCount) {
5234
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
5235
+ if (globalLimit > minLimit && globalMode === LimitMode.wait && currentCount >= globalLimit) {
5236
+ return true;
5237
+ }
5238
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
5239
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.wait) {
5240
+ const groupCount = this.filter(t => t.group === group).length;
5241
+ if (groupCount >= groupLimitEntry.limit) {
5242
+ return true;
5243
+ }
5244
+ }
5245
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.delete) {
5246
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
5247
+ if (groupCountToRemove > minCount) {
5248
+ this.removeQuantity(groupCountToRemove, group);
5249
+ }
5250
+ }
5251
+ if (globalLimit > minLimit && globalMode === LimitMode.delete) {
5252
+ const globalCountToRemove = this.count + countOffset - globalLimit;
5253
+ if (globalCountToRemove > minCount) {
5254
+ this.#removeAny(globalCountToRemove);
5255
+ }
5256
+ }
5257
+ return false;
5258
+ }
4991
5259
  #createBuckets(zLayers) {
4992
5260
  const bucketCount = Math.max(Math.floor(zLayers), one);
4993
5261
  return Array.from({ length: bucketCount }, () => []);
@@ -5010,6 +5278,70 @@
5010
5278
  }
5011
5279
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
5012
5280
  }
5281
+ async #initDrawersAndUpdaters() {
5282
+ const container = this.#container;
5283
+ await container.initDrawersAndUpdaters();
5284
+ for (const drawer of container.effectDrawers.values()) {
5285
+ await drawer.init?.(container);
5286
+ }
5287
+ for (const drawer of container.shapeDrawers.values()) {
5288
+ await drawer.init?.(container);
5289
+ }
5290
+ }
5291
+ async #initPlugins() {
5292
+ await this.#initPluginsArrays();
5293
+ await this.#initDrawersAndUpdaters();
5294
+ let handled = false;
5295
+ const container = this.#container;
5296
+ for (const plugin of container.plugins) {
5297
+ handled = plugin.particlesInitialization?.() ?? handled;
5298
+ if (handled) {
5299
+ break;
5300
+ }
5301
+ }
5302
+ if (handled) {
5303
+ return;
5304
+ }
5305
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5306
+ for (const group in groups) {
5307
+ const groupOptions = groups[group];
5308
+ if (!groupOptions) {
5309
+ continue;
5310
+ }
5311
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5312
+ this.addParticle(undefined, groupOptions, group);
5313
+ }
5314
+ }
5315
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
5316
+ this.addParticle();
5317
+ }
5318
+ }
5319
+ async #initPluginsArrays() {
5320
+ const container = this.#container;
5321
+ for (const plugin of container.plugins) {
5322
+ if (plugin.redrawInit) {
5323
+ await plugin.redrawInit();
5324
+ }
5325
+ if (plugin.checkParticlePosition) {
5326
+ this.checkParticlePositionPlugins.push(plugin);
5327
+ }
5328
+ if (plugin.update) {
5329
+ this.#updatePlugins.push(plugin);
5330
+ }
5331
+ if (plugin.particleUpdate) {
5332
+ this.#particleUpdatePlugins.push(plugin);
5333
+ }
5334
+ if (plugin.postUpdate) {
5335
+ this.#postUpdatePlugins.push(plugin);
5336
+ }
5337
+ if (plugin.particleReset) {
5338
+ this.#particleResetPlugins.push(plugin);
5339
+ }
5340
+ if (plugin.postParticleUpdate) {
5341
+ this.#postParticleUpdatePlugins.push(plugin);
5342
+ }
5343
+ }
5344
+ }
5013
5345
  #insertParticleIntoBucket(particle) {
5014
5346
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
5015
5347
  if (!bucket) {
@@ -5018,12 +5350,15 @@
5018
5350
  bucket.push(particle);
5019
5351
  this.#particleBuckets.set(particle.id, bucketIndex);
5020
5352
  }
5021
- #removeParticle(index, group, override) {
5353
+ #removeAny(quantity) {
5354
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
5355
+ }
5356
+ #removeParticle(index, group, override, matchGroup = true) {
5022
5357
  const particle = this.#array[index];
5023
5358
  if (!particle) {
5024
5359
  return false;
5025
5360
  }
5026
- if (particle.group !== group) {
5361
+ if (matchGroup && particle.group !== group) {
5027
5362
  return false;
5028
5363
  }
5029
5364
  this.#array.splice(index, deleteCount);
@@ -5110,7 +5445,7 @@
5110
5445
  particlesToDelete.add(particle);
5111
5446
  continue;
5112
5447
  }
5113
- this.grid.insert(particle);
5448
+ this.#grid.insert(particle);
5114
5449
  }
5115
5450
  return particlesToDelete;
5116
5451
  }
@@ -5182,6 +5517,7 @@
5182
5517
  effectDrawers;
5183
5518
  fpsLimit;
5184
5519
  hdr;
5520
+ hdrMode;
5185
5521
  id;
5186
5522
  pageHidden;
5187
5523
  particleCreatedPlugins;
@@ -5189,6 +5525,7 @@
5189
5525
  particlePositionPlugins;
5190
5526
  particleUpdaters;
5191
5527
  particles;
5528
+ peakNits;
5192
5529
  plugins;
5193
5530
  retina;
5194
5531
  shapeDrawers;
@@ -5219,6 +5556,8 @@
5219
5556
  this.id = Symbol(id);
5220
5557
  this.fpsLimit = 120;
5221
5558
  this.hdr = false;
5559
+ this.hdrMode = HdrMode.standard;
5560
+ this.peakNits = 400;
5222
5561
  this.#smooth = false;
5223
5562
  this.#delay = 0;
5224
5563
  this.#duration = 0;
@@ -5282,7 +5621,6 @@
5282
5621
  this.shapeDrawers = new Map();
5283
5622
  this.particleUpdaters = [];
5284
5623
  this.plugins.length = 0;
5285
- this.#pluginManager.clearPlugins(this);
5286
5624
  this.destroyed = true;
5287
5625
  this.#onDestroy(remove);
5288
5626
  this.dispatchEvent(EventType.containerDestroyed);
@@ -5335,31 +5673,15 @@
5335
5673
  await this.initDrawersAndUpdaters();
5336
5674
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
5337
5675
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
5338
- this.plugins.length = 0;
5339
- this.particleDestroyedPlugins.length = 0;
5340
- this.particleCreatedPlugins.length = 0;
5341
- this.particlePositionPlugins.length = 0;
5342
- for (const [plugin, containerPlugin] of allContainerPlugins) {
5343
- if (plugin.needsPlugin(this.actualOptions)) {
5344
- this.plugins.push(containerPlugin);
5345
- if (containerPlugin.particleCreated) {
5346
- this.particleCreatedPlugins.push(containerPlugin);
5347
- }
5348
- if (containerPlugin.particleDestroyed) {
5349
- this.particleDestroyedPlugins.push(containerPlugin);
5350
- }
5351
- if (containerPlugin.particlePosition) {
5352
- this.particlePositionPlugins.push(containerPlugin);
5353
- }
5354
- }
5355
- }
5676
+ this.#initPlugins(allContainerPlugins);
5356
5677
  this.retina.init();
5357
5678
  this.canvas.init();
5358
5679
  this.updateActualOptions();
5359
5680
  this.canvas.initBackground();
5360
5681
  this.canvas.resize();
5361
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5362
- this.hdr = hdr;
5682
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
5683
+ this.hdrMode = toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard);
5684
+ this.peakNits = hdrOptions.peakNits;
5363
5685
  this.zLayers = zLayers;
5364
5686
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5365
5687
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -5379,9 +5701,9 @@
5379
5701
  }
5380
5702
  async initDrawersAndUpdaters() {
5381
5703
  const pluginManager = this.#pluginManager;
5382
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
5383
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
5384
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
5704
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
5705
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
5706
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
5385
5707
  }
5386
5708
  pause() {
5387
5709
  if (!guardCheck(this)) {
@@ -5492,6 +5814,27 @@
5492
5814
  }
5493
5815
  return refresh;
5494
5816
  }
5817
+ #initPlugins(allContainerPlugins) {
5818
+ this.plugins.length = 0;
5819
+ this.particleDestroyedPlugins.length = 0;
5820
+ this.particleCreatedPlugins.length = 0;
5821
+ this.particlePositionPlugins.length = 0;
5822
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
5823
+ if (!plugin.needsPlugin(this.actualOptions)) {
5824
+ continue;
5825
+ }
5826
+ this.plugins.push(containerPlugin);
5827
+ if (containerPlugin.particleCreated) {
5828
+ this.particleCreatedPlugins.push(containerPlugin);
5829
+ }
5830
+ if (containerPlugin.particleDestroyed) {
5831
+ this.particleDestroyedPlugins.push(containerPlugin);
5832
+ }
5833
+ if (containerPlugin.particlePosition) {
5834
+ this.particlePositionPlugins.push(containerPlugin);
5835
+ }
5836
+ }
5837
+ }
5495
5838
  #nextFrame(timestamp) {
5496
5839
  try {
5497
5840
  if (!this.#smooth &&
@@ -5768,11 +6111,11 @@
5768
6111
  }
5769
6112
  }
5770
6113
  async #init() {
5771
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
5772
- if (!availablePathGenerators) {
6114
+ const pluginManager = this.#pluginManager;
6115
+ if (!pluginManager.initializers.pathGenerators) {
5773
6116
  return;
5774
6117
  }
5775
- this.availablePathGenerators = availablePathGenerators;
6118
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
5776
6119
  this.pathGenerators = new Map();
5777
6120
  for (const pathGenerator of this.pathGenerators.values()) {
5778
6121
  pathGenerator.init();
@@ -5788,6 +6131,7 @@
5788
6131
  exports.loadAmbientPreset = loadAmbientPreset;
5789
6132
  exports.tsParticles = tsParticles;
5790
6133
 
5791
- }));
6134
+ })(g.__tsParticlesInternals.presets.ambient = g.__tsParticlesInternals.presets.ambient || {});
6135
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
6136
+
5792
6137
  Object.assign(globalThis.window || globalThis, { loadAmbientPreset: (globalThis.__tsParticlesInternals.presets.ambient || {}).loadAmbientPreset });
5793
- delete (globalThis.window || globalThis).tsparticlesInternalExports;