@tsparticles/preset-triangles 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) :
@@ -295,6 +295,9 @@
295
295
  })(PixelMode || (PixelMode = {}));
296
296
 
297
297
  const minRadius = 0;
298
+ function isForbiddenKey(key) {
299
+ return key === "__proto__" || key === "constructor" || key === "prototype";
300
+ }
298
301
  function hasMatchMedia() {
299
302
  return typeof matchMedia !== "undefined";
300
303
  }
@@ -370,7 +373,7 @@
370
373
  if (!hasNested) {
371
374
  const sourceDict = source, destDict = destination;
372
375
  for (const key of sourceKeys) {
373
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
376
+ if (isForbiddenKey(key)) {
374
377
  continue;
375
378
  }
376
379
  const v = sourceDict[key];
@@ -381,7 +384,7 @@
381
384
  continue;
382
385
  }
383
386
  for (const key of sourceKeys) {
384
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
387
+ if (isForbiddenKey(key)) {
385
388
  continue;
386
389
  }
387
390
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -797,7 +800,7 @@
797
800
  return this.#domArray;
798
801
  }
799
802
  get version() {
800
- return "4.3.1";
803
+ return "4.4.0";
801
804
  }
802
805
  addEventListener(type, listener) {
803
806
  this.#eventDispatcher.addEventListener(type, listener);
@@ -878,6 +881,10 @@
878
881
  }
879
882
 
880
883
  function initEngine() {
884
+ const existing = globalThis.tsParticles;
885
+ if (existing?.pluginManager) {
886
+ return existing;
887
+ }
881
888
  return new Engine();
882
889
  }
883
890
 
@@ -975,6 +982,15 @@
975
982
  AnimationMode["random"] = "random";
976
983
  })(AnimationMode || (AnimationMode = {}));
977
984
 
985
+ var HdrMode;
986
+ (function (HdrMode) {
987
+ HdrMode["standard"] = "standard";
988
+ HdrMode["natural"] = "natural";
989
+ HdrMode["vivid"] = "vivid";
990
+ HdrMode["cinematic"] = "cinematic";
991
+ HdrMode["dynamic"] = "dynamic";
992
+ })(HdrMode || (HdrMode = {}));
993
+
978
994
  var LimitMode;
979
995
  (function (LimitMode) {
980
996
  LimitMode["delete"] = "delete";
@@ -1230,6 +1246,29 @@
1230
1246
  }
1231
1247
  }
1232
1248
 
1249
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1250
+ class HDROptions extends OptionLoader {
1251
+ enable = true;
1252
+ mode = HdrMode.standard;
1253
+ peakNits = defaultPeakNits;
1254
+ doLoad(data) {
1255
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1256
+ throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1257
+ }
1258
+ if (data.mode !== undefined &&
1259
+ (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1260
+ throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1261
+ }
1262
+ if (data.peakNits !== undefined &&
1263
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1264
+ throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1265
+ }
1266
+ loadProperty(this, "enable", data.enable);
1267
+ loadProperty(this, "mode", data.mode);
1268
+ loadProperty(this, "peakNits", data.peakNits);
1269
+ }
1270
+ }
1271
+
1233
1272
  class ResizeEvent extends OptionLoader {
1234
1273
  delay = 0.5;
1235
1274
  enable = true;
@@ -1673,7 +1712,7 @@
1673
1712
  duration = 0;
1674
1713
  fpsLimit = 120;
1675
1714
  fullScreen;
1676
- hdr = true;
1715
+ hdr;
1677
1716
  key;
1678
1717
  name;
1679
1718
  palette;
@@ -1693,6 +1732,7 @@
1693
1732
  this.#container = container;
1694
1733
  this.background = new Background();
1695
1734
  this.fullScreen = new FullScreen();
1735
+ this.hdr = new HDROptions();
1696
1736
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1697
1737
  this.resize = new ResizeEvent();
1698
1738
  }
@@ -1715,7 +1755,15 @@
1715
1755
  loadProperty(this, "detectRetina", data.detectRetina);
1716
1756
  loadRangeProperty(this, "duration", data.duration);
1717
1757
  loadProperty(this, "fpsLimit", data.fpsLimit);
1718
- loadProperty(this, "hdr", data.hdr);
1758
+ const hdrData = data.hdr;
1759
+ if (isBoolean(hdrData)) {
1760
+ this.hdr.enable = hdrData;
1761
+ this.hdr.mode = HdrMode.standard;
1762
+ this.hdr.peakNits = 400;
1763
+ }
1764
+ else {
1765
+ this.hdr.load(hdrData);
1766
+ }
1719
1767
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1720
1768
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1721
1769
  loadProperty(this, "zLayers", data.zLayers);
@@ -1758,7 +1806,7 @@
1758
1806
  }
1759
1807
  }
1760
1808
 
1761
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1809
+ 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, srgbThreshold = 0.04045, srgbDivisor = 12.92, srgbOffset = 0.055, srgbScale = 1.055, srgbExponent = 2.4, linearThreshold = 0.0031308, linearScale = 12.92;
1762
1810
  function getCachedStyle(key, generator) {
1763
1811
  let cached = styleCache.get(key);
1764
1812
  if (!cached) {
@@ -1770,6 +1818,48 @@
1770
1818
  }
1771
1819
  return cached;
1772
1820
  }
1821
+ function acesFilmic(x) {
1822
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1823
+ }
1824
+ function srgbToLinear(c) {
1825
+ return c <= srgbThreshold ? c / srgbDivisor : Math.pow((c + srgbOffset) / srgbScale, srgbExponent);
1826
+ }
1827
+ function linearToSrgb(c) {
1828
+ return c <= linearThreshold ? c * linearScale : srgbScale * Math.pow(c, one / srgbExponent) - srgbOffset;
1829
+ }
1830
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1831
+ switch (mode) {
1832
+ case HdrMode.vivid: {
1833
+ const avg = (r + g + b) / channelCount;
1834
+ return {
1835
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1836
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1837
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1838
+ };
1839
+ }
1840
+ case HdrMode.cinematic: {
1841
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1842
+ return {
1843
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1844
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1845
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1846
+ };
1847
+ }
1848
+ case HdrMode.dynamic: {
1849
+ 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;
1850
+ return {
1851
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1852
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1853
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1854
+ };
1855
+ }
1856
+ case HdrMode.standard:
1857
+ return { b, g, r };
1858
+ case HdrMode.natural:
1859
+ default:
1860
+ return { b, g, r };
1861
+ }
1862
+ }
1773
1863
  function stringToRgba(pluginManager, input) {
1774
1864
  if (!input) {
1775
1865
  return;
@@ -1927,30 +2017,65 @@
1927
2017
  r: getRgbInRangeValue(),
1928
2018
  };
1929
2019
  }
1930
- function getStyleFromRgb(color, hdr, opacity) {
1931
- 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()}`;
1932
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2020
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2021
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2022
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2023
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2024
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
1933
2025
  }
1934
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1935
- const headroom = peakNits / sdrReferenceWhiteNits;
1936
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2026
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
2027
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2028
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2029
+ }
2030
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2031
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2032
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2033
+ return { b: bNorm, g: gNorm, r: rNorm };
2034
+ }
2035
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2036
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2037
+ }
2038
+ function hdrToneMap(normalized, headroom, middleGray) {
2039
+ if (normalized <= middleGray) {
2040
+ return acesFilmic(normalized);
2041
+ }
2042
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2043
+ return acesFilmic(expanded);
1937
2044
  }
1938
2045
  function getSdrStyleFromRgb(color, opacity) {
1939
2046
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1940
2047
  }
1941
- function getStyleFromHsl(color, hdr, opacity) {
1942
- 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()}`;
2048
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2049
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2050
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2051
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1943
2052
  return getCachedStyle(key, () => hdr
1944
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2053
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1945
2054
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1946
2055
  }
1947
- function colorMix(color1, color2, size1, size2) {
2056
+ function colorMix(color1, color2, size1, size2, hdr) {
1948
2057
  let rgb1 = color1, rgb2 = color2;
1949
2058
  if (!("r" in rgb1)) {
1950
- rgb1 = hslToRgb(color1);
2059
+ rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
1951
2060
  }
1952
2061
  if (!("r" in rgb2)) {
1953
- rgb2 = hslToRgb(color2);
2062
+ rgb2 = hdr ? hslToRgbFloat(color2) : hslToRgb(color2);
2063
+ }
2064
+ if (hdr) {
2065
+ const lin1 = {
2066
+ b: srgbToLinear(rgb1.b / rgbMax),
2067
+ g: srgbToLinear(rgb1.g / rgbMax),
2068
+ r: srgbToLinear(rgb1.r / rgbMax),
2069
+ }, lin2 = {
2070
+ b: srgbToLinear(rgb2.b / rgbMax),
2071
+ g: srgbToLinear(rgb2.g / rgbMax),
2072
+ r: srgbToLinear(rgb2.r / rgbMax),
2073
+ }, totalWeight = size1 + size2;
2074
+ return {
2075
+ b: linearToSrgb((lin1.b * size1 + lin2.b * size2) / totalWeight) * rgbMax,
2076
+ g: linearToSrgb((lin1.g * size1 + lin2.g * size2) / totalWeight) * rgbMax,
2077
+ r: linearToSrgb((lin1.r * size1 + lin2.r * size2) / totalWeight) * rgbMax,
2078
+ };
1954
2079
  }
1955
2080
  return {
1956
2081
  b: mix(rgb1.b, rgb2.b, size1, size2),
@@ -1958,14 +2083,14 @@
1958
2083
  r: mix(rgb1.r, rgb2.r, size1, size2),
1959
2084
  };
1960
2085
  }
1961
- function getLinkColor(p1, p2, linkColor) {
2086
+ function getLinkColor(p1, p2, linkColor, hdr) {
1962
2087
  if (linkColor === randomColorValue) {
1963
2088
  return getRandomRgbColor();
1964
2089
  }
1965
2090
  else if (linkColor === midColorValue) {
1966
2091
  const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
1967
2092
  if (sourceColor && destColor && p2) {
1968
- return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius());
2093
+ return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
1969
2094
  }
1970
2095
  else {
1971
2096
  const hslColor = sourceColor ?? destColor;
@@ -2061,7 +2186,7 @@
2061
2186
  colorValue.velocity = defaultVelocity;
2062
2187
  }
2063
2188
  }
2064
- function updateColorValue(data, decrease, delta, hdr) {
2189
+ function updateColorValue(data, decrease, delta, _hdr) {
2065
2190
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2066
2191
  if (!data.enable ||
2067
2192
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2074,7 +2199,7 @@
2074
2199
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2075
2200
  return;
2076
2201
  }
2077
- 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;
2202
+ 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;
2078
2203
  if (!decrease || data.status === AnimationStatus.increasing) {
2079
2204
  data.value += velocity;
2080
2205
  if (data.value > max) {
@@ -2106,9 +2231,9 @@
2106
2231
  return;
2107
2232
  }
2108
2233
  const { h, s, l } = color;
2109
- updateColorValue(h, false, delta, hdr);
2110
- updateColorValue(s, true, delta, hdr);
2111
- updateColorValue(l, true, delta, hdr);
2234
+ updateColorValue(h, false, delta);
2235
+ updateColorValue(s, true, delta);
2236
+ updateColorValue(l, true, delta);
2112
2237
  }
2113
2238
  function alterHsl(color, type, value) {
2114
2239
  return {
@@ -2158,7 +2283,7 @@
2158
2283
  }
2159
2284
 
2160
2285
  async function loadBlendPlugin(engine) {
2161
- engine.checkVersion("4.3.1");
2286
+ engine.checkVersion("4.4.0");
2162
2287
  await engine.pluginManager.register(e => {
2163
2288
  e.pluginManager.addPlugin(new BlendPlugin());
2164
2289
  });
@@ -2195,7 +2320,7 @@
2195
2320
  }
2196
2321
 
2197
2322
  async function loadCircleShape(engine) {
2198
- engine.checkVersion("4.3.1");
2323
+ engine.checkVersion("4.4.0");
2199
2324
  await engine.pluginManager.register(e => {
2200
2325
  e.pluginManager.addShape(["circle"], () => {
2201
2326
  return Promise.resolve(new CircleDrawer());
@@ -2243,7 +2368,7 @@
2243
2368
  }
2244
2369
 
2245
2370
  async function loadHexColorPlugin(engine) {
2246
- engine.checkVersion("4.3.1");
2371
+ engine.checkVersion("4.4.0");
2247
2372
  await engine.pluginManager.register(e => {
2248
2373
  e.pluginManager.addColorManager("hex", new HexColorManager());
2249
2374
  });
@@ -2296,7 +2421,7 @@
2296
2421
  }
2297
2422
 
2298
2423
  async function loadHslColorPlugin(engine) {
2299
- engine.checkVersion("4.3.1");
2424
+ engine.checkVersion("4.4.0");
2300
2425
  await engine.pluginManager.register(e => {
2301
2426
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2302
2427
  });
@@ -2320,7 +2445,7 @@
2320
2445
  }
2321
2446
 
2322
2447
  async function loadMovePlugin(engine) {
2323
- engine.checkVersion("4.3.1");
2448
+ engine.checkVersion("4.4.0");
2324
2449
  await engine.pluginManager.register(e => {
2325
2450
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2326
2451
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2530,7 +2655,7 @@
2530
2655
  }
2531
2656
 
2532
2657
  async function loadOpacityUpdater(engine) {
2533
- engine.checkVersion("4.3.1");
2658
+ engine.checkVersion("4.4.0");
2534
2659
  await engine.pluginManager.register(e => {
2535
2660
  e.pluginManager.addParticleUpdater("opacity", container => {
2536
2661
  return Promise.resolve(new OpacityUpdater(container));
@@ -2875,7 +3000,7 @@
2875
3000
  }
2876
3001
 
2877
3002
  async function loadOutModesUpdater(engine) {
2878
- engine.checkVersion("4.3.1");
3003
+ engine.checkVersion("4.4.0");
2879
3004
  await engine.pluginManager.register(e => {
2880
3005
  e.pluginManager.addParticleUpdater("outModes", container => {
2881
3006
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2946,7 +3071,7 @@
2946
3071
  }
2947
3072
 
2948
3073
  async function loadPaintUpdater(engine) {
2949
- engine.checkVersion("4.3.1");
3074
+ engine.checkVersion("4.4.0");
2950
3075
  await engine.pluginManager.register(e => {
2951
3076
  e.pluginManager.addParticleUpdater("paint", container => {
2952
3077
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3001,7 +3126,7 @@
3001
3126
  }
3002
3127
 
3003
3128
  async function loadRgbColorPlugin(engine) {
3004
- engine.checkVersion("4.3.1");
3129
+ engine.checkVersion("4.4.0");
3005
3130
  await engine.pluginManager.register(e => {
3006
3131
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3007
3132
  });
@@ -3086,7 +3211,7 @@
3086
3211
  }
3087
3212
 
3088
3213
  async function loadSizeUpdater(engine) {
3089
- engine.checkVersion("4.3.1");
3214
+ engine.checkVersion("4.4.0");
3090
3215
  await engine.pluginManager.register(e => {
3091
3216
  e.pluginManager.addParticleUpdater("size", container => {
3092
3217
  return Promise.resolve(new SizeUpdater(container));
@@ -3095,7 +3220,7 @@
3095
3220
  }
3096
3221
 
3097
3222
  async function loadBasic(engine) {
3098
- engine.checkVersion("4.3.1");
3223
+ engine.checkVersion("4.4.0");
3099
3224
  await engine.pluginManager.register(async (e) => {
3100
3225
  await Promise.all([
3101
3226
  loadBlendPlugin(e),
@@ -3296,7 +3421,7 @@
3296
3421
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3297
3422
 
3298
3423
  async function loadInteractivityPlugin(engine) {
3299
- engine.checkVersion("4.3.1");
3424
+ engine.checkVersion("4.4.0");
3300
3425
  await engine.pluginManager.register(e => {
3301
3426
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3302
3427
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3532,7 +3657,7 @@
3532
3657
  const linkColor = linksOptions.id !== undefined
3533
3658
  ? container.particles.linksColors.get(linksOptions.id)
3534
3659
  : container.particles.linksColor;
3535
- return getLinkColor(p1, p2, linkColor);
3660
+ return getLinkColor(p1, p2, linkColor, container.hdr);
3536
3661
  }
3537
3662
  #setColor(p1) {
3538
3663
  if (!p1.options.links) {
@@ -3573,7 +3698,7 @@
3573
3698
  }
3574
3699
 
3575
3700
  async function loadParticlesLinksInteraction(engine) {
3576
- engine.checkVersion("4.3.1");
3701
+ engine.checkVersion("4.4.0");
3577
3702
  await engine.pluginManager.register((e) => {
3578
3703
  const pluginManager = e.pluginManager;
3579
3704
  ensureInteractivityPluginLoaded(e);
@@ -3757,7 +3882,11 @@
3757
3882
  if (!fColor && !sColor) {
3758
3883
  return;
3759
3884
  }
3760
- 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;
3885
+ 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
3886
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3887
+ : undefined, stroke = sColor
3888
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3889
+ : fill;
3761
3890
  transform.a = transform.b = transform.c = transform.d = undefined;
3762
3891
  colorStyles.fill = fill;
3763
3892
  colorStyles.stroke = stroke;
@@ -4091,7 +4220,9 @@
4091
4220
  if (typeof background.element === "string") {
4092
4221
  if (typeof document !== "undefined") {
4093
4222
  const node = document.querySelector(background.element);
4094
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4223
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4224
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4225
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4095
4226
  this.#backgroundElement = node;
4096
4227
  }
4097
4228
  else if (node) {
@@ -4102,10 +4233,10 @@
4102
4233
  }
4103
4234
  }
4104
4235
  }
4105
- else if (background.element instanceof HTMLCanvasElement ||
4106
- background.element instanceof OffscreenCanvas ||
4107
- background.element instanceof HTMLVideoElement ||
4108
- background.element instanceof HTMLImageElement) {
4236
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4237
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4238
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4239
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4109
4240
  this.#backgroundElement = background.element;
4110
4241
  }
4111
4242
  }
@@ -4173,6 +4304,7 @@
4173
4304
  zoom = defaultZoom;
4174
4305
  #container;
4175
4306
  #generated;
4307
+ #hdrMediaListeners;
4176
4308
  #mutationObserver;
4177
4309
  #originalStyle;
4178
4310
  #pluginManager;
@@ -4237,7 +4369,6 @@
4237
4369
  });
4238
4370
  this.resize();
4239
4371
  this.#initStyle();
4240
- this.initBackground();
4241
4372
  this.#safeMutationObserver(obs => {
4242
4373
  const element = this.domElement;
4243
4374
  if (!element || !(element instanceof Node)) {
@@ -4247,6 +4378,8 @@
4247
4378
  });
4248
4379
  this.initPlugins();
4249
4380
  this.#initContext();
4381
+ this.initBackground();
4382
+ this.#initHdrListeners();
4250
4383
  this.render.init();
4251
4384
  }
4252
4385
  initBackground() {
@@ -4256,7 +4389,8 @@
4256
4389
  }
4257
4390
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4258
4391
  if (color) {
4259
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4392
+ const hdrOptions = container.actualOptions.hdr;
4393
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4260
4394
  }
4261
4395
  else {
4262
4396
  elementStyle.backgroundColor = "";
@@ -4353,6 +4487,7 @@
4353
4487
  obs.disconnect();
4354
4488
  });
4355
4489
  this.#mutationObserver = undefined;
4490
+ this.#removeHdrListeners();
4356
4491
  this.render.stop();
4357
4492
  }
4358
4493
  async windowResize() {
@@ -4372,9 +4507,16 @@
4372
4507
  }
4373
4508
  }
4374
4509
  #initContext() {
4375
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4510
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4376
4511
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4377
4512
  safeMatchMedia("(dynamic-range: high)")?.matches;
4513
+ container.hdr = canSupportHdr ?? false;
4514
+ container.hdrMode = container.actualOptions.hdr.mode;
4515
+ container.peakNits = container.actualOptions.hdr.peakNits;
4516
+ const renderCanvas = this.renderCanvas;
4517
+ if (!renderCanvas) {
4518
+ return;
4519
+ }
4378
4520
  this.render.setContextSettings({
4379
4521
  alpha: true,
4380
4522
  desynchronized: true,
@@ -4383,11 +4525,47 @@
4383
4525
  ? { colorSpace: "display-p3", colorType: "float16" }
4384
4526
  : { colorSpace: "srgb" }),
4385
4527
  });
4386
- const renderCanvas = this.renderCanvas;
4387
- if (!renderCanvas) {
4388
- return;
4528
+ let context;
4529
+ try {
4530
+ context = renderCanvas.getContext("2d", this.render.settings);
4531
+ }
4532
+ catch {
4533
+ context = null;
4534
+ }
4535
+ if (canSupportHdr && !context) {
4536
+ container.hdr = false;
4537
+ const sdrSettings = {
4538
+ alpha: true,
4539
+ desynchronized: true,
4540
+ willReadFrequently: false,
4541
+ colorSpace: "srgb",
4542
+ };
4543
+ this.render.setContextSettings(sdrSettings);
4544
+ try {
4545
+ context = renderCanvas.getContext("2d", sdrSettings);
4546
+ }
4547
+ catch {
4548
+ context = null;
4549
+ }
4550
+ }
4551
+ this.render.setContext(context);
4552
+ }
4553
+ #initHdrListeners() {
4554
+ this.#removeHdrListeners();
4555
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4556
+ this.#recreateRenderCanvas();
4557
+ this.#initContext();
4558
+ this.initBackground();
4559
+ }, listeners = [];
4560
+ if (p3Query) {
4561
+ p3Query.addEventListener("change", handleChange);
4562
+ listeners.push({ handler: handleChange, mql: p3Query });
4389
4563
  }
4390
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4564
+ if (hdrQuery) {
4565
+ hdrQuery.addEventListener("change", handleChange);
4566
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4567
+ }
4568
+ this.#hdrMediaListeners = listeners;
4391
4569
  }
4392
4570
  #initStyle() {
4393
4571
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4411,6 +4589,25 @@
4411
4589
  element.style.setProperty(key, value, "important");
4412
4590
  }
4413
4591
  }
4592
+ #recreateRenderCanvas() {
4593
+ const renderCanvas = this.renderCanvas;
4594
+ if (!renderCanvas) {
4595
+ return;
4596
+ }
4597
+ if (this.domElement) {
4598
+ return;
4599
+ }
4600
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4601
+ }
4602
+ #removeHdrListeners() {
4603
+ if (!this.#hdrMediaListeners) {
4604
+ return;
4605
+ }
4606
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4607
+ mql.removeEventListener("change", handler);
4608
+ }
4609
+ this.#hdrMediaListeners = undefined;
4610
+ }
4414
4611
  #repairStyle() {
4415
4612
  const element = this.domElement;
4416
4613
  if (!element) {
@@ -4795,9 +4992,9 @@
4795
4992
  }
4796
4993
  getOpacity() {
4797
4994
  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;
4798
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4995
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4799
4996
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4800
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4997
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4801
4998
  return this.#cachedOpacityData;
4802
4999
  }
4803
5000
  getPosition() {
@@ -5652,6 +5849,7 @@
5652
5849
  effectDrawers;
5653
5850
  fpsLimit;
5654
5851
  hdr;
5852
+ hdrMode;
5655
5853
  id;
5656
5854
  pageHidden;
5657
5855
  particleCreatedPlugins;
@@ -5659,6 +5857,7 @@
5659
5857
  particlePositionPlugins;
5660
5858
  particleUpdaters;
5661
5859
  particles;
5860
+ peakNits;
5662
5861
  plugins;
5663
5862
  retina;
5664
5863
  shapeDrawers;
@@ -5689,6 +5888,8 @@
5689
5888
  this.id = Symbol(id);
5690
5889
  this.fpsLimit = 120;
5691
5890
  this.hdr = false;
5891
+ this.hdrMode = HdrMode.standard;
5892
+ this.peakNits = 400;
5692
5893
  this.#smooth = false;
5693
5894
  this.#delay = 0;
5694
5895
  this.#duration = 0;
@@ -5828,8 +6029,9 @@
5828
6029
  this.updateActualOptions();
5829
6030
  this.canvas.initBackground();
5830
6031
  this.canvas.resize();
5831
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5832
- this.hdr = hdr;
6032
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6033
+ this.hdrMode = hdrOptions.mode;
6034
+ this.peakNits = hdrOptions.peakNits;
5833
6035
  this.zLayers = zLayers;
5834
6036
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5835
6037
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6955,10 +7157,10 @@
6955
7157
  }
6956
7158
  }
6957
7159
  #getCachedStyle(rgb) {
6958
- const key = `${rgb.r},${rgb.g},${rgb.b}`;
7160
+ const key = `${rgb.r},${rgb.g},${rgb.b}-${this.#container.hdr}-${this.#container.peakNits}-${this.#container.hdrMode}`;
6959
7161
  let style = this.#colorCache.get(key);
6960
7162
  if (!style) {
6961
- style = getStyleFromRgb(rgb, this.#container.hdr);
7163
+ style = getStyleFromRgb(rgb, this.#container.hdr, undefined, this.#container.peakNits, this.#container.hdrMode);
6962
7164
  this.#colorCache.set(key, style);
6963
7165
  }
6964
7166
  return style;