@konfetti-js/core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shapes.ts","../src/utils.ts","../src/particle.ts","../src/physics.ts","../src/presets.ts","../src/renderer.ts","../src/konfetti.ts","../src/global.ts"],"sourcesContent":["import type { ShapeType } from './types';\n\n/**\n * Shape rendering functions\n * Each shape function draws centered at (0, 0) with the given size\n */\nexport type ShapeRenderer = (ctx: CanvasRenderingContext2D, size: number) => void;\n\n/**\n * Draw a circle\n */\nfunction drawCircle(ctx: CanvasRenderingContext2D, size: number): void {\n ctx.beginPath();\n ctx.arc(0, 0, size / 2, 0, Math.PI * 2);\n ctx.fill();\n}\n\n/**\n * Draw a square\n */\nfunction drawSquare(ctx: CanvasRenderingContext2D, size: number): void {\n const halfSize = size / 2;\n ctx.fillRect(-halfSize, -halfSize, size, size);\n}\n\n/**\n * Supported shapes; a particle stores its shape as an index into this list\n */\nconst SHAPES: readonly ShapeType[] = ['circle', 'square'];\n\nconst RENDERERS: readonly ShapeRenderer[] = [drawCircle, drawSquare];\n\n/**\n * Whether a value is a supported shape name\n */\nexport function isShape(value: unknown): value is ShapeType {\n return SHAPES.includes(value as ShapeType);\n}\n\n/**\n * Shape index for Float32Array storage\n */\nexport function shapeToIndex(shape: ShapeType): number {\n return Math.max(0, SHAPES.indexOf(shape));\n}\n\n/**\n * Get the renderer for a stored shape index\n */\nexport function getShapeRenderer(index: number): ShapeRenderer {\n return RENDERERS[index] ?? drawCircle;\n}\n","import { isShape } from './shapes';\nimport type { KonfettiOptions, Origin, ResolvedOptions, ShapeType } from './types';\n\n/**\n * Default festive colors\n */\nexport const DEFAULT_COLORS = [\n '#26ccff', // cyan\n '#a25afd', // purple\n '#ff5e7e', // pink\n '#88ff5a', // green\n '#fcff42', // yellow\n '#ffa62d', // orange\n '#ff36ff', // magenta\n];\n\n/**\n * Default options\n */\nexport const DEFAULT_OPTIONS: ResolvedOptions = {\n particleCount: 50,\n angle: 90,\n spread: 45,\n startVelocity: 45,\n decay: 0.9,\n gravity: 1,\n drift: 0,\n ticks: 200,\n origin: { x: 0.5, y: 0.5 },\n colors: DEFAULT_COLORS,\n shapes: ['circle', 'square'] as ShapeType[],\n scalar: 1,\n zIndex: 100,\n disableForReducedMotion: true,\n};\n\n/**\n * Use `value` when it is a finite number, otherwise `fallback`\n */\nfunction finite(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\n/**\n * Merge user options with defaults, replacing missing or invalid values\n */\nexport function resolveOptions(options: KonfettiOptions = {}): ResolvedOptions {\n const d = DEFAULT_OPTIONS;\n const colors = Array.isArray(options.colors)\n ? options.colors.filter((c) => typeof c === 'string' && c.length > 0)\n : [];\n const shapes = Array.isArray(options.shapes) ? options.shapes.filter(isShape) : [];\n\n return {\n particleCount: Math.max(0, Math.round(finite(options.particleCount, d.particleCount))),\n angle: finite(options.angle, d.angle),\n spread: finite(options.spread, d.spread),\n startVelocity: finite(options.startVelocity, d.startVelocity),\n decay: clamp(finite(options.decay, d.decay), 0, 1),\n gravity: finite(options.gravity, d.gravity),\n drift: finite(options.drift, d.drift),\n ticks: Math.max(1, finite(options.ticks, d.ticks)),\n origin: {\n x: finite(options.origin?.x, d.origin.x),\n y: finite(options.origin?.y, d.origin.y),\n },\n colors: colors.length > 0 ? colors : [...d.colors],\n shapes: shapes.length > 0 ? shapes : [...d.shapes],\n scalar: Math.max(0, finite(options.scalar, d.scalar)),\n zIndex: finite(options.zIndex, d.zIndex),\n disableForReducedMotion: options.disableForReducedMotion ?? d.disableForReducedMotion,\n };\n}\n\n/**\n * Layer `override` on top of `base`, skipping keys that are explicitly undefined\n * so a wrapper passing `{ colors: undefined }` keeps the preset's colors\n */\nexport function mergeOptions(base: KonfettiOptions, override?: KonfettiOptions): KonfettiOptions {\n const merged: Record<string, unknown> = { ...base };\n if (override) {\n for (const [key, value] of Object.entries(override)) {\n if (value !== undefined) merged[key] = value;\n }\n // Origins merge per axis, so { x: 0.2 } keeps the base's y\n if (override.origin) merged.origin = mergeOrigin(base.origin, override.origin);\n }\n return merged as KonfettiOptions;\n}\n\n/**\n * Layer the defined axes of `override` on top of `base`\n */\nexport function mergeOrigin(\n base: Partial<Origin> | undefined,\n override: Partial<Origin> | undefined\n): Partial<Origin> {\n return {\n ...base,\n ...(override?.x !== undefined && { x: override.x }),\n ...(override?.y !== undefined && { y: override.y }),\n };\n}\n\n/**\n * Convert degrees to radians\n */\nexport function degToRad(deg: number): number {\n return deg * (Math.PI / 180);\n}\n\n/**\n * Get random number between min and max\n */\nexport function randomRange(min: number, max: number): number {\n return Math.random() * (max - min) + min;\n}\n\n/**\n * Get random item from array\n */\nexport function randomItem<T>(arr: readonly T[]): T {\n return arr[Math.floor(Math.random() * arr.length)];\n}\n\n/**\n * Whether we are running in a browser with a DOM\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if user prefers reduced motion\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false;\n const mediaQuery = window.matchMedia?.('(prefers-reduced-motion: reduce)');\n return mediaQuery?.matches ?? false;\n}\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n","import { shapeToIndex } from './shapes';\nimport { ParticleIndex, type ResolvedOptions } from './types';\nimport { degToRad, randomItem, randomRange } from './utils';\n\n/** Hard upper limit, so a runaway loop of fire() calls cannot eat memory */\nexport const MAX_PARTICLES = 10_000;\n\n/** Above this many colors, unused ones are dropped from the palette */\nconst MAX_PALETTE = 256;\n\n/**\n * Particle pool using Float32Array for performance\n * Each particle uses ParticleIndex.SIZE floats\n */\nexport class ParticlePool {\n /** Raw particle data */\n public data: Float32Array;\n /** Number of active particles */\n public activeCount = 0;\n /**\n * Colors in use; particles store an index into this list, so any CSS color\n * works without parsing it\n */\n public readonly palette: string[] = [];\n private readonly colorIds = new Map<string, number>();\n\n constructor(initialCapacity = 512) {\n this.data = new Float32Array(initialCapacity * ParticleIndex.SIZE);\n }\n\n /** How many particles fit before the buffer has to grow */\n get capacity(): number {\n return this.data.length / ParticleIndex.SIZE;\n }\n\n /**\n * Remove every particle\n */\n reset(): void {\n this.activeCount = 0;\n this.clearPalette();\n }\n\n /**\n * Spawn particles with the given options\n */\n spawn(options: ResolvedOptions, canvasWidth: number, canvasHeight: number): void {\n const count = Math.min(options.particleCount, MAX_PARTICLES - this.activeCount);\n if (count <= 0) return;\n this.ensureCapacity(this.activeCount + count);\n\n const data = this.data;\n const originX = options.origin.x * canvasWidth;\n const originY = options.origin.y * canvasHeight;\n const angleRad = degToRad(options.angle);\n const spreadRad = degToRad(options.spread);\n\n for (let i = 0; i < count; i++) {\n const idx = (this.activeCount + i) * ParticleIndex.SIZE;\n\n // Random angle within spread\n const particleAngle = angleRad + randomRange(-spreadRad / 2, spreadRad / 2);\n // Random velocity variation\n const velocity = options.startVelocity * randomRange(0.5, 1);\n\n // Position\n data[idx + ParticleIndex.X] = originX;\n data[idx + ParticleIndex.Y] = originY;\n\n // Velocity (negative Y because canvas Y is inverted)\n data[idx + ParticleIndex.VelocityX] = Math.cos(particleAngle) * velocity;\n data[idx + ParticleIndex.VelocityY] = -Math.sin(particleAngle) * velocity;\n\n // Rotation\n data[idx + ParticleIndex.Rotation] = randomRange(0, Math.PI * 2);\n data[idx + ParticleIndex.RotationSpeed] = randomRange(-0.1, 0.1);\n\n // Tilt (for wobble effect)\n data[idx + ParticleIndex.Tilt] = randomRange(0, Math.PI * 2);\n data[idx + ParticleIndex.TiltSpeed] = randomRange(0.05, 0.15);\n\n data[idx + ParticleIndex.Color] = this.colorId(randomItem(options.colors));\n data[idx + ParticleIndex.Shape] = shapeToIndex(randomItem(options.shapes));\n\n // Scalar (size)\n data[idx + ParticleIndex.Scalar] = options.scalar * randomRange(0.8, 1.2);\n\n // Life\n data[idx + ParticleIndex.Life] = options.ticks;\n data[idx + ParticleIndex.MaxLife] = options.ticks;\n\n // Physics are stored per particle so each burst keeps its own settings\n data[idx + ParticleIndex.Drift] = options.drift + randomRange(-0.5, 0.5);\n data[idx + ParticleIndex.Gravity] = options.gravity;\n data[idx + ParticleIndex.Decay] = options.decay;\n }\n\n this.activeCount += count;\n }\n\n /**\n * Remove dead particles, keeping live ones packed at the front\n */\n compact(): void {\n const data = this.data;\n let writeIdx = 0;\n\n for (let readIdx = 0; readIdx < this.activeCount; readIdx++) {\n const srcIdx = readIdx * ParticleIndex.SIZE;\n if (data[srcIdx + ParticleIndex.Life] <= 0) continue;\n\n if (writeIdx !== readIdx) {\n const dstIdx = writeIdx * ParticleIndex.SIZE;\n data.copyWithin(dstIdx, srcIdx, srcIdx + ParticleIndex.SIZE);\n }\n writeIdx++;\n }\n\n this.activeCount = writeIdx;\n if (writeIdx === 0) {\n this.clearPalette();\n } else if (this.palette.length > MAX_PALETTE) {\n this.prunePalette();\n }\n }\n\n /**\n * Keep only colors that live particles still use, renumbering them, so a long\n * stream with random colors does not grow the palette forever\n */\n private prunePalette(): void {\n const data = this.data;\n const oldPalette = [...this.palette];\n const remap = new Map<number, number>();\n this.clearPalette();\n\n for (let i = 0; i < this.activeCount; i++) {\n const idx = i * ParticleIndex.SIZE + ParticleIndex.Color;\n const oldId = data[idx];\n let newId = remap.get(oldId);\n if (newId === undefined) {\n newId = this.colorId(oldPalette[oldId]);\n remap.set(oldId, newId);\n }\n data[idx] = newId;\n }\n }\n\n private colorId(color: string): number {\n let id = this.colorIds.get(color);\n if (id === undefined) {\n id = this.palette.length;\n this.palette.push(color);\n this.colorIds.set(color, id);\n }\n return id;\n }\n\n private clearPalette(): void {\n this.palette.length = 0;\n this.colorIds.clear();\n }\n\n private ensureCapacity(needed: number): void {\n if (needed <= this.capacity) return;\n let capacity = this.capacity;\n while (capacity < needed) capacity *= 2;\n const grown = new Float32Array(Math.min(capacity, MAX_PARTICLES) * ParticleIndex.SIZE);\n grown.set(this.data.subarray(0, this.activeCount * ParticleIndex.SIZE));\n this.data = grown;\n }\n}\n","import type { ParticlePool } from './particle';\nimport { ParticleIndex } from './types';\n\n/**\n * Advance every particle by `dt`, measured in 60 fps frames (1 = 16.7 ms), so\n * motion and lifetime look the same at any refresh rate.\n * Returns true if there are still active particles.\n */\nexport function updateParticles(pool: ParticlePool, dt: number): boolean {\n const data = pool.data;\n\n for (let i = 0; i < pool.activeCount; i++) {\n const idx = i * ParticleIndex.SIZE;\n\n let vx = data[idx + ParticleIndex.VelocityX];\n let vy = data[idx + ParticleIndex.VelocityY];\n const tilt = data[idx + ParticleIndex.Tilt];\n\n // Gravity, then horizontal wobble based on tilt\n vy += data[idx + ParticleIndex.Gravity] * dt;\n vx += data[idx + ParticleIndex.Drift] * Math.sin(tilt) * dt;\n\n // Air resistance: decay is the share of speed kept per 60 fps frame\n const damping = data[idx + ParticleIndex.Decay] ** dt;\n vx *= damping;\n vy *= damping;\n\n data[idx + ParticleIndex.VelocityX] = vx;\n data[idx + ParticleIndex.VelocityY] = vy;\n data[idx + ParticleIndex.X] += vx * dt;\n data[idx + ParticleIndex.Y] += vy * dt;\n data[idx + ParticleIndex.Rotation] += data[idx + ParticleIndex.RotationSpeed] * dt;\n data[idx + ParticleIndex.Tilt] = tilt + data[idx + ParticleIndex.TiltSpeed] * dt;\n data[idx + ParticleIndex.Life] -= dt;\n }\n\n // Remove dead particles\n pool.compact();\n\n return pool.activeCount > 0;\n}\n","import type { KonfettiOptions, PresetName } from './types';\n\n/**\n * One burst of a preset, fired `delay` ms after the preset starts\n */\ninterface PresetBurst {\n delay?: number;\n options: KonfettiOptions;\n}\n\ninterface PresetDefinition {\n bursts: readonly PresetBurst[];\n /**\n * Whether the preset is a single burst that can be moved to a caller's origin\n * (for example an element). Screen-wide presets keep their own positions.\n */\n followsOrigin: boolean;\n}\n\nconst FIREWORK_COLORS = ['#ff0000', '#ffff00', '#00ff00', '#00ffff', '#ff00ff'];\nconst FIREWORK: KonfettiOptions = {\n particleCount: 80,\n angle: 90,\n spread: 360,\n startVelocity: 35,\n decay: 0.91,\n gravity: 1,\n colors: FIREWORK_COLORS,\n};\n\nconst PRIDE_COLORS = [\n '#e40303', // red\n '#ff8c00', // orange\n '#ffed00', // yellow\n '#008026', // green\n '#004dff', // blue\n '#750787', // purple\n];\n\n/**\n * Built-in preset effects\n */\nexport const PRESETS: Readonly<Record<PresetName, PresetDefinition>> = {\n // Burst of confetti from bottom center shooting up\n cannon: {\n followsOrigin: true,\n bursts: [\n {\n options: {\n particleCount: 100,\n angle: 90,\n spread: 70,\n startVelocity: 50,\n decay: 0.91,\n gravity: 1,\n origin: { x: 0.5, y: 1 },\n },\n },\n ],\n },\n // 360 degree burst from center\n explosion: {\n followsOrigin: true,\n bursts: [\n {\n options: {\n particleCount: 150,\n angle: 90,\n spread: 360,\n startVelocity: 40,\n decay: 0.92,\n gravity: 0.8,\n origin: { x: 0.5, y: 0.5 },\n },\n },\n ],\n },\n // Three bursts across the top half\n fireworks: {\n followsOrigin: false,\n bursts: [\n { delay: 0, options: { ...FIREWORK, origin: { x: 0.3, y: 0.4 } } },\n { delay: 150, options: { ...FIREWORK, origin: { x: 0.5, y: 0.3 } } },\n { delay: 300, options: { ...FIREWORK, origin: { x: 0.7, y: 0.4 } } },\n ],\n },\n // Particles falling from the top\n rain: {\n followsOrigin: false,\n bursts: [\n {\n options: {\n particleCount: 50,\n angle: 270,\n spread: 60,\n startVelocity: 10,\n decay: 0.95,\n gravity: 0.5,\n drift: 0,\n origin: { x: 0.5, y: 0 },\n ticks: 300,\n },\n },\n ],\n },\n // Gentle falling white flakes\n snow: {\n followsOrigin: false,\n bursts: [\n {\n options: {\n particleCount: 30,\n angle: 270,\n spread: 120,\n startVelocity: 5,\n decay: 0.98,\n gravity: 0.3,\n drift: 1,\n origin: { x: 0.5, y: -0.1 },\n ticks: 400,\n colors: ['#ffffff', '#e0e0e0', '#c0c0c0'],\n shapes: ['circle'],\n },\n },\n ],\n },\n // Bursts from both sides\n sideCannons: {\n followsOrigin: false,\n bursts: [\n {\n options: {\n particleCount: 50,\n angle: 60,\n spread: 55,\n startVelocity: 50,\n origin: { x: 0, y: 0.7 },\n },\n },\n {\n options: {\n particleCount: 50,\n angle: 120,\n spread: 55,\n startVelocity: 50,\n origin: { x: 1, y: 0.7 },\n },\n },\n ],\n },\n // Rainbow colors\n pride: {\n followsOrigin: true,\n bursts: [\n {\n options: {\n particleCount: 100,\n spread: 70,\n origin: { x: 0.5, y: 0.6 },\n colors: PRIDE_COLORS,\n },\n },\n ],\n },\n};\n\n/**\n * Defaults for continuous(): a small burst from the bottom every interval\n */\nexport const CONTINUOUS_DEFAULTS: KonfettiOptions = {\n particleCount: 10,\n angle: 90,\n spread: 55,\n startVelocity: 45,\n origin: { x: 0.5, y: 1 },\n};\n\n/**\n * Names of all built-in presets\n */\nexport const PRESET_NAMES = Object.keys(PRESETS) as readonly PresetName[];\n\n/**\n * Whether a value names a built-in preset (useful for attribute or prop values)\n */\nexport function isPresetName(value: unknown): value is PresetName {\n return typeof value === 'string' && (PRESET_NAMES as readonly string[]).includes(value);\n}\n","import type { ParticlePool } from './particle';\nimport { getShapeRenderer } from './shapes';\nimport { ParticleIndex } from './types';\n\n/** Base particle size in CSS pixels */\nconst BASE_SIZE = 10;\n\n/**\n * Create a full-screen overlay canvas that never blocks the page\n */\nfunction createOverlayCanvas(): HTMLCanvasElement {\n const canvas = document.createElement('canvas');\n canvas.className = 'konfetti-canvas';\n canvas.setAttribute('aria-hidden', 'true');\n Object.assign(canvas.style, {\n position: 'fixed',\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n zIndex: '100',\n });\n document.body.appendChild(canvas);\n return canvas;\n}\n\n/**\n * Canvas renderer for particles\n */\nexport class Renderer {\n private readonly canvas: HTMLCanvasElement;\n private readonly ctx: CanvasRenderingContext2D | null;\n /** True when we created the canvas, so we may style and remove it */\n private readonly ownsCanvas: boolean;\n /** Size in CSS pixels; the backing store is this times the pixel ratio */\n private width = 0;\n private height = 0;\n private pixelRatio = 1;\n /** Particle indices grouped by palette color, reused between frames */\n private readonly buckets: number[][] = [];\n\n constructor(canvas?: HTMLCanvasElement) {\n this.ownsCanvas = !canvas;\n this.canvas = canvas ?? createOverlayCanvas();\n this.ctx = this.canvas.getContext('2d');\n this.resize();\n }\n\n /**\n * Match the canvas to its display size. The full-screen canvas also renders at\n * the screen's pixel density; a canvas you pass in keeps one pixel per CSS\n * pixel, because without a CSS size its display size follows its pixel size\n * and would grow on every resize.\n */\n resize(): void {\n if (this.ownsCanvas) {\n this.width = window.innerWidth;\n this.height = window.innerHeight;\n this.pixelRatio = window.devicePixelRatio || 1;\n } else {\n const rect = this.canvas.getBoundingClientRect();\n this.width = rect.width;\n this.height = rect.height;\n this.pixelRatio = 1;\n }\n this.canvas.width = Math.round(this.width * this.pixelRatio);\n this.canvas.height = Math.round(this.height * this.pixelRatio);\n }\n\n /**\n * Canvas size in CSS pixels\n */\n getDimensions(): { width: number; height: number } {\n return { width: this.width, height: this.height };\n }\n\n /**\n * Set the stacking order; only applies to the full-screen canvas we own\n */\n setZIndex(zIndex: number): void {\n if (this.ownsCanvas) this.canvas.style.zIndex = String(zIndex);\n }\n\n /**\n * Clear the canvas\n */\n clear(): void {\n if (!this.ctx) return;\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n\n /**\n * Draw all particles, batched by color to limit fillStyle changes\n */\n render(pool: ParticlePool): void {\n this.clear();\n const ctx = this.ctx;\n if (!ctx) return;\n\n const data = pool.data;\n const ratio = this.pixelRatio;\n const buckets = this.buckets;\n\n for (const bucket of buckets) bucket.length = 0;\n for (let i = 0; i < pool.activeCount; i++) {\n const colorId = data[i * ParticleIndex.SIZE + ParticleIndex.Color];\n if (!buckets[colorId]) buckets[colorId] = [];\n buckets[colorId].push(i);\n }\n\n for (let colorId = 0; colorId < buckets.length; colorId++) {\n const bucket = buckets[colorId];\n if (!bucket || bucket.length === 0) continue;\n ctx.fillStyle = pool.palette[colorId];\n\n for (const particle of bucket) {\n const idx = particle * ParticleIndex.SIZE;\n const tilt = data[idx + ParticleIndex.Tilt];\n const rotation = data[idx + ParticleIndex.Rotation];\n\n // Fade out over the last half of the particle's life\n const opacity = Math.min(\n 1,\n (data[idx + ParticleIndex.Life] / data[idx + ParticleIndex.MaxLife]) * 2\n );\n const size = BASE_SIZE * data[idx + ParticleIndex.Scalar] * (0.8 + 0.2 * Math.cos(tilt));\n if (size < 0.5 || opacity < 0.01) continue;\n\n // translate(x, y) · rotate(rotation) · scale(1, squash), scaled to device pixels.\n // Setting the matrix directly avoids a save()/restore() per particle.\n const cos = Math.cos(rotation);\n const sin = Math.sin(rotation);\n const squash = 0.6 + 0.4 * Math.abs(Math.cos(tilt));\n ctx.globalAlpha = opacity;\n ctx.setTransform(\n ratio * cos,\n ratio * sin,\n -ratio * sin * squash,\n ratio * cos * squash,\n ratio * data[idx + ParticleIndex.X],\n ratio * data[idx + ParticleIndex.Y]\n );\n getShapeRenderer(data[idx + ParticleIndex.Shape])(ctx, size);\n }\n }\n\n ctx.globalAlpha = 1;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n }\n\n /**\n * Destroy renderer and remove the canvas if we created it\n */\n destroy(): void {\n this.clear();\n if (this.ownsCanvas) this.canvas.remove();\n }\n}\n","import { ParticlePool } from './particle';\nimport { updateParticles } from './physics';\nimport { CONTINUOUS_DEFAULTS, isPresetName, PRESETS } from './presets';\nimport { Renderer } from './renderer';\nimport type { CreateOptions, KonfettiOptions, PresetName } from './types';\nimport { clamp, isBrowser, mergeOptions, prefersReducedMotion, resolveOptions } from './utils';\n\n/** Length of one 60 fps frame; physics are tuned in these units */\nconst FRAME_MS = 1000 / 60;\n/** Largest step per frame, so a long stall does not teleport particles */\nconst MAX_STEP = 4;\n\n/**\n * Manages one canvas: the animation loop, particles, physics and rendering.\n * Safe to construct on the server, where every method does nothing.\n */\nexport class Konfetti {\n private readonly pool = new ParticlePool();\n private readonly renderer: Renderer | null = null;\n private frameId: number | null = null;\n /** Timestamp of the previous frame, or when the loop was scheduled */\n private lastTime = 0;\n private paused = false;\n private destroyed = false;\n private readonly resizeWithWindow: boolean = false;\n private readonly timeouts = new Set<ReturnType<typeof setTimeout>>();\n private readonly intervals = new Set<ReturnType<typeof setInterval>>();\n\n constructor(canvas?: HTMLCanvasElement, createOptions: CreateOptions = {}) {\n if (!isBrowser()) {\n this.destroyed = true;\n return;\n }\n\n this.renderer = new Renderer(canvas);\n this.resizeWithWindow = createOptions.resize !== false;\n if (this.resizeWithWindow) window.addEventListener('resize', this.handleResize);\n document.addEventListener('visibilitychange', this.handleVisibilityChange);\n }\n\n /**\n * Fire one burst. Skipped while the page is hidden, after destroy(), and for\n * visitors who prefer reduced motion (unless disableForReducedMotion is false).\n */\n fire(options?: KonfettiOptions): void {\n if (this.destroyed || !this.renderer || document.hidden) return;\n\n const resolved = resolveOptions(options);\n if (resolved.disableForReducedMotion && prefersReducedMotion()) return;\n\n this.renderer.setZIndex(resolved.zIndex);\n const { width, height } = this.renderer.getDimensions();\n this.pool.spawn(resolved, width, height);\n this.scheduleFrame();\n }\n\n /**\n * Fire a built-in preset; options override the preset's own values\n */\n preset(name: PresetName, options?: KonfettiOptions): void {\n if (!isPresetName(name) || this.destroyed) return;\n\n for (const burst of PRESETS[name].bursts) {\n const merged = mergeOptions(burst.options, options);\n if (burst.delay) {\n const id = setTimeout(() => {\n this.timeouts.delete(id);\n this.fire(merged);\n }, burst.delay);\n this.timeouts.add(id);\n } else {\n this.fire(merged);\n }\n }\n }\n\n /**\n * Fire a small burst every `interval` ms until the returned function is\n * called, or until reset() or destroy()\n */\n continuous(options?: KonfettiOptions, interval = 250): () => void {\n if (this.destroyed) return () => {};\n\n const merged = mergeOptions(CONTINUOUS_DEFAULTS, options);\n const delay = Number.isFinite(interval) && interval >= 16 ? interval : 250;\n const id = setInterval(() => this.fire(merged), delay);\n this.intervals.add(id);\n\n return () => {\n clearInterval(id);\n this.intervals.delete(id);\n };\n }\n\n /**\n * Pause the animation; particles stay where they are\n */\n pause(): void {\n this.paused = true;\n this.cancelFrame();\n }\n\n /**\n * Resume after pause()\n */\n resume(): void {\n this.paused = false;\n this.scheduleFrame();\n }\n\n /**\n * Clear all particles, cancel scheduled bursts and streams, stop animating and\n * undo pause()\n */\n reset(): void {\n this.paused = false;\n this.cancelFrame();\n for (const id of this.timeouts) clearTimeout(id);\n for (const id of this.intervals) clearInterval(id);\n this.timeouts.clear();\n this.intervals.clear();\n this.pool.reset();\n this.renderer?.clear();\n }\n\n /**\n * Reset, remove listeners and remove the canvas if this instance created it.\n * The instance ignores every call afterwards.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.reset();\n this.destroyed = true;\n\n if (this.resizeWithWindow) window.removeEventListener('resize', this.handleResize);\n document.removeEventListener('visibilitychange', this.handleVisibilityChange);\n this.renderer?.destroy();\n }\n\n private readonly handleResize = (): void => {\n this.renderer?.resize();\n };\n\n private readonly handleVisibilityChange = (): void => {\n if (document.hidden) {\n this.cancelFrame();\n } else {\n this.scheduleFrame();\n }\n };\n\n /**\n * Start the loop if there is something to animate and nothing prevents it\n */\n private scheduleFrame(): void {\n if (\n this.frameId !== null ||\n this.paused ||\n this.destroyed ||\n document.hidden ||\n this.pool.activeCount === 0\n ) {\n return;\n }\n this.lastTime = performance.now();\n this.frameId = requestAnimationFrame(this.tick);\n }\n\n private cancelFrame(): void {\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n }\n\n private readonly tick = (time: number): void => {\n this.frameId = null;\n if (!this.renderer) return;\n\n const dt = clamp((time - this.lastTime) / FRAME_MS, 0, MAX_STEP);\n this.lastTime = time;\n\n const hasParticles = updateParticles(this.pool, dt);\n this.renderer.render(this.pool);\n\n if (hasParticles) {\n this.frameId = requestAnimationFrame(this.tick);\n }\n };\n}\n","import { Konfetti } from './konfetti';\nimport { isPresetName, PRESETS } from './presets';\nimport type {\n CreateOptions,\n FireFromElementOptions,\n KonfettiOptions,\n Origin,\n PresetName,\n} from './types';\nimport { isBrowser, mergeOrigin } from './utils';\n\n/**\n * Fire function bound to a canvas, with preset, reset and destroy methods\n */\nexport interface KonfettiInstance {\n (options?: KonfettiOptions): void;\n /** Fire a built-in preset into this canvas */\n preset: (name: PresetName, options?: KonfettiOptions) => void;\n /** Fire a stream into this canvas; returns a function that stops it */\n continuous: (options?: KonfettiOptions, interval?: number) => () => void;\n /** Clear the canvas and cancel scheduled bursts */\n reset: () => void;\n /** Stop for good and release listeners */\n destroy: () => void;\n}\n\n// Global instance for the simple API, created on first use\nlet globalInstance: Konfetti | null = null;\n\nfunction getGlobalInstance(): Konfetti | null {\n if (!isBrowser()) return null;\n globalInstance ??= new Konfetti();\n return globalInstance;\n}\n\n/**\n * Fire konfetti on the full-screen canvas\n */\nexport function fire(options?: KonfettiOptions): void {\n getGlobalInstance()?.fire(options);\n}\n\n/**\n * Fire a built-in preset on the full-screen canvas\n */\nexport function firePreset(name: PresetName, options?: KonfettiOptions): void {\n getGlobalInstance()?.preset(name, options);\n}\n\n/**\n * The center of an element, as an origin relative to the viewport\n */\nexport function originFromElement(element: Element): Origin {\n const rect = element.getBoundingClientRect();\n return {\n x: (rect.left + rect.width / 2) / window.innerWidth,\n y: (rect.top + rect.height / 2) / window.innerHeight,\n };\n}\n\n/**\n * Fire from the center of an element, for example the button that was clicked.\n * Single-burst presets (cannon, explosion, pride) start at the element too;\n * screen-wide presets (fireworks, rain, snow, sideCannons) keep their positions.\n * An origin you pass yourself wins, axis by axis.\n */\nexport function fireFromElement(element: Element, options: FireFromElementOptions = {}): void {\n if (!isBrowser()) return;\n\n const { preset: name, ...rest } = options;\n // An unknown name (for example a typo in plain JavaScript) fires a plain burst\n const preset = isPresetName(name) ? name : undefined;\n const followsOrigin = preset ? PRESETS[preset].followsOrigin : true;\n const merged = followsOrigin\n ? { ...rest, origin: mergeOrigin(originFromElement(element), rest.origin) }\n : rest;\n\n if (preset) {\n firePreset(preset, merged);\n } else {\n fire(merged);\n }\n}\n\n/**\n * Clear the full-screen canvas and cancel scheduled bursts and streams\n */\nexport function reset(): void {\n globalInstance?.reset();\n}\n\n/**\n * Remove the full-screen canvas and its listeners; the next fire() creates a new one\n */\nexport function destroy(): void {\n globalInstance?.destroy();\n globalInstance = null;\n}\n\n/**\n * Create a konfetti instance that draws into your own canvas\n */\nexport function create(canvas: HTMLCanvasElement, createOptions?: CreateOptions): KonfettiInstance {\n const instance = new Konfetti(canvas, createOptions);\n\n const fireFn = ((options?: KonfettiOptions) => instance.fire(options)) as KonfettiInstance;\n fireFn.preset = (name, options) => instance.preset(name, options);\n fireFn.continuous = (options, interval) => instance.continuous(options, interval);\n fireFn.reset = () => instance.reset();\n fireFn.destroy = () => instance.destroy();\n\n return fireFn;\n}\n\n/**\n * Fire a steady stream on the full-screen canvas. Returns a function that stops it.\n */\nexport function continuous(options?: KonfettiOptions, interval?: number): () => void {\n return getGlobalInstance()?.continuous(options, interval) ?? (() => {});\n}\n\n/** Burst of confetti from bottom center shooting up */\nexport const cannon = (options?: KonfettiOptions): void => firePreset('cannon', options);\n\n/** 360 degree burst from center */\nexport const explosion = (options?: KonfettiOptions): void => firePreset('explosion', options);\n\n/** Three quick bursts across the top half */\nexport const fireworks = (options?: KonfettiOptions): void => firePreset('fireworks', options);\n\n/** Particles falling from the top */\nexport const rain = (options?: KonfettiOptions): void => firePreset('rain', options);\n\n/** Gentle falling white flakes */\nexport const snow = (options?: KonfettiOptions): void => firePreset('snow', options);\n\n/** Bursts from both sides */\nexport const sideCannons = (options?: KonfettiOptions): void => firePreset('sideCannons', options);\n\n/** Rainbow colors */\nexport const pride = (options?: KonfettiOptions): void => firePreset('pride', options);\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/shapes.ts","../src/utils.ts","../src/particle.ts","../src/orientation.ts","../src/physics.ts","../src/presets.ts","../src/renderer.ts","../src/konfetti.ts","../src/global.ts"],"sourcesContent":["import type { ShapeType } from './types';\n\n/**\n * Shape rendering functions\n * Each shape function draws centered at (0, 0) with the given size\n */\nexport type ShapeRenderer = (ctx: CanvasRenderingContext2D, size: number) => void;\n\n/**\n * Draw a circle\n */\nfunction drawCircle(ctx: CanvasRenderingContext2D, size: number): void {\n ctx.beginPath();\n ctx.arc(0, 0, size / 2, 0, Math.PI * 2);\n ctx.fill();\n}\n\n/**\n * Draw a square\n */\nfunction drawSquare(ctx: CanvasRenderingContext2D, size: number): void {\n const halfSize = size / 2;\n ctx.fillRect(-halfSize, -halfSize, size, size);\n}\n\n/**\n * Supported shapes; a particle stores its shape as an index into this list\n */\nconst SHAPES: readonly ShapeType[] = ['circle', 'square'];\n\nconst RENDERERS: readonly ShapeRenderer[] = [drawCircle, drawSquare];\n\n/**\n * Whether a value is a supported shape name\n */\nexport function isShape(value: unknown): value is ShapeType {\n return SHAPES.includes(value as ShapeType);\n}\n\n/**\n * Shape index for Float32Array storage\n */\nexport function shapeToIndex(shape: ShapeType): number {\n return Math.max(0, SHAPES.indexOf(shape));\n}\n\n/**\n * Get the renderer for a stored shape index\n */\nexport function getShapeRenderer(index: number): ShapeRenderer {\n return RENDERERS[index] ?? drawCircle;\n}\n","import { isShape } from './shapes';\nimport type { KonfettiOptions, Origin, ResolvedOptions, ShapeType } from './types';\n\n/**\n * Default festive colors\n */\nexport const DEFAULT_COLORS = [\n '#26ccff', // cyan\n '#a25afd', // purple\n '#ff5e7e', // pink\n '#88ff5a', // green\n '#fcff42', // yellow\n '#ffa62d', // orange\n '#ff36ff', // magenta\n];\n\n/**\n * Default options\n */\nexport const DEFAULT_OPTIONS: ResolvedOptions = {\n particleCount: 50,\n angle: 90,\n spread: 45,\n startVelocity: 45,\n decay: 0.9,\n gravity: 1,\n drift: 0,\n ticks: 600,\n origin: { x: 0.5, y: 0.5 },\n colors: DEFAULT_COLORS,\n shapes: ['circle', 'square'] as ShapeType[],\n scalar: 1,\n zIndex: 100,\n disableForReducedMotion: true,\n};\n\n/**\n * Use `value` when it is a finite number, otherwise `fallback`\n */\nfunction finite(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\n/**\n * Merge user options with defaults, replacing missing or invalid values\n */\nexport function resolveOptions(options: KonfettiOptions = {}): ResolvedOptions {\n const d = DEFAULT_OPTIONS;\n const colors = Array.isArray(options.colors)\n ? options.colors.filter((c) => typeof c === 'string' && c.length > 0)\n : [];\n const shapes = Array.isArray(options.shapes) ? options.shapes.filter(isShape) : [];\n\n return {\n particleCount: Math.max(0, Math.round(finite(options.particleCount, d.particleCount))),\n angle: finite(options.angle, d.angle),\n spread: finite(options.spread, d.spread),\n startVelocity: finite(options.startVelocity, d.startVelocity),\n decay: clamp(finite(options.decay, d.decay), 0, 1),\n gravity: finite(options.gravity, d.gravity),\n drift: finite(options.drift, d.drift),\n ticks: Math.max(1, finite(options.ticks, d.ticks)),\n origin: {\n x: finite(options.origin?.x, d.origin.x),\n y: finite(options.origin?.y, d.origin.y),\n },\n colors: colors.length > 0 ? colors : [...d.colors],\n shapes: shapes.length > 0 ? shapes : [...d.shapes],\n scalar: Math.max(0, finite(options.scalar, d.scalar)),\n zIndex: finite(options.zIndex, d.zIndex),\n disableForReducedMotion: options.disableForReducedMotion ?? d.disableForReducedMotion,\n };\n}\n\n/**\n * Layer `override` on top of `base`, skipping keys that are explicitly undefined\n * so a wrapper passing `{ colors: undefined }` keeps the preset's colors\n */\nexport function mergeOptions(base: KonfettiOptions, override?: KonfettiOptions): KonfettiOptions {\n const merged: Record<string, unknown> = { ...base };\n if (override) {\n for (const [key, value] of Object.entries(override)) {\n if (value !== undefined) merged[key] = value;\n }\n // Origins merge per axis, so { x: 0.2 } keeps the base's y\n if (override.origin) merged.origin = mergeOrigin(base.origin, override.origin);\n }\n return merged as KonfettiOptions;\n}\n\n/**\n * Layer the defined axes of `override` on top of `base`\n */\nexport function mergeOrigin(\n base: Partial<Origin> | undefined,\n override: Partial<Origin> | undefined\n): Partial<Origin> {\n return {\n ...base,\n ...(override?.x !== undefined && { x: override.x }),\n ...(override?.y !== undefined && { y: override.y }),\n };\n}\n\n/**\n * Convert degrees to radians\n */\nexport function degToRad(deg: number): number {\n return deg * (Math.PI / 180);\n}\n\n/**\n * Get random number between min and max\n */\nexport function randomRange(min: number, max: number): number {\n return Math.random() * (max - min) + min;\n}\n\n/**\n * -1 or 1 at random\n */\nexport function randomSign(): number {\n return Math.random() < 0.5 ? -1 : 1;\n}\n\n/**\n * Get random item from array\n */\nexport function randomItem<T>(arr: readonly T[]): T {\n return arr[Math.floor(Math.random() * arr.length)];\n}\n\n/**\n * Whether we are running in a browser with a DOM\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if user prefers reduced motion\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false;\n const mediaQuery = window.matchMedia?.('(prefers-reduced-motion: reduce)');\n return mediaQuery?.matches ?? false;\n}\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n","import { shapeToIndex } from './shapes';\nimport { ParticleIndex, type ResolvedOptions } from './types';\nimport { degToRad, randomItem, randomRange, randomSign } from './utils';\n\n/** Hard upper limit, so a runaway loop of fire() calls cannot eat memory */\nexport const MAX_PARTICLES = 10_000;\n\n/** Above this many colors, unused ones are dropped from the palette */\nconst MAX_PALETTE = 256;\n\n/**\n * Particle pool using Float32Array for performance\n * Each particle uses ParticleIndex.SIZE floats\n */\nexport class ParticlePool {\n /** Raw particle data */\n public data: Float32Array;\n /** Number of active particles */\n public activeCount = 0;\n /**\n * Colors in use; particles store an index into this list, so any CSS color\n * works without parsing it\n */\n public readonly palette: string[] = [];\n private readonly colorIds = new Map<string, number>();\n\n constructor(initialCapacity = 512) {\n this.data = new Float32Array(initialCapacity * ParticleIndex.SIZE);\n }\n\n /** How many particles fit before the buffer has to grow */\n get capacity(): number {\n return this.data.length / ParticleIndex.SIZE;\n }\n\n /**\n * Remove every particle\n */\n reset(): void {\n this.activeCount = 0;\n this.clearPalette();\n }\n\n /**\n * Spawn particles with the given options\n */\n spawn(options: ResolvedOptions, canvasWidth: number, canvasHeight: number): void {\n const count = Math.min(options.particleCount, MAX_PARTICLES - this.activeCount);\n if (count <= 0) return;\n this.ensureCapacity(this.activeCount + count);\n\n const data = this.data;\n const originX = options.origin.x * canvasWidth;\n const originY = options.origin.y * canvasHeight;\n const angleRad = degToRad(options.angle);\n const spreadRad = degToRad(options.spread);\n\n for (let i = 0; i < count; i++) {\n const idx = (this.activeCount + i) * ParticleIndex.SIZE;\n\n // Random angle within spread\n const particleAngle = angleRad + randomRange(-spreadRad / 2, spreadRad / 2);\n // Random velocity variation\n const velocity = options.startVelocity * randomRange(0.5, 1);\n\n // Position\n data[idx + ParticleIndex.X] = originX;\n data[idx + ParticleIndex.Y] = originY;\n\n // Velocity (negative Y because canvas Y is inverted)\n data[idx + ParticleIndex.VelocityX] = Math.cos(particleAngle) * velocity;\n data[idx + ParticleIndex.VelocityY] = -Math.sin(particleAngle) * velocity;\n\n // Tumble around all three axes: a fast flip (tilt), a slower wobble and a\n // gentle spin in the screen plane\n data[idx + ParticleIndex.Tilt] = randomRange(0, Math.PI * 2);\n data[idx + ParticleIndex.TiltSpeed] = randomRange(0.08, 0.22) * randomSign();\n data[idx + ParticleIndex.Wobble] = randomRange(0, Math.PI * 2);\n data[idx + ParticleIndex.WobbleSpeed] = randomRange(0.02, 0.07) * randomSign();\n data[idx + ParticleIndex.Rotation] = randomRange(0, Math.PI * 2);\n data[idx + ParticleIndex.RotationSpeed] = randomRange(-0.04, 0.04);\n\n data[idx + ParticleIndex.Color] = this.colorId(randomItem(options.colors));\n data[idx + ParticleIndex.Shape] = shapeToIndex(randomItem(options.shapes));\n\n // Scalar (size)\n data[idx + ParticleIndex.Scalar] = options.scalar * randomRange(0.8, 1.2);\n\n // Life\n data[idx + ParticleIndex.Life] = options.ticks;\n data[idx + ParticleIndex.MaxLife] = options.ticks;\n\n // Physics are stored per particle so each burst keeps its own settings.\n // Drift is the wind around this piece, a little different for each one.\n data[idx + ParticleIndex.Drift] = options.drift + randomRange(-0.5, 0.5);\n data[idx + ParticleIndex.Gravity] = options.gravity;\n data[idx + ParticleIndex.Decay] = options.decay;\n data[idx + ParticleIndex.AirPhase] = randomRange(0, Math.PI * 2);\n data[idx + ParticleIndex.AirPhaseSpeed] = randomRange(0.02, 0.05);\n }\n\n this.activeCount += count;\n }\n\n /**\n * Remove dead particles, keeping live ones packed at the front\n */\n compact(): void {\n const data = this.data;\n let writeIdx = 0;\n\n for (let readIdx = 0; readIdx < this.activeCount; readIdx++) {\n const srcIdx = readIdx * ParticleIndex.SIZE;\n if (data[srcIdx + ParticleIndex.Life] <= 0) continue;\n\n if (writeIdx !== readIdx) {\n const dstIdx = writeIdx * ParticleIndex.SIZE;\n data.copyWithin(dstIdx, srcIdx, srcIdx + ParticleIndex.SIZE);\n }\n writeIdx++;\n }\n\n this.activeCount = writeIdx;\n if (writeIdx === 0) {\n this.clearPalette();\n } else if (this.palette.length > MAX_PALETTE) {\n this.prunePalette();\n }\n }\n\n /**\n * Keep only colors that live particles still use, renumbering them, so a long\n * stream with random colors does not grow the palette forever\n */\n private prunePalette(): void {\n const data = this.data;\n const oldPalette = [...this.palette];\n const remap = new Map<number, number>();\n this.clearPalette();\n\n for (let i = 0; i < this.activeCount; i++) {\n const idx = i * ParticleIndex.SIZE + ParticleIndex.Color;\n const oldId = data[idx];\n let newId = remap.get(oldId);\n if (newId === undefined) {\n newId = this.colorId(oldPalette[oldId]);\n remap.set(oldId, newId);\n }\n data[idx] = newId;\n }\n }\n\n private colorId(color: string): number {\n let id = this.colorIds.get(color);\n if (id === undefined) {\n id = this.palette.length;\n this.palette.push(color);\n this.colorIds.set(color, id);\n }\n return id;\n }\n\n private clearPalette(): void {\n this.palette.length = 0;\n this.colorIds.clear();\n }\n\n private ensureCapacity(needed: number): void {\n if (needed <= this.capacity) return;\n let capacity = this.capacity;\n while (capacity < needed) capacity *= 2;\n const grown = new Float32Array(Math.min(capacity, MAX_PARTICLES) * ParticleIndex.SIZE);\n grown.set(this.data.subarray(0, this.activeCount * ParticleIndex.SIZE));\n this.data = grown;\n }\n}\n","import { ParticleIndex } from './types';\n\n/**\n * 3D orientation of a particle, as the columns of its rotation\n * matrix: where the piece's local x axis, local y axis and surface normal point.\n * Layout: [xAxis.x, xAxis.y, xAxis.z, yAxis.x, yAxis.y, yAxis.z, normal.x, normal.y, normal.z]\n */\nexport type Orientation = Float64Array;\n\n/** Light from the upper left, slightly in front (unit vector) */\nconst LIGHT_X = -0.3;\nconst LIGHT_Y = -0.6;\nconst LIGHT_Z = 0.742;\n\n/**\n * How much the side of the piece facing the viewer faces the light, 0-1.\n * Paper is lit on both sides, so the normal is flipped toward the viewer first.\n */\nexport function lightness(m: Orientation): number {\n const facing = m[8] < 0 ? -1 : 1;\n return Math.max(0, facing * (m[6] * LIGHT_X + m[7] * LIGHT_Y + m[8] * LIGHT_Z));\n}\n\nexport function createOrientation(): Orientation {\n return new Float64Array(9);\n}\n\n/**\n * Fill `out` with the particle's rotation: flip (Tilt) around its x axis, then\n * Wobble around its y axis, then Rotation in the screen plane\n */\nexport function orient(data: Float32Array, idx: number, out: Orientation): Orientation {\n const tilt = data[idx + ParticleIndex.Tilt];\n const wobble = data[idx + ParticleIndex.Wobble];\n const rotation = data[idx + ParticleIndex.Rotation];\n const cx = Math.cos(tilt);\n const sx = Math.sin(tilt);\n const cy = Math.cos(wobble);\n const sy = Math.sin(wobble);\n const cz = Math.cos(rotation);\n const sz = Math.sin(rotation);\n\n out[0] = cz * cy;\n out[1] = sz * cy;\n out[2] = -sy;\n out[3] = cz * sy * sx - sz * cx;\n out[4] = sz * sy * sx + cz * cx;\n out[5] = cy * sx;\n out[6] = cz * sy * cx + sz * sx;\n out[7] = sz * sy * cx - cz * sx;\n out[8] = cy * cx;\n return out;\n}\n","import { createOrientation, lightness, orient } from './orientation';\nimport type { ParticlePool } from './particle';\nimport { ParticleIndex } from './types';\n\n/** Paper is light: pieces feel this share of the gravity setting */\nconst PAPER_GRAVITY = 0.45;\n/** Air resistance on falling paper, which grows with the square of the speed */\nconst FALL_DRAG = 0.0475;\n/**\n * Above this falling speed (px per frame) the drag only grows linearly, so pieces\n * launched downward fly out like the rest of the burst instead of stopping dead\n */\nconst FLUTTER_SPEED = 4;\n/** How strongly a tilted piece glides sideways while falling (the falling-leaf sway) */\nconst GLIDE = 0.6;\n/** Speed of the slow side-to-side air movement, in px per 60 fps frame */\nconst AIR_SWAY = 1;\n/** How far past the edges a piece may go before it is removed, in CSS px */\nconst OFFSCREEN_MARGIN = 60;\n\nconst orientation = createOrientation();\n\n/**\n * Advance every particle by `dt`, measured in 60 fps frames (1 = 16.7 ms), so\n * motion and lifetime look the same at any refresh rate. `width` and `height`\n * are the canvas size, used to remove pieces that left the screen.\n * Returns true if there are still active particles.\n */\nexport function updateParticles(\n pool: ParticlePool,\n dt: number,\n width: number,\n height: number\n): boolean {\n const data = pool.data;\n\n for (let i = 0; i < pool.activeCount; i++) {\n updateParticle(data, i * ParticleIndex.SIZE, dt, width, height);\n }\n\n // Remove dead particles\n pool.compact();\n\n return pool.activeCount > 0;\n}\n\n/**\n * Paper in air: the launch slows quickly, then the piece settles into a slow,\n * swaying descent whose speed depends on how it is turned, and it tumbles\n * faster the faster it moves\n */\nfunction updateParticle(\n data: Float32Array,\n idx: number,\n dt: number,\n width: number,\n height: number\n): void {\n let vx = data[idx + ParticleIndex.VelocityX];\n let vy = data[idx + ParticleIndex.VelocityY];\n\n // Orientation is computed once per frame: physics uses the normal, and the\n // renderer reads the projected axes and light stored here\n const m = orient(data, idx, orientation);\n const nx = m[6];\n const ny = m[7];\n data[idx + ParticleIndex.AxisXX] = m[0];\n data[idx + ParticleIndex.AxisXY] = m[1];\n data[idx + ParticleIndex.AxisYX] = m[3];\n data[idx + ParticleIndex.AxisYY] = m[4];\n data[idx + ParticleIndex.Light] = lightness(m);\n\n vy += data[idx + ParticleIndex.Gravity] * PAPER_GRAVITY * dt;\n\n if (vy > 0) {\n // Falling flat (normal pointing up or down) catches the most air\n const drag = FALL_DRAG * (0.35 + 0.65 * Math.abs(ny));\n vy = Math.max(0, vy - drag * vy * Math.min(vy, FLUTTER_SPEED) * dt);\n // Air pushes along the normal, so a tilted piece glides toward its lower\n // edge; the direction flips as it tumbles\n vx -= GLIDE * vy * 2 * nx * ny * dt;\n }\n\n // The air itself moves: steady wind (drift) plus a slow sway. Decay pulls the\n // piece toward the air's speed rather than toward standing still.\n const phase = data[idx + ParticleIndex.AirPhase];\n const airX = data[idx + ParticleIndex.Drift] + AIR_SWAY * Math.sin(phase);\n const damping = data[idx + ParticleIndex.Decay] ** dt;\n vx = airX + (vx - airX) * damping;\n vy *= damping;\n\n // Autorotation: fast-moving paper flips faster\n const spin = 0.6 + Math.min(1.4, Math.hypot(vx, vy) / 3);\n\n data[idx + ParticleIndex.VelocityX] = vx;\n data[idx + ParticleIndex.VelocityY] = vy;\n data[idx + ParticleIndex.X] += vx * dt;\n data[idx + ParticleIndex.Y] += vy * dt;\n data[idx + ParticleIndex.Tilt] += data[idx + ParticleIndex.TiltSpeed] * spin * dt;\n data[idx + ParticleIndex.Wobble] += data[idx + ParticleIndex.WobbleSpeed] * dt;\n data[idx + ParticleIndex.Rotation] += data[idx + ParticleIndex.RotationSpeed] * dt;\n data[idx + ParticleIndex.AirPhase] = phase + data[idx + ParticleIndex.AirPhaseSpeed] * dt;\n data[idx + ParticleIndex.Life] -= dt;\n\n // Gone once it is out of view and moving away. Pieces may start beyond an edge\n // (snow begins above the screen) and are kept until they head out. Without a\n // canvas size yet (a hidden custom canvas), nothing is removed.\n if (width > 0 && height > 0) {\n const x = data[idx + ParticleIndex.X];\n const y = data[idx + ParticleIndex.Y];\n const fellOut = y > height + OFFSCREEN_MARGIN && vy >= 0;\n const leftOut = x < -OFFSCREEN_MARGIN * 2 && vx <= 0;\n const rightOut = x > width + OFFSCREEN_MARGIN * 2 && vx >= 0;\n // Without gravity pulling down, a piece above the screen never comes back\n const floatedOut = y < -OFFSCREEN_MARGIN && vy <= 0 && data[idx + ParticleIndex.Gravity] <= 0;\n if (fellOut || leftOut || rightOut || floatedOut) {\n data[idx + ParticleIndex.Life] = 0;\n }\n }\n}\n","import type { KonfettiOptions, PresetName } from './types';\n\n/**\n * One burst of a preset, fired `delay` ms after the preset starts\n */\ninterface PresetBurst {\n delay?: number;\n options: KonfettiOptions;\n}\n\ninterface PresetDefinition {\n bursts: readonly PresetBurst[];\n /**\n * Whether the preset is a single burst that can be moved to a caller's origin\n * (for example an element). Screen-wide presets keep their own positions.\n */\n followsOrigin: boolean;\n}\n\nconst FIREWORK_COLORS = ['#ff0000', '#ffff00', '#00ff00', '#00ffff', '#ff00ff'];\nconst FIREWORK: KonfettiOptions = {\n particleCount: 80,\n angle: 90,\n spread: 360,\n startVelocity: 35,\n decay: 0.91,\n gravity: 1,\n colors: FIREWORK_COLORS,\n};\n\nconst PRIDE_COLORS = [\n '#e40303', // red\n '#ff8c00', // orange\n '#ffed00', // yellow\n '#008026', // green\n '#004dff', // blue\n '#750787', // purple\n];\n\n/**\n * Built-in preset effects\n */\nexport const PRESETS: Readonly<Record<PresetName, PresetDefinition>> = {\n // Burst of confetti from bottom center shooting up\n cannon: {\n followsOrigin: true,\n bursts: [\n {\n options: {\n particleCount: 100,\n angle: 90,\n spread: 70,\n startVelocity: 50,\n decay: 0.91,\n gravity: 1,\n origin: { x: 0.5, y: 1 },\n },\n },\n ],\n },\n // 360 degree burst from center\n explosion: {\n followsOrigin: true,\n bursts: [\n {\n options: {\n particleCount: 150,\n angle: 90,\n spread: 360,\n startVelocity: 40,\n decay: 0.92,\n gravity: 0.8,\n origin: { x: 0.5, y: 0.5 },\n },\n },\n ],\n },\n // Three bursts across the top half\n fireworks: {\n followsOrigin: false,\n bursts: [\n { delay: 0, options: { ...FIREWORK, origin: { x: 0.3, y: 0.4 } } },\n { delay: 150, options: { ...FIREWORK, origin: { x: 0.5, y: 0.3 } } },\n { delay: 300, options: { ...FIREWORK, origin: { x: 0.7, y: 0.4 } } },\n ],\n },\n // Particles falling from the top\n rain: {\n followsOrigin: false,\n bursts: [\n {\n options: {\n particleCount: 50,\n angle: 270,\n spread: 60,\n startVelocity: 10,\n decay: 0.95,\n gravity: 0.5,\n drift: 0,\n origin: { x: 0.5, y: 0 },\n ticks: 900,\n },\n },\n ],\n },\n // Gentle falling white flakes\n snow: {\n followsOrigin: false,\n bursts: [\n {\n options: {\n particleCount: 30,\n angle: 270,\n spread: 120,\n startVelocity: 5,\n decay: 0.98,\n gravity: 0.3,\n drift: 1,\n origin: { x: 0.5, y: -0.1 },\n ticks: 1200,\n colors: ['#ffffff', '#e0e0e0', '#c0c0c0'],\n shapes: ['circle'],\n },\n },\n ],\n },\n // Bursts from both sides\n sideCannons: {\n followsOrigin: false,\n bursts: [\n {\n options: {\n particleCount: 50,\n angle: 60,\n spread: 55,\n startVelocity: 50,\n origin: { x: 0, y: 0.7 },\n },\n },\n {\n options: {\n particleCount: 50,\n angle: 120,\n spread: 55,\n startVelocity: 50,\n origin: { x: 1, y: 0.7 },\n },\n },\n ],\n },\n // Rainbow colors\n pride: {\n followsOrigin: true,\n bursts: [\n {\n options: {\n particleCount: 100,\n spread: 70,\n origin: { x: 0.5, y: 0.6 },\n colors: PRIDE_COLORS,\n },\n },\n ],\n },\n};\n\n/**\n * Defaults for continuous(): a small burst from the bottom every interval\n */\nexport const CONTINUOUS_DEFAULTS: KonfettiOptions = {\n particleCount: 10,\n angle: 90,\n spread: 55,\n startVelocity: 45,\n origin: { x: 0.5, y: 1 },\n};\n\n/**\n * Names of all built-in presets\n */\nexport const PRESET_NAMES = Object.keys(PRESETS) as readonly PresetName[];\n\n/**\n * Whether a value names a built-in preset (useful for attribute or prop values)\n */\nexport function isPresetName(value: unknown): value is PresetName {\n return typeof value === 'string' && (PRESET_NAMES as readonly string[]).includes(value);\n}\n","import type { ParticlePool } from './particle';\nimport { getShapeRenderer } from './shapes';\nimport { ParticleIndex } from './types';\n\n/** Base particle size in CSS pixels */\nconst BASE_SIZE = 10;\n\n/** Number of precomputed brightness steps per color */\nconst SHADE_STEPS = 16;\n/** Brightness of a piece facing away from the light, and of one facing it */\nconst MIN_BRIGHTNESS = 0.55;\nconst MAX_BRIGHTNESS = 1.2;\n/** Share of the lifetime at its end during which a piece still on screen fades out */\nconst LIFETIME_FADE = 0.1;\n/** Cap on cached colors; well above the palette size, so live colors never thrash */\nconst MAX_SHADE_CACHE = 4096;\n\ntype Rgba = [number, number, number, number];\n\n/** What an unset canvas fill draws, used for colors the canvas rejects */\nconst BLACK: Rgba = [0, 0, 0, 1];\n\n/**\n * Read any CSS color as RGBA by letting the canvas normalize it. A canvas\n * ignores invalid colors, so the color is applied over two different sentinels:\n * if the results differ, the canvas rejected it.\n */\nfunction parseColor(ctx: CanvasRenderingContext2D, color: string): Rgba | null {\n ctx.fillStyle = '#000000';\n ctx.fillStyle = color;\n const overBlack = String(ctx.fillStyle);\n ctx.fillStyle = '#ffffff';\n ctx.fillStyle = color;\n if (String(ctx.fillStyle) !== overBlack) return null;\n\n const hex = /^#([0-9a-f]{6})$/i.exec(overBlack);\n if (hex) {\n const value = Number.parseInt(hex[1], 16);\n return [value >> 16, (value >> 8) & 255, value & 255, 1];\n }\n const rgba = /^rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*([\\d.]+))?/.exec(overBlack);\n if (!rgba) return null;\n const alpha = rgba[4] === undefined ? 1 : Number(rgba[4]);\n return [Number(rgba[1]), Number(rgba[2]), Number(rgba[3]), alpha];\n}\n\n/**\n * Brightness steps for one color: darker below 1, toward white above 1.\n * Transparency is kept.\n */\nfunction buildShades([r, g, b, alpha]: Rgba): string[] {\n const shades: string[] = [];\n for (let step = 0; step < SHADE_STEPS; step++) {\n const brightness =\n MIN_BRIGHTNESS + ((MAX_BRIGHTNESS - MIN_BRIGHTNESS) * step) / (SHADE_STEPS - 1);\n const [sr, sg, sb] = [r, g, b].map((c) =>\n Math.round(brightness <= 1 ? c * brightness : c + (255 - c) * (brightness - 1))\n );\n shades.push(alpha < 1 ? `rgba(${sr}, ${sg}, ${sb}, ${alpha})` : `rgb(${sr}, ${sg}, ${sb})`);\n }\n return shades;\n}\n\n/**\n * Create a full-screen overlay canvas that never blocks the page\n */\nfunction createOverlayCanvas(): HTMLCanvasElement {\n const canvas = document.createElement('canvas');\n canvas.className = 'konfetti-canvas';\n canvas.setAttribute('aria-hidden', 'true');\n Object.assign(canvas.style, {\n position: 'fixed',\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n zIndex: '100',\n });\n document.body.appendChild(canvas);\n return canvas;\n}\n\n/**\n * Canvas renderer for particles\n */\nexport class Renderer {\n private readonly canvas: HTMLCanvasElement;\n private readonly ctx: CanvasRenderingContext2D | null;\n /** True when we created the canvas, so we may style and remove it */\n private readonly ownsCanvas: boolean;\n /** Size in CSS pixels; the backing store is this times the pixel ratio */\n private width = 0;\n private height = 0;\n private pixelRatio = 1;\n /** Brightness steps per color */\n private readonly shadeCache = new Map<string, string[]>();\n /** Particle indices grouped by color and shade step, reused between frames */\n private readonly buckets: number[][] = [];\n\n constructor(canvas?: HTMLCanvasElement) {\n this.ownsCanvas = !canvas;\n this.canvas = canvas ?? createOverlayCanvas();\n this.ctx = this.canvas.getContext('2d');\n this.resize();\n }\n\n /**\n * Match the canvas to its display size. The full-screen canvas also renders at\n * the screen's pixel density; a canvas you pass in keeps one pixel per CSS\n * pixel, because without a CSS size its display size follows its pixel size\n * and would grow on every resize.\n */\n resize(): void {\n if (this.ownsCanvas) {\n this.width = window.innerWidth;\n this.height = window.innerHeight;\n this.pixelRatio = window.devicePixelRatio || 1;\n } else {\n const rect = this.canvas.getBoundingClientRect();\n this.width = rect.width;\n this.height = rect.height;\n this.pixelRatio = 1;\n }\n this.canvas.width = Math.round(this.width * this.pixelRatio);\n this.canvas.height = Math.round(this.height * this.pixelRatio);\n }\n\n /**\n * Canvas size in CSS pixels\n */\n getDimensions(): { width: number; height: number } {\n return { width: this.width, height: this.height };\n }\n\n /**\n * Set the stacking order; only applies to the full-screen canvas we own\n */\n setZIndex(zIndex: number): void {\n if (this.ownsCanvas) this.canvas.style.zIndex = String(zIndex);\n }\n\n /**\n * Clear the canvas\n */\n clear(): void {\n if (!this.ctx) return;\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n\n /**\n * Draw every piece as flat paper turned in 3D: the transform is the piece's\n * rotation projected onto the screen (computed by physics), and its color is\n * shaded by how much its visible side faces the light. Pieces are drawn\n * grouped by color and shade, so the fill changes once per group.\n */\n render(pool: ParticlePool): void {\n this.clear();\n const ctx = this.ctx;\n if (!ctx) return;\n\n const data = pool.data;\n const ratio = this.pixelRatio;\n const buckets = this.buckets;\n\n // Keys are color × shade, so the array has holes\n for (const bucket of buckets) if (bucket) bucket.length = 0;\n for (let i = 0; i < pool.activeCount; i++) {\n const idx = i * ParticleIndex.SIZE;\n const step = Math.round(data[idx + ParticleIndex.Light] * (SHADE_STEPS - 1));\n const key = data[idx + ParticleIndex.Color] * SHADE_STEPS + step;\n if (!buckets[key]) buckets[key] = [];\n buckets[key].push(idx);\n }\n\n for (let key = 0; key < buckets.length; key++) {\n const bucket = buckets[key];\n if (!bucket || bucket.length === 0) continue;\n const color = pool.palette[Math.floor(key / SHADE_STEPS)];\n ctx.fillStyle = this.shadesFor(ctx, color)[key % SHADE_STEPS];\n\n for (const idx of bucket) {\n // Pieces normally fall out of view; fade only if the lifetime runs out first\n const opacity = Math.min(\n 1,\n data[idx + ParticleIndex.Life] / (data[idx + ParticleIndex.MaxLife] * LIFETIME_FADE)\n );\n const size = BASE_SIZE * data[idx + ParticleIndex.Scalar];\n if (size < 0.5 || opacity < 0.01) continue;\n\n ctx.globalAlpha = opacity;\n ctx.setTransform(\n ratio * data[idx + ParticleIndex.AxisXX],\n ratio * data[idx + ParticleIndex.AxisXY],\n ratio * data[idx + ParticleIndex.AxisYX],\n ratio * data[idx + ParticleIndex.AxisYY],\n ratio * data[idx + ParticleIndex.X],\n ratio * data[idx + ParticleIndex.Y]\n );\n getShapeRenderer(data[idx + ParticleIndex.Shape])(ctx, size);\n }\n }\n\n ctx.globalAlpha = 1;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n }\n\n private shadesFor(ctx: CanvasRenderingContext2D, color: string): string[] {\n let shades = this.shadeCache.get(color);\n if (!shades) {\n if (this.shadeCache.size >= MAX_SHADE_CACHE) this.shadeCache.clear();\n shades = buildShades(parseColor(ctx, color) ?? BLACK);\n this.shadeCache.set(color, shades);\n }\n return shades;\n }\n\n /**\n * Destroy renderer and remove the canvas if we created it\n */\n destroy(): void {\n this.clear();\n if (this.ownsCanvas) this.canvas.remove();\n }\n}\n","import { ParticlePool } from './particle';\nimport { updateParticles } from './physics';\nimport { CONTINUOUS_DEFAULTS, isPresetName, PRESETS } from './presets';\nimport { Renderer } from './renderer';\nimport type { CreateOptions, KonfettiOptions, PresetName } from './types';\nimport { clamp, isBrowser, mergeOptions, prefersReducedMotion, resolveOptions } from './utils';\n\n/** Length of one 60 fps frame; physics are tuned in these units */\nconst FRAME_MS = 1000 / 60;\n/** Largest step per frame, so a long stall does not teleport particles */\nconst MAX_STEP = 4;\n\n/**\n * Manages one canvas: the animation loop, particles, physics and rendering.\n * Safe to construct on the server, where every method does nothing.\n */\nexport class Konfetti {\n private readonly pool = new ParticlePool();\n private readonly renderer: Renderer | null = null;\n private frameId: number | null = null;\n /** Timestamp of the previous frame, or when the loop was scheduled */\n private lastTime = 0;\n private paused = false;\n private destroyed = false;\n private readonly resizeWithWindow: boolean = false;\n /** Follows a custom canvas whose size changes through layout, not just window resizes */\n private resizeObserver: ResizeObserver | null = null;\n private readonly timeouts = new Set<ReturnType<typeof setTimeout>>();\n private readonly intervals = new Set<ReturnType<typeof setInterval>>();\n\n constructor(canvas?: HTMLCanvasElement, createOptions: CreateOptions = {}) {\n if (!isBrowser()) {\n this.destroyed = true;\n return;\n }\n\n this.renderer = new Renderer(canvas);\n this.resizeWithWindow = createOptions.resize !== false;\n if (this.resizeWithWindow) {\n window.addEventListener('resize', this.handleResize);\n if (canvas && typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(this.handleResize);\n this.resizeObserver.observe(canvas);\n }\n }\n document.addEventListener('visibilitychange', this.handleVisibilityChange);\n }\n\n /**\n * Fire one burst. Skipped while the page is hidden, after destroy(), and for\n * visitors who prefer reduced motion (unless disableForReducedMotion is false).\n */\n fire(options?: KonfettiOptions): void {\n if (this.destroyed || !this.renderer || document.hidden) return;\n\n const resolved = resolveOptions(options);\n if (resolved.disableForReducedMotion && prefersReducedMotion()) return;\n\n this.renderer.setZIndex(resolved.zIndex);\n const { width, height } = this.renderer.getDimensions();\n this.pool.spawn(resolved, width, height);\n this.scheduleFrame();\n }\n\n /**\n * Fire a built-in preset; options override the preset's own values\n */\n preset(name: PresetName, options?: KonfettiOptions): void {\n if (!isPresetName(name) || this.destroyed) return;\n\n for (const burst of PRESETS[name].bursts) {\n const merged = mergeOptions(burst.options, options);\n if (burst.delay) {\n const id = setTimeout(() => {\n this.timeouts.delete(id);\n this.fire(merged);\n }, burst.delay);\n this.timeouts.add(id);\n } else {\n this.fire(merged);\n }\n }\n }\n\n /**\n * Fire a small burst every `interval` ms until the returned function is\n * called, or until reset() or destroy()\n */\n continuous(options?: KonfettiOptions, interval = 250): () => void {\n if (this.destroyed) return () => {};\n\n const merged = mergeOptions(CONTINUOUS_DEFAULTS, options);\n const delay = Number.isFinite(interval) && interval >= 16 ? interval : 250;\n const id = setInterval(() => this.fire(merged), delay);\n this.intervals.add(id);\n\n return () => {\n clearInterval(id);\n this.intervals.delete(id);\n };\n }\n\n /**\n * Pause the animation; particles stay where they are\n */\n pause(): void {\n this.paused = true;\n this.cancelFrame();\n }\n\n /**\n * Resume after pause()\n */\n resume(): void {\n this.paused = false;\n this.scheduleFrame();\n }\n\n /**\n * Clear all particles, cancel scheduled bursts and streams, stop animating and\n * undo pause()\n */\n reset(): void {\n this.paused = false;\n this.cancelFrame();\n for (const id of this.timeouts) clearTimeout(id);\n for (const id of this.intervals) clearInterval(id);\n this.timeouts.clear();\n this.intervals.clear();\n this.pool.reset();\n this.renderer?.clear();\n }\n\n /**\n * Reset, remove listeners and remove the canvas if this instance created it.\n * The instance ignores every call afterwards.\n */\n destroy(): void {\n if (this.destroyed) return;\n this.reset();\n this.destroyed = true;\n\n if (this.resizeWithWindow) window.removeEventListener('resize', this.handleResize);\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n document.removeEventListener('visibilitychange', this.handleVisibilityChange);\n this.renderer?.destroy();\n }\n\n private readonly handleResize = (): void => {\n this.renderer?.resize();\n };\n\n private readonly handleVisibilityChange = (): void => {\n if (document.hidden) {\n this.cancelFrame();\n } else {\n this.scheduleFrame();\n }\n };\n\n /**\n * Start the loop if there is something to animate and nothing prevents it\n */\n private scheduleFrame(): void {\n if (\n this.frameId !== null ||\n this.paused ||\n this.destroyed ||\n document.hidden ||\n this.pool.activeCount === 0\n ) {\n return;\n }\n this.lastTime = performance.now();\n this.frameId = requestAnimationFrame(this.tick);\n }\n\n private cancelFrame(): void {\n if (this.frameId !== null) {\n cancelAnimationFrame(this.frameId);\n this.frameId = null;\n }\n }\n\n private readonly tick = (time: number): void => {\n this.frameId = null;\n if (!this.renderer) return;\n\n const dt = clamp((time - this.lastTime) / FRAME_MS, 0, MAX_STEP);\n this.lastTime = time;\n\n const { width, height } = this.renderer.getDimensions();\n const hasParticles = updateParticles(this.pool, dt, width, height);\n this.renderer.render(this.pool);\n\n if (hasParticles) {\n this.frameId = requestAnimationFrame(this.tick);\n }\n };\n}\n","import { Konfetti } from './konfetti';\nimport { isPresetName, PRESETS } from './presets';\nimport type {\n CreateOptions,\n FireFromElementOptions,\n KonfettiOptions,\n Origin,\n PresetName,\n} from './types';\nimport { isBrowser, mergeOrigin } from './utils';\n\n/**\n * Fire function bound to a canvas, with preset, reset and destroy methods\n */\nexport interface KonfettiInstance {\n (options?: KonfettiOptions): void;\n /** Fire a built-in preset into this canvas */\n preset: (name: PresetName, options?: KonfettiOptions) => void;\n /** Fire a stream into this canvas; returns a function that stops it */\n continuous: (options?: KonfettiOptions, interval?: number) => () => void;\n /** Clear the canvas and cancel scheduled bursts */\n reset: () => void;\n /** Stop for good and release listeners */\n destroy: () => void;\n}\n\n// Global instance for the simple API, created on first use\nlet globalInstance: Konfetti | null = null;\n\nfunction getGlobalInstance(): Konfetti | null {\n if (!isBrowser()) return null;\n globalInstance ??= new Konfetti();\n return globalInstance;\n}\n\n/**\n * Fire konfetti on the full-screen canvas\n */\nexport function fire(options?: KonfettiOptions): void {\n getGlobalInstance()?.fire(options);\n}\n\n/**\n * Fire a built-in preset on the full-screen canvas\n */\nexport function firePreset(name: PresetName, options?: KonfettiOptions): void {\n getGlobalInstance()?.preset(name, options);\n}\n\n/**\n * The center of an element, as an origin relative to the viewport\n */\nexport function originFromElement(element: Element): Origin {\n const rect = element.getBoundingClientRect();\n return {\n x: (rect.left + rect.width / 2) / window.innerWidth,\n y: (rect.top + rect.height / 2) / window.innerHeight,\n };\n}\n\n/**\n * Fire from the center of an element, for example the button that was clicked.\n * Single-burst presets (cannon, explosion, pride) start at the element too;\n * screen-wide presets (fireworks, rain, snow, sideCannons) keep their positions.\n * An origin you pass yourself wins, axis by axis.\n */\nexport function fireFromElement(element: Element, options: FireFromElementOptions = {}): void {\n if (!isBrowser()) return;\n\n const { preset: name, ...rest } = options;\n // An unknown name (for example a typo in plain JavaScript) fires a plain burst\n const preset = isPresetName(name) ? name : undefined;\n const followsOrigin = preset ? PRESETS[preset].followsOrigin : true;\n const merged = followsOrigin\n ? { ...rest, origin: mergeOrigin(originFromElement(element), rest.origin) }\n : rest;\n\n if (preset) {\n firePreset(preset, merged);\n } else {\n fire(merged);\n }\n}\n\n/**\n * Clear the full-screen canvas and cancel scheduled bursts and streams\n */\nexport function reset(): void {\n globalInstance?.reset();\n}\n\n/**\n * Remove the full-screen canvas and its listeners; the next fire() creates a new one\n */\nexport function destroy(): void {\n globalInstance?.destroy();\n globalInstance = null;\n}\n\n/**\n * Create a konfetti instance that draws into your own canvas\n */\nexport function create(canvas: HTMLCanvasElement, createOptions?: CreateOptions): KonfettiInstance {\n const instance = new Konfetti(canvas, createOptions);\n\n const fireFn = ((options?: KonfettiOptions) => instance.fire(options)) as KonfettiInstance;\n fireFn.preset = (name, options) => instance.preset(name, options);\n fireFn.continuous = (options, interval) => instance.continuous(options, interval);\n fireFn.reset = () => instance.reset();\n fireFn.destroy = () => instance.destroy();\n\n return fireFn;\n}\n\n/**\n * Fire a steady stream on the full-screen canvas. Returns a function that stops it.\n */\nexport function continuous(options?: KonfettiOptions, interval?: number): () => void {\n return getGlobalInstance()?.continuous(options, interval) ?? (() => {});\n}\n\n/** Burst of confetti from bottom center shooting up */\nexport const cannon = (options?: KonfettiOptions): void => firePreset('cannon', options);\n\n/** 360 degree burst from center */\nexport const explosion = (options?: KonfettiOptions): void => firePreset('explosion', options);\n\n/** Three quick bursts across the top half */\nexport const fireworks = (options?: KonfettiOptions): void => firePreset('fireworks', options);\n\n/** Particles falling from the top */\nexport const rain = (options?: KonfettiOptions): void => firePreset('rain', options);\n\n/** Gentle falling white flakes */\nexport const snow = (options?: KonfettiOptions): void => firePreset('snow', options);\n\n/** Bursts from both sides */\nexport const sideCannons = (options?: KonfettiOptions): void => firePreset('sideCannons', options);\n\n/** Rainbow colors */\nexport const pride = (options?: KonfettiOptions): void => firePreset('pride', options);\n"],"mappings":";AAWA,SAAS,WAAW,KAA+B,MAAoB;AACrE,MAAI,UAAU;AACd,MAAI,IAAI,GAAG,GAAG,OAAO,GAAG,GAAG,KAAK,KAAK,CAAC;AACtC,MAAI,KAAK;AACX;AAKA,SAAS,WAAW,KAA+B,MAAoB;AACrE,QAAM,WAAW,OAAO;AACxB,MAAI,SAAS,CAAC,UAAU,CAAC,UAAU,MAAM,IAAI;AAC/C;AAKA,IAAM,SAA+B,CAAC,UAAU,QAAQ;AAExD,IAAM,YAAsC,CAAC,YAAY,UAAU;AAK5D,SAAS,QAAQ,OAAoC;AAC1D,SAAO,OAAO,SAAS,KAAkB;AAC3C;AAKO,SAAS,aAAa,OAA0B;AACrD,SAAO,KAAK,IAAI,GAAG,OAAO,QAAQ,KAAK,CAAC;AAC1C;AAKO,SAAS,iBAAiB,OAA8B;AAC7D,SAAO,UAAU,KAAK,KAAK;AAC7B;;;AC7CO,IAAM,iBAAiB;AAAA,EAC5B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAKO,IAAM,kBAAmC;AAAA,EAC9C,eAAe;AAAA,EACf,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,EACzB,QAAQ;AAAA,EACR,QAAQ,CAAC,UAAU,QAAQ;AAAA,EAC3B,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,yBAAyB;AAC3B;AAKA,SAAS,OAAO,OAAgB,UAA0B;AACxD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAKO,SAAS,eAAe,UAA2B,CAAC,GAAoB;AAC7E,QAAM,IAAI;AACV,QAAM,SAAS,MAAM,QAAQ,QAAQ,MAAM,IACvC,QAAQ,OAAO,OAAO,CAAC,MAAM,OAAO,MAAM,YAAY,EAAE,SAAS,CAAC,IAClE,CAAC;AACL,QAAM,SAAS,MAAM,QAAQ,QAAQ,MAAM,IAAI,QAAQ,OAAO,OAAO,OAAO,IAAI,CAAC;AAEjF,SAAO;AAAA,IACL,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,QAAQ,eAAe,EAAE,aAAa,CAAC,CAAC;AAAA,IACrF,OAAO,OAAO,QAAQ,OAAO,EAAE,KAAK;AAAA,IACpC,QAAQ,OAAO,QAAQ,QAAQ,EAAE,MAAM;AAAA,IACvC,eAAe,OAAO,QAAQ,eAAe,EAAE,aAAa;AAAA,IAC5D,OAAO,MAAM,OAAO,QAAQ,OAAO,EAAE,KAAK,GAAG,GAAG,CAAC;AAAA,IACjD,SAAS,OAAO,QAAQ,SAAS,EAAE,OAAO;AAAA,IAC1C,OAAO,OAAO,QAAQ,OAAO,EAAE,KAAK;AAAA,IACpC,OAAO,KAAK,IAAI,GAAG,OAAO,QAAQ,OAAO,EAAE,KAAK,CAAC;AAAA,IACjD,QAAQ;AAAA,MACN,GAAG,OAAO,QAAQ,QAAQ,GAAG,EAAE,OAAO,CAAC;AAAA,MACvC,GAAG,OAAO,QAAQ,QAAQ,GAAG,EAAE,OAAO,CAAC;AAAA,IACzC;AAAA,IACA,QAAQ,OAAO,SAAS,IAAI,SAAS,CAAC,GAAG,EAAE,MAAM;AAAA,IACjD,QAAQ,OAAO,SAAS,IAAI,SAAS,CAAC,GAAG,EAAE,MAAM;AAAA,IACjD,QAAQ,KAAK,IAAI,GAAG,OAAO,QAAQ,QAAQ,EAAE,MAAM,CAAC;AAAA,IACpD,QAAQ,OAAO,QAAQ,QAAQ,EAAE,MAAM;AAAA,IACvC,yBAAyB,QAAQ,2BAA2B,EAAE;AAAA,EAChE;AACF;AAMO,SAAS,aAAa,MAAuB,UAA6C;AAC/F,QAAM,SAAkC,EAAE,GAAG,KAAK;AAClD,MAAI,UAAU;AACZ,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,UAAI,UAAU,OAAW,QAAO,GAAG,IAAI;AAAA,IACzC;AAEA,QAAI,SAAS,OAAQ,QAAO,SAAS,YAAY,KAAK,QAAQ,SAAS,MAAM;AAAA,EAC/E;AACA,SAAO;AACT;AAKO,SAAS,YACd,MACA,UACiB;AACjB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,UAAU,MAAM,UAAa,EAAE,GAAG,SAAS,EAAE;AAAA,IACjD,GAAI,UAAU,MAAM,UAAa,EAAE,GAAG,SAAS,EAAE;AAAA,EACnD;AACF;AAKO,SAAS,SAAS,KAAqB;AAC5C,SAAO,OAAO,KAAK,KAAK;AAC1B;AAKO,SAAS,YAAY,KAAa,KAAqB;AAC5D,SAAO,KAAK,OAAO,KAAK,MAAM,OAAO;AACvC;AAKO,SAAS,aAAqB;AACnC,SAAO,KAAK,OAAO,IAAI,MAAM,KAAK;AACpC;AAKO,SAAS,WAAc,KAAsB;AAClD,SAAO,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI,MAAM,CAAC;AACnD;AAKO,SAAS,YAAqB;AACnC,SAAO,OAAO,WAAW,eAAe,OAAO,aAAa;AAC9D;AAKO,SAAS,uBAAgC;AAC9C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,aAAa,OAAO,aAAa,kCAAkC;AACzE,SAAO,YAAY,WAAW;AAChC;AAKO,SAAS,MAAM,OAAe,KAAa,KAAqB;AACrE,SAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAC3C;;;ACpJO,IAAM,gBAAgB;AAG7B,IAAM,cAAc;AAMb,IAAM,eAAN,MAAmB;AAAA,EAYxB,YAAY,kBAAkB,KAAK;AARnC;AAAA,SAAO,cAAc;AAKrB;AAAA;AAAA;AAAA;AAAA,SAAgB,UAAoB,CAAC;AACrC,SAAiB,WAAW,oBAAI,IAAoB;AAGlD,SAAK,OAAO,IAAI,aAAa,+BAAoC;AAAA,EACnE;AAAA;AAAA,EAGA,IAAI,WAAmB;AACrB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,cAAc;AACnB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAA0B,aAAqB,cAA4B;AAC/E,UAAM,QAAQ,KAAK,IAAI,QAAQ,eAAe,gBAAgB,KAAK,WAAW;AAC9E,QAAI,SAAS,EAAG;AAChB,SAAK,eAAe,KAAK,cAAc,KAAK;AAE5C,UAAM,OAAO,KAAK;AAClB,UAAM,UAAU,QAAQ,OAAO,IAAI;AACnC,UAAM,UAAU,QAAQ,OAAO,IAAI;AACnC,UAAM,WAAW,SAAS,QAAQ,KAAK;AACvC,UAAM,YAAY,SAAS,QAAQ,MAAM;AAEzC,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,OAAO,KAAK,cAAc;AAGhC,YAAM,gBAAgB,WAAW,YAAY,CAAC,YAAY,GAAG,YAAY,CAAC;AAE1E,YAAM,WAAW,QAAQ,gBAAgB,YAAY,KAAK,CAAC;AAG3D,WAAK,eAAqB,IAAI;AAC9B,WAAK,eAAqB,IAAI;AAG9B,WAAK,uBAA6B,IAAI,KAAK,IAAI,aAAa,IAAI;AAChE,WAAK,uBAA6B,IAAI,CAAC,KAAK,IAAI,aAAa,IAAI;AAIjE,WAAK,kBAAwB,IAAI,YAAY,GAAG,KAAK,KAAK,CAAC;AAC3D,WAAK,uBAA6B,IAAI,YAAY,MAAM,IAAI,IAAI,WAAW;AAC3E,WAAK,qBAA0B,IAAI,YAAY,GAAG,KAAK,KAAK,CAAC;AAC7D,WAAK,0BAA+B,IAAI,YAAY,MAAM,IAAI,IAAI,WAAW;AAC7E,WAAK,sBAA4B,IAAI,YAAY,GAAG,KAAK,KAAK,CAAC;AAC/D,WAAK,2BAAiC,IAAI,YAAY,OAAO,IAAI;AAEjE,WAAK,mBAAyB,IAAI,KAAK,QAAQ,WAAW,QAAQ,MAAM,CAAC;AACzE,WAAK,mBAAyB,IAAI,aAAa,WAAW,QAAQ,MAAM,CAAC;AAGzE,WAAK,qBAA0B,IAAI,QAAQ,SAAS,YAAY,KAAK,GAAG;AAGxE,WAAK,mBAAwB,IAAI,QAAQ;AACzC,WAAK,sBAA2B,IAAI,QAAQ;AAI5C,WAAK,oBAAyB,IAAI,QAAQ,QAAQ,YAAY,MAAM,GAAG;AACvE,WAAK,sBAA2B,IAAI,QAAQ;AAC5C,WAAK,oBAAyB,IAAI,QAAQ;AAC1C,WAAK,uBAA4B,IAAI,YAAY,GAAG,KAAK,KAAK,CAAC;AAC/D,WAAK,4BAAiC,IAAI,YAAY,MAAM,IAAI;AAAA,IAClE;AAEA,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,UAAM,OAAO,KAAK;AAClB,QAAI,WAAW;AAEf,aAAS,UAAU,GAAG,UAAU,KAAK,aAAa,WAAW;AAC3D,YAAM,SAAS;AACf,UAAI,KAAK,sBAA2B,KAAK,EAAG;AAE5C,UAAI,aAAa,SAAS;AACxB,cAAM,SAAS;AACf,aAAK,WAAW,QAAQ,QAAQ,sBAA2B;AAAA,MAC7D;AACA;AAAA,IACF;AAEA,SAAK,cAAc;AACnB,QAAI,aAAa,GAAG;AAClB,WAAK,aAAa;AAAA,IACpB,WAAW,KAAK,QAAQ,SAAS,aAAa;AAC5C,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAqB;AAC3B,UAAM,OAAO,KAAK;AAClB,UAAM,aAAa,CAAC,GAAG,KAAK,OAAO;AACnC,UAAM,QAAQ,oBAAI,IAAoB;AACtC,SAAK,aAAa;AAElB,aAAS,IAAI,GAAG,IAAI,KAAK,aAAa,KAAK;AACzC,YAAM,MAAM;AACZ,YAAM,QAAQ,KAAK,GAAG;AACtB,UAAI,QAAQ,MAAM,IAAI,KAAK;AAC3B,UAAI,UAAU,QAAW;AACvB,gBAAQ,KAAK,QAAQ,WAAW,KAAK,CAAC;AACtC,cAAM,IAAI,OAAO,KAAK;AAAA,MACxB;AACA,WAAK,GAAG,IAAI;AAAA,IACd;AAAA,EACF;AAAA,EAEQ,QAAQ,OAAuB;AACrC,QAAI,KAAK,KAAK,SAAS,IAAI,KAAK;AAChC,QAAI,OAAO,QAAW;AACpB,WAAK,KAAK,QAAQ;AAClB,WAAK,QAAQ,KAAK,KAAK;AACvB,WAAK,SAAS,IAAI,OAAO,EAAE;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAqB;AAC3B,SAAK,QAAQ,SAAS;AACtB,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA,EAEQ,eAAe,QAAsB;AAC3C,QAAI,UAAU,KAAK,SAAU;AAC7B,QAAI,WAAW,KAAK;AACpB,WAAO,WAAW,OAAQ,aAAY;AACtC,UAAM,QAAQ,IAAI,aAAa,KAAK,IAAI,UAAU,aAAa,iBAAsB;AACrF,UAAM,IAAI,KAAK,KAAK,SAAS,GAAG,KAAK,2BAAgC,CAAC;AACtE,SAAK,OAAO;AAAA,EACd;AACF;;;ACrKA,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,UAAU;AAMT,SAAS,UAAU,GAAwB;AAChD,QAAM,SAAS,EAAE,CAAC,IAAI,IAAI,KAAK;AAC/B,SAAO,KAAK,IAAI,GAAG,UAAU,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,QAAQ;AAChF;AAEO,SAAS,oBAAiC;AAC/C,SAAO,IAAI,aAAa,CAAC;AAC3B;AAMO,SAAS,OAAO,MAAoB,KAAa,KAA+B;AACrF,QAAM,OAAO,KAAK,kBAAwB;AAC1C,QAAM,SAAS,KAAK,qBAA0B;AAC9C,QAAM,WAAW,KAAK,sBAA4B;AAClD,QAAM,KAAK,KAAK,IAAI,IAAI;AACxB,QAAM,KAAK,KAAK,IAAI,IAAI;AACxB,QAAM,KAAK,KAAK,IAAI,MAAM;AAC1B,QAAM,KAAK,KAAK,IAAI,MAAM;AAC1B,QAAM,KAAK,KAAK,IAAI,QAAQ;AAC5B,QAAM,KAAK,KAAK,IAAI,QAAQ;AAE5B,MAAI,CAAC,IAAI,KAAK;AACd,MAAI,CAAC,IAAI,KAAK;AACd,MAAI,CAAC,IAAI,CAAC;AACV,MAAI,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK;AAC7B,MAAI,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK;AAC7B,MAAI,CAAC,IAAI,KAAK;AACd,MAAI,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK;AAC7B,MAAI,CAAC,IAAI,KAAK,KAAK,KAAK,KAAK;AAC7B,MAAI,CAAC,IAAI,KAAK;AACd,SAAO;AACT;;;AC/CA,IAAM,gBAAgB;AAEtB,IAAM,YAAY;AAKlB,IAAM,gBAAgB;AAEtB,IAAM,QAAQ;AAEd,IAAM,WAAW;AAEjB,IAAM,mBAAmB;AAEzB,IAAM,cAAc,kBAAkB;AAQ/B,SAAS,gBACd,MACA,IACA,OACA,QACS;AACT,QAAM,OAAO,KAAK;AAElB,WAAS,IAAI,GAAG,IAAI,KAAK,aAAa,KAAK;AACzC,mBAAe,MAAM,mBAAwB,IAAI,OAAO,MAAM;AAAA,EAChE;AAGA,OAAK,QAAQ;AAEb,SAAO,KAAK,cAAc;AAC5B;AAOA,SAAS,eACP,MACA,KACA,IACA,OACA,QACM;AACN,MAAI,KAAK,KAAK,uBAA6B;AAC3C,MAAI,KAAK,KAAK,uBAA6B;AAI3C,QAAM,IAAI,OAAO,MAAM,KAAK,WAAW;AACvC,QAAM,KAAK,EAAE,CAAC;AACd,QAAM,KAAK,EAAE,CAAC;AACd,OAAK,qBAA0B,IAAI,EAAE,CAAC;AACtC,OAAK,qBAA0B,IAAI,EAAE,CAAC;AACtC,OAAK,qBAA0B,IAAI,EAAE,CAAC;AACtC,OAAK,qBAA0B,IAAI,EAAE,CAAC;AACtC,OAAK,oBAAyB,IAAI,UAAU,CAAC;AAE7C,QAAM,KAAK,sBAA2B,IAAI,gBAAgB;AAE1D,MAAI,KAAK,GAAG;AAEV,UAAM,OAAO,aAAa,OAAO,OAAO,KAAK,IAAI,EAAE;AACnD,SAAK,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,KAAK,IAAI,IAAI,aAAa,IAAI,EAAE;AAGlE,UAAM,QAAQ,KAAK,IAAI,KAAK,KAAK;AAAA,EACnC;AAIA,QAAM,QAAQ,KAAK,uBAA4B;AAC/C,QAAM,OAAO,KAAK,oBAAyB,IAAI,WAAW,KAAK,IAAI,KAAK;AACxE,QAAM,UAAU,KAAK,oBAAyB,KAAK;AACnD,OAAK,QAAQ,KAAK,QAAQ;AAC1B,QAAM;AAGN,QAAM,OAAO,MAAM,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,EAAE,IAAI,CAAC;AAEvD,OAAK,uBAA6B,IAAI;AACtC,OAAK,uBAA6B,IAAI;AACtC,OAAK,eAAqB,KAAK,KAAK;AACpC,OAAK,eAAqB,KAAK,KAAK;AACpC,OAAK,kBAAwB,KAAK,KAAK,uBAA6B,IAAI,OAAO;AAC/E,OAAK,qBAA0B,KAAK,KAAK,0BAA+B,IAAI;AAC5E,OAAK,sBAA4B,KAAK,KAAK,2BAAiC,IAAI;AAChF,OAAK,uBAA4B,IAAI,QAAQ,KAAK,4BAAiC,IAAI;AACvF,OAAK,mBAAwB,KAAK;AAKlC,MAAI,QAAQ,KAAK,SAAS,GAAG;AAC3B,UAAM,IAAI,KAAK,eAAqB;AACpC,UAAM,IAAI,KAAK,eAAqB;AACpC,UAAM,UAAU,IAAI,SAAS,oBAAoB,MAAM;AACvD,UAAM,UAAU,IAAI,CAAC,mBAAmB,KAAK,MAAM;AACnD,UAAM,WAAW,IAAI,QAAQ,mBAAmB,KAAK,MAAM;AAE3D,UAAM,aAAa,IAAI,CAAC,oBAAoB,MAAM,KAAK,KAAK,sBAA2B,KAAK;AAC5F,QAAI,WAAW,WAAW,YAAY,YAAY;AAChD,WAAK,mBAAwB,IAAI;AAAA,IACnC;AAAA,EACF;AACF;;;ACpGA,IAAM,kBAAkB,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AAC9E,IAAM,WAA4B;AAAA,EAChC,eAAe;AAAA,EACf,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,IAAM,eAAe;AAAA,EACnB;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAKO,IAAM,UAA0D;AAAA;AAAA,EAErE,QAAQ;AAAA,IACN,eAAe;AAAA,IACf,QAAQ;AAAA,MACN;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,OAAO;AAAA,UACP,SAAS;AAAA,UACT,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA,WAAW;AAAA,IACT,eAAe;AAAA,IACf,QAAQ;AAAA,MACN;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,OAAO;AAAA,UACP,SAAS;AAAA,UACT,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA,WAAW;AAAA,IACT,eAAe;AAAA,IACf,QAAQ;AAAA,MACN,EAAE,OAAO,GAAG,SAAS,EAAE,GAAG,UAAU,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI,EAAE,EAAE;AAAA,MACjE,EAAE,OAAO,KAAK,SAAS,EAAE,GAAG,UAAU,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI,EAAE,EAAE;AAAA,MACnE,EAAE,OAAO,KAAK,SAAS,EAAE,GAAG,UAAU,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI,EAAE,EAAE;AAAA,IACrE;AAAA,EACF;AAAA;AAAA,EAEA,MAAM;AAAA,IACJ,eAAe;AAAA,IACf,QAAQ;AAAA,MACN;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,OAAO;AAAA,UACP,SAAS;AAAA,UACT,OAAO;AAAA,UACP,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE;AAAA,UACvB,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA,MAAM;AAAA,IACJ,eAAe;AAAA,IACf,QAAQ;AAAA,MACN;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,OAAO;AAAA,UACP,SAAS;AAAA,UACT,OAAO;AAAA,UACP,QAAQ,EAAE,GAAG,KAAK,GAAG,KAAK;AAAA,UAC1B,OAAO;AAAA,UACP,QAAQ,CAAC,WAAW,WAAW,SAAS;AAAA,UACxC,QAAQ,CAAC,QAAQ;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA,aAAa;AAAA,IACX,eAAe;AAAA,IACf,QAAQ;AAAA,MACN;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,QAAQ,EAAE,GAAG,GAAG,GAAG,IAAI;AAAA,QACzB;AAAA,MACF;AAAA,MACA;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,QAAQ,EAAE,GAAG,GAAG,GAAG,IAAI;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAEA,OAAO;AAAA,IACL,eAAe;AAAA,IACf,QAAQ;AAAA,MACN;AAAA,QACE,SAAS;AAAA,UACP,eAAe;AAAA,UACf,QAAQ;AAAA,UACR,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,UACzB,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKO,IAAM,sBAAuC;AAAA,EAClD,eAAe;AAAA,EACf,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE;AACzB;AAKO,IAAM,eAAe,OAAO,KAAK,OAAO;AAKxC,SAAS,aAAa,OAAqC;AAChE,SAAO,OAAO,UAAU,YAAa,aAAmC,SAAS,KAAK;AACxF;;;ACtLA,IAAM,YAAY;AAGlB,IAAM,cAAc;AAEpB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AAEvB,IAAM,gBAAgB;AAEtB,IAAM,kBAAkB;AAKxB,IAAM,QAAc,CAAC,GAAG,GAAG,GAAG,CAAC;AAO/B,SAAS,WAAW,KAA+B,OAA4B;AAC7E,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,QAAM,YAAY,OAAO,IAAI,SAAS;AACtC,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI,OAAO,IAAI,SAAS,MAAM,UAAW,QAAO;AAEhD,QAAM,MAAM,oBAAoB,KAAK,SAAS;AAC9C,MAAI,KAAK;AACP,UAAM,QAAQ,OAAO,SAAS,IAAI,CAAC,GAAG,EAAE;AACxC,WAAO,CAAC,SAAS,IAAK,SAAS,IAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,EACzD;AACA,QAAM,OAAO,mDAAmD,KAAK,SAAS;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,CAAC,MAAM,SAAY,IAAI,OAAO,KAAK,CAAC,CAAC;AACxD,SAAO,CAAC,OAAO,KAAK,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,GAAG,KAAK;AAClE;AAMA,SAAS,YAAY,CAAC,GAAG,GAAG,GAAG,KAAK,GAAmB;AACrD,QAAM,SAAmB,CAAC;AAC1B,WAAS,OAAO,GAAG,OAAO,aAAa,QAAQ;AAC7C,UAAM,aACJ,kBAAmB,iBAAiB,kBAAkB,QAAS,cAAc;AAC/E,UAAM,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,MAAI,CAAC,MAClC,KAAK,MAAM,cAAc,IAAI,IAAI,aAAa,KAAK,MAAM,MAAM,aAAa,EAAE;AAAA,IAChF;AACA,WAAO,KAAK,QAAQ,IAAI,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG;AAAA,EAC5F;AACA,SAAO;AACT;AAKA,SAAS,sBAAyC;AAChD,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,YAAY;AACnB,SAAO,aAAa,eAAe,MAAM;AACzC,SAAO,OAAO,OAAO,OAAO;AAAA,IAC1B,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,QAAQ;AAAA,EACV,CAAC;AACD,WAAS,KAAK,YAAY,MAAM;AAChC,SAAO;AACT;AAKO,IAAM,WAAN,MAAe;AAAA,EAcpB,YAAY,QAA4B;AARxC;AAAA,SAAQ,QAAQ;AAChB,SAAQ,SAAS;AACjB,SAAQ,aAAa;AAErB;AAAA,SAAiB,aAAa,oBAAI,IAAsB;AAExD;AAAA,SAAiB,UAAsB,CAAC;AAGtC,SAAK,aAAa,CAAC;AACnB,SAAK,SAAS,UAAU,oBAAoB;AAC5C,SAAK,MAAM,KAAK,OAAO,WAAW,IAAI;AACtC,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAe;AACb,QAAI,KAAK,YAAY;AACnB,WAAK,QAAQ,OAAO;AACpB,WAAK,SAAS,OAAO;AACrB,WAAK,aAAa,OAAO,oBAAoB;AAAA,IAC/C,OAAO;AACL,YAAM,OAAO,KAAK,OAAO,sBAAsB;AAC/C,WAAK,QAAQ,KAAK;AAClB,WAAK,SAAS,KAAK;AACnB,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,OAAO,QAAQ,KAAK,MAAM,KAAK,QAAQ,KAAK,UAAU;AAC3D,SAAK,OAAO,SAAS,KAAK,MAAM,KAAK,SAAS,KAAK,UAAU;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAmD;AACjD,WAAO,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,QAAsB;AAC9B,QAAI,KAAK,WAAY,MAAK,OAAO,MAAM,SAAS,OAAO,MAAM;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,QAAI,CAAC,KAAK,IAAK;AACf,SAAK,IAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACtC,SAAK,IAAI,UAAU,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,MAA0B;AAC/B,SAAK,MAAM;AACX,UAAM,MAAM,KAAK;AACjB,QAAI,CAAC,IAAK;AAEV,UAAM,OAAO,KAAK;AAClB,UAAM,QAAQ,KAAK;AACnB,UAAM,UAAU,KAAK;AAGrB,eAAW,UAAU,QAAS,KAAI,OAAQ,QAAO,SAAS;AAC1D,aAAS,IAAI,GAAG,IAAI,KAAK,aAAa,KAAK;AACzC,YAAM,MAAM;AACZ,YAAM,OAAO,KAAK,MAAM,KAAK,oBAAyB,KAAK,cAAc,EAAE;AAC3E,YAAM,MAAM,KAAK,mBAAyB,IAAI,cAAc;AAC5D,UAAI,CAAC,QAAQ,GAAG,EAAG,SAAQ,GAAG,IAAI,CAAC;AACnC,cAAQ,GAAG,EAAE,KAAK,GAAG;AAAA,IACvB;AAEA,aAAS,MAAM,GAAG,MAAM,QAAQ,QAAQ,OAAO;AAC7C,YAAM,SAAS,QAAQ,GAAG;AAC1B,UAAI,CAAC,UAAU,OAAO,WAAW,EAAG;AACpC,YAAM,QAAQ,KAAK,QAAQ,KAAK,MAAM,MAAM,WAAW,CAAC;AACxD,UAAI,YAAY,KAAK,UAAU,KAAK,KAAK,EAAE,MAAM,WAAW;AAE5D,iBAAW,OAAO,QAAQ;AAExB,cAAM,UAAU,KAAK;AAAA,UACnB;AAAA,UACA,KAAK,mBAAwB,KAAK,KAAK,sBAA2B,IAAI;AAAA,QACxE;AACA,cAAM,OAAO,YAAY,KAAK,qBAA0B;AACxD,YAAI,OAAO,OAAO,UAAU,KAAM;AAElC,YAAI,cAAc;AAClB,YAAI;AAAA,UACF,QAAQ,KAAK,qBAA0B;AAAA,UACvC,QAAQ,KAAK,qBAA0B;AAAA,UACvC,QAAQ,KAAK,qBAA0B;AAAA,UACvC,QAAQ,KAAK,qBAA0B;AAAA,UACvC,QAAQ,KAAK,eAAqB;AAAA,UAClC,QAAQ,KAAK,eAAqB;AAAA,QACpC;AACA,yBAAiB,KAAK,mBAAyB,CAAC,EAAE,KAAK,IAAI;AAAA,MAC7D;AAAA,IACF;AAEA,QAAI,cAAc;AAClB,QAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,EACnC;AAAA,EAEQ,UAAU,KAA+B,OAAyB;AACxE,QAAI,SAAS,KAAK,WAAW,IAAI,KAAK;AACtC,QAAI,CAAC,QAAQ;AACX,UAAI,KAAK,WAAW,QAAQ,gBAAiB,MAAK,WAAW,MAAM;AACnE,eAAS,YAAY,WAAW,KAAK,KAAK,KAAK,KAAK;AACpD,WAAK,WAAW,IAAI,OAAO,MAAM;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,MAAM;AACX,QAAI,KAAK,WAAY,MAAK,OAAO,OAAO;AAAA,EAC1C;AACF;;;ACzNA,IAAM,WAAW,MAAO;AAExB,IAAM,WAAW;AAMV,IAAM,WAAN,MAAe;AAAA,EAcpB,YAAY,QAA4B,gBAA+B,CAAC,GAAG;AAb3E,SAAiB,OAAO,IAAI,aAAa;AACzC,SAAiB,WAA4B;AAC7C,SAAQ,UAAyB;AAEjC;AAAA,SAAQ,WAAW;AACnB,SAAQ,SAAS;AACjB,SAAQ,YAAY;AACpB,SAAiB,mBAA4B;AAE7C;AAAA,SAAQ,iBAAwC;AAChD,SAAiB,WAAW,oBAAI,IAAmC;AACnE,SAAiB,YAAY,oBAAI,IAAoC;AAyHrE,SAAiB,eAAe,MAAY;AAC1C,WAAK,UAAU,OAAO;AAAA,IACxB;AAEA,SAAiB,yBAAyB,MAAY;AACpD,UAAI,SAAS,QAAQ;AACnB,aAAK,YAAY;AAAA,MACnB,OAAO;AACL,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AA0BA,SAAiB,OAAO,CAAC,SAAuB;AAC9C,WAAK,UAAU;AACf,UAAI,CAAC,KAAK,SAAU;AAEpB,YAAM,KAAK,OAAO,OAAO,KAAK,YAAY,UAAU,GAAG,QAAQ;AAC/D,WAAK,WAAW;AAEhB,YAAM,EAAE,OAAO,OAAO,IAAI,KAAK,SAAS,cAAc;AACtD,YAAM,eAAe,gBAAgB,KAAK,MAAM,IAAI,OAAO,MAAM;AACjE,WAAK,SAAS,OAAO,KAAK,IAAI;AAE9B,UAAI,cAAc;AAChB,aAAK,UAAU,sBAAsB,KAAK,IAAI;AAAA,MAChD;AAAA,IACF;AAxKE,QAAI,CAAC,UAAU,GAAG;AAChB,WAAK,YAAY;AACjB;AAAA,IACF;AAEA,SAAK,WAAW,IAAI,SAAS,MAAM;AACnC,SAAK,mBAAmB,cAAc,WAAW;AACjD,QAAI,KAAK,kBAAkB;AACzB,aAAO,iBAAiB,UAAU,KAAK,YAAY;AACnD,UAAI,UAAU,OAAO,mBAAmB,aAAa;AACnD,aAAK,iBAAiB,IAAI,eAAe,KAAK,YAAY;AAC1D,aAAK,eAAe,QAAQ,MAAM;AAAA,MACpC;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,KAAK,sBAAsB;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,SAAiC;AACpC,QAAI,KAAK,aAAa,CAAC,KAAK,YAAY,SAAS,OAAQ;AAEzD,UAAM,WAAW,eAAe,OAAO;AACvC,QAAI,SAAS,2BAA2B,qBAAqB,EAAG;AAEhE,SAAK,SAAS,UAAU,SAAS,MAAM;AACvC,UAAM,EAAE,OAAO,OAAO,IAAI,KAAK,SAAS,cAAc;AACtD,SAAK,KAAK,MAAM,UAAU,OAAO,MAAM;AACvC,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,MAAkB,SAAiC;AACxD,QAAI,CAAC,aAAa,IAAI,KAAK,KAAK,UAAW;AAE3C,eAAW,SAAS,QAAQ,IAAI,EAAE,QAAQ;AACxC,YAAM,SAAS,aAAa,MAAM,SAAS,OAAO;AAClD,UAAI,MAAM,OAAO;AACf,cAAM,KAAK,WAAW,MAAM;AAC1B,eAAK,SAAS,OAAO,EAAE;AACvB,eAAK,KAAK,MAAM;AAAA,QAClB,GAAG,MAAM,KAAK;AACd,aAAK,SAAS,IAAI,EAAE;AAAA,MACtB,OAAO;AACL,aAAK,KAAK,MAAM;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,SAA2B,WAAW,KAAiB;AAChE,QAAI,KAAK,UAAW,QAAO,MAAM;AAAA,IAAC;AAElC,UAAM,SAAS,aAAa,qBAAqB,OAAO;AACxD,UAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK,YAAY,KAAK,WAAW;AACvE,UAAM,KAAK,YAAY,MAAM,KAAK,KAAK,MAAM,GAAG,KAAK;AACrD,SAAK,UAAU,IAAI,EAAE;AAErB,WAAO,MAAM;AACX,oBAAc,EAAE;AAChB,WAAK,UAAU,OAAO,EAAE;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS;AACd,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAe;AACb,SAAK,SAAS;AACd,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACZ,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,eAAW,MAAM,KAAK,SAAU,cAAa,EAAE;AAC/C,eAAW,MAAM,KAAK,UAAW,eAAc,EAAE;AACjD,SAAK,SAAS,MAAM;AACpB,SAAK,UAAU,MAAM;AACrB,SAAK,KAAK,MAAM;AAChB,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AACd,QAAI,KAAK,UAAW;AACpB,SAAK,MAAM;AACX,SAAK,YAAY;AAEjB,QAAI,KAAK,iBAAkB,QAAO,oBAAoB,UAAU,KAAK,YAAY;AACjF,SAAK,gBAAgB,WAAW;AAChC,SAAK,iBAAiB;AACtB,aAAS,oBAAoB,oBAAoB,KAAK,sBAAsB;AAC5E,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAiBQ,gBAAsB;AAC5B,QACE,KAAK,YAAY,QACjB,KAAK,UACL,KAAK,aACL,SAAS,UACT,KAAK,KAAK,gBAAgB,GAC1B;AACA;AAAA,IACF;AACA,SAAK,WAAW,YAAY,IAAI;AAChC,SAAK,UAAU,sBAAsB,KAAK,IAAI;AAAA,EAChD;AAAA,EAEQ,cAAoB;AAC1B,QAAI,KAAK,YAAY,MAAM;AACzB,2BAAqB,KAAK,OAAO;AACjC,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAiBF;;;AC7KA,IAAI,iBAAkC;AAEtC,SAAS,oBAAqC;AAC5C,MAAI,CAAC,UAAU,EAAG,QAAO;AACzB,sCAAmB,IAAI,SAAS;AAChC,SAAO;AACT;AAKO,SAAS,KAAK,SAAiC;AACpD,oBAAkB,GAAG,KAAK,OAAO;AACnC;AAKO,SAAS,WAAW,MAAkB,SAAiC;AAC5E,oBAAkB,GAAG,OAAO,MAAM,OAAO;AAC3C;AAKO,SAAS,kBAAkB,SAA0B;AAC1D,QAAM,OAAO,QAAQ,sBAAsB;AAC3C,SAAO;AAAA,IACL,IAAI,KAAK,OAAO,KAAK,QAAQ,KAAK,OAAO;AAAA,IACzC,IAAI,KAAK,MAAM,KAAK,SAAS,KAAK,OAAO;AAAA,EAC3C;AACF;AAQO,SAAS,gBAAgB,SAAkB,UAAkC,CAAC,GAAS;AAC5F,MAAI,CAAC,UAAU,EAAG;AAElB,QAAM,EAAE,QAAQ,MAAM,GAAG,KAAK,IAAI;AAElC,QAAM,SAAS,aAAa,IAAI,IAAI,OAAO;AAC3C,QAAM,gBAAgB,SAAS,QAAQ,MAAM,EAAE,gBAAgB;AAC/D,QAAM,SAAS,gBACX,EAAE,GAAG,MAAM,QAAQ,YAAY,kBAAkB,OAAO,GAAG,KAAK,MAAM,EAAE,IACxE;AAEJ,MAAI,QAAQ;AACV,eAAW,QAAQ,MAAM;AAAA,EAC3B,OAAO;AACL,SAAK,MAAM;AAAA,EACb;AACF;AAKO,SAAS,QAAc;AAC5B,kBAAgB,MAAM;AACxB;AAKO,SAAS,UAAgB;AAC9B,kBAAgB,QAAQ;AACxB,mBAAiB;AACnB;AAKO,SAAS,OAAO,QAA2B,eAAiD;AACjG,QAAM,WAAW,IAAI,SAAS,QAAQ,aAAa;AAEnD,QAAM,UAAU,CAAC,YAA8B,SAAS,KAAK,OAAO;AACpE,SAAO,SAAS,CAAC,MAAM,YAAY,SAAS,OAAO,MAAM,OAAO;AAChE,SAAO,aAAa,CAAC,SAAS,aAAa,SAAS,WAAW,SAAS,QAAQ;AAChF,SAAO,QAAQ,MAAM,SAAS,MAAM;AACpC,SAAO,UAAU,MAAM,SAAS,QAAQ;AAExC,SAAO;AACT;AAKO,SAAS,WAAW,SAA2B,UAA+B;AACnF,SAAO,kBAAkB,GAAG,WAAW,SAAS,QAAQ,MAAM,MAAM;AAAA,EAAC;AACvE;AAGO,IAAM,SAAS,CAAC,YAAoC,WAAW,UAAU,OAAO;AAGhF,IAAM,YAAY,CAAC,YAAoC,WAAW,aAAa,OAAO;AAGtF,IAAM,YAAY,CAAC,YAAoC,WAAW,aAAa,OAAO;AAGtF,IAAM,OAAO,CAAC,YAAoC,WAAW,QAAQ,OAAO;AAG5E,IAAM,OAAO,CAAC,YAAoC,WAAW,QAAQ,OAAO;AAG5E,IAAM,cAAc,CAAC,YAAoC,WAAW,eAAe,OAAO;AAG1F,IAAM,QAAQ,CAAC,YAAoC,WAAW,SAAS,OAAO;","names":[]}
@@ -1,2 +1,2 @@
1
- "use strict";var konfetti=(()=>{var I=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var le=(t,e)=>{for(var i in e)I(t,i,{get:e[i],enumerable:!0})},de=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ae(e))!ce.call(t,n)&&n!==i&&I(t,n,{get:()=>e[n],enumerable:!(r=se(e,n))||r.enumerable});return t};var pe=t=>de(I({},"__esModule",{value:!0}),t);var Ce={};le(Ce,{Konfetti:()=>h,PRESET_NAMES:()=>F,cannon:()=>$,continuous:()=>J,create:()=>Q,destroy:()=>G,explosion:()=>ee,fire:()=>A,fireFromElement:()=>q,firePreset:()=>p,fireworks:()=>te,isPresetName:()=>y,originFromElement:()=>k,pride:()=>oe,rain:()=>ie,reset:()=>j,sideCannons:()=>re,snow:()=>ne});function z(t,e){t.beginPath(),t.arc(0,0,e/2,0,Math.PI*2),t.fill()}function fe(t,e){let i=e/2;t.fillRect(-i,-i,e,e)}var D=["circle","square"],he=[z,fe];function Z(t){return D.includes(t)}function _(t){return Math.max(0,D.indexOf(t))}function W(t){return he[t]??z}var ue=["#26ccff","#a25afd","#ff5e7e","#88ff5a","#fcff42","#ffa62d","#ff36ff"],me={particleCount:50,angle:90,spread:45,startVelocity:45,decay:.9,gravity:1,drift:0,ticks:200,origin:{x:.5,y:.5},colors:ue,shapes:["circle","square"],scalar:1,zIndex:100,disableForReducedMotion:!0};function l(t,e){return typeof t=="number"&&Number.isFinite(t)?t:e}function X(t={}){let e=me,i=Array.isArray(t.colors)?t.colors.filter(n=>typeof n=="string"&&n.length>0):[],r=Array.isArray(t.shapes)?t.shapes.filter(Z):[];return{particleCount:Math.max(0,Math.round(l(t.particleCount,e.particleCount))),angle:l(t.angle,e.angle),spread:l(t.spread,e.spread),startVelocity:l(t.startVelocity,e.startVelocity),decay:T(l(t.decay,e.decay),0,1),gravity:l(t.gravity,e.gravity),drift:l(t.drift,e.drift),ticks:Math.max(1,l(t.ticks,e.ticks)),origin:{x:l(t.origin?.x,e.origin.x),y:l(t.origin?.y,e.origin.y)},colors:i.length>0?i:[...e.colors],shapes:r.length>0?r:[...e.shapes],scalar:Math.max(0,l(t.scalar,e.scalar)),zIndex:l(t.zIndex,e.zIndex),disableForReducedMotion:t.disableForReducedMotion??e.disableForReducedMotion}}function R(t,e){let i={...t};if(e){for(let[r,n]of Object.entries(e))n!==void 0&&(i[r]=n);e.origin&&(i.origin=S(t.origin,e.origin))}return i}function S(t,e){return{...t,...e?.x!==void 0&&{x:e.x},...e?.y!==void 0&&{y:e.y}}}function E(t){return t*(Math.PI/180)}function f(t,e){return Math.random()*(e-t)+t}function P(t){return t[Math.floor(Math.random()*t.length)]}function x(){return typeof window<"u"&&typeof document<"u"}function B(){return typeof window>"u"?!1:window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches??!1}function T(t,e,i){return Math.min(Math.max(t,e),i)}var H=1e4,ye=256,b=class{constructor(e=512){this.activeCount=0;this.palette=[];this.colorIds=new Map;this.data=new Float32Array(e*16)}get capacity(){return this.data.length/16}reset(){this.activeCount=0,this.clearPalette()}spawn(e,i,r){let n=Math.min(e.particleCount,H-this.activeCount);if(n<=0)return;this.ensureCapacity(this.activeCount+n);let o=this.data,s=e.origin.x*i,c=e.origin.y*r,u=E(e.angle),d=E(e.spread);for(let m=0;m<n;m++){let a=(this.activeCount+m)*16,g=u+f(-d/2,d/2),v=e.startVelocity*f(.5,1);o[a+0]=s,o[a+1]=c,o[a+2]=Math.cos(g)*v,o[a+3]=-Math.sin(g)*v,o[a+4]=f(0,Math.PI*2),o[a+5]=f(-.1,.1),o[a+6]=f(0,Math.PI*2),o[a+7]=f(.05,.15),o[a+8]=this.colorId(P(e.colors)),o[a+9]=_(P(e.shapes)),o[a+10]=e.scalar*f(.8,1.2),o[a+11]=e.ticks,o[a+12]=e.ticks,o[a+13]=e.drift+f(-.5,.5),o[a+14]=e.gravity,o[a+15]=e.decay}this.activeCount+=n}compact(){let e=this.data,i=0;for(let r=0;r<this.activeCount;r++){let n=r*16;if(!(e[n+11]<=0)){if(i!==r){let o=i*16;e.copyWithin(o,n,n+16)}i++}}this.activeCount=i,i===0?this.clearPalette():this.palette.length>ye&&this.prunePalette()}prunePalette(){let e=this.data,i=[...this.palette],r=new Map;this.clearPalette();for(let n=0;n<this.activeCount;n++){let o=n*16+8,s=e[o],c=r.get(s);c===void 0&&(c=this.colorId(i[s]),r.set(s,c)),e[o]=c}}colorId(e){let i=this.colorIds.get(e);return i===void 0&&(i=this.palette.length,this.palette.push(e),this.colorIds.set(e,i)),i}clearPalette(){this.palette.length=0,this.colorIds.clear()}ensureCapacity(e){if(e<=this.capacity)return;let i=this.capacity;for(;i<e;)i*=2;let r=new Float32Array(Math.min(i,H)*16);r.set(this.data.subarray(0,this.activeCount*16)),this.data=r}};function U(t,e){let i=t.data;for(let r=0;r<t.activeCount;r++){let n=r*16,o=i[n+2],s=i[n+3],c=i[n+6];s+=i[n+14]*e,o+=i[n+13]*Math.sin(c)*e;let u=i[n+15]**e;o*=u,s*=u,i[n+2]=o,i[n+3]=s,i[n+0]+=o*e,i[n+1]+=s*e,i[n+4]+=i[n+5]*e,i[n+6]=c+i[n+7]*e,i[n+11]-=e}return t.compact(),t.activeCount>0}var ge=["#ff0000","#ffff00","#00ff00","#00ffff","#ff00ff"],M={particleCount:80,angle:90,spread:360,startVelocity:35,decay:.91,gravity:1,colors:ge},ve=["#e40303","#ff8c00","#ffed00","#008026","#004dff","#750787"],w={cannon:{followsOrigin:!0,bursts:[{options:{particleCount:100,angle:90,spread:70,startVelocity:50,decay:.91,gravity:1,origin:{x:.5,y:1}}}]},explosion:{followsOrigin:!0,bursts:[{options:{particleCount:150,angle:90,spread:360,startVelocity:40,decay:.92,gravity:.8,origin:{x:.5,y:.5}}}]},fireworks:{followsOrigin:!1,bursts:[{delay:0,options:{...M,origin:{x:.3,y:.4}}},{delay:150,options:{...M,origin:{x:.5,y:.3}}},{delay:300,options:{...M,origin:{x:.7,y:.4}}}]},rain:{followsOrigin:!1,bursts:[{options:{particleCount:50,angle:270,spread:60,startVelocity:10,decay:.95,gravity:.5,drift:0,origin:{x:.5,y:0},ticks:300}}]},snow:{followsOrigin:!1,bursts:[{options:{particleCount:30,angle:270,spread:120,startVelocity:5,decay:.98,gravity:.3,drift:1,origin:{x:.5,y:-.1},ticks:400,colors:["#ffffff","#e0e0e0","#c0c0c0"],shapes:["circle"]}}]},sideCannons:{followsOrigin:!1,bursts:[{options:{particleCount:50,angle:60,spread:55,startVelocity:50,origin:{x:0,y:.7}}},{options:{particleCount:50,angle:120,spread:55,startVelocity:50,origin:{x:1,y:.7}}}]},pride:{followsOrigin:!0,bursts:[{options:{particleCount:100,spread:70,origin:{x:.5,y:.6},colors:ve}}]}},Y={particleCount:10,angle:90,spread:55,startVelocity:45,origin:{x:.5,y:1}},F=Object.keys(w);function y(t){return typeof t=="string"&&F.includes(t)}var xe=10;function we(){let t=document.createElement("canvas");return t.className="konfetti-canvas",t.setAttribute("aria-hidden","true"),Object.assign(t.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:"100"}),document.body.appendChild(t),t}var C=class{constructor(e){this.width=0;this.height=0;this.pixelRatio=1;this.buckets=[];this.ownsCanvas=!e,this.canvas=e??we(),this.ctx=this.canvas.getContext("2d"),this.resize()}resize(){if(this.ownsCanvas)this.width=window.innerWidth,this.height=window.innerHeight,this.pixelRatio=window.devicePixelRatio||1;else{let e=this.canvas.getBoundingClientRect();this.width=e.width,this.height=e.height,this.pixelRatio=1}this.canvas.width=Math.round(this.width*this.pixelRatio),this.canvas.height=Math.round(this.height*this.pixelRatio)}getDimensions(){return{width:this.width,height:this.height}}setZIndex(e){this.ownsCanvas&&(this.canvas.style.zIndex=String(e))}clear(){this.ctx&&(this.ctx.setTransform(1,0,0,1,0,0),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height))}render(e){this.clear();let i=this.ctx;if(!i)return;let r=e.data,n=this.pixelRatio,o=this.buckets;for(let s of o)s.length=0;for(let s=0;s<e.activeCount;s++){let c=r[s*16+8];o[c]||(o[c]=[]),o[c].push(s)}for(let s=0;s<o.length;s++){let c=o[s];if(!(!c||c.length===0)){i.fillStyle=e.palette[s];for(let u of c){let d=u*16,m=r[d+6],a=r[d+4],g=Math.min(1,r[d+11]/r[d+12]*2),v=xe*r[d+10]*(.8+.2*Math.cos(m));if(v<.5||g<.01)continue;let N=Math.cos(a),L=Math.sin(a),V=.6+.4*Math.abs(Math.cos(m));i.globalAlpha=g,i.setTransform(n*N,n*L,-n*L*V,n*N*V,n*r[d+0],n*r[d+1]),W(r[d+9])(i,v)}}}i.globalAlpha=1,i.setTransform(1,0,0,1,0,0)}destroy(){this.clear(),this.ownsCanvas&&this.canvas.remove()}};var Oe=1e3/60,be=4,h=class{constructor(e,i={}){this.pool=new b;this.renderer=null;this.frameId=null;this.lastTime=0;this.paused=!1;this.destroyed=!1;this.resizeWithWindow=!1;this.timeouts=new Set;this.intervals=new Set;this.handleResize=()=>{this.renderer?.resize()};this.handleVisibilityChange=()=>{document.hidden?this.cancelFrame():this.scheduleFrame()};this.tick=e=>{if(this.frameId=null,!this.renderer)return;let i=T((e-this.lastTime)/Oe,0,be);this.lastTime=e;let r=U(this.pool,i);this.renderer.render(this.pool),r&&(this.frameId=requestAnimationFrame(this.tick))};if(!x()){this.destroyed=!0;return}this.renderer=new C(e),this.resizeWithWindow=i.resize!==!1,this.resizeWithWindow&&window.addEventListener("resize",this.handleResize),document.addEventListener("visibilitychange",this.handleVisibilityChange)}fire(e){if(this.destroyed||!this.renderer||document.hidden)return;let i=X(e);if(i.disableForReducedMotion&&B())return;this.renderer.setZIndex(i.zIndex);let{width:r,height:n}=this.renderer.getDimensions();this.pool.spawn(i,r,n),this.scheduleFrame()}preset(e,i){if(!(!y(e)||this.destroyed))for(let r of w[e].bursts){let n=R(r.options,i);if(r.delay){let o=setTimeout(()=>{this.timeouts.delete(o),this.fire(n)},r.delay);this.timeouts.add(o)}else this.fire(n)}}continuous(e,i=250){if(this.destroyed)return()=>{};let r=R(Y,e),n=Number.isFinite(i)&&i>=16?i:250,o=setInterval(()=>this.fire(r),n);return this.intervals.add(o),()=>{clearInterval(o),this.intervals.delete(o)}}pause(){this.paused=!0,this.cancelFrame()}resume(){this.paused=!1,this.scheduleFrame()}reset(){this.paused=!1,this.cancelFrame();for(let e of this.timeouts)clearTimeout(e);for(let e of this.intervals)clearInterval(e);this.timeouts.clear(),this.intervals.clear(),this.pool.reset(),this.renderer?.clear()}destroy(){this.destroyed||(this.reset(),this.destroyed=!0,this.resizeWithWindow&&window.removeEventListener("resize",this.handleResize),document.removeEventListener("visibilitychange",this.handleVisibilityChange),this.renderer?.destroy())}scheduleFrame(){this.frameId!==null||this.paused||this.destroyed||document.hidden||this.pool.activeCount===0||(this.lastTime=performance.now(),this.frameId=requestAnimationFrame(this.tick))}cancelFrame(){this.frameId!==null&&(cancelAnimationFrame(this.frameId),this.frameId=null)}};var O=null;function K(){return x()?(O??(O=new h),O):null}function A(t){K()?.fire(t)}function p(t,e){K()?.preset(t,e)}function k(t){let e=t.getBoundingClientRect();return{x:(e.left+e.width/2)/window.innerWidth,y:(e.top+e.height/2)/window.innerHeight}}function q(t,e={}){if(!x())return;let{preset:i,...r}=e,n=y(i)?i:void 0,s=(n?w[n].followsOrigin:!0)?{...r,origin:S(k(t),r.origin)}:r;n?p(n,s):A(s)}function j(){O?.reset()}function G(){O?.destroy(),O=null}function Q(t,e){let i=new h(t,e),r=(n=>i.fire(n));return r.preset=(n,o)=>i.preset(n,o),r.continuous=(n,o)=>i.continuous(n,o),r.reset=()=>i.reset(),r.destroy=()=>i.destroy(),r}function J(t,e){return K()?.continuous(t,e)??(()=>{})}var $=t=>p("cannon",t),ee=t=>p("explosion",t),te=t=>p("fireworks",t),ie=t=>p("rain",t),ne=t=>p("snow",t),re=t=>p("sideCannons",t),oe=t=>p("pride",t);return pe(Ce);})();
1
+ "use strict";var konfetti=(()=>{var E=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var ve=Object.prototype.hasOwnProperty;var be=(t,e)=>{for(var i in e)E(t,i,{get:e[i],enumerable:!0})},xe=(t,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ge(e))!ve.call(t,r)&&r!==i&&E(t,r,{get:()=>e[r],enumerable:!(n=ye(e,r))||n.enumerable});return t};var Oe=t=>xe(E({},"__esModule",{value:!0}),t);var $e={};be($e,{Konfetti:()=>m,PRESET_NAMES:()=>N,cannon:()=>oe,continuous:()=>re,create:()=>ne,destroy:()=>ie,explosion:()=>se,fire:()=>k,fireFromElement:()=>ee,firePreset:()=>u,fireworks:()=>ae,isPresetName:()=>y,originFromElement:()=>_,pride:()=>fe,rain:()=>ce,reset:()=>te,sideCannons:()=>de,snow:()=>le});function V(t,e){t.beginPath(),t.arc(0,0,e/2,0,Math.PI*2),t.fill()}function Se(t,e){let i=e/2;t.fillRect(-i,-i,e,e)}var X=["circle","square"],we=[V,Se];function W(t){return X.includes(t)}function Y(t){return Math.max(0,X.indexOf(t))}function H(t){return we[t]??V}var Ce=["#26ccff","#a25afd","#ff5e7e","#88ff5a","#fcff42","#ffa62d","#ff36ff"],Re={particleCount:50,angle:90,spread:45,startVelocity:45,decay:.9,gravity:1,drift:0,ticks:600,origin:{x:.5,y:.5},colors:Ce,shapes:["circle","square"],scalar:1,zIndex:100,disableForReducedMotion:!0};function p(t,e){return typeof t=="number"&&Number.isFinite(t)?t:e}function Z(t={}){let e=Re,i=Array.isArray(t.colors)?t.colors.filter(r=>typeof r=="string"&&r.length>0):[],n=Array.isArray(t.shapes)?t.shapes.filter(W):[];return{particleCount:Math.max(0,Math.round(p(t.particleCount,e.particleCount))),angle:p(t.angle,e.angle),spread:p(t.spread,e.spread),startVelocity:p(t.startVelocity,e.startVelocity),decay:K(p(t.decay,e.decay),0,1),gravity:p(t.gravity,e.gravity),drift:p(t.drift,e.drift),ticks:Math.max(1,p(t.ticks,e.ticks)),origin:{x:p(t.origin?.x,e.origin.x),y:p(t.origin?.y,e.origin.y)},colors:i.length>0?i:[...e.colors],shapes:n.length>0?n:[...e.shapes],scalar:Math.max(0,p(t.scalar,e.scalar)),zIndex:p(t.zIndex,e.zIndex),disableForReducedMotion:t.disableForReducedMotion??e.disableForReducedMotion}}function P(t,e){let i={...t};if(e){for(let[n,r]of Object.entries(e))r!==void 0&&(i[n]=r);e.origin&&(i.origin=M(t.origin,e.origin))}return i}function M(t,e){return{...t,...e?.x!==void 0&&{x:e.x},...e?.y!==void 0&&{y:e.y}}}function T(t){return t*(Math.PI/180)}function h(t,e){return Math.random()*(e-t)+t}function A(){return Math.random()<.5?-1:1}function F(t){return t[Math.floor(Math.random()*t.length)]}function b(){return typeof window<"u"&&typeof document<"u"}function G(){return typeof window>"u"?!1:window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches??!1}function K(t,e,i){return Math.min(Math.max(t,e),i)}var B=1e4,Ie=256,C=class{constructor(e=512){this.activeCount=0;this.palette=[];this.colorIds=new Map;this.data=new Float32Array(e*25)}get capacity(){return this.data.length/25}reset(){this.activeCount=0,this.clearPalette()}spawn(e,i,n){let r=Math.min(e.particleCount,B-this.activeCount);if(r<=0)return;this.ensureCapacity(this.activeCount+r);let o=this.data,s=e.origin.x*i,c=e.origin.y*n,f=T(e.angle),l=T(e.spread);for(let d=0;d<r;d++){let a=(this.activeCount+d)*25,v=f+h(-l/2,l/2),S=e.startVelocity*h(.5,1);o[a+0]=s,o[a+1]=c,o[a+2]=Math.cos(v)*S,o[a+3]=-Math.sin(v)*S,o[a+6]=h(0,Math.PI*2),o[a+7]=h(.08,.22)*A(),o[a+16]=h(0,Math.PI*2),o[a+17]=h(.02,.07)*A(),o[a+4]=h(0,Math.PI*2),o[a+5]=h(-.04,.04),o[a+8]=this.colorId(F(e.colors)),o[a+9]=Y(F(e.shapes)),o[a+10]=e.scalar*h(.8,1.2),o[a+11]=e.ticks,o[a+12]=e.ticks,o[a+13]=e.drift+h(-.5,.5),o[a+14]=e.gravity,o[a+15]=e.decay,o[a+18]=h(0,Math.PI*2),o[a+19]=h(.02,.05)}this.activeCount+=r}compact(){let e=this.data,i=0;for(let n=0;n<this.activeCount;n++){let r=n*25;if(!(e[r+11]<=0)){if(i!==n){let o=i*25;e.copyWithin(o,r,r+25)}i++}}this.activeCount=i,i===0?this.clearPalette():this.palette.length>Ie&&this.prunePalette()}prunePalette(){let e=this.data,i=[...this.palette],n=new Map;this.clearPalette();for(let r=0;r<this.activeCount;r++){let o=r*25+8,s=e[o],c=n.get(s);c===void 0&&(c=this.colorId(i[s]),n.set(s,c)),e[o]=c}}colorId(e){let i=this.colorIds.get(e);return i===void 0&&(i=this.palette.length,this.palette.push(e),this.colorIds.set(e,i)),i}clearPalette(){this.palette.length=0,this.colorIds.clear()}ensureCapacity(e){if(e<=this.capacity)return;let i=this.capacity;for(;i<e;)i*=2;let n=new Float32Array(Math.min(i,B)*25);n.set(this.data.subarray(0,this.activeCount*25)),this.data=n}};var Ee=-.3,Pe=-.6,Me=.742;function U(t){let e=t[8]<0?-1:1;return Math.max(0,e*(t[6]*Ee+t[7]*Pe+t[8]*Me))}function $(){return new Float64Array(9)}function q(t,e,i){let n=t[e+6],r=t[e+16],o=t[e+4],s=Math.cos(n),c=Math.sin(n),f=Math.cos(r),l=Math.sin(r),d=Math.cos(o),a=Math.sin(o);return i[0]=d*f,i[1]=a*f,i[2]=-l,i[3]=d*l*c-a*s,i[4]=a*l*c+d*s,i[5]=f*c,i[6]=d*l*s+a*c,i[7]=a*l*s-d*c,i[8]=f*s,i}var Te=.45,Ae=.0475,Fe=4,Ke=.6,Le=1,R=60,Ne=$();function j(t,e,i,n){let r=t.data;for(let o=0;o<t.activeCount;o++)ze(r,o*25,e,i,n);return t.compact(),t.activeCount>0}function ze(t,e,i,n,r){let o=t[e+2],s=t[e+3],c=q(t,e,Ne),f=c[6],l=c[7];if(t[e+20]=c[0],t[e+21]=c[1],t[e+22]=c[3],t[e+23]=c[4],t[e+24]=U(c),s+=t[e+14]*Te*i,s>0){let w=Ae*(.35+.65*Math.abs(l));s=Math.max(0,s-w*s*Math.min(s,Fe)*i),o-=Ke*s*2*f*l*i}let d=t[e+18],a=t[e+13]+Le*Math.sin(d),v=t[e+15]**i;o=a+(o-a)*v,s*=v;let S=.6+Math.min(1.4,Math.hypot(o,s)/3);if(t[e+2]=o,t[e+3]=s,t[e+0]+=o*i,t[e+1]+=s*i,t[e+6]+=t[e+7]*S*i,t[e+16]+=t[e+17]*i,t[e+4]+=t[e+5]*i,t[e+18]=d+t[e+19]*i,t[e+11]-=i,n>0&&r>0){let w=t[e+0],D=t[e+1],he=D>r+R&&s>=0,pe=w<-R*2&&o<=0,ue=w>n+R*2&&o>=0,me=D<-R&&s<=0&&t[e+14]<=0;(he||pe||ue||me)&&(t[e+11]=0)}}var ke=["#ff0000","#ffff00","#00ff00","#00ffff","#ff00ff"],L={particleCount:80,angle:90,spread:360,startVelocity:35,decay:.91,gravity:1,colors:ke},_e=["#e40303","#ff8c00","#ffed00","#008026","#004dff","#750787"],x={cannon:{followsOrigin:!0,bursts:[{options:{particleCount:100,angle:90,spread:70,startVelocity:50,decay:.91,gravity:1,origin:{x:.5,y:1}}}]},explosion:{followsOrigin:!0,bursts:[{options:{particleCount:150,angle:90,spread:360,startVelocity:40,decay:.92,gravity:.8,origin:{x:.5,y:.5}}}]},fireworks:{followsOrigin:!1,bursts:[{delay:0,options:{...L,origin:{x:.3,y:.4}}},{delay:150,options:{...L,origin:{x:.5,y:.3}}},{delay:300,options:{...L,origin:{x:.7,y:.4}}}]},rain:{followsOrigin:!1,bursts:[{options:{particleCount:50,angle:270,spread:60,startVelocity:10,decay:.95,gravity:.5,drift:0,origin:{x:.5,y:0},ticks:900}}]},snow:{followsOrigin:!1,bursts:[{options:{particleCount:30,angle:270,spread:120,startVelocity:5,decay:.98,gravity:.3,drift:1,origin:{x:.5,y:-.1},ticks:1200,colors:["#ffffff","#e0e0e0","#c0c0c0"],shapes:["circle"]}}]},sideCannons:{followsOrigin:!1,bursts:[{options:{particleCount:50,angle:60,spread:55,startVelocity:50,origin:{x:0,y:.7}}},{options:{particleCount:50,angle:120,spread:55,startVelocity:50,origin:{x:1,y:.7}}}]},pride:{followsOrigin:!0,bursts:[{options:{particleCount:100,spread:70,origin:{x:.5,y:.6},colors:_e}}]}},Q={particleCount:10,angle:90,spread:55,startVelocity:45,origin:{x:.5,y:1}},N=Object.keys(x);function y(t){return typeof t=="string"&&N.includes(t)}var De=10,g=16,J=.55,Ve=1.2,Xe=.1,We=4096,Ye=[0,0,0,1];function He(t,e){t.fillStyle="#000000",t.fillStyle=e;let i=String(t.fillStyle);if(t.fillStyle="#ffffff",t.fillStyle=e,String(t.fillStyle)!==i)return null;let n=/^#([0-9a-f]{6})$/i.exec(i);if(n){let s=Number.parseInt(n[1],16);return[s>>16,s>>8&255,s&255,1]}let r=/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?/.exec(i);if(!r)return null;let o=r[4]===void 0?1:Number(r[4]);return[Number(r[1]),Number(r[2]),Number(r[3]),o]}function Ze([t,e,i,n]){let r=[];for(let o=0;o<g;o++){let s=J+(Ve-J)*o/(g-1),[c,f,l]=[t,e,i].map(d=>Math.round(s<=1?d*s:d+(255-d)*(s-1)));r.push(n<1?`rgba(${c}, ${f}, ${l}, ${n})`:`rgb(${c}, ${f}, ${l})`)}return r}function Ge(){let t=document.createElement("canvas");return t.className="konfetti-canvas",t.setAttribute("aria-hidden","true"),Object.assign(t.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",pointerEvents:"none",zIndex:"100"}),document.body.appendChild(t),t}var I=class{constructor(e){this.width=0;this.height=0;this.pixelRatio=1;this.shadeCache=new Map;this.buckets=[];this.ownsCanvas=!e,this.canvas=e??Ge(),this.ctx=this.canvas.getContext("2d"),this.resize()}resize(){if(this.ownsCanvas)this.width=window.innerWidth,this.height=window.innerHeight,this.pixelRatio=window.devicePixelRatio||1;else{let e=this.canvas.getBoundingClientRect();this.width=e.width,this.height=e.height,this.pixelRatio=1}this.canvas.width=Math.round(this.width*this.pixelRatio),this.canvas.height=Math.round(this.height*this.pixelRatio)}getDimensions(){return{width:this.width,height:this.height}}setZIndex(e){this.ownsCanvas&&(this.canvas.style.zIndex=String(e))}clear(){this.ctx&&(this.ctx.setTransform(1,0,0,1,0,0),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height))}render(e){this.clear();let i=this.ctx;if(!i)return;let n=e.data,r=this.pixelRatio,o=this.buckets;for(let s of o)s&&(s.length=0);for(let s=0;s<e.activeCount;s++){let c=s*25,f=Math.round(n[c+24]*(g-1)),l=n[c+8]*g+f;o[l]||(o[l]=[]),o[l].push(c)}for(let s=0;s<o.length;s++){let c=o[s];if(!c||c.length===0)continue;let f=e.palette[Math.floor(s/g)];i.fillStyle=this.shadesFor(i,f)[s%g];for(let l of c){let d=Math.min(1,n[l+11]/(n[l+12]*Xe)),a=De*n[l+10];a<.5||d<.01||(i.globalAlpha=d,i.setTransform(r*n[l+20],r*n[l+21],r*n[l+22],r*n[l+23],r*n[l+0],r*n[l+1]),H(n[l+9])(i,a))}}i.globalAlpha=1,i.setTransform(1,0,0,1,0,0)}shadesFor(e,i){let n=this.shadeCache.get(i);return n||(this.shadeCache.size>=We&&this.shadeCache.clear(),n=Ze(He(e,i)??Ye),this.shadeCache.set(i,n)),n}destroy(){this.clear(),this.ownsCanvas&&this.canvas.remove()}};var Be=1e3/60,Ue=4,m=class{constructor(e,i={}){this.pool=new C;this.renderer=null;this.frameId=null;this.lastTime=0;this.paused=!1;this.destroyed=!1;this.resizeWithWindow=!1;this.resizeObserver=null;this.timeouts=new Set;this.intervals=new Set;this.handleResize=()=>{this.renderer?.resize()};this.handleVisibilityChange=()=>{document.hidden?this.cancelFrame():this.scheduleFrame()};this.tick=e=>{if(this.frameId=null,!this.renderer)return;let i=K((e-this.lastTime)/Be,0,Ue);this.lastTime=e;let{width:n,height:r}=this.renderer.getDimensions(),o=j(this.pool,i,n,r);this.renderer.render(this.pool),o&&(this.frameId=requestAnimationFrame(this.tick))};if(!b()){this.destroyed=!0;return}this.renderer=new I(e),this.resizeWithWindow=i.resize!==!1,this.resizeWithWindow&&(window.addEventListener("resize",this.handleResize),e&&typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(this.handleResize),this.resizeObserver.observe(e))),document.addEventListener("visibilitychange",this.handleVisibilityChange)}fire(e){if(this.destroyed||!this.renderer||document.hidden)return;let i=Z(e);if(i.disableForReducedMotion&&G())return;this.renderer.setZIndex(i.zIndex);let{width:n,height:r}=this.renderer.getDimensions();this.pool.spawn(i,n,r),this.scheduleFrame()}preset(e,i){if(!(!y(e)||this.destroyed))for(let n of x[e].bursts){let r=P(n.options,i);if(n.delay){let o=setTimeout(()=>{this.timeouts.delete(o),this.fire(r)},n.delay);this.timeouts.add(o)}else this.fire(r)}}continuous(e,i=250){if(this.destroyed)return()=>{};let n=P(Q,e),r=Number.isFinite(i)&&i>=16?i:250,o=setInterval(()=>this.fire(n),r);return this.intervals.add(o),()=>{clearInterval(o),this.intervals.delete(o)}}pause(){this.paused=!0,this.cancelFrame()}resume(){this.paused=!1,this.scheduleFrame()}reset(){this.paused=!1,this.cancelFrame();for(let e of this.timeouts)clearTimeout(e);for(let e of this.intervals)clearInterval(e);this.timeouts.clear(),this.intervals.clear(),this.pool.reset(),this.renderer?.clear()}destroy(){this.destroyed||(this.reset(),this.destroyed=!0,this.resizeWithWindow&&window.removeEventListener("resize",this.handleResize),this.resizeObserver?.disconnect(),this.resizeObserver=null,document.removeEventListener("visibilitychange",this.handleVisibilityChange),this.renderer?.destroy())}scheduleFrame(){this.frameId!==null||this.paused||this.destroyed||document.hidden||this.pool.activeCount===0||(this.lastTime=performance.now(),this.frameId=requestAnimationFrame(this.tick))}cancelFrame(){this.frameId!==null&&(cancelAnimationFrame(this.frameId),this.frameId=null)}};var O=null;function z(){return b()?(O??(O=new m),O):null}function k(t){z()?.fire(t)}function u(t,e){z()?.preset(t,e)}function _(t){let e=t.getBoundingClientRect();return{x:(e.left+e.width/2)/window.innerWidth,y:(e.top+e.height/2)/window.innerHeight}}function ee(t,e={}){if(!b())return;let{preset:i,...n}=e,r=y(i)?i:void 0,s=(r?x[r].followsOrigin:!0)?{...n,origin:M(_(t),n.origin)}:n;r?u(r,s):k(s)}function te(){O?.reset()}function ie(){O?.destroy(),O=null}function ne(t,e){let i=new m(t,e),n=(r=>i.fire(r));return n.preset=(r,o)=>i.preset(r,o),n.continuous=(r,o)=>i.continuous(r,o),n.reset=()=>i.reset(),n.destroy=()=>i.destroy(),n}function re(t,e){return z()?.continuous(t,e)??(()=>{})}var oe=t=>u("cannon",t),se=t=>u("explosion",t),ae=t=>u("fireworks",t),ce=t=>u("rain",t),le=t=>u("snow",t),de=t=>u("sideCannons",t),fe=t=>u("pride",t);return Oe($e);})();
2
2
  //# sourceMappingURL=konfetti.min.js.map