@tsparticles/preset-matrix 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),
@@ -3267,7 +3370,7 @@
3267
3370
  }
3268
3371
 
3269
3372
  async function loadMatrixShape(engine) {
3270
- engine.checkVersion("4.3.1");
3373
+ engine.checkVersion("4.4.0");
3271
3374
  await engine.pluginManager.register(e => {
3272
3375
  e.pluginManager.addShape(["matrix"], () => Promise.resolve(new MatrixDrawer()));
3273
3376
  });
@@ -3312,7 +3415,7 @@
3312
3415
  }
3313
3416
 
3314
3417
  async function loadPoissonDiscPlugin(engine) {
3315
- engine.checkVersion("4.3.1");
3418
+ engine.checkVersion("4.4.0");
3316
3419
  await engine.pluginManager.register(e => {
3317
3420
  e.pluginManager.addPlugin(new PoissonDiscPlugin());
3318
3421
  });
@@ -3337,7 +3440,7 @@
3337
3440
  }
3338
3441
  context.save();
3339
3442
  context.shadowBlur = shadowParticle.shadowBlur ?? defaultShadowBlur;
3340
- context.shadowColor = getStyleFromRgb(shadowColor, container.hdr);
3443
+ context.shadowColor = getStyleFromRgb(shadowColor, container.hdr, undefined, container.peakNits, container.hdrMode);
3341
3444
  context.shadowOffsetX = shadowOffset?.x ?? defaultShadowOffsetValue;
3342
3445
  context.shadowOffsetY = shadowOffset?.y ?? defaultShadowOffsetValue;
3343
3446
  }
@@ -3350,7 +3453,7 @@
3350
3453
  }
3351
3454
 
3352
3455
  async function loadShadowEffect(engine) {
3353
- engine.checkVersion("4.3.1");
3456
+ engine.checkVersion("4.4.0");
3354
3457
  await engine.pluginManager.register(e => {
3355
3458
  e.pluginManager.addEffect("shadow", container => {
3356
3459
  return Promise.resolve(new ShadowDrawer(e.pluginManager, container));
@@ -3414,7 +3517,7 @@
3414
3517
  }
3415
3518
 
3416
3519
  async function loadTrailPlugin(engine) {
3417
- engine.checkVersion("4.3.1");
3520
+ engine.checkVersion("4.4.0");
3418
3521
  await engine.pluginManager.register(e => {
3419
3522
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
3420
3523
  });
@@ -3634,7 +3737,11 @@
3634
3737
  if (!fColor && !sColor) {
3635
3738
  return;
3636
3739
  }
3637
- 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;
3740
+ 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
3741
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3742
+ : undefined, stroke = sColor
3743
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3744
+ : fill;
3638
3745
  transform.a = transform.b = transform.c = transform.d = undefined;
3639
3746
  colorStyles.fill = fill;
3640
3747
  colorStyles.stroke = stroke;
@@ -3968,7 +4075,9 @@
3968
4075
  if (typeof background.element === "string") {
3969
4076
  if (typeof document !== "undefined") {
3970
4077
  const node = document.querySelector(background.element);
3971
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4078
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4079
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4080
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
3972
4081
  this.#backgroundElement = node;
3973
4082
  }
3974
4083
  else if (node) {
@@ -3979,10 +4088,10 @@
3979
4088
  }
3980
4089
  }
3981
4090
  }
3982
- else if (background.element instanceof HTMLCanvasElement ||
3983
- background.element instanceof OffscreenCanvas ||
3984
- background.element instanceof HTMLVideoElement ||
3985
- background.element instanceof HTMLImageElement) {
4091
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4092
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4093
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4094
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
3986
4095
  this.#backgroundElement = background.element;
3987
4096
  }
3988
4097
  }
@@ -4050,6 +4159,7 @@
4050
4159
  zoom = defaultZoom;
4051
4160
  #container;
4052
4161
  #generated;
4162
+ #hdrMediaListeners;
4053
4163
  #mutationObserver;
4054
4164
  #originalStyle;
4055
4165
  #pluginManager;
@@ -4114,7 +4224,6 @@
4114
4224
  });
4115
4225
  this.resize();
4116
4226
  this.#initStyle();
4117
- this.initBackground();
4118
4227
  this.#safeMutationObserver(obs => {
4119
4228
  const element = this.domElement;
4120
4229
  if (!element || !(element instanceof Node)) {
@@ -4124,6 +4233,8 @@
4124
4233
  });
4125
4234
  this.initPlugins();
4126
4235
  this.#initContext();
4236
+ this.initBackground();
4237
+ this.#initHdrListeners();
4127
4238
  this.render.init();
4128
4239
  }
4129
4240
  initBackground() {
@@ -4133,7 +4244,8 @@
4133
4244
  }
4134
4245
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4135
4246
  if (color) {
4136
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4247
+ const hdrOptions = container.actualOptions.hdr;
4248
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4137
4249
  }
4138
4250
  else {
4139
4251
  elementStyle.backgroundColor = "";
@@ -4230,6 +4342,7 @@
4230
4342
  obs.disconnect();
4231
4343
  });
4232
4344
  this.#mutationObserver = undefined;
4345
+ this.#removeHdrListeners();
4233
4346
  this.render.stop();
4234
4347
  }
4235
4348
  async windowResize() {
@@ -4249,9 +4362,16 @@
4249
4362
  }
4250
4363
  }
4251
4364
  #initContext() {
4252
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4365
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4253
4366
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4254
4367
  safeMatchMedia("(dynamic-range: high)")?.matches;
4368
+ container.hdr = canSupportHdr ?? false;
4369
+ container.hdrMode = container.actualOptions.hdr.mode;
4370
+ container.peakNits = container.actualOptions.hdr.peakNits;
4371
+ const renderCanvas = this.renderCanvas;
4372
+ if (!renderCanvas) {
4373
+ return;
4374
+ }
4255
4375
  this.render.setContextSettings({
4256
4376
  alpha: true,
4257
4377
  desynchronized: true,
@@ -4260,11 +4380,47 @@
4260
4380
  ? { colorSpace: "display-p3", colorType: "float16" }
4261
4381
  : { colorSpace: "srgb" }),
4262
4382
  });
4263
- const renderCanvas = this.renderCanvas;
4264
- if (!renderCanvas) {
4265
- return;
4383
+ let context;
4384
+ try {
4385
+ context = renderCanvas.getContext("2d", this.render.settings);
4386
+ }
4387
+ catch {
4388
+ context = null;
4389
+ }
4390
+ if (canSupportHdr && !context) {
4391
+ container.hdr = false;
4392
+ const sdrSettings = {
4393
+ alpha: true,
4394
+ desynchronized: true,
4395
+ willReadFrequently: false,
4396
+ colorSpace: "srgb",
4397
+ };
4398
+ this.render.setContextSettings(sdrSettings);
4399
+ try {
4400
+ context = renderCanvas.getContext("2d", sdrSettings);
4401
+ }
4402
+ catch {
4403
+ context = null;
4404
+ }
4405
+ }
4406
+ this.render.setContext(context);
4407
+ }
4408
+ #initHdrListeners() {
4409
+ this.#removeHdrListeners();
4410
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4411
+ this.#recreateRenderCanvas();
4412
+ this.#initContext();
4413
+ this.initBackground();
4414
+ }, listeners = [];
4415
+ if (p3Query) {
4416
+ p3Query.addEventListener("change", handleChange);
4417
+ listeners.push({ handler: handleChange, mql: p3Query });
4418
+ }
4419
+ if (hdrQuery) {
4420
+ hdrQuery.addEventListener("change", handleChange);
4421
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4266
4422
  }
4267
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4423
+ this.#hdrMediaListeners = listeners;
4268
4424
  }
4269
4425
  #initStyle() {
4270
4426
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4288,6 +4444,25 @@
4288
4444
  element.style.setProperty(key, value, "important");
4289
4445
  }
4290
4446
  }
4447
+ #recreateRenderCanvas() {
4448
+ const renderCanvas = this.renderCanvas;
4449
+ if (!renderCanvas) {
4450
+ return;
4451
+ }
4452
+ if (this.domElement) {
4453
+ return;
4454
+ }
4455
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4456
+ }
4457
+ #removeHdrListeners() {
4458
+ if (!this.#hdrMediaListeners) {
4459
+ return;
4460
+ }
4461
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4462
+ mql.removeEventListener("change", handler);
4463
+ }
4464
+ this.#hdrMediaListeners = undefined;
4465
+ }
4291
4466
  #repairStyle() {
4292
4467
  const element = this.domElement;
4293
4468
  if (!element) {
@@ -4672,9 +4847,9 @@
4672
4847
  }
4673
4848
  getOpacity() {
4674
4849
  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;
4675
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4850
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4676
4851
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4677
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4852
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4678
4853
  return this.#cachedOpacityData;
4679
4854
  }
4680
4855
  getPosition() {
@@ -5529,6 +5704,7 @@
5529
5704
  effectDrawers;
5530
5705
  fpsLimit;
5531
5706
  hdr;
5707
+ hdrMode;
5532
5708
  id;
5533
5709
  pageHidden;
5534
5710
  particleCreatedPlugins;
@@ -5536,6 +5712,7 @@
5536
5712
  particlePositionPlugins;
5537
5713
  particleUpdaters;
5538
5714
  particles;
5715
+ peakNits;
5539
5716
  plugins;
5540
5717
  retina;
5541
5718
  shapeDrawers;
@@ -5566,6 +5743,8 @@
5566
5743
  this.id = Symbol(id);
5567
5744
  this.fpsLimit = 120;
5568
5745
  this.hdr = false;
5746
+ this.hdrMode = HdrMode.standard;
5747
+ this.peakNits = 400;
5569
5748
  this.#smooth = false;
5570
5749
  this.#delay = 0;
5571
5750
  this.#duration = 0;
@@ -5705,8 +5884,9 @@
5705
5884
  this.updateActualOptions();
5706
5885
  this.canvas.initBackground();
5707
5886
  this.canvas.resize();
5708
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5709
- this.hdr = hdr;
5887
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
5888
+ this.hdrMode = hdrOptions.mode;
5889
+ this.peakNits = hdrOptions.peakNits;
5710
5890
  this.zLayers = zLayers;
5711
5891
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5712
5892
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6217,7 +6397,7 @@
6217
6397
  let handled = false;
6218
6398
  const canvas = container.canvas;
6219
6399
  if (trailFill.color) {
6220
- canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity));
6400
+ canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity, container.peakNits, container.hdrMode));
6221
6401
  handled = true;
6222
6402
  }
6223
6403
  else if (trailFill.image) {