@tsparticles/preset-fountain 4.3.2 → 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.2 */
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) :
@@ -810,7 +810,7 @@
810
810
  return this.#domArray;
811
811
  }
812
812
  get version() {
813
- return "4.3.2";
813
+ return "4.4.0";
814
814
  }
815
815
  addEventListener(type, listener) {
816
816
  this.#eventDispatcher.addEventListener(type, listener);
@@ -891,6 +891,10 @@
891
891
  }
892
892
 
893
893
  function initEngine() {
894
+ const existing = globalThis.tsParticles;
895
+ if (existing?.pluginManager) {
896
+ return existing;
897
+ }
894
898
  return new Engine();
895
899
  }
896
900
 
@@ -988,6 +992,15 @@
988
992
  AnimationMode["random"] = "random";
989
993
  })(AnimationMode || (AnimationMode = {}));
990
994
 
995
+ var HdrMode;
996
+ (function (HdrMode) {
997
+ HdrMode["standard"] = "standard";
998
+ HdrMode["natural"] = "natural";
999
+ HdrMode["vivid"] = "vivid";
1000
+ HdrMode["cinematic"] = "cinematic";
1001
+ HdrMode["dynamic"] = "dynamic";
1002
+ })(HdrMode || (HdrMode = {}));
1003
+
991
1004
  var LimitMode;
992
1005
  (function (LimitMode) {
993
1006
  LimitMode["delete"] = "delete";
@@ -1243,6 +1256,29 @@
1243
1256
  }
1244
1257
  }
1245
1258
 
1259
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1260
+ class HDROptions extends OptionLoader {
1261
+ enable = true;
1262
+ mode = HdrMode.standard;
1263
+ peakNits = defaultPeakNits;
1264
+ doLoad(data) {
1265
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1266
+ throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1267
+ }
1268
+ if (data.mode !== undefined &&
1269
+ (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1270
+ throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1271
+ }
1272
+ if (data.peakNits !== undefined &&
1273
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1274
+ throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1275
+ }
1276
+ loadProperty(this, "enable", data.enable);
1277
+ loadProperty(this, "mode", data.mode);
1278
+ loadProperty(this, "peakNits", data.peakNits);
1279
+ }
1280
+ }
1281
+
1246
1282
  class ResizeEvent extends OptionLoader {
1247
1283
  delay = 0.5;
1248
1284
  enable = true;
@@ -1686,7 +1722,7 @@
1686
1722
  duration = 0;
1687
1723
  fpsLimit = 120;
1688
1724
  fullScreen;
1689
- hdr = true;
1725
+ hdr;
1690
1726
  key;
1691
1727
  name;
1692
1728
  palette;
@@ -1706,6 +1742,7 @@
1706
1742
  this.#container = container;
1707
1743
  this.background = new Background();
1708
1744
  this.fullScreen = new FullScreen();
1745
+ this.hdr = new HDROptions();
1709
1746
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1710
1747
  this.resize = new ResizeEvent();
1711
1748
  }
@@ -1728,7 +1765,15 @@
1728
1765
  loadProperty(this, "detectRetina", data.detectRetina);
1729
1766
  loadRangeProperty(this, "duration", data.duration);
1730
1767
  loadProperty(this, "fpsLimit", data.fpsLimit);
1731
- loadProperty(this, "hdr", data.hdr);
1768
+ const hdrData = data.hdr;
1769
+ if (isBoolean(hdrData)) {
1770
+ this.hdr.enable = hdrData;
1771
+ this.hdr.mode = HdrMode.standard;
1772
+ this.hdr.peakNits = 400;
1773
+ }
1774
+ else {
1775
+ this.hdr.load(hdrData);
1776
+ }
1732
1777
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1733
1778
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1734
1779
  loadProperty(this, "zLayers", data.zLayers);
@@ -1771,7 +1816,7 @@
1771
1816
  }
1772
1817
  }
1773
1818
 
1774
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1819
+ 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;
1775
1820
  function getCachedStyle(key, generator) {
1776
1821
  let cached = styleCache.get(key);
1777
1822
  if (!cached) {
@@ -1783,6 +1828,42 @@
1783
1828
  }
1784
1829
  return cached;
1785
1830
  }
1831
+ function acesFilmic(x) {
1832
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1833
+ }
1834
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1835
+ switch (mode) {
1836
+ case HdrMode.vivid: {
1837
+ const avg = (r + g + b) / channelCount;
1838
+ return {
1839
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1840
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1841
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1842
+ };
1843
+ }
1844
+ case HdrMode.cinematic: {
1845
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1846
+ return {
1847
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1848
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1849
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1850
+ };
1851
+ }
1852
+ case HdrMode.dynamic: {
1853
+ 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;
1854
+ return {
1855
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1856
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1857
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1858
+ };
1859
+ }
1860
+ case HdrMode.standard:
1861
+ return { b, g, r };
1862
+ case HdrMode.natural:
1863
+ default:
1864
+ return { b, g, r };
1865
+ }
1866
+ }
1786
1867
  function stringToRgba(pluginManager, input) {
1787
1868
  if (!input) {
1788
1869
  return;
@@ -1940,21 +2021,40 @@
1940
2021
  r: getRgbInRangeValue(),
1941
2022
  };
1942
2023
  }
1943
- function getStyleFromRgb(color, hdr, opacity) {
1944
- 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()}`;
1945
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2024
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2025
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2026
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2027
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2028
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
2029
+ }
2030
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
2031
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2032
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
1946
2033
  }
1947
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1948
- const headroom = peakNits / sdrReferenceWhiteNits;
1949
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2034
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2035
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2036
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2037
+ return { b: bNorm, g: gNorm, r: rNorm };
2038
+ }
2039
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2040
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2041
+ }
2042
+ function hdrToneMap(normalized, headroom, middleGray) {
2043
+ if (normalized <= middleGray) {
2044
+ return acesFilmic(normalized);
2045
+ }
2046
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2047
+ return acesFilmic(expanded);
1950
2048
  }
1951
2049
  function getSdrStyleFromRgb(color, opacity) {
1952
2050
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1953
2051
  }
1954
- function getStyleFromHsl(color, hdr, opacity) {
1955
- 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()}`;
2052
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2053
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2054
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2055
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1956
2056
  return getCachedStyle(key, () => hdr
1957
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2057
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1958
2058
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1959
2059
  }
1960
2060
  function getHslFromAnimation(animation) {
@@ -2017,7 +2117,7 @@
2017
2117
  colorValue.velocity = defaultVelocity;
2018
2118
  }
2019
2119
  }
2020
- function updateColorValue(data, decrease, delta, hdr) {
2120
+ function updateColorValue(data, decrease, delta, _hdr) {
2021
2121
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2022
2122
  if (!data.enable ||
2023
2123
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2030,7 +2130,7 @@
2030
2130
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2031
2131
  return;
2032
2132
  }
2033
- 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;
2133
+ 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;
2034
2134
  if (!decrease || data.status === AnimationStatus.increasing) {
2035
2135
  data.value += velocity;
2036
2136
  if (data.value > max) {
@@ -2062,9 +2162,9 @@
2062
2162
  return;
2063
2163
  }
2064
2164
  const { h, s, l } = color;
2065
- updateColorValue(h, false, delta, hdr);
2066
- updateColorValue(s, true, delta, hdr);
2067
- updateColorValue(l, true, delta, hdr);
2165
+ updateColorValue(h, false, delta);
2166
+ updateColorValue(s, true, delta);
2167
+ updateColorValue(l, true, delta);
2068
2168
  }
2069
2169
  function alterHsl(color, type, value) {
2070
2170
  return {
@@ -2114,7 +2214,7 @@
2114
2214
  }
2115
2215
 
2116
2216
  async function loadBlendPlugin(engine) {
2117
- engine.checkVersion("4.3.2");
2217
+ engine.checkVersion("4.4.0");
2118
2218
  await engine.pluginManager.register(e => {
2119
2219
  e.pluginManager.addPlugin(new BlendPlugin());
2120
2220
  });
@@ -2151,7 +2251,7 @@
2151
2251
  }
2152
2252
 
2153
2253
  async function loadCircleShape(engine) {
2154
- engine.checkVersion("4.3.2");
2254
+ engine.checkVersion("4.4.0");
2155
2255
  await engine.pluginManager.register(e => {
2156
2256
  e.pluginManager.addShape(["circle"], () => {
2157
2257
  return Promise.resolve(new CircleDrawer());
@@ -2199,7 +2299,7 @@
2199
2299
  }
2200
2300
 
2201
2301
  async function loadHexColorPlugin(engine) {
2202
- engine.checkVersion("4.3.2");
2302
+ engine.checkVersion("4.4.0");
2203
2303
  await engine.pluginManager.register(e => {
2204
2304
  e.pluginManager.addColorManager("hex", new HexColorManager());
2205
2305
  });
@@ -2252,7 +2352,7 @@
2252
2352
  }
2253
2353
 
2254
2354
  async function loadHslColorPlugin(engine) {
2255
- engine.checkVersion("4.3.2");
2355
+ engine.checkVersion("4.4.0");
2256
2356
  await engine.pluginManager.register(e => {
2257
2357
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2258
2358
  });
@@ -2276,7 +2376,7 @@
2276
2376
  }
2277
2377
 
2278
2378
  async function loadMovePlugin(engine) {
2279
- engine.checkVersion("4.3.2");
2379
+ engine.checkVersion("4.4.0");
2280
2380
  await engine.pluginManager.register(e => {
2281
2381
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2282
2382
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2486,7 +2586,7 @@
2486
2586
  }
2487
2587
 
2488
2588
  async function loadOpacityUpdater(engine) {
2489
- engine.checkVersion("4.3.2");
2589
+ engine.checkVersion("4.4.0");
2490
2590
  await engine.pluginManager.register(e => {
2491
2591
  e.pluginManager.addParticleUpdater("opacity", container => {
2492
2592
  return Promise.resolve(new OpacityUpdater(container));
@@ -2831,7 +2931,7 @@
2831
2931
  }
2832
2932
 
2833
2933
  async function loadOutModesUpdater(engine) {
2834
- engine.checkVersion("4.3.2");
2934
+ engine.checkVersion("4.4.0");
2835
2935
  await engine.pluginManager.register(e => {
2836
2936
  e.pluginManager.addParticleUpdater("outModes", container => {
2837
2937
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2902,7 +3002,7 @@
2902
3002
  }
2903
3003
 
2904
3004
  async function loadPaintUpdater(engine) {
2905
- engine.checkVersion("4.3.2");
3005
+ engine.checkVersion("4.4.0");
2906
3006
  await engine.pluginManager.register(e => {
2907
3007
  e.pluginManager.addParticleUpdater("paint", container => {
2908
3008
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2957,7 +3057,7 @@
2957
3057
  }
2958
3058
 
2959
3059
  async function loadRgbColorPlugin(engine) {
2960
- engine.checkVersion("4.3.2");
3060
+ engine.checkVersion("4.4.0");
2961
3061
  await engine.pluginManager.register(e => {
2962
3062
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2963
3063
  });
@@ -3042,7 +3142,7 @@
3042
3142
  }
3043
3143
 
3044
3144
  async function loadSizeUpdater(engine) {
3045
- engine.checkVersion("4.3.2");
3145
+ engine.checkVersion("4.4.0");
3046
3146
  await engine.pluginManager.register(e => {
3047
3147
  e.pluginManager.addParticleUpdater("size", container => {
3048
3148
  return Promise.resolve(new SizeUpdater(container));
@@ -3051,7 +3151,7 @@
3051
3151
  }
3052
3152
 
3053
3153
  async function loadBasic(engine) {
3054
- engine.checkVersion("4.3.2");
3154
+ engine.checkVersion("4.4.0");
3055
3155
  await engine.pluginManager.register(async (e) => {
3056
3156
  await Promise.all([
3057
3157
  loadBlendPlugin(e),
@@ -3382,7 +3482,7 @@
3382
3482
  }
3383
3483
 
3384
3484
  async function loadDestroyUpdater(engine) {
3385
- engine.checkVersion("4.3.2");
3485
+ engine.checkVersion("4.4.0");
3386
3486
  await engine.pluginManager.register(e => {
3387
3487
  e.pluginManager.addParticleUpdater("destroy", container => {
3388
3488
  return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
@@ -3596,7 +3696,7 @@
3596
3696
  })(EmitterClickMode || (EmitterClickMode = {}));
3597
3697
 
3598
3698
  async function loadEmittersPluginSimple(engine) {
3599
- engine.checkVersion("4.3.2");
3699
+ engine.checkVersion("4.4.0");
3600
3700
  await engine.pluginManager.register(async (e) => {
3601
3701
  const instancesManager = await getEmittersInstancesManager(e);
3602
3702
  await addEmittersShapesManager(e);
@@ -3660,7 +3760,7 @@
3660
3760
  }
3661
3761
 
3662
3762
  async function loadTrailPlugin(engine) {
3663
- engine.checkVersion("4.3.2");
3763
+ engine.checkVersion("4.4.0");
3664
3764
  await engine.pluginManager.register(e => {
3665
3765
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
3666
3766
  });
@@ -3899,7 +3999,11 @@
3899
3999
  if (!fColor && !sColor) {
3900
4000
  return;
3901
4001
  }
3902
- 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;
4002
+ 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
4003
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
4004
+ : undefined, stroke = sColor
4005
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
4006
+ : fill;
3903
4007
  transform.a = transform.b = transform.c = transform.d = undefined;
3904
4008
  colorStyles.fill = fill;
3905
4009
  colorStyles.stroke = stroke;
@@ -4233,7 +4337,9 @@
4233
4337
  if (typeof background.element === "string") {
4234
4338
  if (typeof document !== "undefined") {
4235
4339
  const node = document.querySelector(background.element);
4236
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4340
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4341
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4342
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4237
4343
  this.#backgroundElement = node;
4238
4344
  }
4239
4345
  else if (node) {
@@ -4244,10 +4350,10 @@
4244
4350
  }
4245
4351
  }
4246
4352
  }
4247
- else if (background.element instanceof HTMLCanvasElement ||
4248
- background.element instanceof OffscreenCanvas ||
4249
- background.element instanceof HTMLVideoElement ||
4250
- background.element instanceof HTMLImageElement) {
4353
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4354
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4355
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4356
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4251
4357
  this.#backgroundElement = background.element;
4252
4358
  }
4253
4359
  }
@@ -4315,6 +4421,7 @@
4315
4421
  zoom = defaultZoom;
4316
4422
  #container;
4317
4423
  #generated;
4424
+ #hdrMediaListeners;
4318
4425
  #mutationObserver;
4319
4426
  #originalStyle;
4320
4427
  #pluginManager;
@@ -4379,7 +4486,6 @@
4379
4486
  });
4380
4487
  this.resize();
4381
4488
  this.#initStyle();
4382
- this.initBackground();
4383
4489
  this.#safeMutationObserver(obs => {
4384
4490
  const element = this.domElement;
4385
4491
  if (!element || !(element instanceof Node)) {
@@ -4389,6 +4495,8 @@
4389
4495
  });
4390
4496
  this.initPlugins();
4391
4497
  this.#initContext();
4498
+ this.initBackground();
4499
+ this.#initHdrListeners();
4392
4500
  this.render.init();
4393
4501
  }
4394
4502
  initBackground() {
@@ -4398,7 +4506,8 @@
4398
4506
  }
4399
4507
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4400
4508
  if (color) {
4401
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4509
+ const hdrOptions = container.actualOptions.hdr;
4510
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4402
4511
  }
4403
4512
  else {
4404
4513
  elementStyle.backgroundColor = "";
@@ -4495,6 +4604,7 @@
4495
4604
  obs.disconnect();
4496
4605
  });
4497
4606
  this.#mutationObserver = undefined;
4607
+ this.#removeHdrListeners();
4498
4608
  this.render.stop();
4499
4609
  }
4500
4610
  async windowResize() {
@@ -4514,9 +4624,16 @@
4514
4624
  }
4515
4625
  }
4516
4626
  #initContext() {
4517
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4627
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4518
4628
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4519
4629
  safeMatchMedia("(dynamic-range: high)")?.matches;
4630
+ container.hdr = canSupportHdr ?? false;
4631
+ container.hdrMode = container.actualOptions.hdr.mode;
4632
+ container.peakNits = container.actualOptions.hdr.peakNits;
4633
+ const renderCanvas = this.renderCanvas;
4634
+ if (!renderCanvas) {
4635
+ return;
4636
+ }
4520
4637
  this.render.setContextSettings({
4521
4638
  alpha: true,
4522
4639
  desynchronized: true,
@@ -4525,11 +4642,47 @@
4525
4642
  ? { colorSpace: "display-p3", colorType: "float16" }
4526
4643
  : { colorSpace: "srgb" }),
4527
4644
  });
4528
- const renderCanvas = this.renderCanvas;
4529
- if (!renderCanvas) {
4530
- return;
4645
+ let context;
4646
+ try {
4647
+ context = renderCanvas.getContext("2d", this.render.settings);
4648
+ }
4649
+ catch {
4650
+ context = null;
4651
+ }
4652
+ if (canSupportHdr && !context) {
4653
+ container.hdr = false;
4654
+ const sdrSettings = {
4655
+ alpha: true,
4656
+ desynchronized: true,
4657
+ willReadFrequently: false,
4658
+ colorSpace: "srgb",
4659
+ };
4660
+ this.render.setContextSettings(sdrSettings);
4661
+ try {
4662
+ context = renderCanvas.getContext("2d", sdrSettings);
4663
+ }
4664
+ catch {
4665
+ context = null;
4666
+ }
4667
+ }
4668
+ this.render.setContext(context);
4669
+ }
4670
+ #initHdrListeners() {
4671
+ this.#removeHdrListeners();
4672
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4673
+ this.#recreateRenderCanvas();
4674
+ this.#initContext();
4675
+ this.initBackground();
4676
+ }, listeners = [];
4677
+ if (p3Query) {
4678
+ p3Query.addEventListener("change", handleChange);
4679
+ listeners.push({ handler: handleChange, mql: p3Query });
4680
+ }
4681
+ if (hdrQuery) {
4682
+ hdrQuery.addEventListener("change", handleChange);
4683
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4531
4684
  }
4532
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4685
+ this.#hdrMediaListeners = listeners;
4533
4686
  }
4534
4687
  #initStyle() {
4535
4688
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4553,6 +4706,25 @@
4553
4706
  element.style.setProperty(key, value, "important");
4554
4707
  }
4555
4708
  }
4709
+ #recreateRenderCanvas() {
4710
+ const renderCanvas = this.renderCanvas;
4711
+ if (!renderCanvas) {
4712
+ return;
4713
+ }
4714
+ if (this.domElement) {
4715
+ return;
4716
+ }
4717
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4718
+ }
4719
+ #removeHdrListeners() {
4720
+ if (!this.#hdrMediaListeners) {
4721
+ return;
4722
+ }
4723
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4724
+ mql.removeEventListener("change", handler);
4725
+ }
4726
+ this.#hdrMediaListeners = undefined;
4727
+ }
4556
4728
  #repairStyle() {
4557
4729
  const element = this.domElement;
4558
4730
  if (!element) {
@@ -4937,9 +5109,9 @@
4937
5109
  }
4938
5110
  getOpacity() {
4939
5111
  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;
4940
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5112
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4941
5113
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4942
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5114
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4943
5115
  return this.#cachedOpacityData;
4944
5116
  }
4945
5117
  getPosition() {
@@ -5794,6 +5966,7 @@
5794
5966
  effectDrawers;
5795
5967
  fpsLimit;
5796
5968
  hdr;
5969
+ hdrMode;
5797
5970
  id;
5798
5971
  pageHidden;
5799
5972
  particleCreatedPlugins;
@@ -5801,6 +5974,7 @@
5801
5974
  particlePositionPlugins;
5802
5975
  particleUpdaters;
5803
5976
  particles;
5977
+ peakNits;
5804
5978
  plugins;
5805
5979
  retina;
5806
5980
  shapeDrawers;
@@ -5831,6 +6005,8 @@
5831
6005
  this.id = Symbol(id);
5832
6006
  this.fpsLimit = 120;
5833
6007
  this.hdr = false;
6008
+ this.hdrMode = HdrMode.standard;
6009
+ this.peakNits = 400;
5834
6010
  this.#smooth = false;
5835
6011
  this.#delay = 0;
5836
6012
  this.#duration = 0;
@@ -5970,8 +6146,9 @@
5970
6146
  this.updateActualOptions();
5971
6147
  this.canvas.initBackground();
5972
6148
  this.canvas.resize();
5973
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5974
- this.hdr = hdr;
6149
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6150
+ this.hdrMode = hdrOptions.mode;
6151
+ this.peakNits = hdrOptions.peakNits;
5975
6152
  this.zLayers = zLayers;
5976
6153
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5977
6154
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6559,7 +6736,7 @@
6559
6736
  let handled = false;
6560
6737
  const canvas = container.canvas;
6561
6738
  if (trailFill.color) {
6562
- canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity));
6739
+ canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity, container.peakNits, container.hdrMode));
6563
6740
  handled = true;
6564
6741
  }
6565
6742
  else if (trailFill.image) {