UNPKG

@tsparticles/fireworks

Version:

tsParticles fireworks bundle — easily create spectacular fireworks and fountain particle effects with built-in presets. Ready to use components available for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.

8,807 lines 356 kB
(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);
/* tsParticles v4.4.0 */
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.bundles = global.__tsParticlesInternals.bundles || {}, global.__tsParticlesInternals.bundles.fireworks = global.__tsParticlesInternals.bundles.fireworks || {})));
})(this, (function (exports) { 'use strict';

    const generatedAttribute = "generated", defaultCompositeValue = "source-over", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
        x: 0,
        y: 0,
        z: 0,
    }, defaultTransform = {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
    }, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha$1 = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, spatialHashGridCellSize = 100, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, inverseFactorNumerator = 1, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, minDistance = 0, minRadius$1 = 0, defaultTransformValue = 1, minimumSize = 0, zIndexFactorOffset = 1, defaultOpacity$1 = 1, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minZ = 0, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, defaultAngle = 0, identity$1 = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, maxNits = 400, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0, defaultZoom = 1;

    exports.MoveDirection = void 0;
    (function (MoveDirection) {
        MoveDirection["bottom"] = "bottom";
        MoveDirection["bottomLeft"] = "bottom-left";
        MoveDirection["bottomRight"] = "bottom-right";
        MoveDirection["left"] = "left";
        MoveDirection["none"] = "none";
        MoveDirection["right"] = "right";
        MoveDirection["top"] = "top";
        MoveDirection["topLeft"] = "top-left";
        MoveDirection["topRight"] = "top-right";
        MoveDirection["outside"] = "outside";
        MoveDirection["inside"] = "inside";
    })(exports.MoveDirection || (exports.MoveDirection = {}));

    function getZ(source) {
        return "z" in source ? source.z : originPoint.z;
    }
    class Vector3d {
        x;
        y;
        z;
        constructor(x = originPoint.x, y = originPoint.y, z = originPoint.z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        static get origin() {
            return Vector3d.create(originPoint.x, originPoint.y, originPoint.z);
        }
        get angle() {
            return Math.atan2(this.y, this.x);
        }
        set angle(angle) {
            this.#updateFromAngle(angle, this.length);
        }
        get length() {
            return Math.sqrt(this.getLengthSq());
        }
        set length(length) {
            this.#updateFromAngle(this.angle, length);
        }
        static clone(source) {
            return Vector3d.create(source.x, source.y, getZ(source));
        }
        static create(x, y, z) {
            if (typeof x === "number") {
                return new Vector3d(x, y ?? originPoint.y, z ?? originPoint.z);
            }
            return new Vector3d(x.x, x.y, getZ(x));
        }
        add(v) {
            return Vector3d.create(this.x + v.x, this.y + v.y, this.z + getZ(v));
        }
        addTo(v) {
            this.x += v.x;
            this.y += v.y;
            this.z += getZ(v);
        }
        copy() {
            return Vector3d.clone(this);
        }
        div(n) {
            return Vector3d.create(this.x / n, this.y / n, this.z / n);
        }
        getLengthSq() {
            return this.x ** squareExp + this.y ** squareExp;
        }
        mult(n) {
            return Vector3d.create(this.x * n, this.y * n, this.z * n);
        }
        multTo(n) {
            this.x *= n;
            this.y *= n;
            this.z *= n;
        }
        normalize() {
            const length = this.length;
            if (length != none) {
                this.multTo(inverseFactorNumerator / length);
            }
        }
        rotate(angle) {
            return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), originPoint.z);
        }
        setTo(c) {
            this.x = c.x;
            this.y = c.y;
            this.z = getZ(c);
        }
        sub(v) {
            return Vector3d.create(this.x - v.x, this.y - v.y, this.z - getZ(v));
        }
        subFrom(v) {
            this.x -= v.x;
            this.y -= v.y;
            this.z -= getZ(v);
        }
        #updateFromAngle(angle, length) {
            this.x = Math.cos(angle) * length;
            this.y = Math.sin(angle) * length;
        }
    }
    class Vector extends Vector3d {
        constructor(x = originPoint.x, y = originPoint.y) {
            super(x, y, originPoint.z);
        }
        static get origin() {
            return Vector.create(originPoint.x, originPoint.y);
        }
        static clone(source) {
            return Vector.create(source.x, source.y);
        }
        static create(x, y) {
            if (typeof x === "number") {
                return new Vector(x, y ?? originPoint.y);
            }
            return new Vector(x.x, x.y);
        }
    }

    function isBoolean(arg) {
        return typeof arg === "boolean";
    }
    function isString(arg) {
        return typeof arg === "string";
    }
    function isNumber(arg) {
        return typeof arg === "number";
    }
    function isFunction(arg) {
        return typeof arg === "function";
    }
    function isObject(arg) {
        return typeof arg === "object" && arg !== null;
    }
    function isArray(arg) {
        return Array.isArray(arg);
    }
    function isNull(arg) {
        return arg === null || arg === undefined;
    }

    const piDeg = 180, degToRadFactor = Math.PI / piDeg;
    let _random = Math.random;
    const _animationLoop = {
        nextFrame: (cb) => requestAnimationFrame(cb),
        cancel: (idx) => {
            cancelAnimationFrame(idx);
        },
    };
    function setRandom(rnd = Math.random) {
        _random = rnd;
    }
    function getRandomFn() {
        return _random;
    }
    function getRandom() {
        const min = 0, max = 1;
        return clamp(_random(), min, max - Number.EPSILON);
    }
    function getRandomInRange(min, max) {
        return getRandom() * (max - min) + min;
    }
    function setAnimationFunctions(nextFrame, cancel) {
        _animationLoop.nextFrame = nextFrame;
        _animationLoop.cancel = cancel;
    }
    function animate(fn) {
        return _animationLoop.nextFrame(fn);
    }
    function cancelAnimation(handle) {
        _animationLoop.cancel(handle);
    }
    function clamp(num, min, max) {
        return Math.min(Math.max(num, min), max);
    }
    function mix(comp1, comp2, weight1, weight2) {
        return Math.floor((comp1 * weight1 + comp2 * weight2) / (weight1 + weight2));
    }
    function randomInRangeValue(r) {
        const max = getRangeMax(r), minOffset = 0;
        let min = getRangeMin(r);
        if (max === min) {
            min = minOffset;
        }
        return getRandomInRange(min, max);
    }
    function getRangeValue(value) {
        return isNumber(value) ? value : randomInRangeValue(value);
    }
    function getRangeMin(value) {
        return isNumber(value) ? value : value.min;
    }
    function getRangeMax(value) {
        return isNumber(value) ? value : value.max;
    }
    function setRangeValue(source, value) {
        if (source === value || (value === undefined && isNumber(source))) {
            return source;
        }
        const min = getRangeMin(source), max = getRangeMax(source);
        return value !== undefined
            ? {
                min: Math.min(min, value),
                max: Math.max(max, value),
            }
            : setRangeValue(min, max);
    }
    function getDistances(pointA, pointB) {
        const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y;
        return { dx: dx, dy: dy, distance: Math.hypot(dx, dy) };
    }
    function getDistanceSq(pointA, pointB) {
        const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y;
        return dx * dx + dy * dy;
    }
    function getDistance(pointA, pointB) {
        return Math.sqrt(getDistanceSq(pointA, pointB));
    }
    function checkDistance(pointA, pointB, distance) {
        return getDistanceSq(pointA, pointB) <= distance * distance;
    }
    function degToRad(degrees) {
        return degrees * degToRadFactor;
    }
    function getParticleDirectionAngle(direction, position, center) {
        if (isNumber(direction)) {
            return degToRad(direction);
        }
        switch (direction) {
            case exports.MoveDirection.top:
                return -Math.PI * half;
            case exports.MoveDirection.topRight:
                return -Math.PI * quarter;
            case exports.MoveDirection.right:
                return empty;
            case exports.MoveDirection.bottomRight:
                return Math.PI * quarter;
            case exports.MoveDirection.bottom:
                return Math.PI * half;
            case exports.MoveDirection.bottomLeft:
                return Math.PI * threeQuarter;
            case exports.MoveDirection.left:
                return Math.PI;
            case exports.MoveDirection.topLeft:
                return -Math.PI * threeQuarter;
            case exports.MoveDirection.inside:
                return Math.atan2(center.y - position.y, center.x - position.x);
            case exports.MoveDirection.outside:
                return Math.atan2(position.y - center.y, position.x - center.x);
            default:
                return getRandom() * doublePI;
        }
    }
    function getParticleBaseVelocity(direction) {
        const baseVelocity = Vector.origin;
        baseVelocity.length = 1;
        baseVelocity.angle = direction;
        return baseVelocity;
    }
    function collisionVelocity(v1, v2, m1, m2) {
        return Vector.create((v1.x * (m1 - m2)) / (m1 + m2) + (v2.x * double * m2) / (m1 + m2), v1.y);
    }
    function calcPositionFromSize(data) {
        return data.position?.x !== undefined && data.position.y !== undefined
            ? {
                x: (data.position.x * data.size.width) / percentDenominator,
                y: (data.position.y * data.size.height) / percentDenominator,
            }
            : undefined;
    }
    function calcPositionOrRandomFromSize(data) {
        return {
            x: ((data.position?.x ?? getRandom() * percentDenominator) * data.size.width) / percentDenominator,
            y: ((data.position?.y ?? getRandom() * percentDenominator) * data.size.height) / percentDenominator,
        };
    }
    function calcPositionOrRandomFromSizeRanged(data) {
        const position = {
            x: data.position?.x !== undefined ? getRangeValue(data.position.x) : undefined,
            y: data.position?.y !== undefined ? getRangeValue(data.position.y) : undefined,
        };
        return calcPositionOrRandomFromSize({ size: data.size, position });
    }
    function calcExactPositionOrRandomFromSize(data) {
        const { position, size } = data;
        return {
            x: position?.x ?? getRandom() * size.width,
            y: position?.y ?? getRandom() * size.height,
        };
    }
    function parseAlpha(input) {
        const defaultAlpha = 1;
        if (!input) {
            return defaultAlpha;
        }
        return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
    }

    exports.OutModeDirection = void 0;
    (function (OutModeDirection) {
        OutModeDirection["bottom"] = "bottom";
        OutModeDirection["left"] = "left";
        OutModeDirection["right"] = "right";
        OutModeDirection["top"] = "top";
    })(exports.OutModeDirection || (exports.OutModeDirection = {}));

    exports.PixelMode = void 0;
    (function (PixelMode) {
        PixelMode["precise"] = "precise";
        PixelMode["percent"] = "percent";
    })(exports.PixelMode || (exports.PixelMode = {}));

    const minRadius = 0;
    function isForbiddenKey(key) {
        return key === "__proto__" || key === "constructor" || key === "prototype";
    }
    function hasMatchMedia() {
        return typeof matchMedia !== "undefined";
    }
    function safeDocument() {
        return globalThis.document;
    }
    function safeMatchMedia(query) {
        if (!hasMatchMedia()) {
            return;
        }
        return matchMedia(query);
    }
    function safeMutationObserver(callback) {
        if (typeof MutationObserver === "undefined") {
            return;
        }
        return new MutationObserver(callback);
    }
    function isInArray(value, array) {
        return value === array || (isArray(array) && array.includes(value));
    }
    function itemFromArray(array, index, useIndex = true) {
        return array[index !== undefined && useIndex ? index % array.length : Math.floor(getRandom() * array.length)];
    }
    function isPointInside(point, size, offset, radius, direction) {
        return areBoundsInside(calculateBounds(point, radius ?? minRadius), size, offset, direction);
    }
    function areBoundsInside(bounds, size, offset, direction) {
        let inside = true;
        if (!direction || direction === exports.OutModeDirection.bottom) {
            inside = bounds.top < size.height + offset.x;
        }
        if (inside && (!direction || direction === exports.OutModeDirection.left)) {
            inside = bounds.right > offset.x;
        }
        if (inside && (!direction || direction === exports.OutModeDirection.right)) {
            inside = bounds.left < size.width + offset.y;
        }
        if (inside && (!direction || direction === exports.OutModeDirection.top)) {
            inside = bounds.bottom > offset.y;
        }
        return inside;
    }
    function calculateBounds(point, radius) {
        return {
            bottom: point.y + radius,
            left: point.x - radius,
            right: point.x + radius,
            top: point.y - radius,
        };
    }
    function deepExtend(destination, ...sources) {
        for (const source of sources) {
            if (isNull(source)) {
                continue;
            }
            if (!isObject(source)) {
                destination = source;
                continue;
            }
            if (Array.isArray(source)) {
                if (!Array.isArray(destination)) {
                    destination = [];
                }
            }
            else if (!isObject(destination) || Array.isArray(destination)) {
                destination = Object.create(null);
            }
            const sourceKeys = Object.keys(source), hasNested = sourceKeys.some(k => {
                const v = source[k];
                return isObject(v) || Array.isArray(v);
            });
            if (!hasNested) {
                const sourceDict = source, destDict = destination;
                for (const key of sourceKeys) {
                    if (isForbiddenKey(key)) {
                        continue;
                    }
                    const v = sourceDict[key];
                    if (v !== undefined) {
                        destDict[key] = v;
                    }
                }
                continue;
            }
            for (const key of sourceKeys) {
                if (isForbiddenKey(key)) {
                    continue;
                }
                const sourceDict = source, destDict = destination, value = sourceDict[key];
                destDict[key] = Array.isArray(value)
                    ? value.map(v => deepExtend(undefined, v))
                    : deepExtend(destDict[key], value);
            }
        }
        return destination;
    }
    function circleBounceDataFromParticle(p) {
        return {
            position: p.getPosition(),
            radius: p.getRadius(),
            mass: p.getMass(),
            velocity: p.velocity,
            factor: Vector.create(getRangeValue(p.options.bounce.horizontal.value), getRangeValue(p.options.bounce.vertical.value)),
        };
    }
    function circleBounce(p1, p2) {
        const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity), [pos1, pos2] = [p1.position, p2.position], { dx: xDist, dy: yDist } = getDistances(pos2, pos1), minimumDistance = 0;
        if (xVelocityDiff * xDist + yVelocityDiff * yDist < minimumDistance) {
            return;
        }
        const angle = -Math.atan2(yDist, xDist), m1 = p1.mass, m2 = p2.mass, u1 = p1.velocity.rotate(angle), u2 = p2.velocity.rotate(angle), v1 = collisionVelocity(u1, u2, m1, m2), v2 = collisionVelocity(u2, u1, m1, m2), vFinal1 = v1.rotate(-angle), vFinal2 = v2.rotate(-angle);
        p1.velocity.x = vFinal1.x * p1.factor.x;
        p1.velocity.y = vFinal1.y * p1.factor.y;
        p2.velocity.x = vFinal2.x * p2.factor.x;
        p2.velocity.y = vFinal2.y * p2.factor.y;
    }
    function executeOnSingleOrMultiple(obj, callback) {
        const defaultIndex = 0;
        return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, defaultIndex);
    }
    function itemFromSingleOrMultiple(obj, index, useIndex) {
        return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj;
    }
    function getPositionOrSize(positionOrSize, canvasSize) {
        const isPercent = positionOrSize.mode === exports.PixelMode.percent;
        if (!isPercent) {
            const { mode: _, ...rest } = positionOrSize;
            return rest;
        }
        const isPosition = "x" in positionOrSize;
        if (isPosition) {
            return {
                x: (positionOrSize.x / percentDenominator) * canvasSize.width,
                y: (positionOrSize.y / percentDenominator) * canvasSize.height,
            };
        }
        else {
            return {
                width: (positionOrSize.width / percentDenominator) * canvasSize.width,
                height: (positionOrSize.height / percentDenominator) * canvasSize.height,
            };
        }
    }
    function getPosition(position, canvasSize) {
        return getPositionOrSize(position, canvasSize);
    }
    function cloneStyle(style) {
        const clonedStyle = safeDocument().createElement("div").style;
        for (const key in style) {
            const styleKey = style[key];
            if (!(key in style) || isNull(styleKey)) {
                continue;
            }
            const styleValue = style.getPropertyValue?.(styleKey);
            if (!styleValue) {
                continue;
            }
            const stylePriority = style.getPropertyPriority?.(styleKey);
            if (stylePriority) {
                clonedStyle.setProperty(styleKey, styleValue, stylePriority);
            }
            else {
                clonedStyle.setProperty(styleKey, styleValue);
            }
        }
        return clonedStyle;
    }
    let _cachedZIndex, _cachedStyle;
    function getFullScreenStyle(zIndex) {
        if (_cachedZIndex !== zIndex || !_cachedStyle) {
            _cachedZIndex = zIndex;
            const fullScreenStyle = safeDocument().createElement("div").style, radix = 10, style = {
                width: "100%",
                height: "100%",
                margin: "0",
                padding: "0",
                borderWidth: "0",
                position: "fixed",
                zIndex: zIndex.toString(radix),
                "z-index": zIndex.toString(radix),
                top: "0",
                left: "0",
                "pointer-events": "none",
            };
            for (const key in style) {
                const value = style[key];
                if (value === undefined) {
                    continue;
                }
                fullScreenStyle.setProperty(key, value);
            }
            _cachedStyle = fullScreenStyle;
        }
        return _cachedStyle;
    }
    function manageListener(element, event, handler, add, options) {
        if (add) {
            let addOptions = { passive: true };
            if (isBoolean(options)) {
                addOptions.capture = options;
            }
            else if (options !== undefined) {
                addOptions = options;
            }
            element.addEventListener(event, handler, addOptions);
        }
        else {
            const removeOptions = options;
            element.removeEventListener(event, handler, removeOptions);
        }
    }
    async function getItemsFromInitializer(container, map, initializers, force = false) {
        let res = map.get(container);
        if (!res || force) {
            res = await Promise.all([...initializers.values()].map(t => t(container)));
            map.set(container, res);
        }
        return res;
    }
    async function getItemMapFromInitializer(container, map, initializers, force = false) {
        let res = map.get(container);
        if (!res || force) {
            const entries = await Promise.all([...initializers.entries()].map(([key, initializer]) => initializer(container).then(item => [key, item])));
            res = new Map(entries);
            map.set(container, res);
        }
        return res;
    }

    class EventDispatcher {
        #listeners;
        constructor() {
            this.#listeners = new Map();
        }
        addEventListener(type, listener) {
            this.removeEventListener(type, listener);
            let arr = this.#listeners.get(type);
            if (!arr) {
                arr = [];
                this.#listeners.set(type, arr);
            }
            arr.push(listener);
        }
        dispatchEvent(type, args) {
            const listeners = this.#listeners.get(type);
            listeners?.forEach(handler => {
                handler(args);
            });
        }
        hasEventListener(type) {
            return !!this.#listeners.get(type);
        }
        removeAllEventListeners(type) {
            if (!type) {
                this.#listeners = new Map();
            }
            else {
                this.#listeners.delete(type);
            }
        }
        removeEventListener(type, listener) {
            const arr = this.#listeners.get(type);
            if (!arr) {
                return;
            }
            const length = arr.length, idx = arr.indexOf(listener);
            if (idx < minIndex) {
                return;
            }
            if (length === deleteCount) {
                this.#listeners.delete(type);
            }
            else {
                arr.splice(idx, deleteCount);
            }
        }
    }

    exports.EventType = void 0;
    (function (EventType) {
        EventType["configAdded"] = "configAdded";
        EventType["containerInit"] = "containerInit";
        EventType["particlesSetup"] = "particlesSetup";
        EventType["containerStarted"] = "containerStarted";
        EventType["containerStopped"] = "containerStopped";
        EventType["containerDestroyed"] = "containerDestroyed";
        EventType["containerPaused"] = "containerPaused";
        EventType["containerPlay"] = "containerPlay";
        EventType["containerBuilt"] = "containerBuilt";
        EventType["particleAdded"] = "particleAdded";
        EventType["particleDestroyed"] = "particleDestroyed";
        EventType["particleRemoved"] = "particleRemoved";
    })(exports.EventType || (exports.EventType = {}));

    class PluginManager {
        colorManagers = new Map();
        easingFunctions = new Map();
        effectDrawers = new Map();
        initializers = {
            effects: new Map(),
            shapes: new Map(),
            updaters: new Map(),
        };
        palettes = new Map();
        plugins = [];
        presets = new Map();
        shapeDrawers = new Map();
        updaters = new Map();
        #allLoadersSet = new Set();
        #configs = new Map();
        #engine;
        #executedSet = new Set();
        #initialized = false;
        #isRunningLoaders = false;
        #loadPromises = new Set();
        constructor(engine) {
            this.#engine = engine;
        }
        get configs() {
            const res = {};
            for (const [name, config] of this.#configs) {
                res[name] = config;
            }
            return res;
        }
        addColorManager(name, manager) {
            this.colorManagers.set(name, manager);
        }
        addConfig(config) {
            const key = config.key ?? config.name ?? "default";
            this.#configs.set(key, config);
            this.#engine.dispatchEvent(exports.EventType.configAdded, { data: { name: key, config } });
        }
        addEasing(name, easing) {
            if (this.easingFunctions.get(name)) {
                return;
            }
            this.easingFunctions.set(name, easing);
        }
        addEffect(effect, drawer) {
            this.initializers.effects.set(effect, drawer);
        }
        addPalette(name, palette) {
            this.palettes.set(name, palette);
        }
        addParticleUpdater(name, updaterInitializer) {
            this.initializers.updaters.set(name, updaterInitializer);
        }
        addPlugin(plugin) {
            if (this.getPlugin(plugin.id)) {
                return;
            }
            this.plugins.push(plugin);
        }
        addPreset(preset, options, override = false) {
            if (!(override || !this.getPreset(preset))) {
                return;
            }
            this.presets.set(preset, options);
        }
        addShape(shapes, drawer) {
            for (const shape of shapes) {
                this.initializers.shapes.set(shape, drawer);
            }
        }
        clearPlugins(container) {
            this.effectDrawers.delete(container);
            this.shapeDrawers.delete(container);
            this.updaters.delete(container);
        }
        getEasing(name) {
            return this.easingFunctions.get(name) ?? ((value) => value);
        }
        getEffectDrawers(container, force = false) {
            return getItemMapFromInitializer(container, this.effectDrawers, this.initializers.effects, force);
        }
        getPalette(name) {
            return this.palettes.get(name);
        }
        getPlugin(plugin) {
            return this.plugins.find(t => t.id === plugin);
        }
        getPreset(preset) {
            return this.presets.get(preset);
        }
        async getShapeDrawers(container, force = false) {
            return getItemMapFromInitializer(container, this.shapeDrawers, this.initializers.shapes, force);
        }
        async getUpdaters(container, force = false) {
            return getItemsFromInitializer(container, this.updaters, this.initializers.updaters, force);
        }
        async init() {
            if (this.#initialized || this.#isRunningLoaders) {
                return;
            }
            this.#isRunningLoaders = true;
            this.#executedSet = new Set();
            this.#allLoadersSet = new Set(this.#loadPromises);
            try {
                for (const loader of this.#allLoadersSet) {
                    await this.#runLoader(loader, this.#executedSet, this.#allLoadersSet);
                }
            }
            finally {
                this.#loadPromises.clear();
                this.#isRunningLoaders = false;
                this.#initialized = true;
            }
        }
        loadParticlesOptions(container, options, ...sourceOptions) {
            const updaters = this.updaters.get(container);
            if (!updaters) {
                return;
            }
            updaters.forEach(updater => updater.loadOptions?.(options, ...sourceOptions));
        }
        async register(...loaders) {
            if (this.#initialized) {
                throw new Error("Register plugins can only be done before calling tsParticles.load()");
            }
            for (const loader of loaders) {
                if (this.#isRunningLoaders) {
                    await this.#runLoader(loader, this.#executedSet, this.#allLoadersSet);
                }
                else {
                    this.#loadPromises.add(loader);
                }
            }
        }
        async #runLoader(loader, executed, allLoaders) {
            if (executed.has(loader))
                return;
            executed.add(loader);
            allLoaders.add(loader);
            await loader(this.#engine);
        }
    }

    const errorPrefix = "tsParticles - Error";
    const wrap = (fn) => (...args) => {
        fn(...args);
    }, _logger = {
        debug: wrap(console.debug),
        error: (message, ...optionalParams) => {
            console.error(`${errorPrefix} - ${message}`, ...optionalParams);
        },
        info: wrap(console.info),
        log: wrap(console.log),
        trace: wrap(console.trace),
        verbose: wrap(console.log),
        warning: wrap(console.warn),
    };
    function setLogger(logger) {
        if (logger.debug) {
            _logger.debug = wrap(logger.debug);
        }
        if (logger.error) {
            _logger.error = wrap(logger.error);
        }
        if (logger.info) {
            _logger.info = wrap(logger.info);
        }
        if (logger.log) {
            _logger.log = wrap(logger.log);
        }
        if (logger.trace) {
            _logger.trace = wrap(logger.trace);
        }
        if (logger.verbose) {
            _logger.verbose = wrap(logger.verbose);
        }
        if (logger.warning) {
            _logger.warning = wrap(logger.warning);
        }
    }
    function getLogger() {
        return _logger;
    }

    const fullPercent = "100%";
    async function getDataFromUrl(data) {
        const url = itemFromSingleOrMultiple(data.url, data.index);
        if (!url) {
            return data.fallback;
        }
        const response = await fetch(url);
        if (response.ok) {
            return (await response.json());
        }
        getLogger().error(`${response.status.toString()} while retrieving config file`);
        return data.fallback;
    }
    const getCanvasFromContainer = (domContainer) => {
        const documentSafe = safeDocument();
        let canvasEl;
        const isCanvas = domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag;
        if (isCanvas) {
            canvasEl = domContainer;
            canvasEl.dataset[generatedAttribute] ??= generatedFalse;
            if (canvasEl.dataset[generatedAttribute] === generatedTrue) {
                canvasEl.style.width ||= fullPercent;
                canvasEl.style.height ||= fullPercent;
                canvasEl.style.pointerEvents = "none";
                canvasEl.style.setProperty("pointer-events", "none");
            }
        }
        else {
            const existingCanvases = domContainer.getElementsByTagName(canvasTag), foundCanvas = existingCanvases.item(canvasFirstIndex);
            if (foundCanvas) {
                canvasEl = foundCanvas;
                canvasEl.dataset[generatedAttribute] = generatedFalse;
            }
            else {
                canvasEl = documentSafe.createElement(canvasTag);
                canvasEl.dataset[generatedAttribute] = generatedTrue;
                domContainer.appendChild(canvasEl);
            }
            canvasEl.style.width ||= fullPercent;
            canvasEl.style.height ||= fullPercent;
            canvasEl.style.pointerEvents = "none";
            canvasEl.style.setProperty("pointer-events", "none");
        }
        return canvasEl;
    }, getDomContainer = (id, source) => {
        const documentSafe = safeDocument();
        let domContainer = source ?? documentSafe.getElementById(id);
        if (domContainer) {
            return domContainer;
        }
        domContainer = documentSafe.createElement("canvas");
        domContainer.id = id;
        domContainer.dataset[generatedAttribute] = generatedTrue;
        documentSafe.body.append(domContainer);
        return domContainer;
    };
    class Engine {
        pluginManager = new PluginManager(this);
        #domArray = [];
        #eventDispatcher = new EventDispatcher();
        #initialized = false;
        get items() {
            return this.#domArray;
        }
        get version() {
            return "4.4.0";
        }
        addEventListener(type, listener) {
            this.#eventDispatcher.addEventListener(type, listener);
        }
        checkVersion(pluginVersion) {
            if (this.version === pluginVersion) {
                return;
            }
            throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
        }
        dispatchEvent(type, args) {
            this.#eventDispatcher.dispatchEvent(type, args);
        }
        async init() {
            if (this.#initialized) {
                return;
            }
            await this.pluginManager.init();
            this.#initialized = true;
        }
        item(index) {
            const items = this.items, item = items[index];
            if (item?.destroyed) {
                items.splice(index, removeDeleteCount);
                return;
            }
            return item;
        }
        async load(params) {
            await this.init();
            let domSourceElement;
            if (typeof HTMLElement !== "undefined" && params.element instanceof HTMLElement) {
                domSourceElement = params.element;
            }
            const { Container } = await Promise.resolve().then(function () { return Container$1; }), id = params.id ?? domSourceElement?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor).toString()}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options, currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container({
                dispatchCallback: (eventType, args) => {
                    this.dispatchEvent(eventType, args);
                },
                id,
                onDestroy: (remove) => {
                    if (!remove) {
                        return;
                    }
                    const mainArr = this.items, idx = mainArr.indexOf(newItem);
                    if (idx >= removeMinIndex) {
                        mainArr.splice(idx, removeDeleteCount);
                    }
                },
                pluginManager: this.pluginManager,
                sourceOptions: currentOptions,
            });
            if (oldIndex >= loadMinIndex) {
                const old = this.item(oldIndex), deleteCount = old ? one : none;
                if (old && !old.destroyed) {
                    old.destroy(false);
                }
                items.splice(oldIndex, deleteCount, newItem);
            }
            else {
                items.push(newItem);
            }
            const sourceCanvas = typeof OffscreenCanvas !== "undefined" && params.element instanceof OffscreenCanvas
                ? params.element
                : getCanvasFromContainer(getDomContainer(id, domSourceElement));
            newItem.canvas.loadCanvas(sourceCanvas);
            await newItem.start();
            return newItem;
        }
        async refresh(refresh = true) {
            if (!refresh) {
                return;
            }
            await Promise.all(this.items.map(t => t.refresh()));
        }
        removeEventListener(type, listener) {
            this.#eventDispatcher.removeEventListener(type, listener);
        }
    }

    function initEngine() {
        const existing = globalThis.tsParticles;
        if (existing?.pluginManager) {
            return existing;
        }
        return new Engine();
    }

    var RangeType;
    (function (RangeType) {
        RangeType["circle"] = "circle";
        RangeType["rectangle"] = "rectangle";
    })(RangeType || (RangeType = {}));

    class BaseRange {
        position;
        type;
        constructor(x, y, type) {
            this.position = {
                x: x,
                y: y,
            };
            this.type = type;
        }
        _resetPosition(x, y) {
            this.position.x = x;
            this.position.y = y;
        }
    }
    class Circle extends BaseRange {
        radius;
        constructor(x, y, radius) {
            super(x, y, RangeType.circle);
            this.radius = radius;
        }
        contains(point) {
            return checkDistance(point, this.position, this.radius);
        }
        intersects(range) {
            const pos1 = this.position, pos2 = range.position, r = this.radius, dx = Math.abs(pos2.x - pos1.x), dy = Math.abs(pos2.y - pos1.y);
            if (range instanceof Circle || range.type === RangeType.circle) {
                const circleRange = range, rSum = r + circleRange.radius, dist = Math.hypot(dx, dy);
                return rSum > dist;
            }
            else if (range instanceof Rectangle || range.type === RangeType.rectangle) {
                const rectRange = range, { width, height } = rectRange.size, edges = Math.pow(dx - width, squareExp) + Math.pow(dy - height, squareExp);
                return edges <= r ** squareExp || (dx <= r + width && dy <= r + height) || dx <= width || dy <= height;
            }
            return false;
        }
        reset(x, y, radius) {
            this._resetPosition(x, y);
            this.radius = radius;
            return this;
        }
    }
    class Rectangle extends BaseRange {
        size;
        constructor(x, y, width, height) {
            super(x, y, RangeType.rectangle);
            this.size = {
                height: height,
                width: width,
            };
        }
        contains(point) {
            const w = this.size.width, h = this.size.height, pos = this.position;
            return point.x >= pos.x && point.x <= pos.x + w && point.y >= pos.y && point.y <= pos.y + h;
        }
        intersects(range) {
            if (range instanceof Circle) {
                return range.intersects(this);
            }
            if (!(range instanceof Rectangle)) {
                return false;
            }
            const w = this.size.width, h = this.size.height, pos1 = this.position, pos2 = range.position, size2 = range.size, w2 = size2.width, h2 = size2.height;
            return pos2.x < pos1.x + w && pos2.x + w2 > pos1.x && pos2.y < pos1.y + h && pos2.y + h2 > pos1.y;
        }
        reset(x, y, width, height) {
            this._resetPosition(x, y);
            this.size.width = width;
            this.size.height = height;
            return this;
        }
    }

    exports.RotateDirection = void 0;
    (function (RotateDirection) {
        RotateDirection["clockwise"] = "clockwise";
        RotateDirection["counterClockwise"] = "counter-clockwise";
        RotateDirection["random"] = "random";
    })(exports.RotateDirection || (exports.RotateDirection = {}));

    exports.AnimationMode = void 0;
    (function (AnimationMode) {
        AnimationMode["auto"] = "auto";
        AnimationMode["increase"] = "increase";
        AnimationMode["decrease"] = "decrease";
        AnimationMode["random"] = "random";
    })(exports.AnimationMode || (exports.AnimationMode = {}));

    exports.HdrMode = void 0;
    (function (HdrMode) {
        HdrMode["standard"] = "standard";
        HdrMode["natural"] = "natural";
        HdrMode["vivid"] = "vivid";
        HdrMode["cinematic"] = "cinematic";
        HdrMode["dynamic"] = "dynamic";
    })(exports.HdrMode || (exports.HdrMode = {}));

    exports.LimitMode = void 0;
    (function (LimitMode) {
        LimitMode["delete"] = "delete";
        LimitMode["wait"] = "wait";
    })(exports.LimitMode || (exports.LimitMode = {}));

    exports.OutMode = void 0;
    (function (OutMode) {
        OutMode["bounce"] = "bounce";
        OutMode["none"] = "none";
        OutMode["out"] = "out";
        OutMode["destroy"] = "destroy";
        OutMode["split"] = "split";
    })(exports.OutMode || (exports.OutMode = {}));

    exports.AlterType = void 0;
    (function (AlterType) {
        AlterType["darken"] = "darken";
        AlterType["enlighten"] = "enlighten";
    })(exports.AlterType || (exports.AlterType = {}));

    exports.DestroyType = void 0;
    (function (DestroyType) {
        DestroyType["none"] = "none";
        DestroyType["max"] = "max";
        DestroyType["min"] = "min";
    })(exports.DestroyType || (exports.DestroyType = {}));

    exports.GradientType = void 0;
    (function (GradientType) {
        GradientType["linear"] = "linear";
        GradientType["radial"] = "radial";
        GradientType["random"] = "random";
    })(exports.GradientType || (exports.GradientType = {}));

    exports.ParticleOutType = void 0;
    (function (ParticleOutType) {
        ParticleOutType["normal"] = "normal";
        ParticleOutType["inside"] = "inside";
        ParticleOutType["outside"] = "outside";
    })(exports.ParticleOutType || (exports.ParticleOutType = {}));

    exports.StartValueType = void 0;
    (function (StartValueType) {
        StartValueType["max"] = "max";
        StartValueType["min"] = "min";
        StartValueType["random"] = "random";
    })(exports.StartValueType || (exports.StartValueType = {}));

    exports.AnimationStatus = void 0;
    (function (AnimationStatus) {
        AnimationStatus["increasing"] = "increasing";
        AnimationStatus["decreasing"] = "decreasing";
    })(exports.AnimationStatus || (exports.AnimationStatus = {}));

    exports.DrawLayer = void 0;
    (function (DrawLayer) {
        DrawLayer[DrawLayer["BackgroundElement"] = 0] = "BackgroundElement";
        DrawLayer[DrawLayer["BackgroundDraw"] = 1] = "BackgroundDraw";
        DrawLayer[DrawLayer["BackgroundMask"] = 2] = "BackgroundMask";
        DrawLayer[DrawLayer["CanvasSetup"] = 3] = "CanvasSetup";
        DrawLayer[DrawLayer["PluginContent"] = 4] = "PluginContent";
        DrawLayer[DrawLayer["Particles"] = 5] = "Particles";
        DrawLayer[DrawLayer["CanvasCleanup"] = 6] = "CanvasCleanup";
        DrawLayer[DrawLayer["Foreground"] = 7] = "Foreground";
    })(exports.DrawLayer || (exports.DrawLayer = {}));

    class OptionLoader {
        load(data) {
            if (isNull(data)) {
                return;
            }
            this.doLoad(data);
        }
    }
    function loadOptions(options, ...sourceOptionsArr) {
        for (const sourceOptions of sourceOptionsArr) {
            options.load(sourceOptions);
        }
    }

    function loadProperty(obj, key, value) {
        if (value !== undefined) {
            obj[key] = value;
        }
    }
    function loadRangeProperty(obj, key, value) {
        if (value !== undefined) {
            obj[key] = setRangeValue(value);
        }
    }
    function loadNestedProperty(obj, key, value) {
        if (value !== undefined) {
            obj[key].load(value);
        }
    }
    function loadLazyProperty(obj, key, value, factory) {
        if (value !== undefined) {
            const objRecord = obj;
            objRecord[key] ??= factory();
            objRecord[key].load(value);
        }
    }
    function loadExtendProperty(obj, key, value) {
        if (value !== undefined) {
            const keyStr = key;
            if (keyStr === "__proto__" || keyStr === "constructor" || keyStr === "prototype") {
                return;
            }
            const objRecord = obj, currentValue = Object.prototype.hasOwnProperty.call(objRecord, keyStr) ? objRecord[keyStr] : {};
            objRecord[keyStr] = deepExtend(currentValue, value);
        }
    }
    function loadOptionProperty(obj, key, optionClass, ...sources) {
        const objRecord = obj;
        objRecord[key] ??= new optionClass();
        const target = objRecord[key];
        for (const source of sources) {
            target.load(source?.[key]);
        }
    }

    class AnimationOptions extends OptionLoader {
        count = 0;
        decay = 0;
        delay = 0;
        enable = false;
        speed = 1;
        sync = false;
        doLoad(data) {
            loadRangeProperty(this, "count", data.count);
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "decay", data.decay);
            loadRangeProperty(this, "delay", data.delay);
            loadProperty(this, "sync", data.sync);
        }
    }
    class RangedAnimationOptions extends AnimationOptions {
        mode = exports.AnimationMode.auto;
        startValue = exports.StartValueType.random;
        doLoad(data) {
            super.doLoad(data);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "startValue", data.startValue);
        }
    }

    class ColorAnimation extends AnimationOptions {
        max;
        min;
        offset = 0;
        sync = true;
        constructor(min, max) {
            super();
            this.min = min;
            this.max = max;
        }
        doLoad(data) {
            super.doLoad(data);
            loadProperty(this, "max", data.max);
            loadProperty(this, "min", data.min);
            loadRangeProperty(this, "offset", data.offset);
        }
    }

    class HslAnimation extends OptionLoader {
        h = new ColorAnimation(hMin, hMax);
        l = new ColorAnimation(lMin, lMax);
        s = new ColorAnimation(sMin, sMax);
        doLoad(data) {
            this.h.load(data.h);
            this.s.load(data.s);
            this.l.load(data.l);
        }
    }

    class OptionsColor extends OptionLoader {
        value = "";
        static create(source, data) {
            const color = new OptionsColor();
            color.load(source);
            if (data !== undefined) {
                if (isString(data) || isArray(data)) {
                    color.load({ value: data });
                }
                else {
                    color.load(data);
                }
            }
            return color;
        }
        doLoad(data) {
            if (!isNull(data.value)) {
                this.value = data.value;
            }
        }
    }

    class AnimatableColor extends OptionsColor {
        animation = new HslAnimation();
        static create(source, data) {
            const color = new AnimatableColor();
            color.load(source);
            if (data !== undefined) {
                if (isString(data) || isArray(data)) {
                    color.load({ value: data });
                }
                else {
                    color.load(data);
                }
            }
            return color;
        }
        doLoad(data) {
            super.doLoad(data);
            const colorAnimation = data.animation;
            if (colorAnimation !== undefined) {
                if (colorAnimation.enable === undefined) {
                    this.animation.load(data.animation);
                }
                else {
                    this.animation.h.load(colorAnimation);
                }
            }
        }
    }

    class Background extends OptionLoader {
        color;
        draw;
        element;
        image = "";
        opacity = 1;
        position = "";
        repeat = "";
        size = "";
        constructor() {
            super();
            this.color = new OptionsColor();
            this.color.value = "";
        }
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = OptionsColor.create(this.color, data.color);
            }
            loadProperty(this, "element", data.element);
            loadProperty(this, "draw", data.draw);
            loadProperty(this, "image", data.image);
            loadProperty(this, "position", data.position);
            loadProperty(this, "repeat", data.repeat);
            loadProperty(this, "size", data.size);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    class FullScreen extends OptionLoader {
        enable = true;
        zIndex = 0;
        doLoad(data) {
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "zIndex", data.zIndex);
        }
    }

    const defaultPeakNits = 400, minPeakNits = 0, toStringValue = (value) => String(value);
    class HDROptions extends OptionLoader {
        enable = true;
        mode = exports.HdrMode.standard;
        peakNits = defaultPeakNits;
        doLoad(data) {
            if (data.enable !== undefined && !isBoolean(data.enable)) {
                throw new Error(`Invalid HDR "enable" value: expected a boolean, got "${String(data.enable)}"`);
            }
            if (data.mode !== undefined &&
                (typeof data.mode !== "string" || !Object.values(exports.HdrMode).includes(data.mode))) {
                throw new Error(`Invalid HDR "mode" value: expected one of ${Object.values(exports.HdrMode).join(", ")}, got "${toStringValue(data.mode)}"`);
            }
            if (data.peakNits !== undefined &&
                (!isNumber(data.peakNits) || !Number.isFinite(data.peakNits) || data.peakNits <= minPeakNits)) {
                throw new Error(`Invalid HDR "peakNits" value: expected a positive number, got "${String(data.peakNits)}"`);
            }
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "peakNits", data.peakNits);
        }
    }

    class ResizeEvent extends OptionLoader {
        delay = 0.5;
        enable = true;
        doLoad(data) {
            loadProperty(this, "delay", data.delay);
            loadProperty(this, "enable", data.enable);
        }
    }

    class Effect extends OptionLoader {
        close = true;
        options = {};
        type = [];
        doLoad(data) {
            const options = data.options;
            if (options !== undefined) {
                for (const effect in options) {
                    const item = options[effect];
                    if (item) {
                        this.options[effect] = deepExtend(this.options[effect] ?? {}, item);
                    }
                }
            }
            loadProperty(this, "close", data.close);
            loadProperty(this, "type", data.type);
        }
    }

    class Fill extends OptionLoader {
        color;
        enable = true;
        opacity = 1;
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = AnimatableColor.create(this.color, data.color);
            }
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class MoveAngle extends OptionLoader {
        offset = 0;
        value = 90;
        doLoad(data) {
            loadRangeProperty(this, "offset", data.offset);
            loadRangeProperty(this, "value", data.value);
        }
    }

    class MoveCenter extends OptionLoader {
        mode = exports.PixelMode.percent;
        radius = 0;
        x = 50;
        y = 50;
        doLoad(data) {
            loadProperty(this, "x", data.x);
            loadProperty(this, "y", data.y);
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "radius", data.radius);
        }
    }

    class MoveGravity extends OptionLoader {
        acceleration = 9.81;
        enable = false;
        inverse = false;
        maxSpeed = 50;
        doLoad(data) {
            loadRangeProperty(this, "acceleration", data.acceleration);
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "inverse", data.inverse);
            loadRangeProperty(this, "maxSpeed", data.maxSpeed);
        }
    }

    class ValueWithRandom extends OptionLoader {
        value = 0;
        doLoad(data) {
            if (!isNull(data.value)) {
                this.value = setRangeValue(data.value);
            }
        }
    }
    class AnimationValueWithRandom extends ValueWithRandom {
        animation = new AnimationOptions();
        doLoad(data) {
            super.doLoad(data);
            loadNestedProperty(this, "animation", data.animation);
        }
    }
    class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
        animation = new RangedAnimationOptions();
    }

    class MovePath extends OptionLoader {
        clamp = true;
        delay = new ValueWithRandom();
        enable = false;
        generator;
        options = {};
        doLoad(data) {
            loadProperty(this, "clamp", data.clamp);
            this.delay.load(data.delay);
            loadProperty(this, "enable", data.enable);
            this.generator = data.generator;
            if (data.options) {
                this.options = deepExtend(this.options, data.options);
            }
        }
    }

    class OutModes extends OptionLoader {
        bottom;
        default = exports.OutMode.out;
        left;
        right;
        top;
        doLoad(data) {
            if (data.default !== undefined) {
                this.default = data.default;
            }
            this.bottom = data.bottom ?? data.default;
            this.left = data.left ?? data.default;
            this.right = data.right ?? data.default;
            this.top = data.top ?? data.default;
        }
    }

    class Spin extends OptionLoader {
        acceleration = 0;
        enable = false;
        position;
        doLoad(data) {
            loadRangeProperty(this, "acceleration", data.acceleration);
            loadProperty(this, "enable", data.enable);
            if (data.position) {
                this.position = deepExtend({}, data.position);
            }
        }
    }

    class Move extends OptionLoader {
        angle = new MoveAngle();
        center = new MoveCenter();
        decay = 0;
        direction = exports.MoveDirection.none;
        distance = {};
        drift = 0;
        enable = false;
        gravity = new MoveGravity();
        outModes = new OutModes();
        path = new MovePath();
        random = false;
        size = false;
        speed = 2;
        spin = new Spin();
        straight = false;
        vibrate = false;
        warp = false;
        doLoad(data) {
            this.angle.load(isNumber(data.angle) ? { value: data.angle } : data.angle);
            this.center.load(data.center);
            loadRangeProperty(this, "decay", data.decay);
            loadProperty(this, "direction", data.direction);
            if (data.distance !== undefined) {
                this.distance = isNumber(data.distance)
                    ? {
                        horizontal: data.distance,
                        vertical: data.distance,
                    }
                    : { ...data.distance };
            }
            loadRangeProperty(this, "drift", data.drift);
            loadProperty(this, "enable", data.enable);
            this.gravity.load(data.gravity);
            const outModes = data.outModes;
            if (outModes !== undefined) {
                if (isObject(outModes)) {
                    this.outModes.load(outModes);
                }
                else {
                    this.outModes.load({
                        default: outModes,
                    });
                }
            }
            this.path.load(data.path);
            loadProperty(this, "random", data.random);
            loadProperty(this, "size", data.size);
            loadRangeProperty(this, "speed", data.speed);
            this.spin.load(data.spin);
            loadProperty(this, "straight", data.straight);
            loadProperty(this, "vibrate", data.vibrate);
            loadProperty(this, "warp", data.warp);
        }
    }

    class Stroke extends OptionLoader {
        color;
        opacity;
        width = 0;
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = AnimatableColor.create(this.color, data.color);
            }
            loadRangeProperty(this, "width", data.width);
            loadRangeProperty(this, "opacity", data.opacity);
        }
    }

    class Paint extends OptionLoader {
        color;
        fill;
        stroke;
        doLoad(data) {
            if (data.color !== undefined) {
                this.color = AnimatableColor.create(this.color, data.color);
            }
            loadLazyProperty(this, "fill", data.fill, () => new Fill());
            loadLazyProperty(this, "stroke", data.stroke, () => new Stroke());
        }
    }

    class ParticlesBounceFactor extends ValueWithRandom {
        value = 1;
    }

    class ParticlesBounce extends OptionLoader {
        horizontal = new ParticlesBounceFactor();
        vertical = new ParticlesBounceFactor();
        doLoad(data) {
            this.horizontal.load(data.horizontal);
            this.vertical.load(data.vertical);
        }
    }

    class ParticlesDensity extends OptionLoader {
        enable = false;
        height = 1080;
        width = 1920;
        doLoad(data) {
            loadProperty(this, "enable", data.enable);
            loadProperty(this, "width", data.width);
            loadProperty(this, "height", data.height);
        }
    }

    class ParticlesNumberLimit extends OptionLoader {
        mode = exports.LimitMode.delete;
        value = 0;
        doLoad(data) {
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "value", data.value);
        }
    }

    class ParticlesNumber extends OptionLoader {
        density = new ParticlesDensity();
        limit = new ParticlesNumberLimit();
        value = 0;
        doLoad(data) {
            this.density.load(data.density);
            this.limit.load(data.limit);
            loadProperty(this, "value", data.value);
        }
    }

    class Shape extends OptionLoader {
        close = true;
        options = {};
        type = "circle";
        doLoad(data) {
            const options = data.options;
            if (options !== undefined) {
                for (const shape in options) {
                    const item = options[shape];
                    if (item) {
                        this.options[shape] = deepExtend(this.options[shape] ?? {}, item);
                    }
                }
            }
            loadProperty(this, "close", data.close);
            loadProperty(this, "type", data.type);
        }
    }

    class ZIndex extends ValueWithRandom {
        opacityRate = 1;
        sizeRate = 1;
        velocityRate = 1;
        doLoad(data) {
            super.doLoad(data);
            loadProperty(this, "opacityRate", data.opacityRate);
            loadProperty(this, "sizeRate", data.sizeRate);
            loadProperty(this, "velocityRate", data.velocityRate);
        }
    }

    class ParticlesOptions extends OptionLoader {
        bounce = new ParticlesBounce();
        effect = new Effect();
        groups = {};
        move = new Move();
        number = new ParticlesNumber();
        paint;
        palette;
        reduceDuplicates = false;
        shape = new Shape();
        zIndex = new ZIndex();
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            super();
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.paint = new Paint();
            this.paint.color = new AnimatableColor();
            this.paint.color.value = "#fff";
            this.paint.fill = new Fill();
            this.paint.fill.enable = true;
        }
        doLoad(data) {
            if (data.palette) {
                this.palette = data.palette;
                this.#importPalette(this.palette);
            }
            if (data.groups !== undefined) {
                for (const group of Object.keys(data.groups)) {
                    if (!(group in data.groups)) {
                        continue;
                    }
                    const item = data.groups[group];
                    if (item !== undefined) {
                        this.groups[group] = deepExtend(this.groups[group] ?? {}, item);
                    }
                }
            }
            if (data.reduceDuplicates !== undefined) {
                this.reduceDuplicates = data.reduceDuplicates;
            }
            this.bounce.load(data.bounce);
            this.effect.load(data.effect);
            this.move.load(data.move);
            this.number.load(data.number);
            const paintToLoad = data.paint;
            if (paintToLoad) {
                if (isArray(paintToLoad)) {
                    this.paint = executeOnSingleOrMultiple(paintToLoad, t => {
                        const tmp = new Paint();
                        tmp.load(t);
                        return tmp;
                    });
                }
                else if (isArray(this.paint)) {
                    this.paint = new Paint();
                    this.paint.load(paintToLoad);
                }
                else {
                    this.paint.load(paintToLoad);
                }
            }
            this.shape.load(data.shape);
            this.zIndex.load(data.zIndex);
            if (this.#container) {
                for (const plugin of this.#pluginManager.plugins) {
                    if (plugin.loadParticlesOptions) {
                        plugin.loadParticlesOptions(this.#container, this, data);
                    }
                }
                const updaters = this.#pluginManager.updaters.get(this.#container);
                if (updaters) {
                    for (const updater of updaters) {
                        if (updater.loadOptions) {
                            updater.loadOptions(this, data);
                        }
                    }
                }
            }
        }
        #importPalette(palette) {
            const paletteData = this.#pluginManager.getPalette(palette);
            if (!paletteData) {
                return;
            }
            const paletteColors = paletteData.colors, defaultPaintStrokeWidth = 0, defaultPaintVariantsLength = 1, firstPaintVariantIndex = 0, defaultPalettePaintVariant = {}, colorVariants = isArray(paletteColors) ? paletteColors : [paletteColors], palettePaintVariants = colorVariants.flatMap(variant => {
                const paletteFill = variant.fill, paletteStroke = variant.stroke, fillPart = paletteFill
                    ? {
                        color: {
                            value: paletteFill.value,
                        },
                        enable: paletteFill.enable,
                        opacity: paletteFill.opacity,
                    }
                    : undefined;
                if (!paletteStroke) {
                    return [
                        {
                            fill: fillPart,
                        },
                    ];
                }
                return [
                    {
                        fill: fillPart,
                        stroke: {
                            color: {
                                value: paletteStroke.value,
                            },
                            opacity: paletteStroke.opacity,
                            width: paletteStroke.width || defaultPaintStrokeWidth,
                        },
                    },
                ];
            }), palettePaint = palettePaintVariants.length > defaultPaintVariantsLength
                ? palettePaintVariants
                : (palettePaintVariants[firstPaintVariantIndex] ?? defaultPalettePaintVariant);
            this.load({
                paint: palettePaint,
                blend: {
                    enable: true,
                    mode: paletteData.blendMode,
                },
            });
        }
    }

    function loadParticlesOptions(pluginManager, container, ...sourceOptionsArr) {
        const options = new ParticlesOptions(pluginManager, container);
        loadOptions(options, ...sourceOptionsArr);
        return options;
    }

    class Options extends OptionLoader {
        autoPlay = true;
        background;
        clear = true;
        defaultThemes = {};
        delay = 0;
        detectRetina = true;
        duration = 0;
        fpsLimit = 120;
        fullScreen;
        hdr;
        key;
        name;
        palette;
        particles;
        pauseOnBlur = true;
        pauseOnOutsideViewport = true;
        preset;
        resize;
        smooth = false;
        style = {};
        zLayers = 100;
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            super();
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.background = new Background();
            this.fullScreen = new FullScreen();
            this.hdr = new HDROptions();
            this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
            this.resize = new ResizeEvent();
        }
        doLoad(data) {
            if (data.preset !== undefined) {
                this.preset = data.preset;
                executeOnSingleOrMultiple(this.preset, preset => {
                    this.#importPreset(preset);
                });
            }
            if (data.palette !== undefined) {
                this.palette = data.palette;
                this.#importPalette(this.palette);
            }
            loadProperty(this, "autoPlay", data.autoPlay);
            loadProperty(this, "clear", data.clear);
            loadProperty(this, "key", data.key);
            loadProperty(this, "name", data.name);
            loadRangeProperty(this, "delay", data.delay);
            loadProperty(this, "detectRetina", data.detectRetina);
            loadRangeProperty(this, "duration", data.duration);
            loadProperty(this, "fpsLimit", data.fpsLimit);
            const hdrData = data.hdr;
            if (isBoolean(hdrData)) {
                this.hdr.enable = hdrData;
                this.hdr.mode = exports.HdrMode.standard;
                this.hdr.peakNits = 400;
            }
            else {
                this.hdr.load(hdrData);
            }
            loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
            loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
            loadProperty(this, "zLayers", data.zLayers);
            this.background.load(data.background);
            const fullScreen = data.fullScreen;
            if (isBoolean(fullScreen)) {
                this.fullScreen.enable = fullScreen;
            }
            else {
                this.fullScreen.load(fullScreen);
            }
            this.particles.load(data.particles);
            this.resize.load(data.resize);
            this.style = deepExtend(this.style, data.style);
            loadProperty(this, "smooth", data.smooth);
            this.#pluginManager.plugins.forEach(plugin => {
                plugin.loadOptions(this.#container, this, data);
            });
        }
        #importPalette(palette) {
            const paletteData = this.#pluginManager.getPalette(palette);
            if (!paletteData) {
                return;
            }
            this.load({
                background: {
                    color: paletteData.background,
                },
                blend: {
                    enable: true,
                    mode: paletteData.blendMode,
                },
                particles: {
                    palette,
                },
            });
        }
        #importPreset(preset) {
            this.load(this.#pluginManager.getPreset(preset));
        }
    }

    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;
    function getCachedStyle(key, generator) {
        let cached = styleCache.get(key);
        if (!cached) {
            cached = generator();
            if (styleCache.size > maxStyleCacheSize) {
                styleCache.clear();
            }
            styleCache.set(key, cached);
        }
        return cached;
    }
    function acesFilmic(x) {
        return clamp((x * (acesA * x + acesB)) / (x * (acesC * x + acesD) + acesE), none, one);
    }
    function srgbToLinear(c) {
        return c <= srgbThreshold ? c / srgbDivisor : Math.pow((c + srgbOffset) / srgbScale, srgbExponent);
    }
    function linearToSrgb(c) {
        return c <= linearThreshold ? c * linearScale : srgbScale * Math.pow(c, one / srgbExponent) - srgbOffset;
    }
    function applyHdrModeAdjustments(r, g, b, mode, maxChannel) {
        switch (mode) {
            case exports.HdrMode.vivid: {
                const avg = (r + g + b) / channelCount;
                return {
                    b: clamp(clamp(avg + (b - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
                    g: clamp(clamp(avg + (g - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
                    r: clamp(clamp(avg + (r - avg) * saturationBoost, none, maxChannel) * lightnessBoost, none, maxChannel),
                };
            }
            case exports.HdrMode.cinematic: {
                const tempR = r * temperatureR, tempB = b * temperatureB, avg = (tempR + g + tempB) / channelCount;
                return {
                    b: clamp(avg + (tempB - avg) * contrastFactor, none, maxChannel),
                    g: clamp(avg + (g - avg) * contrastFactor, none, maxChannel),
                    r: clamp(avg + (tempR - avg) * contrastFactor, none, maxChannel),
                };
            }
            case exports.HdrMode.dynamic: {
                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;
                return {
                    b: clamp(b * naturalWeight + vividB * vividWeight, none, maxChannel),
                    g: clamp(g * naturalWeight + vividG * vividWeight, none, maxChannel),
                    r: clamp(r * naturalWeight + vividR * vividWeight, none, maxChannel),
                };
            }
            case exports.HdrMode.standard:
                return { b, g, r };
            case exports.HdrMode.natural:
            default:
                return { b, g, r };
        }
    }
    function stringToRgba(pluginManager, input) {
        if (!input) {
            return;
        }
        for (const manager of pluginManager.colorManagers.values()) {
            if (manager.accepts(input)) {
                return manager.parseString(input);
            }
        }
        return undefined;
    }
    function rangeColorToRgb(pluginManager, input, index, useIndex = true) {
        if (!input) {
            return;
        }
        const color = isString(input) ? { value: input } : input;
        if (isString(color.value)) {
            return colorToRgb(pluginManager, color.value, index, useIndex);
        }
        if (isArray(color.value)) {
            const value = itemFromArray(color.value, index, useIndex);
            if (!value) {
                return;
            }
            return rangeColorToRgb(pluginManager, {
                value,
            });
        }
        for (const manager of pluginManager.colorManagers.values()) {
            const res = manager.handleRangeColor(color);
            if (res) {
                return res;
            }
        }
        return undefined;
    }
    function colorToRgb(pluginManager, input, index, useIndex = true) {
        if (!input) {
            return;
        }
        const color = isString(input) ? { value: input } : input;
        if (isString(color.value)) {
            return color.value === randomColorValue ? getRandomRgbColor() : stringToRgb(pluginManager, color.value);
        }
        if (isArray(color.value)) {
            const value = itemFromArray(color.value, index, useIndex);
            if (!value) {
                return;
            }
            return colorToRgb(pluginManager, {
                value,
            });
        }
        for (const manager of pluginManager.colorManagers.values()) {
            const res = manager.handleColor(color);
            if (res) {
                return res;
            }
        }
        return undefined;
    }
    function rangeColorToHsl(pluginManager, color, index, useIndex = true) {
        const rgb = rangeColorToRgb(pluginManager, color, index, useIndex);
        return rgb ? rgbToHsl(rgb) : undefined;
    }
    function rgbToHsl(color) {
        const r1 = color.r / rgbMax, g1 = color.g / rgbMax, b1 = color.b / rgbMax, max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1), res = {
            h: hMin,
            l: (max + min) * half,
            s: sMin,
        };
        if (max !== min) {
            res.s = res.l < half ? (max - min) / (max + min) : (max - min) / (double - max - min);
            if (r1 === max) {
                res.h = (g1 - b1) / (max - min);
            }
            else if (g1 === max) {
                res.h = double + (b1 - r1) / (max - min);
            }
            else {
                res.h = double * double + (r1 - g1) / (max - min);
            }
        }
        res.l *= lMax;
        res.s *= sMax;
        res.h *= hPhase;
        if (res.h < hMin) {
            res.h += hMax;
        }
        if (res.h >= hMax) {
            res.h -= hMax;
        }
        return res;
    }
    function stringToAlpha(pluginManager, input) {
        return stringToRgba(pluginManager, input)?.a;
    }
    function stringToRgb(pluginManager, input) {
        return stringToRgba(pluginManager, input);
    }
    function hslChannel(temp1, temp2, temp3) {
        const temp3Min = 0, temp3Max = 1;
        if (temp3 < temp3Min) {
            temp3++;
        }
        if (temp3 > temp3Max) {
            temp3--;
        }
        if (temp3 * sextuple < temp3Max) {
            return temp1 + (temp2 - temp1) * sextuple * temp3;
        }
        if (temp3 * double < temp3Max) {
            return temp2;
        }
        if (temp3 * triple < temp3Max * double) {
            const temp3Offset = double / triple;
            return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
        }
        return temp1;
    }
    function hslToRgb(hsl) {
        const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
        if (s === sMin) {
            const grayscaleValue = Math.round(lNormalized * rgbMax);
            return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
        }
        const temp1 = lNormalized < half
            ? lNormalized * (sNormalizedOffset + sNormalized)
            : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
        return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
    }
    function hslToRgbFloat(hsl) {
        const h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax;
        if (s === sMin) {
            const grayscaleValue = lNormalized * rgbMax;
            return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
        }
        const temp1 = lNormalized < half
            ? lNormalized * (sNormalizedOffset + sNormalized)
            : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseThird = phaseNumerator / triple, red = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(rgbMax, rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
        return { r: red, g: green, b: blue };
    }
    function hslaToRgba(hsla) {
        const rgbResult = hslToRgb(hsla);
        return {
            a: hsla.a,
            b: rgbResult.b,
            g: rgbResult.g,
            r: rgbResult.r,
        };
    }
    function getRandomRgbColor(min, hdr) {
        const fixedMin = min ?? defaultRgbMin;
        if (hdr) {
            return {
                r: getRandomInRange(fixedMin, rgbMax),
                g: getRandomInRange(fixedMin, rgbMax),
                b: getRandomInRange(fixedMin, rgbMax),
            };
        }
        const fixedMax = rgbMax + identity$1, getRgbInRangeValue = () => Math.floor(getRandomInRange(fixedMin, fixedMax));
        return {
            b: getRgbInRangeValue(),
            g: getRgbInRangeValue(),
            r: getRgbInRangeValue(),
        };
    }
    function getStyleFromRgb(color, hdr, opacity, peakNits, mode) {
        const rgbPrecision = hdr ? hdrRgbFixedPrecision : rgbFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
            ? `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
            : `rgb-${color.r.toFixed(rgbPrecision)}-${color.g.toFixed(rgbPrecision)}-${color.b.toFixed(rgbPrecision)}-sdr-${op.toString()}`;
        return getCachedStyle(key, () => hdr ? getHdrStyleFromRgb(color, opacity, peakNits, mode) : getSdrStyleFromRgb(color, opacity));
    }
    function getHdrStyleFromRgb(color, opacity, peakNits = maxNits, mode = exports.HdrMode.standard) {
        const headroom = peakNits / sdrReferenceWhiteNits, middleGray = 0.18, mapped = hdrToneMapColor(color, headroom, middleGray, mode);
        return `color(display-p3 ${mapped.r.toString()} ${mapped.g.toString()} ${mapped.b.toString()} / ${(opacity ?? defaultOpacity$1).toString()})`;
    }
    function hdrToneMapColor(color, headroom, middleGray, mode) {
        const rNorm = color.r / rgbMax, gNorm = color.g / rgbMax, bNorm = color.b / rgbMax;
        if (mode !== exports.HdrMode.natural && mode !== exports.HdrMode.vivid && mode !== exports.HdrMode.cinematic && mode !== exports.HdrMode.dynamic) {
            return { b: bNorm, g: gNorm, r: rNorm };
        }
        const maxChannel = Math.max(one, headroom), luminance = luminanceR * rNorm + luminanceG * gNorm + luminanceB * bNorm, mappedLuminance = hdrToneMap(luminance, headroom, middleGray), scale = luminance > none ? mappedLuminance / luminance : one;
        return applyHdrModeAdjustments(clamp(rNorm * scale, none, maxChannel), clamp(gNorm * scale, none, maxChannel), clamp(bNorm * scale, none, maxChannel), mode, maxChannel);
    }
    function hdrToneMap(normalized, headroom, middleGray) {
        if (normalized <= middleGray) {
            return acesFilmic(normalized);
        }
        const expanded = normalized + (normalized - middleGray) * (headroom - one);
        return acesFilmic(expanded);
    }
    function getSdrStyleFromRgb(color, opacity) {
        return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? defaultOpacity$1).toString()})`;
    }
    function getStyleFromHsl(color, hdr, opacity, peakNits, mode) {
        const hslPrecision = hdr ? hdrHslFixedPrecision : hslFixedPrecision, op = opacity ?? defaultOpacity$1, key = hdr
            ? `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-hdr-${op.toString()}-${(peakNits ?? maxNits).toString()}-${mode ?? exports.HdrMode.standard}`
            : `hsl-${color.h.toFixed(hslPrecision)}-${color.s.toFixed(hslPrecision)}-${color.l.toFixed(hslPrecision)}-sdr-${op.toString()}`;
        return getCachedStyle(key, () => hdr
            ? getStyleFromRgb(hslToRgbFloat(color), true, opacity, peakNits, mode)
            : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
    }
    function colorMix(color1, color2, size1, size2, hdr) {
        let rgb1 = color1, rgb2 = color2;
        if (!("r" in rgb1)) {
            rgb1 = hdr ? hslToRgbFloat(color1) : hslToRgb(color1);
        }
        if (!("r" in rgb2)) {
            rgb2 = hdr ? hslToRgbFloat(color2) : hslToRgb(color2);
        }
        if (hdr) {
            const lin1 = {
                b: srgbToLinear(rgb1.b / rgbMax),
                g: srgbToLinear(rgb1.g / rgbMax),
                r: srgbToLinear(rgb1.r / rgbMax),
            }, lin2 = {
                b: srgbToLinear(rgb2.b / rgbMax),
                g: srgbToLinear(rgb2.g / rgbMax),
                r: srgbToLinear(rgb2.r / rgbMax),
            }, totalWeight = size1 + size2;
            return {
                b: linearToSrgb((lin1.b * size1 + lin2.b * size2) / totalWeight) * rgbMax,
                g: linearToSrgb((lin1.g * size1 + lin2.g * size2) / totalWeight) * rgbMax,
                r: linearToSrgb((lin1.r * size1 + lin2.r * size2) / totalWeight) * rgbMax,
            };
        }
        return {
            b: mix(rgb1.b, rgb2.b, size1, size2),
            g: mix(rgb1.g, rgb2.g, size1, size2),
            r: mix(rgb1.r, rgb2.r, size1, size2),
        };
    }
    function getLinkColor(p1, p2, linkColor, hdr) {
        if (linkColor === randomColorValue) {
            return getRandomRgbColor();
        }
        else if (linkColor === midColorValue) {
            const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(), destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
            if (sourceColor && destColor && p2) {
                return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius(), hdr);
            }
            else {
                const hslColor = sourceColor ?? destColor;
                if (hslColor) {
                    return hslToRgb(hslColor);
                }
            }
        }
        else {
            return linkColor;
        }
        return undefined;
    }
    function getLinkRandomColor(pluginManager, optColor, blink, consent) {
        const color = isString(optColor) ? optColor : optColor.value;
        if (color === randomColorValue) {
            if (consent) {
                return rangeColorToRgb(pluginManager, {
                    value: color,
                });
            }
            if (blink) {
                return randomColorValue;
            }
            return midColorValue;
        }
        else if (color === midColorValue) {
            return midColorValue;
        }
        else {
            return rangeColorToRgb(pluginManager, {
                value: color,
            });
        }
    }
    function getHslFromAnimation(animation) {
        return animation === undefined
            ? undefined
            : {
                h: animation.h.value,
                s: animation.s.value,
                l: animation.l.value,
            };
    }
    function getHslAnimationFromHsl(hsl, animationOptions, reduceFactor) {
        const resColor = {
            h: {
                enable: false,
                value: hsl.h,
                min: hMin,
                max: hMax,
            },
            s: {
                enable: false,
                value: hsl.s,
                min: sMin,
                max: sMax,
            },
            l: {
                enable: false,
                value: hsl.l,
                min: lMin,
                max: lMax,
            },
        };
        if (animationOptions) {
            setColorAnimation(resColor.h, animationOptions.h, reduceFactor);
            setColorAnimation(resColor.s, animationOptions.s, reduceFactor);
            setColorAnimation(resColor.l, animationOptions.l, reduceFactor);
        }
        return resColor;
    }
    function setColorAnimation(colorValue, colorAnimation, reduceFactor) {
        colorValue.enable = colorAnimation.enable;
        colorValue.min = colorAnimation.min;
        colorValue.max = colorAnimation.max;
        if (colorValue.enable) {
            colorValue.velocity = (getRangeValue(colorAnimation.speed) / percentDenominator) * reduceFactor;
            colorValue.decay = decayOffset - getRangeValue(colorAnimation.decay);
            colorValue.status = exports.AnimationStatus.increasing;
            colorValue.loops = defaultLoops;
            colorValue.maxLoops = getRangeValue(colorAnimation.count);
            colorValue.time = defaultTime;
            colorValue.delayTime = getRangeValue(colorAnimation.delay) * millisecondsToSeconds;
            if (!colorAnimation.sync) {
                colorValue.velocity *= getRandom();
                colorValue.value *= getRandom();
            }
            colorValue.initialValue = colorValue.value;
            colorValue.offset = setRangeValue(colorAnimation.offset);
        }
        else {
            colorValue.velocity = defaultVelocity;
        }
    }
    function updateColorValue(data, decrease, delta, _hdr) {
        const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
        if (!data.enable ||
            ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
            return;
        }
        data.time ??= 0;
        if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
            data.time += delta.value;
        }
        if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
            return;
        }
        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;
        if (!decrease || data.status === exports.AnimationStatus.increasing) {
            data.value += velocity;
            if (data.value > max) {
                data.loops ??= 0;
                data.loops++;
                if (decrease) {
                    data.status = exports.AnimationStatus.decreasing;
                }
                else {
                    data.value -= max;
                }
            }
        }
        else {
            data.value -= velocity;
            if (data.value < min) {
                data.loops ??= 0;
                data.loops++;
                data.status = exports.AnimationStatus.increasing;
            }
        }
        if (data.velocity && decay !== identity) {
            data.velocity *= decay;
        }
        data.value = clamp(data.value, min, max);
    }
    function updateColor(color, delta, hdr) {
        if (!color) {
            return;
        }
        const { h, s, l } = color;
        updateColorValue(h, false, delta);
        updateColorValue(s, true, delta);
        updateColorValue(l, true, delta);
    }
    function alterHsl(color, type, value) {
        return {
            h: color.h,
            s: color.s,
            l: color.l + (type === exports.AlterType.darken ? -lFactor : lFactor) * value,
        };
    }

    const tsParticles = initEngine();

    class FireworkOptions {
        background;
        brightness;
        colors;
        gravity;
        minHeight;
        rate;
        saturation;
        sounds;
        speed;
        splitCount;
        constructor() {
            this.background = "none";
            this.brightness = {
                min: -30,
                max: 30,
            };
            this.colors = [
                "#FF0000",
                "#FF2A00",
                "#FF5500",
                "#FF8000",
                "#FFAA00",
                "#FFD400",
                "#FFFF00",
                "#D4FF00",
                "#AAFF00",
                "#80FF00",
                "#55FF00",
                "#2AFF00",
                "#00FF00",
                "#00FF2A",
                "#00FF55",
                "#00FF80",
                "#00FFAA",
                "#00FFD4",
                "#00FFFF",
                "#00D4FF",
                "#00AAFF",
                "#0080FF",
                "#0055FF",
                "#002AFF",
                "#0000FF",
                "#2A00FF",
                "#5500FF",
                "#8000FF",
                "#AA00FF",
                "#D400FF",
                "#FF00FF",
                "#FF00D4",
                "#FF00AA",
                "#FF0080",
                "#FF0055",
                "#FF002A",
            ];
            this.gravity = 30;
            this.minHeight = {
                min: 10,
                max: 30,
            };
            this.rate = 10;
            this.saturation = {
                min: -30,
                max: 30,
            };
            this.sounds = true;
            this.speed = { min: 20, max: 40 };
            this.splitCount = 100;
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.colors !== undefined) {
                if (isArray(data.colors)) {
                    this.colors = [...data.colors];
                }
                else {
                    this.colors = data.colors;
                }
            }
            loadProperty(this, "background", data.background);
            loadRangeProperty(this, "brightness", data.brightness);
            loadRangeProperty(this, "gravity", data.gravity);
            loadRangeProperty(this, "minHeight", data.minHeight);
            loadRangeProperty(this, "rate", data.rate);
            loadRangeProperty(this, "saturation", data.saturation);
            loadProperty(this, "sounds", data.sounds);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "splitCount", data.splitCount);
        }
    }

    const instances = new Map();
    function deleteFireworksInstance(id) {
        instances.delete(id);
    }
    const explodeSoundCheck = (args) => {
        const data = args.data;
        return data?.particle?.options.move.gravity.enable ?? false;
    };
    function getOptions(options, canvas) {
        const identity = 1;
        return {
            detectRetina: true,
            background: {
                color: options.background,
            },
            blend: {
                enable: true,
                mode: "lighter",
            },
            fullScreen: {
                enable: !canvas,
            },
            fpsLimit: 60,
            emitters: {
                direction: exports.MoveDirection.top,
                life: {
                    count: 0,
                    duration: 0.1,
                    delay: 0.1,
                },
                rate: {
                    delay: isNumber(options.rate)
                        ? identity / options.rate
                        : { min: identity / getRangeMin(options.rate), max: identity / getRangeMax(options.rate) },
                    quantity: 1,
                },
                size: {
                    width: 100,
                    height: 0,
                },
                position: {
                    y: 100,
                    x: 50,
                },
            },
            particles: {
                number: {
                    value: 0,
                },
                paint: {
                    fill: {
                        enable: false,
                    },
                    stroke: {
                        color: {
                            value: options.colors,
                        },
                        width: 2,
                    },
                },
                destroy: {
                    mode: "split",
                    bounds: {
                        top: setRangeValue(options.minHeight),
                    },
                    split: {
                        count: 1,
                        factor: {
                            value: 0.333333,
                        },
                        rate: {
                            value: options.splitCount,
                        },
                        strokeColorOffset: {
                            s: options.saturation,
                            l: options.brightness,
                        },
                        particles: {
                            group: "split",
                            number: {
                                value: 0,
                            },
                            opacity: {
                                value: {
                                    min: 0.1,
                                    max: 1,
                                },
                                animation: {
                                    enable: true,
                                    speed: { min: 2, max: 4 },
                                    sync: true,
                                    startValue: exports.StartValueType.max,
                                    destroy: exports.DestroyType.min,
                                    count: 1,
                                },
                            },
                            size: {
                                value: { min: 5, max: 10 },
                            },
                            life: {
                                count: 1,
                                duration: {
                                    value: {
                                        min: 0.5,
                                        max: 1,
                                    },
                                },
                            },
                            move: {
                                decay: 0.05,
                                enable: true,
                                gravity: {
                                    enable: false,
                                },
                                speed: {
                                    min: 10,
                                    max: 25,
                                },
                                direction: "outside",
                                outModes: exports.OutMode.destroy,
                            },
                        },
                    },
                },
                life: {
                    count: 1,
                },
                shape: {
                    type: "line",
                    options: {
                        line: {
                            cap: "round",
                        },
                    },
                },
                size: {
                    value: { min: 10, max: 20 },
                },
                rotate: {
                    path: true,
                },
                move: {
                    enable: true,
                    gravity: {
                        acceleration: setRangeValue(options.gravity),
                        enable: true,
                        inverse: true,
                        maxSpeed: 150,
                    },
                    speed: setRangeValue(options.speed),
                    outModes: {
                        default: exports.OutMode.destroy,
                        top: exports.OutMode.none,
                    },
                },
            },
            sounds: {
                enable: options.sounds,
                events: [
                    {
                        event: exports.EventType.particleRemoved,
                        filter: explodeSoundCheck,
                        audio: [
                            "https://particles.js.org/audio/explosion0.mp3",
                            "https://particles.js.org/audio/explosion1.mp3",
                            "https://particles.js.org/audio/explosion2.mp3",
                        ],
                    },
                ],
                volume: 50,
            },
        };
    }
    async function getFireworksInstance(engine, id, sourceOptions, canvas) {
        const existing = instances.get(id);
        if (existing instanceof Promise) {
            return existing;
        }
        if (existing) {
            if (!existing.destroyed) {
                return existing;
            }
            instances.delete(id);
        }
        const create = async () => {
            const options = new FireworkOptions();
            options.load(sourceOptions);
            const particlesOptions = getOptions(options, canvas), container = await engine.load({ id, element: canvas, options: particlesOptions });
            if (!container) {
                instances.delete(id);
                return;
            }
            const { FireworksInstance } = await Promise.resolve().then(function () { return FireworksInstance$1; }), instance = new FireworksInstance(container, id);
            instances.set(id, instance);
            return instance;
        }, createPromise = create();
        instances.set(id, createPromise);
        return createPromise;
    }

    class Blend {
        enable = false;
        mode = "destination-out";
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "enable", data.enable);
        }
    }

    class BlendPlugin {
        id = "blend";
        async getPlugin(container) {
            const { BlendPluginInstance } = await Promise.resolve().then(function () { return BlendPluginInstance$1; });
            return new BlendPluginInstance(container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let blendOptions = options.blend;
            if (!blendOptions?.load) {
                options.blend = blendOptions = new Blend();
            }
            blendOptions.load(source?.blend);
        }
        loadParticlesOptions(_container, options, source) {
            options.blend ??= new Blend();
            options.blend.load(source?.blend);
        }
        needsPlugin(options) {
            return !!options?.blend?.enable || !!options?.particles?.blend?.enable;
        }
    }

    async function loadBlendPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new BlendPlugin());
        });
    }

    const minAngle$1 = 0;
    function drawCircle(data) {
        const { context, particle, radius } = data;
        particle.circleRange ??= { min: minAngle$1, max: doublePI };
        const circleRange = particle.circleRange;
        context.arc(originPoint.x, originPoint.y, radius, circleRange.min, circleRange.max, false);
    }

    const sides$2 = 12, maxAngle = 360, minAngle = 0;
    class CircleDrawer {
        draw(data) {
            drawCircle(data);
        }
        getSidesCount() {
            return sides$2;
        }
        particleInit(_container, particle) {
            const shapeData = particle.shapeData, angle = shapeData?.angle ?? {
                max: maxAngle,
                min: minAngle,
            };
            particle.circleRange = isObject(angle)
                ? { min: degToRad(angle.min), max: degToRad(angle.max) }
                : {
                    min: minAngle,
                    max: degToRad(angle),
                };
        }
    }

    async function loadCircleShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["circle"], () => {
                return Promise.resolve(new CircleDrawer());
            });
        });
    }

    var RgbIndexes$1;
    (function (RgbIndexes) {
        RgbIndexes[RgbIndexes["r"] = 1] = "r";
        RgbIndexes[RgbIndexes["g"] = 2] = "g";
        RgbIndexes[RgbIndexes["b"] = 3] = "b";
        RgbIndexes[RgbIndexes["a"] = 4] = "a";
    })(RgbIndexes$1 || (RgbIndexes$1 = {}));
    const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, hexRadix = 16, defaultAlpha = 1, alphaFactor = 0xff;
    class HexColorManager {
        accepts(input) {
            return input.startsWith("#");
        }
        handleColor(color) {
            return this.#parseString(color.value);
        }
        handleRangeColor(color) {
            return this.#parseString(color.value);
        }
        parseString(input) {
            return this.#parseString(input);
        }
        #parseString(hexColor) {
            if (typeof hexColor !== "string" || !this.accepts(hexColor)) {
                return;
            }
            const hexFixed = hexColor.replace(shorthandHexRegex, (_, r, g, b, a) => {
                return r + r + g + g + b + b + (a === undefined ? "" : a + a);
            }), result = hexRegex.exec(hexFixed);
            return result
                ? {
                    a: result[RgbIndexes$1.a] ? Number.parseInt(result[RgbIndexes$1.a], hexRadix) / alphaFactor : defaultAlpha,
                    b: Number.parseInt(result[RgbIndexes$1.b] ?? "0", hexRadix),
                    g: Number.parseInt(result[RgbIndexes$1.g] ?? "0", hexRadix),
                    r: Number.parseInt(result[RgbIndexes$1.r] ?? "0", hexRadix),
                }
                : undefined;
        }
    }

    async function loadHexColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("hex", new HexColorManager());
        });
    }

    var HslIndexes;
    (function (HslIndexes) {
        HslIndexes[HslIndexes["h"] = 1] = "h";
        HslIndexes[HslIndexes["s"] = 2] = "s";
        HslIndexes[HslIndexes["l"] = 3] = "l";
        HslIndexes[HslIndexes["a"] = 5] = "a";
    })(HslIndexes || (HslIndexes = {}));
    const hslRegex = /hsla?\(\s*(\d+)\s*[\s,]\s*(\d+)%\s*[\s,]\s*(\d+)%\s*([\s,]\s*(0|1|0?\.\d+|(\d{1,3})%)\s*)?\)/i;
    class HslColorManager {
        accepts(input) {
            return input.startsWith("hsl");
        }
        handleColor(color) {
            const colorValue = color.value, hslColor = colorValue.hsl ?? color.value;
            if (!("h" in hslColor) || !("s" in hslColor) || !("l" in hslColor)) {
                return;
            }
            return hslToRgb(hslColor);
        }
        handleRangeColor(color) {
            const colorValue = color.value, hslColor = colorValue.hsl ?? color.value;
            if (!("h" in hslColor) || !("s" in hslColor) || !("l" in hslColor)) {
                return;
            }
            return hslToRgb({
                h: getRangeValue(hslColor.h),
                l: getRangeValue(hslColor.l),
                s: getRangeValue(hslColor.s),
            });
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = hslRegex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
            return result
                ? hslaToRgba({
                    a: result.length > minLength ? parseAlpha(result[HslIndexes.a]) : defaultAlpha,
                    h: Number.parseInt(result[HslIndexes.h] ?? "0", radix),
                    l: Number.parseInt(result[HslIndexes.l] ?? "0", radix),
                    s: Number.parseInt(result[HslIndexes.s] ?? "0", radix),
                })
                : undefined;
        }
    }

    async function loadHslColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("hsl", new HslColorManager());
        });
    }

    class MovePlugin {
        id = "move";
        #pluginManager;
        constructor(pluginManager) {
            this.#pluginManager = pluginManager;
        }
        async getPlugin(container) {
            const { MovePluginInstance } = await Promise.resolve().then(function () { return MovePluginInstance$1; });
            return new MovePluginInstance(this.#pluginManager, container);
        }
        loadOptions() {
        }
        needsPlugin() {
            return true;
        }
    }

    async function loadMovePlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            const moveEngine = e, movePluginManager = moveEngine.pluginManager;
            movePluginManager.initializers.pathGenerators ??= new Map();
            movePluginManager.pathGenerators ??= new Map();
            movePluginManager.addPathGenerator = (name, generator) => {
                movePluginManager.initializers.pathGenerators ??= new Map();
                movePluginManager.initializers.pathGenerators.set(name, generator);
            };
            movePluginManager.getPathGenerators = async (container, force = false) => {
                movePluginManager.initializers.pathGenerators ??= new Map();
                movePluginManager.pathGenerators ??= new Map();
                return getItemMapFromInitializer(container, movePluginManager.pathGenerators, movePluginManager.initializers.pathGenerators, force);
            };
            e.pluginManager.addPlugin(new MovePlugin(e.pluginManager));
        });
    }

    function checkDestroy(particle, destroyType, value, minValue, maxValue) {
        switch (destroyType) {
            case exports.DestroyType.max:
                if (value >= maxValue) {
                    particle.destroy();
                }
                break;
            case exports.DestroyType.min:
                if (value <= minValue) {
                    particle.destroy();
                }
                break;
        }
    }
    function initParticleNumericAnimationValue(options, pxRatio) {
        const valueRange = options.value, animationOptions = options.animation, res = {
            delayTime: getRangeValue(animationOptions.delay) * millisecondsToSeconds,
            enable: animationOptions.enable,
            value: getRangeValue(options.value) * pxRatio,
            max: getRangeMax(valueRange) * pxRatio,
            min: getRangeMin(valueRange) * pxRatio,
            loops: 0,
            maxLoops: getRangeValue(animationOptions.count),
            time: 0,
        }, decayOffset = 1;
        if (animationOptions.enable) {
            res.decay = decayOffset - getRangeValue(animationOptions.decay);
            switch (animationOptions.mode) {
                case exports.AnimationMode.increase:
                    res.status = exports.AnimationStatus.increasing;
                    break;
                case exports.AnimationMode.decrease:
                    res.status = exports.AnimationStatus.decreasing;
                    break;
                case exports.AnimationMode.random:
                    res.status = getRandom() >= half ? exports.AnimationStatus.increasing : exports.AnimationStatus.decreasing;
                    break;
            }
            const autoStatus = animationOptions.mode === exports.AnimationMode.auto;
            switch (animationOptions.startValue) {
                case exports.StartValueType.min:
                    res.value = res.min;
                    if (autoStatus) {
                        res.status = exports.AnimationStatus.increasing;
                    }
                    break;
                case exports.StartValueType.max:
                    res.value = res.max;
                    if (autoStatus) {
                        res.status = exports.AnimationStatus.decreasing;
                    }
                    break;
                case exports.StartValueType.random:
                default:
                    res.value = randomInRangeValue(res);
                    if (autoStatus) {
                        res.status = getRandom() >= half ? exports.AnimationStatus.increasing : exports.AnimationStatus.decreasing;
                    }
                    break;
            }
        }
        res.initialValue = res.value;
        return res;
    }
    function updateAnimation(particle, data, changeDirection, destroyType, delta) {
        const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minDecay = 1;
        if (particle.destroyed ||
            !data.enable ||
            ((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
            return;
        }
        const velocity = (data.velocity ?? minVelocity) * delta.factor, minValue = data.min, maxValue = data.max, decay = data.decay ?? minDecay;
        data.time ??= 0;
        const delayTime = data.delayTime ?? minDelay;
        if (delayTime > minDelay && data.time < delayTime) {
            data.time += delta.value;
            if (data.time < delayTime) {
                return;
            }
        }
        switch (data.status) {
            case exports.AnimationStatus.increasing:
                data.value += velocity;
                break;
            case exports.AnimationStatus.decreasing:
                data.value -= velocity;
                break;
        }
        if (data.velocity && decay !== identity) {
            data.velocity *= decay;
        }
        switch (data.status) {
            case exports.AnimationStatus.increasing:
                if (data.value >= maxValue) {
                    if (changeDirection) {
                        data.status = exports.AnimationStatus.decreasing;
                    }
                    else {
                        data.value -= maxValue;
                    }
                    data.loops ??= minLoops;
                    data.loops++;
                }
                break;
            case exports.AnimationStatus.decreasing:
                if (data.value <= minValue) {
                    if (changeDirection) {
                        data.status = exports.AnimationStatus.increasing;
                    }
                    else {
                        data.value += maxValue;
                    }
                    data.loops ??= minLoops;
                    data.loops++;
                }
                break;
        }
        checkDestroy(particle, destroyType, data.value, minValue, maxValue);
        if (!particle.destroyed) {
            data.value = clamp(data.value, minValue, maxValue);
        }
    }

    class OpacityAnimation extends RangedAnimationOptions {
        destroy = exports.DestroyType.none;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "destroy", data.destroy);
        }
    }

    class Opacity extends RangedAnimationValueWithRandom {
        animation = new OpacityAnimation();
        value = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            const animation = data.animation;
            if (animation !== undefined) {
                this.animation.load(animation);
            }
        }
    }

    class OpacityUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const opacityOptions = particle.options.opacity, pxRatio = 1;
            if (!opacityOptions) {
                return;
            }
            particle.opacity = initParticleNumericAnimationValue(opacityOptions, pxRatio);
            const opacityAnimation = opacityOptions.animation;
            if (opacityAnimation.enable) {
                particle.opacity.velocity =
                    (getRangeValue(opacityAnimation.speed) / percentDenominator) * this.#container.retina.reduceFactor;
                if (!opacityAnimation.sync) {
                    particle.opacity.velocity *= getRandom();
                }
            }
        }
        isEnabled(particle) {
            const none = 0;
            return (!particle.destroyed &&
                !particle.spawning &&
                !!particle.opacity &&
                particle.opacity.enable &&
                ((particle.opacity.maxLoops ?? none) <= none ||
                    ((particle.opacity.maxLoops ?? none) > none &&
                        (particle.opacity.loops ?? none) < (particle.opacity.maxLoops ?? none))));
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "opacity", Opacity, ...sources);
        }
        reset(particle) {
            if (!particle.opacity) {
                return;
            }
            particle.opacity.time = 0;
            particle.opacity.loops = 0;
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.opacity || !particle.options.opacity) {
                return;
            }
            updateAnimation(particle, particle.opacity, true, particle.options.opacity.animation.destroy, delta);
        }
    }

    async function loadOpacityUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("opacity", container => {
                return Promise.resolve(new OpacityUpdater(container));
            });
        });
    }

    const boundsMin = 0;
    function bounceHorizontal(data) {
        if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
            (data.direction !== exports.OutModeDirection.left && data.direction !== exports.OutModeDirection.right)) {
            return;
        }
        if (data.bounds.right < boundsMin && data.direction === exports.OutModeDirection.left) {
            data.particle.position.x = data.size + data.offset.x;
        }
        else if (data.bounds.left > data.canvasSize.width && data.direction === exports.OutModeDirection.right) {
            data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
        }
        const velocity = data.particle.velocity.x;
        let bounced = false;
        if (data.outOfCanvas &&
            ((data.direction === exports.OutModeDirection.right && velocity > minVelocity) ||
                (data.direction === exports.OutModeDirection.left && velocity < minVelocity))) {
            const newVelocity = getRangeValue(data.particle.options.bounce.horizontal.value);
            data.particle.velocity.x *= -newVelocity;
            bounced = true;
        }
        if (!bounced) {
            return;
        }
        const minPos = data.offset.x + data.size;
        if (data.outOfCanvas && data.direction === exports.OutModeDirection.right) {
            data.particle.position.x = data.canvasSize.width - minPos;
        }
        else if (data.outOfCanvas && data.direction === exports.OutModeDirection.left) {
            data.particle.position.x = minPos;
        }
        if (data.outMode === exports.OutMode.split) {
            data.particle.destroy();
        }
    }
    function bounceVertical(data) {
        if ((data.outMode !== exports.OutMode.bounce && data.outMode !== exports.OutMode.split) ||
            (data.direction !== exports.OutModeDirection.bottom && data.direction !== exports.OutModeDirection.top)) {
            return;
        }
        if (data.bounds.bottom < boundsMin && data.direction === exports.OutModeDirection.top) {
            data.particle.position.y = data.size + data.offset.y;
        }
        else if (data.bounds.top > data.canvasSize.height && data.direction === exports.OutModeDirection.bottom) {
            data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
        }
        const velocity = data.particle.velocity.y;
        let bounced = false;
        if (data.outOfCanvas &&
            ((data.direction === exports.OutModeDirection.bottom && velocity > minVelocity) ||
                (data.direction === exports.OutModeDirection.top && velocity < minVelocity))) {
            const newVelocity = getRangeValue(data.particle.options.bounce.vertical.value);
            data.particle.velocity.y *= -newVelocity;
            bounced = true;
        }
        if (!bounced) {
            return;
        }
        const minPos = data.offset.y + data.size;
        if (data.outOfCanvas && data.direction === exports.OutModeDirection.bottom) {
            data.particle.position.y = data.canvasSize.height - minPos;
        }
        else if (data.outOfCanvas && data.direction === exports.OutModeDirection.top) {
            data.particle.position.y = minPos;
        }
        if (data.outMode === exports.OutMode.split) {
            data.particle.destroy();
        }
    }

    class BounceOutMode {
        modes;
        #container;
        #particleBouncePlugins;
        constructor(container) {
            this.#container = container;
            this.modes = [
                exports.OutMode.bounce,
                exports.OutMode.split,
            ];
            this.#particleBouncePlugins = container.plugins.filter(p => p.particleBounce !== undefined);
        }
        update(particle, direction, delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            const container = this.#container;
            let handled = false;
            for (const plugin of this.#particleBouncePlugins) {
                handled = plugin.particleBounce?.(particle, delta, direction) ?? false;
                if (handled) {
                    break;
                }
            }
            if (handled) {
                return;
            }
            const pos = particle.getPosition(), offset = particle.offset, size = particle.getRadius(), bounds = calculateBounds(pos, size), canvasSize = container.canvas.size, outOfCanvas = !particle.isInsideCanvasForOutMode(outMode, direction);
            bounceHorizontal({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
            bounceVertical({ particle, outMode, direction, bounds, canvasSize, offset, outOfCanvas, size });
        }
    }

    class DestroyOutMode {
        modes;
        constructor(_container) {
            this.modes = [exports.OutMode.destroy];
        }
        update(particle, direction, _delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            switch (particle.outType) {
                case exports.ParticleOutType.normal:
                case exports.ParticleOutType.outside:
                    if (particle.isInsideCanvasForOutMode(outMode, direction)) {
                        return;
                    }
                    break;
                case exports.ParticleOutType.inside: {
                    const { dx, dy } = getDistances(particle.position, particle.moveCenter), { x: vx, y: vy } = particle.velocity;
                    if ((vx < minVelocity && dx > particle.moveCenter.radius) ||
                        (vy < minVelocity && dy > particle.moveCenter.radius) ||
                        (vx >= minVelocity && dx < -particle.moveCenter.radius) ||
                        (vy >= minVelocity && dy < -particle.moveCenter.radius)) {
                        return;
                    }
                    break;
                }
            }
            particle.destroy(true);
        }
    }

    class NoneOutMode {
        modes;
        #container;
        constructor(container) {
            this.#container = container;
            this.modes = [exports.OutMode.none];
        }
        update(particle, direction, _delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            if ((particle.options.move.distance.horizontal &&
                (direction === exports.OutModeDirection.left || direction === exports.OutModeDirection.right)) ??
                (particle.options.move.distance.vertical &&
                    (direction === exports.OutModeDirection.top || direction === exports.OutModeDirection.bottom))) {
                return;
            }
            const gravityOptions = particle.options.move.gravity, container = this.#container, canvasSize = container.canvas.size, pRadius = particle.getRadius();
            if (!gravityOptions.enable) {
                if ((particle.velocity.y > minVelocity && particle.position.y <= canvasSize.height + pRadius) ||
                    (particle.velocity.y < minVelocity && particle.position.y >= -pRadius) ||
                    (particle.velocity.x > minVelocity && particle.position.x <= canvasSize.width + pRadius) ||
                    (particle.velocity.x < minVelocity && particle.position.x >= -pRadius)) {
                    return;
                }
                if (!isPointInside(particle.position, container.canvas.size, originPoint, pRadius, direction)) {
                    particle.destroy();
                }
            }
            else {
                const position = particle.position;
                if ((!gravityOptions.inverse &&
                    position.y > canvasSize.height + pRadius &&
                    direction === exports.OutModeDirection.bottom) ||
                    (gravityOptions.inverse && position.y < -pRadius && direction === exports.OutModeDirection.top)) {
                    particle.destroy();
                }
            }
        }
    }

    const updateVector = Vector.origin;
    class OutOutMode {
        modes;
        #container;
        constructor(container) {
            this.#container = container;
            this.modes = [exports.OutMode.out];
        }
        update(particle, direction, _delta, outMode) {
            if (!this.modes.includes(outMode)) {
                return;
            }
            const container = this.#container;
            switch (particle.outType) {
                case exports.ParticleOutType.inside: {
                    const { x: vx, y: vy } = particle.velocity;
                    updateVector.setTo(originPoint);
                    updateVector.length = particle.moveCenter.radius;
                    updateVector.angle = particle.velocity.angle + Math.PI;
                    updateVector.addTo(particle.moveCenter);
                    const { dx, dy } = getDistances(particle.position, updateVector);
                    if ((vx <= minVelocity && dx >= minDistance) ||
                        (vy <= minVelocity && dy >= minDistance) ||
                        (vx >= minVelocity && dx <= minDistance) ||
                        (vy >= minVelocity && dy <= minDistance)) {
                        return;
                    }
                    particle.position.x = Math.floor(randomInRangeValue({
                        min: 0,
                        max: container.canvas.size.width,
                    }));
                    particle.position.y = Math.floor(randomInRangeValue({
                        min: 0,
                        max: container.canvas.size.height,
                    }));
                    const { dx: newDx, dy: newDy } = getDistances(particle.position, particle.moveCenter);
                    particle.direction = Math.atan2(-newDy, -newDx);
                    particle.velocity.angle = particle.direction;
                    particle.justWarped = true;
                    break;
                }
                default: {
                    if (particle.isInsideCanvasForOutMode(outMode, direction)) {
                        return;
                    }
                    switch (particle.outType) {
                        case exports.ParticleOutType.outside: {
                            particle.position.x =
                                Math.floor(randomInRangeValue({
                                    min: -particle.moveCenter.radius,
                                    max: particle.moveCenter.radius,
                                })) + particle.moveCenter.x;
                            particle.position.y =
                                Math.floor(randomInRangeValue({
                                    min: -particle.moveCenter.radius,
                                    max: particle.moveCenter.radius,
                                })) + particle.moveCenter.y;
                            const { dx, dy } = getDistances(particle.position, particle.moveCenter);
                            if (particle.moveCenter.radius) {
                                particle.direction = Math.atan2(dy, dx);
                                particle.velocity.angle = particle.direction;
                            }
                            particle.justWarped = true;
                            break;
                        }
                        case exports.ParticleOutType.normal: {
                            const warp = particle.options.move.warp, canvasSize = container.canvas.size, newPos = {
                                bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
                                left: -particle.getRadius() - particle.offset.x,
                                right: canvasSize.width + particle.getRadius() + particle.offset.x,
                                top: -particle.getRadius() - particle.offset.y,
                            }, sizeValue = particle.getRadius(), nextBounds = calculateBounds(particle.position, sizeValue);
                            if (direction === exports.OutModeDirection.right && nextBounds.left > canvasSize.width + particle.offset.x) {
                                particle.position.x = newPos.left;
                                particle.initialPosition.x = particle.position.x;
                                if (!warp) {
                                    particle.position.y = getRandom() * canvasSize.height;
                                    particle.initialPosition.y = particle.position.y;
                                }
                                particle.justWarped = true;
                            }
                            else if (direction === exports.OutModeDirection.left && nextBounds.right < -particle.offset.x) {
                                particle.position.x = newPos.right;
                                particle.initialPosition.x = particle.position.x;
                                if (!warp) {
                                    particle.position.y = getRandom() * canvasSize.height;
                                    particle.initialPosition.y = particle.position.y;
                                }
                                particle.justWarped = true;
                            }
                            if (direction === exports.OutModeDirection.bottom && nextBounds.top > canvasSize.height + particle.offset.y) {
                                if (!warp) {
                                    particle.position.x = getRandom() * canvasSize.width;
                                    particle.initialPosition.x = particle.position.x;
                                }
                                particle.position.y = newPos.top;
                                particle.initialPosition.y = particle.position.y;
                                particle.justWarped = true;
                            }
                            else if (direction === exports.OutModeDirection.top && nextBounds.bottom < -particle.offset.y) {
                                if (!warp) {
                                    particle.position.x = getRandom() * canvasSize.width;
                                    particle.initialPosition.x = particle.position.x;
                                }
                                particle.position.y = newPos.bottom;
                                particle.initialPosition.y = particle.position.y;
                                particle.justWarped = true;
                            }
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }

    const checkOutMode = (outModes, outMode) => {
        return (outModes.default === outMode ||
            outModes.bottom === outMode ||
            outModes.left === outMode ||
            outModes.right === outMode ||
            outModes.top === outMode);
    };
    class OutOfCanvasUpdater {
        updaters;
        #container;
        constructor(container) {
            this.#container = container;
            this.updaters = new Map();
        }
        init(particle) {
            this.#addUpdaterIfMissing(particle, exports.OutMode.bounce, container => new BounceOutMode(container));
            this.#addUpdaterIfMissing(particle, exports.OutMode.out, container => new OutOutMode(container));
            this.#addUpdaterIfMissing(particle, exports.OutMode.destroy, container => new DestroyOutMode(container));
            this.#addUpdaterIfMissing(particle, exports.OutMode.none, container => new NoneOutMode(container));
        }
        isEnabled(particle) {
            return !particle.destroyed && !particle.spawning;
        }
        update(particle, delta) {
            const outModes = particle.options.move.outModes;
            particle.justWarped = false;
            this.#updateOutMode(particle, delta, outModes.bottom ?? outModes.default, exports.OutModeDirection.bottom);
            this.#updateOutMode(particle, delta, outModes.left ?? outModes.default, exports.OutModeDirection.left);
            this.#updateOutMode(particle, delta, outModes.right ?? outModes.default, exports.OutModeDirection.right);
            this.#updateOutMode(particle, delta, outModes.top ?? outModes.default, exports.OutModeDirection.top);
        }
        #addUpdaterIfMissing(particle, outMode, getUpdater) {
            const outModes = particle.options.move.outModes;
            if (!this.updaters.has(outMode) && checkOutMode(outModes, outMode)) {
                this.updaters.set(outMode, getUpdater(this.#container));
            }
        }
        #updateOutMode(particle, delta, outMode, direction) {
            for (const updater of this.updaters.values()) {
                updater.update(particle, direction, delta, outMode);
            }
        }
    }

    async function loadOutModesUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("outModes", container => {
                return Promise.resolve(new OutOfCanvasUpdater(container));
            });
        });
    }

    const defaultOpacity = 1;
    class PaintUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
        }
        init(particle) {
            const container = this.#container, options = particle.options, paint = itemFromSingleOrMultiple(options.paint, particle.id, options.reduceDuplicates), color = paint?.color, paintColor = color ?? undefined, fill = paint?.fill, stroke = paint?.stroke;
            if (fill) {
                const fillColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), fill.color);
                particle.fillEnabled = fill.enable;
                particle.fillOpacity = getRangeValue(fill.opacity);
                particle.fillAnimation = fillColor.animation;
                const fillHslColor = rangeColorToHsl(this.#pluginManager, fillColor);
                if (fillHslColor) {
                    particle.fillColor = getHslAnimationFromHsl(fillHslColor, particle.fillAnimation, container.retina.reduceFactor);
                }
            }
            else {
                particle.fillEnabled = false;
                particle.fillAnimation = undefined;
                particle.fillColor = undefined;
                particle.fillOpacity = defaultOpacity;
            }
            if (stroke) {
                const strokeColor = AnimatableColor.create(paintColor === undefined ? undefined : AnimatableColor.create(undefined, paintColor), stroke.color);
                particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
                particle.strokeOpacity = getRangeValue(stroke.opacity ?? defaultOpacity);
                particle.strokeAnimation = strokeColor.animation;
                const strokeHslColor = rangeColorToHsl(this.#pluginManager, strokeColor) ?? particle.getFillColor();
                if (strokeHslColor) {
                    particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
                }
            }
            else {
                particle.strokeAnimation = undefined;
                particle.strokeColor = undefined;
                particle.strokeOpacity = defaultOpacity;
                particle.strokeWidth = 0;
            }
        }
        isEnabled(particle) {
            const { fillAnimation, fillColor, strokeAnimation, strokeColor } = particle, fillEnabled = !!fillAnimation &&
                ((fillColor?.h.value !== undefined && fillColor.h.enable) ||
                    (fillColor?.s.value !== undefined && fillColor.s.enable) ||
                    (fillColor?.l.value !== undefined && fillColor.l.enable)), strokeEnabled = !!strokeAnimation &&
                ((strokeColor?.h.value !== undefined && strokeColor.h.enable) ||
                    (strokeColor?.s.value !== undefined && strokeColor.s.enable) ||
                    (strokeColor?.l.value !== undefined && strokeColor.l.enable));
            return !particle.destroyed && !particle.spawning && (fillEnabled || strokeEnabled);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            updateColor(particle.fillColor, delta, this.#container.hdr);
            updateColor(particle.strokeColor, delta, this.#container.hdr);
        }
    }

    async function loadPaintUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("paint", container => {
                return Promise.resolve(new PaintUpdater(e.pluginManager, container));
            });
        });
    }

    var RgbIndexes;
    (function (RgbIndexes) {
        RgbIndexes[RgbIndexes["r"] = 1] = "r";
        RgbIndexes[RgbIndexes["g"] = 2] = "g";
        RgbIndexes[RgbIndexes["b"] = 3] = "b";
        RgbIndexes[RgbIndexes["a"] = 5] = "a";
    })(RgbIndexes || (RgbIndexes = {}));
    const rgbRegex = /rgba?\(\s*(\d{1,3})\s*[\s,]\s*(\d{1,3})\s*[\s,]\s*(\d{1,3})\s*([\s,]\s*(0|1|0?\.\d+|(\d{1,3})%)\s*)?\)/i;
    class RgbColorManager {
        accepts(input) {
            return input.startsWith("rgb");
        }
        handleColor(color) {
            const colorValue = color.value, rgbColor = colorValue.rgb ?? color.value;
            if (!("r" in rgbColor) || !("g" in rgbColor) || !("b" in rgbColor)) {
                return;
            }
            return rgbColor;
        }
        handleRangeColor(color) {
            const colorValue = color.value, rgbColor = colorValue.rgb ?? color.value;
            if (!("r" in rgbColor) || !("g" in rgbColor) || !("b" in rgbColor)) {
                return;
            }
            return {
                r: getRangeValue(rgbColor.r),
                g: getRangeValue(rgbColor.g),
                b: getRangeValue(rgbColor.b),
            };
        }
        parseString(input) {
            if (!this.accepts(input)) {
                return;
            }
            const result = rgbRegex.exec(input), radix = 10, minLength = 4, defaultAlpha = 1;
            return result
                ? {
                    a: result.length > minLength ? parseAlpha(result[RgbIndexes.a]) : defaultAlpha,
                    b: parseInt(result[RgbIndexes.b] ?? "0", radix),
                    g: parseInt(result[RgbIndexes.g] ?? "0", radix),
                    r: parseInt(result[RgbIndexes.r] ?? "0", radix),
                }
                : undefined;
        }
    }

    async function loadRgbColorPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addColorManager("rgb", new RgbColorManager());
        });
    }

    class SizeAnimation extends RangedAnimationOptions {
        destroy = exports.DestroyType.none;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "destroy", data.destroy);
        }
    }

    class Size extends RangedAnimationValueWithRandom {
        animation = new SizeAnimation();
        value = 3;
        load(data) {
            super.load(data);
            if (isNull(data)) {
                return;
            }
            const animation = data.animation;
            if (animation !== undefined) {
                this.animation.load(animation);
            }
        }
    }

    const minLoops = 0;
    class SizeUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const container = this.#container, sizeOptions = particle.options.size;
            if (!sizeOptions) {
                return;
            }
            const sizeAnimation = sizeOptions.animation;
            if (!sizeAnimation.enable) {
                return;
            }
            particle.size.velocity = (particle.retina.sizeAnimationSpeed / percentDenominator) * container.retina.reduceFactor;
            if (sizeAnimation.sync) {
                return;
            }
            particle.size.velocity *= getRandom();
        }
        isEnabled(particle) {
            return (!particle.destroyed &&
                !particle.spawning &&
                particle.size.enable &&
                ((particle.size.maxLoops ?? minLoops) <= minLoops ||
                    ((particle.size.maxLoops ?? minLoops) > minLoops &&
                        (particle.size.loops ?? minLoops) < (particle.size.maxLoops ?? minLoops))));
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "size", Size, ...sources);
        }
        preInit(particle) {
            const pxRatio = this.#container.retina.pixelRatio, options = particle.options, sizeOptions = options.size;
            if (!sizeOptions) {
                return;
            }
            particle.size = initParticleNumericAnimationValue(sizeOptions, pxRatio);
            particle.retina.sizeAnimationSpeed = getRangeValue(sizeOptions.animation.speed) * pxRatio;
        }
        reset(particle) {
            particle.size.time = 0;
            particle.size.loops = 0;
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.options.size) {
                return;
            }
            updateAnimation(particle, particle.size, true, particle.options.size.animation.destroy, delta);
        }
    }

    async function loadSizeUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("size", container => {
                return Promise.resolve(new SizeUpdater(container));
            });
        });
    }

    async function loadBasic(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            await Promise.all([
                loadBlendPlugin(e),
                loadHexColorPlugin(e),
                loadHslColorPlugin(e),
                loadRgbColorPlugin(e),
                loadMovePlugin(e),
                loadCircleShape(e),
                loadPaintUpdater(e),
                loadOpacityUpdater(e),
                loadOutModesUpdater(e),
                loadSizeUpdater(e),
            ]);
        });
    }

    class DestroyBounds {
        bottom;
        left;
        right;
        top;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "bottom", data.bottom);
            loadRangeProperty(this, "left", data.left);
            loadRangeProperty(this, "right", data.right);
            loadRangeProperty(this, "top", data.top);
        }
    }

    var DestroyMode;
    (function (DestroyMode) {
        DestroyMode["explode"] = "explode";
        DestroyMode["none"] = "none";
        DestroyMode["split"] = "split";
    })(DestroyMode || (DestroyMode = {}));

    class Explode {
        maxSizeFactor = 3;
        speed = 2;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "maxSizeFactor", data.maxSizeFactor);
            loadProperty(this, "speed", data.speed);
        }
    }

    class SplitFactor extends ValueWithRandom {
        value = 3;
    }

    class SplitRate extends ValueWithRandom {
        value = { min: 4, max: 9 };
    }

    class Split {
        count = 1;
        factor = new SplitFactor();
        fillColor;
        fillColorOffset;
        particles;
        rate = new SplitRate();
        sizeOffset = true;
        strokeColor;
        strokeColorOffset;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.fillColor !== undefined) {
                this.fillColor = OptionsColor.create(this.fillColor, data.fillColor);
            }
            if (data.strokeColor !== undefined) {
                this.strokeColor = OptionsColor.create(this.strokeColor, data.strokeColor);
            }
            loadProperty(this, "count", data.count);
            this.factor.load(data.factor);
            this.rate.load(data.rate);
            this.particles = executeOnSingleOrMultiple(data.particles, particles => {
                return deepExtend({}, particles);
            });
            loadProperty(this, "sizeOffset", data.sizeOffset);
            if (data.fillColorOffset) {
                this.fillColorOffset = this.fillColorOffset ?? {};
                if (data.fillColorOffset.h !== undefined) {
                    this.fillColorOffset.h = data.fillColorOffset.h;
                }
                if (data.fillColorOffset.s !== undefined) {
                    this.fillColorOffset.s = data.fillColorOffset.s;
                }
                if (data.fillColorOffset.l !== undefined) {
                    this.fillColorOffset.l = data.fillColorOffset.l;
                }
            }
            if (data.strokeColorOffset) {
                this.strokeColorOffset = this.strokeColorOffset ?? {};
                if (data.strokeColorOffset.h !== undefined) {
                    this.strokeColorOffset.h = data.strokeColorOffset.h;
                }
                if (data.strokeColorOffset.s !== undefined) {
                    this.strokeColorOffset.s = data.strokeColorOffset.s;
                }
                if (data.strokeColorOffset.l !== undefined) {
                    this.strokeColorOffset.l = data.strokeColorOffset.l;
                }
            }
        }
    }

    class Destroy {
        bounds = new DestroyBounds();
        explode = new Explode();
        mode = DestroyMode.none;
        split = new Split();
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.mode) {
                this.mode = data.mode;
            }
            if (data.bounds) {
                this.bounds.load(data.bounds);
            }
            this.explode.load(data.explode);
            this.split.load(data.split);
        }
    }

    const defaultOffset = 0, minDestroySize = 0.5, defaultSplitCount = 0, increment = 1, unbreakableTime = 500, minSplitCount = 0, minHue = 0, hueRange = 360, minSaturation = 0, maxSaturation = 100, minLightness = 0, maxLightness = 100;
    function createParentColor(parentColor) {
        return AnimatableColor.create(undefined, {
            value: {
                hsl: parentColor,
            },
        });
    }
    function createOffsetColor(parentColor, offset) {
        const offsetH = getRangeValue(offset.h ?? defaultOffset), offsetS = getRangeValue(offset.s ?? defaultOffset), offsetL = getRangeValue(offset.l ?? defaultOffset), h = (parentColor.h + offsetH) % hueRange, s = Math.max(minSaturation, Math.min(maxSaturation, parentColor.s + offsetS)), l = Math.max(minLightness, Math.min(maxLightness, parentColor.l + offsetL));
        return AnimatableColor.create(undefined, {
            value: {
                hsl: {
                    h: h < minHue ? h + hueRange : h,
                    s,
                    l,
                },
            },
        });
    }
    function resolveSplitColor(offset, splitColor, splitParticlesColor, parentColor) {
        if (offset && parentColor) {
            return createOffsetColor(parentColor, offset);
        }
        if (splitColor) {
            return AnimatableColor.create(undefined, splitColor);
        }
        if (splitParticlesColor) {
            return AnimatableColor.create(undefined, splitParticlesColor);
        }
        return parentColor ? createParentColor(parentColor) : undefined;
    }
    function addSplitParticle(pluginManager, container, parent, splitParticlesOptions) {
        const destroyOptions = parent.options.destroy;
        if (!destroyOptions) {
            return;
        }
        const splitOptions = destroyOptions.split, splitParticleOptions = loadParticlesOptions(pluginManager, container, parent.options), splitFillColor = itemFromSingleOrMultiple(splitOptions.fillColor), splitStrokeColor = itemFromSingleOrMultiple(splitOptions.strokeColor), parentFillColor = parent.getFillColor(), parentStrokeColor = parent.getStrokeColor();
        splitParticleOptions.move.load({
            center: {
                x: parent.position.x,
                y: parent.position.y,
                mode: exports.PixelMode.precise,
            },
        });
        const factor = identity$1 / getRangeValue(splitOptions.factor.value), sizeOptions = splitParticleOptions["size"];
        if (sizeOptions) {
            if (isNumber(sizeOptions.value)) {
                sizeOptions.value *= factor;
            }
            else {
                sizeOptions.value.min *= factor;
                sizeOptions.value.max *= factor;
            }
        }
        splitParticleOptions.load(splitParticlesOptions);
        const splitParticlePaintOptions = itemFromSingleOrMultiple(splitParticleOptions.paint), splitParticleFillOptions = splitParticlePaintOptions?.fill, splitParticleStrokeOptions = splitParticlePaintOptions?.stroke, fillColor = resolveSplitColor(splitOptions.fillColorOffset, splitFillColor, splitParticleFillOptions?.color, parentFillColor), strokeColor = resolveSplitColor(splitOptions.strokeColorOffset, splitStrokeColor, splitParticleStrokeOptions?.color, parentStrokeColor);
        if (fillColor && splitParticleFillOptions) {
            splitParticleFillOptions.color = fillColor;
        }
        if (strokeColor && splitParticleStrokeOptions) {
            splitParticleStrokeOptions.color = strokeColor;
        }
        const offset = splitOptions.sizeOffset ? setRangeValue(-parent.size.value, parent.size.value) : defaultOffset, position = {
            x: parent.position.x + randomInRangeValue(offset),
            y: parent.position.y + randomInRangeValue(offset),
        };
        return container.particles.addParticle(position, splitParticleOptions, parent.group, (particle) => {
            if (particle.size.value < minDestroySize) {
                return false;
            }
            particle.velocity.length = randomInRangeValue(setRangeValue(parent.velocity.length, particle.velocity.length));
            particle.splitCount = (parent.splitCount ?? defaultSplitCount) + increment;
            particle.unbreakable = true;
            particle.unbreakableUntil = performance.now() + unbreakableTime;
            return true;
        });
    }
    function split(pluginManager, container, particle) {
        const destroyOptions = particle.options.destroy;
        if (!destroyOptions) {
            return;
        }
        const splitOptions = destroyOptions.split;
        if (splitOptions.count >= minSplitCount) {
            if (particle.splitCount === undefined || particle.splitCount > splitOptions.count) {
                return;
            }
            particle.splitCount++;
        }
        const rate = getRangeValue(splitOptions.rate.value), particlesSplitOptions = itemFromSingleOrMultiple(splitOptions.particles);
        for (let i = 0; i < rate; i++) {
            addSplitParticle(pluginManager, container, particle, particlesSplitOptions);
        }
    }

    const defaultDeltaFactor$1 = 1, fpsFactor = 60, minExplodeSpeed = 0.01, maxExplodeProgress = 1;
    class DestroyUpdater {
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#container = container;
            this.#pluginManager = pluginManager;
        }
        init(particle) {
            const container = this.#container, particlesOptions = particle.options, destroyOptions = particlesOptions.destroy;
            if (!destroyOptions) {
                return;
            }
            particle.exploding = undefined;
            particle.splitCount = 0;
            const destroyBoundsOptions = destroyOptions.bounds;
            particle.destroyBounds ??= {};
            const { bottom, left, right, top } = destroyBoundsOptions, { destroyBounds } = particle, canvasSize = container.canvas.size;
            if (bottom) {
                destroyBounds.bottom = (getRangeValue(bottom) * canvasSize.height) / percentDenominator;
            }
            if (left) {
                destroyBounds.left = (getRangeValue(left) * canvasSize.width) / percentDenominator;
            }
            if (right) {
                destroyBounds.right = (getRangeValue(right) * canvasSize.width) / percentDenominator;
            }
            if (top) {
                destroyBounds.top = (getRangeValue(top) * canvasSize.height) / percentDenominator;
            }
        }
        isEnabled(particle) {
            const destroyParticle = particle;
            return !destroyParticle.destroyed || !!destroyParticle.exploding;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "destroy", Destroy, ...sources);
        }
        particleDestroyed(particle, override) {
            if (override) {
                return;
            }
            const destroyOptions = particle.options.destroy;
            switch (destroyOptions?.mode) {
                case DestroyMode.split:
                    split(this.#pluginManager, this.#container, particle);
                    break;
                case DestroyMode.explode: {
                    if (particle.exploding) {
                        particle.destroyed = false;
                        break;
                    }
                    const { explode } = destroyOptions, initialSize = particle.size.value, maxSize = initialSize * explode.maxSizeFactor, opacity = particle.getOpacity();
                    particle.exploding = {
                        initialFillOpacity: opacity.fillOpacity,
                        initialSize,
                        initialStrokeOpacity: opacity.strokeOpacity,
                        maxSize,
                        progress: 0,
                        speed: Math.max(explode.speed, minExplodeSpeed),
                    };
                    particle.fillOpacity = opacity.fillOpacity;
                    particle.strokeOpacity = opacity.strokeOpacity;
                    particle.destroyed = false;
                    break;
                }
            }
        }
        update(particle, delta) {
            if (particle.exploding) {
                const explosionState = particle.exploding, deltaFactor = delta.factor || defaultDeltaFactor$1;
                explosionState.progress = Math.min(maxExplodeProgress, explosionState.progress + (explosionState.speed * deltaFactor) / fpsFactor);
                const progress = explosionState.progress;
                particle.size.value =
                    explosionState.initialSize + (explosionState.maxSize - explosionState.initialSize) * progress;
                particle.fillOpacity = explosionState.initialFillOpacity * (maxExplodeProgress - progress);
                particle.strokeOpacity = explosionState.initialStrokeOpacity * (maxExplodeProgress - progress);
                if (progress >= maxExplodeProgress) {
                    particle.exploding = undefined;
                    particle.destroy(true);
                }
                return;
            }
            if (particle.unbreakableUntil !== undefined && performance.now() >= particle.unbreakableUntil) {
                particle.unbreakable = false;
                particle.unbreakableUntil = undefined;
            }
            const position = particle.getPosition(), bounds = particle.destroyBounds;
            if (!bounds) {
                return;
            }
            if ((bounds.bottom !== undefined && position.y >= bounds.bottom) ||
                (bounds.left !== undefined && position.x <= bounds.left) ||
                (bounds.right !== undefined && position.x >= bounds.right) ||
                (bounds.top !== undefined && position.y <= bounds.top)) {
                particle.destroy();
            }
        }
    }

    async function loadDestroyUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("destroy", container => {
                return Promise.resolve(new DestroyUpdater(e.pluginManager, container));
            });
        });
    }

    class EmitterLife {
        count;
        delay;
        duration;
        wait = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "count", data.count);
            loadRangeProperty(this, "delay", data.delay);
            loadRangeProperty(this, "duration", data.duration);
            loadProperty(this, "wait", data.wait);
        }
    }

    class EmitterRate {
        delay = 0.1;
        quantity = 1;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadRangeProperty(this, "quantity", data.quantity);
            loadRangeProperty(this, "delay", data.delay);
        }
    }

    class EmitterShapeReplace {
        color = false;
        opacity = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "color", data.color);
            loadProperty(this, "opacity", data.opacity);
        }
    }

    class EmitterShape {
        options = {};
        replace = new EmitterShapeReplace();
        type = "square";
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.options !== undefined) {
                this.options = deepExtend({}, data.options ?? {});
            }
            this.replace.load(data.replace);
            loadProperty(this, "type", data.type);
        }
    }

    class EmitterSize {
        height = 0;
        mode = exports.PixelMode.percent;
        width = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "mode", data.mode);
            loadProperty(this, "height", data.height);
            loadProperty(this, "width", data.width);
        }
    }

    class EmitterSpawn {
        fill;
        stroke;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (data.fill) {
                this.fill ??= new Fill();
                this.fill.load(data.fill);
            }
            if (data.stroke) {
                this.stroke ??= new Stroke();
                this.stroke.load(data.stroke);
            }
        }
    }

    class Emitter {
        autoPlay = true;
        direction;
        domId;
        fill = true;
        life = new EmitterLife();
        name;
        particles;
        position;
        rate = new EmitterRate();
        shape = new EmitterShape();
        size;
        spawn = new EmitterSpawn();
        spawnFillColor;
        spawnStrokeColor;
        startCount = 0;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "autoPlay", data.autoPlay);
            if (data.size !== undefined) {
                this.size ??= new EmitterSize();
                this.size.load(data.size);
            }
            loadProperty(this, "direction", data.direction);
            loadProperty(this, "domId", data.domId);
            loadProperty(this, "fill", data.fill);
            this.life.load(data.life);
            loadProperty(this, "name", data.name);
            this.particles = executeOnSingleOrMultiple(data.particles, particles => {
                return deepExtend({}, particles);
            });
            this.rate.load(data.rate);
            this.shape.load(data.shape);
            this.spawn.load(data.spawn);
            if (data.position !== undefined) {
                this.position = {};
                if (data.position.x !== undefined) {
                    this.position.x = setRangeValue(data.position.x);
                }
                if (data.position.y !== undefined) {
                    this.position.y = setRangeValue(data.position.y);
                }
            }
            if (data.spawnFillColor !== undefined) {
                this.spawnFillColor ??= new AnimatableColor();
                this.spawnFillColor.load(data.spawnFillColor);
            }
            if (data.spawnStrokeColor !== undefined) {
                this.spawnStrokeColor ??= new AnimatableColor();
                this.spawnStrokeColor.load(data.spawnStrokeColor);
            }
            loadProperty(this, "startCount", data.startCount);
        }
    }

    class EmittersPlugin {
        id = "emitters";
        #instancesManager;
        constructor(instancesManager) {
            this.#instancesManager = instancesManager;
        }
        async getPlugin(container) {
            const { EmittersPluginInstance } = await Promise.resolve().then(function () { return EmittersPluginInstance$1; });
            return new EmittersPluginInstance(this.#instancesManager, container);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            if (source?.emitters) {
                options.emitters = executeOnSingleOrMultiple(source.emitters, emitter => {
                    const tmp = new Emitter();
                    tmp.load(emitter);
                    return tmp;
                });
            }
        }
        needsPlugin(options) {
            if (!options) {
                return false;
            }
            const emitters = options.emitters;
            return (isArray(emitters) && !!emitters.length) || emitters !== undefined;
        }
    }

    async function addEmittersShapesManager(e) {
        const { ShapeManager } = await Promise.resolve().then(function () { return ShapeManager$1; }), pluginManager = e.pluginManager;
        pluginManager.emitterShapeManager ??= new ShapeManager();
        pluginManager.addEmitterShapeGenerator ??= (name, generator) => {
            pluginManager.emitterShapeManager?.addShapeGenerator(name, generator);
        };
    }

    const instancesManagers = new WeakMap();
    function getEmittersInstancesManager(e) {
        const pluginManager = e.pluginManager;
        let manager = instancesManagers.get(pluginManager);
        if (!manager) {
            manager = Promise.resolve().then(function () { return EmittersInstancesManager$1; })
                .then(({ EmittersInstancesManager }) => new EmittersInstancesManager(pluginManager))
                .catch((error) => {
                instancesManagers.delete(pluginManager);
                throw error;
            });
            instancesManagers.set(pluginManager, manager);
        }
        return manager;
    }

    class EmitterShapeBase {
        fill;
        options;
        position;
        size;
        constructor(position, size, fill, options) {
            this.position = position;
            this.size = size;
            this.fill = fill;
            this.options = options;
        }
        resize(position, size) {
            this.position = position;
            this.size = size;
        }
    }

    var EmitterClickMode;
    (function (EmitterClickMode) {
        EmitterClickMode["emitter"] = "emitter";
    })(EmitterClickMode || (EmitterClickMode = {}));

    async function loadEmittersPluginSimple(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const instancesManager = await getEmittersInstancesManager(e);
            await addEmittersShapesManager(e);
            e.pluginManager.addPlugin(new EmittersPlugin(instancesManager));
        });
    }

    function ensureEmittersPluginLoaded(e) {
        if (!e.pluginManager.addEmitterShapeGenerator) {
            throw new Error("tsParticles Emitters Plugin is not loaded");
        }
    }

    const sides$1 = 4;
    var Sides;
    (function (Sides) {
        Sides[Sides["TopLeft"] = 0] = "TopLeft";
        Sides[Sides["TopRight"] = 1] = "TopRight";
        Sides[Sides["BottomRight"] = 2] = "BottomRight";
        Sides[Sides["BottomLeft"] = 3] = "BottomLeft";
    })(Sides || (Sides = {}));
    function randomSquareCoordinate(position, offset) {
        return position + offset * (getRandom() - half);
    }
    function getRandomSize(sides) {
        return Math.floor(getRandom() * sides);
    }
    class EmittersSquareShape extends EmitterShapeBase {
        constructor(position, size, fill, options) {
            super(position, size, fill, options);
        }
        async init() {
        }
        randomPosition() {
            const fill = this.fill, position = this.position, size = this.size;
            if (fill) {
                return {
                    position: {
                        x: randomSquareCoordinate(position.x, size.width),
                        y: randomSquareCoordinate(position.y, size.height),
                    },
                };
            }
            else {
                const halfW = size.width * half, halfH = size.height * half, side = getRandomSize(sides$1), v = (getRandom() - half) * double;
                switch (side) {
                    case Sides.TopLeft:
                        return {
                            position: {
                                x: position.x + v * halfW,
                                y: position.y - halfH,
                            },
                        };
                    case Sides.TopRight:
                        return {
                            position: {
                                x: position.x - halfW,
                                y: position.y + v * halfH,
                            },
                        };
                    case Sides.BottomRight:
                        return {
                            position: {
                                x: position.x + v * halfW,
                                y: position.y + halfH,
                            },
                        };
                    case Sides.BottomLeft:
                    default:
                        return {
                            position: {
                                x: position.x + halfW,
                                y: position.y + v * halfH,
                            },
                        };
                }
            }
        }
    }

    class EmittersSquareShapeGenerator {
        generate(_container, position, size, fill, options) {
            return new EmittersSquareShape(position, size, fill, options);
        }
    }

    async function loadEmittersShapeSquare(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register((e) => {
            ensureEmittersPluginLoaded(e);
            e.pluginManager.addEmitterShapeGenerator?.("square", new EmittersSquareShapeGenerator());
        });
    }

    class LifeDelay extends ValueWithRandom {
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "sync", data.sync);
        }
    }

    class LifeDuration extends ValueWithRandom {
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "sync", data.sync);
        }
    }

    class Life {
        count = 0;
        delay = new LifeDelay();
        duration = new LifeDuration();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "count", data.count);
            this.delay.load(data.delay);
            this.duration.load(data.duration);
        }
    }

    const noTime$1 = 0, infiniteValue$1 = -1, noLife = 0, minCanvasSize = 0;
    function updateLife(particle, delta, canvasSize) {
        if (!particle.life) {
            return;
        }
        const life = particle.life;
        let justSpawned = false;
        if (particle.spawning) {
            life.delayTime += delta.value;
            if (life.delayTime >= particle.life.delay) {
                justSpawned = true;
                particle.spawning = false;
                life.delayTime = noTime$1;
                life.time = noTime$1;
            }
            else {
                return;
            }
        }
        if (life.duration === infiniteValue$1) {
            return;
        }
        if (justSpawned) {
            life.time = noTime$1;
        }
        else {
            life.time += delta.value;
        }
        if (life.time < life.duration) {
            return;
        }
        life.time = noTime$1;
        if (particle.life.count > noLife) {
            particle.life.count--;
        }
        if (particle.life.count === noLife) {
            particle.destroy();
            return;
        }
        const widthRange = setRangeValue(minCanvasSize, canvasSize.width), heightRange = setRangeValue(minCanvasSize, canvasSize.width);
        particle.position.x = randomInRangeValue(widthRange);
        particle.position.y = randomInRangeValue(heightRange);
        particle.spawning = true;
        life.delayTime = noTime$1;
        life.time = noTime$1;
        particle.reset();
        const lifeOptions = particle.options.life;
        if (lifeOptions) {
            life.delay = getRangeValue(lifeOptions.delay.value) * millisecondsToSeconds;
            life.duration = getRangeValue(lifeOptions.duration.value) * millisecondsToSeconds;
        }
    }

    const noTime = 0, identity = 1, infiniteValue = -1;
    class LifeUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const container = this.#container, particlesOptions = particle.options, lifeOptions = particlesOptions.life;
            if (!lifeOptions) {
                return;
            }
            const delayFactor = lifeOptions.delay.sync ? identity : getRandom(), durationFactor = lifeOptions.duration.sync ? identity : getRandom();
            particle.life = {
                delay: container.retina.reduceFactor
                    ? ((getRangeValue(lifeOptions.delay.value) * delayFactor) / container.retina.reduceFactor) *
                        millisecondsToSeconds
                    : noTime,
                delayTime: noTime,
                duration: container.retina.reduceFactor
                    ? ((getRangeValue(lifeOptions.duration.value) * durationFactor) / container.retina.reduceFactor) *
                        millisecondsToSeconds
                    : noTime,
                time: noTime,
                count: lifeOptions.count,
            };
            if (particle.life.duration <= noTime) {
                particle.life.duration = infiniteValue;
            }
            if (particle.life.count <= noTime) {
                particle.life.count = infiniteValue;
            }
            particle.spawning = particle.life.delay > noTime;
        }
        isEnabled(particle) {
            return !particle.destroyed;
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "life", Life, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle) || !particle.life) {
                return;
            }
            updateLife(particle, delta, this.#container.canvas.size);
        }
    }

    async function loadLifeUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("life", container => {
                return Promise.resolve(new LifeUpdater(container));
            });
        });
    }

    function drawLine(data) {
        const { context, particle, radius } = data, shapeData = particle.shapeData, centerY = 0;
        context.moveTo(-radius, centerY);
        context.lineTo(radius, centerY);
        context.lineCap = shapeData?.cap ?? "butt";
    }

    const sides = 1;
    class LineDrawer {
        draw(data) {
            drawLine(data);
        }
        getSidesCount() {
            return sides;
        }
    }

    async function loadLineShape(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addShape(["line"], () => Promise.resolve(new LineDrawer()));
        });
    }

    class RotateAnimation {
        decay = 0;
        enable = false;
        speed = 0;
        sync = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            loadRangeProperty(this, "speed", data.speed);
            loadRangeProperty(this, "decay", data.decay);
            loadProperty(this, "sync", data.sync);
        }
    }

    class Rotate extends ValueWithRandom {
        animation = new RotateAnimation();
        direction = exports.RotateDirection.clockwise;
        path = false;
        load(data) {
            if (isNull(data)) {
                return;
            }
            super.load(data);
            loadProperty(this, "direction", data.direction);
            this.animation.load(data.animation);
            loadProperty(this, "path", data.path);
        }
    }

    const doublePIDeg = 360;
    class RotateUpdater {
        #container;
        constructor(container) {
            this.#container = container;
        }
        init(particle) {
            const rotateOptions = particle.options.rotate;
            if (!rotateOptions) {
                return;
            }
            particle.rotate = {
                enable: rotateOptions.animation.enable,
                value: degToRad(getRangeValue(rotateOptions.value)),
                min: 0,
                max: doublePI,
            };
            particle.pathRotation = rotateOptions.path;
            let rotateDirection = rotateOptions.direction;
            if (rotateDirection === exports.RotateDirection.random) {
                const index = Math.floor(getRandom() * double), minIndex = 0;
                rotateDirection = index > minIndex ? exports.RotateDirection.counterClockwise : exports.RotateDirection.clockwise;
            }
            switch (rotateDirection) {
                case exports.RotateDirection.counterClockwise:
                case "counterClockwise":
                    particle.rotate.status = exports.AnimationStatus.decreasing;
                    break;
                case exports.RotateDirection.clockwise:
                    particle.rotate.status = exports.AnimationStatus.increasing;
                    break;
            }
            const rotateAnimation = rotateOptions.animation;
            if (rotateAnimation.enable) {
                particle.rotate.decay = identity$1 - getRangeValue(rotateAnimation.decay);
                particle.rotate.velocity =
                    (getRangeValue(rotateAnimation.speed) / doublePIDeg) * this.#container.retina.reduceFactor;
                if (!rotateAnimation.sync) {
                    particle.rotate.velocity *= getRandom();
                }
            }
            particle.rotation = particle.rotate.value;
        }
        isEnabled(particle) {
            const rotate = particle.options.rotate;
            if (!rotate) {
                return false;
            }
            return !particle.destroyed && !particle.spawning && (!!rotate.value || rotate.animation.enable || rotate.path);
        }
        loadOptions(options, ...sources) {
            loadOptionProperty(options, "rotate", Rotate, ...sources);
        }
        update(particle, delta) {
            if (!this.isEnabled(particle)) {
                return;
            }
            particle.isRotating = !!particle.rotate;
            if (!particle.rotate) {
                return;
            }
            updateAnimation(particle, particle.rotate, false, exports.DestroyType.none, delta);
            particle.rotation = particle.rotate.value;
        }
    }

    async function loadRotateUpdater(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addParticleUpdater("rotate", container => {
                return Promise.resolve(new RotateUpdater(container));
            });
        });
    }

    const mouseDownEvent = "pointerdown", touchStartEvent = "touchstart";

    class SoundsAudio {
        loop = false;
        source = "";
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (isObject(data)) {
                loadProperty(this, "loop", data.loop);
                if (data.source !== undefined) {
                    this.source = data.source;
                }
            }
            else {
                this.source = data;
            }
        }
    }

    class SoundsNote {
        duration = 500;
        value = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "duration", data.duration);
            loadProperty(this, "value", data.value);
        }
    }

    class SoundsMelody {
        loop = false;
        melodies = [];
        notes = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "loop", data.loop);
            if (data.melodies !== undefined) {
                this.melodies = data.melodies.map(s => {
                    const tmp = new SoundsMelody();
                    tmp.load(s);
                    return tmp;
                });
            }
            if (data.notes !== undefined) {
                this.notes = data.notes.map(s => {
                    const tmp = new SoundsNote();
                    tmp.load(s);
                    return tmp;
                });
            }
        }
    }

    class SoundsEvent {
        audio;
        event = [];
        filter;
        melodies;
        notes = [];
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "event", data.event);
            if (data.audio !== undefined) {
                if (isArray(data.audio)) {
                    this.audio = data.audio.map(s => {
                        const tmp = new SoundsAudio();
                        tmp.load(s);
                        return tmp;
                    });
                }
                else {
                    this.audio = new SoundsAudio();
                    this.audio.load(data.audio);
                }
            }
            if (data.notes !== undefined) {
                this.notes = data.notes.map(t => {
                    const tmp = new SoundsNote();
                    tmp.load(t);
                    return tmp;
                });
            }
            if (data.melodies !== undefined) {
                this.melodies = data.melodies.map(t => {
                    const tmp = new SoundsMelody();
                    tmp.load(t);
                    return tmp;
                });
            }
            if (data.filter) {
                if (isString(data.filter)) {
                    const filterFunc = globalThis[data.filter];
                    if (isFunction(filterFunc)) {
                        this.filter = filterFunc;
                    }
                }
                else {
                    this.filter = data.filter;
                }
            }
        }
    }

    class SoundsIcon {
        height = 24;
        path;
        style = "";
        svg;
        width = 24;
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "path", data.path);
            loadProperty(this, "svg", data.svg);
            loadProperty(this, "width", data.width);
            loadProperty(this, "height", data.height);
        }
    }

    class SoundsIcons {
        enable;
        mute;
        unmute;
        volumeDown;
        volumeUp;
        constructor() {
            this.mute = new SoundsIcon();
            this.unmute = new SoundsIcon();
            this.volumeDown = new SoundsIcon();
            this.volumeUp = new SoundsIcon();
            this.enable = false;
            this.mute.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M19.707,5.293c-0.391-0.391-1.023-0.391-1.414,0l-1.551,1.551c-0.345-0.688-0.987-1.02-1.604-1.02c-0.449,0-0.905,0.152-1.356,0.453l-2.672,1.781C10.357,8.561,8.904,9,8,9c-1.654,0-3,1.346-3,3v2c0,1.237,0.754,2.302,1.826,2.76l-1.533,1.533c-0.391,0.391-0.391,1.023,0,1.414C5.488,19.902,5.744,20,6,20s0.512-0.098,0.707-0.293l2.527-2.527c0.697,0.174,1.416,0.455,1.875,0.762l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C16.035,20.176,17,19.495,17,18V9.414l2.707-2.707C20.098,6.316,20.098,5.684,19.707,5.293z M14.891,7.941c0.038-0.025,0.073-0.046,0.104-0.062C14.998,7.914,15,7.954,15,8v1.293l-2,2V9.202L14.891,7.941z M7,12c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146v2.439l-2.83,2.83C8.757,15.046,8.356,15,8,15c-0.552,0-1-0.448-1-1V12z M10.301,15.406L12,13.707v2.439C11.519,15.859,10.925,15.604,10.301,15.406z M14.994,18.12c-0.03-0.016-0.065-0.036-0.104-0.062L13,16.798v-4.091l2-2V18C15,18.046,14.998,18.086,14.994,18.12z"/>
    </g>
</svg>`;
            this.unmute.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M17.138,5.824c-0.449,0-0.905,0.152-1.356,0.453l-2.672,1.781C12.357,8.561,10.904,9,10,9c-1.654,0-3,1.346-3,3v2c0,1.654,1.346,3,3,3c0.904,0,2.357,0.439,3.109,0.941l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C18.035,20.176,19,19.495,19,18V8C19,6.505,18.035,5.824,17.138,5.824z M14,16.146C12.907,15.495,11.211,15,10,15c-0.552,0-1-0.448-1-1v-2c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146V16.146z M17,18c0,0.046-0.002,0.086-0.006,0.12c-0.03-0.016-0.065-0.036-0.104-0.062L15,16.798V9.202l1.891-1.261c0.038-0.025,0.073-0.046,0.104-0.062C16.998,7.914,17,7.954,17,8V18z"/>
    </g>
</svg>`;
            this.volumeDown.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M15.138,5.824c-0.449,0-0.905,0.152-1.356,0.453l-2.672,1.781C10.357,8.561,8.904,9,8,9c-1.654,0-3,1.346-3,3v2c0,1.654,1.346,3,3,3c0.904,0,2.357,0.439,3.109,0.941l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C16.035,20.176,17,19.495,17,18V8C17,6.505,16.035,5.824,15.138,5.824z M8,15c-0.552,0-1-0.448-1-1v-2c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146v6.293C10.907,15.495,9.211,15,8,15z M15,18c0,0.046-0.002,0.086-0.006,0.12c-0.03-0.016-0.065-0.036-0.104-0.062L13,16.798V9.202l1.891-1.261c0.038-0.025,0.073-0.046,0.104-0.062C14.998,7.914,15,7.954,15,8V18z"/>
        <path fill="#fff" d="M18.292,10.294c-0.39,0.391-0.39,1.023,0.002,1.414c0.345,0.345,0.535,0.803,0.535,1.291c0,0.489-0.19,0.948-0.536,1.294c-0.391,0.39-0.391,1.023,0,1.414C18.488,15.902,18.744,16,19,16s0.512-0.098,0.707-0.293c0.724-0.723,1.122-1.685,1.122-2.708s-0.398-1.984-1.123-2.707C19.317,9.903,18.683,9.901,18.292,10.294z"/>
    </g>
</svg>`;
            this.volumeUp.svg = `<?xml version="1.0"?>
<svg baseProfile="tiny" height="24px" version="1.2" viewBox="0 0 24 24" width="24px"
    xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="Layer_1">
        <path fill="#fff" d="M16.706,10.292c-0.389-0.389-1.023-0.391-1.414,0.002c-0.39,0.391-0.39,1.023,0.002,1.414c0.345,0.345,0.535,0.803,0.535,1.291c0,0.489-0.19,0.948-0.536,1.294c-0.391,0.39-0.391,1.023,0,1.414C15.488,15.902,15.744,16,16,16s0.512-0.098,0.707-0.293c0.724-0.723,1.122-1.685,1.122-2.708S17.431,11.015,16.706,10.292z"/>
        <path fill="#fff" d="M18.706,8.292c-0.391-0.389-1.023-0.39-1.414,0.002c-0.39,0.391-0.39,1.024,0.002,1.414c0.879,0.877,1.363,2.044,1.364,3.287c0.001,1.246-0.484,2.417-1.365,3.298c-0.391,0.391-0.391,1.023,0,1.414C17.488,17.902,17.744,18,18,18s0.512-0.098,0.707-0.293c1.259-1.259,1.952-2.933,1.951-4.713C20.657,11.217,19.964,9.547,18.706,8.292z"/>
        <path fill="#fff" d="M20.706,6.292c-0.391-0.389-1.023-0.39-1.414,0.002c-0.39,0.391-0.39,1.024,0.002,1.414c1.412,1.409,2.191,3.285,2.192,5.284c0.002,2.002-0.777,3.885-2.193,5.301c-0.391,0.391-0.391,1.023,0,1.414C19.488,19.902,19.744,20,20,20s0.512-0.098,0.707-0.293c1.794-1.794,2.781-4.18,2.779-6.717C23.485,10.457,22.497,8.078,20.706,6.292z"/>
        <path fill="#fff" d="M12.138,5.824c-0.449,0-0.905,0.152-1.356,0.453L8.109,8.059C7.357,8.561,5.904,9,5,9c-1.654,0-3,1.346-3,3v2c0,1.654,1.346,3,3,3c0.904,0,2.357,0.439,3.109,0.941l2.672,1.781c0.451,0.301,0.907,0.453,1.356,0.453C13.035,20.176,14,19.495,14,18V8C14,6.505,13.035,5.824,12.138,5.824z M5,15c-0.552,0-1-0.448-1-1v-2c0-0.552,0.448-1,1-1c1.211,0,2.907-0.495,4-1.146v6.293C7.907,15.495,6.211,15,5,15z M12,18c0,0.046-0.002,0.086-0.006,0.12c-0.03-0.016-0.065-0.036-0.104-0.062L10,16.798V9.202l1.891-1.261c0.038-0.025,0.073-0.046,0.104-0.062C11.998,7.914,12,7.954,12,8V18z"/>
    </g>
</svg>`;
        }
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "enable", data.enable);
            this.mute.load(data.mute);
            this.unmute.load(data.unmute);
            this.volumeDown.load(data.volumeDown);
            this.volumeUp.load(data.volumeUp);
        }
    }

    class SoundsVolume {
        max = 100;
        min = 0;
        step = 10;
        value = 100;
        load(data) {
            if (isNull(data)) {
                return;
            }
            if (isObject(data)) {
                loadProperty(this, "max", data.max);
                loadProperty(this, "min", data.min);
                loadProperty(this, "step", data.step);
                if (data.value !== undefined) {
                    this.value = data.value;
                }
            }
            else {
                this.value = data;
            }
        }
    }

    class Sounds {
        autoPlay = true;
        enable = false;
        events = [];
        icons = new SoundsIcons();
        volume = new SoundsVolume();
        load(data) {
            if (isNull(data)) {
                return;
            }
            loadProperty(this, "autoPlay", data.autoPlay);
            loadProperty(this, "enable", data.enable);
            if (data.events !== undefined) {
                this.events = data.events.map(t => {
                    const event = new SoundsEvent();
                    event.load(t);
                    return event;
                });
            }
            this.icons.load(data.icons);
            if (data.volume !== undefined) {
                this.volume.load(data.volume);
            }
        }
    }

    const notes = new Map();
    notes.set("C", [16.35, 32.7, 65.41, 130.81, 261.63, 523.25, 1046.5, 2093.0, 4186.01]);
    notes.set("Db", [17.32, 34.65, 69.3, 138.59, 277.18, 554.37, 1108.73, 2217.46, 4434.92]);
    notes.set("D", [18.35, 36.71, 73.42, 146.83, 293.66, 587.33, 1174.66, 2349.32, 4698.63]);
    notes.set("Eb", [19.45, 38.89, 77.78, 155.56, 311.13, 622.25, 1244.51, 2489.02, 4978.03]);
    notes.set("E", [20.6, 41.2, 82.41, 164.81, 329.63, 659.25, 1318.51, 2637.02, 5274.04]);
    notes.set("F", [21.83, 43.65, 87.31, 174.61, 349.23, 698.46, 1396.91, 2793.83, 5587.65]);
    notes.set("Gb", [23.12, 46.25, 92.5, 185.0, 369.99, 739.99, 1479.98, 2959.96, 5919.91]);
    notes.set("G", [24.5, 49.0, 98.0, 196.0, 392.0, 783.99, 1567.98, 3135.96, 6271.93]);
    notes.set("Ab", [25.96, 51.91, 103.83, 207.65, 415.3, 830.61, 1661.22, 3322.44, 6644.88]);
    notes.set("A", [27.5, 55.0, 110.0, 220.0, 440.0, 880.0, 1760.0, 3520.0, 7040.0]);
    notes.set("Bb", [29.14, 58.27, 116.54, 233.08, 466.16, 932.33, 1864.66, 3729.31, 7458.62]);
    notes.set("B", [30.87, 61.74, 123.47, 246.94, 493.88, 987.77, 1975.53, 3951.07, 7902.13]);
    notes.set("pause", [0]);
    function getNoteFrequency(note) {
        const regex = /(([A-G]b?)(\d))|pause/i, result = regex.exec(note), groupKey = 2, defaultMatchKey = 0, innerGroupKey = 3;
        if (!result?.length) {
            return;
        }
        const noteKey = result[groupKey] ?? result[defaultMatchKey], noteItem = notes.get(noteKey);
        if (!noteItem) {
            return;
        }
        return noteItem[parseInt(result[innerGroupKey] ?? "0")];
    }
    let muted = true;
    const isWindowMuted = () => {
        return muted;
    };
    const unmuteWindow = () => {
        muted = false;
    };

    const generalFirstClickHandler = () => {
        removeEventListener(mouseDownEvent, generalFirstClickHandler);
        removeEventListener(touchStartEvent, generalFirstClickHandler);
        unmuteWindow();
    };
    class SoundsPlugin {
        id = "sounds";
        #engine;
        constructor(engine) {
            this.#engine = engine;
            const listenerOptions = {
                capture: true,
                once: true,
            };
            addEventListener(mouseDownEvent, generalFirstClickHandler, listenerOptions);
            addEventListener(touchStartEvent, generalFirstClickHandler, listenerOptions);
        }
        async getPlugin(container) {
            const { SoundsPluginInstance } = await Promise.resolve().then(function () { return SoundsPluginInstance$1; });
            return new SoundsPluginInstance(container, this.#engine);
        }
        loadOptions(_container, options, source) {
            if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
                return;
            }
            let soundsOptions = options.sounds;
            if (soundsOptions?.load === undefined) {
                options.sounds = soundsOptions = new Sounds();
            }
            soundsOptions.load(source?.sounds);
        }
        needsPlugin(options) {
            return options?.sounds?.enable ?? false;
        }
    }

    async function loadSoundsPlugin(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(e => {
            e.pluginManager.addPlugin(new SoundsPlugin(e));
        });
    }

    let initPromise = null;
    async function doInitPlugins(engine) {
        engine.checkVersion("4.4.0");
        await engine.pluginManager.register(async (e) => {
            const loadEmittersForFireworks = async (e) => {
                await loadEmittersPluginSimple(e);
                await loadEmittersShapeSquare(e);
            };
            await Promise.all([
                loadBasic(e),
                loadLineShape(e),
                loadBlendPlugin(e),
                loadEmittersForFireworks(e),
                loadSoundsPlugin(e),
                loadRotateUpdater(e),
                loadDestroyUpdater(e),
                loadLifeUpdater(e),
                loadPaintUpdater(e),
            ]);
        });
    }
    async function initPlugins(engine) {
        if (initPromise) {
            return initPromise;
        }
        initPromise = doInitPlugins(engine);
        return initPromise;
    }
    async function fireworks(idOrOptions, sourceOptions) {
        await initPlugins(tsParticles);
        let id, options;
        if (isString(idOrOptions)) {
            id = idOrOptions;
            options = sourceOptions ?? {};
        }
        else {
            id = "fireworks";
            options = idOrOptions ?? {};
        }
        return getFireworksInstance(tsParticles, id, options);
    }
    fireworks.create = async (canvas, options) => {
        await initPlugins(tsParticles);
        const id = canvas?.id ?? "fireworks";
        return getFireworksInstance(tsParticles, id, options ?? {}, canvas ?? undefined);
    };
    fireworks.init = async () => {
        await initPlugins(tsParticles);
    };
    fireworks.version = "4.4.0";
    globalThis.fireworks = fireworks;

    const globalObject = globalThis;
    globalObject.fireworks = fireworks;
    globalObject.tsParticles = tsParticles;

    const fColorIndex = 0, sColorIndex = 1;
    function setTransformValue(factor, newFactor, key) {
        const newValue = newFactor[key];
        if (newValue !== undefined) {
            factor[key] = (factor[key] ?? defaultTransformValue) * newValue;
        }
    }
    class RenderManager {
        #backgroundElement;
        #backgroundWarnings;
        #canvasClearPlugins;
        #canvasManager;
        #colorPlugins;
        #container;
        #context;
        #contextSettings;
        #drawParticlePlugins;
        #drawParticlesCleanupPlugins;
        #drawParticlesSetupPlugins;
        #layers;
        #pluginManager;
        #postDrawUpdaters;
        #preDrawUpdaters;
        #reusableColorStyles = {};
        #reusablePluginColors = [undefined, undefined];
        #reusableTransform = {};
        constructor(pluginManager, container, canvasManager) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#canvasManager = canvasManager;
            this.#context = null;
            this.#backgroundElement = null;
            this.#backgroundWarnings = new Set();
            this.#preDrawUpdaters = [];
            this.#postDrawUpdaters = [];
            this.#canvasClearPlugins = [];
            this.#colorPlugins = [];
            this.#drawParticlePlugins = [];
            this.#drawParticlesCleanupPlugins = [];
            this.#drawParticlesSetupPlugins = [];
            this.#layers = {
                0: [],
                1: [],
                2: [],
                3: [],
                4: [],
                5: [],
                6: [],
                7: [],
            };
        }
        get settings() {
            return this.#contextSettings;
        }
        canvasClear() {
            if (!this.#container.actualOptions.clear) {
                return;
            }
            this.draw(ctx => {
                ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
            });
        }
        clear() {
            for (const plugin of this.#canvasClearPlugins) {
                if (plugin.canvasClear?.() ?? false) {
                    return;
                }
            }
            for (const layer of Object.values(exports.DrawLayer)) {
                if (typeof layer === "number") {
                    for (const plugin of this.#getLayerPlugins(layer)) {
                        if (plugin.canvasClear?.() ?? false) {
                            return;
                        }
                    }
                }
            }
            this.canvasClear();
        }
        destroy() {
            this.stop();
            this.#backgroundElement = null;
            this.#backgroundWarnings.clear();
            this.#preDrawUpdaters = [];
            this.#postDrawUpdaters = [];
            this.#canvasClearPlugins = [];
            this.#colorPlugins = [];
            this.#drawParticlePlugins = [];
            this.#drawParticlesCleanupPlugins = [];
            this.#drawParticlesSetupPlugins = [];
            for (const layer of Object.values(exports.DrawLayer)) {
                if (typeof layer === "number") {
                    this.#layers[layer] = [];
                }
            }
        }
        draw(cb) {
            const ctx = this.#context;
            if (!ctx) {
                return;
            }
            return cb(ctx);
        }
        drawParticle(particle, delta) {
            if (particle.spawning || particle.destroyed) {
                return;
            }
            const radius = particle.getRadius();
            if (radius <= minimumSize) {
                return;
            }
            const pfColor = particle.getFillColor(), psColor = particle.getStrokeColor();
            let [fColor, sColor] = this.#getPluginParticleColors(particle);
            fColor ??= pfColor;
            sColor ??= psColor;
            if (!fColor && !sColor) {
                return;
            }
            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, container.peakNits, container.hdrMode)
                : undefined, stroke = sColor
                ? getStyleFromHsl(sColor, container.hdr, strokeOpacity * opacity, container.peakNits, container.hdrMode)
                : fill;
            transform.a = transform.b = transform.c = transform.d = undefined;
            colorStyles.fill = fill;
            colorStyles.stroke = stroke;
            this.draw((context) => {
                for (const plugin of this.#drawParticlesSetupPlugins) {
                    plugin.drawParticleSetup?.(context, particle, delta);
                }
                this.#applyPreDrawUpdaters(context, particle, radius, opacity, colorStyles, transform);
                this.#drawParticle({
                    container,
                    context,
                    particle,
                    delta,
                    colorStyles,
                    radius: radius * zIndexFactor ** zIndexOptions.sizeRate,
                    opacity: opacity,
                    transform,
                });
                this.#applyPostDrawUpdaters(particle);
                for (const plugin of this.#drawParticlesCleanupPlugins) {
                    plugin.drawParticleCleanup?.(context, particle, delta);
                }
            });
        }
        drawParticlePlugins(particle, delta) {
            this.draw(ctx => {
                for (const plugin of this.#drawParticlePlugins) {
                    this.#drawParticlePlugin(ctx, plugin, particle, delta);
                }
            });
        }
        drawParticles(delta) {
            const { particles, actualOptions } = this.#container;
            this.clear();
            particles.update(delta);
            this.draw(ctx => {
                const width = this.#canvasManager.size.width, height = this.#canvasManager.size.height;
                if (this.#backgroundElement) {
                    try {
                        ctx.drawImage(this.#backgroundElement, originPoint.x, originPoint.y, width, height);
                    }
                    catch {
                        this.#warnOnce("background-element-draw-error", "Error drawing background element onto canvas");
                    }
                }
                const background = actualOptions.background;
                if (background.draw) {
                    try {
                        background.draw(ctx, delta);
                    }
                    catch {
                        this.#warnOnce("background-draw-error", "Error in background.draw callback");
                    }
                }
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
                    plugin.canvasPaint?.();
                }
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasSetup)) {
                    plugin.drawSettingsSetup?.(ctx, delta);
                }
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.PluginContent)) {
                    plugin.draw?.(ctx, delta);
                }
                particles.drawParticles(delta);
                for (const plugin of this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup)) {
                    plugin.clearDraw?.(ctx, delta);
                    plugin.drawSettingsCleanup?.(ctx, delta);
                }
            });
        }
        init() {
            this.initUpdaters();
            this.initPlugins();
            this.#resolveBackgroundElement();
            this.paint();
        }
        initPlugins() {
            this.#canvasClearPlugins = [];
            this.#colorPlugins = [];
            this.#drawParticlePlugins = [];
            this.#drawParticlesSetupPlugins = [];
            this.#drawParticlesCleanupPlugins = [];
            for (const layer of Object.values(exports.DrawLayer)) {
                if (typeof layer === "number") {
                    this.#layers[layer] = [];
                }
            }
            for (const plugin of this.#container.plugins) {
                if (plugin.particleFillColor ?? plugin.particleStrokeColor) {
                    this.#colorPlugins.push(plugin);
                }
                if (plugin.drawParticle) {
                    this.#drawParticlePlugins.push(plugin);
                }
                if (plugin.drawParticleSetup) {
                    this.#drawParticlesSetupPlugins.push(plugin);
                }
                if (plugin.drawParticleCleanup) {
                    this.#drawParticlesCleanupPlugins.push(plugin);
                }
                if (plugin.canvasClear) {
                    this.#canvasClearPlugins.push(plugin);
                }
                if (plugin.canvasPaint) {
                    this.#getLayerPlugins(exports.DrawLayer.BackgroundMask).push(plugin);
                }
                if (plugin.drawSettingsSetup) {
                    this.#getLayerPlugins(exports.DrawLayer.CanvasSetup).push(plugin);
                }
                if (plugin.draw) {
                    this.#getLayerPlugins(exports.DrawLayer.PluginContent).push(plugin);
                }
                if (plugin.clearDraw ?? plugin.drawSettingsCleanup) {
                    this.#getLayerPlugins(exports.DrawLayer.CanvasCleanup).push(plugin);
                }
            }
        }
        initUpdaters() {
            this.#preDrawUpdaters = [];
            this.#postDrawUpdaters = [];
            for (const updater of this.#container.particleUpdaters) {
                if (updater.afterDraw) {
                    this.#postDrawUpdaters.push(updater);
                }
                if (updater.getColorStyles ?? updater.getTransformValues ?? updater.beforeDraw) {
                    this.#preDrawUpdaters.push(updater);
                }
            }
        }
        paint() {
            let handled = false;
            for (const plugin of this.#getLayerPlugins(exports.DrawLayer.BackgroundMask)) {
                handled = plugin.canvasPaint?.() ?? false;
                if (handled) {
                    break;
                }
            }
            if (handled) {
                return;
            }
            this.paintBase();
        }
        paintBase(baseColor) {
            this.draw(ctx => {
                ctx.fillStyle = baseColor ?? "rgba(0,0,0,0)";
                ctx.fillRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
            });
        }
        paintImage(image, opacity) {
            this.draw(ctx => {
                if (!image) {
                    return;
                }
                const prevAlpha = ctx.globalAlpha;
                ctx.globalAlpha = opacity;
                ctx.drawImage(image, originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
                ctx.globalAlpha = prevAlpha;
            });
        }
        setContext(context) {
            this.#context = context;
            if (this.#context) {
                this.#context.globalCompositeOperation = defaultCompositeValue;
            }
        }
        setContextSettings(settings) {
            this.#contextSettings = settings;
        }
        stop() {
            this.draw(ctx => {
                ctx.clearRect(originPoint.x, originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
            });
        }
        #applyPostDrawUpdaters(particle) {
            for (const updater of this.#postDrawUpdaters) {
                updater.afterDraw?.(particle);
            }
        }
        #applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) {
            for (const updater of this.#preDrawUpdaters) {
                if (updater.getColorStyles) {
                    const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity);
                    if (fill) {
                        colorStyles.fill = fill;
                    }
                    if (stroke) {
                        colorStyles.stroke = stroke;
                    }
                }
                if (updater.getTransformValues) {
                    const updaterTransform = updater.getTransformValues(particle);
                    for (const key in updaterTransform) {
                        setTransformValue(transform, updaterTransform, key);
                    }
                }
                updater.beforeDraw?.(particle);
            }
        }
        #drawAfterEffect(drawer, data) {
            if (!drawer?.drawAfter) {
                return;
            }
            const { particle } = data;
            if (!particle.effect) {
                return;
            }
            drawer.drawAfter(data);
        }
        #drawBeforeEffect(drawer, data) {
            if (!drawer?.drawBefore) {
                return;
            }
            const { particle } = data;
            if (!particle.effect) {
                return;
            }
            drawer.drawBefore(data);
        }
        #drawParticle(data) {
            const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = defaultZoom, drawPosition = {
                x: pos.x,
                y: pos.y,
            };
            context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
            if (colorStyles.fill) {
                context.fillStyle = colorStyles.fill;
            }
            const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
            context.lineWidth = strokeWidth;
            if (colorStyles.stroke) {
                context.strokeStyle = colorStyles.stroke;
            }
            const drawData = {
                context,
                particle,
                radius,
                drawRadius: radius * drawScale,
                opacity,
                delta,
                pixelRatio: container.retina.pixelRatio,
                fill: fillEnabled,
                stroke: strokeWidth > minStrokeWidth,
                transformData,
                position: { ...pos },
                drawPosition,
                drawScale,
            };
            for (const plugin of container.plugins) {
                plugin.drawParticleTransform?.(drawData);
            }
            const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
            this.#drawBeforeEffect(effect, drawData);
            this.#drawShapeBeforeDraw(shape, drawData);
            this.#drawShape(shape, drawData);
            this.#drawShapeAfterDraw(shape, drawData);
            this.#drawAfterEffect(effect, drawData);
            context.resetTransform();
        }
        #drawParticlePlugin(context, plugin, particle, delta) {
            if (!plugin.drawParticle) {
                return;
            }
            plugin.drawParticle(context, particle, delta);
        }
        #drawShape(drawer, data) {
            if (!drawer) {
                return;
            }
            const { context, fill, particle, stroke } = data;
            if (!particle.shape) {
                return;
            }
            context.beginPath();
            drawer.draw(data);
            if (particle.shapeClose) {
                context.closePath();
            }
            if (fill) {
                context.fill();
            }
            if (stroke) {
                context.stroke();
            }
        }
        #drawShapeAfterDraw(drawer, data) {
            if (!drawer?.afterDraw) {
                return;
            }
            const { particle } = data;
            if (!particle.shape) {
                return;
            }
            drawer.afterDraw(data);
        }
        #drawShapeBeforeDraw(drawer, data) {
            if (!drawer?.beforeDraw) {
                return;
            }
            const { particle } = data;
            if (!particle.shape) {
                return;
            }
            drawer.beforeDraw(data);
        }
        #getLayerPlugins(layer) {
            return this.#layers[layer];
        }
        #getPluginParticleColors(particle) {
            let fColor, sColor;
            for (const plugin of this.#colorPlugins) {
                if (!fColor && plugin.particleFillColor) {
                    fColor = rangeColorToHsl(this.#pluginManager, plugin.particleFillColor(particle));
                }
                if (!sColor && plugin.particleStrokeColor) {
                    sColor = rangeColorToHsl(this.#pluginManager, plugin.particleStrokeColor(particle));
                }
                if (fColor && sColor) {
                    break;
                }
            }
            this.#reusablePluginColors[fColorIndex] = fColor;
            this.#reusablePluginColors[sColorIndex] = sColor;
            return this.#reusablePluginColors;
        }
        #resolveBackgroundElement() {
            const background = this.#container.actualOptions.background;
            this.#backgroundElement = null;
            if (!background.element) {
                return;
            }
            if (typeof background.element === "string") {
                if (typeof document !== "undefined") {
                    const node = document.querySelector(background.element);
                    if ((typeof HTMLCanvasElement !== "undefined" && node instanceof HTMLCanvasElement) ||
                        (typeof HTMLVideoElement !== "undefined" && node instanceof HTMLVideoElement) ||
                        (typeof HTMLImageElement !== "undefined" && node instanceof HTMLImageElement)) {
                        this.#backgroundElement = node;
                    }
                    else if (node) {
                        this.#warnOnce("background-element-not-supported", `Background element "${background.element}" is not a supported drawable element (canvas, video, or img)`);
                    }
                    else {
                        this.#warnOnce("background-element-not-found", `Background element selector "${background.element}" not found`);
                    }
                }
            }
            else if ((typeof HTMLCanvasElement !== "undefined" && background.element instanceof HTMLCanvasElement) ||
                (typeof OffscreenCanvas !== "undefined" && background.element instanceof OffscreenCanvas) ||
                (typeof HTMLVideoElement !== "undefined" && background.element instanceof HTMLVideoElement) ||
                (typeof HTMLImageElement !== "undefined" && background.element instanceof HTMLImageElement)) {
                this.#backgroundElement = background.element;
            }
        }
        #warnOnce(key, message) {
            if (!this.#backgroundWarnings.has(key)) {
                this.#backgroundWarnings.add(key);
                getLogger().warning(message);
            }
        }
    }

    const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
        const transferredCanvas = transferredCanvases.get(canvas);
        if (transferredCanvas) {
            return transferredCanvas;
        }
        if (typeof canvas.transferControlToOffscreen !== "function") {
            throw new TypeError("OffscreenCanvas is required but not supported by this browser");
        }
        try {
            const offscreenCanvas = canvas.transferControlToOffscreen();
            transferredCanvases.set(canvas, offscreenCanvas);
            return offscreenCanvas;
        }
        catch {
            throw new TypeError("OffscreenCanvas transfer failed");
        }
    }, isHtmlCanvasElement = (canvas) => {
        return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement;
    };
    function setStyle(canvas, style, important = false) {
        if (!style) {
            return;
        }
        const element = canvas, elementStyle = element.style, keys = new Set();
        for (let i = 0; i < elementStyle.length; i++) {
            const key = elementStyle.item(i);
            if (!key) {
                continue;
            }
            keys.add(key);
        }
        for (let i = 0; i < style.length; i++) {
            const key = style.item(i);
            if (!key) {
                continue;
            }
            keys.add(key);
        }
        for (const key of keys) {
            const value = style.getPropertyValue(key);
            if (value) {
                elementStyle.setProperty(key, value, important ? "important" : "");
            }
            else {
                elementStyle.removeProperty(key);
            }
        }
    }
    class CanvasManager {
        domElement;
        render;
        renderCanvas;
        size;
        zoom = defaultZoom;
        #container;
        #generated;
        #hdrMediaListeners;
        #mutationObserver;
        #originalStyle;
        #pluginManager;
        #pointerEvents;
        #resizePlugins;
        #standardSize;
        #zoomCenter;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.render = new RenderManager(pluginManager, container, this);
            this.#standardSize = {
                height: 0,
                width: 0,
            };
            const pxRatio = container.retina.pixelRatio, stdSize = this.#standardSize;
            this.size = {
                height: stdSize.height * pxRatio,
                width: stdSize.width * pxRatio,
            };
            this.#generated = false;
            this.#resizePlugins = [];
            this.#pointerEvents = "none";
        }
        get #fullScreen() {
            return this.#container.actualOptions.fullScreen.enable;
        }
        destroy() {
            this.stop();
            if (this.#generated) {
                const element = this.domElement;
                element?.remove();
                this.domElement = undefined;
                this.renderCanvas = undefined;
            }
            else {
                this.#resetOriginalStyle();
            }
            this.render.destroy();
            this.#resizePlugins = [];
        }
        getZoomCenter() {
            const pxRatio = this.#container.retina.pixelRatio, { width, height } = this.size;
            if (this.#zoomCenter) {
                return this.#zoomCenter;
            }
            return {
                x: (width * half) / pxRatio,
                y: (height * half) / pxRatio,
            };
        }
        init() {
            this.#safeMutationObserver(obs => {
                obs.disconnect();
            });
            this.#mutationObserver = safeMutationObserver(records => {
                for (const record of records) {
                    if (record.type === "attributes" && record.attributeName === "style") {
                        this.#repairStyle();
                    }
                }
            });
            this.resize();
            this.#initStyle();
            this.#safeMutationObserver(obs => {
                const element = this.domElement;
                if (!element || !(element instanceof Node)) {
                    return;
                }
                obs.observe(element, { attributes: true });
            });
            this.initPlugins();
            this.#initContext();
            this.initBackground();
            this.#initHdrListeners();
            this.render.init();
        }
        initBackground() {
            const container = this.#container, options = container.actualOptions, background = options.background, element = this.domElement;
            if (!element) {
                return;
            }
            const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
            if (color) {
                const hdrOptions = container.actualOptions.hdr;
                elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity, hdrOptions.peakNits, hdrOptions.mode);
            }
            else {
                elementStyle.backgroundColor = "";
            }
            elementStyle.backgroundImage = background.image || "";
            elementStyle.backgroundPosition = background.position || "";
            elementStyle.backgroundRepeat = background.repeat || "";
            elementStyle.backgroundSize = background.size || "";
        }
        initPlugins() {
            this.#resizePlugins = [];
            for (const plugin of this.#container.plugins) {
                if (plugin.resize) {
                    this.#resizePlugins.push(plugin);
                }
            }
        }
        loadCanvas(canvas) {
            if (this.#generated && this.domElement) {
                this.domElement.remove();
            }
            const domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
            this.domElement = domCanvas;
            this.#generated = domCanvas ? domCanvas.dataset[generatedAttribute] === "true" : false;
            this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
            const domElement = this.domElement;
            if (domElement) {
                domElement.ariaHidden = "true";
                this.#originalStyle = cloneStyle(domElement.style);
            }
            const standardSize = this.#standardSize, renderCanvas = this.renderCanvas;
            if (domElement) {
                standardSize.height = domElement.offsetHeight;
                standardSize.width = domElement.offsetWidth;
            }
            else {
                standardSize.height = renderCanvas.height;
                standardSize.width = renderCanvas.width;
            }
            const pxRatio = this.#container.retina.pixelRatio, retinaSize = this.size;
            renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
            renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
        }
        resize() {
            const element = this.domElement;
            if (!element) {
                return false;
            }
            const container = this.#container, renderCanvas = this.renderCanvas;
            if (renderCanvas === undefined) {
                return false;
            }
            const currentSize = container.canvas.#standardSize, newSize = {
                width: element.offsetWidth,
                height: element.offsetHeight,
            }, pxRatio = container.retina.pixelRatio, retinaSize = {
                width: newSize.width * pxRatio,
                height: newSize.height * pxRatio,
            };
            if (newSize.height === currentSize.height &&
                newSize.width === currentSize.width &&
                retinaSize.height === renderCanvas.height &&
                retinaSize.width === renderCanvas.width) {
                return false;
            }
            const oldSize = { ...currentSize };
            currentSize.height = newSize.height;
            currentSize.width = newSize.width;
            const canvasSize = this.size;
            renderCanvas.width = canvasSize.width = retinaSize.width;
            renderCanvas.height = canvasSize.height = retinaSize.height;
            if (this.#container.started) {
                container.particles.setResizeFactor({
                    width: currentSize.width / oldSize.width,
                    height: currentSize.height / oldSize.height,
                });
            }
            return true;
        }
        setPointerEvents(type) {
            const element = this.domElement;
            if (!element) {
                return;
            }
            this.#pointerEvents = type;
            this.#repairStyle();
        }
        setZoom(zoomLevel, center) {
            this.zoom = zoomLevel;
            this.#zoomCenter = center;
        }
        stop() {
            this.#safeMutationObserver(obs => {
                obs.disconnect();
            });
            this.#mutationObserver = undefined;
            this.#removeHdrListeners();
            this.render.stop();
        }
        async windowResize() {
            if (!this.domElement || !this.resize()) {
                return;
            }
            const container = this.#container, needsRefresh = container.updateActualOptions();
            container.particles.setDensity();
            this.#applyResizePlugins();
            if (needsRefresh) {
                await container.refresh();
            }
        }
        #applyResizePlugins() {
            for (const plugin of this.#resizePlugins) {
                plugin.resize?.();
            }
        }
        #initContext() {
            const container = this.#container, canSupportHdr = container.actualOptions.hdr.enable &&
                safeMatchMedia("(color-gamut: p3)")?.matches &&
                safeMatchMedia("(dynamic-range: high)")?.matches;
            container.hdr = canSupportHdr ?? false;
            container.hdrMode = container.actualOptions.hdr.mode;
            container.peakNits = container.actualOptions.hdr.peakNits;
            const renderCanvas = this.renderCanvas;
            if (!renderCanvas) {
                return;
            }
            this.render.setContextSettings({
                alpha: true,
                desynchronized: true,
                willReadFrequently: false,
                ...(canSupportHdr
                    ? { colorSpace: "display-p3", colorType: "float16" }
                    : { colorSpace: "srgb" }),
            });
            let context;
            try {
                context = renderCanvas.getContext("2d", this.render.settings);
            }
            catch {
                context = null;
            }
            if (canSupportHdr && !context) {
                container.hdr = false;
                const sdrSettings = {
                    alpha: true,
                    desynchronized: true,
                    willReadFrequently: false,
                    colorSpace: "srgb",
                };
                this.render.setContextSettings(sdrSettings);
                try {
                    context = renderCanvas.getContext("2d", sdrSettings);
                }
                catch {
                    context = null;
                }
            }
            this.render.setContext(context);
        }
        #initHdrListeners() {
            this.#removeHdrListeners();
            const p3Query = safeMatchMedia("(color-gamut: p3)"), hdrQuery = safeMatchMedia("(dynamic-range: high)"), handleChange = () => {
                this.#recreateRenderCanvas();
                this.#initContext();
                this.initBackground();
            }, listeners = [];
            if (p3Query) {
                p3Query.addEventListener("change", handleChange);
                listeners.push({ handler: handleChange, mql: p3Query });
            }
            if (hdrQuery) {
                hdrQuery.addEventListener("change", handleChange);
                listeners.push({ handler: handleChange, mql: hdrQuery });
            }
            this.#hdrMediaListeners = listeners;
        }
        #initStyle() {
            const element = this.domElement, options = this.#container.actualOptions;
            if (!element) {
                return;
            }
            if (this.#fullScreen) {
                this.#setFullScreenStyle();
            }
            else {
                this.#resetOriginalStyle();
            }
            for (const key in options.style) {
                if (!key || !(key in options.style)) {
                    continue;
                }
                const value = options.style[key];
                if (!value) {
                    continue;
                }
                element.style.setProperty(key, value, "important");
            }
        }
        #recreateRenderCanvas() {
            const renderCanvas = this.renderCanvas;
            if (!renderCanvas) {
                return;
            }
            if (this.domElement) {
                return;
            }
            this.renderCanvas = new OffscreenCanvas(renderCanvas.width, renderCanvas.height);
        }
        #removeHdrListeners() {
            if (!this.#hdrMediaListeners) {
                return;
            }
            for (const { handler, mql } of this.#hdrMediaListeners) {
                mql.removeEventListener("change", handler);
            }
            this.#hdrMediaListeners = undefined;
        }
        #repairStyle() {
            const element = this.domElement;
            if (!element) {
                return;
            }
            this.#safeMutationObserver(observer => {
                observer.disconnect();
            });
            this.#initStyle();
            this.initBackground();
            const pointerEvents = this.#pointerEvents;
            element.style.pointerEvents = pointerEvents;
            element.style.setProperty("pointer-events", pointerEvents);
            this.#safeMutationObserver(observer => {
                if (!(element instanceof Node)) {
                    return;
                }
                observer.observe(element, { attributes: true });
            });
        }
        #resetOriginalStyle() {
            const element = this.domElement, originalStyle = this.#originalStyle;
            if (!element || !originalStyle) {
                return;
            }
            setStyle(element, originalStyle, true);
        }
        #safeMutationObserver(callback) {
            if (!this.#mutationObserver) {
                return;
            }
            callback(this.#mutationObserver);
        }
        #setFullScreenStyle() {
            const element = this.domElement;
            if (!element) {
                return;
            }
            setStyle(element, getFullScreenStyle(this.#container.actualOptions.fullScreen.zIndex), true);
        }
    }

    class EventListeners {
        #container;
        #handlers;
        #resizeObserver;
        #resizeTimeout;
        constructor(container) {
            this.#container = container;
            this.#handlers = {
                visibilityChange: () => {
                    this.#handleVisibilityChange();
                },
                resize: () => {
                    this.#handleWindowResize();
                },
            };
        }
        addListeners() {
            this.#manageListeners(true);
        }
        removeListeners() {
            this.#manageListeners(false);
        }
        #handleVisibilityChange() {
            const container = this.#container, options = container.actualOptions;
            if (!options.pauseOnBlur) {
                return;
            }
            if (safeDocument().hidden) {
                container.pageHidden = true;
                container.pause();
            }
            else {
                container.pageHidden = false;
                if (container.animationStatus) {
                    container.play(true);
                }
                else {
                    container.draw(true);
                }
            }
        }
        #handleWindowResize() {
            if (this.#resizeTimeout) {
                clearTimeout(this.#resizeTimeout);
                this.#resizeTimeout = undefined;
            }
            const handleResize = async () => {
                const canvas = this.#container.canvas;
                await canvas.windowResize();
            };
            this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * millisecondsToSeconds);
        }
        #manageListeners(add) {
            const handlers = this.#handlers;
            this.#manageResize(add);
            manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
        }
        #manageResize(add) {
            const handlers = this.#handlers, container = this.#container, options = container.actualOptions;
            if (!options.resize.enable) {
                return;
            }
            if (typeof ResizeObserver === "undefined") {
                manageListener(globalThis, resizeEvent, handlers.resize, add);
                return;
            }
            const canvasEl = container.canvas.domElement;
            if (this.#resizeObserver && !add) {
                if (canvasEl) {
                    this.#resizeObserver.unobserve(canvasEl);
                }
                this.#resizeObserver.disconnect();
                this.#resizeObserver = undefined;
            }
            else if (!this.#resizeObserver && add && canvasEl) {
                this.#resizeObserver = new ResizeObserver((entries) => {
                    const entry = entries.find(e => e.target === canvasEl);
                    if (!entry) {
                        return;
                    }
                    this.#handleWindowResize();
                });
                this.#resizeObserver.observe(canvasEl);
            }
        }
    }

    function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
        const effectData = effectOptions.options[effect];
        return deepExtend({
            close: effectOptions.close,
        }, itemFromSingleOrMultiple(effectData, id, reduceDuplicates));
    }
    function loadShapeData(shape, shapeOptions, id, reduceDuplicates) {
        const shapeData = shapeOptions.options[shape];
        return deepExtend({
            close: shapeOptions.close,
        }, itemFromSingleOrMultiple(shapeData, id, reduceDuplicates));
    }
    function fixOutMode(data) {
        if (!isInArray(data.outMode, data.checkModes)) {
            return;
        }
        const diameter = data.radius * double;
        if (data.coord > data.maxCoord - diameter) {
            data.setCb(-data.radius);
        }
        else if (data.coord < diameter) {
            data.setCb(data.radius);
        }
    }
    function normalizeAngle(angle, modulus) {
        const normalized = angle % modulus;
        return normalized < defaultAngle ? normalized + modulus : normalized;
    }
    function initParticleState(particle, id, group) {
        particle.id = id;
        particle.group = group;
        particle.justWarped = false;
        particle.effectClose = true;
        particle.shapeClose = true;
        particle.pathRotation = false;
        particle.lastPathTime = 0;
        particle.destroyed = false;
        particle.unbreakable = false;
        particle.isRotating = false;
        particle.rotation = 0;
        particle.misplaced = false;
        particle.retina = {
            maxDistance: {},
            maxSpeed: 0,
            moveDrift: 0,
            moveSpeed: 0,
            sizeAnimationSpeed: 0,
        };
        particle.size = {
            value: 1,
            max: 1,
            min: 1,
            enable: false,
        };
        particle.outType = exports.ParticleOutType.normal;
        particle.ignoresResizeRatio = true;
    }
    function resolveParticleOptions(particle, container, pluginManager, overrideOptions) {
        const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates;
        particle.effect = itemFromSingleOrMultiple(particlesOptions.effect.type, particle.id, reduceDuplicates);
        particle.shape = itemFromSingleOrMultiple(particlesOptions.shape.type, particle.id, reduceDuplicates);
        const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
        if (overrideOptions) {
            if (overrideOptions.effect) {
                const overrideEffectType = overrideOptions.effect.type;
                if (overrideEffectType && overrideEffectType !== particle.effect) {
                    const effect = itemFromSingleOrMultiple(overrideEffectType, particle.id, reduceDuplicates);
                    if (effect) {
                        particle.effect = effect;
                    }
                }
                effectOptions.load(overrideOptions.effect);
            }
            if (overrideOptions.shape) {
                const overrideShapeType = overrideOptions.shape.type;
                if (overrideShapeType && overrideShapeType !== particle.shape) {
                    const shape = itemFromSingleOrMultiple(overrideShapeType, particle.id, reduceDuplicates);
                    if (shape) {
                        particle.shape = shape;
                    }
                }
                shapeOptions.load(overrideOptions.shape);
            }
        }
        if (particle.effect === randomColorValue) {
            const availableEffects = [...container.effectDrawers.keys()];
            particle.effect = availableEffects[Math.floor(getRandom() * availableEffects.length)];
        }
        if (particle.shape === randomColorValue) {
            const availableShapes = [...container.shapeDrawers.keys()];
            particle.shape = availableShapes[Math.floor(getRandom() * availableShapes.length)];
        }
        particle.effectData = particle.effect
            ? loadEffectData(particle.effect, effectOptions, particle.id, reduceDuplicates)
            : undefined;
        particle.shapeData = particle.shape
            ? loadShapeData(particle.shape, shapeOptions, particle.id, reduceDuplicates)
            : undefined;
        particlesOptions.load(overrideOptions);
        const effectData = particle.effectData, shapeData = particle.shapeData;
        if (effectData) {
            particlesOptions.load(effectData.particles);
        }
        if (shapeData) {
            particlesOptions.load(shapeData.particles);
        }
        particle.effectClose = effectData?.close ?? particlesOptions.effect.close;
        particle.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
        return particlesOptions;
    }
    function initParticleDrawers(particle, container) {
        let effectDrawer, shapeDrawer;
        if (particle.effect) {
            effectDrawer = container.effectDrawers.get(particle.effect);
        }
        if (effectDrawer?.loadEffect) {
            effectDrawer.loadEffect(particle);
        }
        if (particle.shape) {
            shapeDrawer = container.shapeDrawers.get(particle.shape);
        }
        if (shapeDrawer?.loadShape) {
            shapeDrawer.loadShape(particle);
        }
        const sideCountFunc = shapeDrawer?.getSidesCount;
        if (sideCountFunc) {
            particle.sides = sideCountFunc(particle);
        }
    }
    function runUpdaterPreInit(updaters, particle) {
        for (const updater of updaters) {
            updater.preInit?.(particle);
        }
    }
    function runUpdaterInit(updaters, particle) {
        for (const updater of updaters) {
            updater.init(particle);
        }
    }
    function runDrawerInit(container, particle) {
        const shapeDrawer = particle.shape ? container.shapeDrawers.get(particle.shape) : undefined, effectDrawer = particle.effect ? container.effectDrawers.get(particle.effect) : undefined;
        effectDrawer?.particleInit?.(container, particle);
        shapeDrawer?.particleInit?.(container, particle);
    }
    function runParticleCreatedPlugins(container, particle) {
        for (const plugin of container.particleCreatedPlugins) {
            plugin.particleCreated?.(particle);
        }
    }
    class Particle {
        backColor;
        destroyed;
        direction;
        effect;
        effectClose;
        effectData;
        fillColor;
        fillEnabled;
        fillOpacity;
        group;
        id;
        ignoresResizeRatio;
        initialPosition;
        initialVelocity;
        isRotating;
        justWarped;
        lastPathTime;
        misplaced;
        moveCenter;
        offset;
        opacity;
        options;
        outType;
        pathRotation;
        position;
        randomIndexData;
        retina;
        roll;
        rotation;
        shape;
        shapeClose;
        shapeData;
        sides;
        size;
        spawning;
        strokeColor;
        strokeOpacity;
        strokeWidth;
        unbreakable;
        velocity;
        zIndexFactor;
        #cachedOpacityData = {
            fillOpacity: defaultOpacity$1,
            opacity: defaultOpacity$1,
            strokeOpacity: defaultOpacity$1,
        };
        #cachedPosition = Vector3d.origin;
        #cachedRotateData = { sin: 0, cos: 0 };
        #cachedTransform = {
            a: 1,
            b: 0,
            c: 0,
            d: 1,
        };
        #container;
        #modifiers = [];
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
        }
        addModifier(modifier) {
            this.#modifiers.push(modifier);
            this.#modifiers.sort((a, b) => a.priority - b.priority);
        }
        clearModifiers() {
            this.#modifiers.length = 0;
        }
        destroy(override) {
            if (this.unbreakable || this.destroyed) {
                return;
            }
            this.destroyed = true;
            this.clearModifiers();
            const container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined;
            shapeDrawer?.particleDestroy?.(this);
            for (const plugin of container.particleDestroyedPlugins) {
                plugin.particleDestroyed?.(this, override);
            }
            for (const updater of container.particleUpdaters) {
                updater.particleDestroyed?.(this, override);
            }
            this.#container.dispatchEvent(exports.EventType.particleDestroyed, {
                particle: this,
            });
        }
        draw(delta) {
            const container = this.#container, render = container.canvas.render;
            render.drawParticlePlugins(this, delta);
            render.drawParticle(this, delta);
        }
        getAngle() {
            return this.rotation + (this.pathRotation ? this.velocity.angle : defaultAngle);
        }
        getFillColor() {
            return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.fillColor), m => m.fillColor));
        }
        getMass() {
            return this.getRadius() ** squareExp * Math.PI * half;
        }
        getModifier(id) {
            return this.#modifiers.find(m => m.id === id);
        }
        getOpacity() {
            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;
            this.#cachedOpacityData.fillOpacity = fillOpacity;
            this.#cachedOpacityData.opacity = opacity * zOpacityFactor;
            this.#cachedOpacityData.strokeOpacity = strokeOpacity;
            return this.#cachedOpacityData;
        }
        getPosition() {
            this.#cachedPosition.x = this.position.x + this.offset.x;
            this.#cachedPosition.y = this.position.y + this.offset.y;
            this.#cachedPosition.z = this.position.z;
            return this.#cachedPosition;
        }
        getRadius() {
            return this.#applyModifiers(this.size.value, m => m.radius);
        }
        getRotateData() {
            const angle = this.getAngle();
            this.#cachedRotateData.sin = Math.sin(angle);
            this.#cachedRotateData.cos = Math.cos(angle);
            return this.#cachedRotateData;
        }
        getStrokeColor() {
            return this.#getRollColor(this.#applyModifiers(getHslFromAnimation(this.strokeColor), m => m.strokeColor));
        }
        getTransformData(externalTransform) {
            const rotateData = this.getRotateData(), rotating = this.isRotating;
            this.#cachedTransform.a = rotateData.cos * (externalTransform.a ?? defaultTransform.a);
            this.#cachedTransform.b = rotating
                ? rotateData.sin * (externalTransform.b ?? identity$1)
                : (externalTransform.b ?? defaultTransform.b);
            this.#cachedTransform.c = rotating
                ? -rotateData.sin * (externalTransform.c ?? identity$1)
                : (externalTransform.c ?? defaultTransform.c);
            this.#cachedTransform.d = rotateData.cos * (externalTransform.d ?? defaultTransform.d);
            return this.#cachedTransform;
        }
        init(id, position, overrideOptions, group) {
            const container = this.#container;
            initParticleState(this, id, group);
            this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
            container.retina.initParticle(this);
            runUpdaterPreInit(container.particleUpdaters, this);
            this.#initPosition(position);
            this.initialVelocity = this.#calculateVelocity();
            this.velocity = this.initialVelocity.copy();
            this.zIndexFactor = this.position.z / container.zLayers;
            this.sides = 24;
            initParticleDrawers(this, container);
            this.spawning = false;
            runUpdaterInit(container.particleUpdaters, this);
            runDrawerInit(container, this);
            runParticleCreatedPlugins(container, this);
        }
        isInsideCanvas(direction) {
            return this.#getInsideCanvasResult({ direction }).inside;
        }
        isInsideCanvasForOutMode(outMode, direction) {
            return this.#getInsideCanvasResult({ direction, outMode }).inside;
        }
        isShowingBack() {
            if (!this.roll) {
                return false;
            }
            const angle = this.roll.angle;
            if (this.roll.horizontal && this.roll.vertical) {
                const adjustedAngle = normalizeAngle(angle, doublePI);
                return adjustedAngle >= Math.PI * half && adjustedAngle < Math.PI * triple * half;
            }
            if (this.roll.horizontal) {
                const adjustedAngle = normalizeAngle(angle + Math.PI * half, doublePI);
                return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
            }
            if (this.roll.vertical) {
                const adjustedAngle = normalizeAngle(angle, doublePI);
                return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * double;
            }
            return false;
        }
        isVisible() {
            return !this.destroyed && !this.spawning && this.isInsideCanvas();
        }
        removeModifier(id) {
            const idx = this.#modifiers.findIndex(m => m.id === id);
            if (idx >= defaultAngle) {
                this.#modifiers.splice(idx, identity$1);
            }
        }
        reset() {
            for (const updater of this.#container.particleUpdaters) {
                updater.reset?.(this);
            }
        }
        #applyModifiers(base, getter) {
            let value = base;
            for (const mod of this.#modifiers) {
                if (mod.enabled) {
                    const override = getter(mod);
                    if (override !== undefined) {
                        value = override;
                    }
                }
            }
            return value;
        }
        #calcPosition(position, zIndex) {
            let tryCount = defaultRetryCount, posVec = position ? Vector3d.create(position.x, position.y, zIndex) : undefined;
            const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
            for (;;) {
                for (const plugin of plugins) {
                    const pluginPos = plugin.particlePosition?.(posVec, this);
                    if (pluginPos) {
                        return Vector3d.create(pluginPos.x, pluginPos.y, zIndex);
                    }
                }
                const exactPosition = calcExactPositionOrRandomFromSize({
                    size: canvasSize,
                    position: posVec,
                }), pos = Vector3d.create(exactPosition.x, exactPosition.y, zIndex);
                this.#fixHorizontal(pos, radius, outModes.left ?? outModes.default);
                this.#fixHorizontal(pos, radius, outModes.right ?? outModes.default);
                this.#fixVertical(pos, radius, outModes.top ?? outModes.default);
                this.#fixVertical(pos, radius, outModes.bottom ?? outModes.default);
                let isValidPosition = true;
                for (const plugin of container.particles.checkParticlePositionPlugins) {
                    isValidPosition = plugin.checkParticlePosition?.(this, pos, tryCount) ?? true;
                    if (!isValidPosition) {
                        break;
                    }
                }
                if (isValidPosition) {
                    return pos;
                }
                tryCount += tryCountIncrement;
                posVec = undefined;
            }
        }
        #calculateVelocity() {
            const moveOptions = this.options.move, baseVelocity = getParticleBaseVelocity(this.direction), res = baseVelocity.copy();
            if (moveOptions.direction === exports.MoveDirection.inside || moveOptions.direction === exports.MoveDirection.outside) {
                return res;
            }
            const rad = degToRad(getRangeValue(moveOptions.angle.value)), radOffset = degToRad(getRangeValue(moveOptions.angle.offset)), range = {
                left: radOffset - rad * half,
                right: radOffset + rad * half,
            };
            if (!moveOptions.straight) {
                res.angle += randomInRangeValue(setRangeValue(range.left, range.right));
            }
            if (moveOptions.random && typeof moveOptions.speed === "number") {
                res.length *= getRandom();
            }
            return res;
        }
        #fixHorizontal(pos, radius, outMode) {
            fixOutMode({
                outMode,
                checkModes: [exports.OutMode.bounce],
                coord: pos.x,
                maxCoord: this.#container.canvas.size.width,
                setCb: (value) => (pos.x += value),
                radius,
            });
        }
        #fixVertical(pos, radius, outMode) {
            fixOutMode({
                outMode,
                checkModes: [exports.OutMode.bounce],
                coord: pos.y,
                maxCoord: this.#container.canvas.size.height,
                setCb: (value) => (pos.y += value),
                radius,
            });
        }
        #getDefaultInsideCanvasResult(direction, outMode) {
            const radius = this.getRadius(), canvasSize = this.#container.canvas.size, position = this.position, isBounce = outMode === exports.OutMode.bounce;
            if (direction === exports.OutModeDirection.bottom) {
                return {
                    inside: isBounce ? position.y + radius < canvasSize.height : position.y - radius < canvasSize.height,
                    reason: "default",
                };
            }
            if (direction === exports.OutModeDirection.left) {
                return {
                    inside: isBounce ? position.x - radius > defaultAngle : position.x + radius > defaultAngle,
                    reason: "default",
                };
            }
            if (direction === exports.OutModeDirection.right) {
                return {
                    inside: isBounce ? position.x + radius < canvasSize.width : position.x - radius < canvasSize.width,
                    reason: "default",
                };
            }
            if (direction === exports.OutModeDirection.top) {
                return {
                    inside: isBounce ? position.y - radius > defaultAngle : position.y + radius > defaultAngle,
                    reason: "default",
                };
            }
            return {
                inside: position.x >= -radius &&
                    position.y >= -radius &&
                    position.y <= canvasSize.height + radius &&
                    position.x <= canvasSize.width + radius,
                reason: "default",
            };
        }
        #getInsideCanvasCallbackData(direction, outMode) {
            return {
                canvasSize: this.#container.canvas.size,
                direction,
                outMode,
                particle: this,
                radius: this.getRadius(),
            };
        }
        #getInsideCanvasResult(data) {
            const defaultResult = this.#getDefaultInsideCanvasResult(data.direction, data.outMode), container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined, effectDrawer = this.effect ? container.effectDrawers.get(this.effect) : undefined, shapeCheck = shapeDrawer?.isInsideCanvas, effectCheck = effectDrawer?.isInsideCanvas;
            if (!shapeCheck && !effectCheck) {
                return defaultResult;
            }
            const callbackData = this.#getInsideCanvasCallbackData(data.direction, data.outMode), shapeResult = shapeCheck ? this.#normalizeInsideCanvasResult(shapeCheck(callbackData), "shape") : undefined, effectResult = effectCheck ? this.#normalizeInsideCanvasResult(effectCheck(callbackData), "effect") : undefined;
            if (shapeResult && effectResult) {
                const margin = Math.max(shapeResult.margin ?? defaultAngle, effectResult.margin ?? defaultAngle);
                return {
                    inside: shapeResult.inside && effectResult.inside,
                    margin: margin > defaultAngle ? margin : undefined,
                    reason: "combined",
                };
            }
            return shapeResult ?? effectResult ?? defaultResult;
        }
        #getRollColor(color) {
            if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
                return color;
            }
            if (!this.isShowingBack()) {
                return color;
            }
            if (this.backColor) {
                return this.backColor;
            }
            if (this.roll.alter) {
                return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
            }
            return color;
        }
        #initPosition(position) {
            const container = this.#container, zIndexValue = Math.floor(getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, clamp(zIndexValue, minZ, container.zLayers));
            if (!initialPosition) {
                throw new Error("a valid position cannot be found for particle");
            }
            this.position = initialPosition;
            this.initialPosition = this.position.copy();
            const canvasSize = container.canvas.size;
            this.moveCenter = {
                ...getPosition(this.options.move.center, canvasSize),
                radius: this.options.move.center.radius,
                mode: this.options.move.center.mode,
            };
            this.direction = getParticleDirectionAngle(this.options.move.direction, this.position, this.moveCenter);
            switch (this.options.move.direction) {
                case exports.MoveDirection.inside:
                    this.outType = exports.ParticleOutType.inside;
                    break;
                case exports.MoveDirection.outside:
                    this.outType = exports.ParticleOutType.outside;
                    break;
            }
            this.offset = Vector.origin;
        }
        #normalizeInsideCanvasResult(result, reason) {
            if (typeof result === "boolean") {
                return {
                    inside: result,
                    reason,
                };
            }
            return {
                inside: result.inside,
                margin: result.margin,
                reason: result.reason ?? reason,
            };
        }
    }

    class SpatialHashGrid {
        #cellSize;
        #cells = new Map();
        #circlePool = [];
        #circlePoolIdx;
        #pendingCellSize;
        #rectanglePool = [];
        #rectanglePoolIdx;
        constructor(cellSize) {
            this.#cellSize = cellSize;
            this.#circlePoolIdx = 0;
            this.#rectanglePoolIdx = 0;
        }
        clear() {
            this.#cells.clear();
            const pendingCellSize = this.#pendingCellSize;
            if (pendingCellSize) {
                this.#cellSize = pendingCellSize;
            }
            this.#pendingCellSize = undefined;
        }
        insert(particle) {
            const { x, y } = particle.getPosition(), key = this.#cellKeyFromCoords(x, y);
            if (!this.#cells.has(key)) {
                this.#cells.set(key, []);
            }
            this.#cells.get(key)?.push(particle);
        }
        query(range, check, out = []) {
            const bounds = this.#getRangeBounds(range);
            if (!bounds) {
                return out;
            }
            const minCellX = Math.floor(bounds.minX / this.#cellSize), maxCellX = Math.floor(bounds.maxX / this.#cellSize), minCellY = Math.floor(bounds.minY / this.#cellSize), maxCellY = Math.floor(bounds.maxY / this.#cellSize);
            for (let cx = minCellX; cx <= maxCellX; cx++) {
                for (let cy = minCellY; cy <= maxCellY; cy++) {
                    const key = `${cx}_${cy}`, cellParticles = this.#cells.get(key);
                    if (!cellParticles) {
                        continue;
                    }
                    for (const p of cellParticles) {
                        if (check && !check(p)) {
                            continue;
                        }
                        if (range.contains(p.getPosition())) {
                            out.push(p);
                        }
                    }
                }
            }
            return out;
        }
        queryCircle(position, radius, check, out = []) {
            const circle = this.#acquireCircle(position.x, position.y, radius), result = this.query(circle, check, out);
            this.#releaseShapes();
            return result;
        }
        queryRectangle(position, size, check, out = []) {
            const rect = this.#acquireRectangle(position.x, position.y, size.width, size.height), result = this.query(rect, check, out);
            this.#releaseShapes();
            return result;
        }
        setCellSize(cellSize) {
            this.#pendingCellSize = cellSize;
        }
        #acquireCircle(x, y, r) {
            return (this.#circlePool[this.#circlePoolIdx++] ??= new Circle(x, y, r)).reset(x, y, r);
        }
        #acquireRectangle(x, y, w, h) {
            return (this.#rectanglePool[this.#rectanglePoolIdx++] ??= new Rectangle(x, y, w, h)).reset(x, y, w, h);
        }
        #cellKeyFromCoords(x, y) {
            const cellX = Math.floor(x / this.#cellSize), cellY = Math.floor(y / this.#cellSize);
            return `${cellX}_${cellY}`;
        }
        #getRangeBounds(range) {
            if (range instanceof Circle) {
                const r = range.radius, { x, y } = range.position;
                return {
                    minX: x - r,
                    maxX: x + r,
                    minY: y - r,
                    maxY: y + r,
                };
            }
            if (range instanceof Rectangle) {
                const { x, y } = range.position, { width, height } = range.size;
                return {
                    minX: x,
                    maxX: x + width,
                    minY: y,
                    maxY: y + height,
                };
            }
            return null;
        }
        #releaseShapes() {
            this.#circlePoolIdx = 0;
            this.#rectanglePoolIdx = 0;
        }
    }

    class ParticlesManager {
        checkParticlePositionPlugins;
        grid;
        #array;
        #container;
        #groupLimits;
        #limit;
        #nextId;
        #particleBuckets;
        #particleResetPlugins;
        #particleUpdatePlugins;
        #pluginManager;
        #pool;
        #postParticleUpdatePlugins;
        #postUpdatePlugins;
        #resizeFactor;
        #updatePlugins;
        #zBuckets;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#nextId = 0;
            this.#array = [];
            this.#pool = [];
            this.#limit = 0;
            this.#groupLimits = new Map();
            this.#particleBuckets = new Map();
            this.#zBuckets = this.#createBuckets(this.#container.zLayers);
            this.grid = new SpatialHashGrid(spatialHashGridCellSize);
            this.checkParticlePositionPlugins = [];
            this.#particleResetPlugins = [];
            this.#particleUpdatePlugins = [];
            this.#postUpdatePlugins = [];
            this.#postParticleUpdatePlugins = [];
            this.#updatePlugins = [];
        }
        get count() {
            return this.#array.length;
        }
        addParticle(position, overrideOptions, group, initializer) {
            const limitMode = this.#container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this.#limit : (this.#groupLimits.get(group) ?? this.#limit), currentCount = this.count;
            if (limit > minLimit) {
                switch (limitMode) {
                    case exports.LimitMode.delete: {
                        const countToRemove = currentCount + countOffset - limit;
                        if (countToRemove > minCount) {
                            this.removeQuantity(countToRemove);
                        }
                        break;
                    }
                    case exports.LimitMode.wait:
                        if (currentCount >= limit) {
                            return;
                        }
                        break;
                }
            }
            try {
                const particle = this.#pool.pop() ?? new Particle(this.#pluginManager, this.#container);
                particle.init(this.#nextId, position, overrideOptions, group);
                let canAdd = true;
                if (initializer) {
                    canAdd = initializer(particle);
                }
                if (!canAdd) {
                    this.#pool.push(particle);
                    return;
                }
                this.#array.push(particle);
                this.#insertParticleIntoBucket(particle);
                this.#nextId++;
                this.#container.dispatchEvent(exports.EventType.particleAdded, {
                    particle,
                });
                return particle;
            }
            catch (e) {
                getLogger().warning(`error adding particle: ${e}`);
            }
            return undefined;
        }
        clear() {
            this.#array = [];
            this.#particleBuckets.clear();
            this.#resetBuckets(this.#container.zLayers);
        }
        destroy() {
            this.#array = [];
            this.#pool.length = 0;
            this.#particleBuckets.clear();
            this.#zBuckets = [];
            this.checkParticlePositionPlugins = [];
            this.#particleResetPlugins = [];
            this.#particleUpdatePlugins = [];
            this.#postUpdatePlugins = [];
            this.#postParticleUpdatePlugins = [];
            this.#updatePlugins = [];
        }
        drawParticles(delta) {
            for (let i = this.#zBuckets.length - one; i >= minIndex; i--) {
                const bucket = this.#zBuckets[i];
                if (!bucket) {
                    continue;
                }
                for (const particle of bucket) {
                    particle.draw(delta);
                }
            }
        }
        filter(condition) {
            return this.#array.filter(condition);
        }
        find(condition) {
            return this.#array.find(condition);
        }
        get(index) {
            return this.#array[index];
        }
        async init() {
            const container = this.#container, options = container.actualOptions;
            this.checkParticlePositionPlugins = [];
            this.#updatePlugins = [];
            this.#particleUpdatePlugins = [];
            this.#postUpdatePlugins = [];
            this.#particleResetPlugins = [];
            this.#postParticleUpdatePlugins = [];
            this.#particleBuckets.clear();
            this.#resetBuckets(container.zLayers);
            this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
            for (const plugin of container.plugins) {
                if (plugin.redrawInit) {
                    await plugin.redrawInit();
                }
                if (plugin.checkParticlePosition) {
                    this.checkParticlePositionPlugins.push(plugin);
                }
                if (plugin.update) {
                    this.#updatePlugins.push(plugin);
                }
                if (plugin.particleUpdate) {
                    this.#particleUpdatePlugins.push(plugin);
                }
                if (plugin.postUpdate) {
                    this.#postUpdatePlugins.push(plugin);
                }
                if (plugin.particleReset) {
                    this.#particleResetPlugins.push(plugin);
                }
                if (plugin.postParticleUpdate) {
                    this.#postParticleUpdatePlugins.push(plugin);
                }
            }
            await this.#container.initDrawersAndUpdaters();
            for (const drawer of this.#container.effectDrawers.values()) {
                await drawer.init?.(container);
            }
            for (const drawer of this.#container.shapeDrawers.values()) {
                await drawer.init?.(container);
            }
            let handled = false;
            for (const plugin of container.plugins) {
                handled = plugin.particlesInitialization?.() ?? handled;
                if (handled) {
                    break;
                }
            }
            if (!handled) {
                const particlesOptions = options.particles, groups = particlesOptions.groups;
                for (const group in groups) {
                    const groupOptions = groups[group];
                    if (!groupOptions) {
                        continue;
                    }
                    for (let i = this.count, j = 0; j < groupOptions.number.value && i < particlesOptions.number.value; i++, j++) {
                        this.addParticle(undefined, groupOptions, group);
                    }
                }
                for (let i = this.count; i < particlesOptions.number.value; i++) {
                    this.addParticle();
                }
            }
        }
        push(nb, position, overrideOptions, group) {
            for (let i = 0; i < nb; i++) {
                this.addParticle(position, overrideOptions, group);
            }
        }
        async redraw() {
            this.clear();
            await this.init();
            this.#container.canvas.render.drawParticles({ value: 0, factor: 0 });
        }
        remove(particle, group, override) {
            this.removeAt(this.#array.indexOf(particle), undefined, group, override);
        }
        removeAt(index, quantity = defaultRemoveQuantity, group, override) {
            if (index < minIndex || index > this.count) {
                return;
            }
            let deleted = 0;
            for (let i = index; deleted < quantity && i < this.count; i++) {
                if (this.#removeParticle(i, group, override)) {
                    i--;
                    deleted++;
                }
            }
        }
        removeQuantity(quantity, group) {
            this.removeAt(minIndex, quantity, group);
        }
        setDensity() {
            const options = this.#container.actualOptions, groups = options.particles.groups;
            let pluginsCount = 0;
            for (const plugin of this.#container.plugins) {
                if (plugin.particlesDensityCount) {
                    pluginsCount += plugin.particlesDensityCount();
                }
            }
            for (const group in groups) {
                const groupData = groups[group];
                if (!groupData) {
                    continue;
                }
                const groupDataOptions = loadParticlesOptions(this.#pluginManager, this.#container, groupData);
                this.#applyDensity(groupDataOptions, pluginsCount, group);
            }
            this.#applyDensity(options.particles, pluginsCount);
        }
        setResizeFactor(factor) {
            this.#resizeFactor = factor;
        }
        update(delta) {
            this.grid.clear();
            for (const plugin of this.#updatePlugins) {
                plugin.update?.(delta);
            }
            const particlesToDelete = this.#updateParticlesPhase1(delta);
            for (const plugin of this.#postUpdatePlugins) {
                plugin.postUpdate?.(delta);
            }
            this.#updateParticlesPhase2(delta, particlesToDelete);
            if (particlesToDelete.size) {
                for (const particle of particlesToDelete) {
                    this.remove(particle);
                }
            }
            this.#resizeFactor = undefined;
        }
        #addToPool(...particles) {
            this.#pool.push(...particles);
        }
        #applyDensity(options, pluginsCount, group, groupOptions) {
            const numberOptions = options.number;
            if (!numberOptions.density.enable) {
                if (group === undefined) {
                    this.#limit = numberOptions.limit.value;
                }
                else if (groupOptions?.number.limit.value ?? numberOptions.limit.value) {
                    this.#groupLimits.set(group, groupOptions?.number.limit.value ?? numberOptions.limit.value);
                }
                return;
            }
            const densityFactor = this.#initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + pluginsCount, particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
            if (group === undefined) {
                this.#limit = numberOptions.limit.value * densityFactor;
            }
            else {
                this.#groupLimits.set(group, numberOptions.limit.value * densityFactor);
            }
            if (particlesCount < particlesNumber) {
                this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
            }
            else if (particlesCount > particlesNumber) {
                this.removeQuantity(particlesCount - particlesNumber, group);
            }
        }
        #createBuckets(zLayers) {
            const bucketCount = Math.max(Math.floor(zLayers), one);
            return Array.from({ length: bucketCount }, () => []);
        }
        #getBucketIndex(zIndex) {
            const maxBucketIndex = this.#zBuckets.length - one;
            if (maxBucketIndex <= minIndex) {
                return minIndex;
            }
            return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
        }
        #initDensityFactor(densityOptions) {
            const container = this.#container;
            if (!densityOptions.enable) {
                return defaultDensityFactor;
            }
            const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
            if (!canvasSize.width || !canvasSize.height) {
                return defaultDensityFactor;
            }
            return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
        }
        #insertParticleIntoBucket(particle) {
            const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
            if (!bucket) {
                return;
            }
            bucket.push(particle);
            this.#particleBuckets.set(particle.id, bucketIndex);
        }
        #removeParticle(index, group, override) {
            const particle = this.#array[index];
            if (!particle) {
                return false;
            }
            if (particle.group !== group) {
                return false;
            }
            this.#array.splice(index, deleteCount);
            this.#removeParticleFromBucket(particle);
            particle.destroy(override);
            this.#container.dispatchEvent(exports.EventType.particleRemoved, {
                particle,
            });
            this.#addToPool(particle);
            return true;
        }
        #removeParticleFromBucket(particle) {
            const bucketIndex = this.#particleBuckets.get(particle.id) ?? this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
            if (!bucket) {
                this.#particleBuckets.delete(particle.id);
                return;
            }
            const idx = bucket.findIndex(p => p.id === particle.id);
            if (idx >= minIndex) {
                bucket.splice(idx, deleteCount);
            }
            this.#particleBuckets.delete(particle.id);
        }
        #resetBuckets(zLayers) {
            const bucketCount = Math.max(Math.floor(zLayers), one);
            if (this.#zBuckets.length !== bucketCount) {
                this.#zBuckets = this.#createBuckets(bucketCount);
                return;
            }
            for (const bucket of this.#zBuckets) {
                bucket.length = minIndex;
            }
        }
        #updateParticleBucket(particle) {
            const newBucketIndex = this.#getBucketIndex(particle.position.z), currentBucketIndex = this.#particleBuckets.get(particle.id);
            if (currentBucketIndex === undefined) {
                this.#insertParticleIntoBucket(particle);
                return;
            }
            if (currentBucketIndex === newBucketIndex) {
                return;
            }
            const currentBucket = this.#zBuckets[currentBucketIndex];
            if (currentBucket) {
                const idx = currentBucket.findIndex(p => p.id === particle.id);
                if (idx >= minIndex) {
                    currentBucket.splice(idx, deleteCount);
                }
            }
            const newBucket = this.#zBuckets[newBucketIndex];
            if (!newBucket) {
                this.#particleBuckets.set(particle.id, newBucketIndex);
                return;
            }
            newBucket.push(particle);
            if (newBucket.length >= double) {
                const prev = newBucket[newBucket.length - double];
                if (prev && particle.id < prev.id) {
                    newBucket.sort((a, b) => a.id - b.id);
                }
            }
            this.#particleBuckets.set(particle.id, newBucketIndex);
        }
        #updateParticlesPhase1(delta) {
            const particlesToDelete = new Set(), resizeFactor = this.#resizeFactor;
            for (const particle of this.#array) {
                if (resizeFactor && !particle.ignoresResizeRatio) {
                    particle.position.x *= resizeFactor.width;
                    particle.position.y *= resizeFactor.height;
                    particle.initialPosition.x *= resizeFactor.width;
                    particle.initialPosition.y *= resizeFactor.height;
                }
                particle.ignoresResizeRatio = false;
                for (const plugin of this.#particleResetPlugins) {
                    plugin.particleReset?.(particle);
                }
                for (const plugin of this.#particleUpdatePlugins) {
                    if (particle.destroyed) {
                        break;
                    }
                    plugin.particleUpdate?.(particle, delta);
                }
                if (particle.destroyed) {
                    particlesToDelete.add(particle);
                    continue;
                }
                this.grid.insert(particle);
            }
            return particlesToDelete;
        }
        #updateParticlesPhase2(delta, particlesToDelete) {
            for (const particle of this.#array) {
                if (particle.destroyed) {
                    particlesToDelete.add(particle);
                    continue;
                }
                for (const updater of this.#container.particleUpdaters) {
                    updater.update(particle, delta);
                }
                if (!particle.spawning) {
                    for (const plugin of this.#postParticleUpdatePlugins) {
                        plugin.postParticleUpdate?.(particle, delta);
                    }
                }
                this.#updateParticleBucket(particle);
            }
        }
    }

    class Retina {
        pixelRatio;
        reduceFactor;
        #container;
        constructor(container) {
            this.#container = container;
            this.pixelRatio = defaultRatio;
            this.reduceFactor = defaultReduceFactor;
        }
        init() {
            const container = this.#container, options = container.actualOptions;
            this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
            this.reduceFactor = defaultReduceFactor;
            const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
            if (element) {
                canvas.size.width = element.offsetWidth * ratio;
                canvas.size.height = element.offsetHeight * ratio;
            }
        }
        initParticle(particle) {
            const options = particle.options, ratio = this.pixelRatio, moveOptions = options.move, moveDistance = moveOptions.distance, props = particle.retina;
            props.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
            props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
            props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
            const maxDistance = props.maxDistance;
            maxDistance.horizontal = moveDistance.horizontal === undefined ? undefined : moveDistance.horizontal * ratio;
            maxDistance.vertical = moveDistance.vertical === undefined ? undefined : moveDistance.vertical * ratio;
        }
    }

    function guardCheck(container) {
        return !container.destroyed;
    }
    function updateDelta(delta, value, fpsLimit = defaultFps, smooth = false) {
        delta.value = value;
        delta.factor = smooth ? defaultFps / fpsLimit : (defaultFps * value) / millisecondsToSeconds;
    }
    function loadContainerOptions(pluginManager, container, ...sourceOptionsArr) {
        const options = new Options(pluginManager, container);
        loadOptions(options, ...sourceOptionsArr);
        return options;
    }
    class Container {
        actualOptions;
        canvas;
        destroyed;
        effectDrawers;
        fpsLimit;
        hdr;
        hdrMode;
        id;
        pageHidden;
        particleCreatedPlugins;
        particleDestroyedPlugins;
        particlePositionPlugins;
        particleUpdaters;
        particles;
        peakNits;
        plugins;
        retina;
        shapeDrawers;
        started;
        zLayers;
        #delay;
        #delayTimeout;
        #delta = { value: 0, factor: 0 };
        #dispatchCallback;
        #drawAnimationFrame;
        #duration;
        #eventListeners;
        #firstStart;
        #initialSourceOptions;
        #lastFrameTime;
        #lifeTime;
        #onDestroy;
        #options;
        #paused;
        #pluginManager;
        #smooth;
        #sourceOptions;
        constructor(params) {
            const { dispatchCallback, pluginManager, id, onDestroy, sourceOptions } = params;
            this.#pluginManager = pluginManager;
            this.#dispatchCallback = dispatchCallback;
            this.#onDestroy = onDestroy;
            this.id = Symbol(id);
            this.fpsLimit = 120;
            this.hdr = false;
            this.hdrMode = exports.HdrMode.standard;
            this.peakNits = 400;
            this.#smooth = false;
            this.#delay = 0;
            this.#duration = 0;
            this.#lifeTime = 0;
            this.#firstStart = true;
            this.started = false;
            this.destroyed = false;
            this.#paused = true;
            this.#lastFrameTime = 0;
            this.zLayers = 100;
            this.pageHidden = false;
            this.#sourceOptions = sourceOptions;
            this.#initialSourceOptions = sourceOptions;
            this.effectDrawers = new Map();
            this.shapeDrawers = new Map();
            this.particleUpdaters = [];
            this.retina = new Retina(this);
            this.canvas = new CanvasManager(this.#pluginManager, this);
            this.particles = new ParticlesManager(this.#pluginManager, this);
            this.plugins = [];
            this.particleDestroyedPlugins = [];
            this.particleCreatedPlugins = [];
            this.particlePositionPlugins = [];
            this.#options = loadContainerOptions(this.#pluginManager, this);
            this.actualOptions = loadContainerOptions(this.#pluginManager, this);
            this.#eventListeners = new EventListeners(this);
            this.dispatchEvent(exports.EventType.containerBuilt);
        }
        get animationStatus() {
            return !this.#paused && !this.pageHidden && guardCheck(this);
        }
        get options() {
            return this.#options;
        }
        get sourceOptions() {
            return this.#sourceOptions;
        }
        addLifeTime(value) {
            this.#lifeTime += value;
        }
        alive() {
            return !this.#duration || this.#lifeTime <= this.#duration;
        }
        destroy(remove = true) {
            if (!guardCheck(this)) {
                return;
            }
            this.stop();
            this.particles.destroy();
            this.canvas.destroy();
            for (const [, effectDrawer] of this.effectDrawers) {
                effectDrawer.destroy?.(this);
            }
            for (const [, shapeDrawer] of this.shapeDrawers) {
                shapeDrawer.destroy?.(this);
            }
            for (const plugin of this.plugins) {
                plugin.destroy?.();
            }
            this.effectDrawers = new Map();
            this.shapeDrawers = new Map();
            this.particleUpdaters = [];
            this.plugins.length = 0;
            this.#pluginManager.clearPlugins(this);
            this.destroyed = true;
            this.#onDestroy(remove);
            this.dispatchEvent(exports.EventType.containerDestroyed);
        }
        dispatchEvent(type, data) {
            this.#dispatchCallback(type, {
                container: this,
                data,
            });
        }
        draw(force) {
            if (!guardCheck(this)) {
                return;
            }
            let refreshTime = force;
            this.#drawAnimationFrame = animate((timestamp) => {
                if (refreshTime) {
                    this.#lastFrameTime = undefined;
                    refreshTime = false;
                }
                this.#nextFrame(timestamp);
            });
        }
        async export(type, options = {}) {
            for (const plugin of this.plugins) {
                if (!plugin.export) {
                    continue;
                }
                const res = await plugin.export(type, options);
                if (!res.supported) {
                    continue;
                }
                return res.blob;
            }
            getLogger().error(`Export plugin with type ${type} not found`);
            return undefined;
        }
        async init() {
            if (!guardCheck(this)) {
                return;
            }
            const allContainerPlugins = new Map();
            for (const plugin of this.#pluginManager.plugins) {
                const containerPlugin = await plugin.getPlugin(this);
                if (containerPlugin.preInit) {
                    await containerPlugin.preInit();
                }
                allContainerPlugins.set(plugin, containerPlugin);
            }
            await this.initDrawersAndUpdaters();
            this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
            this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
            this.plugins.length = 0;
            this.particleDestroyedPlugins.length = 0;
            this.particleCreatedPlugins.length = 0;
            this.particlePositionPlugins.length = 0;
            for (const [plugin, containerPlugin] of allContainerPlugins) {
                if (plugin.needsPlugin(this.actualOptions)) {
                    this.plugins.push(containerPlugin);
                    if (containerPlugin.particleCreated) {
                        this.particleCreatedPlugins.push(containerPlugin);
                    }
                    if (containerPlugin.particleDestroyed) {
                        this.particleDestroyedPlugins.push(containerPlugin);
                    }
                    if (containerPlugin.particlePosition) {
                        this.particlePositionPlugins.push(containerPlugin);
                    }
                }
            }
            this.retina.init();
            this.canvas.init();
            this.updateActualOptions();
            this.canvas.initBackground();
            this.canvas.resize();
            const { delay, duration, fpsLimit, smooth, zLayers } = this.actualOptions, hdrOptions = this.actualOptions.hdr;
            this.hdrMode = hdrOptions.mode;
            this.peakNits = hdrOptions.peakNits;
            this.zLayers = zLayers;
            this.#duration = getRangeValue(duration) * millisecondsToSeconds;
            this.#delay = getRangeValue(delay) * millisecondsToSeconds;
            this.#lifeTime = 0;
            this.fpsLimit = fpsLimit > minFpsLimit ? fpsLimit : defaultFpsLimit;
            this.#smooth = smooth;
            for (const plugin of this.plugins) {
                await plugin.init?.();
            }
            await this.particles.init();
            this.dispatchEvent(exports.EventType.containerInit);
            this.particles.setDensity();
            for (const plugin of this.plugins) {
                plugin.particlesSetup?.();
            }
            this.dispatchEvent(exports.EventType.particlesSetup);
        }
        async initDrawersAndUpdaters() {
            const pluginManager = this.#pluginManager;
            this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
            this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
            this.particleUpdaters = await pluginManager.getUpdaters(this, true);
        }
        pause() {
            if (!guardCheck(this)) {
                return;
            }
            if (this.#drawAnimationFrame !== undefined) {
                cancelAnimation(this.#drawAnimationFrame);
                this.#drawAnimationFrame = undefined;
            }
            if (this.#paused) {
                return;
            }
            for (const plugin of this.plugins) {
                plugin.pause?.();
            }
            if (!this.pageHidden) {
                this.#paused = true;
            }
            this.dispatchEvent(exports.EventType.containerPaused);
        }
        play(force) {
            if (!guardCheck(this)) {
                return;
            }
            const needsUpdate = this.#paused || force;
            if (this.#firstStart && !this.actualOptions.autoPlay) {
                this.#firstStart = false;
                return;
            }
            if (this.#paused) {
                this.#paused = false;
            }
            if (needsUpdate) {
                for (const plugin of this.plugins) {
                    if (plugin.play) {
                        plugin.play();
                    }
                }
            }
            this.dispatchEvent(exports.EventType.containerPlay);
            this.draw(needsUpdate ?? false);
        }
        async refresh() {
            if (!guardCheck(this)) {
                return;
            }
            this.stop();
            return this.start();
        }
        async reset(sourceOptions) {
            if (!guardCheck(this)) {
                return;
            }
            this.#initialSourceOptions = sourceOptions;
            this.#sourceOptions = sourceOptions;
            this.#options = loadContainerOptions(this.#pluginManager, this, this.#initialSourceOptions, this.sourceOptions);
            this.actualOptions = loadContainerOptions(this.#pluginManager, this, this.#options);
            return this.refresh();
        }
        async start() {
            if (!guardCheck(this) || this.started) {
                return;
            }
            await this.init();
            this.started = true;
            await new Promise(resolve => {
                const start = async () => {
                    this.#eventListeners.addListeners();
                    for (const plugin of this.plugins) {
                        await plugin.start?.();
                    }
                    this.dispatchEvent(exports.EventType.containerStarted);
                    this.play();
                    resolve();
                };
                this.#delayTimeout = setTimeout(() => void start(), this.#delay);
            });
        }
        stop() {
            if (!guardCheck(this) || !this.started) {
                return;
            }
            if (this.#delayTimeout) {
                clearTimeout(this.#delayTimeout);
                this.#delayTimeout = undefined;
            }
            this.#firstStart = true;
            this.started = false;
            this.#eventListeners.removeListeners();
            this.pause();
            this.particles.clear();
            this.canvas.stop();
            for (const plugin of this.plugins) {
                plugin.stop?.();
            }
            this.particleCreatedPlugins.length = 0;
            this.particleDestroyedPlugins.length = 0;
            this.particlePositionPlugins.length = 0;
            this.#sourceOptions = this.#options;
            this.dispatchEvent(exports.EventType.containerStopped);
        }
        updateActualOptions() {
            let refresh = false;
            for (const plugin of this.plugins) {
                if (plugin.updateActualOptions) {
                    refresh = plugin.updateActualOptions() || refresh;
                }
            }
            return refresh;
        }
        #nextFrame(timestamp) {
            try {
                if (!this.#smooth &&
                    this.#lastFrameTime !== undefined &&
                    timestamp < this.#lastFrameTime + millisecondsToSeconds / this.fpsLimit) {
                    this.draw(false);
                    return;
                }
                this.#lastFrameTime ??= timestamp;
                updateDelta(this.#delta, timestamp - this.#lastFrameTime, this.fpsLimit, this.#smooth);
                this.addLifeTime(this.#delta.value);
                this.#lastFrameTime = timestamp;
                if (this.#delta.value > millisecondsToSeconds) {
                    this.draw(false);
                    return;
                }
                this.canvas.render.drawParticles(this.#delta);
                if (!this.alive()) {
                    this.destroy();
                    return;
                }
                if (this.animationStatus) {
                    this.draw(false);
                }
            }
            catch (e) {
                getLogger().error("error in animation loop", e);
            }
        }
    }

    var Container$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        Container: Container
    });

    class FireworksInstance {
        #container;
        #id;
        constructor(container, id) {
            this.#container = container;
            this.#id = id;
        }
        get destroyed() {
            return this.#container.destroyed;
        }
        destroy() {
            this.#container.destroy();
            deleteFireworksInstance(this.#id);
        }
        pause() {
            this.#container.pause();
        }
        play() {
            this.#container.play();
        }
        stop() {
            this.#container.stop();
        }
    }

    var FireworksInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        FireworksInstance: FireworksInstance
    });

    class BlendPluginInstance {
        layer = exports.DrawLayer.CanvasSetup;
        #container;
        #defaultCompositeValue;
        constructor(container) {
            this.#container = container;
        }
        drawParticleCleanup(context, particle) {
            if (!particle.options.blend?.enable) {
                return;
            }
            context.globalCompositeOperation = particle.originalBlendMode ?? defaultCompositeValue;
            particle.originalBlendMode = undefined;
        }
        drawParticleSetup(context, particle) {
            if (!particle.options.blend?.enable) {
                return;
            }
            particle.originalBlendMode = context.globalCompositeOperation;
            context.globalCompositeOperation = particle.options.blend.mode;
        }
        drawSettingsCleanup(context) {
            if (!this.#defaultCompositeValue) {
                return;
            }
            context.globalCompositeOperation = this.#defaultCompositeValue;
        }
        drawSettingsSetup(context) {
            const previousComposite = context.globalCompositeOperation, blend = this.#container.actualOptions.blend;
            this.#defaultCompositeValue = previousComposite;
            context.globalCompositeOperation = blend?.enable ? blend.mode : previousComposite;
        }
    }

    var BlendPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        BlendPluginInstance: BlendPluginInstance
    });

    const moveSpeedFactor = 60, minSpinRadius = 0, spinFactor = 0.01, defaultPathDelay = 0, noDecay = 1;
    function applyDistance(particle) {
        const initialPosition = particle.initialPosition, { dx, dy } = getDistances(initialPosition, particle.position), dxFixed = Math.abs(dx), dyFixed = Math.abs(dy), { maxDistance } = particle.retina, hDistance = maxDistance.horizontal, vDistance = maxDistance.vertical;
        if (!hDistance && !vDistance) {
            return;
        }
        const hasHDistance = (hDistance && dxFixed >= hDistance) ?? false, hasVDistance = (vDistance && dyFixed >= vDistance) ?? false;
        if ((hasHDistance || hasVDistance) && !particle.misplaced) {
            particle.misplaced = (!!hDistance && dxFixed > hDistance) || (!!vDistance && dyFixed > vDistance);
            if (hDistance) {
                particle.velocity.x = particle.velocity.y * half - particle.velocity.x;
            }
            if (vDistance) {
                particle.velocity.y = particle.velocity.x * half - particle.velocity.y;
            }
        }
        else if ((!hDistance || dxFixed < hDistance) && (!vDistance || dyFixed < vDistance) && particle.misplaced) {
            particle.misplaced = false;
        }
        else if (particle.misplaced) {
            const pos = particle.position, vel = particle.velocity;
            if (hDistance &&
                ((pos.x < initialPosition.x && vel.x < minVelocity) || (pos.x > initialPosition.x && vel.x > minVelocity))) {
                vel.x *= -getRandom();
            }
            if (vDistance &&
                ((pos.y < initialPosition.y && vel.y < minVelocity) || (pos.y > initialPosition.y && vel.y > minVelocity))) {
                vel.y *= -getRandom();
            }
        }
    }
    function move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, reduceFactor, delta) {
        applyPath(particle, delta);
        const gravityOptions = particle.gravity, gravityFactor = gravityOptions?.enable && gravityOptions.inverse ? -identity$1 : identity$1;
        if (moveDrift && moveSpeed) {
            particle.velocity.x += (moveDrift * delta.factor) / (moveSpeedFactor * moveSpeed);
        }
        if (gravityOptions?.enable && moveSpeed) {
            particle.velocity.y +=
                (gravityFactor * (gravityOptions.acceleration * delta.factor)) / (moveSpeedFactor * moveSpeed);
        }
        const decay = particle.moveDecay;
        particle.velocity.multTo(decay ?? noDecay);
        const velocity = particle.velocity.mult(moveSpeed);
        if (gravityOptions?.enable &&
            maxSpeed > minVelocity &&
            ((!gravityOptions.inverse && velocity.y >= minVelocity && velocity.y >= maxSpeed) ||
                (gravityOptions.inverse && velocity.y <= minVelocity && velocity.y <= -maxSpeed))) {
            velocity.y = gravityFactor * maxSpeed;
            if (moveSpeed) {
                particle.velocity.y = velocity.y / moveSpeed;
            }
        }
        const zIndexOptions = particle.options.zIndex, zVelocityFactor = (identity$1 - particle.zIndexFactor) ** zIndexOptions.velocityRate;
        velocity.multTo(zVelocityFactor);
        velocity.multTo(reduceFactor);
        const { position } = particle;
        position.addTo(velocity);
        if (moveOptions.vibrate) {
            position.x += Math.sin(position.x * Math.cos(position.y)) * reduceFactor;
            position.y += Math.cos(position.y * Math.sin(position.x)) * reduceFactor;
        }
    }
    function spin(container, particle, moveSpeed, reduceFactor) {
        if (!particle.spin) {
            return;
        }
        const spinClockwise = particle.spin.direction === exports.RotateDirection.clockwise, updateFunc = {
            x: spinClockwise ? Math.cos : Math.sin,
            y: spinClockwise ? Math.sin : Math.cos,
        };
        particle.position.x =
            particle.spin.center.x + particle.spin.radius * updateFunc.x(particle.spin.angle) * reduceFactor;
        particle.position.y =
            particle.spin.center.y + particle.spin.radius * updateFunc.y(particle.spin.angle) * reduceFactor;
        particle.spin.radius += particle.spin.acceleration * reduceFactor;
        const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height), halfMaxSize = maxCanvasSize * half;
        if (particle.spin.radius > halfMaxSize) {
            particle.spin.radius = halfMaxSize;
            particle.spin.acceleration *= -identity$1;
        }
        else if (particle.spin.radius < minSpinRadius) {
            particle.spin.radius = minSpinRadius;
            particle.spin.acceleration *= -identity$1;
        }
        particle.spin.angle += moveSpeed * spinFactor * (identity$1 - particle.spin.radius / maxCanvasSize);
    }
    function applyPath(particle, delta) {
        const particlesOptions = particle.options, pathOptions = particlesOptions.move.path, pathEnabled = pathOptions.enable;
        if (!pathEnabled) {
            return;
        }
        const pathDelay = particle.pathDelay ?? defaultPathDelay;
        if (particle.lastPathTime <= pathDelay) {
            particle.lastPathTime += delta.value;
            return;
        }
        const path = particle.pathGenerator?.generate(particle, delta);
        if (path) {
            particle.velocity.addTo(path);
        }
        if (pathOptions.clamp) {
            particle.velocity.x = clamp(particle.velocity.x, -identity$1, identity$1);
            particle.velocity.y = clamp(particle.velocity.y, -identity$1, identity$1);
        }
        particle.lastPathTime -= pathDelay;
    }
    function getProximitySpeedFactor(particle) {
        const mod = particle.getModifier("slow");
        return mod?.enabled ? (mod.speedFactor ?? identity$1) : identity$1;
    }
    function initSpin(container, particle) {
        const options = particle.options, spinOptions = options.move.spin;
        if (!spinOptions.enable) {
            return;
        }
        const spinPos = spinOptions.position ?? { x: 50, y: 50 }, spinFactor = 0.01, spinCenter = {
            x: spinPos.x * spinFactor * container.canvas.size.width,
            y: spinPos.y * spinFactor * container.canvas.size.height,
        }, pos = particle.getPosition(), distance = getDistance(pos, spinCenter), spinAcceleration = getRangeValue(spinOptions.acceleration);
        particle.retina.spinAcceleration = spinAcceleration * container.retina.pixelRatio;
        particle.spin = {
            center: spinCenter,
            direction: particle.velocity.x >= minVelocity ? exports.RotateDirection.clockwise : exports.RotateDirection.counterClockwise,
            angle: getRandom() * doublePI,
            radius: distance,
            acceleration: particle.retina.spinAcceleration,
        };
    }

    const defaultSizeFactor = 1, defaultDeltaFactor = 1;
    class MovePluginInstance {
        availablePathGenerators;
        pathGenerators;
        #container;
        #pluginManager;
        constructor(pluginManager, container) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.availablePathGenerators = new Map();
            this.pathGenerators = new Map();
        }
        destroy() {
            this.availablePathGenerators = new Map();
            this.pathGenerators = new Map();
        }
        isEnabled(particle) {
            return !particle.destroyed && particle.options.move.enable;
        }
        particleCreated(particle) {
            const options = particle.options, moveOptions = options.move, gravityOptions = moveOptions.gravity, pathOptions = moveOptions.path;
            particle.moveDecay = decayOffset - getRangeValue(moveOptions.decay);
            particle.pathDelay = getRangeValue(pathOptions.delay.value) * millisecondsToSeconds;
            if (pathOptions.generator) {
                let pathGenerator = this.pathGenerators.get(pathOptions.generator);
                if (!pathGenerator) {
                    pathGenerator = this.availablePathGenerators.get(pathOptions.generator);
                    if (pathGenerator) {
                        this.pathGenerators.set(pathOptions.generator, pathGenerator);
                        pathGenerator.init();
                    }
                }
                particle.pathGenerator = pathGenerator;
            }
            particle.gravity = {
                enable: gravityOptions.enable,
                acceleration: getRangeValue(gravityOptions.acceleration),
                inverse: gravityOptions.inverse,
            };
            initSpin(this.#container, particle);
        }
        particleDestroyed(particle) {
            const pathGenerator = particle.pathGenerator;
            pathGenerator?.reset(particle);
        }
        particleUpdate(particle, delta) {
            const particleOptions = particle.options, moveOptions = particleOptions.move;
            if (!moveOptions.enable) {
                return;
            }
            const container = this.#container, slowFactor = getProximitySpeedFactor(particle), reduceFactor = container.retina.reduceFactor, baseSpeed = particle.retina.moveSpeed, moveDrift = particle.retina.moveDrift, maxSize = particle.size.max, sizeFactor = moveOptions.size ? particle.getRadius() / maxSize : defaultSizeFactor, deltaFactor = delta.factor || defaultDeltaFactor, moveSpeed = baseSpeed * sizeFactor * slowFactor * deltaFactor * half, maxSpeed = particle.retina.maxSpeed;
            if (moveOptions.spin.enable) {
                spin(container, particle, moveSpeed, reduceFactor);
            }
            else {
                move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, reduceFactor, delta);
            }
            applyDistance(particle);
        }
        preInit() {
            return this.#init();
        }
        redrawInit() {
            return this.#init();
        }
        update() {
            for (const pathGenerator of this.pathGenerators.values()) {
                pathGenerator.update();
            }
        }
        async #init() {
            const availablePathGenerators = await this.#pluginManager.getPathGenerators?.(this.#container, true);
            if (!availablePathGenerators) {
                return;
            }
            this.availablePathGenerators = availablePathGenerators;
            this.pathGenerators = new Map();
            for (const pathGenerator of this.pathGenerators.values()) {
                pathGenerator.init();
            }
        }
    }

    var MovePluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        MovePluginInstance: MovePluginInstance
    });

    class EmittersPluginInstance {
        #container;
        #instancesManager;
        constructor(instancesManager, container) {
            this.#instancesManager = instancesManager;
            this.#container = container;
            this.#instancesManager.initContainer(container);
        }
        async init() {
            const emittersOptions = this.#container.actualOptions.emitters;
            if (isArray(emittersOptions)) {
                for (const emitterOptions of emittersOptions) {
                    await this.#instancesManager.addEmitter(this.#container, emitterOptions);
                }
            }
            else {
                await this.#instancesManager.addEmitter(this.#container, emittersOptions);
            }
        }
        pause() {
            for (const emitter of this.#instancesManager.getArray(this.#container)) {
                emitter.pause();
            }
        }
        play() {
            for (const emitter of this.#instancesManager.getArray(this.#container)) {
                emitter.play();
            }
        }
        resize() {
            for (const emitter of this.#instancesManager.getArray(this.#container)) {
                emitter.resize();
            }
        }
        stop() {
            this.#instancesManager.clear(this.#container);
        }
        update(delta) {
            this.#instancesManager.getArray(this.#container).forEach(emitter => {
                emitter.update(delta);
            });
        }
    }

    var EmittersPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        EmittersPluginInstance: EmittersPluginInstance
    });

    const shapeGenerators = new Map();
    class ShapeManager {
        addShapeGenerator(name, generator) {
            if (!this.getShapeGenerator(name)) {
                shapeGenerators.set(name, generator);
            }
        }
        getShapeGenerator(name) {
            return shapeGenerators.get(name);
        }
        getSupportedShapeGenerators() {
            return shapeGenerators.keys();
        }
    }

    var ShapeManager$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ShapeManager: ShapeManager
    });

    const defaultIndex = 0;
    class EmittersInstancesManager {
        #containerArrays;
        #pluginManager;
        constructor(pluginManager) {
            this.#containerArrays = new Map();
            this.#pluginManager = pluginManager;
        }
        async addEmitter(container, options, position) {
            const emitterOptions = new Emitter();
            emitterOptions.load(options);
            const { EmitterInstance } = await Promise.resolve().then(function () { return EmitterInstance$1; }), emitter = new EmitterInstance(this.#pluginManager, container, (emitter) => {
                this.removeEmitter(container, emitter);
            }, emitterOptions, position);
            await emitter.init();
            this.getArray(container).push(emitter);
            return emitter;
        }
        clear(container) {
            this.initContainer(container);
            this.#containerArrays.set(container, []);
        }
        getArray(container) {
            this.initContainer(container);
            let array = this.#containerArrays.get(container);
            if (!array) {
                array = [];
                this.#containerArrays.set(container, array);
            }
            return array;
        }
        initContainer(container) {
            if (this.#containerArrays.has(container)) {
                return;
            }
            this.#containerArrays.set(container, []);
            container.getEmitter = (idxOrName) => {
                const array = this.getArray(container);
                return idxOrName === undefined || isNumber(idxOrName)
                    ? array[idxOrName ?? defaultIndex]
                    : array.find(t => t.name === idxOrName);
            };
            container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
            container.removeEmitter = (idxOrName) => {
                const emitter = container.getEmitter?.(idxOrName);
                if (emitter) {
                    this.removeEmitter(container, emitter);
                }
            };
            container.playEmitter = (idxOrName) => {
                const emitter = container.getEmitter?.(idxOrName);
                if (emitter) {
                    emitter.externalPlay();
                }
            };
            container.pauseEmitter = (idxOrName) => {
                const emitter = container.getEmitter?.(idxOrName);
                if (emitter) {
                    emitter.externalPause();
                }
            };
        }
        removeEmitter(container, emitter) {
            const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
            if (index >= minIndex) {
                this.getArray(container).splice(index, deleteCount);
            }
        }
    }

    var EmittersInstancesManager$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        EmittersInstancesManager: EmittersInstancesManager
    });

    var SoundsEventType;
    (function (SoundsEventType) {
        SoundsEventType["mute"] = "soundsMuted";
        SoundsEventType["unmute"] = "soundsUnmuted";
    })(SoundsEventType || (SoundsEventType = {}));
    var ImageDisplay;
    (function (ImageDisplay) {
        ImageDisplay["Block"] = "block";
        ImageDisplay["None"] = "none";
    })(ImageDisplay || (ImageDisplay = {}));

    const zIndexOffset = 1, rightOffset = 1, minVolume = 0;
    function initImage(data) {
        const img = safeDocument().createElement("img"), { clickCb, container, display, iconOptions, margin, options, pos, rightOffsets } = data, { width, path, style, svg } = iconOptions, defaultAccumulator = 0;
        setIconStyle(img, pos.top + margin, pos.right -
            (margin * (rightOffsets.length + rightOffset) + width + rightOffsets.reduce((a, b) => a + b, defaultAccumulator)), display, options.fullScreen.zIndex + zIndexOffset, width, margin, style);
        img.src = path ?? (svg ? `data:image/svg+xml;base64,${btoa(svg)}` : "");
        const parent = container.canvas.domElement?.parentNode ?? safeDocument().body;
        parent.append(img);
        img.addEventListener("click", () => {
            void clickCb();
        });
        return img;
    }
    function removeImage(image) {
        if (!image) {
            return;
        }
        image.remove();
    }
    function setIconStyle(icon, top, left, display, zIndex, width, margin, style) {
        icon.style.userSelect = "none";
        icon.style.position = "absolute";
        icon.style.top = `${(top + margin).toString()}px`;
        icon.style.left = `${(left - margin - width).toString()}px`;
        icon.style.display = display;
        icon.style.zIndex = (zIndex + zIndexOffset).toString();
        icon.style.cssText += style;
    }
    class SoundsPluginInstance {
        #audioMap;
        #audioSources;
        #container;
        #engine;
        #gain;
        #muteImg;
        #unmuteImg;
        #volume;
        #volumeDownImg;
        #volumeUpImg;
        constructor(container, engine) {
            this.#container = container;
            this.#engine = engine;
            this.#volume = 0;
            this.#audioSources = [];
            this.#audioMap = new Map();
        }
        async init() {
            const container = this.#container, options = container.actualOptions, soundsOptions = options.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            if (soundsOptions.autoPlay && isWindowMuted()) {
                const firstClickHandler = () => {
                    removeEventListener(mouseDownEvent, firstClickHandler);
                    removeEventListener(touchStartEvent, firstClickHandler);
                    unmuteWindow();
                    void this.unmute();
                }, listenerOptions = {
                    capture: true,
                    once: true,
                };
                addEventListener(mouseDownEvent, firstClickHandler, listenerOptions);
                addEventListener(touchStartEvent, firstClickHandler, listenerOptions);
            }
            this.#volume = soundsOptions.volume.value;
            const events = soundsOptions.events;
            this.#audioMap = new Map();
            for (const event of events) {
                if (!event.audio) {
                    continue;
                }
                const promises = executeOnSingleOrMultiple(event.audio, async (audio) => {
                    const response = await fetch(audio.source);
                    if (!response.ok) {
                        return;
                    }
                    const arrayBuffer = await response.arrayBuffer(), audioContext = this.#getAudioContext(), audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
                    this.#audioMap.set(audio.source, audioBuffer);
                });
                if (promises instanceof Promise) {
                    await promises;
                }
                else {
                    await Promise.allSettled(promises);
                }
            }
        }
        async mute() {
            if (!this.#container.muted) {
                await this.toggleMute();
            }
        }
        async start() {
            const container = this.#container, options = container.actualOptions, soundsOptions = options.sounds;
            if (!soundsOptions?.enable || !container.canvas.domElement) {
                return;
            }
            container.muted = true;
            const canvas = container.canvas.domElement, pos = {
                top: canvas.offsetTop,
                right: canvas.offsetLeft + canvas.offsetWidth,
            }, { mute, unmute, volumeDown, volumeUp } = soundsOptions.icons, margin = 10, toggleMute = async () => {
                await this.toggleMute();
            }, enableIcons = soundsOptions.icons.enable, display = enableIcons ? ImageDisplay.Block : ImageDisplay.None;
            this.#muteImg = initImage({
                container,
                options,
                pos,
                display,
                iconOptions: mute,
                margin,
                rightOffsets: [volumeDown.width, volumeUp.width],
                clickCb: toggleMute,
            });
            this.#unmuteImg = initImage({
                container,
                options,
                pos,
                display: ImageDisplay.None,
                iconOptions: unmute,
                margin,
                rightOffsets: [volumeDown.width, volumeUp.width],
                clickCb: toggleMute,
            });
            this.#volumeDownImg = initImage({
                container,
                options,
                pos,
                display,
                iconOptions: volumeDown,
                margin,
                rightOffsets: [volumeUp.width],
                clickCb: async () => {
                    await this.volumeDown();
                },
            });
            this.#volumeUpImg = initImage({
                container,
                options,
                pos,
                display,
                iconOptions: volumeUp,
                margin,
                rightOffsets: [],
                clickCb: async () => {
                    await this.volumeUp();
                },
            });
            if (!isWindowMuted() && soundsOptions.autoPlay) {
                await this.unmute();
            }
        }
        stop() {
            this.#container.muted = true;
            void (async () => {
                await this.#mute();
                removeImage(this.#muteImg);
                removeImage(this.#unmuteImg);
                removeImage(this.#volumeDownImg);
                removeImage(this.#volumeUpImg);
            })();
        }
        async toggleMute() {
            const container = this.#container;
            container.muted = !container.muted;
            this.#updateMuteIcons();
            await this.#updateMuteStatus();
        }
        async unmute() {
            if (this.#container.muted) {
                await this.toggleMute();
            }
        }
        async volumeDown() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            if (container.muted) {
                this.#volume = 0;
            }
            this.#volume -= soundsOptions.volume.step;
            await this.#updateVolume();
        }
        async volumeUp() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            this.#volume += soundsOptions.volume.step;
            await this.#updateVolume();
        }
        #addBuffer(audioCtx) {
            const buffer = audioCtx.createBufferSource();
            this.#audioSources.push(buffer);
            return buffer;
        }
        #addOscillator(audioCtx) {
            const oscillator = audioCtx.createOscillator();
            this.#audioSources.push(oscillator);
            return oscillator;
        }
        #getAudioContext() {
            const container = this.#container;
            container.audioContext ??= new AudioContext();
            return container.audioContext;
        }
        #initEvents() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable || !container.canvas.domElement) {
                return;
            }
            for (const event of soundsOptions.events) {
                const cb = (args) => {
                    if (!args) {
                        return;
                    }
                    void (async () => {
                        const filterNotValid = event.filter && !event.filter(args);
                        if (this.#container !== args.container) {
                            return;
                        }
                        if (!!this.#container.muted || this.#container.destroyed) {
                            executeOnSingleOrMultiple(event.event, item => {
                                this.#engine.removeEventListener(item, cb);
                            });
                            return;
                        }
                        if (filterNotValid) {
                            return;
                        }
                        const defaultNoteIndex = 0;
                        if (event.audio) {
                            const audio = itemFromSingleOrMultiple(event.audio);
                            if (!audio) {
                                return;
                            }
                            this.#playBuffer(audio);
                        }
                        else if (event.melodies) {
                            const melody = itemFromArray(event.melodies);
                            if (!melody) {
                                return;
                            }
                            if (melody.melodies.length) {
                                await Promise.allSettled(melody.melodies.map(m => this.#playNote(m.notes, defaultNoteIndex, melody.loop)));
                            }
                            else {
                                await this.#playNote(melody.notes, defaultNoteIndex, melody.loop);
                            }
                        }
                        else if (event.notes) {
                            const note = itemFromArray(event.notes);
                            if (!note) {
                                return;
                            }
                            await this.#playNote([note], defaultNoteIndex, false);
                        }
                    })();
                };
                executeOnSingleOrMultiple(event.event, item => {
                    this.#engine.addEventListener(item, cb);
                });
            }
        }
        async #mute() {
            const container = this.#container, audioContext = this.#getAudioContext();
            for (const source of this.#audioSources) {
                this.#removeAudioSource(source);
            }
            if (this.#gain) {
                this.#gain.disconnect();
            }
            await audioContext.close();
            container.audioContext = undefined;
            this.#container.dispatchEvent(SoundsEventType.mute);
        }
        #playBuffer(audio) {
            const audioBuffer = this.#audioMap.get(audio.source);
            if (!audioBuffer) {
                return;
            }
            const audioCtx = this.#container.audioContext;
            if (!audioCtx) {
                return;
            }
            const source = this.#addBuffer(audioCtx);
            source.loop = audio.loop;
            source.buffer = audioBuffer;
            source.connect(this.#gain ?? audioCtx.destination);
            source.start();
        }
        async #playFrequency(frequency, duration) {
            if (!this.#gain || this.#container.muted) {
                return;
            }
            const audioContext = this.#getAudioContext(), oscillator = this.#addOscillator(audioContext);
            oscillator.connect(this.#gain);
            oscillator.type = "sine";
            oscillator.frequency.value = frequency;
            oscillator.start();
            return new Promise(resolve => {
                setTimeout(() => {
                    this.#removeAudioSource(oscillator);
                    resolve();
                }, duration);
            });
        }
        #playMuteSound() {
            if (this.#container.muted) {
                return;
            }
            const audioContext = this.#getAudioContext(), gain = audioContext.createGain();
            gain.connect(audioContext.destination);
            gain.gain.value = 0;
            const oscillator = audioContext.createOscillator();
            oscillator.connect(gain);
            oscillator.type = "sine";
            oscillator.frequency.value = 1;
            oscillator.start();
            setTimeout(() => {
                oscillator.stop();
                oscillator.disconnect();
                gain.disconnect();
            });
        }
        async #playNote(notes, noteIdx, loop) {
            if (this.#container.muted) {
                return;
            }
            const note = notes[noteIdx];
            if (!note) {
                return;
            }
            const value = note.value, promises = executeOnSingleOrMultiple(value, async (_, idx) => {
                return this.#playNoteValue(notes, noteIdx, idx);
            });
            await (isArray(promises) ? Promise.allSettled(promises) : promises);
            const indexOffset = 1;
            let nextNoteIdx = noteIdx + indexOffset;
            if (loop && nextNoteIdx >= notes.length) {
                nextNoteIdx = nextNoteIdx % notes.length;
            }
            await this.#playNote(notes, nextNoteIdx, loop);
        }
        async #playNoteValue(notes, noteIdx, valueIdx) {
            const note = notes[noteIdx];
            if (!note) {
                return;
            }
            const value = itemFromSingleOrMultiple(note.value, valueIdx, true);
            if (!value) {
                return;
            }
            try {
                const freq = getNoteFrequency(value);
                if (!isNumber(freq)) {
                    return;
                }
                await this.#playFrequency(freq, note.duration);
            }
            catch (e) {
                getLogger().error(e);
            }
        }
        #removeAudioSource(source) {
            source.stop();
            source.disconnect();
            const deleteCount = 1;
            this.#audioSources.splice(this.#audioSources.indexOf(source), deleteCount);
        }
        #unmute() {
            const container = this.#container, options = container.actualOptions, soundsOptions = options.sounds;
            if (!soundsOptions) {
                return;
            }
            const audioContext = this.#getAudioContext(), gain = audioContext.createGain();
            gain.connect(audioContext.destination);
            gain.gain.value = soundsOptions.volume.value / percentDenominator;
            this.#gain = gain;
            this.#initEvents();
            this.#container.dispatchEvent(SoundsEventType.unmute);
        }
        #updateMuteIcons() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable || !soundsOptions.icons.enable) {
                return;
            }
            const muteImg = this.#muteImg, unmuteImg = this.#unmuteImg;
            if (muteImg) {
                muteImg.style.display = container.muted ? "block" : "none";
            }
            if (unmuteImg) {
                unmuteImg.style.display = container.muted ? "none" : "block";
            }
        }
        async #updateMuteStatus() {
            const container = this.#container, audioContext = this.#getAudioContext();
            if (container.muted) {
                await audioContext.suspend();
                await this.#mute();
            }
            else {
                await audioContext.resume();
                this.#unmute();
                this.#playMuteSound();
            }
        }
        async #updateVolume() {
            const container = this.#container, soundsOptions = container.actualOptions.sounds;
            if (!soundsOptions?.enable) {
                return;
            }
            clamp(this.#volume, soundsOptions.volume.min, soundsOptions.volume.max);
            let stateChanged = false;
            if (this.#volume <= minVolume && !container.muted) {
                this.#volume = 0;
                container.muted = true;
                stateChanged = true;
            }
            else if (this.#volume > minVolume && container.muted) {
                container.muted = false;
                stateChanged = true;
            }
            if (stateChanged) {
                this.#updateMuteIcons();
                await this.#updateMuteStatus();
            }
            if (this.#gain?.gain) {
                this.#gain.gain.value = this.#volume / percentDenominator;
            }
        }
    }

    var SoundsPluginInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        SoundsPluginInstance: SoundsPluginInstance
    });

    const defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultEmitDelay = 0, defaultLifeCount = -1, defaultColorAnimationFactor = 1, colorFactor = 3.6, defaultStrokeWidth = 1;
    function setParticlesOptionsFillColor(particlesOptions, color, opacity, enable) {
        const paint = (particlesOptions.paint ??= new Paint());
        paint.fill = {
            color: AnimatableColor.create(undefined, { value: color }),
            enable,
            opacity,
        };
    }
    function setParticlesOptionsStrokeColor(particlesOptions, color, opacity, width) {
        const paint = (particlesOptions.paint ??= new Paint());
        paint.stroke = {
            color: AnimatableColor.create(undefined, { value: color }),
            opacity,
            width,
        };
    }
    class EmitterInstance {
        fill;
        name;
        options;
        position;
        size;
        spawnFillColor;
        spawnFillEnabled;
        spawnFillOpacity;
        spawnStrokeColor;
        spawnStrokeOpacity;
        spawnStrokeWidth;
        #container;
        #currentDuration;
        #currentEmitDelay;
        #currentSpawnDelay;
        #duration;
        #emitDelay;
        #firstSpawn;
        #immortal;
        #initialPosition;
        #lifeCount;
        #mutationObserver;
        #particlesOptions;
        #paused;
        #pluginManager;
        #removeCallback;
        #resizeObserver;
        #shape;
        #size;
        #spawnDelay;
        #startParticlesAdded;
        constructor(pluginManager, container, removeCallback, options, position) {
            this.#pluginManager = pluginManager;
            this.#container = container;
            this.#removeCallback = removeCallback;
            this.#currentDuration = 0;
            this.#currentEmitDelay = 0;
            this.#currentSpawnDelay = 0;
            this.#initialPosition = position;
            if (options instanceof Emitter) {
                this.options = options;
            }
            else {
                this.options = new Emitter();
                this.options.load(options);
            }
            this.#spawnDelay = container.retina.reduceFactor
                ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
                    container.retina.reduceFactor
                : Infinity;
            this.position = this.#initialPosition ?? this.#calcPosition();
            this.name = this.options.name;
            this.fill = this.options.fill;
            this.#firstSpawn = !this.options.life.wait;
            this.#startParticlesAdded = false;
            const particlesOptions = deepExtend({}, this.options.particles);
            particlesOptions.move ??= {};
            particlesOptions.move.direction ??= this.options.direction;
            if (this.options.spawn.fill?.color) {
                this.spawnFillColor = rangeColorToHsl(this.#pluginManager, this.options.spawn.fill.color);
            }
            if (this.options.spawn.stroke?.color) {
                this.spawnStrokeColor = rangeColorToHsl(this.#pluginManager, this.options.spawn.stroke.color);
            }
            this.#paused = !this.options.autoPlay;
            this.#particlesOptions = particlesOptions;
            this.#size = this.#calcSize();
            this.size =
                this.#size.mode === exports.PixelMode.percent
                    ? {
                        width: (this.#size.width / percentDenominator) * this.#container.canvas.size.width,
                        height: (this.#size.height / percentDenominator) * this.#container.canvas.size.height,
                    }
                    : { width: this.#size.width, height: this.#size.height };
            this.#lifeCount = this.options.life.count ?? defaultLifeCount;
            this.#immortal = this.#lifeCount <= minLifeCount;
            if (this.options.domId) {
                const element = safeDocument().getElementById(this.options.domId);
                if (element) {
                    this.#mutationObserver = new MutationObserver(() => {
                        this.resize();
                    });
                    this.#resizeObserver = new ResizeObserver(() => {
                        this.resize();
                    });
                    this.#mutationObserver.observe(element, {
                        attributes: true,
                        attributeFilter: ["style", "width", "height"],
                    });
                    this.#resizeObserver.observe(element);
                }
            }
            const shapeOptions = this.options.shape, shapeGenerator = this.#pluginManager.emitterShapeManager?.getShapeGenerator(shapeOptions.type);
            if (shapeGenerator) {
                this.#shape = shapeGenerator.generate(this.#container, this.position, this.size, this.fill, shapeOptions.options);
            }
            this.#container.dispatchEvent("emitterCreated", {
                emitter: this,
            });
            this.play();
        }
        externalPause() {
            this.#paused = true;
            this.pause();
        }
        externalPlay() {
            this.#paused = false;
            this.play();
        }
        async init() {
            await this.#shape?.init();
        }
        pause() {
            if (this.#paused) {
                return;
            }
            this.#emitDelay = undefined;
        }
        play() {
            if (this.#paused) {
                return;
            }
            if (!((this.#lifeCount > minLifeCount || this.#immortal || !this.options.life.count) &&
                (this.#firstSpawn || this.#currentSpawnDelay >= (this.#spawnDelay ?? defaultSpawnDelay)))) {
                return;
            }
            const container = this.#container;
            if (this.#emitDelay === undefined) {
                const delay = getRangeValue(this.options.rate.delay);
                this.#emitDelay = container.retina.reduceFactor
                    ? (delay * millisecondsToSeconds) / container.retina.reduceFactor
                    : Infinity;
            }
            if (this.#lifeCount > minLifeCount || this.#immortal) {
                this.#prepareToDie();
            }
        }
        resize() {
            const initialPosition = this.#initialPosition, container = this.#container;
            this.position =
                initialPosition && isPointInside(initialPosition, container.canvas.size, Vector.origin)
                    ? initialPosition
                    : this.#calcPosition();
            this.#size = this.#calcSize();
            this.size =
                this.#size.mode === exports.PixelMode.percent
                    ? {
                        width: (this.#size.width / percentDenominator) * container.canvas.size.width,
                        height: (this.#size.height / percentDenominator) * container.canvas.size.height,
                    }
                    : { width: this.#size.width, height: this.#size.height };
            this.#shape?.resize(this.position, this.size);
        }
        update(delta) {
            if (this.#paused) {
                return;
            }
            const container = this.#container;
            if (this.#firstSpawn) {
                this.#firstSpawn = false;
                this.#currentSpawnDelay = this.#spawnDelay ?? defaultSpawnDelay;
                this.#currentEmitDelay = this.#emitDelay ?? defaultEmitDelay;
            }
            if (!this.#startParticlesAdded) {
                this.#startParticlesAdded = true;
                this.#emitParticles(this.options.startCount);
            }
            if (this.#duration !== undefined) {
                this.#currentDuration += delta.value;
                if (this.#currentDuration >= this.#duration) {
                    this.pause();
                    if (this.#spawnDelay !== undefined) {
                        this.#spawnDelay = undefined;
                    }
                    if (!this.#immortal) {
                        this.#lifeCount--;
                    }
                    if (this.#lifeCount > minLifeCount || this.#immortal) {
                        this.position = this.#calcPosition();
                        this.#shape?.resize(this.position, this.size);
                        this.#spawnDelay = container.retina.reduceFactor
                            ? (getRangeValue(this.options.life.delay ?? defaultLifeDelay) * millisecondsToSeconds) /
                                container.retina.reduceFactor
                            : Infinity;
                    }
                    else {
                        this.#destroy();
                    }
                    this.#currentDuration -= this.#duration;
                    this.#duration = undefined;
                }
            }
            if (this.#spawnDelay !== undefined) {
                this.#currentSpawnDelay += delta.value;
                if (this.#currentSpawnDelay >= this.#spawnDelay) {
                    this.#container.dispatchEvent("emitterPlay");
                    this.play();
                    this.#currentSpawnDelay -= this.#spawnDelay;
                    this.#spawnDelay = undefined;
                }
            }
            if (this.#emitDelay !== undefined) {
                this.#currentEmitDelay += delta.value;
                if (this.#currentEmitDelay >= this.#emitDelay) {
                    this.#emit();
                    this.#currentEmitDelay -= this.#emitDelay;
                }
            }
        }
        #calcPosition() {
            const container = this.#container;
            if (this.options.domId) {
                const element = safeDocument().getElementById(this.options.domId);
                if (element) {
                    const elRect = element.getBoundingClientRect(), pxRatio = container.retina.pixelRatio;
                    return {
                        x: (elRect.x + elRect.width * half) * pxRatio,
                        y: (elRect.y + elRect.height * half) * pxRatio,
                    };
                }
            }
            return calcPositionOrRandomFromSizeRanged({
                size: container.canvas.size,
                position: this.options.position,
            });
        }
        #calcSize() {
            const container = this.#container;
            if (this.options.domId) {
                const element = safeDocument().getElementById(this.options.domId);
                if (element) {
                    const elRect = element.getBoundingClientRect();
                    return {
                        width: elRect.width * container.retina.pixelRatio,
                        height: elRect.height * container.retina.pixelRatio,
                        mode: exports.PixelMode.precise,
                    };
                }
            }
            return (this.options.size ??
                (() => {
                    const size = new EmitterSize();
                    size.load({
                        height: 0,
                        mode: exports.PixelMode.percent,
                        width: 0,
                    });
                    return size;
                })());
        }
        #destroy() {
            this.#mutationObserver?.disconnect();
            this.#mutationObserver = undefined;
            this.#resizeObserver?.disconnect();
            this.#resizeObserver = undefined;
            this.#removeCallback(this);
            this.#container.dispatchEvent("emitterDestroyed", {
                emitter: this,
            });
        }
        #emit() {
            if (this.#paused) {
                return;
            }
            const quantity = getRangeValue(this.options.rate.quantity);
            this.#emitParticles(quantity);
        }
        #emitParticles(quantity) {
            const singleParticlesOptions = (itemFromSingleOrMultiple(this.#particlesOptions) ??
                {}), fillHslAnimation = this.options.spawn.fill?.color?.animation, fillEnabled = this.options.spawn.fill?.enable ?? !!this.options.spawn.fill?.color, fillOpacity = this.options.spawn.fill?.opacity === undefined
                ? defaultOpacity$1
                : getRangeValue(this.options.spawn.fill.opacity), strokeHslAnimation = this.options.spawn.stroke?.color?.animation, strokeOpacity = this.options.spawn.stroke?.opacity === undefined
                ? defaultOpacity$1
                : getRangeValue(this.options.spawn.stroke.opacity), strokeWidth = this.options.spawn.stroke?.width === undefined
                ? defaultStrokeWidth
                : getRangeValue(this.options.spawn.stroke.width), reduceFactor = this.#container.retina.reduceFactor, needsFillColorAnimation = !!fillHslAnimation, needsStrokeColorAnimation = !!strokeHslAnimation, needsShapeData = !!this.#shape, needsColorAnimation = needsFillColorAnimation || needsStrokeColorAnimation, needsCopy = needsColorAnimation || needsShapeData, maxValues = needsColorAnimation ? { h: hMax, s: sMax, l: lMax } : null, shapeOptions = this.options.shape;
            for (let i = 0; i < quantity * reduceFactor; i++) {
                const particlesOptions = needsCopy
                    ? deepExtend({}, singleParticlesOptions)
                    : singleParticlesOptions;
                this.spawnFillOpacity = fillOpacity;
                this.spawnFillEnabled = fillEnabled;
                this.spawnStrokeOpacity = strokeOpacity;
                this.spawnStrokeWidth = strokeWidth;
                if (this.spawnFillColor) {
                    if (fillHslAnimation && maxValues) {
                        this.spawnFillColor.h = this.#setColorAnimation(fillHslAnimation.h, this.spawnFillColor.h, maxValues.h, colorFactor);
                        this.spawnFillColor.s = this.#setColorAnimation(fillHslAnimation.s, this.spawnFillColor.s, maxValues.s);
                        this.spawnFillColor.l = this.#setColorAnimation(fillHslAnimation.l, this.spawnFillColor.l, maxValues.l);
                    }
                    setParticlesOptionsFillColor(particlesOptions, this.spawnFillColor, this.spawnFillOpacity, this.spawnFillEnabled);
                }
                if (this.spawnStrokeColor) {
                    if (strokeHslAnimation && maxValues) {
                        this.spawnStrokeColor.h = this.#setColorAnimation(strokeHslAnimation.h, this.spawnStrokeColor.h, maxValues.h, colorFactor);
                        this.spawnStrokeColor.s = this.#setColorAnimation(strokeHslAnimation.s, this.spawnStrokeColor.s, maxValues.s);
                        this.spawnStrokeColor.l = this.#setColorAnimation(strokeHslAnimation.l, this.spawnStrokeColor.l, maxValues.l);
                    }
                    setParticlesOptionsStrokeColor(particlesOptions, this.spawnStrokeColor, this.spawnStrokeOpacity, this.spawnStrokeWidth);
                }
                let position = this.position;
                if (this.#shape) {
                    const shapePosData = this.#shape.randomPosition();
                    if (shapePosData) {
                        position = shapePosData.position;
                        const replaceData = shapeOptions.replace;
                        if (replaceData.color && shapePosData.color) {
                            setParticlesOptionsFillColor(particlesOptions, shapePosData.color, replaceData.opacity ? (shapePosData.opacity ?? defaultOpacity$1) : defaultOpacity$1, true);
                        }
                    }
                    else {
                        position = null;
                    }
                }
                if (position) {
                    this.#container.particles.addParticle(position, particlesOptions);
                }
            }
        }
        #prepareToDie() {
            if (this.#paused) {
                return;
            }
            const duration = this.options.life.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
            if ((this.#lifeCount > minLifeCount || this.#immortal) && duration !== undefined && duration > minDuration) {
                this.#duration = duration * millisecondsToSeconds;
            }
        }
        #setColorAnimation(animation, initValue, maxValue, factor = defaultColorAnimationFactor) {
            const container = this.#container;
            if (!animation.enable) {
                return initValue;
            }
            const colorOffset = randomInRangeValue(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = container.retina.reduceFactor
                ? (delay * millisecondsToSeconds) / container.retina.reduceFactor
                : Infinity, colorSpeed = getRangeValue(animation.speed);
            return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
        }
    }

    var EmitterInstance$1 = /*#__PURE__*/Object.freeze({
        __proto__: null,
        EmitterInstance: EmitterInstance
    });

    exports.AnimatableColor = AnimatableColor;
    exports.AnimationOptions = AnimationOptions;
    exports.AnimationValueWithRandom = AnimationValueWithRandom;
    exports.Background = Background;
    exports.BaseRange = BaseRange;
    exports.Circle = Circle;
    exports.ColorAnimation = ColorAnimation;
    exports.Fill = Fill;
    exports.FullScreen = FullScreen;
    exports.HDROptions = HDROptions;
    exports.HslAnimation = HslAnimation;
    exports.Move = Move;
    exports.MoveAngle = MoveAngle;
    exports.MoveCenter = MoveCenter;
    exports.MoveGravity = MoveGravity;
    exports.MovePath = MovePath;
    exports.OptionLoader = OptionLoader;
    exports.Options = Options;
    exports.OptionsColor = OptionsColor;
    exports.OutModes = OutModes;
    exports.Paint = Paint;
    exports.ParticlesBounce = ParticlesBounce;
    exports.ParticlesBounceFactor = ParticlesBounceFactor;
    exports.ParticlesDensity = ParticlesDensity;
    exports.ParticlesNumber = ParticlesNumber;
    exports.ParticlesNumberLimit = ParticlesNumberLimit;
    exports.ParticlesOptions = ParticlesOptions;
    exports.RangedAnimationOptions = RangedAnimationOptions;
    exports.RangedAnimationValueWithRandom = RangedAnimationValueWithRandom;
    exports.Rectangle = Rectangle;
    exports.ResizeEvent = ResizeEvent;
    exports.Shape = Shape;
    exports.Spin = Spin;
    exports.Stroke = Stroke;
    exports.ValueWithRandom = ValueWithRandom;
    exports.Vector = Vector;
    exports.Vector3d = Vector3d;
    exports.ZIndex = ZIndex;
    exports.alterHsl = alterHsl;
    exports.animate = animate;
    exports.areBoundsInside = areBoundsInside;
    exports.calcExactPositionOrRandomFromSize = calcExactPositionOrRandomFromSize;
    exports.calcPositionFromSize = calcPositionFromSize;
    exports.calcPositionOrRandomFromSize = calcPositionOrRandomFromSize;
    exports.calcPositionOrRandomFromSizeRanged = calcPositionOrRandomFromSizeRanged;
    exports.calculateBounds = calculateBounds;
    exports.cancelAnimation = cancelAnimation;
    exports.canvasFirstIndex = canvasFirstIndex;
    exports.canvasTag = canvasTag;
    exports.checkDistance = checkDistance;
    exports.circleBounce = circleBounce;
    exports.circleBounceDataFromParticle = circleBounceDataFromParticle;
    exports.clamp = clamp;
    exports.cloneStyle = cloneStyle;
    exports.collisionVelocity = collisionVelocity;
    exports.colorMix = colorMix;
    exports.colorToRgb = colorToRgb;
    exports.countOffset = countOffset;
    exports.decayOffset = decayOffset;
    exports.deepExtend = deepExtend;
    exports.defaultAlpha = defaultAlpha$1;
    exports.defaultAngle = defaultAngle;
    exports.defaultCompositeValue = defaultCompositeValue;
    exports.defaultDensityFactor = defaultDensityFactor;
    exports.defaultFps = defaultFps;
    exports.defaultFpsLimit = defaultFpsLimit;
    exports.defaultLoops = defaultLoops;
    exports.defaultOpacity = defaultOpacity$1;
    exports.defaultRatio = defaultRatio;
    exports.defaultReduceFactor = defaultReduceFactor;
    exports.defaultRemoveQuantity = defaultRemoveQuantity;
    exports.defaultRetryCount = defaultRetryCount;
    exports.defaultRgbMin = defaultRgbMin;
    exports.defaultTime = defaultTime;
    exports.defaultTransform = defaultTransform;
    exports.defaultTransformValue = defaultTransformValue;
    exports.defaultVelocity = defaultVelocity;
    exports.defaultZoom = defaultZoom;
    exports.degToRad = degToRad;
    exports.deleteCount = deleteCount;
    exports.double = double;
    exports.doublePI = doublePI;
    exports.empty = empty;
    exports.executeOnSingleOrMultiple = executeOnSingleOrMultiple;
    exports.fireworks = fireworks;
    exports.generatedAttribute = generatedAttribute;
    exports.generatedFalse = generatedFalse;
    exports.generatedTrue = generatedTrue;
    exports.getDistance = getDistance;
    exports.getDistanceSq = getDistanceSq;
    exports.getDistances = getDistances;
    exports.getFullScreenStyle = getFullScreenStyle;
    exports.getHslAnimationFromHsl = getHslAnimationFromHsl;
    exports.getHslFromAnimation = getHslFromAnimation;
    exports.getItemMapFromInitializer = getItemMapFromInitializer;
    exports.getItemsFromInitializer = getItemsFromInitializer;
    exports.getLinkColor = getLinkColor;
    exports.getLinkRandomColor = getLinkRandomColor;
    exports.getLogger = getLogger;
    exports.getParticleBaseVelocity = getParticleBaseVelocity;
    exports.getParticleDirectionAngle = getParticleDirectionAngle;
    exports.getPosition = getPosition;
    exports.getRandom = getRandom;
    exports.getRandomFn = getRandomFn;
    exports.getRandomInRange = getRandomInRange;
    exports.getRandomRgbColor = getRandomRgbColor;
    exports.getRangeMax = getRangeMax;
    exports.getRangeMin = getRangeMin;
    exports.getRangeValue = getRangeValue;
    exports.getStyleFromHsl = getStyleFromHsl;
    exports.getStyleFromRgb = getStyleFromRgb;
    exports.hMax = hMax;
    exports.hMin = hMin;
    exports.hPhase = hPhase;
    exports.half = half;
    exports.hslToRgb = hslToRgb;
    exports.hslToRgbFloat = hslToRgbFloat;
    exports.hslaToRgba = hslaToRgba;
    exports.identity = identity$1;
    exports.inverseFactorNumerator = inverseFactorNumerator;
    exports.isArray = isArray;
    exports.isBoolean = isBoolean;
    exports.isFunction = isFunction;
    exports.isInArray = isInArray;
    exports.isNull = isNull;
    exports.isNumber = isNumber;
    exports.isObject = isObject;
    exports.isPointInside = isPointInside;
    exports.isString = isString;
    exports.itemFromArray = itemFromArray;
    exports.itemFromSingleOrMultiple = itemFromSingleOrMultiple;
    exports.lFactor = lFactor;
    exports.lMax = lMax;
    exports.lMin = lMin;
    exports.lengthOffset = lengthOffset;
    exports.loadExtendProperty = loadExtendProperty;
    exports.loadLazyProperty = loadLazyProperty;
    exports.loadMinIndex = loadMinIndex;
    exports.loadNestedProperty = loadNestedProperty;
    exports.loadOptionProperty = loadOptionProperty;
    exports.loadOptions = loadOptions;
    exports.loadParticlesOptions = loadParticlesOptions;
    exports.loadProperty = loadProperty;
    exports.loadRandomFactor = loadRandomFactor;
    exports.loadRangeProperty = loadRangeProperty;
    exports.manageListener = manageListener;
    exports.maxNits = maxNits;
    exports.midColorValue = midColorValue;
    exports.millisecondsToSeconds = millisecondsToSeconds;
    exports.minCount = minCount;
    exports.minDistance = minDistance;
    exports.minFpsLimit = minFpsLimit;
    exports.minIndex = minIndex;
    exports.minLimit = minLimit;
    exports.minRadius = minRadius$1;
    exports.minStrokeWidth = minStrokeWidth;
    exports.minVelocity = minVelocity;
    exports.minZ = minZ;
    exports.minimumSize = minimumSize;
    exports.mix = mix;
    exports.none = none;
    exports.one = one;
    exports.originPoint = originPoint;
    exports.parseAlpha = parseAlpha;
    exports.percentDenominator = percentDenominator;
    exports.phaseNumerator = phaseNumerator;
    exports.quarter = quarter;
    exports.randomColorValue = randomColorValue;
    exports.randomInRangeValue = randomInRangeValue;
    exports.rangeColorToHsl = rangeColorToHsl;
    exports.rangeColorToRgb = rangeColorToRgb;
    exports.removeDeleteCount = removeDeleteCount;
    exports.removeMinIndex = removeMinIndex;
    exports.resizeEvent = resizeEvent;
    exports.rgbMax = rgbMax;
    exports.rgbToHsl = rgbToHsl;
    exports.sMax = sMax;
    exports.sMin = sMin;
    exports.sNormalizedOffset = sNormalizedOffset;
    exports.safeDocument = safeDocument;
    exports.safeMatchMedia = safeMatchMedia;
    exports.safeMutationObserver = safeMutationObserver;
    exports.setAnimationFunctions = setAnimationFunctions;
    exports.setLogger = setLogger;
    exports.setRandom = setRandom;
    exports.setRangeValue = setRangeValue;
    exports.sextuple = sextuple;
    exports.spatialHashGridCellSize = spatialHashGridCellSize;
    exports.squareExp = squareExp;
    exports.stringToAlpha = stringToAlpha;
    exports.stringToRgb = stringToRgb;
    exports.threeQuarter = threeQuarter;
    exports.triple = triple;
    exports.tryCountIncrement = tryCountIncrement;
    exports.tsParticles = tsParticles;
    exports.updateColor = updateColor;
    exports.updateColorValue = updateColorValue;
    exports.visibilityChangeEvent = visibilityChangeEvent;
    exports.zIndexFactorOffset = zIndexFactorOffset;

}));
Object.assign(globalThis.window || globalThis, { fireworks: (globalThis.__tsParticlesInternals.bundles.fireworks || {}).fireworks });
delete (globalThis.window || globalThis).tsparticlesInternalExports;