@tsparticles/basic 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
- /* tsParticles v4.3.2 */
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) :
@@ -880,7 +880,7 @@
880
880
  return this.#domArray;
881
881
  }
882
882
  get version() {
883
- return "4.3.2";
883
+ return "4.4.0";
884
884
  }
885
885
  addEventListener(type, listener) {
886
886
  this.#eventDispatcher.addEventListener(type, listener);
@@ -961,6 +961,10 @@
961
961
  }
962
962
 
963
963
  function initEngine() {
964
+ const existing = globalThis.tsParticles;
965
+ if (existing?.pluginManager) {
966
+ return existing;
967
+ }
964
968
  return new Engine();
965
969
  }
966
970
 
@@ -1058,6 +1062,15 @@
1058
1062
  AnimationMode["random"] = "random";
1059
1063
  })(exports.AnimationMode || (exports.AnimationMode = {}));
1060
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
+
1061
1074
  exports.LimitMode = void 0;
1062
1075
  (function (LimitMode) {
1063
1076
  LimitMode["delete"] = "delete";
@@ -1323,6 +1336,29 @@
1323
1336
  }
1324
1337
  }
1325
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
+
1326
1362
  class ResizeEvent extends OptionLoader {
1327
1363
  delay = 0.5;
1328
1364
  enable = true;
@@ -1766,7 +1802,7 @@
1766
1802
  duration = 0;
1767
1803
  fpsLimit = 120;
1768
1804
  fullScreen;
1769
- hdr = true;
1805
+ hdr;
1770
1806
  key;
1771
1807
  name;
1772
1808
  palette;
@@ -1786,6 +1822,7 @@
1786
1822
  this.#container = container;
1787
1823
  this.background = new Background();
1788
1824
  this.fullScreen = new FullScreen();
1825
+ this.hdr = new HDROptions();
1789
1826
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1790
1827
  this.resize = new ResizeEvent();
1791
1828
  }
@@ -1808,7 +1845,15 @@
1808
1845
  loadProperty(this, "detectRetina", data.detectRetina);
1809
1846
  loadRangeProperty(this, "duration", data.duration);
1810
1847
  loadProperty(this, "fpsLimit", data.fpsLimit);
1811
- 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
+ }
1812
1857
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1813
1858
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1814
1859
  loadProperty(this, "zLayers", data.zLayers);
@@ -1851,7 +1896,7 @@
1851
1896
  }
1852
1897
  }
1853
1898
 
1854
- 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;
1855
1900
  function getCachedStyle(key, generator) {
1856
1901
  let cached = styleCache.get(key);
1857
1902
  if (!cached) {
@@ -1863,6 +1908,48 @@
1863
1908
  }
1864
1909
  return cached;
1865
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
+ }
1866
1953
  function stringToRgba(pluginManager, input) {
1867
1954
  if (!input) {
1868
1955
  return;
@@ -2030,30 +2117,65 @@
2030
2117
  r: getRgbInRangeValue(),
2031
2118
  };
2032
2119
  }
2033
- function getStyleFromRgb(color, hdr, opacity) {
2034
- 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()}`;
2035
- 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$1, 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));
2125
+ }
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$1).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);
2036
2137
  }
2037
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
2038
- const headroom = peakNits / sdrReferenceWhiteNits;
2039
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
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);
2040
2144
  }
2041
2145
  function getSdrStyleFromRgb(color, opacity) {
2042
2146
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
2043
2147
  }
2044
- function getStyleFromHsl(color, hdr, opacity) {
2045
- 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()}`;
2148
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2149
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, 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()}`;
2046
2152
  return getCachedStyle(key, () => hdr
2047
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2153
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
2048
2154
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
2049
2155
  }
2050
- function colorMix(color1, color2, size1, size2) {
2156
+ function colorMix(color1, color2, size1, size2, hdr) {
2051
2157
  let rgb1 = color1, rgb2 = color2;
2052
2158
  if (!("r" in rgb1)) {
2053
- rgb1 = hslToRgb(color1);
2159
+ rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
2054
2160
  }
2055
2161
  if (!("r" in rgb2)) {
2056
- 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
+ };
2057
2179
  }
2058
2180
  return {
2059
2181
  b: mix(rgb1.b, rgb2.b, size1, size2),
@@ -2061,14 +2183,14 @@
2061
2183
  r: mix(rgb1.r, rgb2.r, size1, size2),
2062
2184
  };
2063
2185
  }
2064
- function getLinkColor(p1, p2, linkColor) {
2186
+ function getLinkColor(p1, p2, linkColor, hdr) {
2065
2187
  if (linkColor === randomColorValue) {
2066
2188
  return getRandomRgbColor();
2067
2189
  }
2068
2190
  else if (linkColor === midColorValue) {
2069
2191
  const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
2070
2192
  if (sourceColor && destColor && p2) {
2071
- return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius());
2193
+ return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
2072
2194
  }
2073
2195
  else {
2074
2196
  const hslColor = sourceColor ?? destColor;
@@ -2164,7 +2286,7 @@
2164
2286
  colorValue.velocity = defaultVelocity;
2165
2287
  }
2166
2288
  }
2167
- function updateColorValue(data, decrease, delta, hdr) {
2289
+ function updateColorValue(data, decrease, delta, _hdr) {
2168
2290
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2169
2291
  if (!data.enable ||
2170
2292
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2177,7 +2299,7 @@
2177
2299
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2178
2300
  return;
2179
2301
  }
2180
- 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;
2181
2303
  if (!decrease || data.status === exports.AnimationStatus.increasing) {
2182
2304
  data.value += velocity;
2183
2305
  if (data.value > max) {
@@ -2209,9 +2331,9 @@
2209
2331
  return;
2210
2332
  }
2211
2333
  const { h, s, l } = color;
2212
- updateColorValue(h, false, delta, hdr);
2213
- updateColorValue(s, true, delta, hdr);
2214
- updateColorValue(l, true, delta, hdr);
2334
+ updateColorValue(h, false, delta);
2335
+ updateColorValue(s, true, delta);
2336
+ updateColorValue(l, true, delta);
2215
2337
  }
2216
2338
  function alterHsl(color, type, value) {
2217
2339
  return {
@@ -2261,7 +2383,7 @@
2261
2383
  }
2262
2384
 
2263
2385
  async function loadBlendPlugin(engine) {
2264
- engine.checkVersion("4.3.2");
2386
+ engine.checkVersion("4.4.0");
2265
2387
  await engine.pluginManager.register(e => {
2266
2388
  e.pluginManager.addPlugin(new BlendPlugin());
2267
2389
  });
@@ -2298,7 +2420,7 @@
2298
2420
  }
2299
2421
 
2300
2422
  async function loadCircleShape(engine) {
2301
- engine.checkVersion("4.3.2");
2423
+ engine.checkVersion("4.4.0");
2302
2424
  await engine.pluginManager.register(e => {
2303
2425
  e.pluginManager.addShape(["circle"], () => {
2304
2426
  return Promise.resolve(new CircleDrawer());
@@ -2346,7 +2468,7 @@
2346
2468
  }
2347
2469
 
2348
2470
  async function loadHexColorPlugin(engine) {
2349
- engine.checkVersion("4.3.2");
2471
+ engine.checkVersion("4.4.0");
2350
2472
  await engine.pluginManager.register(e => {
2351
2473
  e.pluginManager.addColorManager("hex", new HexColorManager());
2352
2474
  });
@@ -2399,7 +2521,7 @@
2399
2521
  }
2400
2522
 
2401
2523
  async function loadHslColorPlugin(engine) {
2402
- engine.checkVersion("4.3.2");
2524
+ engine.checkVersion("4.4.0");
2403
2525
  await engine.pluginManager.register(e => {
2404
2526
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2405
2527
  });
@@ -2423,7 +2545,7 @@
2423
2545
  }
2424
2546
 
2425
2547
  async function loadMovePlugin(engine) {
2426
- engine.checkVersion("4.3.2");
2548
+ engine.checkVersion("4.4.0");
2427
2549
  await engine.pluginManager.register(e => {
2428
2550
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2429
2551
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2633,7 +2755,7 @@
2633
2755
  }
2634
2756
 
2635
2757
  async function loadOpacityUpdater(engine) {
2636
- engine.checkVersion("4.3.2");
2758
+ engine.checkVersion("4.4.0");
2637
2759
  await engine.pluginManager.register(e => {
2638
2760
  e.pluginManager.addParticleUpdater("opacity", container => {
2639
2761
  return Promise.resolve(new OpacityUpdater(container));
@@ -2978,7 +3100,7 @@
2978
3100
  }
2979
3101
 
2980
3102
  async function loadOutModesUpdater(engine) {
2981
- engine.checkVersion("4.3.2");
3103
+ engine.checkVersion("4.4.0");
2982
3104
  await engine.pluginManager.register(e => {
2983
3105
  e.pluginManager.addParticleUpdater("outModes", container => {
2984
3106
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -3049,7 +3171,7 @@
3049
3171
  }
3050
3172
 
3051
3173
  async function loadPaintUpdater(engine) {
3052
- engine.checkVersion("4.3.2");
3174
+ engine.checkVersion("4.4.0");
3053
3175
  await engine.pluginManager.register(e => {
3054
3176
  e.pluginManager.addParticleUpdater("paint", container => {
3055
3177
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -3104,7 +3226,7 @@
3104
3226
  }
3105
3227
 
3106
3228
  async function loadRgbColorPlugin(engine) {
3107
- engine.checkVersion("4.3.2");
3229
+ engine.checkVersion("4.4.0");
3108
3230
  await engine.pluginManager.register(e => {
3109
3231
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
3110
3232
  });
@@ -3189,7 +3311,7 @@
3189
3311
  }
3190
3312
 
3191
3313
  async function loadSizeUpdater(engine) {
3192
- engine.checkVersion("4.3.2");
3314
+ engine.checkVersion("4.4.0");
3193
3315
  await engine.pluginManager.register(e => {
3194
3316
  e.pluginManager.addParticleUpdater("size", container => {
3195
3317
  return Promise.resolve(new SizeUpdater(container));
@@ -3198,7 +3320,7 @@
3198
3320
  }
3199
3321
 
3200
3322
  async function loadBasic(engine) {
3201
- engine.checkVersion("4.3.2");
3323
+ engine.checkVersion("4.4.0");
3202
3324
  await engine.pluginManager.register(async (e) => {
3203
3325
  await Promise.all([
3204
3326
  loadBlendPlugin(e),
@@ -3337,7 +3459,11 @@
3337
3459
  if (!fColor && !sColor) {
3338
3460
  return;
3339
3461
  }
3340
- 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;
3462
+ 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
3463
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
3464
+ : undefined, stroke = sColor
3465
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
3466
+ : fill;
3341
3467
  transform.a = transform.b = transform.c = transform.d = undefined;
3342
3468
  colorStyles.fill = fill;
3343
3469
  colorStyles.stroke = stroke;
@@ -3671,7 +3797,9 @@
3671
3797
  if (typeof background.element === "string") {
3672
3798
  if (typeof document !== "undefined") {
3673
3799
  const node = document.querySelector(background.element);
3674
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
3800
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
3801
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
3802
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
3675
3803
  this.#backgroundElement = node;
3676
3804
  }
3677
3805
  else if (node) {
@@ -3682,10 +3810,10 @@
3682
3810
  }
3683
3811
  }
3684
3812
  }
3685
- else if (background.element instanceof HTMLCanvasElement ||
3686
- background.element instanceof OffscreenCanvas ||
3687
- background.element instanceof HTMLVideoElement ||
3688
- background.element instanceof HTMLImageElement) {
3813
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
3814
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
3815
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
3816
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
3689
3817
  this.#backgroundElement = background.element;
3690
3818
  }
3691
3819
  }
@@ -3753,6 +3881,7 @@
3753
3881
  zoom = defaultZoom;
3754
3882
  #container;
3755
3883
  #generated;
3884
+ #hdrMediaListeners;
3756
3885
  #mutationObserver;
3757
3886
  #originalStyle;
3758
3887
  #pluginManager;
@@ -3817,7 +3946,6 @@
3817
3946
  });
3818
3947
  this.resize();
3819
3948
  this.#initStyle();
3820
- this.initBackground();
3821
3949
  this.#safeMutationObserver(obs => {
3822
3950
  const element = this.domElement;
3823
3951
  if (!element || !(element instanceof Node)) {
@@ -3827,6 +3955,8 @@
3827
3955
  });
3828
3956
  this.initPlugins();
3829
3957
  this.#initContext();
3958
+ this.initBackground();
3959
+ this.#initHdrListeners();
3830
3960
  this.render.init();
3831
3961
  }
3832
3962
  initBackground() {
@@ -3836,7 +3966,8 @@
3836
3966
  }
3837
3967
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
3838
3968
  if (color) {
3839
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
3969
+ const hdrOptions = container.actualOptions.hdr;
3970
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
3840
3971
  }
3841
3972
  else {
3842
3973
  elementStyle.backgroundColor = "";
@@ -3933,6 +4064,7 @@
3933
4064
  obs.disconnect();
3934
4065
  });
3935
4066
  this.#mutationObserver = undefined;
4067
+ this.#removeHdrListeners();
3936
4068
  this.render.stop();
3937
4069
  }
3938
4070
  async windowResize() {
@@ -3952,9 +4084,16 @@
3952
4084
  }
3953
4085
  }
3954
4086
  #initContext() {
3955
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4087
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
3956
4088
  safeMatchMedia("(color-gamut: p3)")?.matches &&
3957
4089
  safeMatchMedia("(dynamic-range: high)")?.matches;
4090
+ container.hdr = canSupportHdr ?? false;
4091
+ container.hdrMode = container.actualOptions.hdr.mode;
4092
+ container.peakNits = container.actualOptions.hdr.peakNits;
4093
+ const renderCanvas = this.renderCanvas;
4094
+ if (!renderCanvas) {
4095
+ return;
4096
+ }
3958
4097
  this.render.setContextSettings({
3959
4098
  alpha: true,
3960
4099
  desynchronized: true,
@@ -3963,11 +4102,47 @@
3963
4102
  ? { colorSpace: "display-p3", colorType: "float16" }
3964
4103
  : { colorSpace: "srgb" }),
3965
4104
  });
3966
- const renderCanvas = this.renderCanvas;
3967
- if (!renderCanvas) {
3968
- return;
4105
+ let context;
4106
+ try {
4107
+ context = renderCanvas.getContext("2d", this.render.settings);
4108
+ }
4109
+ catch {
4110
+ context = null;
4111
+ }
4112
+ if (canSupportHdr && !context) {
4113
+ container.hdr = false;
4114
+ const sdrSettings = {
4115
+ alpha: true,
4116
+ desynchronized: true,
4117
+ willReadFrequently: false,
4118
+ colorSpace: "srgb",
4119
+ };
4120
+ this.render.setContextSettings(sdrSettings);
4121
+ try {
4122
+ context = renderCanvas.getContext("2d", sdrSettings);
4123
+ }
4124
+ catch {
4125
+ context = null;
4126
+ }
4127
+ }
4128
+ this.render.setContext(context);
4129
+ }
4130
+ #initHdrListeners() {
4131
+ this.#removeHdrListeners();
4132
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
4133
+ this.#recreateRenderCanvas();
4134
+ this.#initContext();
4135
+ this.initBackground();
4136
+ }, listeners = [];
4137
+ if (p3Query) {
4138
+ p3Query.addEventListener("change", handleChange);
4139
+ listeners.push({ handler: handleChange, mql: p3Query });
3969
4140
  }
3970
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
4141
+ if (hdrQuery) {
4142
+ hdrQuery.addEventListener("change", handleChange);
4143
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4144
+ }
4145
+ this.#hdrMediaListeners = listeners;
3971
4146
  }
3972
4147
  #initStyle() {
3973
4148
  const element = this.domElement, options = this.#container.actualOptions;
@@ -3991,6 +4166,25 @@
3991
4166
  element.style.setProperty(key, value, "important");
3992
4167
  }
3993
4168
  }
4169
+ #recreateRenderCanvas() {
4170
+ const renderCanvas = this.renderCanvas;
4171
+ if (!renderCanvas) {
4172
+ return;
4173
+ }
4174
+ if (this.domElement) {
4175
+ return;
4176
+ }
4177
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
4178
+ }
4179
+ #removeHdrListeners() {
4180
+ if (!this.#hdrMediaListeners) {
4181
+ return;
4182
+ }
4183
+ for (const { handler, mql } of this.#hdrMediaListeners) {
4184
+ mql.removeEventListener("change", handler);
4185
+ }
4186
+ this.#hdrMediaListeners = undefined;
4187
+ }
3994
4188
  #repairStyle() {
3995
4189
  const element = this.domElement;
3996
4190
  if (!element) {
@@ -4375,9 +4569,9 @@
4375
4569
  }
4376
4570
  getOpacity() {
4377
4571
  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;
4378
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
4572
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
4379
4573
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
4380
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
4574
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
4381
4575
  return this.#cachedOpacityData;
4382
4576
  }
4383
4577
  getPosition() {
@@ -5232,6 +5426,7 @@
5232
5426
  effectDrawers;
5233
5427
  fpsLimit;
5234
5428
  hdr;
5429
+ hdrMode;
5235
5430
  id;
5236
5431
  pageHidden;
5237
5432
  particleCreatedPlugins;
@@ -5239,6 +5434,7 @@
5239
5434
  particlePositionPlugins;
5240
5435
  particleUpdaters;
5241
5436
  particles;
5437
+ peakNits;
5242
5438
  plugins;
5243
5439
  retina;
5244
5440
  shapeDrawers;
@@ -5269,6 +5465,8 @@
5269
5465
  this.id = Symbol(id);
5270
5466
  this.fpsLimit = 120;
5271
5467
  this.hdr = false;
5468
+ this.hdrMode = exports.HdrMode.standard;
5469
+ this.peakNits = 400;
5272
5470
  this.#smooth = false;
5273
5471
  this.#delay = 0;
5274
5472
  this.#duration = 0;
@@ -5408,8 +5606,9 @@
5408
5606
  this.updateActualOptions();
5409
5607
  this.canvas.initBackground();
5410
5608
  this.canvas.resize();
5411
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
5412
- this.hdr = hdr;
5609
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
5610
+ this.hdrMode = hdrOptions.mode;
5611
+ this.peakNits = hdrOptions.peakNits;
5413
5612
  this.zLayers = zLayers;
5414
5613
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
5415
5614
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;
@@ -5844,6 +6043,7 @@
5844
6043
  exports.ColorAnimation = ColorAnimation;
5845
6044
  exports.Fill = Fill;
5846
6045
  exports.FullScreen = FullScreen;
6046
+ exports.HDROptions = HDROptions;
5847
6047
  exports.HslAnimation = HslAnimation;
5848
6048
  exports.Move = Move;
5849
6049
  exports.MoveAngle = MoveAngle;