@tsparticles/preset-hyperspace 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) :
@@ -305,6 +305,9 @@
305
305
  })(PixelMode || (PixelMode = {}));
306
306
 
307
307
  const minRadius = 0;
308
+ function isForbiddenKey(key) {
309
+ return key === "__proto__" || key === "constructor" || key === "prototype";
310
+ }
308
311
  function hasMatchMedia() {
309
312
  return typeof matchMedia !== "undefined";
310
313
  }
@@ -380,7 +383,7 @@
380
383
  if (!hasNested) {
381
384
  const sourceDict = source, destDict = destination;
382
385
  for (const key of sourceKeys) {
383
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
386
+ if (isForbiddenKey(key)) {
384
387
  continue;
385
388
  }
386
389
  const v = sourceDict[key];
@@ -391,7 +394,7 @@
391
394
  continue;
392
395
  }
393
396
  for (const key of sourceKeys) {
394
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
397
+ if (isForbiddenKey(key)) {
395
398
  continue;
396
399
  }
397
400
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -807,7 +810,7 @@
807
810
  return this.#domArray;
808
811
  }
809
812
  get version() {
810
- return "4.3.1";
813
+ return "4.4.0";
811
814
  }
812
815
  addEventListener(type, listener) {
813
816
  this.#eventDispatcher.addEventListener(type, listener);
@@ -888,6 +891,10 @@
888
891
  }
889
892
 
890
893
  function initEngine() {
894
+ const existing = globalThis.tsParticles;
895
+ if (existing?.pluginManager) {
896
+ return existing;
897
+ }
891
898
  return new Engine();
892
899
  }
893
900
 
@@ -985,6 +992,15 @@
985
992
  AnimationMode["random"] = "random";
986
993
  })(AnimationMode || (AnimationMode = {}));
987
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
+
988
1004
  var LimitMode;
989
1005
  (function (LimitMode) {
990
1006
  LimitMode["delete"] = "delete";
@@ -1240,6 +1256,29 @@
1240
1256
  }
1241
1257
  }
1242
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
+
1243
1282
  class ResizeEvent extends OptionLoader {
1244
1283
  delay = 0.5;
1245
1284
  enable = true;
@@ -1683,7 +1722,7 @@
1683
1722
  duration = 0;
1684
1723
  fpsLimit = 120;
1685
1724
  fullScreen;
1686
- hdr = true;
1725
+ hdr;
1687
1726
  key;
1688
1727
  name;
1689
1728
  palette;
@@ -1703,6 +1742,7 @@
1703
1742
  this.#container = container;
1704
1743
  this.background = new Background();
1705
1744
  this.fullScreen = new FullScreen();
1745
+ this.hdr = new HDROptions();
1706
1746
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1707
1747
  this.resize = new ResizeEvent();
1708
1748
  }
@@ -1725,7 +1765,15 @@
1725
1765
  loadProperty(this, "detectRetina", data.detectRetina);
1726
1766
  loadRangeProperty(this, "duration", data.duration);
1727
1767
  loadProperty(this, "fpsLimit", data.fpsLimit);
1728
- 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
+ }
1729
1777
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1730
1778
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1731
1779
  loadProperty(this, "zLayers", data.zLayers);
@@ -1768,7 +1816,7 @@
1768
1816
  }
1769
1817
  }
1770
1818
 
1771
- 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;
1772
1820
  function getCachedStyle(key, generator) {
1773
1821
  let cached = styleCache.get(key);
1774
1822
  if (!cached) {
@@ -1780,6 +1828,42 @@
1780
1828
  }
1781
1829
  return cached;
1782
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
+ }
1783
1867
  function stringToRgba(pluginManager, input) {
1784
1868
  if (!input) {
1785
1869
  return;
@@ -1937,21 +2021,40 @@
1937
2021
  r: getRgbInRangeValue(),
1938
2022
  };
1939
2023
  }
1940
- function getStyleFromRgb(color, hdr, opacity) {
1941
- 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()}`;
1942
- 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));
1943
2029
  }
1944
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1945
- const headroom = peakNits / sdrReferenceWhiteNits;
1946
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
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()})`;
2033
+ }
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);
1947
2048
  }
1948
2049
  function getSdrStyleFromRgb(color, opacity) {
1949
2050
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1950
2051
  }
1951
- function getStyleFromHsl(color, hdr, opacity) {
1952
- 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()}`;
1953
2056
  return getCachedStyle(key, () => hdr
1954
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2057
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1955
2058
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1956
2059
  }
1957
2060
  function getHslFromAnimation(animation) {
@@ -2014,7 +2117,7 @@
2014
2117
  colorValue.velocity = defaultVelocity;
2015
2118
  }
2016
2119
  }
2017
- function updateColorValue(data, decrease, delta, hdr) {
2120
+ function updateColorValue(data, decrease, delta, _hdr) {
2018
2121
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2019
2122
  if (!data.enable ||
2020
2123
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2027,7 +2130,7 @@
2027
2130
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2028
2131
  return;
2029
2132
  }
2030
- 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;
2031
2134
  if (!decrease || data.status === AnimationStatus.increasing) {
2032
2135
  data.value += velocity;
2033
2136
  if (data.value > max) {
@@ -2059,9 +2162,9 @@
2059
2162
  return;
2060
2163
  }
2061
2164
  const { h, s, l } = color;
2062
- updateColorValue(h, false, delta, hdr);
2063
- updateColorValue(s, true, delta, hdr);
2064
- updateColorValue(l, true, delta, hdr);
2165
+ updateColorValue(h, false, delta);
2166
+ updateColorValue(s, true, delta);
2167
+ updateColorValue(l, true, delta);
2065
2168
  }
2066
2169
  function alterHsl(color, type, value) {
2067
2170
  return {
@@ -2111,7 +2214,7 @@
2111
2214
  }
2112
2215
 
2113
2216
  async function loadBlendPlugin(engine) {
2114
- engine.checkVersion("4.3.1");
2217
+ engine.checkVersion("4.4.0");
2115
2218
  await engine.pluginManager.register(e => {
2116
2219
  e.pluginManager.addPlugin(new BlendPlugin());
2117
2220
  });
@@ -2148,7 +2251,7 @@
2148
2251
  }
2149
2252
 
2150
2253
  async function loadCircleShape(engine) {
2151
- engine.checkVersion("4.3.1");
2254
+ engine.checkVersion("4.4.0");
2152
2255
  await engine.pluginManager.register(e => {
2153
2256
  e.pluginManager.addShape(["circle"], () => {
2154
2257
  return Promise.resolve(new CircleDrawer());
@@ -2196,7 +2299,7 @@
2196
2299
  }
2197
2300
 
2198
2301
  async function loadHexColorPlugin(engine) {
2199
- engine.checkVersion("4.3.1");
2302
+ engine.checkVersion("4.4.0");
2200
2303
  await engine.pluginManager.register(e => {
2201
2304
  e.pluginManager.addColorManager("hex", new HexColorManager());
2202
2305
  });
@@ -2249,7 +2352,7 @@
2249
2352
  }
2250
2353
 
2251
2354
  async function loadHslColorPlugin(engine) {
2252
- engine.checkVersion("4.3.1");
2355
+ engine.checkVersion("4.4.0");
2253
2356
  await engine.pluginManager.register(e => {
2254
2357
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2255
2358
  });
@@ -2273,7 +2376,7 @@
2273
2376
  }
2274
2377
 
2275
2378
  async function loadMovePlugin(engine) {
2276
- engine.checkVersion("4.3.1");
2379
+ engine.checkVersion("4.4.0");
2277
2380
  await engine.pluginManager.register(e => {
2278
2381
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2279
2382
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2483,7 +2586,7 @@
2483
2586
  }
2484
2587
 
2485
2588
  async function loadOpacityUpdater(engine) {
2486
- engine.checkVersion("4.3.1");
2589
+ engine.checkVersion("4.4.0");
2487
2590
  await engine.pluginManager.register(e => {
2488
2591
  e.pluginManager.addParticleUpdater("opacity", container => {
2489
2592
  return Promise.resolve(new OpacityUpdater(container));
@@ -2828,7 +2931,7 @@
2828
2931
  }
2829
2932
 
2830
2933
  async function loadOutModesUpdater(engine) {
2831
- engine.checkVersion("4.3.1");
2934
+ engine.checkVersion("4.4.0");
2832
2935
  await engine.pluginManager.register(e => {
2833
2936
  e.pluginManager.addParticleUpdater("outModes", container => {
2834
2937
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2899,7 +3002,7 @@
2899
3002
  }
2900
3003
 
2901
3004
  async function loadPaintUpdater(engine) {
2902
- engine.checkVersion("4.3.1");
3005
+ engine.checkVersion("4.4.0");
2903
3006
  await engine.pluginManager.register(e => {
2904
3007
  e.pluginManager.addParticleUpdater("paint", container => {
2905
3008
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2954,7 +3057,7 @@
2954
3057
  }
2955
3058
 
2956
3059
  async function loadRgbColorPlugin(engine) {
2957
- engine.checkVersion("4.3.1");
3060
+ engine.checkVersion("4.4.0");
2958
3061
  await engine.pluginManager.register(e => {
2959
3062
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2960
3063
  });
@@ -3039,7 +3142,7 @@
3039
3142
  }
3040
3143
 
3041
3144
  async function loadSizeUpdater(engine) {
3042
- engine.checkVersion("4.3.1");
3145
+ engine.checkVersion("4.4.0");
3043
3146
  await engine.pluginManager.register(e => {
3044
3147
  e.pluginManager.addParticleUpdater("size", container => {
3045
3148
  return Promise.resolve(new SizeUpdater(container));
@@ -3048,7 +3151,7 @@
3048
3151
  }
3049
3152
 
3050
3153
  async function loadBasic(engine) {
3051
- engine.checkVersion("4.3.1");
3154
+ engine.checkVersion("4.4.0");
3052
3155
  await engine.pluginManager.register(async (e) => {
3053
3156
  await Promise.all([
3054
3157
  loadBlendPlugin(e),
@@ -3288,7 +3391,7 @@
3288
3391
  })(EmitterClickMode || (EmitterClickMode = {}));
3289
3392
 
3290
3393
  async function loadEmittersPluginSimple(engine) {
3291
- engine.checkVersion("4.3.1");
3394
+ engine.checkVersion("4.4.0");
3292
3395
  await engine.pluginManager.register(async (e) => {
3293
3396
  const instancesManager = await getEmittersInstancesManager(e);
3294
3397
  await addEmittersShapesManager(e);
@@ -3376,7 +3479,7 @@
3376
3479
  }
3377
3480
 
3378
3481
  async function loadEmittersShapeSquare(engine) {
3379
- engine.checkVersion("4.3.1");
3482
+ engine.checkVersion("4.4.0");
3380
3483
  await engine.pluginManager.register((e) => {
3381
3484
  ensureEmittersPluginLoaded(e);
3382
3485
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -3520,7 +3623,7 @@
3520
3623
  }
3521
3624
 
3522
3625
  async function loadLifeUpdater(engine) {
3523
- engine.checkVersion("4.3.1");
3626
+ engine.checkVersion("4.4.0");
3524
3627
  await engine.pluginManager.register(e => {
3525
3628
  e.pluginManager.addParticleUpdater("life", container => {
3526
3629
  return Promise.resolve(new LifeUpdater(container));
@@ -3584,7 +3687,7 @@
3584
3687
  }
3585
3688
 
3586
3689
  async function loadTrailPlugin(engine) {
3587
- engine.checkVersion("4.3.1");
3690
+ engine.checkVersion("4.4.0");
3588
3691
  await engine.pluginManager.register(e => {
3589
3692
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
3590
3693
  });
@@ -3791,7 +3894,11 @@
3791
3894
  if (!fColor && !sColor) {
3792
3895
  return;
3793
3896
  }
3794
- 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;
3897
+ 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
3898
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3899
+ : undefined, stroke = sColor
3900
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3901
+ : fill;
3795
3902
  transform.a = transform.b = transform.c = transform.d = undefined;
3796
3903
  colorStyles.fill = fill;
3797
3904
  colorStyles.stroke = stroke;
@@ -4125,7 +4232,9 @@
4125
4232
  if (typeof background.element === "string") {
4126
4233
  if (typeof document !== "undefined") {
4127
4234
  const node = document.querySelector(background.element);
4128
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4235
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4236
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4237
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4129
4238
  this.#backgroundElement = node;
4130
4239
  }
4131
4240
  else if (node) {
@@ -4136,10 +4245,10 @@
4136
4245
  }
4137
4246
  }
4138
4247
  }
4139
- else if (background.element instanceof HTMLCanvasElement ||
4140
- background.element instanceof OffscreenCanvas ||
4141
- background.element instanceof HTMLVideoElement ||
4142
- background.element instanceof HTMLImageElement) {
4248
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4249
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4250
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4251
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4143
4252
  this.#backgroundElement = background.element;
4144
4253
  }
4145
4254
  }
@@ -4207,6 +4316,7 @@
4207
4316
  zoom = defaultZoom;
4208
4317
  #container;
4209
4318
  #generated;
4319
+ #hdrMediaListeners;
4210
4320
  #mutationObserver;
4211
4321
  #originalStyle;
4212
4322
  #pluginManager;
@@ -4271,7 +4381,6 @@
4271
4381
  });
4272
4382
  this.resize();
4273
4383
  this.#initStyle();
4274
- this.initBackground();
4275
4384
  this.#safeMutationObserver(obs => {
4276
4385
  const element = this.domElement;
4277
4386
  if (!element || !(element instanceof Node)) {
@@ -4281,6 +4390,8 @@
4281
4390
  });
4282
4391
  this.initPlugins();
4283
4392
  this.#initContext();
4393
+ this.initBackground();
4394
+ this.#initHdrListeners();
4284
4395
  this.render.init();
4285
4396
  }
4286
4397
  initBackground() {
@@ -4290,7 +4401,8 @@
4290
4401
  }
4291
4402
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4292
4403
  if (color) {
4293
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4404
+ const hdrOptions = container.actualOptions.hdr;
4405
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4294
4406
  }
4295
4407
  else {
4296
4408
  elementStyle.backgroundColor = "";
@@ -4387,6 +4499,7 @@
4387
4499
  obs.disconnect();
4388
4500
  });
4389
4501
  this.#mutationObserver = undefined;
4502
+ this.#removeHdrListeners();
4390
4503
  this.render.stop();
4391
4504
  }
4392
4505
  async windowResize() {
@@ -4406,9 +4519,16 @@
4406
4519
  }
4407
4520
  }
4408
4521
  #initContext() {
4409
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4522
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4410
4523
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4411
4524
  safeMatchMedia("(dynamic-range: high)")?.matches;
4525
+ container.hdr = canSupportHdr ?? false;
4526
+ container.hdrMode = container.actualOptions.hdr.mode;
4527
+ container.peakNits = container.actualOptions.hdr.peakNits;
4528
+ const renderCanvas = this.renderCanvas;
4529
+ if (!renderCanvas) {
4530
+ return;
4531
+ }
4412
4532
  this.render.setContextSettings({
4413
4533
  alpha: true,
4414
4534
  desynchronized: true,
@@ -4417,11 +4537,47 @@
4417
4537
  ? { colorSpace: "display-p3", colorType: "float16" }
4418
4538
  : { colorSpace: "srgb" }),
4419
4539
  });
4420
- const renderCanvas = this.renderCanvas;
4421
- if (!renderCanvas) {
4422
- return;
4540
+ let context;
4541
+ try {
4542
+ context = renderCanvas.getContext("2d", this.render.settings);
4543
+ }
4544
+ catch {
4545
+ context = null;
4546
+ }
4547
+ if (canSupportHdr && !context) {
4548
+ container.hdr = false;
4549
+ const sdrSettings = {
4550
+ alpha: true,
4551
+ desynchronized: true,
4552
+ willReadFrequently: false,
4553
+ colorSpace: "srgb",
4554
+ };
4555
+ this.render.setContextSettings(sdrSettings);
4556
+ try {
4557
+ context = renderCanvas.getContext("2d", sdrSettings);
4558
+ }
4559
+ catch {
4560
+ context = null;
4561
+ }
4562
+ }
4563
+ this.render.setContext(context);
4564
+ }
4565
+ #initHdrListeners() {
4566
+ this.#removeHdrListeners();
4567
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4568
+ this.#recreateRenderCanvas();
4569
+ this.#initContext();
4570
+ this.initBackground();
4571
+ }, listeners = [];
4572
+ if (p3Query) {
4573
+ p3Query.addEventListener("change", handleChange);
4574
+ listeners.push({ handler: handleChange, mql: p3Query });
4575
+ }
4576
+ if (hdrQuery) {
4577
+ hdrQuery.addEventListener("change", handleChange);
4578
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4423
4579
  }
4424
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4580
+ this.#hdrMediaListeners = listeners;
4425
4581
  }
4426
4582
  #initStyle() {
4427
4583
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4445,6 +4601,25 @@
4445
4601
  element.style.setProperty(key, value, "important");
4446
4602
  }
4447
4603
  }
4604
+ #recreateRenderCanvas() {
4605
+ const renderCanvas = this.renderCanvas;
4606
+ if (!renderCanvas) {
4607
+ return;
4608
+ }
4609
+ if (this.domElement) {
4610
+ return;
4611
+ }
4612
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4613
+ }
4614
+ #removeHdrListeners() {
4615
+ if (!this.#hdrMediaListeners) {
4616
+ return;
4617
+ }
4618
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4619
+ mql.removeEventListener("change", handler);
4620
+ }
4621
+ this.#hdrMediaListeners = undefined;
4622
+ }
4448
4623
  #repairStyle() {
4449
4624
  const element = this.domElement;
4450
4625
  if (!element) {
@@ -4829,9 +5004,9 @@
4829
5004
  }
4830
5005
  getOpacity() {
4831
5006
  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;
4832
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5007
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4833
5008
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4834
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5009
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4835
5010
  return this.#cachedOpacityData;
4836
5011
  }
4837
5012
  getPosition() {
@@ -5686,6 +5861,7 @@
5686
5861
  effectDrawers;
5687
5862
  fpsLimit;
5688
5863
  hdr;
5864
+ hdrMode;
5689
5865
  id;
5690
5866
  pageHidden;
5691
5867
  particleCreatedPlugins;
@@ -5693,6 +5869,7 @@
5693
5869
  particlePositionPlugins;
5694
5870
  particleUpdaters;
5695
5871
  particles;
5872
+ peakNits;
5696
5873
  plugins;
5697
5874
  retina;
5698
5875
  shapeDrawers;
@@ -5723,6 +5900,8 @@
5723
5900
  this.id = Symbol(id);
5724
5901
  this.fpsLimit = 120;
5725
5902
  this.hdr = false;
5903
+ this.hdrMode = HdrMode.standard;
5904
+ this.peakNits = 400;
5726
5905
  this.#smooth = false;
5727
5906
  this.#delay = 0;
5728
5907
  this.#duration = 0;
@@ -5862,8 +6041,9 @@
5862
6041
  this.updateActualOptions();
5863
6042
  this.canvas.initBackground();
5864
6043
  this.canvas.resize();
5865
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5866
- this.hdr = hdr;
6044
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6045
+ this.hdrMode = hdrOptions.mode;
6046
+ this.peakNits = hdrOptions.peakNits;
5867
6047
  this.zLayers = zLayers;
5868
6048
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5869
6049
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6451,7 +6631,7 @@
6451
6631
  let handled = false;
6452
6632
  const canvas = container.canvas;
6453
6633
  if (trailFill.color) {
6454
- canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity));
6634
+ canvas.render.paintBase(getStyleFromRgb(trailFill.color, container.hdr, trailFill.opacity, container.peakNits, container.hdrMode));
6455
6635
  handled = true;
6456
6636
  }
6457
6637
  else if (trailFill.image) {