@tsparticles/preset-triangles 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) :
@@ -800,7 +800,7 @@
800
800
  return this.#domArray;
801
801
  }
802
802
  get version() {
803
- return "4.3.2";
803
+ return "4.4.0";
804
804
  }
805
805
  addEventListener(type, listener) {
806
806
  this.#eventDispatcher.addEventListener(type, listener);
@@ -881,6 +881,10 @@
881
881
  }
882
882
 
883
883
  function initEngine() {
884
+ const existing = globalThis.tsParticles;
885
+ if (existing?.pluginManager) {
886
+ return existing;
887
+ }
884
888
  return new Engine();
885
889
  }
886
890
 
@@ -978,6 +982,15 @@
978
982
  AnimationMode["random"] = "random";
979
983
  })(AnimationMode || (AnimationMode = {}));
980
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
+
981
994
  var LimitMode;
982
995
  (function (LimitMode) {
983
996
  LimitMode["delete"] = "delete";
@@ -1233,6 +1246,29 @@
1233
1246
  }
1234
1247
  }
1235
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
+
1236
1272
  class ResizeEvent extends OptionLoader {
1237
1273
  delay = 0.5;
1238
1274
  enable = true;
@@ -1676,7 +1712,7 @@
1676
1712
  duration = 0;
1677
1713
  fpsLimit = 120;
1678
1714
  fullScreen;
1679
- hdr = true;
1715
+ hdr;
1680
1716
  key;
1681
1717
  name;
1682
1718
  palette;
@@ -1696,6 +1732,7 @@
1696
1732
  this.#container = container;
1697
1733
  this.background = new Background();
1698
1734
  this.fullScreen = new FullScreen();
1735
+ this.hdr = new HDROptions();
1699
1736
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1700
1737
  this.resize = new ResizeEvent();
1701
1738
  }
@@ -1718,7 +1755,15 @@
1718
1755
  loadProperty(this, "detectRetina", data.detectRetina);
1719
1756
  loadRangeProperty(this, "duration", data.duration);
1720
1757
  loadProperty(this, "fpsLimit", data.fpsLimit);
1721
- 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
+ }
1722
1767
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1723
1768
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1724
1769
  loadProperty(this, "zLayers", data.zLayers);
@@ -1761,7 +1806,7 @@
1761
1806
  }
1762
1807
  }
1763
1808
 
1764
- 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;
1765
1810
  function getCachedStyle(key, generator) {
1766
1811
  let cached = styleCache.get(key);
1767
1812
  if (!cached) {
@@ -1773,6 +1818,48 @@
1773
1818
  }
1774
1819
  return cached;
1775
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
+ }
1776
1863
  function stringToRgba(pluginManager, input) {
1777
1864
  if (!input) {
1778
1865
  return;
@@ -1930,30 +2017,65 @@
1930
2017
  r: getRgbInRangeValue(),
1931
2018
  };
1932
2019
  }
1933
- function getStyleFromRgb(color, hdr, opacity) {
1934
- 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()}`;
1935
- 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));
2025
+ }
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()})`;
1936
2029
  }
1937
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1938
- const headroom = peakNits / sdrReferenceWhiteNits;
1939
- 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 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);
1940
2044
  }
1941
2045
  function getSdrStyleFromRgb(color, opacity) {
1942
2046
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1943
2047
  }
1944
- function getStyleFromHsl(color, hdr, opacity) {
1945
- 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()}`;
1946
2052
  return getCachedStyle(key, () => hdr
1947
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2053
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1948
2054
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1949
2055
  }
1950
- function colorMix(color1, color2, size1, size2) {
2056
+ function colorMix(color1, color2, size1, size2, hdr) {
1951
2057
  let rgb1 = color1, rgb2 = color2;
1952
2058
  if (!("r" in rgb1)) {
1953
- rgb1 = hslToRgb(color1);
2059
+ rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
1954
2060
  }
1955
2061
  if (!("r" in rgb2)) {
1956
- 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
+ };
1957
2079
  }
1958
2080
  return {
1959
2081
  b: mix(rgb1.b, rgb2.b, size1, size2),
@@ -1961,14 +2083,14 @@
1961
2083
  r: mix(rgb1.r, rgb2.r, size1, size2),
1962
2084
  };
1963
2085
  }
1964
- function getLinkColor(p1, p2, linkColor) {
2086
+ function getLinkColor(p1, p2, linkColor, hdr) {
1965
2087
  if (linkColor === randomColorValue) {
1966
2088
  return getRandomRgbColor();
1967
2089
  }
1968
2090
  else if (linkColor === midColorValue) {
1969
2091
  const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
1970
2092
  if (sourceColor && destColor && p2) {
1971
- return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius());
2093
+ return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
1972
2094
  }
1973
2095
  else {
1974
2096
  const hslColor = sourceColor ?? destColor;
@@ -2064,7 +2186,7 @@
2064
2186
  colorValue.velocity = defaultVelocity;
2065
2187
  }
2066
2188
  }
2067
- function updateColorValue(data, decrease, delta, hdr) {
2189
+ function updateColorValue(data, decrease, delta, _hdr) {
2068
2190
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2069
2191
  if (!data.enable ||
2070
2192
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2077,7 +2199,7 @@
2077
2199
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2078
2200
  return;
2079
2201
  }
2080
- 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;
2081
2203
  if (!decrease || data.status === AnimationStatus.increasing) {
2082
2204
  data.value += velocity;
2083
2205
  if (data.value > max) {
@@ -2109,9 +2231,9 @@
2109
2231
  return;
2110
2232
  }
2111
2233
  const { h, s, l } = color;
2112
- updateColorValue(h, false, delta, hdr);
2113
- updateColorValue(s, true, delta, hdr);
2114
- updateColorValue(l, true, delta, hdr);
2234
+ updateColorValue(h, false, delta);
2235
+ updateColorValue(s, true, delta);
2236
+ updateColorValue(l, true, delta);
2115
2237
  }
2116
2238
  function alterHsl(color, type, value) {
2117
2239
  return {
@@ -2161,7 +2283,7 @@
2161
2283
  }
2162
2284
 
2163
2285
  async function loadBlendPlugin(engine) {
2164
- engine.checkVersion("4.3.2");
2286
+ engine.checkVersion("4.4.0");
2165
2287
  await engine.pluginManager.register(e => {
2166
2288
  e.pluginManager.addPlugin(new BlendPlugin());
2167
2289
  });
@@ -2198,7 +2320,7 @@
2198
2320
  }
2199
2321
 
2200
2322
  async function loadCircleShape(engine) {
2201
- engine.checkVersion("4.3.2");
2323
+ engine.checkVersion("4.4.0");
2202
2324
  await engine.pluginManager.register(e => {
2203
2325
  e.pluginManager.addShape(["circle"], () => {
2204
2326
  return Promise.resolve(new CircleDrawer());
@@ -2246,7 +2368,7 @@
2246
2368
  }
2247
2369
 
2248
2370
  async function loadHexColorPlugin(engine) {
2249
- engine.checkVersion("4.3.2");
2371
+ engine.checkVersion("4.4.0");
2250
2372
  await engine.pluginManager.register(e => {
2251
2373
  e.pluginManager.addColorManager("hex", new HexColorManager());
2252
2374
  });
@@ -2299,7 +2421,7 @@
2299
2421
  }
2300
2422
 
2301
2423
  async function loadHslColorPlugin(engine) {
2302
- engine.checkVersion("4.3.2");
2424
+ engine.checkVersion("4.4.0");
2303
2425
  await engine.pluginManager.register(e => {
2304
2426
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2305
2427
  });
@@ -2323,7 +2445,7 @@
2323
2445
  }
2324
2446
 
2325
2447
  async function loadMovePlugin(engine) {
2326
- engine.checkVersion("4.3.2");
2448
+ engine.checkVersion("4.4.0");
2327
2449
  await engine.pluginManager.register(e => {
2328
2450
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2329
2451
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2533,7 +2655,7 @@
2533
2655
  }
2534
2656
 
2535
2657
  async function loadOpacityUpdater(engine) {
2536
- engine.checkVersion("4.3.2");
2658
+ engine.checkVersion("4.4.0");
2537
2659
  await engine.pluginManager.register(e => {
2538
2660
  e.pluginManager.addParticleUpdater("opacity", container => {
2539
2661
  return Promise.resolve(new OpacityUpdater(container));
@@ -2878,7 +3000,7 @@
2878
3000
  }
2879
3001
 
2880
3002
  async function loadOutModesUpdater(engine) {
2881
- engine.checkVersion("4.3.2");
3003
+ engine.checkVersion("4.4.0");
2882
3004
  await engine.pluginManager.register(e => {
2883
3005
  e.pluginManager.addParticleUpdater("outModes", container => {
2884
3006
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2949,7 +3071,7 @@
2949
3071
  }
2950
3072
 
2951
3073
  async function loadPaintUpdater(engine) {
2952
- engine.checkVersion("4.3.2");
3074
+ engine.checkVersion("4.4.0");
2953
3075
  await engine.pluginManager.register(e => {
2954
3076
  e.pluginManager.addParticleUpdater("paint", container => {
2955
3077
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3004,7 +3126,7 @@
3004
3126
  }
3005
3127
 
3006
3128
  async function loadRgbColorPlugin(engine) {
3007
- engine.checkVersion("4.3.2");
3129
+ engine.checkVersion("4.4.0");
3008
3130
  await engine.pluginManager.register(e => {
3009
3131
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3010
3132
  });
@@ -3089,7 +3211,7 @@
3089
3211
  }
3090
3212
 
3091
3213
  async function loadSizeUpdater(engine) {
3092
- engine.checkVersion("4.3.2");
3214
+ engine.checkVersion("4.4.0");
3093
3215
  await engine.pluginManager.register(e => {
3094
3216
  e.pluginManager.addParticleUpdater("size", container => {
3095
3217
  return Promise.resolve(new SizeUpdater(container));
@@ -3098,7 +3220,7 @@
3098
3220
  }
3099
3221
 
3100
3222
  async function loadBasic(engine) {
3101
- engine.checkVersion("4.3.2");
3223
+ engine.checkVersion("4.4.0");
3102
3224
  await engine.pluginManager.register(async (e) => {
3103
3225
  await Promise.all([
3104
3226
  loadBlendPlugin(e),
@@ -3299,7 +3421,7 @@
3299
3421
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3300
3422
 
3301
3423
  async function loadInteractivityPlugin(engine) {
3302
- engine.checkVersion("4.3.2");
3424
+ engine.checkVersion("4.4.0");
3303
3425
  await engine.pluginManager.register(e => {
3304
3426
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3305
3427
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3535,7 +3657,7 @@
3535
3657
  const linkColor = linksOptions.id !== undefined
3536
3658
  ? container.particles.linksColors.get(linksOptions.id)
3537
3659
  : container.particles.linksColor;
3538
- return getLinkColor(p1, p2, linkColor);
3660
+ return getLinkColor(p1, p2, linkColor, container.hdr);
3539
3661
  }
3540
3662
  #setColor(p1) {
3541
3663
  if (!p1.options.links) {
@@ -3576,7 +3698,7 @@
3576
3698
  }
3577
3699
 
3578
3700
  async function loadParticlesLinksInteraction(engine) {
3579
- engine.checkVersion("4.3.2");
3701
+ engine.checkVersion("4.4.0");
3580
3702
  await engine.pluginManager.register((e) => {
3581
3703
  const pluginManager = e.pluginManager;
3582
3704
  ensureInteractivityPluginLoaded(e);
@@ -3760,7 +3882,11 @@
3760
3882
  if (!fColor && !sColor) {
3761
3883
  return;
3762
3884
  }
3763
- 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;
3764
3890
  transform.a = transform.b = transform.c = transform.d = undefined;
3765
3891
  colorStyles.fill = fill;
3766
3892
  colorStyles.stroke = stroke;
@@ -4094,7 +4220,9 @@
4094
4220
  if (typeof background.element === "string") {
4095
4221
  if (typeof document !== "undefined") {
4096
4222
  const node = document.querySelector(background.element);
4097
- 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)) {
4098
4226
  this.#backgroundElement = node;
4099
4227
  }
4100
4228
  else if (node) {
@@ -4105,10 +4233,10 @@
4105
4233
  }
4106
4234
  }
4107
4235
  }
4108
- else if (background.element instanceof HTMLCanvasElement ||
4109
- background.element instanceof OffscreenCanvas ||
4110
- background.element instanceof HTMLVideoElement ||
4111
- 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)) {
4112
4240
  this.#backgroundElement = background.element;
4113
4241
  }
4114
4242
  }
@@ -4176,6 +4304,7 @@
4176
4304
  zoom = defaultZoom;
4177
4305
  #container;
4178
4306
  #generated;
4307
+ #hdrMediaListeners;
4179
4308
  #mutationObserver;
4180
4309
  #originalStyle;
4181
4310
  #pluginManager;
@@ -4240,7 +4369,6 @@
4240
4369
  });
4241
4370
  this.resize();
4242
4371
  this.#initStyle();
4243
- this.initBackground();
4244
4372
  this.#safeMutationObserver(obs => {
4245
4373
  const element = this.domElement;
4246
4374
  if (!element || !(element instanceof Node)) {
@@ -4250,6 +4378,8 @@
4250
4378
  });
4251
4379
  this.initPlugins();
4252
4380
  this.#initContext();
4381
+ this.initBackground();
4382
+ this.#initHdrListeners();
4253
4383
  this.render.init();
4254
4384
  }
4255
4385
  initBackground() {
@@ -4259,7 +4389,8 @@
4259
4389
  }
4260
4390
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4261
4391
  if (color) {
4262
- 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);
4263
4394
  }
4264
4395
  else {
4265
4396
  elementStyle.backgroundColor = "";
@@ -4356,6 +4487,7 @@
4356
4487
  obs.disconnect();
4357
4488
  });
4358
4489
  this.#mutationObserver = undefined;
4490
+ this.#removeHdrListeners();
4359
4491
  this.render.stop();
4360
4492
  }
4361
4493
  async windowResize() {
@@ -4375,9 +4507,16 @@
4375
4507
  }
4376
4508
  }
4377
4509
  #initContext() {
4378
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4510
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4379
4511
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4380
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
+ }
4381
4520
  this.render.setContextSettings({
4382
4521
  alpha: true,
4383
4522
  desynchronized: true,
@@ -4386,11 +4525,47 @@
4386
4525
  ? { colorSpace: "display-p3", colorType: "float16" }
4387
4526
  : { colorSpace: "srgb" }),
4388
4527
  });
4389
- const renderCanvas = this.renderCanvas;
4390
- if (!renderCanvas) {
4391
- 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 });
4392
4563
  }
4393
- 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;
4394
4569
  }
4395
4570
  #initStyle() {
4396
4571
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4414,6 +4589,25 @@
4414
4589
  element.style.setProperty(key, value, "important");
4415
4590
  }
4416
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
+ }
4417
4611
  #repairStyle() {
4418
4612
  const element = this.domElement;
4419
4613
  if (!element) {
@@ -4798,9 +4992,9 @@
4798
4992
  }
4799
4993
  getOpacity() {
4800
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;
4801
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4995
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4802
4996
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4803
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4997
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4804
4998
  return this.#cachedOpacityData;
4805
4999
  }
4806
5000
  getPosition() {
@@ -5655,6 +5849,7 @@
5655
5849
  effectDrawers;
5656
5850
  fpsLimit;
5657
5851
  hdr;
5852
+ hdrMode;
5658
5853
  id;
5659
5854
  pageHidden;
5660
5855
  particleCreatedPlugins;
@@ -5662,6 +5857,7 @@
5662
5857
  particlePositionPlugins;
5663
5858
  particleUpdaters;
5664
5859
  particles;
5860
+ peakNits;
5665
5861
  plugins;
5666
5862
  retina;
5667
5863
  shapeDrawers;
@@ -5692,6 +5888,8 @@
5692
5888
  this.id = Symbol(id);
5693
5889
  this.fpsLimit = 120;
5694
5890
  this.hdr = false;
5891
+ this.hdrMode = HdrMode.standard;
5892
+ this.peakNits = 400;
5695
5893
  this.#smooth = false;
5696
5894
  this.#delay = 0;
5697
5895
  this.#duration = 0;
@@ -5831,8 +6029,9 @@
5831
6029
  this.updateActualOptions();
5832
6030
  this.canvas.initBackground();
5833
6031
  this.canvas.resize();
5834
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5835
- 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;
5836
6035
  this.zLayers = zLayers;
5837
6036
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5838
6037
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -6958,10 +7157,10 @@
6958
7157
  }
6959
7158
  }
6960
7159
  #getCachedStyle(rgb) {
6961
- 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}`;
6962
7161
  let style = this.#colorCache.get(key);
6963
7162
  if (!style) {
6964
- style = getStyleFromRgb(rgb, this.#container.hdr);
7163
+ style = getStyleFromRgb(rgb, this.#container.hdr, undefined, this.#container.peakNits, this.#container.hdrMode);
6965
7164
  this.#colorCache.set(key, style);
6966
7165
  }
6967
7166
  return style;