@tsparticles/preset-hyperspace 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),
@@ -3291,7 +3391,7 @@
3291
3391
  })(EmitterClickMode || (EmitterClickMode = {}));
3292
3392
 
3293
3393
  async function loadEmittersPluginSimple(engine) {
3294
- engine.checkVersion("4.3.2");
3394
+ engine.checkVersion("4.4.0");
3295
3395
  await engine.pluginManager.register(async (e) => {
3296
3396
  const instancesManager = await getEmittersInstancesManager(e);
3297
3397
  await addEmittersShapesManager(e);
@@ -3379,7 +3479,7 @@
3379
3479
  }
3380
3480
 
3381
3481
  async function loadEmittersShapeSquare(engine) {
3382
- engine.checkVersion("4.3.2");
3482
+ engine.checkVersion("4.4.0");
3383
3483
  await engine.pluginManager.register((e) => {
3384
3484
  ensureEmittersPluginLoaded(e);
3385
3485
  e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
@@ -3523,7 +3623,7 @@
3523
3623
  }
3524
3624
 
3525
3625
  async function loadLifeUpdater(engine) {
3526
- engine.checkVersion("4.3.2");
3626
+ engine.checkVersion("4.4.0");
3527
3627
  await engine.pluginManager.register(e => {
3528
3628
  e.pluginManager.addParticleUpdater("life", container => {
3529
3629
  return Promise.resolve(new LifeUpdater(container));
@@ -3587,7 +3687,7 @@
3587
3687
  }
3588
3688
 
3589
3689
  async function loadTrailPlugin(engine) {
3590
- engine.checkVersion("4.3.2");
3690
+ engine.checkVersion("4.4.0");
3591
3691
  await engine.pluginManager.register(e => {
3592
3692
  e.pluginManager.addPlugin(new TrailPlugin(e.pluginManager));
3593
3693
  });
@@ -3794,7 +3894,11 @@
3794
3894
  if (!fColor && !sColor) {
3795
3895
  return;
3796
3896
  }
3797
- 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;
3798
3902
  transform.a = transform.b = transform.c = transform.d = undefined;
3799
3903
  colorStyles.fill = fill;
3800
3904
  colorStyles.stroke = stroke;
@@ -4128,7 +4232,9 @@
4128
4232
  if (typeof background.element === "string") {
4129
4233
  if (typeof document !== "undefined") {
4130
4234
  const node = document.querySelector(background.element);
4131
- 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)) {
4132
4238
  this.#backgroundElement = node;
4133
4239
  }
4134
4240
  else if (node) {
@@ -4139,10 +4245,10 @@
4139
4245
  }
4140
4246
  }
4141
4247
  }
4142
- else if (background.element instanceof HTMLCanvasElement ||
4143
- background.element instanceof OffscreenCanvas ||
4144
- background.element instanceof HTMLVideoElement ||
4145
- 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)) {
4146
4252
  this.#backgroundElement = background.element;
4147
4253
  }
4148
4254
  }
@@ -4210,6 +4316,7 @@
4210
4316
  zoom = defaultZoom;
4211
4317
  #container;
4212
4318
  #generated;
4319
+ #hdrMediaListeners;
4213
4320
  #mutationObserver;
4214
4321
  #originalStyle;
4215
4322
  #pluginManager;
@@ -4274,7 +4381,6 @@
4274
4381
  });
4275
4382
  this.resize();
4276
4383
  this.#initStyle();
4277
- this.initBackground();
4278
4384
  this.#safeMutationObserver(obs => {
4279
4385
  const element = this.domElement;
4280
4386
  if (!element || !(element instanceof Node)) {
@@ -4284,6 +4390,8 @@
4284
4390
  });
4285
4391
  this.initPlugins();
4286
4392
  this.#initContext();
4393
+ this.initBackground();
4394
+ this.#initHdrListeners();
4287
4395
  this.render.init();
4288
4396
  }
4289
4397
  initBackground() {
@@ -4293,7 +4401,8 @@
4293
4401
  }
4294
4402
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4295
4403
  if (color) {
4296
- 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);
4297
4406
  }
4298
4407
  else {
4299
4408
  elementStyle.backgroundColor = "";
@@ -4390,6 +4499,7 @@
4390
4499
  obs.disconnect();
4391
4500
  });
4392
4501
  this.#mutationObserver = undefined;
4502
+ this.#removeHdrListeners();
4393
4503
  this.render.stop();
4394
4504
  }
4395
4505
  async windowResize() {
@@ -4409,9 +4519,16 @@
4409
4519
  }
4410
4520
  }
4411
4521
  #initContext() {
4412
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4522
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4413
4523
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4414
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
+ }
4415
4532
  this.render.setContextSettings({
4416
4533
  alpha: true,
4417
4534
  desynchronized: true,
@@ -4420,11 +4537,47 @@
4420
4537
  ? { colorSpace: "display-p3", colorType: "float16" }
4421
4538
  : { colorSpace: "srgb" }),
4422
4539
  });
4423
- const renderCanvas = this.renderCanvas;
4424
- if (!renderCanvas) {
4425
- 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 });
4426
4579
  }
4427
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4580
+ this.#hdrMediaListeners = listeners;
4428
4581
  }
4429
4582
  #initStyle() {
4430
4583
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4448,6 +4601,25 @@
4448
4601
  element.style.setProperty(key, value, "important");
4449
4602
  }
4450
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
+ }
4451
4623
  #repairStyle() {
4452
4624
  const element = this.domElement;
4453
4625
  if (!element) {
@@ -4832,9 +5004,9 @@
4832
5004
  }
4833
5005
  getOpacity() {
4834
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;
4835
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5007
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4836
5008
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4837
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5009
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4838
5010
  return this.#cachedOpacityData;
4839
5011
  }
4840
5012
  getPosition() {
@@ -5689,6 +5861,7 @@
5689
5861
  effectDrawers;
5690
5862
  fpsLimit;
5691
5863
  hdr;
5864
+ hdrMode;
5692
5865
  id;
5693
5866
  pageHidden;
5694
5867
  particleCreatedPlugins;
@@ -5696,6 +5869,7 @@
5696
5869
  particlePositionPlugins;
5697
5870
  particleUpdaters;
5698
5871
  particles;
5872
+ peakNits;
5699
5873
  plugins;
5700
5874
  retina;
5701
5875
  shapeDrawers;
@@ -5726,6 +5900,8 @@
5726
5900
  this.id = Symbol(id);
5727
5901
  this.fpsLimit = 120;
5728
5902
  this.hdr = false;
5903
+ this.hdrMode = HdrMode.standard;
5904
+ this.peakNits = 400;
5729
5905
  this.#smooth = false;
5730
5906
  this.#delay = 0;
5731
5907
  this.#duration = 0;
@@ -5865,8 +6041,9 @@
5865
6041
  this.updateActualOptions();
5866
6042
  this.canvas.initBackground();
5867
6043
  this.canvas.resize();
5868
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5869
- 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;
5870
6047
  this.zLayers = zLayers;
5871
6048
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5872
6049
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6454,7 +6631,7 @@
6454
6631
  let handled = false;
6455
6632
  const canvas = container.canvas;
6456
6633
  if (trailFill.color) {
6457
- 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));
6458
6635
  handled = true;
6459
6636
  }
6460
6637
  else if (trailFill.image) {