@tsparticles/preset-big-circles 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.bigCircles = global.__tsParticlesInternals.presets.bigCircles || {})));
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),
@@ -3215,21 +3387,28 @@
3215
3387
  });
3216
3388
  }
3217
3389
  clear() {
3390
+ const visited = new Set();
3218
3391
  for (const plugin of this.#canvasClearPlugins) {
3392
+ visited.add(plugin);
3219
3393
  if (plugin.canvasClear?.() ?? false) {
3220
- return;
3394
+ return plugin;
3221
3395
  }
3222
3396
  }
3223
3397
  for (const layer of Object.values(DrawLayer)) {
3224
3398
  if (typeof layer === "number") {
3225
3399
  for (const plugin of this.#getLayerPlugins(layer)) {
3400
+ if (visited.has(plugin)) {
3401
+ continue;
3402
+ }
3403
+ visited.add(plugin);
3226
3404
  if (plugin.canvasClear?.() ?? false) {
3227
- return;
3405
+ return plugin;
3228
3406
  }
3229
3407
  }
3230
3408
  }
3231
3409
  }
3232
3410
  this.canvasClear();
3411
+ return undefined;
3233
3412
  }
3234
3413
  destroy() {
3235
3414
  this.stop();
@@ -3270,7 +3449,11 @@
3270
3449
  if (!fColor && !sColor) {
3271
3450
  return;
3272
3451
  }
3273
- 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;
3452
+ 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
3453
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3454
+ : undefined, stroke = sColor
3455
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3456
+ : fill;
3274
3457
  transform.a = transform.b = transform.c = transform.d = undefined;
3275
3458
  colorStyles.fill = fill;
3276
3459
  colorStyles.stroke = stroke;
@@ -3303,8 +3486,7 @@
3303
3486
  });
3304
3487
  }
3305
3488
  drawParticles(delta) {
3306
- const { particles, actualOptions } = this.#container;
3307
- this.clear();
3489
+ const { particles, actualOptions } = this.#container, clearedPlugin = this.clear();
3308
3490
  particles.update(delta);
3309
3491
  this.draw(ctx => {
3310
3492
  const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
@@ -3326,7 +3508,9 @@
3326
3508
  }
3327
3509
  }
3328
3510
  for (const plugin of this.#getLayerPlugins(DrawLayer.BackgroundMask)) {
3329
- plugin.canvasPaint?.();
3511
+ if (plugin !== clearedPlugin) {
3512
+ plugin.canvasPaint?.();
3513
+ }
3330
3514
  }
3331
3515
  for (const plugin of this.#getLayerPlugins(DrawLayer.CanvasSetup)) {
3332
3516
  plugin.drawSettingsSetup?.(ctx, delta);
@@ -3358,35 +3542,7 @@
3358
3542
  this.#layers[layer] = [];
3359
3543
  }
3360
3544
  }
3361
- for (const plugin of this.#container.plugins) {
3362
- if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3363
- this.#colorPlugins.push(plugin);
3364
- }
3365
- if (plugin.drawParticle) {
3366
- this.#drawParticlePlugins.push(plugin);
3367
- }
3368
- if (plugin.drawParticleSetup) {
3369
- this.#drawParticlesSetupPlugins.push(plugin);
3370
- }
3371
- if (plugin.drawParticleCleanup) {
3372
- this.#drawParticlesCleanupPlugins.push(plugin);
3373
- }
3374
- if (plugin.canvasClear) {
3375
- this.#canvasClearPlugins.push(plugin);
3376
- }
3377
- if (plugin.canvasPaint) {
3378
- this.#getLayerPlugins(DrawLayer.BackgroundMask).push(plugin);
3379
- }
3380
- if (plugin.drawSettingsSetup) {
3381
- this.#getLayerPlugins(DrawLayer.CanvasSetup).push(plugin);
3382
- }
3383
- if (plugin.draw) {
3384
- this.#getLayerPlugins(DrawLayer.PluginContent).push(plugin);
3385
- }
3386
- if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
3387
- this.#getLayerPlugins(DrawLayer.CanvasCleanup).push(plugin);
3388
- }
3389
- }
3545
+ this.#initPluginsArray();
3390
3546
  }
3391
3547
  initUpdaters() {
3392
3548
  this.#preDrawUpdaters = [];
@@ -3595,6 +3751,45 @@
3595
3751
  this.#reusablePluginColors[sColorIndex] = sColor;
3596
3752
  return this.#reusablePluginColors;
3597
3753
  }
3754
+ #initLayerPlugin(plugin) {
3755
+ const layerMap = [
3756
+ [DrawLayer.BackgroundMask, !!plugin.canvasPaint],
3757
+ [DrawLayer.CanvasSetup, !!plugin.drawSettingsSetup],
3758
+ [DrawLayer.PluginContent, !!plugin.draw],
3759
+ [DrawLayer.CanvasCleanup, !!(plugin.clearDraw ?? plugin.drawSettingsCleanup)],
3760
+ ];
3761
+ for (const [layer, active] of layerMap) {
3762
+ if (active) {
3763
+ this.#layers[layer].push(plugin);
3764
+ }
3765
+ }
3766
+ }
3767
+ #initPluginsArray() {
3768
+ for (const plugin of this.#container.plugins) {
3769
+ if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
3770
+ this.#colorPlugins.push(plugin);
3771
+ }
3772
+ if (plugin.drawParticle) {
3773
+ this.#drawParticlePlugins.push(plugin);
3774
+ }
3775
+ if (plugin.drawParticleSetup) {
3776
+ this.#drawParticlesSetupPlugins.push(plugin);
3777
+ }
3778
+ if (plugin.drawParticleCleanup) {
3779
+ this.#drawParticlesCleanupPlugins.push(plugin);
3780
+ }
3781
+ if (plugin.canvasClear) {
3782
+ this.#canvasClearPlugins.push(plugin);
3783
+ }
3784
+ this.#initLayerPlugin(plugin);
3785
+ }
3786
+ }
3787
+ #isSupportedElement(element) {
3788
+ return ((typeof HTMLCanvasElement !== "undefined" && element instanceof HTMLCanvasElement) ||
3789
+ (typeof OffscreenCanvas !== "undefined" && element instanceof OffscreenCanvas) ||
3790
+ (typeof HTMLVideoElement !== "undefined" && element instanceof HTMLVideoElement) ||
3791
+ (typeof HTMLImageElement !== "undefined" && element instanceof HTMLImageElement));
3792
+ }
3598
3793
  #resolveBackgroundElement() {
3599
3794
  const background = this.#container.actualOptions.background;
3600
3795
  this.#backgroundElement = null;
@@ -3604,7 +3799,7 @@
3604
3799
  if (typeof background.element === "string") {
3605
3800
  if (typeof document !== "undefined") {
3606
3801
  const node = document.querySelector(background.element);
3607
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
3802
+ if (node && this.#isSupportedElement(node)) {
3608
3803
  this.#backgroundElement = node;
3609
3804
  }
3610
3805
  else if (node) {
@@ -3615,10 +3810,7 @@
3615
3810
  }
3616
3811
  }
3617
3812
  }
3618
- else if (background.element instanceof HTMLCanvasElement ||
3619
- background.element instanceof OffscreenCanvas ||
3620
- background.element instanceof HTMLVideoElement ||
3621
- background.element instanceof HTMLImageElement) {
3813
+ else if (this.#isSupportedElement(background.element)) {
3622
3814
  this.#backgroundElement = background.element;
3623
3815
  }
3624
3816
  }
@@ -3636,7 +3828,7 @@
3636
3828
  return transferredCanvas;
3637
3829
  }
3638
3830
  if (typeof canvas.transferControlToOffscreen !== "function") {
3639
- throw new TypeError("OffscreenCanvas is required but not supported by this browser");
3831
+ throw new TypeError(getErrorMessage(ErrorCodes$1.offscreenCanvasUnsupported));
3640
3832
  }
3641
3833
  try {
3642
3834
  const offscreenCanvas = canvas.transferControlToOffscreen();
@@ -3644,10 +3836,16 @@
3644
3836
  return offscreenCanvas;
3645
3837
  }
3646
3838
  catch {
3647
- throw new TypeError("OffscreenCanvas transfer failed");
3839
+ throw new TypeError(getErrorMessage(ErrorCodes$1.offscreenCanvasTransferFailed));
3648
3840
  }
3649
3841
  }, isHtmlCanvasElement = (canvas) => {
3650
3842
  return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
3843
+ }, getEffectiveColorSpace = (context) => {
3844
+ if (!context) {
3845
+ return undefined;
3846
+ }
3847
+ const colorInfo = context;
3848
+ return colorInfo.getContextAttributes?.().colorSpace ?? undefined;
3651
3849
  };
3652
3850
  function setStyle(canvas, style, important = false) {
3653
3851
  if (!style) {
@@ -3686,6 +3884,7 @@
3686
3884
  zoom = defaultZoom;
3687
3885
  #container;
3688
3886
  #generated;
3887
+ #hdrMediaListeners;
3689
3888
  #mutationObserver;
3690
3889
  #originalStyle;
3691
3890
  #pluginManager;
@@ -3750,7 +3949,6 @@
3750
3949
  });
3751
3950
  this.resize();
3752
3951
  this.#initStyle();
3753
- this.initBackground();
3754
3952
  this.#safeMutationObserver(obs => {
3755
3953
  const element = this.domElement;
3756
3954
  if (!element || !(element instanceof Node)) {
@@ -3760,6 +3958,8 @@
3760
3958
  });
3761
3959
  this.initPlugins();
3762
3960
  this.#initContext();
3961
+ this.initBackground();
3962
+ this.#initHdrListeners();
3763
3963
  this.render.init();
3764
3964
  }
3765
3965
  initBackground() {
@@ -3769,7 +3969,8 @@
3769
3969
  }
3770
3970
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
3771
3971
  if (color) {
3772
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
3972
+ const hdrOptions = container.actualOptions.hdr;
3973
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard));
3773
3974
  }
3774
3975
  else {
3775
3976
  elementStyle.backgroundColor = "";
@@ -3866,6 +4067,7 @@
3866
4067
  obs.disconnect();
3867
4068
  });
3868
4069
  this.#mutationObserver = undefined;
4070
+ this.#removeHdrListeners();
3869
4071
  this.render.stop();
3870
4072
  }
3871
4073
  async windowResize() {
@@ -3885,9 +4087,16 @@
3885
4087
  }
3886
4088
  }
3887
4089
  #initContext() {
3888
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4090
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
3889
4091
  safeMatchMedia("(color-gamut: p3)")?.matches &&
3890
4092
  safeMatchMedia("(dynamic-range: high)")?.matches;
4093
+ container.hdrMode = toEnumValue(HdrMode, container.actualOptions.hdr.mode, HdrMode.standard);
4094
+ container.peakNits = container.actualOptions.hdr.peakNits;
4095
+ const renderCanvas = this.renderCanvas;
4096
+ if (!renderCanvas) {
4097
+ container.hdr = canSupportHdr ?? false;
4098
+ return;
4099
+ }
3891
4100
  this.render.setContextSettings({
3892
4101
  alpha: true,
3893
4102
  desynchronized: true,
@@ -3896,11 +4105,51 @@
3896
4105
  ? { colorSpace: "display-p3", colorType: "float16" }
3897
4106
  : { colorSpace: "srgb" }),
3898
4107
  });
3899
- const renderCanvas = this.renderCanvas;
3900
- if (!renderCanvas) {
3901
- return;
4108
+ let context;
4109
+ try {
4110
+ context = renderCanvas.getContext("2d", this.render.settings);
4111
+ }
4112
+ catch {
4113
+ context = null;
4114
+ }
4115
+ if (canSupportHdr && !context) {
4116
+ const sdrSettings = {
4117
+ alpha: true,
4118
+ desynchronized: true,
4119
+ willReadFrequently: false,
4120
+ colorSpace: "srgb",
4121
+ };
4122
+ this.render.setContextSettings(sdrSettings);
4123
+ try {
4124
+ context = renderCanvas.getContext("2d", sdrSettings);
4125
+ }
4126
+ catch {
4127
+ context = null;
4128
+ }
4129
+ }
4130
+ this.render.setContext(context);
4131
+ if (context) {
4132
+ const effectiveColorSpace = getEffectiveColorSpace(context);
4133
+ if (effectiveColorSpace !== undefined) {
4134
+ container.hdr = effectiveColorSpace === "display-p3";
4135
+ }
3902
4136
  }
3903
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4137
+ }
4138
+ #initHdrListeners() {
4139
+ this.#removeHdrListeners();
4140
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4141
+ this.#initContext();
4142
+ this.initBackground();
4143
+ }, listeners = [];
4144
+ if (p3Query) {
4145
+ p3Query.addEventListener("change", handleChange);
4146
+ listeners.push({ handler: handleChange, mql: p3Query });
4147
+ }
4148
+ if (hdrQuery) {
4149
+ hdrQuery.addEventListener("change", handleChange);
4150
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4151
+ }
4152
+ this.#hdrMediaListeners = listeners;
3904
4153
  }
3905
4154
  #initStyle() {
3906
4155
  const element = this.domElement, options = this.#container.actualOptions;
@@ -3924,6 +4173,15 @@
3924
4173
  element.style.setProperty(key, value, "important");
3925
4174
  }
3926
4175
  }
4176
+ #removeHdrListeners() {
4177
+ if (!this.#hdrMediaListeners) {
4178
+ return;
4179
+ }
4180
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4181
+ mql.removeEventListener("change", handler);
4182
+ }
4183
+ this.#hdrMediaListeners = undefined;
4184
+ }
3927
4185
  #repairStyle() {
3928
4186
  const element = this.domElement;
3929
4187
  if (!element) {
@@ -4013,8 +4271,7 @@
4013
4271
  this.#resizeTimeout = undefined;
4014
4272
  }
4015
4273
  const handleResize = async () => {
4016
- const canvas = this.#container.canvas;
4017
- await canvas.windowResize();
4274
+ await this.#container.canvas.windowResize();
4018
4275
  };
4019
4276
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
4020
4277
  }
@@ -4042,8 +4299,8 @@
4042
4299
  }
4043
4300
  else if (!this.#resizeObserver && add && canvasEl) {
4044
4301
  this.#resizeObserver = new ResizeObserver((entries) => {
4045
- const entry = entries.find(e => e.target === canvasEl);
4046
- if (!entry) {
4302
+ const res = entries.some(e => e.target === canvasEl);
4303
+ if (!res) {
4047
4304
  return;
4048
4305
  }
4049
4306
  this.#handleWindowResize();
@@ -4307,10 +4564,10 @@
4307
4564
  return this.#modifiers.find(m => m.id === id);
4308
4565
  }
4309
4566
  getOpacity() {
4310
- 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;
4311
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4567
+ 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;
4568
+ this.#cachedOpacityData.fillOpacity = this.fillOpacity ?? defaultOpacity$1;
4312
4569
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4313
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4570
+ this.#cachedOpacityData.strokeOpacity = this.strokeOpacity ?? defaultOpacity$1;
4314
4571
  return this.#cachedOpacityData;
4315
4572
  }
4316
4573
  getPosition() {
@@ -4557,7 +4814,7 @@
4557
4814
  #initPosition(position) {
4558
4815
  const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
4559
4816
  if (!initialPosition) {
4560
- throw new Error("a valid position cannot be found for particle");
4817
+ throw new Error(getErrorMessage(ErrorCodes$1.particlePositionNotFound));
4561
4818
  }
4562
4819
  this.position = initialPosition;
4563
4820
  this.initialPosition = this.position.copy();
@@ -4606,6 +4863,12 @@
4606
4863
  this.#circlePoolIdx = 0;
4607
4864
  this.#rectanglePoolIdx = 0;
4608
4865
  }
4866
+ get cellSize() {
4867
+ return this.#cellSize;
4868
+ }
4869
+ set cellSize(value) {
4870
+ this.#pendingCellSize = value;
4871
+ }
4609
4872
  clear() {
4610
4873
  this.#cells.clear();
4611
4874
  const pendingCellSize = this.#pendingCellSize;
@@ -4629,18 +4892,7 @@
4629
4892
  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);
4630
4893
  for (let cx = minCellX; cx <= maxCellX; cx++) {
4631
4894
  for (let cy = minCellY; cy <= maxCellY; cy++) {
4632
- const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
4633
- if (!cellParticles) {
4634
- continue;
4635
- }
4636
- for (const p of cellParticles) {
4637
- if (check && !check(p)) {
4638
- continue;
4639
- }
4640
- if (range.contains(p.getPosition())) {
4641
- out.push(p);
4642
- }
4643
- }
4895
+ this.#queryCell(cx, cy, range, check, out);
4644
4896
  }
4645
4897
  }
4646
4898
  return out;
@@ -4655,14 +4907,23 @@
4655
4907
  this.#releaseShapes();
4656
4908
  return result;
4657
4909
  }
4658
- setCellSize(cellSize) {
4659
- this.#pendingCellSize = cellSize;
4660
- }
4661
4910
  #acquireCircle(x, y, r) {
4662
- return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
4911
+ const idx = this.#circlePoolIdx++;
4912
+ let circle = this.#circlePool[idx];
4913
+ if (!circle) {
4914
+ circle = new Circle(x, y, r);
4915
+ this.#circlePool[idx] = circle;
4916
+ }
4917
+ return circle.reset(x, y, r);
4663
4918
  }
4664
4919
  #acquireRectangle(x, y, w, h) {
4665
- return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
4920
+ const idx = this.#rectanglePoolIdx++;
4921
+ let rectangle = this.#rectanglePool[idx];
4922
+ if (!rectangle) {
4923
+ rectangle = new Rectangle(x, y, w, h);
4924
+ this.#rectanglePool[idx] = rectangle;
4925
+ }
4926
+ return rectangle.reset(x, y, w, h);
4666
4927
  }
4667
4928
  #cellKeyFromCoords(x, y) {
4668
4929
  const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
@@ -4689,6 +4950,20 @@
4689
4950
  }
4690
4951
  return null;
4691
4952
  }
4953
+ #queryCell(cx, cy, range, check, out) {
4954
+ const cellParticles = this.#cells.get(`${cx}_${cy}`);
4955
+ if (!cellParticles) {
4956
+ return;
4957
+ }
4958
+ for (const p of cellParticles) {
4959
+ if (check && !check(p)) {
4960
+ continue;
4961
+ }
4962
+ if (range.contains(p.getPosition())) {
4963
+ out.push(p);
4964
+ }
4965
+ }
4966
+ }
4692
4967
  #releaseShapes() {
4693
4968
  this.#circlePoolIdx = 0;
4694
4969
  this.#rectanglePoolIdx = 0;
@@ -4697,9 +4972,9 @@
4697
4972
 
4698
4973
  class ParticlesManager {
4699
4974
  checkParticlePositionPlugins;
4700
- grid;
4701
4975
  #array;
4702
4976
  #container;
4977
+ #grid;
4703
4978
  #groupLimits;
4704
4979
  #limit;
4705
4980
  #nextId;
@@ -4723,7 +4998,7 @@
4723
4998
  this.#groupLimits = new Map();
4724
4999
  this.#particleBuckets = new Map();
4725
5000
  this.#zBuckets = this.#createBuckets(this.#container.zLayers);
4726
- this.grid = new SpatialHashGrid(spatialHashGridCellSize);
5001
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize);
4727
5002
  this.checkParticlePositionPlugins = [];
4728
5003
  this.#particleResetPlugins = [];
4729
5004
  this.#particleUpdatePlugins = [];
@@ -4734,23 +5009,12 @@
4734
5009
  get count() {
4735
5010
  return this.#array.length;
4736
5011
  }
5012
+ get grid() {
5013
+ return this.#grid;
5014
+ }
4737
5015
  addParticle(position, overrideOptions, group, initializer) {
4738
- const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
4739
- if (limit > minLimit) {
4740
- switch (limitMode) {
4741
- case LimitMode.delete: {
4742
- const countToRemove = currentCount + countOffset - limit;
4743
- if (countToRemove > minCount) {
4744
- this.removeQuantity(countToRemove);
4745
- }
4746
- break;
4747
- }
4748
- case LimitMode.wait:
4749
- if (currentCount >= limit) {
4750
- return;
4751
- }
4752
- break;
4753
- }
5016
+ if (this.#checkAndApplyLimits(group, this.count)) {
5017
+ return;
4754
5018
  }
4755
5019
  try {
4756
5020
  const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
@@ -4814,7 +5078,7 @@
4814
5078
  return this.#array[index];
4815
5079
  }
4816
5080
  async init() {
4817
- const container = this.#container, options = container.actualOptions;
5081
+ const container = this.#container;
4818
5082
  this.checkParticlePositionPlugins = [];
4819
5083
  this.#updatePlugins = [];
4820
5084
  this.#particleUpdatePlugins = [];
@@ -4823,59 +5087,16 @@
4823
5087
  this.#postParticleUpdatePlugins = [];
4824
5088
  this.#particleBuckets.clear();
4825
5089
  this.#resetBuckets(container.zLayers);
4826
- this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
4827
- for (const plugin of container.plugins) {
4828
- if (plugin.redrawInit) {
4829
- await plugin.redrawInit();
4830
- }
4831
- if (plugin.checkParticlePosition) {
4832
- this.checkParticlePositionPlugins.push(plugin);
4833
- }
4834
- if (plugin.update) {
4835
- this.#updatePlugins.push(plugin);
4836
- }
4837
- if (plugin.particleUpdate) {
4838
- this.#particleUpdatePlugins.push(plugin);
4839
- }
4840
- if (plugin.postUpdate) {
4841
- this.#postUpdatePlugins.push(plugin);
4842
- }
4843
- if (plugin.particleReset) {
4844
- this.#particleResetPlugins.push(plugin);
4845
- }
4846
- if (plugin.postParticleUpdate) {
4847
- this.#postParticleUpdatePlugins.push(plugin);
4848
- }
4849
- }
4850
- await this.#container.initDrawersAndUpdaters();
4851
- for (const drawer of this.#container.effectDrawers.values()) {
4852
- await drawer.init?.(container);
4853
- }
4854
- for (const drawer of this.#container.shapeDrawers.values()) {
4855
- await drawer.init?.(container);
4856
- }
4857
- let handled = false;
4858
- for (const plugin of container.plugins) {
4859
- handled = plugin.particlesInitialization?.() ?? handled;
4860
- if (handled) {
4861
- break;
4862
- }
4863
- }
4864
- if (!handled) {
4865
- const particlesOptions = options.particles, groups = particlesOptions.groups;
4866
- for (const group in groups) {
4867
- const groupOptions = groups[group];
4868
- if (!groupOptions) {
4869
- continue;
4870
- }
4871
- for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
4872
- this.addParticle(undefined, groupOptions, group);
4873
- }
4874
- }
4875
- for (let i = this.count; i < particlesOptions.number.value; i++) {
4876
- this.addParticle();
5090
+ this.#grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
5091
+ this.#applyLimits(container.actualOptions.particles);
5092
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5093
+ for (const group in groups) {
5094
+ const groupData = groups[group];
5095
+ if (groupData) {
5096
+ this.#applyLimits(loadParticlesOptions(this.#pluginManager, this.#container, groupData), group, groupData);
4877
5097
  }
4878
5098
  }
5099
+ await this.#initPlugins();
4879
5100
  }
4880
5101
  push(nb, position, overrideOptions, group) {
4881
5102
  for (let i = 0; i < nb; i++) {
@@ -4890,13 +5111,13 @@
4890
5111
  remove(particle, group, override) {
4891
5112
  this.removeAt(this.#array.indexOf(particle), undefined, group, override);
4892
5113
  }
4893
- removeAt(index, quantity = defaultRemoveQuantity, group, override) {
5114
+ removeAt(index, quantity = defaultRemoveQuantity, group, override, matchGroup = true) {
4894
5115
  if (index < minIndex || index > this.count) {
4895
5116
  return;
4896
5117
  }
4897
5118
  let deleted = 0;
4898
5119
  for (let i = index; deleted < quantity && i < this.count; i++) {
4899
- if (this.#removeParticle(i, group, override)) {
5120
+ if (this.#removeParticle(i, group, override, matchGroup)) {
4900
5121
  i--;
4901
5122
  deleted++;
4902
5123
  }
@@ -4927,7 +5148,7 @@
4927
5148
  this.#resizeFactor = factor;
4928
5149
  }
4929
5150
  update(delta) {
4930
- this.grid.clear();
5151
+ this.#grid.clear();
4931
5152
  for (const plugin of this.#updatePlugins) {
4932
5153
  plugin.update?.(delta);
4933
5154
  }
@@ -4938,7 +5159,7 @@
4938
5159
  this.#updateParticlesPhase2(delta, particlesToDelete);
4939
5160
  if (particlesToDelete.size) {
4940
5161
  for (const particle of particlesToDelete) {
4941
- this.remove(particle);
5162
+ this.remove(particle, particle.group);
4942
5163
  }
4943
5164
  }
4944
5165
  this.#resizeFactor = undefined;
@@ -4949,12 +5170,7 @@
4949
5170
  #applyDensity(options, pluginsCount, group, groupOptions) {
4950
5171
  const numberOptions = options.number;
4951
5172
  if (!numberOptions.density.enable) {
4952
- if (group === undefined) {
4953
- this.#limit = numberOptions.limit.value;
4954
- }
4955
- else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
4956
- this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
4957
- }
5173
+ this.#applyLimits(options, group, groupOptions);
4958
5174
  return;
4959
5175
  }
4960
5176
  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);
@@ -4962,7 +5178,10 @@
4962
5178
  this.#limit = numberOptions.limit.value * densityFactor;
4963
5179
  }
4964
5180
  else {
4965
- this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
5181
+ this.#groupLimits.set(group, {
5182
+ limit: numberOptions.limit.value * densityFactor,
5183
+ mode: toEnumValue(LimitMode, numberOptions.limit.mode, LimitMode.delete),
5184
+ });
4966
5185
  }
4967
5186
  if (particlesCount < particlesNumber) {
4968
5187
  this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
@@ -4971,6 +5190,55 @@
4971
5190
  this.removeQuantity(particlesCount - particlesNumber, group);
4972
5191
  }
4973
5192
  }
5193
+ #applyLimits(options, group, groupOptions) {
5194
+ if (group === undefined) {
5195
+ this.#limit = options.number.limit.value;
5196
+ const groups = this.#container.actualOptions.particles.groups;
5197
+ for (const existingGroup of this.#groupLimits.keys()) {
5198
+ if (!(existingGroup in groups)) {
5199
+ this.#groupLimits.delete(existingGroup);
5200
+ }
5201
+ }
5202
+ }
5203
+ else {
5204
+ const limitValue = groupOptions?.number?.limit?.value ?? options.number.limit.value;
5205
+ if (limitValue > minLimit) {
5206
+ this.#groupLimits.set(group, {
5207
+ limit: limitValue,
5208
+ mode: toEnumValue(LimitMode, groupOptions?.number?.limit?.mode ?? options.number.limit.mode, LimitMode.delete),
5209
+ });
5210
+ }
5211
+ else {
5212
+ this.#groupLimits.delete(group);
5213
+ }
5214
+ }
5215
+ }
5216
+ #checkAndApplyLimits(group, currentCount) {
5217
+ const globalLimit = this.#limit, globalMode = this.#container.actualOptions.particles.number.limit.mode;
5218
+ if (globalLimit > minLimit && globalMode === LimitMode.wait && currentCount >= globalLimit) {
5219
+ return true;
5220
+ }
5221
+ const groupLimitEntry = group === undefined ? undefined : this.#groupLimits.get(group);
5222
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.wait) {
5223
+ const groupCount = this.filter(t => t.group === group).length;
5224
+ if (groupCount >= groupLimitEntry.limit) {
5225
+ return true;
5226
+ }
5227
+ }
5228
+ if (groupLimitEntry && groupLimitEntry.limit > minLimit && groupLimitEntry.mode === LimitMode.delete) {
5229
+ const groupCountToRemove = this.filter(t => t.group === group).length + countOffset - groupLimitEntry.limit;
5230
+ if (groupCountToRemove > minCount) {
5231
+ this.removeQuantity(groupCountToRemove, group);
5232
+ }
5233
+ }
5234
+ if (globalLimit > minLimit && globalMode === LimitMode.delete) {
5235
+ const globalCountToRemove = this.count + countOffset - globalLimit;
5236
+ if (globalCountToRemove > minCount) {
5237
+ this.#removeAny(globalCountToRemove);
5238
+ }
5239
+ }
5240
+ return false;
5241
+ }
4974
5242
  #createBuckets(zLayers) {
4975
5243
  const bucketCount = Math.max(Math.floor(zLayers), one);
4976
5244
  return Array.from({ length: bucketCount }, () => []);
@@ -4993,6 +5261,70 @@
4993
5261
  }
4994
5262
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
4995
5263
  }
5264
+ async #initDrawersAndUpdaters() {
5265
+ const container = this.#container;
5266
+ await container.initDrawersAndUpdaters();
5267
+ for (const drawer of container.effectDrawers.values()) {
5268
+ await drawer.init?.(container);
5269
+ }
5270
+ for (const drawer of container.shapeDrawers.values()) {
5271
+ await drawer.init?.(container);
5272
+ }
5273
+ }
5274
+ async #initPlugins() {
5275
+ await this.#initPluginsArrays();
5276
+ await this.#initDrawersAndUpdaters();
5277
+ let handled = false;
5278
+ const container = this.#container;
5279
+ for (const plugin of container.plugins) {
5280
+ handled = plugin.particlesInitialization?.() ?? handled;
5281
+ if (handled) {
5282
+ break;
5283
+ }
5284
+ }
5285
+ if (handled) {
5286
+ return;
5287
+ }
5288
+ const particlesOptions = container.actualOptions.particles, groups = particlesOptions.groups;
5289
+ for (const group in groups) {
5290
+ const groupOptions = groups[group];
5291
+ if (!groupOptions) {
5292
+ continue;
5293
+ }
5294
+ for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
5295
+ this.addParticle(undefined, groupOptions, group);
5296
+ }
5297
+ }
5298
+ for (let i = this.count; i < particlesOptions.number.value; i++) {
5299
+ this.addParticle();
5300
+ }
5301
+ }
5302
+ async #initPluginsArrays() {
5303
+ const container = this.#container;
5304
+ for (const plugin of container.plugins) {
5305
+ if (plugin.redrawInit) {
5306
+ await plugin.redrawInit();
5307
+ }
5308
+ if (plugin.checkParticlePosition) {
5309
+ this.checkParticlePositionPlugins.push(plugin);
5310
+ }
5311
+ if (plugin.update) {
5312
+ this.#updatePlugins.push(plugin);
5313
+ }
5314
+ if (plugin.particleUpdate) {
5315
+ this.#particleUpdatePlugins.push(plugin);
5316
+ }
5317
+ if (plugin.postUpdate) {
5318
+ this.#postUpdatePlugins.push(plugin);
5319
+ }
5320
+ if (plugin.particleReset) {
5321
+ this.#particleResetPlugins.push(plugin);
5322
+ }
5323
+ if (plugin.postParticleUpdate) {
5324
+ this.#postParticleUpdatePlugins.push(plugin);
5325
+ }
5326
+ }
5327
+ }
4996
5328
  #insertParticleIntoBucket(particle) {
4997
5329
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
4998
5330
  if (!bucket) {
@@ -5001,12 +5333,15 @@
5001
5333
  bucket.push(particle);
5002
5334
  this.#particleBuckets.set(particle.id, bucketIndex);
5003
5335
  }
5004
- #removeParticle(index, group, override) {
5336
+ #removeAny(quantity) {
5337
+ this.removeAt(minIndex, quantity, undefined, undefined, false);
5338
+ }
5339
+ #removeParticle(index, group, override, matchGroup = true) {
5005
5340
  const particle = this.#array[index];
5006
5341
  if (!particle) {
5007
5342
  return false;
5008
5343
  }
5009
- if (particle.group !== group) {
5344
+ if (matchGroup && particle.group !== group) {
5010
5345
  return false;
5011
5346
  }
5012
5347
  this.#array.splice(index, deleteCount);
@@ -5093,7 +5428,7 @@
5093
5428
  particlesToDelete.add(particle);
5094
5429
  continue;
5095
5430
  }
5096
- this.grid.insert(particle);
5431
+ this.#grid.insert(particle);
5097
5432
  }
5098
5433
  return particlesToDelete;
5099
5434
  }
@@ -5165,6 +5500,7 @@
5165
5500
  effectDrawers;
5166
5501
  fpsLimit;
5167
5502
  hdr;
5503
+ hdrMode;
5168
5504
  id;
5169
5505
  pageHidden;
5170
5506
  particleCreatedPlugins;
@@ -5172,6 +5508,7 @@
5172
5508
  particlePositionPlugins;
5173
5509
  particleUpdaters;
5174
5510
  particles;
5511
+ peakNits;
5175
5512
  plugins;
5176
5513
  retina;
5177
5514
  shapeDrawers;
@@ -5202,6 +5539,8 @@
5202
5539
  this.id = Symbol(id);
5203
5540
  this.fpsLimit = 120;
5204
5541
  this.hdr = false;
5542
+ this.hdrMode = HdrMode.standard;
5543
+ this.peakNits = 400;
5205
5544
  this.#smooth = false;
5206
5545
  this.#delay = 0;
5207
5546
  this.#duration = 0;
@@ -5265,7 +5604,6 @@
5265
5604
  this.shapeDrawers = new Map();
5266
5605
  this.particleUpdaters = [];
5267
5606
  this.plugins.length = 0;
5268
- this.#pluginManager.clearPlugins(this);
5269
5607
  this.destroyed = true;
5270
5608
  this.#onDestroy(remove);
5271
5609
  this.dispatchEvent(EventType.containerDestroyed);
@@ -5318,31 +5656,15 @@
5318
5656
  await this.initDrawersAndUpdaters();
5319
5657
  this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
5320
5658
  this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
5321
- this.plugins.length = 0;
5322
- this.particleDestroyedPlugins.length = 0;
5323
- this.particleCreatedPlugins.length = 0;
5324
- this.particlePositionPlugins.length = 0;
5325
- for (const [plugin, containerPlugin] of allContainerPlugins) {
5326
- if (plugin.needsPlugin(this.actualOptions)) {
5327
- this.plugins.push(containerPlugin);
5328
- if (containerPlugin.particleCreated) {
5329
- this.particleCreatedPlugins.push(containerPlugin);
5330
- }
5331
- if (containerPlugin.particleDestroyed) {
5332
- this.particleDestroyedPlugins.push(containerPlugin);
5333
- }
5334
- if (containerPlugin.particlePosition) {
5335
- this.particlePositionPlugins.push(containerPlugin);
5336
- }
5337
- }
5338
- }
5659
+ this.#initPlugins(allContainerPlugins);
5339
5660
  this.retina.init();
5340
5661
  this.canvas.init();
5341
5662
  this.updateActualOptions();
5342
5663
  this.canvas.initBackground();
5343
5664
  this.canvas.resize();
5344
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5345
- this.hdr = hdr;
5665
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
5666
+ this.hdrMode = toEnumValue(HdrMode, hdrOptions.mode, HdrMode.standard);
5667
+ this.peakNits = hdrOptions.peakNits;
5346
5668
  this.zLayers = zLayers;
5347
5669
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5348
5670
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -5362,9 +5684,9 @@
5362
5684
  }
5363
5685
  async initDrawersAndUpdaters() {
5364
5686
  const pluginManager = this.#pluginManager;
5365
- this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
5366
- this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
5367
- this.particleUpdaters = await pluginManager.getUpdaters(this, true);
5687
+ this.effectDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.effects);
5688
+ this.shapeDrawers = await getItemMapFromInitializer(this, pluginManager.initializers.shapes);
5689
+ this.particleUpdaters = await getItemsFromInitializer(this, pluginManager.initializers.updaters);
5368
5690
  }
5369
5691
  pause() {
5370
5692
  if (!guardCheck(this)) {
@@ -5475,6 +5797,27 @@
5475
5797
  }
5476
5798
  return refresh;
5477
5799
  }
5800
+ #initPlugins(allContainerPlugins) {
5801
+ this.plugins.length = 0;
5802
+ this.particleDestroyedPlugins.length = 0;
5803
+ this.particleCreatedPlugins.length = 0;
5804
+ this.particlePositionPlugins.length = 0;
5805
+ for (const [plugin, containerPlugin] of allContainerPlugins) {
5806
+ if (!plugin.needsPlugin(this.actualOptions)) {
5807
+ continue;
5808
+ }
5809
+ this.plugins.push(containerPlugin);
5810
+ if (containerPlugin.particleCreated) {
5811
+ this.particleCreatedPlugins.push(containerPlugin);
5812
+ }
5813
+ if (containerPlugin.particleDestroyed) {
5814
+ this.particleDestroyedPlugins.push(containerPlugin);
5815
+ }
5816
+ if (containerPlugin.particlePosition) {
5817
+ this.particlePositionPlugins.push(containerPlugin);
5818
+ }
5819
+ }
5820
+ }
5478
5821
  #nextFrame(timestamp) {
5479
5822
  try {
5480
5823
  if (!this.#smooth &&
@@ -5751,11 +6094,11 @@
5751
6094
  }
5752
6095
  }
5753
6096
  async #init() {
5754
- const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
5755
- if (!availablePathGenerators) {
6097
+ const pluginManager = this.#pluginManager;
6098
+ if (!pluginManager.initializers.pathGenerators) {
5756
6099
  return;
5757
6100
  }
5758
- this.availablePathGenerators = availablePathGenerators;
6101
+ this.availablePathGenerators = await getItemMapFromInitializer(this.#container, pluginManager.initializers.pathGenerators);
5759
6102
  this.pathGenerators = new Map();
5760
6103
  for (const pathGenerator of this.pathGenerators.values()) {
5761
6104
  pathGenerator.init();
@@ -5771,6 +6114,7 @@
5771
6114
  exports.loadBigCirclesPreset = loadBigCirclesPreset;
5772
6115
  exports.tsParticles = tsParticles;
5773
6116
 
5774
- }));
6117
+ })(g.__tsParticlesInternals.presets.bigCircles = g.__tsParticlesInternals.presets.bigCircles || {});
6118
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : self);
6119
+
5775
6120
  Object.assign(globalThis.window || globalThis, { loadBigCirclesPreset: (globalThis.__tsParticlesInternals.presets.bigCircles || {}).loadBigCirclesPreset });
5776
- delete (globalThis.window || globalThis).tsparticlesInternalExports;