@tsparticles/preset-squares 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) :
@@ -291,6 +291,9 @@
291
291
  })(PixelMode || (PixelMode = {}));
292
292
 
293
293
  const minRadius = 0;
294
+ function isForbiddenKey(key) {
295
+ return key === "__proto__" || key === "constructor" || key === "prototype";
296
+ }
294
297
  function hasMatchMedia() {
295
298
  return typeof matchMedia !== "undefined";
296
299
  }
@@ -366,7 +369,7 @@
366
369
  if (!hasNested) {
367
370
  const sourceDict = source, destDict = destination;
368
371
  for (const key of sourceKeys) {
369
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
372
+ if (isForbiddenKey(key)) {
370
373
  continue;
371
374
  }
372
375
  const v = sourceDict[key];
@@ -377,7 +380,7 @@
377
380
  continue;
378
381
  }
379
382
  for (const key of sourceKeys) {
380
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
383
+ if (isForbiddenKey(key)) {
381
384
  continue;
382
385
  }
383
386
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -793,7 +796,7 @@
793
796
  return this.#domArray;
794
797
  }
795
798
  get version() {
796
- return "4.3.1";
799
+ return "4.4.0";
797
800
  }
798
801
  addEventListener(type, listener) {
799
802
  this.#eventDispatcher.addEventListener(type, listener);
@@ -874,6 +877,10 @@
874
877
  }
875
878
 
876
879
  function initEngine() {
880
+ const existing = globalThis.tsParticles;
881
+ if (existing?.pluginManager) {
882
+ return existing;
883
+ }
877
884
  return new Engine();
878
885
  }
879
886
 
@@ -971,6 +978,15 @@
971
978
  AnimationMode["random"] = "random";
972
979
  })(AnimationMode || (AnimationMode = {}));
973
980
 
981
+ var HdrMode;
982
+ (function (HdrMode) {
983
+ HdrMode["standard"] = "standard";
984
+ HdrMode["natural"] = "natural";
985
+ HdrMode["vivid"] = "vivid";
986
+ HdrMode["cinematic"] = "cinematic";
987
+ HdrMode["dynamic"] = "dynamic";
988
+ })(HdrMode || (HdrMode = {}));
989
+
974
990
  var LimitMode;
975
991
  (function (LimitMode) {
976
992
  LimitMode["delete"] = "delete";
@@ -1226,6 +1242,29 @@
1226
1242
  }
1227
1243
  }
1228
1244
 
1245
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1246
+ class HDROptions extends OptionLoader {
1247
+ enable = true;
1248
+ mode = HdrMode.standard;
1249
+ peakNits = defaultPeakNits;
1250
+ doLoad(data) {
1251
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1252
+ throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1253
+ }
1254
+ if (data.mode !== undefined &&
1255
+ (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1256
+ throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1257
+ }
1258
+ if (data.peakNits !== undefined &&
1259
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1260
+ throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1261
+ }
1262
+ loadProperty(this, "enable", data.enable);
1263
+ loadProperty(this, "mode", data.mode);
1264
+ loadProperty(this, "peakNits", data.peakNits);
1265
+ }
1266
+ }
1267
+
1229
1268
  class ResizeEvent extends OptionLoader {
1230
1269
  delay = 0.5;
1231
1270
  enable = true;
@@ -1669,7 +1708,7 @@
1669
1708
  duration = 0;
1670
1709
  fpsLimit = 120;
1671
1710
  fullScreen;
1672
- hdr = true;
1711
+ hdr;
1673
1712
  key;
1674
1713
  name;
1675
1714
  palette;
@@ -1689,6 +1728,7 @@
1689
1728
  this.#container = container;
1690
1729
  this.background = new Background();
1691
1730
  this.fullScreen = new FullScreen();
1731
+ this.hdr = new HDROptions();
1692
1732
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1693
1733
  this.resize = new ResizeEvent();
1694
1734
  }
@@ -1711,7 +1751,15 @@
1711
1751
  loadProperty(this, "detectRetina", data.detectRetina);
1712
1752
  loadRangeProperty(this, "duration", data.duration);
1713
1753
  loadProperty(this, "fpsLimit", data.fpsLimit);
1714
- loadProperty(this, "hdr", data.hdr);
1754
+ const hdrData = data.hdr;
1755
+ if (isBoolean(hdrData)) {
1756
+ this.hdr.enable = hdrData;
1757
+ this.hdr.mode = HdrMode.standard;
1758
+ this.hdr.peakNits = 400;
1759
+ }
1760
+ else {
1761
+ this.hdr.load(hdrData);
1762
+ }
1715
1763
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1716
1764
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1717
1765
  loadProperty(this, "zLayers", data.zLayers);
@@ -1754,7 +1802,7 @@
1754
1802
  }
1755
1803
  }
1756
1804
 
1757
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1805
+ 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;
1758
1806
  function getCachedStyle(key, generator) {
1759
1807
  let cached = styleCache.get(key);
1760
1808
  if (!cached) {
@@ -1766,6 +1814,42 @@
1766
1814
  }
1767
1815
  return cached;
1768
1816
  }
1817
+ function acesFilmic(x) {
1818
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1819
+ }
1820
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1821
+ switch (mode) {
1822
+ case HdrMode.vivid: {
1823
+ const avg = (r + g + b) / channelCount;
1824
+ return {
1825
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1826
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1827
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1828
+ };
1829
+ }
1830
+ case HdrMode.cinematic: {
1831
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1832
+ return {
1833
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1834
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1835
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1836
+ };
1837
+ }
1838
+ case HdrMode.dynamic: {
1839
+ 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;
1840
+ return {
1841
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1842
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1843
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1844
+ };
1845
+ }
1846
+ case HdrMode.standard:
1847
+ return { b, g, r };
1848
+ case HdrMode.natural:
1849
+ default:
1850
+ return { b, g, r };
1851
+ }
1852
+ }
1769
1853
  function stringToRgba(pluginManager, input) {
1770
1854
  if (!input) {
1771
1855
  return;
@@ -1903,21 +1987,40 @@
1903
1987
  r: getRgbInRangeValue(),
1904
1988
  };
1905
1989
  }
1906
- function getStyleFromRgb(color, hdr, opacity) {
1907
- 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()}`;
1908
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1990
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
1991
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
1992
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
1993
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
1994
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
1909
1995
  }
1910
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1911
- const headroom = peakNits / sdrReferenceWhiteNits;
1912
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
1996
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
1997
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
1998
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
1999
+ }
2000
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2001
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2002
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2003
+ return { b: bNorm, g: gNorm, r: rNorm };
2004
+ }
2005
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2006
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2007
+ }
2008
+ function hdrToneMap(normalized, headroom, middleGray) {
2009
+ if (normalized <= middleGray) {
2010
+ return acesFilmic(normalized);
2011
+ }
2012
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2013
+ return acesFilmic(expanded);
1913
2014
  }
1914
2015
  function getSdrStyleFromRgb(color, opacity) {
1915
2016
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1916
2017
  }
1917
- function getStyleFromHsl(color, hdr, opacity) {
1918
- 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()}`;
2018
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2019
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2020
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2021
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1919
2022
  return getCachedStyle(key, () => hdr
1920
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2023
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1921
2024
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1922
2025
  }
1923
2026
  function getHslFromAnimation(animation) {
@@ -1980,7 +2083,7 @@
1980
2083
  colorValue.velocity = defaultVelocity;
1981
2084
  }
1982
2085
  }
1983
- function updateColorValue(data, decrease, delta, hdr) {
2086
+ function updateColorValue(data, decrease, delta, _hdr) {
1984
2087
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
1985
2088
  if (!data.enable ||
1986
2089
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -1993,7 +2096,7 @@
1993
2096
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
1994
2097
  return;
1995
2098
  }
1996
- 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;
2099
+ 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;
1997
2100
  if (!decrease || data.status === AnimationStatus.increasing) {
1998
2101
  data.value += velocity;
1999
2102
  if (data.value > max) {
@@ -2025,9 +2128,9 @@
2025
2128
  return;
2026
2129
  }
2027
2130
  const { h, s, l } = color;
2028
- updateColorValue(h, false, delta, hdr);
2029
- updateColorValue(s, true, delta, hdr);
2030
- updateColorValue(l, true, delta, hdr);
2131
+ updateColorValue(h, false, delta);
2132
+ updateColorValue(s, true, delta);
2133
+ updateColorValue(l, true, delta);
2031
2134
  }
2032
2135
  function alterHsl(color, type, value) {
2033
2136
  return {
@@ -2245,7 +2348,7 @@
2245
2348
  })(EmitterClickMode || (EmitterClickMode = {}));
2246
2349
 
2247
2350
  async function loadEmittersPluginSimple(engine) {
2248
- engine.checkVersion("4.3.1");
2351
+ engine.checkVersion("4.4.0");
2249
2352
  await engine.pluginManager.register(async (e) => {
2250
2353
  const instancesManager = await getEmittersInstancesManager(e);
2251
2354
  await addEmittersShapesManager(e);
@@ -2293,7 +2396,7 @@
2293
2396
  }
2294
2397
 
2295
2398
  async function loadHexColorPlugin(engine) {
2296
- engine.checkVersion("4.3.1");
2399
+ engine.checkVersion("4.4.0");
2297
2400
  await engine.pluginManager.register(e => {
2298
2401
  e.pluginManager.addColorManager("hex", new HexColorManager());
2299
2402
  });
@@ -2362,7 +2465,7 @@
2362
2465
  }
2363
2466
 
2364
2467
  async function loadPaintUpdater(engine) {
2365
- engine.checkVersion("4.3.1");
2468
+ engine.checkVersion("4.4.0");
2366
2469
  await engine.pluginManager.register(e => {
2367
2470
  e.pluginManager.addParticleUpdater("paint", container => {
2368
2471
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2591,7 +2694,7 @@
2591
2694
  }
2592
2695
 
2593
2696
  async function loadRotateUpdater(engine) {
2594
- engine.checkVersion("4.3.1");
2697
+ engine.checkVersion("4.4.0");
2595
2698
  await engine.pluginManager.register(e => {
2596
2699
  e.pluginManager.addParticleUpdater("rotate", container => {
2597
2700
  return Promise.resolve(new RotateUpdater(container));
@@ -2678,7 +2781,7 @@
2678
2781
  }
2679
2782
 
2680
2783
  async function loadSizeUpdater(engine) {
2681
- engine.checkVersion("4.3.1");
2784
+ engine.checkVersion("4.4.0");
2682
2785
  await engine.pluginManager.register(e => {
2683
2786
  e.pluginManager.addParticleUpdater("size", container => {
2684
2787
  return Promise.resolve(new SizeUpdater(container));
@@ -2702,7 +2805,7 @@
2702
2805
  }
2703
2806
 
2704
2807
  async function loadSquareShape(engine) {
2705
- engine.checkVersion("4.3.1");
2808
+ engine.checkVersion("4.4.0");
2706
2809
  await engine.pluginManager.register(e => {
2707
2810
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
2708
2811
  });
@@ -2896,7 +2999,11 @@
2896
2999
  if (!fColor && !sColor) {
2897
3000
  return;
2898
3001
  }
2899
- 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;
3002
+ 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
3003
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3004
+ : undefined, stroke = sColor
3005
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3006
+ : fill;
2900
3007
  transform.a = transform.b = transform.c = transform.d = undefined;
2901
3008
  colorStyles.fill = fill;
2902
3009
  colorStyles.stroke = stroke;
@@ -3230,7 +3337,9 @@
3230
3337
  if (typeof background.element === "string") {
3231
3338
  if (typeof document !== "undefined") {
3232
3339
  const node = document.querySelector(background.element);
3233
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
3340
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
3341
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
3342
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
3234
3343
  this.#backgroundElement = node;
3235
3344
  }
3236
3345
  else if (node) {
@@ -3241,10 +3350,10 @@
3241
3350
  }
3242
3351
  }
3243
3352
  }
3244
- else if (background.element instanceof HTMLCanvasElement ||
3245
- background.element instanceof OffscreenCanvas ||
3246
- background.element instanceof HTMLVideoElement ||
3247
- background.element instanceof HTMLImageElement) {
3353
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
3354
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
3355
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
3356
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
3248
3357
  this.#backgroundElement = background.element;
3249
3358
  }
3250
3359
  }
@@ -3312,6 +3421,7 @@
3312
3421
  zoom = defaultZoom;
3313
3422
  #container;
3314
3423
  #generated;
3424
+ #hdrMediaListeners;
3315
3425
  #mutationObserver;
3316
3426
  #originalStyle;
3317
3427
  #pluginManager;
@@ -3376,7 +3486,6 @@
3376
3486
  });
3377
3487
  this.resize();
3378
3488
  this.#initStyle();
3379
- this.initBackground();
3380
3489
  this.#safeMutationObserver(obs => {
3381
3490
  const element = this.domElement;
3382
3491
  if (!element || !(element instanceof Node)) {
@@ -3386,6 +3495,8 @@
3386
3495
  });
3387
3496
  this.initPlugins();
3388
3497
  this.#initContext();
3498
+ this.initBackground();
3499
+ this.#initHdrListeners();
3389
3500
  this.render.init();
3390
3501
  }
3391
3502
  initBackground() {
@@ -3395,7 +3506,8 @@
3395
3506
  }
3396
3507
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
3397
3508
  if (color) {
3398
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
3509
+ const hdrOptions = container.actualOptions.hdr;
3510
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
3399
3511
  }
3400
3512
  else {
3401
3513
  elementStyle.backgroundColor = "";
@@ -3492,6 +3604,7 @@
3492
3604
  obs.disconnect();
3493
3605
  });
3494
3606
  this.#mutationObserver = undefined;
3607
+ this.#removeHdrListeners();
3495
3608
  this.render.stop();
3496
3609
  }
3497
3610
  async windowResize() {
@@ -3511,9 +3624,16 @@
3511
3624
  }
3512
3625
  }
3513
3626
  #initContext() {
3514
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
3627
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
3515
3628
  safeMatchMedia("(color-gamut: p3)")?.matches &&
3516
3629
  safeMatchMedia("(dynamic-range: high)")?.matches;
3630
+ container.hdr = canSupportHdr ?? false;
3631
+ container.hdrMode = container.actualOptions.hdr.mode;
3632
+ container.peakNits = container.actualOptions.hdr.peakNits;
3633
+ const renderCanvas = this.renderCanvas;
3634
+ if (!renderCanvas) {
3635
+ return;
3636
+ }
3517
3637
  this.render.setContextSettings({
3518
3638
  alpha: true,
3519
3639
  desynchronized: true,
@@ -3522,11 +3642,47 @@
3522
3642
  ? { colorSpace: "display-p3", colorType: "float16" }
3523
3643
  : { colorSpace: "srgb" }),
3524
3644
  });
3525
- const renderCanvas = this.renderCanvas;
3526
- if (!renderCanvas) {
3527
- return;
3645
+ let context;
3646
+ try {
3647
+ context = renderCanvas.getContext("2d", this.render.settings);
3648
+ }
3649
+ catch {
3650
+ context = null;
3651
+ }
3652
+ if (canSupportHdr && !context) {
3653
+ container.hdr = false;
3654
+ const sdrSettings = {
3655
+ alpha: true,
3656
+ desynchronized: true,
3657
+ willReadFrequently: false,
3658
+ colorSpace: "srgb",
3659
+ };
3660
+ this.render.setContextSettings(sdrSettings);
3661
+ try {
3662
+ context = renderCanvas.getContext("2d", sdrSettings);
3663
+ }
3664
+ catch {
3665
+ context = null;
3666
+ }
3667
+ }
3668
+ this.render.setContext(context);
3669
+ }
3670
+ #initHdrListeners() {
3671
+ this.#removeHdrListeners();
3672
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
3673
+ this.#recreateRenderCanvas();
3674
+ this.#initContext();
3675
+ this.initBackground();
3676
+ }, listeners = [];
3677
+ if (p3Query) {
3678
+ p3Query.addEventListener("change", handleChange);
3679
+ listeners.push({ handler: handleChange, mql: p3Query });
3680
+ }
3681
+ if (hdrQuery) {
3682
+ hdrQuery.addEventListener("change", handleChange);
3683
+ listeners.push({ handler: handleChange, mql: hdrQuery });
3528
3684
  }
3529
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
3685
+ this.#hdrMediaListeners = listeners;
3530
3686
  }
3531
3687
  #initStyle() {
3532
3688
  const element = this.domElement, options = this.#container.actualOptions;
@@ -3550,6 +3706,25 @@
3550
3706
  element.style.setProperty(key, value, "important");
3551
3707
  }
3552
3708
  }
3709
+ #recreateRenderCanvas() {
3710
+ const renderCanvas = this.renderCanvas;
3711
+ if (!renderCanvas) {
3712
+ return;
3713
+ }
3714
+ if (this.domElement) {
3715
+ return;
3716
+ }
3717
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
3718
+ }
3719
+ #removeHdrListeners() {
3720
+ if (!this.#hdrMediaListeners) {
3721
+ return;
3722
+ }
3723
+ for (const { handler, mql } of this.#hdrMediaListeners) {
3724
+ mql.removeEventListener("change", handler);
3725
+ }
3726
+ this.#hdrMediaListeners = undefined;
3727
+ }
3553
3728
  #repairStyle() {
3554
3729
  const element = this.domElement;
3555
3730
  if (!element) {
@@ -3934,9 +4109,9 @@
3934
4109
  }
3935
4110
  getOpacity() {
3936
4111
  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;
3937
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4112
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
3938
4113
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
3939
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4114
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
3940
4115
  return this.#cachedOpacityData;
3941
4116
  }
3942
4117
  getPosition() {
@@ -4791,6 +4966,7 @@
4791
4966
  effectDrawers;
4792
4967
  fpsLimit;
4793
4968
  hdr;
4969
+ hdrMode;
4794
4970
  id;
4795
4971
  pageHidden;
4796
4972
  particleCreatedPlugins;
@@ -4798,6 +4974,7 @@
4798
4974
  particlePositionPlugins;
4799
4975
  particleUpdaters;
4800
4976
  particles;
4977
+ peakNits;
4801
4978
  plugins;
4802
4979
  retina;
4803
4980
  shapeDrawers;
@@ -4828,6 +5005,8 @@
4828
5005
  this.id = Symbol(id);
4829
5006
  this.fpsLimit = 120;
4830
5007
  this.hdr = false;
5008
+ this.hdrMode = HdrMode.standard;
5009
+ this.peakNits = 400;
4831
5010
  this.#smooth = false;
4832
5011
  this.#delay = 0;
4833
5012
  this.#duration = 0;
@@ -4967,8 +5146,9 @@
4967
5146
  this.updateActualOptions();
4968
5147
  this.canvas.initBackground();
4969
5148
  this.canvas.resize();
4970
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
4971
- this.hdr = hdr;
5149
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
5150
+ this.hdrMode = hdrOptions.mode;
5151
+ this.peakNits = hdrOptions.peakNits;
4972
5152
  this.zLayers = zLayers;
4973
5153
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
4974
5154
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;