@tsparticles/particles 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
- /* tsParticles v4.3.1 */
2
+ /* tsParticles 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) :
@@ -332,6 +332,9 @@
332
332
  })(exports.PixelMode || (exports.PixelMode = {}));
333
333
 
334
334
  const minRadius = 0;
335
+ function isForbiddenKey(key) {
336
+ return key === "__proto__" || key === "constructor" || key === "prototype";
337
+ }
335
338
  function hasMatchMedia() {
336
339
  return typeof matchMedia !== "undefined";
337
340
  }
@@ -407,7 +410,7 @@
407
410
  if (!hasNested) {
408
411
  const sourceDict = source, destDict = destination;
409
412
  for (const key of sourceKeys) {
410
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
413
+ if (isForbiddenKey(key)) {
411
414
  continue;
412
415
  }
413
416
  const v = sourceDict[key];
@@ -418,7 +421,7 @@
418
421
  continue;
419
422
  }
420
423
  for (const key of sourceKeys) {
421
- if (key === "__proto__" || key === "constructor" || key === "prototype") {
424
+ if (isForbiddenKey(key)) {
422
425
  continue;
423
426
  }
424
427
  const sourceDict = source, destDict = destination, value = sourceDict[key];
@@ -877,7 +880,7 @@
877
880
  return this.#domArray;
878
881
  }
879
882
  get version() {
880
- return "4.3.1";
883
+ return "4.4.0";
881
884
  }
882
885
  addEventListener(type, listener) {
883
886
  this.#eventDispatcher.addEventListener(type, listener);
@@ -958,6 +961,10 @@
958
961
  }
959
962
 
960
963
  function initEngine() {
964
+ const existing = globalThis.tsParticles;
965
+ if (existing?.pluginManager) {
966
+ return existing;
967
+ }
961
968
  return new Engine();
962
969
  }
963
970
 
@@ -1055,6 +1062,15 @@
1055
1062
  AnimationMode["random"] = "random";
1056
1063
  })(exports.AnimationMode || (exports.AnimationMode = {}));
1057
1064
 
1065
+ exports.HdrMode = void 0;
1066
+ (function (HdrMode) {
1067
+ HdrMode["standard"] = "standard";
1068
+ HdrMode["natural"] = "natural";
1069
+ HdrMode["vivid"] = "vivid";
1070
+ HdrMode["cinematic"] = "cinematic";
1071
+ HdrMode["dynamic"] = "dynamic";
1072
+ })(exports.HdrMode || (exports.HdrMode = {}));
1073
+
1058
1074
  exports.LimitMode = void 0;
1059
1075
  (function (LimitMode) {
1060
1076
  LimitMode["delete"] = "delete";
@@ -1160,7 +1176,12 @@
1160
1176
  }
1161
1177
  function loadExtendProperty(obj, key, value) {
1162
1178
  if (value !== undefined) {
1163
- obj[key] = deepExtend(obj[key] ?? {}, value);
1179
+ const keyStr = key;
1180
+ if (keyStr === "__proto__" || keyStr === "constructor" || keyStr === "prototype") {
1181
+ return;
1182
+ }
1183
+ const objRecord = obj, currentValue = Object.prototype.hasOwnProperty.call(objRecord, keyStr) ? objRecord[keyStr] : {};
1184
+ objRecord[keyStr] = deepExtend(currentValue, value);
1164
1185
  }
1165
1186
  }
1166
1187
  function loadOptionProperty(obj, key, optionClass, ...sources) {
@@ -1315,6 +1336,29 @@
1315
1336
  }
1316
1337
  }
1317
1338
 
1339
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1340
+ class HDROptions extends OptionLoader {
1341
+ enable = true;
1342
+ mode = exports.HdrMode.standard;
1343
+ peakNits = defaultPeakNits;
1344
+ doLoad(data) {
1345
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1346
+ throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1347
+ }
1348
+ if (data.mode !== undefined &&
1349
+ (typeof data.mode !== "string" || !Object.values(exports.HdrMode).includes(data.mode))) {
1350
+ throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(exports.HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1351
+ }
1352
+ if (data.peakNits !== undefined &&
1353
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1354
+ throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1355
+ }
1356
+ loadProperty(this, "enable", data.enable);
1357
+ loadProperty(this, "mode", data.mode);
1358
+ loadProperty(this, "peakNits", data.peakNits);
1359
+ }
1360
+ }
1361
+
1318
1362
  class ResizeEvent extends OptionLoader {
1319
1363
  delay = 0.5;
1320
1364
  enable = true;
@@ -1758,7 +1802,7 @@
1758
1802
  duration = 0;
1759
1803
  fpsLimit = 120;
1760
1804
  fullScreen;
1761
- hdr = true;
1805
+ hdr;
1762
1806
  key;
1763
1807
  name;
1764
1808
  palette;
@@ -1778,6 +1822,7 @@
1778
1822
  this.#container = container;
1779
1823
  this.background = new Background();
1780
1824
  this.fullScreen = new FullScreen();
1825
+ this.hdr = new HDROptions();
1781
1826
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1782
1827
  this.resize = new ResizeEvent();
1783
1828
  }
@@ -1800,7 +1845,15 @@
1800
1845
  loadProperty(this, "detectRetina", data.detectRetina);
1801
1846
  loadRangeProperty(this, "duration", data.duration);
1802
1847
  loadProperty(this, "fpsLimit", data.fpsLimit);
1803
- loadProperty(this, "hdr", data.hdr);
1848
+ const hdrData = data.hdr;
1849
+ if (isBoolean(hdrData)) {
1850
+ this.hdr.enable = hdrData;
1851
+ this.hdr.mode = exports.HdrMode.standard;
1852
+ this.hdr.peakNits = 400;
1853
+ }
1854
+ else {
1855
+ this.hdr.load(hdrData);
1856
+ }
1804
1857
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1805
1858
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1806
1859
  loadProperty(this, "zLayers", data.zLayers);
@@ -1843,7 +1896,7 @@
1843
1896
  }
1844
1897
  }
1845
1898
 
1846
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1899
+ 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;
1847
1900
  function getCachedStyle(key, generator) {
1848
1901
  let cached = styleCache.get(key);
1849
1902
  if (!cached) {
@@ -1855,6 +1908,48 @@
1855
1908
  }
1856
1909
  return cached;
1857
1910
  }
1911
+ function acesFilmic(x) {
1912
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1913
+ }
1914
+ function srgbToLinear(c) {
1915
+ return c <= srgbThreshold ? c / srgbDivisor : Math.pow((c + srgbOffset) / srgbScale, srgbExponent);
1916
+ }
1917
+ function linearToSrgb(c) {
1918
+ return c <= linearThreshold ? c * linearScale : srgbScale * Math.pow(c, one / srgbExponent) - srgbOffset;
1919
+ }
1920
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1921
+ switch (mode) {
1922
+ case exports.HdrMode.vivid: {
1923
+ const avg = (r + g + b) / channelCount;
1924
+ return {
1925
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1926
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1927
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1928
+ };
1929
+ }
1930
+ case exports.HdrMode.cinematic: {
1931
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1932
+ return {
1933
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1934
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1935
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1936
+ };
1937
+ }
1938
+ case exports.HdrMode.dynamic: {
1939
+ 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;
1940
+ return {
1941
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1942
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1943
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1944
+ };
1945
+ }
1946
+ case exports.HdrMode.standard:
1947
+ return { b, g, r };
1948
+ case exports.HdrMode.natural:
1949
+ default:
1950
+ return { b, g, r };
1951
+ }
1952
+ }
1858
1953
  function stringToRgba(pluginManager, input) {
1859
1954
  if (!input) {
1860
1955
  return;
@@ -2022,30 +2117,65 @@
2022
2117
  r: getRgbInRangeValue(),
2023
2118
  };
2024
2119
  }
2025
- function getStyleFromRgb(color, hdr, opacity) {
2026
- const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$2, key = `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2027
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2120
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2121
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$2, key = hdr
2122
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
2123
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2124
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
2028
2125
  }
2029
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
2030
- const headroom = peakNits / sdrReferenceWhiteNits;
2031
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$2).toString()})`;
2126
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = exports.HdrMode.standard) {
2127
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2128
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$2).toString()})`;
2129
+ }
2130
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2131
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2132
+ if (mode !== exports.HdrMode.natural && mode !== exports.HdrMode.vivid && mode !== exports.HdrMode.cinematic && mode !== exports.HdrMode.dynamic) {
2133
+ return { b: bNorm, g: gNorm, r: rNorm };
2134
+ }
2135
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2136
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2137
+ }
2138
+ function hdrToneMap(normalized, headroom, middleGray) {
2139
+ if (normalized <= middleGray) {
2140
+ return acesFilmic(normalized);
2141
+ }
2142
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2143
+ return acesFilmic(expanded);
2032
2144
  }
2033
2145
  function getSdrStyleFromRgb(color, opacity) {
2034
2146
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$2).toString()})`;
2035
2147
  }
2036
- function getStyleFromHsl(color, hdr, opacity) {
2037
- const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$2, key = `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2148
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2149
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$2, key = hdr
2150
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
2151
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
2038
2152
  return getCachedStyle(key, () => hdr
2039
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2153
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
2040
2154
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
2041
2155
  }
2042
- function colorMix(color1, color2, size1, size2) {
2156
+ function colorMix(color1, color2, size1, size2, hdr) {
2043
2157
  let rgb1 = color1, rgb2 = color2;
2044
2158
  if (!("r" in rgb1)) {
2045
- rgb1 = hslToRgb(color1);
2159
+ rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
2046
2160
  }
2047
2161
  if (!("r" in rgb2)) {
2048
- rgb2 = hslToRgb(color2);
2162
+ rgb2 = hdr ? hslToRgbFloat(color2) : hslToRgb(color2);
2163
+ }
2164
+ if (hdr) {
2165
+ const lin1 = {
2166
+ b: srgbToLinear(rgb1.b / rgbMax),
2167
+ g: srgbToLinear(rgb1.g / rgbMax),
2168
+ r: srgbToLinear(rgb1.r / rgbMax),
2169
+ }, lin2 = {
2170
+ b: srgbToLinear(rgb2.b / rgbMax),
2171
+ g: srgbToLinear(rgb2.g / rgbMax),
2172
+ r: srgbToLinear(rgb2.r / rgbMax),
2173
+ }, totalWeight = size1 + size2;
2174
+ return {
2175
+ b: linearToSrgb((lin1.b * size1 + lin2.b * size2) / totalWeight) * rgbMax,
2176
+ g: linearToSrgb((lin1.g * size1 + lin2.g * size2) / totalWeight) * rgbMax,
2177
+ r: linearToSrgb((lin1.r * size1 + lin2.r * size2) / totalWeight) * rgbMax,
2178
+ };
2049
2179
  }
2050
2180
  return {
2051
2181
  b: mix(rgb1.b, rgb2.b, size1, size2),
@@ -2053,14 +2183,14 @@
2053
2183
  r: mix(rgb1.r, rgb2.r, size1, size2),
2054
2184
  };
2055
2185
  }
2056
- function getLinkColor(p1, p2, linkColor) {
2186
+ function getLinkColor(p1, p2, linkColor, hdr) {
2057
2187
  if (linkColor === randomColorValue) {
2058
2188
  return getRandomRgbColor();
2059
2189
  }
2060
2190
  else if (linkColor === midColorValue) {
2061
2191
  const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
2062
2192
  if (sourceColor && destColor && p2) {
2063
- return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius());
2193
+ return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
2064
2194
  }
2065
2195
  else {
2066
2196
  const hslColor = sourceColor ?? destColor;
@@ -2156,7 +2286,7 @@
2156
2286
  colorValue.velocity = defaultVelocity;
2157
2287
  }
2158
2288
  }
2159
- function updateColorValue(data, decrease, delta, hdr) {
2289
+ function updateColorValue(data, decrease, delta, _hdr) {
2160
2290
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2161
2291
  if (!data.enable ||
2162
2292
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2169,7 +2299,7 @@
2169
2299
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2170
2300
  return;
2171
2301
  }
2172
- 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;
2302
+ 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;
2173
2303
  if (!decrease || data.status === exports.AnimationStatus.increasing) {
2174
2304
  data.value += velocity;
2175
2305
  if (data.value > max) {
@@ -2201,9 +2331,9 @@
2201
2331
  return;
2202
2332
  }
2203
2333
  const { h, s, l } = color;
2204
- updateColorValue(h, false, delta, hdr);
2205
- updateColorValue(s, true, delta, hdr);
2206
- updateColorValue(l, true, delta, hdr);
2334
+ updateColorValue(h, false, delta);
2335
+ updateColorValue(s, true, delta);
2336
+ updateColorValue(l, true, delta);
2207
2337
  }
2208
2338
  function alterHsl(color, type, value) {
2209
2339
  return {
@@ -2319,7 +2449,7 @@
2319
2449
  }
2320
2450
 
2321
2451
  async function loadBlendPlugin(engine) {
2322
- engine.checkVersion("4.3.1");
2452
+ engine.checkVersion("4.4.0");
2323
2453
  await engine.pluginManager.register(e => {
2324
2454
  e.pluginManager.addPlugin(new BlendPlugin());
2325
2455
  });
@@ -2356,7 +2486,7 @@
2356
2486
  }
2357
2487
 
2358
2488
  async function loadCircleShape(engine) {
2359
- engine.checkVersion("4.3.1");
2489
+ engine.checkVersion("4.4.0");
2360
2490
  await engine.pluginManager.register(e => {
2361
2491
  e.pluginManager.addShape(["circle"], () => {
2362
2492
  return Promise.resolve(new CircleDrawer());
@@ -2404,7 +2534,7 @@
2404
2534
  }
2405
2535
 
2406
2536
  async function loadHexColorPlugin(engine) {
2407
- engine.checkVersion("4.3.1");
2537
+ engine.checkVersion("4.4.0");
2408
2538
  await engine.pluginManager.register(e => {
2409
2539
  e.pluginManager.addColorManager("hex", new HexColorManager());
2410
2540
  });
@@ -2457,7 +2587,7 @@
2457
2587
  }
2458
2588
 
2459
2589
  async function loadHslColorPlugin(engine) {
2460
- engine.checkVersion("4.3.1");
2590
+ engine.checkVersion("4.4.0");
2461
2591
  await engine.pluginManager.register(e => {
2462
2592
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2463
2593
  });
@@ -2481,7 +2611,7 @@
2481
2611
  }
2482
2612
 
2483
2613
  async function loadMovePlugin(engine) {
2484
- engine.checkVersion("4.3.1");
2614
+ engine.checkVersion("4.4.0");
2485
2615
  await engine.pluginManager.register(e => {
2486
2616
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2487
2617
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2691,7 +2821,7 @@
2691
2821
  }
2692
2822
 
2693
2823
  async function loadOpacityUpdater(engine) {
2694
- engine.checkVersion("4.3.1");
2824
+ engine.checkVersion("4.4.0");
2695
2825
  await engine.pluginManager.register(e => {
2696
2826
  e.pluginManager.addParticleUpdater("opacity", container => {
2697
2827
  return Promise.resolve(new OpacityUpdater(container));
@@ -3036,7 +3166,7 @@
3036
3166
  }
3037
3167
 
3038
3168
  async function loadOutModesUpdater(engine) {
3039
- engine.checkVersion("4.3.1");
3169
+ engine.checkVersion("4.4.0");
3040
3170
  await engine.pluginManager.register(e => {
3041
3171
  e.pluginManager.addParticleUpdater("outModes", container => {
3042
3172
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3107,7 +3237,7 @@
3107
3237
  }
3108
3238
 
3109
3239
  async function loadPaintUpdater(engine) {
3110
- engine.checkVersion("4.3.1");
3240
+ engine.checkVersion("4.4.0");
3111
3241
  await engine.pluginManager.register(e => {
3112
3242
  e.pluginManager.addParticleUpdater("paint", container => {
3113
3243
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3162,7 +3292,7 @@
3162
3292
  }
3163
3293
 
3164
3294
  async function loadRgbColorPlugin(engine) {
3165
- engine.checkVersion("4.3.1");
3295
+ engine.checkVersion("4.4.0");
3166
3296
  await engine.pluginManager.register(e => {
3167
3297
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3168
3298
  });
@@ -3247,7 +3377,7 @@
3247
3377
  }
3248
3378
 
3249
3379
  async function loadSizeUpdater(engine) {
3250
- engine.checkVersion("4.3.1");
3380
+ engine.checkVersion("4.4.0");
3251
3381
  await engine.pluginManager.register(e => {
3252
3382
  e.pluginManager.addParticleUpdater("size", container => {
3253
3383
  return Promise.resolve(new SizeUpdater(container));
@@ -3256,7 +3386,7 @@
3256
3386
  }
3257
3387
 
3258
3388
  async function loadBasic(engine) {
3259
- engine.checkVersion("4.3.1");
3389
+ engine.checkVersion("4.4.0");
3260
3390
  await engine.pluginManager.register(async (e) => {
3261
3391
  await Promise.all([
3262
3392
  loadBlendPlugin(e),
@@ -3457,7 +3587,7 @@
3457
3587
  const clickEvent = "click", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel";
3458
3588
 
3459
3589
  async function loadInteractivityPlugin(engine) {
3460
- engine.checkVersion("4.3.1");
3590
+ engine.checkVersion("4.4.0");
3461
3591
  await engine.pluginManager.register(e => {
3462
3592
  const interactivityEngine = e, interactivityPluginManager = interactivityEngine.pluginManager;
3463
3593
  interactivityPluginManager.addPlugin(new InteractivityPlugin(interactivityPluginManager));
@@ -3691,7 +3821,7 @@
3691
3821
  }
3692
3822
 
3693
3823
  async function loadParticlesCollisionsInteraction(engine) {
3694
- engine.checkVersion("4.3.1");
3824
+ engine.checkVersion("4.4.0");
3695
3825
  await engine.pluginManager.register((e) => {
3696
3826
  ensureInteractivityPluginLoaded(e);
3697
3827
  e.pluginManager.addPlugin(new OverlapPlugin());
@@ -3904,7 +4034,7 @@
3904
4034
  const linkColor = linksOptions.id !== undefined
3905
4035
  ? container.particles.linksColors.get(linksOptions.id)
3906
4036
  : container.particles.linksColor;
3907
- return getLinkColor(p1, p2, linkColor);
4037
+ return getLinkColor(p1, p2, linkColor, container.hdr);
3908
4038
  }
3909
4039
  #setColor(p1) {
3910
4040
  if (!p1.options.links) {
@@ -3945,7 +4075,7 @@
3945
4075
  }
3946
4076
 
3947
4077
  async function loadParticlesLinksInteraction(engine) {
3948
- engine.checkVersion("4.3.1");
4078
+ engine.checkVersion("4.4.0");
3949
4079
  await engine.pluginManager.register((e) => {
3950
4080
  const pluginManager = e.pluginManager;
3951
4081
  ensureInteractivityPluginLoaded(e);
@@ -3958,7 +4088,7 @@
3958
4088
 
3959
4089
  let initPromise = null;
3960
4090
  async function doInitPlugins(engine) {
3961
- engine.checkVersion("4.3.1");
4091
+ engine.checkVersion("4.4.0");
3962
4092
  await engine.pluginManager.register(async (e) => {
3963
4093
  const loadParticlesInteractivity = async (e) => {
3964
4094
  await loadInteractivityPlugin(e);
@@ -4001,7 +4131,7 @@
4001
4131
  particles.init = async () => {
4002
4132
  await initPlugins(tsParticles);
4003
4133
  };
4004
- particles.version = "4.3.1";
4134
+ particles.version = "4.4.0";
4005
4135
  globalThis.particles = particles;
4006
4136
 
4007
4137
  const globalObject = globalThis;
@@ -4126,7 +4256,11 @@
4126
4256
  if (!fColor && !sColor) {
4127
4257
  return;
4128
4258
  }
4129
- 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;
4259
+ 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
4260
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
4261
+ : undefined, stroke = sColor
4262
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
4263
+ : fill;
4130
4264
  transform.a = transform.b = transform.c = transform.d = undefined;
4131
4265
  colorStyles.fill = fill;
4132
4266
  colorStyles.stroke = stroke;
@@ -4460,7 +4594,9 @@
4460
4594
  if (typeof background.element === "string") {
4461
4595
  if (typeof document !== "undefined") {
4462
4596
  const node = document.querySelector(background.element);
4463
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4597
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4598
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4599
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4464
4600
  this.#backgroundElement = node;
4465
4601
  }
4466
4602
  else if (node) {
@@ -4471,10 +4607,10 @@
4471
4607
  }
4472
4608
  }
4473
4609
  }
4474
- else if (background.element instanceof HTMLCanvasElement ||
4475
- background.element instanceof OffscreenCanvas ||
4476
- background.element instanceof HTMLVideoElement ||
4477
- background.element instanceof HTMLImageElement) {
4610
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4611
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4612
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4613
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4478
4614
  this.#backgroundElement = background.element;
4479
4615
  }
4480
4616
  }
@@ -4542,6 +4678,7 @@
4542
4678
  zoom = defaultZoom;
4543
4679
  #container;
4544
4680
  #generated;
4681
+ #hdrMediaListeners;
4545
4682
  #mutationObserver;
4546
4683
  #originalStyle;
4547
4684
  #pluginManager;
@@ -4606,7 +4743,6 @@
4606
4743
  });
4607
4744
  this.resize();
4608
4745
  this.#initStyle();
4609
- this.initBackground();
4610
4746
  this.#safeMutationObserver(obs => {
4611
4747
  const element = this.domElement;
4612
4748
  if (!element || !(element instanceof Node)) {
@@ -4616,6 +4752,8 @@
4616
4752
  });
4617
4753
  this.initPlugins();
4618
4754
  this.#initContext();
4755
+ this.initBackground();
4756
+ this.#initHdrListeners();
4619
4757
  this.render.init();
4620
4758
  }
4621
4759
  initBackground() {
@@ -4625,7 +4763,8 @@
4625
4763
  }
4626
4764
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4627
4765
  if (color) {
4628
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4766
+ const hdrOptions = container.actualOptions.hdr;
4767
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4629
4768
  }
4630
4769
  else {
4631
4770
  elementStyle.backgroundColor = "";
@@ -4722,6 +4861,7 @@
4722
4861
  obs.disconnect();
4723
4862
  });
4724
4863
  this.#mutationObserver = undefined;
4864
+ this.#removeHdrListeners();
4725
4865
  this.render.stop();
4726
4866
  }
4727
4867
  async windowResize() {
@@ -4741,9 +4881,16 @@
4741
4881
  }
4742
4882
  }
4743
4883
  #initContext() {
4744
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4884
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4745
4885
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4746
4886
  safeMatchMedia("(dynamic-range: high)")?.matches;
4887
+ container.hdr = canSupportHdr ?? false;
4888
+ container.hdrMode = container.actualOptions.hdr.mode;
4889
+ container.peakNits = container.actualOptions.hdr.peakNits;
4890
+ const renderCanvas = this.renderCanvas;
4891
+ if (!renderCanvas) {
4892
+ return;
4893
+ }
4747
4894
  this.render.setContextSettings({
4748
4895
  alpha: true,
4749
4896
  desynchronized: true,
@@ -4752,11 +4899,47 @@
4752
4899
  ? { colorSpace: "display-p3", colorType: "float16" }
4753
4900
  : { colorSpace: "srgb" }),
4754
4901
  });
4755
- const renderCanvas = this.renderCanvas;
4756
- if (!renderCanvas) {
4757
- return;
4902
+ let context;
4903
+ try {
4904
+ context = renderCanvas.getContext("2d", this.render.settings);
4905
+ }
4906
+ catch {
4907
+ context = null;
4908
+ }
4909
+ if (canSupportHdr && !context) {
4910
+ container.hdr = false;
4911
+ const sdrSettings = {
4912
+ alpha: true,
4913
+ desynchronized: true,
4914
+ willReadFrequently: false,
4915
+ colorSpace: "srgb",
4916
+ };
4917
+ this.render.setContextSettings(sdrSettings);
4918
+ try {
4919
+ context = renderCanvas.getContext("2d", sdrSettings);
4920
+ }
4921
+ catch {
4922
+ context = null;
4923
+ }
4758
4924
  }
4759
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4925
+ this.render.setContext(context);
4926
+ }
4927
+ #initHdrListeners() {
4928
+ this.#removeHdrListeners();
4929
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4930
+ this.#recreateRenderCanvas();
4931
+ this.#initContext();
4932
+ this.initBackground();
4933
+ }, listeners = [];
4934
+ if (p3Query) {
4935
+ p3Query.addEventListener("change", handleChange);
4936
+ listeners.push({ handler: handleChange, mql: p3Query });
4937
+ }
4938
+ if (hdrQuery) {
4939
+ hdrQuery.addEventListener("change", handleChange);
4940
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4941
+ }
4942
+ this.#hdrMediaListeners = listeners;
4760
4943
  }
4761
4944
  #initStyle() {
4762
4945
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4780,6 +4963,25 @@
4780
4963
  element.style.setProperty(key, value, "important");
4781
4964
  }
4782
4965
  }
4966
+ #recreateRenderCanvas() {
4967
+ const renderCanvas = this.renderCanvas;
4968
+ if (!renderCanvas) {
4969
+ return;
4970
+ }
4971
+ if (this.domElement) {
4972
+ return;
4973
+ }
4974
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4975
+ }
4976
+ #removeHdrListeners() {
4977
+ if (!this.#hdrMediaListeners) {
4978
+ return;
4979
+ }
4980
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4981
+ mql.removeEventListener("change", handler);
4982
+ }
4983
+ this.#hdrMediaListeners = undefined;
4984
+ }
4783
4985
  #repairStyle() {
4784
4986
  const element = this.domElement;
4785
4987
  if (!element) {
@@ -5164,9 +5366,9 @@
5164
5366
  }
5165
5367
  getOpacity() {
5166
5368
  const zIndexOptions = this.options.zIndex, zIndexFactor = zIndexFactorOffset - this.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, baseOpacity = getRangeValue(this.opacity?.value ?? defaultOpacity$2), modifierOpacity = this.#applyModifiers(undefined, m => m.opacity), opacity = modifierOpacity ?? baseOpacity, fillOpacity = this.fillOpacity ?? defaultOpacity$2, strokeOpacity = this.strokeOpacity ?? defaultOpacity$2;
5167
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5369
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
5168
5370
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5169
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5371
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
5170
5372
  return this.#cachedOpacityData;
5171
5373
  }
5172
5374
  getPosition() {
@@ -6021,6 +6223,7 @@
6021
6223
  effectDrawers;
6022
6224
  fpsLimit;
6023
6225
  hdr;
6226
+ hdrMode;
6024
6227
  id;
6025
6228
  pageHidden;
6026
6229
  particleCreatedPlugins;
@@ -6028,6 +6231,7 @@
6028
6231
  particlePositionPlugins;
6029
6232
  particleUpdaters;
6030
6233
  particles;
6234
+ peakNits;
6031
6235
  plugins;
6032
6236
  retina;
6033
6237
  shapeDrawers;
@@ -6058,6 +6262,8 @@
6058
6262
  this.id = Symbol(id);
6059
6263
  this.fpsLimit = 120;
6060
6264
  this.hdr = false;
6265
+ this.hdrMode = exports.HdrMode.standard;
6266
+ this.peakNits = 400;
6061
6267
  this.#smooth = false;
6062
6268
  this.#delay = 0;
6063
6269
  this.#duration = 0;
@@ -6197,8 +6403,9 @@
6197
6403
  this.updateActualOptions();
6198
6404
  this.canvas.initBackground();
6199
6405
  this.canvas.resize();
6200
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
6201
- this.hdr = hdr;
6406
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6407
+ this.hdrMode = hdrOptions.mode;
6408
+ this.peakNits = hdrOptions.peakNits;
6202
6409
  this.zLayers = zLayers;
6203
6410
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
6204
6411
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -7385,10 +7592,10 @@
7385
7592
  }
7386
7593
  }
7387
7594
  #getCachedStyle(rgb) {
7388
- const key = `${rgb.r},${rgb.g},${rgb.b}`;
7595
+ const key = `${rgb.r},${rgb.g},${rgb.b}-${this.#container.hdr}-${this.#container.peakNits}-${this.#container.hdrMode}`;
7389
7596
  let style = this.#colorCache.get(key);
7390
7597
  if (!style) {
7391
- style = getStyleFromRgb(rgb, this.#container.hdr);
7598
+ style = getStyleFromRgb(rgb, this.#container.hdr, undefined, this.#container.peakNits, this.#container.hdrMode);
7392
7599
  this.#colorCache.set(key, style);
7393
7600
  }
7394
7601
  return style;
@@ -7415,6 +7622,7 @@
7415
7622
  exports.ColorAnimation = ColorAnimation;
7416
7623
  exports.Fill = Fill;
7417
7624
  exports.FullScreen = FullScreen;
7625
+ exports.HDROptions = HDROptions;
7418
7626
  exports.HslAnimation = HslAnimation;
7419
7627
  exports.Move = Move;
7420
7628
  exports.MoveAngle = MoveAngle;