{"version":3,"sources":["../src/core/Config.ts","../src/core/Random.ts","../src/core/Vector2D.ts","../src/core/Particle.ts","../src/core/Renderer.ts","../src/core/Engine.ts","../src/index.ts"],"sourcesContent":["export interface ConfettiConfig {\n    position: { x: number; y: number };\n    count: number;\n    size: number;\n    velocity: number;\n    fade: boolean;\n    color?: string[] | number[];\n}\n\nconst DEFAULT_CONFIG = {\n    count: 75,\n    size: 1,\n    velocity: 200,\n    fade: false,\n};\n\nexport default class Config {\n    static init(config: Partial<ConfettiConfig>): ConfettiConfig {\n        return {\n            position: { x: window.innerWidth / 2, y: window.innerHeight / 3 },\n            ...DEFAULT_CONFIG,\n            ...config,\n        };\n    }\n}\n","export default class Random {\n    static range(min: number, max: number): number {\n        return Math.random() * (max - min) + min;\n    }\n}\n","export default class Vector2D {\n    x: number;\n    y: number;\n\n    constructor(x: number = 0, y: number = 0) {\n        this.x = x;\n        this.y = y;\n    }\n\n    copy(): Vector2D {\n        return new Vector2D(this.x, this.y);\n    }\n\n    magnitude(): number {\n        return Math.hypot(this.x, this.y);\n    }\n\n    normalize(): Vector2D {\n        const mag = this.magnitude();\n        if (mag === 0) {\n            this.x = 0;\n            this.y = 0;\n            return this;\n        }\n        const inv = 1 / mag;\n        this.x *= inv;\n        this.y *= inv;\n        return this;\n    }\n\n    scale(s: number): Vector2D {\n        this.x *= s;\n        this.y *= s;\n        return this;\n    }\n}\n","import { ConfettiConfig } from \"./Config\";\nimport Random from \"./Random\";\nimport Renderer from \"./Renderer\";\nimport Vector2D from \"./Vector2D\";\n\nexport default class Particle {\n    private config: ConfettiConfig;\n    private position: Vector2D;\n    private size: Vector2D;\n    private velocity: Vector2D;\n    private rotation: number;\n    private rotationSpeed: number;\n    private color: string | number;\n    private opacity: number;\n    private fadeRate: number;\n\n    constructor(config: ConfettiConfig) {\n        this.config = config;\n        this.position = this.initPosition();\n        this.size = this.initSize();\n        this.velocity = this.initVelocity();\n        this.rotation = Random.range(0, 360);\n        this.rotationSpeed = Random.range(-250, 250);\n        this.color = this.initColor();\n        this.opacity = 100;\n        this.fadeRate = 100 / Random.range(0.5, 2.5);\n    }\n\n    private initPosition(): Vector2D {\n        const x = this.config.position.x;\n        const y = this.config.position.y;\n        return new Vector2D(x, y);\n    }\n\n    private initSize(): Vector2D {\n        const x = Random.range(2, 10) * this.config.size;\n        const y = Random.range(2, 4) * this.config.size;\n        return new Vector2D(x, y);\n    }\n\n    private initVelocity(): Vector2D {\n        const x = Random.range(-0.5, 0.5);\n        const y = Random.range(-0.75, 0.25);\n        const direction = new Vector2D(x, y).normalize();\n        direction.x *= Random.range(0, this.config.velocity * 4);\n        direction.y *= Random.range(0, this.config.velocity * 4);\n        return direction;\n    }\n\n    private initColor(): string | number {\n        if (this.config.color && this.config.color.length > 0) {\n            const index = Math.floor(Random.range(0, this.config.color.length));\n            return this.config.color[index];\n        } else {\n            return Random.range(0, 360);\n        }\n    }\n\n    update(delta: number, damping: number): void {\n        this.velocity.x += Random.range(-350, 350) * delta;\n        this.velocity.y += 75 * this.size.y * delta;\n\n        this.velocity.scale(damping);\n\n        this.position.x += this.velocity.x * delta;\n        this.position.y += this.velocity.y * delta;\n\n        this.rotation += this.rotationSpeed * delta;\n\n        if (this.config.fade) {\n            this.opacity -= this.fadeRate * delta;\n            if (this.opacity < 0) this.opacity = 0;\n        }\n    }\n\n    draw(renderer: Renderer): void {\n        renderer.drawRect(\n            this.position,\n            this.size,\n            this.rotation,\n            this.color,\n            this.opacity\n        );\n    }\n\n    cull(renderer: Renderer): boolean {\n        const padding = Math.max(this.size.x, this.size.y) * 2;\n        const offScreen = this.position.y > renderer.height + padding;\n        return offScreen || this.opacity <= 0;\n    }\n}\n","import Vector2D from \"./Vector2D\";\n\nexport default class Renderer {\n    private canvas: HTMLCanvasElement;\n    private context: CanvasRenderingContext2D;\n\n    private dpr: number;\n    private rafId: number;\n    private boundResize: () => void;\n\n    constructor() {\n        const canvas = document.createElement(\"canvas\");\n        const context = canvas.getContext(\"2d\");\n        if (!context) {\n            throw new Error(\"Unable to create 2d context\");\n        }\n\n        this.canvas = canvas;\n        this.context = context;\n\n        this.dpr = Math.max(1, window.devicePixelRatio || 1);\n        this.rafId = 0;\n        this.boundResize = this.resize.bind(this);\n\n        this.resize();\n        window.addEventListener(\"resize\", this.boundResize);\n\n        canvas.style.position = \"fixed\";\n        canvas.style.top = \"0\";\n        canvas.style.left = \"0\";\n        canvas.style.width = \"100%\";\n        canvas.style.height = \"100%\";\n        canvas.style.margin = \"0\";\n        canvas.style.padding = \"0\";\n        canvas.style.zIndex = \"999999999\";\n        canvas.style.pointerEvents = \"none\";\n\n        document.body.appendChild(canvas);\n\n        this.context.imageSmoothingEnabled = true;\n    }\n\n    private resize(): void {\n        if (this.rafId) cancelAnimationFrame(this.rafId);\n        this.rafId = requestAnimationFrame(() => {\n            const { innerWidth, innerHeight } = window;\n            this.canvas.width = Math.round(innerWidth * this.dpr);\n            this.canvas.height = Math.round(innerHeight * this.dpr);\n            this.canvas.style.width = `${innerWidth}px`;\n            this.canvas.style.height = `${innerHeight}px`;\n            this.context.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);\n            this.context.imageSmoothingEnabled = true;\n            this.rafId = 0;\n        });\n    }\n\n    get width(): number {\n        return this.canvas.width / this.dpr;\n    }\n\n    get height(): number {\n        return this.canvas.height / this.dpr;\n    }\n\n    clear(): void {\n        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n    }\n\n    drawRect(p: Vector2D, s: Vector2D, r: number, c: string | number, o: number): void {\n        const rad = (r * Math.PI) / 180;\n        const cos = Math.cos(rad);\n        const sin = Math.sin(rad);\n        const width = s.x * this.dpr;\n        const height = s.y * this.dpr;\n        const tx = p.x * this.dpr;\n        const ty = p.y * this.dpr;\n        this.context.setTransform(cos, sin, -sin, cos, tx, ty);\n        this.context.beginPath();\n        this.context.rect(-width / 2, -height / 2, width, height);\n        this.context.fillStyle = typeof c === \"string\" ? `oklch(from ${c} l c h / ${o}%)` : `oklch(0.85 0.25 ${c}deg / ${o}%)`;\n        this.context.fill();\n        this.context.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);\n    }\n\n    cleanup(): void {\n        window.removeEventListener(\"resize\", this.boundResize);\n        if (this.rafId) cancelAnimationFrame(this.rafId);\n        this.canvas.remove();\n    }\n}\n","import { ConfettiConfig } from \"./Config\";\nimport Particle from \"./Particle\";\nimport Renderer from \"./Renderer\";\n\nexport default class Engine {\n    private renderer: Renderer;\n    private particles: Particle[];\n\n    private lastTime: number;\n    private rafId: number;\n    private boundUpdate: (time: number) => void;\n\n    private static sharedEngine: Engine | null = null;\n\n    private constructor() {\n        this.renderer = new Renderer();\n        this.particles = [];\n\n        this.boundUpdate = this.update.bind(this);\n        this.lastTime = 0;\n        this.rafId = window.requestAnimationFrame(this.boundUpdate);\n    }\n\n    private update(time: number): void {\n        const delta = this.lastTime ? Math.min((time - this.lastTime) / 1000, 0.064) : 0;\n        this.lastTime = time;\n\n        if (this.particles.length === 0) {\n            this.cleanup();\n            return;\n        }\n\n        this.renderer.clear();\n\n        let write = 0;\n        const damping = Math.pow(0.98, delta * 60);\n        for (let i = 0; i < this.particles.length; i++) {\n            this.particles[i].update(delta, damping);\n            if (!this.particles[i].cull(this.renderer)) {\n                this.particles[i].draw(this.renderer);\n                this.particles[write++] = this.particles[i];\n            }\n        }\n        this.particles.length = write;\n\n        this.rafId = window.requestAnimationFrame(this.boundUpdate);\n    }\n\n    private cleanup(): void {\n        if(this.rafId) window.cancelAnimationFrame(this.rafId);\n        this.renderer.cleanup();\n        Engine.sharedEngine = null;\n    }\n\n    trigger(config: ConfettiConfig): void {\n        for (let i = 0; i < config.count; i++) {\n            this.particles.push(new Particle(config));\n        }\n    }\n\n    static acquire(): Engine {\n        if (!Engine.sharedEngine) {\n            Engine.sharedEngine = new Engine();\n        }\n        return Engine.sharedEngine;\n    }\n}","import Config, { ConfettiConfig } from \"./core/Config\";\nimport Engine from \"./core/Engine\";\n\nexport default function confetti(c: Partial<ConfettiConfig> = {}): void {\n    const config = Config.init(c);\n    const engine = Engine.acquire();\n    engine.trigger(config);\n}"],"mappings":"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","names":[]}