@tsparticles/preset-confetti 4.3.2 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  (function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
2
- /* Preset v4.3.2 */
2
+ /* Preset v4.4.0 */
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
5
5
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -810,7 +810,7 @@
810
810
  return this.#domArray;
811
811
  }
812
812
  get version() {
813
- return "4.3.2";
813
+ return "4.4.0";
814
814
  }
815
815
  addEventListener(type, listener) {
816
816
  this.#eventDispatcher.addEventListener(type, listener);
@@ -891,6 +891,10 @@
891
891
  }
892
892
 
893
893
  function initEngine() {
894
+ const existing = globalThis.tsParticles;
895
+ if (existing?.pluginManager) {
896
+ return existing;
897
+ }
894
898
  return new Engine();
895
899
  }
896
900
 
@@ -988,6 +992,15 @@
988
992
  AnimationMode["random"] = "random";
989
993
  })(AnimationMode || (AnimationMode = {}));
990
994
 
995
+ var HdrMode;
996
+ (function (HdrMode) {
997
+ HdrMode["standard"] = "standard";
998
+ HdrMode["natural"] = "natural";
999
+ HdrMode["vivid"] = "vivid";
1000
+ HdrMode["cinematic"] = "cinematic";
1001
+ HdrMode["dynamic"] = "dynamic";
1002
+ })(HdrMode || (HdrMode = {}));
1003
+
991
1004
  var LimitMode;
992
1005
  (function (LimitMode) {
993
1006
  LimitMode["delete"] = "delete";
@@ -1243,6 +1256,29 @@
1243
1256
  }
1244
1257
  }
1245
1258
 
1259
+ const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
1260
+ class HDROptions extends OptionLoader {
1261
+ enable = true;
1262
+ mode = HdrMode.standard;
1263
+ peakNits = defaultPeakNits;
1264
+ doLoad(data) {
1265
+ if (data.enable !== undefined && !isBoolean(data.enable)) {
1266
+ throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
1267
+ }
1268
+ if (data.mode !== undefined &&
1269
+ (typeof data.mode !== "string" || !Object.values(HdrMode).includes(data.mode))) {
1270
+ throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
1271
+ }
1272
+ if (data.peakNits !== undefined &&
1273
+ (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
1274
+ throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
1275
+ }
1276
+ loadProperty(this, "enable", data.enable);
1277
+ loadProperty(this, "mode", data.mode);
1278
+ loadProperty(this, "peakNits", data.peakNits);
1279
+ }
1280
+ }
1281
+
1246
1282
  class ResizeEvent extends OptionLoader {
1247
1283
  delay = 0.5;
1248
1284
  enable = true;
@@ -1686,7 +1722,7 @@
1686
1722
  duration = 0;
1687
1723
  fpsLimit = 120;
1688
1724
  fullScreen;
1689
- hdr = true;
1725
+ hdr;
1690
1726
  key;
1691
1727
  name;
1692
1728
  palette;
@@ -1706,6 +1742,7 @@
1706
1742
  this.#container = container;
1707
1743
  this.background = new Background();
1708
1744
  this.fullScreen = new FullScreen();
1745
+ this.hdr = new HDROptions();
1709
1746
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1710
1747
  this.resize = new ResizeEvent();
1711
1748
  }
@@ -1728,7 +1765,15 @@
1728
1765
  loadProperty(this, "detectRetina", data.detectRetina);
1729
1766
  loadRangeProperty(this, "duration", data.duration);
1730
1767
  loadProperty(this, "fpsLimit", data.fpsLimit);
1731
- loadProperty(this, "hdr", data.hdr);
1768
+ const hdrData = data.hdr;
1769
+ if (isBoolean(hdrData)) {
1770
+ this.hdr.enable = hdrData;
1771
+ this.hdr.mode = HdrMode.standard;
1772
+ this.hdr.peakNits = 400;
1773
+ }
1774
+ else {
1775
+ this.hdr.load(hdrData);
1776
+ }
1732
1777
  loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
1733
1778
  loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
1734
1779
  loadProperty(this, "zLayers", data.zLayers);
@@ -1771,7 +1816,7 @@
1771
1816
  }
1772
1817
  }
1773
1818
 
1774
- const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, hdrAnimationScale = sdrReferenceWhiteNits / maxNits;
1819
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, hdrRgbFixedPrecision = 4, hdrHslFixedPrecision = 4, sdrReferenceWhiteNits = 203, acesA = 2.51, acesB = 0.03, acesC = 2.43, acesD = 0.59, acesE = 0.14, saturationBoost = 1.15, lightnessBoost = 1.05, temperatureR = 1.05, temperatureB = 0.95, contrastFactor = 1.1, luminanceR = 0.2126, luminanceG = 0.7152, luminanceB = 0.0722, dynamicLuminanceFactor = 2, channelCount = 3;
1775
1820
  function getCachedStyle(key, generator) {
1776
1821
  let cached = styleCache.get(key);
1777
1822
  if (!cached) {
@@ -1783,6 +1828,42 @@
1783
1828
  }
1784
1829
  return cached;
1785
1830
  }
1831
+ function acesFilmic(x) {
1832
+ return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
1833
+ }
1834
+ function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
1835
+ switch (mode) {
1836
+ case HdrMode.vivid: {
1837
+ const avg = (r + g + b) / channelCount;
1838
+ return {
1839
+ b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1840
+ g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1841
+ r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
1842
+ };
1843
+ }
1844
+ case HdrMode.cinematic: {
1845
+ const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
1846
+ return {
1847
+ b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
1848
+ g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
1849
+ r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
1850
+ };
1851
+ }
1852
+ case HdrMode.dynamic: {
1853
+ const luminance = luminanceR * r + luminanceG * g + luminanceB * b, vividWeight = Math.min(one, luminance * dynamicLuminanceFactor), naturalWeight = one - vividWeight, avg = (r + g + b) / channelCount, vividR = clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, vividG = clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, vividB = clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost;
1854
+ return {
1855
+ b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
1856
+ g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
1857
+ r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
1858
+ };
1859
+ }
1860
+ case HdrMode.standard:
1861
+ return { b, g, r };
1862
+ case HdrMode.natural:
1863
+ default:
1864
+ return { b, g, r };
1865
+ }
1866
+ }
1786
1867
  function stringToRgba(pluginManager, input) {
1787
1868
  if (!input) {
1788
1869
  return;
@@ -1940,21 +2021,40 @@
1940
2021
  r: getRgbInRangeValue(),
1941
2022
  };
1942
2023
  }
1943
- function getStyleFromRgb(color, hdr, opacity) {
1944
- const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1945
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
2024
+ function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
2025
+ const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2026
+ ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2027
+ : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
2028
+ return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
2029
+ }
2030
+ function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = HdrMode.standard) {
2031
+ const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
2032
+ return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
1946
2033
  }
1947
- function getHdrStyleFromRgb(color, opacity, peakNits = maxNits) {
1948
- const headroom = peakNits / sdrReferenceWhiteNits;
1949
- return `color(display-p3 ${((color.r / rgbMax) * headroom).toString()} ${((color.g / rgbMax) * headroom).toString()} ${((color.b / rgbMax) * headroom).toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
2034
+ function hdrToneMapColor(color, headroom, middleGray, mode) {
2035
+ const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
2036
+ if (mode !== HdrMode.natural && mode !== HdrMode.vivid && mode !== HdrMode.cinematic && mode !== HdrMode.dynamic) {
2037
+ return { b: bNorm, g: gNorm, r: rNorm };
2038
+ }
2039
+ const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
2040
+ return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
2041
+ }
2042
+ function hdrToneMap(normalized, headroom, middleGray) {
2043
+ if (normalized <= middleGray) {
2044
+ return acesFilmic(normalized);
2045
+ }
2046
+ const expanded = normalized + (normalized - middleGray) * (headroom - one);
2047
+ return acesFilmic(expanded);
1950
2048
  }
1951
2049
  function getSdrStyleFromRgb(color, opacity) {
1952
2050
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
1953
2051
  }
1954
- function getStyleFromHsl(color, hdr, opacity) {
1955
- const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
2052
+ function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
2053
+ const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
2054
+ ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? HdrMode.standard}`
2055
+ : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
1956
2056
  return getCachedStyle(key, () => hdr
1957
- ? getStyleFromRgb(hslToRgbFloat(color), true, opacity)
2057
+ ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
1958
2058
  : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1959
2059
  }
1960
2060
  function getHslFromAnimation(animation) {
@@ -2017,7 +2117,7 @@
2017
2117
  colorValue.velocity = defaultVelocity;
2018
2118
  }
2019
2119
  }
2020
- function updateColorValue(data, decrease, delta, hdr) {
2120
+ function updateColorValue(data, decrease, delta, _hdr) {
2021
2121
  const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
2022
2122
  if (!data.enable ||
2023
2123
  ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
@@ -2030,7 +2130,7 @@
2030
2130
  if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
2031
2131
  return;
2032
2132
  }
2033
- const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = ((data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor) * (hdr ? hdrAnimationScale : identity), decay = data.decay ?? identity, max = data.max, min = data.min;
2133
+ const offset = data.offset ? randomInRangeValue(data.offset) : minOffset, velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor, decay = data.decay ?? identity, max = data.max, min = data.min;
2034
2134
  if (!decrease || data.status === AnimationStatus.increasing) {
2035
2135
  data.value += velocity;
2036
2136
  if (data.value > max) {
@@ -2062,9 +2162,9 @@
2062
2162
  return;
2063
2163
  }
2064
2164
  const { h, s, l } = color;
2065
- updateColorValue(h, false, delta, hdr);
2066
- updateColorValue(s, true, delta, hdr);
2067
- updateColorValue(l, true, delta, hdr);
2165
+ updateColorValue(h, false, delta);
2166
+ updateColorValue(s, true, delta);
2167
+ updateColorValue(l, true, delta);
2068
2168
  }
2069
2169
  function alterHsl(color, type, value) {
2070
2170
  return {
@@ -2114,7 +2214,7 @@
2114
2214
  }
2115
2215
 
2116
2216
  async function loadBlendPlugin(engine) {
2117
- engine.checkVersion("4.3.2");
2217
+ engine.checkVersion("4.4.0");
2118
2218
  await engine.pluginManager.register(e => {
2119
2219
  e.pluginManager.addPlugin(new BlendPlugin());
2120
2220
  });
@@ -2151,7 +2251,7 @@
2151
2251
  }
2152
2252
 
2153
2253
  async function loadCircleShape(engine) {
2154
- engine.checkVersion("4.3.2");
2254
+ engine.checkVersion("4.4.0");
2155
2255
  await engine.pluginManager.register(e => {
2156
2256
  e.pluginManager.addShape(["circle"], () => {
2157
2257
  return Promise.resolve(new CircleDrawer());
@@ -2199,7 +2299,7 @@
2199
2299
  }
2200
2300
 
2201
2301
  async function loadHexColorPlugin(engine) {
2202
- engine.checkVersion("4.3.2");
2302
+ engine.checkVersion("4.4.0");
2203
2303
  await engine.pluginManager.register(e => {
2204
2304
  e.pluginManager.addColorManager("hex", new HexColorManager());
2205
2305
  });
@@ -2252,7 +2352,7 @@
2252
2352
  }
2253
2353
 
2254
2354
  async function loadHslColorPlugin(engine) {
2255
- engine.checkVersion("4.3.2");
2355
+ engine.checkVersion("4.4.0");
2256
2356
  await engine.pluginManager.register(e => {
2257
2357
  e.pluginManager.addColorManager("hsl", new HslColorManager());
2258
2358
  });
@@ -2276,7 +2376,7 @@
2276
2376
  }
2277
2377
 
2278
2378
  async function loadMovePlugin(engine) {
2279
- engine.checkVersion("4.3.2");
2379
+ engine.checkVersion("4.4.0");
2280
2380
  await engine.pluginManager.register(e => {
2281
2381
  const moveEngine = e, movePluginManager = moveEngine.pluginManager;
2282
2382
  movePluginManager.initializers.pathGenerators ??= new Map();
@@ -2492,7 +2592,7 @@
2492
2592
  }
2493
2593
 
2494
2594
  async function loadOpacityUpdater(engine) {
2495
- engine.checkVersion("4.3.2");
2595
+ engine.checkVersion("4.4.0");
2496
2596
  await engine.pluginManager.register(e => {
2497
2597
  e.pluginManager.addParticleUpdater("opacity", container => {
2498
2598
  return Promise.resolve(new OpacityUpdater(container));
@@ -2837,7 +2937,7 @@
2837
2937
  }
2838
2938
 
2839
2939
  async function loadOutModesUpdater(engine) {
2840
- engine.checkVersion("4.3.2");
2940
+ engine.checkVersion("4.4.0");
2841
2941
  await engine.pluginManager.register(e => {
2842
2942
  e.pluginManager.addParticleUpdater("outModes", container => {
2843
2943
  return Promise.resolve(new OutOfCanvasUpdater(container));
@@ -2908,7 +3008,7 @@
2908
3008
  }
2909
3009
 
2910
3010
  async function loadPaintUpdater(engine) {
2911
- engine.checkVersion("4.3.2");
3011
+ engine.checkVersion("4.4.0");
2912
3012
  await engine.pluginManager.register(e => {
2913
3013
  e.pluginManager.addParticleUpdater("paint", container => {
2914
3014
  return Promise.resolve(new PaintUpdater(e.pluginManager, container));
@@ -2963,7 +3063,7 @@
2963
3063
  }
2964
3064
 
2965
3065
  async function loadRgbColorPlugin(engine) {
2966
- engine.checkVersion("4.3.2");
3066
+ engine.checkVersion("4.4.0");
2967
3067
  await engine.pluginManager.register(e => {
2968
3068
  e.pluginManager.addColorManager("rgb", new RgbColorManager());
2969
3069
  });
@@ -3048,7 +3148,7 @@
3048
3148
  }
3049
3149
 
3050
3150
  async function loadSizeUpdater(engine) {
3051
- engine.checkVersion("4.3.2");
3151
+ engine.checkVersion("4.4.0");
3052
3152
  await engine.pluginManager.register(e => {
3053
3153
  e.pluginManager.addParticleUpdater("size", container => {
3054
3154
  return Promise.resolve(new SizeUpdater(container));
@@ -3057,7 +3157,7 @@
3057
3157
  }
3058
3158
 
3059
3159
  async function loadBasic(engine) {
3060
- engine.checkVersion("4.3.2");
3160
+ engine.checkVersion("4.4.0");
3061
3161
  await engine.pluginManager.register(async (e) => {
3062
3162
  await Promise.all([
3063
3163
  loadBlendPlugin(e),
@@ -3310,7 +3410,7 @@
3310
3410
  })(EmitterClickMode || (EmitterClickMode = {}));
3311
3411
 
3312
3412
  async function loadEmittersPluginSimple(engine) {
3313
- engine.checkVersion("4.3.2");
3413
+ engine.checkVersion("4.4.0");
3314
3414
  await engine.pluginManager.register(async (e) => {
3315
3415
  const instancesManager = await getEmittersInstancesManager(e);
3316
3416
  await addEmittersShapesManager(e);
@@ -3455,7 +3555,7 @@
3455
3555
  }
3456
3556
 
3457
3557
  async function loadLifeUpdater(engine) {
3458
- engine.checkVersion("4.3.2");
3558
+ engine.checkVersion("4.4.0");
3459
3559
  await engine.pluginManager.register(e => {
3460
3560
  e.pluginManager.addParticleUpdater("life", container => {
3461
3561
  return Promise.resolve(new LifeUpdater(container));
@@ -3509,7 +3609,7 @@
3509
3609
  }
3510
3610
 
3511
3611
  async function loadMotionPlugin(engine) {
3512
- engine.checkVersion("4.3.2");
3612
+ engine.checkVersion("4.4.0");
3513
3613
  await engine.pluginManager.register(e => {
3514
3614
  e.pluginManager.addPlugin(new MotionPlugin());
3515
3615
  });
@@ -3642,7 +3742,7 @@
3642
3742
  }
3643
3743
 
3644
3744
  async function loadRollUpdater(engine) {
3645
- engine.checkVersion("4.3.2");
3745
+ engine.checkVersion("4.4.0");
3646
3746
  await engine.pluginManager.register(e => {
3647
3747
  e.pluginManager.addParticleUpdater("roll", () => {
3648
3748
  return Promise.resolve(new RollUpdater(e.pluginManager));
@@ -3748,7 +3848,7 @@
3748
3848
  }
3749
3849
 
3750
3850
  async function loadRotateUpdater(engine) {
3751
- engine.checkVersion("4.3.2");
3851
+ engine.checkVersion("4.4.0");
3752
3852
  await engine.pluginManager.register(e => {
3753
3853
  e.pluginManager.addParticleUpdater("rotate", container => {
3754
3854
  return Promise.resolve(new RotateUpdater(container));
@@ -3772,7 +3872,7 @@
3772
3872
  }
3773
3873
 
3774
3874
  async function loadSquareShape(engine) {
3775
- engine.checkVersion("4.3.2");
3875
+ engine.checkVersion("4.4.0");
3776
3876
  await engine.pluginManager.register(e => {
3777
3877
  e.pluginManager.addShape(["edge", "square"], () => Promise.resolve(new SquareDrawer()));
3778
3878
  });
@@ -3881,7 +3981,7 @@
3881
3981
  }
3882
3982
 
3883
3983
  async function loadTiltUpdater(engine) {
3884
- engine.checkVersion("4.3.2");
3984
+ engine.checkVersion("4.4.0");
3885
3985
  await engine.pluginManager.register(e => {
3886
3986
  e.pluginManager.addParticleUpdater("tilt", container => {
3887
3987
  return Promise.resolve(new TiltUpdater(container));
@@ -3983,7 +4083,7 @@
3983
4083
  }
3984
4084
 
3985
4085
  async function loadWobbleUpdater(engine) {
3986
- engine.checkVersion("4.3.2");
4086
+ engine.checkVersion("4.4.0");
3987
4087
  await engine.pluginManager.register(e => {
3988
4088
  e.pluginManager.addParticleUpdater("wobble", container => {
3989
4089
  return Promise.resolve(new WobbleUpdater(container));
@@ -4262,7 +4362,11 @@
4262
4362
  if (!fColor && !sColor) {
4263
4363
  return;
4264
4364
  }
4265
- 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;
4365
+ 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
4366
+ ? getStyleFromHsl(fColor, container.hdr, fillOpacity * opacity, container.peakNits, container.hdrMode)
4367
+ : undefined, stroke = sColor
4368
+ ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
4369
+ : fill;
4266
4370
  transform.a = transform.b = transform.c = transform.d = undefined;
4267
4371
  colorStyles.fill = fill;
4268
4372
  colorStyles.stroke = stroke;
@@ -4596,7 +4700,9 @@
4596
4700
  if (typeof background.element === "string") {
4597
4701
  if (typeof document !== "undefined") {
4598
4702
  const node = document.querySelector(background.element);
4599
- if (node instanceof HTMLCanvasElement || node instanceof HTMLVideoElement || node instanceof HTMLImageElement) {
4703
+ if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
4704
+ (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
4705
+ (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
4600
4706
  this.#backgroundElement = node;
4601
4707
  }
4602
4708
  else if (node) {
@@ -4607,10 +4713,10 @@
4607
4713
  }
4608
4714
  }
4609
4715
  }
4610
- else if (background.element instanceof HTMLCanvasElement ||
4611
- background.element instanceof OffscreenCanvas ||
4612
- background.element instanceof HTMLVideoElement ||
4613
- background.element instanceof HTMLImageElement) {
4716
+ else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
4717
+ (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
4718
+ (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
4719
+ (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
4614
4720
  this.#backgroundElement = background.element;
4615
4721
  }
4616
4722
  }
@@ -4678,6 +4784,7 @@
4678
4784
  zoom = defaultZoom;
4679
4785
  #container;
4680
4786
  #generated;
4787
+ #hdrMediaListeners;
4681
4788
  #mutationObserver;
4682
4789
  #originalStyle;
4683
4790
  #pluginManager;
@@ -4742,7 +4849,6 @@
4742
4849
  });
4743
4850
  this.resize();
4744
4851
  this.#initStyle();
4745
- this.initBackground();
4746
4852
  this.#safeMutationObserver(obs => {
4747
4853
  const element = this.domElement;
4748
4854
  if (!element || !(element instanceof Node)) {
@@ -4752,6 +4858,8 @@
4752
4858
  });
4753
4859
  this.initPlugins();
4754
4860
  this.#initContext();
4861
+ this.initBackground();
4862
+ this.#initHdrListeners();
4755
4863
  this.render.init();
4756
4864
  }
4757
4865
  initBackground() {
@@ -4761,7 +4869,8 @@
4761
4869
  }
4762
4870
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
4763
4871
  if (color) {
4764
- elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
4872
+ const hdrOptions = container.actualOptions.hdr;
4873
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
4765
4874
  }
4766
4875
  else {
4767
4876
  elementStyle.backgroundColor = "";
@@ -4858,6 +4967,7 @@
4858
4967
  obs.disconnect();
4859
4968
  });
4860
4969
  this.#mutationObserver = undefined;
4970
+ this.#removeHdrListeners();
4861
4971
  this.render.stop();
4862
4972
  }
4863
4973
  async windowResize() {
@@ -4877,9 +4987,16 @@
4877
4987
  }
4878
4988
  }
4879
4989
  #initContext() {
4880
- const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
4990
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
4881
4991
  safeMatchMedia("(color-gamut: p3)")?.matches &&
4882
4992
  safeMatchMedia("(dynamic-range: high)")?.matches;
4993
+ container.hdr = canSupportHdr ?? false;
4994
+ container.hdrMode = container.actualOptions.hdr.mode;
4995
+ container.peakNits = container.actualOptions.hdr.peakNits;
4996
+ const renderCanvas = this.renderCanvas;
4997
+ if (!renderCanvas) {
4998
+ return;
4999
+ }
4883
5000
  this.render.setContextSettings({
4884
5001
  alpha: true,
4885
5002
  desynchronized: true,
@@ -4888,11 +5005,47 @@
4888
5005
  ? { colorSpace: "display-p3", colorType: "float16" }
4889
5006
  : { colorSpace: "srgb" }),
4890
5007
  });
4891
- const renderCanvas = this.renderCanvas;
4892
- if (!renderCanvas) {
4893
- return;
5008
+ let context;
5009
+ try {
5010
+ context = renderCanvas.getContext("2d", this.render.settings);
5011
+ }
5012
+ catch {
5013
+ context = null;
5014
+ }
5015
+ if (canSupportHdr && !context) {
5016
+ container.hdr = false;
5017
+ const sdrSettings = {
5018
+ alpha: true,
5019
+ desynchronized: true,
5020
+ willReadFrequently: false,
5021
+ colorSpace: "srgb",
5022
+ };
5023
+ this.render.setContextSettings(sdrSettings);
5024
+ try {
5025
+ context = renderCanvas.getContext("2d", sdrSettings);
5026
+ }
5027
+ catch {
5028
+ context = null;
5029
+ }
5030
+ }
5031
+ this.render.setContext(context);
5032
+ }
5033
+ #initHdrListeners() {
5034
+ this.#removeHdrListeners();
5035
+ const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
5036
+ this.#recreateRenderCanvas();
5037
+ this.#initContext();
5038
+ this.initBackground();
5039
+ }, listeners = [];
5040
+ if (p3Query) {
5041
+ p3Query.addEventListener("change", handleChange);
5042
+ listeners.push({ handler: handleChange, mql: p3Query });
5043
+ }
5044
+ if (hdrQuery) {
5045
+ hdrQuery.addEventListener("change", handleChange);
5046
+ listeners.push({ handler: handleChange, mql: hdrQuery });
4894
5047
  }
4895
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
5048
+ this.#hdrMediaListeners = listeners;
4896
5049
  }
4897
5050
  #initStyle() {
4898
5051
  const element = this.domElement, options = this.#container.actualOptions;
@@ -4916,6 +5069,25 @@
4916
5069
  element.style.setProperty(key, value, "important");
4917
5070
  }
4918
5071
  }
5072
+ #recreateRenderCanvas() {
5073
+ const renderCanvas = this.renderCanvas;
5074
+ if (!renderCanvas) {
5075
+ return;
5076
+ }
5077
+ if (this.domElement) {
5078
+ return;
5079
+ }
5080
+ this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
5081
+ }
5082
+ #removeHdrListeners() {
5083
+ if (!this.#hdrMediaListeners) {
5084
+ return;
5085
+ }
5086
+ for (const { handler, mql } of this.#hdrMediaListeners) {
5087
+ mql.removeEventListener("change", handler);
5088
+ }
5089
+ this.#hdrMediaListeners = undefined;
5090
+ }
4919
5091
  #repairStyle() {
4920
5092
  const element = this.domElement;
4921
5093
  if (!element) {
@@ -5300,9 +5472,9 @@
5300
5472
  }
5301
5473
  getOpacity() {
5302
5474
  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;
5303
- this.#cachedOpacityData.fillOpacity = opacity * fillOpacity * zOpacityFactor;
5475
+ this.#cachedOpacityData.fillOpacity = fillOpacity;
5304
5476
  this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
5305
- this.#cachedOpacityData.strokeOpacity = opacity * strokeOpacity * zOpacityFactor;
5477
+ this.#cachedOpacityData.strokeOpacity = strokeOpacity;
5306
5478
  return this.#cachedOpacityData;
5307
5479
  }
5308
5480
  getPosition() {
@@ -6157,6 +6329,7 @@
6157
6329
  effectDrawers;
6158
6330
  fpsLimit;
6159
6331
  hdr;
6332
+ hdrMode;
6160
6333
  id;
6161
6334
  pageHidden;
6162
6335
  particleCreatedPlugins;
@@ -6164,6 +6337,7 @@
6164
6337
  particlePositionPlugins;
6165
6338
  particleUpdaters;
6166
6339
  particles;
6340
+ peakNits;
6167
6341
  plugins;
6168
6342
  retina;
6169
6343
  shapeDrawers;
@@ -6194,6 +6368,8 @@
6194
6368
  this.id = Symbol(id);
6195
6369
  this.fpsLimit = 120;
6196
6370
  this.hdr = false;
6371
+ this.hdrMode = HdrMode.standard;
6372
+ this.peakNits = 400;
6197
6373
  this.#smooth = false;
6198
6374
  this.#delay = 0;
6199
6375
  this.#duration = 0;
@@ -6333,8 +6509,9 @@
6333
6509
  this.updateActualOptions();
6334
6510
  this.canvas.initBackground();
6335
6511
  this.canvas.resize();
6336
- const { delay, duration, fpsLimit, hdr, smooth, zLayers } = this.actualOptions;
6337
- this.hdr = hdr;
6512
+ const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
6513
+ this.hdrMode = hdrOptions.mode;
6514
+ this.peakNits = hdrOptions.peakNits;
6338
6515
  this.zLayers = zLayers;
6339
6516
  this.#duration = getRangeValue(duration) * millisecondsToSeconds;
6340
6517
  this.#delay = getRangeValue(delay) * millisecondsToSeconds;