@tsparticles/preset-firefly 4.3.1 → 4.4.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,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.3.1 */
2
+ /* Preset v4.4.0 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -292,6 +292,9 @@
292
292
  })(PixelMode || (PixelMode = {}));
293
293
 
294
294
  const minRadius = 0;
295
+ function isForbiddenKey(key) {
296
+ return key === "__proto__" || key === "constructor" || key === "prototype";
297
+ }
295
298
  function hasMatchMedia() {
296
299
  return typeof matchMedia !== "undefined";
297
300
  }
@@ -367,7 +370,7 @@
367
370
  if (!hasNested) {
368
371
  const sourceDict = source, destDict = destination;
369
372
  for (const key of sourceKeys) {
370
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
373
+ if (isForbiddenKey(key)) {
371
374
  continue;
372
375
  }
373
376
  const v = sourceDict[key];
@@ -378,7 +381,7 @@
378
381
  continue;
379
382
  }
380
383
  for (const key of sourceKeys) {
381
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
384
+ if (isForbiddenKey(key)) {
382
385
  continue;
383
386
  }
384
387
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -794,7 +797,7 @@
794
797
  return this.#domArray;
795
798
  }
796
799
  get version() {
797
- return "4.3.1";
800
+ return "4.4.0";
798
801
  }
799
802
  addEventListener(type, listener) {
800
803
  this.#eventDispatcher.addEventListener(type, listener);
@@ -875,6 +878,10 @@
875
878
  }
876
879
 
877
880
  function initEngine() {
881
+ const existing = globalThis.tsParticles;
882
+ if (existing?.pluginManager) {
883
+ return existing;
884
+ }
878
885
  return new Engine();
879
886
  }
880
887
 
@@ -972,6 +979,15 @@
972
979
  AnimationMode["random"] = "random";
973
980
  })(AnimationMode || (AnimationMode = {}));
974
981
 
982
+ var HdrMode;
983
+ (function (HdrMode) {
984
+ HdrMode["standard"] = "standard";
985
+ HdrMode["natural"] = "natural";
986
+ HdrMode["vivid"] = "vivid";
987
+ HdrMode["cinematic"] = "cinematic";
988
+ HdrMode["dynamic"] = "dynamic";
989
+ })(HdrMode || (HdrMode = {}));
990
+
975
991
  var LimitMode;
976
992
  (function (LimitMode) {
977
993
  LimitMode["delete"] = "delete";
@@ -1227,6 +1243,29 @@
1227
1243
  }
1228
1244
  }
1229
1245
 
1246
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1247
+ class HDROptions extends OptionLoader {
1248
+ enable = true;
1249
+ mode = HdrMode.standard;
1250
+ peakNits = defaultPeakNits;
1251
+ doLoad(data) {
1252
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1253
+ throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1254
+ }
1255
+ if (data.mode !== undefined &&
1256
+ (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1257
+ throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1258
+ }
1259
+ if (data.peakNits !== undefined &&
1260
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1261
+ throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1262
+ }
1263
+ loadProperty(this, "enable", data.enable);
1264
+ loadProperty(this, "mode", data.mode);
1265
+ loadProperty(this, "peakNits", data.peakNits);
1266
+ }
1267
+ }
1268
+
1230
1269
  class ResizeEvent extends OptionLoader {
1231
1270
  delay = 0.5;
1232
1271
  enable = true;
@@ -1670,7 +1709,7 @@
1670
1709
  duration = 0;
1671
1710
  fpsLimit = 120;
1672
1711
  fullScreen;
1673
- hdr = true;
1712
+ hdr;
1674
1713
  key;
1675
1714
  name;
1676
1715
  palette;
@@ -1690,6 +1729,7 @@
1690
1729
  this.#container = container;
1691
1730
  this.background = new Background();
1692
1731
  this.fullScreen = new FullScreen();
1732
+ this.hdr = new HDROptions();
1693
1733
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1694
1734
  this.resize = new ResizeEvent();
1695
1735
  }
@@ -1712,7 +1752,15 @@
1712
1752
  loadProperty(this, "detectRetina", data.detectRetina);
1713
1753
  loadRangeProperty(this, "duration", data.duration);
1714
1754
  loadProperty(this, "fpsLimit", data.fpsLimit);
1715
- loadProperty(this, "hdr", data.hdr);
1755
+ const hdrData = data.hdr;
1756
+ if (isBoolean(hdrData)) {
1757
+ this.hdr.enable = hdrData;
1758
+ this.hdr.mode = HdrMode.standard;
1759
+ this.hdr.peakNits = 400;
1760
+ }
1761
+ else {
1762
+ this.hdr.load(hdrData);
1763
+ }
1716
1764
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1717
1765
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1718
1766
  loadProperty(this, "zLayers", data.zLayers);
@@ -1755,7 +1803,7 @@
1755
1803
  }
1756
1804
  }
1757
1805
 
1758
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1806
+ 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;
1759
1807
  function getCachedStyle(key, generator) {
1760
1808
  let cached = styleCache.get(key);
1761
1809
  if (!cached) {
@@ -1767,6 +1815,42 @@
1767
1815
  }
1768
1816
  return cached;
1769
1817
  }
1818
+ function acesFilmic(x) {
1819
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1820
+ }
1821
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1822
+ switch (mode) {
1823
+ case HdrMode.vivid: {
1824
+ const avg = (r + g + b) / channelCount;
1825
+ return {
1826
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1827
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1828
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1829
+ };
1830
+ }
1831
+ case HdrMode.cinematic: {
1832
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1833
+ return {
1834
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1835
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1836
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1837
+ };
1838
+ }
1839
+ case HdrMode.dynamic: {
1840
+ 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;
1841
+ return {
1842
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1843
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1844
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1845
+ };
1846
+ }
1847
+ case HdrMode.standard:
1848
+ return { b, g, r };
1849
+ case HdrMode.natural:
1850
+ default:
1851
+ return { b, g, r };
1852
+ }
1853
+ }
1770
1854
  function stringToRgba(pluginManager, input) {
1771
1855
  if (!input) {
1772
1856
  return;
@@ -1924,21 +2008,40 @@
1924
2008
  r: getRgbInRangeValue(),
1925
2009
  };
1926
2010
  }
1927
- function getStyleFromRgb(color, hdr, opacity) {
1928
- 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()}`;
1929
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2011
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2012
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2013
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2014
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2015
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
1930
2016
  }
1931
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1932
- const headroom = peakNits / sdrReferenceWhiteNits;
1933
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2017
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
2018
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2019
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2020
+ }
2021
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2022
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2023
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2024
+ return { b: bNorm, g: gNorm, r: rNorm };
2025
+ }
2026
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2027
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2028
+ }
2029
+ function hdrToneMap(normalized, headroom, middleGray) {
2030
+ if (normalized <= middleGray) {
2031
+ return acesFilmic(normalized);
2032
+ }
2033
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2034
+ return acesFilmic(expanded);
1934
2035
  }
1935
2036
  function getSdrStyleFromRgb(color, opacity) {
1936
2037
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1937
2038
  }
1938
- function getStyleFromHsl(color, hdr, opacity) {
1939
- 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()}`;
2039
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2040
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2041
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2042
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1940
2043
  return getCachedStyle(key, () => hdr
1941
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2044
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1942
2045
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1943
2046
  }
1944
2047
  function getHslFromAnimation(animation) {
@@ -2001,7 +2104,7 @@
2001
2104
  colorValue.velocity = defaultVelocity;
2002
2105
  }
2003
2106
  }
2004
- function updateColorValue(data, decrease, delta, hdr) {
2107
+ function updateColorValue(data, decrease, delta, _hdr) {
2005
2108
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2006
2109
  if (!data.enable ||
2007
2110
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2014,7 +2117,7 @@
2014
2117
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2015
2118
  return;
2016
2119
  }
2017
- 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;
2120
+ 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;
2018
2121
  if (!decrease || data.status === AnimationStatus.increasing) {
2019
2122
  data.value += velocity;
2020
2123
  if (data.value > max) {
@@ -2046,9 +2149,9 @@
2046
2149
  return;
2047
2150
  }
2048
2151
  const { h, s, l } = color;
2049
- updateColorValue(h, false, delta, hdr);
2050
- updateColorValue(s, true, delta, hdr);
2051
- updateColorValue(l, true, delta, hdr);
2152
+ updateColorValue(h, false, delta);
2153
+ updateColorValue(s, true, delta);
2154
+ updateColorValue(l, true, delta);
2052
2155
  }
2053
2156
  function alterHsl(color, type, value) {
2054
2157
  return {
@@ -2098,7 +2201,7 @@
2098
2201
  }
2099
2202
 
2100
2203
  async function loadBlendPlugin(engine) {
2101
- engine.checkVersion("4.3.1");
2204
+ engine.checkVersion("4.4.0");
2102
2205
  await engine.pluginManager.register(e => {
2103
2206
  e.pluginManager.addPlugin(new BlendPlugin());
2104
2207
  });
@@ -2135,7 +2238,7 @@
2135
2238
  }
2136
2239
 
2137
2240
  async function loadCircleShape(engine) {
2138
- engine.checkVersion("4.3.1");
2241
+ engine.checkVersion("4.4.0");
2139
2242
  await engine.pluginManager.register(e => {
2140
2243
  e.pluginManager.addShape(["circle"], () => {
2141
2244
  return Promise.resolve(new CircleDrawer());
@@ -2183,7 +2286,7 @@
2183
2286
  }
2184
2287
 
2185
2288
  async function loadHexColorPlugin(engine) {
2186
- engine.checkVersion("4.3.1");
2289
+ engine.checkVersion("4.4.0");
2187
2290
  await engine.pluginManager.register(e => {
2188
2291
  e.pluginManager.addColorManager("hex", new HexColorManager());
2189
2292
  });
@@ -2236,7 +2339,7 @@
2236
2339
  }
2237
2340
 
2238
2341
  async function loadHslColorPlugin(engine) {
2239
- engine.checkVersion("4.3.1");
2342
+ engine.checkVersion("4.4.0");
2240
2343
  await engine.pluginManager.register(e => {
2241
2344
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2242
2345
  });
@@ -2260,7 +2363,7 @@
2260
2363
  }
2261
2364
 
2262
2365
  async function loadMovePlugin(engine) {
2263
- engine.checkVersion("4.3.1");
2366
+ engine.checkVersion("4.4.0");
2264
2367
  await engine.pluginManager.register(e => {
2265
2368
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2266
2369
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2470,7 +2573,7 @@
2470
2573
  }
2471
2574
 
2472
2575
  async function loadOpacityUpdater(engine) {
2473
- engine.checkVersion("4.3.1");
2576
+ engine.checkVersion("4.4.0");
2474
2577
  await engine.pluginManager.register(e => {
2475
2578
  e.pluginManager.addParticleUpdater("opacity", container => {
2476
2579
  return Promise.resolve(new OpacityUpdater(container));
@@ -2815,7 +2918,7 @@
2815
2918
  }
2816
2919
 
2817
2920
  async function loadOutModesUpdater(engine) {
2818
- engine.checkVersion("4.3.1");
2921
+ engine.checkVersion("4.4.0");
2819
2922
  await engine.pluginManager.register(e => {
2820
2923
  e.pluginManager.addParticleUpdater("outModes", container => {
2821
2924
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2886,7 +2989,7 @@
2886
2989
  }
2887
2990
 
2888
2991
  async function loadPaintUpdater(engine) {
2889
- engine.checkVersion("4.3.1");
2992
+ engine.checkVersion("4.4.0");
2890
2993
  await engine.pluginManager.register(e => {
2891
2994
  e.pluginManager.addParticleUpdater("paint", container => {
2892
2995
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2941,7 +3044,7 @@
2941
3044
  }
2942
3045
 
2943
3046
  async function loadRgbColorPlugin(engine) {
2944
- engine.checkVersion("4.3.1");
3047
+ engine.checkVersion("4.4.0");
2945
3048
  await engine.pluginManager.register(e => {
2946
3049
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2947
3050
  });
@@ -3026,7 +3129,7 @@
3026
3129
  }
3027
3130
 
3028
3131
  async function loadSizeUpdater(engine) {
3029
- engine.checkVersion("4.3.1");
3132
+ engine.checkVersion("4.4.0");
3030
3133
  await engine.pluginManager.register(e => {
3031
3134
  e.pluginManager.addParticleUpdater("size", container => {
3032
3135
  return Promise.resolve(new SizeUpdater(container));
@@ -3035,7 +3138,7 @@
3035
3138
  }
3036
3139
 
3037
3140
  async function loadBasic(engine) {
3038
- engine.checkVersion("4.3.1");
3141
+ engine.checkVersion("4.4.0");
3039
3142
  await engine.pluginManager.register(async (e) => {
3040
3143
  await Promise.all([
3041
3144
  loadBlendPlugin(e),
@@ -3236,7 +3339,7 @@
3236
3339
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3237
3340
 
3238
3341
  async function loadInteractivityPlugin(engine) {
3239
- engine.checkVersion("4.3.1");
3342
+ engine.checkVersion("4.4.0");
3240
3343
  await engine.pluginManager.register(e => {
3241
3344
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3242
3345
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3433,7 +3536,7 @@
3433
3536
  }
3434
3537
 
3435
3538
  async function loadExternalTrailInteraction(engine) {
3436
- engine.checkVersion("4.3.1");
3539
+ engine.checkVersion("4.4.0");
3437
3540
  await engine.pluginManager.register((e) => {
3438
3541
  ensureInteractivityPluginLoaded(e);
3439
3542
  e.pluginManager.addInteractor?.("externalTrail", container => {
@@ -3579,7 +3682,7 @@
3579
3682
  }
3580
3683
 
3581
3684
  async function loadLifeUpdater(engine) {
3582
- engine.checkVersion("4.3.1");
3685
+ engine.checkVersion("4.4.0");
3583
3686
  await engine.pluginManager.register(e => {
3584
3687
  e.pluginManager.addParticleUpdater("life", container => {
3585
3688
  return Promise.resolve(new LifeUpdater(container));
@@ -3788,7 +3891,11 @@
3788
3891
  if (!fColor && !sColor) {
3789
3892
  return;
3790
3893
  }
3791
- 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;
3894
+ 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
3895
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3896
+ : undefined, stroke = sColor
3897
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3898
+ : fill;
3792
3899
  transform.a = transform.b = transform.c = transform.d = undefined;
3793
3900
  colorStyles.fill = fill;
3794
3901
  colorStyles.stroke = stroke;
@@ -4122,7 +4229,9 @@
4122
4229
  if (typeof background.element === "string") {
4123
4230
  if (typeof document !== "undefined") {
4124
4231
  const node = document.querySelector(background.element);
4125
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4232
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4233
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4234
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4126
4235
  this.#backgroundElement = node;
4127
4236
  }
4128
4237
  else if (node) {
@@ -4133,10 +4242,10 @@
4133
4242
  }
4134
4243
  }
4135
4244
  }
4136
- else if (background.element instanceof HTMLCanvasElement ||
4137
- background.element instanceof OffscreenCanvas ||
4138
- background.element instanceof HTMLVideoElement ||
4139
- background.element instanceof HTMLImageElement) {
4245
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4246
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4247
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4248
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4140
4249
  this.#backgroundElement = background.element;
4141
4250
  }
4142
4251
  }
@@ -4204,6 +4313,7 @@
4204
4313
  zoom = defaultZoom;
4205
4314
  #container;
4206
4315
  #generated;
4316
+ #hdrMediaListeners;
4207
4317
  #mutationObserver;
4208
4318
  #originalStyle;
4209
4319
  #pluginManager;
@@ -4268,7 +4378,6 @@
4268
4378
  });
4269
4379
  this.resize();
4270
4380
  this.#initStyle();
4271
- this.initBackground();
4272
4381
  this.#safeMutationObserver(obs => {
4273
4382
  const element = this.domElement;
4274
4383
  if (!element || !(element instanceof Node)) {
@@ -4278,6 +4387,8 @@
4278
4387
  });
4279
4388
  this.initPlugins();
4280
4389
  this.#initContext();
4390
+ this.initBackground();
4391
+ this.#initHdrListeners();
4281
4392
  this.render.init();
4282
4393
  }
4283
4394
  initBackground() {
@@ -4287,7 +4398,8 @@
4287
4398
  }
4288
4399
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4289
4400
  if (color) {
4290
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4401
+ const hdrOptions = container.actualOptions.hdr;
4402
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4291
4403
  }
4292
4404
  else {
4293
4405
  elementStyle.backgroundColor = "";
@@ -4384,6 +4496,7 @@
4384
4496
  obs.disconnect();
4385
4497
  });
4386
4498
  this.#mutationObserver = undefined;
4499
+ this.#removeHdrListeners();
4387
4500
  this.render.stop();
4388
4501
  }
4389
4502
  async windowResize() {
@@ -4403,9 +4516,16 @@
4403
4516
  }
4404
4517
  }
4405
4518
  #initContext() {
4406
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4519
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4407
4520
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4408
4521
  safeMatchMedia("(dynamic-range: high)")?.matches;
4522
+ container.hdr = canSupportHdr ?? false;
4523
+ container.hdrMode = container.actualOptions.hdr.mode;
4524
+ container.peakNits = container.actualOptions.hdr.peakNits;
4525
+ const renderCanvas = this.renderCanvas;
4526
+ if (!renderCanvas) {
4527
+ return;
4528
+ }
4409
4529
  this.render.setContextSettings({
4410
4530
  alpha: true,
4411
4531
  desynchronized: true,
@@ -4414,11 +4534,47 @@
4414
4534
  ? { colorSpace: "display-p3", colorType: "float16" }
4415
4535
  : { colorSpace: "srgb" }),
4416
4536
  });
4417
- const renderCanvas = this.renderCanvas;
4418
- if (!renderCanvas) {
4419
- return;
4537
+ let context;
4538
+ try {
4539
+ context = renderCanvas.getContext("2d", this.render.settings);
4540
+ }
4541
+ catch {
4542
+ context = null;
4543
+ }
4544
+ if (canSupportHdr && !context) {
4545
+ container.hdr = false;
4546
+ const sdrSettings = {
4547
+ alpha: true,
4548
+ desynchronized: true,
4549
+ willReadFrequently: false,
4550
+ colorSpace: "srgb",
4551
+ };
4552
+ this.render.setContextSettings(sdrSettings);
4553
+ try {
4554
+ context = renderCanvas.getContext("2d", sdrSettings);
4555
+ }
4556
+ catch {
4557
+ context = null;
4558
+ }
4559
+ }
4560
+ this.render.setContext(context);
4561
+ }
4562
+ #initHdrListeners() {
4563
+ this.#removeHdrListeners();
4564
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4565
+ this.#recreateRenderCanvas();
4566
+ this.#initContext();
4567
+ this.initBackground();
4568
+ }, listeners = [];
4569
+ if (p3Query) {
4570
+ p3Query.addEventListener("change", handleChange);
4571
+ listeners.push({ handler: handleChange, mql: p3Query });
4572
+ }
4573
+ if (hdrQuery) {
4574
+ hdrQuery.addEventListener("change", handleChange);
4575
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4420
4576
  }
4421
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4577
+ this.#hdrMediaListeners = listeners;
4422
4578
  }
4423
4579
  #initStyle() {
4424
4580
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4442,6 +4598,25 @@
4442
4598
  element.style.setProperty(key, value, "important");
4443
4599
  }
4444
4600
  }
4601
+ #recreateRenderCanvas() {
4602
+ const renderCanvas = this.renderCanvas;
4603
+ if (!renderCanvas) {
4604
+ return;
4605
+ }
4606
+ if (this.domElement) {
4607
+ return;
4608
+ }
4609
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4610
+ }
4611
+ #removeHdrListeners() {
4612
+ if (!this.#hdrMediaListeners) {
4613
+ return;
4614
+ }
4615
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4616
+ mql.removeEventListener("change", handler);
4617
+ }
4618
+ this.#hdrMediaListeners = undefined;
4619
+ }
4445
4620
  #repairStyle() {
4446
4621
  const element = this.domElement;
4447
4622
  if (!element) {
@@ -4826,9 +5001,9 @@
4826
5001
  }
4827
5002
  getOpacity() {
4828
5003
  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;
4829
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5004
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4830
5005
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4831
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5006
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4832
5007
  return this.#cachedOpacityData;
4833
5008
  }
4834
5009
  getPosition() {
@@ -5683,6 +5858,7 @@
5683
5858
  effectDrawers;
5684
5859
  fpsLimit;
5685
5860
  hdr;
5861
+ hdrMode;
5686
5862
  id;
5687
5863
  pageHidden;
5688
5864
  particleCreatedPlugins;
@@ -5690,6 +5866,7 @@
5690
5866
  particlePositionPlugins;
5691
5867
  particleUpdaters;
5692
5868
  particles;
5869
+ peakNits;
5693
5870
  plugins;
5694
5871
  retina;
5695
5872
  shapeDrawers;
@@ -5720,6 +5897,8 @@
5720
5897
  this.id = Symbol(id);
5721
5898
  this.fpsLimit = 120;
5722
5899
  this.hdr = false;
5900
+ this.hdrMode = HdrMode.standard;
5901
+ this.peakNits = 400;
5723
5902
  this.#smooth = false;
5724
5903
  this.#delay = 0;
5725
5904
  this.#duration = 0;
@@ -5859,8 +6038,9 @@
5859
6038
  this.updateActualOptions();
5860
6039
  this.canvas.initBackground();
5861
6040
  this.canvas.resize();
5862
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5863
- this.hdr = hdr;
6041
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6042
+ this.hdrMode = hdrOptions.mode;
6043
+ this.peakNits = hdrOptions.peakNits;
5864
6044
  this.zLayers = zLayers;
5865
6045
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5866
6046
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;